| Index: src/core/SkPathMeasure.cpp
 | 
| diff --git a/src/core/SkPathMeasure.cpp b/src/core/SkPathMeasure.cpp
 | 
| index eb80cf3b831acd3f4493610f8bc0ab2da87daf7d..67862d5e40307b799f2c96ae42ea28ec0d5917d4 100644
 | 
| --- a/src/core/SkPathMeasure.cpp
 | 
| +++ b/src/core/SkPathMeasure.cpp
 | 
| @@ -73,6 +73,15 @@ static bool quad_too_curvy(const SkPoint pts[3]) {
 | 
|      return dist > CHEAP_DIST_LIMIT;
 | 
|  }
 | 
|  
 | 
| +static bool conic_too_curvy(const SkPoint& firstPt, const SkPoint& midTPt,
 | 
| +                            const SkPoint& lastPt) {
 | 
| +    SkPoint midEnds = firstPt + lastPt;
 | 
| +    midEnds *= 0.5f;
 | 
| +    SkVector dxy = midTPt - midEnds;
 | 
| +    SkScalar dist = SkMaxScalar(SkScalarAbs(dxy.fX), SkScalarAbs(dxy.fY));
 | 
| +    return dist > CHEAP_DIST_LIMIT;
 | 
| +}
 | 
| +
 | 
|  static bool cheap_dist_exceeds_limit(const SkPoint& pt,
 | 
|                                       SkScalar x, SkScalar y) {
 | 
|      SkScalar dist = SkMaxScalar(SkScalarAbs(x - pt.fX), SkScalarAbs(y - pt.fY));
 | 
| @@ -90,28 +99,58 @@ static bool cubic_too_curvy(const SkPoint pts[4]) {
 | 
|                           SkScalarInterp(pts[0].fY, pts[3].fY, SK_Scalar1*2/3));
 | 
|  }
 | 
|  
 | 
| +static SkScalar quad_folded_len(const SkPoint pts[3]) {
 | 
| +    SkScalar t = SkFindQuadMaxCurvature(pts);
 | 
| +    SkPoint pt = SkEvalQuadAt(pts, t);
 | 
| +    SkVector a = pts[2] - pt;
 | 
| +    SkScalar result = a.length();
 | 
| +    if (0 != t) {
 | 
| +        SkVector b = pts[0] - pt;
 | 
| +        result += b.length();
 | 
| +    }
 | 
| +    SkASSERT(SkScalarIsFinite(result));
 | 
| +    return result;
 | 
| +}
 | 
| +
 | 
|  /* from http://www.malczak.linuxpl.com/blog/quadratic-bezier-curve-length/ */
 | 
| +/* This works -- more needs to be done to see if it is performant on all platforms.
 | 
| +   To use this to measure parts of quads requires recomputing everything -- perhaps
 | 
| +   a chop-like interface can start from a larger measurement and get two new measurements
 | 
| +   with one call here.
 | 
| + */
 | 
|  static SkScalar compute_quad_len(const SkPoint pts[3]) {
 | 
| -     SkPoint a,b;
 | 
| -     a.fX = pts[0].fX - 2 * pts[1].fX + pts[2].fX;
 | 
| -     a.fY = pts[0].fY - 2 * pts[1].fY + pts[2].fY;
 | 
| -     b.fX = 2 * (pts[1].fX - pts[0].fX);
 | 
| -     b.fY = 2 * (pts[1].fY - pts[0].fY);
 | 
| -     SkScalar A = 4 * (a.fX * a.fX + a.fY * a.fY);
 | 
| -     SkScalar B = 4 * (a.fX * b.fX + a.fY * b.fY);
 | 
| -     SkScalar C =      b.fX * b.fX + b.fY * b.fY;
 | 
| -
 | 
| -     SkScalar Sabc = 2 * SkScalarSqrt(A + B + C);
 | 
| -     SkScalar A_2  = SkScalarSqrt(A);
 | 
| -     SkScalar A_32 = 2 * A * A_2;
 | 
| -     SkScalar C_2  = 2 * SkScalarSqrt(C);
 | 
| -     SkScalar BA   = B / A_2;
 | 
| -
 | 
| -     return (A_32 * Sabc + A_2 * B * (Sabc - C_2) +
 | 
| -            (4 * C * A - B * B) * SkScalarLog((2 * A_2 + BA + Sabc) / (BA + C_2))) / (4 * A_32);
 | 
| +    SkPoint a,b;
 | 
| +    a.fX = pts[0].fX - 2 * pts[1].fX + pts[2].fX;
 | 
| +    a.fY = pts[0].fY - 2 * pts[1].fY + pts[2].fY;
 | 
| +    SkScalar A = 4 * (a.fX * a.fX + a.fY * a.fY);
 | 
| +    if (0 == A) {
 | 
| +        a = pts[2] - pts[0];
 | 
| +        return a.length();
 | 
| +    }
 | 
| +    b.fX = 2 * (pts[1].fX - pts[0].fX);
 | 
| +    b.fY = 2 * (pts[1].fY - pts[0].fY);
 | 
| +    SkScalar B = 4 * (a.fX * b.fX + a.fY * b.fY);
 | 
| +    SkScalar C =      b.fX * b.fX + b.fY * b.fY;
 | 
| +    SkScalar Sabc = 2 * SkScalarSqrt(A + B + C);
 | 
| +    SkScalar A_2  = SkScalarSqrt(A);
 | 
| +    SkScalar A_32 = 2 * A * A_2;
 | 
| +    SkScalar C_2  = 2 * SkScalarSqrt(C);
 | 
| +    SkScalar BA   = B / A_2;
 | 
| +    if (0 == BA + C_2) {
 | 
| +        return quad_folded_len(pts);
 | 
| +    }
 | 
| +    SkScalar J = A_32 * Sabc + A_2 * B * (Sabc - C_2);
 | 
| +    SkScalar K = 4 * C * A - B * B;
 | 
| +    SkScalar L = (2 * A_2 + BA + Sabc) / (BA + C_2);
 | 
| +    if (L <= 0) {
 | 
| +        return quad_folded_len(pts);
 | 
| +    }
 | 
| +    SkScalar M = SkScalarLog(L);
 | 
| +    SkScalar result = (J + K * M) / (4 * A_32);
 | 
| +    SkASSERT(SkScalarIsFinite(result));
 | 
| +    return result;
 | 
|  }
 | 
|  
 | 
| -
 | 
|  SkScalar SkPathMeasure::compute_quad_segs(const SkPoint pts[3],
 | 
|                            SkScalar distance, int mint, int maxt, int ptIndex) {
 | 
|      if (tspan_big_enough(maxt - mint) && quad_too_curvy(pts)) {
 | 
| @@ -136,6 +175,7 @@ SkScalar SkPathMeasure::compute_quad_segs(const SkPoint pts[3],
 | 
|      return distance;
 | 
|  }
 | 
|  
 | 
| +#ifdef SK_SUPPORT_LEGACY_CONIC_MEASURE
 | 
|  SkScalar SkPathMeasure::compute_conic_segs(const SkConic& conic,
 | 
|                                             SkScalar distance, int mint, int maxt, int ptIndex) {
 | 
|      if (tspan_big_enough(maxt - mint) && quad_too_curvy(conic.fPts)) {
 | 
| @@ -159,6 +199,30 @@ SkScalar SkPathMeasure::compute_conic_segs(const SkConic& conic,
 | 
|      }
 | 
|      return distance;
 | 
|  }
 | 
| +#else
 | 
| +SkScalar SkPathMeasure::compute_conic_segs(const SkConic& conic, SkScalar distance,
 | 
| +                                           int mint, const SkPoint& minPt,
 | 
| +                                           int maxt, const SkPoint& maxPt, int ptIndex) {
 | 
| +    int halft = (mint + maxt) >> 1;
 | 
| +    SkPoint halfPt = conic.evalAt(tValue2Scalar(halft));
 | 
| +    if (tspan_big_enough(maxt - mint) && conic_too_curvy(minPt, halfPt, maxPt)) {
 | 
| +        distance = this->compute_conic_segs(conic, distance, mint, minPt, halft, halfPt, ptIndex);
 | 
| +        distance = this->compute_conic_segs(conic, distance, halft, halfPt, maxt, maxPt, ptIndex);
 | 
| +    } else {
 | 
| +        SkScalar d = SkPoint::Distance(minPt, maxPt);
 | 
| +        SkScalar prevD = distance;
 | 
| +        distance += d;
 | 
| +        if (distance > prevD) {
 | 
| +            Segment* seg = fSegments.append();
 | 
| +            seg->fDistance = distance;
 | 
| +            seg->fPtIndex = ptIndex;
 | 
| +            seg->fType = kConic_SegType;
 | 
| +            seg->fTValue = maxt;
 | 
| +        }
 | 
| +    }
 | 
| +    return distance;
 | 
| +}
 | 
| +#endif
 | 
|  
 | 
|  SkScalar SkPathMeasure::compute_cubic_segs(const SkPoint pts[4],
 | 
|                             SkScalar distance, int mint, int maxt, int ptIndex) {
 | 
| @@ -253,7 +317,12 @@ void SkPathMeasure::buildSegments() {
 | 
|              case SkPath::kConic_Verb: {
 | 
|                  const SkConic conic(pts, fIter.conicWeight());
 | 
|                  SkScalar prevD = distance;
 | 
| +#ifdef SK_SUPPORT_LEGACY_CONIC_MEASURE
 | 
|                  distance = this->compute_conic_segs(conic, distance, 0, kMaxTValue, ptIndex);
 | 
| +#else
 | 
| +                distance = this->compute_conic_segs(conic, distance, 0, conic.fPts[0],
 | 
| +                                                    kMaxTValue, conic.fPts[2], ptIndex);
 | 
| +#endif
 | 
|                  if (distance > prevD) {
 | 
|                      // we store the conic weight in our next point, followed by the last 2 pts
 | 
|                      // thus to reconstitue a conic, you'd need to say
 | 
| @@ -406,7 +475,8 @@ static void seg_to(const SkPoint pts[], int segType,
 | 
|                      dst->conicTo(tmp[0].fPts[1], tmp[0].fPts[2], tmp[0].fW);
 | 
|                  }
 | 
|              } else {
 | 
| -                SkConic tmp1[2];
 | 
| +#ifdef SK_SUPPORT_LEGACY_CONIC_MEASURE
 | 
| +                SkConic tmp1[2];	
 | 
|                  conic.chopAt(startT, tmp1);
 | 
|                  if (SK_Scalar1 == stopT) {
 | 
|                      dst->conicTo(tmp1[1].fPts[1], tmp1[1].fPts[2], tmp1[1].fW);
 | 
| @@ -415,6 +485,17 @@ static void seg_to(const SkPoint pts[], int segType,
 | 
|                      tmp1[1].chopAt((stopT - startT) / (SK_Scalar1 - startT), tmp2);
 | 
|                      dst->conicTo(tmp2[0].fPts[1], tmp2[0].fPts[2], tmp2[0].fW);
 | 
|                  }
 | 
| +#else
 | 
| +                if (SK_Scalar1 == stopT) {
 | 
| +                    SkConic tmp1[2];
 | 
| +                    conic.chopAt(startT, tmp1);
 | 
| +                    dst->conicTo(tmp1[1].fPts[1], tmp1[1].fPts[2], tmp1[1].fW);
 | 
| +                } else {
 | 
| +                    SkConic tmp;
 | 
| +                    conic.chopAt(startT, stopT, &tmp);
 | 
| +                    dst->conicTo(tmp.fPts[1], tmp.fPts[2], tmp.fW);
 | 
| +                }
 | 
| +#endif
 | 
|              }
 | 
|          } break;
 | 
|          case kCubic_SegType:
 | 
| 
 |