5 #include "math_support.h"
7 #include "FontLoader.h"
9 #include "math_cursor.h"
10 #include "math_defs.h"
11 #include "math_inset.h"
12 #include "math_parser.h"
21 bool isBinaryOp(char c, MathTextCodes type)
23 return type < LM_TC_SYMB && strchr("+-<>=/*", c);
31 Matrix(int, double, double);
33 void transform(double &, double &);
40 Matrix::Matrix(int code, double x, double y)
42 double const cs = (code & 1) ? 0 : (1 - code);
43 double const sn = (code & 1) ? (2 - code) : 0;
51 void Matrix::transform(double & x, double & y)
53 double xx = m_[0][0] * x + m_[0][1] * y;
54 double yy = m_[1][0] * x + m_[1][1] * y;
62 LyXFont * MathFonts = 0;
63 bool font_available[LM_FONT_END];
64 bool font_available_initialized[LM_FONT_END];
87 void mathed_init_fonts()
89 MathFonts = new LyXFont[FONT_NUM];
91 MathFonts[FONT_IT].setShape(LyXFont::ITALIC_SHAPE);
93 MathFonts[FONT_SYMBOL].setFamily(LyXFont::SYMBOL_FAMILY);
95 MathFonts[FONT_SYMBOLI].setFamily(LyXFont::SYMBOL_FAMILY);
96 MathFonts[FONT_SYMBOLI].setShape(LyXFont::ITALIC_SHAPE);
98 MathFonts[FONT_BF].setSeries(LyXFont::BOLD_SERIES);
100 MathFonts[FONT_TT].setFamily(LyXFont::TYPEWRITER_FAMILY);
101 MathFonts[FONT_RM].setFamily(LyXFont::ROMAN_FAMILY);
102 MathFonts[FONT_SF].setFamily(LyXFont::SANS_FAMILY);
104 MathFonts[FONT_CMR].setFamily(LyXFont::CMR_FAMILY);
105 MathFonts[FONT_CMSY].setFamily(LyXFont::CMSY_FAMILY);
106 MathFonts[FONT_CMM].setFamily(LyXFont::CMM_FAMILY);
107 MathFonts[FONT_CMEX].setFamily(LyXFont::CMEX_FAMILY);
108 MathFonts[FONT_MSA].setFamily(LyXFont::MSA_FAMILY);
109 MathFonts[FONT_MSB].setFamily(LyXFont::MSB_FAMILY);
110 MathFonts[FONT_EUFRAK].setFamily(LyXFont::EUFRAK_FAMILY);
112 MathFonts[FONT_FAKEBB].setFamily(LyXFont::TYPEWRITER_FAMILY);
113 MathFonts[FONT_FAKEBB].setSeries(LyXFont::BOLD_SERIES);
115 MathFonts[FONT_FAKECAL].setFamily(LyXFont::SANS_FAMILY);
116 MathFonts[FONT_FAKECAL].setShape(LyXFont::ITALIC_SHAPE);
118 MathFonts[FONT_FAKEFRAK].setFamily(LyXFont::SANS_FAMILY);
119 MathFonts[FONT_FAKEFRAK].setSeries(LyXFont::BOLD_SERIES);
121 for (int i = 0; i < LM_FONT_END; ++i)
122 font_available_initialized[i] = false;
126 LyXFont const & whichFontBaseIntern(MathTextCodes type)
134 return MathFonts[FONT_SYMBOLI];
138 return MathFonts[FONT_IT];
141 return MathFonts[FONT_BF];
144 return MathFonts[FONT_MSB];
147 return MathFonts[FONT_CMSY];
150 return MathFonts[FONT_TT];
157 return MathFonts[FONT_RM];
160 return MathFonts[FONT_SF];
163 return MathFonts[FONT_CMR];
166 return MathFonts[FONT_CMSY];
169 return MathFonts[FONT_CMM];
172 return MathFonts[FONT_CMEX];
175 return MathFonts[FONT_MSA];
178 return MathFonts[FONT_MSB];
181 return MathFonts[FONT_EUFRAK];
190 LyXFont const & whichFontBase(MathTextCodes type)
197 if (math_font_available(LM_TC_MSB))
198 return MathFonts[FONT_MSB];
200 return MathFonts[FONT_FAKEBB];
203 if (math_font_available(LM_TC_CMSY))
204 return MathFonts[FONT_CMSY];
206 return MathFonts[FONT_FAKECAL];
209 if (math_font_available(LM_TC_EUFRAK))
210 return MathFonts[FONT_EUFRAK];
212 return MathFonts[FONT_FAKEFRAK];
217 return whichFontBaseIntern(type);
221 LyXFont whichFont(MathTextCodes type, MathMetricsInfo const & size)
223 LyXFont f = whichFontBase(type);
225 f.setSize(size.font.size());
227 switch (size.style) {
229 if (type == LM_TC_BOLDSYMB || type == LM_TC_CMEX) {
243 case LM_ST_SCRIPTSCRIPT:
250 lyxerr << "Math Error: wrong font size: " << size.style << endl;
254 if (type != LM_TC_TEXTRM && type != LM_TC_BOX)
255 f.setColor(LColor::math);
257 if (type == LM_TC_TEX)
258 f.setColor(LColor::latex);
266 bool math_font_available(MathTextCodes type)
268 if (!font_available_initialized[type]) {
269 font_available_initialized[type] = true;
270 font_available[type] = fontloader.available(whichFontBaseIntern(type));
272 return font_available[type];
279 * Internal struct of a drawing: code n x1 y1 ... xn yn, where code is:
280 * 0 = end, 1 = line, 2 = polyline, 3 = square line, 4= square polyline
284 double const parenthHigh[] = {
286 0.9840, 0.0014, 0.7143, 0.0323, 0.4603, 0.0772,
287 0.2540, 0.1278, 0.1746, 0.1966, 0.0952, 0.3300,
288 0.0950, 0.5000, 0.0952, 0.6700, 0.1746, 0.8034,
289 0.2540, 0.8722, 0.4603, 0.9228, 0.7143, 0.9677,
295 double const parenth[] = {
297 0.9930, 0.0071, 0.7324, 0.0578, 0.5141, 0.1126,
298 0.3380, 0.1714, 0.2183, 0.2333, 0.0634, 0.3621,
299 0.0141, 0.5000, 0.0563, 0.6369, 0.2113, 0.7647,
300 0.3310, 0.8276, 0.5070, 0.8864, 0.7254, 0.9412,
306 double const brace[] = {
308 0.9492, 0.0020, 0.9379, 0.0020, 0.7458, 0.0243,
309 0.5819, 0.0527, 0.4859, 0.0892, 0.4463, 0.1278,
310 0.4463, 0.3732, 0.4011, 0.4199, 0.2712, 0.4615,
311 0.0734, 0.4919, 0.0113, 0.5000, 0.0734, 0.5081,
312 0.2712, 0.5385, 0.4011, 0.5801, 0.4463, 0.6268,
313 0.4463, 0.8722, 0.4859, 0.9108, 0.5819, 0.9473,
314 0.7458, 0.9757, 0.9379, 0.9980, 0.9492, 0.9980,
319 double const arrow[] = {
321 0.0150, 0.7500, 0.2000, 0.6000, 0.3500, 0.3500,
322 0.5000, 0.0500, 0.6500, 0.3500, 0.8000, 0.6000,
324 3, 0.5000, 0.1500, 0.5000, 0.9500,
329 double const Arrow[] = {
331 0.0150, 0.7500, 0.2000, 0.6000, 0.3500, 0.3500,
332 0.5000, 0.0500, 0.6500, 0.3500, 0.8000, 0.6000,
334 3, 0.3500, 0.5000, 0.3500, 0.9500,
335 3, 0.6500, 0.5000, 0.6500, 0.9500,
340 double const udarrow[] = {
342 0.015, 0.25, 0.5, 0.05, 0.95, 0.25,
344 0.015, 0.75, 0.5, 0.95, 0.95, 0.75,
345 1, 0.5, 0.2, 0.5, 0.8,
350 double const Udarrow[] = {
352 0.015, 0.25, 0.5, 0.05, 0.95, 0.25,
354 0.015, 0.75, 0.5, 0.95, 0.95, 0.75,
355 1, 0.35, 0.2, 0.35, 0.8,
356 1, 0.65, 0.2, 0.65, 0.8,
361 double const brack[] = {
363 0.95, 0.05, 0.05, 0.05, 0.05, 0.95, 0.95, 0.95,
368 double const corner[] = {
370 0.95, 0.05, 0.05, 0.05, 0.05, 0.95,
375 double const angle[] = {
377 1, 0, 0.05, 0.5, 1, 1,
382 double const slash[] = {
383 1, 0.95, 0.05, 0.05, 0.95,
388 double const hline[] = {
389 1, 0.00, 0.5, 1.0, 0.5,
394 double const hline2[] = {
395 1, 0.1, 0.5, 0.3, 0.5,
396 1, 0.7, 0.5, 0.9, 0.5,
401 double const hline3[] = {
403 1, 0.475, 0, 0.525, 0,
409 double const dline3[] = {
410 1, 0.1, 0.1, 0.15, 0.15,
411 1, 0.475, 0.475, 0.525, 0.525,
412 1, 0.85, 0.85, 0.9, 0.9,
417 double const hlinesmall[] = {
418 1, 0.4, 0.5, 0.6, 0.5,
423 double const vert[] = {
424 1, 0.5, 0.05, 0.5, 0.95,
429 double const Vert[] = {
430 1, 0.3, 0.05, 0.3, 0.95,
431 1, 0.7, 0.05, 0.7, 0.95,
436 double const tilde[] = {
438 0.05, 0.8, 0.25, 0.2, 0.75, 0.8, 0.95, 0.2,
448 struct named_deco_struct {
454 named_deco_struct deco_table[] = {
456 {"widehat", angle, 3 },
457 {"widetilde", tilde, 0 },
458 {"underbar", hline, 0 },
459 {"underline", hline, 0 },
460 {"overline", hline, 0 },
461 {"underbrace", brace, 1 },
462 {"overbrace", brace, 3 },
463 {"overleftarrow", arrow, 1 },
464 {"overrightarrow", arrow, 3 },
477 {"backslash", slash, 1 },
478 {"langle", angle, 0 },
479 {"lceil", corner, 0 },
480 {"lfloor", corner, 1 },
481 {"rangle", angle, 2 },
482 {"rceil", corner, 3 },
483 {"rfloor", corner, 2 },
484 {"downarrow", arrow, 2 },
485 {"Downarrow", Arrow, 2 },
486 {"uparrow", arrow, 0 },
487 {"Uparrow", Arrow, 0 },
488 {"updownarrow", udarrow, 0 },
489 {"Updownarrow", Udarrow, 0 },
492 {"ddot", hline2, 0 },
494 {"grave", slash, 1 },
495 {"acute", slash, 0 },
496 {"tilde", tilde, 0 },
498 {"dot", hlinesmall, 0 },
499 {"check", angle, 1 },
500 {"breve", parenth, 1 },
505 {"ldots", hline3, 0 },
506 {"cdots", hline3, 0 },
507 {"vdots", hline3, 1 },
508 {"ddots", dline3, 0 }
512 map<string, deco_struct> deco_list;
514 // sort the table on startup
515 struct init_deco_table {
517 unsigned const n = sizeof(deco_table) / sizeof(deco_table[0]);
518 for (named_deco_struct * p = deco_table; p != deco_table + n; ++p) {
522 deco_list[p->name]= d;
527 static init_deco_table dummy;
530 deco_struct const * search_deco(string const & name)
532 map<string, deco_struct>::const_iterator p = deco_list.find(name);
533 return (p == deco_list.end()) ? 0 : &(p->second);
540 void mathed_char_dim(MathTextCodes type, MathMetricsInfo const & size,
541 unsigned char c, int & asc, int & des, int & wid)
543 LyXFont const font = whichFont(type, size);
544 des = lyxfont::descent(c, font);
545 asc = lyxfont::ascent(c, font);
546 wid = mathed_char_width(type, size, c);
550 int mathed_char_height(MathTextCodes type, MathMetricsInfo const & size,
551 unsigned char c, int & asc, int & des)
553 LyXFont const font = whichFont(type, size);
554 des = lyxfont::descent(c, font);
555 asc = lyxfont::ascent(c, font);
560 int mathed_char_height(MathTextCodes type, MathMetricsInfo const & size,
565 return mathed_char_height(type, size, c, asc, des);
569 int mathed_char_ascent(MathTextCodes type, MathMetricsInfo const & size,
572 LyXFont const font = whichFont(type, size);
573 return lyxfont::ascent(c, font);
577 int mathed_char_descent(MathTextCodes type, MathMetricsInfo const & size,
580 LyXFont const font = whichFont(type, size);
581 return lyxfont::descent(c, font);
585 int mathed_char_width(MathTextCodes type, MathMetricsInfo const & size,
588 LyXFont const font = whichFont(type, size);
589 if (isBinaryOp(c, type))
590 return lyxfont::width(c, font) + 2 * lyxfont::width(' ', font);
592 return lyxfont::width(c, font);
596 void mathed_string_dim(MathTextCodes type, MathMetricsInfo const & size,
597 string const & s, int & asc, int & des, int & wid)
599 mathed_string_height(type, size, s, asc, des);
600 wid = mathed_string_width(type, size, s);
604 int mathed_string_height(MathTextCodes type, MathMetricsInfo const & size,
605 string const & s, int & asc, int & des)
607 LyXFont const font = whichFont(type, size);
609 for (string::const_iterator it = s.begin(); it != s.end(); ++it) {
610 des = max(des, lyxfont::descent(*it, font));
611 asc = max(asc, lyxfont::ascent(*it, font));
617 int mathed_string_width(MathTextCodes type, MathMetricsInfo const & size,
620 return lyxfont::width(s, whichFont(type, size));
624 int mathed_string_ascent(MathTextCodes type, MathMetricsInfo const & size,
627 LyXFont const font = whichFont(type, size);
629 for (string::const_iterator it = s.begin(); it != s.end(); ++it)
630 asc = max(asc, lyxfont::ascent(*it, font));
635 int mathed_string_descent(MathTextCodes type, MathMetricsInfo const & size,
638 LyXFont const font = whichFont(type, size);
640 for (string::const_iterator it = s.begin(); it != s.end(); ++it)
641 des = max(des, lyxfont::descent(*it, font));
647 void mathed_draw_deco(Painter & pain, int x, int y, int w, int h,
651 pain.line(x + w/2, y, x + w/2, y + h,
652 LColor::mathcursor, Painter::line_onoffdash);
656 deco_struct const * mds = search_deco(name);
658 lyxerr << "Deco was not found. Programming error?\n";
659 lyxerr << "name: '" << name << "'\n";
663 int const n = (w < h) ? w : h;
664 int const r = mds->angle;
665 double const * d = mds->data;
667 if (h > 70 && (name == "(" || name == ")"))
671 Matrix sqmt(r, n, n);
679 for (int i = 0; d[i]; ) {
680 int code = int(d[i++]);
681 if (code & 1) { // code == 1 || code == 3
687 sqmt.transform(xx, yy);
689 mt.transform(xx, yy);
690 mt.transform(x2, y2);
691 pain.line(x + int(xx), y + int(yy), x + int(x2), y + int(y2),
696 int const n = int(d[i++]);
697 for (int j = 0; j < n; ++j) {
700 // lyxerr << " " << xx << " " << yy << " ";
702 sqmt.transform(xx, yy);
704 mt.transform(xx, yy);
707 // lyxerr << "P[" << j " " << xx << " " << yy << " " << x << " " << y << "]";
709 pain.lines(xp, yp, n, LColor::math);
715 void mathed_draw_framebox(Painter & pain, int x, int y, MathInset const * p)
717 if (mathcursor && mathcursor->isInside(p))
718 pain.rectangle(x, y - p->ascent(), p->width(), p->height(),
723 // In the future maybe we use a better fonts renderer
724 void drawStr(Painter & pain, MathTextCodes type, MathMetricsInfo const & siz,
725 int x, int y, string const & s)
727 pain.text(x, y, s, whichFont(type, siz));
731 void drawChar(Painter & pain, MathTextCodes type, MathMetricsInfo const & siz,
732 int x, int y, char c)
735 if (isBinaryOp(c, type))
738 if (isBinaryOp(c, type))
740 drawStr(pain, type, siz, x, y, s);
744 // decrease math size for super- and subscripts
745 void smallerStyleScript(MathMetricsInfo & st)
749 case LM_ST_TEXT: st.style = LM_ST_SCRIPT; break;
750 default: st.style = LM_ST_SCRIPTSCRIPT;
755 // decrease math size for fractions
756 void smallerStyleFrac(MathMetricsInfo & st)
759 case LM_ST_DISPLAY: st.style = LM_ST_TEXT; break;
760 case LM_ST_TEXT: st.style = LM_ST_SCRIPT; break;
761 default: st.style = LM_ST_SCRIPTSCRIPT;
766 void math_font_max_dim(MathTextCodes code, MathMetricsInfo const & siz,
767 int & asc, int & des)
769 LyXFont font = whichFont(code, siz);
770 asc = lyxfont::maxAscent(font);
771 des = lyxfont::maxDescent(font);
775 char const * latex_mathspace[] = {
776 "!", ",", ":", ";", "quad", "qquad"
780 char const * latex_mathstyle[] = {
781 "textstyle", "displaystyle", "scriptstyle", "scriptscriptstyle"
784 char const * latex_mathfontcmds[] = {
785 "font-bold", "font-emph", "font-roman", "font-code", "font-sans",
786 "font-ital", "font-noun", "font-frak", "font-free", "font-default"
790 char const * math_font_name(MathTextCodes code)
792 static char const * theFontNames[] = {
804 if (code >= LM_TC_RM && code <= LM_TC_TEXTRM)
805 return theFontNames[code - LM_TC_RM];