diff options
author | senorblanco <senorblanco@chromium.org> | 2015-03-02 09:34:13 -0800 |
---|---|---|
committer | Commit bot <commit-bot@chromium.org> | 2015-03-02 09:34:13 -0800 |
commit | a2b6d28755916cbb4817cd9d1cd1b0e237de9a50 (patch) | |
tree | f801855466786da0e0100752e4aadd8caa619c07 /src/gpu | |
parent | b3310c222104d9234970c684d2b88b13038db7f0 (diff) |
Fix for out-of-bounds intersection (found by fuzzer).
Sometimes, the intersection returned by check_intersection() is
out-of-bounds for both edges (above both tops or below both bottoms)
due to floating-point inaccuracy. This causes split_edge() to create a
tiny negative-length edge on one side (which would then assert).
Although we could safely remove this assert and allow the negative
length edge to be removed, it's faster/safer to simply avoid its
creation in the first place by adjusting one edge to the other edge's
endpoint.
Added a new unit test to exercise this case.
Review URL: https://codereview.chromium.org/968993002
Diffstat (limited to 'src/gpu')
-rw-r--r-- | src/gpu/GrTessellatingPathRenderer.cpp | 20 |
1 files changed, 13 insertions, 7 deletions
diff --git a/src/gpu/GrTessellatingPathRenderer.cpp b/src/gpu/GrTessellatingPathRenderer.cpp index be28a69106..a9ae6fa4e1 100644 --- a/src/gpu/GrTessellatingPathRenderer.cpp +++ b/src/gpu/GrTessellatingPathRenderer.cpp @@ -958,13 +958,19 @@ void split_edge(Edge* edge, Vertex* v, Edge** activeEdges, SkChunkAlloc& alloc) LOG("splitting edge (%g -> %g) at vertex %g (%g, %g)\n", edge->fTop->fID, edge->fBottom->fID, v->fID, v->fPoint.fX, v->fPoint.fY); - Edge* newEdge = ALLOC_NEW(Edge, (v, edge->fBottom, edge->fWinding), alloc); - insert_edge_below(newEdge, v); - insert_edge_above(newEdge, edge->fBottom); - set_bottom(edge, v, activeEdges); - cleanup_active_edges(edge, activeEdges, alloc); - fix_active_state(newEdge, activeEdges); - merge_collinear_edges(newEdge, activeEdges); + if (sweep_lt(v->fPoint, edge->fTop->fPoint)) { + set_top(edge, v, activeEdges); + } else if (sweep_gt(v->fPoint, edge->fBottom->fPoint)) { + set_bottom(edge, v, activeEdges); + } else { + Edge* newEdge = ALLOC_NEW(Edge, (v, edge->fBottom, edge->fWinding), alloc); + insert_edge_below(newEdge, v); + insert_edge_above(newEdge, edge->fBottom); + set_bottom(edge, v, activeEdges); + cleanup_active_edges(edge, activeEdges, alloc); + fix_active_state(newEdge, activeEdges); + merge_collinear_edges(newEdge, activeEdges); + } } void merge_vertices(Vertex* src, Vertex* dst, Vertex** head, SkChunkAlloc& alloc) { |