Bug 930443 - Convert SVGPathSegUtils to Moz2D. r=heycam
authorJonathan Watt <jwatt@jwatt.org>
Thu, 24 Oct 2013 14:46:38 +0200
changeset 166728 36f6d6b62494e2d391ae7a348f71c64d44886f93
parent 166727 d15e9fb2b5a86a910733f1e3661a4a69325bf741
child 166729 17156fbebbc8ab184d214b6190f6ed8582bce219
push id428
push userbbajaj@mozilla.com
push dateTue, 28 Jan 2014 00:16:25 +0000
treeherdermozilla-release@cd72a7ff3a75 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersheycam
bugs930443
milestone27.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 930443 - Convert SVGPathSegUtils to Moz2D. r=heycam
content/svg/content/src/SVGPathSegUtils.cpp
content/svg/content/src/SVGPathSegUtils.h
--- a/content/svg/content/src/SVGPathSegUtils.cpp
+++ b/content/svg/content/src/SVGPathSegUtils.cpp
@@ -1,18 +1,21 @@
 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* 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/. */
 
 #include "SVGPathSegUtils.h"
+
+#include "gfx2DGlue.h"
 #include "nsSVGPathDataParser.h"
 #include "nsTextFormatter.h"
 
 using namespace mozilla;
+using namespace mozilla::gfx;
 
 static const float PATH_SEG_LENGTH_TOLERANCE = 0.0000001f;
 static const uint32_t MAX_RECURSION = 10;
 
 
 /* static */ void
 SVGPathSegUtils::GetValueAsString(const float* aSeg, nsAString& aValue)
 {
@@ -75,41 +78,41 @@ SVGPathSegUtils::GetValueAsString(const 
   //
   if (aValue[aValue.Length() - 1] == PRUnichar('\0')) {
     aValue.SetLength(aValue.Length() - 1);
   }
 }
 
 
 static float
-CalcDistanceBetweenPoints(const gfxPoint& aP1, const gfxPoint& aP2)
+CalcDistanceBetweenPoints(const Point& aP1, const Point& aP2)
 {
   return NS_hypot(aP2.x - aP1.x, aP2.y - aP1.y);
 }
 
 
 static void
-SplitQuadraticBezier(const gfxPoint* aCurve, gfxPoint* aLeft, gfxPoint* aRight)
+SplitQuadraticBezier(const Point* aCurve, Point* aLeft, Point* aRight)
 {
   aLeft[0].x = aCurve[0].x;
   aLeft[0].y = aCurve[0].y;
   aRight[2].x = aCurve[2].x;
   aRight[2].y = aCurve[2].y;
   aLeft[1].x = (aCurve[0].x + aCurve[1].x) / 2;
   aLeft[1].y = (aCurve[0].y + aCurve[1].y) / 2;
   aRight[1].x = (aCurve[1].x + aCurve[2].x) / 2;
   aRight[1].y = (aCurve[1].y + aCurve[2].y) / 2;
   aLeft[2].x = aRight[0].x = (aLeft[1].x + aRight[1].x) / 2;
   aLeft[2].y = aRight[0].y = (aLeft[1].y + aRight[1].y) / 2;
 }
 
 static void
-SplitCubicBezier(const gfxPoint* aCurve, gfxPoint* aLeft, gfxPoint* aRight)
+SplitCubicBezier(const Point* aCurve, Point* aLeft, Point* aRight)
 {
-  gfxPoint tmp;
+  Point tmp;
   tmp.x = (aCurve[1].x + aCurve[2].x) / 4;
   tmp.y = (aCurve[1].y + aCurve[2].y) / 4;
   aLeft[0].x = aCurve[0].x;
   aLeft[0].y = aCurve[0].y;
   aRight[3].x = aCurve[3].x;
   aRight[3].y = aCurve[3].y;
   aLeft[1].x = (aCurve[0].x + aCurve[1].x) / 2;
   aLeft[1].y = (aCurve[0].y + aCurve[1].y) / 2;
@@ -119,50 +122,50 @@ SplitCubicBezier(const gfxPoint* aCurve,
   aLeft[2].y = aLeft[1].y / 2 + tmp.y;
   aRight[1].x = aRight[2].x / 2 + tmp.x;
   aRight[1].y = aRight[2].y / 2 + tmp.y;
   aLeft[3].x = aRight[0].x = (aLeft[2].x + aRight[1].x) / 2;
   aLeft[3].y = aRight[0].y = (aLeft[2].y + aRight[1].y) / 2;
 }
 
 static gfxFloat
-CalcBezLengthHelper(gfxPoint* aCurve, uint32_t aNumPts,
+CalcBezLengthHelper(const Point* aCurve, uint32_t aNumPts,
                     uint32_t aRecursionCount,
-                    void (*aSplit)(const gfxPoint*, gfxPoint*, gfxPoint*))
+                    void (*aSplit)(const Point*, Point*, Point*))
 {
-  gfxPoint left[4];
-  gfxPoint right[4];
+  Point left[4];
+  Point right[4];
   gfxFloat length = 0, dist;
   for (uint32_t i = 0; i < aNumPts - 1; i++) {
     length += CalcDistanceBetweenPoints(aCurve[i], aCurve[i+1]);
   }
   dist = CalcDistanceBetweenPoints(aCurve[0], aCurve[aNumPts - 1]);
   if (length - dist > PATH_SEG_LENGTH_TOLERANCE &&
       aRecursionCount < MAX_RECURSION) {
     aSplit(aCurve, left, right);
     ++aRecursionCount;
     return CalcBezLengthHelper(left, aNumPts, aRecursionCount, aSplit) +
            CalcBezLengthHelper(right, aNumPts, aRecursionCount, aSplit);
   }
   return length;
 }
 
 static inline gfxFloat
-CalcLengthOfCubicBezier(const gfxPoint& aPos, const gfxPoint &aCP1,
-                        const gfxPoint& aCP2, const gfxPoint &aTo)
+CalcLengthOfCubicBezier(const Point& aPos, const Point &aCP1,
+                        const Point& aCP2, const Point &aTo)
 {
-  gfxPoint curve[4] = { aPos, aCP1, aCP2, aTo };
+  Point curve[4] = { aPos, aCP1, aCP2, aTo };
   return CalcBezLengthHelper(curve, 4, 0, SplitCubicBezier);
 }
 
 static inline gfxFloat
-CalcLengthOfQuadraticBezier(const gfxPoint& aPos, const gfxPoint& aCP,
-                            const gfxPoint& aTo)
+CalcLengthOfQuadraticBezier(const Point& aPos, const Point& aCP,
+                            const Point& aTo)
 {
-  gfxPoint curve[3] = { aPos, aCP, aTo };
+  Point curve[3] = { aPos, aCP, aTo };
   return CalcBezLengthHelper(curve, 3, 0, SplitQuadraticBezier);
 }
 
 
 static void
 TraverseClosePath(const float* aArgs, SVGPathTraversalState& aState)
 {
   if (aState.ShouldUpdateLengthAndControlPoints()) {
@@ -170,59 +173,59 @@ TraverseClosePath(const float* aArgs, SV
     aState.cp1 = aState.cp2 = aState.start;
   }
   aState.pos = aState.start;
 }
 
 static void
 TraverseMovetoAbs(const float* aArgs, SVGPathTraversalState& aState)
 {
-  aState.start = aState.pos = gfxPoint(aArgs[0], aArgs[1]);
+  aState.start = aState.pos = Point(aArgs[0], aArgs[1]);
   if (aState.ShouldUpdateLengthAndControlPoints()) {
     // aState.length is unchanged, since move commands don't affect path length.
     aState.cp1 = aState.cp2 = aState.start;
   }
 }
 
 static void
 TraverseMovetoRel(const float* aArgs, SVGPathTraversalState& aState)
 {
-  aState.start = aState.pos += gfxPoint(aArgs[0], aArgs[1]);
+  aState.start = aState.pos += Point(aArgs[0], aArgs[1]);
   if (aState.ShouldUpdateLengthAndControlPoints()) {
     // aState.length is unchanged, since move commands don't affect path length.
     aState.cp1 = aState.cp2 = aState.start;
   }
 }
 
 static void
 TraverseLinetoAbs(const float* aArgs, SVGPathTraversalState& aState)
 {
-  gfxPoint to(aArgs[0], aArgs[1]);
+  Point to(aArgs[0], aArgs[1]);
   if (aState.ShouldUpdateLengthAndControlPoints()) {
     aState.length += CalcDistanceBetweenPoints(aState.pos, to);
     aState.cp1 = aState.cp2 = to;
   }
   aState.pos = to;
 }
 
 static void
 TraverseLinetoRel(const float* aArgs, SVGPathTraversalState& aState)
 {
-  gfxPoint to = aState.pos + gfxPoint(aArgs[0], aArgs[1]);
+  Point to = aState.pos + Point(aArgs[0], aArgs[1]);
   if (aState.ShouldUpdateLengthAndControlPoints()) {
     aState.length += CalcDistanceBetweenPoints(aState.pos, to);
     aState.cp1 = aState.cp2 = to;
   }
   aState.pos = to;
 }
 
 static void
 TraverseLinetoHorizontalAbs(const float* aArgs, SVGPathTraversalState& aState)
 {
-  gfxPoint to(aArgs[0], aState.pos.y);
+  Point to(aArgs[0], aState.pos.y);
   if (aState.ShouldUpdateLengthAndControlPoints()) {
     aState.length += fabs(to.x - aState.pos.x);
     aState.cp1 = aState.cp2 = to;
   }
   aState.pos = to;
 }
 
 static void
@@ -233,17 +236,17 @@ TraverseLinetoHorizontalRel(const float*
     aState.length += fabs(aArgs[0]);
     aState.cp1 = aState.cp2 = aState.pos;
   }
 }
 
 static void
 TraverseLinetoVerticalAbs(const float* aArgs, SVGPathTraversalState& aState)
 {
-  gfxPoint to(aState.pos.x, aArgs[0]);
+  Point to(aState.pos.x, aArgs[0]);
   if (aState.ShouldUpdateLengthAndControlPoints()) {
     aState.length += fabs(to.y - aState.pos.y);
     aState.cp1 = aState.cp2 = to;
   }
   aState.pos = to;
 }
 
 static void
@@ -254,163 +257,167 @@ TraverseLinetoVerticalRel(const float* a
     aState.length += fabs(aArgs[0]);
     aState.cp1 = aState.cp2 = aState.pos;
   }
 }
 
 static void
 TraverseCurvetoCubicAbs(const float* aArgs, SVGPathTraversalState& aState)
 {
-  gfxPoint to(aArgs[4], aArgs[5]);
+  Point to(aArgs[4], aArgs[5]);
   if (aState.ShouldUpdateLengthAndControlPoints()) {
-    gfxPoint cp1(aArgs[0], aArgs[1]);
-    gfxPoint cp2(aArgs[2], aArgs[3]);
+    Point cp1(aArgs[0], aArgs[1]);
+    Point cp2(aArgs[2], aArgs[3]);
     aState.length += (float)CalcLengthOfCubicBezier(aState.pos, cp1, cp2, to);
     aState.cp2 = cp2;
     aState.cp1 = to;
   }
   aState.pos = to;
 }
 
 static void
 TraverseCurvetoCubicSmoothAbs(const float* aArgs, SVGPathTraversalState& aState)
 {
-  gfxPoint to(aArgs[2], aArgs[3]);
+  Point to(aArgs[2], aArgs[3]);
   if (aState.ShouldUpdateLengthAndControlPoints()) {
-    gfxPoint cp1 = aState.pos - (aState.cp2 - aState.pos);
-    gfxPoint cp2(aArgs[0], aArgs[1]);
+    Point cp1 = aState.pos - (aState.cp2 - aState.pos);
+    Point cp2(aArgs[0], aArgs[1]);
     aState.length += (float)CalcLengthOfCubicBezier(aState.pos, cp1, cp2, to);
     aState.cp2 = cp2;
     aState.cp1 = to;
   }
   aState.pos = to;
 }
 
 static void
 TraverseCurvetoCubicRel(const float* aArgs, SVGPathTraversalState& aState)
 {
-  gfxPoint to = aState.pos + gfxPoint(aArgs[4], aArgs[5]);
+  Point to = aState.pos + Point(aArgs[4], aArgs[5]);
   if (aState.ShouldUpdateLengthAndControlPoints()) {
-    gfxPoint cp1 = aState.pos + gfxPoint(aArgs[0], aArgs[1]);
-    gfxPoint cp2 = aState.pos + gfxPoint(aArgs[2], aArgs[3]);
+    Point cp1 = aState.pos + Point(aArgs[0], aArgs[1]);
+    Point cp2 = aState.pos + Point(aArgs[2], aArgs[3]);
     aState.length += (float)CalcLengthOfCubicBezier(aState.pos, cp1, cp2, to);
     aState.cp2 = cp2;
     aState.cp1 = to;
   }
   aState.pos = to;
 }
 
 static void
 TraverseCurvetoCubicSmoothRel(const float* aArgs, SVGPathTraversalState& aState)
 {
-  gfxPoint to = aState.pos + gfxPoint(aArgs[2], aArgs[3]);
+  Point to = aState.pos + Point(aArgs[2], aArgs[3]);
   if (aState.ShouldUpdateLengthAndControlPoints()) {
-    gfxPoint cp1 = aState.pos - (aState.cp2 - aState.pos);
-    gfxPoint cp2 = aState.pos + gfxPoint(aArgs[0], aArgs[1]);
+    Point cp1 = aState.pos - (aState.cp2 - aState.pos);
+    Point cp2 = aState.pos + Point(aArgs[0], aArgs[1]);
     aState.length += (float)CalcLengthOfCubicBezier(aState.pos, cp1, cp2, to);
     aState.cp2 = cp2;
     aState.cp1 = to;
   }
   aState.pos = to;
 }
 
 static void
 TraverseCurvetoQuadraticAbs(const float* aArgs, SVGPathTraversalState& aState)
 {
-  gfxPoint to(aArgs[2], aArgs[3]);
+  Point to(aArgs[2], aArgs[3]);
   if (aState.ShouldUpdateLengthAndControlPoints()) {
-    gfxPoint cp(aArgs[0], aArgs[1]);
+    Point cp(aArgs[0], aArgs[1]);
     aState.length += (float)CalcLengthOfQuadraticBezier(aState.pos, cp, to);
     aState.cp1 = cp;
     aState.cp2 = to;
   }
   aState.pos = to;
 }
 
 static void
 TraverseCurvetoQuadraticSmoothAbs(const float* aArgs,
                                   SVGPathTraversalState& aState)
 {
-  gfxPoint to(aArgs[0], aArgs[1]);
+  Point to(aArgs[0], aArgs[1]);
   if (aState.ShouldUpdateLengthAndControlPoints()) {
-    gfxPoint cp = aState.pos - (aState.cp1 - aState.pos);
+    Point cp = aState.pos - (aState.cp1 - aState.pos);
     aState.length += (float)CalcLengthOfQuadraticBezier(aState.pos, cp, to);
     aState.cp1 = cp;
     aState.cp2 = to;
   }
   aState.pos = to;
 }
 
 static void
 TraverseCurvetoQuadraticRel(const float* aArgs, SVGPathTraversalState& aState)
 {
-  gfxPoint to = aState.pos + gfxPoint(aArgs[2], aArgs[3]);
+  Point to = aState.pos + Point(aArgs[2], aArgs[3]);
   if (aState.ShouldUpdateLengthAndControlPoints()) {
-    gfxPoint cp = aState.pos + gfxPoint(aArgs[0], aArgs[1]);
+    Point cp = aState.pos + Point(aArgs[0], aArgs[1]);
     aState.length += (float)CalcLengthOfQuadraticBezier(aState.pos, cp, to);
     aState.cp1 = cp;
     aState.cp2 = to;
   }
   aState.pos = to;
 }
 
 static void
 TraverseCurvetoQuadraticSmoothRel(const float* aArgs,
                                   SVGPathTraversalState& aState)
 {
-  gfxPoint to = aState.pos + gfxPoint(aArgs[0], aArgs[1]);
+  Point to = aState.pos + Point(aArgs[0], aArgs[1]);
   if (aState.ShouldUpdateLengthAndControlPoints()) {
-    gfxPoint cp = aState.pos - (aState.cp1 - aState.pos);
+    Point cp = aState.pos - (aState.cp1 - aState.pos);
     aState.length += (float)CalcLengthOfQuadraticBezier(aState.pos, cp, to);
     aState.cp1 = cp;
     aState.cp2 = to;
   }
   aState.pos = to;
 }
 
 static void
 TraverseArcAbs(const float* aArgs, SVGPathTraversalState& aState)
 {
   gfxPoint to(aArgs[5], aArgs[6]);
   if (aState.ShouldUpdateLengthAndControlPoints()) {
     float dist = 0;
     gfxPoint radii(aArgs[0], aArgs[1]);
-    gfxPoint bez[4] = { aState.pos, gfxPoint(0, 0),
-                        gfxPoint(0, 0), gfxPoint(0, 0) };
-    nsSVGArcConverter converter(aState.pos, to, radii, aArgs[2],
+    gfxPoint pos = ThebesPoint(aState.pos);
+    gfxPoint bez[4] = { pos, gfxPoint(0, 0), gfxPoint(0, 0), gfxPoint(0, 0) };
+    nsSVGArcConverter converter(pos, to, radii, aArgs[2],
                                 aArgs[3] != 0, aArgs[4] != 0);
     while (converter.GetNextSegment(&bez[1], &bez[2], &bez[3])) {
-      dist += CalcBezLengthHelper(bez, 4, 0, SplitCubicBezier);
+      Point moz2dbez[4] = { ToPoint(bez[0]), ToPoint(bez[1]),
+                            ToPoint(bez[2]), ToPoint(bez[3]) };
+      dist += CalcBezLengthHelper(moz2dbez, 4, 0, SplitCubicBezier);
       bez[0] = bez[3];
     }
     aState.length += dist;
-    aState.cp1 = aState.cp2 = to;
+    aState.cp1 = aState.cp2 = ToPoint(to);
   }
-  aState.pos = to;
+  aState.pos = ToPoint(to);
 }
 
 static void
 TraverseArcRel(const float* aArgs, SVGPathTraversalState& aState)
 {
-  gfxPoint to = aState.pos + gfxPoint(aArgs[5], aArgs[6]);
+  gfxPoint to = ThebesPoint(aState.pos + Point(aArgs[5], aArgs[6]));
   if (aState.ShouldUpdateLengthAndControlPoints()) {
     float dist = 0;
     gfxPoint radii(aArgs[0], aArgs[1]);
-    gfxPoint bez[4] = { aState.pos, gfxPoint(0, 0),
-                        gfxPoint(0, 0), gfxPoint(0, 0) };
-    nsSVGArcConverter converter(aState.pos, to, radii, aArgs[2],
+    gfxPoint pos = ThebesPoint(aState.pos);
+    gfxPoint bez[4] = { pos, gfxPoint(0, 0), gfxPoint(0, 0), gfxPoint(0, 0) };
+    nsSVGArcConverter converter(pos, to, radii, aArgs[2],
                                 aArgs[3] != 0, aArgs[4] != 0);
     while (converter.GetNextSegment(&bez[1], &bez[2], &bez[3])) {
-      dist += CalcBezLengthHelper(bez, 4, 0, SplitCubicBezier);
+      Point moz2dbez[4] = { ToPoint(bez[0]), ToPoint(bez[1]),
+                            ToPoint(bez[2]), ToPoint(bez[3]) };
+      dist += CalcBezLengthHelper(moz2dbez, 4, 0, SplitCubicBezier);
       bez[0] = bez[3];
     }
     aState.length += dist;
-    aState.cp1 = aState.cp2 = to;
+    aState.cp1 = aState.cp2 = ToPoint(to);
   }
-  aState.pos = to;
+  aState.pos = ToPoint(to);
 }
 
 
 typedef void (*TraverseFunc)(const float*, SVGPathTraversalState&);
 
 static TraverseFunc gTraverseFuncTable[NS_SVG_PATH_SEG_TYPE_COUNT] = {
   nullptr, //  0 == PATHSEG_UNKNOWN
   TraverseClosePath,
--- a/content/svg/content/src/SVGPathSegUtils.h
+++ b/content/svg/content/src/SVGPathSegUtils.h
@@ -2,16 +2,17 @@
 /* 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_SVGPATHSEGUTILS_H__
 #define MOZILLA_SVGPATHSEGUTILS_H__
 
 #include "gfxPoint.h"
+#include "mozilla/gfx/Point.h"
 #include "nsDebug.h"
 #include "nsMemory.h"
 
 namespace mozilla {
 
 // Path Segment Types
 static const unsigned short PATHSEG_UNKNOWN                      = 0;
 static const unsigned short PATHSEG_CLOSEPATH                    = 1;
@@ -41,43 +42,45 @@ static const unsigned short PATHSEG_CURV
 
 /**
  * Code that works with path segments can use an instance of this class to
  * store/provide information about the start of the current subpath and the
  * last path segment (if any).
  */
 struct SVGPathTraversalState
 {
+  typedef gfx::Point Point;
+
   enum TraversalMode {
     eUpdateAll,
     eUpdateOnlyStartAndCurrentPos
   };
 
   SVGPathTraversalState()
     : start(0.0, 0.0)
     , pos(0.0, 0.0)
     , cp1(0.0, 0.0)
     , cp2(0.0, 0.0)
     , length(0.0)
     , mode(eUpdateAll)
   {}
 
   bool ShouldUpdateLengthAndControlPoints() { return mode == eUpdateAll; }
 
-  gfxPoint start; // start point of current sub path (reset each moveto)
+  Point start; // start point of current sub path (reset each moveto)
 
-  gfxPoint pos;   // current position (end point of previous segment)
+  Point pos;   // current position (end point of previous segment)
 
-  gfxPoint cp1;   // quadratic control point - if the previous segment was a
-                  // quadratic bezier curve then this is set to the absolute
-                  // position of its control point, otherwise its set to pos
+  Point cp1;   // quadratic control point - if the previous segment was a
+               // quadratic bezier curve then this is set to the absolute
+               // position of its control point, otherwise its set to pos
 
-  gfxPoint cp2;   // cubic control point - if the previous segment was a cubic
-                  // bezier curve then this is set to the absolute position of
-                  // its second control point, otherwise it's set to pos
+  Point cp2;   // cubic control point - if the previous segment was a cubic
+               // bezier curve then this is set to the absolute position of
+               // its second control point, otherwise it's set to pos
 
   float length;   // accumulated path length
 
   TraversalMode mode;  // indicates what to track while traversing a path
 };
 
 
 /**