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/Changer.h"
31 #include "support/debug.h"
32 #include "support/docstream.h"
33 #include "support/lassert.h"
34 #include "support/Length.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 (char_type const c : s) {
581 dim.asc = max(dim.asc, fm.ascent(c));
582 dim.des = max(dim.des, fm.descent(c));
584 dim.wid = fm.width(s);
588 int mathed_string_width(FontInfo const & font, docstring const & s)
590 return theFontMetrics(font).width(s);
594 void mathed_draw_deco(PainterInfo & pi, int x, int y, int w, int h,
595 docstring const & name)
598 pi.pain.line(x + w/2, y, x + w/2, y + h,
599 Color_cursor, Painter::line_onoffdash);
603 deco_struct const * mds = search_deco(name);
605 lyxerr << "Deco was not found. Programming error?" << endl;
606 lyxerr << "name: '" << to_utf8(name) << "'" << endl;
610 int const n = (w < h) ? w : h;
611 int const r = mds->angle;
612 double const * d = mds->data;
614 if (h > 70 && (name == "(" || name == ")"))
618 Matrix sqmt(r, n, n);
626 for (int i = 0; d[i]; ) {
627 int code = int(d[i++]);
628 if (code & 1) { // code == 1 || code == 3 || code == 5
634 sqmt.transform(xx, yy);
636 mt.transform(xx, yy);
637 mt.transform(x2, y2);
639 int(x + xx + 0.5), int(y + yy + 0.5),
640 int(x + x2 + 0.5), int(y + y2 + 0.5),
641 pi.base.font.color());
642 if (code == 5) { // thicker, but rounded
644 int(x + xx + 0.5+1), int(y + yy + 0.5-1),
645 int(x + x2 + 0.5-1), int(y + y2 + 0.5-1),
646 pi.base.font.color());
648 int(x + xx + 0.5+1), int(y + yy + 0.5+1),
649 int(x + x2 + 0.5-1), int(y + y2 + 0.5+1),
650 pi.base.font.color());
655 int const n2 = int(d[i++]);
656 for (int j = 0; j < n2; ++j) {
659 // lyxerr << ' ' << xx << ' ' << yy << ' ';
661 sqmt.transform(xx, yy);
663 mt.transform(xx, yy);
664 xp[j] = int(x + xx + 0.5);
665 yp[j] = int(y + yy + 0.5);
666 // lyxerr << "P[" << j ' ' << xx << ' ' << yy << ' ' << x << ' ' << y << ']';
668 pi.pain.lines(xp, yp, n2, pi.base.font.color());
674 docstring const & mathedSymbol(MetricsBase & mb, latexkeys const * sym)
676 return (mb.font.style() == DISPLAY_STYLE && !sym->dsp_draw.empty()) ?
677 sym->dsp_draw : sym->draw;
681 int mathedSymbolDim(MetricsBase & mb, Dimension & dim, latexkeys const * sym)
683 LASSERT((bool)sym, return 0);
684 //lyxerr << "metrics: symbol: '" << sym->name
685 // << "' in font: '" << sym->inset
686 // << "' drawn as: '" << sym->draw
689 bool const italic_upcase_greek = sym->inset == "cmr" &&
690 sym->extra == "mathalpha" &&
691 mb.fontname == "mathit";
692 std::string const font = italic_upcase_greek ? "cmm" : sym->inset;
693 bool const change_font = font != "cmr" ||
694 (mb.fontname != "mathbb" &&
695 mb.fontname != "mathds" &&
696 mb.fontname != "mathfrak" &&
697 mb.fontname != "mathcal" &&
698 mb.fontname != "mathscr");
699 Changer dummy = change_font ? mb.changeFontSet(font) : noChange();
700 mathed_string_dim(mb.font, mathedSymbol(mb, sym), dim);
701 return mathed_char_kerning(mb.font, mathedSymbol(mb, sym).back());
705 void mathedSymbolDraw(PainterInfo & pi, int x, int y, latexkeys const * sym)
707 LASSERT((bool)sym, return);
708 //lyxerr << "drawing: symbol: '" << sym->name
709 // << "' in font: '" << sym->inset
710 // << "' drawn as: '" << sym->draw
713 bool const italic_upcase_greek = sym->inset == "cmr" &&
714 sym->extra == "mathalpha" &&
715 pi.base.fontname == "mathit";
716 std::string const font = italic_upcase_greek ? "cmm" : sym->inset;
717 bool const change_font = font != "cmr" ||
718 (pi.base.fontname != "mathbb" &&
719 pi.base.fontname != "mathds" &&
720 pi.base.fontname != "mathfrak" &&
721 pi.base.fontname != "mathcal" &&
722 pi.base.fontname != "mathscr");
723 Changer dummy = change_font ? pi.base.changeFontSet(font) : noChange();
724 pi.draw(x, y, mathedSymbol(pi.base, sym));
728 void metricsStrRedBlack(MetricsInfo & mi, Dimension & dim, docstring const & str)
730 FontInfo font = mi.base.font;
731 augmentFont(font, "mathnormal");
732 mathed_string_dim(font, str, dim);
736 void drawStrRed(PainterInfo & pi, int x, int y, docstring const & str)
738 FontInfo f = pi.base.font;
739 augmentFont(f, "mathnormal");
740 f.setColor(Color_latex);
741 pi.pain.text(x, y, str, f);
745 void drawStrBlack(PainterInfo & pi, int x, int y, docstring const & str)
747 FontInfo f = pi.base.font;
748 augmentFont(f, "mathnormal");
749 f.setColor(Color_foreground);
750 pi.pain.text(x, y, str, f);
754 void math_font_max_dim(FontInfo const & font, int & asc, int & des)
756 frontend::FontMetrics const & fm = theFontMetrics(font);
757 asc = fm.maxAscent();
758 des = fm.maxDescent();
771 FontFamily const inh_family = INHERIT_FAMILY;
772 FontSeries const inh_series = INHERIT_SERIES;
773 FontShape const inh_shape = INHERIT_SHAPE;
776 // mathnormal should be the first, otherwise the fallback further down
778 fontinfo fontinfos[] = {
780 // Color_math determines which fonts are math (see isMathFont)
781 {"mathnormal", ROMAN_FAMILY, MEDIUM_SERIES,
782 ITALIC_SHAPE, Color_math},
783 {"mathbf", inh_family, BOLD_SERIES,
784 inh_shape, Color_math},
785 {"mathcal", CMSY_FAMILY, inh_series,
786 inh_shape, Color_math},
787 {"mathfrak", EUFRAK_FAMILY, inh_series,
788 inh_shape, Color_math},
789 {"mathrm", ROMAN_FAMILY, inh_series,
790 UP_SHAPE, Color_math},
791 {"mathsf", SANS_FAMILY, inh_series,
792 inh_shape, Color_math},
793 {"mathbb", MSB_FAMILY, inh_series,
794 inh_shape, Color_math},
795 {"mathds", DS_FAMILY, inh_series,
796 inh_shape, Color_math},
797 {"mathtt", TYPEWRITER_FAMILY, inh_series,
798 inh_shape, Color_math},
799 {"mathit", inh_family, inh_series,
800 ITALIC_SHAPE, Color_math},
801 {"mathscr", RSFS_FAMILY, inh_series,
802 inh_shape, Color_math},
803 {"cmex", CMEX_FAMILY, inh_series,
804 inh_shape, Color_math},
805 {"cmm", CMM_FAMILY, inh_series,
806 inh_shape, Color_math},
807 {"cmr", CMR_FAMILY, inh_series,
808 inh_shape, Color_math},
809 {"cmsy", CMSY_FAMILY, inh_series,
810 inh_shape, Color_math},
811 {"eufrak", EUFRAK_FAMILY, inh_series,
812 inh_shape, Color_math},
813 {"msa", MSA_FAMILY, inh_series,
814 inh_shape, Color_math},
815 {"msb", MSB_FAMILY, inh_series,
816 inh_shape, Color_math},
817 {"stmry", STMARY_FAMILY, inh_series,
818 inh_shape, Color_math},
819 {"wasy", WASY_FAMILY, inh_series,
820 inh_shape, Color_math},
821 {"esint", ESINT_FAMILY, inh_series,
822 inh_shape, Color_math},
825 {"text", inh_family, inh_series,
826 inh_shape, Color_foreground},
827 {"textbf", inh_family, BOLD_SERIES,
828 inh_shape, Color_foreground},
829 {"textit", inh_family, inh_series,
830 ITALIC_SHAPE, Color_foreground},
831 {"textmd", inh_family, MEDIUM_SERIES,
832 inh_shape, Color_foreground},
833 {"textnormal", inh_family, inh_series,
834 UP_SHAPE, Color_foreground},
835 {"textrm", ROMAN_FAMILY,
836 inh_series, UP_SHAPE,Color_foreground},
837 {"textsc", inh_family, inh_series,
838 SMALLCAPS_SHAPE, Color_foreground},
839 {"textsf", SANS_FAMILY, inh_series,
840 inh_shape, Color_foreground},
841 {"textsl", inh_family, inh_series,
842 SLANTED_SHAPE, Color_foreground},
843 {"texttt", TYPEWRITER_FAMILY, inh_series,
844 inh_shape, Color_foreground},
845 {"textup", inh_family, inh_series,
846 UP_SHAPE, Color_foreground},
849 {"textipa", inh_family, inh_series,
850 inh_shape, Color_foreground},
853 {"ce", inh_family, inh_series,
854 inh_shape, Color_foreground},
855 {"cf", inh_family, inh_series,
856 inh_shape, Color_foreground},
858 // LyX internal usage
859 {"lyxtex", inh_family, inh_series,
860 UP_SHAPE, Color_latex},
861 // FIXME: The following two don't work on OS X, since the Symbol font
862 // uses a different encoding, and is therefore disabled in
863 // FontLoader::available().
864 {"lyxsymbol", SYMBOL_FAMILY, inh_series,
865 inh_shape, Color_math},
866 {"lyxboldsymbol", SYMBOL_FAMILY, BOLD_SERIES,
867 inh_shape, Color_math},
868 {"lyxblacktext", ROMAN_FAMILY, MEDIUM_SERIES,
869 UP_SHAPE, Color_foreground},
870 {"lyxnochange", inh_family, inh_series,
871 inh_shape, Color_foreground},
872 {"lyxfakebb", TYPEWRITER_FAMILY, BOLD_SERIES,
873 UP_SHAPE, Color_math},
874 {"lyxfakecal", SANS_FAMILY, MEDIUM_SERIES,
875 ITALIC_SHAPE, Color_math},
876 {"lyxfakefrak", ROMAN_FAMILY, BOLD_SERIES,
877 ITALIC_SHAPE, Color_math}
881 fontinfo * lookupFont(string const & name)
883 //lyxerr << "searching font '" << name << "'" << endl;
884 int const n = sizeof(fontinfos) / sizeof(fontinfo);
885 for (int i = 0; i < n; ++i)
886 if (fontinfos[i].cmd_ == name) {
887 //lyxerr << "found '" << i << "'" << endl;
888 return fontinfos + i;
894 fontinfo * searchFont(string const & name)
896 fontinfo * f = lookupFont(name);
897 return f ? f : fontinfos;
898 // this should be mathnormal
899 //return searchFont("mathnormal");
903 bool isFontName(string const & name)
905 return lookupFont(name);
909 bool isMathFont(string const & name)
911 fontinfo * f = lookupFont(name);
912 return f && f->color_ == Color_math;
916 bool isTextFont(string const & name)
918 fontinfo * f = lookupFont(name);
919 return f && f->color_ == Color_foreground;
923 FontInfo getFont(string const & name)
926 augmentFont(font, name);
931 void fakeFont(string const & orig, string const & fake)
933 fontinfo * forig = searchFont(orig);
934 fontinfo * ffake = searchFont(fake);
935 if (forig && ffake) {
936 forig->family_ = ffake->family_;
937 forig->series_ = ffake->series_;
938 forig->shape_ = ffake->shape_;
939 forig->color_ = ffake->color_;
941 lyxerr << "Can't fake font '" << orig << "' with '"
942 << fake << "'" << endl;
947 void augmentFont(FontInfo & font, string const & name)
949 static bool initialized = false;
952 // fake fonts if necessary
953 if (!theFontLoader().available(getFont("mathfrak")))
954 fakeFont("mathfrak", "lyxfakefrak");
955 if (!theFontLoader().available(getFont("mathcal")))
956 fakeFont("mathcal", "lyxfakecal");
958 fontinfo * info = searchFont(name);
959 if (info->family_ != inh_family)
960 font.setFamily(info->family_);
961 if (info->series_ != inh_series)
962 font.setSeries(info->series_);
963 if (info->shape_ != inh_shape)
964 font.setShape(info->shape_);
965 if (info->color_ != Color_none)
966 font.setColor(info->color_);
970 bool isAlphaSymbol(MathAtom const & at)
972 if (at->asCharInset() ||
973 (at->asSymbolInset() &&
974 at->asSymbolInset()->isOrdAlpha()))
977 if (at->asFontInset()) {
978 MathData const & ar = at->asFontInset()->cell(0);
979 for (size_t i = 0; i < ar.size(); ++i) {
980 if (!(ar[i]->asCharInset() ||
981 (ar[i]->asSymbolInset() &&
982 ar[i]->asSymbolInset()->isOrdAlpha())))
991 docstring asString(MathData const & ar)
994 otexrowstream ots(os);
995 TeXMathStream ws(ots);
1001 void asArray(docstring const & str, MathData & ar, Parse::flags pf)
1003 // If the QUIET flag is set, we are going to parse for either
1004 // a paste operation or a macro definition. We try to do the
1005 // right thing in all cases.
1007 bool quiet = pf & Parse::QUIET;
1008 bool macro = pf & Parse::MACRODEF;
1009 if ((str.size() == 1 && quiet) || (!mathed_parse_cell(ar, str, pf) && quiet && !macro))
1010 mathed_parse_cell(ar, str, pf | Parse::VERBATIM);
1014 docstring asString(InsetMath const & inset)
1016 odocstringstream os;
1017 otexrowstream ots(os);
1018 TeXMathStream ws(ots);
1024 docstring asString(MathAtom const & at)
1026 odocstringstream os;
1027 otexrowstream ots(os);
1028 TeXMathStream ws(ots);
1034 int axis_height(MetricsBase & mb)
1036 Changer dummy = mb.changeFontSet("mathnormal");
1037 return theFontMetrics(mb.font).ascent('-') - 1;
1041 void validate_math_word(LaTeXFeatures & features, docstring const & word)
1043 MathWordList const & words = mathedWordList();
1044 MathWordList::const_iterator it = words.find(word);
1045 if (it != words.end()) {
1046 string const req = it->second.required;
1048 features.require(req);