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);
224 void whichFont(LyXFont & f, MathTextCodes type, MathMetricsInfo const & size)
226 f = whichFontBase(type);
228 f.setSize(size.font.size());
230 switch (size.style) {
232 if (type == LM_TC_BOLDSYMB || type == LM_TC_CMEX) {
246 case LM_ST_SCRIPTSCRIPT:
253 lyxerr << "Math Error: wrong font size: " << size.style << endl;
257 if (type != LM_TC_TEXTRM && type != LM_TC_BOX)
258 f.setColor(LColor::math);
260 if (type == LM_TC_TEX)
261 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(LyXFont const & font,
557 unsigned char c, int & asc, int & des, int & wid)
559 des = lyxfont::descent(c, font);
560 asc = lyxfont::ascent(c, font);
561 wid = mathed_char_width(font, c);
565 int mathed_char_height(LyXFont const & font,
566 unsigned char c, int & asc, int & des)
568 des = lyxfont::descent(c, font);
569 asc = lyxfont::ascent(c, font);
574 int mathed_char_height(LyXFont const & font, unsigned char c)
578 return mathed_char_height(font, c, asc, des);
582 int mathed_char_ascent(LyXFont const & font, unsigned char c)
584 return lyxfont::ascent(c, font);
588 int mathed_char_descent(LyXFont const & font, unsigned char c)
590 return lyxfont::descent(c, font);
594 int mathed_char_width(LyXFont const & font,
597 //if (isBinaryOp(c, type))
598 // return lyxfont::width(c, font) + 2 * lyxfont::width(' ', font);
599 return lyxfont::width(c, font);
603 void mathed_string_dim(LyXFont const & font,
604 string const & s, int & asc, int & des, int & wid)
606 mathed_string_height(font, s, asc, des);
607 wid = mathed_string_width(font, s);
611 int mathed_string_height(LyXFont const & font,
612 string const & s, int & asc, int & des)
615 for (string::const_iterator it = s.begin(); it != s.end(); ++it) {
616 des = max(des, lyxfont::descent(*it, font));
617 asc = max(asc, lyxfont::ascent(*it, font));
623 int mathed_string_width(LyXFont const & font, string const & s)
625 return lyxfont::width(s, font);
629 int mathed_string_ascent(LyXFont const & font, string const & s)
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(LyXFont const & font, string const & s)
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, LyXFont const & font,
726 int x, int y, string const & str)
728 pain.text(x, y, str, font);
732 void drawChar(Painter & pain, LyXFont const & font, int x, int y, char c)
734 //if (isBinaryOp(c, type))
735 // x += lyxfont::width(' ', font);
736 pain.text(x, y, c, font);
740 // decrease math size for super- and subscripts
741 void smallerStyleScript(MathMetricsInfo & st)
745 case LM_ST_TEXT: st.style = LM_ST_SCRIPT; break;
746 default: st.style = LM_ST_SCRIPTSCRIPT;
751 // decrease math size for fractions
752 void smallerStyleFrac(MathMetricsInfo & st)
755 case LM_ST_DISPLAY: st.style = LM_ST_TEXT; break;
756 case LM_ST_TEXT: st.style = LM_ST_SCRIPT; break;
757 default: st.style = LM_ST_SCRIPTSCRIPT;
762 void math_font_max_dim(LyXFont const & font, int & asc, int & des)
764 asc = lyxfont::maxAscent(font);
765 des = lyxfont::maxDescent(font);
769 char const * latex_mathspace[] = {
770 "!", ",", ":", ";", "quad", "qquad"
775 char const * math_font_name(MathTextCodes code)
777 static char const * theFontNames[] = {
789 if (code >= LM_TC_RM && code <= LM_TC_TEXTRM)
790 return theFontNames[code - LM_TC_RM];
794 string convertDelimToLatexName(string const & name)
810 return "\\" + name + " ";