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];
125 void mathed_init_fonts()
127 MathFonts = new LyXFont[FONT_NUM]; //DEC cxx cannot initialize all fonts
130 for (int i = 0 ; i < FONT_NUM ; ++i) {
131 MathFonts[i] = LyXFont(LyXFont::ALL_SANE);
134 MathFonts[FONT_IT].setShape(LyXFont::ITALIC_SHAPE);
136 MathFonts[FONT_SYMBOL].setFamily(LyXFont::SYMBOL_FAMILY);
138 MathFonts[FONT_SYMBOLI].setFamily(LyXFont::SYMBOL_FAMILY);
139 MathFonts[FONT_SYMBOLI].setShape(LyXFont::ITALIC_SHAPE);
141 MathFonts[FONT_BF].setSeries(LyXFont::BOLD_SERIES);
143 MathFonts[FONT_BB].setSeries(LyXFont::BOLD_SERIES);
144 MathFonts[FONT_BB].setFamily(LyXFont::TYPEWRITER_FAMILY);
146 MathFonts[FONT_CAL].setFamily(LyXFont::SANS_FAMILY);
147 MathFonts[FONT_CAL].setShape(LyXFont::ITALIC_SHAPE);
149 MathFonts[FONT_TT].setFamily(LyXFont::TYPEWRITER_FAMILY);
151 MathFonts[FONT_RM].setFamily(LyXFont::ROMAN_FAMILY);
153 MathFonts[FONT_SF].setFamily(LyXFont::SANS_FAMILY);
155 MathFonts[FONT_CMR].setFamily(LyXFont::CMR_FAMILY);
156 MathFonts[FONT_CMSY].setFamily(LyXFont::CMSY_FAMILY);
157 MathFonts[FONT_CMM].setFamily(LyXFont::CMM_FAMILY);
158 MathFonts[FONT_CMEX].setFamily(LyXFont::CMEX_FAMILY);
159 MathFonts[FONT_MSA].setFamily(LyXFont::MSA_FAMILY);
160 MathFonts[FONT_MSB].setFamily(LyXFont::MSB_FAMILY);
162 for (int i = 0; i < LM_FONT_END; ++i)
163 font_available_initialized[i] = false;
167 LyXFont const & whichFontBase(MathTextCodes type)
175 return MathFonts[FONT_SYMBOLI];
179 return MathFonts[FONT_IT];
182 return MathFonts[FONT_BF];
185 if (math_font_available(LM_TC_MSB))
186 return MathFonts[FONT_MSB];
188 return MathFonts[FONT_BB];
191 if (math_font_available(LM_TC_CMSY))
192 return MathFonts[FONT_CMSY];
194 return MathFonts[FONT_CAL];
197 return MathFonts[FONT_TT];
203 return MathFonts[FONT_RM];
206 return MathFonts[FONT_SF];
209 return MathFonts[FONT_CMR];
212 return MathFonts[FONT_CMSY];
215 return MathFonts[FONT_CMM];
218 return MathFonts[FONT_CMEX];
221 return MathFonts[FONT_MSA];
224 return MathFonts[FONT_MSB];
233 LyXFont whichFont(MathTextCodes type, MathStyles size)
235 LyXFont f = whichFontBase(type);
239 if (type == LM_TC_BOLDSYMB || type == LM_TC_CMEX) {
253 case LM_ST_SCRIPTSCRIPT:
260 lyxerr << "Math Error: wrong font size: " << size << endl;
264 if (type != LM_TC_TEXTRM)
265 f.setColor(LColor::math);
267 if (type == LM_TC_TEX)
268 f.setColor(LColor::latex);
276 bool math_font_available(MathTextCodes type)
278 if (!font_available_initialized[type]) {
279 font_available_initialized[type] = true;
280 font_available[type] =
281 fontloader.available(whichFontBase(type));
283 return font_available[type];
290 * Internal struct of a drawing: code n x1 y1 ... xn yn, where code is:
291 * 0 = end, 1 = line, 2 = polyline, 3 = square line, 4= square polyline
295 float const parenthHigh[] = {
297 0.9840, 0.0014, 0.7143, 0.0323, 0.4603, 0.0772,
298 0.2540, 0.1278, 0.1746, 0.1966, 0.0952, 0.3300,
299 0.0950, 0.5000, 0.0952, 0.6700, 0.1746, 0.8034,
300 0.2540, 0.8722, 0.4603, 0.9228, 0.7143, 0.9677,
306 float const parenth[] = {
308 0.9930, 0.0071, 0.7324, 0.0578, 0.5141, 0.1126,
309 0.3380, 0.1714, 0.2183, 0.2333, 0.0634, 0.3621,
310 0.0141, 0.5000, 0.0563, 0.6369, 0.2113, 0.7647,
311 0.3310, 0.8276, 0.5070, 0.8864, 0.7254, 0.9412,
317 float const brace[] = {
319 0.9492, 0.0020, 0.9379, 0.0020, 0.7458, 0.0243,
320 0.5819, 0.0527, 0.4859, 0.0892, 0.4463, 0.1278,
321 0.4463, 0.3732, 0.4011, 0.4199, 0.2712, 0.4615,
322 0.0734, 0.4919, 0.0113, 0.5000, 0.0734, 0.5081,
323 0.2712, 0.5385, 0.4011, 0.5801, 0.4463, 0.6268,
324 0.4463, 0.8722, 0.4859, 0.9108, 0.5819, 0.9473,
325 0.7458, 0.9757, 0.9379, 0.9980, 0.9492, 0.9980,
330 // Is this correct? (Lgb)
331 float const arrow[] = {
333 0.0150, 0.7500, 0.2000, 0.6000, 0.3500, 0.3500,
334 0.5000, 0.0500, 0.6500, 0.3500, 0.8000, 0.6000,
336 3, 0.5000, 0.1500, 0.5000, 0.9500,
341 // Is this correct? (Lgb)
342 float const Arrow[] = {
344 0.0150, 0.7500, 0.2000, 0.6000, 0.3500, 0.3500,
345 0.5000, 0.0500, 0.6500, 0.3500, 0.8000, 0.6000,
347 3, 0.3500, 0.5000, 0.3500, 0.9500,
348 3, 0.6500, 0.5000, 0.6500, 0.9500,
353 float const udarrow[] = {
355 0.015, 0.25, 0.5, 0.05, 0.95, 0.25,
357 0.015, 0.75, 0.5, 0.95, 0.95, 0.75,
358 1, 0.5, 0.2, 0.5, 0.8,
363 float const Udarrow[] = {
365 0.015, 0.25, 0.5, 0.05, 0.95, 0.25,
367 0.015, 0.75, 0.5, 0.95, 0.95, 0.75,
368 1, 0.35, 0.2, 0.35, 0.8,
369 1, 0.65, 0.2, 0.65, 0.8,
374 float const brack[] = {
376 0.95, 0.05, 0.05, 0.05, 0.05, 0.95, 0.95, 0.95,
381 float const corner[] = {
383 0.95, 0.05, 0.05, 0.05, 0.05, 0.95,
388 float const angle[] = {
390 1, 0, 0.05, 0.5, 1, 1,
395 float const slash[] = {
396 1, 0.95, 0.05, 0.05, 0.95,
401 float const hline[] = {
402 1, 0.05, 0.5, 0.95, 0.5,
407 float const hline2[] = {
408 1, 0.1, 0.5, 0.3, 0.5,
409 1, 0.7, 0.5, 0.9, 0.5,
414 float const hline3[] = {
416 1, 0.475, 0, 0.525, 0,
422 float const dline3[] = {
423 1, 0.1, 0.1, 0.15, 0.15,
424 1, 0.475, 0.475, 0.525, 0.525,
425 1, 0.85, 0.85, 0.9, 0.9,
430 float const hlinesmall[] = {
431 1, 0.4, 0.5, 0.6, 0.5,
436 float const vert[] = {
437 1, 0.5, 0.05, 0.5, 0.95,
442 float const Vert[] = {
443 1, 0.3, 0.05, 0.3, 0.95,
444 1, 0.7, 0.05, 0.7, 0.95,
449 float const tilde[] = {
451 0.05, 0.8, 0.25, 0.2, 0.75, 0.8, 0.95, 0.2,
462 deco_struct deco_table[] = {
464 { LM_widehat, &angle[0], 3 },
465 { LM_widetilde, &tilde[0], 0 },
466 { LM_underline, &hline[0], 0 },
467 { LM_overline, &hline[0], 0 },
468 { LM_underbrace, &brace[0], 1 },
469 { LM_overbrace, &brace[0], 3 },
470 { LM_overleftarrow, &arrow[0], 1 },
471 { LM_overightarrow, &arrow[0], 3 },
474 { '(', &parenth[0], 0 },
475 { ')', &parenth[0], 2 },
476 { '{', &brace[0], 0 },
477 { '}', &brace[0], 2 },
478 { '[', &brack[0], 0 },
479 { ']', &brack[0], 2 },
480 { '|', &vert[0], 0 },
481 { '/', &slash[0], 0 },
482 { LM_Vert, &Vert[0], 0 },
483 { '\\', &slash[0], 1 },
484 { LM_langle, &angle[0], 0 },
485 { LM_lceil, &corner[0], 0 },
486 { LM_lfloor, &corner[0], 1 },
487 { LM_rangle, &angle[0], 2 },
488 { LM_rceil, &corner[0], 3 },
489 { LM_rfloor, &corner[0], 2 },
490 { LM_downarrow, &arrow[0], 2 },
491 { LM_Downarrow, &Arrow[0], 2 },
492 { LM_uparrow, &arrow[0], 0 },
493 { LM_Uparrow, &Arrow[0], 0 },
494 { LM_updownarrow, &udarrow[0], 0 },
495 { LM_Updownarrow, &Udarrow[0], 0 },
498 { LM_ddot, &hline2[0], 0 },
499 { LM_hat, &angle[0], 3 },
500 { LM_grave, &slash[0], 1 },
501 { LM_acute, &slash[0], 0 },
502 { LM_tilde, &tilde[0], 0 },
503 { LM_bar, &hline[0], 0 },
504 { LM_dot, &hlinesmall[0], 0 },
505 { LM_check, &angle[0], 1 },
506 { LM_breve, &parenth[0], 1 },
507 { LM_vec, &arrow[0], 3 },
508 { LM_not, &slash[0], 0 },
511 { LM_ldots, &hline3[0], 0 },
512 { LM_cdots, &hline3[0], 0 },
513 { LM_vdots, &hline3[0], 1 },
514 { LM_ddots, &dline3[0], 0 }
518 struct deco_compare {
519 /// for use by sort and lower_bound
520 int operator()(deco_struct const & a, deco_struct const & b) const
522 return a.code < b.code;
527 int const deco_table_size = sizeof(deco_table) / sizeof(deco_struct);
530 // sort the table on startup
531 struct init_deco_table {
533 std::sort(deco_table,
534 deco_table + deco_table_size,
539 static init_deco_table dummy;
542 deco_struct const * search_deco(int code)
544 const deco_struct search_elem = { code, 0, 0 };
546 deco_struct const * res =
547 lower_bound(deco_table, deco_table + deco_table_size, search_elem,
549 if (res != deco_table + deco_table_size &&
559 void mathed_char_dim(MathTextCodes type, MathStyles size, unsigned char c,
560 int & asc, int & des, int & wid)
562 LyXFont const font = whichFont(type, size);
563 des = lyxfont::descent(c, font);
564 asc = lyxfont::ascent(c, font);
565 wid = mathed_char_width(type, size, c);
569 int mathed_char_height(MathTextCodes type, MathStyles size, unsigned char c,
570 int & asc, int & des)
572 LyXFont const font = whichFont(type, size);
573 des = lyxfont::descent(c, font);
574 asc = lyxfont::ascent(c, font);
579 int mathed_char_height(MathTextCodes type, MathStyles size, unsigned char c)
583 return mathed_char_height(type, size, c, asc, des);
587 int mathed_char_ascent(MathTextCodes type, MathStyles size, unsigned char c)
589 LyXFont const font = whichFont(type, size);
590 return lyxfont::ascent(c, font);
594 int mathed_char_descent(MathTextCodes type, MathStyles size, unsigned char c)
596 LyXFont const font = whichFont(type, size);
597 return lyxfont::descent(c, font);
601 int mathed_char_width(MathTextCodes type, MathStyles size, unsigned char c)
603 LyXFont const font = whichFont(type, size);
604 LyXFont const f1 = whichFont(LM_TC_TEXTRM, size);
605 #warning why f1 is used ?
606 if (isBinaryOp(c, type))
607 return lyxfont::width(c, font) + 2 * lyxfont::width(' ', f1);
609 return lyxfont::width(c, font);
613 void mathed_string_dim(MathTextCodes type, MathStyles size, string const & s,
614 int & asc, int & des, int & wid)
616 mathed_string_height(type, size, s, asc, des);
617 wid = mathed_string_width(type, size, s);
621 int mathed_string_height(MathTextCodes type, MathStyles size, string const & s,
622 int & asc, int & des)
624 LyXFont const font = whichFont(type, size);
626 for (string::const_iterator it = s.begin(); it != s.end(); ++it) {
627 des = max(des, lyxfont::descent(*it, font));
628 asc = max(asc, lyxfont::ascent(*it, font));
634 int mathed_string_width(MathTextCodes type, MathStyles size, string const & s)
636 return lyxfont::width(s, whichFont(type, size));
640 void mathed_draw_deco(Painter & pain, int x, int y, int w, int h,
646 string const & name = l->name;
647 int code = (name.size() > 1) ? l->id : name[0];
650 pain.line(x + w/2, y, x + w/2, y + h,
651 LColor::mathcursor, Painter::line_onoffdash);
655 deco_struct const * mds = search_deco(code);
657 lyxerr << "Deco was not found. Programming error?\n";
658 lyxerr << "name: '" << name << "', code: " << code << "\n";
662 int const r = mds->angle;
663 float const * d = mds->data;
665 if (h > 70 && (mds->code == int('(') || mds->code == int(')')))
671 int const n = (w < h) ? w : h;
694 xx = d[i++]; yy = d[i++];
695 x2 = d[i++]; y2 = d[i++];
697 sqmt.transform(xx, yy, xx, yy);
699 mt.transform(xx, yy, xx, yy);
700 mt.transform(x2, y2, x2, y2);
701 pain.line(x + int(xx), y + int(yy),
702 x + int(x2), y + int(y2),
711 int const n = int(d[i++]);
712 for (int j = 0; j < n; ++j) {
713 xx = d[i++]; yy = d[i++];
714 // lyxerr << " " << xx << " " << yy << " ";
716 sqmt.transform(xx, yy, xx, yy);
718 mt.transform(xx, yy, xx, yy);
721 // lyxerr << "P[" << j " " << xx << " " << yy << " " << x << " " << y << "]";
723 pain.lines(xp, yp, n, LColor::mathline);
730 // In the future maybe we use a better fonts renderer
731 void drawStr(Painter & pain, MathTextCodes type, MathStyles siz,
732 int x, int y, string const & s)
734 pain.text(x, y, s, whichFont(type, siz));
739 (Painter & pain, MathTextCodes type, MathStyles siz, int x, int y, char c)
742 if (isBinaryOp(c, type))
745 if (isBinaryOp(c, type))
747 drawStr(pain, type, siz, x, y, s);
751 // decrease math size for super- and subscripts
752 MathStyles smallerStyleScript(MathStyles st)
756 case LM_ST_TEXT: st = LM_ST_SCRIPT; break;
757 default: st = LM_ST_SCRIPTSCRIPT;
763 // decrease math size for fractions
764 MathStyles smallerStyleFrac(MathStyles st)
767 case LM_ST_DISPLAY: st = LM_ST_TEXT; break;
768 case LM_ST_TEXT: st = LM_ST_SCRIPT; break;
769 default: st = LM_ST_SCRIPTSCRIPT;
775 void math_font_max_dim(MathTextCodes code, MathStyles siz, int & asc, int & des)
777 LyXFont font = whichFont(code, siz);
778 asc = lyxfont::maxAscent(font);
779 des = lyxfont::maxDescent(font);
783 char const * latex_mathspace[] = {
784 "!", ",", ":", ";", "quad", "qquad"