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

Unified Diff: src/core/SkGeometry.cpp

Issue 1311273002: fix zero-length tangent (Closed) Base URL: https://skia.googlesource.com/skia.git@master
Patch Set: remove duplicate code; add unit tests Created 5 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 | « gm/strokes.cpp ('k') | tests/GeometryTest.cpp » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/core/SkGeometry.cpp
diff --git a/src/core/SkGeometry.cpp b/src/core/SkGeometry.cpp
index 6afd9d7ffb0ed1478b6afd0062a76ce93f2db02a..4f820795a002b5d947f226de706b388f66a79c00 100644
--- a/src/core/SkGeometry.cpp
+++ b/src/core/SkGeometry.cpp
@@ -130,13 +130,6 @@ static SkScalar eval_quad(const SkScalar src[], SkScalar t) {
#endif
}
-static SkScalar eval_quad_derivative(const SkScalar src[], SkScalar t) {
- SkScalar A = src[4] - 2 * src[2] + src[0];
- SkScalar B = src[2] - src[0];
-
- return 2 * SkScalarMulAdd(A, t, B);
-}
-
void SkQuadToCoeff(const SkPoint pts[3], SkPoint coeff[3]) {
Sk2s p0 = from_point(pts[0]);
Sk2s p1 = from_point(pts[1]);
@@ -157,8 +150,7 @@ void SkEvalQuadAt(const SkPoint src[3], SkScalar t, SkPoint* pt, SkVector* tange
pt->set(eval_quad(&src[0].fX, t), eval_quad(&src[0].fY, t));
}
if (tangent) {
- tangent->set(eval_quad_derivative(&src[0].fX, t),
- eval_quad_derivative(&src[0].fY, t));
+ *tangent = SkEvalQuadTangentAt(src, t);
}
}
@@ -179,6 +171,12 @@ SkPoint SkEvalQuadAt(const SkPoint src[3], SkScalar t) {
}
SkVector SkEvalQuadTangentAt(const SkPoint src[3], SkScalar t) {
+ // The derivative equation is 2(b - a +(a - 2b +c)t). This returns a
+ // zero tangent vector when t is 0 or 1, and the control point is equal
+ // to the end point. In this case, use the quad end points to compute the tangent.
+ if ((t == 0 && src[0] == src[1]) || (t == 1 && src[1] == src[2])) {
+ return src[2] - src[0];
+ }
SkASSERT(src);
SkASSERT(t >= 0 && t <= SK_Scalar1);
@@ -398,8 +396,22 @@ void SkEvalCubicAt(const SkPoint src[4], SkScalar t, SkPoint* loc,
loc->set(eval_cubic(&src[0].fX, t), eval_cubic(&src[0].fY, t));
}
if (tangent) {
- tangent->set(eval_cubic_derivative(&src[0].fX, t),
- eval_cubic_derivative(&src[0].fY, t));
+ // The derivative equation returns a zero tangent vector when t is 0 or 1, and the
+ // adjacent control point is equal to the end point. In this case, use the
+ // next control point or the end points to compute the tangent.
+ if ((t == 0 && src[0] == src[1]) || (t == 1 && src[2] == src[3])) {
+ if (t == 0) {
+ *tangent = src[2] - src[0];
+ } else {
+ *tangent = src[3] - src[1];
+ }
+ if (!tangent->fX && !tangent->fY) {
+ *tangent = src[3] - src[0];
+ }
+ } else {
+ tangent->set(eval_cubic_derivative(&src[0].fX, t),
+ eval_cubic_derivative(&src[0].fY, t));
+ }
}
if (curvature) {
curvature->set(eval_cubic_2ndDerivative(&src[0].fX, t),
@@ -1176,12 +1188,6 @@ static void conic_deriv_coeff(const SkScalar src[],
coeff[2] = wP10;
}
-static SkScalar conic_eval_tan(const SkScalar coord[], SkScalar w, SkScalar t) {
- SkScalar coeff[3];
- conic_deriv_coeff(coord, w, coeff);
- return t * (t * coeff[0] + coeff[1]) + coeff[2];
-}
-
static bool conic_find_extrema(const SkScalar src[], SkScalar w, SkScalar* t) {
SkScalar coeff[3];
conic_deriv_coeff(src, w, coeff);
@@ -1232,8 +1238,7 @@ void SkConic::evalAt(SkScalar t, SkPoint* pt, SkVector* tangent) const {
conic_eval_pos(&fPts[0].fY, fW, t));
}
if (tangent) {
- tangent->set(conic_eval_tan(&fPts[0].fX, fW, t),
- conic_eval_tan(&fPts[0].fY, fW, t));
+ *tangent = evalTangentAt(t);
}
}
@@ -1291,6 +1296,12 @@ SkPoint SkConic::evalAt(SkScalar t) const {
}
SkVector SkConic::evalTangentAt(SkScalar t) const {
+ // The derivative equation returns a zero tangent vector when t is 0 or 1,
+ // and the control point is equal to the end point.
+ // In this case, use the conic endpoints to compute the tangent.
+ if ((t == 0 && fPts[0] == fPts[1]) || (t == 1 && fPts[1] == fPts[2])) {
+ return fPts[2] - fPts[0];
+ }
Sk2s p0 = from_point(fPts[0]);
Sk2s p1 = from_point(fPts[1]);
Sk2s p2 = from_point(fPts[2]);
« no previous file with comments | « gm/strokes.cpp ('k') | tests/GeometryTest.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698