no bug - Import translations from android-l10n r=release a=l10n CLOSED TREE
[gecko.git] / layout / painting / DottedCornerFinder.h
blobfd3a9e5d047883fd1b71932c090a9a8781359094
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/. */
7 #ifndef mozilla_DottedCornerFinder_h_
8 #define mozilla_DottedCornerFinder_h_
10 #include "mozilla/gfx/2D.h"
11 #include "mozilla/gfx/BezierUtils.h"
12 #include "gfxRect.h"
14 namespace mozilla {
16 // Calculate C_i and r_i for each filled/unfilled circles in dotted corner.
17 // Returns circle with C_{2j} and r_{2j} where 0 < 2j < n.
19 // ____-----------+
20 // __---- ***** ###|
21 // __---- ********* ####|
22 // __--- ##### ***********#####|
23 // _-- ######### *****+*****#####+ C_0
24 // _- ########### *** C_1****#####|
25 // / #####+##### ********* ####|
26 // / . ### C_2 ### ***** ###|
27 // | ######### ____-------+
28 // | . #####____-----
29 // | __----
30 // | . /
31 // | /
32 // | ***** |
33 // | ******* |
34 // |*********|
35 // |****+****|
36 // | C_{n-1} |
37 // | ******* |
38 // | ***** |
39 // | ##### |
40 // | ####### |
41 // |#########|
42 // +----+----+
43 // C_n
45 class DottedCornerFinder {
46 typedef mozilla::gfx::Bezier Bezier;
47 typedef mozilla::gfx::Float Float;
48 typedef mozilla::gfx::Point Point;
49 typedef mozilla::gfx::Size Size;
51 public:
52 struct Result {
53 // Center point of dot and its radius.
54 Point C;
55 Float r;
57 Result(const Point& aC, Float aR) : C(aC), r(aR) { MOZ_ASSERT(aR >= 0); }
60 // aBorderRadiusX
61 // aCornerDim.width
62 // |<----------------->|
63 // | | v
64 // --+-------------___---+--
65 // ^ | __-- | |
66 // | | _- | | aR0
67 // | | / aC0 +--
68 // | | / | ^
69 // | | | |
70 // aBorderRadiusY | | | __--+
71 // aCornerDim.height | || _-
72 // | || /
73 // | | /
74 // | | |
75 // | | |
76 // | | |
77 // | | |
78 // v | aCn |
79 // --+----+----+
80 // | |
81 // |<-->|
82 // aRn
84 // aCornerDim and (aBorderRadiusX, aBorderRadiusY) can be different when
85 // aBorderRadiusX is smaller than aRn*2 or
86 // aBorderRadiusY is smaller than aR0*2.
88 // aCornerDim.width
89 // |<----------------->|
90 // | |
91 // | aBorderRadiusX |
92 // |<--------->| |
93 // | | |
94 // -------------------+-------__--+-------+--
95 // ^ ^ | _- | ^
96 // | | | / | |
97 // | | | / | |
98 // | aBorderRadiusY | | | | | aR0
99 // | | || | |
100 // | | | | |
101 // aCornerDim.height | v | | v
102 // | --+ aC0 +--
103 // | | |
104 // | | |
105 // | | |
106 // | | |
107 // | | |
108 // v | aCn |
109 // -------------------+---------+---------+
110 // | |
111 // |<------->|
112 // aRn
113 DottedCornerFinder(const Bezier& aOuterBezier, const Bezier& aInnerBezier,
114 mozilla::Corner aCorner, Float aBorderRadiusX,
115 Float aBorderRadiusY, const Point& aC0, Float aR0,
116 const Point& aCn, Float aRn, const Size& aCornerDim);
118 bool HasMore(void) const;
119 Result Next(void);
121 private:
122 static const size_t MAX_LOOP = 32;
124 // Bezier control points for the outer curve, the inner curve, and a curve
125 // that center points of circles are on (center curve).
127 // ___---+ outer curve
128 // __-- |
129 // _- |
130 // / __---+ center curve
131 // / __-- |
132 // | / |
133 // | / __--+ inner curve
134 // | | _-
135 // | | /
136 // | | /
137 // | | |
138 // | | |
139 // | | |
140 // | | |
141 // | | |
142 // +----+----+
143 Bezier mOuterBezier;
144 Bezier mInnerBezier;
145 Bezier mCenterBezier;
147 mozilla::Corner mCorner;
149 // Sign of the normal vector used in radius calculation, flipped depends on
150 // corner and start and end radii.
151 Float mNormalSign;
153 // Center points and raii for start and end circles, mR0 >= mRn.
154 // mMaxR = max(mR0, mRn)
156 // v
157 // ___---+------
158 // __-- #|# | mRn
159 // _- ##|## |
160 // / ##+## ---
161 // / mCn ^
162 // | #|#
163 // | __--+
164 // | _-
165 // | /
166 // | /
167 // | |
168 // | |
169 // | ##### |
170 // | ####### |
171 // |#########|
172 // +----+----+
173 // |## mC0 ##|
174 // | ####### |
175 // | ##### |
176 // | |
177 // |<-->|
179 // mR0
181 Point mC0;
182 Point mCn;
183 Float mR0;
184 Float mRn;
185 Float mMaxR;
187 // Parameters for the center curve with perfect circle and the inner curve.
188 // The center curve doesn't necessarily share the origin with others.
190 // ___---+
191 // __-- |
192 // _- |
193 // / __-+ |
194 // / __-- |
195 // | / |
196 // | / __--+--
197 // | | _- | ^
198 // | | / | |
199 // | | / | |
200 // | | | | |
201 // | | | | | mInnerHeight
202 // | | | | |
203 // | + | | |
204 // | | | v
205 // +---------+---------+
206 // | | mInnerCurveOrigin
207 // |<------->|
208 // mInnerWidth
210 // ___---+
211 // __--
212 // _-
213 // / __-+
214 // / __-- |
215 // | / |
216 // | / __--+
217 // | | _- |
218 // | | / |
219 // | | / |
220 // | | | |
221 // | | | |
222 // | | | |
223 // | +--- | ------+
224 // | | | | mCenterCurveOrigin
225 // + | + |
226 // | |
227 // | |
228 // | |
229 // | |
230 // |<---------->|
231 // mCenterCurveR
233 Point mCenterCurveOrigin;
234 Float mCenterCurveR;
235 Point mInnerCurveOrigin;
236 Float mInnerWidth;
237 Float mInnerHeight;
239 Point mLastC;
240 Float mLastR;
241 Float mLastT;
243 // Overlap between two circles.
244 // It uses arc length on PERFECT, SINGLE_CURVE_AND_RADIUS, and SINGLE_CURVE,
245 // and direct distance on OTHER.
246 Float mBestOverlap;
248 // If one of border-widths is 0, do not calculate overlap, and draw circles
249 // until it reaches the other side or exceeds mMaxCount.
250 bool mHasZeroBorderWidth;
251 bool mHasMore;
253 // The maximum number of filled/unfilled circles.
254 size_t mMaxCount;
256 enum {
257 // radius.width
258 // |<----------------->|
259 // | |
260 // --+-------------___---+----
261 // ^ | __-- #|# ^
262 // | | _- ##|## |
263 // | | / ##+## | top-width
264 // | | / ##|## |
265 // | | | #|# v
266 // | | | __--+----
267 // radius.height | || _-
268 // | || /
269 // | | /
270 // | | |
271 // | | |
272 // | | ##### |
273 // | | ####### |
274 // v |#########|
275 // --+----+----+
276 // |#########|
277 // | ####### |
278 // | ##### |
279 // | |
280 // |<------->|
281 // left-width
283 // * top-width == left-width
284 // * radius.width == radius.height
285 // * top-width < radius.width * 2
287 // All circles has same radii and are on single perfect circle's arc.
288 // Overlap is known.
290 // Split the perfect circle's arc into 2n segments, each segment's length is
291 // top-width * (1 - overlap). Place each circle's center point C_i on each
292 // end of the segment, each circle's radius r_i is top-width / 2
294 // #####
295 // #######
296 // perfect #########
297 // circle's ___---+####
298 // arc ##### __-- ## C_0 ##
299 // | #####_- ###|###
300 // | ####+#### ##|##
301 // | ##/C_i ## |
302 // | |###### |
303 // | | ##### |
304 // +->| |
305 // | |
306 // ##|## |
307 // ###|### |
308 // ####|#### |
309 // ####+-------------------+
310 // ## C_n ##
311 // #######
312 // #####
313 PERFECT,
315 // * top-width == left-width
316 // * 0.5 < radius.width / radius.height < 2.0
317 // * top-width < min(radius.width, radius.height) * 2
319 // All circles has same radii and are on single elliptic arc.
320 // Overlap is known.
322 // Split the elliptic arc into 2n segments, each segment's length is
323 // top-width * (1 - overlap). Place each circle's center point C_i on each
324 // end of the segment, each circle's radius r_i is top-width / 2
326 // #####
327 // #######
328 // ##### #########
329 // ####### ____----+####
330 // elliptic ######__--- ## C_0 ##
331 // arc ##__+-### ###|###
332 // | / # C_i # ##|##
333 // +--> / ##### |
334 // | |
335 // ###|# |
336 // ###|### |
337 // ####|#### |
338 // ####+------------------------+
339 // ## C_n ##
340 // #######
341 // #####
342 SINGLE_CURVE_AND_RADIUS,
344 // * top-width != left-width
345 // * 0 < min(top-width, left-width)
346 // * 0.5 < radius.width / radius.height < 2.0
347 // * max(top-width, left-width) < min(radius.width, radius.height) * 2
349 // All circles are on single elliptic arc.
350 // Overlap is unknown.
352 // Place each circle's center point C_i on elliptic arc, each circle's
353 // radius r_i is the distance between the center point and the inner curve.
354 // The arc segment's length between C_i and C_{i-1} is
355 // (r_i + r_{i-1}) * (1 - overlap).
357 // outer curve
358 // /
359 // /
360 // / / center curve
361 // / ####### /
362 // /## /#
363 // +# / #
364 // /# / #
365 // / # C_i / #
366 // / # + # /
367 // / # / \ # / inner curve
368 // # / \ #/
369 // # / r_i \+
370 // #/ ##/
371 // / ####### /
372 // /
373 SINGLE_CURVE,
375 // Other cases.
376 // Circles are not on single elliptic arc.
377 // Overlap are unknown.
379 // Place tangent point innerTangent on the inner curve and find circle's
380 // center point C_i and radius r_i where the circle is also tangent to the
381 // outer curve.
382 // Distance between C_i and C_{i-1} is (r_i + r_{i-1}) * (1 - overlap).
384 // outer curve
385 // /
386 // /
387 // /
388 // / #######
389 // /## ##
390 // +# #
391 // /# \ #
392 // / # \ #
393 // / # + # /
394 // / # C_i \ # / inner curve
395 // # \ #/
396 // # r_i \+
397 // ## ##/ innerTangent
398 // ####### /
399 // /
400 OTHER
401 } mType;
403 size_t mI;
404 size_t mCount;
406 // Determine mType from parameters.
407 void DetermineType(Float aBorderRadiusX, Float aBorderRadiusY);
409 // Reset calculation.
410 void Reset(void);
412 // Find radius for the given tangent point on the inner curve such that the
413 // circle is also tangent to the outer curve.
414 void FindPointAndRadius(Point& C, Float& r, const Point& innerTangent,
415 const Point& normal, Float t);
417 // Find next dot.
418 Float FindNext(Float overlap);
420 // Find mBestOverlap for parameters.
421 void FindBestOverlap(Float aMinR, Float aMinBorderRadius,
422 Float aMaxBorderRadius);
424 // Fill corner with dots with given overlap, and return the number of dots
425 // and last two dots's overlap.
426 bool GetCountAndLastOverlap(Float aOverlap, size_t* aCount,
427 Float* aActualOverlap);
430 } // namespace mozilla
432 #endif /* mozilla_DottedCornerFinder_h_ */