Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(123)

Unified Diff: src/utils/SkCurveMeasure.cpp

Issue 2243313002: Implement Conics in SkCurveMeasure (Closed) Base URL: https://skia.googlesource.com/skia.git@cubic_fix
Patch Set: Refactor coefficients and minor fixups Created 4 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « src/utils/SkCurveMeasure.h ('k') | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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) {
« no previous file with comments | « src/utils/SkCurveMeasure.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698