]> git.lyx.org Git - lyx.git/blob - src/mathed/math_xdata.C
traversing math tables should be at least as fast as for ordinary table by
[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 "debug.h"
11
12
13 using std::max;
14 using std::min;
15
16
17 extern MathScriptInset const * asScript(MathArray::const_iterator it);
18
19
20 MathXArray::MathXArray()
21         : width_(0), ascent_(0), descent_(0), xo_(0), yo_(0), size_(),
22           clean_(false), drawn_(false)
23 {}
24
25
26 void MathXArray::touch() const
27 {       
28         clean_  = false;
29         drawn_  = false;
30 }
31
32
33 void MathXArray::metrics(MathMetricsInfo const & mi) const
34 {
35         if (clean_)
36                 return;
37
38         size_   = mi;
39         clean_  = true;
40         drawn_  = false;
41
42         if (data_.empty()) {
43                 mathed_char_dim(LM_TC_VAR, mi, 'I', ascent_, descent_, width_);
44                 return;
45         }
46
47         ascent_  = 0;
48         descent_ = 0;
49         width_   = 0;
50
51         for (const_iterator it = begin(); it != end(); ++it) {
52                 MathInset const * p = it->nucleus();
53                 MathScriptInset const * q = (it + 1 == end()) ? 0 : asScript(it);
54                 if (q) {
55                         q->metrics(p, mi);
56                         ascent_  = max(ascent_,  q->ascent2(p));
57                         descent_ = max(descent_, q->descent2(p));
58                         width_  += q->width2(p);        
59                         ++it;
60                 } else {
61                         p->metrics(mi);
62                         ascent_  = max(ascent_,  p->ascent());
63                         descent_ = max(descent_, p->descent());
64                         width_  += p->width();  
65                 }
66         }
67         //lyxerr << "MathXArray::metrics(): '" << ascent_ << " " 
68         //      << descent_ << " " << width_ << "'\n";
69 }
70
71
72 void MathXArray::draw(Painter & pain, int x, int y) const
73 {
74         //if (drawn_ && x == xo_ && y == yo_)
75         //      return;
76
77         xo_    = x;
78         yo_    = y;
79         drawn_ = true;
80
81         const_iterator it = begin(), et = end();
82
83         if (it == et) {
84                 pain.rectangle(x, y - ascent_, width_, height(), LColor::mathline);
85                 return;
86         }
87
88         for (; it != et; ++it) {
89                 MathInset const * p = it->nucleus();
90                 MathScriptInset const * q = (it + 1 == et) ? 0 : asScript(it);
91                 if (q) {
92                         q->draw(p, pain, x, y);
93                         x += q->width2(p);
94                         ++it;
95                 } else {
96                         p->draw(pain, x, y);
97                         x += p->width();
98                 }
99         }
100 }
101
102
103 int MathXArray::pos2x(size_type targetpos) const
104 {
105         int x = 0;
106         const_iterator target = min(begin() + targetpos, end());
107         for (const_iterator it = begin(); it < target; ++it) {
108                 MathInset const * p = it->nucleus();
109                 MathScriptInset const * q = (it + 1 == end()) ? 0 : asScript(it);
110                 if (q) {
111                         ++it;
112                         if (it < target)
113                                 x += q->width2(p);
114                         else  // "half" position
115                                 x += q->dxx(p) + q->nwid(p);
116                 } else
117                         x += p->width();
118         }
119         return x;
120 }
121
122
123 MathArray::size_type MathXArray::x2pos(int targetx) const
124 {
125         const_iterator it = begin();
126         int lastx = 0;
127         int currx = 0;
128         for (; currx < targetx && it < end(); ++it) {
129                 lastx = currx;
130
131                 int wid = 0;
132                 MathInset const * p = it->nucleus();
133                 MathScriptInset const * q = 0;
134                 if (it + 1 != end())
135                         q = asScript(it);
136                 if (q) {
137                         wid = q->width2(p);
138                         ++it;
139                 } else
140                         wid = p->width();
141
142                 currx += wid;
143         }
144         if (abs(lastx - targetx) < abs(currx - targetx) && it != begin())
145                 --it;
146         return it - begin();
147 }
148
149
150 int MathXArray::dist(int x, int y) const
151 {
152         int xx = 0;
153         int yy = 0;
154
155         if (x < xo_)
156                 xx = xo_ - x;
157         else if (x > xo_ + width_)
158                 xx = x - xo_ - width_;
159
160         if (y < yo_ - ascent_)
161                 yy = yo_ - ascent_ - y;
162         else if (y > yo_ + descent_)
163                 yy = y - yo_ - descent_;
164
165         return xx + yy; 
166 }
167
168
169 void MathXArray::boundingBox(int & x1, int & x2, int & y1, int & y2)
170 {
171         x1 = xo_;
172         x2 = xo_ + width_;
173         y1 = yo_ - ascent_;
174         y2 = yo_ + descent_;
175 }
176
177 /*
178 void MathXArray::findPos(MathPosFinder & f) const
179 {
180         double x = xo_;
181         double y = yo_; 
182         for (const_iterator it = begin(); it < end(); ++it) {
183                 // check this position in the cell first
184                 f.visit(x, y);
185                 f.nextPos();
186
187                 // check inset
188                 MathInset const * p = it->nucleus();
189                 p->findPos(f);
190
191                 // move on
192                 MathScriptInset const * q = (it + 1 == end()) ? 0 : asScript(it);
193                 if (q) {
194                         x += q->width(p);
195                         f.nextPos();
196                         ++it;
197                 } else {
198                         x += p->width();
199                 }
200         }
201 }
202 */
203
204 void MathXArray::center(int & x, int & y) const
205 {
206         x = xo_ + width_ / 2;
207         y = yo_ + (descent_ - ascent_) / 2;
208 }
209
210
211 void MathXArray::towards(int & x, int & y) const
212 {
213         int cx = 0;
214         int cy = 0;
215         center(cx, cy);
216
217         double r = 1.0;
218         //int dist = (x - cx) * (x - cx) + (y - cy) * (y - cy);
219
220         x = cx + int(r * (x - cx));
221         y = cy + int(r * (y - cy));
222 }