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