]> git.lyx.org Git - lyx.git/blob - src/mathed/support.C
small cleanup, doxygen, formatting changes
[lyx.git] / src / mathed / support.C
1 #include <config.h>
2
3 #include <algorithm>
4
5 #include "mathed/support.h"
6 #include "lyxfont.h"
7 #include "font.h"
8 #include "math_defs.h"
9 #include "Painter.h"
10 #include "matriz.h"
11 #include "symbol_def.h"
12 #include "debug.h"
13 #include "math_utils.h"
14
15 using std::sort;
16 using std::lower_bound;
17 using std::endl;
18 using std::max;
19
20 extern LyXFont WhichFont(short type, int size);
21
22 char const * math_font_name[] = {
23         "mathrm",
24         "mathcal",
25         "mathbf",
26         "mathsf",
27         "mathtt",
28         "mathit",
29         "textrm"
30 };
31
32
33 char const * latex_mathspace[] = {
34         "!", ",", ":", ";", "quad", "qquad"
35 };
36
37 /* 
38  * Internal struct of a drawing: code n x1 y1 ... xn yn, where code is:
39  * 0 = end, 1 = line, 2 = polyline, 3 = square line, 4= square polyline
40  */
41
42
43 static
44 float const parenthHigh[] = {
45         2.0, 13.0,
46         0.9840, 0.0014, 0.7143, 0.0323, 0.4603, 0.0772,
47         0.2540, 0.1278, 0.1746, 0.1966, 0.0952, 0.3300,
48         0.0950, 0.5000, 0.0952, 0.6700, 0.1746, 0.8034,
49         0.2540, 0.8722, 0.4603, 0.9228, 0.7143, 0.9677,
50         0.9840, 0.9986,
51         0.0 
52 };
53
54
55 static
56 float const parenth[] = {
57         2.0, 13.0,
58         0.9930, 0.0071, 0.7324, 0.0578, 0.5141, 0.1126,
59         0.3380, 0.1714, 0.2183, 0.2333, 0.0634, 0.3621,
60         0.0141, 0.5000, 0.0563, 0.6369, 0.2113, 0.7647,
61         0.3310, 0.8276, 0.5070, 0.8864, 0.7254, 0.9412,
62         0.9930, 0.9919,
63         0.0   
64 };
65
66
67 static
68 float const brace[] = {
69         2.0, 21.0,
70         0.9492, 0.0020, 0.9379, 0.0020, 0.7458, 0.0243,
71         0.5819, 0.0527, 0.4859, 0.0892, 0.4463, 0.1278,
72         0.4463, 0.3732, 0.4011, 0.4199, 0.2712, 0.4615,
73         0.0734, 0.4919, 0.0113, 0.5000, 0.0734, 0.5081,
74         0.2712, 0.5385, 0.4011, 0.5801, 0.4463, 0.6268,
75         0.4463, 0.8722, 0.4859, 0.9108, 0.5819, 0.9473,
76         0.7458, 0.9757, 0.9379, 0.9980, 0.9492, 0.9980,
77         0.0
78 };
79
80
81 // Is this correct? (Lgb)
82 static
83 float const arrow[] = {
84         4, 7,
85         0.0150, 0.7500, 0.2000, 0.6000, 0.3500, 0.3500,
86         0.5000, 0.0500, 0.6500, 0.3500, 0.8000, 0.6000,
87         0.9500, 0.7500,
88         3, 0.5000, 0.1500, 0.5000, 0.9500,
89         0.0 
90 };
91
92
93 // Is this correct? (Lgb)
94 static
95 float const Arrow[] = {
96         4, 7,
97         0.0150, 0.7500, 0.2000, 0.6000, 0.3500, 0.3500,
98         0.5000, 0.0500, 0.6500, 0.3500, 0.8000, 0.6000,
99         0.9500, 0.7500,
100         3, 0.3500, 0.5000, 0.3500, 0.9500,
101         3, 0.6500, 0.5000, 0.6500, 0.9500,
102         0.0
103 };
104
105
106 static
107 float const udarrow[] = {
108         2, 3,
109         0.015, 0.25,  0.5, 0.05, 0.95, 0.25,
110         2, 3,
111         0.015, 0.75,  0.5, 0.95, 0.95, 0.75,  
112         1, 0.5, 0.2,  0.5, 0.8,
113         0.0 
114 };
115
116
117 static
118 float const Udarrow[] = {
119         2, 3,
120         0.015, 0.25,  0.5, 0.05, 0.95, 0.25,
121         2, 3,
122         0.015, 0.75,  0.5, 0.95, 0.95, 0.75,  
123         1, 0.35, 0.2, 0.35, 0.8,
124         1, 0.65, 0.2, 0.65, 0.8,
125         0.0 
126 };
127
128
129 static
130 float const brack[] = {
131         2.0, 4,
132         0.95, 0.05,  0.05, 0.05,  0.05, 0.95,  0.95, 0.95,
133         0.0
134 };
135
136
137 static
138 float const corner[] = {
139         2.0, 3,
140         0.95, 0.05,  0.05, 0.05,  0.05, 0.95,
141         0.0
142 };
143
144
145 static
146 float const angle[] = {
147         2.0, 3,
148         1, 0,  0.05, 0.5,  1, 1,
149         0.0
150 };
151
152
153 static
154 float const slash[] = {
155         1, 0.95, 0.05,  0.05, 0.95, 
156         0.0
157 };
158
159
160 static const float hline[] = {
161         1, 0.05, 0.5,  0.95, 0.5, 
162         0.0
163 };
164
165
166 static
167 float const hline2[] = {
168    1, 0.1, 0.5,  0.3, 0.5,
169    1, 0.7, 0.5,  0.9, 0.5,
170    0.0
171 }; 
172
173
174 static
175 float const hline3[] = {
176         1, 0.1, 0,  0.15, 0,
177         1, 0.475, 0,  0.525, 0,
178         1, 0.85, 0,  0.9, 0,  
179         0.0
180 };
181
182
183 static
184 float const dline3[] = {
185         1, 0.1, 0.1,  0.15, 0.15,
186         1, 0.475, 0.475,  0.525, 0.525,
187         1, 0.85, 0.85,  0.9, 0.9,
188         0.0
189 };     
190
191
192 static
193 float const hlinesmall[] = {
194         1, 0.4, 0.5,  0.6, 0.5, 
195         0.0
196 };
197
198
199 static
200 float const vert[] = {
201         1, 0.5, 0.05,  0.5, 0.95, 
202         0.0
203 };
204
205
206 static
207 float const  Vert[] = {
208         1, 0.3, 0.05,  0.3, 0.95, 
209         1, 0.7, 0.05,  0.7, 0.95,
210         0.0
211 };
212
213
214 static
215 float const tilde[] = {
216         2.0, 4,
217         0.05, 0.8,  0.25, 0.2,  0.75, 0.8,  0.95, 0.2,
218         0.0
219 };
220
221
222 static
223 math_deco_struct math_deco_table[] = {   
224         // Decorations
225         { LM_widehat, &angle[0], 3 },
226         { LM_widetilde, &tilde[0], 0 },
227         { LM_underline, &hline[0], 0 },
228         { LM_overline, &hline[0], 0 },
229         { LM_underbrace, &brace[0], 1 },
230         { LM_overbrace,  &brace[0], 3 },
231         { LM_overleftarrow, &arrow[0], 1 },
232         { LM_overightarrow, &arrow[0], 3 },
233         
234         // Delimiters
235         { '(', &parenth[0], 0 },
236         { ')', &parenth[0], 2 },
237         { '{', &brace[0], 0 },
238         { '}', &brace[0], 2 },
239         { '[', &brack[0], 0 },
240         { ']', &brack[0], 2 },
241         { '|', &vert[0], 0 },
242         { '/', &slash[0], 0 },
243         { LM_Vert, &Vert[0], 0 },
244         { LM_backslash, &slash[0], 1 },
245         { LM_langle, &angle[0], 0 },
246         { LM_lceil, &corner[0], 0 }, 
247         { LM_lfloor, &corner[0], 1 },  
248         { LM_rangle, &angle[0], 2 }, 
249         { LM_rceil, &corner[0], 3 }, 
250         { LM_rfloor, &corner[0], 2 },
251         { LM_downarrow, &arrow[0], 2 },
252         { LM_Downarrow, &Arrow[0], 2 }, 
253         { LM_uparrow, &arrow[0], 0 },
254         { LM_Uparrow, &Arrow[0], 0 },
255         { LM_updownarrow, &udarrow[0], 0 },
256         { LM_Updownarrow, &Udarrow[0], 0 },      
257         
258         // Accents   
259         { LM_ddot, &hline2[0], 0 },
260         { LM_hat, &angle[0], 3 },
261         { LM_grave, &slash[0], 1 },
262         { LM_acute, &slash[0], 0 },
263         { LM_tilde, &tilde[0], 0 },
264         { LM_bar, &hline[0], 0 },
265         { LM_dot, &hlinesmall[0], 0 },
266         { LM_check, &angle[0], 1 },
267         { LM_breve, &parenth[0], 1 },
268         { LM_vec, &arrow[0], 3 },
269         { LM_not, &slash[0], 0 },  
270         
271         // Dots
272         { LM_ldots, &hline3[0], 0 }, 
273         { LM_cdots, &hline3[0], 0 },
274         { LM_vdots, &hline3[0], 1 },
275         { LM_ddots, &dline3[0], 0 }
276 };
277
278
279 struct math_deco_compare {
280         /// for use by sort and lower_bound
281         inline
282         int operator()(math_deco_struct const & a,
283                        math_deco_struct const & b) const {
284                 return a.code < b.code;
285         }
286 };
287
288
289 static
290 int const math_deco_table_size =
291 sizeof(math_deco_table) /sizeof(math_deco_struct);
292
293
294 class init_deco_table {
295 public:
296         init_deco_table() {
297                 if (!init) {
298                         sort(math_deco_table,
299                              math_deco_table + math_deco_table_size,
300                              math_deco_compare());
301                         init_deco_table::init = true;
302                 }
303         }
304 private:
305         static bool init;
306 };
307
308
309 bool init_deco_table::init = false;
310 static init_deco_table idt;
311
312
313 int mathed_char_height(short type, int size, byte c, int & asc, int & des)
314 {
315         LyXFont const font = WhichFont(type, size);
316         des = lyxfont::descent(c, font);
317         asc = lyxfont::ascent(c, font);
318         return asc + des;
319 }
320
321
322 int mathed_char_width(short type, int size, byte c)
323 {
324         if (MathIsBinary(type)) {
325                 string s;
326                 s += c;
327                 return mathed_string_width(type, size, s);
328         } else
329                 return lyxfont::width(c, WhichFont(type, size));
330 }
331
332
333 int mathed_string_height(short type, int size, string const & s,
334                          int & asc, int & des)
335 {
336         LyXFont const font = WhichFont(type, size);
337         asc = des = 0;
338         for (string::const_iterator it = s.begin(); it != s.end(); ++it) {
339                 des = max(des, lyxfont::descent(*it, font));
340                 asc = max(asc, lyxfont::ascent(*it, font));
341         }
342         return asc + des;
343 }
344
345
346 int mathed_string_width(short type, int size, string const & s)
347 {
348         string st;
349         if (MathIsBinary(type))
350                 for (string::const_iterator it = s.begin();
351                      it != s.end(); ++it) {
352                         st += ' ';
353                         st += *it;
354                         st += ' ';
355                 }
356         else
357                 st = s;
358         
359         LyXFont const f = WhichFont(type, size);
360         return lyxfont::width(st, f);
361 }
362
363
364 LyXFont mathed_get_font(short type, int size)
365 {
366         LyXFont f = WhichFont(type, size);
367         if (type == LM_TC_TEX) {
368                 f.setLatex(LyXFont::ON);
369         }
370         return f;
371 }
372
373
374 void mathed_draw_deco(Painter & pain, int x, int y, int w, int h, int code)
375 {
376         Matriz mt;
377         Matriz sqmt;
378         float xx;
379         float yy;
380         float x2;
381         float y2;
382         int i = 0;
383         
384 #if USE_EXCEPTIONS
385         math_deco_struct mds;
386         try {
387                 mds = search_deco(code);
388         }
389         catch (deco_not_found) {
390                 // Should this ever happen?
391                 lyxerr << "Deco was not found. Programming error?" << endl;
392                 return;
393         }
394         
395         int const r = mds.angle;
396         float const * d = mds.data;
397         
398         if (h > 70 && (mds.code == int('(')
399                        || mds.code == int(')')))
400                 d = parenthHigh;
401 #else
402         math_deco_struct const * mds = search_deco(code);
403         if (!mds) {
404                 // Should this ever happen?
405                 lyxerr << "Deco was not found. Programming error?" << endl;
406                 return;
407         }
408         
409         
410         int const r = mds->angle;
411         float const * d = mds->data;
412         
413         if (h > 70 && (mds->code == int('(')
414                        || mds->code == int(')')))
415                 d = parenthHigh;
416 #endif
417         
418         mt.rota(r);
419         mt.escala(w, h);
420         
421         int const n = (w < h) ? w : h;
422         sqmt.rota(r);
423         sqmt.escala(n, n);
424         if (r > 0 && r < 3) y += h;   
425         if (r >= 2) x += w;   
426         do {
427                 code = int(d[i++]);
428                 switch (code) {
429                 case 0: break;
430                 case 1: 
431                 case 3:
432                 {
433                         xx = d[i++]; yy = d[i++];
434                         x2 = d[i++]; y2 = d[i++];
435                         if (code == 3) 
436                                 sqmt.transf(xx, yy, xx, yy);
437                         else
438                                 mt.transf(xx, yy, xx, yy);
439                         mt.transf(x2, y2, x2, y2);
440                         pain.line(x + int(xx), y + int(yy),
441                                   x + int(x2), y + int(y2),
442                                   LColor::mathline);
443                         break;
444                 }        
445                 case 2: 
446                 case 4:
447                 {
448                         int xp[32];
449                         int yp[32];
450                         int const n = int(d[i++]);
451                         for (int j = 0; j < n; ++j) {
452                                 xx = d[i++]; yy = d[i++];
453 //           lyxerr << " " << xx << " " << yy << " ";
454                                 if (code == 4) 
455                                         sqmt.transf(xx, yy, xx, yy);
456                                 else
457                                         mt.transf(xx, yy, xx, yy);
458                                 xp[j] = x + int(xx);
459                                 yp[j] = y + int(yy);
460                                 //  lyxerr << "P[" << j " " << xx << " " << yy << " " << x << " " << y << "]";
461                         }
462                         pain.lines(xp, yp, n, LColor::mathline);
463                 }
464                 }
465         } while (code);
466 }
467
468
469 #define USE_EXCEPTIONS 0
470 #if USE_EXCEPTIONS
471 struct deco_not_found {};
472
473
474 math_deco_struct const & search_deco(int code)
475 {
476         math_deco_struct const * res =
477                 lower_bound(math_deco_table,
478                             math_deco_table + math_deco_table_size,
479                             code, math_deco_compare());
480         if (res != math_deco_table + math_deco_table_size &&
481             res->code == code)
482                 return *res;
483         throw deco_not_found();
484 }
485
486 #else
487
488
489 math_deco_struct const * search_deco(int code)
490 {
491         math_deco_struct search_elem = { code, 0, 0 };
492         
493         math_deco_struct const * res =
494                 lower_bound(math_deco_table,
495                             math_deco_table + math_deco_table_size,
496                             search_elem, math_deco_compare());
497         if (res != math_deco_table + math_deco_table_size &&
498             res->code == code)
499                 return res;
500         return 0;
501 }
502 #endif
503
504
505 bool MathIsInset(short x)
506 {
507         return LM_TC_INSET <= x && x <= LM_TC_ACTIVE_INSET;
508 }
509
510
511 bool MathIsFont(short x)
512 {
513         return LM_TC_CONST <= x && x <= LM_TC_BSYM;
514 }
515
516
517 bool MathIsAlphaFont(short x)
518 {
519         return LM_TC_VAR <= x && x <= LM_TC_TEXTRM;
520 }
521
522
523 bool MathIsActive(short x)
524 {
525         return LM_TC_INSET < x && x <= LM_TC_ACTIVE_INSET;
526 }
527
528
529 bool MathIsUp(short x)
530 {
531         return x == LM_TC_UP;
532 }
533
534
535 bool MathIsDown(short x)
536 {
537         return x == LM_TC_DOWN;
538 }
539
540
541 bool MathIsScript(short x)
542 {
543         return x == LM_TC_DOWN || x == LM_TC_UP;
544 }
545
546
547 bool MathIsBOPS(short x)
548 {
549         return MathedLookupBOP(x) > LMB_NONE;
550 }
551
552
553 bool MathIsBinary(short x)
554 {
555         return x == LM_TC_BOP || x == LM_TC_BOPS;
556 }
557
558
559 bool MathIsSymbol(short x)
560 {
561         return LM_TC_SYMB <= x && x <= LM_TC_BSYM;
562 }
563      
564
565 bool is_eqn_type(short int type)
566 {
567         return type >= LM_OT_MIN && type < LM_OT_MATRIX;
568 }
569
570
571 bool is_matrix_type(short int type)
572 {
573         return type == LM_OT_MATRIX;
574 }
575
576
577 bool is_multiline(short int type)
578 {
579         return type >= LM_OT_MPAR && type < LM_OT_MATRIX;
580 }
581
582
583 bool is_ams(short int type)
584 {
585         return type > LM_OT_MPARN && type < LM_OT_MATRIX;
586 }
587
588
589 bool is_singlely_numbered(short int type)
590 {
591         return type == LM_OT_PARN || type == LM_OT_MULTLINEN;
592 }
593
594
595 bool is_multi_numbered(short int type)
596 {
597         return type == LM_OT_MPARN || type == LM_OT_ALIGNN
598                 || type == LM_OT_ALIGNATN;
599 }
600
601
602 bool is_numbered(short int type)
603 {
604         return is_singlely_numbered(type) || is_multi_numbered(type);
605 }
606
607
608 bool is_multicolumn(short int type)
609 {
610         return type == LM_OT_ALIGN || type == LM_OT_ALIGNN
611                 || type == LM_OT_ALIGNAT || type == LM_OT_ALIGNATN;
612 }