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