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