Bug 984796 - Fix some small errors in path flattening code. r=jwatt, a=sledru
authorBas Schouten <bschouten@mozilla.com>
Sat, 22 Mar 2014 18:40:58 +0100
changeset 192450 a31b22a5e8a4bc09f1fe276af44f73ec7d5961ac
parent 192449 1b0d28323d93f7e0ee9b482411c5c295353483d2
child 192451 5c8cea3942d2809a19318dbc63a1485b5f49b99e
push id474
push userasasaki@mozilla.com
push dateMon, 02 Jun 2014 21:01:02 +0000
treeherdermozilla-release@967f4cf1b31c [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjwatt, sledru
bugs984796
milestone30.0a2
Bug 984796 - Fix some small errors in path flattening code. r=jwatt, a=sledru
gfx/2d/Path.cpp
--- a/gfx/2d/Path.cpp
+++ b/gfx/2d/Path.cpp
@@ -5,16 +5,25 @@
 
 #include "2D.h"
 #include "PathAnalysis.h"
 #include "PathHelpers.h"
 
 namespace mozilla {
 namespace gfx {
 
+static float CubicRoot(float aValue) {
+  if (aValue < 0.0) {
+    return -CubicRoot(-aValue);
+  }
+  else {
+    return powf(aValue, 1.0f / 3.0f);
+  }
+}
+
 struct BezierControlPoints
 {
   BezierControlPoints() {}
   BezierControlPoints(const Point &aCP1, const Point &aCP2,
                       const Point &aCP3, const Point &aCP4)
     : mCP1(aCP1), mCP2(aCP2), mCP3(aCP3), mCP4(aCP4)
   {
   }
@@ -264,33 +273,33 @@ FindInflectionApproximationRange(BezierC
 {
     SplitBezier(aControlPoints, nullptr, &aControlPoints, aT);
 
     Point cp21 = aControlPoints.mCP2 - aControlPoints.mCP1;
     Point cp41 = aControlPoints.mCP4 - aControlPoints.mCP1;
 
     if (cp21.x == 0 && cp21.y == 0) {
       // In this case s3 becomes lim[n->0] (cp41.x * n) / n - (cp41.y * n) / n = cp41.x - cp41.y.
-      *aMin = aT - pow(aTolerance / (cp41.x - cp41.y), Float(1. / 3.));
-      *aMax = aT + pow(aTolerance / (cp41.x - cp41.y), Float(1. / 3.));;
+      *aMin = aT - CubicRoot(double(aTolerance / (cp41.x - cp41.y)));
+      *aMax = aT + CubicRoot(aTolerance / (cp41.x - cp41.y));
       return;
     }
 
     Float s3 = (cp41.x * cp21.y - cp41.y * cp21.x) / hypotf(cp21.x, cp21.y);
 
     if (s3 == 0) {
       // This means within the precision we have it can be approximated
       // infinitely by a linear segment. Deal with this by specifying the
       // approximation range as extending beyond the entire curve.
       *aMin = -1.0f;
       *aMax = 2.0f;
       return;
     }
 
-    Float tf = pow(abs(aTolerance / s3), Float(1. / 3.));
+    Float tf = CubicRoot(abs(aTolerance / s3));
 
     *aMin = aT - tf * (1 - aT);
     *aMax = aT + tf * (1 - aT);
 }
 
 /* Find the inflection points of a bezier curve. Will return false if the
  * curve is degenerate in such a way that it is best approximated by a straight
  * line.
@@ -440,17 +449,17 @@ FlattenBezier(const BezierControlPoints 
   // segments.
   if (t1min > 0) {
     // Flatten the Bezier up until the first inflection point's approximation
     // point.
     SplitBezier(aControlPoints, &prevCPs,
                 &remainingCP, t1min);
     FlattenBezierCurveSegment(prevCPs, aSink, aTolerance);
   }
-  if (t1max < 1.0 && (count == 1 || t2min > t1max)) {
+  if (t1max >= 0 && t1max < 1.0 && (count == 1 || t2min > t1max)) {
     // The second inflection point's approximation range begins after the end
     // of the first, approximate the first inflection point by a line and
     // subsequently flatten up until the end or the next inflection point.
     SplitBezier(aControlPoints, nullptr, &nextCPs, t1max);
 
     aSink->LineTo(nextCPs.mCP1);
 
     if (count == 1 || (count > 1 && t2min >= 1.0)) {