Bug 987077: Correctly deal with a constant acceleration. r=jwatt
authorBas Schouten <bschouten@mozilla.com>
Wed, 02 Apr 2014 21:16:57 +0100
changeset 176809 f853e8ff85eaf87876b29dfe99141da58a840e2d
parent 176808 2c4c218a7a099cdd995cd31d9de900c1ac4d9ac2
child 176810 7f56669bdfdfd8b763e107efd552d8bf26d6161c
push id26533
push usercbook@mozilla.com
push dateThu, 03 Apr 2014 10:45:54 +0000
treeherdermozilla-central@57b4d6a3a401 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjwatt
bugs987077
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 987077: Correctly deal with a constant acceleration. r=jwatt
gfx/2d/Path.cpp
--- a/gfx/2d/Path.cpp
+++ b/gfx/2d/Path.cpp
@@ -346,17 +346,17 @@ FindInflectionApproximationRange(BezierC
  * x = (-b + sqrt(b * b - 4 * a * c)) / (2 * a)
  * x = (-3 * b + sqrt(3 * b * 3 * b - 4 * a * 3 * 9 * c / 3)) / (2 * 3 * a)
  * x = 3 * (-b + sqrt(b * b - 4 * a * c)) / (2 * 3 * a)
  * x = (-b + sqrt(b * b - 4 * a * c)) / (2 * a)
  *
  * I haven't looked into whether the formulation of the quadratic formula in
  * hain has any numerical advantages over the one used below.
  */
-static inline bool
+static inline void
 FindInflectionPoints(const BezierControlPoints &aControlPoints,
                      Float *aT1, Float *aT2, uint32_t *aCount)
 {
   // Find inflection points.
   // See www.faculty.idc.ac.il/arik/quality/appendixa.html for an explanation
   // of this approach.
   Point A = aControlPoints.mCP2 - aControlPoints.mCP1;
   Point B = aControlPoints.mCP3 - (aControlPoints.mCP2 * 2) + aControlPoints.mCP1;
@@ -364,22 +364,27 @@ FindInflectionPoints(const BezierControl
 
   Float a = Float(B.x) * C.y - Float(B.y) * C.x;
   Float b = Float(A.x) * C.y - Float(A.y) * C.x;
   Float c = Float(A.x) * B.y - Float(A.y) * B.x;
 
   if (a == 0) {
     // Not a quadratic equation.
     if (b == 0) {
-      // Instead of a linear equation we have a constant.
-      return false;
+      // Instead of a linear acceleration change we have a constant
+      // acceleration change. This means the equation has no solution
+      // and there are no inflection points, unless the constant is 0.
+      // In that case the curve is a straight line, but we'll let
+      // FlattenBezierCurveSegment deal with this.
+      *aCount = 0;
+      return;
     }
     *aT1 = -c / b;
     *aCount = 1;
-    return true;
+    return;
   } else {
     Float discriminant = b * b - 4 * a * c;
 
     if (discriminant < 0) {
       // No inflection points.
       *aCount = 0;
     } else if (discriminant == 0) {
       *aCount = 1;
@@ -403,31 +408,28 @@ FindInflectionPoints(const BezierControl
       *aT2 = c / q;
       if (*aT1 > *aT2) {
         std::swap(*aT1, *aT2);
       }
       *aCount = 2;
     }
   }
 
-  return true;
+  return;
 }
 
 void
 FlattenBezier(const BezierControlPoints &aControlPoints,
               PathSink *aSink, Float aTolerance)
 {
   Float t1;
   Float t2;
   uint32_t count;
 
-  if (!FindInflectionPoints(aControlPoints, &t1, &t2, &count)) {
-    aSink->LineTo(aControlPoints.mCP4);
-    return;
-  }
+  FindInflectionPoints(aControlPoints, &t1, &t2, &count);
 
   // Check that at least one of the inflection points is inside [0..1]
   if (count == 0 || ((t1 < 0 || t1 > 1.0) && ((t2 < 0 || t2 > 1.0) || count == 1)) ) {
     FlattenBezierCurveSegment(aControlPoints, aSink, aTolerance);
     return;
   }
 
   Float t1min = t1, t1max = t1, t2min = t2, t2max = t2;