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