Index: src/gpu/GrPathUtils.cpp |
diff --git a/src/gpu/GrPathUtils.cpp b/src/gpu/GrPathUtils.cpp |
index 8e4eeb0a3141fec7c7b45f5149d53c4651de5d73..464231a8dc3656b184c837f9dacac8d7c373a17f 100644 |
--- a/src/gpu/GrPathUtils.cpp |
+++ b/src/gpu/GrPathUtils.cpp |
@@ -405,49 +405,56 @@ void convert_noninflect_cubic_to_quads(const SkPoint p[4], |
dc = p[1] - p[3]; |
} |
- // When the ab and cd tangents are nearly parallel with vector from d to a the constraint that |
- // the quad point falls between the tangents becomes hard to enforce and we are likely to hit |
- // the max subdivision count. However, in this case the cubic is approaching a line and the |
- // accuracy of the quad point isn't so important. We check if the two middle cubic control |
- // points are very close to the baseline vector. If so then we just pick quadratic points on the |
- // control polygon. |
+ // When the ab and cd tangents are degenerate or nearly parallel with vector from d to a the |
+ // constraint that the quad point falls between the tangents becomes hard to enforce and we are |
+ // likely to hit the max subdivision count. However, in this case the cubic is approaching a |
+ // line and the accuracy of the quad point isn't so important. We check if the two middle cubic |
+ // control points are very close to the baseline vector. If so then we just pick quadratic |
+ // points on the control polygon. |
if (constrainWithinTangents) { |
SkVector da = p[0] - p[3]; |
- SkScalar invDALengthSqd = da.lengthSqd(); |
- if (invDALengthSqd > SK_ScalarNearlyZero) { |
- invDALengthSqd = SkScalarInvert(invDALengthSqd); |
- // cross(ab, da)^2/length(da)^2 == sqd distance from b to line from d to a. |
- // same goed for point c using vector cd. |
- SkScalar detABSqd = ab.cross(da); |
- detABSqd = SkScalarSquare(detABSqd); |
- SkScalar detDCSqd = dc.cross(da); |
- detDCSqd = SkScalarSquare(detDCSqd); |
- if (SkScalarMul(detABSqd, invDALengthSqd) < toleranceSqd && |
- SkScalarMul(detDCSqd, invDALengthSqd) < toleranceSqd) { |
- SkPoint b = p[0] + ab; |
- SkPoint c = p[3] + dc; |
- SkPoint mid = b + c; |
- mid.scale(SK_ScalarHalf); |
- // Insert two quadratics to cover the case when ab points away from d and/or dc |
- // points away from a. |
- if (SkVector::DotProduct(da, dc) < 0 || SkVector::DotProduct(ab,da) > 0) { |
- SkPoint* qpts = quads->push_back_n(6); |
- qpts[0] = p[0]; |
- qpts[1] = b; |
- qpts[2] = mid; |
- qpts[3] = mid; |
- qpts[4] = c; |
- qpts[5] = p[3]; |
- } else { |
- SkPoint* qpts = quads->push_back_n(3); |
- qpts[0] = p[0]; |
- qpts[1] = mid; |
- qpts[2] = p[3]; |
+ bool doQuads = dc.lengthSqd() < SK_ScalarNearlyZero || |
+ ab.lengthSqd() < SK_ScalarNearlyZero; |
+ if (!doQuads) { |
+ SkScalar invDALengthSqd = da.lengthSqd(); |
+ if (invDALengthSqd > SK_ScalarNearlyZero) { |
+ invDALengthSqd = SkScalarInvert(invDALengthSqd); |
+ // cross(ab, da)^2/length(da)^2 == sqd distance from b to line from d to a. |
+ // same goes for point c using vector cd. |
+ SkScalar detABSqd = ab.cross(da); |
+ detABSqd = SkScalarSquare(detABSqd); |
+ SkScalar detDCSqd = dc.cross(da); |
+ detDCSqd = SkScalarSquare(detDCSqd); |
+ if (SkScalarMul(detABSqd, invDALengthSqd) < toleranceSqd && |
+ SkScalarMul(detDCSqd, invDALengthSqd) < toleranceSqd) { |
+ doQuads = true; |
} |
- return; |
} |
} |
+ if (doQuads) { |
+ SkPoint b = p[0] + ab; |
+ SkPoint c = p[3] + dc; |
+ SkPoint mid = b + c; |
+ mid.scale(SK_ScalarHalf); |
+ // Insert two quadratics to cover the case when ab points away from d and/or dc |
+ // points away from a. |
+ if (SkVector::DotProduct(da, dc) < 0 || SkVector::DotProduct(ab,da) > 0) { |
+ SkPoint* qpts = quads->push_back_n(6); |
+ qpts[0] = p[0]; |
+ qpts[1] = b; |
+ qpts[2] = mid; |
+ qpts[3] = mid; |
+ qpts[4] = c; |
+ qpts[5] = p[3]; |
+ } else { |
+ SkPoint* qpts = quads->push_back_n(3); |
+ qpts[0] = p[0]; |
+ qpts[1] = mid; |
+ qpts[2] = p[3]; |
+ } |
+ return; |
+ } |
} |
static const SkScalar kLengthScale = 3 * SK_Scalar1 / 2; |