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 ring[] = {
441 0.5, 0.8, 0.8, 0.5, 0.5, 0.2, 0.2, 0.5, 0.5, 0.8,
446 double const tilde[] = {
448 0.05, 0.8, 0.25, 0.2, 0.75, 0.8, 0.95, 0.2,
458 struct named_deco_struct {
464 named_deco_struct deco_table[] = {
466 {"widehat", angle, 3 },
467 {"widetilde", tilde, 0 },
468 {"underbar", hline, 0 },
469 {"underline", hline, 0 },
470 {"overline", hline, 0 },
471 {"underbrace", brace, 1 },
472 {"overbrace", brace, 3 },
473 {"overleftarrow", arrow, 1 },
474 {"overrightarrow", arrow, 3 },
475 {"overleftrightarrow", udarrow, 1 },
476 {"xleftarrow", arrow, 1 },
477 {"xrightarrow", arrow, 3 },
478 {"underleftarrow", arrow, 1 },
479 {"underrightarrow", arrow, 3 },
480 {"underleftrightarrow",udarrow, 1 },
493 {"backslash", slash, 1 },
494 {"langle", angle, 0 },
495 {"lceil", corner, 0 },
496 {"lfloor", corner, 1 },
497 {"rangle", angle, 2 },
498 {"rceil", corner, 3 },
499 {"rfloor", corner, 2 },
500 {"downarrow", arrow, 2 },
501 {"Downarrow", Arrow, 2 },
502 {"uparrow", arrow, 0 },
503 {"Uparrow", Arrow, 0 },
504 {"updownarrow", udarrow, 0 },
505 {"Updownarrow", Udarrow, 0 },
509 {"dddot", dddot, 0 },
511 {"grave", slash, 1 },
512 {"acute", slash, 0 },
513 {"tilde", tilde, 0 },
515 {"dot", hlinesmall, 0 },
516 {"check", angle, 1 },
517 {"breve", parenth, 1 },
520 {"mathring", ring, 0 },
523 {"ldots", hline3, 0 },
524 {"cdots", hline3, 0 },
525 {"vdots", hline3, 1 },
526 {"ddots", dline3, 0 }
530 map<string, deco_struct> deco_list;
532 // sort the table on startup
533 struct init_deco_table {
535 unsigned const n = sizeof(deco_table) / sizeof(deco_table[0]);
536 for (named_deco_struct * p = deco_table; p != deco_table + n; ++p) {
540 deco_list[p->name]= d;
545 static init_deco_table dummy;
548 deco_struct const * search_deco(string const & name)
550 map<string, deco_struct>::const_iterator p = deco_list.find(name);
551 return (p == deco_list.end()) ? 0 : &(p->second);
558 void mathed_char_dim(LyXFont const & font,
559 unsigned char c, int & asc, int & des, int & wid)
561 des = lyxfont::descent(c, font);
562 asc = lyxfont::ascent(c, font);
563 wid = mathed_char_width(font, c);
567 int mathed_char_ascent(LyXFont const & font, unsigned char c)
569 return lyxfont::ascent(c, font);
573 int mathed_char_descent(LyXFont const & font, unsigned char c)
575 return lyxfont::descent(c, font);
579 int mathed_char_width(LyXFont const & font, unsigned char c)
581 return lyxfont::width(c, font);
585 void mathed_string_dim(LyXFont const & font,
586 string const & s, int & asc, int & des, int & wid)
589 for (string::const_iterator it = s.begin(); it != s.end(); ++it) {
590 des = max(des, lyxfont::descent(*it, font));
591 asc = max(asc, lyxfont::ascent(*it, font));
593 wid = lyxfont::width(s, font);
597 int mathed_string_width(LyXFont const & font, string const & s)
599 return lyxfont::width(s, font);
603 int mathed_string_ascent(LyXFont const & font, string const & s)
606 for (string::const_iterator it = s.begin(); it != s.end(); ++it)
607 asc = max(asc, lyxfont::ascent(*it, font));
612 int mathed_string_descent(LyXFont const & font, string const & s)
615 for (string::const_iterator it = s.begin(); it != s.end(); ++it)
616 des = max(des, lyxfont::descent(*it, font));
622 void mathed_draw_deco(Painter & pain, int x, int y, int w, int h,
626 pain.line(x + w/2, y, x + w/2, y + h,
627 LColor::mathcursor, Painter::line_onoffdash);
631 deco_struct const * mds = search_deco(name);
633 lyxerr << "Deco was not found. Programming error?\n";
634 lyxerr << "name: '" << name << "'\n";
638 int const n = (w < h) ? w : h;
639 int const r = mds->angle;
640 double const * d = mds->data;
642 if (h > 70 && (name == "(" || name == ")"))
646 Matrix sqmt(r, n, n);
654 for (int i = 0; d[i];) {
655 int code = int(d[i++]);
656 if (code & 1) { // code == 1 || code == 3
662 sqmt.transform(xx, yy);
664 mt.transform(xx, yy);
665 mt.transform(x2, y2);
666 pain.line(x + int(xx), y + int(yy), x + int(x2), y + int(y2),
671 int const n = int(d[i++]);
672 for (int j = 0; j < n; ++j) {
675 // lyxerr << " " << xx << " " << yy << " ";
677 sqmt.transform(xx, yy);
679 mt.transform(xx, yy);
682 // lyxerr << "P[" << j " " << xx << " " << yy << " " << x << " " << y << "]";
684 pain.lines(xp, yp, n, LColor::math);
690 void mathed_draw_framebox(Painter & pain, int x, int y, MathInset const * p)
692 if (mathcursor && mathcursor->isInside(p))
693 pain.rectangle(x, y - p->ascent(), p->width(), p->height(),
698 // In the future maybe we use a better fonts renderer
699 void drawStr(Painter & pain, LyXFont const & font,
700 int x, int y, string const & str)
702 pain.text(x, y, str, font);
706 void drawChar(Painter & pain, LyXFont const & font, int x, int y, char c)
708 pain.text(x, y, c, font);
712 // decrease math size for super- and subscripts
713 void smallerStyleScript(MathMetricsInfo & st)
717 case LM_ST_TEXT: st.style = LM_ST_SCRIPT; break;
718 default: st.style = LM_ST_SCRIPTSCRIPT;
723 // decrease math size for fractions
724 void smallerStyleFrac(MathMetricsInfo & st)
727 case LM_ST_DISPLAY: st.style = LM_ST_TEXT; break;
728 case LM_ST_TEXT: st.style = LM_ST_SCRIPT; break;
729 default: st.style = LM_ST_SCRIPTSCRIPT;
734 void math_font_max_dim(LyXFont const & font, int & asc, int & des)
736 asc = lyxfont::maxAscent(font);
737 des = lyxfont::maxDescent(font);
741 char const * math_font_name(MathTextCodes code)
743 static char const * theFontNames[] = {
755 if (code >= LM_TC_RM && code <= LM_TC_TEXTRM)
756 return theFontNames[code - LM_TC_RM];
760 string convertDelimToLatexName(string const & name)
776 return "\\" + name + " ";