1 /* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*-
2 * This Source Code Form is subject to the terms of the Mozilla Public
3 * License, v. 2.0. If a copy of the MPL was not distributed with this
4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6 #ifndef MOZILLA_GFX_PATHHELPERS_H_
7 #define MOZILLA_GFX_PATHHELPERS_H_
10 #include "mozilla/Constants.h"
16 void ArcToBezier(T
* aSink
, const Point
&aOrigin
, float aRadius
, float aStartAngle
,
17 float aEndAngle
, bool aAntiClockwise
)
19 Point
startPoint(aOrigin
.x
+ cos(aStartAngle
) * aRadius
,
20 aOrigin
.y
+ sin(aStartAngle
) * aRadius
);
22 aSink
->LineTo(startPoint
);
24 // Clockwise we always sweep from the smaller to the larger angle, ccw
26 if (!aAntiClockwise
&& (aEndAngle
< aStartAngle
)) {
27 Float correction
= Float(ceil((aStartAngle
- aEndAngle
) / (2.0f
* M_PI
)));
28 aEndAngle
+= float(correction
* 2.0f
* M_PI
);
29 } else if (aAntiClockwise
&& (aStartAngle
< aEndAngle
)) {
30 Float correction
= (Float
)ceil((aEndAngle
- aStartAngle
) / (2.0f
* M_PI
));
31 aStartAngle
+= float(correction
* 2.0f
* M_PI
);
34 // Sweeping more than 2 * pi is a full circle.
35 if (!aAntiClockwise
&& (aEndAngle
- aStartAngle
> 2 * M_PI
)) {
36 aEndAngle
= float(aStartAngle
+ 2.0f
* M_PI
);
37 } else if (aAntiClockwise
&& (aStartAngle
- aEndAngle
> 2.0f
* M_PI
)) {
38 aEndAngle
= float(aStartAngle
- 2.0f
* M_PI
);
41 // Calculate the total arc we're going to sweep.
42 Float arcSweepLeft
= fabs(aEndAngle
- aStartAngle
);
44 Float sweepDirection
= aAntiClockwise
? -1.0f
: 1.0f
;
46 Float currentStartAngle
= aStartAngle
;
48 while (arcSweepLeft
> 0) {
49 // We guarantee here the current point is the start point of the next
51 Float currentEndAngle
;
53 if (arcSweepLeft
> M_PI
/ 2.0f
) {
54 currentEndAngle
= Float(currentStartAngle
+ M_PI
/ 2.0f
* sweepDirection
);
56 currentEndAngle
= currentStartAngle
+ arcSweepLeft
* sweepDirection
;
59 Point
currentStartPoint(aOrigin
.x
+ cos(currentStartAngle
) * aRadius
,
60 aOrigin
.y
+ sin(currentStartAngle
) * aRadius
);
61 Point
currentEndPoint(aOrigin
.x
+ cos(currentEndAngle
) * aRadius
,
62 aOrigin
.y
+ sin(currentEndAngle
) * aRadius
);
64 // Calculate kappa constant for partial curve. The sign of angle in the
65 // tangent will actually ensure this is negative for a counter clockwise
66 // sweep, so changing signs later isn't needed.
67 Float kappa
= (4.0f
/ 3.0f
) * tan((currentEndAngle
- currentStartAngle
) / 4.0f
) * aRadius
;
69 Point
tangentStart(-sin(currentStartAngle
), cos(currentStartAngle
));
70 Point cp1
= currentStartPoint
;
71 cp1
+= tangentStart
* kappa
;
73 Point
revTangentEnd(sin(currentEndAngle
), -cos(currentEndAngle
));
74 Point cp2
= currentEndPoint
;
75 cp2
+= revTangentEnd
* kappa
;
77 aSink
->BezierTo(cp1
, cp2
, currentEndPoint
);
79 arcSweepLeft
-= Float(M_PI
/ 2.0f
);
80 currentStartAngle
= currentEndAngle
;
85 * Appends a path represending a rounded rectangle to the path being built by
88 * aRect The rectangle to append.
89 * aCornerRadii Contains the radii of the top-left, top-right, bottom-right
90 * and bottom-left corners, in that order.
91 * aDrawClockwise If set to true, the path will start at the left of the top
92 * left edge and draw clockwise. If set to false the path will
93 * start at the right of the top left edge and draw counter-
96 GFX2D_API
void AppendRoundedRectToPath(PathBuilder
* aPathBuilder
,
98 const Size(& aCornerRadii
)[4],
99 bool aDrawClockwise
= true);
102 * Appends a path represending an ellipse to the path being built by
105 * The ellipse extends aDimensions.width / 2.0 in the horizontal direction
106 * from aCenter, and aDimensions.height / 2.0 in the vertical direction.
108 GFX2D_API
void AppendEllipseToPath(PathBuilder
* aPathBuilder
,
109 const Point
& aCenter
,
110 const Size
& aDimensions
);
113 } // namespace mozilla
115 #endif /* MOZILLA_GFX_PATHHELPERS_H_ */