Bug 987077 - Correctly deal with a constant acceleration. r=jwatt, a=sledru
 author Bas Schouten Wed, 02 Apr 2014 21:16:57 +0100 changeset 193019 cca7eb7fc75efd1100905e350cb34d25e50ef98b parent 193018 8dc71e439d4221dfd0fcd3dc34dbd8218fb24df7 child 193020 bee1ba424663a093bceb15352f1d8bc244b605b4 push id 474 push user asasaki@mozilla.com push date Mon, 02 Jun 2014 21:01:02 +0000 treeherder mozilla-release@967f4cf1b31c [default view] [failures only] perfherder [talos] [build metrics] [platform microbench] (compared to previous push) reviewers jwatt, sledru bugs 987077 milestone 30.0a2
Bug 987077 - Correctly deal with a constant acceleration. r=jwatt, a=sledru
 gfx/2d/Path.cpp file | annotate | diff | comparison | revisions
```--- 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) {
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;```