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 typedef float matriz_data[2][2];
35 void escalate(float, float);
37 void transform(float, float, float &, float &);
42 void multiply(matriz_data & a);
53 void Matrix::rotate(int code)
60 float const cs = (code & 1) ? 0 : (1 - code);
61 float const sn = (code & 1) ? (2 - code) : 0;
69 void Matrix::escalate(float x, float y)
79 void Matrix::multiply(matriz_data & a)
82 c[0][0] = a[0][0] * m_[0][0] + a[0][1] * m_[1][0];
83 c[1][0] = a[1][0] * m_[0][0] + a[1][1] * m_[1][0];
84 c[0][1] = a[0][0] * m_[0][1] + a[0][1] * m_[1][1];
85 c[1][1] = a[1][0] * m_[0][1] + a[1][1] * m_[1][1];
92 void Matrix::transform(float xp, float yp, float & x, float & y)
94 x = m_[0][0] * xp + m_[0][1] * yp;
95 y = m_[1][0] * xp + m_[1][1] * yp;
101 LyXFont * MathFonts = 0;
102 bool font_available[LM_FONT_END];
103 bool font_available_initialized[LM_FONT_END];
124 void mathed_init_fonts()
126 MathFonts = new LyXFont[FONT_NUM]; //DEC cxx cannot initialize all fonts
129 for (int i = 0 ; i < FONT_NUM ; ++i) {
130 MathFonts[i] = LyXFont(LyXFont::ALL_SANE);
133 MathFonts[FONT_IT].setShape(LyXFont::ITALIC_SHAPE);
135 MathFonts[FONT_SYMBOL].setFamily(LyXFont::SYMBOL_FAMILY);
137 MathFonts[FONT_SYMBOLI].setFamily(LyXFont::SYMBOL_FAMILY);
138 MathFonts[FONT_SYMBOLI].setShape(LyXFont::ITALIC_SHAPE);
140 MathFonts[FONT_BF].setSeries(LyXFont::BOLD_SERIES);
142 MathFonts[FONT_BB].setSeries(LyXFont::BOLD_SERIES);
143 MathFonts[FONT_BB].setFamily(LyXFont::TYPEWRITER_FAMILY);
145 MathFonts[FONT_CAL].setFamily(LyXFont::SANS_FAMILY);
146 MathFonts[FONT_CAL].setShape(LyXFont::ITALIC_SHAPE);
148 MathFonts[FONT_TT].setFamily(LyXFont::TYPEWRITER_FAMILY);
150 MathFonts[FONT_RM].setFamily(LyXFont::ROMAN_FAMILY);
152 MathFonts[FONT_SF].setFamily(LyXFont::SANS_FAMILY);
154 MathFonts[FONT_CMR].setFamily(LyXFont::CMR_FAMILY);
155 MathFonts[FONT_CMSY].setFamily(LyXFont::CMSY_FAMILY);
156 MathFonts[FONT_CMM].setFamily(LyXFont::CMM_FAMILY);
157 MathFonts[FONT_CMEX].setFamily(LyXFont::CMEX_FAMILY);
158 MathFonts[FONT_MSA].setFamily(LyXFont::MSA_FAMILY);
159 MathFonts[FONT_MSB].setFamily(LyXFont::MSB_FAMILY);
161 for (int i = 0; i < LM_FONT_END; ++i)
162 font_available_initialized[i] = false;
166 LyXFont const & whichFontBase(MathTextCodes type)
174 return MathFonts[FONT_SYMBOLI];
178 return MathFonts[FONT_IT];
181 return MathFonts[FONT_BF];
184 if (math_font_available(LM_TC_MSB))
185 return MathFonts[FONT_MSB];
187 return MathFonts[FONT_BB];
190 if (math_font_available(LM_TC_CMSY))
191 return MathFonts[FONT_CMSY];
193 return MathFonts[FONT_CAL];
196 return MathFonts[FONT_TT];
202 return MathFonts[FONT_RM];
205 return MathFonts[FONT_SF];
208 return MathFonts[FONT_CMR];
211 return MathFonts[FONT_CMSY];
214 return MathFonts[FONT_CMM];
217 return MathFonts[FONT_CMEX];
220 return MathFonts[FONT_MSA];
223 return MathFonts[FONT_MSB];
232 LyXFont whichFont(MathTextCodes type, MathStyles size)
234 LyXFont f = whichFontBase(type);
238 if (type == LM_TC_BOLDSYMB || type == LM_TC_CMEX) {
252 case LM_ST_SCRIPTSCRIPT:
259 lyxerr << "Math Error: wrong font size: " << size << endl;
263 if (type != LM_TC_TEXTRM)
264 f.setColor(LColor::math);
266 if (type == LM_TC_TEX)
267 f.setColor(LColor::latex);
275 bool math_font_available(MathTextCodes type)
277 if (!font_available_initialized[type]) {
278 font_available_initialized[type] = true;
279 font_available[type] =
280 fontloader.available(whichFontBase(type));
282 return font_available[type];
289 * Internal struct of a drawing: code n x1 y1 ... xn yn, where code is:
290 * 0 = end, 1 = line, 2 = polyline, 3 = square line, 4= square polyline
294 float const parenthHigh[] = {
296 0.9840, 0.0014, 0.7143, 0.0323, 0.4603, 0.0772,
297 0.2540, 0.1278, 0.1746, 0.1966, 0.0952, 0.3300,
298 0.0950, 0.5000, 0.0952, 0.6700, 0.1746, 0.8034,
299 0.2540, 0.8722, 0.4603, 0.9228, 0.7143, 0.9677,
305 float const parenth[] = {
307 0.9930, 0.0071, 0.7324, 0.0578, 0.5141, 0.1126,
308 0.3380, 0.1714, 0.2183, 0.2333, 0.0634, 0.3621,
309 0.0141, 0.5000, 0.0563, 0.6369, 0.2113, 0.7647,
310 0.3310, 0.8276, 0.5070, 0.8864, 0.7254, 0.9412,
316 float const brace[] = {
318 0.9492, 0.0020, 0.9379, 0.0020, 0.7458, 0.0243,
319 0.5819, 0.0527, 0.4859, 0.0892, 0.4463, 0.1278,
320 0.4463, 0.3732, 0.4011, 0.4199, 0.2712, 0.4615,
321 0.0734, 0.4919, 0.0113, 0.5000, 0.0734, 0.5081,
322 0.2712, 0.5385, 0.4011, 0.5801, 0.4463, 0.6268,
323 0.4463, 0.8722, 0.4859, 0.9108, 0.5819, 0.9473,
324 0.7458, 0.9757, 0.9379, 0.9980, 0.9492, 0.9980,
329 // Is this correct? (Lgb)
330 float 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.5000, 0.1500, 0.5000, 0.9500,
340 // Is this correct? (Lgb)
341 float const Arrow[] = {
343 0.0150, 0.7500, 0.2000, 0.6000, 0.3500, 0.3500,
344 0.5000, 0.0500, 0.6500, 0.3500, 0.8000, 0.6000,
346 3, 0.3500, 0.5000, 0.3500, 0.9500,
347 3, 0.6500, 0.5000, 0.6500, 0.9500,
352 float const udarrow[] = {
354 0.015, 0.25, 0.5, 0.05, 0.95, 0.25,
356 0.015, 0.75, 0.5, 0.95, 0.95, 0.75,
357 1, 0.5, 0.2, 0.5, 0.8,
362 float const Udarrow[] = {
364 0.015, 0.25, 0.5, 0.05, 0.95, 0.25,
366 0.015, 0.75, 0.5, 0.95, 0.95, 0.75,
367 1, 0.35, 0.2, 0.35, 0.8,
368 1, 0.65, 0.2, 0.65, 0.8,
373 float const brack[] = {
375 0.95, 0.05, 0.05, 0.05, 0.05, 0.95, 0.95, 0.95,
380 float const corner[] = {
382 0.95, 0.05, 0.05, 0.05, 0.05, 0.95,
387 float const angle[] = {
389 1, 0, 0.05, 0.5, 1, 1,
394 float const slash[] = {
395 1, 0.95, 0.05, 0.05, 0.95,
400 float const hline[] = {
401 1, 0.05, 0.5, 0.95, 0.5,
406 float const hline2[] = {
407 1, 0.1, 0.5, 0.3, 0.5,
408 1, 0.7, 0.5, 0.9, 0.5,
413 float const hline3[] = {
415 1, 0.475, 0, 0.525, 0,
421 float const dline3[] = {
422 1, 0.1, 0.1, 0.15, 0.15,
423 1, 0.475, 0.475, 0.525, 0.525,
424 1, 0.85, 0.85, 0.9, 0.9,
429 float const hlinesmall[] = {
430 1, 0.4, 0.5, 0.6, 0.5,
435 float const vert[] = {
436 1, 0.5, 0.05, 0.5, 0.95,
441 float const Vert[] = {
442 1, 0.3, 0.05, 0.3, 0.95,
443 1, 0.7, 0.05, 0.7, 0.95,
448 float const tilde[] = {
450 0.05, 0.8, 0.25, 0.2, 0.75, 0.8, 0.95, 0.2,
460 struct named_deco_struct {
466 named_deco_struct deco_table[] = {
468 {"widehat", angle, 3 },
469 {"widetilde", tilde, 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 },
488 {"backslash", slash, 1 },
489 {"langle", angle, 0 },
490 {"lceil", corner, 0 },
491 {"lfloor", corner, 1 },
492 {"rangle", angle, 2 },
493 {"rceil", corner, 3 },
494 {"rfloor", corner, 2 },
495 {"downarrow", arrow, 2 },
496 {"Downarrow", Arrow, 2 },
497 {"uparrow", arrow, 0 },
498 {"Uparrow", Arrow, 0 },
499 {"updownarrow", udarrow, 0 },
500 {"Updownarrow", Udarrow, 0 },
503 {"ddot", hline2, 0 },
505 {"grave", slash, 1 },
506 {"acute", slash, 0 },
507 {"tilde", tilde, 0 },
509 {"dot", hlinesmall, 0 },
510 {"check", angle, 1 },
511 {"breve", parenth, 1 },
516 {"ldots", hline3, 0 },
517 {"cdots", hline3, 0 },
518 {"vdots", hline3, 1 },
519 {"ddots", dline3, 0 }
523 map<string, deco_struct> deco_list;
525 // sort the table on startup
526 struct init_deco_table {
528 unsigned const n = sizeof(deco_table) / sizeof(deco_table[0]);
529 for (named_deco_struct * p = deco_table; p != deco_table + n; ++p) {
533 deco_list[p->name]= d;
538 static init_deco_table dummy;
541 deco_struct const * search_deco(string const & name)
543 map<string, deco_struct>::const_iterator p = deco_list.find(name);
544 return (p == deco_list.end()) ? 0 : &(p->second);
551 void mathed_char_dim(MathTextCodes type, MathStyles size, unsigned char c,
552 int & asc, int & des, int & wid)
554 LyXFont const font = whichFont(type, size);
555 des = lyxfont::descent(c, font);
556 asc = lyxfont::ascent(c, font);
557 wid = mathed_char_width(type, size, c);
561 int mathed_char_height(MathTextCodes type, MathStyles size, unsigned char c,
562 int & asc, int & des)
564 LyXFont const font = whichFont(type, size);
565 des = lyxfont::descent(c, font);
566 asc = lyxfont::ascent(c, font);
571 int mathed_char_height(MathTextCodes type, MathStyles size, unsigned char c)
575 return mathed_char_height(type, size, c, asc, des);
579 int mathed_char_ascent(MathTextCodes type, MathStyles size, unsigned char c)
581 LyXFont const font = whichFont(type, size);
582 return lyxfont::ascent(c, font);
586 int mathed_char_descent(MathTextCodes type, MathStyles size, unsigned char c)
588 LyXFont const font = whichFont(type, size);
589 return lyxfont::descent(c, font);
593 int mathed_char_width(MathTextCodes type, MathStyles size, unsigned char c)
595 LyXFont const font = whichFont(type, size);
596 LyXFont const f1 = whichFont(LM_TC_TEXTRM, size);
597 #warning why f1 is used ?
598 if (isBinaryOp(c, type))
599 return lyxfont::width(c, font) + 2 * lyxfont::width(' ', f1);
601 return lyxfont::width(c, font);
605 void mathed_string_dim(MathTextCodes type, MathStyles size, string const & s,
606 int & asc, int & des, int & wid)
608 mathed_string_height(type, size, s, asc, des);
609 wid = mathed_string_width(type, size, s);
613 int mathed_string_height(MathTextCodes type, MathStyles size, string const & s,
614 int & asc, int & des)
616 LyXFont const font = whichFont(type, size);
618 for (string::const_iterator it = s.begin(); it != s.end(); ++it) {
619 des = max(des, lyxfont::descent(*it, font));
620 asc = max(asc, lyxfont::ascent(*it, font));
626 int mathed_string_width(MathTextCodes type, MathStyles size, string const & s)
628 return lyxfont::width(s, whichFont(type, size));
632 void mathed_draw_deco(Painter & pain, int x, int y, int w, int h,
640 pain.line(x + w/2, y, x + w/2, y + h,
641 LColor::mathcursor, Painter::line_onoffdash);
645 deco_struct const * mds = search_deco(name);
647 lyxerr << "Deco was not found. Programming error?\n";
648 lyxerr << "name: '" << name << "'\n";
652 int const r = mds->angle;
653 float const * d = mds->data;
655 if (h > 70 && (name == "(" || name == ")"))
661 int const n = (w < h) ? w : h;
685 xx = d[i++]; yy = d[i++];
686 x2 = d[i++]; y2 = d[i++];
688 sqmt.transform(xx, yy, xx, yy);
690 mt.transform(xx, yy, xx, yy);
691 mt.transform(x2, y2, x2, y2);
692 pain.line(x + int(xx), y + int(yy),
693 x + int(x2), y + int(y2),
702 int const n = int(d[i++]);
703 for (int j = 0; j < n; ++j) {
704 xx = d[i++]; yy = d[i++];
705 // lyxerr << " " << xx << " " << yy << " ";
707 sqmt.transform(xx, yy, xx, yy);
709 mt.transform(xx, yy, xx, yy);
712 // lyxerr << "P[" << j " " << xx << " " << yy << " " << x << " " << y << "]";
714 pain.lines(xp, yp, n, LColor::mathline);
721 // In the future maybe we use a better fonts renderer
722 void drawStr(Painter & pain, MathTextCodes type, MathStyles siz,
723 int x, int y, string const & s)
725 pain.text(x, y, s, whichFont(type, siz));
730 (Painter & pain, MathTextCodes type, MathStyles siz, int x, int y, char c)
733 if (isBinaryOp(c, type))
736 if (isBinaryOp(c, type))
738 drawStr(pain, type, siz, x, y, s);
742 // decrease math size for super- and subscripts
743 MathStyles smallerStyleScript(MathStyles st)
747 case LM_ST_TEXT: st = LM_ST_SCRIPT; break;
748 default: st = LM_ST_SCRIPTSCRIPT;
754 // decrease math size for fractions
755 MathStyles smallerStyleFrac(MathStyles st)
758 case LM_ST_DISPLAY: st = LM_ST_TEXT; break;
759 case LM_ST_TEXT: st = LM_ST_SCRIPT; break;
760 default: st = LM_ST_SCRIPTSCRIPT;
766 void math_font_max_dim(MathTextCodes code, MathStyles siz, int & asc, int & des)
768 LyXFont font = whichFont(code, siz);
769 asc = lyxfont::maxAscent(font);
770 des = lyxfont::maxDescent(font);
774 char const * latex_mathspace[] = {
775 "!", ",", ":", ";", "quad", "qquad"