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];
85 void mathed_init_fonts()
87 MathFonts = new LyXFont[FONT_NUM]; //DEC cxx cannot initialize all fonts
90 for (int i = 0 ; i < FONT_NUM ; ++i) {
91 MathFonts[i] = LyXFont(LyXFont::ALL_SANE);
94 MathFonts[FONT_IT].setShape(LyXFont::ITALIC_SHAPE);
96 MathFonts[FONT_SYMBOL].setFamily(LyXFont::SYMBOL_FAMILY);
98 MathFonts[FONT_SYMBOLI].setFamily(LyXFont::SYMBOL_FAMILY);
99 MathFonts[FONT_SYMBOLI].setShape(LyXFont::ITALIC_SHAPE);
101 MathFonts[FONT_BF].setSeries(LyXFont::BOLD_SERIES);
103 MathFonts[FONT_BB].setSeries(LyXFont::BOLD_SERIES);
104 MathFonts[FONT_BB].setFamily(LyXFont::TYPEWRITER_FAMILY);
106 MathFonts[FONT_CAL].setFamily(LyXFont::SANS_FAMILY);
107 MathFonts[FONT_CAL].setShape(LyXFont::ITALIC_SHAPE);
109 MathFonts[FONT_TT].setFamily(LyXFont::TYPEWRITER_FAMILY);
111 MathFonts[FONT_RM].setFamily(LyXFont::ROMAN_FAMILY);
113 MathFonts[FONT_SF].setFamily(LyXFont::SANS_FAMILY);
115 MathFonts[FONT_CMR].setFamily(LyXFont::CMR_FAMILY);
116 MathFonts[FONT_CMSY].setFamily(LyXFont::CMSY_FAMILY);
117 MathFonts[FONT_CMM].setFamily(LyXFont::CMM_FAMILY);
118 MathFonts[FONT_CMEX].setFamily(LyXFont::CMEX_FAMILY);
119 MathFonts[FONT_MSA].setFamily(LyXFont::MSA_FAMILY);
120 MathFonts[FONT_MSB].setFamily(LyXFont::MSB_FAMILY);
121 MathFonts[FONT_EUFRAK].setFamily(LyXFont::EUFRAK_FAMILY);
123 for (int i = 0; i < LM_FONT_END; ++i)
124 font_available_initialized[i] = false;
128 LyXFont const & whichFontBase(MathTextCodes type)
136 return MathFonts[FONT_SYMBOLI];
140 return MathFonts[FONT_IT];
143 return MathFonts[FONT_BF];
146 if (math_font_available(LM_TC_MSB))
147 return MathFonts[FONT_MSB];
149 return MathFonts[FONT_BB];
152 if (math_font_available(LM_TC_CMSY))
153 return MathFonts[FONT_CMSY];
155 return MathFonts[FONT_CAL];
158 return MathFonts[FONT_TT];
164 return MathFonts[FONT_RM];
167 return MathFonts[FONT_SF];
170 return MathFonts[FONT_CMR];
173 return MathFonts[FONT_CMSY];
176 return MathFonts[FONT_CMM];
179 return MathFonts[FONT_CMEX];
182 return MathFonts[FONT_MSA];
185 return MathFonts[FONT_MSB];
188 if (math_font_available(LM_TC_EUFRAK))
189 return MathFonts[FONT_EUFRAK];
191 return MathFonts[FONT_BB];
200 LyXFont whichFont(MathTextCodes type, MathMetricsInfo const & size)
202 LyXFont f = whichFontBase(type);
204 f.setSize(size.font.size());
206 switch (size.style) {
208 if (type == LM_TC_BOLDSYMB || type == LM_TC_CMEX) {
222 case LM_ST_SCRIPTSCRIPT:
229 lyxerr << "Math Error: wrong font size: " << size.style << endl;
233 if (type != LM_TC_TEXTRM)
234 f.setColor(LColor::math);
236 if (type == LM_TC_TEX)
237 f.setColor(LColor::latex);
245 bool math_font_available(MathTextCodes type)
247 if (!font_available_initialized[type]) {
248 font_available_initialized[type] = true;
249 font_available[type] = fontloader.available(whichFontBase(type));
251 return font_available[type];
258 * Internal struct of a drawing: code n x1 y1 ... xn yn, where code is:
259 * 0 = end, 1 = line, 2 = polyline, 3 = square line, 4= square polyline
263 double const parenthHigh[] = {
265 0.9840, 0.0014, 0.7143, 0.0323, 0.4603, 0.0772,
266 0.2540, 0.1278, 0.1746, 0.1966, 0.0952, 0.3300,
267 0.0950, 0.5000, 0.0952, 0.6700, 0.1746, 0.8034,
268 0.2540, 0.8722, 0.4603, 0.9228, 0.7143, 0.9677,
274 double const parenth[] = {
276 0.9930, 0.0071, 0.7324, 0.0578, 0.5141, 0.1126,
277 0.3380, 0.1714, 0.2183, 0.2333, 0.0634, 0.3621,
278 0.0141, 0.5000, 0.0563, 0.6369, 0.2113, 0.7647,
279 0.3310, 0.8276, 0.5070, 0.8864, 0.7254, 0.9412,
285 double const brace[] = {
287 0.9492, 0.0020, 0.9379, 0.0020, 0.7458, 0.0243,
288 0.5819, 0.0527, 0.4859, 0.0892, 0.4463, 0.1278,
289 0.4463, 0.3732, 0.4011, 0.4199, 0.2712, 0.4615,
290 0.0734, 0.4919, 0.0113, 0.5000, 0.0734, 0.5081,
291 0.2712, 0.5385, 0.4011, 0.5801, 0.4463, 0.6268,
292 0.4463, 0.8722, 0.4859, 0.9108, 0.5819, 0.9473,
293 0.7458, 0.9757, 0.9379, 0.9980, 0.9492, 0.9980,
298 double const arrow[] = {
300 0.0150, 0.7500, 0.2000, 0.6000, 0.3500, 0.3500,
301 0.5000, 0.0500, 0.6500, 0.3500, 0.8000, 0.6000,
303 3, 0.5000, 0.1500, 0.5000, 0.9500,
308 double const Arrow[] = {
310 0.0150, 0.7500, 0.2000, 0.6000, 0.3500, 0.3500,
311 0.5000, 0.0500, 0.6500, 0.3500, 0.8000, 0.6000,
313 3, 0.3500, 0.5000, 0.3500, 0.9500,
314 3, 0.6500, 0.5000, 0.6500, 0.9500,
319 double const udarrow[] = {
321 0.015, 0.25, 0.5, 0.05, 0.95, 0.25,
323 0.015, 0.75, 0.5, 0.95, 0.95, 0.75,
324 1, 0.5, 0.2, 0.5, 0.8,
329 double const Udarrow[] = {
331 0.015, 0.25, 0.5, 0.05, 0.95, 0.25,
333 0.015, 0.75, 0.5, 0.95, 0.95, 0.75,
334 1, 0.35, 0.2, 0.35, 0.8,
335 1, 0.65, 0.2, 0.65, 0.8,
340 double const brack[] = {
342 0.95, 0.05, 0.05, 0.05, 0.05, 0.95, 0.95, 0.95,
347 double const corner[] = {
349 0.95, 0.05, 0.05, 0.05, 0.05, 0.95,
354 double const angle[] = {
356 1, 0, 0.05, 0.5, 1, 1,
361 double const slash[] = {
362 1, 0.95, 0.05, 0.05, 0.95,
367 double const hline[] = {
368 1, 0.00, 0.5, 1.0, 0.5,
373 double const hline2[] = {
374 1, 0.1, 0.5, 0.3, 0.5,
375 1, 0.7, 0.5, 0.9, 0.5,
380 double const hline3[] = {
382 1, 0.475, 0, 0.525, 0,
388 double const dline3[] = {
389 1, 0.1, 0.1, 0.15, 0.15,
390 1, 0.475, 0.475, 0.525, 0.525,
391 1, 0.85, 0.85, 0.9, 0.9,
396 double const hlinesmall[] = {
397 1, 0.4, 0.5, 0.6, 0.5,
402 double const vert[] = {
403 1, 0.5, 0.05, 0.5, 0.95,
408 double const Vert[] = {
409 1, 0.3, 0.05, 0.3, 0.95,
410 1, 0.7, 0.05, 0.7, 0.95,
415 double const tilde[] = {
417 0.05, 0.8, 0.25, 0.2, 0.75, 0.8, 0.95, 0.2,
427 struct named_deco_struct {
433 named_deco_struct deco_table[] = {
435 {"widehat", angle, 3 },
436 {"widetilde", tilde, 0 },
437 {"underline", hline, 0 },
438 {"overline", hline, 0 },
439 {"underbrace", brace, 1 },
440 {"overbrace", brace, 3 },
441 {"overleftarrow", arrow, 1 },
442 {"overrightarrow", arrow, 3 },
455 {"backslash", slash, 1 },
456 {"langle", angle, 0 },
457 {"lceil", corner, 0 },
458 {"lfloor", corner, 1 },
459 {"rangle", angle, 2 },
460 {"rceil", corner, 3 },
461 {"rfloor", corner, 2 },
462 {"downarrow", arrow, 2 },
463 {"Downarrow", Arrow, 2 },
464 {"uparrow", arrow, 0 },
465 {"Uparrow", Arrow, 0 },
466 {"updownarrow", udarrow, 0 },
467 {"Updownarrow", Udarrow, 0 },
470 {"ddot", hline2, 0 },
472 {"grave", slash, 1 },
473 {"acute", slash, 0 },
474 {"tilde", tilde, 0 },
476 {"dot", hlinesmall, 0 },
477 {"check", angle, 1 },
478 {"breve", parenth, 1 },
483 {"ldots", hline3, 0 },
484 {"cdots", hline3, 0 },
485 {"vdots", hline3, 1 },
486 {"ddots", dline3, 0 }
490 map<string, deco_struct> deco_list;
492 // sort the table on startup
493 struct init_deco_table {
495 unsigned const n = sizeof(deco_table) / sizeof(deco_table[0]);
496 for (named_deco_struct * p = deco_table; p != deco_table + n; ++p) {
500 deco_list[p->name]= d;
505 static init_deco_table dummy;
508 deco_struct const * search_deco(string const & name)
510 map<string, deco_struct>::const_iterator p = deco_list.find(name);
511 return (p == deco_list.end()) ? 0 : &(p->second);
518 void mathed_char_dim(MathTextCodes type, MathMetricsInfo const & size,
519 unsigned char c, int & asc, int & des, int & wid)
521 LyXFont const font = whichFont(type, size);
522 des = lyxfont::descent(c, font);
523 asc = lyxfont::ascent(c, font);
524 wid = mathed_char_width(type, size, c);
528 int mathed_char_height(MathTextCodes type, MathMetricsInfo const & size,
529 unsigned char c, int & asc, int & des)
531 LyXFont const font = whichFont(type, size);
532 des = lyxfont::descent(c, font);
533 asc = lyxfont::ascent(c, font);
538 int mathed_char_height(MathTextCodes type, MathMetricsInfo const & size,
543 return mathed_char_height(type, size, c, asc, des);
547 int mathed_char_ascent(MathTextCodes type, MathMetricsInfo const & size,
550 LyXFont const font = whichFont(type, size);
551 return lyxfont::ascent(c, font);
555 int mathed_char_descent(MathTextCodes type, MathMetricsInfo const & size,
558 LyXFont const font = whichFont(type, size);
559 return lyxfont::descent(c, font);
563 int mathed_char_width(MathTextCodes type, MathMetricsInfo const & size,
566 LyXFont const font = whichFont(type, size);
567 if (isBinaryOp(c, type))
568 return lyxfont::width(c, font) + 2 * lyxfont::width(' ', font);
570 return lyxfont::width(c, font);
574 void mathed_string_dim(MathTextCodes type, MathMetricsInfo const & size,
575 string const & s, int & asc, int & des, int & wid)
577 mathed_string_height(type, size, s, asc, des);
578 wid = mathed_string_width(type, size, s);
582 int mathed_string_height(MathTextCodes type, MathMetricsInfo const & size,
583 string const & s, int & asc, int & des)
585 LyXFont const font = whichFont(type, size);
587 for (string::const_iterator it = s.begin(); it != s.end(); ++it) {
588 des = max(des, lyxfont::descent(*it, font));
589 asc = max(asc, lyxfont::ascent(*it, font));
595 int mathed_string_width(MathTextCodes type, MathMetricsInfo const & size,
598 return lyxfont::width(s, whichFont(type, size));
602 int mathed_string_ascent(MathTextCodes type, MathMetricsInfo const & size,
605 LyXFont const font = whichFont(type, size);
607 for (string::const_iterator it = s.begin(); it != s.end(); ++it)
608 asc = max(asc, lyxfont::ascent(*it, font));
613 int mathed_string_descent(MathTextCodes type, MathMetricsInfo const & size,
616 LyXFont const font = whichFont(type, size);
618 for (string::const_iterator it = s.begin(); it != s.end(); ++it)
619 des = max(des, lyxfont::descent(*it, font));
625 void mathed_draw_deco(Painter & pain, int x, int y, int w, int h,
629 pain.line(x + w/2, y, x + w/2, y + h,
630 LColor::mathcursor, Painter::line_onoffdash);
634 deco_struct const * mds = search_deco(name);
636 lyxerr << "Deco was not found. Programming error?\n";
637 lyxerr << "name: '" << name << "'\n";
641 int const n = (w < h) ? w : h;
642 int const r = mds->angle;
643 double const * d = mds->data;
645 if (h > 70 && (name == "(" || name == ")"))
649 Matrix sqmt(r, n, n);
657 for (int i = 0; d[i]; ) {
658 int code = int(d[i++]);
659 if (code & 1) { // code == 1 || code == 3
665 sqmt.transform(xx, yy);
667 mt.transform(xx, yy);
668 mt.transform(x2, y2);
669 pain.line(x + int(xx), y + int(yy), x + int(x2), y + int(y2),
674 int const n = int(d[i++]);
675 for (int j = 0; j < n; ++j) {
678 // lyxerr << " " << xx << " " << yy << " ";
680 sqmt.transform(xx, yy);
682 mt.transform(xx, yy);
685 // lyxerr << "P[" << j " " << xx << " " << yy << " " << x << " " << y << "]";
687 pain.lines(xp, yp, n, LColor::math);
693 // In the future maybe we use a better fonts renderer
694 void drawStr(Painter & pain, MathTextCodes type, MathMetricsInfo const & siz,
695 int x, int y, string const & s)
697 pain.text(x, y, s, whichFont(type, siz));
701 void drawChar(Painter & pain, MathTextCodes type, MathMetricsInfo const & siz,
702 int x, int y, char c)
705 if (isBinaryOp(c, type))
708 if (isBinaryOp(c, type))
710 drawStr(pain, type, siz, x, y, s);
714 // decrease math size for super- and subscripts
715 void smallerStyleScript(MathMetricsInfo & st)
719 case LM_ST_TEXT: st.style = LM_ST_SCRIPT; break;
720 default: st.style = LM_ST_SCRIPTSCRIPT;
725 // decrease math size for fractions
726 void smallerStyleFrac(MathMetricsInfo & st)
729 case LM_ST_DISPLAY: st.style = LM_ST_TEXT; break;
730 case LM_ST_TEXT: st.style = LM_ST_SCRIPT; break;
731 default: st.style = LM_ST_SCRIPTSCRIPT;
736 void math_font_max_dim(MathTextCodes code, MathMetricsInfo const & siz,
737 int & asc, int & des)
739 LyXFont font = whichFont(code, siz);
740 asc = lyxfont::maxAscent(font);
741 des = lyxfont::maxDescent(font);
745 char const * latex_mathspace[] = {
746 "!", ",", ":", ";", "quad", "qquad"
750 char const * math_font_name(MathTextCodes code)
752 static char const * theFontNames[] = {
764 if (code >= LM_TC_RM && code <= LM_TC_TEXTRM)
765 return theFontNames[code - LM_TC_RM];