5 #include "math_support.h"
7 #include "FontLoader.h"
9 #include "math_cursor.h"
10 #include "math_defs.h"
11 #include "math_inset.h"
12 #include "math_parser.h"
15 #include "commandtags.h"
26 Matrix(int, double, double);
28 void transform(double &, double &);
35 Matrix::Matrix(int code, double x, double y)
37 double const cs = (code & 1) ? 0 : (1 - code);
38 double const sn = (code & 1) ? (2 - code) : 0;
46 void Matrix::transform(double & x, double & y)
48 double xx = m_[0][0] * x + m_[0][1] * y;
49 double yy = m_[1][0] * x + m_[1][1] * y;
57 LyXFont * MathFonts = 0;
58 bool font_available[LM_FONT_END];
59 bool font_available_initialized[LM_FONT_END];
82 void mathed_init_fonts()
84 MathFonts = new LyXFont[FONT_NUM];
86 MathFonts[FONT_IT].setShape(LyXFont::ITALIC_SHAPE);
88 MathFonts[FONT_SYMBOL].setFamily(LyXFont::SYMBOL_FAMILY);
90 MathFonts[FONT_SYMBOLI].setFamily(LyXFont::SYMBOL_FAMILY);
91 MathFonts[FONT_SYMBOLI].setShape(LyXFont::ITALIC_SHAPE);
93 MathFonts[FONT_BF].setSeries(LyXFont::BOLD_SERIES);
95 MathFonts[FONT_TT].setFamily(LyXFont::TYPEWRITER_FAMILY);
96 MathFonts[FONT_RM].setFamily(LyXFont::ROMAN_FAMILY);
97 MathFonts[FONT_SF].setFamily(LyXFont::SANS_FAMILY);
99 MathFonts[FONT_CMR].setFamily(LyXFont::CMR_FAMILY);
100 MathFonts[FONT_CMSY].setFamily(LyXFont::CMSY_FAMILY);
101 MathFonts[FONT_CMM].setFamily(LyXFont::CMM_FAMILY);
102 MathFonts[FONT_CMEX].setFamily(LyXFont::CMEX_FAMILY);
103 MathFonts[FONT_MSA].setFamily(LyXFont::MSA_FAMILY);
104 MathFonts[FONT_MSB].setFamily(LyXFont::MSB_FAMILY);
105 MathFonts[FONT_EUFRAK].setFamily(LyXFont::EUFRAK_FAMILY);
107 MathFonts[FONT_FAKEBB].setFamily(LyXFont::TYPEWRITER_FAMILY);
108 MathFonts[FONT_FAKEBB].setSeries(LyXFont::BOLD_SERIES);
110 MathFonts[FONT_FAKECAL].setFamily(LyXFont::SANS_FAMILY);
111 MathFonts[FONT_FAKECAL].setShape(LyXFont::ITALIC_SHAPE);
113 MathFonts[FONT_FAKEFRAK].setFamily(LyXFont::SANS_FAMILY);
114 MathFonts[FONT_FAKEFRAK].setSeries(LyXFont::BOLD_SERIES);
116 for (int i = 0; i < LM_FONT_END; ++i)
117 font_available_initialized[i] = false;
121 LyXFont const & whichFontBaseIntern(MathTextCodes type)
129 return MathFonts[FONT_SYMBOLI];
133 return MathFonts[FONT_IT];
136 return MathFonts[FONT_BF];
139 return MathFonts[FONT_MSB];
142 return MathFonts[FONT_CMSY];
145 return MathFonts[FONT_TT];
152 return MathFonts[FONT_RM];
155 return MathFonts[FONT_SF];
158 return MathFonts[FONT_CMR];
161 return MathFonts[FONT_CMSY];
164 return MathFonts[FONT_CMM];
167 return MathFonts[FONT_CMEX];
170 return MathFonts[FONT_MSA];
173 return MathFonts[FONT_MSB];
176 return MathFonts[FONT_EUFRAK];
185 LyXFont const & whichFontBase(MathTextCodes type)
192 if (math_font_available(LM_TC_MSB))
193 return MathFonts[FONT_MSB];
195 return MathFonts[FONT_FAKEBB];
198 if (math_font_available(LM_TC_CMSY))
199 return MathFonts[FONT_CMSY];
201 return MathFonts[FONT_FAKECAL];
204 if (math_font_available(LM_TC_EUFRAK))
205 return MathFonts[FONT_EUFRAK];
207 return MathFonts[FONT_FAKEFRAK];
212 return whichFontBaseIntern(type);
218 void whichFont(LyXFont & f, MathTextCodes type, MathMetricsInfo const & size)
220 f = whichFontBase(type);
222 f.setSize(size.font.size());
224 switch (size.style) {
226 if (type == LM_TC_BOLDSYMB || type == LM_TC_CMEX) {
240 case LM_ST_SCRIPTSCRIPT:
247 lyxerr << "Math Error: wrong font size: " << size.style << endl;
251 if (type != LM_TC_TEXTRM && type != LM_TC_BOX)
252 f.setColor(LColor::math);
254 if (type == LM_TC_TEX)
255 f.setColor(LColor::latex);
259 bool math_font_available(MathTextCodes type)
261 if (!font_available_initialized[type]) {
262 font_available_initialized[type] = true;
263 font_available[type] = fontloader.available(whichFontBaseIntern(type));
264 if (!font_available[type])
265 lyxerr[Debug::FONT] << "Math font " << type << " not available.\n";
267 return font_available[type];
274 * Internal struct of a drawing: code n x1 y1 ... xn yn, where code is:
275 * 0 = end, 1 = line, 2 = polyline, 3 = square line, 4= square polyline
279 double const parenthHigh[] = {
281 0.9840, 0.0014, 0.7143, 0.0323, 0.4603, 0.0772,
282 0.2540, 0.1278, 0.1746, 0.1966, 0.0952, 0.3300,
283 0.0950, 0.5000, 0.0952, 0.6700, 0.1746, 0.8034,
284 0.2540, 0.8722, 0.4603, 0.9228, 0.7143, 0.9677,
290 double const parenth[] = {
292 0.9930, 0.0071, 0.7324, 0.0578, 0.5141, 0.1126,
293 0.3380, 0.1714, 0.2183, 0.2333, 0.0634, 0.3621,
294 0.0141, 0.5000, 0.0563, 0.6369, 0.2113, 0.7647,
295 0.3310, 0.8276, 0.5070, 0.8864, 0.7254, 0.9412,
301 double const brace[] = {
303 0.9492, 0.0020, 0.9379, 0.0020, 0.7458, 0.0243,
304 0.5819, 0.0527, 0.4859, 0.0892, 0.4463, 0.1278,
305 0.4463, 0.3732, 0.4011, 0.4199, 0.2712, 0.4615,
306 0.0734, 0.4919, 0.0113, 0.5000, 0.0734, 0.5081,
307 0.2712, 0.5385, 0.4011, 0.5801, 0.4463, 0.6268,
308 0.4463, 0.8722, 0.4859, 0.9108, 0.5819, 0.9473,
309 0.7458, 0.9757, 0.9379, 0.9980, 0.9492, 0.9980,
314 double const arrow[] = {
316 0.0150, 0.7500, 0.2000, 0.6000, 0.3500, 0.3500,
317 0.5000, 0.0500, 0.6500, 0.3500, 0.8000, 0.6000,
319 3, 0.5000, 0.1500, 0.5000, 0.9500,
324 double const Arrow[] = {
326 0.0150, 0.7500, 0.2000, 0.6000, 0.3500, 0.3500,
327 0.5000, 0.0500, 0.6500, 0.3500, 0.8000, 0.6000,
329 3, 0.3500, 0.5000, 0.3500, 0.9500,
330 3, 0.6500, 0.5000, 0.6500, 0.9500,
335 double const udarrow[] = {
337 0.015, 0.25, 0.5, 0.05, 0.95, 0.25,
339 0.015, 0.75, 0.5, 0.95, 0.95, 0.75,
340 1, 0.5, 0.2, 0.5, 0.8,
345 double const Udarrow[] = {
347 0.015, 0.25, 0.5, 0.05, 0.95, 0.25,
349 0.015, 0.75, 0.5, 0.95, 0.95, 0.75,
350 1, 0.35, 0.2, 0.35, 0.8,
351 1, 0.65, 0.2, 0.65, 0.8,
356 double const brack[] = {
358 0.95, 0.05, 0.05, 0.05, 0.05, 0.95, 0.95, 0.95,
363 double const corner[] = {
365 0.95, 0.05, 0.05, 0.05, 0.05, 0.95,
370 double const angle[] = {
372 1, 0, 0.05, 0.5, 1, 1,
377 double const slash[] = {
378 1, 0.95, 0.05, 0.05, 0.95,
383 double const hline[] = {
384 1, 0.00, 0.5, 1.0, 0.5,
389 double const ddot[] = {
390 1, 0.2, 0.5, 0.3, 0.5,
391 1, 0.7, 0.5, 0.8, 0.5,
396 double const dddot[] = {
397 1, 0.1, 0.5, 0.2, 0.5,
398 1, 0.45, 0.5, 0.55, 0.5,
399 1, 0.8, 0.5, 0.9, 0.5,
404 double const hline3[] = {
406 1, 0.475, 0, 0.525, 0,
412 double const dline3[] = {
413 1, 0.1, 0.1, 0.15, 0.15,
414 1, 0.475, 0.475, 0.525, 0.525,
415 1, 0.85, 0.85, 0.9, 0.9,
420 double const hlinesmall[] = {
421 1, 0.4, 0.5, 0.6, 0.5,
426 double const vert[] = {
427 1, 0.5, 0.05, 0.5, 0.95,
432 double const Vert[] = {
433 1, 0.3, 0.05, 0.3, 0.95,
434 1, 0.7, 0.05, 0.7, 0.95,
439 double const tilde[] = {
441 0.05, 0.8, 0.25, 0.2, 0.75, 0.8, 0.95, 0.2,
451 struct named_deco_struct {
457 named_deco_struct deco_table[] = {
459 {"widehat", angle, 3 },
460 {"widetilde", tilde, 0 },
461 {"underbar", hline, 0 },
462 {"underline", hline, 0 },
463 {"overline", hline, 0 },
464 {"underbrace", brace, 1 },
465 {"overbrace", brace, 3 },
466 {"overleftarrow", arrow, 1 },
467 {"overrightarrow", arrow, 3 },
468 {"overleftrightarrow", udarrow, 1 },
469 {"xleftarrow", arrow, 1 },
470 {"xrightarrow", arrow, 3 },
471 {"underleftarrow", arrow, 1 },
472 {"underrightarrow", arrow, 3 },
473 {"underleftrightarrow",udarrow, 1 },
486 {"backslash", slash, 1 },
487 {"langle", angle, 0 },
488 {"lceil", corner, 0 },
489 {"lfloor", corner, 1 },
490 {"rangle", angle, 2 },
491 {"rceil", corner, 3 },
492 {"rfloor", corner, 2 },
493 {"downarrow", arrow, 2 },
494 {"Downarrow", Arrow, 2 },
495 {"uparrow", arrow, 0 },
496 {"Uparrow", Arrow, 0 },
497 {"updownarrow", udarrow, 0 },
498 {"Updownarrow", Udarrow, 0 },
502 {"dddot", dddot, 0 },
504 {"grave", slash, 1 },
505 {"acute", slash, 0 },
506 {"tilde", tilde, 0 },
508 {"dot", hlinesmall, 0 },
509 {"check", angle, 1 },
510 {"breve", parenth, 1 },
515 {"ldots", hline3, 0 },
516 {"cdots", hline3, 0 },
517 {"vdots", hline3, 1 },
518 {"ddots", dline3, 0 }
522 map<string, deco_struct> deco_list;
524 // sort the table on startup
525 struct init_deco_table {
527 unsigned const n = sizeof(deco_table) / sizeof(deco_table[0]);
528 for (named_deco_struct * p = deco_table; p != deco_table + n; ++p) {
532 deco_list[p->name]= d;
537 static init_deco_table dummy;
540 deco_struct const * search_deco(string const & name)
542 map<string, deco_struct>::const_iterator p = deco_list.find(name);
543 return (p == deco_list.end()) ? 0 : &(p->second);
550 void mathed_char_dim(LyXFont const & font,
551 unsigned char c, int & asc, int & des, int & wid)
553 des = lyxfont::descent(c, font);
554 asc = lyxfont::ascent(c, font);
555 wid = mathed_char_width(font, c);
559 int mathed_char_ascent(LyXFont const & font, unsigned char c)
561 return lyxfont::ascent(c, font);
565 int mathed_char_descent(LyXFont const & font, unsigned char c)
567 return lyxfont::descent(c, font);
571 int mathed_char_width(LyXFont const & font, unsigned char c)
573 return lyxfont::width(c, font);
577 void mathed_string_dim(LyXFont const & font,
578 string const & s, int & asc, int & des, int & wid)
581 for (string::const_iterator it = s.begin(); it != s.end(); ++it) {
582 des = max(des, lyxfont::descent(*it, font));
583 asc = max(asc, lyxfont::ascent(*it, font));
585 wid = lyxfont::width(s, font);
589 int mathed_string_width(LyXFont const & font, string const & s)
591 return lyxfont::width(s, font);
595 int mathed_string_ascent(LyXFont const & font, string const & s)
598 for (string::const_iterator it = s.begin(); it != s.end(); ++it)
599 asc = max(asc, lyxfont::ascent(*it, font));
604 int mathed_string_descent(LyXFont const & font, string const & s)
607 for (string::const_iterator it = s.begin(); it != s.end(); ++it)
608 des = max(des, lyxfont::descent(*it, font));
614 void mathed_draw_deco(Painter & pain, int x, int y, int w, int h,
618 pain.line(x + w/2, y, x + w/2, y + h,
619 LColor::mathcursor, Painter::line_onoffdash);
623 deco_struct const * mds = search_deco(name);
625 lyxerr << "Deco was not found. Programming error?\n";
626 lyxerr << "name: '" << name << "'\n";
630 int const n = (w < h) ? w : h;
631 int const r = mds->angle;
632 double const * d = mds->data;
634 if (h > 70 && (name == "(" || name == ")"))
638 Matrix sqmt(r, n, n);
646 for (int i = 0; d[i];) {
647 int code = int(d[i++]);
648 if (code & 1) { // code == 1 || code == 3
654 sqmt.transform(xx, yy);
656 mt.transform(xx, yy);
657 mt.transform(x2, y2);
658 pain.line(x + int(xx), y + int(yy), x + int(x2), y + int(y2),
663 int const n = int(d[i++]);
664 for (int j = 0; j < n; ++j) {
667 // lyxerr << " " << xx << " " << yy << " ";
669 sqmt.transform(xx, yy);
671 mt.transform(xx, yy);
674 // lyxerr << "P[" << j " " << xx << " " << yy << " " << x << " " << y << "]";
676 pain.lines(xp, yp, n, LColor::math);
682 void mathed_draw_framebox(Painter & pain, int x, int y, MathInset const * p)
684 if (mathcursor && mathcursor->isInside(p))
685 pain.rectangle(x, y - p->ascent(), p->width(), p->height(),
690 // In the future maybe we use a better fonts renderer
691 void drawStr(Painter & pain, LyXFont const & font,
692 int x, int y, string const & str)
694 pain.text(x, y, str, font);
698 void drawChar(Painter & pain, LyXFont const & font, int x, int y, char c)
700 pain.text(x, y, c, font);
704 // decrease math size for super- and subscripts
705 void smallerStyleScript(MathMetricsInfo & st)
709 case LM_ST_TEXT: st.style = LM_ST_SCRIPT; break;
710 default: st.style = LM_ST_SCRIPTSCRIPT;
715 // decrease math size for fractions
716 void smallerStyleFrac(MathMetricsInfo & st)
719 case LM_ST_DISPLAY: st.style = LM_ST_TEXT; break;
720 case LM_ST_TEXT: st.style = LM_ST_SCRIPT; break;
721 default: st.style = LM_ST_SCRIPTSCRIPT;
726 void math_font_max_dim(LyXFont const & font, int & asc, int & des)
728 asc = lyxfont::maxAscent(font);
729 des = lyxfont::maxDescent(font);
733 char const * latex_mathspace[] = {
734 "!", ",", ":", ";", "quad", "qquad"
739 char const * math_font_name(MathTextCodes code)
741 static char const * theFontNames[] = {
753 if (code >= LM_TC_RM && code <= LM_TC_TEXTRM)
754 return theFontNames[code - LM_TC_RM];
758 string convertDelimToLatexName(string const & name)
774 return "\\" + name + " ";