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);
612 return lyxfont::width(c, font);
616 void mathed_string_dim(MathTextCodes type, MathMetricsInfo const & size,
617 string const & s, int & asc, int & des, int & wid)
619 mathed_string_height(type, size, s, asc, des);
620 wid = mathed_string_width(type, size, s);
624 int mathed_string_height(MathTextCodes type, MathMetricsInfo const & size,
625 string const & s, int & asc, int & des)
628 whichFont(font, type, size);
630 for (string::const_iterator it = s.begin(); it != s.end(); ++it) {
631 des = max(des, lyxfont::descent(*it, font));
632 asc = max(asc, lyxfont::ascent(*it, font));
638 int mathed_string_width(MathTextCodes type, MathMetricsInfo const & size,
642 whichFont(font, type, size);
643 return lyxfont::width(s, font);
647 int mathed_string_ascent(MathTextCodes type, MathMetricsInfo const & size,
651 whichFont(font, type, size);
653 for (string::const_iterator it = s.begin(); it != s.end(); ++it)
654 asc = max(asc, lyxfont::ascent(*it, font));
659 int mathed_string_descent(MathTextCodes type, MathMetricsInfo const & size,
663 whichFont(font, type, size);
665 for (string::const_iterator it = s.begin(); it != s.end(); ++it)
666 des = max(des, lyxfont::descent(*it, font));
672 void mathed_draw_deco(Painter & pain, int x, int y, int w, int h,
676 pain.line(x + w/2, y, x + w/2, y + h,
677 LColor::mathcursor, Painter::line_onoffdash);
681 deco_struct const * mds = search_deco(name);
683 lyxerr << "Deco was not found. Programming error?\n";
684 lyxerr << "name: '" << name << "'\n";
688 int const n = (w < h) ? w : h;
689 int const r = mds->angle;
690 double const * d = mds->data;
692 if (h > 70 && (name == "(" || name == ")"))
696 Matrix sqmt(r, n, n);
704 for (int i = 0; d[i];) {
705 int code = int(d[i++]);
706 if (code & 1) { // code == 1 || code == 3
712 sqmt.transform(xx, yy);
714 mt.transform(xx, yy);
715 mt.transform(x2, y2);
716 pain.line(x + int(xx), y + int(yy), x + int(x2), y + int(y2),
721 int const n = int(d[i++]);
722 for (int j = 0; j < n; ++j) {
725 // lyxerr << " " << xx << " " << yy << " ";
727 sqmt.transform(xx, yy);
729 mt.transform(xx, yy);
732 // lyxerr << "P[" << j " " << xx << " " << yy << " " << x << " " << y << "]";
734 pain.lines(xp, yp, n, LColor::math);
740 void mathed_draw_framebox(Painter & pain, int x, int y, MathInset const * p)
742 if (mathcursor && mathcursor->isInside(p))
743 pain.rectangle(x, y - p->ascent(), p->width(), p->height(),
748 // In the future maybe we use a better fonts renderer
749 void drawStr(Painter & pain, MathTextCodes type, MathMetricsInfo const & size,
750 int x, int y, string const & str)
753 whichFont(font, type, size);
754 pain.text(x, y, str, font);
758 void drawChar(Painter & pain, MathTextCodes type, MathMetricsInfo const & size,
759 int x, int y, char c)
762 whichFont(font, type, size);
763 if (isBinaryOp(c, type))
764 x += lyxfont::width(' ', font);
765 pain.text(x, y, c, font);
769 // decrease math size for super- and subscripts
770 void smallerStyleScript(MathMetricsInfo & st)
774 case LM_ST_TEXT: st.style = LM_ST_SCRIPT; break;
775 default: st.style = LM_ST_SCRIPTSCRIPT;
780 // decrease math size for fractions
781 void smallerStyleFrac(MathMetricsInfo & st)
784 case LM_ST_DISPLAY: st.style = LM_ST_TEXT; break;
785 case LM_ST_TEXT: st.style = LM_ST_SCRIPT; break;
786 default: st.style = LM_ST_SCRIPTSCRIPT;
791 void math_font_max_dim(MathTextCodes code, MathMetricsInfo const & size,
792 int & asc, int & des)
795 whichFont(font, code, size);
796 asc = lyxfont::maxAscent(font);
797 des = lyxfont::maxDescent(font);
801 char const * latex_mathspace[] = {
802 "!", ",", ":", ";", "quad", "qquad"
807 char const * math_font_name(MathTextCodes code)
809 static char const * theFontNames[] = {
821 if (code >= LM_TC_RM && code <= LM_TC_TEXTRM)
822 return theFontNames[code - LM_TC_RM];
826 string convertDelimToLatexName(string const & name)
842 return "\\" + name + " ";