5 #include "mathed/support.h"
7 #include "FontLoader.h"
10 #include "math_inset.h"
11 #include "math_parser.h"
20 bool isBinaryOp(char c, MathTextCodes type)
22 return type < LM_TC_SYMB && strchr("+-<>=/*", c);
30 Matrix(int, double, double);
32 void transform(double &, double &);
39 Matrix::Matrix(int code, double x, double y)
41 double const cs = (code & 1) ? 0 : (1 - code);
42 double const sn = (code & 1) ? (2 - code) : 0;
50 void Matrix::transform(double & x, double & y)
52 double xx = m_[0][0] * x + m_[0][1] * y;
53 double yy = m_[1][0] * x + m_[1][1] * y;
61 LyXFont * MathFonts = 0;
62 bool font_available[LM_FONT_END];
63 bool font_available_initialized[LM_FONT_END];
84 void mathed_init_fonts()
86 MathFonts = new LyXFont[FONT_NUM]; //DEC cxx cannot initialize all fonts
89 for (int i = 0 ; i < FONT_NUM ; ++i) {
90 MathFonts[i] = LyXFont(LyXFont::ALL_SANE);
93 MathFonts[FONT_IT].setShape(LyXFont::ITALIC_SHAPE);
95 MathFonts[FONT_SYMBOL].setFamily(LyXFont::SYMBOL_FAMILY);
97 MathFonts[FONT_SYMBOLI].setFamily(LyXFont::SYMBOL_FAMILY);
98 MathFonts[FONT_SYMBOLI].setShape(LyXFont::ITALIC_SHAPE);
100 MathFonts[FONT_BF].setSeries(LyXFont::BOLD_SERIES);
102 MathFonts[FONT_BB].setSeries(LyXFont::BOLD_SERIES);
103 MathFonts[FONT_BB].setFamily(LyXFont::TYPEWRITER_FAMILY);
105 MathFonts[FONT_CAL].setFamily(LyXFont::SANS_FAMILY);
106 MathFonts[FONT_CAL].setShape(LyXFont::ITALIC_SHAPE);
108 MathFonts[FONT_TT].setFamily(LyXFont::TYPEWRITER_FAMILY);
110 MathFonts[FONT_RM].setFamily(LyXFont::ROMAN_FAMILY);
112 MathFonts[FONT_SF].setFamily(LyXFont::SANS_FAMILY);
114 MathFonts[FONT_CMR].setFamily(LyXFont::CMR_FAMILY);
115 MathFonts[FONT_CMSY].setFamily(LyXFont::CMSY_FAMILY);
116 MathFonts[FONT_CMM].setFamily(LyXFont::CMM_FAMILY);
117 MathFonts[FONT_CMEX].setFamily(LyXFont::CMEX_FAMILY);
118 MathFonts[FONT_MSA].setFamily(LyXFont::MSA_FAMILY);
119 MathFonts[FONT_MSB].setFamily(LyXFont::MSB_FAMILY);
121 for (int i = 0; i < LM_FONT_END; ++i)
122 font_available_initialized[i] = false;
126 LyXFont const & whichFontBase(MathTextCodes type)
134 return MathFonts[FONT_SYMBOLI];
138 return MathFonts[FONT_IT];
141 return MathFonts[FONT_BF];
144 if (math_font_available(LM_TC_MSB))
145 return MathFonts[FONT_MSB];
147 return MathFonts[FONT_BB];
150 if (math_font_available(LM_TC_CMSY))
151 return MathFonts[FONT_CMSY];
153 return MathFonts[FONT_CAL];
156 return MathFonts[FONT_TT];
162 return MathFonts[FONT_RM];
165 return MathFonts[FONT_SF];
168 return MathFonts[FONT_CMR];
171 return MathFonts[FONT_CMSY];
174 return MathFonts[FONT_CMM];
177 return MathFonts[FONT_CMEX];
180 return MathFonts[FONT_MSA];
183 return MathFonts[FONT_MSB];
192 LyXFont whichFont(MathTextCodes type, MathMetricsInfo const & size)
194 LyXFont f = whichFontBase(type);
196 f.setSize(size.font.size());
198 switch (size.style) {
200 if (type == LM_TC_BOLDSYMB || type == LM_TC_CMEX) {
214 case LM_ST_SCRIPTSCRIPT:
221 lyxerr << "Math Error: wrong font size: " << size.style << endl;
225 if (type != LM_TC_TEXTRM)
226 f.setColor(LColor::math);
228 if (type == LM_TC_TEX)
229 f.setColor(LColor::latex);
237 bool math_font_available(MathTextCodes type)
239 if (!font_available_initialized[type]) {
240 font_available_initialized[type] = true;
241 font_available[type] = fontloader.available(whichFontBase(type));
243 return font_available[type];
250 * Internal struct of a drawing: code n x1 y1 ... xn yn, where code is:
251 * 0 = end, 1 = line, 2 = polyline, 3 = square line, 4= square polyline
255 double const parenthHigh[] = {
257 0.9840, 0.0014, 0.7143, 0.0323, 0.4603, 0.0772,
258 0.2540, 0.1278, 0.1746, 0.1966, 0.0952, 0.3300,
259 0.0950, 0.5000, 0.0952, 0.6700, 0.1746, 0.8034,
260 0.2540, 0.8722, 0.4603, 0.9228, 0.7143, 0.9677,
266 double const parenth[] = {
268 0.9930, 0.0071, 0.7324, 0.0578, 0.5141, 0.1126,
269 0.3380, 0.1714, 0.2183, 0.2333, 0.0634, 0.3621,
270 0.0141, 0.5000, 0.0563, 0.6369, 0.2113, 0.7647,
271 0.3310, 0.8276, 0.5070, 0.8864, 0.7254, 0.9412,
277 double const brace[] = {
279 0.9492, 0.0020, 0.9379, 0.0020, 0.7458, 0.0243,
280 0.5819, 0.0527, 0.4859, 0.0892, 0.4463, 0.1278,
281 0.4463, 0.3732, 0.4011, 0.4199, 0.2712, 0.4615,
282 0.0734, 0.4919, 0.0113, 0.5000, 0.0734, 0.5081,
283 0.2712, 0.5385, 0.4011, 0.5801, 0.4463, 0.6268,
284 0.4463, 0.8722, 0.4859, 0.9108, 0.5819, 0.9473,
285 0.7458, 0.9757, 0.9379, 0.9980, 0.9492, 0.9980,
290 double const arrow[] = {
292 0.0150, 0.7500, 0.2000, 0.6000, 0.3500, 0.3500,
293 0.5000, 0.0500, 0.6500, 0.3500, 0.8000, 0.6000,
295 3, 0.5000, 0.1500, 0.5000, 0.9500,
300 double const Arrow[] = {
302 0.0150, 0.7500, 0.2000, 0.6000, 0.3500, 0.3500,
303 0.5000, 0.0500, 0.6500, 0.3500, 0.8000, 0.6000,
305 3, 0.3500, 0.5000, 0.3500, 0.9500,
306 3, 0.6500, 0.5000, 0.6500, 0.9500,
311 double const udarrow[] = {
313 0.015, 0.25, 0.5, 0.05, 0.95, 0.25,
315 0.015, 0.75, 0.5, 0.95, 0.95, 0.75,
316 1, 0.5, 0.2, 0.5, 0.8,
321 double const Udarrow[] = {
323 0.015, 0.25, 0.5, 0.05, 0.95, 0.25,
325 0.015, 0.75, 0.5, 0.95, 0.95, 0.75,
326 1, 0.35, 0.2, 0.35, 0.8,
327 1, 0.65, 0.2, 0.65, 0.8,
332 double const brack[] = {
334 0.95, 0.05, 0.05, 0.05, 0.05, 0.95, 0.95, 0.95,
339 double const corner[] = {
341 0.95, 0.05, 0.05, 0.05, 0.05, 0.95,
346 double const angle[] = {
348 1, 0, 0.05, 0.5, 1, 1,
353 double const slash[] = {
354 1, 0.95, 0.05, 0.05, 0.95,
359 double const hline[] = {
360 1, 0.00, 0.5, 1.0, 0.5,
365 double const hline2[] = {
366 1, 0.1, 0.5, 0.3, 0.5,
367 1, 0.7, 0.5, 0.9, 0.5,
372 double const hline3[] = {
374 1, 0.475, 0, 0.525, 0,
380 double const dline3[] = {
381 1, 0.1, 0.1, 0.15, 0.15,
382 1, 0.475, 0.475, 0.525, 0.525,
383 1, 0.85, 0.85, 0.9, 0.9,
388 double const hlinesmall[] = {
389 1, 0.4, 0.5, 0.6, 0.5,
394 double const vert[] = {
395 1, 0.5, 0.05, 0.5, 0.95,
400 double const Vert[] = {
401 1, 0.3, 0.05, 0.3, 0.95,
402 1, 0.7, 0.05, 0.7, 0.95,
407 double const tilde[] = {
409 0.05, 0.8, 0.25, 0.2, 0.75, 0.8, 0.95, 0.2,
419 struct named_deco_struct {
425 named_deco_struct deco_table[] = {
427 {"widehat", angle, 3 },
428 {"widetilde", tilde, 0 },
429 {"underline", hline, 0 },
430 {"overline", hline, 0 },
431 {"underbrace", brace, 1 },
432 {"overbrace", brace, 3 },
433 {"overleftarrow", arrow, 1 },
434 {"overrightarrow", arrow, 3 },
447 {"backslash", slash, 1 },
448 {"langle", angle, 0 },
449 {"lceil", corner, 0 },
450 {"lfloor", corner, 1 },
451 {"rangle", angle, 2 },
452 {"rceil", corner, 3 },
453 {"rfloor", corner, 2 },
454 {"downarrow", arrow, 2 },
455 {"Downarrow", Arrow, 2 },
456 {"uparrow", arrow, 0 },
457 {"Uparrow", Arrow, 0 },
458 {"updownarrow", udarrow, 0 },
459 {"Updownarrow", Udarrow, 0 },
462 {"ddot", hline2, 0 },
464 {"grave", slash, 1 },
465 {"acute", slash, 0 },
466 {"tilde", tilde, 0 },
468 {"dot", hlinesmall, 0 },
469 {"check", angle, 1 },
470 {"breve", parenth, 1 },
475 {"ldots", hline3, 0 },
476 {"cdots", hline3, 0 },
477 {"vdots", hline3, 1 },
478 {"ddots", dline3, 0 }
482 map<string, deco_struct> deco_list;
484 // sort the table on startup
485 struct init_deco_table {
487 unsigned const n = sizeof(deco_table) / sizeof(deco_table[0]);
488 for (named_deco_struct * p = deco_table; p != deco_table + n; ++p) {
492 deco_list[p->name]= d;
497 static init_deco_table dummy;
500 deco_struct const * search_deco(string const & name)
502 map<string, deco_struct>::const_iterator p = deco_list.find(name);
503 return (p == deco_list.end()) ? 0 : &(p->second);
510 void mathed_char_dim(MathTextCodes type, MathMetricsInfo const & size,
511 unsigned char c, int & asc, int & des, int & wid)
513 LyXFont const font = whichFont(type, size);
514 des = lyxfont::descent(c, font);
515 asc = lyxfont::ascent(c, font);
516 wid = mathed_char_width(type, size, c);
520 int mathed_char_height(MathTextCodes type, MathMetricsInfo const & size,
521 unsigned char c, int & asc, int & des)
523 LyXFont const font = whichFont(type, size);
524 des = lyxfont::descent(c, font);
525 asc = lyxfont::ascent(c, font);
530 int mathed_char_height(MathTextCodes type, MathMetricsInfo const & size,
535 return mathed_char_height(type, size, c, asc, des);
539 int mathed_char_ascent(MathTextCodes type, MathMetricsInfo const & size,
542 LyXFont const font = whichFont(type, size);
543 return lyxfont::ascent(c, font);
547 int mathed_char_descent(MathTextCodes type, MathMetricsInfo const & size,
550 LyXFont const font = whichFont(type, size);
551 return lyxfont::descent(c, font);
555 int mathed_char_width(MathTextCodes type, MathMetricsInfo const & size,
558 LyXFont const font = whichFont(type, size);
559 if (isBinaryOp(c, type))
560 return lyxfont::width(c, font) + 2 * lyxfont::width(' ', font);
562 return lyxfont::width(c, font);
566 void mathed_string_dim(MathTextCodes type, MathMetricsInfo const & size,
567 string const & s, int & asc, int & des, int & wid)
569 mathed_string_height(type, size, s, asc, des);
570 wid = mathed_string_width(type, size, s);
574 int mathed_string_height(MathTextCodes type, MathMetricsInfo const & size,
575 string const & s, int & asc, int & des)
577 LyXFont const font = whichFont(type, size);
579 for (string::const_iterator it = s.begin(); it != s.end(); ++it) {
580 des = max(des, lyxfont::descent(*it, font));
581 asc = max(asc, lyxfont::ascent(*it, font));
587 int mathed_string_width(MathTextCodes type, MathMetricsInfo const & size,
590 return lyxfont::width(s, whichFont(type, size));
594 void mathed_draw_deco(Painter & pain, int x, int y, int w, int h,
598 pain.line(x + w/2, y, x + w/2, y + h,
599 LColor::mathcursor, Painter::line_onoffdash);
603 deco_struct const * mds = search_deco(name);
605 lyxerr << "Deco was not found. Programming error?\n";
606 lyxerr << "name: '" << name << "'\n";
610 int const n = (w < h) ? w : h;
611 int const r = mds->angle;
612 double const * d = mds->data;
614 if (h > 70 && (name == "(" || name == ")"))
618 Matrix sqmt(r, n, n);
626 for (int i = 0; d[i]; ) {
627 int code = int(d[i++]);
628 if (code & 1) { // code == 1 || code == 3
634 sqmt.transform(xx, yy);
636 mt.transform(xx, yy);
637 mt.transform(x2, y2);
638 pain.line(x + int(xx), y + int(yy), x + int(x2), y + int(y2),
643 int const n = int(d[i++]);
644 for (int j = 0; j < n; ++j) {
647 // lyxerr << " " << xx << " " << yy << " ";
649 sqmt.transform(xx, yy);
651 mt.transform(xx, yy);
654 // lyxerr << "P[" << j " " << xx << " " << yy << " " << x << " " << y << "]";
656 pain.lines(xp, yp, n, LColor::mathline);
662 // In the future maybe we use a better fonts renderer
663 void drawStr(Painter & pain, MathTextCodes type, MathMetricsInfo const & siz,
664 int x, int y, string const & s)
666 pain.text(x, y, s, whichFont(type, siz));
670 void drawChar(Painter & pain, MathTextCodes type, MathMetricsInfo const & siz,
671 int x, int y, char c)
674 if (isBinaryOp(c, type))
677 if (isBinaryOp(c, type))
679 drawStr(pain, type, siz, x, y, s);
683 // decrease math size for super- and subscripts
684 void smallerStyleScript(MathMetricsInfo & st)
688 case LM_ST_TEXT: st.style = LM_ST_SCRIPT; break;
689 default: st.style = LM_ST_SCRIPTSCRIPT;
694 // decrease math size for fractions
695 void smallerStyleFrac(MathMetricsInfo & st)
698 case LM_ST_DISPLAY: st.style = LM_ST_TEXT; break;
699 case LM_ST_TEXT: st.style = LM_ST_SCRIPT; break;
700 default: st.style = LM_ST_SCRIPTSCRIPT;
705 void math_font_max_dim(MathTextCodes code, MathMetricsInfo const & siz,
706 int & asc, int & des)
708 LyXFont font = whichFont(code, siz);
709 asc = lyxfont::maxAscent(font);
710 des = lyxfont::maxDescent(font);
714 char const * latex_mathspace[] = {
715 "!", ",", ":", ";", "quad", "qquad"