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));
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 hline2[] = {
396 1, 0.1, 0.5, 0.3, 0.5,
397 1, 0.7, 0.5, 0.9, 0.5,
402 double const hline3[] = {
404 1, 0.475, 0, 0.525, 0,
410 double const dline3[] = {
411 1, 0.1, 0.1, 0.15, 0.15,
412 1, 0.475, 0.475, 0.525, 0.525,
413 1, 0.85, 0.85, 0.9, 0.9,
418 double const hlinesmall[] = {
419 1, 0.4, 0.5, 0.6, 0.5,
424 double const vert[] = {
425 1, 0.5, 0.05, 0.5, 0.95,
430 double const Vert[] = {
431 1, 0.3, 0.05, 0.3, 0.95,
432 1, 0.7, 0.05, 0.7, 0.95,
437 double const tilde[] = {
439 0.05, 0.8, 0.25, 0.2, 0.75, 0.8, 0.95, 0.2,
449 struct named_deco_struct {
455 named_deco_struct deco_table[] = {
457 {"widehat", angle, 3 },
458 {"widetilde", tilde, 0 },
459 {"underbar", hline, 0 },
460 {"underline", hline, 0 },
461 {"overline", hline, 0 },
462 {"underbrace", brace, 1 },
463 {"overbrace", brace, 3 },
464 {"overleftarrow", arrow, 1 },
465 {"overrightarrow", arrow, 3 },
478 {"backslash", slash, 1 },
479 {"langle", angle, 0 },
480 {"lceil", corner, 0 },
481 {"lfloor", corner, 1 },
482 {"rangle", angle, 2 },
483 {"rceil", corner, 3 },
484 {"rfloor", corner, 2 },
485 {"downarrow", arrow, 2 },
486 {"Downarrow", Arrow, 2 },
487 {"uparrow", arrow, 0 },
488 {"Uparrow", Arrow, 0 },
489 {"updownarrow", udarrow, 0 },
490 {"Updownarrow", Udarrow, 0 },
493 {"ddot", hline2, 0 },
495 {"grave", slash, 1 },
496 {"acute", slash, 0 },
497 {"tilde", tilde, 0 },
499 {"dot", hlinesmall, 0 },
500 {"check", angle, 1 },
501 {"breve", parenth, 1 },
506 {"ldots", hline3, 0 },
507 {"cdots", hline3, 0 },
508 {"vdots", hline3, 1 },
509 {"ddots", dline3, 0 }
513 map<string, deco_struct> deco_list;
515 // sort the table on startup
516 struct init_deco_table {
518 unsigned const n = sizeof(deco_table) / sizeof(deco_table[0]);
519 for (named_deco_struct * p = deco_table; p != deco_table + n; ++p) {
523 deco_list[p->name]= d;
528 static init_deco_table dummy;
531 deco_struct const * search_deco(string const & name)
533 map<string, deco_struct>::const_iterator p = deco_list.find(name);
534 return (p == deco_list.end()) ? 0 : &(p->second);
541 void mathed_char_dim(MathTextCodes type, MathMetricsInfo const & size,
542 unsigned char c, int & asc, int & des, int & wid)
544 LyXFont const font = whichFont(type, size);
545 des = lyxfont::descent(c, font);
546 asc = lyxfont::ascent(c, font);
547 wid = mathed_char_width(type, size, c);
551 int mathed_char_height(MathTextCodes type, MathMetricsInfo const & size,
552 unsigned char c, int & asc, int & des)
554 LyXFont const font = whichFont(type, size);
555 des = lyxfont::descent(c, font);
556 asc = lyxfont::ascent(c, font);
561 int mathed_char_height(MathTextCodes type, MathMetricsInfo const & size,
566 return mathed_char_height(type, size, c, asc, des);
570 int mathed_char_ascent(MathTextCodes type, MathMetricsInfo const & size,
573 LyXFont const font = whichFont(type, size);
574 return lyxfont::ascent(c, font);
578 int mathed_char_descent(MathTextCodes type, MathMetricsInfo const & size,
581 LyXFont const font = whichFont(type, size);
582 return lyxfont::descent(c, font);
586 int mathed_char_width(MathTextCodes type, MathMetricsInfo const & size,
589 LyXFont const font = whichFont(type, size);
590 if (isBinaryOp(c, type))
591 return lyxfont::width(c, font) + 2 * lyxfont::width(' ', font);
593 return lyxfont::width(c, font);
597 void mathed_string_dim(MathTextCodes type, MathMetricsInfo const & size,
598 string const & s, int & asc, int & des, int & wid)
600 mathed_string_height(type, size, s, asc, des);
601 wid = mathed_string_width(type, size, s);
605 int mathed_string_height(MathTextCodes type, MathMetricsInfo const & size,
606 string const & s, int & asc, int & des)
608 LyXFont const font = whichFont(type, size);
610 for (string::const_iterator it = s.begin(); it != s.end(); ++it) {
611 des = max(des, lyxfont::descent(*it, font));
612 asc = max(asc, lyxfont::ascent(*it, font));
618 int mathed_string_width(MathTextCodes type, MathMetricsInfo const & size,
621 return lyxfont::width(s, whichFont(type, size));
625 int mathed_string_ascent(MathTextCodes type, MathMetricsInfo const & size,
628 LyXFont const font = whichFont(type, size);
630 for (string::const_iterator it = s.begin(); it != s.end(); ++it)
631 asc = max(asc, lyxfont::ascent(*it, font));
636 int mathed_string_descent(MathTextCodes type, MathMetricsInfo const & size,
639 LyXFont const font = whichFont(type, size);
641 for (string::const_iterator it = s.begin(); it != s.end(); ++it)
642 des = max(des, lyxfont::descent(*it, font));
648 void mathed_draw_deco(Painter & pain, int x, int y, int w, int h,
652 pain.line(x + w/2, y, x + w/2, y + h,
653 LColor::mathcursor, Painter::line_onoffdash);
657 deco_struct const * mds = search_deco(name);
659 lyxerr << "Deco was not found. Programming error?\n";
660 lyxerr << "name: '" << name << "'\n";
664 int const n = (w < h) ? w : h;
665 int const r = mds->angle;
666 double const * d = mds->data;
668 if (h > 70 && (name == "(" || name == ")"))
672 Matrix sqmt(r, n, n);
680 for (int i = 0; d[i]; ) {
681 int code = int(d[i++]);
682 if (code & 1) { // code == 1 || code == 3
688 sqmt.transform(xx, yy);
690 mt.transform(xx, yy);
691 mt.transform(x2, y2);
692 pain.line(x + int(xx), y + int(yy), x + int(x2), y + int(y2),
697 int const n = int(d[i++]);
698 for (int j = 0; j < n; ++j) {
701 // lyxerr << " " << xx << " " << yy << " ";
703 sqmt.transform(xx, yy);
705 mt.transform(xx, yy);
708 // lyxerr << "P[" << j " " << xx << " " << yy << " " << x << " " << y << "]";
710 pain.lines(xp, yp, n, LColor::math);
716 void mathed_draw_framebox(Painter & pain, int x, int y, MathInset const * p)
718 if (mathcursor && mathcursor->isInside(p))
719 pain.rectangle(x, y - p->ascent(), p->width(), p->height(),
724 // In the future maybe we use a better fonts renderer
725 void drawStr(Painter & pain, MathTextCodes type, MathMetricsInfo const & siz,
726 int x, int y, string const & s)
728 pain.text(x, y, s, whichFont(type, siz));
732 void drawChar(Painter & pain, MathTextCodes type, MathMetricsInfo const & siz,
733 int x, int y, char c)
736 if (isBinaryOp(c, type))
739 if (isBinaryOp(c, type))
741 drawStr(pain, type, siz, x, y, s);
745 // decrease math size for super- and subscripts
746 void smallerStyleScript(MathMetricsInfo & st)
750 case LM_ST_TEXT: st.style = LM_ST_SCRIPT; break;
751 default: st.style = LM_ST_SCRIPTSCRIPT;
756 // decrease math size for fractions
757 void smallerStyleFrac(MathMetricsInfo & st)
760 case LM_ST_DISPLAY: st.style = LM_ST_TEXT; break;
761 case LM_ST_TEXT: st.style = LM_ST_SCRIPT; break;
762 default: st.style = LM_ST_SCRIPTSCRIPT;
767 void math_font_max_dim(MathTextCodes code, MathMetricsInfo const & siz,
768 int & asc, int & des)
770 LyXFont font = whichFont(code, siz);
771 asc = lyxfont::maxAscent(font);
772 des = lyxfont::maxDescent(font);
776 char const * latex_mathspace[] = {
777 "!", ",", ":", ";", "quad", "qquad"
781 char const * latex_mathstyle[] = {
782 "textstyle", "displaystyle", "scriptstyle", "scriptscriptstyle"
785 kb_action latex_mathfontcmds[] = {
786 LFUN_BOLD, LFUN_EMPH, LFUN_ROMAN, LFUN_CODE, LFUN_SANS,
787 LFUN_ITAL, LFUN_NOUN, LFUN_FRAK, LFUN_FREE, LFUN_DEFAULT
791 char const * math_font_name(MathTextCodes code)
793 static char const * theFontNames[] = {
805 if (code >= LM_TC_RM && code <= LM_TC_TEXTRM)
806 return theFontNames[code - LM_TC_RM];