diff options
author | lsalzman <lsalzman@mozilla.com> | 2016-05-31 09:46:00 -0700 |
---|---|---|
committer | Commit bot <commit-bot@chromium.org> | 2016-05-31 09:46:00 -0700 |
commit | d15947ea4d2d0ceee797a973a90fc1e5f86772bd (patch) | |
tree | 2189999a592414e9e5974f1e6fb5a1ebfecb3144 /src/gpu | |
parent | 99eb6e2d5abab2cb74e3d413fc99d5cbbfac8765 (diff) |
Filter out degenerate contours in GrConvexPolyEffect
As noticed in a downstream Firefox bug report https://bugzilla.mozilla.org/show_bug.cgi?id=1255062
If a path such as (moveTo, moveTo, lineTo, lineTo, close) is supplied,
and if the non-degenerate contour is convex, the convexity test will
pass, and GrConvexPolyEffect will be used.
However, the path's raw points are used to build the edge list, which
does not filter out degenerate contours. This may cause the polygon to
fail to draw.
This patch ensures that the degenerate contours are filtered out by
using an iterator as the path convexity test does.
BUG=skia:
GOLD_TRYBOT_URL= https://gold.skia.org/search?issue=2018613003
Review-Url: https://codereview.chromium.org/2018613003
Diffstat (limited to 'src/gpu')
-rw-r--r-- | src/gpu/effects/GrConvexPolyEffect.cpp | 56 |
1 files changed, 35 insertions, 21 deletions
diff --git a/src/gpu/effects/GrConvexPolyEffect.cpp b/src/gpu/effects/GrConvexPolyEffect.cpp index 7b78305bb1..caf86c2804 100644 --- a/src/gpu/effects/GrConvexPolyEffect.cpp +++ b/src/gpu/effects/GrConvexPolyEffect.cpp @@ -247,13 +247,6 @@ GrFragmentProcessor* GrConvexPolyEffect::Create(GrPrimitiveEdgeType type, const return nullptr; } - if (path.countPoints() > kMaxEdges) { - return nullptr; - } - - SkPoint pts[kMaxEdges]; - SkScalar edges[3 * kMaxEdges]; - SkPathPriv::FirstDirection dir; // The only way this should fail is if the clip is effectively a infinitely thin line. In that // case nothing is inside the clip. It'd be nice to detect this at a higher level and either @@ -273,24 +266,45 @@ GrFragmentProcessor* GrConvexPolyEffect::Create(GrPrimitiveEdgeType type, const t = *offset; } - int count = path.getPoints(pts, kMaxEdges); + SkScalar edges[3 * kMaxEdges]; + SkPoint pts[4]; + SkPath::Verb verb; + SkPath::Iter iter(path, true); + + // SkPath considers itself convex so long as there is a convex contour within it, + // regardless of any degenerate contours such as a string of moveTos before it. + // Iterate here to consume any degenerate contours and only process the points + // on the actual convex contour. int n = 0; - for (int lastPt = count - 1, i = 0; i < count; lastPt = i++) { - if (pts[lastPt] != pts[i]) { - SkVector v = pts[i] - pts[lastPt]; - v.normalize(); - if (SkPathPriv::kCCW_FirstDirection == dir) { - edges[3 * n] = v.fY; - edges[3 * n + 1] = -v.fX; - } else { - edges[3 * n] = -v.fY; - edges[3 * n + 1] = v.fX; + while ((verb = iter.next(pts, true, true)) != SkPath::kDone_Verb) { + switch (verb) { + case SkPath::kMove_Verb: + SkASSERT(n == 0); + case SkPath::kClose_Verb: + break; + case SkPath::kLine_Verb: { + if (n >= kMaxEdges) { + return nullptr; + } + SkVector v = pts[1] - pts[0]; + v.normalize(); + if (SkPathPriv::kCCW_FirstDirection == dir) { + edges[3 * n] = v.fY; + edges[3 * n + 1] = -v.fX; + } else { + edges[3 * n] = -v.fY; + edges[3 * n + 1] = v.fX; + } + SkPoint p = pts[1] + t; + edges[3 * n + 2] = -(edges[3 * n] * p.fX + edges[3 * n + 1] * p.fY); + ++n; + break; } - SkPoint p = pts[i] + t; - edges[3 * n + 2] = -(edges[3 * n] * p.fX + edges[3 * n + 1] * p.fY); - ++n; + default: + return nullptr; } } + if (path.isInverseFillType()) { type = GrInvertProcessorEdgeType(type); } |