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 LyXFont whichFont(MathTextCodes type, MathMetricsInfo const & size)
224 LyXFont 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);
267 bool math_font_available(MathTextCodes type)
269 if (!font_available_initialized[type]) {
270 font_available_initialized[type] = true;
271 font_available[type] = fontloader.available(whichFontBaseIntern(type));
272 if (!font_available[type])
273 lyxerr[Debug::FONT] << "Math font " << type << " not available.\n";
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 ddot[] = {
398 1, 0.2, 0.5, 0.3, 0.5,
399 1, 0.7, 0.5, 0.8, 0.5,
404 double const dddot[] = {
405 1, 0.1, 0.5, 0.2, 0.5,
406 1, 0.45, 0.5, 0.55, 0.5,
407 1, 0.8, 0.5, 0.9, 0.5,
412 double const hline3[] = {
414 1, 0.475, 0, 0.525, 0,
420 double const dline3[] = {
421 1, 0.1, 0.1, 0.15, 0.15,
422 1, 0.475, 0.475, 0.525, 0.525,
423 1, 0.85, 0.85, 0.9, 0.9,
428 double const hlinesmall[] = {
429 1, 0.4, 0.5, 0.6, 0.5,
434 double const vert[] = {
435 1, 0.5, 0.05, 0.5, 0.95,
440 double const Vert[] = {
441 1, 0.3, 0.05, 0.3, 0.95,
442 1, 0.7, 0.05, 0.7, 0.95,
447 double const tilde[] = {
449 0.05, 0.8, 0.25, 0.2, 0.75, 0.8, 0.95, 0.2,
459 struct named_deco_struct {
465 named_deco_struct deco_table[] = {
467 {"widehat", angle, 3 },
468 {"widetilde", tilde, 0 },
469 {"underbar", hline, 0 },
470 {"underline", hline, 0 },
471 {"overline", hline, 0 },
472 {"underbrace", brace, 1 },
473 {"overbrace", brace, 3 },
474 {"overleftarrow", arrow, 1 },
475 {"overrightarrow", arrow, 3 },
476 {"xleftarrow", arrow, 1 },
477 {"xrightarrow", arrow, 3 },
478 {"underleftarrow", arrow, 1 },
479 {"underrightarrow", arrow, 3 },
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)
559 LyXFont const font = whichFont(type, size);
560 des = lyxfont::descent(c, font);
561 asc = lyxfont::ascent(c, font);
562 wid = mathed_char_width(type, size, c);
566 int mathed_char_height(MathTextCodes type, MathMetricsInfo const & size,
567 unsigned char c, int & asc, int & des)
569 LyXFont const font = whichFont(type, size);
570 des = lyxfont::descent(c, font);
571 asc = lyxfont::ascent(c, font);
576 int mathed_char_height(MathTextCodes type, MathMetricsInfo const & size,
581 return mathed_char_height(type, size, c, asc, des);
585 int mathed_char_ascent(MathTextCodes type, MathMetricsInfo const & size,
588 LyXFont const font = whichFont(type, size);
589 return lyxfont::ascent(c, font);
593 int mathed_char_descent(MathTextCodes type, MathMetricsInfo const & size,
596 LyXFont const font = whichFont(type, size);
597 return lyxfont::descent(c, font);
601 int mathed_char_width(MathTextCodes type, MathMetricsInfo const & size,
604 LyXFont const font = whichFont(type, size);
605 if (isBinaryOp(c, type))
606 return lyxfont::width(c, font) + 2 * lyxfont::width(' ', font);
608 return lyxfont::width(c, font);
612 void mathed_string_dim(MathTextCodes type, MathMetricsInfo const & size,
613 string const & s, int & asc, int & des, int & wid)
615 mathed_string_height(type, size, s, asc, des);
616 wid = mathed_string_width(type, size, s);
620 int mathed_string_height(MathTextCodes type, MathMetricsInfo const & size,
621 string const & s, int & asc, int & des)
623 LyXFont const font = whichFont(type, size);
625 for (string::const_iterator it = s.begin(); it != s.end(); ++it) {
626 des = max(des, lyxfont::descent(*it, font));
627 asc = max(asc, lyxfont::ascent(*it, font));
633 int mathed_string_width(MathTextCodes type, MathMetricsInfo const & size,
636 return lyxfont::width(s, whichFont(type, size));
640 int mathed_string_ascent(MathTextCodes type, MathMetricsInfo const & size,
643 LyXFont const font = whichFont(type, size);
645 for (string::const_iterator it = s.begin(); it != s.end(); ++it)
646 asc = max(asc, lyxfont::ascent(*it, font));
651 int mathed_string_descent(MathTextCodes type, MathMetricsInfo const & size,
654 LyXFont const font = whichFont(type, size);
656 for (string::const_iterator it = s.begin(); it != s.end(); ++it)
657 des = max(des, lyxfont::descent(*it, font));
663 void mathed_draw_deco(Painter & pain, int x, int y, int w, int h,
667 pain.line(x + w/2, y, x + w/2, y + h,
668 LColor::mathcursor, Painter::line_onoffdash);
672 deco_struct const * mds = search_deco(name);
674 lyxerr << "Deco was not found. Programming error?\n";
675 lyxerr << "name: '" << name << "'\n";
679 int const n = (w < h) ? w : h;
680 int const r = mds->angle;
681 double const * d = mds->data;
683 if (h > 70 && (name == "(" || name == ")"))
687 Matrix sqmt(r, n, n);
695 for (int i = 0; d[i]; ) {
696 int code = int(d[i++]);
697 if (code & 1) { // code == 1 || code == 3
703 sqmt.transform(xx, yy);
705 mt.transform(xx, yy);
706 mt.transform(x2, y2);
707 pain.line(x + int(xx), y + int(yy), x + int(x2), y + int(y2),
712 int const n = int(d[i++]);
713 for (int j = 0; j < n; ++j) {
716 // lyxerr << " " << xx << " " << yy << " ";
718 sqmt.transform(xx, yy);
720 mt.transform(xx, yy);
723 // lyxerr << "P[" << j " " << xx << " " << yy << " " << x << " " << y << "]";
725 pain.lines(xp, yp, n, LColor::math);
731 void mathed_draw_framebox(Painter & pain, int x, int y, MathInset const * p)
733 if (mathcursor && mathcursor->isInside(p))
734 pain.rectangle(x, y - p->ascent(), p->width(), p->height(),
739 // In the future maybe we use a better fonts renderer
740 void drawStr(Painter & pain, MathTextCodes type, MathMetricsInfo const & siz,
741 int x, int y, string const & s)
743 pain.text(x, y, s, whichFont(type, siz));
747 void drawChar(Painter & pain, MathTextCodes type, MathMetricsInfo const & siz,
748 int x, int y, char c)
751 if (isBinaryOp(c, type))
754 if (isBinaryOp(c, type))
756 drawStr(pain, type, siz, x, y, s);
760 // decrease math size for super- and subscripts
761 void smallerStyleScript(MathMetricsInfo & st)
765 case LM_ST_TEXT: st.style = LM_ST_SCRIPT; break;
766 default: st.style = LM_ST_SCRIPTSCRIPT;
771 // decrease math size for fractions
772 void smallerStyleFrac(MathMetricsInfo & st)
775 case LM_ST_DISPLAY: st.style = LM_ST_TEXT; break;
776 case LM_ST_TEXT: st.style = LM_ST_SCRIPT; break;
777 default: st.style = LM_ST_SCRIPTSCRIPT;
782 void math_font_max_dim(MathTextCodes code, MathMetricsInfo const & siz,
783 int & asc, int & des)
785 LyXFont font = whichFont(code, siz);
786 asc = lyxfont::maxAscent(font);
787 des = lyxfont::maxDescent(font);
791 char const * latex_mathspace[] = {
792 "!", ",", ":", ";", "quad", "qquad"
797 char const * math_font_name(MathTextCodes code)
799 static char const * theFontNames[] = {
811 if (code >= LM_TC_RM && code <= LM_TC_TEXTRM)
812 return theFontNames[code - LM_TC_RM];
816 string convertDelimToLatexName(string const & name)
832 return "\\" + name + " ";