]> git.lyx.org Git - lyx.git/blob - src/mathed/math_support.C
remove unneeded member
[lyx.git] / src / mathed / math_support.C
1 #include <config.h>
2
3 #include <map>
4
5 #include "math_support.h"
6 #include "lyxfont.h"
7 #include "math_cursor.h"
8 #include "math_inset.h"
9 #include "math_parser.h"
10 #include "frontends/Painter.h"
11 #include "frontends/font_metrics.h"
12 #include "frontends/font_loader.h"
13 #include "debug.h"
14 #include "commandtags.h"
15
16 using std::map;
17 using std::endl;
18 using std::max;
19
20
21 ///
22 class Matrix {
23 public:
24         ///
25         Matrix(int, double, double);
26         ///
27         void transform(double &, double &);
28 private:
29         ///
30         double m_[2][2];
31 };
32
33
34 Matrix::Matrix(int code, double x, double y)
35 {
36         double const cs = (code & 1) ? 0 : (1 - code);
37         double const sn = (code & 1) ? (2 - code) : 0;
38         m_[0][0] =  cs * x;
39         m_[0][1] =  sn * x;
40         m_[1][0] = -sn * y;
41         m_[1][1] =  cs * y;
42 }
43
44
45 void Matrix::transform(double & x, double & y)
46 {
47         double xx = m_[0][0] * x + m_[0][1] * y;
48         double yy = m_[1][0] * x + m_[1][1] * y;
49         x = xx;
50         y = yy;
51 }
52
53
54
55 namespace {
56
57 /*
58  * Internal struct of a drawing: code n x1 y1 ... xn yn, where code is:
59  * 0 = end, 1 = line, 2 = polyline, 3 = square line, 4 = square polyline
60  */
61
62
63 double const parenthHigh[] = {
64         2, 13,
65         0.9840, 0.0014, 0.7143, 0.0323, 0.4603, 0.0772,
66         0.2540, 0.1278, 0.1746, 0.1966, 0.0952, 0.3300,
67         0.0950, 0.5000, 0.0952, 0.6700, 0.1746, 0.8034,
68         0.2540, 0.8722, 0.4603, 0.9228, 0.7143, 0.9677,
69         0.9840, 0.9986,
70         0
71 };
72
73
74 double const parenth[] = {
75         2, 13,
76         0.9930, 0.0071, 0.7324, 0.0578, 0.5141, 0.1126,
77         0.3380, 0.1714, 0.2183, 0.2333, 0.0634, 0.3621,
78         0.0141, 0.5000, 0.0563, 0.6369, 0.2113, 0.7647,
79         0.3310, 0.8276, 0.5070, 0.8864, 0.7254, 0.9412,
80         0.9930, 0.9919,
81         0
82 };
83
84
85 double const brace[] = {
86         2, 21,
87         0.9492, 0.0020, 0.9379, 0.0020, 0.7458, 0.0243,
88         0.5819, 0.0527, 0.4859, 0.0892, 0.4463, 0.1278,
89         0.4463, 0.3732, 0.4011, 0.4199, 0.2712, 0.4615,
90         0.0734, 0.4919, 0.0113, 0.5000, 0.0734, 0.5081,
91         0.2712, 0.5385, 0.4011, 0.5801, 0.4463, 0.6268,
92         0.4463, 0.8722, 0.4859, 0.9108, 0.5819, 0.9473,
93         0.7458, 0.9757, 0.9379, 0.9980, 0.9492, 0.9980,
94         0
95 };
96
97
98 double const arrow[] = {
99         4, 7,
100         0.0150, 0.7500, 0.2000, 0.6000, 0.3500, 0.3500,
101         0.5000, 0.0500, 0.6500, 0.3500, 0.8000, 0.6000,
102         0.9500, 0.7500,
103         3, 0.5000, 0.1500, 0.5000, 0.9500,
104         0
105 };
106
107
108 double const Arrow[] = {
109         4, 7,
110         0.0150, 0.7500, 0.2000, 0.6000, 0.3500, 0.3500,
111         0.5000, 0.0500, 0.6500, 0.3500, 0.8000, 0.6000,
112         0.9500, 0.7500,
113         3, 0.3500, 0.5000, 0.3500, 0.9500,
114         3, 0.6500, 0.5000, 0.6500, 0.9500,
115         0
116 };
117
118
119 double const udarrow[] = {
120         2, 3,
121         0.015, 0.25,  0.5, 0.05, 0.95, 0.25,
122         2, 3,
123         0.015, 0.75,  0.5, 0.95, 0.95, 0.75,
124         1, 0.5, 0.2,  0.5, 0.8,
125         0
126 };
127
128
129 double const Udarrow[] = {
130         2, 3,
131         0.015, 0.25,  0.5, 0.05, 0.95, 0.25,
132         2, 3,
133         0.015, 0.75,  0.5, 0.95, 0.95, 0.75,
134         1, 0.35, 0.2, 0.35, 0.8,
135         1, 0.65, 0.2, 0.65, 0.8,
136         0
137 };
138
139
140 double const brack[] = {
141         2, 4,
142         0.95, 0.05,  0.05, 0.05,  0.05, 0.95,  0.95, 0.95,
143         0
144 };
145
146
147 double const corner[] = {
148         2, 3,
149         0.95, 0.05,  0.05, 0.05,  0.05, 0.95,
150         0
151 };
152
153
154 double const angle[] = {
155         2, 3,
156         1, 0,  0.05, 0.5,  1, 1,
157         0
158 };
159
160
161 double const slash[] = {
162         1, 0.95, 0.05, 0.05, 0.95,
163         0
164 };
165
166
167 double const hline[] = {
168         1, 0.00, 0.5, 1.0, 0.5,
169         0
170 };
171
172
173 double const ddot[] = {
174         1, 0.2, 0.5,  0.3, 0.5,
175         1, 0.7, 0.5,  0.8, 0.5,
176         0
177 };
178
179
180 double const dddot[] = {
181         1, 0.1, 0.5,  0.2, 0.5,
182         1, 0.45, 0.5, 0.55, 0.5,
183         1, 0.8, 0.5,  0.9, 0.5,
184         0
185 };
186
187
188 double const hline3[] = {
189         1, 0.1,   0,  0.15,  0,
190         1, 0.475, 0,  0.525, 0,
191         1, 0.85,  0,  0.9,   0,
192         0
193 };
194
195
196 double const dline3[] = {
197         1, 0.1,   0.1,   0.15,  0.15,
198         1, 0.475, 0.475, 0.525, 0.525,
199         1, 0.85,  0.85,  0.9,   0.9,
200         0
201 };
202
203
204 double const hlinesmall[] = {
205         1, 0.4, 0.5, 0.6, 0.5,
206         0
207 };
208
209
210 double const ring[] = {
211         2, 5,
212         0.5, 0.8,  0.8, 0.5,  0.5, 0.2,  0.2, 0.5,  0.5, 0.8,
213         0
214 };
215
216
217 double const vert[] = {
218         1, 0.5, 0.05,  0.5, 0.95,
219         0
220 };
221
222
223 double const  Vert[] = {
224         1, 0.3, 0.05,  0.3, 0.95,
225         1, 0.7, 0.05,  0.7, 0.95,
226         0
227 };
228
229
230 double const tilde[] = {
231         2, 4,
232         0.00, 0.8,  0.25, 0.2,  0.75, 0.8,  1.00, 0.2,
233         0
234 };
235
236
237 struct deco_struct {
238         double const * data;
239         int angle;
240 };
241
242 struct named_deco_struct {
243         char const * name;
244         double const * data;
245         int angle;
246 };
247
248 named_deco_struct deco_table[] = {
249         // Decorations
250         {"widehat",             angle,    3 },
251         {"widetilde",           tilde,    0 },
252         {"underbar",            hline,    0 },
253         {"underline",           hline,    0 },
254         {"overline",            hline,    0 },
255         {"underbrace",          brace,    1 },
256         {"overbrace",           brace,    3 },
257         {"overleftarrow",       arrow,    1 },
258         {"overrightarrow",      arrow,    3 },
259         {"overleftrightarrow",  udarrow,  1 },
260         {"xleftarrow",          arrow,    1 },
261         {"xrightarrow",         arrow,    3 },
262         {"underleftarrow",      arrow,    1 },
263         {"underrightarrow",     arrow,    3 },
264         {"underleftrightarrow", udarrow,  1 },
265
266         // Delimiters
267         {"(",              parenth,    0 },
268         {")",              parenth,    2 },
269         {"{",              brace,      0 },
270         {"}",              brace,      2 },
271         {"[",              brack,      0 },
272         {"]",              brack,      2 },
273         {"|",              vert,       0 },
274         {"/",              slash,      0 },
275         {"vert",           vert,       0 },
276         {"Vert",           Vert,       0 },
277         {"'",              slash,      1 },
278         {"backslash",      slash,      1 },
279         {"langle",         angle,      0 },
280         {"lceil",          corner,     0 },
281         {"lfloor",         corner,     1 },
282         {"rangle",         angle,      2 },
283         {"rceil",          corner,     3 },
284         {"rfloor",         corner,     2 },
285         {"downarrow",      arrow,      2 },
286         {"Downarrow",      Arrow,      2 },
287         {"uparrow",        arrow,      0 },
288         {"Uparrow",        Arrow,      0 },
289         {"updownarrow",    udarrow,    0 },
290         {"Updownarrow",    Udarrow,    0 },
291
292         // Accents
293         {"ddot",           ddot,       0 },
294         {"dddot",          dddot,      0 },
295         {"hat",            angle,      3 },
296         {"grave",          slash,      1 },
297         {"acute",          slash,      0 },
298         {"tilde",          tilde,      0 },
299         {"bar",            hline,      0 },
300         {"dot",            hlinesmall, 0 },
301         {"check",          angle,      1 },
302         {"breve",          parenth,    1 },
303         {"vec",            arrow,      3 },
304         {"not",            slash,      0 },
305         {"mathring",       ring,       0 },
306
307         // Dots
308         {"ldots",          hline3,     0 },
309         {"cdots",          hline3,     0 },
310         {"vdots",          hline3,     1 },
311         {"ddots",          dline3,     0 },
312         {"dotsb",          hline3,     0 },
313         {"dotsc",          hline3,     0 },
314         {"dotsi",          hline3,     0 },
315         {"dotsm",          hline3,     0 },
316         {"dotso",          hline3,     0 }
317 };
318
319
320 map<string, deco_struct> deco_list;
321
322 // sort the table on startup
323 struct init_deco_table {
324         init_deco_table() {
325                 unsigned const n = sizeof(deco_table) / sizeof(deco_table[0]);
326                 for (named_deco_struct * p = deco_table; p != deco_table + n; ++p) {
327                         deco_struct d;
328                         d.data  = p->data;
329                         d.angle = p->angle;
330                         deco_list[p->name]= d;
331                 }
332         }
333 };
334
335 static init_deco_table dummy;
336
337
338 deco_struct const * search_deco(string const & name)
339 {
340         map<string, deco_struct>::const_iterator p = deco_list.find(name);
341         return (p == deco_list.end()) ? 0 : &(p->second);
342 }
343
344
345 } // namespace anon
346
347
348 void mathed_char_dim(LyXFont const & font,
349         unsigned char c, int & asc, int & des, int & wid)
350 {
351         des = font_metrics::descent(c, font);
352         asc = font_metrics::ascent(c, font);
353         wid = mathed_char_width(font, c);
354 }
355
356
357 int mathed_char_ascent(LyXFont const & font, unsigned char c)
358 {
359         return font_metrics::ascent(c, font);
360 }
361
362
363 int mathed_char_descent(LyXFont const & font, unsigned char c)
364 {
365         return font_metrics::descent(c, font);
366 }
367
368
369 int mathed_char_width(LyXFont const & font, unsigned char c)
370 {
371         return font_metrics::width(c, font);
372 }
373
374
375 void mathed_string_dim(LyXFont const & font,
376         string const & s, int & asc, int & des, int & wid)
377 {
378         asc = des = 0;
379         for (string::const_iterator it = s.begin(); it != s.end(); ++it) {
380                 des = max(des, font_metrics::descent(*it, font));
381                 asc = max(asc, font_metrics::ascent(*it, font));
382         }
383         wid = font_metrics::width(s, font);
384 }
385
386
387 int mathed_string_width(LyXFont const & font, string const & s)
388 {
389         return font_metrics::width(s, font);
390 }
391
392
393 int mathed_string_ascent(LyXFont const & font, string const & s)
394 {
395         int asc = 0;
396         for (string::const_iterator it = s.begin(); it != s.end(); ++it)
397                 asc = max(asc, font_metrics::ascent(*it, font));
398         return asc;
399 }
400
401
402 int mathed_string_descent(LyXFont const & font, string const & s)
403 {
404         int des = 0;
405         for (string::const_iterator it = s.begin(); it != s.end(); ++it)
406                 des = max(des, font_metrics::descent(*it, font));
407         return des;
408 }
409
410
411
412 void mathed_draw_deco(MathPainterInfo & pi, int x, int y, int w, int h,
413         const string & name)
414 {
415         if (name == ".") {
416                 pi.pain.line(x + w/2, y, x + w/2, y + h,
417                           LColor::mathcursor, Painter::line_onoffdash);
418                 return;
419         }
420
421         deco_struct const * mds = search_deco(name);
422         if (!mds) {
423                 lyxerr << "Deco was not found. Programming error?\n";
424                 lyxerr << "name: '" << name << "'\n";
425                 return;
426         }
427
428         int const n = (w < h) ? w : h;
429         int const r = mds->angle;
430         double const * d = mds->data;
431
432         if (h > 70 && (name == "(" || name == ")"))
433                 d = parenthHigh;
434
435         Matrix mt(r, w, h);
436         Matrix sqmt(r, n, n);
437
438         if (r > 0 && r < 3)
439                 y += h;
440
441         if (r >= 2)
442                 x += w;
443
444         for (int i = 0; d[i]; ) {
445                 int code = int(d[i++]);
446                 if (code & 1) {  // code == 1 || code == 3
447                         double xx = d[i++];
448                         double yy = d[i++];
449                         double x2 = d[i++];
450                         double y2 = d[i++];
451                         if (code == 3)
452                                 sqmt.transform(xx, yy);
453                         else
454                                 mt.transform(xx, yy);
455                         mt.transform(x2, y2);
456                         pi.pain.line(
457                                 x + int(xx + 0.5), y + int(yy + 0.5),
458                                 x + int(x2 + 0.5), y + int(y2 + 0.5),
459                                 LColor::math);
460                 }       else {
461                         int xp[32];
462                         int yp[32];
463                         int const n = int(d[i++]);
464                         for (int j = 0; j < n; ++j) {
465                                 double xx = d[i++];
466                                 double yy = d[i++];
467 //           lyxerr << " " << xx << " " << yy << " ";
468                                 if (code == 4)
469                                         sqmt.transform(xx, yy);
470                                 else
471                                         mt.transform(xx, yy);
472                                 xp[j] = x + int(xx + 0.5);
473                                 yp[j] = y + int(yy + 0.5);
474                                 //  lyxerr << "P[" << j " " << xx << " " << yy << " " << x << " " << y << "]";
475                         }
476                         pi.pain.lines(xp, yp, n, LColor::math);
477                 }
478         }
479 }
480
481
482 void mathed_draw_framebox(MathPainterInfo & pi, int x, int y, MathInset const * p)
483 {
484         if (mathcursor && mathcursor->isInside(p))
485                 pi.pain.rectangle(x, y - p->ascent(), p->width(), p->height(),
486                         LColor::mathframe);
487 }
488
489
490 // In the future maybe we use a better fonts renderer
491 void drawStr(MathPainterInfo & pi, LyXFont const & font,
492         int x, int y, string const & str)
493 {
494         pi.pain.text(x, y, str, font);
495 }
496
497
498 void drawStrRed(MathPainterInfo & pi, int x, int y, string const & str)
499 {
500         LyXFont f = pi.base.font;
501         f.setColor(LColor::latex);
502         pi.pain.text(x, y, str, f);
503 }
504
505
506 void drawStrBlack(MathPainterInfo & pi, int x, int y, string const & str)
507 {
508         LyXFont f = pi.base.font;
509         f.setColor(LColor::black);
510         pi.pain.text(x, y, str, f);
511 }
512
513
514 void drawChar(MathPainterInfo & pi, LyXFont const & font, int x, int y, char c)
515 {
516         pi.pain.text(x, y, c, font);
517 }
518
519
520 void math_font_max_dim(LyXFont const & font, int & asc, int & des)
521 {
522         asc = font_metrics::maxAscent(font);
523         des = font_metrics::maxDescent(font);
524 }
525
526
527 struct fontinfo {
528         string cmd_;
529         LyXFont::FONT_FAMILY family_;
530         LyXFont::FONT_SERIES series_;
531         LyXFont::FONT_SHAPE  shape_;
532         LColor::color        color_;
533 };
534
535
536 LyXFont::FONT_FAMILY const inh_family = LyXFont::INHERIT_FAMILY;
537 LyXFont::FONT_SERIES const inh_series = LyXFont::INHERIT_SERIES;
538 LyXFont::FONT_SHAPE  const inh_shape  = LyXFont::INHERIT_SHAPE; 
539
540
541 // mathnormal should be the first, otherwise the fallback fuerther down
542 // does not work
543 fontinfo fontinfos[] = {
544         {"mathnormal", inh_family,inh_series, LyXFont::UP_SHAPE, LColor::math},
545         {"mathbf", inh_family, LyXFont::BOLD_SERIES, inh_shape, LColor::math},
546         {"mathcal",LyXFont::CMSY_FAMILY, inh_series, inh_shape, LColor::math},
547         {"mathfrak", LyXFont::EUFRAK_FAMILY, inh_series, inh_shape, LColor::math},
548         {"mathrm", LyXFont::ROMAN_FAMILY, inh_series, inh_shape, LColor::math},
549         {"mathsf", LyXFont::SANS_FAMILY, inh_series, inh_shape, LColor::math},
550         {"cmex",   LyXFont::CMEX_FAMILY, inh_series, inh_shape, LColor::math},
551         {"cmm",    LyXFont::CMM_FAMILY, inh_series, inh_shape, LColor::math},
552         {"cmr",    LyXFont::CMR_FAMILY, inh_series, inh_shape, LColor::math},
553         {"cmsy",   LyXFont::CMSY_FAMILY, inh_series, inh_shape, LColor::math},
554         {"eufrak", LyXFont::EUFRAK_FAMILY, inh_series, inh_shape, LColor::math},
555         {"msa",    LyXFont::MSA_FAMILY, inh_series, inh_shape, LColor::math},
556         {"msb",    LyXFont::MSB_FAMILY, inh_series, inh_shape, LColor::math},
557         {"wasy",   LyXFont::WASY_FAMILY, inh_series, inh_shape, LColor::math},
558         {"text",   inh_family, inh_series, inh_shape, LColor::black},
559         {"textbf", inh_family, LyXFont::BOLD_SERIES, inh_shape, LColor::black},
560         {"textit", inh_family, inh_series, LyXFont::ITALIC_SHAPE, LColor::black},
561         {"textmd", inh_family, LyXFont::MEDIUM_SERIES, inh_shape, LColor::black},
562         {"textnormal", inh_family, inh_series, LyXFont::UP_SHAPE, LColor::black},
563         {"textrm", LyXFont::ROMAN_FAMILY, inh_series,LyXFont::UP_SHAPE,LColor::black},
564         {"textsc", inh_family, inh_series, LyXFont::SMALLCAPS_SHAPE, LColor::black},
565         {"textsf", LyXFont::SANS_FAMILY, inh_series, inh_shape, LColor::black},
566         {"textsl", inh_family, inh_series, LyXFont::SLANTED_SHAPE, LColor::black},
567         {"texttt", LyXFont::TYPEWRITER_FAMILY, inh_series, inh_shape, LColor::black},
568         {"textup", inh_family, inh_series, LyXFont::UP_SHAPE, LColor::black},
569
570         // TIPA support
571         {"textipa",   inh_family, inh_series, inh_shape, LColor::black},
572
573         {"lyxtex", inh_family, inh_series, inh_shape, LColor::latex},
574         {"lyxsymbol", LyXFont::SYMBOL_FAMILY, inh_series, inh_shape, LColor::math},
575         {"lyxboldsymbol",
576                 LyXFont::SYMBOL_FAMILY, LyXFont::BOLD_SERIES, inh_shape, LColor::math},
577         {"lyxitsymbol", LyXFont::SYMBOL_FAMILY,
578                 inh_series, LyXFont::ITALIC_SHAPE, LColor::math},
579         {"lyxblacktext", LyXFont::ROMAN_FAMILY,
580                 LyXFont::MEDIUM_SERIES, LyXFont::UP_SHAPE, LColor::black},
581         {"lyxnochange", inh_family, inh_series, inh_shape, LColor::black},
582
583         {"lyxfakebb", LyXFont::TYPEWRITER_FAMILY, LyXFont::BOLD_SERIES,
584                 LyXFont::UP_SHAPE, LColor::math},
585         {"lyxfakecal", LyXFont::SANS_FAMILY, LyXFont::MEDIUM_SERIES,
586                 LyXFont::ITALIC_SHAPE, LColor::math},
587         {"lyxfakefrak", LyXFont::ROMAN_FAMILY, LyXFont::BOLD_SERIES,
588                 LyXFont::ITALIC_SHAPE, LColor::math}
589 };
590
591
592 fontinfo * lookupFont(string const & name)
593 {
594         //lyxerr << "searching font '" << name << "'\n"; 
595         int const n = sizeof(fontinfos) / sizeof(fontinfo);
596         for (int i = 0; i < n; ++i)
597                 if (fontinfos[i].cmd_ == name) {
598                         //lyxerr << "found '" << i << "'\n"; 
599                         return fontinfos + i;
600                 }
601         return 0;
602 }
603
604
605 fontinfo * searchFont(string const & name)
606 {
607         fontinfo * f = lookupFont(name);
608         return f ? f : fontinfos;
609         // this should be mathnormal
610         //return searchFont("mathnormal");
611 }
612
613
614 bool isFontName(string const & name)
615 {
616         return lookupFont(name);
617 }
618
619
620 LyXFont getFont(string const & name)
621 {
622         LyXFont font;
623         augmentFont(font, name);
624         return font;
625 }
626
627
628 void fakeFont(string const & orig, string const & fake)
629 {
630         fontinfo * forig = searchFont(orig);
631         fontinfo * ffake = searchFont(fake);
632         if (forig && ffake) {
633                 forig->family_ = ffake->family_;
634                 forig->series_ = ffake->series_;
635                 forig->shape_  = ffake->shape_;
636                 forig->color_  = ffake->color_;
637         } else {
638                 lyxerr << "Can't fake font '" << orig << "' with '" << fake << "'\n";
639         }
640 }
641
642
643 void augmentFont(LyXFont & font, string const & name)
644 {
645         static bool initialized = false;
646         if (!initialized) {
647                 initialized = true;
648
649                 // fake fonts if necessary
650                 if (!fontloader.available(getFont("mathfrak")))
651                         fakeFont("mathfrak", "lyxfakefrak");
652                 if (!fontloader.available(getFont("mathcal")))
653                         fakeFont("mathcal", "lyxfakecal");
654         }
655         fontinfo * info = searchFont(name);
656         if (info->family_ != inh_family)
657                 font.setFamily(info->family_);
658         if (info->series_ != inh_series)
659                 font.setSeries(info->series_);
660         if (info->shape_ != inh_shape)
661                 font.setShape(info->shape_);
662         if (info->color_ != LColor::none)
663                 font.setColor(info->color_);
664 }