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