5 #include "mathed/support.h"
7 #include "FontLoader.h"
10 #include "math_inset.h"
11 #include "math_parser.h"
20 bool isBinaryOp(char c, MathTextCodes type)
22 return type < LM_TC_SYMB && strchr("+-<>=/*", c);
30 Matrix(int, double, double);
32 void transform(double &, double &);
39 Matrix::Matrix(int code, double x, double y)
41 double const cs = (code & 1) ? 0 : (1 - code);
42 double const sn = (code & 1) ? (2 - code) : 0;
50 void Matrix::transform(double & x, double & y)
52 double xx = m_[0][0] * x + m_[0][1] * y;
53 double yy = m_[1][0] * x + m_[1][1] * y;
61 LyXFont * MathFonts = 0;
62 bool font_available[LM_FONT_END];
63 bool font_available_initialized[LM_FONT_END];
84 void mathed_init_fonts()
86 MathFonts = new LyXFont[FONT_NUM]; //DEC cxx cannot initialize all fonts
89 for (int i = 0 ; i < FONT_NUM ; ++i) {
90 MathFonts[i] = LyXFont(LyXFont::ALL_SANE);
93 MathFonts[FONT_IT].setShape(LyXFont::ITALIC_SHAPE);
95 MathFonts[FONT_SYMBOL].setFamily(LyXFont::SYMBOL_FAMILY);
97 MathFonts[FONT_SYMBOLI].setFamily(LyXFont::SYMBOL_FAMILY);
98 MathFonts[FONT_SYMBOLI].setShape(LyXFont::ITALIC_SHAPE);
100 MathFonts[FONT_BF].setSeries(LyXFont::BOLD_SERIES);
102 MathFonts[FONT_BB].setSeries(LyXFont::BOLD_SERIES);
103 MathFonts[FONT_BB].setFamily(LyXFont::TYPEWRITER_FAMILY);
105 MathFonts[FONT_CAL].setFamily(LyXFont::SANS_FAMILY);
106 MathFonts[FONT_CAL].setShape(LyXFont::ITALIC_SHAPE);
108 MathFonts[FONT_TT].setFamily(LyXFont::TYPEWRITER_FAMILY);
110 MathFonts[FONT_RM].setFamily(LyXFont::ROMAN_FAMILY);
112 MathFonts[FONT_SF].setFamily(LyXFont::SANS_FAMILY);
114 MathFonts[FONT_CMR].setFamily(LyXFont::CMR_FAMILY);
115 MathFonts[FONT_CMSY].setFamily(LyXFont::CMSY_FAMILY);
116 MathFonts[FONT_CMM].setFamily(LyXFont::CMM_FAMILY);
117 MathFonts[FONT_CMEX].setFamily(LyXFont::CMEX_FAMILY);
118 MathFonts[FONT_MSA].setFamily(LyXFont::MSA_FAMILY);
119 MathFonts[FONT_MSB].setFamily(LyXFont::MSB_FAMILY);
121 for (int i = 0; i < LM_FONT_END; ++i)
122 font_available_initialized[i] = false;
126 LyXFont const & whichFontBase(MathTextCodes type)
134 return MathFonts[FONT_SYMBOLI];
138 return MathFonts[FONT_IT];
141 return MathFonts[FONT_BF];
144 if (math_font_available(LM_TC_MSB))
145 return MathFonts[FONT_MSB];
147 return MathFonts[FONT_BB];
150 if (math_font_available(LM_TC_CMSY))
151 return MathFonts[FONT_CMSY];
153 return MathFonts[FONT_CAL];
156 return MathFonts[FONT_TT];
162 return MathFonts[FONT_RM];
165 return MathFonts[FONT_SF];
168 return MathFonts[FONT_CMR];
171 return MathFonts[FONT_CMSY];
174 return MathFonts[FONT_CMM];
177 return MathFonts[FONT_CMEX];
180 return MathFonts[FONT_MSA];
183 return MathFonts[FONT_MSB];
192 LyXFont whichFont(MathTextCodes type, MathMetricsInfo const & size)
194 LyXFont f = whichFontBase(type);
197 #warning Want to fix formula sizes in headings? Look here!
199 // unfortunatly, size.font is sometimes nonzero and size.font->size()
201 //lyxerr << "setting font size to " << size.font->size() << "\n";
202 //f.setSize(size.font->size());
205 switch (size.style) {
207 if (type == LM_TC_BOLDSYMB || type == LM_TC_CMEX) {
221 case LM_ST_SCRIPTSCRIPT:
228 lyxerr << "Math Error: wrong font size: " << size.style << endl;
232 if (type != LM_TC_TEXTRM)
233 f.setColor(LColor::math);
235 if (type == LM_TC_TEX)
236 f.setColor(LColor::latex);
244 bool math_font_available(MathTextCodes type)
246 if (!font_available_initialized[type]) {
247 font_available_initialized[type] = true;
248 font_available[type] = fontloader.available(whichFontBase(type));
250 return font_available[type];
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 double 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 double 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 double 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 double const arrow[] = {
299 0.0150, 0.7500, 0.2000, 0.6000, 0.3500, 0.3500,
300 0.5000, 0.0500, 0.6500, 0.3500, 0.8000, 0.6000,
302 3, 0.5000, 0.1500, 0.5000, 0.9500,
307 double 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 double 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 double 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 double const brack[] = {
341 0.95, 0.05, 0.05, 0.05, 0.05, 0.95, 0.95, 0.95,
346 double const corner[] = {
348 0.95, 0.05, 0.05, 0.05, 0.05, 0.95,
353 double const angle[] = {
355 1, 0, 0.05, 0.5, 1, 1,
360 double const slash[] = {
361 1, 0.95, 0.05, 0.05, 0.95,
366 double const hline[] = {
367 1, 0.00, 0.5, 1.0, 0.5,
372 double const hline2[] = {
373 1, 0.1, 0.5, 0.3, 0.5,
374 1, 0.7, 0.5, 0.9, 0.5,
379 double const hline3[] = {
381 1, 0.475, 0, 0.525, 0,
387 double 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 double const hlinesmall[] = {
396 1, 0.4, 0.5, 0.6, 0.5,
401 double const vert[] = {
402 1, 0.5, 0.05, 0.5, 0.95,
407 double const Vert[] = {
408 1, 0.3, 0.05, 0.3, 0.95,
409 1, 0.7, 0.05, 0.7, 0.95,
414 double const tilde[] = {
416 0.05, 0.8, 0.25, 0.2, 0.75, 0.8, 0.95, 0.2,
426 struct named_deco_struct {
432 named_deco_struct deco_table[] = {
434 {"widehat", angle, 3 },
435 {"widetilde", tilde, 0 },
436 {"underline", hline, 0 },
437 {"overline", hline, 0 },
438 {"underbrace", brace, 1 },
439 {"overbrace", brace, 3 },
440 {"overleftarrow", arrow, 1 },
441 {"overrightarrow", arrow, 3 },
454 {"backslash", slash, 1 },
455 {"langle", angle, 0 },
456 {"lceil", corner, 0 },
457 {"lfloor", corner, 1 },
458 {"rangle", angle, 2 },
459 {"rceil", corner, 3 },
460 {"rfloor", corner, 2 },
461 {"downarrow", arrow, 2 },
462 {"Downarrow", Arrow, 2 },
463 {"uparrow", arrow, 0 },
464 {"Uparrow", Arrow, 0 },
465 {"updownarrow", udarrow, 0 },
466 {"Updownarrow", Udarrow, 0 },
469 {"ddot", hline2, 0 },
471 {"grave", slash, 1 },
472 {"acute", slash, 0 },
473 {"tilde", tilde, 0 },
475 {"dot", hlinesmall, 0 },
476 {"check", angle, 1 },
477 {"breve", parenth, 1 },
482 {"ldots", hline3, 0 },
483 {"cdots", hline3, 0 },
484 {"vdots", hline3, 1 },
485 {"ddots", dline3, 0 }
489 map<string, deco_struct> deco_list;
491 // sort the table on startup
492 struct init_deco_table {
494 unsigned const n = sizeof(deco_table) / sizeof(deco_table[0]);
495 for (named_deco_struct * p = deco_table; p != deco_table + n; ++p) {
499 deco_list[p->name]= d;
504 static init_deco_table dummy;
507 deco_struct const * search_deco(string const & name)
509 map<string, deco_struct>::const_iterator p = deco_list.find(name);
510 return (p == deco_list.end()) ? 0 : &(p->second);
517 void mathed_char_dim(MathTextCodes type, MathMetricsInfo const & size,
518 unsigned char c, int & asc, int & des, int & wid)
520 LyXFont const font = whichFont(type, size);
521 des = lyxfont::descent(c, font);
522 asc = lyxfont::ascent(c, font);
523 wid = mathed_char_width(type, size, c);
527 int mathed_char_height(MathTextCodes type, MathMetricsInfo const & size,
528 unsigned char c, int & asc, int & des)
530 LyXFont const font = whichFont(type, size);
531 des = lyxfont::descent(c, font);
532 asc = lyxfont::ascent(c, font);
537 int mathed_char_height(MathTextCodes type, MathMetricsInfo const & size,
542 return mathed_char_height(type, size, c, asc, des);
546 int mathed_char_ascent(MathTextCodes type, MathMetricsInfo const & size,
549 LyXFont const font = whichFont(type, size);
550 return lyxfont::ascent(c, font);
554 int mathed_char_descent(MathTextCodes type, MathMetricsInfo const & size,
557 LyXFont const font = whichFont(type, size);
558 return lyxfont::descent(c, font);
562 int mathed_char_width(MathTextCodes type, MathMetricsInfo const & size,
565 LyXFont const font = whichFont(type, size);
566 if (isBinaryOp(c, type))
567 return lyxfont::width(c, font) + 2 * lyxfont::width(' ', font);
569 return lyxfont::width(c, font);
573 void mathed_string_dim(MathTextCodes type, MathMetricsInfo const & size,
574 string const & s, int & asc, int & des, int & wid)
576 mathed_string_height(type, size, s, asc, des);
577 wid = mathed_string_width(type, size, s);
581 int mathed_string_height(MathTextCodes type, MathMetricsInfo const & size,
582 string const & s, int & asc, int & des)
584 LyXFont const font = whichFont(type, size);
586 for (string::const_iterator it = s.begin(); it != s.end(); ++it) {
587 des = max(des, lyxfont::descent(*it, font));
588 asc = max(asc, lyxfont::ascent(*it, font));
594 int mathed_string_width(MathTextCodes type, MathMetricsInfo const & size,
597 return lyxfont::width(s, whichFont(type, size));
601 void mathed_draw_deco(Painter & pain, int x, int y, int w, int h,
605 pain.line(x + w/2, y, x + w/2, y + h,
606 LColor::mathcursor, Painter::line_onoffdash);
610 deco_struct const * mds = search_deco(name);
612 lyxerr << "Deco was not found. Programming error?\n";
613 lyxerr << "name: '" << name << "'\n";
617 int const n = (w < h) ? w : h;
618 int const r = mds->angle;
619 double const * d = mds->data;
621 if (h > 70 && (name == "(" || name == ")"))
625 Matrix sqmt(r, n, n);
633 for (int i = 0; d[i]; ) {
634 int code = int(d[i++]);
635 if (code & 1) { // code == 1 || code == 3
641 sqmt.transform(xx, yy);
643 mt.transform(xx, yy);
644 mt.transform(x2, y2);
645 pain.line(x + int(xx), y + int(yy), x + int(x2), y + int(y2),
650 int const n = int(d[i++]);
651 for (int j = 0; j < n; ++j) {
654 // lyxerr << " " << xx << " " << yy << " ";
656 sqmt.transform(xx, yy);
658 mt.transform(xx, yy);
661 // lyxerr << "P[" << j " " << xx << " " << yy << " " << x << " " << y << "]";
663 pain.lines(xp, yp, n, LColor::mathline);
669 // In the future maybe we use a better fonts renderer
670 void drawStr(Painter & pain, MathTextCodes type, MathMetricsInfo const & siz,
671 int x, int y, string const & s)
673 pain.text(x, y, s, whichFont(type, siz));
677 void drawChar(Painter & pain, MathTextCodes type, MathMetricsInfo const & siz,
678 int x, int y, char c)
681 if (isBinaryOp(c, type))
684 if (isBinaryOp(c, type))
686 drawStr(pain, type, siz, x, y, s);
690 // decrease math size for super- and subscripts
691 void smallerStyleScript(MathMetricsInfo & st)
695 case LM_ST_TEXT: st.style = LM_ST_SCRIPT; break;
696 default: st.style = LM_ST_SCRIPTSCRIPT;
701 // decrease math size for fractions
702 void smallerStyleFrac(MathMetricsInfo & st)
705 case LM_ST_DISPLAY: st.style = LM_ST_TEXT; break;
706 case LM_ST_TEXT: st.style = LM_ST_SCRIPT; break;
707 default: st.style = LM_ST_SCRIPTSCRIPT;
712 void math_font_max_dim(MathTextCodes code, MathMetricsInfo const & siz,
713 int & asc, int & des)
715 LyXFont font = whichFont(code, siz);
716 asc = lyxfont::maxAscent(font);
717 des = lyxfont::maxDescent(font);
721 char const * latex_mathspace[] = {
722 "!", ",", ":", ";", "quad", "qquad"