]> git.lyx.org Git - lyx.git/blob - src/mathed/math_xdata.C
small cleanup
[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),
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         width_   = 0;
50
51         int a = 0;
52         int d = 0;
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                 int w = 0;
57                 if (q) {
58                         q->metrics(p, mi);
59                         a = max(a, q->ascent2(p));
60                         d = max(d, q->descent2(p));
61                         w = q->width2(p);
62                         ++it;
63                 } else {
64                         p->metrics(mi);
65                         a = max(a, p->ascent());
66                         d = max(d, p->descent());
67                         w = p->width();
68                 }
69                 width_ += w;
70         }
71
72         ascent_  = a;
73         descent_ = d;
74         //width_   = 0;
75
76         //lyxerr << "MathXArray::metrics(): '" << ascent_ << " "
77         //      << descent_ << " " << width_ << "'\n";
78
79
80         //
81         // re-break paragraph
82         //
83         if (mi.base.restrictwidth) {
84                 width_ = mi.base.textwidth;
85                 lyxerr << "restricting width to " << width_ << " pixel\n";
86         }
87 }
88
89
90 void MathXArray::draw(MathPainterInfo & pi, int x, int y) const
91 {
92         //if (drawn_ && x == xo_ && y == yo_)
93         //      return;
94
95         //lyxerr << "x: " << x << " y: " << y << " " << pain.workAreaHeight() << endl;
96
97         xo_    = x;
98         yo_    = y;
99         drawn_ = true;
100
101         if (y + descent_ <= 0)                   // don't draw above the workarea
102                 return;
103         if (y - ascent_ >= pi.pain.paperHeight())   // don't draw below the workarea
104                 return;
105         if (x + width_ <= 0)                     // don't draw left of workarea
106                 return;
107         if (x >= pi.pain.paperWidth())              // don't draw right of workarea
108                 return;
109
110         const_iterator it = begin(), et = end();
111
112         if (it == et) {
113                 pi.pain.rectangle(x, y - ascent_, width_, height(), LColor::mathline);
114                 return;
115         }
116
117         for (; it != et; ++it) {
118                 MathInset const * p = it->nucleus();
119                 MathScriptInset const * q = (it + 1 == et) ? 0 : asScript(it);
120                 if (q) {
121                         q->draw(p, pi, x, y);
122                         x += q->width2(p);
123                         ++it;
124                 } else {
125                         p->draw(pi, x, y);
126                         x += p->width();
127                 }
128         }
129
130         //
131         // re-break paragraph
132         //
133         if (pi.base.restrictwidth) {
134         }
135 }
136
137
138 void MathXArray::metricsT(TextMetricsInfo const & mi) const
139 {
140         //if (clean_)
141         //      return;
142
143         ascent_  = 0;
144         descent_ = 0;
145         width_   = 0;
146
147         for (const_iterator it = begin(); it != end(); ++it) {
148                 MathInset const * p = it->nucleus();
149                 MathScriptInset const * q = (it + 1 == end()) ? 0 : asScript(it);
150                 if (q) {
151                         q->metricsT(p, mi);
152                         ascent_  = max(ascent_,  q->ascent2(p));
153                         descent_ = max(descent_, q->descent2(p));
154                         width_  += q->width2(p);
155                         ++it;
156                 } else {
157                         p->metricsT(mi);
158                         ascent_  = max(ascent_,  p->ascent());
159                         descent_ = max(descent_, p->descent());
160                         width_  += p->width();
161                 }
162         }
163 }
164
165
166 void MathXArray::drawT(TextPainter & pain, int x, int y) const
167 {
168         //if (drawn_ && x == xo_ && y == yo_)
169         //      return;
170
171         //lyxerr << "x: " << x << " y: " << y << " " << pain.workAreaHeight() << endl;
172
173         xo_    = x;
174         yo_    = y;
175         drawn_ = true;
176
177         const_iterator it = begin(), et = end();
178
179         for (; it != et; ++it) {
180                 MathInset const * p = it->nucleus();
181                 MathScriptInset const * q = (it + 1 == et) ? 0 : asScript(it);
182                 if (q) {
183                         q->drawT(p, pain, x, y);
184                         x += q->width2(p);
185                         ++it;
186                 } else {
187                         p->drawT(pain, x, y);
188                         x += p->width();
189                 }
190         }
191 }
192
193
194 int MathXArray::pos2x(size_type targetpos) const
195 {
196         int x = 0;
197         const_iterator target = min(begin() + targetpos, end());
198         for (const_iterator it = begin(); it < target; ++it) {
199                 MathInset const * p = it->nucleus();
200                 MathScriptInset const * q = (it + 1 == end()) ? 0 : asScript(it);
201                 if (q) {
202                         ++it;
203                         if (it < target)
204                                 x += q->width2(p);
205                         else  // "half" position
206                                 x += q->dxx(p) + q->nwid(p);
207                 } else
208                         x += p->width();
209         }
210         return x;
211 }
212
213
214 MathArray::size_type MathXArray::x2pos(int targetx) const
215 {
216         const_iterator it = begin();
217         int lastx = 0;
218         int currx = 0;
219         for (; currx < targetx && it < end(); ++it) {
220                 lastx = currx;
221
222                 int wid = 0;
223                 MathInset const * p = it->nucleus();
224                 MathScriptInset const * q = 0;
225                 if (it + 1 != end())
226                         q = asScript(it);
227                 if (q) {
228                         wid = q->width2(p);
229                         ++it;
230                 } else
231                         wid = p->width();
232
233                 currx += wid;
234         }
235         if (abs(lastx - targetx) < abs(currx - targetx) && it != begin())
236                 --it;
237         return it - begin();
238 }
239
240
241 int MathXArray::dist(int x, int y) const
242 {
243         int xx = 0;
244         int yy = 0;
245
246         if (x < xo_)
247                 xx = xo_ - x;
248         else if (x > xo_ + width_)
249                 xx = x - xo_ - width_;
250
251         if (y < yo_ - ascent_)
252                 yy = yo_ - ascent_ - y;
253         else if (y > yo_ + descent_)
254                 yy = y - yo_ - descent_;
255
256         return xx + yy;
257 }
258
259
260 void MathXArray::boundingBox(int & x1, int & x2, int & y1, int & y2)
261 {
262         x1 = xo_;
263         x2 = xo_ + width_;
264         y1 = yo_ - ascent_;
265         y2 = yo_ + descent_;
266 }
267
268 /*
269 void MathXArray::findPos(MathPosFinder & f) const
270 {
271         double x = xo_;
272         double y = yo_;
273         for (const_iterator it = begin(); it < end(); ++it) {
274                 // check this position in the cell first
275                 f.visit(x, y);
276                 f.nextPos();
277
278                 // check inset
279                 MathInset const * p = it->nucleus();
280                 p->findPos(f);
281
282                 // move on
283                 MathScriptInset const * q = (it + 1 == end()) ? 0 : asScript(it);
284                 if (q) {
285                         x += q->width(p);
286                         f.nextPos();
287                         ++it;
288                 } else {
289                         x += p->width();
290                 }
291         }
292 }
293 */
294
295 void MathXArray::center(int & x, int & y) const
296 {
297         x = xo_ + width_ / 2;
298         y = yo_ + (descent_ - ascent_) / 2;
299 }
300
301
302 void MathXArray::towards(int & x, int & y) const
303 {
304         int cx = 0;
305         int cy = 0;
306         center(cx, cy);
307
308         double r = 1.0;
309         //int dist = (x - cx) * (x - cx) + (y - cy) * (y - cy);
310
311         x = cx + int(r * (x - cx));
312         y = cy + int(r * (y - cy));
313 }