Add GrPathUtils::conicHasCusp

Bug: skia:10419
Change-Id: I4250dddf463a66f803148310304f29e0c629bc33
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/397657
Commit-Queue: Chris Dalton <csmartdalton@google.com>
Reviewed-by: Greg Daniel <egdaniel@google.com>
This commit is contained in:
Chris Dalton 2021-04-19 20:55:16 -06:00 committed by Skia Commit-Bot
parent 1a15e57ce6
commit 6475638790
3 changed files with 14 additions and 18 deletions

View File

@ -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

View File

@ -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);

View File

@ -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.