Backed out changeset 496886cb30a5 (bug 1867152) for bc failures on browser_user_input...
[gecko.git] / layout / painting / DashedCornerFinder.h
blob3a409d19f70ecf21c9e135be5a37def138fb9440
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_DashedCornerFinder_h_
8 #define mozilla_DashedCornerFinder_h_
10 #include "mozilla/gfx/2D.h"
11 #include "mozilla/gfx/BezierUtils.h"
13 namespace mozilla {
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
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
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.
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 // +--------+
84 class DashedCornerFinder {
85 typedef mozilla::gfx::Bezier Bezier;
86 typedef mozilla::gfx::Float Float;
87 typedef mozilla::gfx::Point Point;
88 typedef mozilla::gfx::Size Size;
90 public:
91 struct Result {
92 // Control points for the outer curve and the inner curve.
94 // outerSectionBezier
95 // |
96 // v _+ 3
97 // ___---#|
98 // 0 +---#######|
99 // |###########|
100 // |###########|
101 // |##########|
102 // |##########|
103 // |#########|
104 // |#####____+ 3
105 // 0 +----
106 // ^
107 // |
108 // innerSectionBezier
109 Bezier outerSectionBezier;
110 Bezier innerSectionBezier;
112 Result(const Bezier& aOuterSectionBezier, const Bezier& aInnerSectionBezier)
113 : outerSectionBezier(aOuterSectionBezier),
114 innerSectionBezier(aInnerSectionBezier) {}
117 // aCornerDim.width
118 // |<----------------->|
119 // | |
120 // --+-------------___---+--
121 // ^ | __-- | ^
122 // | | _- | |
123 // | | / | | aBorderWidthH
124 // | | / | |
125 // | | | | v
126 // | | | __--+--
127 // aCornerDim.height | || _-
128 // | || /
129 // | | /
130 // | | |
131 // | | |
132 // | | |
133 // | | |
134 // v | |
135 // --+---------+
136 // | |
137 // |<------->|
138 // aBorderWidthV
139 DashedCornerFinder(const Bezier& aOuterBezier, const Bezier& aInnerBezier,
140 Float aBorderWidthH, Float aBorderWidthV,
141 const Size& aCornerDim);
143 bool HasMore(void) const;
144 Result Next(void);
146 private:
147 static const size_t MAX_LOOP = 32;
149 // Bezier control points for the outer curve and the inner curve.
151 // ___---+ outer curve
152 // __-- |
153 // _- |
154 // / |
155 // / |
156 // | |
157 // | __--+ inner curve
158 // | _-
159 // | /
160 // | /
161 // | |
162 // | |
163 // | |
164 // | |
165 // | |
166 // +---------+
167 Bezier mOuterBezier;
168 Bezier mInnerBezier;
170 Point mLastOuterP;
171 Point mLastInnerP;
172 Float mLastOuterT;
173 Float mLastInnerT;
175 // Length for each segment, ratio of the border width at that point.
176 Float mBestDashLength;
178 // If one of border-widths is 0, do not calculate mBestDashLength, and draw
179 // segments until it reaches the other side or exceeds mMaxCount.
180 bool mHasZeroBorderWidth;
181 bool mHasMore;
183 // The maximum number of segments.
184 size_t mMaxCount;
186 enum {
187 // radius.width
188 // |<----------------->|
189 // | |
190 // --+-------------___---+--
191 // ^ | __-- | ^
192 // | | _- | |
193 // | | / + | top-width
194 // | | / | |
195 // | | | | v
196 // | | | __--+--
197 // radius.height | || _-
198 // | || /
199 // | | /
200 // | | |
201 // | | |
202 // | | |
203 // | | |
204 // v | |
205 // --+----+----+
206 // | |
207 // |<------->|
208 // left-width
210 // * top-width == left-width
211 // * radius.width == radius.height
212 // * top-width < radius.width * 2
214 // Split the perfect circle's arc into 2n segments, each segment's length is
215 // top-width * dashLength. Then split the inner curve and the outer curve
216 // with same angles.
218 // radius.width
219 // |<---------------------->|
220 // | | v
221 // --+------------------------+--
222 // ^ | | | top-width / 2
223 // | | perfect | |
224 // | | circle's ___---+--
225 // | | arc __-+ | ^
226 // | | | _- | |
227 // radius.height | | | + | +--
228 // | | | / \ | |
229 // | | | | \ | |
230 // | | | | \ | |
231 // | | +->| \ | |
232 // | | +---__ \ | |
233 // | | | --__ \ | |
234 // | | | ---__ \ | |
235 // v | | --_\||
236 // --+----+----+--------------+
237 // | | |
238 // |<-->| |
239 // left-width / 2
240 PERFECT,
242 // Other cases.
244 // Split the outer curve and the inner curve into 2n segments, each segment
245 // satisfies following:
246 // (OuterL_i + InnerL_i) / 2 == dashLength * (W_i + W_{i-1}) / 2
247 OTHER
248 } mType;
250 size_t mI;
251 size_t mCount;
253 // Determine mType from parameters.
254 void DetermineType(Float aBorderWidthH, Float aBorderWidthV);
256 // Reset calculation.
257 void Reset(void);
259 // Find next segment.
260 Float FindNext(Float dashLength);
262 // Find mBestDashLength for parameters.
263 void FindBestDashLength(Float aMinBorderWidth, Float aMaxBorderWidth,
264 Float aMinBorderRadius, Float aMaxBorderRadius);
266 // Fill corner with dashes with given dash length, and return the number of
267 // segments and last segment's dash length.
268 bool GetCountAndLastDashLength(Float aDashLength, size_t* aCount,
269 Float* aActualDashLength);
272 } // namespace mozilla
274 #endif /* mozilla_DashedCornerFinder_h_ */