]> git.lyx.org Git - lyx.git/blob - src/mathed/math_xdata.C
fix typo that put too many include paths for most people
[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 "Painter.h"
10 #include "textpainter.h"
11 #include "debug.h"
12
13
14 using std::max;
15 using std::min;
16
17
18 extern MathScriptInset const * asScript(MathArray::const_iterator it);
19
20
21 MathXArray::MathXArray()
22         : width_(0), ascent_(0), descent_(0), xo_(0), yo_(0), size_(),
23           clean_(false), drawn_(false)
24 {}
25
26
27 void MathXArray::touch() const
28 {
29         clean_  = false;
30         drawn_  = false;
31 }
32
33
34 void MathXArray::metrics(MathMetricsInfo const & mi) const
35 {
36         //if (clean_)
37         //      return;
38
39         size_   = mi;
40         clean_  = true;
41         drawn_  = false;
42
43         if (data_.empty()) {
44                 LyXFont font;
45                 whichFont(font, LM_TC_VAR, mi);
46                 mathed_char_dim(font, 'I', ascent_, descent_, width_);
47                 return;
48         }
49
50         ascent_  = 0;
51         descent_ = 0;
52         width_   = 0;
53
54         for (const_iterator it = begin(); it != end(); ++it) {
55                 MathInset const * p = it->nucleus();
56                 MathScriptInset const * q = (it + 1 == end()) ? 0 : asScript(it);
57                 if (q) {
58                         q->metrics(p, mi);
59                         ascent_  = max(ascent_,  q->ascent2(p));
60                         descent_ = max(descent_, q->descent2(p));
61                         width_  += q->width2(p);
62                         ++it;
63                 } else {
64                         p->metrics(mi);
65                         ascent_  = max(ascent_,  p->ascent());
66                         descent_ = max(descent_, p->descent());
67                         width_  += p->width();
68                 }
69         }
70         //lyxerr << "MathXArray::metrics(): '" << ascent_ << " "
71         //      << descent_ << " " << width_ << "'\n";
72 }
73
74
75 void MathXArray::draw(Painter & pain, int x, int y) const
76 {
77         //if (drawn_ && x == xo_ && y == yo_)
78         //      return;
79
80         //lyxerr << "x: " << x << " y: " << y << " " << pain.workAreaHeight() << endl;
81
82         xo_    = x;
83         yo_    = y;
84         drawn_ = true;
85
86         if (y + descent_ <= 0)                   // don't draw above the workarea
87                 return;
88         if (y - ascent_ >= pain.paperHeight())   // don't draw below the workarea
89                 return;
90         if (x + width_ <= 0)                     // don't draw left of workarea
91                 return;
92         if (x >= pain.paperWidth())              // don't draw right of workarea
93                 return;
94
95         const_iterator it = begin(), et = end();
96
97         if (it == et) {
98                 pain.rectangle(x, y - ascent_, width_, height(), LColor::mathline);
99                 return;
100         }
101
102         for (; it != et; ++it) {
103                 MathInset const * p = it->nucleus();
104                 MathScriptInset const * q = (it + 1 == et) ? 0 : asScript(it);
105                 if (q) {
106                         q->draw(p, pain, x, y);
107                         x += q->width2(p);
108                         ++it;
109                 } else {
110                         p->draw(pain, x, y);
111                         x += p->width();
112                 }
113         }
114 }
115
116
117 void MathXArray::metricsT(TextMetricsInfo const & mi) const
118 {
119         //if (clean_)
120         //      return;
121
122         ascent_  = 0;
123         descent_ = 0;
124         width_   = 0;
125
126         for (const_iterator it = begin(); it != end(); ++it) {
127                 MathInset const * p = it->nucleus();
128                 MathScriptInset const * q = (it + 1 == end()) ? 0 : asScript(it);
129                 if (q) {
130                         q->metricsT(p, mi);
131                         ascent_  = max(ascent_,  q->ascent2(p));
132                         descent_ = max(descent_, q->descent2(p));
133                         width_  += q->width2(p);
134                         ++it;
135                 } else {
136                         p->metricsT(mi);
137                         ascent_  = max(ascent_,  p->ascent());
138                         descent_ = max(descent_, p->descent());
139                         width_  += p->width();
140                 }
141         }
142 }
143
144
145 void MathXArray::drawT(TextPainter & pain, int x, int y) const
146 {
147         //if (drawn_ && x == xo_ && y == yo_)
148         //      return;
149
150         //lyxerr << "x: " << x << " y: " << y << " " << pain.workAreaHeight() << endl;
151
152         xo_    = x;
153         yo_    = y;
154         drawn_ = true;
155
156         const_iterator it = begin(), et = end();
157
158         for (; it != et; ++it) {
159                 MathInset const * p = it->nucleus();
160                 MathScriptInset const * q = (it + 1 == et) ? 0 : asScript(it);
161                 if (q) {
162                         q->drawT(p, pain, x, y);
163                         x += q->width2(p);
164                         ++it;
165                 } else {
166                         p->drawT(pain, x, y);
167                         x += p->width();
168                 }
169         }
170 }
171
172
173 int MathXArray::pos2x(size_type targetpos) const
174 {
175         int x = 0;
176         const_iterator target = min(begin() + targetpos, end());
177         for (const_iterator it = begin(); it < target; ++it) {
178                 MathInset const * p = it->nucleus();
179                 MathScriptInset const * q = (it + 1 == end()) ? 0 : asScript(it);
180                 if (q) {
181                         ++it;
182                         if (it < target)
183                                 x += q->width2(p);
184                         else  // "half" position
185                                 x += q->dxx(p) + q->nwid(p);
186                 } else
187                         x += p->width();
188         }
189         return x;
190 }
191
192
193 MathArray::size_type MathXArray::x2pos(int targetx) const
194 {
195         const_iterator it = begin();
196         int lastx = 0;
197         int currx = 0;
198         for (; currx < targetx && it < end(); ++it) {
199                 lastx = currx;
200
201                 int wid = 0;
202                 MathInset const * p = it->nucleus();
203                 MathScriptInset const * q = 0;
204                 if (it + 1 != end())
205                         q = asScript(it);
206                 if (q) {
207                         wid = q->width2(p);
208                         ++it;
209                 } else
210                         wid = p->width();
211
212                 currx += wid;
213         }
214         if (abs(lastx - targetx) < abs(currx - targetx) && it != begin())
215                 --it;
216         return it - begin();
217 }
218
219
220 int MathXArray::dist(int x, int y) const
221 {
222         int xx = 0;
223         int yy = 0;
224
225         if (x < xo_)
226                 xx = xo_ - x;
227         else if (x > xo_ + width_)
228                 xx = x - xo_ - width_;
229
230         if (y < yo_ - ascent_)
231                 yy = yo_ - ascent_ - y;
232         else if (y > yo_ + descent_)
233                 yy = y - yo_ - descent_;
234
235         return xx + yy;
236 }
237
238
239 void MathXArray::boundingBox(int & x1, int & x2, int & y1, int & y2)
240 {
241         x1 = xo_;
242         x2 = xo_ + width_;
243         y1 = yo_ - ascent_;
244         y2 = yo_ + descent_;
245 }
246
247 /*
248 void MathXArray::findPos(MathPosFinder & f) const
249 {
250         double x = xo_;
251         double y = yo_;
252         for (const_iterator it = begin(); it < end(); ++it) {
253                 // check this position in the cell first
254                 f.visit(x, y);
255                 f.nextPos();
256
257                 // check inset
258                 MathInset const * p = it->nucleus();
259                 p->findPos(f);
260
261                 // move on
262                 MathScriptInset const * q = (it + 1 == end()) ? 0 : asScript(it);
263                 if (q) {
264                         x += q->width(p);
265                         f.nextPos();
266                         ++it;
267                 } else {
268                         x += p->width();
269                 }
270         }
271 }
272 */
273
274 void MathXArray::center(int & x, int & y) const
275 {
276         x = xo_ + width_ / 2;
277         y = yo_ + (descent_ - ascent_) / 2;
278 }
279
280
281 void MathXArray::towards(int & x, int & y) const
282 {
283         int cx = 0;
284         int cy = 0;
285         center(cx, cy);
286
287         double r = 1.0;
288         //int dist = (x - cx) * (x - cx) + (y - cy) * (y - cy);
289
290         x = cx + int(r * (x - cx));
291         y = cy + int(r * (y - cy));
292 }