GrTessellator: handle three consecutive collinear edges.

In some cases, splitting may produce three consecutive edges which
are collinear. The first one was being merged out, causing the third
one to be missed.

The fix is to switch the arguments to merge_edges_*, ensuring that the
second parameter (the destination edge) is never merged out.

Bug: 851409.
Change-Id: I70fbbc506e97a26b259c1443b6d1787adec0f9b0
Reviewed-on: https://skia-review.googlesource.com/138561
Reviewed-by: Robert Phillips <robertphillips@google.com>
Commit-Queue: Stephen White <senorblanco@chromium.org>
This commit is contained in:
Stephen White 2018-06-29 11:41:59 -04:00 committed by Skia Commit-Bot
parent 8deab3ac1e
commit 26bb0e66f2
2 changed files with 18 additions and 5 deletions

View File

@ -1055,16 +1055,16 @@ void merge_collinear_edges(Edge* edge, EdgeList* activeEdges, Vertex** current,
for (;;) {
if (edge->fPrevEdgeAbove && (edge->fTop == edge->fPrevEdgeAbove->fTop ||
!edge->fPrevEdgeAbove->isLeftOf(edge->fTop))) {
merge_edges_above(edge, edge->fPrevEdgeAbove, activeEdges, current, c);
merge_edges_above(edge->fPrevEdgeAbove, edge, activeEdges, current, c);
} else if (edge->fNextEdgeAbove && (edge->fTop == edge->fNextEdgeAbove->fTop ||
!edge->isLeftOf(edge->fNextEdgeAbove->fTop))) {
merge_edges_above(edge, edge->fNextEdgeAbove, activeEdges, current, c);
merge_edges_above(edge->fNextEdgeAbove, edge, activeEdges, current, c);
} else if (edge->fPrevEdgeBelow && (edge->fBottom == edge->fPrevEdgeBelow->fBottom ||
!edge->fPrevEdgeBelow->isLeftOf(edge->fBottom))) {
merge_edges_below(edge, edge->fPrevEdgeBelow, activeEdges, current, c);
merge_edges_below(edge->fPrevEdgeBelow, edge, activeEdges, current, c);
} else if (edge->fNextEdgeBelow && (edge->fBottom == edge->fNextEdgeBelow->fBottom ||
!edge->isLeftOf(edge->fNextEdgeBelow->fBottom))) {
merge_edges_below(edge, edge->fNextEdgeBelow, activeEdges, current, c);
merge_edges_below(edge->fNextEdgeBelow, edge, activeEdges, current, c);
} else {
break;
}

View File

@ -560,7 +560,7 @@ static SkPath create_path_38() {
return path;
}
// Reduction from crbug.com/851409.
// Reduction from crbug.com/851409. Exercises collinear last vertex.
static SkPath create_path_39() {
SkPath path;
path.moveTo(2072553216, 0);
@ -571,6 +571,18 @@ static SkPath create_path_39() {
return path;
}
// Another reduction from crbug.com/851409. Exercises two sequential collinear edges.
static SkPath create_path_40() {
SkPath path;
path.moveTo(2072553216, 0);
path.lineTo(2072553216, 1);
path.lineTo(2072553472, -13);
path.lineTo(2072553216, 0);
path.lineTo(2072553472, -6);
path.lineTo(2072553472, -13);
return path;
}
static std::unique_ptr<GrFragmentProcessor> create_linear_gradient_processor(GrContext* ctx) {
SkPoint pts[2] = { {0, 0}, {1, 1} };
@ -670,4 +682,5 @@ DEF_GPUTEST_FOR_ALL_CONTEXTS(TessellatingPathRendererTests, reporter, ctxInfo) {
test_path(ctx, rtc.get(), create_path_37());
test_path(ctx, rtc.get(), create_path_38(), SkMatrix(), GrAAType::kCoverage);
test_path(ctx, rtc.get(), create_path_39());
test_path(ctx, rtc.get(), create_path_40());
}