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"
24 #include "LaTeXFeatures.h"
25 #include "MetricsInfo.h"
27 #include "frontends/FontLoader.h"
28 #include "frontends/FontMetrics.h"
29 #include "frontends/Painter.h"
31 #include "support/Changer.h"
32 #include "support/debug.h"
33 #include "support/docstream.h"
34 #include "support/lassert.h"
35 #include "support/Length.h"
36 #include "support/textutils.h"
45 using frontend::Painter;
52 Matrix(int, double, double);
54 void transform(double &, double &);
61 Matrix::Matrix(int code, double x, double y)
63 double const cs = (code & 1) ? 0 : (1 - code);
64 double const sn = (code & 1) ? (2 - code) : 0;
72 void Matrix::transform(double & x, double & y)
74 double xx = m_[0][0] * x + m_[0][1] * y;
75 double yy = m_[1][0] * x + m_[1][1] * y;
85 * Internal struct of a drawing: code n x1 y1 ... xn yn, where code is:
86 * 0 = end, 1 = line, 2 = polyline, 3 = square line, 4 = square polyline
87 * 5 = rounded thick line (i.e. dot for short line)
91 double const parenthHigh[] = {
93 0.9840, 0.0014, 0.7143, 0.0323, 0.4603, 0.0772,
94 0.2540, 0.1278, 0.1746, 0.1966, 0.0952, 0.3300,
95 0.0950, 0.5000, 0.0952, 0.6700, 0.1746, 0.8034,
96 0.2540, 0.8722, 0.4603, 0.9228, 0.7143, 0.9677,
102 double const parenth[] = {
104 0.9930, 0.0071, 0.7324, 0.0578, 0.5141, 0.1126,
105 0.3380, 0.1714, 0.2183, 0.2333, 0.0634, 0.3621,
106 0.0141, 0.5000, 0.0634, 0.6379, 0.2183, 0.7667,
107 0.3380, 0.8286, 0.5141, 0.8874, 0.7324, 0.9422,
113 double const breve[] = {
115 0.100, 0.400, 0.125, 0.550, 0.200, 0.700, 0.400, 0.800,
116 0.600, 0.800, 0.800, 0.700, 0.875, 0.550, 0.900, 0.400,
121 double const brace[] = {
123 0.9492, 0.0020, 0.9379, 0.0020, 0.7458, 0.0243,
124 0.5819, 0.0527, 0.4859, 0.0892, 0.4463, 0.1278,
125 0.4463, 0.3732, 0.4011, 0.4199, 0.2712, 0.4615,
126 0.0734, 0.4919, 0.0113, 0.5000, 0.0734, 0.5081,
127 0.2712, 0.5385, 0.4011, 0.5801, 0.4463, 0.6268,
128 0.4463, 0.8722, 0.4859, 0.9108, 0.5819, 0.9473,
129 0.7458, 0.9757, 0.9379, 0.9980, 0.9492, 0.9980,
134 double const mapsto[] = {
136 0.75, 0.015, 0.95, 0.5, 0.75, 0.985,
137 1, 0.015, 0.475, 0.945, 0.475,
138 1, 0.015, 0.015, 0.015, 0.985,
143 double const lhook[] = {
145 0.25, 0.015, 0.05, 0.5, 0.25, 0.985,
146 1, 0.015, 0.475, 0.7, 0.475,
148 0.7, 0.015, 0.825, 0.15, 0.985, 0.25,
149 0.825, 0.35, 0.7, 0.475,
154 double const rhook[] = {
156 0.75, 0.015, 0.95, 0.5, 0.75, 0.985,
157 1, 0.3, 0.475, 0.985, 0.475,
159 0.3, 0.015, 0.175, 0.15, 0.05, 0.25,
160 0.175, 0.35, 0.3, 0.475,
165 double const LRArrow[] = {
167 0.25, 0.015, 0.05, 0.5, 0.25, 0.985,
169 0.75, 0.015, 0.95, 0.5, 0.75, 0.985,
170 1, 0.2, 0.8, 0.8, 0.8,
171 1, 0.2, 0.2, 0.8, 0.2,
176 double const LArrow[] = {
178 0.25, 0.015, 0.05, 0.5, 0.25, 0.985,
179 1, 0.2, 0.8, 0.985, 0.8,
180 1, 0.2, 0.2, 0.985, 0.2,
185 double const lharpoondown[] = {
187 0.015, 0.5, 0.25, 0.985,
188 1, 0.02, 0.475, 0.985, 0.475,
193 double const lharpoonup[] = {
195 0.25, 0.015, 0.015, 0.5,
196 1, 0.02, 0.525, 0.985, 0.525,
201 double const lrharpoons[] = {
203 0.25, 0.015, 0.015, 0.225,
204 1, 0.02, 0.23, 0.985, 0.23,
206 0.75, 0.985, 0.985, 0.775,
207 1, 0.02, 0.7, 0.980, 0.7,
212 double const rlharpoons[] = {
214 0.75, 0.015, 0.985, 0.225,
215 1, 0.02, 0.23, 0.985, 0.23,
217 0.25, 0.985, 0.015, 0.775,
218 1, 0.02, 0.7, 0.980, 0.7,
223 double const vec[] = {
225 0.2000, 0.5000, 0.3000, 0.4000, 0.4000, 0.2500,
226 0.5000, 0.0000, 0.6000, 0.2500, 0.7000, 0.4000,
228 3, 0.5000, 0.1000, 0.5000, 0.9500,
233 double const arrow[] = {
235 0.0500, 0.7500, 0.2000, 0.6000, 0.3500, 0.3500,
236 0.5000, 0.0500, 0.6500, 0.3500, 0.8000, 0.6000,
238 3, 0.5000, 0.1500, 0.5000, 0.9500,
243 double const Arrow[] = {
245 0.0150, 0.7500, 0.2000, 0.6000, 0.3500, 0.3500,
246 0.5000, 0.0500, 0.6500, 0.3500, 0.8000, 0.6000,
248 3, 0.3500, 0.5000, 0.3500, 0.9500,
249 3, 0.6500, 0.5000, 0.6500, 0.9500,
254 double const udarrow[] = {
256 0.015, 0.25, 0.5, 0.05, 0.95, 0.25,
258 0.015, 0.75, 0.5, 0.95, 0.95, 0.75,
259 1, 0.5, 0.1, 0.5, 0.9,
264 double const Udarrow[] = {
266 0.015, 0.25, 0.5, 0.05, 0.95, 0.25,
268 0.015, 0.75, 0.5, 0.95, 0.95, 0.75,
269 1, 0.35, 0.2, 0.35, 0.8,
270 1, 0.65, 0.2, 0.65, 0.8,
275 double const brack[] = {
277 0.95, 0.05, 0.05, 0.05, 0.05, 0.95, 0.95, 0.95,
282 double const dbrack[] = {
284 0.95, 0.05, 0.05, 0.05, 0.05, 0.95, 0.95, 0.95,
286 0.50, 0.05, 0.50, 0.95,
291 double const corner[] = {
293 0.95, 0.05, 0.05, 0.05, 0.05, 0.95,
298 double const angle[] = {
300 0.9, 0.05, 0.05, 0.5, 0.9, 0.95,
305 double const slash[] = {
306 1, 0.95, 0.05, 0.05, 0.95,
311 double const hline[] = {
312 1, 0.00, 0.5, 1.0, 0.5,
317 double const dot[] = {
318 // 1, 0.5, 0.2, 0.5, 0.2,
319 // 1, 0.4, 0.4, 0.6, 0.4,
320 // 1, 0.5, 0.5, 0.5, 0.5,
321 5, 0.4, 0.5, 0.6, 0.5,
326 double const ddot[] = {
327 5, 0.1, 0.5, 0.3, 0.5,
328 5, 0.6, 0.5, 0.8, 0.5,
333 double const dddot[] = {
334 5, 0.0, 0.5, 0.2, 0.5,
335 5, 0.4, 0.5, 0.6, 0.5,
336 5, 0.8, 0.5, 1.0, 0.5,
341 double const ddddot[] = {
342 5, -0.2, 0.5, 0.0, 0.5,
343 5, 0.2, 0.5, 0.4, 0.5,
344 5, 0.6, 0.5, 0.8, 0.5,
345 5, 1.0, 0.5, 1.2, 0.5,
350 double const hline3[] = {
352 1, 0.475, 0, 0.525, 0,
358 double const dline3[] = {
359 1, 0.1, 0.1, 0.15, 0.15,
360 1, 0.475, 0.475, 0.525, 0.525,
361 1, 0.85, 0.85, 0.9, 0.9,
366 double const ring[] = {
368 0.5000, 0.7750, 0.6375, 0.7375, 0.7375, 0.6375, 0.7750, 0.5000,
369 0.7375, 0.3625, 0.6375, 0.2625, 0.5000, 0.2250, 0.3625, 0.2625,
370 0.2625, 0.3625, 0.2250, 0.5000, 0.2625, 0.6375, 0.3625, 0.7375,
376 double const vert[] = {
377 1, 0.5, 0.05, 0.5, 0.95,
382 double const Vert[] = {
383 1, 0.3, 0.05, 0.3, 0.95,
384 1, 0.7, 0.05, 0.7, 0.95,
389 double const tilde[] = {
391 0.000, 0.625, 0.050, 0.500, 0.150, 0.350, 0.275, 0.275, 0.400, 0.350,
392 0.575, 0.650, 0.700, 0.725, 0.825, 0.650, 0.925, 0.500, 0.975, 0.375,
402 struct named_deco_struct {
408 named_deco_struct deco_table[] = {
410 {"widehat", angle, 3 },
411 {"widetilde", tilde, 0 },
412 {"underbar", hline, 0 },
413 {"underline", hline, 0 },
414 {"overline", hline, 0 },
415 {"underbrace", brace, 1 },
416 {"overbrace", brace, 3 },
417 {"overleftarrow", arrow, 1 },
418 {"overrightarrow", arrow, 3 },
419 {"overleftrightarrow", udarrow, 1 },
420 {"xhookleftarrow", lhook, 0 },
421 {"xhookrightarrow", rhook, 0 },
422 {"xleftarrow", arrow, 1 },
423 {"xLeftarrow", LArrow, 0 },
424 {"xleftharpoondown", lharpoondown, 0 },
425 {"xleftharpoonup", lharpoonup, 0 },
426 {"xleftrightharpoons", lrharpoons, 0 },
427 {"xleftrightarrow", udarrow, 1 },
428 {"xLeftrightarrow", LRArrow, 0 },
429 {"xmapsto", mapsto, 0 },
430 {"xrightarrow", arrow, 3 },
431 {"xRightarrow", LArrow, 2 },
432 {"xrightharpoondown", lharpoonup, 2 },
433 {"xrightharpoonup", lharpoondown, 2 },
434 {"xrightleftharpoons", rlharpoons, 0 },
435 {"underleftarrow", arrow, 1 },
436 {"underrightarrow", arrow, 3 },
437 {"underleftrightarrow", udarrow, 1 },
438 {"undertilde", tilde, 0 },
439 {"utilde", tilde, 0 },
446 {"lbrace", brace, 0 },
447 {"rbrace", brace, 2 },
450 {"llbracket", dbrack, 0 },
451 {"rrbracket", dbrack, 2 },
454 {"slash", slash, 0 },
465 {"backslash", slash, 1 },
466 {"langle", angle, 0 },
467 {"lceil", corner, 0 },
468 {"lfloor", corner, 1 },
469 {"rangle", angle, 2 },
470 {"rceil", corner, 3 },
471 {"rfloor", corner, 2 },
472 {"downarrow", arrow, 2 },
473 {"Downarrow", Arrow, 2 },
474 {"uparrow", arrow, 0 },
475 {"Uparrow", Arrow, 0 },
476 {"updownarrow", udarrow, 0 },
477 {"Updownarrow", Udarrow, 0 },
481 {"dddot", dddot, 0 },
482 {"ddddot", ddddot, 0 },
484 {"grave", slash, 1 },
485 {"acute", slash, 0 },
486 {"tilde", tilde, 0 },
489 {"check", angle, 1 },
490 {"breve", breve, 0 },
492 {"mathring", ring, 0 },
495 {"dots", hline3, 0 },
496 {"ldots", hline3, 0 },
497 {"cdots", hline3, 0 },
498 {"vdots", hline3, 1 },
499 {"ddots", dline3, 0 },
500 {"adots", dline3, 1 },
501 {"iddots", dline3, 1 },
502 {"dotsb", hline3, 0 },
503 {"dotsc", hline3, 0 },
504 {"dotsi", hline3, 0 },
505 {"dotsm", hline3, 0 },
506 {"dotso", hline3, 0 }
510 map<docstring, deco_struct> deco_list;
512 // sort the table on startup
513 class init_deco_table {
516 unsigned const n = sizeof(deco_table) / sizeof(deco_table[0]);
517 for (named_deco_struct * p = deco_table; p != deco_table + n; ++p) {
521 deco_list[from_ascii(p->name)] = d;
526 static init_deco_table dummy_deco_table;
529 deco_struct const * search_deco(docstring const & name)
531 map<docstring, deco_struct>::const_iterator p = deco_list.find(name);
532 return p == deco_list.end() ? 0 : &(p->second);
539 int mathed_font_em(FontInfo const & font)
541 return theFontMetrics(font).em();
545 int mathed_font_x_height(FontInfo const & font)
547 return theFontMetrics(font).xHeight();
550 /* The math units. Quoting TeX by Topic, p.205:
552 * Spacing around mathematical objects is measured in mu units. A mu
553 * is 1/18th part of \fontdimen6 of the font in family 2 in the
554 * current style, the ‘quad’ value of the symbol font.
556 * A \thickmuskip (default value in plain TeX: 5mu plus 5mu) is
557 * inserted around (binary) relations, except where these are preceded
558 * or followed by other relations or punctuation, and except if they
559 * follow an open, or precede a close symbol.
561 * A \medmuskip (default value in plain TeX: 4mu plus 2mu minus 4mu)
562 * is put around binary operators.
564 * A \thinmuskip (default value in plain TeX: 3mu) follows after
565 * punctuation, and is put around inner objects, except where these
566 * are followed by a close or preceded by an open symbol, and except
567 * if the other object is a large operator or a binary relation.
569 * See the file MathClass.cpp for a formal implementation of the rules
573 int mathed_mu(FontInfo const & font, double mu)
575 MetricsBase mb(nullptr, font);
576 return mb.inPixels(Length(mu, Length::MU));
579 int mathed_thinmuskip(FontInfo const & font) { return mathed_mu(font, 3.0); }
580 int mathed_medmuskip(FontInfo const & font) { return mathed_mu(font, 4.0); }
581 int mathed_thickmuskip(FontInfo const & font) { return mathed_mu(font, 5.0); }
584 int mathed_char_width(FontInfo const & font, char_type c)
586 return theFontMetrics(font).width(c);
590 int mathed_char_kerning(FontInfo const & font, char_type c)
592 frontend::FontMetrics const & fm = theFontMetrics(font);
593 return max(0, fm.rbearing(c) - fm.width(c));
597 double mathed_char_slope(MetricsBase const & mb, char_type c)
599 bool slanted = isAlphaASCII(c) || Encodings::isMathAlpha(c);
600 if (slanted && mb.fontname == "mathnormal")
601 return theFontMetrics(mb.font).italicSlope();
606 void mathed_string_dim(FontInfo const & font,
610 frontend::FontMetrics const & fm = theFontMetrics(font);
613 for (char_type const c : s) {
614 dim.asc = max(dim.asc, fm.ascent(c));
615 dim.des = max(dim.des, fm.descent(c));
617 dim.wid = fm.width(s);
621 int mathed_string_width(FontInfo const & font, docstring const & s)
623 return theFontMetrics(font).width(s);
627 void mathed_draw_deco(PainterInfo & pi, int x, int y, int w, int h,
628 docstring const & name)
630 int const lw = pi.base.solidLineThickness();
633 pi.pain.line(x + w/2, y, x + w/2, y + h,
634 Color_cursor, Painter::line_onoffdash, lw);
638 deco_struct const * mds = search_deco(name);
640 lyxerr << "Deco was not found. Programming error?" << endl;
641 lyxerr << "name: '" << to_utf8(name) << "'" << endl;
645 int const n = (w < h) ? w : h;
646 int const r = mds->angle;
647 double const * d = mds->data;
649 if (h > 70 && (name == "(" || name == ")"))
653 Matrix sqmt(r, n, n);
661 for (int i = 0; d[i]; ) {
662 int code = int(d[i++]);
663 if (code & 1) { // code == 1 || code == 3 || code == 5
669 sqmt.transform(xx, yy);
671 mt.transform(xx, yy);
672 mt.transform(x2, y2);
674 int(x + xx + 0.5), int(y + yy + 0.5),
675 int(x + x2 + 0.5), int(y + y2 + 0.5),
676 pi.base.font.color(), Painter::line_solid, lw);
677 if (code == 5) { // thicker, but rounded
678 double const xa = x + xx + 0.5;
679 double const xb = x + x2 + 0.5;
680 double const ya = y + yy + 0.5;
681 double const yb = y + y2 + 0.5;
682 pi.pain.line(int(xa + 1), int(ya - 1),
683 int(xb - 1), int(yb - 1),
684 pi.base.font.color(),
685 Painter::line_solid, lw);
686 pi.pain.line(int(xa + 1), int(ya + 1),
687 int(xb - 1), int(yb + 1),
688 pi.base.font.color(),
689 Painter::line_solid, lw);
690 for (int k = 2; xa + k <= xb - k; k++) {
691 pi.pain.line(int(xa + k), int(ya - k),
692 int(xb - k), int(yb - k),
693 pi.base.font.color(),
694 Painter::line_solid, lw);
695 pi.pain.line(int(xa + k), int(ya + k),
696 int(xb - k), int(yb + k),
697 pi.base.font.color(),
698 Painter::line_solid, lw);
704 int const n2 = int(d[i++]);
705 for (int j = 0; j < n2; ++j) {
708 // lyxerr << ' ' << xx << ' ' << yy << ' ';
710 sqmt.transform(xx, yy);
712 mt.transform(xx, yy);
713 xp[j] = int(x + xx + 0.5);
714 yp[j] = int(y + yy + 0.5);
715 // lyxerr << "P[" << j ' ' << xx << ' ' << yy << ' ' << x << ' ' << y << ']';
717 pi.pain.lines(xp, yp, n2, pi.base.font.color(),
718 Painter::fill_none, Painter::line_solid, lw);
724 docstring const & mathedSymbol(MetricsBase & mb, latexkeys const * sym)
726 return (mb.font.style() == DISPLAY_STYLE && !sym->dsp_draw.empty()) ?
727 sym->dsp_draw : sym->draw;
731 int mathedSymbolDim(MetricsBase & mb, Dimension & dim, latexkeys const * sym)
733 LASSERT((bool)sym, return 0);
734 //lyxerr << "metrics: symbol: '" << sym->name
735 // << "' in font: '" << sym->inset
736 // << "' drawn as: '" << sym->draw
739 bool const italic_upcase_greek = sym->inset == "cmr" &&
740 sym->extra == "mathalpha" &&
741 mb.fontname == "mathit";
742 std::string const font = italic_upcase_greek ? "cmm" : sym->inset;
743 bool const change_font = font != "cmr" ||
744 (mb.fontname != "mathbb" &&
745 mb.fontname != "mathds" &&
746 mb.fontname != "mathfrak" &&
747 mb.fontname != "mathcal" &&
748 mb.fontname != "mathscr");
749 Changer dummy = change_font ? mb.changeFontSet(font) : noChange();
750 mathed_string_dim(mb.font, mathedSymbol(mb, sym), dim);
751 return mathed_char_kerning(mb.font, mathedSymbol(mb, sym).back());
755 void mathedSymbolDraw(PainterInfo & pi, int x, int y, latexkeys const * sym)
757 LASSERT((bool)sym, return);
758 //lyxerr << "drawing: symbol: '" << sym->name
759 // << "' in font: '" << sym->inset
760 // << "' drawn as: '" << sym->draw
763 bool const italic_upcase_greek = sym->inset == "cmr" &&
764 sym->extra == "mathalpha" &&
765 pi.base.fontname == "mathit";
766 std::string const font = italic_upcase_greek ? "cmm" : sym->inset;
767 bool const change_font = font != "cmr" ||
768 (pi.base.fontname != "mathbb" &&
769 pi.base.fontname != "mathds" &&
770 pi.base.fontname != "mathfrak" &&
771 pi.base.fontname != "mathcal" &&
772 pi.base.fontname != "mathscr");
773 Changer dummy = change_font ? pi.base.changeFontSet(font) : noChange();
774 pi.draw(x, y, mathedSymbol(pi.base, sym));
778 void metricsStrRedBlack(MetricsInfo & mi, Dimension & dim, docstring const & str)
780 FontInfo font = mi.base.font;
781 augmentFont(font, "mathnormal");
782 mathed_string_dim(font, str, dim);
786 void drawStrRed(PainterInfo & pi, int x, int y, docstring const & str)
788 FontInfo f = pi.base.font;
789 augmentFont(f, "mathnormal");
790 f.setColor(Color_latex);
791 pi.pain.text(x, y, str, f);
795 void drawStrBlack(PainterInfo & pi, int x, int y, docstring const & str)
797 FontInfo f = pi.base.font;
798 augmentFont(f, "mathnormal");
799 f.setColor(Color_foreground);
800 pi.pain.text(x, y, str, f);
804 void math_font_max_dim(FontInfo const & font, int & asc, int & des)
806 frontend::FontMetrics const & fm = theFontMetrics(font);
807 asc = fm.maxAscent();
808 des = fm.maxDescent();
821 FontFamily const inh_family = INHERIT_FAMILY;
822 FontSeries const inh_series = INHERIT_SERIES;
823 FontShape const inh_shape = INHERIT_SHAPE;
826 // mathnormal should be the first, otherwise the fallback further down
828 fontinfo fontinfos[] = {
830 // Color_math determines which fonts are math (see isMathFont)
831 {"mathnormal", ROMAN_FAMILY, MEDIUM_SERIES,
832 ITALIC_SHAPE, Color_math},
833 {"mathbf", inh_family, BOLD_SERIES,
834 inh_shape, Color_math},
835 {"mathcal", CMSY_FAMILY, inh_series,
836 inh_shape, Color_math},
837 {"mathfrak", EUFRAK_FAMILY, inh_series,
838 inh_shape, Color_math},
839 {"mathrm", ROMAN_FAMILY, inh_series,
840 UP_SHAPE, Color_math},
841 {"mathsf", SANS_FAMILY, inh_series,
842 inh_shape, Color_math},
843 {"mathbb", MSB_FAMILY, inh_series,
844 inh_shape, Color_math},
845 {"mathds", DS_FAMILY, inh_series,
846 inh_shape, Color_math},
847 {"mathtt", TYPEWRITER_FAMILY, inh_series,
848 inh_shape, Color_math},
849 {"mathit", inh_family, inh_series,
850 ITALIC_SHAPE, Color_math},
851 {"mathscr", RSFS_FAMILY, inh_series,
852 inh_shape, Color_math},
853 {"cmex", CMEX_FAMILY, inh_series,
854 inh_shape, Color_math},
855 {"cmm", CMM_FAMILY, inh_series,
856 inh_shape, Color_math},
857 {"cmr", CMR_FAMILY, inh_series,
858 inh_shape, Color_math},
859 {"cmsy", CMSY_FAMILY, inh_series,
860 inh_shape, Color_math},
861 {"eufrak", EUFRAK_FAMILY, inh_series,
862 inh_shape, Color_math},
863 {"msa", MSA_FAMILY, inh_series,
864 inh_shape, Color_math},
865 {"msb", MSB_FAMILY, inh_series,
866 inh_shape, Color_math},
867 {"stmry", STMARY_FAMILY, inh_series,
868 inh_shape, Color_math},
869 {"wasy", WASY_FAMILY, inh_series,
870 inh_shape, Color_math},
871 {"esint", ESINT_FAMILY, inh_series,
872 inh_shape, Color_math},
875 {"text", inh_family, inh_series,
876 inh_shape, Color_foreground},
877 {"textbf", inh_family, BOLD_SERIES,
878 inh_shape, Color_foreground},
879 {"textit", inh_family, inh_series,
880 ITALIC_SHAPE, Color_foreground},
881 {"textmd", inh_family, MEDIUM_SERIES,
882 inh_shape, Color_foreground},
883 {"textnormal", inh_family, inh_series,
884 UP_SHAPE, Color_foreground},
885 {"textrm", ROMAN_FAMILY,
886 inh_series, UP_SHAPE,Color_foreground},
887 {"textsc", inh_family, inh_series,
888 SMALLCAPS_SHAPE, Color_foreground},
889 {"textsf", SANS_FAMILY, inh_series,
890 inh_shape, Color_foreground},
891 {"textsl", inh_family, inh_series,
892 SLANTED_SHAPE, Color_foreground},
893 {"texttt", TYPEWRITER_FAMILY, inh_series,
894 inh_shape, Color_foreground},
895 {"textup", inh_family, inh_series,
896 UP_SHAPE, Color_foreground},
899 {"textipa", inh_family, inh_series,
900 inh_shape, Color_foreground},
903 {"ce", inh_family, inh_series,
904 inh_shape, Color_foreground},
905 {"cf", inh_family, inh_series,
906 inh_shape, Color_foreground},
908 // LyX internal usage
909 {"lyxtex", inh_family, inh_series,
910 UP_SHAPE, Color_latex},
911 // FIXME: The following two don't work on OS X, since the Symbol font
912 // uses a different encoding, and is therefore disabled in
913 // FontLoader::available().
914 {"lyxsymbol", SYMBOL_FAMILY, inh_series,
915 inh_shape, Color_math},
916 {"lyxboldsymbol", SYMBOL_FAMILY, BOLD_SERIES,
917 inh_shape, Color_math},
918 {"lyxblacktext", ROMAN_FAMILY, MEDIUM_SERIES,
919 UP_SHAPE, Color_foreground},
920 {"lyxnochange", inh_family, inh_series,
921 inh_shape, Color_foreground},
922 {"lyxfakebb", TYPEWRITER_FAMILY, BOLD_SERIES,
923 UP_SHAPE, Color_math},
924 {"lyxfakecal", SANS_FAMILY, MEDIUM_SERIES,
925 ITALIC_SHAPE, Color_math},
926 {"lyxfakefrak", ROMAN_FAMILY, BOLD_SERIES,
927 ITALIC_SHAPE, Color_math}
931 fontinfo * lookupFont(string const & name)
933 //lyxerr << "searching font '" << name << "'" << endl;
934 int const n = sizeof(fontinfos) / sizeof(fontinfo);
935 for (int i = 0; i < n; ++i)
936 if (fontinfos[i].cmd_ == name) {
937 //lyxerr << "found '" << i << "'" << endl;
938 return fontinfos + i;
944 fontinfo * searchFont(string const & name)
946 fontinfo * f = lookupFont(name);
947 return f ? f : fontinfos;
948 // this should be mathnormal
949 //return searchFont("mathnormal");
953 bool isFontName(string const & name)
955 return lookupFont(name);
959 bool isMathFont(string const & name)
961 fontinfo * f = lookupFont(name);
962 return f && f->color_ == Color_math;
966 bool isTextFont(string const & name)
968 fontinfo * f = lookupFont(name);
969 return f && f->color_ == Color_foreground;
973 FontInfo getFont(string const & name)
976 augmentFont(font, name);
981 void fakeFont(string const & orig, string const & fake)
983 fontinfo * forig = searchFont(orig);
984 fontinfo * ffake = searchFont(fake);
985 if (forig && ffake) {
986 forig->family_ = ffake->family_;
987 forig->series_ = ffake->series_;
988 forig->shape_ = ffake->shape_;
989 forig->color_ = ffake->color_;
991 lyxerr << "Can't fake font '" << orig << "' with '"
992 << fake << "'" << endl;
997 void augmentFont(FontInfo & font, string const & name)
999 static bool initialized = false;
1002 // fake fonts if necessary
1003 if (!theFontLoader().available(getFont("mathfrak")))
1004 fakeFont("mathfrak", "lyxfakefrak");
1005 if (!theFontLoader().available(getFont("mathcal")))
1006 fakeFont("mathcal", "lyxfakecal");
1008 fontinfo * info = searchFont(name);
1009 if (info->family_ != inh_family)
1010 font.setFamily(info->family_);
1011 if (info->series_ != inh_series)
1012 font.setSeries(info->series_);
1013 if (info->shape_ != inh_shape)
1014 font.setShape(info->shape_);
1015 if (info->color_ != Color_none)
1016 font.setColor(info->color_);
1020 bool isAlphaSymbol(MathAtom const & at)
1022 if (at->asCharInset() ||
1023 (at->asSymbolInset() &&
1024 at->asSymbolInset()->isOrdAlpha()))
1027 if (at->asFontInset()) {
1028 MathData const & ar = at->asFontInset()->cell(0);
1029 for (size_t i = 0; i < ar.size(); ++i) {
1030 if (!(ar[i]->asCharInset() ||
1031 (ar[i]->asSymbolInset() &&
1032 ar[i]->asSymbolInset()->isOrdAlpha())))
1041 docstring asString(MathData const & ar)
1043 odocstringstream os;
1044 otexrowstream ots(os);
1045 TeXMathStream ws(ots);
1051 void asArray(docstring const & str, MathData & ar, Parse::flags pf)
1053 // If the QUIET flag is set, we are going to parse for either
1054 // a paste operation or a macro definition. We try to do the
1055 // right thing in all cases.
1057 bool quiet = pf & Parse::QUIET;
1058 bool macro = pf & Parse::MACRODEF;
1059 if ((str.size() == 1 && quiet) || (!mathed_parse_cell(ar, str, pf) && quiet && !macro))
1060 mathed_parse_cell(ar, str, pf | Parse::VERBATIM);
1064 docstring asString(InsetMath const & inset)
1066 odocstringstream os;
1067 otexrowstream ots(os);
1068 TeXMathStream ws(ots);
1074 docstring asString(MathAtom const & at)
1076 odocstringstream os;
1077 otexrowstream ots(os);
1078 TeXMathStream ws(ots);
1084 int axis_height(MetricsBase & mb)
1086 Changer dummy = mb.changeFontSet("mathnormal");
1087 return theFontMetrics(mb.font).ascent('-') - 1;
1091 void validate_math_word(LaTeXFeatures & features, docstring const & word)
1093 MathWordList const & words = mathedWordList();
1094 MathWordList::const_iterator it = words.find(word);
1095 if (it != words.end()) {
1096 string const req = it->second.required;
1098 features.require(req);