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 {"overightarrow", arrow, 3 },
488 {"langle", angle, 0 },
489 {"lceil", corner, 0 },
490 {"lfloor", corner, 1 },
491 {"rangle", angle, 2 },
492 {"rceil", corner, 3 },
493 {"rfloor", corner, 2 },
494 {"downarrow", arrow, 2 },
495 {"Downarrow", Arrow, 2 },
496 {"uparrow", arrow, 0 },
497 {"Uparrow", Arrow, 0 },
498 {"updownarrow", udarrow, 0 },
499 {"Updownarrow", Udarrow, 0 },
502 {"ddot", hline2, 0 },
504 {"grave", slash, 1 },
505 {"acute", slash, 0 },
506 {"tilde", tilde, 0 },
508 {"dot", hlinesmall, 0 },
509 {"check", angle, 1 },
510 {"breve", parenth, 1 },
515 {"ldots", hline3, 0 },
516 {"cdots", hline3, 0 },
517 {"vdots", hline3, 1 },
518 {"ddots", dline3, 0 }
522 map<string, deco_struct> deco_list;
524 // sort the table on startup
525 struct init_deco_table {
527 unsigned const n = sizeof(deco_table) / sizeof(deco_table[0]);
528 for (named_deco_struct * p = deco_table; p != deco_table + n; ++p) {
532 deco_list[p->name]= d;
537 static init_deco_table dummy;
540 deco_struct const * search_deco(string const & name)
542 map<string, deco_struct>::const_iterator p = deco_list.find(name);
543 return (p == deco_list.end()) ? 0 : &(p->second);
550 void mathed_char_dim(MathTextCodes type, MathStyles size, unsigned char c,
551 int & asc, int & des, int & wid)
553 LyXFont const font = whichFont(type, size);
554 des = lyxfont::descent(c, font);
555 asc = lyxfont::ascent(c, font);
556 wid = mathed_char_width(type, size, c);
560 int mathed_char_height(MathTextCodes type, MathStyles size, unsigned char c,
561 int & asc, int & des)
563 LyXFont const font = whichFont(type, size);
564 des = lyxfont::descent(c, font);
565 asc = lyxfont::ascent(c, font);
570 int mathed_char_height(MathTextCodes type, MathStyles size, unsigned char c)
574 return mathed_char_height(type, size, c, asc, des);
578 int mathed_char_ascent(MathTextCodes type, MathStyles size, unsigned char c)
580 LyXFont const font = whichFont(type, size);
581 return lyxfont::ascent(c, font);
585 int mathed_char_descent(MathTextCodes type, MathStyles size, unsigned char c)
587 LyXFont const font = whichFont(type, size);
588 return lyxfont::descent(c, font);
592 int mathed_char_width(MathTextCodes type, MathStyles size, unsigned char c)
594 LyXFont const font = whichFont(type, size);
595 LyXFont const f1 = whichFont(LM_TC_TEXTRM, size);
596 #warning why f1 is used ?
597 if (isBinaryOp(c, type))
598 return lyxfont::width(c, font) + 2 * lyxfont::width(' ', f1);
600 return lyxfont::width(c, font);
604 void mathed_string_dim(MathTextCodes type, MathStyles size, string const & s,
605 int & asc, int & des, int & wid)
607 mathed_string_height(type, size, s, asc, des);
608 wid = mathed_string_width(type, size, s);
612 int mathed_string_height(MathTextCodes type, MathStyles size, string const & s,
613 int & asc, int & des)
615 LyXFont const font = whichFont(type, size);
617 for (string::const_iterator it = s.begin(); it != s.end(); ++it) {
618 des = max(des, lyxfont::descent(*it, font));
619 asc = max(asc, lyxfont::ascent(*it, font));
625 int mathed_string_width(MathTextCodes type, MathStyles size, string const & s)
627 return lyxfont::width(s, whichFont(type, size));
631 void mathed_draw_deco(Painter & pain, int x, int y, int w, int h,
639 pain.line(x + w/2, y, x + w/2, y + h,
640 LColor::mathcursor, Painter::line_onoffdash);
644 deco_struct const * mds = search_deco(name);
646 lyxerr << "Deco was not found. Programming error?\n";
647 lyxerr << "name: '" << name << "\n";
651 int const r = mds->angle;
652 float const * d = mds->data;
654 if (h > 70 && (name == "(" || name == ")"))
660 int const n = (w < h) ? w : h;
684 xx = d[i++]; yy = d[i++];
685 x2 = d[i++]; y2 = d[i++];
687 sqmt.transform(xx, yy, xx, yy);
689 mt.transform(xx, yy, xx, yy);
690 mt.transform(x2, y2, x2, y2);
691 pain.line(x + int(xx), y + int(yy),
692 x + int(x2), y + int(y2),
701 int const n = int(d[i++]);
702 for (int j = 0; j < n; ++j) {
703 xx = d[i++]; yy = d[i++];
704 // lyxerr << " " << xx << " " << yy << " ";
706 sqmt.transform(xx, yy, xx, yy);
708 mt.transform(xx, yy, xx, yy);
711 // lyxerr << "P[" << j " " << xx << " " << yy << " " << x << " " << y << "]";
713 pain.lines(xp, yp, n, LColor::mathline);
720 // In the future maybe we use a better fonts renderer
721 void drawStr(Painter & pain, MathTextCodes type, MathStyles siz,
722 int x, int y, string const & s)
724 pain.text(x, y, s, whichFont(type, siz));
729 (Painter & pain, MathTextCodes type, MathStyles siz, int x, int y, char c)
732 if (isBinaryOp(c, type))
735 if (isBinaryOp(c, type))
737 drawStr(pain, type, siz, x, y, s);
741 // decrease math size for super- and subscripts
742 MathStyles smallerStyleScript(MathStyles st)
746 case LM_ST_TEXT: st = LM_ST_SCRIPT; break;
747 default: st = LM_ST_SCRIPTSCRIPT;
753 // decrease math size for fractions
754 MathStyles smallerStyleFrac(MathStyles st)
757 case LM_ST_DISPLAY: st = LM_ST_TEXT; break;
758 case LM_ST_TEXT: st = LM_ST_SCRIPT; break;
759 default: st = LM_ST_SCRIPTSCRIPT;
765 void math_font_max_dim(MathTextCodes code, MathStyles siz, int & asc, int & des)
767 LyXFont font = whichFont(code, siz);
768 asc = lyxfont::maxAscent(font);
769 des = lyxfont::maxDescent(font);
773 char const * latex_mathspace[] = {
774 "!", ",", ":", ";", "quad", "qquad"