]> git.lyx.org Git - lyx.git/blob - src/mathed/support.C
Few math fonts improvements (use cmr for uppercase greek, support for
[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 "FontLoader.h"
8 #include "font.h"
9 #include "math_defs.h"
10 #include "math_parser.h"
11 #include "Painter.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
20 bool isBinaryOp(char c, MathTextCodes type)
21 {
22         return type < LM_TC_SYMB && strchr("+-<>=/*", c); 
23 }
24
25
26 ///
27 class Matrix {
28 public:
29         ///
30         typedef float matriz_data[2][2];
31         ///
32         Matrix();
33         ///
34         void rotate(int);
35         ///
36         void escalate(float, float);
37         ///
38         void transform(float, float, float &, float &);
39 private:
40         ///
41         matriz_data m_;
42         ///
43         void multiply(matriz_data & a);
44 };
45
46 Matrix::Matrix()
47 {
48         m_[0][0] = 1;
49         m_[0][1] = 0;
50         m_[1][0] = 0;
51         m_[1][1] = 1;
52 }
53
54 void Matrix::rotate(int code)
55 {
56         matriz_data r;
57         r[0][0] = 1;
58         r[0][1] = 0;
59         r[1][0] = 0;
60         r[1][1] = 1;
61         float const cs = (code & 1) ? 0 : (1 - code);
62         float const sn = (code & 1) ? (2 - code) : 0;
63         r[0][0] = cs;
64         r[0][1] = sn;
65         r[1][0] = -r[0][1];
66         r[1][1] = r[0][0];
67         multiply(r);
68 }
69
70 void Matrix::escalate(float x, float y)
71 {
72         matriz_data s;
73         s[0][0] = x;
74         s[0][1] = 0;
75         s[1][0] = 0;
76         s[1][1] = y;
77         multiply(s);
78 }
79
80 void Matrix::multiply(matriz_data & a)
81 {
82         matriz_data c;
83         c[0][0] = a[0][0] * m_[0][0] + a[0][1] * m_[1][0];
84         c[1][0] = a[1][0] * m_[0][0] + a[1][1] * m_[1][0];
85         c[0][1] = a[0][0] * m_[0][1] + a[0][1] * m_[1][1];
86         c[1][1] = a[1][0] * m_[0][1] + a[1][1] * m_[1][1];
87         m_[0][0] = c[0][0];     
88         m_[0][1] = c[0][1];     
89         m_[1][0] = c[1][0];     
90         m_[1][1] = c[1][1];     
91 }
92
93 void Matrix::transform(float xp, float yp, float & x, float & y)
94 {
95         x = m_[0][0] * xp + m_[0][1] * yp;
96         y = m_[1][0] * xp + m_[1][1] * yp;
97 }
98
99
100 namespace {
101
102 LyXFont * MathFonts = 0;
103 bool font_available[LM_FONT_END];
104 bool font_available_initialized[LM_FONT_END];
105
106 enum MathFont {
107         FONT_IT,
108         FONT_SYMBOL,
109         FONT_SYMBOLI,
110         FONT_BF,
111         FONT_BB,
112         FONT_CAL,
113         FONT_TT,
114         FONT_RM,
115         FONT_SF,
116         FONT_CMR,
117         FONT_CMSY,
118         FONT_CMM,
119         FONT_CMEX,
120         FONT_MSA,
121         FONT_MSB,
122         FONT_NUM
123 };
124
125 void mathed_init_fonts()
126 {
127         MathFonts = new LyXFont[FONT_NUM]; //DEC cxx cannot initialize all fonts
128         //at once (JMarc) rc
129
130         for (int i = 0 ; i < FONT_NUM ; ++i) {
131                 MathFonts[i] = LyXFont(LyXFont::ALL_SANE);
132         }
133
134         MathFonts[FONT_IT].setShape(LyXFont::ITALIC_SHAPE);
135
136         MathFonts[FONT_SYMBOL].setFamily(LyXFont::SYMBOL_FAMILY);
137
138         MathFonts[FONT_SYMBOLI].setFamily(LyXFont::SYMBOL_FAMILY);
139         MathFonts[FONT_SYMBOLI].setShape(LyXFont::ITALIC_SHAPE);
140
141         MathFonts[FONT_BF].setSeries(LyXFont::BOLD_SERIES);
142
143         MathFonts[FONT_BB].setSeries(LyXFont::BOLD_SERIES);
144         MathFonts[FONT_BB].setFamily(LyXFont::TYPEWRITER_FAMILY);
145
146         MathFonts[FONT_CAL].setFamily(LyXFont::SANS_FAMILY);
147         MathFonts[FONT_CAL].setShape(LyXFont::ITALIC_SHAPE);
148
149         MathFonts[FONT_TT].setFamily(LyXFont::TYPEWRITER_FAMILY);
150
151         MathFonts[FONT_RM].setFamily(LyXFont::ROMAN_FAMILY);
152
153         MathFonts[FONT_SF].setFamily(LyXFont::SANS_FAMILY);
154
155         MathFonts[FONT_CMR].setFamily(LyXFont::CMR_FAMILY);
156         MathFonts[FONT_CMSY].setFamily(LyXFont::CMSY_FAMILY);
157         MathFonts[FONT_CMM].setFamily(LyXFont::CMM_FAMILY);
158         MathFonts[FONT_CMEX].setFamily(LyXFont::CMEX_FAMILY);
159         MathFonts[FONT_MSA].setFamily(LyXFont::MSA_FAMILY);
160         MathFonts[FONT_MSB].setFamily(LyXFont::MSB_FAMILY);
161
162         for (int i = 0; i < LM_FONT_END; ++i)
163                 font_available_initialized[i] = false;
164 }
165
166
167 LyXFont const & whichFontBase(MathTextCodes type)
168 {
169         if (!MathFonts)
170                 mathed_init_fonts();
171
172         switch (type) {
173         case LM_TC_SYMB:        
174         case LM_TC_BOLDSYMB:    
175                 return MathFonts[FONT_SYMBOLI];
176
177         case LM_TC_VAR:
178         case LM_TC_IT:
179                 return MathFonts[FONT_IT];
180
181         case LM_TC_BF:
182                 return MathFonts[FONT_BF];
183
184         case LM_TC_BB:
185                 if (math_font_available(LM_TC_MSB))
186                         return MathFonts[FONT_MSB];
187                 else
188                         return MathFonts[FONT_BB];
189
190         case LM_TC_CAL:
191                 if (math_font_available(LM_TC_CMSY))
192                         return MathFonts[FONT_CMSY];
193                 else
194                         return MathFonts[FONT_CAL];
195
196         case LM_TC_TT:
197                 return MathFonts[FONT_TT];
198
199         case LM_TC_TEXTRM:
200         case LM_TC_CONST:
201         case LM_TC_TEX:
202         case LM_TC_RM:
203                 return MathFonts[FONT_RM];
204
205         case LM_TC_SF:
206                 return MathFonts[FONT_SF];
207
208         case LM_TC_CMR:
209                 return MathFonts[FONT_CMR];
210
211         case LM_TC_CMSY:
212                 return MathFonts[FONT_CMSY];
213
214         case LM_TC_CMM:
215                 return MathFonts[FONT_CMM];
216
217         case LM_TC_CMEX:
218                 return MathFonts[FONT_CMEX];
219
220         case LM_TC_MSA:
221                 return MathFonts[FONT_MSA];
222
223         case LM_TC_MSB:
224                 return MathFonts[FONT_MSB];
225
226         default:
227                 break;
228         }
229         return MathFonts[1];
230 }
231
232
233 LyXFont whichFont(MathTextCodes type, MathStyles size)
234 {
235         LyXFont f = whichFontBase(type);
236
237         switch (size) {
238         case LM_ST_DISPLAY:
239                 if (type == LM_TC_BOLDSYMB || type == LM_TC_CMEX) {
240                         f.incSize();
241                         f.incSize();
242                 }
243                 break;
244
245         case LM_ST_TEXT:
246                 break;
247
248         case LM_ST_SCRIPT:
249                 f.decSize();
250                 f.decSize();
251                 break;
252
253         case LM_ST_SCRIPTSCRIPT:
254                 f.decSize();
255                 f.decSize();
256                 f.decSize();
257                 break;
258
259         default:
260                 lyxerr << "Math Error: wrong font size: " << size << endl;
261                 break;
262         }
263
264         if (type != LM_TC_TEXTRM)
265                 f.setColor(LColor::math);
266
267         if (type == LM_TC_TEX)
268                 f.setColor(LColor::latex);
269
270         return f;
271 }
272
273 } // namespace
274
275
276 bool math_font_available(MathTextCodes type)
277 {
278         if (!font_available_initialized[type]) {
279                 font_available_initialized[type] = true;
280                 font_available[type] = 
281                         fontloader.available(whichFontBase(type));
282         }
283         return font_available[type];
284 }
285
286
287 namespace {
288
289 /* 
290  * Internal struct of a drawing: code n x1 y1 ... xn yn, where code is:
291  * 0 = end, 1 = line, 2 = polyline, 3 = square line, 4= square polyline
292  */
293
294
295 float const parenthHigh[] = {
296         2.0, 13.0,
297         0.9840, 0.0014, 0.7143, 0.0323, 0.4603, 0.0772,
298         0.2540, 0.1278, 0.1746, 0.1966, 0.0952, 0.3300,
299         0.0950, 0.5000, 0.0952, 0.6700, 0.1746, 0.8034,
300         0.2540, 0.8722, 0.4603, 0.9228, 0.7143, 0.9677,
301         0.9840, 0.9986,
302         0.0 
303 };
304
305
306 float const parenth[] = {
307         2.0, 13.0,
308         0.9930, 0.0071, 0.7324, 0.0578, 0.5141, 0.1126,
309         0.3380, 0.1714, 0.2183, 0.2333, 0.0634, 0.3621,
310         0.0141, 0.5000, 0.0563, 0.6369, 0.2113, 0.7647,
311         0.3310, 0.8276, 0.5070, 0.8864, 0.7254, 0.9412,
312         0.9930, 0.9919,
313         0.0   
314 };
315
316
317 float const brace[] = {
318         2.0, 21.0,
319         0.9492, 0.0020, 0.9379, 0.0020, 0.7458, 0.0243,
320         0.5819, 0.0527, 0.4859, 0.0892, 0.4463, 0.1278,
321         0.4463, 0.3732, 0.4011, 0.4199, 0.2712, 0.4615,
322         0.0734, 0.4919, 0.0113, 0.5000, 0.0734, 0.5081,
323         0.2712, 0.5385, 0.4011, 0.5801, 0.4463, 0.6268,
324         0.4463, 0.8722, 0.4859, 0.9108, 0.5819, 0.9473,
325         0.7458, 0.9757, 0.9379, 0.9980, 0.9492, 0.9980,
326         0.0
327 };
328
329
330 // Is this correct? (Lgb)
331 float const arrow[] = {
332         4, 7,
333         0.0150, 0.7500, 0.2000, 0.6000, 0.3500, 0.3500,
334         0.5000, 0.0500, 0.6500, 0.3500, 0.8000, 0.6000,
335         0.9500, 0.7500,
336         3, 0.5000, 0.1500, 0.5000, 0.9500,
337         0.0 
338 };
339
340
341 // Is this correct? (Lgb)
342 float const Arrow[] = {
343         4, 7,
344         0.0150, 0.7500, 0.2000, 0.6000, 0.3500, 0.3500,
345         0.5000, 0.0500, 0.6500, 0.3500, 0.8000, 0.6000,
346         0.9500, 0.7500,
347         3, 0.3500, 0.5000, 0.3500, 0.9500,
348         3, 0.6500, 0.5000, 0.6500, 0.9500,
349         0.0
350 };
351
352
353 float const udarrow[] = {
354         2, 3,
355         0.015, 0.25,  0.5, 0.05, 0.95, 0.25,
356         2, 3,
357         0.015, 0.75,  0.5, 0.95, 0.95, 0.75,  
358         1, 0.5, 0.2,  0.5, 0.8,
359         0.0 
360 };
361
362
363 float const Udarrow[] = {
364         2, 3,
365         0.015, 0.25,  0.5, 0.05, 0.95, 0.25,
366         2, 3,
367         0.015, 0.75,  0.5, 0.95, 0.95, 0.75,  
368         1, 0.35, 0.2, 0.35, 0.8,
369         1, 0.65, 0.2, 0.65, 0.8,
370         0.0 
371 };
372
373
374 float const brack[] = {
375         2.0, 4,
376         0.95, 0.05,  0.05, 0.05,  0.05, 0.95,  0.95, 0.95,
377         0.0
378 };
379
380
381 float const corner[] = {
382         2.0, 3,
383         0.95, 0.05,  0.05, 0.05,  0.05, 0.95,
384         0.0
385 };
386
387
388 float const angle[] = {
389         2.0, 3,
390         1, 0,  0.05, 0.5,  1, 1,
391         0.0
392 };
393
394
395 float const slash[] = {
396         1, 0.95, 0.05,  0.05, 0.95, 
397         0.0
398 };
399
400
401 float const hline[] = {
402         1, 0.05, 0.5,  0.95, 0.5, 
403         0.0
404 };
405
406
407 float const hline2[] = {
408    1, 0.1, 0.5,  0.3, 0.5,
409    1, 0.7, 0.5,  0.9, 0.5,
410    0.0
411 }; 
412
413
414 float const hline3[] = {
415         1, 0.1, 0,  0.15, 0,
416         1, 0.475, 0,  0.525, 0,
417         1, 0.85, 0,  0.9, 0,  
418         0.0
419 };
420
421
422 float const dline3[] = {
423         1, 0.1, 0.1,  0.15, 0.15,
424         1, 0.475, 0.475,  0.525, 0.525,
425         1, 0.85, 0.85,  0.9, 0.9,
426         0.0
427 };     
428
429
430 float const hlinesmall[] = {
431         1, 0.4, 0.5,  0.6, 0.5, 
432         0.0
433 };
434
435
436 float const vert[] = {
437         1, 0.5, 0.05,  0.5, 0.95, 
438         0.0
439 };
440
441
442 float const  Vert[] = {
443         1, 0.3, 0.05,  0.3, 0.95, 
444         1, 0.7, 0.05,  0.7, 0.95,
445         0.0
446 };
447
448
449 float const tilde[] = {
450         2.0, 4,
451         0.05, 0.8,  0.25, 0.2,  0.75, 0.8,  0.95, 0.2,
452         0.0
453 };
454
455
456 struct deco_struct {
457         int code;
458         float const * data;
459         int angle;
460 };
461
462 deco_struct deco_table[] = {   
463         // Decorations
464         { LM_widehat,       &angle[0],      3 },
465         { LM_widetilde,     &tilde[0],      0 },
466         { LM_underline,     &hline[0],      0 },
467         { LM_overline,      &hline[0],      0 },
468         { LM_underbrace,    &brace[0],      1 },
469         { LM_overbrace,     &brace[0],      3 },
470         { LM_overleftarrow, &arrow[0],      1 },
471         { LM_overightarrow, &arrow[0],      3 },
472                                             
473         // Delimiters                       
474         { '(',              &parenth[0],    0 },
475         { ')',              &parenth[0],    2 },
476         { '{',              &brace[0],      0 },
477         { '}',              &brace[0],      2 },
478         { '[',              &brack[0],      0 },
479         { ']',              &brack[0],      2 },
480         { '|',              &vert[0],       0 },
481         { '/',              &slash[0],      0 },
482         { LM_Vert,          &Vert[0],       0 },
483         { '\\',             &slash[0],      1 },
484         { LM_langle,        &angle[0],      0 },
485         { LM_lceil,         &corner[0],     0 }, 
486         { LM_lfloor,        &corner[0],     1 },  
487         { LM_rangle,        &angle[0],      2 }, 
488         { LM_rceil,         &corner[0],     3 }, 
489         { LM_rfloor,        &corner[0],     2 },
490         { LM_downarrow,     &arrow[0],      2 },
491         { LM_Downarrow,     &Arrow[0],      2 }, 
492         { LM_uparrow,       &arrow[0],      0 },
493         { LM_Uparrow,       &Arrow[0],      0 },
494         { LM_updownarrow,   &udarrow[0],    0 },
495         { LM_Updownarrow,   &Udarrow[0],    0 },         
496                                             
497         // Accents                          
498         { LM_ddot,          &hline2[0],     0 },
499         { LM_hat,           &angle[0],      3 },
500         { LM_grave,         &slash[0],      1 },
501         { LM_acute,         &slash[0],      0 },
502         { LM_tilde,         &tilde[0],      0 },
503         { LM_bar,           &hline[0],      0 },
504         { LM_dot,           &hlinesmall[0], 0 },
505         { LM_check,         &angle[0],      1 },
506         { LM_breve,         &parenth[0],    1 },
507         { LM_vec,           &arrow[0],      3 },
508         { LM_not,           &slash[0],      0 },  
509                                             
510         // Dots                             
511         { LM_ldots,         &hline3[0],     0 }, 
512         { LM_cdots,         &hline3[0],     0 },
513         { LM_vdots,         &hline3[0],     1 },
514         { LM_ddots,         &dline3[0],     0 }
515 };
516
517
518 struct deco_compare {
519         /// for use by sort and lower_bound
520         int operator()(deco_struct const & a, deco_struct const & b) const
521         {
522                 return a.code < b.code;
523         }
524 };
525
526
527 int const deco_table_size =
528         sizeof(deco_table) / sizeof(deco_struct);
529
530
531 // sort the table on startup
532 struct init_deco_table {
533         init_deco_table() {
534                         std::sort(deco_table,
535                              deco_table + deco_table_size,
536                              deco_compare());
537         }
538 };
539
540 static init_deco_table dummy;
541
542
543 deco_struct const * search_deco(int code)
544 {
545         const deco_struct search_elem = { code, 0, 0 };
546         
547         deco_struct const * res =
548                 lower_bound(deco_table, deco_table + deco_table_size, search_elem,
549                         deco_compare());
550         if (res != deco_table + deco_table_size &&
551             res->code == code)
552                 return res;
553         return 0;
554 }
555
556
557 } // namespace anon
558
559
560 void mathed_char_dim(MathTextCodes type, MathStyles size, unsigned char c,
561         int & asc, int & des, int & wid)
562 {
563         LyXFont const font = whichFont(type, size);
564         des = lyxfont::descent(c, font);
565         asc = lyxfont::ascent(c, font);
566         wid = mathed_char_width(type, size, c);
567 }
568
569
570 int mathed_char_height(MathTextCodes type, MathStyles size, unsigned char c,
571         int & asc, int & des)
572 {
573         LyXFont const font = whichFont(type, size);
574         des = lyxfont::descent(c, font);
575         asc = lyxfont::ascent(c, font);
576         return asc + des;
577 }
578
579
580 int mathed_char_height(MathTextCodes type, MathStyles size, unsigned char c)
581 {
582         int asc;
583         int des;
584         return mathed_char_height(type, size, c, asc, des);
585 }
586
587
588 int mathed_char_ascent(MathTextCodes type, MathStyles size, unsigned char c)
589 {
590         LyXFont const font = whichFont(type, size);
591         return lyxfont::ascent(c, font);
592 }
593
594
595 int mathed_char_descent(MathTextCodes type, MathStyles size, unsigned char c)
596 {
597         LyXFont const font = whichFont(type, size);
598         return lyxfont::descent(c, font);
599 }
600
601
602 int mathed_char_width(MathTextCodes type, MathStyles size, unsigned char c)
603 {
604         LyXFont const font = whichFont(type, size);
605         LyXFont const f1 = whichFont(LM_TC_TEXTRM, size);
606 #warning why f1 is used ?
607         if (isBinaryOp(c, type))
608                 return lyxfont::width(c, font) + 2 * lyxfont::width(' ', f1);
609         else
610                 return lyxfont::width(c, font);
611 }
612
613
614 void mathed_string_dim(MathTextCodes type, MathStyles size, string const & s,
615                          int & asc, int & des, int & wid)
616 {
617         mathed_string_height(type, size, s, asc, des);
618         wid = mathed_string_width(type, size, s);
619 }
620
621
622 int mathed_string_height(MathTextCodes type, MathStyles size, string const & s,
623                          int & asc, int & des)
624 {
625         LyXFont const font = whichFont(type, size);
626         asc = des = 0;
627         for (string::const_iterator it = s.begin(); it != s.end(); ++it) {
628                 des = max(des, lyxfont::descent(*it, font));
629                 asc = max(asc, lyxfont::ascent(*it, font));
630         }
631         return asc + des;
632 }
633
634
635 int mathed_string_width(MathTextCodes type, MathStyles size, string const & s)
636 {
637         return lyxfont::width(s, whichFont(type, size));
638 }
639
640
641 void mathed_draw_deco(Painter & pain, int x, int y, int w, int h,
642         latexkeys const * l)
643 {
644         Matrix mt;
645         Matrix sqmt;
646         int i = 0;
647         string const & name = l->name;
648         int code = (name.size() > 1) ? l->id : name[0];
649
650         if (name == ".") {
651                 pain.line(x + w/2, y, x + w/2, y + h,
652                           LColor::mathcursor, Painter::line_onoffdash);
653                 return;
654         }       
655         
656         deco_struct const * mds = search_deco(code);
657         if (!mds) {
658                 lyxerr << "Deco was not found. Programming error?\n";
659                 lyxerr << "name: '" << name << "', code: " << code << "\n";
660                 return;
661         }
662         
663         int const r = mds->angle;
664         float const * d = mds->data;
665         
666         if (h > 70 && (mds->code == int('(') || mds->code == int(')')))
667                 d = parenthHigh;
668         
669         mt.rotate(r);
670         mt.escalate(w, h);
671         
672         int const n = (w < h) ? w : h;
673
674         sqmt.rotate(r);
675         sqmt.escalate(n, n);
676
677         if (r > 0 && r < 3)
678                 y += h;
679
680         if (r >= 2)
681                 x += w;   
682
683         do {
684                 float xx;
685                 float yy;
686                 float x2;
687                 float y2;
688
689                 code = int(d[i++]);
690                 switch (code) {
691                 case 0: break;
692                 case 1: 
693                 case 3:
694                 {
695                         xx = d[i++]; yy = d[i++];
696                         x2 = d[i++]; y2 = d[i++];
697                         if (code == 3) 
698                                 sqmt.transform(xx, yy, xx, yy);
699                         else
700                                 mt.transform(xx, yy, xx, yy);
701                         mt.transform(x2, y2, x2, y2);
702                         pain.line(x + int(xx), y + int(yy),
703                                   x + int(x2), y + int(y2),
704                                   LColor::mathline);
705                         break;
706                 }        
707                 case 2: 
708                 case 4:
709                 {
710                         int xp[32];
711                         int yp[32];
712                         int const n = int(d[i++]);
713                         for (int j = 0; j < n; ++j) {
714                                 xx = d[i++]; yy = d[i++];
715 //           lyxerr << " " << xx << " " << yy << " ";
716                                 if (code == 4) 
717                                         sqmt.transform(xx, yy, xx, yy);
718                                 else
719                                         mt.transform(xx, yy, xx, yy);
720                                 xp[j] = x + int(xx);
721                                 yp[j] = y + int(yy);
722                                 //  lyxerr << "P[" << j " " << xx << " " << yy << " " << x << " " << y << "]";
723                         }
724                         pain.lines(xp, yp, n, LColor::mathline);
725                 }
726                 }
727         } while (code);
728 }
729
730
731 // In the future maybe we use a better fonts renderer
732 void drawStr(Painter & pain, MathTextCodes type, MathStyles siz,
733         int x, int y, string const & s)
734 {
735         pain.text(x, y, s, whichFont(type, siz));
736 }
737
738
739 void drawChar
740         (Painter & pain, MathTextCodes type, MathStyles siz, int x, int y, char c)
741 {
742         string s;
743         if (isBinaryOp(c, type))
744                 s += ' ';
745         s += c;
746         if (isBinaryOp(c, type))
747                 s += ' ';
748         drawStr(pain, type, siz, x, y, s);
749 }
750
751
752 // decrease math size for super- and subscripts
753 MathStyles smallerStyleScript(MathStyles st)
754 {
755         switch (st) {
756                 case LM_ST_DISPLAY:
757                 case LM_ST_TEXT:    st = LM_ST_SCRIPT; break;
758                 default:            st = LM_ST_SCRIPTSCRIPT;
759         }
760         return st;
761 }
762
763
764 // decrease math size for fractions
765 MathStyles smallerStyleFrac(MathStyles st)
766 {
767         switch (st) {
768                 case LM_ST_DISPLAY: st = LM_ST_TEXT; break;
769                 case LM_ST_TEXT:    st = LM_ST_SCRIPT; break;
770                 default:            st = LM_ST_SCRIPTSCRIPT;
771         }
772         return st;
773 }
774
775
776 void math_font_max_dim(MathTextCodes code, MathStyles siz, int & asc, int & des)
777 {
778         LyXFont font = whichFont(code, siz);
779         asc = lyxfont::maxAscent(font);
780         des = lyxfont::maxDescent(font);
781 }
782
783
784 char const * latex_mathspace[] = {
785         "!", ",", ":", ";", "quad", "qquad"
786 };