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 double matriz_data[2][2];
35 void escalate(double, double);
37 void transform(double, double, double &, double &);
42 void multiply(matriz_data & a);
53 void Matrix::rotate(int code)
60 double const cs = (code & 1) ? 0 : (1 - code);
61 double const sn = (code & 1) ? (2 - code) : 0;
69 void Matrix::escalate(double x, double 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(double xp, double yp, double & x, double & 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 double 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 double 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 double 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 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.5000, 0.1500, 0.5000, 0.9500,
340 // Is this correct? (Lgb)
341 double 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 double 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 double 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 double const brack[] = {
375 0.95, 0.05, 0.05, 0.05, 0.05, 0.95, 0.95, 0.95,
380 double const corner[] = {
382 0.95, 0.05, 0.05, 0.05, 0.05, 0.95,
387 double const angle[] = {
389 1, 0, 0.05, 0.5, 1, 1,
394 double const slash[] = {
395 1, 0.95, 0.05, 0.05, 0.95,
400 double const hline[] = {
401 1, 0.05, 0.5, 0.95, 0.5,
406 double const hline2[] = {
407 1, 0.1, 0.5, 0.3, 0.5,
408 1, 0.7, 0.5, 0.9, 0.5,
413 double const hline3[] = {
415 1, 0.475, 0, 0.525, 0,
421 double 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 double const hlinesmall[] = {
430 1, 0.4, 0.5, 0.6, 0.5,
435 double const vert[] = {
436 1, 0.5, 0.05, 0.5, 0.95,
441 double const Vert[] = {
442 1, 0.3, 0.05, 0.3, 0.95,
443 1, 0.7, 0.05, 0.7, 0.95,
448 double 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,
636 pain.line(x + w/2, y, x + w/2, y + h,
637 LColor::mathcursor, Painter::line_onoffdash);
641 deco_struct const * mds = search_deco(name);
643 lyxerr << "Deco was not found. Programming error?\n";
644 lyxerr << "name: '" << name << "'\n";
648 int const r = mds->angle;
649 double const * d = mds->data;
651 if (h > 70 && (name == "(" || name == ")"))
660 int const n = (w < h) ? w : h;
671 for (int i = 0; d[i]; ) {
672 int code = int(d[i++]);
673 if (code & 1) { // code == 1 || code == 3
679 sqmt.transform(xx, yy, xx, yy);
681 mt.transform(xx, yy, xx, yy);
682 mt.transform(x2, y2, x2, y2);
683 pain.line(x + int(xx), y + int(yy),
684 x + int(x2), y + int(y2),
689 int const n = int(d[i++]);
690 for (int j = 0; j < n; ++j) {
693 // lyxerr << " " << xx << " " << yy << " ";
695 sqmt.transform(xx, yy, xx, yy);
697 mt.transform(xx, yy, xx, yy);
700 // lyxerr << "P[" << j " " << xx << " " << yy << " " << x << " " << y << "]";
702 pain.lines(xp, yp, n, LColor::mathline);
708 // In the future maybe we use a better fonts renderer
709 void drawStr(Painter & pain, MathTextCodes type, MathStyles siz,
710 int x, int y, string const & s)
712 pain.text(x, y, s, whichFont(type, siz));
717 (Painter & pain, MathTextCodes type, MathStyles siz, int x, int y, char c)
720 if (isBinaryOp(c, type))
723 if (isBinaryOp(c, type))
725 drawStr(pain, type, siz, x, y, s);
729 // decrease math size for super- and subscripts
730 MathStyles smallerStyleScript(MathStyles st)
734 case LM_ST_TEXT: st = LM_ST_SCRIPT; break;
735 default: st = LM_ST_SCRIPTSCRIPT;
741 // decrease math size for fractions
742 MathStyles smallerStyleFrac(MathStyles st)
745 case LM_ST_DISPLAY: st = LM_ST_TEXT; break;
746 case LM_ST_TEXT: st = LM_ST_SCRIPT; break;
747 default: st = LM_ST_SCRIPTSCRIPT;
753 void math_font_max_dim(MathTextCodes code, MathStyles siz, int & asc, int & des)
755 LyXFont font = whichFont(code, siz);
756 asc = lyxfont::maxAscent(font);
757 des = lyxfont::maxDescent(font);
761 char const * latex_mathspace[] = {
762 "!", ",", ":", ";", "quad", "qquad"