]> git.lyx.org Git - features.git/blob - src/mathed/MathSupport.cpp
ff4702ff71a586994787230692dbffdb3735150f
[features.git] / src / mathed / MathSupport.cpp
1 /**
2  * \file MathSupport.cpp
3  * This file is part of LyX, the document processor.
4  * Licence details can be found in the file COPYING.
5  *
6  * \author Alejandro Aguilar Sierra
7  * \author André Pönitz
8  *
9  * Full author contact details are available in file CREDITS.
10  */
11
12 #include <config.h>
13
14 #include "MathSupport.h"
15
16 #include "InsetMathFont.h"
17 #include "InsetMathSymbol.h"
18 #include "MathData.h"
19 #include "MathParser.h"
20 #include "MathStream.h"
21
22 #include "frontends/FontLoader.h"
23 #include "frontends/FontMetrics.h"
24 #include "frontends/Painter.h"
25
26 #include "support/debug.h"
27 #include "support/docstream.h"
28
29 #include <map>
30 #include <algorithm>
31
32 using namespace std;
33
34 namespace lyx {
35
36 using frontend::Painter;
37
38
39 ///
40 class Matrix {
41 public:
42         ///
43         Matrix(int, double, double);
44         ///
45         void transform(double &, double &);
46 private:
47         ///
48         double m_[2][2];
49 };
50
51
52 Matrix::Matrix(int code, double x, double y)
53 {
54         double const cs = (code & 1) ? 0 : (1 - code);
55         double const sn = (code & 1) ? (2 - code) : 0;
56         m_[0][0] =  cs * x;
57         m_[0][1] =  sn * x;
58         m_[1][0] = -sn * y;
59         m_[1][1] =  cs * y;
60 }
61
62
63 void Matrix::transform(double & x, double & y)
64 {
65         double xx = m_[0][0] * x + m_[0][1] * y;
66         double yy = m_[1][0] * x + m_[1][1] * y;
67         x = xx;
68         y = yy;
69 }
70
71
72
73 namespace {
74
75 /*
76  * Internal struct of a drawing: code n x1 y1 ... xn yn, where code is:
77  * 0 = end, 1 = line, 2 = polyline, 3 = square line, 4 = square polyline
78  */
79
80
81 double const parenthHigh[] = {
82         2, 13,
83         0.9840, 0.0014, 0.7143, 0.0323, 0.4603, 0.0772,
84         0.2540, 0.1278, 0.1746, 0.1966, 0.0952, 0.3300,
85         0.0950, 0.5000, 0.0952, 0.6700, 0.1746, 0.8034,
86         0.2540, 0.8722, 0.4603, 0.9228, 0.7143, 0.9677,
87         0.9840, 0.9986,
88         0
89 };
90
91
92 double const parenth[] = {
93         2, 13,
94         0.9930, 0.0071, 0.7324, 0.0578, 0.5141, 0.1126,
95         0.3380, 0.1714, 0.2183, 0.2333, 0.0634, 0.3621,
96         0.0141, 0.5000, 0.0563, 0.6369, 0.2113, 0.7647,
97         0.3310, 0.8276, 0.5070, 0.8864, 0.7254, 0.9412,
98         0.9930, 0.9919,
99         0
100 };
101
102
103 double const brace[] = {
104         2, 21,
105         0.9492, 0.0020, 0.9379, 0.0020, 0.7458, 0.0243,
106         0.5819, 0.0527, 0.4859, 0.0892, 0.4463, 0.1278,
107         0.4463, 0.3732, 0.4011, 0.4199, 0.2712, 0.4615,
108         0.0734, 0.4919, 0.0113, 0.5000, 0.0734, 0.5081,
109         0.2712, 0.5385, 0.4011, 0.5801, 0.4463, 0.6268,
110         0.4463, 0.8722, 0.4859, 0.9108, 0.5819, 0.9473,
111         0.7458, 0.9757, 0.9379, 0.9980, 0.9492, 0.9980,
112         0
113 };
114
115
116 double const arrow[] = {
117         4, 7,
118         0.0150, 0.7500, 0.2000, 0.6000, 0.3500, 0.3500,
119         0.5000, 0.0500, 0.6500, 0.3500, 0.8000, 0.6000,
120         0.9500, 0.7500,
121         3, 0.5000, 0.1500, 0.5000, 0.9500,
122         0
123 };
124
125
126 double const Arrow[] = {
127         4, 7,
128         0.0150, 0.7500, 0.2000, 0.6000, 0.3500, 0.3500,
129         0.5000, 0.0500, 0.6500, 0.3500, 0.8000, 0.6000,
130         0.9500, 0.7500,
131         3, 0.3500, 0.5000, 0.3500, 0.9500,
132         3, 0.6500, 0.5000, 0.6500, 0.9500,
133         0
134 };
135
136
137 double const udarrow[] = {
138         2, 3,
139         0.015, 0.25,  0.5, 0.05, 0.95, 0.25,
140         2, 3,
141         0.015, 0.75,  0.5, 0.95, 0.95, 0.75,
142         1, 0.5, 0.1,  0.5, 0.9,
143         0
144 };
145
146
147 double const Udarrow[] = {
148         2, 3,
149         0.015, 0.25,  0.5, 0.05, 0.95, 0.25,
150         2, 3,
151         0.015, 0.75,  0.5, 0.95, 0.95, 0.75,
152         1, 0.35, 0.2, 0.35, 0.8,
153         1, 0.65, 0.2, 0.65, 0.8,
154         0
155 };
156
157
158 double const brack[] = {
159         2, 4,
160         0.95, 0.05,  0.05, 0.05,  0.05, 0.95,  0.95, 0.95,
161         0
162 };
163
164
165 double const dbrack[] = {
166         2, 4,
167         0.95, 0.05,  0.05, 0.05,  0.05, 0.95,  0.95, 0.95,
168         2, 2,
169         0.50, 0.05,  0.50, 0.95,
170         0
171 };
172
173
174 double const corner[] = {
175         2, 3,
176         0.95, 0.05,  0.05, 0.05,  0.05, 0.95,
177         0
178 };
179
180
181 double const angle[] = {
182         2, 3,
183         1, 0,  0.05, 0.5,  1, 1,
184         0
185 };
186
187
188 double const slash[] = {
189         1, 0.95, 0.05, 0.05, 0.95,
190         0
191 };
192
193
194 double const hline[] = {
195         1, 0.00, 0.5, 1.0, 0.5,
196         0
197 };
198
199
200 double const ddot[] = {
201         1, 0.2, 0.5, 0.3, 0.5,
202         1, 0.7, 0.5, 0.8, 0.5,
203         0
204 };
205
206
207 double const dddot[] = {
208         1, 0.1,  0.5, 0.2,  0.5,
209         1, 0.45, 0.5, 0.55, 0.5,
210         1, 0.8,  0.5, 0.9,  0.5,
211         0
212 };
213
214
215 double const ddddot[] = {
216         1, 0.1,  0.5, 0.2,  0.5,
217         1, 0.45, 0.5, 0.55, 0.5,
218         1, 0.8,  0.5, 0.9,  0.5,
219         1, 1.15, 0.5, 1.25, 0.5,
220         0
221 };
222
223
224 double const hline3[] = {
225         1, 0.1,   0,  0.15,  0,
226         1, 0.475, 0,  0.525, 0,
227         1, 0.85,  0,  0.9,   0,
228         0
229 };
230
231
232 double const dline3[] = {
233         1, 0.1,   0.1,   0.15,  0.15,
234         1, 0.475, 0.475, 0.525, 0.525,
235         1, 0.85,  0.85,  0.9,   0.9,
236         0
237 };
238
239
240 double const hlinesmall[] = {
241         1, 0.4, 0.5, 0.6, 0.5,
242         0
243 };
244
245
246 double const ring[] = {
247         2, 5,
248         0.5, 0.8,  0.8, 0.5,  0.5, 0.2,  0.2, 0.5,  0.5, 0.8,
249         0
250 };
251
252
253 double const vert[] = {
254         1, 0.5, 0.05,  0.5, 0.95,
255         0
256 };
257
258
259 double const  Vert[] = {
260         1, 0.3, 0.05,  0.3, 0.95,
261         1, 0.7, 0.05,  0.7, 0.95,
262         0
263 };
264
265
266 double const tilde[] = {
267         2, 4,
268         0.00, 0.8,  0.25, 0.2,  0.75, 0.8,  1.00, 0.2,
269         0
270 };
271
272
273 struct deco_struct {
274         double const * data;
275         int angle;
276 };
277
278 struct named_deco_struct {
279         char const * name;
280         double const * data;
281         int angle;
282 };
283
284 named_deco_struct deco_table[] = {
285         // Decorations
286         {"widehat",             angle,    3 },
287         {"widetilde",           tilde,    0 },
288         {"underbar",            hline,    0 },
289         {"underline",           hline,    0 },
290         {"overline",            hline,    0 },
291         {"underbrace",          brace,    1 },
292         {"overbrace",           brace,    3 },
293         {"overleftarrow",       arrow,    1 },
294         {"overrightarrow",      arrow,    3 },
295         {"overleftrightarrow",  udarrow,  1 },
296         {"xleftarrow",          arrow,    1 },
297         {"xrightarrow",         arrow,    3 },
298         {"underleftarrow",      arrow,    1 },
299         {"underrightarrow",     arrow,    3 },
300         {"underleftrightarrow", udarrow,  1 },
301         {"undertilde",          tilde,    0 },
302         {"utilde",              tilde,    0 },
303
304         // Delimiters
305         {"(",              parenth,    0 },
306         {")",              parenth,    2 },
307         {"{",              brace,      0 },
308         {"}",              brace,      2 },
309         {"lbrace",         brace,      0 },
310         {"rbrace",         brace,      2 },
311         {"[",              brack,      0 },
312         {"]",              brack,      2 },
313         {"llbracket",      dbrack,     0 },
314         {"rrbracket",      dbrack,     2 },
315         {"|",              vert,       0 },
316         {"/",              slash,      0 },
317         {"slash",          slash,      0 },
318         {"vert",           vert,       0 },
319         {"lvert",          vert,       0 },
320         {"rvert",          vert,       0 },
321         {"Vert",           Vert,       0 },
322         {"lVert",          Vert,       0 },
323         {"rVert",          Vert,       0 },
324         {"'",              slash,      1 },
325         {"<",              angle,      0 },
326         {">",              angle,      2 },
327         {"\\",             slash,      1 },
328         {"backslash",      slash,      1 },
329         {"langle",         angle,      0 },
330         {"lceil",          corner,     0 },
331         {"lfloor",         corner,     1 },
332         {"rangle",         angle,      2 },
333         {"rceil",          corner,     3 },
334         {"rfloor",         corner,     2 },
335         {"downarrow",      arrow,      2 },
336         {"Downarrow",      Arrow,      2 },
337         {"uparrow",        arrow,      0 },
338         {"Uparrow",        Arrow,      0 },
339         {"updownarrow",    udarrow,    0 },
340         {"Updownarrow",    Udarrow,    0 },
341
342         // Accents
343         {"ddot",           ddot,       0 },
344         {"dddot",          dddot,      0 },
345         {"ddddot",         ddddot,     0 },
346         {"hat",            angle,      3 },
347         {"grave",          slash,      1 },
348         {"acute",          slash,      0 },
349         {"tilde",          tilde,      0 },
350         {"bar",            hline,      0 },
351         {"dot",            hlinesmall, 0 },
352         {"check",          angle,      1 },
353         {"breve",          parenth,    1 },
354         {"vec",            arrow,      3 },
355         {"mathring",       ring,       0 },
356
357         // Dots
358         {"dots",           hline3,     0 },
359         {"ldots",          hline3,     0 },
360         {"cdots",          hline3,     0 },
361         {"vdots",          hline3,     1 },
362         {"ddots",          dline3,     0 },
363         {"adots",          dline3,     1 },
364         {"iddots",         dline3,     1 },
365         {"dotsb",          hline3,     0 },
366         {"dotsc",          hline3,     0 },
367         {"dotsi",          hline3,     0 },
368         {"dotsm",          hline3,     0 },
369         {"dotso",          hline3,     0 }
370 };
371
372
373 map<docstring, deco_struct> deco_list;
374
375 // sort the table on startup
376 class init_deco_table {
377 public:
378         init_deco_table() {
379                 unsigned const n = sizeof(deco_table) / sizeof(deco_table[0]);
380                 for (named_deco_struct * p = deco_table; p != deco_table + n; ++p) {
381                         deco_struct d;
382                         d.data  = p->data;
383                         d.angle = p->angle;
384                         deco_list[from_ascii(p->name)] = d;
385                 }
386         }
387 };
388
389 static init_deco_table dummy;
390
391
392 deco_struct const * search_deco(docstring const & name)
393 {
394         map<docstring, deco_struct>::const_iterator p = deco_list.find(name);
395         return p == deco_list.end() ? 0 : &(p->second);
396 }
397
398
399 } // namespace anon
400
401
402 int mathed_char_width(FontInfo const & font, char_type c)
403 {
404         return theFontMetrics(font).width(c);
405 }
406
407
408 int mathed_char_kerning(FontInfo const & font, char_type c)
409 {
410         frontend::FontMetrics const & fm = theFontMetrics(font);
411         return fm.rbearing(c) - fm.width(c);
412 }
413
414
415 void mathed_string_dim(FontInfo const & font,
416                        docstring const & s,
417                        Dimension & dim)
418 {
419         frontend::FontMetrics const & fm = theFontMetrics(font);
420         dim.asc = 0;
421         dim.des = 0;
422         for (docstring::const_iterator it = s.begin();
423              it != s.end();
424              ++it) {
425                 dim.asc = max(dim.asc, fm.ascent(*it));
426                 dim.des = max(dim.des, fm.descent(*it));
427         }
428         dim.wid = fm.width(s);
429 }
430
431
432 int mathed_string_width(FontInfo const & font, docstring const & s)
433 {
434         return theFontMetrics(font).width(s);
435 }
436
437
438 void mathed_draw_deco(PainterInfo & pi, int x, int y, int w, int h,
439         docstring const & name)
440 {
441         if (name == ".") {
442                 pi.pain.line(x + w/2, y, x + w/2, y + h,
443                           Color_cursor, Painter::line_onoffdash);
444                 return;
445         }
446
447         deco_struct const * mds = search_deco(name);
448         if (!mds) {
449                 lyxerr << "Deco was not found. Programming error?" << endl;
450                 lyxerr << "name: '" << to_utf8(name) << "'" << endl;
451                 return;
452         }
453
454         int const n = (w < h) ? w : h;
455         int const r = mds->angle;
456         double const * d = mds->data;
457
458         if (h > 70 && (name == "(" || name == ")"))
459                 d = parenthHigh;
460
461         Matrix mt(r, w, h);
462         Matrix sqmt(r, n, n);
463
464         if (r > 0 && r < 3)
465                 y += h;
466
467         if (r >= 2)
468                 x += w;
469
470         for (int i = 0; d[i]; ) {
471                 int code = int(d[i++]);
472                 if (code & 1) {  // code == 1 || code == 3
473                         double xx = d[i++];
474                         double yy = d[i++];
475                         double x2 = d[i++];
476                         double y2 = d[i++];
477                         if (code == 3)
478                                 sqmt.transform(xx, yy);
479                         else
480                                 mt.transform(xx, yy);
481                         mt.transform(x2, y2);
482                         pi.pain.line(
483                                 int(x + xx + 0.5), int(y + yy + 0.5),
484                                 int(x + x2 + 0.5), int(y + y2 + 0.5),
485                                 pi.base.font.color());
486                 } else {
487                         int xp[32];
488                         int yp[32];
489                         int const n = int(d[i++]);
490                         for (int j = 0; j < n; ++j) {
491                                 double xx = d[i++];
492                                 double yy = d[i++];
493 //           lyxerr << ' ' << xx << ' ' << yy << ' ';
494                                 if (code == 4)
495                                         sqmt.transform(xx, yy);
496                                 else
497                                         mt.transform(xx, yy);
498                                 xp[j] = int(x + xx + 0.5);
499                                 yp[j] = int(y + yy + 0.5);
500                                 //  lyxerr << "P[" << j ' ' << xx << ' ' << yy << ' ' << x << ' ' << y << ']';
501                         }
502                         pi.pain.lines(xp, yp, n, pi.base.font.color());
503                 }
504         }
505 }
506
507
508 void metricsStrRedBlack(MetricsInfo & mi, Dimension & dim, docstring const & str)
509 {
510         FontInfo font = mi.base.font;
511         augmentFont(font, from_ascii("mathnormal"));
512         mathed_string_dim(font, str, dim);
513 }
514
515
516 void drawStrRed(PainterInfo & pi, int x, int y, docstring const & str)
517 {
518         FontInfo f = pi.base.font;
519         augmentFont(f, from_ascii("mathnormal"));
520         f.setColor(Color_latex);
521         pi.pain.text(x, y, str, f);
522 }
523
524
525 void drawStrBlack(PainterInfo & pi, int x, int y, docstring const & str)
526 {
527         FontInfo f = pi.base.font;
528         augmentFont(f, from_ascii("mathnormal"));
529         f.setColor(Color_foreground);
530         pi.pain.text(x, y, str, f);
531 }
532
533
534 void math_font_max_dim(FontInfo const & font, int & asc, int & des)
535 {
536         frontend::FontMetrics const & fm = theFontMetrics(font);
537         asc = fm.maxAscent();
538         des = fm.maxDescent();
539 }
540
541
542 struct fontinfo {
543         string cmd_;
544         FontFamily family_;
545         FontSeries series_;
546         FontShape  shape_;
547         ColorCode        color_;
548 };
549
550
551 FontFamily const inh_family = INHERIT_FAMILY;
552 FontSeries const inh_series = INHERIT_SERIES;
553 FontShape  const inh_shape  = INHERIT_SHAPE;
554
555
556 // mathnormal should be the first, otherwise the fallback further down
557 // does not work
558 fontinfo fontinfos[] = {
559         // math fonts
560         {"mathnormal",    ROMAN_FAMILY, MEDIUM_SERIES,
561                           ITALIC_SHAPE, Color_math},
562         {"mathbf",        inh_family, BOLD_SERIES,
563                           inh_shape, Color_math},
564         {"mathcal",       CMSY_FAMILY, inh_series,
565                           inh_shape, Color_math},
566         {"mathfrak",      EUFRAK_FAMILY, inh_series,
567                           inh_shape, Color_math},
568         {"mathrm",        ROMAN_FAMILY, inh_series,
569                           UP_SHAPE, Color_math},
570         {"mathsf",        SANS_FAMILY, inh_series,
571                           inh_shape, Color_math},
572         {"mathbb",        MSB_FAMILY, inh_series,
573                           inh_shape, Color_math},
574         {"mathtt",        TYPEWRITER_FAMILY, inh_series,
575                           inh_shape, Color_math},
576         {"mathit",        inh_family, inh_series,
577                           ITALIC_SHAPE, Color_math},
578         {"mathscr",       RSFS_FAMILY, inh_series,
579                           inh_shape, Color_math},
580         {"cmex",          CMEX_FAMILY, inh_series,
581                           inh_shape, Color_math},
582         {"cmm",           CMM_FAMILY, inh_series,
583                           inh_shape, Color_math},
584         {"cmr",           CMR_FAMILY, inh_series,
585                           inh_shape, Color_math},
586         {"cmsy",          CMSY_FAMILY, inh_series,
587                           inh_shape, Color_math},
588         {"eufrak",        EUFRAK_FAMILY, inh_series,
589                           inh_shape, Color_math},
590         {"msa",           MSA_FAMILY, inh_series,
591                           inh_shape, Color_math},
592         {"msb",           MSB_FAMILY, inh_series,
593                           inh_shape, Color_math},
594         {"stmry",         STMARY_FAMILY, inh_series,
595                           inh_shape, Color_math},
596         {"wasy",          WASY_FAMILY, inh_series,
597                           inh_shape, Color_math},
598         {"esint",         ESINT_FAMILY, inh_series,
599                           inh_shape, Color_math},
600
601         // Text fonts
602         {"text",          inh_family, inh_series,
603                           inh_shape, Color_foreground},
604         {"textbf",        inh_family, BOLD_SERIES,
605                           inh_shape, Color_foreground},
606         {"textit",        inh_family, inh_series,
607                           ITALIC_SHAPE, Color_foreground},
608         {"textmd",        inh_family, MEDIUM_SERIES,
609                           inh_shape, Color_foreground},
610         {"textnormal",    inh_family, inh_series,
611                           UP_SHAPE, Color_foreground},
612         {"textrm",        ROMAN_FAMILY,
613                           inh_series, UP_SHAPE,Color_foreground},
614         {"textsc",        inh_family, inh_series,
615                           SMALLCAPS_SHAPE, Color_foreground},
616         {"textsf",        SANS_FAMILY, inh_series,
617                           inh_shape, Color_foreground},
618         {"textsl",        inh_family, inh_series,
619                           SLANTED_SHAPE, Color_foreground},
620         {"texttt",        TYPEWRITER_FAMILY, inh_series,
621                           inh_shape, Color_foreground},
622         {"textup",        inh_family, inh_series,
623                           UP_SHAPE, Color_foreground},
624
625         // TIPA support
626         {"textipa",       inh_family, inh_series,
627                           inh_shape, Color_foreground},
628
629         // mhchem support
630         {"ce",            inh_family, inh_series,
631                           inh_shape, Color_foreground},
632         {"cf",            inh_family, inh_series,
633                           inh_shape, Color_foreground},
634
635         // LyX internal usage
636         {"lyxtex",        inh_family, inh_series,
637                           UP_SHAPE, Color_latex},
638         {"lyxsymbol",     SYMBOL_FAMILY, inh_series,
639                           inh_shape, Color_math},
640         {"lyxboldsymbol", SYMBOL_FAMILY, BOLD_SERIES,
641                           inh_shape, Color_math},
642         {"lyxblacktext",  ROMAN_FAMILY, MEDIUM_SERIES,
643                           UP_SHAPE, Color_foreground},
644         {"lyxnochange",   inh_family, inh_series,
645                           inh_shape, Color_foreground},
646         {"lyxfakebb",     TYPEWRITER_FAMILY, BOLD_SERIES,
647                           UP_SHAPE, Color_math},
648         {"lyxfakecal",    SANS_FAMILY, MEDIUM_SERIES,
649                           ITALIC_SHAPE, Color_math},
650         {"lyxfakefrak",   ROMAN_FAMILY, BOLD_SERIES,
651                           ITALIC_SHAPE, Color_math}
652 };
653
654
655 fontinfo * lookupFont(docstring const & name0)
656 {
657         //lyxerr << "searching font '" << name << "'" << endl;
658         int const n = sizeof(fontinfos) / sizeof(fontinfo);
659         string name = to_utf8(name0);
660         for (int i = 0; i < n; ++i)
661                 if (fontinfos[i].cmd_ == name) {
662                         //lyxerr << "found '" << i << "'" << endl;
663                         return fontinfos + i;
664                 }
665         return 0;
666 }
667
668
669 fontinfo * searchFont(docstring const & name)
670 {
671         fontinfo * f = lookupFont(name);
672         return f ? f : fontinfos;
673         // this should be mathnormal
674         //return searchFont("mathnormal");
675 }
676
677
678 bool isFontName(docstring const & name)
679 {
680         return lookupFont(name);
681 }
682
683
684 bool isMathFont(docstring const & name)
685 {
686         fontinfo * f = lookupFont(name);
687         return f && f->color_ == Color_math;
688 }
689
690
691 bool isTextFont(docstring const & name)
692 {
693         fontinfo * f = lookupFont(name);
694         return f && f->color_ == Color_foreground;
695 }
696
697
698 FontInfo getFont(docstring const & name)
699 {
700         FontInfo font;
701         augmentFont(font, name);
702         return font;
703 }
704
705
706 void fakeFont(docstring const & orig, docstring const & fake)
707 {
708         fontinfo * forig = searchFont(orig);
709         fontinfo * ffake = searchFont(fake);
710         if (forig && ffake) {
711                 forig->family_ = ffake->family_;
712                 forig->series_ = ffake->series_;
713                 forig->shape_  = ffake->shape_;
714                 forig->color_  = ffake->color_;
715         } else {
716                 lyxerr << "Can't fake font '" << to_utf8(orig) << "' with '"
717                        << to_utf8(fake) << "'" << endl;
718         }
719 }
720
721
722 void augmentFont(FontInfo & font, docstring const & name)
723 {
724         static bool initialized = false;
725         if (!initialized) {
726                 initialized = true;
727                 // fake fonts if necessary
728                 if (!theFontLoader().available(getFont(from_ascii("mathfrak"))))
729                         fakeFont(from_ascii("mathfrak"), from_ascii("lyxfakefrak"));
730                 if (!theFontLoader().available(getFont(from_ascii("mathcal"))))
731                         fakeFont(from_ascii("mathcal"), from_ascii("lyxfakecal"));
732         }
733         fontinfo * info = searchFont(name);
734         if (info->family_ != inh_family)
735                 font.setFamily(info->family_);
736         if (info->series_ != inh_series)
737                 font.setSeries(info->series_);
738         if (info->shape_ != inh_shape)
739                 font.setShape(info->shape_);
740         if (info->color_ != Color_none)
741                 font.setColor(info->color_);
742 }
743
744
745 bool isAlphaSymbol(MathAtom const & at)
746 {
747         if (at->asCharInset() ||
748             (at->asSymbolInset() &&
749              at->asSymbolInset()->isOrdAlpha()))
750                 return true;
751
752         if (at->asFontInset()) {
753                 MathData const & ar = at->asFontInset()->cell(0);
754                 for (size_t i = 0; i < ar.size(); ++i) {
755                         if (!(ar[i]->asCharInset() ||
756                               (ar[i]->asSymbolInset() &&
757                                ar[i]->asSymbolInset()->isOrdAlpha())))
758                                 return false;
759                 }
760                 return true;
761         }
762         return false;
763 }
764
765
766 docstring asString(MathData const & ar)
767 {
768         odocstringstream os;
769         WriteStream ws(os);
770         ws << ar;
771         return os.str();
772 }
773
774
775 void asArray(docstring const & str, MathData & ar, Parse::flags pf)
776 {
777         bool quiet = pf & Parse::QUIET;
778         if ((str.size() == 1 && quiet) || (!mathed_parse_cell(ar, str, pf) && quiet))
779                 mathed_parse_cell(ar, str, pf | Parse::VERBATIM);
780 }
781
782
783 docstring asString(InsetMath const & inset)
784 {
785         odocstringstream os;
786         WriteStream ws(os);
787         inset.write(ws);
788         return os.str();
789 }
790
791
792 docstring asString(MathAtom const & at)
793 {
794         odocstringstream os;
795         WriteStream ws(os);
796         at->write(ws);
797         return os.str();
798 }
799
800
801 } // namespace lyx