Bug 984796: Fix some small errors in path flattening code. r=jwatt
authorBas Schouten <bschouten@mozilla.com>
Sat, 22 Mar 2014 18:40:58 +0100
changeset 174914 56e6067c9514e9cdc89fbeda011d0330991b3ef1
parent 174913 d1dbd1864d47b75d3dbc70d234678d6b385dc8dc
child 174915 2f5fff1478a8c2173d6deb3d0d777a8467b8a9c0
push id26467
push userphilringnalda@gmail.com
push dateSun, 23 Mar 2014 00:31:32 +0000
treeherdermozilla-central@2f5fff1478a8 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjwatt
bugs984796
milestone31.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 984796: Fix some small errors in path flattening code. r=jwatt
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)) {