2 * \file MathSupport.cpp
3 * This file is part of LyX, the document processor.
4 * Licence details can be found in the file COPYING.
6 * \author Alejandro Aguilar Sierra
9 * Full author contact details are available in file CREDITS.
14 #include "MathSupport.h"
16 #include "InsetMathFont.h"
17 #include "InsetMathSymbol.h"
19 #include "MathFactory.h"
20 #include "MathParser.h"
21 #include "MathStream.h"
23 #include "LaTeXFeatures.h"
24 #include "MetricsInfo.h"
26 #include "frontends/FontLoader.h"
27 #include "frontends/FontMetrics.h"
28 #include "frontends/Painter.h"
30 #include "support/debug.h"
31 #include "support/docstream.h"
32 #include "support/lassert.h"
33 #include "support/Length.h"
34 #include "support/lyxlib.h"
43 using frontend::Painter;
50 Matrix(int, double, double);
52 void transform(double &, double &);
59 Matrix::Matrix(int code, double x, double y)
61 double const cs = (code & 1) ? 0 : (1 - code);
62 double const sn = (code & 1) ? (2 - code) : 0;
70 void Matrix::transform(double & x, double & y)
72 double xx = m_[0][0] * x + m_[0][1] * y;
73 double yy = m_[1][0] * x + m_[1][1] * y;
83 * Internal struct of a drawing: code n x1 y1 ... xn yn, where code is:
84 * 0 = end, 1 = line, 2 = polyline, 3 = square line, 4 = square polyline
85 * 5 = rounded thick line (i.e. dot for short line)
89 double const parenthHigh[] = {
91 0.9840, 0.0014, 0.7143, 0.0323, 0.4603, 0.0772,
92 0.2540, 0.1278, 0.1746, 0.1966, 0.0952, 0.3300,
93 0.0950, 0.5000, 0.0952, 0.6700, 0.1746, 0.8034,
94 0.2540, 0.8722, 0.4603, 0.9228, 0.7143, 0.9677,
100 double const parenth[] = {
102 0.9930, 0.0071, 0.7324, 0.0578, 0.5141, 0.1126,
103 0.3380, 0.1714, 0.2183, 0.2333, 0.0634, 0.3621,
104 0.0141, 0.5000, 0.0563, 0.6369, 0.2113, 0.7647,
105 0.3310, 0.8276, 0.5070, 0.8864, 0.7254, 0.9412,
111 double const brace[] = {
113 0.9492, 0.0020, 0.9379, 0.0020, 0.7458, 0.0243,
114 0.5819, 0.0527, 0.4859, 0.0892, 0.4463, 0.1278,
115 0.4463, 0.3732, 0.4011, 0.4199, 0.2712, 0.4615,
116 0.0734, 0.4919, 0.0113, 0.5000, 0.0734, 0.5081,
117 0.2712, 0.5385, 0.4011, 0.5801, 0.4463, 0.6268,
118 0.4463, 0.8722, 0.4859, 0.9108, 0.5819, 0.9473,
119 0.7458, 0.9757, 0.9379, 0.9980, 0.9492, 0.9980,
124 double const mapsto[] = {
126 0.75, 0.015, 0.95, 0.5, 0.75, 0.985,
127 1, 0.015, 0.475, 0.945, 0.475,
128 1, 0.015, 0.015, 0.015, 0.985,
133 double const lhook[] = {
135 0.25, 0.015, 0.05, 0.5, 0.25, 0.985,
136 1, 0.015, 0.475, 0.7, 0.475,
138 0.7, 0.015, 0.825, 0.15, 0.985, 0.25,
139 0.825, 0.35, 0.7, 0.475,
144 double const rhook[] = {
146 0.75, 0.015, 0.95, 0.5, 0.75, 0.985,
147 1, 0.3, 0.475, 0.985, 0.475,
149 0.3, 0.015, 0.175, 0.15, 0.05, 0.25,
150 0.175, 0.35, 0.3, 0.475,
155 double const LRArrow[] = {
157 0.25, 0.015, 0.05, 0.5, 0.25, 0.985,
159 0.75, 0.015, 0.95, 0.5, 0.75, 0.985,
160 1, 0.2, 0.8, 0.8, 0.8,
161 1, 0.2, 0.2, 0.8, 0.2,
166 double const LArrow[] = {
168 0.25, 0.015, 0.05, 0.5, 0.25, 0.985,
169 1, 0.2, 0.8, 0.985, 0.8,
170 1, 0.2, 0.2, 0.985, 0.2,
175 double const lharpoondown[] = {
177 0.015, 0.5, 0.25, 0.985,
178 1, 0.02, 0.475, 0.985, 0.475,
183 double const lharpoonup[] = {
185 0.25, 0.015, 0.015, 0.5,
186 1, 0.02, 0.525, 0.985, 0.525,
191 double const lrharpoons[] = {
193 0.25, 0.015, 0.015, 0.225,
194 1, 0.02, 0.23, 0.985, 0.23,
196 0.75, 0.985, 0.985, 0.775,
197 1, 0.02, 0.7, 0.980, 0.7,
202 double const rlharpoons[] = {
204 0.75, 0.015, 0.985, 0.225,
205 1, 0.02, 0.23, 0.985, 0.23,
207 0.25, 0.985, 0.015, 0.775,
208 1, 0.02, 0.7, 0.980, 0.7,
213 double const arrow[] = {
215 0.0150, 0.7500, 0.2000, 0.6000, 0.3500, 0.3500,
216 0.5000, 0.0500, 0.6500, 0.3500, 0.8000, 0.6000,
218 3, 0.5000, 0.1500, 0.5000, 0.9500,
223 double const Arrow[] = {
225 0.0150, 0.7500, 0.2000, 0.6000, 0.3500, 0.3500,
226 0.5000, 0.0500, 0.6500, 0.3500, 0.8000, 0.6000,
228 3, 0.3500, 0.5000, 0.3500, 0.9500,
229 3, 0.6500, 0.5000, 0.6500, 0.9500,
234 double const udarrow[] = {
236 0.015, 0.25, 0.5, 0.05, 0.95, 0.25,
238 0.015, 0.75, 0.5, 0.95, 0.95, 0.75,
239 1, 0.5, 0.1, 0.5, 0.9,
244 double const Udarrow[] = {
246 0.015, 0.25, 0.5, 0.05, 0.95, 0.25,
248 0.015, 0.75, 0.5, 0.95, 0.95, 0.75,
249 1, 0.35, 0.2, 0.35, 0.8,
250 1, 0.65, 0.2, 0.65, 0.8,
255 double const brack[] = {
257 0.95, 0.05, 0.05, 0.05, 0.05, 0.95, 0.95, 0.95,
262 double const dbrack[] = {
264 0.95, 0.05, 0.05, 0.05, 0.05, 0.95, 0.95, 0.95,
266 0.50, 0.05, 0.50, 0.95,
271 double const corner[] = {
273 0.95, 0.05, 0.05, 0.05, 0.05, 0.95,
278 double const angle[] = {
280 1, 0, 0.05, 0.5, 1, 1,
285 double const slash[] = {
286 1, 0.95, 0.05, 0.05, 0.95,
291 double const hline[] = {
292 1, 0.00, 0.5, 1.0, 0.5,
297 double const dot[] = {
298 // 1, 0.5, 0.2, 0.5, 0.2,
299 // 1, 0.4, 0.4, 0.6, 0.4,
300 // 1, 0.5, 0.5, 0.5, 0.5,
301 5, 0.4, 0.4, 0.6, 0.4,
306 double const ddot[] = {
307 5, 0.0, 0.4, 0.3, 0.4,
308 5, 0.6, 0.4, 1.0, 0.4,
313 double const dddot[] = {
314 1, 0.1, 0.5, 0.2, 0.5,
315 1, 0.45, 0.5, 0.55, 0.5,
316 1, 0.8, 0.5, 0.9, 0.5,
321 double const ddddot[] = {
322 1, 0.1, 0.5, 0.2, 0.5,
323 1, 0.45, 0.5, 0.55, 0.5,
324 1, 0.8, 0.5, 0.9, 0.5,
325 1, 1.15, 0.5, 1.25, 0.5,
330 double const hline3[] = {
332 1, 0.475, 0, 0.525, 0,
338 double const dline3[] = {
339 1, 0.1, 0.1, 0.15, 0.15,
340 1, 0.475, 0.475, 0.525, 0.525,
341 1, 0.85, 0.85, 0.9, 0.9,
346 double const ring[] = {
348 0.5, 0.8, 0.8, 0.5, 0.5, 0.2, 0.2, 0.5, 0.5, 0.8,
353 double const vert[] = {
354 1, 0.5, 0.05, 0.5, 0.95,
359 double const Vert[] = {
360 1, 0.3, 0.05, 0.3, 0.95,
361 1, 0.7, 0.05, 0.7, 0.95,
366 double const tilde[] = {
368 0.00, 0.8, 0.25, 0.2, 0.75, 0.8, 1.00, 0.2,
378 struct named_deco_struct {
384 named_deco_struct deco_table[] = {
386 {"widehat", angle, 3 },
387 {"widetilde", tilde, 0 },
388 {"underbar", hline, 0 },
389 {"underline", hline, 0 },
390 {"overline", hline, 0 },
391 {"underbrace", brace, 1 },
392 {"overbrace", brace, 3 },
393 {"overleftarrow", arrow, 1 },
394 {"overrightarrow", arrow, 3 },
395 {"overleftrightarrow", udarrow, 1 },
396 {"xhookleftarrow", lhook, 0 },
397 {"xhookrightarrow", rhook, 0 },
398 {"xleftarrow", arrow, 1 },
399 {"xLeftarrow", LArrow, 0 },
400 {"xleftharpoondown", lharpoondown, 0 },
401 {"xleftharpoonup", lharpoonup, 0 },
402 {"xleftrightharpoons", lrharpoons, 0 },
403 {"xleftrightarrow", udarrow, 1 },
404 {"xLeftrightarrow", LRArrow, 0 },
405 {"xmapsto", mapsto, 0 },
406 {"xrightarrow", arrow, 3 },
407 {"xRightarrow", LArrow, 2 },
408 {"xrightharpoondown", lharpoonup, 2 },
409 {"xrightharpoonup", lharpoondown, 2 },
410 {"xrightleftharpoons", rlharpoons, 0 },
411 {"underleftarrow", arrow, 1 },
412 {"underrightarrow", arrow, 3 },
413 {"underleftrightarrow", udarrow, 1 },
414 {"undertilde", tilde, 0 },
415 {"utilde", tilde, 0 },
422 {"lbrace", brace, 0 },
423 {"rbrace", brace, 2 },
426 {"llbracket", dbrack, 0 },
427 {"rrbracket", dbrack, 2 },
430 {"slash", slash, 0 },
441 {"backslash", slash, 1 },
442 {"langle", angle, 0 },
443 {"lceil", corner, 0 },
444 {"lfloor", corner, 1 },
445 {"rangle", angle, 2 },
446 {"rceil", corner, 3 },
447 {"rfloor", corner, 2 },
448 {"downarrow", arrow, 2 },
449 {"Downarrow", Arrow, 2 },
450 {"uparrow", arrow, 0 },
451 {"Uparrow", Arrow, 0 },
452 {"updownarrow", udarrow, 0 },
453 {"Updownarrow", Udarrow, 0 },
457 {"dddot", dddot, 0 },
458 {"ddddot", ddddot, 0 },
460 {"grave", slash, 1 },
461 {"acute", slash, 0 },
462 {"tilde", tilde, 0 },
465 {"check", angle, 1 },
466 {"breve", parenth, 1 },
468 {"mathring", ring, 0 },
471 {"dots", hline3, 0 },
472 {"ldots", hline3, 0 },
473 {"cdots", hline3, 0 },
474 {"vdots", hline3, 1 },
475 {"ddots", dline3, 0 },
476 {"adots", dline3, 1 },
477 {"iddots", dline3, 1 },
478 {"dotsb", hline3, 0 },
479 {"dotsc", hline3, 0 },
480 {"dotsi", hline3, 0 },
481 {"dotsm", hline3, 0 },
482 {"dotso", hline3, 0 }
486 map<docstring, deco_struct> deco_list;
488 // sort the table on startup
489 class init_deco_table {
492 unsigned const n = sizeof(deco_table) / sizeof(deco_table[0]);
493 for (named_deco_struct * p = deco_table; p != deco_table + n; ++p) {
497 deco_list[from_ascii(p->name)] = d;
502 static init_deco_table dummy_deco_table;
505 deco_struct const * search_deco(docstring const & name)
507 map<docstring, deco_struct>::const_iterator p = deco_list.find(name);
508 return p == deco_list.end() ? 0 : &(p->second);
515 int mathed_font_em(FontInfo const & font)
517 return theFontMetrics(font).em();
521 int mathed_font_x_height(FontInfo const & font)
523 return theFontMetrics(font).xHeight();
526 /* The math units. Quoting TeX by Topic, p.205:
528 * Spacing around mathematical objects is measured in mu units. A mu
529 * is 1/18th part of \fontdimen6 of the font in family 2 in the
530 * current style, the ‘quad’ value of the symbol font.
532 * A \thickmuskip (default value in plain TeX: 5mu plus 5mu) is
533 * inserted around (binary) relations, except where these are preceded
534 * or followed by other relations or punctuation, and except if they
535 * follow an open, or precede a close symbol.
537 * A \medmuskip (default value in plain TeX: 4mu plus 2mu minus 4mu)
538 * is put around binary operators.
540 * A \thinmuskip (default value in plain TeX: 3mu) follows after
541 * punctuation, and is put around inner objects, except where these
542 * are followed by a close or preceded by an open symbol, and except
543 * if the other object is a large operator or a binary relation.
545 * See the file MathClass.cpp for a formal implementation of the rules
549 int mathed_mu(FontInfo const & font, double mu)
551 MetricsBase mb(nullptr, font);
552 return mb.inPixels(Length(mu, Length::MU));
555 int mathed_thinmuskip(FontInfo const & font) { return mathed_mu(font, 3.0); }
556 int mathed_medmuskip(FontInfo const & font) { return mathed_mu(font, 4.0); }
557 int mathed_thickmuskip(FontInfo const & font) { return mathed_mu(font, 5.0); }
560 int mathed_char_width(FontInfo const & font, char_type c)
562 return theFontMetrics(font).width(c);
566 int mathed_char_kerning(FontInfo const & font, char_type c)
568 frontend::FontMetrics const & fm = theFontMetrics(font);
569 return max(0, fm.rbearing(c) - fm.width(c));
573 void mathed_string_dim(FontInfo const & font,
577 frontend::FontMetrics const & fm = theFontMetrics(font);
580 for (docstring::const_iterator it = s.begin();
583 dim.asc = max(dim.asc, fm.ascent(*it));
584 dim.des = max(dim.des, fm.descent(*it));
586 dim.wid = fm.width(s);
590 int mathed_string_width(FontInfo const & font, docstring const & s)
592 return theFontMetrics(font).width(s);
596 void mathed_draw_deco(PainterInfo & pi, int x, int y, int w, int h,
597 docstring const & name)
600 pi.pain.line(x + w/2, y, x + w/2, y + h,
601 Color_cursor, Painter::line_onoffdash);
605 deco_struct const * mds = search_deco(name);
607 lyxerr << "Deco was not found. Programming error?" << endl;
608 lyxerr << "name: '" << to_utf8(name) << "'" << endl;
612 int const n = (w < h) ? w : h;
613 int const r = mds->angle;
614 double const * d = mds->data;
616 if (h > 70 && (name == "(" || name == ")"))
620 Matrix sqmt(r, n, n);
628 for (int i = 0; d[i]; ) {
629 int code = int(d[i++]);
630 if (code & 1) { // code == 1 || code == 3 || code == 5
636 sqmt.transform(xx, yy);
638 mt.transform(xx, yy);
639 mt.transform(x2, y2);
641 int(x + xx + 0.5), int(y + yy + 0.5),
642 int(x + x2 + 0.5), int(y + y2 + 0.5),
643 pi.base.font.color());
644 if (code == 5) { // thicker, but rounded
646 int(x + xx + 0.5+1), int(y + yy + 0.5-1),
647 int(x + x2 + 0.5-1), int(y + y2 + 0.5-1),
648 pi.base.font.color());
650 int(x + xx + 0.5+1), int(y + yy + 0.5+1),
651 int(x + x2 + 0.5-1), int(y + y2 + 0.5+1),
652 pi.base.font.color());
657 int const n2 = int(d[i++]);
658 for (int j = 0; j < n2; ++j) {
661 // lyxerr << ' ' << xx << ' ' << yy << ' ';
663 sqmt.transform(xx, yy);
665 mt.transform(xx, yy);
666 xp[j] = int(x + xx + 0.5);
667 yp[j] = int(y + yy + 0.5);
668 // lyxerr << "P[" << j ' ' << xx << ' ' << yy << ' ' << x << ' ' << y << ']';
670 pi.pain.lines(xp, yp, n2, pi.base.font.color());
676 docstring const & mathedSymbol(MetricsBase & mb, latexkeys const * sym)
678 return (mb.font.style() == DISPLAY_STYLE && !sym->dsp_draw.empty()) ?
679 sym->dsp_draw : sym->draw;
683 int mathedSymbolDim(MetricsBase & mb, Dimension & dim, latexkeys const * sym)
685 LASSERT((bool)sym, return 0);
686 //lyxerr << "metrics: symbol: '" << sym->name
687 // << "' in font: '" << sym->inset
688 // << "' drawn as: '" << sym->draw
691 bool const italic_upcase_greek = sym->inset == "cmr" &&
692 sym->extra == "mathalpha" &&
693 mb.fontname == "mathit";
694 std::string const font = italic_upcase_greek ? "cmm" : sym->inset;
695 bool const change_font = font != "cmr" ||
696 (mb.fontname != "mathbb" &&
697 mb.fontname != "mathds" &&
698 mb.fontname != "mathfrak" &&
699 mb.fontname != "mathcal" &&
700 mb.fontname != "mathscr");
701 Changer dummy = change_font ? mb.changeFontSet(font) : Changer();
702 mathed_string_dim(mb.font, mathedSymbol(mb, sym), dim);
703 return mathed_char_kerning(mb.font, mathedSymbol(mb, sym).back());
707 void mathedSymbolDraw(PainterInfo & pi, int x, int y, latexkeys const * sym)
709 LASSERT((bool)sym, return);
710 //lyxerr << "drawing: symbol: '" << sym->name
711 // << "' in font: '" << sym->inset
712 // << "' drawn as: '" << sym->draw
715 bool const italic_upcase_greek = sym->inset == "cmr" &&
716 sym->extra == "mathalpha" &&
717 pi.base.fontname == "mathit";
718 std::string const font = italic_upcase_greek ? "cmm" : sym->inset;
719 bool const change_font = font != "cmr" ||
720 (pi.base.fontname != "mathbb" &&
721 pi.base.fontname != "mathds" &&
722 pi.base.fontname != "mathfrak" &&
723 pi.base.fontname != "mathcal" &&
724 pi.base.fontname != "mathscr");
725 Changer dummy = change_font ? pi.base.changeFontSet(font) : Changer();
726 pi.draw(x, y, mathedSymbol(pi.base, sym));
730 void metricsStrRedBlack(MetricsInfo & mi, Dimension & dim, docstring const & str)
732 FontInfo font = mi.base.font;
733 augmentFont(font, "mathnormal");
734 mathed_string_dim(font, str, dim);
738 void drawStrRed(PainterInfo & pi, int x, int y, docstring const & str)
740 FontInfo f = pi.base.font;
741 augmentFont(f, "mathnormal");
742 f.setColor(Color_latex);
743 pi.pain.text(x, y, str, f);
747 void drawStrBlack(PainterInfo & pi, int x, int y, docstring const & str)
749 FontInfo f = pi.base.font;
750 augmentFont(f, "mathnormal");
751 f.setColor(Color_foreground);
752 pi.pain.text(x, y, str, f);
756 void math_font_max_dim(FontInfo const & font, int & asc, int & des)
758 frontend::FontMetrics const & fm = theFontMetrics(font);
759 asc = fm.maxAscent();
760 des = fm.maxDescent();
773 FontFamily const inh_family = INHERIT_FAMILY;
774 FontSeries const inh_series = INHERIT_SERIES;
775 FontShape const inh_shape = INHERIT_SHAPE;
778 // mathnormal should be the first, otherwise the fallback further down
780 fontinfo fontinfos[] = {
782 // Color_math determines which fonts are math (see isMathFont)
783 {"mathnormal", ROMAN_FAMILY, MEDIUM_SERIES,
784 ITALIC_SHAPE, Color_math},
785 {"mathbf", inh_family, BOLD_SERIES,
786 inh_shape, Color_math},
787 {"mathcal", CMSY_FAMILY, inh_series,
788 inh_shape, Color_math},
789 {"mathfrak", EUFRAK_FAMILY, inh_series,
790 inh_shape, Color_math},
791 {"mathrm", ROMAN_FAMILY, inh_series,
792 UP_SHAPE, Color_math},
793 {"mathsf", SANS_FAMILY, inh_series,
794 inh_shape, Color_math},
795 {"mathbb", MSB_FAMILY, inh_series,
796 inh_shape, Color_math},
797 {"mathds", DS_FAMILY, inh_series,
798 inh_shape, Color_math},
799 {"mathtt", TYPEWRITER_FAMILY, inh_series,
800 inh_shape, Color_math},
801 {"mathit", inh_family, inh_series,
802 ITALIC_SHAPE, Color_math},
803 {"mathscr", RSFS_FAMILY, inh_series,
804 inh_shape, Color_math},
805 {"cmex", CMEX_FAMILY, inh_series,
806 inh_shape, Color_math},
807 {"cmm", CMM_FAMILY, inh_series,
808 inh_shape, Color_math},
809 {"cmr", CMR_FAMILY, inh_series,
810 inh_shape, Color_math},
811 {"cmsy", CMSY_FAMILY, inh_series,
812 inh_shape, Color_math},
813 {"eufrak", EUFRAK_FAMILY, inh_series,
814 inh_shape, Color_math},
815 {"msa", MSA_FAMILY, inh_series,
816 inh_shape, Color_math},
817 {"msb", MSB_FAMILY, inh_series,
818 inh_shape, Color_math},
819 {"stmry", STMARY_FAMILY, inh_series,
820 inh_shape, Color_math},
821 {"wasy", WASY_FAMILY, inh_series,
822 inh_shape, Color_math},
823 {"esint", ESINT_FAMILY, inh_series,
824 inh_shape, Color_math},
827 {"text", inh_family, inh_series,
828 inh_shape, Color_foreground},
829 {"textbf", inh_family, BOLD_SERIES,
830 inh_shape, Color_foreground},
831 {"textit", inh_family, inh_series,
832 ITALIC_SHAPE, Color_foreground},
833 {"textmd", inh_family, MEDIUM_SERIES,
834 inh_shape, Color_foreground},
835 {"textnormal", inh_family, inh_series,
836 UP_SHAPE, Color_foreground},
837 {"textrm", ROMAN_FAMILY,
838 inh_series, UP_SHAPE,Color_foreground},
839 {"textsc", inh_family, inh_series,
840 SMALLCAPS_SHAPE, Color_foreground},
841 {"textsf", SANS_FAMILY, inh_series,
842 inh_shape, Color_foreground},
843 {"textsl", inh_family, inh_series,
844 SLANTED_SHAPE, Color_foreground},
845 {"texttt", TYPEWRITER_FAMILY, inh_series,
846 inh_shape, Color_foreground},
847 {"textup", inh_family, inh_series,
848 UP_SHAPE, Color_foreground},
851 {"textipa", inh_family, inh_series,
852 inh_shape, Color_foreground},
855 {"ce", inh_family, inh_series,
856 inh_shape, Color_foreground},
857 {"cf", inh_family, inh_series,
858 inh_shape, Color_foreground},
860 // LyX internal usage
861 {"lyxtex", inh_family, inh_series,
862 UP_SHAPE, Color_latex},
863 // FIXME: The following two don't work on OS X, since the Symbol font
864 // uses a different encoding, and is therefore disabled in
865 // FontLoader::available().
866 {"lyxsymbol", SYMBOL_FAMILY, inh_series,
867 inh_shape, Color_math},
868 {"lyxboldsymbol", SYMBOL_FAMILY, BOLD_SERIES,
869 inh_shape, Color_math},
870 {"lyxblacktext", ROMAN_FAMILY, MEDIUM_SERIES,
871 UP_SHAPE, Color_foreground},
872 {"lyxnochange", inh_family, inh_series,
873 inh_shape, Color_foreground},
874 {"lyxfakebb", TYPEWRITER_FAMILY, BOLD_SERIES,
875 UP_SHAPE, Color_math},
876 {"lyxfakecal", SANS_FAMILY, MEDIUM_SERIES,
877 ITALIC_SHAPE, Color_math},
878 {"lyxfakefrak", ROMAN_FAMILY, BOLD_SERIES,
879 ITALIC_SHAPE, Color_math}
883 fontinfo * lookupFont(string const & name)
885 //lyxerr << "searching font '" << name << "'" << endl;
886 int const n = sizeof(fontinfos) / sizeof(fontinfo);
887 for (int i = 0; i < n; ++i)
888 if (fontinfos[i].cmd_ == name) {
889 //lyxerr << "found '" << i << "'" << endl;
890 return fontinfos + i;
896 fontinfo * searchFont(string const & name)
898 fontinfo * f = lookupFont(name);
899 return f ? f : fontinfos;
900 // this should be mathnormal
901 //return searchFont("mathnormal");
905 bool isFontName(string const & name)
907 return lookupFont(name);
911 bool isMathFont(string const & name)
913 fontinfo * f = lookupFont(name);
914 return f && f->color_ == Color_math;
918 bool isTextFont(string const & name)
920 fontinfo * f = lookupFont(name);
921 return f && f->color_ == Color_foreground;
925 FontInfo getFont(string const & name)
928 augmentFont(font, name);
933 void fakeFont(string const & orig, string const & fake)
935 fontinfo * forig = searchFont(orig);
936 fontinfo * ffake = searchFont(fake);
937 if (forig && ffake) {
938 forig->family_ = ffake->family_;
939 forig->series_ = ffake->series_;
940 forig->shape_ = ffake->shape_;
941 forig->color_ = ffake->color_;
943 lyxerr << "Can't fake font '" << orig << "' with '"
944 << fake << "'" << endl;
949 void augmentFont(FontInfo & font, string const & name)
951 static bool initialized = false;
954 // fake fonts if necessary
955 if (!theFontLoader().available(getFont("mathfrak")))
956 fakeFont("mathfrak", "lyxfakefrak");
957 if (!theFontLoader().available(getFont("mathcal")))
958 fakeFont("mathcal", "lyxfakecal");
960 fontinfo * info = searchFont(name);
961 if (info->family_ != inh_family)
962 font.setFamily(info->family_);
963 if (info->series_ != inh_series)
964 font.setSeries(info->series_);
965 if (info->shape_ != inh_shape)
966 font.setShape(info->shape_);
967 if (info->color_ != Color_none)
968 font.setColor(info->color_);
972 bool isAlphaSymbol(MathAtom const & at)
974 if (at->asCharInset() ||
975 (at->asSymbolInset() &&
976 at->asSymbolInset()->isOrdAlpha()))
979 if (at->asFontInset()) {
980 MathData const & ar = at->asFontInset()->cell(0);
981 for (size_t i = 0; i < ar.size(); ++i) {
982 if (!(ar[i]->asCharInset() ||
983 (ar[i]->asSymbolInset() &&
984 ar[i]->asSymbolInset()->isOrdAlpha())))
993 docstring asString(MathData const & ar)
996 otexrowstream ots(os);
1003 void asArray(docstring const & str, MathData & ar, Parse::flags pf)
1005 // If the QUIET flag is set, we are going to parse for either
1006 // a paste operation or a macro definition. We try to do the
1007 // right thing in all cases.
1009 bool quiet = pf & Parse::QUIET;
1010 bool macro = pf & Parse::MACRODEF;
1011 if ((str.size() == 1 && quiet) || (!mathed_parse_cell(ar, str, pf) && quiet && !macro))
1012 mathed_parse_cell(ar, str, pf | Parse::VERBATIM);
1016 docstring asString(InsetMath const & inset)
1018 odocstringstream os;
1019 otexrowstream ots(os);
1020 WriteStream ws(ots);
1026 docstring asString(MathAtom const & at)
1028 odocstringstream os;
1029 otexrowstream ots(os);
1030 WriteStream ws(ots);
1036 int axis_height(MetricsBase & mb)
1038 Changer dummy = mb.changeFontSet("mathnormal");
1039 return theFontMetrics(mb.font).ascent('-') - 1;
1043 void validate_math_word(LaTeXFeatures & features, docstring const & word)
1045 MathWordList const & words = mathedWordList();
1046 MathWordList::const_iterator it = words.find(word);
1047 if (it != words.end()) {
1048 string const req = it->second.required;
1050 features.require(req);