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 || x == LM_TC_BOPS;
37 bool MathIsSymbol(MathTextCodes x)
39 return x == LM_TC_SYMB || x == LM_TC_BOPS || 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)
190 case LM_TC_SPECIAL: //f = Math_Fonts[0]; break;
204 if (type == LM_TC_BSYM) {
218 case LM_ST_SCRIPTSCRIPT:
225 lyxerr << "Math Error: wrong font size: " << size << endl;
229 if (type != LM_TC_TEXTRM)
230 f.setColor(LColor::math);
232 if (type == LM_TC_TEX)
233 f.setColor(LColor::latex);
238 char const * math_font_name[] = {
249 char const * latex_mathspace[] = {
250 "!", ",", ":", ";", "quad", "qquad"
257 * Internal struct of a drawing: code n x1 y1 ... xn yn, where code is:
258 * 0 = end, 1 = line, 2 = polyline, 3 = square line, 4= square polyline
262 float const parenthHigh[] = {
264 0.9840, 0.0014, 0.7143, 0.0323, 0.4603, 0.0772,
265 0.2540, 0.1278, 0.1746, 0.1966, 0.0952, 0.3300,
266 0.0950, 0.5000, 0.0952, 0.6700, 0.1746, 0.8034,
267 0.2540, 0.8722, 0.4603, 0.9228, 0.7143, 0.9677,
273 float const parenth[] = {
275 0.9930, 0.0071, 0.7324, 0.0578, 0.5141, 0.1126,
276 0.3380, 0.1714, 0.2183, 0.2333, 0.0634, 0.3621,
277 0.0141, 0.5000, 0.0563, 0.6369, 0.2113, 0.7647,
278 0.3310, 0.8276, 0.5070, 0.8864, 0.7254, 0.9412,
284 float const brace[] = {
286 0.9492, 0.0020, 0.9379, 0.0020, 0.7458, 0.0243,
287 0.5819, 0.0527, 0.4859, 0.0892, 0.4463, 0.1278,
288 0.4463, 0.3732, 0.4011, 0.4199, 0.2712, 0.4615,
289 0.0734, 0.4919, 0.0113, 0.5000, 0.0734, 0.5081,
290 0.2712, 0.5385, 0.4011, 0.5801, 0.4463, 0.6268,
291 0.4463, 0.8722, 0.4859, 0.9108, 0.5819, 0.9473,
292 0.7458, 0.9757, 0.9379, 0.9980, 0.9492, 0.9980,
297 // Is this correct? (Lgb)
298 float const arrow[] = {
300 0.0150, 0.7500, 0.2000, 0.6000, 0.3500, 0.3500,
301 0.5000, 0.0500, 0.6500, 0.3500, 0.8000, 0.6000,
303 3, 0.5000, 0.1500, 0.5000, 0.9500,
308 // Is this correct? (Lgb)
309 float const Arrow[] = {
311 0.0150, 0.7500, 0.2000, 0.6000, 0.3500, 0.3500,
312 0.5000, 0.0500, 0.6500, 0.3500, 0.8000, 0.6000,
314 3, 0.3500, 0.5000, 0.3500, 0.9500,
315 3, 0.6500, 0.5000, 0.6500, 0.9500,
320 float const udarrow[] = {
322 0.015, 0.25, 0.5, 0.05, 0.95, 0.25,
324 0.015, 0.75, 0.5, 0.95, 0.95, 0.75,
325 1, 0.5, 0.2, 0.5, 0.8,
330 float const Udarrow[] = {
332 0.015, 0.25, 0.5, 0.05, 0.95, 0.25,
334 0.015, 0.75, 0.5, 0.95, 0.95, 0.75,
335 1, 0.35, 0.2, 0.35, 0.8,
336 1, 0.65, 0.2, 0.65, 0.8,
341 float const brack[] = {
343 0.95, 0.05, 0.05, 0.05, 0.05, 0.95, 0.95, 0.95,
348 float const corner[] = {
350 0.95, 0.05, 0.05, 0.05, 0.05, 0.95,
355 float const angle[] = {
357 1, 0, 0.05, 0.5, 1, 1,
362 float const slash[] = {
363 1, 0.95, 0.05, 0.05, 0.95,
368 float const hline[] = {
369 1, 0.05, 0.5, 0.95, 0.5,
374 float const hline2[] = {
375 1, 0.1, 0.5, 0.3, 0.5,
376 1, 0.7, 0.5, 0.9, 0.5,
381 float const hline3[] = {
383 1, 0.475, 0, 0.525, 0,
389 float const dline3[] = {
390 1, 0.1, 0.1, 0.15, 0.15,
391 1, 0.475, 0.475, 0.525, 0.525,
392 1, 0.85, 0.85, 0.9, 0.9,
397 float const hlinesmall[] = {
398 1, 0.4, 0.5, 0.6, 0.5,
403 float const vert[] = {
404 1, 0.5, 0.05, 0.5, 0.95,
409 float const Vert[] = {
410 1, 0.3, 0.05, 0.3, 0.95,
411 1, 0.7, 0.05, 0.7, 0.95,
416 float const tilde[] = {
418 0.05, 0.8, 0.25, 0.2, 0.75, 0.8, 0.95, 0.2,
423 struct math_deco_struct {
429 math_deco_struct math_deco_table[] = {
431 { LM_widehat, &angle[0], 3 },
432 { LM_widetilde, &tilde[0], 0 },
433 { LM_underline, &hline[0], 0 },
434 { LM_overline, &hline[0], 0 },
435 { LM_underbrace, &brace[0], 1 },
436 { LM_overbrace, &brace[0], 3 },
437 { LM_overleftarrow, &arrow[0], 1 },
438 { LM_overightarrow, &arrow[0], 3 },
441 { '(', &parenth[0], 0 },
442 { ')', &parenth[0], 2 },
443 { '{', &brace[0], 0 },
444 { '}', &brace[0], 2 },
445 { '[', &brack[0], 0 },
446 { ']', &brack[0], 2 },
447 { '|', &vert[0], 0 },
448 { '/', &slash[0], 0 },
449 { LM_Vert, &Vert[0], 0 },
450 { LM_backslash, &slash[0], 1 },
451 { LM_langle, &angle[0], 0 },
452 { LM_lceil, &corner[0], 0 },
453 { LM_lfloor, &corner[0], 1 },
454 { LM_rangle, &angle[0], 2 },
455 { LM_rceil, &corner[0], 3 },
456 { LM_rfloor, &corner[0], 2 },
457 { LM_downarrow, &arrow[0], 2 },
458 { LM_Downarrow, &Arrow[0], 2 },
459 { LM_uparrow, &arrow[0], 0 },
460 { LM_Uparrow, &Arrow[0], 0 },
461 { LM_updownarrow, &udarrow[0], 0 },
462 { LM_Updownarrow, &Udarrow[0], 0 },
465 { LM_ddot, &hline2[0], 0 },
466 { LM_hat, &angle[0], 3 },
467 { LM_grave, &slash[0], 1 },
468 { LM_acute, &slash[0], 0 },
469 { LM_tilde, &tilde[0], 0 },
470 { LM_bar, &hline[0], 0 },
471 { LM_dot, &hlinesmall[0], 0 },
472 { LM_check, &angle[0], 1 },
473 { LM_breve, &parenth[0], 1 },
474 { LM_vec, &arrow[0], 3 },
475 { LM_not, &slash[0], 0 },
478 { LM_ldots, &hline3[0], 0 },
479 { LM_cdots, &hline3[0], 0 },
480 { LM_vdots, &hline3[0], 1 },
481 { LM_ddots, &dline3[0], 0 }
485 struct math_deco_compare {
486 /// for use by sort and lower_bound
488 int operator()(math_deco_struct const & a,
489 math_deco_struct const & b) const {
490 return a.code < b.code;
495 int const math_deco_table_size =
496 sizeof(math_deco_table) /sizeof(math_deco_struct);
499 class init_deco_table {
503 sort(math_deco_table,
504 math_deco_table + math_deco_table_size,
505 math_deco_compare());
506 init_deco_table::init = true;
514 bool init_deco_table::init = false;
515 static init_deco_table idt;
519 void mathed_char_dim (MathTextCodes type, MathStyles size, unsigned char c,
520 int & asc, int & des, int & wid)
522 LyXFont const font = WhichFont(type, size);
523 des = lyxfont::descent(c, font);
524 asc = lyxfont::ascent(c, font);
525 wid = mathed_char_width(type, size, c);
528 int mathed_char_height(MathTextCodes type, MathStyles size, unsigned char c,
529 int & asc, int & des)
531 LyXFont const font = WhichFont(type, size);
532 des = lyxfont::descent(c, font);
533 asc = lyxfont::ascent(c, font);
538 int mathed_char_width(MathTextCodes type, MathStyles size, unsigned char c)
540 if (MathIsBinary(type)) {
543 return mathed_string_width(type, size, s);
545 return lyxfont::width(c, WhichFont(type, size));
549 void mathed_string_dim(MathTextCodes type, MathStyles size, string const & s,
550 int & asc, int & des, int & wid)
552 mathed_string_height(type, size, s, asc, des);
553 wid = mathed_string_width(type, size, s);
556 int mathed_string_height(MathTextCodes type, MathStyles size, string const & s,
557 int & asc, int & des)
559 LyXFont const font = WhichFont(type, size);
561 for (string::const_iterator it = s.begin(); it != s.end(); ++it) {
562 des = max(des, lyxfont::descent(*it, font));
563 asc = max(asc, lyxfont::ascent(*it, font));
569 int mathed_string_width(MathTextCodes type, MathStyles size, string const & s)
572 if (MathIsBinary(type))
573 for (string::const_iterator it = s.begin();
574 it != s.end(); ++it) {
582 return lyxfont::width(st, WhichFont(type, size));
588 math_deco_struct const * search_deco(int code)
590 math_deco_struct search_elem = { code, 0, 0 };
592 math_deco_struct const * res =
593 lower_bound(math_deco_table,
594 math_deco_table + math_deco_table_size,
595 search_elem, math_deco_compare());
596 if (res != math_deco_table + math_deco_table_size &&
604 void mathed_draw_deco(Painter & pain, int x, int y, int w, int h, int code)
614 math_deco_struct const * mds = search_deco(code);
616 // Should this ever happen?
617 lyxerr << "Deco was not found. Programming error?" << endl;
621 int const r = mds->angle;
622 float const * d = mds->data;
624 if (h > 70 && (mds->code == int('(') || mds->code == int(')')))
630 int const n = (w < h) ? w : h;
633 if (r > 0 && r < 3) y += h;
642 xx = d[i++]; yy = d[i++];
643 x2 = d[i++]; y2 = d[i++];
645 sqmt.transform(xx, yy, xx, yy);
647 mt.transform(xx, yy, xx, yy);
648 mt.transform(x2, y2, x2, y2);
649 pain.line(x + int(xx), y + int(yy),
650 x + int(x2), y + int(y2),
659 int const n = int(d[i++]);
660 for (int j = 0; j < n; ++j) {
661 xx = d[i++]; yy = d[i++];
662 // lyxerr << " " << xx << " " << yy << " ";
664 sqmt.transform(xx, yy, xx, yy);
666 mt.transform(xx, yy, xx, yy);
669 // lyxerr << "P[" << j " " << xx << " " << yy << " " << x << " " << y << "]";
671 pain.lines(xp, yp, n, LColor::mathline);
679 // In a near future maybe we use a better fonts renderer
680 void drawStr(Painter & pain, MathTextCodes type, MathStyles siz,
681 int x, int y, string const & s)
684 if (MathIsBinary(type))
685 for (string::const_iterator it = s.begin();
686 it != s.end(); ++it) {
694 pain.text(x, y, st, WhichFont(type, siz));
697 void drawChar(Painter & pain, MathTextCodes type, MathStyles siz, int x, int y, char c)
701 drawStr(pain, type, siz, x, y, s);
704 // decrease math size for super- and subscripts
705 MathStyles smallerStyleScript(MathStyles st)
709 case LM_ST_TEXT: st = LM_ST_SCRIPT; break;
710 default: st = LM_ST_SCRIPTSCRIPT;
715 // decrease math size for fractions
716 MathStyles smallerStyleFrac(MathStyles st)
719 case LM_ST_DISPLAY: st = LM_ST_TEXT; break;
720 case LM_ST_TEXT: st = LM_ST_SCRIPT; break;
721 default: st = LM_ST_SCRIPTSCRIPT;
726 bool MathIsRelOp(unsigned char c, MathTextCodes f)
728 if (f == LM_TC_BOP && (c == '=' || c == '<' || c == '>'))
730 #ifndef WITH_WARNINGS
731 #warning implement me properly
733 if (f == LM_TC_SYMB && (c == LM_leq || c == LM_geq))
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);