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 },
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 }
531 map<string, deco_struct> deco_list;
533 // sort the table on startup
534 struct init_deco_table {
536 unsigned const n = sizeof(deco_table) / sizeof(deco_table[0]);
537 for (named_deco_struct * p = deco_table; p != deco_table + n; ++p) {
541 deco_list[p->name]= d;
546 static init_deco_table dummy;
549 deco_struct const * search_deco(string const & name)
551 map<string, deco_struct>::const_iterator p = deco_list.find(name);
552 return (p == deco_list.end()) ? 0 : &(p->second);
559 void mathed_char_dim(LyXFont const & font,
560 unsigned char c, int & asc, int & des, int & wid)
562 des = lyxfont::descent(c, font);
563 asc = lyxfont::ascent(c, font);
564 wid = mathed_char_width(font, c);
568 int mathed_char_ascent(LyXFont const & font, unsigned char c)
570 return lyxfont::ascent(c, font);
574 int mathed_char_descent(LyXFont const & font, unsigned char c)
576 return lyxfont::descent(c, font);
580 int mathed_char_width(LyXFont const & font, unsigned char c)
582 return lyxfont::width(c, font);
586 void mathed_string_dim(LyXFont const & font,
587 string const & s, int & asc, int & des, int & wid)
590 for (string::const_iterator it = s.begin(); it != s.end(); ++it) {
591 des = max(des, lyxfont::descent(*it, font));
592 asc = max(asc, lyxfont::ascent(*it, font));
594 wid = lyxfont::width(s, font);
598 int mathed_string_width(LyXFont const & font, string const & s)
600 return lyxfont::width(s, font);
604 int mathed_string_ascent(LyXFont const & font, string const & s)
607 for (string::const_iterator it = s.begin(); it != s.end(); ++it)
608 asc = max(asc, lyxfont::ascent(*it, font));
613 int mathed_string_descent(LyXFont const & font, string const & s)
616 for (string::const_iterator it = s.begin(); it != s.end(); ++it)
617 des = max(des, lyxfont::descent(*it, font));
623 void mathed_draw_deco(Painter & pain, int x, int y, int w, int h,
627 pain.line(x + w/2, y, x + w/2, y + h,
628 LColor::mathcursor, Painter::line_onoffdash);
632 deco_struct const * mds = search_deco(name);
634 lyxerr << "Deco was not found. Programming error?\n";
635 lyxerr << "name: '" << name << "'\n";
639 int const n = (w < h) ? w : h;
640 int const r = mds->angle;
641 double const * d = mds->data;
643 if (h > 70 && (name == "(" || name == ")"))
647 Matrix sqmt(r, n, n);
655 for (int i = 0; d[i];) {
656 int code = int(d[i++]);
657 if (code & 1) { // code == 1 || code == 3
663 sqmt.transform(xx, yy);
665 mt.transform(xx, yy);
666 mt.transform(x2, y2);
667 pain.line(x + int(xx), y + int(yy), x + int(x2), y + int(y2),
672 int const n = int(d[i++]);
673 for (int j = 0; j < n; ++j) {
676 // lyxerr << " " << xx << " " << yy << " ";
678 sqmt.transform(xx, yy);
680 mt.transform(xx, yy);
683 // lyxerr << "P[" << j " " << xx << " " << yy << " " << x << " " << y << "]";
685 pain.lines(xp, yp, n, LColor::math);
691 void mathed_draw_framebox(Painter & pain, int x, int y, MathInset const * p)
693 if (mathcursor && mathcursor->isInside(p))
694 pain.rectangle(x, y - p->ascent(), p->width(), p->height(),
699 // In the future maybe we use a better fonts renderer
700 void drawStr(Painter & pain, LyXFont const & font,
701 int x, int y, string const & str)
703 pain.text(x, y, str, font);
707 void drawChar(Painter & pain, LyXFont const & font, int x, int y, char c)
709 pain.text(x, y, c, font);
713 // decrease math size for super- and subscripts
714 void smallerStyleScript(MathMetricsInfo & st)
718 case LM_ST_TEXT: st.style = LM_ST_SCRIPT; break;
719 default: st.style = LM_ST_SCRIPTSCRIPT;
724 // decrease math size for fractions
725 void smallerStyleFrac(MathMetricsInfo & st)
728 case LM_ST_DISPLAY: st.style = LM_ST_TEXT; break;
729 case LM_ST_TEXT: st.style = LM_ST_SCRIPT; break;
730 default: st.style = LM_ST_SCRIPTSCRIPT;
735 void math_font_max_dim(LyXFont const & font, int & asc, int & des)
737 asc = lyxfont::maxAscent(font);
738 des = lyxfont::maxDescent(font);
742 char const * math_font_name(MathTextCodes code)
744 static char const * theFontNames[] = {
756 if (code >= LM_TC_RM && code <= LM_TC_TEXTRM)
757 return theFontNames[code - LM_TC_RM];
761 string convertDelimToLatexName(string const & name)
777 return "\\" + name + " ";