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"
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
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
26 // _+__-----------+ OuterCurve
27 // OuterP_2 __---- | OuterL_1 |
29 // __--- | OuterL_2 | |
30 // OuterP_3 _-- | | W_1 | W_0
34 // | \ | InnerL_2|____-------+ InnerCurve
35 // | \ |____----+ InnerP_0
36 // | . \ __---+ InnerP_1
44 // OuterP_{n-1} +--------+ InnerP_{n-1}
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
60 // __+---#| | |######|
61 // _+---##|####| | |######|
62 // _-- |#####|#####| | |#####|
63 // _+ |#####|#####| | |#####|
64 // / \ |#####|####| | |#####|
65 // / \ |####|#####| | |#####|
66 // | \ |####|####| |____-+-----+ InnerCurve
67 // | \ |####|____+---+
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
;
92 // Control points for the outer curve and the inner curve.
108 // innerSectionBezier
109 Bezier outerSectionBezier
;
110 Bezier innerSectionBezier
;
112 Result(const Bezier
& aOuterSectionBezier
, const Bezier
& aInnerSectionBezier
)
113 : outerSectionBezier(aOuterSectionBezier
),
114 innerSectionBezier(aInnerSectionBezier
) {}
118 // |<----------------->|
120 // --+-------------___---+--
123 // | | / | | aBorderWidthH
127 // aCornerDim.height | || _-
139 DashedCornerFinder(const Bezier
& aOuterBezier
, const Bezier
& aInnerBezier
,
140 Float aBorderWidthH
, Float aBorderWidthV
,
141 const Size
& aCornerDim
);
143 bool HasMore(void) const;
147 static const size_t MAX_LOOP
= 32;
149 // Bezier control points for the outer curve and the inner curve.
151 // ___---+ outer curve
157 // | __--+ inner curve
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
;
183 // The maximum number of segments.
188 // |<----------------->|
190 // --+-------------___---+--
193 // | | / + | top-width
197 // radius.height | || _-
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
219 // |<---------------------->|
221 // --+------------------------+--
222 // ^ | | | top-width / 2
224 // | | circle's ___---+--
227 // radius.height | | | + | +--
236 // --+----+----+--------------+
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
253 // Determine mType from parameters.
254 void DetermineType(Float aBorderWidthH
, Float aBorderWidthV
);
256 // Reset calculation.
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_ */