/src/mozilla-central/layout/painting/DashedCornerFinder.h
Line | Count | Source (jump to first uncovered line) |
1 | | /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ |
2 | | /* vim: set ts=8 sts=2 et sw=2 tw=80: */ |
3 | | /* This Source Code Form is subject to the terms of the Mozilla Public |
4 | | * License, v. 2.0. If a copy of the MPL was not distributed with this |
5 | | * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ |
6 | | |
7 | | #ifndef mozilla_DashedCornerFinder_h_ |
8 | | #define mozilla_DashedCornerFinder_h_ |
9 | | |
10 | | #include "mozilla/gfx/2D.h" |
11 | | #include "mozilla/gfx/BezierUtils.h" |
12 | | |
13 | | namespace mozilla { |
14 | | |
15 | | // Calculate {OuterT_i, InnerT_i} for each 1 < i < n, that |
16 | | // (OuterL_i + InnerL_i) / 2 == dashLength * (W_i + W_{i-1}) / 2 |
17 | | // where |
18 | | // OuterP_i: OuterCurve(OuterT_i) |
19 | | // InnerP_i: InnerCurve(OuterT_i) |
20 | | // OuterL_i: Elliptic arc length between OuterP_i - OuterP_{i-1} |
21 | | // InnerL_i: Elliptic arc length between InnerP_i - InnerP_{i-1} |
22 | | // W_i = |OuterP_i - InnerP_i| |
23 | | // 1.0 < dashLength < 3.0 |
24 | | // |
25 | | // OuterP_1 OuterP_0 |
26 | | // _+__-----------+ OuterCurve |
27 | | // OuterP_2 __---- | OuterL_1 | |
28 | | // __+--- | | |
29 | | // __--- | OuterL_2 | | |
30 | | // OuterP_3 _-- | | W_1 | W_0 |
31 | | // _+ | | | |
32 | | // / \ W_2 | | | |
33 | | // / \ | | InnerL_1 | |
34 | | // | \ | InnerL_2|____-------+ InnerCurve |
35 | | // | \ |____----+ InnerP_0 |
36 | | // | . \ __---+ InnerP_1 |
37 | | // | \ / InnerP_2 |
38 | | // | . /+ InnerP_3 |
39 | | // | | |
40 | | // | . | |
41 | | // | | |
42 | | // | | |
43 | | // | | |
44 | | // OuterP_{n-1} +--------+ InnerP_{n-1} |
45 | | // | | |
46 | | // | | |
47 | | // | | |
48 | | // | | |
49 | | // | | |
50 | | // OuterP_n +--------+ InnerP_n |
51 | | // |
52 | | // Returns region with [OuterCurve((OuterT_{2j} + OuterT_{2j-1}) / 2), |
53 | | // OuterCurve((OuterT_{2j} + OuterT_{2j-1}) / 2), |
54 | | // InnerCurve((OuterT_{2j} + OuterT_{2j+1}) / 2), |
55 | | // InnerCurve((OuterT_{2j} + OuterT_{2j+1}) / 2)], |
56 | | // to start and end with half segment. |
57 | | // |
58 | | // _+__----+------+ OuterCurve |
59 | | // _+---- | |######| |
60 | | // __+---#| | |######| |
61 | | // _+---##|####| | |######| |
62 | | // _-- |#####|#####| | |#####| |
63 | | // _+ |#####|#####| | |#####| |
64 | | // / \ |#####|####| | |#####| |
65 | | // / \ |####|#####| | |#####| |
66 | | // | \ |####|####| |____-+-----+ InnerCurve |
67 | | // | \ |####|____+---+ |
68 | | // | . \ __+---+ |
69 | | // | \ / |
70 | | // | . /+ |
71 | | // | | |
72 | | // | . | |
73 | | // | | |
74 | | // | | |
75 | | // | | |
76 | | // +--------+ |
77 | | // | | |
78 | | // | | |
79 | | // +--------+ |
80 | | // |########| |
81 | | // |########| |
82 | | // +--------+ |
83 | | |
84 | | class DashedCornerFinder |
85 | | { |
86 | | typedef mozilla::gfx::Bezier Bezier; |
87 | | typedef mozilla::gfx::Float Float; |
88 | | typedef mozilla::gfx::Point Point; |
89 | | typedef mozilla::gfx::Size Size; |
90 | | |
91 | | public: |
92 | | struct Result |
93 | | { |
94 | | // Control points for the outer curve and the inner curve. |
95 | | // |
96 | | // outerSectionBezier |
97 | | // | |
98 | | // v _+ 3 |
99 | | // ___---#| |
100 | | // 0 +---#######| |
101 | | // |###########| |
102 | | // |###########| |
103 | | // |##########| |
104 | | // |##########| |
105 | | // |#########| |
106 | | // |#####____+ 3 |
107 | | // 0 +---- |
108 | | // ^ |
109 | | // | |
110 | | // innerSectionBezier |
111 | | Bezier outerSectionBezier; |
112 | | Bezier innerSectionBezier; |
113 | | |
114 | | Result(const Bezier& aOuterSectionBezier, const Bezier& aInnerSectionBezier) |
115 | | : outerSectionBezier(aOuterSectionBezier) |
116 | | , innerSectionBezier(aInnerSectionBezier) |
117 | 0 | { |
118 | 0 | } |
119 | | }; |
120 | | |
121 | | // aCornerDim.width |
122 | | // |<----------------->| |
123 | | // | | |
124 | | // --+-------------___---+-- |
125 | | // ^ | __-- | ^ |
126 | | // | | _- | | |
127 | | // | | / | | aBorderWidthH |
128 | | // | | / | | |
129 | | // | | | | v |
130 | | // | | | __--+-- |
131 | | // aCornerDim.height | || _- |
132 | | // | || / |
133 | | // | | / |
134 | | // | | | |
135 | | // | | | |
136 | | // | | | |
137 | | // | | | |
138 | | // v | | |
139 | | // --+---------+ |
140 | | // | | |
141 | | // |<------->| |
142 | | // aBorderWidthV |
143 | | DashedCornerFinder(const Bezier& aOuterBezier, |
144 | | const Bezier& aInnerBezier, |
145 | | Float aBorderWidthH, |
146 | | Float aBorderWidthV, |
147 | | const Size& aCornerDim); |
148 | | |
149 | | bool HasMore(void) const; |
150 | | Result Next(void); |
151 | | |
152 | | private: |
153 | | static const size_t MAX_LOOP = 32; |
154 | | |
155 | | // Bezier control points for the outer curve and the inner curve. |
156 | | // |
157 | | // ___---+ outer curve |
158 | | // __-- | |
159 | | // _- | |
160 | | // / | |
161 | | // / | |
162 | | // | | |
163 | | // | __--+ inner curve |
164 | | // | _- |
165 | | // | / |
166 | | // | / |
167 | | // | | |
168 | | // | | |
169 | | // | | |
170 | | // | | |
171 | | // | | |
172 | | // +---------+ |
173 | | Bezier mOuterBezier; |
174 | | Bezier mInnerBezier; |
175 | | |
176 | | Point mLastOuterP; |
177 | | Point mLastInnerP; |
178 | | Float mLastOuterT; |
179 | | Float mLastInnerT; |
180 | | |
181 | | // Length for each segment, ratio of the border width at that point. |
182 | | Float mBestDashLength; |
183 | | |
184 | | // If one of border-widths is 0, do not calculate mBestDashLength, and draw |
185 | | // segments until it reaches the other side or exceeds mMaxCount. |
186 | | bool mHasZeroBorderWidth; |
187 | | bool mHasMore; |
188 | | |
189 | | // The maximum number of segments. |
190 | | size_t mMaxCount; |
191 | | |
192 | | enum |
193 | | { |
194 | | // radius.width |
195 | | // |<----------------->| |
196 | | // | | |
197 | | // --+-------------___---+-- |
198 | | // ^ | __-- | ^ |
199 | | // | | _- | | |
200 | | // | | / + | top-width |
201 | | // | | / | | |
202 | | // | | | | v |
203 | | // | | | __--+-- |
204 | | // radius.height | || _- |
205 | | // | || / |
206 | | // | | / |
207 | | // | | | |
208 | | // | | | |
209 | | // | | | |
210 | | // | | | |
211 | | // v | | |
212 | | // --+----+----+ |
213 | | // | | |
214 | | // |<------->| |
215 | | // left-width |
216 | | |
217 | | // * top-width == left-width |
218 | | // * radius.width == radius.height |
219 | | // * top-width < radius.width * 2 |
220 | | // |
221 | | // Split the perfect circle's arc into 2n segments, each segment's length is |
222 | | // top-width * dashLength. Then split the inner curve and the outer curve |
223 | | // with same angles. |
224 | | // |
225 | | // radius.width |
226 | | // |<---------------------->| |
227 | | // | | v |
228 | | // --+------------------------+-- |
229 | | // ^ | | | top-width / 2 |
230 | | // | | perfect | | |
231 | | // | | circle's ___---+-- |
232 | | // | | arc __-+ | ^ |
233 | | // | | | _- | | |
234 | | // radius.height | | | + | +-- |
235 | | // | | | / \ | | |
236 | | // | | | | \ | | |
237 | | // | | | | \ | | |
238 | | // | | +->| \ | | |
239 | | // | | +---__ \ | | |
240 | | // | | | --__ \ | | |
241 | | // | | | ---__ \ | | |
242 | | // v | | --_\|| |
243 | | // --+----+----+--------------+ |
244 | | // | | | |
245 | | // |<-->| | |
246 | | // left-width / 2 |
247 | | PERFECT, |
248 | | |
249 | | // Other cases. |
250 | | // |
251 | | // Split the outer curve and the inner curve into 2n segments, each segment |
252 | | // satisfies following: |
253 | | // (OuterL_i + InnerL_i) / 2 == dashLength * (W_i + W_{i-1}) / 2 |
254 | | OTHER |
255 | | } mType; |
256 | | |
257 | | size_t mI; |
258 | | size_t mCount; |
259 | | |
260 | | // Determine mType from parameters. |
261 | | void DetermineType(Float aBorderWidthH, Float aBorderWidthV); |
262 | | |
263 | | // Reset calculation. |
264 | | void Reset(void); |
265 | | |
266 | | // Find next segment. |
267 | | Float FindNext(Float dashLength); |
268 | | |
269 | | // Find mBestDashLength for parameters. |
270 | | void FindBestDashLength(Float aMinBorderWidth, |
271 | | Float aMaxBorderWidth, |
272 | | Float aMinBorderRadius, |
273 | | Float aMaxBorderRadius); |
274 | | |
275 | | // Fill corner with dashes with given dash length, and return the number of |
276 | | // segments and last segment's dash length. |
277 | | bool GetCountAndLastDashLength(Float aDashLength, |
278 | | size_t* aCount, |
279 | | Float* aActualDashLength); |
280 | | }; |
281 | | |
282 | | } // namespace mozilla |
283 | | |
284 | | #endif /* mozilla_DashedCornerFinder_h_ */ |