Bug 944704, part 1 - Extend Moz2D's ArcToBezier helper so that it can draw ellipse arcs in addition to circle arcs. r=Bas
authorJonathan Watt <jwatt@jwatt.org>
Fri, 13 Dec 2013 12:14:36 +0000
changeset 160397 15e0c5ced15510aa8ef8695049d53cf44f6baee7
parent 160396 456d3ef07190dc92997f48be72f894ed293d575c
child 160398 756ce0d34c9fb68331915ca6c2cfef22cdb3277b
push id25831
push userryanvm@gmail.com
push dateFri, 13 Dec 2013 21:16:01 +0000
treeherdermozilla-central@9d593727eb94 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersBas
bugs944704
milestone29.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 944704, part 1 - Extend Moz2D's ArcToBezier helper so that it can draw ellipse arcs in addition to circle arcs. r=Bas
gfx/2d/Path.cpp
gfx/2d/PathCairo.cpp
gfx/2d/PathHelpers.h
gfx/2d/PathSkia.cpp
--- a/gfx/2d/Path.cpp
+++ b/gfx/2d/Path.cpp
@@ -116,17 +116,17 @@ FlattenedPath::Close()
   MOZ_ASSERT(!mCalculatedLength);
   LineTo(mLastMove);
 }
 
 void
 FlattenedPath::Arc(const Point &aOrigin, float aRadius, float aStartAngle,
                    float aEndAngle, bool aAntiClockwise)
 {
-  ArcToBezier(this, aOrigin, aRadius, aStartAngle, aEndAngle, aAntiClockwise);
+  ArcToBezier(this, aOrigin, Size(aRadius, aRadius), aStartAngle, aEndAngle, aAntiClockwise);
 }
 
 Float
 FlattenedPath::ComputeLength()
 {
   if (!mCalculatedLength) {
     Point currentPoint;
 
--- a/gfx/2d/PathCairo.cpp
+++ b/gfx/2d/PathCairo.cpp
@@ -108,17 +108,17 @@ PathBuilderCairo::Close()
 
   mCurrentPoint = mBeginPoint;
 }
 
 void
 PathBuilderCairo::Arc(const Point &aOrigin, float aRadius, float aStartAngle,
                      float aEndAngle, bool aAntiClockwise)
 {
-  ArcToBezier(this, aOrigin, aRadius, aStartAngle, aEndAngle, aAntiClockwise);
+  ArcToBezier(this, aOrigin, Size(aRadius, aRadius), aStartAngle, aEndAngle, aAntiClockwise);
 }
 
 Point
 PathBuilderCairo::CurrentPoint() const
 {
   return mCurrentPoint;
 }
 
--- a/gfx/2d/PathHelpers.h
+++ b/gfx/2d/PathHelpers.h
@@ -8,21 +8,21 @@
 
 #include "2D.h"
 #include "mozilla/Constants.h"
 
 namespace mozilla {
 namespace gfx {
 
 template <typename T>
-void ArcToBezier(T* aSink, const Point &aOrigin, float aRadius, float aStartAngle,
-                 float aEndAngle, bool aAntiClockwise)
+void ArcToBezier(T* aSink, const Point &aOrigin, const Size &aRadius,
+                 float aStartAngle, float aEndAngle, bool aAntiClockwise)
 {
-  Point startPoint(aOrigin.x + cos(aStartAngle) * aRadius,
-                   aOrigin.y + sin(aStartAngle) * aRadius);
+  Point startPoint(aOrigin.x + cos(aStartAngle) * aRadius.width,
+                   aOrigin.y + sin(aStartAngle) * aRadius.height);
 
   aSink->LineTo(startPoint);
 
   // Clockwise we always sweep from the smaller to the larger angle, ccw
   // it's vice versa.
   if (!aAntiClockwise && (aEndAngle < aStartAngle)) {
     Float correction = Float(ceil((aStartAngle - aEndAngle) / (2.0f * M_PI)));
     aEndAngle += float(correction * 2.0f * M_PI);
@@ -51,33 +51,35 @@ void ArcToBezier(T* aSink, const Point &
     Float currentEndAngle;
 
     if (arcSweepLeft > M_PI / 2.0f) {
       currentEndAngle = Float(currentStartAngle + M_PI / 2.0f * sweepDirection);
     } else {
       currentEndAngle = currentStartAngle + arcSweepLeft * sweepDirection;
     }
 
-    Point currentStartPoint(aOrigin.x + cos(currentStartAngle) * aRadius,
-                            aOrigin.y + sin(currentStartAngle) * aRadius);
-    Point currentEndPoint(aOrigin.x + cos(currentEndAngle) * aRadius,
-                          aOrigin.y + sin(currentEndAngle) * aRadius);
+    Point currentStartPoint(aOrigin.x + cos(currentStartAngle) * aRadius.width,
+                            aOrigin.y + sin(currentStartAngle) * aRadius.height);
+    Point currentEndPoint(aOrigin.x + cos(currentEndAngle) * aRadius.width,
+                          aOrigin.y + sin(currentEndAngle) * aRadius.height);
 
     // Calculate kappa constant for partial curve. The sign of angle in the
     // tangent will actually ensure this is negative for a counter clockwise
     // sweep, so changing signs later isn't needed.
-    Float kappa = (4.0f / 3.0f) * tan((currentEndAngle - currentStartAngle) / 4.0f) * aRadius;
+    Float kappaFactor = (4.0f / 3.0f) * tan((currentEndAngle - currentStartAngle) / 4.0f);
+    Float kappaX = kappaFactor * aRadius.width;
+    Float kappaY = kappaFactor * aRadius.height;
 
     Point tangentStart(-sin(currentStartAngle), cos(currentStartAngle));
     Point cp1 = currentStartPoint;
-    cp1 += tangentStart * kappa;
+    cp1 += Point(tangentStart.x * kappaX, tangentStart.y * kappaY);
 
     Point revTangentEnd(sin(currentEndAngle), -cos(currentEndAngle));
     Point cp2 = currentEndPoint;
-    cp2 += revTangentEnd * kappa;
+    cp2 += Point(revTangentEnd.x * kappaX, revTangentEnd.y * kappaY);
 
     aSink->BezierTo(cp1, cp2, currentEndPoint);
 
     arcSweepLeft -= Float(M_PI / 2.0f);
     currentStartAngle = currentEndAngle;
   }
 }
 
--- a/gfx/2d/PathSkia.cpp
+++ b/gfx/2d/PathSkia.cpp
@@ -83,17 +83,17 @@ PathBuilderSkia::Close()
 {
   mPath.close();
 }
 
 void
 PathBuilderSkia::Arc(const Point &aOrigin, float aRadius, float aStartAngle,
                      float aEndAngle, bool aAntiClockwise)
 {
-  ArcToBezier(this, aOrigin, aRadius, aStartAngle, aEndAngle, aAntiClockwise);
+  ArcToBezier(this, aOrigin, Size(aRadius, aRadius), aStartAngle, aEndAngle, aAntiClockwise);
 }
 
 Point
 PathBuilderSkia::CurrentPoint() const
 {
   int pointCount = mPath.countPoints();
   if (!pointCount) {
     return Point(0, 0);