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];
86 void mathed_init_fonts()
88 MathFonts = new LyXFont[FONT_NUM]; //DEC cxx cannot initialize all fonts
91 for (int i = 0 ; i < FONT_NUM ; ++i) {
92 MathFonts[i] = LyXFont(LyXFont::ALL_SANE);
95 MathFonts[FONT_IT].setShape(LyXFont::ITALIC_SHAPE);
97 MathFonts[FONT_SYMBOL].setFamily(LyXFont::SYMBOL_FAMILY);
99 MathFonts[FONT_SYMBOLI].setFamily(LyXFont::SYMBOL_FAMILY);
100 MathFonts[FONT_SYMBOLI].setShape(LyXFont::ITALIC_SHAPE);
102 MathFonts[FONT_BF].setSeries(LyXFont::BOLD_SERIES);
104 MathFonts[FONT_TT].setFamily(LyXFont::TYPEWRITER_FAMILY);
105 MathFonts[FONT_RM].setFamily(LyXFont::ROMAN_FAMILY);
106 MathFonts[FONT_SF].setFamily(LyXFont::SANS_FAMILY);
108 MathFonts[FONT_CMR].setFamily(LyXFont::CMR_FAMILY);
109 MathFonts[FONT_CMSY].setFamily(LyXFont::CMSY_FAMILY);
110 MathFonts[FONT_CMM].setFamily(LyXFont::CMM_FAMILY);
111 MathFonts[FONT_CMEX].setFamily(LyXFont::CMEX_FAMILY);
112 MathFonts[FONT_MSA].setFamily(LyXFont::MSA_FAMILY);
113 MathFonts[FONT_MSB].setFamily(LyXFont::MSB_FAMILY);
114 MathFonts[FONT_EUFRAK].setFamily(LyXFont::EUFRAK_FAMILY);
116 MathFonts[FONT_FAKEBB].setFamily(LyXFont::TYPEWRITER_FAMILY);
117 MathFonts[FONT_FAKEBB].setSeries(LyXFont::BOLD_SERIES);
119 MathFonts[FONT_FAKECAL].setFamily(LyXFont::SANS_FAMILY);
120 MathFonts[FONT_FAKECAL].setShape(LyXFont::ITALIC_SHAPE);
122 MathFonts[FONT_FAKEFRAK].setFamily(LyXFont::SANS_FAMILY);
123 MathFonts[FONT_FAKEFRAK].setSeries(LyXFont::BOLD_SERIES);
125 for (int i = 0; i < LM_FONT_END; ++i)
126 font_available_initialized[i] = false;
130 LyXFont const & whichFontBaseIntern(MathTextCodes type)
138 return MathFonts[FONT_SYMBOLI];
142 return MathFonts[FONT_IT];
145 return MathFonts[FONT_BF];
148 return MathFonts[FONT_MSB];
151 return MathFonts[FONT_CMSY];
154 return MathFonts[FONT_TT];
160 return MathFonts[FONT_RM];
163 return MathFonts[FONT_SF];
166 return MathFonts[FONT_CMR];
169 return MathFonts[FONT_CMSY];
172 return MathFonts[FONT_CMM];
175 return MathFonts[FONT_CMEX];
178 return MathFonts[FONT_MSA];
181 return MathFonts[FONT_MSB];
184 return MathFonts[FONT_EUFRAK];
192 LyXFont const & whichFontBase(MathTextCodes type)
199 if (math_font_available(LM_TC_MSB))
200 return MathFonts[FONT_MSB];
202 return MathFonts[FONT_FAKEBB];
205 if (math_font_available(LM_TC_CMSY))
206 return MathFonts[FONT_CMSY];
208 return MathFonts[FONT_FAKECAL];
211 if (math_font_available(LM_TC_EUFRAK))
212 return MathFonts[FONT_EUFRAK];
214 return MathFonts[FONT_FAKEFRAK];
219 return whichFontBaseIntern(type);
223 LyXFont whichFont(MathTextCodes type, MathMetricsInfo const & size)
225 LyXFont f = whichFontBase(type);
227 f.setSize(size.font.size());
229 switch (size.style) {
231 if (type == LM_TC_BOLDSYMB || type == LM_TC_CMEX) {
245 case LM_ST_SCRIPTSCRIPT:
252 lyxerr << "Math Error: wrong font size: " << size.style << endl;
256 if (type != LM_TC_TEXTRM)
257 f.setColor(LColor::math);
259 if (type == LM_TC_TEX)
260 f.setColor(LColor::latex);
268 bool math_font_available(MathTextCodes type)
270 if (!font_available_initialized[type]) {
271 font_available_initialized[type] = true;
272 font_available[type] = fontloader.available(whichFontBaseIntern(type));
274 return font_available[type];
281 * Internal struct of a drawing: code n x1 y1 ... xn yn, where code is:
282 * 0 = end, 1 = line, 2 = polyline, 3 = square line, 4= square polyline
286 double const parenthHigh[] = {
288 0.9840, 0.0014, 0.7143, 0.0323, 0.4603, 0.0772,
289 0.2540, 0.1278, 0.1746, 0.1966, 0.0952, 0.3300,
290 0.0950, 0.5000, 0.0952, 0.6700, 0.1746, 0.8034,
291 0.2540, 0.8722, 0.4603, 0.9228, 0.7143, 0.9677,
297 double const parenth[] = {
299 0.9930, 0.0071, 0.7324, 0.0578, 0.5141, 0.1126,
300 0.3380, 0.1714, 0.2183, 0.2333, 0.0634, 0.3621,
301 0.0141, 0.5000, 0.0563, 0.6369, 0.2113, 0.7647,
302 0.3310, 0.8276, 0.5070, 0.8864, 0.7254, 0.9412,
308 double const brace[] = {
310 0.9492, 0.0020, 0.9379, 0.0020, 0.7458, 0.0243,
311 0.5819, 0.0527, 0.4859, 0.0892, 0.4463, 0.1278,
312 0.4463, 0.3732, 0.4011, 0.4199, 0.2712, 0.4615,
313 0.0734, 0.4919, 0.0113, 0.5000, 0.0734, 0.5081,
314 0.2712, 0.5385, 0.4011, 0.5801, 0.4463, 0.6268,
315 0.4463, 0.8722, 0.4859, 0.9108, 0.5819, 0.9473,
316 0.7458, 0.9757, 0.9379, 0.9980, 0.9492, 0.9980,
321 double const arrow[] = {
323 0.0150, 0.7500, 0.2000, 0.6000, 0.3500, 0.3500,
324 0.5000, 0.0500, 0.6500, 0.3500, 0.8000, 0.6000,
326 3, 0.5000, 0.1500, 0.5000, 0.9500,
331 double const Arrow[] = {
333 0.0150, 0.7500, 0.2000, 0.6000, 0.3500, 0.3500,
334 0.5000, 0.0500, 0.6500, 0.3500, 0.8000, 0.6000,
336 3, 0.3500, 0.5000, 0.3500, 0.9500,
337 3, 0.6500, 0.5000, 0.6500, 0.9500,
342 double const udarrow[] = {
344 0.015, 0.25, 0.5, 0.05, 0.95, 0.25,
346 0.015, 0.75, 0.5, 0.95, 0.95, 0.75,
347 1, 0.5, 0.2, 0.5, 0.8,
352 double const Udarrow[] = {
354 0.015, 0.25, 0.5, 0.05, 0.95, 0.25,
356 0.015, 0.75, 0.5, 0.95, 0.95, 0.75,
357 1, 0.35, 0.2, 0.35, 0.8,
358 1, 0.65, 0.2, 0.65, 0.8,
363 double const brack[] = {
365 0.95, 0.05, 0.05, 0.05, 0.05, 0.95, 0.95, 0.95,
370 double const corner[] = {
372 0.95, 0.05, 0.05, 0.05, 0.05, 0.95,
377 double const angle[] = {
379 1, 0, 0.05, 0.5, 1, 1,
384 double const slash[] = {
385 1, 0.95, 0.05, 0.05, 0.95,
390 double const hline[] = {
391 1, 0.00, 0.5, 1.0, 0.5,
396 double const hline2[] = {
397 1, 0.1, 0.5, 0.3, 0.5,
398 1, 0.7, 0.5, 0.9, 0.5,
403 double const hline3[] = {
405 1, 0.475, 0, 0.525, 0,
411 double const dline3[] = {
412 1, 0.1, 0.1, 0.15, 0.15,
413 1, 0.475, 0.475, 0.525, 0.525,
414 1, 0.85, 0.85, 0.9, 0.9,
419 double const hlinesmall[] = {
420 1, 0.4, 0.5, 0.6, 0.5,
425 double const vert[] = {
426 1, 0.5, 0.05, 0.5, 0.95,
431 double const Vert[] = {
432 1, 0.3, 0.05, 0.3, 0.95,
433 1, 0.7, 0.05, 0.7, 0.95,
438 double const tilde[] = {
440 0.05, 0.8, 0.25, 0.2, 0.75, 0.8, 0.95, 0.2,
450 struct named_deco_struct {
456 named_deco_struct deco_table[] = {
458 {"widehat", angle, 3 },
459 {"widetilde", tilde, 0 },
460 {"underline", hline, 0 },
461 {"overline", hline, 0 },
462 {"underbrace", brace, 1 },
463 {"overbrace", brace, 3 },
464 {"overleftarrow", arrow, 1 },
465 {"overrightarrow", arrow, 3 },
478 {"backslash", slash, 1 },
479 {"langle", angle, 0 },
480 {"lceil", corner, 0 },
481 {"lfloor", corner, 1 },
482 {"rangle", angle, 2 },
483 {"rceil", corner, 3 },
484 {"rfloor", corner, 2 },
485 {"downarrow", arrow, 2 },
486 {"Downarrow", Arrow, 2 },
487 {"uparrow", arrow, 0 },
488 {"Uparrow", Arrow, 0 },
489 {"updownarrow", udarrow, 0 },
490 {"Updownarrow", Udarrow, 0 },
493 {"ddot", hline2, 0 },
495 {"grave", slash, 1 },
496 {"acute", slash, 0 },
497 {"tilde", tilde, 0 },
499 {"dot", hlinesmall, 0 },
500 {"check", angle, 1 },
501 {"breve", parenth, 1 },
506 {"ldots", hline3, 0 },
507 {"cdots", hline3, 0 },
508 {"vdots", hline3, 1 },
509 {"ddots", dline3, 0 }
513 map<string, deco_struct> deco_list;
515 // sort the table on startup
516 struct init_deco_table {
518 unsigned const n = sizeof(deco_table) / sizeof(deco_table[0]);
519 for (named_deco_struct * p = deco_table; p != deco_table + n; ++p) {
523 deco_list[p->name]= d;
528 static init_deco_table dummy;
531 deco_struct const * search_deco(string const & name)
533 map<string, deco_struct>::const_iterator p = deco_list.find(name);
534 return (p == deco_list.end()) ? 0 : &(p->second);
541 void mathed_char_dim(MathTextCodes type, MathMetricsInfo const & size,
542 unsigned char c, int & asc, int & des, int & wid)
544 LyXFont const font = whichFont(type, size);
545 des = lyxfont::descent(c, font);
546 asc = lyxfont::ascent(c, font);
547 wid = mathed_char_width(type, size, c);
551 int mathed_char_height(MathTextCodes type, MathMetricsInfo const & size,
552 unsigned char c, int & asc, int & des)
554 LyXFont const font = whichFont(type, size);
555 des = lyxfont::descent(c, font);
556 asc = lyxfont::ascent(c, font);
561 int mathed_char_height(MathTextCodes type, MathMetricsInfo const & size,
566 return mathed_char_height(type, size, c, asc, des);
570 int mathed_char_ascent(MathTextCodes type, MathMetricsInfo const & size,
573 LyXFont const font = whichFont(type, size);
574 return lyxfont::ascent(c, font);
578 int mathed_char_descent(MathTextCodes type, MathMetricsInfo const & size,
581 LyXFont const font = whichFont(type, size);
582 return lyxfont::descent(c, font);
586 int mathed_char_width(MathTextCodes type, MathMetricsInfo const & size,
589 LyXFont const font = whichFont(type, size);
590 if (isBinaryOp(c, type))
591 return lyxfont::width(c, font) + 2 * lyxfont::width(' ', font);
593 return lyxfont::width(c, font);
597 void mathed_string_dim(MathTextCodes type, MathMetricsInfo const & size,
598 string const & s, int & asc, int & des, int & wid)
600 mathed_string_height(type, size, s, asc, des);
601 wid = mathed_string_width(type, size, s);
605 int mathed_string_height(MathTextCodes type, MathMetricsInfo const & size,
606 string const & s, int & asc, int & des)
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));
612 asc = max(asc, lyxfont::ascent(*it, font));
618 int mathed_string_width(MathTextCodes type, MathMetricsInfo const & size,
621 return lyxfont::width(s, whichFont(type, size));
625 int mathed_string_ascent(MathTextCodes type, MathMetricsInfo const & size,
628 LyXFont const font = whichFont(type, size);
630 for (string::const_iterator it = s.begin(); it != s.end(); ++it)
631 asc = max(asc, lyxfont::ascent(*it, font));
636 int mathed_string_descent(MathTextCodes type, MathMetricsInfo const & size,
639 LyXFont const font = whichFont(type, size);
641 for (string::const_iterator it = s.begin(); it != s.end(); ++it)
642 des = max(des, lyxfont::descent(*it, font));
648 void mathed_draw_deco(Painter & pain, int x, int y, int w, int h,
652 pain.line(x + w/2, y, x + w/2, y + h,
653 LColor::mathcursor, Painter::line_onoffdash);
657 deco_struct const * mds = search_deco(name);
659 lyxerr << "Deco was not found. Programming error?\n";
660 lyxerr << "name: '" << name << "'\n";
664 int const n = (w < h) ? w : h;
665 int const r = mds->angle;
666 double const * d = mds->data;
668 if (h > 70 && (name == "(" || name == ")"))
672 Matrix sqmt(r, n, n);
680 for (int i = 0; d[i]; ) {
681 int code = int(d[i++]);
682 if (code & 1) { // code == 1 || code == 3
688 sqmt.transform(xx, yy);
690 mt.transform(xx, yy);
691 mt.transform(x2, y2);
692 pain.line(x + int(xx), y + int(yy), x + int(x2), y + int(y2),
697 int const n = int(d[i++]);
698 for (int j = 0; j < n; ++j) {
701 // lyxerr << " " << xx << " " << yy << " ";
703 sqmt.transform(xx, yy);
705 mt.transform(xx, yy);
708 // lyxerr << "P[" << j " " << xx << " " << yy << " " << x << " " << y << "]";
710 pain.lines(xp, yp, n, LColor::math);
716 // In the future maybe we use a better fonts renderer
717 void drawStr(Painter & pain, MathTextCodes type, MathMetricsInfo const & siz,
718 int x, int y, string const & s)
720 pain.text(x, y, s, whichFont(type, siz));
724 void drawChar(Painter & pain, MathTextCodes type, MathMetricsInfo const & siz,
725 int x, int y, char c)
728 if (isBinaryOp(c, type))
731 if (isBinaryOp(c, type))
733 drawStr(pain, type, siz, x, y, s);
737 // decrease math size for super- and subscripts
738 void smallerStyleScript(MathMetricsInfo & st)
742 case LM_ST_TEXT: st.style = LM_ST_SCRIPT; break;
743 default: st.style = LM_ST_SCRIPTSCRIPT;
748 // decrease math size for fractions
749 void smallerStyleFrac(MathMetricsInfo & st)
752 case LM_ST_DISPLAY: st.style = LM_ST_TEXT; break;
753 case LM_ST_TEXT: st.style = LM_ST_SCRIPT; break;
754 default: st.style = LM_ST_SCRIPTSCRIPT;
759 void math_font_max_dim(MathTextCodes code, MathMetricsInfo const & siz,
760 int & asc, int & des)
762 LyXFont font = whichFont(code, siz);
763 asc = lyxfont::maxAscent(font);
764 des = lyxfont::maxDescent(font);
768 char const * latex_mathspace[] = {
769 "!", ",", ":", ";", "quad", "qquad"
773 char const * math_font_name(MathTextCodes code)
775 static char const * theFontNames[] = {
787 if (code >= LM_TC_RM && code <= LM_TC_TEXTRM)
788 return theFontNames[code - LM_TC_RM];