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