5 #include "mathed/support.h"
9 #include "math_parser.h"
14 using std::lower_bound;
19 bool MathIsInset(MathTextCodes x)
21 return LM_TC_INSET == x;
25 bool MathIsAlphaFont(MathTextCodes x)
27 return LM_TC_VAR <= x && x <= LM_TC_TEXTRM;
31 bool MathIsBinary(MathTextCodes x)
33 return x == LM_TC_BOP;
37 bool MathIsSymbol(MathTextCodes x)
39 return x == LM_TC_SYMB || x == LM_TC_BSYM;
48 typedef float matriz_data[2][2];
54 void escalate(float, float);
56 void transform(float, float, float &, float &);
61 void multiply(matriz_data & a);
72 void Matrix::rotate(int code)
79 float const cs = (code & 1) ? 0 : (1 - code);
80 float const sn = (code & 1) ? (2 - code) : 0;
88 void Matrix::escalate(float x, float y)
98 void Matrix::multiply(matriz_data & a)
101 c[0][0] = a[0][0] * m_[0][0] + a[0][1] * m_[1][0];
102 c[1][0] = a[1][0] * m_[0][0] + a[1][1] * m_[1][0];
103 c[0][1] = a[0][0] * m_[0][1] + a[0][1] * m_[1][1];
104 c[1][1] = a[1][0] * m_[0][1] + a[1][1] * m_[1][1];
111 void Matrix::transform(float xp, float yp, float & x, float & y)
113 x = m_[0][0] * xp + m_[0][1] * yp;
114 y = m_[1][0] * xp + m_[1][1] * yp;
120 LyXFont * Math_Fonts = 0;
122 void mathed_init_fonts()
124 Math_Fonts = new LyXFont[8]; //DEC cxx cannot initialize all fonts
127 for (int i = 0 ; i < 8 ; ++i) {
128 Math_Fonts[i] = LyXFont(LyXFont::ALL_SANE);
131 Math_Fonts[0].setShape(LyXFont::ITALIC_SHAPE);
133 Math_Fonts[1].setFamily(LyXFont::SYMBOL_FAMILY);
135 Math_Fonts[2].setFamily(LyXFont::SYMBOL_FAMILY);
136 Math_Fonts[2].setShape(LyXFont::ITALIC_SHAPE);
138 Math_Fonts[3].setSeries(LyXFont::BOLD_SERIES);
140 Math_Fonts[4].setFamily(LyXFont::SANS_FAMILY);
141 Math_Fonts[4].setShape(LyXFont::ITALIC_SHAPE);
143 Math_Fonts[5].setFamily(LyXFont::TYPEWRITER_FAMILY);
145 Math_Fonts[6].setFamily(LyXFont::ROMAN_FAMILY);
147 Math_Fonts[7].setFamily(LyXFont::SANS_FAMILY);
153 LyXFont WhichFont(MathTextCodes type, MathStyles size)
187 case LM_TC_SPECIAL: //f = Math_Fonts[0]; break;
201 if (type == LM_TC_BSYM) {
215 case LM_ST_SCRIPTSCRIPT:
222 lyxerr << "Math Error: wrong font size: " << size << endl;
226 if (type != LM_TC_TEXTRM)
227 f.setColor(LColor::math);
229 if (type == LM_TC_TEX)
230 f.setColor(LColor::latex);
235 char const * math_font_name[] = {
246 char const * latex_mathspace[] = {
247 "!", ",", ":", ";", "quad", "qquad"
254 * Internal struct of a drawing: code n x1 y1 ... xn yn, where code is:
255 * 0 = end, 1 = line, 2 = polyline, 3 = square line, 4= square polyline
259 float const parenthHigh[] = {
261 0.9840, 0.0014, 0.7143, 0.0323, 0.4603, 0.0772,
262 0.2540, 0.1278, 0.1746, 0.1966, 0.0952, 0.3300,
263 0.0950, 0.5000, 0.0952, 0.6700, 0.1746, 0.8034,
264 0.2540, 0.8722, 0.4603, 0.9228, 0.7143, 0.9677,
270 float const parenth[] = {
272 0.9930, 0.0071, 0.7324, 0.0578, 0.5141, 0.1126,
273 0.3380, 0.1714, 0.2183, 0.2333, 0.0634, 0.3621,
274 0.0141, 0.5000, 0.0563, 0.6369, 0.2113, 0.7647,
275 0.3310, 0.8276, 0.5070, 0.8864, 0.7254, 0.9412,
281 float const brace[] = {
283 0.9492, 0.0020, 0.9379, 0.0020, 0.7458, 0.0243,
284 0.5819, 0.0527, 0.4859, 0.0892, 0.4463, 0.1278,
285 0.4463, 0.3732, 0.4011, 0.4199, 0.2712, 0.4615,
286 0.0734, 0.4919, 0.0113, 0.5000, 0.0734, 0.5081,
287 0.2712, 0.5385, 0.4011, 0.5801, 0.4463, 0.6268,
288 0.4463, 0.8722, 0.4859, 0.9108, 0.5819, 0.9473,
289 0.7458, 0.9757, 0.9379, 0.9980, 0.9492, 0.9980,
294 // Is this correct? (Lgb)
295 float const arrow[] = {
297 0.0150, 0.7500, 0.2000, 0.6000, 0.3500, 0.3500,
298 0.5000, 0.0500, 0.6500, 0.3500, 0.8000, 0.6000,
300 3, 0.5000, 0.1500, 0.5000, 0.9500,
305 // Is this correct? (Lgb)
306 float const Arrow[] = {
308 0.0150, 0.7500, 0.2000, 0.6000, 0.3500, 0.3500,
309 0.5000, 0.0500, 0.6500, 0.3500, 0.8000, 0.6000,
311 3, 0.3500, 0.5000, 0.3500, 0.9500,
312 3, 0.6500, 0.5000, 0.6500, 0.9500,
317 float const udarrow[] = {
319 0.015, 0.25, 0.5, 0.05, 0.95, 0.25,
321 0.015, 0.75, 0.5, 0.95, 0.95, 0.75,
322 1, 0.5, 0.2, 0.5, 0.8,
327 float const Udarrow[] = {
329 0.015, 0.25, 0.5, 0.05, 0.95, 0.25,
331 0.015, 0.75, 0.5, 0.95, 0.95, 0.75,
332 1, 0.35, 0.2, 0.35, 0.8,
333 1, 0.65, 0.2, 0.65, 0.8,
338 float const brack[] = {
340 0.95, 0.05, 0.05, 0.05, 0.05, 0.95, 0.95, 0.95,
345 float const corner[] = {
347 0.95, 0.05, 0.05, 0.05, 0.05, 0.95,
352 float const angle[] = {
354 1, 0, 0.05, 0.5, 1, 1,
359 float const slash[] = {
360 1, 0.95, 0.05, 0.05, 0.95,
365 float const hline[] = {
366 1, 0.05, 0.5, 0.95, 0.5,
371 float const hline2[] = {
372 1, 0.1, 0.5, 0.3, 0.5,
373 1, 0.7, 0.5, 0.9, 0.5,
378 float const hline3[] = {
380 1, 0.475, 0, 0.525, 0,
386 float const dline3[] = {
387 1, 0.1, 0.1, 0.15, 0.15,
388 1, 0.475, 0.475, 0.525, 0.525,
389 1, 0.85, 0.85, 0.9, 0.9,
394 float const hlinesmall[] = {
395 1, 0.4, 0.5, 0.6, 0.5,
400 float const vert[] = {
401 1, 0.5, 0.05, 0.5, 0.95,
406 float const Vert[] = {
407 1, 0.3, 0.05, 0.3, 0.95,
408 1, 0.7, 0.05, 0.7, 0.95,
413 float const tilde[] = {
415 0.05, 0.8, 0.25, 0.2, 0.75, 0.8, 0.95, 0.2,
420 struct math_deco_struct {
426 math_deco_struct math_deco_table[] = {
428 { LM_widehat, &angle[0], 3 },
429 { LM_widetilde, &tilde[0], 0 },
430 { LM_underline, &hline[0], 0 },
431 { LM_overline, &hline[0], 0 },
432 { LM_underbrace, &brace[0], 1 },
433 { LM_overbrace, &brace[0], 3 },
434 { LM_overleftarrow, &arrow[0], 1 },
435 { LM_overightarrow, &arrow[0], 3 },
438 { '(', &parenth[0], 0 },
439 { ')', &parenth[0], 2 },
440 { '{', &brace[0], 0 },
441 { '}', &brace[0], 2 },
442 { '[', &brack[0], 0 },
443 { ']', &brack[0], 2 },
444 { '|', &vert[0], 0 },
445 { '/', &slash[0], 0 },
446 { LM_Vert, &Vert[0], 0 },
447 { LM_backslash, &slash[0], 1 },
448 { LM_langle, &angle[0], 0 },
449 { LM_lceil, &corner[0], 0 },
450 { LM_lfloor, &corner[0], 1 },
451 { LM_rangle, &angle[0], 2 },
452 { LM_rceil, &corner[0], 3 },
453 { LM_rfloor, &corner[0], 2 },
454 { LM_downarrow, &arrow[0], 2 },
455 { LM_Downarrow, &Arrow[0], 2 },
456 { LM_uparrow, &arrow[0], 0 },
457 { LM_Uparrow, &Arrow[0], 0 },
458 { LM_updownarrow, &udarrow[0], 0 },
459 { LM_Updownarrow, &Udarrow[0], 0 },
462 { LM_ddot, &hline2[0], 0 },
463 { LM_hat, &angle[0], 3 },
464 { LM_grave, &slash[0], 1 },
465 { LM_acute, &slash[0], 0 },
466 { LM_tilde, &tilde[0], 0 },
467 { LM_bar, &hline[0], 0 },
468 { LM_dot, &hlinesmall[0], 0 },
469 { LM_check, &angle[0], 1 },
470 { LM_breve, &parenth[0], 1 },
471 { LM_vec, &arrow[0], 3 },
472 { LM_not, &slash[0], 0 },
475 { LM_ldots, &hline3[0], 0 },
476 { LM_cdots, &hline3[0], 0 },
477 { LM_vdots, &hline3[0], 1 },
478 { LM_ddots, &dline3[0], 0 }
482 struct math_deco_compare {
483 /// for use by sort and lower_bound
485 int operator()(math_deco_struct const & a,
486 math_deco_struct const & b) const {
487 return a.code < b.code;
492 int const math_deco_table_size =
493 sizeof(math_deco_table) /sizeof(math_deco_struct);
496 class init_deco_table {
500 sort(math_deco_table,
501 math_deco_table + math_deco_table_size,
502 math_deco_compare());
503 init_deco_table::init = true;
511 bool init_deco_table::init = false;
512 static init_deco_table idt;
516 void mathed_char_dim (MathTextCodes type, MathStyles size, unsigned char c,
517 int & asc, int & des, int & wid)
519 LyXFont const font = WhichFont(type, size);
520 des = lyxfont::descent(c, font);
521 asc = lyxfont::ascent(c, font);
522 wid = mathed_char_width(type, size, c);
525 int mathed_char_height(MathTextCodes type, MathStyles size, unsigned char c,
526 int & asc, int & des)
528 LyXFont const font = WhichFont(type, size);
529 des = lyxfont::descent(c, font);
530 asc = lyxfont::ascent(c, font);
535 int mathed_char_width(MathTextCodes type, MathStyles size, unsigned char c)
537 if (MathIsBinary(type)) {
540 return mathed_string_width(type, size, s);
542 return lyxfont::width(c, WhichFont(type, size));
546 void mathed_string_dim(MathTextCodes type, MathStyles size, string const & s,
547 int & asc, int & des, int & wid)
549 mathed_string_height(type, size, s, asc, des);
550 wid = mathed_string_width(type, size, s);
553 int mathed_string_height(MathTextCodes type, MathStyles size, string const & s,
554 int & asc, int & des)
556 LyXFont const font = WhichFont(type, size);
558 for (string::const_iterator it = s.begin(); it != s.end(); ++it) {
559 des = max(des, lyxfont::descent(*it, font));
560 asc = max(asc, lyxfont::ascent(*it, font));
566 int mathed_string_width(MathTextCodes type, MathStyles size, string const & s)
569 if (MathIsBinary(type))
570 for (string::const_iterator it = s.begin();
571 it != s.end(); ++it) {
579 return lyxfont::width(st, WhichFont(type, size));
585 math_deco_struct const * search_deco(int code)
587 math_deco_struct search_elem = { code, 0, 0 };
589 math_deco_struct const * res =
590 lower_bound(math_deco_table,
591 math_deco_table + math_deco_table_size,
592 search_elem, math_deco_compare());
593 if (res != math_deco_table + math_deco_table_size &&
601 void mathed_draw_deco(Painter & pain, int x, int y, int w, int h, int code)
611 math_deco_struct const * mds = search_deco(code);
613 // Should this ever happen?
614 lyxerr << "Deco was not found. Programming error?" << endl;
618 int const r = mds->angle;
619 float const * d = mds->data;
621 if (h > 70 && (mds->code == int('(') || mds->code == int(')')))
627 int const n = (w < h) ? w : h;
630 if (r > 0 && r < 3) y += h;
639 xx = d[i++]; yy = d[i++];
640 x2 = d[i++]; y2 = d[i++];
642 sqmt.transform(xx, yy, xx, yy);
644 mt.transform(xx, yy, xx, yy);
645 mt.transform(x2, y2, x2, y2);
646 pain.line(x + int(xx), y + int(yy),
647 x + int(x2), y + int(y2),
656 int const n = int(d[i++]);
657 for (int j = 0; j < n; ++j) {
658 xx = d[i++]; yy = d[i++];
659 // lyxerr << " " << xx << " " << yy << " ";
661 sqmt.transform(xx, yy, xx, yy);
663 mt.transform(xx, yy, xx, yy);
666 // lyxerr << "P[" << j " " << xx << " " << yy << " " << x << " " << y << "]";
668 pain.lines(xp, yp, n, LColor::mathline);
676 // In a near future maybe we use a better fonts renderer
677 void drawStr(Painter & pain, MathTextCodes type, MathStyles siz,
678 int x, int y, string const & s)
681 if (MathIsBinary(type))
682 for (string::const_iterator it = s.begin();
683 it != s.end(); ++it) {
691 pain.text(x, y, st, WhichFont(type, siz));
694 void drawChar(Painter & pain, MathTextCodes type, MathStyles siz, int x, int y, char c)
698 drawStr(pain, type, siz, x, y, s);
701 // decrease math size for super- and subscripts
702 MathStyles smallerStyleScript(MathStyles st)
706 case LM_ST_TEXT: st = LM_ST_SCRIPT; break;
707 default: st = LM_ST_SCRIPTSCRIPT;
712 // decrease math size for fractions
713 MathStyles smallerStyleFrac(MathStyles st)
716 case LM_ST_DISPLAY: st = LM_ST_TEXT; break;
717 case LM_ST_TEXT: st = LM_ST_SCRIPT; break;
718 default: st = LM_ST_SCRIPTSCRIPT;
723 bool MathIsRelOp(unsigned char c, MathTextCodes f)
725 if (f == LM_TC_BOP && (c == '=' || c == '<' || c == '>'))
727 #ifndef WITH_WARNINGS
728 #warning implement me properly
730 if (f == LM_TC_SYMB && (c == LM_leq || c == LM_geq))
736 void math_font_max_dim(MathTextCodes code, MathStyles siz, int & asc, int & des)
738 LyXFont font = WhichFont(code, siz);
739 asc = lyxfont::maxAscent(font);
740 des = lyxfont::maxDescent(font);