5 #include "mathed/support.h"
7 #include "FontLoader.h"
10 #include "math_parser.h"
15 using std::lower_bound;
20 bool isBinaryOp(char c, MathTextCodes type)
22 return type < LM_TC_SYMB && strchr("+-<>=/*", c);
30 typedef float matriz_data[2][2];
36 void escalate(float, float);
38 void transform(float, float, float &, float &);
43 void multiply(matriz_data & a);
54 void Matrix::rotate(int code)
61 float const cs = (code & 1) ? 0 : (1 - code);
62 float const sn = (code & 1) ? (2 - code) : 0;
70 void Matrix::escalate(float x, float y)
80 void Matrix::multiply(matriz_data & a)
83 c[0][0] = a[0][0] * m_[0][0] + a[0][1] * m_[1][0];
84 c[1][0] = a[1][0] * m_[0][0] + a[1][1] * m_[1][0];
85 c[0][1] = a[0][0] * m_[0][1] + a[0][1] * m_[1][1];
86 c[1][1] = a[1][0] * m_[0][1] + a[1][1] * m_[1][1];
93 void Matrix::transform(float xp, float yp, float & x, float & y)
95 x = m_[0][0] * xp + m_[0][1] * yp;
96 y = m_[1][0] * xp + m_[1][1] * yp;
102 LyXFont * MathFonts = 0;
103 bool font_available[LM_FONT_END];
104 bool font_available_initialized[LM_FONT_END];
106 void mathed_init_fonts()
108 MathFonts = new LyXFont[13]; //DEC cxx cannot initialize all fonts
111 for (int i = 0 ; i < 13 ; ++i) {
112 MathFonts[i] = LyXFont(LyXFont::ALL_SANE);
115 MathFonts[0].setShape(LyXFont::ITALIC_SHAPE);
117 MathFonts[1].setFamily(LyXFont::SYMBOL_FAMILY);
119 MathFonts[2].setFamily(LyXFont::SYMBOL_FAMILY);
120 MathFonts[2].setShape(LyXFont::ITALIC_SHAPE);
122 MathFonts[3].setSeries(LyXFont::BOLD_SERIES);
124 MathFonts[4].setFamily(LyXFont::SANS_FAMILY);
125 MathFonts[4].setShape(LyXFont::ITALIC_SHAPE);
127 MathFonts[5].setFamily(LyXFont::TYPEWRITER_FAMILY);
129 MathFonts[6].setFamily(LyXFont::ROMAN_FAMILY);
131 MathFonts[7].setFamily(LyXFont::SANS_FAMILY);
133 MathFonts[8].setFamily(LyXFont::CMSY_FAMILY);
134 MathFonts[9].setFamily(LyXFont::CMM_FAMILY);
135 MathFonts[10].setFamily(LyXFont::CMEX_FAMILY);
136 MathFonts[11].setFamily(LyXFont::MSA_FAMILY);
137 MathFonts[12].setFamily(LyXFont::MSB_FAMILY);
139 for (int i = 0; i < LM_FONT_END; ++i)
140 font_available_initialized[i] = false;
144 LyXFont const & whichFontBase(MathTextCodes type)
183 return MathFonts[10];
186 return MathFonts[11];
189 return MathFonts[12];
198 LyXFont whichFont(MathTextCodes type, MathStyles size)
200 LyXFont f = whichFontBase(type);
204 if (type == LM_TC_BSYM || type == LM_TC_CMEX) {
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);
241 bool math_font_available(MathTextCodes type)
243 if (!font_available_initialized[type]) {
244 font_available_initialized[type] = true;
245 font_available[type] =
246 fontloader.available(whichFontBase(type));
248 return font_available[type];
255 * Internal struct of a drawing: code n x1 y1 ... xn yn, where code is:
256 * 0 = end, 1 = line, 2 = polyline, 3 = square line, 4= square polyline
260 float const parenthHigh[] = {
262 0.9840, 0.0014, 0.7143, 0.0323, 0.4603, 0.0772,
263 0.2540, 0.1278, 0.1746, 0.1966, 0.0952, 0.3300,
264 0.0950, 0.5000, 0.0952, 0.6700, 0.1746, 0.8034,
265 0.2540, 0.8722, 0.4603, 0.9228, 0.7143, 0.9677,
271 float const parenth[] = {
273 0.9930, 0.0071, 0.7324, 0.0578, 0.5141, 0.1126,
274 0.3380, 0.1714, 0.2183, 0.2333, 0.0634, 0.3621,
275 0.0141, 0.5000, 0.0563, 0.6369, 0.2113, 0.7647,
276 0.3310, 0.8276, 0.5070, 0.8864, 0.7254, 0.9412,
282 float const brace[] = {
284 0.9492, 0.0020, 0.9379, 0.0020, 0.7458, 0.0243,
285 0.5819, 0.0527, 0.4859, 0.0892, 0.4463, 0.1278,
286 0.4463, 0.3732, 0.4011, 0.4199, 0.2712, 0.4615,
287 0.0734, 0.4919, 0.0113, 0.5000, 0.0734, 0.5081,
288 0.2712, 0.5385, 0.4011, 0.5801, 0.4463, 0.6268,
289 0.4463, 0.8722, 0.4859, 0.9108, 0.5819, 0.9473,
290 0.7458, 0.9757, 0.9379, 0.9980, 0.9492, 0.9980,
295 // Is this correct? (Lgb)
296 float const arrow[] = {
298 0.0150, 0.7500, 0.2000, 0.6000, 0.3500, 0.3500,
299 0.5000, 0.0500, 0.6500, 0.3500, 0.8000, 0.6000,
301 3, 0.5000, 0.1500, 0.5000, 0.9500,
306 // Is this correct? (Lgb)
307 float const Arrow[] = {
309 0.0150, 0.7500, 0.2000, 0.6000, 0.3500, 0.3500,
310 0.5000, 0.0500, 0.6500, 0.3500, 0.8000, 0.6000,
312 3, 0.3500, 0.5000, 0.3500, 0.9500,
313 3, 0.6500, 0.5000, 0.6500, 0.9500,
318 float const udarrow[] = {
320 0.015, 0.25, 0.5, 0.05, 0.95, 0.25,
322 0.015, 0.75, 0.5, 0.95, 0.95, 0.75,
323 1, 0.5, 0.2, 0.5, 0.8,
328 float const Udarrow[] = {
330 0.015, 0.25, 0.5, 0.05, 0.95, 0.25,
332 0.015, 0.75, 0.5, 0.95, 0.95, 0.75,
333 1, 0.35, 0.2, 0.35, 0.8,
334 1, 0.65, 0.2, 0.65, 0.8,
339 float const brack[] = {
341 0.95, 0.05, 0.05, 0.05, 0.05, 0.95, 0.95, 0.95,
346 float const corner[] = {
348 0.95, 0.05, 0.05, 0.05, 0.05, 0.95,
353 float const angle[] = {
355 1, 0, 0.05, 0.5, 1, 1,
360 float const slash[] = {
361 1, 0.95, 0.05, 0.05, 0.95,
366 float const hline[] = {
367 1, 0.05, 0.5, 0.95, 0.5,
372 float const hline2[] = {
373 1, 0.1, 0.5, 0.3, 0.5,
374 1, 0.7, 0.5, 0.9, 0.5,
379 float const hline3[] = {
381 1, 0.475, 0, 0.525, 0,
387 float const dline3[] = {
388 1, 0.1, 0.1, 0.15, 0.15,
389 1, 0.475, 0.475, 0.525, 0.525,
390 1, 0.85, 0.85, 0.9, 0.9,
395 float const hlinesmall[] = {
396 1, 0.4, 0.5, 0.6, 0.5,
401 float const vert[] = {
402 1, 0.5, 0.05, 0.5, 0.95,
407 float const Vert[] = {
408 1, 0.3, 0.05, 0.3, 0.95,
409 1, 0.7, 0.05, 0.7, 0.95,
414 float const tilde[] = {
416 0.05, 0.8, 0.25, 0.2, 0.75, 0.8, 0.95, 0.2,
427 deco_struct deco_table[] = {
429 { LM_widehat, &angle[0], 3 },
430 { LM_widetilde, &tilde[0], 0 },
431 { LM_underline, &hline[0], 0 },
432 { LM_overline, &hline[0], 0 },
433 { LM_underbrace, &brace[0], 1 },
434 { LM_overbrace, &brace[0], 3 },
435 { LM_overleftarrow, &arrow[0], 1 },
436 { LM_overightarrow, &arrow[0], 3 },
439 { '(', &parenth[0], 0 },
440 { ')', &parenth[0], 2 },
441 { '{', &brace[0], 0 },
442 { '}', &brace[0], 2 },
443 { '[', &brack[0], 0 },
444 { ']', &brack[0], 2 },
445 { '|', &vert[0], 0 },
446 { '/', &slash[0], 0 },
447 { LM_Vert, &Vert[0], 0 },
448 { '\\', &slash[0], 1 },
449 { LM_langle, &angle[0], 0 },
450 { LM_lceil, &corner[0], 0 },
451 { LM_lfloor, &corner[0], 1 },
452 { LM_rangle, &angle[0], 2 },
453 { LM_rceil, &corner[0], 3 },
454 { LM_rfloor, &corner[0], 2 },
455 { LM_downarrow, &arrow[0], 2 },
456 { LM_Downarrow, &Arrow[0], 2 },
457 { LM_uparrow, &arrow[0], 0 },
458 { LM_Uparrow, &Arrow[0], 0 },
459 { LM_updownarrow, &udarrow[0], 0 },
460 { LM_Updownarrow, &Udarrow[0], 0 },
463 { LM_ddot, &hline2[0], 0 },
464 { LM_hat, &angle[0], 3 },
465 { LM_grave, &slash[0], 1 },
466 { LM_acute, &slash[0], 0 },
467 { LM_tilde, &tilde[0], 0 },
468 { LM_bar, &hline[0], 0 },
469 { LM_dot, &hlinesmall[0], 0 },
470 { LM_check, &angle[0], 1 },
471 { LM_breve, &parenth[0], 1 },
472 { LM_vec, &arrow[0], 3 },
473 { LM_not, &slash[0], 0 },
476 { LM_ldots, &hline3[0], 0 },
477 { LM_cdots, &hline3[0], 0 },
478 { LM_vdots, &hline3[0], 1 },
479 { LM_ddots, &dline3[0], 0 }
483 struct deco_compare {
484 /// for use by sort and lower_bound
485 int operator()(deco_struct const & a, deco_struct const & b) const
487 return a.code < b.code;
492 int const deco_table_size =
493 sizeof(deco_table) / sizeof(deco_struct);
496 // sort the table on startup
497 struct init_deco_table {
499 std::sort(deco_table,
500 deco_table + deco_table_size,
505 static init_deco_table dummy;
508 deco_struct const * search_deco(int code)
510 const deco_struct search_elem = { code, 0, 0 };
512 deco_struct const * res =
513 lower_bound(deco_table, deco_table + deco_table_size, search_elem,
515 if (res != deco_table + deco_table_size &&
525 void mathed_char_dim(MathTextCodes type, MathStyles size, unsigned char c,
526 int & asc, int & des, int & wid)
528 LyXFont const font = whichFont(type, size);
529 des = lyxfont::descent(c, font);
530 asc = lyxfont::ascent(c, font);
531 wid = mathed_char_width(type, size, c);
535 int mathed_char_height(MathTextCodes type, MathStyles size, unsigned char c,
536 int & asc, int & des)
538 LyXFont const font = whichFont(type, size);
539 des = lyxfont::descent(c, font);
540 asc = lyxfont::ascent(c, font);
545 int mathed_char_height(MathTextCodes type, MathStyles size, unsigned char c)
549 return mathed_char_height(type, size, c, asc, des);
553 int mathed_char_ascent(MathTextCodes type, MathStyles size, unsigned char c)
555 LyXFont const font = whichFont(type, size);
556 return lyxfont::ascent(c, font);
560 int mathed_char_descent(MathTextCodes type, MathStyles size, unsigned char c)
562 LyXFont const font = whichFont(type, size);
563 return lyxfont::descent(c, font);
567 int mathed_char_width(MathTextCodes type, MathStyles size, unsigned char c)
569 LyXFont const font = whichFont(type, size);
570 LyXFont const f1 = whichFont(LM_TC_TEXTRM, size);
571 #warning why f1 is used ?
572 if (isBinaryOp(c, type))
573 return lyxfont::width(c, font) + 2 * lyxfont::width(' ', f1);
575 return lyxfont::width(c, font);
579 void mathed_string_dim(MathTextCodes type, MathStyles size, string const & s,
580 int & asc, int & des, int & wid)
582 mathed_string_height(type, size, s, asc, des);
583 wid = mathed_string_width(type, size, s);
587 int mathed_string_height(MathTextCodes type, MathStyles size, string const & s,
588 int & asc, int & des)
590 LyXFont const font = whichFont(type, size);
592 for (string::const_iterator it = s.begin(); it != s.end(); ++it) {
593 des = max(des, lyxfont::descent(*it, font));
594 asc = max(asc, lyxfont::ascent(*it, font));
600 int mathed_string_width(MathTextCodes type, MathStyles size, string const & s)
602 return lyxfont::width(s, whichFont(type, size));
606 void mathed_draw_deco(Painter & pain, int x, int y, int w, int h,
612 string const & name = l->name;
613 int code = (name.size() > 1) ? l->id : name[0];
616 pain.line(x + w/2, y, x + w/2, y + h,
617 LColor::mathcursor, Painter::line_onoffdash);
621 deco_struct const * mds = search_deco(code);
623 lyxerr << "Deco was not found. Programming error?\n";
624 lyxerr << "name: '" << name << "', code: " << code << "\n";
628 int const r = mds->angle;
629 float const * d = mds->data;
631 if (h > 70 && (mds->code == int('(') || mds->code == int(')')))
637 int const n = (w < h) ? w : h;
660 xx = d[i++]; yy = d[i++];
661 x2 = d[i++]; y2 = d[i++];
663 sqmt.transform(xx, yy, xx, yy);
665 mt.transform(xx, yy, xx, yy);
666 mt.transform(x2, y2, x2, y2);
667 pain.line(x + int(xx), y + int(yy),
668 x + int(x2), y + int(y2),
677 int const n = int(d[i++]);
678 for (int j = 0; j < n; ++j) {
679 xx = d[i++]; yy = d[i++];
680 // lyxerr << " " << xx << " " << yy << " ";
682 sqmt.transform(xx, yy, xx, yy);
684 mt.transform(xx, yy, xx, yy);
687 // lyxerr << "P[" << j " " << xx << " " << yy << " " << x << " " << y << "]";
689 pain.lines(xp, yp, n, LColor::mathline);
696 // In the future maybe we use a better fonts renderer
697 void drawStr(Painter & pain, MathTextCodes type, MathStyles siz,
698 int x, int y, string const & s)
700 pain.text(x, y, s, whichFont(type, siz));
705 (Painter & pain, MathTextCodes type, MathStyles siz, int x, int y, char c)
708 if (isBinaryOp(c, type))
711 if (isBinaryOp(c, type))
713 drawStr(pain, type, siz, x, y, s);
717 // decrease math size for super- and subscripts
718 MathStyles smallerStyleScript(MathStyles st)
722 case LM_ST_TEXT: st = LM_ST_SCRIPT; break;
723 default: st = LM_ST_SCRIPTSCRIPT;
729 // decrease math size for fractions
730 MathStyles smallerStyleFrac(MathStyles st)
733 case LM_ST_DISPLAY: st = LM_ST_TEXT; break;
734 case LM_ST_TEXT: st = LM_ST_SCRIPT; break;
735 default: st = LM_ST_SCRIPTSCRIPT;
741 void math_font_max_dim(MathTextCodes code, MathStyles siz, int & asc, int & des)
743 LyXFont font = whichFont(code, siz);
744 asc = lyxfont::maxAscent(font);
745 des = lyxfont::maxDescent(font);
749 char const * latex_mathspace[] = {
750 "!", ",", ":", ";", "quad", "qquad"