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