5 #include "mathed/support.h"
7 #include "FontLoader.h"
10 #include "math_parser.h"
19 bool isBinaryOp(char c, MathTextCodes type)
21 return type < LM_TC_SYMB && strchr("+-<>=/*", c);
29 Matrix(int, double, double);
31 void transform(double &, double &);
38 Matrix::Matrix(int code, double x, double y)
40 double const cs = (code & 1) ? 0 : (1 - code);
41 double const sn = (code & 1) ? (2 - code) : 0;
49 void Matrix::transform(double & x, double & y)
51 double xx = m_[0][0] * x + m_[0][1] * y;
52 double yy = m_[1][0] * x + m_[1][1] * y;
60 LyXFont * MathFonts = 0;
61 bool font_available[LM_FONT_END];
62 bool font_available_initialized[LM_FONT_END];
83 void mathed_init_fonts()
85 MathFonts = new LyXFont[FONT_NUM]; //DEC cxx cannot initialize all fonts
88 for (int i = 0 ; i < FONT_NUM ; ++i) {
89 MathFonts[i] = LyXFont(LyXFont::ALL_SANE);
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_BB].setSeries(LyXFont::BOLD_SERIES);
102 MathFonts[FONT_BB].setFamily(LyXFont::TYPEWRITER_FAMILY);
104 MathFonts[FONT_CAL].setFamily(LyXFont::SANS_FAMILY);
105 MathFonts[FONT_CAL].setShape(LyXFont::ITALIC_SHAPE);
107 MathFonts[FONT_TT].setFamily(LyXFont::TYPEWRITER_FAMILY);
109 MathFonts[FONT_RM].setFamily(LyXFont::ROMAN_FAMILY);
111 MathFonts[FONT_SF].setFamily(LyXFont::SANS_FAMILY);
113 MathFonts[FONT_CMR].setFamily(LyXFont::CMR_FAMILY);
114 MathFonts[FONT_CMSY].setFamily(LyXFont::CMSY_FAMILY);
115 MathFonts[FONT_CMM].setFamily(LyXFont::CMM_FAMILY);
116 MathFonts[FONT_CMEX].setFamily(LyXFont::CMEX_FAMILY);
117 MathFonts[FONT_MSA].setFamily(LyXFont::MSA_FAMILY);
118 MathFonts[FONT_MSB].setFamily(LyXFont::MSB_FAMILY);
120 for (int i = 0; i < LM_FONT_END; ++i)
121 font_available_initialized[i] = false;
125 LyXFont const & whichFontBase(MathTextCodes type)
133 return MathFonts[FONT_SYMBOLI];
137 return MathFonts[FONT_IT];
140 return MathFonts[FONT_BF];
143 if (math_font_available(LM_TC_MSB))
144 return MathFonts[FONT_MSB];
146 return MathFonts[FONT_BB];
149 if (math_font_available(LM_TC_CMSY))
150 return MathFonts[FONT_CMSY];
152 return MathFonts[FONT_CAL];
155 return MathFonts[FONT_TT];
161 return MathFonts[FONT_RM];
164 return MathFonts[FONT_SF];
167 return MathFonts[FONT_CMR];
170 return MathFonts[FONT_CMSY];
173 return MathFonts[FONT_CMM];
176 return MathFonts[FONT_CMEX];
179 return MathFonts[FONT_MSA];
182 return MathFonts[FONT_MSB];
191 LyXFont whichFont(MathTextCodes type, MathStyles size)
193 LyXFont f = whichFontBase(type);
197 if (type == LM_TC_BOLDSYMB || type == LM_TC_CMEX) {
211 case LM_ST_SCRIPTSCRIPT:
218 lyxerr << "Math Error: wrong font size: " << size << endl;
222 if (type != LM_TC_TEXTRM)
223 f.setColor(LColor::math);
225 if (type == LM_TC_TEX)
226 f.setColor(LColor::latex);
234 bool math_font_available(MathTextCodes type)
236 if (!font_available_initialized[type]) {
237 font_available_initialized[type] = true;
238 font_available[type] =
239 fontloader.available(whichFontBase(type));
241 return font_available[type];
248 * Internal struct of a drawing: code n x1 y1 ... xn yn, where code is:
249 * 0 = end, 1 = line, 2 = polyline, 3 = square line, 4= square polyline
253 double const parenthHigh[] = {
255 0.9840, 0.0014, 0.7143, 0.0323, 0.4603, 0.0772,
256 0.2540, 0.1278, 0.1746, 0.1966, 0.0952, 0.3300,
257 0.0950, 0.5000, 0.0952, 0.6700, 0.1746, 0.8034,
258 0.2540, 0.8722, 0.4603, 0.9228, 0.7143, 0.9677,
264 double const parenth[] = {
266 0.9930, 0.0071, 0.7324, 0.0578, 0.5141, 0.1126,
267 0.3380, 0.1714, 0.2183, 0.2333, 0.0634, 0.3621,
268 0.0141, 0.5000, 0.0563, 0.6369, 0.2113, 0.7647,
269 0.3310, 0.8276, 0.5070, 0.8864, 0.7254, 0.9412,
275 double const brace[] = {
277 0.9492, 0.0020, 0.9379, 0.0020, 0.7458, 0.0243,
278 0.5819, 0.0527, 0.4859, 0.0892, 0.4463, 0.1278,
279 0.4463, 0.3732, 0.4011, 0.4199, 0.2712, 0.4615,
280 0.0734, 0.4919, 0.0113, 0.5000, 0.0734, 0.5081,
281 0.2712, 0.5385, 0.4011, 0.5801, 0.4463, 0.6268,
282 0.4463, 0.8722, 0.4859, 0.9108, 0.5819, 0.9473,
283 0.7458, 0.9757, 0.9379, 0.9980, 0.9492, 0.9980,
288 double const arrow[] = {
290 0.0150, 0.7500, 0.2000, 0.6000, 0.3500, 0.3500,
291 0.5000, 0.0500, 0.6500, 0.3500, 0.8000, 0.6000,
293 3, 0.5000, 0.1500, 0.5000, 0.9500,
298 double const Arrow[] = {
300 0.0150, 0.7500, 0.2000, 0.6000, 0.3500, 0.3500,
301 0.5000, 0.0500, 0.6500, 0.3500, 0.8000, 0.6000,
303 3, 0.3500, 0.5000, 0.3500, 0.9500,
304 3, 0.6500, 0.5000, 0.6500, 0.9500,
309 double const udarrow[] = {
311 0.015, 0.25, 0.5, 0.05, 0.95, 0.25,
313 0.015, 0.75, 0.5, 0.95, 0.95, 0.75,
314 1, 0.5, 0.2, 0.5, 0.8,
319 double const Udarrow[] = {
321 0.015, 0.25, 0.5, 0.05, 0.95, 0.25,
323 0.015, 0.75, 0.5, 0.95, 0.95, 0.75,
324 1, 0.35, 0.2, 0.35, 0.8,
325 1, 0.65, 0.2, 0.65, 0.8,
330 double const brack[] = {
332 0.95, 0.05, 0.05, 0.05, 0.05, 0.95, 0.95, 0.95,
337 double const corner[] = {
339 0.95, 0.05, 0.05, 0.05, 0.05, 0.95,
344 double const angle[] = {
346 1, 0, 0.05, 0.5, 1, 1,
351 double const slash[] = {
352 1, 0.95, 0.05, 0.05, 0.95,
357 double const hline[] = {
358 1, 0.05, 0.5, 0.95, 0.5,
363 double const hline2[] = {
364 1, 0.1, 0.5, 0.3, 0.5,
365 1, 0.7, 0.5, 0.9, 0.5,
370 double const hline3[] = {
372 1, 0.475, 0, 0.525, 0,
378 double const dline3[] = {
379 1, 0.1, 0.1, 0.15, 0.15,
380 1, 0.475, 0.475, 0.525, 0.525,
381 1, 0.85, 0.85, 0.9, 0.9,
386 double const hlinesmall[] = {
387 1, 0.4, 0.5, 0.6, 0.5,
392 double const vert[] = {
393 1, 0.5, 0.05, 0.5, 0.95,
398 double const Vert[] = {
399 1, 0.3, 0.05, 0.3, 0.95,
400 1, 0.7, 0.05, 0.7, 0.95,
405 double const tilde[] = {
407 0.05, 0.8, 0.25, 0.2, 0.75, 0.8, 0.95, 0.2,
417 struct named_deco_struct {
423 named_deco_struct deco_table[] = {
425 {"widehat", angle, 3 },
426 {"widetilde", tilde, 0 },
427 {"underline", hline, 0 },
428 {"overline", hline, 0 },
429 {"underbrace", brace, 1 },
430 {"overbrace", brace, 3 },
431 {"overleftarrow", arrow, 1 },
432 {"overrightarrow", arrow, 3 },
445 {"backslash", slash, 1 },
446 {"langle", angle, 0 },
447 {"lceil", corner, 0 },
448 {"lfloor", corner, 1 },
449 {"rangle", angle, 2 },
450 {"rceil", corner, 3 },
451 {"rfloor", corner, 2 },
452 {"downarrow", arrow, 2 },
453 {"Downarrow", Arrow, 2 },
454 {"uparrow", arrow, 0 },
455 {"Uparrow", Arrow, 0 },
456 {"updownarrow", udarrow, 0 },
457 {"Updownarrow", Udarrow, 0 },
460 {"ddot", hline2, 0 },
462 {"grave", slash, 1 },
463 {"acute", slash, 0 },
464 {"tilde", tilde, 0 },
466 {"dot", hlinesmall, 0 },
467 {"check", angle, 1 },
468 {"breve", parenth, 1 },
473 {"ldots", hline3, 0 },
474 {"cdots", hline3, 0 },
475 {"vdots", hline3, 1 },
476 {"ddots", dline3, 0 }
480 map<string, deco_struct> deco_list;
482 // sort the table on startup
483 struct init_deco_table {
485 unsigned const n = sizeof(deco_table) / sizeof(deco_table[0]);
486 for (named_deco_struct * p = deco_table; p != deco_table + n; ++p) {
490 deco_list[p->name]= d;
495 static init_deco_table dummy;
498 deco_struct const * search_deco(string const & name)
500 map<string, deco_struct>::const_iterator p = deco_list.find(name);
501 return (p == deco_list.end()) ? 0 : &(p->second);
508 void mathed_char_dim(MathTextCodes type, MathStyles size, unsigned char c,
509 int & asc, int & des, int & wid)
511 LyXFont const font = whichFont(type, size);
512 des = lyxfont::descent(c, font);
513 asc = lyxfont::ascent(c, font);
514 wid = mathed_char_width(type, size, c);
518 int mathed_char_height(MathTextCodes type, MathStyles size, unsigned char c,
519 int & asc, int & des)
521 LyXFont const font = whichFont(type, size);
522 des = lyxfont::descent(c, font);
523 asc = lyxfont::ascent(c, font);
528 int mathed_char_height(MathTextCodes type, MathStyles size, unsigned char c)
532 return mathed_char_height(type, size, c, asc, des);
536 int mathed_char_ascent(MathTextCodes type, MathStyles size, unsigned char c)
538 LyXFont const font = whichFont(type, size);
539 return lyxfont::ascent(c, font);
543 int mathed_char_descent(MathTextCodes type, MathStyles size, unsigned char c)
545 LyXFont const font = whichFont(type, size);
546 return lyxfont::descent(c, font);
550 int mathed_char_width(MathTextCodes type, MathStyles size, unsigned char c)
552 LyXFont const font = whichFont(type, size);
553 if (isBinaryOp(c, type))
554 return lyxfont::width(c, font) + 2 * lyxfont::width(' ', font);
556 return lyxfont::width(c, font);
560 void mathed_string_dim(MathTextCodes type, MathStyles size, string const & s,
561 int & asc, int & des, int & wid)
563 mathed_string_height(type, size, s, asc, des);
564 wid = mathed_string_width(type, size, s);
568 int mathed_string_height(MathTextCodes type, MathStyles size, string const & s,
569 int & asc, int & des)
571 LyXFont const font = whichFont(type, size);
573 for (string::const_iterator it = s.begin(); it != s.end(); ++it) {
574 des = max(des, lyxfont::descent(*it, font));
575 asc = max(asc, lyxfont::ascent(*it, font));
581 int mathed_string_width(MathTextCodes type, MathStyles size, string const & s)
583 return lyxfont::width(s, whichFont(type, size));
587 void mathed_draw_deco(Painter & pain, int x, int y, int w, int h,
591 pain.line(x + w/2, y, x + w/2, y + h,
592 LColor::mathcursor, Painter::line_onoffdash);
596 deco_struct const * mds = search_deco(name);
598 lyxerr << "Deco was not found. Programming error?\n";
599 lyxerr << "name: '" << name << "'\n";
603 int const n = (w < h) ? w : h;
604 int const r = mds->angle;
605 double const * d = mds->data;
607 if (h > 70 && (name == "(" || name == ")"))
611 Matrix sqmt(r, n, n);
619 for (int i = 0; d[i]; ) {
620 int code = int(d[i++]);
621 if (code & 1) { // code == 1 || code == 3
627 sqmt.transform(xx, yy);
629 mt.transform(xx, yy);
630 mt.transform(x2, y2);
631 pain.line(x + int(xx), y + int(yy), x + int(x2), y + int(y2),
636 int const n = int(d[i++]);
637 for (int j = 0; j < n; ++j) {
640 // lyxerr << " " << xx << " " << yy << " ";
642 sqmt.transform(xx, yy);
644 mt.transform(xx, yy);
647 // lyxerr << "P[" << j " " << xx << " " << yy << " " << x << " " << y << "]";
649 pain.lines(xp, yp, n, LColor::mathline);
655 // In the future maybe we use a better fonts renderer
656 void drawStr(Painter & pain, MathTextCodes type, MathStyles siz,
657 int x, int y, string const & s)
659 pain.text(x, y, s, whichFont(type, siz));
664 (Painter & pain, MathTextCodes type, MathStyles siz, int x, int y, char c)
667 if (isBinaryOp(c, type))
670 if (isBinaryOp(c, type))
672 drawStr(pain, type, siz, x, y, s);
676 // decrease math size for super- and subscripts
677 MathStyles smallerStyleScript(MathStyles st)
681 case LM_ST_TEXT: st = LM_ST_SCRIPT; break;
682 default: st = LM_ST_SCRIPTSCRIPT;
688 // decrease math size for fractions
689 MathStyles smallerStyleFrac(MathStyles st)
692 case LM_ST_DISPLAY: st = LM_ST_TEXT; break;
693 case LM_ST_TEXT: st = LM_ST_SCRIPT; break;
694 default: st = LM_ST_SCRIPTSCRIPT;
700 void math_font_max_dim(MathTextCodes code, MathStyles siz, int & asc, int & des)
702 LyXFont font = whichFont(code, siz);
703 asc = lyxfont::maxAscent(font);
704 des = lyxfont::maxDescent(font);
708 char const * latex_mathspace[] = {
709 "!", ",", ":", ";", "quad", "qquad"