5 #include "math_support.h"
7 #include "FontLoader.h"
10 #include "math_inset.h"
11 #include "math_parser.h"
20 bool isBinaryOp(char c, MathTextCodes type)
22 return type < LM_TC_SYMB && strchr("+-<>=/*", c);
30 Matrix(int, double, double);
32 void transform(double &, double &);
39 Matrix::Matrix(int code, double x, double y)
41 double const cs = (code & 1) ? 0 : (1 - code);
42 double const sn = (code & 1) ? (2 - code) : 0;
50 void Matrix::transform(double & x, double & y)
52 double xx = m_[0][0] * x + m_[0][1] * y;
53 double yy = m_[1][0] * x + m_[1][1] * y;
61 LyXFont * MathFonts = 0;
62 bool font_available[LM_FONT_END];
63 bool font_available_initialized[LM_FONT_END];
84 void mathed_init_fonts()
86 MathFonts = new LyXFont[FONT_NUM]; //DEC cxx cannot initialize all fonts
89 for (int i = 0 ; i < FONT_NUM ; ++i) {
90 MathFonts[i] = LyXFont(LyXFont::ALL_SANE);
93 MathFonts[FONT_IT].setShape(LyXFont::ITALIC_SHAPE);
95 MathFonts[FONT_SYMBOL].setFamily(LyXFont::SYMBOL_FAMILY);
97 MathFonts[FONT_SYMBOLI].setFamily(LyXFont::SYMBOL_FAMILY);
98 MathFonts[FONT_SYMBOLI].setShape(LyXFont::ITALIC_SHAPE);
100 MathFonts[FONT_BF].setSeries(LyXFont::BOLD_SERIES);
102 MathFonts[FONT_BB].setSeries(LyXFont::BOLD_SERIES);
103 MathFonts[FONT_BB].setFamily(LyXFont::TYPEWRITER_FAMILY);
105 MathFonts[FONT_CAL].setFamily(LyXFont::SANS_FAMILY);
106 MathFonts[FONT_CAL].setShape(LyXFont::ITALIC_SHAPE);
108 MathFonts[FONT_TT].setFamily(LyXFont::TYPEWRITER_FAMILY);
110 MathFonts[FONT_RM].setFamily(LyXFont::ROMAN_FAMILY);
112 MathFonts[FONT_SF].setFamily(LyXFont::SANS_FAMILY);
114 MathFonts[FONT_CMR].setFamily(LyXFont::CMR_FAMILY);
115 MathFonts[FONT_CMSY].setFamily(LyXFont::CMSY_FAMILY);
116 MathFonts[FONT_CMM].setFamily(LyXFont::CMM_FAMILY);
117 MathFonts[FONT_CMEX].setFamily(LyXFont::CMEX_FAMILY);
118 MathFonts[FONT_MSA].setFamily(LyXFont::MSA_FAMILY);
119 MathFonts[FONT_MSB].setFamily(LyXFont::MSB_FAMILY);
121 for (int i = 0; i < LM_FONT_END; ++i)
122 font_available_initialized[i] = false;
126 LyXFont const & whichFontBase(MathTextCodes type)
134 return MathFonts[FONT_SYMBOLI];
138 return MathFonts[FONT_IT];
141 return MathFonts[FONT_BF];
144 if (math_font_available(LM_TC_MSB))
145 return MathFonts[FONT_MSB];
147 return MathFonts[FONT_BB];
150 if (math_font_available(LM_TC_CMSY))
151 return MathFonts[FONT_CMSY];
153 return MathFonts[FONT_CAL];
156 return MathFonts[FONT_TT];
162 return MathFonts[FONT_RM];
165 return MathFonts[FONT_SF];
168 return MathFonts[FONT_CMR];
171 return MathFonts[FONT_CMSY];
174 return MathFonts[FONT_CMM];
177 return MathFonts[FONT_CMEX];
180 return MathFonts[FONT_MSA];
183 return MathFonts[FONT_MSB];
192 LyXFont whichFont(MathTextCodes type, MathMetricsInfo const & size)
194 LyXFont f = whichFontBase(type);
196 f.setSize(size.font.size());
198 switch (size.style) {
200 if (type == LM_TC_BOLDSYMB || type == LM_TC_CMEX) {
214 case LM_ST_SCRIPTSCRIPT:
221 lyxerr << "Math Error: wrong font size: " << size.style << endl;
225 if (type != LM_TC_TEXTRM)
226 f.setColor(LColor::math);
228 if (type == LM_TC_TEX)
229 f.setColor(LColor::latex);
237 bool math_font_available(MathTextCodes type)
239 if (!font_available_initialized[type]) {
240 font_available_initialized[type] = true;
241 font_available[type] = fontloader.available(whichFontBase(type));
243 return font_available[type];
250 * Internal struct of a drawing: code n x1 y1 ... xn yn, where code is:
251 * 0 = end, 1 = line, 2 = polyline, 3 = square line, 4= square polyline
255 double const parenthHigh[] = {
257 0.9840, 0.0014, 0.7143, 0.0323, 0.4603, 0.0772,
258 0.2540, 0.1278, 0.1746, 0.1966, 0.0952, 0.3300,
259 0.0950, 0.5000, 0.0952, 0.6700, 0.1746, 0.8034,
260 0.2540, 0.8722, 0.4603, 0.9228, 0.7143, 0.9677,
266 double const parenth[] = {
268 0.9930, 0.0071, 0.7324, 0.0578, 0.5141, 0.1126,
269 0.3380, 0.1714, 0.2183, 0.2333, 0.0634, 0.3621,
270 0.0141, 0.5000, 0.0563, 0.6369, 0.2113, 0.7647,
271 0.3310, 0.8276, 0.5070, 0.8864, 0.7254, 0.9412,
277 double const brace[] = {
279 0.9492, 0.0020, 0.9379, 0.0020, 0.7458, 0.0243,
280 0.5819, 0.0527, 0.4859, 0.0892, 0.4463, 0.1278,
281 0.4463, 0.3732, 0.4011, 0.4199, 0.2712, 0.4615,
282 0.0734, 0.4919, 0.0113, 0.5000, 0.0734, 0.5081,
283 0.2712, 0.5385, 0.4011, 0.5801, 0.4463, 0.6268,
284 0.4463, 0.8722, 0.4859, 0.9108, 0.5819, 0.9473,
285 0.7458, 0.9757, 0.9379, 0.9980, 0.9492, 0.9980,
290 double const arrow[] = {
292 0.0150, 0.7500, 0.2000, 0.6000, 0.3500, 0.3500,
293 0.5000, 0.0500, 0.6500, 0.3500, 0.8000, 0.6000,
295 3, 0.5000, 0.1500, 0.5000, 0.9500,
300 double const Arrow[] = {
302 0.0150, 0.7500, 0.2000, 0.6000, 0.3500, 0.3500,
303 0.5000, 0.0500, 0.6500, 0.3500, 0.8000, 0.6000,
305 3, 0.3500, 0.5000, 0.3500, 0.9500,
306 3, 0.6500, 0.5000, 0.6500, 0.9500,
311 double const udarrow[] = {
313 0.015, 0.25, 0.5, 0.05, 0.95, 0.25,
315 0.015, 0.75, 0.5, 0.95, 0.95, 0.75,
316 1, 0.5, 0.2, 0.5, 0.8,
321 double const Udarrow[] = {
323 0.015, 0.25, 0.5, 0.05, 0.95, 0.25,
325 0.015, 0.75, 0.5, 0.95, 0.95, 0.75,
326 1, 0.35, 0.2, 0.35, 0.8,
327 1, 0.65, 0.2, 0.65, 0.8,
332 double const brack[] = {
334 0.95, 0.05, 0.05, 0.05, 0.05, 0.95, 0.95, 0.95,
339 double const corner[] = {
341 0.95, 0.05, 0.05, 0.05, 0.05, 0.95,
346 double const angle[] = {
348 1, 0, 0.05, 0.5, 1, 1,
353 double const slash[] = {
354 1, 0.95, 0.05, 0.05, 0.95,
359 double const hline[] = {
360 1, 0.00, 0.5, 1.0, 0.5,
365 double const hline2[] = {
366 1, 0.1, 0.5, 0.3, 0.5,
367 1, 0.7, 0.5, 0.9, 0.5,
372 double const hline3[] = {
374 1, 0.475, 0, 0.525, 0,
380 double const dline3[] = {
381 1, 0.1, 0.1, 0.15, 0.15,
382 1, 0.475, 0.475, 0.525, 0.525,
383 1, 0.85, 0.85, 0.9, 0.9,
388 double const hlinesmall[] = {
389 1, 0.4, 0.5, 0.6, 0.5,
394 double const vert[] = {
395 1, 0.5, 0.05, 0.5, 0.95,
400 double const Vert[] = {
401 1, 0.3, 0.05, 0.3, 0.95,
402 1, 0.7, 0.05, 0.7, 0.95,
407 double const tilde[] = {
409 0.05, 0.8, 0.25, 0.2, 0.75, 0.8, 0.95, 0.2,
419 struct named_deco_struct {
425 named_deco_struct deco_table[] = {
427 {"widehat", angle, 3 },
428 {"widetilde", tilde, 0 },
429 {"underline", hline, 0 },
430 {"overline", hline, 0 },
431 {"underbrace", brace, 1 },
432 {"overbrace", brace, 3 },
433 {"overleftarrow", arrow, 1 },
434 {"overrightarrow", arrow, 3 },
447 {"backslash", slash, 1 },
448 {"langle", angle, 0 },
449 {"lceil", corner, 0 },
450 {"lfloor", corner, 1 },
451 {"rangle", angle, 2 },
452 {"rceil", corner, 3 },
453 {"rfloor", corner, 2 },
454 {"downarrow", arrow, 2 },
455 {"Downarrow", Arrow, 2 },
456 {"uparrow", arrow, 0 },
457 {"Uparrow", Arrow, 0 },
458 {"updownarrow", udarrow, 0 },
459 {"Updownarrow", Udarrow, 0 },
462 {"ddot", hline2, 0 },
464 {"grave", slash, 1 },
465 {"acute", slash, 0 },
466 {"tilde", tilde, 0 },
468 {"dot", hlinesmall, 0 },
469 {"check", angle, 1 },
470 {"breve", parenth, 1 },
475 {"ldots", hline3, 0 },
476 {"cdots", hline3, 0 },
477 {"vdots", hline3, 1 },
478 {"ddots", dline3, 0 }
482 map<string, deco_struct> deco_list;
484 // sort the table on startup
485 struct init_deco_table {
487 unsigned const n = sizeof(deco_table) / sizeof(deco_table[0]);
488 for (named_deco_struct * p = deco_table; p != deco_table + n; ++p) {
492 deco_list[p->name]= d;
497 static init_deco_table dummy;
500 deco_struct const * search_deco(string const & name)
502 map<string, deco_struct>::const_iterator p = deco_list.find(name);
503 return (p == deco_list.end()) ? 0 : &(p->second);
510 void mathed_char_dim(MathTextCodes type, MathMetricsInfo const & size,
511 unsigned char c, int & asc, int & des, int & wid)
513 LyXFont const font = whichFont(type, size);
514 des = lyxfont::descent(c, font);
515 asc = lyxfont::ascent(c, font);
516 wid = mathed_char_width(type, size, c);
520 int mathed_char_height(MathTextCodes type, MathMetricsInfo const & size,
521 unsigned char c, int & asc, int & des)
523 LyXFont const font = whichFont(type, size);
524 des = lyxfont::descent(c, font);
525 asc = lyxfont::ascent(c, font);
530 int mathed_char_height(MathTextCodes type, MathMetricsInfo const & size,
535 return mathed_char_height(type, size, c, asc, des);
539 int mathed_char_ascent(MathTextCodes type, MathMetricsInfo const & size,
542 LyXFont const font = whichFont(type, size);
543 return lyxfont::ascent(c, font);
547 int mathed_char_descent(MathTextCodes type, MathMetricsInfo const & size,
550 LyXFont const font = whichFont(type, size);
551 return lyxfont::descent(c, font);
555 int mathed_char_width(MathTextCodes type, MathMetricsInfo const & size,
558 LyXFont const font = whichFont(type, size);
559 if (isBinaryOp(c, type))
560 return lyxfont::width(c, font) + 2 * lyxfont::width(' ', font);
562 return lyxfont::width(c, font);
566 void mathed_string_dim(MathTextCodes type, MathMetricsInfo const & size,
567 string const & s, int & asc, int & des, int & wid)
569 mathed_string_height(type, size, s, asc, des);
570 wid = mathed_string_width(type, size, s);
574 int mathed_string_height(MathTextCodes type, MathMetricsInfo const & size,
575 string const & s, int & asc, int & des)
577 LyXFont const font = whichFont(type, size);
579 for (string::const_iterator it = s.begin(); it != s.end(); ++it) {
580 des = max(des, lyxfont::descent(*it, font));
581 asc = max(asc, lyxfont::ascent(*it, font));
587 int mathed_string_width(MathTextCodes type, MathMetricsInfo const & size,
590 return lyxfont::width(s, whichFont(type, size));
594 int mathed_string_ascent(MathTextCodes type, MathMetricsInfo const & size,
597 LyXFont const font = whichFont(type, size);
599 for (string::const_iterator it = s.begin(); it != s.end(); ++it)
600 asc = max(asc, lyxfont::ascent(*it, font));
605 int mathed_string_descent(MathTextCodes type, MathMetricsInfo const & size,
608 LyXFont const font = whichFont(type, size);
610 for (string::const_iterator it = s.begin(); it != s.end(); ++it)
611 des = max(des, lyxfont::descent(*it, font));
617 void mathed_draw_deco(Painter & pain, int x, int y, int w, int h,
621 pain.line(x + w/2, y, x + w/2, y + h,
622 LColor::mathcursor, Painter::line_onoffdash);
626 deco_struct const * mds = search_deco(name);
628 lyxerr << "Deco was not found. Programming error?\n";
629 lyxerr << "name: '" << name << "'\n";
633 int const n = (w < h) ? w : h;
634 int const r = mds->angle;
635 double const * d = mds->data;
637 if (h > 70 && (name == "(" || name == ")"))
641 Matrix sqmt(r, n, n);
649 for (int i = 0; d[i]; ) {
650 int code = int(d[i++]);
651 if (code & 1) { // code == 1 || code == 3
657 sqmt.transform(xx, yy);
659 mt.transform(xx, yy);
660 mt.transform(x2, y2);
661 pain.line(x + int(xx), y + int(yy), x + int(x2), y + int(y2),
666 int const n = int(d[i++]);
667 for (int j = 0; j < n; ++j) {
670 // lyxerr << " " << xx << " " << yy << " ";
672 sqmt.transform(xx, yy);
674 mt.transform(xx, yy);
677 // lyxerr << "P[" << j " " << xx << " " << yy << " " << x << " " << y << "]";
679 pain.lines(xp, yp, n, LColor::mathline);
685 // In the future maybe we use a better fonts renderer
686 void drawStr(Painter & pain, MathTextCodes type, MathMetricsInfo const & siz,
687 int x, int y, string const & s)
689 pain.text(x, y, s, whichFont(type, siz));
693 void drawChar(Painter & pain, MathTextCodes type, MathMetricsInfo const & siz,
694 int x, int y, char c)
697 if (isBinaryOp(c, type))
700 if (isBinaryOp(c, type))
702 drawStr(pain, type, siz, x, y, s);
706 // decrease math size for super- and subscripts
707 void smallerStyleScript(MathMetricsInfo & st)
711 case LM_ST_TEXT: st.style = LM_ST_SCRIPT; break;
712 default: st.style = LM_ST_SCRIPTSCRIPT;
717 // decrease math size for fractions
718 void smallerStyleFrac(MathMetricsInfo & st)
721 case LM_ST_DISPLAY: st.style = LM_ST_TEXT; break;
722 case LM_ST_TEXT: st.style = LM_ST_SCRIPT; break;
723 default: st.style = LM_ST_SCRIPTSCRIPT;
728 void math_font_max_dim(MathTextCodes code, MathMetricsInfo const & siz,
729 int & asc, int & des)
731 LyXFont font = whichFont(code, siz);
732 asc = lyxfont::maxAscent(font);
733 des = lyxfont::maxDescent(font);
737 char const * latex_mathspace[] = {
738 "!", ",", ":", ";", "quad", "qquad"
742 char const * math_font_name(MathTextCodes code)
744 static char const * theFontNames[] = {
755 if (code >= LM_TC_RM && code <= LM_TC_TEXTRM)
756 return theFontNames[code - LM_TC_RM];