]> git.lyx.org Git - lyx.git/blob - src/mathed/math_xdata.C
some more changes
[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         : xo_(0), yo_(0), clean_(false), drawn_(false)
24 {}
25
26
27 void MathXArray::touch() const
28 {
29         clean_  = false;
30         drawn_  = false;
31 }
32
33
34 Dimension const & MathXArray::metrics(MathMetricsInfo & mi) const
35 {
36         //if (clean_)
37         //      return;
38
39         size_   = mi;
40         clean_  = true;
41         drawn_  = false;
42
43         if (data_.empty()) {
44                 mathed_char_dim(mi.base.font, 'I', dim_);
45                 return dim_;;
46         }
47
48         dim_.clear();
49         for (const_iterator it = begin(); it != end(); ++it) {
50                 MathInset const * p = it->nucleus();
51                 MathScriptInset const * q = (it + 1 == end()) ? 0 : asScript(it);
52                 Dimension d;
53                 if (q) {
54                         q->metrics(p, mi);
55                         q->dimensions2(p, d);
56                         ++it;
57                 } else {
58                         p->metrics(mi);
59                         p->dimensions(d);
60                 }
61                 dim_ += d;
62         }
63
64         //lyxerr << "MathXArray::metrics(): '" << dim_ << "\n";
65         return dim_;
66 }
67
68
69 void MathXArray::metricsExternal(MathMetricsInfo & mi,
70         std::vector<Row> & v) const
71 {
72         //if (clean_)
73         //      return;
74
75         size_   = mi;
76         clean_  = true;
77         drawn_  = false;
78
79         if (data_.empty()) {
80                 mathed_char_dim(mi.base.font, 'I', dim_);
81                 return;
82         }
83
84         dim_.clear();
85         for (const_iterator it = begin(); it != end(); ++it) {
86                 MathInset const * p = it->nucleus();
87                 MathScriptInset const * q = (it + 1 == end()) ? 0 : asScript(it);
88                 Dimension d;
89                 if (q) {
90                         q->metrics(p, mi);
91                         q->dimensions2(p, d);
92                         ++it;
93                         v.push_back(Row());
94                         v.back().dim = d;
95                         v.push_back(Row());
96                 } else {
97                         p->metrics(mi);
98                         p->dimensions(d);
99                         v.push_back(Row());
100                         v.back().dim = d;
101                 }
102         }
103
104         //lyxerr << "MathXArray::metrics(): '" << dim_ << "\n";
105 }
106
107
108 void MathXArray::draw(MathPainterInfo & pi, int x, int y) const
109 {
110         //if (drawn_ && x == xo_ && y == yo_)
111         //      return;
112
113         //lyxerr << "x: " << x << " y: " << y << " " << pain.workAreaHeight() << endl;
114
115         xo_    = x;
116         yo_    = y;
117         drawn_ = true;
118
119         if (y + descent() <= 0)                   // don't draw above the workarea
120                 return;
121         if (y - ascent() >= pi.pain.paperHeight())   // don't draw below the workarea
122                 return;
123         if (x + width() <= 0)                     // don't draw left of workarea
124                 return;
125         if (x >= pi.pain.paperWidth())              // don't draw right of workarea
126                 return;
127
128         const_iterator it = begin(), et = end();
129
130         if (it == et) {
131                 pi.pain.rectangle(x, y - ascent(), width(), height(), LColor::mathline);
132                 return;
133         }
134
135         for (; it != et; ++it) {
136                 MathInset const * p = it->nucleus();
137                 MathScriptInset const * q = (it + 1 == et) ? 0 : asScript(it);
138                 if (q) {
139                         q->draw(p, pi, x, y);
140                         x += q->width2(p);
141                         ++it;
142                 } else {
143                         p->draw(pi, x, y);
144                         x += p->width();
145                 }
146         }
147 }
148
149
150 void MathXArray::drawExternal(MathPainterInfo & pi, int x, int y,
151         std::vector<Row> const & v) const
152 {
153         for (size_type r = 0, pos = 0; r != v.size(); ++r) {
154                 int xx = x;
155                 int yy = y + v[r].yo;
156                 for ( ; pos != v[r].end; ++pos) {
157                         MathInset const * p = data_[pos].nucleus();
158                         MathScriptInset const * q = 0;
159                         if (pos + 1 != data_.size())
160                                 q = asScript(begin() + pos + 1);
161                         if (q) {
162                                 q->draw(p, pi, xx, yy);
163                                 xx += q->width2(p);
164                                 ++pos;
165                         } else {
166                                 p->draw(pi, xx, yy);
167                                 xx += p->width();
168                         }
169                 }
170         }
171 }
172
173
174 Dimension const & MathXArray::metricsT(TextMetricsInfo const & mi) const
175 {
176         //if (clean_)
177         //      return;
178         dim_.clear();
179         for (const_iterator it = begin(); it != end(); ++it) {
180                 MathInset const * p = it->nucleus();
181                 MathScriptInset const * q = (it + 1 == end()) ? 0 : asScript(it);
182                 Dimension d;
183                 if (q) {
184                         q->metricsT(p, mi);
185                         q->dimensions2(p, d);
186                         ++it;
187                 } else {
188                         p->metricsT(mi);
189                         p->dimensions(d);
190                 }
191                 dim_ += d;
192         }
193         return dim_;
194 }
195
196
197 void MathXArray::drawT(TextPainter & pain, int x, int y) const
198 {
199         //if (drawn_ && x == xo_ && y == yo_)
200         //      return;
201
202         //lyxerr << "x: " << x << " y: " << y << " " << pain.workAreaHeight() << endl;
203
204         xo_    = x;
205         yo_    = y;
206         drawn_ = true;
207
208         const_iterator it = begin(), et = end();
209
210         for (; it != et; ++it) {
211                 MathInset const * p = it->nucleus();
212                 MathScriptInset const * q = (it + 1 == et) ? 0 : asScript(it);
213                 if (q) {
214                         q->drawT(p, pain, x, y);
215                         x += q->width2(p);
216                         ++it;
217                 } else {
218                         p->drawT(pain, x, y);
219                         x += p->width();
220                 }
221         }
222 }
223
224
225 int MathXArray::pos2x(size_type targetpos) const
226 {
227         int x = 0;
228         const_iterator target = min(begin() + targetpos, end());
229         for (const_iterator it = begin(); it < target; ++it) {
230                 MathInset const * p = it->nucleus();
231                 MathScriptInset const * q = (it + 1 == end()) ? 0 : asScript(it);
232                 if (q) {
233                         ++it;
234                         if (it < target)
235                                 x += q->width2(p);
236                         else  // "half" position
237                                 x += q->dxx(p) + q->nwid(p);
238                 } else
239                         x += p->width();
240         }
241         return x;
242 }
243
244
245 MathArray::size_type MathXArray::x2pos(int targetx) const
246 {
247         const_iterator it = begin();
248         int lastx = 0;
249         int currx = 0;
250         for (; currx < targetx && it < end(); ++it) {
251                 lastx = currx;
252
253                 int wid = 0;
254                 MathInset const * p = it->nucleus();
255                 MathScriptInset const * q = 0;
256                 if (it + 1 != end())
257                         q = asScript(it);
258                 if (q) {
259                         wid = q->width2(p);
260                         ++it;
261                 } else
262                         wid = p->width();
263
264                 currx += wid;
265         }
266         if (abs(lastx - targetx) < abs(currx - targetx) && it != begin())
267                 --it;
268         return it - begin();
269 }
270
271
272 int MathXArray::dist(int x, int y) const
273 {
274         int xx = 0;
275         int yy = 0;
276
277         if (x < xo_)
278                 xx = xo_ - x;
279         else if (x > xo_ + width())
280                 xx = x - xo_ - width();
281
282         if (y < yo_ - ascent())
283                 yy = yo_ - ascent() - y;
284         else if (y > yo_ + descent())
285                 yy = y - yo_ - descent();
286
287         return xx + yy;
288 }
289
290
291 void MathXArray::boundingBox(int & x1, int & x2, int & y1, int & y2)
292 {
293         x1 = xo_;
294         x2 = xo_ + width();
295         y1 = yo_ - ascent();
296         y2 = yo_ + descent();
297 }
298
299 /*
300 void MathXArray::findPos(MathPosFinder & f) const
301 {
302         double x = xo_;
303         double y = yo_;
304         for (const_iterator it = begin(); it < end(); ++it) {
305                 // check this position in the cell first
306                 f.visit(x, y);
307                 f.nextPos();
308
309                 // check inset
310                 MathInset const * p = it->nucleus();
311                 p->findPos(f);
312
313                 // move on
314                 MathScriptInset const * q = (it + 1 == end()) ? 0 : asScript(it);
315                 if (q) {
316                         x += q->width(p);
317                         f.nextPos();
318                         ++it;
319                 } else {
320                         x += p->width();
321                 }
322         }
323 }
324 */
325
326 void MathXArray::center(int & x, int & y) const
327 {
328         x = xo_ + width() / 2;
329         y = yo_ + (descent() - ascent()) / 2;
330 }
331
332
333 void MathXArray::towards(int & x, int & y) const
334 {
335         int cx = 0;
336         int cy = 0;
337         center(cx, cy);
338
339         double r = 1.0;
340         //int dist = (x - cx) * (x - cx) + (y - cy) * (y - cy);
341
342         x = cx + int(r * (x - cx));
343         y = cy + int(r * (y - cy));
344 }