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];
90 MathFonts[FONT_IT].setShape(LyXFont::ITALIC_SHAPE);
92 MathFonts[FONT_SYMBOL].setFamily(LyXFont::SYMBOL_FAMILY);
94 MathFonts[FONT_SYMBOLI].setFamily(LyXFont::SYMBOL_FAMILY);
95 MathFonts[FONT_SYMBOLI].setShape(LyXFont::ITALIC_SHAPE);
97 MathFonts[FONT_BF].setSeries(LyXFont::BOLD_SERIES);
99 MathFonts[FONT_TT].setFamily(LyXFont::TYPEWRITER_FAMILY);
100 MathFonts[FONT_RM].setFamily(LyXFont::ROMAN_FAMILY);
101 MathFonts[FONT_SF].setFamily(LyXFont::SANS_FAMILY);
103 MathFonts[FONT_CMR].setFamily(LyXFont::CMR_FAMILY);
104 MathFonts[FONT_CMSY].setFamily(LyXFont::CMSY_FAMILY);
105 MathFonts[FONT_CMM].setFamily(LyXFont::CMM_FAMILY);
106 MathFonts[FONT_CMEX].setFamily(LyXFont::CMEX_FAMILY);
107 MathFonts[FONT_MSA].setFamily(LyXFont::MSA_FAMILY);
108 MathFonts[FONT_MSB].setFamily(LyXFont::MSB_FAMILY);
109 MathFonts[FONT_EUFRAK].setFamily(LyXFont::EUFRAK_FAMILY);
111 MathFonts[FONT_FAKEBB].setFamily(LyXFont::TYPEWRITER_FAMILY);
112 MathFonts[FONT_FAKEBB].setSeries(LyXFont::BOLD_SERIES);
114 MathFonts[FONT_FAKECAL].setFamily(LyXFont::SANS_FAMILY);
115 MathFonts[FONT_FAKECAL].setShape(LyXFont::ITALIC_SHAPE);
117 MathFonts[FONT_FAKEFRAK].setFamily(LyXFont::SANS_FAMILY);
118 MathFonts[FONT_FAKEFRAK].setSeries(LyXFont::BOLD_SERIES);
120 for (int i = 0; i < LM_FONT_END; ++i)
121 font_available_initialized[i] = false;
125 LyXFont const & whichFontBaseIntern(MathTextCodes type)
133 return MathFonts[FONT_SYMBOLI];
137 return MathFonts[FONT_IT];
140 return MathFonts[FONT_BF];
143 return MathFonts[FONT_MSB];
146 return MathFonts[FONT_CMSY];
149 return MathFonts[FONT_TT];
156 return MathFonts[FONT_RM];
159 return MathFonts[FONT_SF];
162 return MathFonts[FONT_CMR];
165 return MathFonts[FONT_CMSY];
168 return MathFonts[FONT_CMM];
171 return MathFonts[FONT_CMEX];
174 return MathFonts[FONT_MSA];
177 return MathFonts[FONT_MSB];
180 return MathFonts[FONT_EUFRAK];
188 LyXFont const & whichFontBase(MathTextCodes type)
195 if (math_font_available(LM_TC_MSB))
196 return MathFonts[FONT_MSB];
198 return MathFonts[FONT_FAKEBB];
201 if (math_font_available(LM_TC_CMSY))
202 return MathFonts[FONT_CMSY];
204 return MathFonts[FONT_FAKECAL];
207 if (math_font_available(LM_TC_EUFRAK))
208 return MathFonts[FONT_EUFRAK];
210 return MathFonts[FONT_FAKEFRAK];
215 return whichFontBaseIntern(type);
219 LyXFont whichFont(MathTextCodes type, MathMetricsInfo const & size)
221 LyXFont f = whichFontBase(type);
223 f.setSize(size.font.size());
225 switch (size.style) {
227 if (type == LM_TC_BOLDSYMB || type == LM_TC_CMEX) {
241 case LM_ST_SCRIPTSCRIPT:
248 lyxerr << "Math Error: wrong font size: " << size.style << endl;
252 if (type != LM_TC_TEXTRM && type != LM_TC_BOX)
253 f.setColor(LColor::math);
255 if (type == LM_TC_TEX)
256 f.setColor(LColor::latex);
264 bool math_font_available(MathTextCodes type)
266 if (!font_available_initialized[type]) {
267 font_available_initialized[type] = true;
268 font_available[type] = fontloader.available(whichFontBaseIntern(type));
270 return font_available[type];
277 * Internal struct of a drawing: code n x1 y1 ... xn yn, where code is:
278 * 0 = end, 1 = line, 2 = polyline, 3 = square line, 4= square polyline
282 double const parenthHigh[] = {
284 0.9840, 0.0014, 0.7143, 0.0323, 0.4603, 0.0772,
285 0.2540, 0.1278, 0.1746, 0.1966, 0.0952, 0.3300,
286 0.0950, 0.5000, 0.0952, 0.6700, 0.1746, 0.8034,
287 0.2540, 0.8722, 0.4603, 0.9228, 0.7143, 0.9677,
293 double const parenth[] = {
295 0.9930, 0.0071, 0.7324, 0.0578, 0.5141, 0.1126,
296 0.3380, 0.1714, 0.2183, 0.2333, 0.0634, 0.3621,
297 0.0141, 0.5000, 0.0563, 0.6369, 0.2113, 0.7647,
298 0.3310, 0.8276, 0.5070, 0.8864, 0.7254, 0.9412,
304 double const brace[] = {
306 0.9492, 0.0020, 0.9379, 0.0020, 0.7458, 0.0243,
307 0.5819, 0.0527, 0.4859, 0.0892, 0.4463, 0.1278,
308 0.4463, 0.3732, 0.4011, 0.4199, 0.2712, 0.4615,
309 0.0734, 0.4919, 0.0113, 0.5000, 0.0734, 0.5081,
310 0.2712, 0.5385, 0.4011, 0.5801, 0.4463, 0.6268,
311 0.4463, 0.8722, 0.4859, 0.9108, 0.5819, 0.9473,
312 0.7458, 0.9757, 0.9379, 0.9980, 0.9492, 0.9980,
317 double const arrow[] = {
319 0.0150, 0.7500, 0.2000, 0.6000, 0.3500, 0.3500,
320 0.5000, 0.0500, 0.6500, 0.3500, 0.8000, 0.6000,
322 3, 0.5000, 0.1500, 0.5000, 0.9500,
327 double const Arrow[] = {
329 0.0150, 0.7500, 0.2000, 0.6000, 0.3500, 0.3500,
330 0.5000, 0.0500, 0.6500, 0.3500, 0.8000, 0.6000,
332 3, 0.3500, 0.5000, 0.3500, 0.9500,
333 3, 0.6500, 0.5000, 0.6500, 0.9500,
338 double const udarrow[] = {
340 0.015, 0.25, 0.5, 0.05, 0.95, 0.25,
342 0.015, 0.75, 0.5, 0.95, 0.95, 0.75,
343 1, 0.5, 0.2, 0.5, 0.8,
348 double const Udarrow[] = {
350 0.015, 0.25, 0.5, 0.05, 0.95, 0.25,
352 0.015, 0.75, 0.5, 0.95, 0.95, 0.75,
353 1, 0.35, 0.2, 0.35, 0.8,
354 1, 0.65, 0.2, 0.65, 0.8,
359 double const brack[] = {
361 0.95, 0.05, 0.05, 0.05, 0.05, 0.95, 0.95, 0.95,
366 double const corner[] = {
368 0.95, 0.05, 0.05, 0.05, 0.05, 0.95,
373 double const angle[] = {
375 1, 0, 0.05, 0.5, 1, 1,
380 double const slash[] = {
381 1, 0.95, 0.05, 0.05, 0.95,
386 double const hline[] = {
387 1, 0.00, 0.5, 1.0, 0.5,
392 double const hline2[] = {
393 1, 0.1, 0.5, 0.3, 0.5,
394 1, 0.7, 0.5, 0.9, 0.5,
399 double const hline3[] = {
401 1, 0.475, 0, 0.525, 0,
407 double const dline3[] = {
408 1, 0.1, 0.1, 0.15, 0.15,
409 1, 0.475, 0.475, 0.525, 0.525,
410 1, 0.85, 0.85, 0.9, 0.9,
415 double const hlinesmall[] = {
416 1, 0.4, 0.5, 0.6, 0.5,
421 double const vert[] = {
422 1, 0.5, 0.05, 0.5, 0.95,
427 double const Vert[] = {
428 1, 0.3, 0.05, 0.3, 0.95,
429 1, 0.7, 0.05, 0.7, 0.95,
434 double const tilde[] = {
436 0.05, 0.8, 0.25, 0.2, 0.75, 0.8, 0.95, 0.2,
446 struct named_deco_struct {
452 named_deco_struct deco_table[] = {
454 {"widehat", angle, 3 },
455 {"widetilde", tilde, 0 },
456 {"underline", hline, 0 },
457 {"overline", hline, 0 },
458 {"underbrace", brace, 1 },
459 {"overbrace", brace, 3 },
460 {"overleftarrow", arrow, 1 },
461 {"overrightarrow", arrow, 3 },
474 {"backslash", slash, 1 },
475 {"langle", angle, 0 },
476 {"lceil", corner, 0 },
477 {"lfloor", corner, 1 },
478 {"rangle", angle, 2 },
479 {"rceil", corner, 3 },
480 {"rfloor", corner, 2 },
481 {"downarrow", arrow, 2 },
482 {"Downarrow", Arrow, 2 },
483 {"uparrow", arrow, 0 },
484 {"Uparrow", Arrow, 0 },
485 {"updownarrow", udarrow, 0 },
486 {"Updownarrow", Udarrow, 0 },
489 {"ddot", hline2, 0 },
491 {"grave", slash, 1 },
492 {"acute", slash, 0 },
493 {"tilde", tilde, 0 },
495 {"dot", hlinesmall, 0 },
496 {"check", angle, 1 },
497 {"breve", parenth, 1 },
502 {"ldots", hline3, 0 },
503 {"cdots", hline3, 0 },
504 {"vdots", hline3, 1 },
505 {"ddots", dline3, 0 }
509 map<string, deco_struct> deco_list;
511 // sort the table on startup
512 struct init_deco_table {
514 unsigned const n = sizeof(deco_table) / sizeof(deco_table[0]);
515 for (named_deco_struct * p = deco_table; p != deco_table + n; ++p) {
519 deco_list[p->name]= d;
524 static init_deco_table dummy;
527 deco_struct const * search_deco(string const & name)
529 map<string, deco_struct>::const_iterator p = deco_list.find(name);
530 return (p == deco_list.end()) ? 0 : &(p->second);
537 void mathed_char_dim(MathTextCodes type, MathMetricsInfo const & size,
538 unsigned char c, int & asc, int & des, int & wid)
540 LyXFont const font = whichFont(type, size);
541 des = lyxfont::descent(c, font);
542 asc = lyxfont::ascent(c, font);
543 wid = mathed_char_width(type, size, c);
547 int mathed_char_height(MathTextCodes type, MathMetricsInfo const & size,
548 unsigned char c, int & asc, int & des)
550 LyXFont const font = whichFont(type, size);
551 des = lyxfont::descent(c, font);
552 asc = lyxfont::ascent(c, font);
557 int mathed_char_height(MathTextCodes type, MathMetricsInfo const & size,
562 return mathed_char_height(type, size, c, asc, des);
566 int mathed_char_ascent(MathTextCodes type, MathMetricsInfo const & size,
569 LyXFont const font = whichFont(type, size);
570 return lyxfont::ascent(c, font);
574 int mathed_char_descent(MathTextCodes type, MathMetricsInfo const & size,
577 LyXFont const font = whichFont(type, size);
578 return lyxfont::descent(c, font);
582 int mathed_char_width(MathTextCodes type, MathMetricsInfo const & size,
585 LyXFont const font = whichFont(type, size);
586 if (isBinaryOp(c, type))
587 return lyxfont::width(c, font) + 2 * lyxfont::width(' ', font);
589 return lyxfont::width(c, font);
593 void mathed_string_dim(MathTextCodes type, MathMetricsInfo const & size,
594 string const & s, int & asc, int & des, int & wid)
596 mathed_string_height(type, size, s, asc, des);
597 wid = mathed_string_width(type, size, s);
601 int mathed_string_height(MathTextCodes type, MathMetricsInfo const & size,
602 string const & s, int & asc, int & des)
604 LyXFont const font = whichFont(type, size);
606 for (string::const_iterator it = s.begin(); it != s.end(); ++it) {
607 des = max(des, lyxfont::descent(*it, font));
608 asc = max(asc, lyxfont::ascent(*it, font));
614 int mathed_string_width(MathTextCodes type, MathMetricsInfo const & size,
617 return lyxfont::width(s, whichFont(type, size));
621 int mathed_string_ascent(MathTextCodes type, MathMetricsInfo const & size,
624 LyXFont const font = whichFont(type, size);
626 for (string::const_iterator it = s.begin(); it != s.end(); ++it)
627 asc = max(asc, lyxfont::ascent(*it, font));
632 int mathed_string_descent(MathTextCodes type, MathMetricsInfo const & size,
635 LyXFont const font = whichFont(type, size);
637 for (string::const_iterator it = s.begin(); it != s.end(); ++it)
638 des = max(des, lyxfont::descent(*it, font));
644 void mathed_draw_deco(Painter & pain, int x, int y, int w, int h,
648 pain.line(x + w/2, y, x + w/2, y + h,
649 LColor::mathcursor, Painter::line_onoffdash);
653 deco_struct const * mds = search_deco(name);
655 lyxerr << "Deco was not found. Programming error?\n";
656 lyxerr << "name: '" << name << "'\n";
660 int const n = (w < h) ? w : h;
661 int const r = mds->angle;
662 double const * d = mds->data;
664 if (h > 70 && (name == "(" || name == ")"))
668 Matrix sqmt(r, n, n);
676 for (int i = 0; d[i]; ) {
677 int code = int(d[i++]);
678 if (code & 1) { // code == 1 || code == 3
684 sqmt.transform(xx, yy);
686 mt.transform(xx, yy);
687 mt.transform(x2, y2);
688 pain.line(x + int(xx), y + int(yy), x + int(x2), y + int(y2),
693 int const n = int(d[i++]);
694 for (int j = 0; j < n; ++j) {
697 // lyxerr << " " << xx << " " << yy << " ";
699 sqmt.transform(xx, yy);
701 mt.transform(xx, yy);
704 // lyxerr << "P[" << j " " << xx << " " << yy << " " << x << " " << y << "]";
706 pain.lines(xp, yp, n, LColor::math);
712 // In the future maybe we use a better fonts renderer
713 void drawStr(Painter & pain, MathTextCodes type, MathMetricsInfo const & siz,
714 int x, int y, string const & s)
716 pain.text(x, y, s, whichFont(type, siz));
720 void drawChar(Painter & pain, MathTextCodes type, MathMetricsInfo const & siz,
721 int x, int y, char c)
724 if (isBinaryOp(c, type))
727 if (isBinaryOp(c, type))
729 drawStr(pain, type, siz, x, y, s);
733 // decrease math size for super- and subscripts
734 void smallerStyleScript(MathMetricsInfo & st)
738 case LM_ST_TEXT: st.style = LM_ST_SCRIPT; break;
739 default: st.style = LM_ST_SCRIPTSCRIPT;
744 // decrease math size for fractions
745 void smallerStyleFrac(MathMetricsInfo & st)
748 case LM_ST_DISPLAY: st.style = LM_ST_TEXT; break;
749 case LM_ST_TEXT: st.style = LM_ST_SCRIPT; break;
750 default: st.style = LM_ST_SCRIPTSCRIPT;
755 void math_font_max_dim(MathTextCodes code, MathMetricsInfo const & siz,
756 int & asc, int & des)
758 LyXFont font = whichFont(code, siz);
759 asc = lyxfont::maxAscent(font);
760 des = lyxfont::maxDescent(font);
764 char const * latex_mathspace[] = {
765 "!", ",", ":", ";", "quad", "qquad"
769 char const * math_font_name(MathTextCodes code)
771 static char const * theFontNames[] = {
783 if (code >= LM_TC_RM && code <= LM_TC_TEXTRM)
784 return theFontNames[code - LM_TC_RM];