| 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) {
|
|
|