diff options
-rw-r--r-- | src/gpu/GrTessellator.cpp | 43 | ||||
-rw-r--r-- | tests/TessellatingPathRendererTests.cpp | 11 |
2 files changed, 23 insertions, 31 deletions
diff --git a/src/gpu/GrTessellator.cpp b/src/gpu/GrTessellator.cpp index d69833df2e..4d3c1eb0ee 100644 --- a/src/gpu/GrTessellator.cpp +++ b/src/gpu/GrTessellator.cpp @@ -1131,6 +1131,17 @@ void merge_vertices(Vertex* src, Vertex* dst, VertexList* mesh, Comparator& c, mesh->remove(src); } +bool out_of_range_and_collinear(const SkPoint& p, Edge* edge, Comparator& c) { + if (c.sweep_lt(p, edge->fTop->fPoint) && + !Line(p, edge->fBottom->fPoint).dist(edge->fTop->fPoint)) { + return true; + } else if (c.sweep_lt(edge->fBottom->fPoint, p) && + !Line(edge->fTop->fPoint, p).dist(edge->fBottom->fPoint)) { + return true; + } + return false; +} + Vertex* create_sorted_vertex(const SkPoint& p, uint8_t alpha, VertexList* mesh, Vertex* reference, Comparator& c, SkArenaAlloc& alloc) { Vertex* prevV = reference; @@ -1163,12 +1174,6 @@ Vertex* create_sorted_vertex(const SkPoint& p, uint8_t alpha, VertexList* mesh, return v; } -bool nearly_flat(Comparator& c, Edge* edge) { - SkPoint diff = edge->fBottom->fPoint - edge->fTop->fPoint; - float primaryDiff = c.fDirection == Comparator::Direction::kHorizontal ? diff.fX : diff.fY; - return fabs(primaryDiff) < std::numeric_limits<float>::epsilon(); -} - bool check_for_intersection(Edge* edge, Edge* other, EdgeList* activeEdges, Vertex** current, VertexList* mesh, Comparator& c, SkArenaAlloc& alloc) { if (!edge || !other) { @@ -1177,7 +1182,13 @@ bool check_for_intersection(Edge* edge, Edge* other, EdgeList* activeEdges, Vert SkPoint p; uint8_t alpha; if (edge->intersect(*other, &p, &alpha) && p.isFinite()) { - Vertex* v = nullptr; + // Ignore any out-of-range intersections which are also collinear, + // since the resulting edges would cancel each other out by merging. + if (out_of_range_and_collinear(p, edge, c) || + out_of_range_and_collinear(p, other, c)) { + return false; + } + Vertex* v; LOG("found intersection, pt is %g, %g\n", p.fX, p.fY); Vertex* top = *current; // If the intersection point is above the current vertex, rewind to the vertex above the @@ -1185,23 +1196,15 @@ bool check_for_intersection(Edge* edge, Edge* other, EdgeList* activeEdges, Vert while (top && c.sweep_lt(p, top->fPoint)) { top = top->fPrev; } - if (p == edge->fTop->fPoint || - (c.sweep_lt(p, edge->fTop->fPoint) && !nearly_flat(c, edge))) { + if (p == edge->fTop->fPoint) { v = edge->fTop; - } - if (p == edge->fBottom->fPoint || - (c.sweep_lt(edge->fBottom->fPoint, p) && !nearly_flat(c, edge))) { + } else if (p == edge->fBottom->fPoint) { v = edge->fBottom; - } - if (p == other->fTop->fPoint || - (c.sweep_lt(p, other->fTop->fPoint) && !nearly_flat(c, other))) { + } else if (p == other->fTop->fPoint) { v = other->fTop; - } - if (p == other->fBottom->fPoint || - (c.sweep_lt(other->fBottom->fPoint, p) && !nearly_flat(c, other))) { + } else if (p == other->fBottom->fPoint) { v = other->fBottom; - } - if (!v) { + } else { v = create_sorted_vertex(p, alpha, mesh, top, c, alloc); if (edge->fTop->fPartner) { Line line1 = edge->fLine; diff --git a/tests/TessellatingPathRendererTests.cpp b/tests/TessellatingPathRendererTests.cpp index a2dc95986e..00f43985dd 100644 --- a/tests/TessellatingPathRendererTests.cpp +++ b/tests/TessellatingPathRendererTests.cpp @@ -502,16 +502,6 @@ static SkPath create_path_33() { return path; } -// From crbug.com/844873. Hangs repeatedly splitting alternate vertices. -static SkPath create_path_34() { - SkPath path; - path.moveTo(10, -1e+20f); - path.lineTo(11, 25000); - path.lineTo(10, 25000); - path.lineTo(11, 25010); - return path; -} - static std::unique_ptr<GrFragmentProcessor> create_linear_gradient_processor(GrContext* ctx) { SkPoint pts[2] = { {0, 0}, {1, 1} }; @@ -605,6 +595,5 @@ DEF_GPUTEST_FOR_ALL_CONTEXTS(TessellatingPathRendererTests, reporter, ctxInfo) { test_path(ctx, rtc.get(), create_path_31(), SkMatrix(), GrAAType::kCoverage); test_path(ctx, rtc.get(), create_path_32()); test_path(ctx, rtc.get(), create_path_33()); - test_path(ctx, rtc.get(), create_path_34()); } #endif |