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"
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.
21 // __---- ********* ####|
22 // __--- ##### ***********#####|
23 // _-- ######### *****+*****#####+ C_0
24 // _- ########### *** C_1****#####|
25 // / #####+##### ********* ####|
26 // / . ### C_2 ### ***** ###|
27 // | ######### ____-------+
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
;
53 // Center point of dot and its radius.
57 Result(const Point
& aC
, Float aR
) : C(aC
), r(aR
) { MOZ_ASSERT(aR
>= 0); }
62 // |<----------------->|
64 // --+-------------___---+--
70 // aBorderRadiusY | | | __--+
71 // aCornerDim.height | || _-
84 // aCornerDim and (aBorderRadiusX, aBorderRadiusY) can be different when
85 // aBorderRadiusX is smaller than aRn*2 or
86 // aBorderRadiusY is smaller than aR0*2.
89 // |<----------------->|
94 // -------------------+-------__--+-------+--
98 // | aBorderRadiusY | | | | | aR0
101 // aCornerDim.height | v | | v
109 // -------------------+---------+---------+
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;
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
130 // / __---+ center curve
133 // | / __--+ inner curve
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.
153 // Center points and raii for start and end circles, mR0 >= mRn.
154 // mMaxR = max(mR0, mRn)
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.
201 // | | | | | mInnerHeight
205 // +---------+---------+
206 // | | mInnerCurveOrigin
224 // | | | | mCenterCurveOrigin
233 Point mCenterCurveOrigin
;
235 Point mInnerCurveOrigin
;
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.
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
;
253 // The maximum number of filled/unfilled circles.
258 // |<----------------->|
260 // --+-------------___---+----
263 // | | / ##+## | top-width
267 // radius.height | || _-
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.
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
297 // circle's ___---+####
298 // arc ##### __-- ## C_0 ##
309 // ####+-------------------+
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.
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
329 // ####### ____----+####
330 // elliptic ######__--- ## C_0 ##
331 // arc ##__+-### ###|###
338 // ####+------------------------+
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).
367 // / # / \ # / inner curve
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
382 // Distance between C_i and C_{i-1} is (r_i + r_{i-1}) * (1 - overlap).
394 // / # C_i \ # / inner curve
397 // ## ##/ innerTangent
406 // Determine mType from parameters.
407 void DetermineType(Float aBorderRadiusX
, Float aBorderRadiusY
);
409 // Reset calculation.
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
);
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_ */