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];
190 LyXFont const & whichFontBase(MathTextCodes type)
197 if (math_font_available(LM_TC_MSB))
198 return MathFonts[FONT_MSB];
200 return MathFonts[FONT_FAKEBB];
203 if (math_font_available(LM_TC_CMSY))
204 return MathFonts[FONT_CMSY];
206 return MathFonts[FONT_FAKECAL];
209 if (math_font_available(LM_TC_EUFRAK))
210 return MathFonts[FONT_EUFRAK];
212 return MathFonts[FONT_FAKEFRAK];
217 return whichFontBaseIntern(type);
221 LyXFont whichFont(MathTextCodes type, MathMetricsInfo const & size)
223 LyXFont f = whichFontBase(type);
225 f.setSize(size.font.size());
227 switch (size.style) {
229 if (type == LM_TC_BOLDSYMB || type == LM_TC_CMEX) {
243 case LM_ST_SCRIPTSCRIPT:
250 lyxerr << "Math Error: wrong font size: " << size.style << endl;
254 if (type != LM_TC_TEXTRM && type != LM_TC_BOX)
255 f.setColor(LColor::math);
257 if (type == LM_TC_TEX)
258 f.setColor(LColor::latex);
266 bool math_font_available(MathTextCodes type)
268 if (!font_available_initialized[type]) {
269 font_available_initialized[type] = true;
270 font_available[type] = fontloader.available(whichFontBaseIntern(type));
272 return font_available[type];
279 * Internal struct of a drawing: code n x1 y1 ... xn yn, where code is:
280 * 0 = end, 1 = line, 2 = polyline, 3 = square line, 4= square polyline
284 double const parenthHigh[] = {
286 0.9840, 0.0014, 0.7143, 0.0323, 0.4603, 0.0772,
287 0.2540, 0.1278, 0.1746, 0.1966, 0.0952, 0.3300,
288 0.0950, 0.5000, 0.0952, 0.6700, 0.1746, 0.8034,
289 0.2540, 0.8722, 0.4603, 0.9228, 0.7143, 0.9677,
295 double const parenth[] = {
297 0.9930, 0.0071, 0.7324, 0.0578, 0.5141, 0.1126,
298 0.3380, 0.1714, 0.2183, 0.2333, 0.0634, 0.3621,
299 0.0141, 0.5000, 0.0563, 0.6369, 0.2113, 0.7647,
300 0.3310, 0.8276, 0.5070, 0.8864, 0.7254, 0.9412,
306 double const brace[] = {
308 0.9492, 0.0020, 0.9379, 0.0020, 0.7458, 0.0243,
309 0.5819, 0.0527, 0.4859, 0.0892, 0.4463, 0.1278,
310 0.4463, 0.3732, 0.4011, 0.4199, 0.2712, 0.4615,
311 0.0734, 0.4919, 0.0113, 0.5000, 0.0734, 0.5081,
312 0.2712, 0.5385, 0.4011, 0.5801, 0.4463, 0.6268,
313 0.4463, 0.8722, 0.4859, 0.9108, 0.5819, 0.9473,
314 0.7458, 0.9757, 0.9379, 0.9980, 0.9492, 0.9980,
319 double const arrow[] = {
321 0.0150, 0.7500, 0.2000, 0.6000, 0.3500, 0.3500,
322 0.5000, 0.0500, 0.6500, 0.3500, 0.8000, 0.6000,
324 3, 0.5000, 0.1500, 0.5000, 0.9500,
329 double const Arrow[] = {
331 0.0150, 0.7500, 0.2000, 0.6000, 0.3500, 0.3500,
332 0.5000, 0.0500, 0.6500, 0.3500, 0.8000, 0.6000,
334 3, 0.3500, 0.5000, 0.3500, 0.9500,
335 3, 0.6500, 0.5000, 0.6500, 0.9500,
340 double const udarrow[] = {
342 0.015, 0.25, 0.5, 0.05, 0.95, 0.25,
344 0.015, 0.75, 0.5, 0.95, 0.95, 0.75,
345 1, 0.5, 0.2, 0.5, 0.8,
350 double const Udarrow[] = {
352 0.015, 0.25, 0.5, 0.05, 0.95, 0.25,
354 0.015, 0.75, 0.5, 0.95, 0.95, 0.75,
355 1, 0.35, 0.2, 0.35, 0.8,
356 1, 0.65, 0.2, 0.65, 0.8,
361 double const brack[] = {
363 0.95, 0.05, 0.05, 0.05, 0.05, 0.95, 0.95, 0.95,
368 double const corner[] = {
370 0.95, 0.05, 0.05, 0.05, 0.05, 0.95,
375 double const angle[] = {
377 1, 0, 0.05, 0.5, 1, 1,
382 double const slash[] = {
383 1, 0.95, 0.05, 0.05, 0.95,
388 double const hline[] = {
389 1, 0.00, 0.5, 1.0, 0.5,
394 double const hline2[] = {
395 1, 0.1, 0.5, 0.3, 0.5,
396 1, 0.7, 0.5, 0.9, 0.5,
401 double const hline3[] = {
403 1, 0.475, 0, 0.525, 0,
409 double const dline3[] = {
410 1, 0.1, 0.1, 0.15, 0.15,
411 1, 0.475, 0.475, 0.525, 0.525,
412 1, 0.85, 0.85, 0.9, 0.9,
417 double const hlinesmall[] = {
418 1, 0.4, 0.5, 0.6, 0.5,
423 double const vert[] = {
424 1, 0.5, 0.05, 0.5, 0.95,
429 double const Vert[] = {
430 1, 0.3, 0.05, 0.3, 0.95,
431 1, 0.7, 0.05, 0.7, 0.95,
436 double const tilde[] = {
438 0.05, 0.8, 0.25, 0.2, 0.75, 0.8, 0.95, 0.2,
448 struct named_deco_struct {
454 named_deco_struct deco_table[] = {
456 {"widehat", angle, 3 },
457 {"widetilde", tilde, 0 },
458 {"underline", hline, 0 },
459 {"overline", hline, 0 },
460 {"underbrace", brace, 1 },
461 {"overbrace", brace, 3 },
462 {"overleftarrow", arrow, 1 },
463 {"overrightarrow", arrow, 3 },
476 {"backslash", slash, 1 },
477 {"langle", angle, 0 },
478 {"lceil", corner, 0 },
479 {"lfloor", corner, 1 },
480 {"rangle", angle, 2 },
481 {"rceil", corner, 3 },
482 {"rfloor", corner, 2 },
483 {"downarrow", arrow, 2 },
484 {"Downarrow", Arrow, 2 },
485 {"uparrow", arrow, 0 },
486 {"Uparrow", Arrow, 0 },
487 {"updownarrow", udarrow, 0 },
488 {"Updownarrow", Udarrow, 0 },
491 {"ddot", hline2, 0 },
493 {"grave", slash, 1 },
494 {"acute", slash, 0 },
495 {"tilde", tilde, 0 },
497 {"dot", hlinesmall, 0 },
498 {"check", angle, 1 },
499 {"breve", parenth, 1 },
504 {"ldots", hline3, 0 },
505 {"cdots", hline3, 0 },
506 {"vdots", hline3, 1 },
507 {"ddots", dline3, 0 }
511 map<string, deco_struct> deco_list;
513 // sort the table on startup
514 struct 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[p->name]= d;
526 static init_deco_table dummy;
529 deco_struct const * search_deco(string const & name)
531 map<string, deco_struct>::const_iterator p = deco_list.find(name);
532 return (p == deco_list.end()) ? 0 : &(p->second);
539 void mathed_char_dim(MathTextCodes type, MathMetricsInfo const & size,
540 unsigned char c, int & asc, int & des, int & wid)
542 LyXFont const font = whichFont(type, size);
543 des = lyxfont::descent(c, font);
544 asc = lyxfont::ascent(c, font);
545 wid = mathed_char_width(type, size, c);
549 int mathed_char_height(MathTextCodes type, MathMetricsInfo const & size,
550 unsigned char c, int & asc, int & des)
552 LyXFont const font = whichFont(type, size);
553 des = lyxfont::descent(c, font);
554 asc = lyxfont::ascent(c, font);
559 int mathed_char_height(MathTextCodes type, MathMetricsInfo const & size,
564 return mathed_char_height(type, size, c, asc, des);
568 int mathed_char_ascent(MathTextCodes type, MathMetricsInfo const & size,
571 LyXFont const font = whichFont(type, size);
572 return lyxfont::ascent(c, font);
576 int mathed_char_descent(MathTextCodes type, MathMetricsInfo const & size,
579 LyXFont const font = whichFont(type, size);
580 return lyxfont::descent(c, font);
584 int mathed_char_width(MathTextCodes type, MathMetricsInfo const & size,
587 LyXFont const font = whichFont(type, size);
588 if (isBinaryOp(c, type))
589 return lyxfont::width(c, font) + 2 * lyxfont::width(' ', font);
591 return lyxfont::width(c, font);
595 void mathed_string_dim(MathTextCodes type, MathMetricsInfo const & size,
596 string const & s, int & asc, int & des, int & wid)
598 mathed_string_height(type, size, s, asc, des);
599 wid = mathed_string_width(type, size, s);
603 int mathed_string_height(MathTextCodes type, MathMetricsInfo const & size,
604 string const & s, int & asc, int & des)
606 LyXFont const font = whichFont(type, size);
608 for (string::const_iterator it = s.begin(); it != s.end(); ++it) {
609 des = max(des, lyxfont::descent(*it, font));
610 asc = max(asc, lyxfont::ascent(*it, font));
616 int mathed_string_width(MathTextCodes type, MathMetricsInfo const & size,
619 return lyxfont::width(s, whichFont(type, size));
623 int mathed_string_ascent(MathTextCodes type, MathMetricsInfo const & size,
626 LyXFont const font = whichFont(type, size);
628 for (string::const_iterator it = s.begin(); it != s.end(); ++it)
629 asc = max(asc, lyxfont::ascent(*it, font));
634 int mathed_string_descent(MathTextCodes type, MathMetricsInfo const & size,
637 LyXFont const font = whichFont(type, size);
639 for (string::const_iterator it = s.begin(); it != s.end(); ++it)
640 des = max(des, lyxfont::descent(*it, font));
646 void mathed_draw_deco(Painter & pain, int x, int y, int w, int h,
650 pain.line(x + w/2, y, x + w/2, y + h,
651 LColor::mathcursor, Painter::line_onoffdash);
655 deco_struct const * mds = search_deco(name);
657 lyxerr << "Deco was not found. Programming error?\n";
658 lyxerr << "name: '" << name << "'\n";
662 int const n = (w < h) ? w : h;
663 int const r = mds->angle;
664 double const * d = mds->data;
666 if (h > 70 && (name == "(" || name == ")"))
670 Matrix sqmt(r, n, n);
678 for (int i = 0; d[i]; ) {
679 int code = int(d[i++]);
680 if (code & 1) { // code == 1 || code == 3
686 sqmt.transform(xx, yy);
688 mt.transform(xx, yy);
689 mt.transform(x2, y2);
690 pain.line(x + int(xx), y + int(yy), x + int(x2), y + int(y2),
695 int const n = int(d[i++]);
696 for (int j = 0; j < n; ++j) {
699 // lyxerr << " " << xx << " " << yy << " ";
701 sqmt.transform(xx, yy);
703 mt.transform(xx, yy);
706 // lyxerr << "P[" << j " " << xx << " " << yy << " " << x << " " << y << "]";
708 pain.lines(xp, yp, n, LColor::math);
714 void mathed_draw_framebox(Painter & pain, int x, int y, MathInset const * p)
716 if (mathcursor && mathcursor->isInside(p))
717 pain.rectangle(x, y - p->ascent(), p->width(), p->height(),
722 // In the future maybe we use a better fonts renderer
723 void drawStr(Painter & pain, MathTextCodes type, MathMetricsInfo const & siz,
724 int x, int y, string const & s)
726 pain.text(x, y, s, whichFont(type, siz));
730 void drawChar(Painter & pain, MathTextCodes type, MathMetricsInfo const & siz,
731 int x, int y, char c)
734 if (isBinaryOp(c, type))
737 if (isBinaryOp(c, type))
739 drawStr(pain, type, siz, x, y, s);
743 // decrease math size for super- and subscripts
744 void smallerStyleScript(MathMetricsInfo & st)
748 case LM_ST_TEXT: st.style = LM_ST_SCRIPT; break;
749 default: st.style = LM_ST_SCRIPTSCRIPT;
754 // decrease math size for fractions
755 void smallerStyleFrac(MathMetricsInfo & st)
758 case LM_ST_DISPLAY: st.style = LM_ST_TEXT; break;
759 case LM_ST_TEXT: st.style = LM_ST_SCRIPT; break;
760 default: st.style = LM_ST_SCRIPTSCRIPT;
765 void math_font_max_dim(MathTextCodes code, MathMetricsInfo const & siz,
766 int & asc, int & des)
768 LyXFont font = whichFont(code, siz);
769 asc = lyxfont::maxAscent(font);
770 des = lyxfont::maxDescent(font);
774 char const * latex_mathspace[] = {
775 "!", ",", ":", ";", "quad", "qquad"
779 char const * latex_mathstyle[] = {
780 "textstyle", "displaystyle", "scriptstyle", "scriptscriptstyle",
781 "mathbf", "mathcal","mathrm","mathtt", "mathsf", "mathit",
782 "mathbb","mathfrak", "textrm", "mathnormal"
786 char const * math_font_name(MathTextCodes code)
788 static char const * theFontNames[] = {
800 if (code >= LM_TC_RM && code <= LM_TC_TEXTRM)
801 return theFontNames[code - LM_TC_RM];