5 #include "math_support.h"
7 #include "frontends/font_loader.h"
8 #include "frontends/font_metrics.h"
9 #include "math_cursor.h"
10 #include "math_defs.h"
11 #include "math_inset.h"
12 #include "math_parser.h"
13 #include "frontends/Painter.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 },
494 {"backslash", slash, 1 },
495 {"langle", angle, 0 },
496 {"lceil", corner, 0 },
497 {"lfloor", corner, 1 },
498 {"rangle", angle, 2 },
499 {"rceil", corner, 3 },
500 {"rfloor", corner, 2 },
501 {"downarrow", arrow, 2 },
502 {"Downarrow", Arrow, 2 },
503 {"uparrow", arrow, 0 },
504 {"Uparrow", Arrow, 0 },
505 {"updownarrow", udarrow, 0 },
506 {"Updownarrow", Udarrow, 0 },
510 {"dddot", dddot, 0 },
512 {"grave", slash, 1 },
513 {"acute", slash, 0 },
514 {"tilde", tilde, 0 },
516 {"dot", hlinesmall, 0 },
517 {"check", angle, 1 },
518 {"breve", parenth, 1 },
521 {"mathring", ring, 0 },
524 {"ldots", hline3, 0 },
525 {"cdots", hline3, 0 },
526 {"vdots", hline3, 1 },
527 {"ddots", dline3, 0 },
528 {"dotsb", hline3, 0 },
529 {"dotsc", hline3, 0 },
530 {"dotsi", hline3, 0 },
531 {"dotsm", hline3, 0 },
532 {"dotso", hline3, 0 }
536 map<string, deco_struct> deco_list;
538 // sort the table on startup
539 struct init_deco_table {
541 unsigned const n = sizeof(deco_table) / sizeof(deco_table[0]);
542 for (named_deco_struct * p = deco_table; p != deco_table + n; ++p) {
546 deco_list[p->name]= d;
551 static init_deco_table dummy;
554 deco_struct const * search_deco(string const & name)
556 map<string, deco_struct>::const_iterator p = deco_list.find(name);
557 return (p == deco_list.end()) ? 0 : &(p->second);
564 void mathed_char_dim(LyXFont const & font,
565 unsigned char c, int & asc, int & des, int & wid)
567 des = font_metrics::descent(c, font);
568 asc = font_metrics::ascent(c, font);
569 wid = mathed_char_width(font, c);
573 int mathed_char_ascent(LyXFont const & font, unsigned char c)
575 return font_metrics::ascent(c, font);
579 int mathed_char_descent(LyXFont const & font, unsigned char c)
581 return font_metrics::descent(c, font);
585 int mathed_char_width(LyXFont const & font, unsigned char c)
587 return font_metrics::width(c, font);
591 void mathed_string_dim(LyXFont const & font,
592 string const & s, int & asc, int & des, int & wid)
595 for (string::const_iterator it = s.begin(); it != s.end(); ++it) {
596 des = max(des, font_metrics::descent(*it, font));
597 asc = max(asc, font_metrics::ascent(*it, font));
599 wid = font_metrics::width(s, font);
603 int mathed_string_width(LyXFont const & font, string const & s)
605 return font_metrics::width(s, font);
609 int mathed_string_ascent(LyXFont const & font, string const & s)
612 for (string::const_iterator it = s.begin(); it != s.end(); ++it)
613 asc = max(asc, font_metrics::ascent(*it, font));
618 int mathed_string_descent(LyXFont const & font, string const & s)
621 for (string::const_iterator it = s.begin(); it != s.end(); ++it)
622 des = max(des, font_metrics::descent(*it, font));
628 void mathed_draw_deco(Painter & pain, int x, int y, int w, int h,
632 pain.line(x + w/2, y, x + w/2, y + h,
633 LColor::mathcursor, Painter::line_onoffdash);
637 deco_struct const * mds = search_deco(name);
639 lyxerr << "Deco was not found. Programming error?\n";
640 lyxerr << "name: '" << name << "'\n";
644 int const n = (w < h) ? w : h;
645 int const r = mds->angle;
646 double const * d = mds->data;
648 if (h > 70 && (name == "(" || name == ")"))
652 Matrix sqmt(r, n, n);
660 for (int i = 0; d[i];) {
661 int code = int(d[i++]);
662 if (code & 1) { // code == 1 || code == 3
668 sqmt.transform(xx, yy);
670 mt.transform(xx, yy);
671 mt.transform(x2, y2);
672 pain.line(x + int(xx), y + int(yy), x + int(x2), y + int(y2),
677 int const n = int(d[i++]);
678 for (int j = 0; j < n; ++j) {
681 // lyxerr << " " << xx << " " << yy << " ";
683 sqmt.transform(xx, yy);
685 mt.transform(xx, yy);
688 // lyxerr << "P[" << j " " << xx << " " << yy << " " << x << " " << y << "]";
690 pain.lines(xp, yp, n, LColor::math);
696 void mathed_draw_framebox(Painter & pain, int x, int y, MathInset const * p)
698 if (mathcursor && mathcursor->isInside(p))
699 pain.rectangle(x, y - p->ascent(), p->width(), p->height(),
704 // In the future maybe we use a better fonts renderer
705 void drawStr(Painter & pain, LyXFont const & font,
706 int x, int y, string const & str)
708 pain.text(x, y, str, font);
712 void drawChar(Painter & pain, LyXFont const & font, int x, int y, char c)
714 pain.text(x, y, c, font);
718 // decrease math size for super- and subscripts
719 void smallerStyleScript(MathMetricsInfo & st)
723 case LM_ST_TEXT: st.style = LM_ST_SCRIPT; break;
724 default: st.style = LM_ST_SCRIPTSCRIPT;
729 // decrease math size for fractions
730 void smallerStyleFrac(MathMetricsInfo & st)
733 case LM_ST_DISPLAY: st.style = LM_ST_TEXT; break;
734 case LM_ST_TEXT: st.style = LM_ST_SCRIPT; break;
735 default: st.style = LM_ST_SCRIPTSCRIPT;
740 void math_font_max_dim(LyXFont const & font, int & asc, int & des)
742 asc = font_metrics::maxAscent(font);
743 des = font_metrics::maxDescent(font);
747 char const * math_font_name(MathTextCodes code)
749 static char const * theFontNames[] = {
761 if (code >= LM_TC_RM && code <= LM_TC_TEXTRM)
762 return theFontNames[code - LM_TC_RM];
766 string convertDelimToLatexName(string const & name)
782 return "\\" + name + " ";