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 hline2[] = {
398 1, 0.2, 0.5, 0.3, 0.5,
399 1, 0.7, 0.5, 0.8, 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 {"underbar", hline, 0 },
462 {"underline", hline, 0 },
463 {"overline", hline, 0 },
464 {"underbrace", brace, 1 },
465 {"overbrace", brace, 3 },
466 {"overleftarrow", arrow, 1 },
467 {"overrightarrow", arrow, 3 },
468 {"xleftarrow", arrow, 1 },
469 {"xrightarrow", arrow, 3 },
482 {"backslash", slash, 1 },
483 {"langle", angle, 0 },
484 {"lceil", corner, 0 },
485 {"lfloor", corner, 1 },
486 {"rangle", angle, 2 },
487 {"rceil", corner, 3 },
488 {"rfloor", corner, 2 },
489 {"downarrow", arrow, 2 },
490 {"Downarrow", Arrow, 2 },
491 {"uparrow", arrow, 0 },
492 {"Uparrow", Arrow, 0 },
493 {"updownarrow", udarrow, 0 },
494 {"Updownarrow", Udarrow, 0 },
497 {"ddot", hline2, 0 },
499 {"grave", slash, 1 },
500 {"acute", slash, 0 },
501 {"tilde", tilde, 0 },
503 {"dot", hlinesmall, 0 },
504 {"check", angle, 1 },
505 {"breve", parenth, 1 },
510 {"ldots", hline3, 0 },
511 {"cdots", hline3, 0 },
512 {"vdots", hline3, 1 },
513 {"ddots", dline3, 0 }
517 map<string, deco_struct> deco_list;
519 // sort the table on startup
520 struct init_deco_table {
522 unsigned const n = sizeof(deco_table) / sizeof(deco_table[0]);
523 for (named_deco_struct * p = deco_table; p != deco_table + n; ++p) {
527 deco_list[p->name]= d;
532 static init_deco_table dummy;
535 deco_struct const * search_deco(string const & name)
537 map<string, deco_struct>::const_iterator p = deco_list.find(name);
538 return (p == deco_list.end()) ? 0 : &(p->second);
545 void mathed_char_dim(MathTextCodes type, MathMetricsInfo const & size,
546 unsigned char c, int & asc, int & des, int & wid)
548 LyXFont const font = whichFont(type, size);
549 des = lyxfont::descent(c, font);
550 asc = lyxfont::ascent(c, font);
551 wid = mathed_char_width(type, size, c);
555 int mathed_char_height(MathTextCodes type, MathMetricsInfo const & size,
556 unsigned char c, int & asc, int & des)
558 LyXFont const font = whichFont(type, size);
559 des = lyxfont::descent(c, font);
560 asc = lyxfont::ascent(c, font);
565 int mathed_char_height(MathTextCodes type, MathMetricsInfo const & size,
570 return mathed_char_height(type, size, c, asc, des);
574 int mathed_char_ascent(MathTextCodes type, MathMetricsInfo const & size,
577 LyXFont const font = whichFont(type, size);
578 return lyxfont::ascent(c, font);
582 int mathed_char_descent(MathTextCodes type, MathMetricsInfo const & size,
585 LyXFont const font = whichFont(type, size);
586 return lyxfont::descent(c, font);
590 int mathed_char_width(MathTextCodes type, MathMetricsInfo const & size,
593 LyXFont const font = whichFont(type, size);
594 if (isBinaryOp(c, type))
595 return lyxfont::width(c, font) + 2 * lyxfont::width(' ', font);
597 return lyxfont::width(c, font);
601 void mathed_string_dim(MathTextCodes type, MathMetricsInfo const & size,
602 string const & s, int & asc, int & des, int & wid)
604 mathed_string_height(type, size, s, asc, des);
605 wid = mathed_string_width(type, size, s);
609 int mathed_string_height(MathTextCodes type, MathMetricsInfo const & size,
610 string const & s, int & asc, int & des)
612 LyXFont const font = whichFont(type, size);
614 for (string::const_iterator it = s.begin(); it != s.end(); ++it) {
615 des = max(des, lyxfont::descent(*it, font));
616 asc = max(asc, lyxfont::ascent(*it, font));
622 int mathed_string_width(MathTextCodes type, MathMetricsInfo const & size,
625 return lyxfont::width(s, whichFont(type, size));
629 int mathed_string_ascent(MathTextCodes type, MathMetricsInfo const & size,
632 LyXFont const font = whichFont(type, size);
634 for (string::const_iterator it = s.begin(); it != s.end(); ++it)
635 asc = max(asc, lyxfont::ascent(*it, font));
640 int mathed_string_descent(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 des = max(des, lyxfont::descent(*it, font));
652 void mathed_draw_deco(Painter & pain, int x, int y, int w, int h,
656 pain.line(x + w/2, y, x + w/2, y + h,
657 LColor::mathcursor, Painter::line_onoffdash);
661 deco_struct const * mds = search_deco(name);
663 lyxerr << "Deco was not found. Programming error?\n";
664 lyxerr << "name: '" << name << "'\n";
668 int const n = (w < h) ? w : h;
669 int const r = mds->angle;
670 double const * d = mds->data;
672 if (h > 70 && (name == "(" || name == ")"))
676 Matrix sqmt(r, n, n);
684 for (int i = 0; d[i]; ) {
685 int code = int(d[i++]);
686 if (code & 1) { // code == 1 || code == 3
692 sqmt.transform(xx, yy);
694 mt.transform(xx, yy);
695 mt.transform(x2, y2);
696 pain.line(x + int(xx), y + int(yy), x + int(x2), y + int(y2),
701 int const n = int(d[i++]);
702 for (int j = 0; j < n; ++j) {
705 // lyxerr << " " << xx << " " << yy << " ";
707 sqmt.transform(xx, yy);
709 mt.transform(xx, yy);
712 // lyxerr << "P[" << j " " << xx << " " << yy << " " << x << " " << y << "]";
714 pain.lines(xp, yp, n, LColor::math);
720 void mathed_draw_framebox(Painter & pain, int x, int y, MathInset const * p)
722 if (mathcursor && mathcursor->isInside(p))
723 pain.rectangle(x, y - p->ascent(), p->width(), p->height(),
728 // In the future maybe we use a better fonts renderer
729 void drawStr(Painter & pain, MathTextCodes type, MathMetricsInfo const & siz,
730 int x, int y, string const & s)
732 pain.text(x, y, s, whichFont(type, siz));
736 void drawChar(Painter & pain, MathTextCodes type, MathMetricsInfo const & siz,
737 int x, int y, char c)
740 if (isBinaryOp(c, type))
743 if (isBinaryOp(c, type))
745 drawStr(pain, type, siz, x, y, s);
749 // decrease math size for super- and subscripts
750 void smallerStyleScript(MathMetricsInfo & st)
754 case LM_ST_TEXT: st.style = LM_ST_SCRIPT; break;
755 default: st.style = LM_ST_SCRIPTSCRIPT;
760 // decrease math size for fractions
761 void smallerStyleFrac(MathMetricsInfo & st)
764 case LM_ST_DISPLAY: st.style = LM_ST_TEXT; break;
765 case LM_ST_TEXT: st.style = LM_ST_SCRIPT; break;
766 default: st.style = LM_ST_SCRIPTSCRIPT;
771 void math_font_max_dim(MathTextCodes code, MathMetricsInfo const & siz,
772 int & asc, int & des)
774 LyXFont font = whichFont(code, siz);
775 asc = lyxfont::maxAscent(font);
776 des = lyxfont::maxDescent(font);
780 char const * latex_mathspace[] = {
781 "!", ",", ":", ";", "quad", "qquad"
786 char const * math_font_name(MathTextCodes code)
788 static char const * theFontNames[] = {
800 if (code >= LM_TC_RM && code <= LM_TC_TEXTRM)
801 return theFontNames[code - LM_TC_RM];