GrTessellator: yet another out-of-range splitting fix.

It's actually possible for an intersection to be out-of-range on both
the intersected edges (e.g., below both bottom points), because
floating point. So we need to clamp against both edges.

Bug: 846014
Change-Id: I9fe25a1fcd3b5242af7b1ee36b17f1e968aeb836
Reviewed-on: https://skia-review.googlesource.com/132323
Reviewed-by: Brian Salomon <bsalomon@google.com>
Commit-Queue: Stephen White <senorblanco@chromium.org>
This commit is contained in:
Stephen White 2018-06-05 18:45:07 -04:00 committed by Skia Commit-Bot
parent e2aa7b6a55
commit e62999f6ef
2 changed files with 29 additions and 9 deletions

View File

@ -1175,6 +1175,16 @@ bool nearly_flat(Comparator& c, Edge* edge) {
return fabs(primaryDiff) < std::numeric_limits<float>::epsilon();
}
SkPoint clamp(SkPoint p, SkPoint min, SkPoint max, Comparator& c) {
if (c.sweep_lt(p, min)) {
return min;
} else if (c.sweep_lt(max, p)) {
return max;
} else {
return p;
}
}
bool check_for_intersection(Edge* edge, Edge* other, EdgeList* activeEdges, Vertex** current,
VertexList* mesh, Comparator& c, SkArenaAlloc& alloc) {
if (!edge || !other) {
@ -1191,15 +1201,13 @@ bool check_for_intersection(Edge* edge, Edge* other, EdgeList* activeEdges, Vert
while (top && c.sweep_lt(p, top->fPoint)) {
top = top->fPrev;
}
if (c.sweep_lt(p, edge->fTop->fPoint) && !nearly_flat(c, edge)) {
v = edge->fTop;
} else if (c.sweep_lt(edge->fBottom->fPoint, p) && !nearly_flat(c, edge)) {
v = edge->fBottom;
} else if (c.sweep_lt(p, other->fTop->fPoint) && !nearly_flat(c, other)) {
v = other->fTop;
} else if (c.sweep_lt(other->fBottom->fPoint, p) && !nearly_flat(c, other)) {
v = other->fBottom;
} else if (p == edge->fTop->fPoint) {
if (!nearly_flat(c, edge)) {
p = clamp(p, edge->fTop->fPoint, edge->fBottom->fPoint, c);
}
if (!nearly_flat(c, other)) {
p = clamp(p, other->fTop->fPoint, other->fBottom->fPoint, c);
}
if (p == edge->fTop->fPoint) {
v = edge->fTop;
} else if (p == edge->fBottom->fPoint) {
v = edge->fBottom;

View File

@ -524,6 +524,17 @@ static SkPath create_path_35() {
return path;
}
// Reduction from crbug.com/843135 where an intersection is found
// below the bottom of both intersected edges.
static SkPath create_path_36() {
SkPath path;
path.moveTo(-2791476679359332352, 2608107002026524672);
path.lineTo( 0, 11.95427703857421875);
path.lineTo(-2781824066779086848, 2599088532777598976);
path.lineTo( -7772.6875, 7274);
return path;
}
static std::unique_ptr<GrFragmentProcessor> create_linear_gradient_processor(GrContext* ctx) {
SkPoint pts[2] = { {0, 0}, {1, 1} };
@ -619,4 +630,5 @@ DEF_GPUTEST_FOR_ALL_CONTEXTS(TessellatingPathRendererTests, reporter, ctxInfo) {
test_path(ctx, rtc.get(), create_path_33());
test_path(ctx, rtc.get(), create_path_34());
test_path(ctx, rtc.get(), create_path_35());
test_path(ctx, rtc.get(), create_path_36());
}