5 #include "math_support.h"
7 #include "FontLoader.h"
9 #include "math_cursor.h"
10 #include "math_defs.h"
11 #include "math_inset.h"
12 #include "math_parser.h"
21 bool isBinaryOp(char c, MathTextCodes type)
23 return type < LM_TC_SYMB && strchr("+-<>=/*", c);
31 Matrix(int, double, double);
33 void transform(double &, double &);
40 Matrix::Matrix(int code, double x, double y)
42 double const cs = (code & 1) ? 0 : (1 - code);
43 double const sn = (code & 1) ? (2 - code) : 0;
51 void Matrix::transform(double & x, double & y)
53 double xx = m_[0][0] * x + m_[0][1] * y;
54 double yy = m_[1][0] * x + m_[1][1] * y;
62 LyXFont * MathFonts = 0;
63 bool font_available[LM_FONT_END];
64 bool font_available_initialized[LM_FONT_END];
87 void mathed_init_fonts()
89 MathFonts = new LyXFont[FONT_NUM];
91 MathFonts[FONT_IT].setShape(LyXFont::ITALIC_SHAPE);
93 MathFonts[FONT_SYMBOL].setFamily(LyXFont::SYMBOL_FAMILY);
95 MathFonts[FONT_SYMBOLI].setFamily(LyXFont::SYMBOL_FAMILY);
96 MathFonts[FONT_SYMBOLI].setShape(LyXFont::ITALIC_SHAPE);
98 MathFonts[FONT_BF].setSeries(LyXFont::BOLD_SERIES);
100 MathFonts[FONT_TT].setFamily(LyXFont::TYPEWRITER_FAMILY);
101 MathFonts[FONT_RM].setFamily(LyXFont::ROMAN_FAMILY);
102 MathFonts[FONT_SF].setFamily(LyXFont::SANS_FAMILY);
104 MathFonts[FONT_CMR].setFamily(LyXFont::CMR_FAMILY);
105 MathFonts[FONT_CMSY].setFamily(LyXFont::CMSY_FAMILY);
106 MathFonts[FONT_CMM].setFamily(LyXFont::CMM_FAMILY);
107 MathFonts[FONT_CMEX].setFamily(LyXFont::CMEX_FAMILY);
108 MathFonts[FONT_MSA].setFamily(LyXFont::MSA_FAMILY);
109 MathFonts[FONT_MSB].setFamily(LyXFont::MSB_FAMILY);
110 MathFonts[FONT_EUFRAK].setFamily(LyXFont::EUFRAK_FAMILY);
112 MathFonts[FONT_FAKEBB].setFamily(LyXFont::TYPEWRITER_FAMILY);
113 MathFonts[FONT_FAKEBB].setSeries(LyXFont::BOLD_SERIES);
115 MathFonts[FONT_FAKECAL].setFamily(LyXFont::SANS_FAMILY);
116 MathFonts[FONT_FAKECAL].setShape(LyXFont::ITALIC_SHAPE);
118 MathFonts[FONT_FAKEFRAK].setFamily(LyXFont::SANS_FAMILY);
119 MathFonts[FONT_FAKEFRAK].setSeries(LyXFont::BOLD_SERIES);
121 for (int i = 0; i < LM_FONT_END; ++i)
122 font_available_initialized[i] = false;
126 LyXFont const & whichFontBaseIntern(MathTextCodes type)
134 return MathFonts[FONT_SYMBOLI];
138 return MathFonts[FONT_IT];
141 return MathFonts[FONT_BF];
144 return MathFonts[FONT_MSB];
147 return MathFonts[FONT_CMSY];
150 return MathFonts[FONT_TT];
157 return MathFonts[FONT_RM];
160 return MathFonts[FONT_SF];
163 return MathFonts[FONT_CMR];
166 return MathFonts[FONT_CMSY];
169 return MathFonts[FONT_CMM];
172 return MathFonts[FONT_CMEX];
175 return MathFonts[FONT_MSA];
178 return MathFonts[FONT_MSB];
181 return MathFonts[FONT_EUFRAK];
189 LyXFont const & whichFontBase(MathTextCodes type)
196 if (math_font_available(LM_TC_MSB))
197 return MathFonts[FONT_MSB];
199 return MathFonts[FONT_FAKEBB];
202 if (math_font_available(LM_TC_CMSY))
203 return MathFonts[FONT_CMSY];
205 return MathFonts[FONT_FAKECAL];
208 if (math_font_available(LM_TC_EUFRAK))
209 return MathFonts[FONT_EUFRAK];
211 return MathFonts[FONT_FAKEFRAK];
216 return whichFontBaseIntern(type);
220 LyXFont whichFont(MathTextCodes type, MathMetricsInfo const & size)
222 LyXFont f = whichFontBase(type);
224 f.setSize(size.font.size());
226 switch (size.style) {
228 if (type == LM_TC_BOLDSYMB || type == LM_TC_CMEX) {
242 case LM_ST_SCRIPTSCRIPT:
249 lyxerr << "Math Error: wrong font size: " << size.style << endl;
253 if (type != LM_TC_TEXTRM && type != LM_TC_BOX)
254 f.setColor(LColor::math);
256 if (type == LM_TC_TEX)
257 f.setColor(LColor::latex);
265 bool math_font_available(MathTextCodes type)
267 if (!font_available_initialized[type]) {
268 font_available_initialized[type] = true;
269 font_available[type] = fontloader.available(whichFontBaseIntern(type));
271 return font_available[type];
278 * Internal struct of a drawing: code n x1 y1 ... xn yn, where code is:
279 * 0 = end, 1 = line, 2 = polyline, 3 = square line, 4= square polyline
283 double const parenthHigh[] = {
285 0.9840, 0.0014, 0.7143, 0.0323, 0.4603, 0.0772,
286 0.2540, 0.1278, 0.1746, 0.1966, 0.0952, 0.3300,
287 0.0950, 0.5000, 0.0952, 0.6700, 0.1746, 0.8034,
288 0.2540, 0.8722, 0.4603, 0.9228, 0.7143, 0.9677,
294 double const parenth[] = {
296 0.9930, 0.0071, 0.7324, 0.0578, 0.5141, 0.1126,
297 0.3380, 0.1714, 0.2183, 0.2333, 0.0634, 0.3621,
298 0.0141, 0.5000, 0.0563, 0.6369, 0.2113, 0.7647,
299 0.3310, 0.8276, 0.5070, 0.8864, 0.7254, 0.9412,
305 double const brace[] = {
307 0.9492, 0.0020, 0.9379, 0.0020, 0.7458, 0.0243,
308 0.5819, 0.0527, 0.4859, 0.0892, 0.4463, 0.1278,
309 0.4463, 0.3732, 0.4011, 0.4199, 0.2712, 0.4615,
310 0.0734, 0.4919, 0.0113, 0.5000, 0.0734, 0.5081,
311 0.2712, 0.5385, 0.4011, 0.5801, 0.4463, 0.6268,
312 0.4463, 0.8722, 0.4859, 0.9108, 0.5819, 0.9473,
313 0.7458, 0.9757, 0.9379, 0.9980, 0.9492, 0.9980,
318 double const arrow[] = {
320 0.0150, 0.7500, 0.2000, 0.6000, 0.3500, 0.3500,
321 0.5000, 0.0500, 0.6500, 0.3500, 0.8000, 0.6000,
323 3, 0.5000, 0.1500, 0.5000, 0.9500,
328 double const Arrow[] = {
330 0.0150, 0.7500, 0.2000, 0.6000, 0.3500, 0.3500,
331 0.5000, 0.0500, 0.6500, 0.3500, 0.8000, 0.6000,
333 3, 0.3500, 0.5000, 0.3500, 0.9500,
334 3, 0.6500, 0.5000, 0.6500, 0.9500,
339 double const udarrow[] = {
341 0.015, 0.25, 0.5, 0.05, 0.95, 0.25,
343 0.015, 0.75, 0.5, 0.95, 0.95, 0.75,
344 1, 0.5, 0.2, 0.5, 0.8,
349 double const Udarrow[] = {
351 0.015, 0.25, 0.5, 0.05, 0.95, 0.25,
353 0.015, 0.75, 0.5, 0.95, 0.95, 0.75,
354 1, 0.35, 0.2, 0.35, 0.8,
355 1, 0.65, 0.2, 0.65, 0.8,
360 double const brack[] = {
362 0.95, 0.05, 0.05, 0.05, 0.05, 0.95, 0.95, 0.95,
367 double const corner[] = {
369 0.95, 0.05, 0.05, 0.05, 0.05, 0.95,
374 double const angle[] = {
376 1, 0, 0.05, 0.5, 1, 1,
381 double const slash[] = {
382 1, 0.95, 0.05, 0.05, 0.95,
387 double const hline[] = {
388 1, 0.00, 0.5, 1.0, 0.5,
393 double const hline2[] = {
394 1, 0.1, 0.5, 0.3, 0.5,
395 1, 0.7, 0.5, 0.9, 0.5,
400 double const hline3[] = {
402 1, 0.475, 0, 0.525, 0,
408 double const dline3[] = {
409 1, 0.1, 0.1, 0.15, 0.15,
410 1, 0.475, 0.475, 0.525, 0.525,
411 1, 0.85, 0.85, 0.9, 0.9,
416 double const hlinesmall[] = {
417 1, 0.4, 0.5, 0.6, 0.5,
422 double const vert[] = {
423 1, 0.5, 0.05, 0.5, 0.95,
428 double const Vert[] = {
429 1, 0.3, 0.05, 0.3, 0.95,
430 1, 0.7, 0.05, 0.7, 0.95,
435 double const tilde[] = {
437 0.05, 0.8, 0.25, 0.2, 0.75, 0.8, 0.95, 0.2,
447 struct named_deco_struct {
453 named_deco_struct deco_table[] = {
455 {"widehat", angle, 3 },
456 {"widetilde", tilde, 0 },
457 {"underline", hline, 0 },
458 {"overline", hline, 0 },
459 {"underbrace", brace, 1 },
460 {"overbrace", brace, 3 },
461 {"overleftarrow", arrow, 1 },
462 {"overrightarrow", arrow, 3 },
475 {"backslash", slash, 1 },
476 {"langle", angle, 0 },
477 {"lceil", corner, 0 },
478 {"lfloor", corner, 1 },
479 {"rangle", angle, 2 },
480 {"rceil", corner, 3 },
481 {"rfloor", corner, 2 },
482 {"downarrow", arrow, 2 },
483 {"Downarrow", Arrow, 2 },
484 {"uparrow", arrow, 0 },
485 {"Uparrow", Arrow, 0 },
486 {"updownarrow", udarrow, 0 },
487 {"Updownarrow", Udarrow, 0 },
490 {"ddot", hline2, 0 },
492 {"grave", slash, 1 },
493 {"acute", slash, 0 },
494 {"tilde", tilde, 0 },
496 {"dot", hlinesmall, 0 },
497 {"check", angle, 1 },
498 {"breve", parenth, 1 },
503 {"ldots", hline3, 0 },
504 {"cdots", hline3, 0 },
505 {"vdots", hline3, 1 },
506 {"ddots", dline3, 0 }
510 map<string, deco_struct> deco_list;
512 // sort the table on startup
513 struct init_deco_table {
515 unsigned const n = sizeof(deco_table) / sizeof(deco_table[0]);
516 for (named_deco_struct * p = deco_table; p != deco_table + n; ++p) {
520 deco_list[p->name]= d;
525 static init_deco_table dummy;
528 deco_struct const * search_deco(string const & name)
530 map<string, deco_struct>::const_iterator p = deco_list.find(name);
531 return (p == deco_list.end()) ? 0 : &(p->second);
538 void mathed_char_dim(MathTextCodes type, MathMetricsInfo const & size,
539 unsigned char c, int & asc, int & des, int & wid)
541 LyXFont const font = whichFont(type, size);
542 des = lyxfont::descent(c, font);
543 asc = lyxfont::ascent(c, font);
544 wid = mathed_char_width(type, size, c);
548 int mathed_char_height(MathTextCodes type, MathMetricsInfo const & size,
549 unsigned char c, int & asc, int & des)
551 LyXFont const font = whichFont(type, size);
552 des = lyxfont::descent(c, font);
553 asc = lyxfont::ascent(c, font);
558 int mathed_char_height(MathTextCodes type, MathMetricsInfo const & size,
563 return mathed_char_height(type, size, c, asc, des);
567 int mathed_char_ascent(MathTextCodes type, MathMetricsInfo const & size,
570 LyXFont const font = whichFont(type, size);
571 return lyxfont::ascent(c, font);
575 int mathed_char_descent(MathTextCodes type, MathMetricsInfo const & size,
578 LyXFont const font = whichFont(type, size);
579 return lyxfont::descent(c, font);
583 int mathed_char_width(MathTextCodes type, MathMetricsInfo const & size,
586 LyXFont const font = whichFont(type, size);
587 if (isBinaryOp(c, type))
588 return lyxfont::width(c, font) + 2 * lyxfont::width(' ', font);
590 return lyxfont::width(c, font);
594 void mathed_string_dim(MathTextCodes type, MathMetricsInfo const & size,
595 string const & s, int & asc, int & des, int & wid)
597 mathed_string_height(type, size, s, asc, des);
598 wid = mathed_string_width(type, size, s);
602 int mathed_string_height(MathTextCodes type, MathMetricsInfo const & size,
603 string const & s, int & asc, int & des)
605 LyXFont const font = whichFont(type, size);
607 for (string::const_iterator it = s.begin(); it != s.end(); ++it) {
608 des = max(des, lyxfont::descent(*it, font));
609 asc = max(asc, lyxfont::ascent(*it, font));
615 int mathed_string_width(MathTextCodes type, MathMetricsInfo const & size,
618 return lyxfont::width(s, whichFont(type, size));
622 int mathed_string_ascent(MathTextCodes type, MathMetricsInfo const & size,
625 LyXFont const font = whichFont(type, size);
627 for (string::const_iterator it = s.begin(); it != s.end(); ++it)
628 asc = max(asc, lyxfont::ascent(*it, font));
633 int mathed_string_descent(MathTextCodes type, MathMetricsInfo const & size,
636 LyXFont const font = whichFont(type, size);
638 for (string::const_iterator it = s.begin(); it != s.end(); ++it)
639 des = max(des, lyxfont::descent(*it, font));
645 void mathed_draw_deco(Painter & pain, int x, int y, int w, int h,
649 pain.line(x + w/2, y, x + w/2, y + h,
650 LColor::mathcursor, Painter::line_onoffdash);
654 deco_struct const * mds = search_deco(name);
656 lyxerr << "Deco was not found. Programming error?\n";
657 lyxerr << "name: '" << name << "'\n";
661 int const n = (w < h) ? w : h;
662 int const r = mds->angle;
663 double const * d = mds->data;
665 if (h > 70 && (name == "(" || name == ")"))
669 Matrix sqmt(r, n, n);
677 for (int i = 0; d[i]; ) {
678 int code = int(d[i++]);
679 if (code & 1) { // code == 1 || code == 3
685 sqmt.transform(xx, yy);
687 mt.transform(xx, yy);
688 mt.transform(x2, y2);
689 pain.line(x + int(xx), y + int(yy), x + int(x2), y + int(y2),
694 int const n = int(d[i++]);
695 for (int j = 0; j < n; ++j) {
698 // lyxerr << " " << xx << " " << yy << " ";
700 sqmt.transform(xx, yy);
702 mt.transform(xx, yy);
705 // lyxerr << "P[" << j " " << xx << " " << yy << " " << x << " " << y << "]";
707 pain.lines(xp, yp, n, LColor::math);
713 void mathed_draw_framebox(Painter & pain, int x, int y, MathInset const * p)
715 if (mathcursor && mathcursor->isInside(p))
716 pain.rectangle(x, y - p->ascent(), p->width(), p->height(),
721 // In the future maybe we use a better fonts renderer
722 void drawStr(Painter & pain, MathTextCodes type, MathMetricsInfo const & siz,
723 int x, int y, string const & s)
725 pain.text(x, y, s, whichFont(type, siz));
729 void drawChar(Painter & pain, MathTextCodes type, MathMetricsInfo const & siz,
730 int x, int y, char c)
733 if (isBinaryOp(c, type))
736 if (isBinaryOp(c, type))
738 drawStr(pain, type, siz, x, y, s);
742 // decrease math size for super- and subscripts
743 void smallerStyleScript(MathMetricsInfo & st)
747 case LM_ST_TEXT: st.style = LM_ST_SCRIPT; break;
748 default: st.style = LM_ST_SCRIPTSCRIPT;
753 // decrease math size for fractions
754 void smallerStyleFrac(MathMetricsInfo & st)
757 case LM_ST_DISPLAY: st.style = LM_ST_TEXT; break;
758 case LM_ST_TEXT: st.style = LM_ST_SCRIPT; break;
759 default: st.style = LM_ST_SCRIPTSCRIPT;
764 void math_font_max_dim(MathTextCodes code, MathMetricsInfo const & siz,
765 int & asc, int & des)
767 LyXFont font = whichFont(code, siz);
768 asc = lyxfont::maxAscent(font);
769 des = lyxfont::maxDescent(font);
773 char const * latex_mathspace[] = {
774 "!", ",", ":", ";", "quad", "qquad"
778 char const * math_font_name(MathTextCodes code)
780 static char const * theFontNames[] = {
792 if (code >= LM_TC_RM && code <= LM_TC_TEXTRM)
793 return theFontNames[code - LM_TC_RM];