From 647563879004712ea3940a6fa95145f57b8184bc Mon Sep 17 00:00:00 2001 From: Chris Dalton Date: Mon, 19 Apr 2021 20:55:16 -0600 Subject: [PATCH] Add GrPathUtils::conicHasCusp Bug: skia:10419 Change-Id: I4250dddf463a66f803148310304f29e0c629bc33 Reviewed-on: https://skia-review.googlesource.com/c/skia/+/397657 Commit-Queue: Chris Dalton Reviewed-by: Greg Daniel --- src/gpu/geometry/GrPathUtils.h | 11 +++++++++++ src/gpu/tessellate/GrStrokeHardwareTessellator.cpp | 13 ++----------- src/gpu/tessellate/GrStrokeIndirectTessellator.cpp | 8 +------- 3 files changed, 14 insertions(+), 18 deletions(-) diff --git a/src/gpu/geometry/GrPathUtils.h b/src/gpu/geometry/GrPathUtils.h index 259571d6ff..fdbd45ca53 100644 --- a/src/gpu/geometry/GrPathUtils.h +++ b/src/gpu/geometry/GrPathUtils.h @@ -162,6 +162,17 @@ inline void convertQuadToCubic(const SkPoint p[3], SkPoint out[4]) { // point(s) occurred at 180-degree turnaround points on a degenerate flat line. int findCubicConvex180Chops(const SkPoint[], float T[2], bool* areCusps); +// Returns true if the given conic (or quadratic) has a cusp point. The w value is not necessary in +// determining this. If there is a cusp, it can be found at the midtangent. +inline bool conicHasCusp(const SkPoint p[3]) { + SkVector a = p[1] - p[0]; + SkVector b = p[2] - p[1]; + // A conic of any class can only have a cusp if it is a degenerate flat line with a 180 degree + // turnarund. To detect this, the beginning and ending tangents must be parallel + // (a.cross(b) == 0) and pointing in opposite directions (a.dot(b) < 0). + return a.cross(b) == 0 && a.dot(b) < 0; +} + } // namespace GrPathUtils #endif diff --git a/src/gpu/tessellate/GrStrokeHardwareTessellator.cpp b/src/gpu/tessellate/GrStrokeHardwareTessellator.cpp index aee3ab38e5..8dc2783022 100644 --- a/src/gpu/tessellate/GrStrokeHardwareTessellator.cpp +++ b/src/gpu/tessellate/GrStrokeHardwareTessellator.cpp @@ -634,15 +634,6 @@ private: GrVertexColor fDynamicColor; }; -SK_ALWAYS_INLINE static bool conic_has_cusp(const SkPoint p[3]) { - SkVector a = p[1] - p[0]; - SkVector b = p[2] - p[1]; - // A conic of any class can only have a cusp if it is a degenerate flat line with a 180 degree - // turnarund. To detect this, the beginning and ending tangents must be parallel - // (a.cross(b) == 0) and pointing in opposite directions (a.dot(b) < 0). - return a.cross(b) == 0 && a.dot(b) < 0; -} - SK_ALWAYS_INLINE static bool cubic_has_cusp(const SkPoint p[4]) { using grvx::float2; @@ -764,7 +755,7 @@ void GrStrokeHardwareTessellator::prepare(GrMeshDrawOp::Target* target, patchWriter.writeLineTo(p[0], p[2]); continue; } - if (conic_has_cusp(p)) { + if (GrPathUtils::conicHasCusp(p)) { // Cusps are rare, but the tessellation shader can't handle them. Chop the // curve into segments that the shader can handle. SkPoint cusp = SkEvalQuadAt(p, SkFindQuadMidTangent(p)); @@ -799,7 +790,7 @@ void GrStrokeHardwareTessellator::prepare(GrMeshDrawOp::Target* target, patchWriter.writeLineTo(p[0], p[2]); continue; } - if (conic_has_cusp(p)) { + if (GrPathUtils::conicHasCusp(p)) { // Cusps are rare, but the tessellation shader can't handle them. Chop the // curve into segments that the shader can handle. SkConic conic(p, *w); diff --git a/src/gpu/tessellate/GrStrokeIndirectTessellator.cpp b/src/gpu/tessellate/GrStrokeIndirectTessellator.cpp index 93a2ede22c..254e46f781 100644 --- a/src/gpu/tessellate/GrStrokeIndirectTessellator.cpp +++ b/src/gpu/tessellate/GrStrokeIndirectTessellator.cpp @@ -526,13 +526,7 @@ GrStrokeIndirectTessellator::GrStrokeIndirectTessellator(ShaderFlags shaderFlags // close to what the actual number of subdivisions would have been. [[fallthrough]]; case Verb::kQuad: { - // Check for a cusp. A conic of any class can only have a cusp if it is a - // degenerate flat line with a 180 degree turnarund. To detect this, the - // beginning and ending tangents must be parallel (a.cross(b) == 0) and pointing - // in opposite directions (a.dot(b) < 0). - SkVector a = pts[1] - pts[0]; - SkVector b = pts[2] - pts[1]; - if (a.cross(b) == 0 && a.dot(b) < 0) { + if (GrPathUtils::conicHasCusp(pts)) { // The curve has a cusp. Draw two lines and a circle instead of a quad. int8_t cuspResolveLevel = counter.countCircles(1); *nextResolveLevel++ = -cuspResolveLevel; // Negative signals a cusp.