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 {"overleftrightarrow", udarrow, 1 },
477 {"xleftarrow", arrow, 1 },
478 {"xrightarrow", arrow, 3 },
479 {"underleftarrow", arrow, 1 },
480 {"underrightarrow", arrow, 3 },
481 {"underleftrightarrow",udarrow, 1 },
494 {"backslash", slash, 1 },
495 {"langle", angle, 0 },
496 {"lceil", corner, 0 },
497 {"lfloor", corner, 1 },
498 {"rangle", angle, 2 },
499 {"rceil", corner, 3 },
500 {"rfloor", corner, 2 },
501 {"downarrow", arrow, 2 },
502 {"Downarrow", Arrow, 2 },
503 {"uparrow", arrow, 0 },
504 {"Uparrow", Arrow, 0 },
505 {"updownarrow", udarrow, 0 },
506 {"Updownarrow", Udarrow, 0 },
510 {"dddot", dddot, 0 },
512 {"grave", slash, 1 },
513 {"acute", slash, 0 },
514 {"tilde", tilde, 0 },
516 {"dot", hlinesmall, 0 },
517 {"check", angle, 1 },
518 {"breve", parenth, 1 },
523 {"ldots", hline3, 0 },
524 {"cdots", hline3, 0 },
525 {"vdots", hline3, 1 },
526 {"ddots", dline3, 0 }
530 map<string, deco_struct> deco_list;
532 // sort the table on startup
533 struct init_deco_table {
535 unsigned const n = sizeof(deco_table) / sizeof(deco_table[0]);
536 for (named_deco_struct * p = deco_table; p != deco_table + n; ++p) {
540 deco_list[p->name]= d;
545 static init_deco_table dummy;
548 deco_struct const * search_deco(string const & name)
550 map<string, deco_struct>::const_iterator p = deco_list.find(name);
551 return (p == deco_list.end()) ? 0 : &(p->second);
558 void mathed_char_dim(MathTextCodes type, MathMetricsInfo const & size,
559 unsigned char c, int & asc, int & des, int & wid)
561 LyXFont const font = whichFont(type, size);
562 des = lyxfont::descent(c, font);
563 asc = lyxfont::ascent(c, font);
564 wid = mathed_char_width(type, size, c);
568 int mathed_char_height(MathTextCodes type, MathMetricsInfo const & size,
569 unsigned char c, int & asc, int & des)
571 LyXFont const font = whichFont(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,
590 LyXFont const font = whichFont(type, size);
591 return lyxfont::ascent(c, font);
595 int mathed_char_descent(MathTextCodes type, MathMetricsInfo const & size,
598 LyXFont const font = whichFont(type, size);
599 return lyxfont::descent(c, font);
603 int mathed_char_width(MathTextCodes type, MathMetricsInfo const & size,
606 LyXFont const font = whichFont(type, size);
607 if (isBinaryOp(c, type))
608 return lyxfont::width(c, font) + 2 * lyxfont::width(' ', font);
610 return lyxfont::width(c, font);
614 void mathed_string_dim(MathTextCodes type, MathMetricsInfo const & size,
615 string const & s, int & asc, int & des, int & wid)
617 mathed_string_height(type, size, s, asc, des);
618 wid = mathed_string_width(type, size, s);
622 int mathed_string_height(MathTextCodes type, MathMetricsInfo const & size,
623 string const & s, int & asc, int & des)
625 LyXFont const font = whichFont(type, size);
627 for (string::const_iterator it = s.begin(); it != s.end(); ++it) {
628 des = max(des, lyxfont::descent(*it, font));
629 asc = max(asc, lyxfont::ascent(*it, font));
635 int mathed_string_width(MathTextCodes type, MathMetricsInfo const & size,
638 return lyxfont::width(s, whichFont(type, size));
642 int mathed_string_ascent(MathTextCodes type, MathMetricsInfo const & size,
645 LyXFont const font = whichFont(type, size);
647 for (string::const_iterator it = s.begin(); it != s.end(); ++it)
648 asc = max(asc, lyxfont::ascent(*it, font));
653 int mathed_string_descent(MathTextCodes type, MathMetricsInfo const & size,
656 LyXFont const font = whichFont(type, size);
658 for (string::const_iterator it = s.begin(); it != s.end(); ++it)
659 des = max(des, lyxfont::descent(*it, font));
665 void mathed_draw_deco(Painter & pain, int x, int y, int w, int h,
669 pain.line(x + w/2, y, x + w/2, y + h,
670 LColor::mathcursor, Painter::line_onoffdash);
674 deco_struct const * mds = search_deco(name);
676 lyxerr << "Deco was not found. Programming error?\n";
677 lyxerr << "name: '" << name << "'\n";
681 int const n = (w < h) ? w : h;
682 int const r = mds->angle;
683 double const * d = mds->data;
685 if (h > 70 && (name == "(" || name == ")"))
689 Matrix sqmt(r, n, n);
697 for (int i = 0; d[i]; ) {
698 int code = int(d[i++]);
699 if (code & 1) { // code == 1 || code == 3
705 sqmt.transform(xx, yy);
707 mt.transform(xx, yy);
708 mt.transform(x2, y2);
709 pain.line(x + int(xx), y + int(yy), x + int(x2), y + int(y2),
714 int const n = int(d[i++]);
715 for (int j = 0; j < n; ++j) {
718 // lyxerr << " " << xx << " " << yy << " ";
720 sqmt.transform(xx, yy);
722 mt.transform(xx, yy);
725 // lyxerr << "P[" << j " " << xx << " " << yy << " " << x << " " << y << "]";
727 pain.lines(xp, yp, n, LColor::math);
733 void mathed_draw_framebox(Painter & pain, int x, int y, MathInset const * p)
735 if (mathcursor && mathcursor->isInside(p))
736 pain.rectangle(x, y - p->ascent(), p->width(), p->height(),
741 // In the future maybe we use a better fonts renderer
742 void drawStr(Painter & pain, MathTextCodes type, MathMetricsInfo const & siz,
743 int x, int y, string const & s)
745 pain.text(x, y, s, whichFont(type, siz));
749 void drawChar(Painter & pain, MathTextCodes type, MathMetricsInfo const & siz,
750 int x, int y, char c)
753 if (isBinaryOp(c, type))
756 if (isBinaryOp(c, type))
758 drawStr(pain, type, siz, x, y, s);
762 // decrease math size for super- and subscripts
763 void smallerStyleScript(MathMetricsInfo & st)
767 case LM_ST_TEXT: st.style = LM_ST_SCRIPT; break;
768 default: st.style = LM_ST_SCRIPTSCRIPT;
773 // decrease math size for fractions
774 void smallerStyleFrac(MathMetricsInfo & st)
777 case LM_ST_DISPLAY: st.style = LM_ST_TEXT; break;
778 case LM_ST_TEXT: st.style = LM_ST_SCRIPT; break;
779 default: st.style = LM_ST_SCRIPTSCRIPT;
784 void math_font_max_dim(MathTextCodes code, MathMetricsInfo const & siz,
785 int & asc, int & des)
787 LyXFont font = whichFont(code, siz);
788 asc = lyxfont::maxAscent(font);
789 des = lyxfont::maxDescent(font);
793 char const * latex_mathspace[] = {
794 "!", ",", ":", ";", "quad", "qquad"
799 char const * math_font_name(MathTextCodes code)
801 static char const * theFontNames[] = {
813 if (code >= LM_TC_RM && code <= LM_TC_TEXTRM)
814 return theFontNames[code - LM_TC_RM];
818 string convertDelimToLatexName(string const & name)
834 return "\\" + name + " ";