]> git.lyx.org Git - lyx.git/blob - src/mathed/math_xdata.C
fonts as insets
[lyx.git] / src / mathed / math_xdata.C
1 #include <config.h>
2
3 #ifdef __GNUG__
4 #pragma implementation
5 #endif
6
7 #include "math_scriptinset.h"
8 #include "math_support.h"
9 #include "frontends/Painter.h"
10 #include "textpainter.h"
11 #include "debug.h"
12
13
14 using std::max;
15 using std::min;
16 using std::abs;
17
18
19 extern MathScriptInset const * asScript(MathArray::const_iterator it);
20
21
22 MathXArray::MathXArray()
23         : width_(0), ascent_(0), descent_(0), xo_(0), yo_(0), size_(),
24           clean_(false), drawn_(false)
25 {}
26
27
28 void MathXArray::touch() const
29 {
30         clean_  = false;
31         drawn_  = false;
32 }
33
34
35 void MathXArray::metrics(MathMetricsInfo & mi) const
36 {
37         //if (clean_)
38         //      return;
39
40         size_   = mi;
41         clean_  = true;
42         drawn_  = false;
43
44         if (data_.empty()) {
45                 mathed_char_dim(mi.base.font, 'I', ascent_, descent_, width_);
46                 return;
47         }
48
49         ascent_  = 0;
50         descent_ = 0;
51         width_   = 0;
52
53         for (const_iterator it = begin(); it != end(); ++it) {
54                 MathInset const * p = it->nucleus();
55                 MathScriptInset const * q = (it + 1 == end()) ? 0 : asScript(it);
56                 if (q) {
57                         q->metrics(p, mi);
58                         ascent_  = max(ascent_,  q->ascent2(p));
59                         descent_ = max(descent_, q->descent2(p));
60                         width_  += q->width2(p);
61                         ++it;
62                 } else {
63                         p->metrics(mi);
64                         ascent_  = max(ascent_,  p->ascent());
65                         descent_ = max(descent_, p->descent());
66                         width_  += p->width();
67                 }
68         }
69         //lyxerr << "MathXArray::metrics(): '" << ascent_ << " "
70         //      << descent_ << " " << width_ << "'\n";
71 }
72
73
74 void MathXArray::draw(MathPainterInfo & pi, int x, int y) const
75 {
76         //if (drawn_ && x == xo_ && y == yo_)
77         //      return;
78
79         //lyxerr << "x: " << x << " y: " << y << " " << pain.workAreaHeight() << endl;
80
81         xo_    = x;
82         yo_    = y;
83         drawn_ = true;
84
85         if (y + descent_ <= 0)                   // don't draw above the workarea
86                 return;
87         if (y - ascent_ >= pi.pain.paperHeight())   // don't draw below the workarea
88                 return;
89         if (x + width_ <= 0)                     // don't draw left of workarea
90                 return;
91         if (x >= pi.pain.paperWidth())              // don't draw right of workarea
92                 return;
93
94         const_iterator it = begin(), et = end();
95
96         if (it == et) {
97                 pi.pain.rectangle(x, y - ascent_, width_, height(), LColor::mathline);
98                 return;
99         }
100
101         for (; it != et; ++it) {
102                 MathInset const * p = it->nucleus();
103                 MathScriptInset const * q = (it + 1 == et) ? 0 : asScript(it);
104                 if (q) {
105                         q->draw(p, pi, x, y);
106                         x += q->width2(p);
107                         ++it;
108                 } else {
109                         p->draw(pi, x, y);
110                         x += p->width();
111                 }
112         }
113 }
114
115
116 void MathXArray::metricsT(TextMetricsInfo const & mi) const
117 {
118         //if (clean_)
119         //      return;
120
121         ascent_  = 0;
122         descent_ = 0;
123         width_   = 0;
124
125         for (const_iterator it = begin(); it != end(); ++it) {
126                 MathInset const * p = it->nucleus();
127                 MathScriptInset const * q = (it + 1 == end()) ? 0 : asScript(it);
128                 if (q) {
129                         q->metricsT(p, mi);
130                         ascent_  = max(ascent_,  q->ascent2(p));
131                         descent_ = max(descent_, q->descent2(p));
132                         width_  += q->width2(p);
133                         ++it;
134                 } else {
135                         p->metricsT(mi);
136                         ascent_  = max(ascent_,  p->ascent());
137                         descent_ = max(descent_, p->descent());
138                         width_  += p->width();
139                 }
140         }
141 }
142
143
144 void MathXArray::drawT(TextPainter & pain, int x, int y) const
145 {
146         //if (drawn_ && x == xo_ && y == yo_)
147         //      return;
148
149         //lyxerr << "x: " << x << " y: " << y << " " << pain.workAreaHeight() << endl;
150
151         xo_    = x;
152         yo_    = y;
153         drawn_ = true;
154
155         const_iterator it = begin(), et = end();
156
157         for (; it != et; ++it) {
158                 MathInset const * p = it->nucleus();
159                 MathScriptInset const * q = (it + 1 == et) ? 0 : asScript(it);
160                 if (q) {
161                         q->drawT(p, pain, x, y);
162                         x += q->width2(p);
163                         ++it;
164                 } else {
165                         p->drawT(pain, x, y);
166                         x += p->width();
167                 }
168         }
169 }
170
171
172 int MathXArray::pos2x(size_type targetpos) const
173 {
174         int x = 0;
175         const_iterator target = min(begin() + targetpos, end());
176         for (const_iterator it = begin(); it < target; ++it) {
177                 MathInset const * p = it->nucleus();
178                 MathScriptInset const * q = (it + 1 == end()) ? 0 : asScript(it);
179                 if (q) {
180                         ++it;
181                         if (it < target)
182                                 x += q->width2(p);
183                         else  // "half" position
184                                 x += q->dxx(p) + q->nwid(p);
185                 } else
186                         x += p->width();
187         }
188         return x;
189 }
190
191
192 MathArray::size_type MathXArray::x2pos(int targetx) const
193 {
194         const_iterator it = begin();
195         int lastx = 0;
196         int currx = 0;
197         for (; currx < targetx && it < end(); ++it) {
198                 lastx = currx;
199
200                 int wid = 0;
201                 MathInset const * p = it->nucleus();
202                 MathScriptInset const * q = 0;
203                 if (it + 1 != end())
204                         q = asScript(it);
205                 if (q) {
206                         wid = q->width2(p);
207                         ++it;
208                 } else
209                         wid = p->width();
210
211                 currx += wid;
212         }
213         if (abs(lastx - targetx) < abs(currx - targetx) && it != begin())
214                 --it;
215         return it - begin();
216 }
217
218
219 int MathXArray::dist(int x, int y) const
220 {
221         int xx = 0;
222         int yy = 0;
223
224         if (x < xo_)
225                 xx = xo_ - x;
226         else if (x > xo_ + width_)
227                 xx = x - xo_ - width_;
228
229         if (y < yo_ - ascent_)
230                 yy = yo_ - ascent_ - y;
231         else if (y > yo_ + descent_)
232                 yy = y - yo_ - descent_;
233
234         return xx + yy;
235 }
236
237
238 void MathXArray::boundingBox(int & x1, int & x2, int & y1, int & y2)
239 {
240         x1 = xo_;
241         x2 = xo_ + width_;
242         y1 = yo_ - ascent_;
243         y2 = yo_ + descent_;
244 }
245
246 /*
247 void MathXArray::findPos(MathPosFinder & f) const
248 {
249         double x = xo_;
250         double y = yo_;
251         for (const_iterator it = begin(); it < end(); ++it) {
252                 // check this position in the cell first
253                 f.visit(x, y);
254                 f.nextPos();
255
256                 // check inset
257                 MathInset const * p = it->nucleus();
258                 p->findPos(f);
259
260                 // move on
261                 MathScriptInset const * q = (it + 1 == end()) ? 0 : asScript(it);
262                 if (q) {
263                         x += q->width(p);
264                         f.nextPos();
265                         ++it;
266                 } else {
267                         x += p->width();
268                 }
269         }
270 }
271 */
272
273 void MathXArray::center(int & x, int & y) const
274 {
275         x = xo_ + width_ / 2;
276         y = yo_ + (descent_ - ascent_) / 2;
277 }
278
279
280 void MathXArray::towards(int & x, int & y) const
281 {
282         int cx = 0;
283         int cy = 0;
284         center(cx, cy);
285
286         double r = 1.0;
287         //int dist = (x - cx) * (x - cx) + (y - cy) * (y - cy);
288
289         x = cx + int(r * (x - cx));
290         y = cy + int(r * (y - cy));
291 }