]> git.lyx.org Git - lyx.git/blob - src/mathed/math_xdata.C
speed up math drawing
[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         if (data_.empty()) {
82                 pain.rectangle(x, y - ascent_, width_, height(), LColor::mathline);
83                 return;
84         }
85
86         for (const_iterator it = begin(); it != end(); ++it) {
87                 MathInset const * p = it->nucleus();
88                 MathScriptInset const * q = (it + 1 == end()) ? 0 : asScript(it);
89                 if (q) {
90                         q->draw(p, pain, x, y);
91                         x += q->width2(p);
92                         ++it;
93                 } else {
94                         p->draw(pain, x, y);
95                         x += p->width();
96                 }
97         }
98 }
99
100
101 int MathXArray::pos2x(size_type targetpos) const
102 {
103         int x = 0;
104         const_iterator target = min(begin() + targetpos, end());
105         for (const_iterator it = begin(); it < target; ++it) {
106                 MathInset const * p = it->nucleus();
107                 MathScriptInset const * q = (it + 1 == end()) ? 0 : asScript(it);
108                 if (q) {
109                         ++it;
110                         if (it < target)
111                                 x += q->width2(p);
112                         else  // "half" position
113                                 x += q->dxx(p) + q->nwid(p);
114                 } else
115                         x += p->width();
116         }
117         return x;
118 }
119
120
121 MathArray::size_type MathXArray::x2pos(int targetx) const
122 {
123         const_iterator it = begin();
124         int lastx = 0;
125         int currx = 0;
126         for (; currx < targetx && it < end(); ++it) {
127                 lastx = currx;
128
129                 int wid = 0;
130                 MathInset const * p = it->nucleus();
131                 MathScriptInset const * q = 0;
132                 if (it + 1 != end())
133                         q = asScript(it);
134                 if (q) {
135                         wid = q->width2(p);
136                         ++it;
137                 } else
138                         wid = p->width();
139
140                 currx += wid;
141         }
142         if (abs(lastx - targetx) < abs(currx - targetx) && it != begin())
143                 --it;
144         return it - begin();
145 }
146
147
148 int MathXArray::dist(int x, int y) const
149 {
150         int xx = 0;
151         int yy = 0;
152
153         if (x < xo_)
154                 xx = xo_ - x;
155         else if (x > xo_ + width_)
156                 xx = x - xo_ - width_;
157
158         if (y < yo_ - ascent_)
159                 yy = yo_ - ascent_ - y;
160         else if (y > yo_ + descent_)
161                 yy = y - yo_ - descent_;
162
163         return xx + yy; 
164 }
165
166
167 void MathXArray::boundingBox(int & x1, int & x2, int & y1, int & y2)
168 {
169         x1 = xo_;
170         x2 = xo_ + width_;
171         y1 = yo_ - ascent_;
172         y2 = yo_ + descent_;
173 }
174
175 /*
176 void MathXArray::findPos(MathPosFinder & f) const
177 {
178         double x = xo_;
179         double y = yo_; 
180         for (const_iterator it = begin(); it < end(); ++it) {
181                 // check this position in the cell first
182                 f.visit(x, y);
183                 f.nextPos();
184
185                 // check inset
186                 MathInset const * p = it->nucleus();
187                 p->findPos(f);
188
189                 // move on
190                 MathScriptInset const * q = (it + 1 == end()) ? 0 : asScript(it);
191                 if (q) {
192                         x += q->width(p);
193                         f.nextPos();
194                         ++it;
195                 } else {
196                         x += p->width();
197                 }
198         }
199 }
200 */
201
202 void MathXArray::center(int & x, int & y) const
203 {
204         x = xo_ + width_ / 2;
205         y = yo_ + (descent_ - ascent_) / 2;
206 }
207
208
209 void MathXArray::towards(int & x, int & y) const
210 {
211         int cx = 0;
212         int cy = 0;
213         center(cx, cy);
214
215         double r = 1.0;
216         //int dist = (x - cx) * (x - cx) + (y - cy) * (y - cy);
217
218         x = cx + int(r * (x - cx));
219         y = cy + int(r * (y - cy));
220 }