From 69aaa5a49a10454d573cbd8c5d980029d78ae459 Mon Sep 17 00:00:00 2001 From: halcanary Date: Wed, 10 Aug 2016 11:40:37 -0700 Subject: Revert 386ba54 and 4ab47e0 : perf debug assert. Revert "Refactor SkCurveMeasure to use existing eval code" This reverts commit 4ab47e087ecfc82f070cbbaef4d9eb562d3fd163. Revert "Fastpath lines in SkCurveMeasure" This reverts commit 386ba540612defc7808edc28126b9b8afcf45b89. TBR= NOTRY=true GOLD_TRYBOT_URL= https://gold.skia.org/search?issue=2233683004 Review-Url: https://codereview.chromium.org/2233683004 --- src/utils/SkCurveMeasure.cpp | 136 ++++++++++++++++++------------------------- src/utils/SkCurveMeasure.h | 16 +++-- 2 files changed, 63 insertions(+), 89 deletions(-) (limited to 'src') diff --git a/src/utils/SkCurveMeasure.cpp b/src/utils/SkCurveMeasure.cpp index 2a74a49c22..fc2aa84faa 100644 --- a/src/utils/SkCurveMeasure.cpp +++ b/src/utils/SkCurveMeasure.cpp @@ -6,66 +6,10 @@ */ #include "SkCurveMeasure.h" -#include "SkGeometry.h" // for abs #include -#define UNIMPLEMENTED SkDEBUGF(("%s:%d unimplemented\n", __FILE__, __LINE__)) - -/// Used inside SkCurveMeasure::getTime's Newton's iteration -static inline SkPoint evaluate(const SkPoint pts[4], SkSegType segType, - SkScalar t) { - SkPoint pos; - switch (segType) { - case kQuad_SegType: - pos = SkEvalQuadAt(pts, t); - break; - case kLine_SegType: - pos = SkPoint::Make(SkScalarInterp(pts[0].x(), pts[1].x(), t), - SkScalarInterp(pts[0].y(), pts[1].y(), t)); - break; - case kCubic_SegType: - SkEvalCubicAt(pts, t, &pos, nullptr, nullptr); - break; - case kConic_SegType: { - SkConic conic(pts, pts[3].x()); - conic.evalAt(t, &pos); - } - break; - default: - UNIMPLEMENTED; - } - - return pos; -} - -/// Used inside SkCurveMeasure::getTime's Newton's iteration -static inline SkVector evaluateDerivative(const SkPoint pts[4], - SkSegType segType, SkScalar t) { - SkVector tan; - switch (segType) { - case kQuad_SegType: - tan = SkEvalQuadTangentAt(pts, t); - break; - case kLine_SegType: - tan = pts[1] - pts[0]; - break; - case kCubic_SegType: - SkEvalCubicAt(pts, t, nullptr, &tan, nullptr); - break; - case kConic_SegType: { - SkConic conic(pts, pts[3].x()); - conic.evalAt(t, nullptr, &tan); - } - break; - default: - UNIMPLEMENTED; - } - - return tan; -} -/// Used in ArcLengthIntegrator::computeLength static inline Sk8f evaluateDerivativeLength(const Sk8f& ts, const Sk8f (&xCoeff)[3], const Sk8f (&yCoeff)[3], @@ -77,15 +21,18 @@ static inline Sk8f evaluateDerivativeLength(const Sk8f& ts, x = xCoeff[0]*ts + xCoeff[1]; y = yCoeff[0]*ts + yCoeff[1]; break; + case kLine_SegType: + SkDebugf("Unimplemented"); + break; case kCubic_SegType: x = (xCoeff[0]*ts + xCoeff[1])*ts + xCoeff[2]; y = (yCoeff[0]*ts + yCoeff[1])*ts + yCoeff[2]; break; case kConic_SegType: - UNIMPLEMENTED; + SkDebugf("Unimplemented"); break; default: - UNIMPLEMENTED; + SkDebugf("Unimplemented"); } x = x * x; @@ -93,7 +40,6 @@ static inline Sk8f evaluateDerivativeLength(const Sk8f& ts, return (x + y).sqrt(); } - ArcLengthIntegrator::ArcLengthIntegrator(const SkPoint* pts, SkSegType segType) : fSegType(segType) { switch (fSegType) { @@ -113,6 +59,9 @@ ArcLengthIntegrator::ArcLengthIntegrator(const SkPoint* pts, SkSegType segType) yCoeff[1] = Sk8f(2.0f*(By - Ay)); } break; + case kLine_SegType: + SkDEBUGF(("Unimplemented")); + break; case kCubic_SegType: { float Ax = pts[0].x(); @@ -124,7 +73,6 @@ ArcLengthIntegrator::ArcLengthIntegrator(const SkPoint* pts, SkSegType segType) float Cy = pts[2].y(); float Dy = pts[3].y(); - // precompute coefficients for derivative xCoeff[0] = Sk8f(3.0f*(-Ax + 3.0f*(Bx - Cx) + Dx)); xCoeff[1] = Sk8f(3.0f*(2.0f*(Ax - 2.0f*Bx + Cx))); xCoeff[2] = Sk8f(3.0f*(-Ax + Bx)); @@ -135,10 +83,10 @@ ArcLengthIntegrator::ArcLengthIntegrator(const SkPoint* pts, SkSegType segType) } break; case kConic_SegType: - UNIMPLEMENTED; + SkDEBUGF(("Unimplemented")); break; default: - UNIMPLEMENTED; + SkDEBUGF(("Unimplemented")); } } @@ -169,9 +117,7 @@ SkCurveMeasure::SkCurveMeasure(const SkPoint* pts, SkSegType segType) } break; case SkSegType::kLine_SegType: - fPts[0] = pts[0]; - fPts[1] = pts[1]; - fLength = (fPts[1] - fPts[0]).length(); + SkDebugf("Unimplemented"); break; case SkSegType::kCubic_SegType: for (size_t i = 0; i < 4; i++) { @@ -179,17 +125,13 @@ SkCurveMeasure::SkCurveMeasure(const SkPoint* pts, SkSegType segType) } break; case SkSegType::kConic_SegType: - for (size_t i = 0; i < 4; i++) { - fPts[i] = pts[i]; - } + SkDebugf("Unimplemented"); break; default: - UNIMPLEMENTED; + SkDEBUGF(("Unimplemented")); break; } - if (kLine_SegType != segType) { - fIntegrator = ArcLengthIntegrator(fPts, fSegType); - } + fIntegrator = ArcLengthIntegrator(fPts, fSegType); } SkScalar SkCurveMeasure::getLength() { @@ -218,9 +160,6 @@ SkScalar SkCurveMeasure::getTime(SkScalar targetLength) { if (SkScalarNearlyEqual(targetLength, currentLength)) { return 1.0f; } - if (kLine_SegType == fSegType) { - return targetLength / currentLength; - } // initial estimate of t is percentage of total length SkScalar currentT = targetLength / currentLength; @@ -260,8 +199,9 @@ SkScalar SkCurveMeasure::getTime(SkScalar targetLength) { prevT = currentT; if (iterations < kNewtonIters) { + // TODO(hstern) switch here on curve type. // This is just newton's formula. - SkScalar dt = evaluateDerivative(fPts, fSegType, currentT).length(); + SkScalar dt = evaluateQuadDerivative(currentT).length(); newT = currentT - (lengthDiff / dt); // If newT is out of bounds, bisect inside newton. @@ -278,7 +218,7 @@ SkScalar SkCurveMeasure::getTime(SkScalar targetLength) { newT = (minT + maxT) * 0.5f; } else { SkDEBUGF(("%.7f %.7f didn't get close enough after bisection.\n", - currentT, currentLength)); + currentT, currentLength)); break; } currentT = newT; @@ -295,16 +235,52 @@ SkScalar SkCurveMeasure::getTime(SkScalar targetLength) { } void SkCurveMeasure::getPosTanTime(SkScalar targetLength, SkPoint* pos, - SkVector* tan, SkScalar* time) { + SkVector* tan, SkScalar* time) { SkScalar t = getTime(targetLength); if (time) { *time = t; } if (pos) { - *pos = evaluate(fPts, fSegType, t); + // TODO(hstern) switch here on curve type. + *pos = evaluateQuad(t); } if (tan) { - *tan = evaluateDerivative(fPts, fSegType, t); + // TODO(hstern) switch here on curve type. + *tan = evaluateQuadDerivative(t); } } + +// this is why I feel that the ArcLengthIntegrator should be combined +// with some sort of evaluator that caches the constants computed from the +// control points. this is basically the same code in ArcLengthIntegrator +SkPoint SkCurveMeasure::evaluateQuad(SkScalar t) { + SkScalar ti = 1.0f - t; + + SkScalar Ax = fPts[0].x(); + SkScalar Bx = fPts[1].x(); + SkScalar Cx = fPts[2].x(); + SkScalar Ay = fPts[0].y(); + SkScalar By = fPts[1].y(); + SkScalar Cy = fPts[2].y(); + + SkScalar x = Ax*ti*ti + 2.0f*Bx*t*ti + Cx*t*t; + SkScalar y = Ay*ti*ti + 2.0f*By*t*ti + Cy*t*t; + return SkPoint::Make(x, y); +} + +SkVector SkCurveMeasure::evaluateQuadDerivative(SkScalar t) { + SkScalar Ax = fPts[0].x(); + SkScalar Bx = fPts[1].x(); + SkScalar Cx = fPts[2].x(); + SkScalar Ay = fPts[0].y(); + SkScalar By = fPts[1].y(); + SkScalar Cy = fPts[2].y(); + + SkScalar A2BCx = 2.0f*(Ax - 2*Bx + Cx); + SkScalar A2BCy = 2.0f*(Ay - 2*By + Cy); + SkScalar ABx = 2.0f*(Bx - Ax); + SkScalar ABy = 2.0f*(By - Ay); + + return SkPoint::Make(A2BCx*t + ABx, A2BCy*t + ABy); +} diff --git a/src/utils/SkCurveMeasure.h b/src/utils/SkCurveMeasure.h index 5807211236..2846103633 100644 --- a/src/utils/SkCurveMeasure.h +++ b/src/utils/SkCurveMeasure.h @@ -44,15 +44,6 @@ private: class SkCurveMeasure { public: SkCurveMeasure() {} - - // Almost exactly the same as in SkPath::Iter: - // kLine_SegType -> 2 points: start end - // kQuad_SegType -> 3 points: start control end - // kCubic_SegType -> 4 points: start control1 control2 end - // kConic_SegType -> 4 points: start control end (w, w) - // - // i.e. the only difference is that the conic's last point is a point - // consisting of the w value twice SkCurveMeasure(const SkPoint* pts, SkSegType segType); SkScalar getTime(SkScalar targetLength); @@ -60,6 +51,13 @@ public: SkScalar getLength(); private: + SkPoint evaluateQuad(SkScalar t); + SkVector evaluateQuadDerivative(SkScalar t); + //SkPoint evaluate_cubic(SkScalar t); + //SkVector evaluate_cubic_derivative(SkScalar t); + //SkPoint evaluate_conic(SkScalar t); + //SkVector evaluate_conic_derivative(SkScalar t); + const SkScalar kTolerance = 0.0001f; const int kNewtonIters = 5; const int kBisectIters = 5; -- cgit v1.2.3