5 #include "mathed/support.h"
9 #include "math_parser.h"
14 using std::lower_bound;
19 bool MathIsAlphaFont(MathTextCodes x)
21 return LM_TC_VAR <= x && x <= LM_TC_TEXTRM;
25 bool MathIsBinary(MathTextCodes x)
27 return x == LM_TC_BOP;
31 bool MathIsSymbol(MathTextCodes x)
33 return x == LM_TC_SYMB || x == LM_TC_BSYM;
42 typedef float matriz_data[2][2];
48 void escalate(float, float);
50 void transform(float, float, float &, float &);
55 void multiply(matriz_data & a);
66 void Matrix::rotate(int code)
73 float const cs = (code & 1) ? 0 : (1 - code);
74 float const sn = (code & 1) ? (2 - code) : 0;
82 void Matrix::escalate(float x, float y)
92 void Matrix::multiply(matriz_data & a)
95 c[0][0] = a[0][0] * m_[0][0] + a[0][1] * m_[1][0];
96 c[1][0] = a[1][0] * m_[0][0] + a[1][1] * m_[1][0];
97 c[0][1] = a[0][0] * m_[0][1] + a[0][1] * m_[1][1];
98 c[1][1] = a[1][0] * m_[0][1] + a[1][1] * m_[1][1];
105 void Matrix::transform(float xp, float yp, float & x, float & y)
107 x = m_[0][0] * xp + m_[0][1] * yp;
108 y = m_[1][0] * xp + m_[1][1] * yp;
114 LyXFont * Math_Fonts = 0;
116 void mathed_init_fonts()
118 Math_Fonts = new LyXFont[8]; //DEC cxx cannot initialize all fonts
121 for (int i = 0 ; i < 8 ; ++i) {
122 Math_Fonts[i] = LyXFont(LyXFont::ALL_SANE);
125 Math_Fonts[0].setShape(LyXFont::ITALIC_SHAPE);
127 Math_Fonts[1].setFamily(LyXFont::SYMBOL_FAMILY);
129 Math_Fonts[2].setFamily(LyXFont::SYMBOL_FAMILY);
130 Math_Fonts[2].setShape(LyXFont::ITALIC_SHAPE);
132 Math_Fonts[3].setSeries(LyXFont::BOLD_SERIES);
134 Math_Fonts[4].setFamily(LyXFont::SANS_FAMILY);
135 Math_Fonts[4].setShape(LyXFont::ITALIC_SHAPE);
137 Math_Fonts[5].setFamily(LyXFont::TYPEWRITER_FAMILY);
139 Math_Fonts[6].setFamily(LyXFont::ROMAN_FAMILY);
141 Math_Fonts[7].setFamily(LyXFont::SANS_FAMILY);
147 LyXFont WhichFont(MathTextCodes type, MathStyles size)
181 case LM_TC_SPECIAL: //f = Math_Fonts[0]; break;
195 if (type == LM_TC_BSYM) {
209 case LM_ST_SCRIPTSCRIPT:
216 lyxerr << "Math Error: wrong font size: " << size << endl;
220 if (type != LM_TC_TEXTRM)
221 f.setColor(LColor::math);
223 if (type == LM_TC_TEX)
224 f.setColor(LColor::latex);
229 char const * math_font_name[] = {
240 char const * latex_mathspace[] = {
241 "!", ",", ":", ";", "quad", "qquad"
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 float 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 float 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 float 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 // Is this correct? (Lgb)
289 float const arrow[] = {
291 0.0150, 0.7500, 0.2000, 0.6000, 0.3500, 0.3500,
292 0.5000, 0.0500, 0.6500, 0.3500, 0.8000, 0.6000,
294 3, 0.5000, 0.1500, 0.5000, 0.9500,
299 // Is this correct? (Lgb)
300 float 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 float 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 float 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 float const brack[] = {
334 0.95, 0.05, 0.05, 0.05, 0.05, 0.95, 0.95, 0.95,
339 float const corner[] = {
341 0.95, 0.05, 0.05, 0.05, 0.05, 0.95,
346 float const angle[] = {
348 1, 0, 0.05, 0.5, 1, 1,
353 float const slash[] = {
354 1, 0.95, 0.05, 0.05, 0.95,
359 float const hline[] = {
360 1, 0.05, 0.5, 0.95, 0.5,
365 float const hline2[] = {
366 1, 0.1, 0.5, 0.3, 0.5,
367 1, 0.7, 0.5, 0.9, 0.5,
372 float const hline3[] = {
374 1, 0.475, 0, 0.525, 0,
380 float 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 float const hlinesmall[] = {
389 1, 0.4, 0.5, 0.6, 0.5,
394 float const vert[] = {
395 1, 0.5, 0.05, 0.5, 0.95,
400 float const Vert[] = {
401 1, 0.3, 0.05, 0.3, 0.95,
402 1, 0.7, 0.05, 0.7, 0.95,
407 float const tilde[] = {
409 0.05, 0.8, 0.25, 0.2, 0.75, 0.8, 0.95, 0.2,
414 struct math_deco_struct {
420 math_deco_struct math_deco_table[] = {
422 { LM_widehat, &angle[0], 3 },
423 { LM_widetilde, &tilde[0], 0 },
424 { LM_underline, &hline[0], 0 },
425 { LM_overline, &hline[0], 0 },
426 { LM_underbrace, &brace[0], 1 },
427 { LM_overbrace, &brace[0], 3 },
428 { LM_overleftarrow, &arrow[0], 1 },
429 { LM_overightarrow, &arrow[0], 3 },
432 { '(', &parenth[0], 0 },
433 { ')', &parenth[0], 2 },
434 { '{', &brace[0], 0 },
435 { '}', &brace[0], 2 },
436 { '[', &brack[0], 0 },
437 { ']', &brack[0], 2 },
438 { '|', &vert[0], 0 },
439 { '/', &slash[0], 0 },
440 { LM_Vert, &Vert[0], 0 },
441 { LM_backslash, &slash[0], 1 },
442 { LM_langle, &angle[0], 0 },
443 { LM_lceil, &corner[0], 0 },
444 { LM_lfloor, &corner[0], 1 },
445 { LM_rangle, &angle[0], 2 },
446 { LM_rceil, &corner[0], 3 },
447 { LM_rfloor, &corner[0], 2 },
448 { LM_downarrow, &arrow[0], 2 },
449 { LM_Downarrow, &Arrow[0], 2 },
450 { LM_uparrow, &arrow[0], 0 },
451 { LM_Uparrow, &Arrow[0], 0 },
452 { LM_updownarrow, &udarrow[0], 0 },
453 { LM_Updownarrow, &Udarrow[0], 0 },
456 { LM_ddot, &hline2[0], 0 },
457 { LM_hat, &angle[0], 3 },
458 { LM_grave, &slash[0], 1 },
459 { LM_acute, &slash[0], 0 },
460 { LM_tilde, &tilde[0], 0 },
461 { LM_bar, &hline[0], 0 },
462 { LM_dot, &hlinesmall[0], 0 },
463 { LM_check, &angle[0], 1 },
464 { LM_breve, &parenth[0], 1 },
465 { LM_vec, &arrow[0], 3 },
466 { LM_not, &slash[0], 0 },
469 { LM_ldots, &hline3[0], 0 },
470 { LM_cdots, &hline3[0], 0 },
471 { LM_vdots, &hline3[0], 1 },
472 { LM_ddots, &dline3[0], 0 }
476 struct math_deco_compare {
477 /// for use by sort and lower_bound
479 int operator()(math_deco_struct const & a,
480 math_deco_struct const & b) const {
481 return a.code < b.code;
486 int const math_deco_table_size =
487 sizeof(math_deco_table) /sizeof(math_deco_struct);
490 class init_deco_table {
494 sort(math_deco_table,
495 math_deco_table + math_deco_table_size,
496 math_deco_compare());
497 init_deco_table::init = true;
505 bool init_deco_table::init = false;
506 static init_deco_table idt;
510 void mathed_char_dim(MathTextCodes type, MathStyles size, unsigned char c,
511 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);
519 int mathed_char_height(MathTextCodes type, MathStyles size, unsigned char c,
520 int & asc, int & des)
522 LyXFont const font = WhichFont(type, size);
523 des = lyxfont::descent(c, font);
524 asc = lyxfont::ascent(c, font);
529 int mathed_char_height(MathTextCodes type, MathStyles size, unsigned char c)
533 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);
542 int mathed_char_descent(MathTextCodes type, MathStyles size, unsigned char c)
544 LyXFont const font = WhichFont(type, size);
545 return lyxfont::descent(c, font);
550 int mathed_char_width(MathTextCodes type, MathStyles size, unsigned char c)
552 if (MathIsBinary(type)) {
555 return mathed_string_width(type, size, s);
557 return lyxfont::width(c, WhichFont(type, size));
561 void mathed_string_dim(MathTextCodes type, MathStyles size, string const & s,
562 int & asc, int & des, int & wid)
564 mathed_string_height(type, size, s, asc, des);
565 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)
584 if (MathIsBinary(type))
585 for (string::const_iterator it = s.begin();
586 it != s.end(); ++it) {
594 return lyxfont::width(st, WhichFont(type, size));
600 math_deco_struct const * search_deco(int code)
602 math_deco_struct search_elem = { code, 0, 0 };
604 math_deco_struct const * res =
605 lower_bound(math_deco_table,
606 math_deco_table + math_deco_table_size,
607 search_elem, math_deco_compare());
608 if (res != math_deco_table + math_deco_table_size &&
616 void mathed_draw_deco(Painter & pain, int x, int y, int w, int h, int code)
626 math_deco_struct const * mds = search_deco(code);
628 // Should this ever happen?
629 lyxerr << "Deco was not found. Programming error?" << endl;
633 int const r = mds->angle;
634 float const * d = mds->data;
636 if (h > 70 && (mds->code == int('(') || mds->code == int(')')))
642 int const n = (w < h) ? w : h;
645 if (r > 0 && r < 3) y += h;
654 xx = d[i++]; yy = d[i++];
655 x2 = d[i++]; y2 = d[i++];
657 sqmt.transform(xx, yy, xx, yy);
659 mt.transform(xx, yy, xx, yy);
660 mt.transform(x2, y2, x2, y2);
661 pain.line(x + int(xx), y + int(yy),
662 x + int(x2), y + int(y2),
671 int const n = int(d[i++]);
672 for (int j = 0; j < n; ++j) {
673 xx = d[i++]; yy = d[i++];
674 // lyxerr << " " << xx << " " << yy << " ";
676 sqmt.transform(xx, yy, xx, yy);
678 mt.transform(xx, yy, xx, yy);
681 // lyxerr << "P[" << j " " << xx << " " << yy << " " << x << " " << y << "]";
683 pain.lines(xp, yp, n, LColor::mathline);
691 // In a near future maybe we use a better fonts renderer
692 void drawStr(Painter & pain, MathTextCodes type, MathStyles siz,
693 int x, int y, string const & s)
696 if (MathIsBinary(type))
697 for (string::const_iterator it = s.begin();
698 it != s.end(); ++it) {
706 pain.text(x, y, st, WhichFont(type, siz));
709 void drawChar(Painter & pain, MathTextCodes type, MathStyles siz, int x, int y, char c)
713 drawStr(pain, type, siz, x, y, s);
716 // decrease math size for super- and subscripts
717 MathStyles smallerStyleScript(MathStyles st)
721 case LM_ST_TEXT: st = LM_ST_SCRIPT; break;
722 default: st = LM_ST_SCRIPTSCRIPT;
727 // decrease math size for fractions
728 MathStyles smallerStyleFrac(MathStyles st)
731 case LM_ST_DISPLAY: st = LM_ST_TEXT; break;
732 case LM_ST_TEXT: st = LM_ST_SCRIPT; break;
733 default: st = LM_ST_SCRIPTSCRIPT;
739 void math_font_max_dim(MathTextCodes code, MathStyles siz, int & asc, int & des)
741 LyXFont font = WhichFont(code, siz);
742 asc = lyxfont::maxAscent(font);
743 des = lyxfont::maxDescent(font);