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 =
528 sizeof(deco_table) / sizeof(deco_struct);
531 // sort the table on startup
532 struct init_deco_table {
534 std::sort(deco_table,
535 deco_table + deco_table_size,
540 static init_deco_table dummy;
543 deco_struct const * search_deco(int code)
545 const deco_struct search_elem = { code, 0, 0 };
547 deco_struct const * res =
548 lower_bound(deco_table, deco_table + deco_table_size, search_elem,
550 if (res != deco_table + deco_table_size &&
560 void mathed_char_dim(MathTextCodes type, MathStyles size, unsigned char c,
561 int & asc, int & des, int & wid)
563 LyXFont const font = whichFont(type, size);
564 des = lyxfont::descent(c, font);
565 asc = lyxfont::ascent(c, font);
566 wid = mathed_char_width(type, size, c);
570 int mathed_char_height(MathTextCodes type, MathStyles size, unsigned char c,
571 int & asc, int & des)
573 LyXFont const font = whichFont(type, size);
574 des = lyxfont::descent(c, font);
575 asc = lyxfont::ascent(c, font);
580 int mathed_char_height(MathTextCodes type, MathStyles size, unsigned char c)
584 return mathed_char_height(type, size, c, asc, des);
588 int mathed_char_ascent(MathTextCodes type, MathStyles size, unsigned char c)
590 LyXFont const font = whichFont(type, size);
591 return lyxfont::ascent(c, font);
595 int mathed_char_descent(MathTextCodes type, MathStyles size, unsigned char c)
597 LyXFont const font = whichFont(type, size);
598 return lyxfont::descent(c, font);
602 int mathed_char_width(MathTextCodes type, MathStyles size, unsigned char c)
604 LyXFont const font = whichFont(type, size);
605 LyXFont const f1 = whichFont(LM_TC_TEXTRM, size);
606 #warning why f1 is used ?
607 if (isBinaryOp(c, type))
608 return lyxfont::width(c, font) + 2 * lyxfont::width(' ', f1);
610 return lyxfont::width(c, font);
614 void mathed_string_dim(MathTextCodes type, MathStyles size, string const & s,
615 int & asc, int & des, int & wid)
617 mathed_string_height(type, size, s, asc, des);
618 wid = mathed_string_width(type, size, s);
622 int mathed_string_height(MathTextCodes type, MathStyles size, string const & s,
623 int & asc, int & des)
625 LyXFont const font = whichFont(type, size);
627 for (string::const_iterator it = s.begin(); it != s.end(); ++it) {
628 des = max(des, lyxfont::descent(*it, font));
629 asc = max(asc, lyxfont::ascent(*it, font));
635 int mathed_string_width(MathTextCodes type, MathStyles size, string const & s)
637 return lyxfont::width(s, whichFont(type, size));
641 void mathed_draw_deco(Painter & pain, int x, int y, int w, int h,
647 string const & name = l->name;
648 int code = (name.size() > 1) ? l->id : name[0];
651 pain.line(x + w/2, y, x + w/2, y + h,
652 LColor::mathcursor, Painter::line_onoffdash);
656 deco_struct const * mds = search_deco(code);
658 lyxerr << "Deco was not found. Programming error?\n";
659 lyxerr << "name: '" << name << "', code: " << code << "\n";
663 int const r = mds->angle;
664 float const * d = mds->data;
666 if (h > 70 && (mds->code == int('(') || mds->code == int(')')))
672 int const n = (w < h) ? w : h;
695 xx = d[i++]; yy = d[i++];
696 x2 = d[i++]; y2 = d[i++];
698 sqmt.transform(xx, yy, xx, yy);
700 mt.transform(xx, yy, xx, yy);
701 mt.transform(x2, y2, x2, y2);
702 pain.line(x + int(xx), y + int(yy),
703 x + int(x2), y + int(y2),
712 int const n = int(d[i++]);
713 for (int j = 0; j < n; ++j) {
714 xx = d[i++]; yy = d[i++];
715 // lyxerr << " " << xx << " " << yy << " ";
717 sqmt.transform(xx, yy, xx, yy);
719 mt.transform(xx, yy, xx, yy);
722 // lyxerr << "P[" << j " " << xx << " " << yy << " " << x << " " << y << "]";
724 pain.lines(xp, yp, n, LColor::mathline);
731 // In the future maybe we use a better fonts renderer
732 void drawStr(Painter & pain, MathTextCodes type, MathStyles siz,
733 int x, int y, string const & s)
735 pain.text(x, y, s, whichFont(type, siz));
740 (Painter & pain, MathTextCodes type, MathStyles siz, int x, int y, char c)
743 if (isBinaryOp(c, type))
746 if (isBinaryOp(c, type))
748 drawStr(pain, type, siz, x, y, s);
752 // decrease math size for super- and subscripts
753 MathStyles smallerStyleScript(MathStyles st)
757 case LM_ST_TEXT: st = LM_ST_SCRIPT; break;
758 default: st = LM_ST_SCRIPTSCRIPT;
764 // decrease math size for fractions
765 MathStyles smallerStyleFrac(MathStyles st)
768 case LM_ST_DISPLAY: st = LM_ST_TEXT; break;
769 case LM_ST_TEXT: st = LM_ST_SCRIPT; break;
770 default: st = LM_ST_SCRIPTSCRIPT;
776 void math_font_max_dim(MathTextCodes code, MathStyles siz, int & asc, int & des)
778 LyXFont font = whichFont(code, siz);
779 asc = lyxfont::maxAscent(font);
780 des = lyxfont::maxDescent(font);
784 char const * latex_mathspace[] = {
785 "!", ",", ":", ";", "quad", "qquad"