| Index: src/utils/SkCurveMeasure.cpp
 | 
| diff --git a/src/utils/SkCurveMeasure.cpp b/src/utils/SkCurveMeasure.cpp
 | 
| index a82008e67e25a47460b5129a6e7f1598a701ea04..5958f4471f971ecaf7e8fcd76dd4302da2c6487e 100644
 | 
| --- a/src/utils/SkCurveMeasure.cpp
 | 
| +++ b/src/utils/SkCurveMeasure.cpp
 | 
| @@ -11,7 +11,7 @@
 | 
|  // for abs
 | 
|  #include <cmath>
 | 
|  
 | 
| -#define UNIMPLEMENTED SkDEBUGF(("%s:%d unimplemented\n", __FILE__, __LINE__))
 | 
| +#define UNIMPLEMENTED SkDEBUGFAILF("%s:%d unimplemented\n", __FILE__, __LINE__)
 | 
|  
 | 
|  /// Used inside SkCurveMeasure::getTime's Newton's iteration
 | 
|  static inline SkPoint evaluate(const SkPoint pts[4], SkSegType segType,
 | 
| @@ -65,24 +65,74 @@ static inline SkVector evaluateDerivative(const SkPoint pts[4],
 | 
|  
 | 
|      return tan;
 | 
|  }
 | 
| +
 | 
| +/*
 | 
| + * Derivation of conic formulae based on parameterization from
 | 
| + * http://citeseerx.ist.psu.edu/viewdoc/
 | 
| + *   download?doi=10.1.1.44.5740&rep=rep1&type=ps
 | 
| + * referenced in SkGeometry.cpp
 | 
| + *
 | 
| + * Usage: below and in the constructor for ArcLengthIntegrator
 | 
| + *
 | 
| + * Mathematica:
 | 
| + *
 | 
| + * conic[t_] := (A*(1 - t)^2 + 2*w*B*(1 - t)*t + C*t^2)/
 | 
| + *      (1 - 2*(1 - w)*t + 2*(1 - w)*t^2)
 | 
| + *
 | 
| + * conic[0]
 | 
| + *
 | 
| + * >>> A
 | 
| + *
 | 
| + * conic[1]
 | 
| + *
 | 
| + * >>> C
 | 
| + *
 | 
| + * Simplify[Derivative[1][conic][t]]
 | 
| + *
 | 
| + * >>> (2*(C*t*(1 + t*(-1 + w)) - A*(-1 + t)*(t*(-1 + w) - w) + B*(1 - 2*t)*w))/
 | 
| + *     (1 + 2*t*(-1 + w) - 2*t^2*(-1 + w))^2
 | 
| + *
 | 
| + * HornerForm[Numerator[Simplify[Derivative[1][conic][t]]], t]
 | 
| + *
 | 
| + * >>> -2*A*w + 2*B*w + t*(-2*A + 2*C + 4*A*w - 4*B*w +
 | 
| + *               t*(2*A - 2*C - 2*A*w + 2*C*w))
 | 
| + *
 | 
| + * HornerForm[Denominator[Simplify[Derivative[1][conic][t]]], t]
 | 
| + *
 | 
| + * >>> 1 + t*(-4 + 4*w + t*(8 - 12*w + 4*w^2 +
 | 
| + *               t*(-8 + 16*w - 8*w^2 + t*(4 - 8*w + 4*w^2))))
 | 
| + *
 | 
| + */
 | 
| +
 | 
|  /// Used in ArcLengthIntegrator::computeLength
 | 
|  static inline Sk8f evaluateDerivativeLength(const Sk8f& ts,
 | 
| -                                            const Sk8f (&xCoeff)[3],
 | 
| -                                            const Sk8f (&yCoeff)[3],
 | 
| +                                            const Sk8f (&fXCoeff)[3],
 | 
| +                                            const Sk8f (&fYCoeff)[3],
 | 
| +                                            const SkScalar w,
 | 
|                                              const SkSegType segType) {
 | 
|      Sk8f x;
 | 
|      Sk8f y;
 | 
|      switch (segType) {
 | 
|          case kQuad_SegType:
 | 
| -            x = xCoeff[0]*ts + xCoeff[1];
 | 
| -            y = yCoeff[0]*ts + yCoeff[1];
 | 
| +            x = fXCoeff[0]*ts + fXCoeff[1];
 | 
| +            y = fYCoeff[0]*ts + fYCoeff[1];
 | 
|              break;
 | 
|          case kCubic_SegType:
 | 
| -            x = (xCoeff[0]*ts + xCoeff[1])*ts + xCoeff[2];
 | 
| -            y = (yCoeff[0]*ts + yCoeff[1])*ts + yCoeff[2];
 | 
| +            x = (fXCoeff[0]*ts + fXCoeff[1])*ts + fXCoeff[2];
 | 
| +            y = (fYCoeff[0]*ts + fYCoeff[1])*ts + fYCoeff[2];
 | 
|              break;
 | 
| -        case kConic_SegType:
 | 
| -            UNIMPLEMENTED;
 | 
| +        case kConic_SegType: {
 | 
| +            Sk8f xnum = (fXCoeff[0]*ts + fXCoeff[1])*ts + fXCoeff[2];
 | 
| +            Sk8f ynum = (fYCoeff[0]*ts + fYCoeff[1])*ts + fYCoeff[2];
 | 
| +
 | 
| +            SkScalar w44 = 4 + 4*w;
 | 
| +            SkScalar w484 = 4 - 8*w + 4*w*w;
 | 
| +            Sk8f denom =  ts*(-8 + w44 + ts*(8 + -w44 + w484 + ts*(-2*w484
 | 
| +                              + ts*(w484)))) + 1;
 | 
| +
 | 
| +            x = xnum / denom;
 | 
| +            y = ynum / denom;
 | 
| +        }
 | 
|              break;
 | 
|          default:
 | 
|              UNIMPLEMENTED;
 | 
| @@ -106,11 +156,11 @@ ArcLengthIntegrator::ArcLengthIntegrator(const SkPoint* pts, SkSegType segType)
 | 
|              float Cy = pts[2].y();
 | 
|  
 | 
|              // precompute coefficients for derivative
 | 
| -            xCoeff[0] = Sk8f(2*(Ax - 2*Bx + Cx));
 | 
| -            xCoeff[1] = Sk8f(2*(Bx - Ax));
 | 
| +            fXCoeff[0] = Sk8f(2*(Ax - 2*Bx + Cx));
 | 
| +            fXCoeff[1] = Sk8f(2*(Bx - Ax));
 | 
|  
 | 
| -            yCoeff[0] = Sk8f(2*(Ay - 2*By + Cy));
 | 
| -            yCoeff[1] = Sk8f(2*(By - Ay));
 | 
| +            fYCoeff[0] = Sk8f(2*(Ay - 2*By + Cy));
 | 
| +            fYCoeff[1] = Sk8f(2*(By - Ay));
 | 
|          }
 | 
|              break;
 | 
|          case kCubic_SegType:
 | 
| @@ -125,17 +175,40 @@ ArcLengthIntegrator::ArcLengthIntegrator(const SkPoint* pts, SkSegType segType)
 | 
|              float Dy = pts[3].y();
 | 
|  
 | 
|              // precompute coefficients for derivative
 | 
| -            xCoeff[0] = Sk8f(3*(-Ax + 3*(Bx - Cx) + Dx));
 | 
| -            xCoeff[1] = Sk8f(6*(Ax - 2*Bx + Cx));
 | 
| -            xCoeff[2] = Sk8f(3*(-Ax + Bx));
 | 
| +            fXCoeff[0] = Sk8f(3*(-Ax + 3*(Bx - Cx) + Dx));
 | 
| +            fXCoeff[1] = Sk8f(6*(Ax - 2*Bx + Cx));
 | 
| +            fXCoeff[2] = Sk8f(3*(-Ax + Bx));
 | 
|  
 | 
| -            yCoeff[0] = Sk8f(3*(-Ay + 3*(By - Cy) + Dy));
 | 
| -            yCoeff[1] = Sk8f(6*(Ay - 2*By + Cy));
 | 
| -            yCoeff[2] = Sk8f(3*(-Ay + By));
 | 
| +            fYCoeff[0] = Sk8f(3*(-Ay + 3*(By - Cy) + Dy));
 | 
| +            fYCoeff[1] = Sk8f(6*(Ay - 2*By + Cy));
 | 
| +            fYCoeff[2] = Sk8f(3*(-Ay + By));
 | 
|          }
 | 
|              break;
 | 
| -        case kConic_SegType:
 | 
| -            UNIMPLEMENTED;
 | 
| +        case kConic_SegType: {
 | 
| +            float Ax = pts[0].x();
 | 
| +            float Bx = pts[1].x();
 | 
| +            float Cx = pts[2].x();
 | 
| +            float Ay = pts[0].y();
 | 
| +            float By = pts[1].y();
 | 
| +            float Cy = pts[2].y();
 | 
| +
 | 
| +            fConicW = pts[3].x();
 | 
| +
 | 
| +            SkScalar w = fConicW;
 | 
| +
 | 
| +            // precompute coefficients for derivative
 | 
| +            SkScalar AwBwx = -2*(Ax*w - Bx*w);
 | 
| +            SkScalar AxCx = Ax - Cx;
 | 
| +            fXCoeff[0] = Sk8f(2*(AxCx - Ax*w + Cx*w));
 | 
| +            fXCoeff[1] = Sk8f(-2*(AxCx + AwBwx));
 | 
| +            fXCoeff[2] = Sk8f(AwBwx);
 | 
| +
 | 
| +            SkScalar AwBwy = -2*(Ay*w - By*w);
 | 
| +            SkScalar AyCy = Ay - Cy;
 | 
| +            fYCoeff[0] = Sk8f(2*(AyCy - Ay*w + Cy*w));
 | 
| +            fYCoeff[1] = Sk8f(-2*(AyCy + AwBwy));
 | 
| +            fYCoeff[2] = Sk8f(AwBwy);
 | 
| +        }
 | 
|              break;
 | 
|          default:
 | 
|              UNIMPLEMENTED;
 | 
| @@ -148,8 +221,9 @@ ArcLengthIntegrator::ArcLengthIntegrator(const SkPoint* pts, SkSegType segType)
 | 
|  SkScalar ArcLengthIntegrator::computeLength(SkScalar t) {
 | 
|      SkScalar length = 0.0f;
 | 
|  
 | 
| -    Sk8f lengths = evaluateDerivativeLength(absc*t, xCoeff, yCoeff, fSegType);
 | 
| -    lengths = weights*lengths;
 | 
| +    Sk8f lengths =
 | 
| +        evaluateDerivativeLength(absc * t, fXCoeff, fYCoeff, fConicW, fSegType);
 | 
| +    lengths = weights * lengths;
 | 
|      // is it faster or more accurate to sum and then multiply or vice versa?
 | 
|      lengths = lengths*(t*0.5f);
 | 
|  
 | 
| @@ -214,8 +288,8 @@ SkScalar SkCurveMeasure::getTime(SkScalar targetLength) {
 | 
|      }
 | 
|  
 | 
|      SkScalar currentLength = getLength();
 | 
| -
 | 
| -    if (targetLength > currentLength || (SkScalarNearlyEqual(targetLength, currentLength))) {
 | 
| +    if (targetLength > currentLength ||
 | 
| +       (SkScalarNearlyEqual(targetLength, currentLength))) {
 | 
|          return 1.0f;
 | 
|      }
 | 
|      if (kLine_SegType == fSegType) {
 | 
| 
 |