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