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
This commit is contained in:
parent
b3310c2221
commit
a2b6d28755
@ -958,6 +958,11 @@ void split_edge(Edge* edge, Vertex* v, Edge** activeEdges, SkChunkAlloc& alloc)
|
|||||||
LOG("splitting edge (%g -> %g) at vertex %g (%g, %g)\n",
|
LOG("splitting edge (%g -> %g) at vertex %g (%g, %g)\n",
|
||||||
edge->fTop->fID, edge->fBottom->fID,
|
edge->fTop->fID, edge->fBottom->fID,
|
||||||
v->fID, v->fPoint.fX, v->fPoint.fY);
|
v->fID, v->fPoint.fX, v->fPoint.fY);
|
||||||
|
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);
|
Edge* newEdge = ALLOC_NEW(Edge, (v, edge->fBottom, edge->fWinding), alloc);
|
||||||
insert_edge_below(newEdge, v);
|
insert_edge_below(newEdge, v);
|
||||||
insert_edge_above(newEdge, edge->fBottom);
|
insert_edge_above(newEdge, edge->fBottom);
|
||||||
@ -966,6 +971,7 @@ void split_edge(Edge* edge, Vertex* v, Edge** activeEdges, SkChunkAlloc& alloc)
|
|||||||
fix_active_state(newEdge, activeEdges);
|
fix_active_state(newEdge, activeEdges);
|
||||||
merge_collinear_edges(newEdge, activeEdges);
|
merge_collinear_edges(newEdge, activeEdges);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void merge_vertices(Vertex* src, Vertex* dst, Vertex** head, SkChunkAlloc& alloc) {
|
void merge_vertices(Vertex* src, Vertex* dst, Vertex** head, SkChunkAlloc& alloc) {
|
||||||
LOG("found coincident verts at %g, %g; merging %g into %g\n", src->fPoint.fX, src->fPoint.fY,
|
LOG("found coincident verts at %g, %g; merging %g into %g\n", src->fPoint.fX, src->fPoint.fY,
|
||||||
|
@ -220,6 +220,16 @@ static SkPath create_path_14() {
|
|||||||
return path;
|
return path;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static SkPath create_path_15() {
|
||||||
|
SkPath path;
|
||||||
|
path.moveTo( 0.0f, 0.0f);
|
||||||
|
path.lineTo(10000.0f, 0.0f);
|
||||||
|
path.lineTo( 0.0f, -1.0f);
|
||||||
|
path.lineTo(10000.0f, 0.000001f);
|
||||||
|
path.lineTo( 0.0f, -30.0f);
|
||||||
|
return path;
|
||||||
|
}
|
||||||
|
|
||||||
static void test_path(GrDrawTarget* dt, GrRenderTarget* rt, const SkPath& path) {
|
static void test_path(GrDrawTarget* dt, GrRenderTarget* rt, const SkPath& path) {
|
||||||
GrTessellatingPathRenderer tess;
|
GrTessellatingPathRenderer tess;
|
||||||
GrPipelineBuilder pipelineBuilder;
|
GrPipelineBuilder pipelineBuilder;
|
||||||
@ -259,5 +269,6 @@ DEF_GPUTEST(TessellatingPathRendererTests, reporter, factory) {
|
|||||||
test_path(dt, rt, create_path_12());
|
test_path(dt, rt, create_path_12());
|
||||||
test_path(dt, rt, create_path_13());
|
test_path(dt, rt, create_path_13());
|
||||||
test_path(dt, rt, create_path_14());
|
test_path(dt, rt, create_path_14());
|
||||||
|
test_path(dt, rt, create_path_15());
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
Loading…
Reference in New Issue
Block a user