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];
161 return MathFonts[FONT_RM];
164 return MathFonts[FONT_SF];
167 return MathFonts[FONT_CMR];
170 return MathFonts[FONT_CMSY];
173 return MathFonts[FONT_CMM];
176 return MathFonts[FONT_CMEX];
179 return MathFonts[FONT_MSA];
182 return MathFonts[FONT_MSB];
185 return MathFonts[FONT_EUFRAK];
193 LyXFont const & whichFontBase(MathTextCodes type)
200 if (math_font_available(LM_TC_MSB))
201 return MathFonts[FONT_MSB];
203 return MathFonts[FONT_FAKEBB];
206 if (math_font_available(LM_TC_CMSY))
207 return MathFonts[FONT_CMSY];
209 return MathFonts[FONT_FAKECAL];
212 if (math_font_available(LM_TC_EUFRAK))
213 return MathFonts[FONT_EUFRAK];
215 return MathFonts[FONT_FAKEFRAK];
220 return whichFontBaseIntern(type);
224 LyXFont whichFont(MathTextCodes type, MathMetricsInfo const & size)
226 LyXFont f = whichFontBase(type);
228 f.setSize(size.font.size());
230 switch (size.style) {
232 if (type == LM_TC_BOLDSYMB || type == LM_TC_CMEX) {
246 case LM_ST_SCRIPTSCRIPT:
253 lyxerr << "Math Error: wrong font size: " << size.style << endl;
257 if (type != LM_TC_TEXTRM && type != LM_TC_BOX)
258 f.setColor(LColor::math);
260 if (type == LM_TC_TEX)
261 f.setColor(LColor::latex);
269 bool math_font_available(MathTextCodes type)
271 if (!font_available_initialized[type]) {
272 font_available_initialized[type] = true;
273 font_available[type] = fontloader.available(whichFontBaseIntern(type));
275 return font_available[type];
282 * Internal struct of a drawing: code n x1 y1 ... xn yn, where code is:
283 * 0 = end, 1 = line, 2 = polyline, 3 = square line, 4= square polyline
287 double const parenthHigh[] = {
289 0.9840, 0.0014, 0.7143, 0.0323, 0.4603, 0.0772,
290 0.2540, 0.1278, 0.1746, 0.1966, 0.0952, 0.3300,
291 0.0950, 0.5000, 0.0952, 0.6700, 0.1746, 0.8034,
292 0.2540, 0.8722, 0.4603, 0.9228, 0.7143, 0.9677,
298 double const parenth[] = {
300 0.9930, 0.0071, 0.7324, 0.0578, 0.5141, 0.1126,
301 0.3380, 0.1714, 0.2183, 0.2333, 0.0634, 0.3621,
302 0.0141, 0.5000, 0.0563, 0.6369, 0.2113, 0.7647,
303 0.3310, 0.8276, 0.5070, 0.8864, 0.7254, 0.9412,
309 double const brace[] = {
311 0.9492, 0.0020, 0.9379, 0.0020, 0.7458, 0.0243,
312 0.5819, 0.0527, 0.4859, 0.0892, 0.4463, 0.1278,
313 0.4463, 0.3732, 0.4011, 0.4199, 0.2712, 0.4615,
314 0.0734, 0.4919, 0.0113, 0.5000, 0.0734, 0.5081,
315 0.2712, 0.5385, 0.4011, 0.5801, 0.4463, 0.6268,
316 0.4463, 0.8722, 0.4859, 0.9108, 0.5819, 0.9473,
317 0.7458, 0.9757, 0.9379, 0.9980, 0.9492, 0.9980,
322 double const arrow[] = {
324 0.0150, 0.7500, 0.2000, 0.6000, 0.3500, 0.3500,
325 0.5000, 0.0500, 0.6500, 0.3500, 0.8000, 0.6000,
327 3, 0.5000, 0.1500, 0.5000, 0.9500,
332 double const Arrow[] = {
334 0.0150, 0.7500, 0.2000, 0.6000, 0.3500, 0.3500,
335 0.5000, 0.0500, 0.6500, 0.3500, 0.8000, 0.6000,
337 3, 0.3500, 0.5000, 0.3500, 0.9500,
338 3, 0.6500, 0.5000, 0.6500, 0.9500,
343 double const udarrow[] = {
345 0.015, 0.25, 0.5, 0.05, 0.95, 0.25,
347 0.015, 0.75, 0.5, 0.95, 0.95, 0.75,
348 1, 0.5, 0.2, 0.5, 0.8,
353 double const Udarrow[] = {
355 0.015, 0.25, 0.5, 0.05, 0.95, 0.25,
357 0.015, 0.75, 0.5, 0.95, 0.95, 0.75,
358 1, 0.35, 0.2, 0.35, 0.8,
359 1, 0.65, 0.2, 0.65, 0.8,
364 double const brack[] = {
366 0.95, 0.05, 0.05, 0.05, 0.05, 0.95, 0.95, 0.95,
371 double const corner[] = {
373 0.95, 0.05, 0.05, 0.05, 0.05, 0.95,
378 double const angle[] = {
380 1, 0, 0.05, 0.5, 1, 1,
385 double const slash[] = {
386 1, 0.95, 0.05, 0.05, 0.95,
391 double const hline[] = {
392 1, 0.00, 0.5, 1.0, 0.5,
397 double const hline2[] = {
398 1, 0.1, 0.5, 0.3, 0.5,
399 1, 0.7, 0.5, 0.9, 0.5,
404 double const hline3[] = {
406 1, 0.475, 0, 0.525, 0,
412 double const dline3[] = {
413 1, 0.1, 0.1, 0.15, 0.15,
414 1, 0.475, 0.475, 0.525, 0.525,
415 1, 0.85, 0.85, 0.9, 0.9,
420 double const hlinesmall[] = {
421 1, 0.4, 0.5, 0.6, 0.5,
426 double const vert[] = {
427 1, 0.5, 0.05, 0.5, 0.95,
432 double const Vert[] = {
433 1, 0.3, 0.05, 0.3, 0.95,
434 1, 0.7, 0.05, 0.7, 0.95,
439 double const tilde[] = {
441 0.05, 0.8, 0.25, 0.2, 0.75, 0.8, 0.95, 0.2,
451 struct named_deco_struct {
457 named_deco_struct deco_table[] = {
459 {"widehat", angle, 3 },
460 {"widetilde", tilde, 0 },
461 {"underline", hline, 0 },
462 {"overline", hline, 0 },
463 {"underbrace", brace, 1 },
464 {"overbrace", brace, 3 },
465 {"overleftarrow", arrow, 1 },
466 {"overrightarrow", arrow, 3 },
479 {"backslash", slash, 1 },
480 {"langle", angle, 0 },
481 {"lceil", corner, 0 },
482 {"lfloor", corner, 1 },
483 {"rangle", angle, 2 },
484 {"rceil", corner, 3 },
485 {"rfloor", corner, 2 },
486 {"downarrow", arrow, 2 },
487 {"Downarrow", Arrow, 2 },
488 {"uparrow", arrow, 0 },
489 {"Uparrow", Arrow, 0 },
490 {"updownarrow", udarrow, 0 },
491 {"Updownarrow", Udarrow, 0 },
494 {"ddot", hline2, 0 },
496 {"grave", slash, 1 },
497 {"acute", slash, 0 },
498 {"tilde", tilde, 0 },
500 {"dot", hlinesmall, 0 },
501 {"check", angle, 1 },
502 {"breve", parenth, 1 },
507 {"ldots", hline3, 0 },
508 {"cdots", hline3, 0 },
509 {"vdots", hline3, 1 },
510 {"ddots", dline3, 0 }
514 map<string, deco_struct> deco_list;
516 // sort the table on startup
517 struct init_deco_table {
519 unsigned const n = sizeof(deco_table) / sizeof(deco_table[0]);
520 for (named_deco_struct * p = deco_table; p != deco_table + n; ++p) {
524 deco_list[p->name]= d;
529 static init_deco_table dummy;
532 deco_struct const * search_deco(string const & name)
534 map<string, deco_struct>::const_iterator p = deco_list.find(name);
535 return (p == deco_list.end()) ? 0 : &(p->second);
542 void mathed_char_dim(MathTextCodes type, MathMetricsInfo const & size,
543 unsigned char c, int & asc, int & des, int & wid)
545 LyXFont const font = whichFont(type, size);
546 des = lyxfont::descent(c, font);
547 asc = lyxfont::ascent(c, font);
548 wid = mathed_char_width(type, size, c);
552 int mathed_char_height(MathTextCodes type, MathMetricsInfo const & size,
553 unsigned char c, int & asc, int & des)
555 LyXFont const font = whichFont(type, size);
556 des = lyxfont::descent(c, font);
557 asc = lyxfont::ascent(c, font);
562 int mathed_char_height(MathTextCodes type, MathMetricsInfo const & size,
567 return mathed_char_height(type, size, c, asc, des);
571 int mathed_char_ascent(MathTextCodes type, MathMetricsInfo const & size,
574 LyXFont const font = whichFont(type, size);
575 return lyxfont::ascent(c, font);
579 int mathed_char_descent(MathTextCodes type, MathMetricsInfo const & size,
582 LyXFont const font = whichFont(type, size);
583 return lyxfont::descent(c, font);
587 int mathed_char_width(MathTextCodes type, MathMetricsInfo const & size,
590 LyXFont const font = whichFont(type, size);
591 if (isBinaryOp(c, type))
592 return lyxfont::width(c, font) + 2 * lyxfont::width(' ', font);
594 return lyxfont::width(c, font);
598 void mathed_string_dim(MathTextCodes type, MathMetricsInfo const & size,
599 string const & s, int & asc, int & des, int & wid)
601 mathed_string_height(type, size, s, asc, des);
602 wid = mathed_string_width(type, size, s);
606 int mathed_string_height(MathTextCodes type, MathMetricsInfo const & size,
607 string const & s, int & asc, int & des)
609 LyXFont const font = whichFont(type, size);
611 for (string::const_iterator it = s.begin(); it != s.end(); ++it) {
612 des = max(des, lyxfont::descent(*it, font));
613 asc = max(asc, lyxfont::ascent(*it, font));
619 int mathed_string_width(MathTextCodes type, MathMetricsInfo const & size,
622 return lyxfont::width(s, whichFont(type, size));
626 int mathed_string_ascent(MathTextCodes type, MathMetricsInfo const & size,
629 LyXFont const font = whichFont(type, size);
631 for (string::const_iterator it = s.begin(); it != s.end(); ++it)
632 asc = max(asc, lyxfont::ascent(*it, font));
637 int mathed_string_descent(MathTextCodes type, MathMetricsInfo const & size,
640 LyXFont const font = whichFont(type, size);
642 for (string::const_iterator it = s.begin(); it != s.end(); ++it)
643 des = max(des, lyxfont::descent(*it, font));
649 void mathed_draw_deco(Painter & pain, int x, int y, int w, int h,
653 pain.line(x + w/2, y, x + w/2, y + h,
654 LColor::mathcursor, Painter::line_onoffdash);
658 deco_struct const * mds = search_deco(name);
660 lyxerr << "Deco was not found. Programming error?\n";
661 lyxerr << "name: '" << name << "'\n";
665 int const n = (w < h) ? w : h;
666 int const r = mds->angle;
667 double const * d = mds->data;
669 if (h > 70 && (name == "(" || name == ")"))
673 Matrix sqmt(r, n, n);
681 for (int i = 0; d[i]; ) {
682 int code = int(d[i++]);
683 if (code & 1) { // code == 1 || code == 3
689 sqmt.transform(xx, yy);
691 mt.transform(xx, yy);
692 mt.transform(x2, y2);
693 pain.line(x + int(xx), y + int(yy), x + int(x2), y + int(y2),
698 int const n = int(d[i++]);
699 for (int j = 0; j < n; ++j) {
702 // lyxerr << " " << xx << " " << yy << " ";
704 sqmt.transform(xx, yy);
706 mt.transform(xx, yy);
709 // lyxerr << "P[" << j " " << xx << " " << yy << " " << x << " " << y << "]";
711 pain.lines(xp, yp, n, LColor::math);
717 // In the future maybe we use a better fonts renderer
718 void drawStr(Painter & pain, MathTextCodes type, MathMetricsInfo const & siz,
719 int x, int y, string const & s)
721 pain.text(x, y, s, whichFont(type, siz));
725 void drawChar(Painter & pain, MathTextCodes type, MathMetricsInfo const & siz,
726 int x, int y, char c)
729 if (isBinaryOp(c, type))
732 if (isBinaryOp(c, type))
734 drawStr(pain, type, siz, x, y, s);
738 // decrease math size for super- and subscripts
739 void smallerStyleScript(MathMetricsInfo & st)
743 case LM_ST_TEXT: st.style = LM_ST_SCRIPT; break;
744 default: st.style = LM_ST_SCRIPTSCRIPT;
749 // decrease math size for fractions
750 void smallerStyleFrac(MathMetricsInfo & st)
753 case LM_ST_DISPLAY: st.style = LM_ST_TEXT; break;
754 case LM_ST_TEXT: st.style = LM_ST_SCRIPT; break;
755 default: st.style = LM_ST_SCRIPTSCRIPT;
760 void math_font_max_dim(MathTextCodes code, MathMetricsInfo const & siz,
761 int & asc, int & des)
763 LyXFont font = whichFont(code, siz);
764 asc = lyxfont::maxAscent(font);
765 des = lyxfont::maxDescent(font);
769 char const * latex_mathspace[] = {
770 "!", ",", ":", ";", "quad", "qquad"
774 char const * math_font_name(MathTextCodes code)
776 static char const * theFontNames[] = {
788 if (code >= LM_TC_RM && code <= LM_TC_TEXTRM)
789 return theFontNames[code - LM_TC_RM];