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"
22 bool isBinaryOp(char c, MathTextCodes type)
24 return type < LM_TC_SYMB && strchr("+-<>=/*", c);
32 Matrix(int, double, double);
34 void transform(double &, double &);
41 Matrix::Matrix(int code, double x, double y)
43 double const cs = (code & 1) ? 0 : (1 - code);
44 double const sn = (code & 1) ? (2 - code) : 0;
52 void Matrix::transform(double & x, double & y)
54 double xx = m_[0][0] * x + m_[0][1] * y;
55 double yy = m_[1][0] * x + m_[1][1] * y;
63 LyXFont * MathFonts = 0;
64 bool font_available[LM_FONT_END];
65 bool font_available_initialized[LM_FONT_END];
88 void mathed_init_fonts()
90 MathFonts = new LyXFont[FONT_NUM];
92 MathFonts[FONT_IT].setShape(LyXFont::ITALIC_SHAPE);
94 MathFonts[FONT_SYMBOL].setFamily(LyXFont::SYMBOL_FAMILY);
96 MathFonts[FONT_SYMBOLI].setFamily(LyXFont::SYMBOL_FAMILY);
97 MathFonts[FONT_SYMBOLI].setShape(LyXFont::ITALIC_SHAPE);
99 MathFonts[FONT_BF].setSeries(LyXFont::BOLD_SERIES);
101 MathFonts[FONT_TT].setFamily(LyXFont::TYPEWRITER_FAMILY);
102 MathFonts[FONT_RM].setFamily(LyXFont::ROMAN_FAMILY);
103 MathFonts[FONT_SF].setFamily(LyXFont::SANS_FAMILY);
105 MathFonts[FONT_CMR].setFamily(LyXFont::CMR_FAMILY);
106 MathFonts[FONT_CMSY].setFamily(LyXFont::CMSY_FAMILY);
107 MathFonts[FONT_CMM].setFamily(LyXFont::CMM_FAMILY);
108 MathFonts[FONT_CMEX].setFamily(LyXFont::CMEX_FAMILY);
109 MathFonts[FONT_MSA].setFamily(LyXFont::MSA_FAMILY);
110 MathFonts[FONT_MSB].setFamily(LyXFont::MSB_FAMILY);
111 MathFonts[FONT_EUFRAK].setFamily(LyXFont::EUFRAK_FAMILY);
113 MathFonts[FONT_FAKEBB].setFamily(LyXFont::TYPEWRITER_FAMILY);
114 MathFonts[FONT_FAKEBB].setSeries(LyXFont::BOLD_SERIES);
116 MathFonts[FONT_FAKECAL].setFamily(LyXFont::SANS_FAMILY);
117 MathFonts[FONT_FAKECAL].setShape(LyXFont::ITALIC_SHAPE);
119 MathFonts[FONT_FAKEFRAK].setFamily(LyXFont::SANS_FAMILY);
120 MathFonts[FONT_FAKEFRAK].setSeries(LyXFont::BOLD_SERIES);
122 for (int i = 0; i < LM_FONT_END; ++i)
123 font_available_initialized[i] = false;
127 LyXFont const & whichFontBaseIntern(MathTextCodes type)
135 return MathFonts[FONT_SYMBOLI];
139 return MathFonts[FONT_IT];
142 return MathFonts[FONT_BF];
145 return MathFonts[FONT_MSB];
148 return MathFonts[FONT_CMSY];
151 return MathFonts[FONT_TT];
158 return MathFonts[FONT_RM];
161 return MathFonts[FONT_SF];
164 return MathFonts[FONT_CMR];
167 return MathFonts[FONT_CMSY];
170 return MathFonts[FONT_CMM];
173 return MathFonts[FONT_CMEX];
176 return MathFonts[FONT_MSA];
179 return MathFonts[FONT_MSB];
182 return MathFonts[FONT_EUFRAK];
191 LyXFont const & whichFontBase(MathTextCodes type)
198 if (math_font_available(LM_TC_MSB))
199 return MathFonts[FONT_MSB];
201 return MathFonts[FONT_FAKEBB];
204 if (math_font_available(LM_TC_CMSY))
205 return MathFonts[FONT_CMSY];
207 return MathFonts[FONT_FAKECAL];
210 if (math_font_available(LM_TC_EUFRAK))
211 return MathFonts[FONT_EUFRAK];
213 return MathFonts[FONT_FAKEFRAK];
218 return whichFontBaseIntern(type);
222 LyXFont whichFont(MathTextCodes type, MathMetricsInfo const & size)
224 LyXFont f = whichFontBase(type);
226 f.setSize(size.font.size());
228 switch (size.style) {
230 if (type == LM_TC_BOLDSYMB || type == LM_TC_CMEX) {
244 case LM_ST_SCRIPTSCRIPT:
251 lyxerr << "Math Error: wrong font size: " << size.style << endl;
255 if (type != LM_TC_TEXTRM && type != LM_TC_BOX)
256 f.setColor(LColor::math);
258 if (type == LM_TC_TEX)
259 f.setColor(LColor::latex);
267 bool math_font_available(MathTextCodes type)
269 if (!font_available_initialized[type]) {
270 font_available_initialized[type] = true;
271 font_available[type] = fontloader.available(whichFontBaseIntern(type));
272 if (!font_available[type])
273 lyxerr[Debug::FONT] << "Math font " << type << " not available.\n";
275 return font_available[type];
282 * Internal struct of a drawing: code n x1 y1 ... xn yn, where code is:
283 * 0 = end, 1 = line, 2 = polyline, 3 = square line, 4= square polyline
287 double const parenthHigh[] = {
289 0.9840, 0.0014, 0.7143, 0.0323, 0.4603, 0.0772,
290 0.2540, 0.1278, 0.1746, 0.1966, 0.0952, 0.3300,
291 0.0950, 0.5000, 0.0952, 0.6700, 0.1746, 0.8034,
292 0.2540, 0.8722, 0.4603, 0.9228, 0.7143, 0.9677,
298 double const parenth[] = {
300 0.9930, 0.0071, 0.7324, 0.0578, 0.5141, 0.1126,
301 0.3380, 0.1714, 0.2183, 0.2333, 0.0634, 0.3621,
302 0.0141, 0.5000, 0.0563, 0.6369, 0.2113, 0.7647,
303 0.3310, 0.8276, 0.5070, 0.8864, 0.7254, 0.9412,
309 double const brace[] = {
311 0.9492, 0.0020, 0.9379, 0.0020, 0.7458, 0.0243,
312 0.5819, 0.0527, 0.4859, 0.0892, 0.4463, 0.1278,
313 0.4463, 0.3732, 0.4011, 0.4199, 0.2712, 0.4615,
314 0.0734, 0.4919, 0.0113, 0.5000, 0.0734, 0.5081,
315 0.2712, 0.5385, 0.4011, 0.5801, 0.4463, 0.6268,
316 0.4463, 0.8722, 0.4859, 0.9108, 0.5819, 0.9473,
317 0.7458, 0.9757, 0.9379, 0.9980, 0.9492, 0.9980,
322 double const arrow[] = {
324 0.0150, 0.7500, 0.2000, 0.6000, 0.3500, 0.3500,
325 0.5000, 0.0500, 0.6500, 0.3500, 0.8000, 0.6000,
327 3, 0.5000, 0.1500, 0.5000, 0.9500,
332 double const Arrow[] = {
334 0.0150, 0.7500, 0.2000, 0.6000, 0.3500, 0.3500,
335 0.5000, 0.0500, 0.6500, 0.3500, 0.8000, 0.6000,
337 3, 0.3500, 0.5000, 0.3500, 0.9500,
338 3, 0.6500, 0.5000, 0.6500, 0.9500,
343 double const udarrow[] = {
345 0.015, 0.25, 0.5, 0.05, 0.95, 0.25,
347 0.015, 0.75, 0.5, 0.95, 0.95, 0.75,
348 1, 0.5, 0.2, 0.5, 0.8,
353 double 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.35, 0.2, 0.35, 0.8,
359 1, 0.65, 0.2, 0.65, 0.8,
364 double const brack[] = {
366 0.95, 0.05, 0.05, 0.05, 0.05, 0.95, 0.95, 0.95,
371 double const corner[] = {
373 0.95, 0.05, 0.05, 0.05, 0.05, 0.95,
378 double const angle[] = {
380 1, 0, 0.05, 0.5, 1, 1,
385 double const slash[] = {
386 1, 0.95, 0.05, 0.05, 0.95,
391 double const hline[] = {
392 1, 0.00, 0.5, 1.0, 0.5,
397 double const hline2[] = {
398 1, 0.2, 0.5, 0.3, 0.5,
399 1, 0.7, 0.5, 0.8, 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 {"xleftarrow", arrow, 1 },
469 {"xrightarrow", arrow, 3 },
470 {"underleftarrow", arrow, 1 },
471 {"underrightarrow", arrow, 3 },
484 {"backslash", slash, 1 },
485 {"langle", angle, 0 },
486 {"lceil", corner, 0 },
487 {"lfloor", corner, 1 },
488 {"rangle", angle, 2 },
489 {"rceil", corner, 3 },
490 {"rfloor", corner, 2 },
491 {"downarrow", arrow, 2 },
492 {"Downarrow", Arrow, 2 },
493 {"uparrow", arrow, 0 },
494 {"Uparrow", Arrow, 0 },
495 {"updownarrow", udarrow, 0 },
496 {"Updownarrow", Udarrow, 0 },
499 {"ddot", hline2, 0 },
501 {"grave", slash, 1 },
502 {"acute", slash, 0 },
503 {"tilde", tilde, 0 },
505 {"dot", hlinesmall, 0 },
506 {"check", angle, 1 },
507 {"breve", parenth, 1 },
512 {"ldots", hline3, 0 },
513 {"cdots", hline3, 0 },
514 {"vdots", hline3, 1 },
515 {"ddots", dline3, 0 }
519 map<string, deco_struct> deco_list;
521 // sort the table on startup
522 struct init_deco_table {
524 unsigned const n = sizeof(deco_table) / sizeof(deco_table[0]);
525 for (named_deco_struct * p = deco_table; p != deco_table + n; ++p) {
529 deco_list[p->name]= d;
534 static init_deco_table dummy;
537 deco_struct const * search_deco(string const & name)
539 map<string, deco_struct>::const_iterator p = deco_list.find(name);
540 return (p == deco_list.end()) ? 0 : &(p->second);
547 void mathed_char_dim(MathTextCodes type, MathMetricsInfo const & size,
548 unsigned char c, int & asc, int & des, int & wid)
550 LyXFont const font = whichFont(type, size);
551 des = lyxfont::descent(c, font);
552 asc = lyxfont::ascent(c, font);
553 wid = mathed_char_width(type, size, c);
557 int mathed_char_height(MathTextCodes type, MathMetricsInfo const & size,
558 unsigned char c, int & asc, int & des)
560 LyXFont const font = whichFont(type, size);
561 des = lyxfont::descent(c, font);
562 asc = lyxfont::ascent(c, font);
567 int mathed_char_height(MathTextCodes type, MathMetricsInfo const & size,
572 return mathed_char_height(type, size, c, asc, des);
576 int mathed_char_ascent(MathTextCodes type, MathMetricsInfo const & size,
579 LyXFont const font = whichFont(type, size);
580 return lyxfont::ascent(c, font);
584 int mathed_char_descent(MathTextCodes type, MathMetricsInfo const & size,
587 LyXFont const font = whichFont(type, size);
588 return lyxfont::descent(c, font);
592 int mathed_char_width(MathTextCodes type, MathMetricsInfo const & size,
595 LyXFont const font = whichFont(type, size);
596 if (isBinaryOp(c, type))
597 return lyxfont::width(c, font) + 2 * lyxfont::width(' ', font);
599 return lyxfont::width(c, font);
603 void mathed_string_dim(MathTextCodes type, MathMetricsInfo const & size,
604 string const & s, int & asc, int & des, int & wid)
606 mathed_string_height(type, size, s, asc, des);
607 wid = mathed_string_width(type, size, s);
611 int mathed_string_height(MathTextCodes type, MathMetricsInfo const & size,
612 string const & s, int & asc, int & des)
614 LyXFont const font = whichFont(type, size);
616 for (string::const_iterator it = s.begin(); it != s.end(); ++it) {
617 des = max(des, lyxfont::descent(*it, font));
618 asc = max(asc, lyxfont::ascent(*it, font));
624 int mathed_string_width(MathTextCodes type, MathMetricsInfo const & size,
627 return lyxfont::width(s, whichFont(type, size));
631 int mathed_string_ascent(MathTextCodes type, MathMetricsInfo const & size,
634 LyXFont const font = whichFont(type, size);
636 for (string::const_iterator it = s.begin(); it != s.end(); ++it)
637 asc = max(asc, lyxfont::ascent(*it, font));
642 int mathed_string_descent(MathTextCodes type, MathMetricsInfo const & size,
645 LyXFont const font = whichFont(type, size);
647 for (string::const_iterator it = s.begin(); it != s.end(); ++it)
648 des = max(des, lyxfont::descent(*it, font));
654 void mathed_draw_deco(Painter & pain, int x, int y, int w, int h,
658 pain.line(x + w/2, y, x + w/2, y + h,
659 LColor::mathcursor, Painter::line_onoffdash);
663 deco_struct const * mds = search_deco(name);
665 lyxerr << "Deco was not found. Programming error?\n";
666 lyxerr << "name: '" << name << "'\n";
670 int const n = (w < h) ? w : h;
671 int const r = mds->angle;
672 double const * d = mds->data;
674 if (h > 70 && (name == "(" || name == ")"))
678 Matrix sqmt(r, n, n);
686 for (int i = 0; d[i]; ) {
687 int code = int(d[i++]);
688 if (code & 1) { // code == 1 || code == 3
694 sqmt.transform(xx, yy);
696 mt.transform(xx, yy);
697 mt.transform(x2, y2);
698 pain.line(x + int(xx), y + int(yy), x + int(x2), y + int(y2),
703 int const n = int(d[i++]);
704 for (int j = 0; j < n; ++j) {
707 // lyxerr << " " << xx << " " << yy << " ";
709 sqmt.transform(xx, yy);
711 mt.transform(xx, yy);
714 // lyxerr << "P[" << j " " << xx << " " << yy << " " << x << " " << y << "]";
716 pain.lines(xp, yp, n, LColor::math);
722 void mathed_draw_framebox(Painter & pain, int x, int y, MathInset const * p)
724 if (mathcursor && mathcursor->isInside(p))
725 pain.rectangle(x, y - p->ascent(), p->width(), p->height(),
730 // In the future maybe we use a better fonts renderer
731 void drawStr(Painter & pain, MathTextCodes type, MathMetricsInfo const & siz,
732 int x, int y, string const & s)
734 pain.text(x, y, s, whichFont(type, siz));
738 void drawChar(Painter & pain, MathTextCodes type, MathMetricsInfo const & siz,
739 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 void smallerStyleScript(MathMetricsInfo & st)
756 case LM_ST_TEXT: st.style = LM_ST_SCRIPT; break;
757 default: st.style = LM_ST_SCRIPTSCRIPT;
762 // decrease math size for fractions
763 void smallerStyleFrac(MathMetricsInfo & st)
766 case LM_ST_DISPLAY: st.style = LM_ST_TEXT; break;
767 case LM_ST_TEXT: st.style = LM_ST_SCRIPT; break;
768 default: st.style = LM_ST_SCRIPTSCRIPT;
773 void math_font_max_dim(MathTextCodes code, MathMetricsInfo const & siz,
774 int & asc, int & des)
776 LyXFont font = whichFont(code, siz);
777 asc = lyxfont::maxAscent(font);
778 des = lyxfont::maxDescent(font);
782 char const * latex_mathspace[] = {
783 "!", ",", ":", ";", "quad", "qquad"
788 char const * math_font_name(MathTextCodes code)
790 static char const * theFontNames[] = {
802 if (code >= LM_TC_RM && code <= LM_TC_TEXTRM)
803 return theFontNames[code - LM_TC_RM];