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"
15 #include "commandtags.h"
22 bool isBinaryOp(char c, MathTextCodes type)
24 return type < LM_TC_SYMB && strchr("+-<>=/*", c);
32 Matrix(int, double, double);
34 void transform(double &, double &);
41 Matrix::Matrix(int code, double x, double y)
43 double const cs = (code & 1) ? 0 : (1 - code);
44 double const sn = (code & 1) ? (2 - code) : 0;
52 void Matrix::transform(double & x, double & y)
54 double xx = m_[0][0] * x + m_[0][1] * y;
55 double yy = m_[1][0] * x + m_[1][1] * y;
63 LyXFont * MathFonts = 0;
64 bool font_available[LM_FONT_END];
65 bool font_available_initialized[LM_FONT_END];
88 void mathed_init_fonts()
90 MathFonts = new LyXFont[FONT_NUM];
92 MathFonts[FONT_IT].setShape(LyXFont::ITALIC_SHAPE);
94 MathFonts[FONT_SYMBOL].setFamily(LyXFont::SYMBOL_FAMILY);
96 MathFonts[FONT_SYMBOLI].setFamily(LyXFont::SYMBOL_FAMILY);
97 MathFonts[FONT_SYMBOLI].setShape(LyXFont::ITALIC_SHAPE);
99 MathFonts[FONT_BF].setSeries(LyXFont::BOLD_SERIES);
101 MathFonts[FONT_TT].setFamily(LyXFont::TYPEWRITER_FAMILY);
102 MathFonts[FONT_RM].setFamily(LyXFont::ROMAN_FAMILY);
103 MathFonts[FONT_SF].setFamily(LyXFont::SANS_FAMILY);
105 MathFonts[FONT_CMR].setFamily(LyXFont::CMR_FAMILY);
106 MathFonts[FONT_CMSY].setFamily(LyXFont::CMSY_FAMILY);
107 MathFonts[FONT_CMM].setFamily(LyXFont::CMM_FAMILY);
108 MathFonts[FONT_CMEX].setFamily(LyXFont::CMEX_FAMILY);
109 MathFonts[FONT_MSA].setFamily(LyXFont::MSA_FAMILY);
110 MathFonts[FONT_MSB].setFamily(LyXFont::MSB_FAMILY);
111 MathFonts[FONT_EUFRAK].setFamily(LyXFont::EUFRAK_FAMILY);
113 MathFonts[FONT_FAKEBB].setFamily(LyXFont::TYPEWRITER_FAMILY);
114 MathFonts[FONT_FAKEBB].setSeries(LyXFont::BOLD_SERIES);
116 MathFonts[FONT_FAKECAL].setFamily(LyXFont::SANS_FAMILY);
117 MathFonts[FONT_FAKECAL].setShape(LyXFont::ITALIC_SHAPE);
119 MathFonts[FONT_FAKEFRAK].setFamily(LyXFont::SANS_FAMILY);
120 MathFonts[FONT_FAKEFRAK].setSeries(LyXFont::BOLD_SERIES);
122 for (int i = 0; i < LM_FONT_END; ++i)
123 font_available_initialized[i] = false;
127 LyXFont const & whichFontBaseIntern(MathTextCodes type)
135 return MathFonts[FONT_SYMBOLI];
139 return MathFonts[FONT_IT];
142 return MathFonts[FONT_BF];
145 return MathFonts[FONT_MSB];
148 return MathFonts[FONT_CMSY];
151 return MathFonts[FONT_TT];
158 return MathFonts[FONT_RM];
161 return MathFonts[FONT_SF];
164 return MathFonts[FONT_CMR];
167 return MathFonts[FONT_CMSY];
170 return MathFonts[FONT_CMM];
173 return MathFonts[FONT_CMEX];
176 return MathFonts[FONT_MSA];
179 return MathFonts[FONT_MSB];
182 return MathFonts[FONT_EUFRAK];
191 LyXFont const & whichFontBase(MathTextCodes type)
198 if (math_font_available(LM_TC_MSB))
199 return MathFonts[FONT_MSB];
201 return MathFonts[FONT_FAKEBB];
204 if (math_font_available(LM_TC_CMSY))
205 return MathFonts[FONT_CMSY];
207 return MathFonts[FONT_FAKECAL];
210 if (math_font_available(LM_TC_EUFRAK))
211 return MathFonts[FONT_EUFRAK];
213 return MathFonts[FONT_FAKEFRAK];
218 return whichFontBaseIntern(type);
222 void whichFont(LyXFont & f, MathTextCodes type, MathMetricsInfo const & size)
224 f = whichFontBase(type);
226 f.setSize(size.font.size());
228 switch (size.style) {
230 if (type == LM_TC_BOLDSYMB || type == LM_TC_CMEX) {
244 case LM_ST_SCRIPTSCRIPT:
251 lyxerr << "Math Error: wrong font size: " << size.style << endl;
255 if (type != LM_TC_TEXTRM && type != LM_TC_BOX)
256 f.setColor(LColor::math);
258 if (type == LM_TC_TEX)
259 f.setColor(LColor::latex);
265 bool math_font_available(MathTextCodes type)
267 if (!font_available_initialized[type]) {
268 font_available_initialized[type] = true;
269 font_available[type] = fontloader.available(whichFontBaseIntern(type));
270 if (!font_available[type])
271 lyxerr[Debug::FONT] << "Math font " << type << " not available.\n";
273 return font_available[type];
280 * Internal struct of a drawing: code n x1 y1 ... xn yn, where code is:
281 * 0 = end, 1 = line, 2 = polyline, 3 = square line, 4= square polyline
285 double const parenthHigh[] = {
287 0.9840, 0.0014, 0.7143, 0.0323, 0.4603, 0.0772,
288 0.2540, 0.1278, 0.1746, 0.1966, 0.0952, 0.3300,
289 0.0950, 0.5000, 0.0952, 0.6700, 0.1746, 0.8034,
290 0.2540, 0.8722, 0.4603, 0.9228, 0.7143, 0.9677,
296 double const parenth[] = {
298 0.9930, 0.0071, 0.7324, 0.0578, 0.5141, 0.1126,
299 0.3380, 0.1714, 0.2183, 0.2333, 0.0634, 0.3621,
300 0.0141, 0.5000, 0.0563, 0.6369, 0.2113, 0.7647,
301 0.3310, 0.8276, 0.5070, 0.8864, 0.7254, 0.9412,
307 double const brace[] = {
309 0.9492, 0.0020, 0.9379, 0.0020, 0.7458, 0.0243,
310 0.5819, 0.0527, 0.4859, 0.0892, 0.4463, 0.1278,
311 0.4463, 0.3732, 0.4011, 0.4199, 0.2712, 0.4615,
312 0.0734, 0.4919, 0.0113, 0.5000, 0.0734, 0.5081,
313 0.2712, 0.5385, 0.4011, 0.5801, 0.4463, 0.6268,
314 0.4463, 0.8722, 0.4859, 0.9108, 0.5819, 0.9473,
315 0.7458, 0.9757, 0.9379, 0.9980, 0.9492, 0.9980,
320 double const arrow[] = {
322 0.0150, 0.7500, 0.2000, 0.6000, 0.3500, 0.3500,
323 0.5000, 0.0500, 0.6500, 0.3500, 0.8000, 0.6000,
325 3, 0.5000, 0.1500, 0.5000, 0.9500,
330 double const Arrow[] = {
332 0.0150, 0.7500, 0.2000, 0.6000, 0.3500, 0.3500,
333 0.5000, 0.0500, 0.6500, 0.3500, 0.8000, 0.6000,
335 3, 0.3500, 0.5000, 0.3500, 0.9500,
336 3, 0.6500, 0.5000, 0.6500, 0.9500,
341 double const udarrow[] = {
343 0.015, 0.25, 0.5, 0.05, 0.95, 0.25,
345 0.015, 0.75, 0.5, 0.95, 0.95, 0.75,
346 1, 0.5, 0.2, 0.5, 0.8,
351 double const Udarrow[] = {
353 0.015, 0.25, 0.5, 0.05, 0.95, 0.25,
355 0.015, 0.75, 0.5, 0.95, 0.95, 0.75,
356 1, 0.35, 0.2, 0.35, 0.8,
357 1, 0.65, 0.2, 0.65, 0.8,
362 double const brack[] = {
364 0.95, 0.05, 0.05, 0.05, 0.05, 0.95, 0.95, 0.95,
369 double const corner[] = {
371 0.95, 0.05, 0.05, 0.05, 0.05, 0.95,
376 double const angle[] = {
378 1, 0, 0.05, 0.5, 1, 1,
383 double const slash[] = {
384 1, 0.95, 0.05, 0.05, 0.95,
389 double const hline[] = {
390 1, 0.00, 0.5, 1.0, 0.5,
395 double const ddot[] = {
396 1, 0.2, 0.5, 0.3, 0.5,
397 1, 0.7, 0.5, 0.8, 0.5,
402 double const dddot[] = {
403 1, 0.1, 0.5, 0.2, 0.5,
404 1, 0.45, 0.5, 0.55, 0.5,
405 1, 0.8, 0.5, 0.9, 0.5,
410 double const hline3[] = {
412 1, 0.475, 0, 0.525, 0,
418 double const dline3[] = {
419 1, 0.1, 0.1, 0.15, 0.15,
420 1, 0.475, 0.475, 0.525, 0.525,
421 1, 0.85, 0.85, 0.9, 0.9,
426 double const hlinesmall[] = {
427 1, 0.4, 0.5, 0.6, 0.5,
432 double const vert[] = {
433 1, 0.5, 0.05, 0.5, 0.95,
438 double const Vert[] = {
439 1, 0.3, 0.05, 0.3, 0.95,
440 1, 0.7, 0.05, 0.7, 0.95,
445 double const tilde[] = {
447 0.05, 0.8, 0.25, 0.2, 0.75, 0.8, 0.95, 0.2,
457 struct named_deco_struct {
463 named_deco_struct deco_table[] = {
465 {"widehat", angle, 3 },
466 {"widetilde", tilde, 0 },
467 {"underbar", hline, 0 },
468 {"underline", hline, 0 },
469 {"overline", hline, 0 },
470 {"underbrace", brace, 1 },
471 {"overbrace", brace, 3 },
472 {"overleftarrow", arrow, 1 },
473 {"overrightarrow", arrow, 3 },
474 {"overleftrightarrow", udarrow, 1 },
475 {"xleftarrow", arrow, 1 },
476 {"xrightarrow", arrow, 3 },
477 {"underleftarrow", arrow, 1 },
478 {"underrightarrow", arrow, 3 },
479 {"underleftrightarrow",udarrow, 1 },
492 {"backslash", slash, 1 },
493 {"langle", angle, 0 },
494 {"lceil", corner, 0 },
495 {"lfloor", corner, 1 },
496 {"rangle", angle, 2 },
497 {"rceil", corner, 3 },
498 {"rfloor", corner, 2 },
499 {"downarrow", arrow, 2 },
500 {"Downarrow", Arrow, 2 },
501 {"uparrow", arrow, 0 },
502 {"Uparrow", Arrow, 0 },
503 {"updownarrow", udarrow, 0 },
504 {"Updownarrow", Udarrow, 0 },
508 {"dddot", dddot, 0 },
510 {"grave", slash, 1 },
511 {"acute", slash, 0 },
512 {"tilde", tilde, 0 },
514 {"dot", hlinesmall, 0 },
515 {"check", angle, 1 },
516 {"breve", parenth, 1 },
521 {"ldots", hline3, 0 },
522 {"cdots", hline3, 0 },
523 {"vdots", hline3, 1 },
524 {"ddots", dline3, 0 }
528 map<string, deco_struct> deco_list;
530 // sort the table on startup
531 struct init_deco_table {
533 unsigned const n = sizeof(deco_table) / sizeof(deco_table[0]);
534 for (named_deco_struct * p = deco_table; p != deco_table + n; ++p) {
538 deco_list[p->name]= d;
543 static init_deco_table dummy;
546 deco_struct const * search_deco(string const & name)
548 map<string, deco_struct>::const_iterator p = deco_list.find(name);
549 return (p == deco_list.end()) ? 0 : &(p->second);
556 void mathed_char_dim(MathTextCodes type, MathMetricsInfo const & size,
557 unsigned char c, int & asc, int & des, int & wid)
560 whichFont(font, type, size);
561 des = lyxfont::descent(c, font);
562 asc = lyxfont::ascent(c, font);
563 wid = mathed_char_width(type, size, c);
567 int mathed_char_height(MathTextCodes type, MathMetricsInfo const & size,
568 unsigned char c, int & asc, int & des)
571 whichFont(font, type, size);
572 des = lyxfont::descent(c, font);
573 asc = lyxfont::ascent(c, font);
578 int mathed_char_height(MathTextCodes type, MathMetricsInfo const & size,
583 return mathed_char_height(type, size, c, asc, des);
587 int mathed_char_ascent(MathTextCodes type, MathMetricsInfo const & size,
591 whichFont(font, type, size);
592 return lyxfont::ascent(c, font);
596 int mathed_char_descent(MathTextCodes type, MathMetricsInfo const & size,
600 whichFont(font, type, size);
601 return lyxfont::descent(c, font);
605 int mathed_char_width(MathTextCodes type, MathMetricsInfo const & size,
609 whichFont(font, type, size);
610 if (isBinaryOp(c, type))
611 return lyxfont::width(c, font) + 2 * lyxfont::width(' ', font);
613 return lyxfont::width(c, font);
617 void mathed_string_dim(MathTextCodes type, MathMetricsInfo const & size,
618 string const & s, int & asc, int & des, int & wid)
620 mathed_string_height(type, size, s, asc, des);
621 wid = mathed_string_width(type, size, s);
625 int mathed_string_height(MathTextCodes type, MathMetricsInfo const & size,
626 string const & s, int & asc, int & des)
629 whichFont(font, type, size);
631 for (string::const_iterator it = s.begin(); it != s.end(); ++it) {
632 des = max(des, lyxfont::descent(*it, font));
633 asc = max(asc, lyxfont::ascent(*it, font));
639 int mathed_string_width(MathTextCodes type, MathMetricsInfo const & size,
643 whichFont(font, type, size);
644 return lyxfont::width(s, font);
648 int mathed_string_ascent(MathTextCodes type, MathMetricsInfo const & size,
652 whichFont(font, type, size);
654 for (string::const_iterator it = s.begin(); it != s.end(); ++it)
655 asc = max(asc, lyxfont::ascent(*it, font));
660 int mathed_string_descent(MathTextCodes type, MathMetricsInfo const & size,
664 whichFont(font, type, size);
666 for (string::const_iterator it = s.begin(); it != s.end(); ++it)
667 des = max(des, lyxfont::descent(*it, font));
673 void mathed_draw_deco(Painter & pain, int x, int y, int w, int h,
677 pain.line(x + w/2, y, x + w/2, y + h,
678 LColor::mathcursor, Painter::line_onoffdash);
682 deco_struct const * mds = search_deco(name);
684 lyxerr << "Deco was not found. Programming error?\n";
685 lyxerr << "name: '" << name << "'\n";
689 int const n = (w < h) ? w : h;
690 int const r = mds->angle;
691 double const * d = mds->data;
693 if (h > 70 && (name == "(" || name == ")"))
697 Matrix sqmt(r, n, n);
705 for (int i = 0; d[i];) {
706 int code = int(d[i++]);
707 if (code & 1) { // code == 1 || code == 3
713 sqmt.transform(xx, yy);
715 mt.transform(xx, yy);
716 mt.transform(x2, y2);
717 pain.line(x + int(xx), y + int(yy), x + int(x2), y + int(y2),
722 int const n = int(d[i++]);
723 for (int j = 0; j < n; ++j) {
726 // lyxerr << " " << xx << " " << yy << " ";
728 sqmt.transform(xx, yy);
730 mt.transform(xx, yy);
733 // lyxerr << "P[" << j " " << xx << " " << yy << " " << x << " " << y << "]";
735 pain.lines(xp, yp, n, LColor::math);
741 void mathed_draw_framebox(Painter & pain, int x, int y, MathInset const * p)
743 if (mathcursor && mathcursor->isInside(p))
744 pain.rectangle(x, y - p->ascent(), p->width(), p->height(),
749 // In the future maybe we use a better fonts renderer
750 void drawStr(Painter & pain, MathTextCodes type, MathMetricsInfo const & size,
751 int x, int y, string const & str)
754 whichFont(font, type, size);
755 pain.text(x, y, str, font);
759 void drawChar(Painter & pain, MathTextCodes type, MathMetricsInfo const & size,
760 int x, int y, char c)
763 if (isBinaryOp(c, type))
766 if (isBinaryOp(c, type))
768 drawStr(pain, type, size, x, y, s);
772 // decrease math size for super- and subscripts
773 void smallerStyleScript(MathMetricsInfo & st)
777 case LM_ST_TEXT: st.style = LM_ST_SCRIPT; break;
778 default: st.style = LM_ST_SCRIPTSCRIPT;
783 // decrease math size for fractions
784 void smallerStyleFrac(MathMetricsInfo & st)
787 case LM_ST_DISPLAY: st.style = LM_ST_TEXT; break;
788 case LM_ST_TEXT: st.style = LM_ST_SCRIPT; break;
789 default: st.style = LM_ST_SCRIPTSCRIPT;
794 void math_font_max_dim(MathTextCodes code, MathMetricsInfo const & size,
795 int & asc, int & des)
798 whichFont(font, code, size);
799 asc = lyxfont::maxAscent(font);
800 des = lyxfont::maxDescent(font);
804 char const * latex_mathspace[] = {
805 "!", ",", ":", ";", "quad", "qquad"
810 char const * math_font_name(MathTextCodes code)
812 static char const * theFontNames[] = {
824 if (code >= LM_TC_RM && code <= LM_TC_TEXTRM)
825 return theFontNames[code - LM_TC_RM];
829 string convertDelimToLatexName(string const & name)
845 return "\\" + name + " ";