summaryrefslogtreecommitdiffstats
path: root/layout/painting/DottedCornerFinder.h
diff options
context:
space:
mode:
Diffstat (limited to 'layout/painting/DottedCornerFinder.h')
-rw-r--r--layout/painting/DottedCornerFinder.h432
1 files changed, 432 insertions, 0 deletions
diff --git a/layout/painting/DottedCornerFinder.h b/layout/painting/DottedCornerFinder.h
new file mode 100644
index 0000000000..fd3a9e5d04
--- /dev/null
+++ b/layout/painting/DottedCornerFinder.h
@@ -0,0 +1,432 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=8 sts=2 et sw=2 tw=80: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifndef mozilla_DottedCornerFinder_h_
+#define mozilla_DottedCornerFinder_h_
+
+#include "mozilla/gfx/2D.h"
+#include "mozilla/gfx/BezierUtils.h"
+#include "gfxRect.h"
+
+namespace mozilla {
+
+// Calculate C_i and r_i for each filled/unfilled circles in dotted corner.
+// Returns circle with C_{2j} and r_{2j} where 0 < 2j < n.
+//
+// ____-----------+
+// __---- ***** ###|
+// __---- ********* ####|
+// __--- ##### ***********#####|
+// _-- ######### *****+*****#####+ C_0
+// _- ########### *** C_1****#####|
+// / #####+##### ********* ####|
+// / . ### C_2 ### ***** ###|
+// | ######### ____-------+
+// | . #####____-----
+// | __----
+// | . /
+// | /
+// | ***** |
+// | ******* |
+// |*********|
+// |****+****|
+// | C_{n-1} |
+// | ******* |
+// | ***** |
+// | ##### |
+// | ####### |
+// |#########|
+// +----+----+
+// C_n
+
+class DottedCornerFinder {
+ typedef mozilla::gfx::Bezier Bezier;
+ typedef mozilla::gfx::Float Float;
+ typedef mozilla::gfx::Point Point;
+ typedef mozilla::gfx::Size Size;
+
+ public:
+ struct Result {
+ // Center point of dot and its radius.
+ Point C;
+ Float r;
+
+ Result(const Point& aC, Float aR) : C(aC), r(aR) { MOZ_ASSERT(aR >= 0); }
+ };
+
+ // aBorderRadiusX
+ // aCornerDim.width
+ // |<----------------->|
+ // | | v
+ // --+-------------___---+--
+ // ^ | __-- | |
+ // | | _- | | aR0
+ // | | / aC0 +--
+ // | | / | ^
+ // | | | |
+ // aBorderRadiusY | | | __--+
+ // aCornerDim.height | || _-
+ // | || /
+ // | | /
+ // | | |
+ // | | |
+ // | | |
+ // | | |
+ // v | aCn |
+ // --+----+----+
+ // | |
+ // |<-->|
+ // aRn
+ //
+ // aCornerDim and (aBorderRadiusX, aBorderRadiusY) can be different when
+ // aBorderRadiusX is smaller than aRn*2 or
+ // aBorderRadiusY is smaller than aR0*2.
+ //
+ // aCornerDim.width
+ // |<----------------->|
+ // | |
+ // | aBorderRadiusX |
+ // |<--------->| |
+ // | | |
+ // -------------------+-------__--+-------+--
+ // ^ ^ | _- | ^
+ // | | | / | |
+ // | | | / | |
+ // | aBorderRadiusY | | | | | aR0
+ // | | || | |
+ // | | | | |
+ // aCornerDim.height | v | | v
+ // | --+ aC0 +--
+ // | | |
+ // | | |
+ // | | |
+ // | | |
+ // | | |
+ // v | aCn |
+ // -------------------+---------+---------+
+ // | |
+ // |<------->|
+ // aRn
+ DottedCornerFinder(const Bezier& aOuterBezier, const Bezier& aInnerBezier,
+ mozilla::Corner aCorner, Float aBorderRadiusX,
+ Float aBorderRadiusY, const Point& aC0, Float aR0,
+ const Point& aCn, Float aRn, const Size& aCornerDim);
+
+ bool HasMore(void) const;
+ Result Next(void);
+
+ private:
+ static const size_t MAX_LOOP = 32;
+
+ // Bezier control points for the outer curve, the inner curve, and a curve
+ // that center points of circles are on (center curve).
+ //
+ // ___---+ outer curve
+ // __-- |
+ // _- |
+ // / __---+ center curve
+ // / __-- |
+ // | / |
+ // | / __--+ inner curve
+ // | | _-
+ // | | /
+ // | | /
+ // | | |
+ // | | |
+ // | | |
+ // | | |
+ // | | |
+ // +----+----+
+ Bezier mOuterBezier;
+ Bezier mInnerBezier;
+ Bezier mCenterBezier;
+
+ mozilla::Corner mCorner;
+
+ // Sign of the normal vector used in radius calculation, flipped depends on
+ // corner and start and end radii.
+ Float mNormalSign;
+
+ // Center points and raii for start and end circles, mR0 >= mRn.
+ // mMaxR = max(mR0, mRn)
+ //
+ // v
+ // ___---+------
+ // __-- #|# | mRn
+ // _- ##|## |
+ // / ##+## ---
+ // / mCn ^
+ // | #|#
+ // | __--+
+ // | _-
+ // | /
+ // | /
+ // | |
+ // | |
+ // | ##### |
+ // | ####### |
+ // |#########|
+ // +----+----+
+ // |## mC0 ##|
+ // | ####### |
+ // | ##### |
+ // | |
+ // |<-->|
+ //
+ // mR0
+ //
+ Point mC0;
+ Point mCn;
+ Float mR0;
+ Float mRn;
+ Float mMaxR;
+
+ // Parameters for the center curve with perfect circle and the inner curve.
+ // The center curve doesn't necessarily share the origin with others.
+ //
+ // ___---+
+ // __-- |
+ // _- |
+ // / __-+ |
+ // / __-- |
+ // | / |
+ // | / __--+--
+ // | | _- | ^
+ // | | / | |
+ // | | / | |
+ // | | | | |
+ // | | | | | mInnerHeight
+ // | | | | |
+ // | + | | |
+ // | | | v
+ // +---------+---------+
+ // | | mInnerCurveOrigin
+ // |<------->|
+ // mInnerWidth
+ //
+ // ___---+
+ // __--
+ // _-
+ // / __-+
+ // / __-- |
+ // | / |
+ // | / __--+
+ // | | _- |
+ // | | / |
+ // | | / |
+ // | | | |
+ // | | | |
+ // | | | |
+ // | +--- | ------+
+ // | | | | mCenterCurveOrigin
+ // + | + |
+ // | |
+ // | |
+ // | |
+ // | |
+ // |<---------->|
+ // mCenterCurveR
+ //
+ Point mCenterCurveOrigin;
+ Float mCenterCurveR;
+ Point mInnerCurveOrigin;
+ Float mInnerWidth;
+ Float mInnerHeight;
+
+ Point mLastC;
+ Float mLastR;
+ Float mLastT;
+
+ // Overlap between two circles.
+ // It uses arc length on PERFECT, SINGLE_CURVE_AND_RADIUS, and SINGLE_CURVE,
+ // and direct distance on OTHER.
+ Float mBestOverlap;
+
+ // If one of border-widths is 0, do not calculate overlap, and draw circles
+ // until it reaches the other side or exceeds mMaxCount.
+ bool mHasZeroBorderWidth;
+ bool mHasMore;
+
+ // The maximum number of filled/unfilled circles.
+ size_t mMaxCount;
+
+ enum {
+ // radius.width
+ // |<----------------->|
+ // | |
+ // --+-------------___---+----
+ // ^ | __-- #|# ^
+ // | | _- ##|## |
+ // | | / ##+## | top-width
+ // | | / ##|## |
+ // | | | #|# v
+ // | | | __--+----
+ // radius.height | || _-
+ // | || /
+ // | | /
+ // | | |
+ // | | |
+ // | | ##### |
+ // | | ####### |
+ // v |#########|
+ // --+----+----+
+ // |#########|
+ // | ####### |
+ // | ##### |
+ // | |
+ // |<------->|
+ // left-width
+
+ // * top-width == left-width
+ // * radius.width == radius.height
+ // * top-width < radius.width * 2
+ //
+ // All circles has same radii and are on single perfect circle's arc.
+ // Overlap is known.
+ //
+ // Split the perfect circle's arc into 2n segments, each segment's length is
+ // top-width * (1 - overlap). Place each circle's center point C_i on each
+ // end of the segment, each circle's radius r_i is top-width / 2
+ //
+ // #####
+ // #######
+ // perfect #########
+ // circle's ___---+####
+ // arc ##### __-- ## C_0 ##
+ // | #####_- ###|###
+ // | ####+#### ##|##
+ // | ##/C_i ## |
+ // | |###### |
+ // | | ##### |
+ // +->| |
+ // | |
+ // ##|## |
+ // ###|### |
+ // ####|#### |
+ // ####+-------------------+
+ // ## C_n ##
+ // #######
+ // #####
+ PERFECT,
+
+ // * top-width == left-width
+ // * 0.5 < radius.width / radius.height < 2.0
+ // * top-width < min(radius.width, radius.height) * 2
+ //
+ // All circles has same radii and are on single elliptic arc.
+ // Overlap is known.
+ //
+ // Split the elliptic arc into 2n segments, each segment's length is
+ // top-width * (1 - overlap). Place each circle's center point C_i on each
+ // end of the segment, each circle's radius r_i is top-width / 2
+ //
+ // #####
+ // #######
+ // ##### #########
+ // ####### ____----+####
+ // elliptic ######__--- ## C_0 ##
+ // arc ##__+-### ###|###
+ // | / # C_i # ##|##
+ // +--> / ##### |
+ // | |
+ // ###|# |
+ // ###|### |
+ // ####|#### |
+ // ####+------------------------+
+ // ## C_n ##
+ // #######
+ // #####
+ SINGLE_CURVE_AND_RADIUS,
+
+ // * top-width != left-width
+ // * 0 < min(top-width, left-width)
+ // * 0.5 < radius.width / radius.height < 2.0
+ // * max(top-width, left-width) < min(radius.width, radius.height) * 2
+ //
+ // All circles are on single elliptic arc.
+ // Overlap is unknown.
+ //
+ // Place each circle's center point C_i on elliptic arc, each circle's
+ // radius r_i is the distance between the center point and the inner curve.
+ // The arc segment's length between C_i and C_{i-1} is
+ // (r_i + r_{i-1}) * (1 - overlap).
+ //
+ // outer curve
+ // /
+ // /
+ // / / center curve
+ // / ####### /
+ // /## /#
+ // +# / #
+ // /# / #
+ // / # C_i / #
+ // / # + # /
+ // / # / \ # / inner curve
+ // # / \ #/
+ // # / r_i \+
+ // #/ ##/
+ // / ####### /
+ // /
+ SINGLE_CURVE,
+
+ // Other cases.
+ // Circles are not on single elliptic arc.
+ // Overlap are unknown.
+ //
+ // Place tangent point innerTangent on the inner curve and find circle's
+ // center point C_i and radius r_i where the circle is also tangent to the
+ // outer curve.
+ // Distance between C_i and C_{i-1} is (r_i + r_{i-1}) * (1 - overlap).
+ //
+ // outer curve
+ // /
+ // /
+ // /
+ // / #######
+ // /## ##
+ // +# #
+ // /# \ #
+ // / # \ #
+ // / # + # /
+ // / # C_i \ # / inner curve
+ // # \ #/
+ // # r_i \+
+ // ## ##/ innerTangent
+ // ####### /
+ // /
+ OTHER
+ } mType;
+
+ size_t mI;
+ size_t mCount;
+
+ // Determine mType from parameters.
+ void DetermineType(Float aBorderRadiusX, Float aBorderRadiusY);
+
+ // Reset calculation.
+ void Reset(void);
+
+ // Find radius for the given tangent point on the inner curve such that the
+ // circle is also tangent to the outer curve.
+ void FindPointAndRadius(Point& C, Float& r, const Point& innerTangent,
+ const Point& normal, Float t);
+
+ // Find next dot.
+ Float FindNext(Float overlap);
+
+ // Find mBestOverlap for parameters.
+ void FindBestOverlap(Float aMinR, Float aMinBorderRadius,
+ Float aMaxBorderRadius);
+
+ // Fill corner with dots with given overlap, and return the number of dots
+ // and last two dots's overlap.
+ bool GetCountAndLastOverlap(Float aOverlap, size_t* aCount,
+ Float* aActualOverlap);
+};
+
+} // namespace mozilla
+
+#endif /* mozilla_DottedCornerFinder_h_ */