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"
35 #include "support/lyxlib.h"
44 using frontend::Painter;
51 Matrix(int, double, double);
53 void transform(double &, double &);
60 Matrix::Matrix(int code, double x, double y)
62 double const cs = (code & 1) ? 0 : (1 - code);
63 double const sn = (code & 1) ? (2 - code) : 0;
71 void Matrix::transform(double & x, double & y)
73 double xx = m_[0][0] * x + m_[0][1] * y;
74 double yy = m_[1][0] * x + m_[1][1] * y;
84 * Internal struct of a drawing: code n x1 y1 ... xn yn, where code is:
85 * 0 = end, 1 = line, 2 = polyline, 3 = square line, 4 = square polyline
86 * 5 = rounded thick line (i.e. dot for short line)
90 double const parenthHigh[] = {
92 0.9840, 0.0014, 0.7143, 0.0323, 0.4603, 0.0772,
93 0.2540, 0.1278, 0.1746, 0.1966, 0.0952, 0.3300,
94 0.0950, 0.5000, 0.0952, 0.6700, 0.1746, 0.8034,
95 0.2540, 0.8722, 0.4603, 0.9228, 0.7143, 0.9677,
101 double const parenth[] = {
103 0.9930, 0.0071, 0.7324, 0.0578, 0.5141, 0.1126,
104 0.3380, 0.1714, 0.2183, 0.2333, 0.0634, 0.3621,
105 0.0141, 0.5000, 0.0563, 0.6369, 0.2113, 0.7647,
106 0.3310, 0.8276, 0.5070, 0.8864, 0.7254, 0.9412,
112 double const brace[] = {
114 0.9492, 0.0020, 0.9379, 0.0020, 0.7458, 0.0243,
115 0.5819, 0.0527, 0.4859, 0.0892, 0.4463, 0.1278,
116 0.4463, 0.3732, 0.4011, 0.4199, 0.2712, 0.4615,
117 0.0734, 0.4919, 0.0113, 0.5000, 0.0734, 0.5081,
118 0.2712, 0.5385, 0.4011, 0.5801, 0.4463, 0.6268,
119 0.4463, 0.8722, 0.4859, 0.9108, 0.5819, 0.9473,
120 0.7458, 0.9757, 0.9379, 0.9980, 0.9492, 0.9980,
125 double const mapsto[] = {
127 0.75, 0.015, 0.95, 0.5, 0.75, 0.985,
128 1, 0.015, 0.475, 0.945, 0.475,
129 1, 0.015, 0.015, 0.015, 0.985,
134 double const lhook[] = {
136 0.25, 0.015, 0.05, 0.5, 0.25, 0.985,
137 1, 0.015, 0.475, 0.7, 0.475,
139 0.7, 0.015, 0.825, 0.15, 0.985, 0.25,
140 0.825, 0.35, 0.7, 0.475,
145 double const rhook[] = {
147 0.75, 0.015, 0.95, 0.5, 0.75, 0.985,
148 1, 0.3, 0.475, 0.985, 0.475,
150 0.3, 0.015, 0.175, 0.15, 0.05, 0.25,
151 0.175, 0.35, 0.3, 0.475,
156 double const LRArrow[] = {
158 0.25, 0.015, 0.05, 0.5, 0.25, 0.985,
160 0.75, 0.015, 0.95, 0.5, 0.75, 0.985,
161 1, 0.2, 0.8, 0.8, 0.8,
162 1, 0.2, 0.2, 0.8, 0.2,
167 double const LArrow[] = {
169 0.25, 0.015, 0.05, 0.5, 0.25, 0.985,
170 1, 0.2, 0.8, 0.985, 0.8,
171 1, 0.2, 0.2, 0.985, 0.2,
176 double const lharpoondown[] = {
178 0.015, 0.5, 0.25, 0.985,
179 1, 0.02, 0.475, 0.985, 0.475,
184 double const lharpoonup[] = {
186 0.25, 0.015, 0.015, 0.5,
187 1, 0.02, 0.525, 0.985, 0.525,
192 double const lrharpoons[] = {
194 0.25, 0.015, 0.015, 0.225,
195 1, 0.02, 0.23, 0.985, 0.23,
197 0.75, 0.985, 0.985, 0.775,
198 1, 0.02, 0.7, 0.980, 0.7,
203 double const rlharpoons[] = {
205 0.75, 0.015, 0.985, 0.225,
206 1, 0.02, 0.23, 0.985, 0.23,
208 0.25, 0.985, 0.015, 0.775,
209 1, 0.02, 0.7, 0.980, 0.7,
214 double const arrow[] = {
216 0.0150, 0.7500, 0.2000, 0.6000, 0.3500, 0.3500,
217 0.5000, 0.0500, 0.6500, 0.3500, 0.8000, 0.6000,
219 3, 0.5000, 0.1500, 0.5000, 0.9500,
224 double const Arrow[] = {
226 0.0150, 0.7500, 0.2000, 0.6000, 0.3500, 0.3500,
227 0.5000, 0.0500, 0.6500, 0.3500, 0.8000, 0.6000,
229 3, 0.3500, 0.5000, 0.3500, 0.9500,
230 3, 0.6500, 0.5000, 0.6500, 0.9500,
235 double const udarrow[] = {
237 0.015, 0.25, 0.5, 0.05, 0.95, 0.25,
239 0.015, 0.75, 0.5, 0.95, 0.95, 0.75,
240 1, 0.5, 0.1, 0.5, 0.9,
245 double const Udarrow[] = {
247 0.015, 0.25, 0.5, 0.05, 0.95, 0.25,
249 0.015, 0.75, 0.5, 0.95, 0.95, 0.75,
250 1, 0.35, 0.2, 0.35, 0.8,
251 1, 0.65, 0.2, 0.65, 0.8,
256 double const brack[] = {
258 0.95, 0.05, 0.05, 0.05, 0.05, 0.95, 0.95, 0.95,
263 double const dbrack[] = {
265 0.95, 0.05, 0.05, 0.05, 0.05, 0.95, 0.95, 0.95,
267 0.50, 0.05, 0.50, 0.95,
272 double const corner[] = {
274 0.95, 0.05, 0.05, 0.05, 0.05, 0.95,
279 double const angle[] = {
281 1, 0, 0.05, 0.5, 1, 1,
286 double const slash[] = {
287 1, 0.95, 0.05, 0.05, 0.95,
292 double const hline[] = {
293 1, 0.00, 0.5, 1.0, 0.5,
298 double const dot[] = {
299 // 1, 0.5, 0.2, 0.5, 0.2,
300 // 1, 0.4, 0.4, 0.6, 0.4,
301 // 1, 0.5, 0.5, 0.5, 0.5,
302 5, 0.4, 0.4, 0.6, 0.4,
307 double const ddot[] = {
308 5, 0.0, 0.4, 0.3, 0.4,
309 5, 0.6, 0.4, 1.0, 0.4,
314 double const dddot[] = {
315 1, 0.1, 0.5, 0.2, 0.5,
316 1, 0.45, 0.5, 0.55, 0.5,
317 1, 0.8, 0.5, 0.9, 0.5,
322 double const ddddot[] = {
323 1, 0.1, 0.5, 0.2, 0.5,
324 1, 0.45, 0.5, 0.55, 0.5,
325 1, 0.8, 0.5, 0.9, 0.5,
326 1, 1.15, 0.5, 1.25, 0.5,
331 double const hline3[] = {
333 1, 0.475, 0, 0.525, 0,
339 double const dline3[] = {
340 1, 0.1, 0.1, 0.15, 0.15,
341 1, 0.475, 0.475, 0.525, 0.525,
342 1, 0.85, 0.85, 0.9, 0.9,
347 double const ring[] = {
349 0.5, 0.8, 0.8, 0.5, 0.5, 0.2, 0.2, 0.5, 0.5, 0.8,
354 double const vert[] = {
355 1, 0.5, 0.05, 0.5, 0.95,
360 double const Vert[] = {
361 1, 0.3, 0.05, 0.3, 0.95,
362 1, 0.7, 0.05, 0.7, 0.95,
367 double const tilde[] = {
369 0.00, 0.8, 0.25, 0.2, 0.75, 0.8, 1.00, 0.2,
379 struct named_deco_struct {
385 named_deco_struct deco_table[] = {
387 {"widehat", angle, 3 },
388 {"widetilde", tilde, 0 },
389 {"underbar", hline, 0 },
390 {"underline", hline, 0 },
391 {"overline", hline, 0 },
392 {"underbrace", brace, 1 },
393 {"overbrace", brace, 3 },
394 {"overleftarrow", arrow, 1 },
395 {"overrightarrow", arrow, 3 },
396 {"overleftrightarrow", udarrow, 1 },
397 {"xhookleftarrow", lhook, 0 },
398 {"xhookrightarrow", rhook, 0 },
399 {"xleftarrow", arrow, 1 },
400 {"xLeftarrow", LArrow, 0 },
401 {"xleftharpoondown", lharpoondown, 0 },
402 {"xleftharpoonup", lharpoonup, 0 },
403 {"xleftrightharpoons", lrharpoons, 0 },
404 {"xleftrightarrow", udarrow, 1 },
405 {"xLeftrightarrow", LRArrow, 0 },
406 {"xmapsto", mapsto, 0 },
407 {"xrightarrow", arrow, 3 },
408 {"xRightarrow", LArrow, 2 },
409 {"xrightharpoondown", lharpoonup, 2 },
410 {"xrightharpoonup", lharpoondown, 2 },
411 {"xrightleftharpoons", rlharpoons, 0 },
412 {"underleftarrow", arrow, 1 },
413 {"underrightarrow", arrow, 3 },
414 {"underleftrightarrow", udarrow, 1 },
415 {"undertilde", tilde, 0 },
416 {"utilde", tilde, 0 },
423 {"lbrace", brace, 0 },
424 {"rbrace", brace, 2 },
427 {"llbracket", dbrack, 0 },
428 {"rrbracket", dbrack, 2 },
431 {"slash", slash, 0 },
442 {"backslash", slash, 1 },
443 {"langle", angle, 0 },
444 {"lceil", corner, 0 },
445 {"lfloor", corner, 1 },
446 {"rangle", angle, 2 },
447 {"rceil", corner, 3 },
448 {"rfloor", corner, 2 },
449 {"downarrow", arrow, 2 },
450 {"Downarrow", Arrow, 2 },
451 {"uparrow", arrow, 0 },
452 {"Uparrow", Arrow, 0 },
453 {"updownarrow", udarrow, 0 },
454 {"Updownarrow", Udarrow, 0 },
458 {"dddot", dddot, 0 },
459 {"ddddot", ddddot, 0 },
461 {"grave", slash, 1 },
462 {"acute", slash, 0 },
463 {"tilde", tilde, 0 },
466 {"check", angle, 1 },
467 {"breve", parenth, 1 },
469 {"mathring", ring, 0 },
472 {"dots", hline3, 0 },
473 {"ldots", hline3, 0 },
474 {"cdots", hline3, 0 },
475 {"vdots", hline3, 1 },
476 {"ddots", dline3, 0 },
477 {"adots", dline3, 1 },
478 {"iddots", dline3, 1 },
479 {"dotsb", hline3, 0 },
480 {"dotsc", hline3, 0 },
481 {"dotsi", hline3, 0 },
482 {"dotsm", hline3, 0 },
483 {"dotso", hline3, 0 }
487 map<docstring, deco_struct> deco_list;
489 // sort the table on startup
490 class init_deco_table {
493 unsigned const n = sizeof(deco_table) / sizeof(deco_table[0]);
494 for (named_deco_struct * p = deco_table; p != deco_table + n; ++p) {
498 deco_list[from_ascii(p->name)] = d;
503 static init_deco_table dummy_deco_table;
506 deco_struct const * search_deco(docstring const & name)
508 map<docstring, deco_struct>::const_iterator p = deco_list.find(name);
509 return p == deco_list.end() ? 0 : &(p->second);
516 int mathed_font_em(FontInfo const & font)
518 return theFontMetrics(font).em();
522 int mathed_font_x_height(FontInfo const & font)
524 return theFontMetrics(font).xHeight();
527 /* The math units. Quoting TeX by Topic, p.205:
529 * Spacing around mathematical objects is measured in mu units. A mu
530 * is 1/18th part of \fontdimen6 of the font in family 2 in the
531 * current style, the ‘quad’ value of the symbol font.
533 * A \thickmuskip (default value in plain TeX: 5mu plus 5mu) is
534 * inserted around (binary) relations, except where these are preceded
535 * or followed by other relations or punctuation, and except if they
536 * follow an open, or precede a close symbol.
538 * A \medmuskip (default value in plain TeX: 4mu plus 2mu minus 4mu)
539 * is put around binary operators.
541 * A \thinmuskip (default value in plain TeX: 3mu) follows after
542 * punctuation, and is put around inner objects, except where these
543 * are followed by a close or preceded by an open symbol, and except
544 * if the other object is a large operator or a binary relation.
546 * See the file MathClass.cpp for a formal implementation of the rules
550 int mathed_mu(FontInfo const & font, double mu)
552 MetricsBase mb(nullptr, font);
553 return mb.inPixels(Length(mu, Length::MU));
556 int mathed_thinmuskip(FontInfo const & font) { return mathed_mu(font, 3.0); }
557 int mathed_medmuskip(FontInfo const & font) { return mathed_mu(font, 4.0); }
558 int mathed_thickmuskip(FontInfo const & font) { return mathed_mu(font, 5.0); }
561 int mathed_char_width(FontInfo const & font, char_type c)
563 return theFontMetrics(font).width(c);
567 int mathed_char_kerning(FontInfo const & font, char_type c)
569 frontend::FontMetrics const & fm = theFontMetrics(font);
570 return max(0, fm.rbearing(c) - fm.width(c));
574 void mathed_string_dim(FontInfo const & font,
578 frontend::FontMetrics const & fm = theFontMetrics(font);
581 for (char_type const c : s) {
582 dim.asc = max(dim.asc, fm.ascent(c));
583 dim.des = max(dim.des, fm.descent(c));
585 dim.wid = fm.width(s);
589 int mathed_string_width(FontInfo const & font, docstring const & s)
591 return theFontMetrics(font).width(s);
595 void mathed_draw_deco(PainterInfo & pi, int x, int y, int w, int h,
596 docstring const & name)
599 pi.pain.line(x + w/2, y, x + w/2, y + h,
600 Color_cursor, Painter::line_onoffdash);
604 deco_struct const * mds = search_deco(name);
606 lyxerr << "Deco was not found. Programming error?" << endl;
607 lyxerr << "name: '" << to_utf8(name) << "'" << endl;
611 int const n = (w < h) ? w : h;
612 int const r = mds->angle;
613 double const * d = mds->data;
615 if (h > 70 && (name == "(" || name == ")"))
619 Matrix sqmt(r, n, n);
627 for (int i = 0; d[i]; ) {
628 int code = int(d[i++]);
629 if (code & 1) { // code == 1 || code == 3 || code == 5
635 sqmt.transform(xx, yy);
637 mt.transform(xx, yy);
638 mt.transform(x2, y2);
640 int(x + xx + 0.5), int(y + yy + 0.5),
641 int(x + x2 + 0.5), int(y + y2 + 0.5),
642 pi.base.font.color());
643 if (code == 5) { // thicker, but rounded
645 int(x + xx + 0.5+1), int(y + yy + 0.5-1),
646 int(x + x2 + 0.5-1), int(y + y2 + 0.5-1),
647 pi.base.font.color());
649 int(x + xx + 0.5+1), int(y + yy + 0.5+1),
650 int(x + x2 + 0.5-1), int(y + y2 + 0.5+1),
651 pi.base.font.color());
656 int const n2 = int(d[i++]);
657 for (int j = 0; j < n2; ++j) {
660 // lyxerr << ' ' << xx << ' ' << yy << ' ';
662 sqmt.transform(xx, yy);
664 mt.transform(xx, yy);
665 xp[j] = int(x + xx + 0.5);
666 yp[j] = int(y + yy + 0.5);
667 // lyxerr << "P[" << j ' ' << xx << ' ' << yy << ' ' << x << ' ' << y << ']';
669 pi.pain.lines(xp, yp, n2, pi.base.font.color());
675 docstring const & mathedSymbol(MetricsBase & mb, latexkeys const * sym)
677 return (mb.font.style() == DISPLAY_STYLE && !sym->dsp_draw.empty()) ?
678 sym->dsp_draw : sym->draw;
682 int mathedSymbolDim(MetricsBase & mb, Dimension & dim, latexkeys const * sym)
684 LASSERT((bool)sym, return 0);
685 //lyxerr << "metrics: symbol: '" << sym->name
686 // << "' in font: '" << sym->inset
687 // << "' drawn as: '" << sym->draw
690 bool const italic_upcase_greek = sym->inset == "cmr" &&
691 sym->extra == "mathalpha" &&
692 mb.fontname == "mathit";
693 std::string const font = italic_upcase_greek ? "cmm" : sym->inset;
694 bool const change_font = font != "cmr" ||
695 (mb.fontname != "mathbb" &&
696 mb.fontname != "mathds" &&
697 mb.fontname != "mathfrak" &&
698 mb.fontname != "mathcal" &&
699 mb.fontname != "mathscr");
700 Changer dummy = change_font ? mb.changeFontSet(font) : noChange();
701 mathed_string_dim(mb.font, mathedSymbol(mb, sym), dim);
702 return mathed_char_kerning(mb.font, mathedSymbol(mb, sym).back());
706 void mathedSymbolDraw(PainterInfo & pi, int x, int y, latexkeys const * sym)
708 LASSERT((bool)sym, return);
709 //lyxerr << "drawing: symbol: '" << sym->name
710 // << "' in font: '" << sym->inset
711 // << "' drawn as: '" << sym->draw
714 bool const italic_upcase_greek = sym->inset == "cmr" &&
715 sym->extra == "mathalpha" &&
716 pi.base.fontname == "mathit";
717 std::string const font = italic_upcase_greek ? "cmm" : sym->inset;
718 bool const change_font = font != "cmr" ||
719 (pi.base.fontname != "mathbb" &&
720 pi.base.fontname != "mathds" &&
721 pi.base.fontname != "mathfrak" &&
722 pi.base.fontname != "mathcal" &&
723 pi.base.fontname != "mathscr");
724 Changer dummy = change_font ? pi.base.changeFontSet(font) : noChange();
725 pi.draw(x, y, mathedSymbol(pi.base, sym));
729 void metricsStrRedBlack(MetricsInfo & mi, Dimension & dim, docstring const & str)
731 FontInfo font = mi.base.font;
732 augmentFont(font, "mathnormal");
733 mathed_string_dim(font, str, dim);
737 void drawStrRed(PainterInfo & pi, int x, int y, docstring const & str)
739 FontInfo f = pi.base.font;
740 augmentFont(f, "mathnormal");
741 f.setColor(Color_latex);
742 pi.pain.text(x, y, str, f);
746 void drawStrBlack(PainterInfo & pi, int x, int y, docstring const & str)
748 FontInfo f = pi.base.font;
749 augmentFont(f, "mathnormal");
750 f.setColor(Color_foreground);
751 pi.pain.text(x, y, str, f);
755 void math_font_max_dim(FontInfo const & font, int & asc, int & des)
757 frontend::FontMetrics const & fm = theFontMetrics(font);
758 asc = fm.maxAscent();
759 des = fm.maxDescent();
772 FontFamily const inh_family = INHERIT_FAMILY;
773 FontSeries const inh_series = INHERIT_SERIES;
774 FontShape const inh_shape = INHERIT_SHAPE;
777 // mathnormal should be the first, otherwise the fallback further down
779 fontinfo fontinfos[] = {
781 // Color_math determines which fonts are math (see isMathFont)
782 {"mathnormal", ROMAN_FAMILY, MEDIUM_SERIES,
783 ITALIC_SHAPE, Color_math},
784 {"mathbf", inh_family, BOLD_SERIES,
785 inh_shape, Color_math},
786 {"mathcal", CMSY_FAMILY, inh_series,
787 inh_shape, Color_math},
788 {"mathfrak", EUFRAK_FAMILY, inh_series,
789 inh_shape, Color_math},
790 {"mathrm", ROMAN_FAMILY, inh_series,
791 UP_SHAPE, Color_math},
792 {"mathsf", SANS_FAMILY, inh_series,
793 inh_shape, Color_math},
794 {"mathbb", MSB_FAMILY, inh_series,
795 inh_shape, Color_math},
796 {"mathds", DS_FAMILY, inh_series,
797 inh_shape, Color_math},
798 {"mathtt", TYPEWRITER_FAMILY, inh_series,
799 inh_shape, Color_math},
800 {"mathit", inh_family, inh_series,
801 ITALIC_SHAPE, Color_math},
802 {"mathscr", RSFS_FAMILY, inh_series,
803 inh_shape, Color_math},
804 {"cmex", CMEX_FAMILY, inh_series,
805 inh_shape, Color_math},
806 {"cmm", CMM_FAMILY, inh_series,
807 inh_shape, Color_math},
808 {"cmr", CMR_FAMILY, inh_series,
809 inh_shape, Color_math},
810 {"cmsy", CMSY_FAMILY, inh_series,
811 inh_shape, Color_math},
812 {"eufrak", EUFRAK_FAMILY, inh_series,
813 inh_shape, Color_math},
814 {"msa", MSA_FAMILY, inh_series,
815 inh_shape, Color_math},
816 {"msb", MSB_FAMILY, inh_series,
817 inh_shape, Color_math},
818 {"stmry", STMARY_FAMILY, inh_series,
819 inh_shape, Color_math},
820 {"wasy", WASY_FAMILY, inh_series,
821 inh_shape, Color_math},
822 {"esint", ESINT_FAMILY, inh_series,
823 inh_shape, Color_math},
826 {"text", inh_family, inh_series,
827 inh_shape, Color_foreground},
828 {"textbf", inh_family, BOLD_SERIES,
829 inh_shape, Color_foreground},
830 {"textit", inh_family, inh_series,
831 ITALIC_SHAPE, Color_foreground},
832 {"textmd", inh_family, MEDIUM_SERIES,
833 inh_shape, Color_foreground},
834 {"textnormal", inh_family, inh_series,
835 UP_SHAPE, Color_foreground},
836 {"textrm", ROMAN_FAMILY,
837 inh_series, UP_SHAPE,Color_foreground},
838 {"textsc", inh_family, inh_series,
839 SMALLCAPS_SHAPE, Color_foreground},
840 {"textsf", SANS_FAMILY, inh_series,
841 inh_shape, Color_foreground},
842 {"textsl", inh_family, inh_series,
843 SLANTED_SHAPE, Color_foreground},
844 {"texttt", TYPEWRITER_FAMILY, inh_series,
845 inh_shape, Color_foreground},
846 {"textup", inh_family, inh_series,
847 UP_SHAPE, Color_foreground},
850 {"textipa", inh_family, inh_series,
851 inh_shape, Color_foreground},
854 {"ce", inh_family, inh_series,
855 inh_shape, Color_foreground},
856 {"cf", inh_family, inh_series,
857 inh_shape, Color_foreground},
859 // LyX internal usage
860 {"lyxtex", inh_family, inh_series,
861 UP_SHAPE, Color_latex},
862 // FIXME: The following two don't work on OS X, since the Symbol font
863 // uses a different encoding, and is therefore disabled in
864 // FontLoader::available().
865 {"lyxsymbol", SYMBOL_FAMILY, inh_series,
866 inh_shape, Color_math},
867 {"lyxboldsymbol", SYMBOL_FAMILY, BOLD_SERIES,
868 inh_shape, Color_math},
869 {"lyxblacktext", ROMAN_FAMILY, MEDIUM_SERIES,
870 UP_SHAPE, Color_foreground},
871 {"lyxnochange", inh_family, inh_series,
872 inh_shape, Color_foreground},
873 {"lyxfakebb", TYPEWRITER_FAMILY, BOLD_SERIES,
874 UP_SHAPE, Color_math},
875 {"lyxfakecal", SANS_FAMILY, MEDIUM_SERIES,
876 ITALIC_SHAPE, Color_math},
877 {"lyxfakefrak", ROMAN_FAMILY, BOLD_SERIES,
878 ITALIC_SHAPE, Color_math}
882 fontinfo * lookupFont(string const & name)
884 //lyxerr << "searching font '" << name << "'" << endl;
885 int const n = sizeof(fontinfos) / sizeof(fontinfo);
886 for (int i = 0; i < n; ++i)
887 if (fontinfos[i].cmd_ == name) {
888 //lyxerr << "found '" << i << "'" << endl;
889 return fontinfos + i;
895 fontinfo * searchFont(string const & name)
897 fontinfo * f = lookupFont(name);
898 return f ? f : fontinfos;
899 // this should be mathnormal
900 //return searchFont("mathnormal");
904 bool isFontName(string const & name)
906 return lookupFont(name);
910 bool isMathFont(string const & name)
912 fontinfo * f = lookupFont(name);
913 return f && f->color_ == Color_math;
917 bool isTextFont(string const & name)
919 fontinfo * f = lookupFont(name);
920 return f && f->color_ == Color_foreground;
924 FontInfo getFont(string const & name)
927 augmentFont(font, name);
932 void fakeFont(string const & orig, string const & fake)
934 fontinfo * forig = searchFont(orig);
935 fontinfo * ffake = searchFont(fake);
936 if (forig && ffake) {
937 forig->family_ = ffake->family_;
938 forig->series_ = ffake->series_;
939 forig->shape_ = ffake->shape_;
940 forig->color_ = ffake->color_;
942 lyxerr << "Can't fake font '" << orig << "' with '"
943 << fake << "'" << endl;
948 void augmentFont(FontInfo & font, string const & name)
950 static bool initialized = false;
953 // fake fonts if necessary
954 if (!theFontLoader().available(getFont("mathfrak")))
955 fakeFont("mathfrak", "lyxfakefrak");
956 if (!theFontLoader().available(getFont("mathcal")))
957 fakeFont("mathcal", "lyxfakecal");
959 fontinfo * info = searchFont(name);
960 if (info->family_ != inh_family)
961 font.setFamily(info->family_);
962 if (info->series_ != inh_series)
963 font.setSeries(info->series_);
964 if (info->shape_ != inh_shape)
965 font.setShape(info->shape_);
966 if (info->color_ != Color_none)
967 font.setColor(info->color_);
971 bool isAlphaSymbol(MathAtom const & at)
973 if (at->asCharInset() ||
974 (at->asSymbolInset() &&
975 at->asSymbolInset()->isOrdAlpha()))
978 if (at->asFontInset()) {
979 MathData const & ar = at->asFontInset()->cell(0);
980 for (size_t i = 0; i < ar.size(); ++i) {
981 if (!(ar[i]->asCharInset() ||
982 (ar[i]->asSymbolInset() &&
983 ar[i]->asSymbolInset()->isOrdAlpha())))
992 docstring asString(MathData const & ar)
995 otexrowstream ots(os);
1002 void asArray(docstring const & str, MathData & ar, Parse::flags pf)
1004 // If the QUIET flag is set, we are going to parse for either
1005 // a paste operation or a macro definition. We try to do the
1006 // right thing in all cases.
1008 bool quiet = pf & Parse::QUIET;
1009 bool macro = pf & Parse::MACRODEF;
1010 if ((str.size() == 1 && quiet) || (!mathed_parse_cell(ar, str, pf) && quiet && !macro))
1011 mathed_parse_cell(ar, str, pf | Parse::VERBATIM);
1015 docstring asString(InsetMath const & inset)
1017 odocstringstream os;
1018 otexrowstream ots(os);
1019 WriteStream ws(ots);
1025 docstring asString(MathAtom const & at)
1027 odocstringstream os;
1028 otexrowstream ots(os);
1029 WriteStream ws(ots);
1035 int axis_height(MetricsBase & mb)
1037 Changer dummy = mb.changeFontSet("mathnormal");
1038 return theFontMetrics(mb.font).ascent('-') - 1;
1042 void validate_math_word(LaTeXFeatures & features, docstring const & word)
1044 MathWordList const & words = mathedWordList();
1045 MathWordList::const_iterator it = words.find(word);
1046 if (it != words.end()) {
1047 string const req = it->second.required;
1049 features.require(req);