]> git.lyx.org Git - lyx.git/blob - src/mathed/math_xdata.C
move things around
[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<Dimension> & 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                         v.push_back(d);
93                         v.push_back(Dimension());
94                         ++it;
95                 } else {
96                         p->metrics(mi);
97                         p->dimensions(d);
98                         v.push_back(d);
99                 }
100         }
101         //for (int i = 0; i < data_.size(); ++i)
102         //      lyxerr << "i: " << i << "  dim: " << v[i] << endl;
103         //lyxerr << "MathXArray::metrics(): '" << dim_ << "\n";
104 }
105
106
107 void MathXArray::draw(MathPainterInfo & pi, int x, int y) const
108 {
109         //if (drawn_ && x == xo_ && y == yo_)
110         //      return;
111
112         //lyxerr << "x: " << x << " y: " << y << " " << pain.workAreaHeight() << endl;
113
114         xo_    = x;
115         yo_    = y;
116         drawn_ = true;
117
118         if (y + descent() <= 0)                   // don't draw above the workarea
119                 return;
120         if (y - ascent() >= pi.pain.paperHeight())   // don't draw below the workarea
121                 return;
122         if (x + width() <= 0)                     // don't draw left of workarea
123                 return;
124         if (x >= pi.pain.paperWidth())              // don't draw right of workarea
125                 return;
126
127         const_iterator it = begin(), et = end();
128
129         if (it == et) {
130                 pi.pain.rectangle(x, y - ascent(), width(), height(), LColor::mathline);
131                 return;
132         }
133
134         for (; it != et; ++it) {
135                 MathInset const * p = it->nucleus();
136                 MathScriptInset const * q = (it + 1 == et) ? 0 : asScript(it);
137                 if (q) {
138                         q->draw(p, pi, x, y);
139                         x += q->width2(p);
140                         ++it;
141                 } else {
142                         p->draw(pi, x, y);
143                         x += p->width();
144                 }
145         }
146 }
147
148
149 void MathXArray::drawExternal(MathPainterInfo & pi, int x, int y,
150         std::vector<Row> const & v) const
151 {
152         //for (size_type r = 0; r < v.size(); ++r)
153         //      lyxerr << "row " << r << " to: " << v[r].end << endl; 
154         //lyxerr << " data: " << data_ << endl;
155
156         xo_    = x;
157         yo_    = y;
158
159         for (size_type r = 0; r < v.size(); ++r) {
160                 int xx = x;
161                 int yy = y + v[r].yo;
162                 for (size_type pos = v[r].begin; pos < v[r].end && pos < data_.size(); ++pos) {
163                         //lyxerr << "drawing pos " << pos << " of " << data_.size() 
164                         //      << " " << int(data_[pos]->getChar()) << endl;
165                         MathInset const * p = data_[pos].nucleus();
166                 
167                         // insert extra glue
168                         if (p->getChar() == ' ') 
169                                 xx += v[r].glue;
170         
171                         MathScriptInset const * q = 0;
172                         if (pos + 1 < data_.size())
173                                 q = asScript(begin() + pos);
174                         if (q) {
175                                 q->draw(p, pi, xx, yy);
176                                 xx += q->width2(p);
177                                 ++pos;
178                         } else {
179                                 p->draw(pi, xx, yy);
180                                 xx += p->width();
181                         }
182                 }
183         }
184 }
185
186
187 Dimension const & MathXArray::metricsT(TextMetricsInfo const & mi) const
188 {
189         //if (clean_)
190         //      return;
191         dim_.clear();
192         for (const_iterator it = begin(); it != end(); ++it) {
193                 MathInset const * p = it->nucleus();
194                 MathScriptInset const * q = (it + 1 == end()) ? 0 : asScript(it);
195                 Dimension d;
196                 if (q) {
197                         q->metricsT(p, mi);
198                         q->dimensions2(p, d);
199                         ++it;
200                 } else {
201                         p->metricsT(mi);
202                         p->dimensions(d);
203                 }
204                 dim_ += d;
205         }
206         return dim_;
207 }
208
209
210 void MathXArray::drawT(TextPainter & pain, int x, int y) const
211 {
212         //if (drawn_ && x == xo_ && y == yo_)
213         //      return;
214
215         //lyxerr << "x: " << x << " y: " << y << " " << pain.workAreaHeight() << endl;
216
217         xo_    = x;
218         yo_    = y;
219         drawn_ = true;
220
221         const_iterator it = begin(), et = end();
222
223         for (; it != et; ++it) {
224                 MathInset const * p = it->nucleus();
225                 MathScriptInset const * q = (it + 1 == et) ? 0 : asScript(it);
226                 if (q) {
227                         q->drawT(p, pain, x, y);
228                         x += q->width2(p);
229                         ++it;
230                 } else {
231                         p->drawT(pain, x, y);
232                         x += p->width();
233                 }
234         }
235 }
236
237
238 int MathXArray::pos2x(size_type pos) const
239 {
240         return pos2x(0, pos, 0);
241 }
242
243
244 int MathXArray::pos2x(size_type pos1, size_type pos2, int glue) const
245 {
246         int x = 0;
247         size_type target = min(pos2, data_.size());
248         for (size_type i = pos1; i < target; ++i) {
249                 const_iterator it = begin() + i;
250                 MathInset const * p = it->nucleus();
251                 if (p->getChar() == ' ')
252                         x += glue;
253                 MathScriptInset const * q = (i + 1 == data_.size()) ? 0 : asScript(it);
254                 if (q) {
255                         ++i;
256                         if (i < target)
257                                 x += q->width2(p);
258                         else  // "half" position
259                                 x += q->dxx(p) + q->nwid(p);
260                 } else
261                         x += p->width();
262         }
263         return x;
264 }
265
266
267 MathArray::size_type MathXArray::x2pos(int targetx) const
268 {
269         return x2pos(0, targetx, 0);
270 }
271
272
273 MathArray::size_type MathXArray::x2pos(size_type startpos, int targetx,
274         int glue) const
275 {
276         const_iterator it = begin() + startpos;
277         int lastx = 0;
278         int currx = 0;
279         for (; currx < targetx && it < end(); ++it) {
280                 size_type pos = it - begin();
281                 lastx = currx;
282
283                 MathInset const * p = it->nucleus();
284                 if (p->getChar() == ' ')
285                         currx += glue;
286                 MathScriptInset const * q = 0;
287                 if (it + 1 != end())
288                         q = asScript(it);
289                 if (q) {
290                         currx += q->width2(p);
291                         ++it;
292                 } else {
293                         currx += p->width();
294                 }
295         }
296         if (abs(lastx - targetx) < abs(currx - targetx) && it != begin() + startpos)
297                 --it;
298         return it - begin();
299 }
300
301
302 int MathXArray::dist(int x, int y) const
303 {
304         int xx = 0;
305         int yy = 0;
306
307         if (x < xo_)
308                 xx = xo_ - x;
309         else if (x > xo_ + width())
310                 xx = x - xo_ - width();
311
312         if (y < yo_ - ascent())
313                 yy = yo_ - ascent() - y;
314         else if (y > yo_ + descent())
315                 yy = y - yo_ - descent();
316
317         return xx + yy;
318 }
319
320
321 void MathXArray::boundingBox(int & x1, int & x2, int & y1, int & y2)
322 {
323         x1 = xo_;
324         x2 = xo_ + width();
325         y1 = yo_ - ascent();
326         y2 = yo_ + descent();
327 }
328
329 /*
330 void MathXArray::findPos(MathPosFinder & f) const
331 {
332         double x = xo_;
333         double y = yo_;
334         for (const_iterator it = begin(); it < end(); ++it) {
335                 // check this position in the cell first
336                 f.visit(x, y);
337                 f.nextPos();
338
339                 // check inset
340                 MathInset const * p = it->nucleus();
341                 p->findPos(f);
342
343                 // move on
344                 MathScriptInset const * q = (it + 1 == end()) ? 0 : asScript(it);
345                 if (q) {
346                         x += q->width(p);
347                         f.nextPos();
348                         ++it;
349                 } else {
350                         x += p->width();
351                 }
352         }
353 }
354 */
355
356 void MathXArray::center(int & x, int & y) const
357 {
358         x = xo_ + width() / 2;
359         y = yo_ + (descent() - ascent()) / 2;
360 }
361
362
363 void MathXArray::towards(int & x, int & y) const
364 {
365         int cx = 0;
366         int cy = 0;
367         center(cx, cy);
368
369         double r = 1.0;
370         //int dist = (x - cx) * (x - cx) + (y - cy) * (y - cy);
371
372         x = cx + int(r * (x - cx));
373         y = cy + int(r * (y - cy));
374 }