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.0563, 0.6369, 0.2113, 0.7647,
107 0.3310, 0.8276, 0.5070, 0.8864, 0.7254, 0.9412,
113 double const brace[] = {
115 0.9492, 0.0020, 0.9379, 0.0020, 0.7458, 0.0243,
116 0.5819, 0.0527, 0.4859, 0.0892, 0.4463, 0.1278,
117 0.4463, 0.3732, 0.4011, 0.4199, 0.2712, 0.4615,
118 0.0734, 0.4919, 0.0113, 0.5000, 0.0734, 0.5081,
119 0.2712, 0.5385, 0.4011, 0.5801, 0.4463, 0.6268,
120 0.4463, 0.8722, 0.4859, 0.9108, 0.5819, 0.9473,
121 0.7458, 0.9757, 0.9379, 0.9980, 0.9492, 0.9980,
126 double const mapsto[] = {
128 0.75, 0.015, 0.95, 0.5, 0.75, 0.985,
129 1, 0.015, 0.475, 0.945, 0.475,
130 1, 0.015, 0.015, 0.015, 0.985,
135 double const lhook[] = {
137 0.25, 0.015, 0.05, 0.5, 0.25, 0.985,
138 1, 0.015, 0.475, 0.7, 0.475,
140 0.7, 0.015, 0.825, 0.15, 0.985, 0.25,
141 0.825, 0.35, 0.7, 0.475,
146 double const rhook[] = {
148 0.75, 0.015, 0.95, 0.5, 0.75, 0.985,
149 1, 0.3, 0.475, 0.985, 0.475,
151 0.3, 0.015, 0.175, 0.15, 0.05, 0.25,
152 0.175, 0.35, 0.3, 0.475,
157 double const LRArrow[] = {
159 0.25, 0.015, 0.05, 0.5, 0.25, 0.985,
161 0.75, 0.015, 0.95, 0.5, 0.75, 0.985,
162 1, 0.2, 0.8, 0.8, 0.8,
163 1, 0.2, 0.2, 0.8, 0.2,
168 double const LArrow[] = {
170 0.25, 0.015, 0.05, 0.5, 0.25, 0.985,
171 1, 0.2, 0.8, 0.985, 0.8,
172 1, 0.2, 0.2, 0.985, 0.2,
177 double const lharpoondown[] = {
179 0.015, 0.5, 0.25, 0.985,
180 1, 0.02, 0.475, 0.985, 0.475,
185 double const lharpoonup[] = {
187 0.25, 0.015, 0.015, 0.5,
188 1, 0.02, 0.525, 0.985, 0.525,
193 double const lrharpoons[] = {
195 0.25, 0.015, 0.015, 0.225,
196 1, 0.02, 0.23, 0.985, 0.23,
198 0.75, 0.985, 0.985, 0.775,
199 1, 0.02, 0.7, 0.980, 0.7,
204 double const rlharpoons[] = {
206 0.75, 0.015, 0.985, 0.225,
207 1, 0.02, 0.23, 0.985, 0.23,
209 0.25, 0.985, 0.015, 0.775,
210 1, 0.02, 0.7, 0.980, 0.7,
215 double const arrow[] = {
217 0.0150, 0.7500, 0.2000, 0.6000, 0.3500, 0.3500,
218 0.5000, 0.0500, 0.6500, 0.3500, 0.8000, 0.6000,
220 3, 0.5000, 0.1500, 0.5000, 0.9500,
225 double const Arrow[] = {
227 0.0150, 0.7500, 0.2000, 0.6000, 0.3500, 0.3500,
228 0.5000, 0.0500, 0.6500, 0.3500, 0.8000, 0.6000,
230 3, 0.3500, 0.5000, 0.3500, 0.9500,
231 3, 0.6500, 0.5000, 0.6500, 0.9500,
236 double const udarrow[] = {
238 0.015, 0.25, 0.5, 0.05, 0.95, 0.25,
240 0.015, 0.75, 0.5, 0.95, 0.95, 0.75,
241 1, 0.5, 0.1, 0.5, 0.9,
246 double const Udarrow[] = {
248 0.015, 0.25, 0.5, 0.05, 0.95, 0.25,
250 0.015, 0.75, 0.5, 0.95, 0.95, 0.75,
251 1, 0.35, 0.2, 0.35, 0.8,
252 1, 0.65, 0.2, 0.65, 0.8,
257 double const brack[] = {
259 0.95, 0.05, 0.05, 0.05, 0.05, 0.95, 0.95, 0.95,
264 double const dbrack[] = {
266 0.95, 0.05, 0.05, 0.05, 0.05, 0.95, 0.95, 0.95,
268 0.50, 0.05, 0.50, 0.95,
273 double const corner[] = {
275 0.95, 0.05, 0.05, 0.05, 0.05, 0.95,
280 double const angle[] = {
282 1, 0, 0.05, 0.5, 1, 1,
287 double const slash[] = {
288 1, 0.95, 0.05, 0.05, 0.95,
293 double const hline[] = {
294 1, 0.00, 0.5, 1.0, 0.5,
299 double const dot[] = {
300 // 1, 0.5, 0.2, 0.5, 0.2,
301 // 1, 0.4, 0.4, 0.6, 0.4,
302 // 1, 0.5, 0.5, 0.5, 0.5,
303 5, 0.4, 0.6, 0.6, 0.6,
308 double const ddot[] = {
309 5, 0.1, 0.6, 0.3, 0.6,
310 5, 0.6, 0.6, 0.8, 0.6,
315 double const dddot[] = {
316 5, -0.2, 0.6, 0.0, 0.6,
317 5, 0.3, 0.6, 0.5, 0.6,
318 5, 0.8, 0.6, 1.0, 0.6,
323 double const ddddot[] = {
324 5, -0.4, 0.6, -0.2, 0.6,
325 5, 0.1, 0.6, 0.3, 0.6,
326 5, 0.6, 0.6, 0.8, 0.6,
327 5, 1.1, 0.6, 1.3, 0.6,
332 double const hline3[] = {
334 1, 0.475, 0, 0.525, 0,
340 double const dline3[] = {
341 1, 0.1, 0.1, 0.15, 0.15,
342 1, 0.475, 0.475, 0.525, 0.525,
343 1, 0.85, 0.85, 0.9, 0.9,
348 double const ring[] = {
350 0.5, 0.8, 0.7, 0.7, 0.8, 0.4,
351 0.7, 0.1, 0.5, 0.0, 0.3, 0.1,
352 0.2, 0.4, 0.3, 0.7, 0.5, 0.8,
357 double const vert[] = {
358 1, 0.5, 0.05, 0.5, 0.95,
363 double const Vert[] = {
364 1, 0.3, 0.05, 0.3, 0.95,
365 1, 0.7, 0.05, 0.7, 0.95,
370 double const tilde[] = {
372 0.0, 0.8, 0.15, 0.2, 0.35, 0.2, 0.65, 0.8, 0.85, 0.8, 1.0, 0.2,
382 struct named_deco_struct {
388 named_deco_struct deco_table[] = {
390 {"widehat", angle, 3 },
391 {"widetilde", tilde, 0 },
392 {"underbar", hline, 0 },
393 {"underline", hline, 0 },
394 {"overline", hline, 0 },
395 {"underbrace", brace, 1 },
396 {"overbrace", brace, 3 },
397 {"overleftarrow", arrow, 1 },
398 {"overrightarrow", arrow, 3 },
399 {"overleftrightarrow", udarrow, 1 },
400 {"xhookleftarrow", lhook, 0 },
401 {"xhookrightarrow", rhook, 0 },
402 {"xleftarrow", arrow, 1 },
403 {"xLeftarrow", LArrow, 0 },
404 {"xleftharpoondown", lharpoondown, 0 },
405 {"xleftharpoonup", lharpoonup, 0 },
406 {"xleftrightharpoons", lrharpoons, 0 },
407 {"xleftrightarrow", udarrow, 1 },
408 {"xLeftrightarrow", LRArrow, 0 },
409 {"xmapsto", mapsto, 0 },
410 {"xrightarrow", arrow, 3 },
411 {"xRightarrow", LArrow, 2 },
412 {"xrightharpoondown", lharpoonup, 2 },
413 {"xrightharpoonup", lharpoondown, 2 },
414 {"xrightleftharpoons", rlharpoons, 0 },
415 {"underleftarrow", arrow, 1 },
416 {"underrightarrow", arrow, 3 },
417 {"underleftrightarrow", udarrow, 1 },
418 {"undertilde", tilde, 0 },
419 {"utilde", tilde, 0 },
426 {"lbrace", brace, 0 },
427 {"rbrace", brace, 2 },
430 {"llbracket", dbrack, 0 },
431 {"rrbracket", dbrack, 2 },
434 {"slash", slash, 0 },
445 {"backslash", slash, 1 },
446 {"langle", angle, 0 },
447 {"lceil", corner, 0 },
448 {"lfloor", corner, 1 },
449 {"rangle", angle, 2 },
450 {"rceil", corner, 3 },
451 {"rfloor", corner, 2 },
452 {"downarrow", arrow, 2 },
453 {"Downarrow", Arrow, 2 },
454 {"uparrow", arrow, 0 },
455 {"Uparrow", Arrow, 0 },
456 {"updownarrow", udarrow, 0 },
457 {"Updownarrow", Udarrow, 0 },
461 {"dddot", dddot, 0 },
462 {"ddddot", ddddot, 0 },
464 {"grave", slash, 1 },
465 {"acute", slash, 0 },
466 {"tilde", tilde, 0 },
469 {"check", angle, 1 },
470 {"breve", parenth, 1 },
472 {"mathring", ring, 0 },
475 {"dots", hline3, 0 },
476 {"ldots", hline3, 0 },
477 {"cdots", hline3, 0 },
478 {"vdots", hline3, 1 },
479 {"ddots", dline3, 0 },
480 {"adots", dline3, 1 },
481 {"iddots", dline3, 1 },
482 {"dotsb", hline3, 0 },
483 {"dotsc", hline3, 0 },
484 {"dotsi", hline3, 0 },
485 {"dotsm", hline3, 0 },
486 {"dotso", hline3, 0 }
490 map<docstring, deco_struct> deco_list;
492 // sort the table on startup
493 class init_deco_table {
496 unsigned const n = sizeof(deco_table) / sizeof(deco_table[0]);
497 for (named_deco_struct * p = deco_table; p != deco_table + n; ++p) {
501 deco_list[from_ascii(p->name)] = d;
506 static init_deco_table dummy_deco_table;
509 deco_struct const * search_deco(docstring const & name)
511 map<docstring, deco_struct>::const_iterator p = deco_list.find(name);
512 return p == deco_list.end() ? 0 : &(p->second);
519 int mathed_font_em(FontInfo const & font)
521 return theFontMetrics(font).em();
525 int mathed_font_x_height(FontInfo const & font)
527 return theFontMetrics(font).xHeight();
530 /* The math units. Quoting TeX by Topic, p.205:
532 * Spacing around mathematical objects is measured in mu units. A mu
533 * is 1/18th part of \fontdimen6 of the font in family 2 in the
534 * current style, the ‘quad’ value of the symbol font.
536 * A \thickmuskip (default value in plain TeX: 5mu plus 5mu) is
537 * inserted around (binary) relations, except where these are preceded
538 * or followed by other relations or punctuation, and except if they
539 * follow an open, or precede a close symbol.
541 * A \medmuskip (default value in plain TeX: 4mu plus 2mu minus 4mu)
542 * is put around binary operators.
544 * A \thinmuskip (default value in plain TeX: 3mu) follows after
545 * punctuation, and is put around inner objects, except where these
546 * are followed by a close or preceded by an open symbol, and except
547 * if the other object is a large operator or a binary relation.
549 * See the file MathClass.cpp for a formal implementation of the rules
553 int mathed_mu(FontInfo const & font, double mu)
555 MetricsBase mb(nullptr, font);
556 return mb.inPixels(Length(mu, Length::MU));
559 int mathed_thinmuskip(FontInfo const & font) { return mathed_mu(font, 3.0); }
560 int mathed_medmuskip(FontInfo const & font) { return mathed_mu(font, 4.0); }
561 int mathed_thickmuskip(FontInfo const & font) { return mathed_mu(font, 5.0); }
564 int mathed_char_width(FontInfo const & font, char_type c)
566 return theFontMetrics(font).width(c);
570 int mathed_char_kerning(FontInfo const & font, char_type c)
572 frontend::FontMetrics const & fm = theFontMetrics(font);
573 return max(0, fm.rbearing(c) - fm.width(c));
577 double mathed_char_slope(MetricsBase const & mb, char_type c)
579 bool slanted = isAlphaASCII(c) || Encodings::isMathAlpha(c);
580 if (slanted && mb.fontname == "mathnormal")
581 return theFontMetrics(mb.font).italicSlope();
586 void mathed_string_dim(FontInfo const & font,
590 frontend::FontMetrics const & fm = theFontMetrics(font);
593 for (char_type const c : s) {
594 dim.asc = max(dim.asc, fm.ascent(c));
595 dim.des = max(dim.des, fm.descent(c));
597 dim.wid = fm.width(s);
601 int mathed_string_width(FontInfo const & font, docstring const & s)
603 return theFontMetrics(font).width(s);
607 void mathed_draw_deco(PainterInfo & pi, int x, int y, int w, int h,
608 docstring const & name)
610 int const lw = pi.base.solidLineThickness();
613 pi.pain.line(x + w/2, y, x + w/2, y + h,
614 Color_cursor, Painter::line_onoffdash, lw);
618 deco_struct const * mds = search_deco(name);
620 lyxerr << "Deco was not found. Programming error?" << endl;
621 lyxerr << "name: '" << to_utf8(name) << "'" << endl;
625 int const n = (w < h) ? w : h;
626 int const r = mds->angle;
627 double const * d = mds->data;
629 if (h > 70 && (name == "(" || name == ")"))
633 Matrix sqmt(r, n, n);
641 for (int i = 0; d[i]; ) {
642 int code = int(d[i++]);
643 if (code & 1) { // code == 1 || code == 3 || code == 5
649 sqmt.transform(xx, yy);
651 mt.transform(xx, yy);
652 mt.transform(x2, y2);
654 int(x + xx + 0.5), int(y + yy + 0.5),
655 int(x + x2 + 0.5), int(y + y2 + 0.5),
656 pi.base.font.color(), Painter::line_solid, lw);
657 if (code == 5) { // thicker, but rounded
658 double const xa = x + xx + 0.5;
659 double const xb = x + x2 + 0.5;
660 double const ya = y + yy + 0.5;
661 double const yb = y + y2 + 0.5;
662 pi.pain.line(int(xa + 1), int(ya - 1),
663 int(xb - 1), int(yb - 1),
664 pi.base.font.color(),
665 Painter::line_solid, lw);
666 pi.pain.line(int(xa + 1), int(ya + 1),
667 int(xb - 1), int(yb + 1),
668 pi.base.font.color(),
669 Painter::line_solid, lw);
670 if (xa + 2 <= xb - 2) {
671 pi.pain.line(int(xa + 2), int(ya - 2),
672 int(xb - 2), int(yb - 2),
673 pi.base.font.color(),
674 Painter::line_solid, lw);
675 pi.pain.line(int(xa + 2), int(ya + 2),
676 int(xb - 2), int(yb + 2),
677 pi.base.font.color(),
678 Painter::line_solid, lw);
680 if (xa + 3 <= xb - 3) {
681 pi.pain.line(int(xa + 3), int(ya - 3),
682 int(xb - 3), int(yb - 3),
683 pi.base.font.color(),
684 Painter::line_solid, lw);
685 pi.pain.line(int(xa + 3), int(ya + 3),
686 int(xb - 3), int(yb + 3),
687 pi.base.font.color(),
688 Painter::line_solid, lw);
690 if (xa + 4 <= xb - 4) {
691 pi.pain.line(int(xa + 4), int(ya - 4),
692 int(xb - 4), int(yb - 4),
693 pi.base.font.color(),
694 Painter::line_solid, lw);
695 pi.pain.line(int(xa + 4), int(ya + 4),
696 int(xb - 4), int(yb + 4),
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);