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.2, 0.5, 0.3, 0.5,
397 1, 0.7, 0.5, 0.8, 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 },
466 {"xleftarrow", arrow, 1 },
467 {"xrightarrow", arrow, 3 },
480 {"backslash", slash, 1 },
481 {"langle", angle, 0 },
482 {"lceil", corner, 0 },
483 {"lfloor", corner, 1 },
484 {"rangle", angle, 2 },
485 {"rceil", corner, 3 },
486 {"rfloor", corner, 2 },
487 {"downarrow", arrow, 2 },
488 {"Downarrow", Arrow, 2 },
489 {"uparrow", arrow, 0 },
490 {"Uparrow", Arrow, 0 },
491 {"updownarrow", udarrow, 0 },
492 {"Updownarrow", Udarrow, 0 },
495 {"ddot", hline2, 0 },
497 {"grave", slash, 1 },
498 {"acute", slash, 0 },
499 {"tilde", tilde, 0 },
501 {"dot", hlinesmall, 0 },
502 {"check", angle, 1 },
503 {"breve", parenth, 1 },
508 {"ldots", hline3, 0 },
509 {"cdots", hline3, 0 },
510 {"vdots", hline3, 1 },
511 {"ddots", dline3, 0 }
515 map<string, deco_struct> deco_list;
517 // sort the table on startup
518 struct init_deco_table {
520 unsigned const n = sizeof(deco_table) / sizeof(deco_table[0]);
521 for (named_deco_struct * p = deco_table; p != deco_table + n; ++p) {
525 deco_list[p->name]= d;
530 static init_deco_table dummy;
533 deco_struct const * search_deco(string const & name)
535 map<string, deco_struct>::const_iterator p = deco_list.find(name);
536 return (p == deco_list.end()) ? 0 : &(p->second);
543 void mathed_char_dim(MathTextCodes type, MathMetricsInfo const & size,
544 unsigned char c, int & asc, int & des, int & wid)
546 LyXFont const font = whichFont(type, size);
547 des = lyxfont::descent(c, font);
548 asc = lyxfont::ascent(c, font);
549 wid = mathed_char_width(type, size, c);
553 int mathed_char_height(MathTextCodes type, MathMetricsInfo const & size,
554 unsigned char c, int & asc, int & des)
556 LyXFont const font = whichFont(type, size);
557 des = lyxfont::descent(c, font);
558 asc = lyxfont::ascent(c, font);
563 int mathed_char_height(MathTextCodes type, MathMetricsInfo const & size,
568 return mathed_char_height(type, size, c, asc, des);
572 int mathed_char_ascent(MathTextCodes type, MathMetricsInfo const & size,
575 LyXFont const font = whichFont(type, size);
576 return lyxfont::ascent(c, font);
580 int mathed_char_descent(MathTextCodes type, MathMetricsInfo const & size,
583 LyXFont const font = whichFont(type, size);
584 return lyxfont::descent(c, font);
588 int mathed_char_width(MathTextCodes type, MathMetricsInfo const & size,
591 LyXFont const font = whichFont(type, size);
592 if (isBinaryOp(c, type))
593 return lyxfont::width(c, font) + 2 * lyxfont::width(' ', font);
595 return lyxfont::width(c, font);
599 void mathed_string_dim(MathTextCodes type, MathMetricsInfo const & size,
600 string const & s, int & asc, int & des, int & wid)
602 mathed_string_height(type, size, s, asc, des);
603 wid = mathed_string_width(type, size, s);
607 int mathed_string_height(MathTextCodes type, MathMetricsInfo const & size,
608 string const & s, int & asc, int & des)
610 LyXFont const font = whichFont(type, size);
612 for (string::const_iterator it = s.begin(); it != s.end(); ++it) {
613 des = max(des, lyxfont::descent(*it, font));
614 asc = max(asc, lyxfont::ascent(*it, font));
620 int mathed_string_width(MathTextCodes type, MathMetricsInfo const & size,
623 return lyxfont::width(s, whichFont(type, size));
627 int mathed_string_ascent(MathTextCodes type, MathMetricsInfo const & size,
630 LyXFont const font = whichFont(type, size);
632 for (string::const_iterator it = s.begin(); it != s.end(); ++it)
633 asc = max(asc, lyxfont::ascent(*it, font));
638 int mathed_string_descent(MathTextCodes type, MathMetricsInfo const & size,
641 LyXFont const font = whichFont(type, size);
643 for (string::const_iterator it = s.begin(); it != s.end(); ++it)
644 des = max(des, lyxfont::descent(*it, font));
650 void mathed_draw_deco(Painter & pain, int x, int y, int w, int h,
654 pain.line(x + w/2, y, x + w/2, y + h,
655 LColor::mathcursor, Painter::line_onoffdash);
659 deco_struct const * mds = search_deco(name);
661 lyxerr << "Deco was not found. Programming error?\n";
662 lyxerr << "name: '" << name << "'\n";
666 int const n = (w < h) ? w : h;
667 int const r = mds->angle;
668 double const * d = mds->data;
670 if (h > 70 && (name == "(" || name == ")"))
674 Matrix sqmt(r, n, n);
682 for (int i = 0; d[i]; ) {
683 int code = int(d[i++]);
684 if (code & 1) { // code == 1 || code == 3
690 sqmt.transform(xx, yy);
692 mt.transform(xx, yy);
693 mt.transform(x2, y2);
694 pain.line(x + int(xx), y + int(yy), x + int(x2), y + int(y2),
699 int const n = int(d[i++]);
700 for (int j = 0; j < n; ++j) {
703 // lyxerr << " " << xx << " " << yy << " ";
705 sqmt.transform(xx, yy);
707 mt.transform(xx, yy);
710 // lyxerr << "P[" << j " " << xx << " " << yy << " " << x << " " << y << "]";
712 pain.lines(xp, yp, n, LColor::math);
718 void mathed_draw_framebox(Painter & pain, int x, int y, MathInset const * p)
720 if (mathcursor && mathcursor->isInside(p))
721 pain.rectangle(x, y - p->ascent(), p->width(), p->height(),
726 // In the future maybe we use a better fonts renderer
727 void drawStr(Painter & pain, MathTextCodes type, MathMetricsInfo const & siz,
728 int x, int y, string const & s)
730 pain.text(x, y, s, whichFont(type, siz));
734 void drawChar(Painter & pain, MathTextCodes type, MathMetricsInfo const & siz,
735 int x, int y, char c)
738 if (isBinaryOp(c, type))
741 if (isBinaryOp(c, type))
743 drawStr(pain, type, siz, x, y, s);
747 // decrease math size for super- and subscripts
748 void smallerStyleScript(MathMetricsInfo & st)
752 case LM_ST_TEXT: st.style = LM_ST_SCRIPT; break;
753 default: st.style = LM_ST_SCRIPTSCRIPT;
758 // decrease math size for fractions
759 void smallerStyleFrac(MathMetricsInfo & st)
762 case LM_ST_DISPLAY: st.style = LM_ST_TEXT; break;
763 case LM_ST_TEXT: st.style = LM_ST_SCRIPT; break;
764 default: st.style = LM_ST_SCRIPTSCRIPT;
769 void math_font_max_dim(MathTextCodes code, MathMetricsInfo const & siz,
770 int & asc, int & des)
772 LyXFont font = whichFont(code, siz);
773 asc = lyxfont::maxAscent(font);
774 des = lyxfont::maxDescent(font);
778 char const * latex_mathspace[] = {
779 "!", ",", ":", ";", "quad", "qquad"
784 char const * math_font_name(MathTextCodes code)
786 static char const * theFontNames[] = {
798 if (code >= LM_TC_RM && code <= LM_TC_TEXTRM)
799 return theFontNames[code - LM_TC_RM];