aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorGravatar Stephen White <senorblanco@chromium.org>2018-06-29 17:02:21 -0400
committerGravatar Skia Commit-Bot <skia-commit-bot@chromium.org>2018-07-02 21:03:43 +0000
commit24289e05d55ccdc04ef239c7972d2b52e402ad0f (patch)
treefe43efa9e511fa7ef67355d929436761ab36b1d4
parente886e80e8b204460a78dabf5c671b7f4146d71f7 (diff)
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: I65be2e8222846c99f7bc8d17ea61ddead617cc31 Reviewed-on: https://skia-review.googlesource.com/138700 Reviewed-by: Robert Phillips <robertphillips@google.com> Commit-Queue: Stephen White <senorblanco@chromium.org>
-rw-r--r--src/gpu/GrTessellator.cpp10
-rw-r--r--tests/TessellatingPathRendererTests.cpp15
2 files changed, 19 insertions, 6 deletions
diff --git a/src/gpu/GrTessellator.cpp b/src/gpu/GrTessellator.cpp
index 6cd54380e6..78616d4e2f 100644
--- a/src/gpu/GrTessellator.cpp
+++ b/src/gpu/GrTessellator.cpp
@@ -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;
}
@@ -1755,7 +1755,7 @@ void reconnect_all_overlap_edges(Vertex* src, Vertex* dst, Edge* current, Compar
}
void Event::apply(VertexList* mesh, Comparator& c, SkArenaAlloc& alloc) {
- if (!fEdge) {
+ if (!fEdge || !fEdge->fTop || !fEdge->fBottom) {
return;
}
Vertex* top = fEdge->fTop;
diff --git a/tests/TessellatingPathRendererTests.cpp b/tests/TessellatingPathRendererTests.cpp
index a9913769df..0c7a5ca4c5 100644
--- a/tests/TessellatingPathRendererTests.cpp
+++ b/tests/TessellatingPathRendererTests.cpp
@@ -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());
}