aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/gpu/GrTessellator.cpp
diff options
context:
space:
mode:
authorGravatar Stephen White <senorblanco@chromium.org>2017-08-15 17:01:15 -0400
committerGravatar Skia Commit-Bot <skia-commit-bot@chromium.org>2017-08-16 13:52:48 +0000
commit3f5301b284f195305371657801b1fc167a7f2671 (patch)
treec7aad233961b54f27a948e84cbd6431ee3f248be /src/gpu/GrTessellator.cpp
parent4c72b266da265d5d31096997ca2d11b4171ec240 (diff)
GrTessellator: fix for collinear out-of-range intersections.
Change 3b5a3fa8b1c11d4bd4499b040311f4c3553ebf8c introduced support for out-of-range intersections, which is necessary when the top and bottom vertices of an edge differ by only one ULP in the primary sort order and can't be split in-order. However, some out-of-range intersections produce edges which cancel each other out on splitting, in particular when the intersection is collinear with the newly-computed edge. This undoes the effect of the split. The tessellator then rewinds, re-detects the intersection, resplits, an infinite loop. The fix is to check for out-of-range intersections which are also collinear, and ignore them. This is ok, because these are not the cases we care about it change 3b5a3f above, which are never collinear. Bug: 753867 Change-Id: I590231e0e6f19c98f1ccf46cb7acc8a63ba35a9d Reviewed-on: https://skia-review.googlesource.com/34925 Reviewed-by: Brian Salomon <bsalomon@google.com> Commit-Queue: Stephen White <senorblanco@chromium.org>
Diffstat (limited to 'src/gpu/GrTessellator.cpp')
-rw-r--r--src/gpu/GrTessellator.cpp17
1 files changed, 17 insertions, 0 deletions
diff --git a/src/gpu/GrTessellator.cpp b/src/gpu/GrTessellator.cpp
index 5f25e5a5fb..2cb9adcbf8 100644
--- a/src/gpu/GrTessellator.cpp
+++ b/src/gpu/GrTessellator.cpp
@@ -1078,6 +1078,17 @@ uint8_t max_edge_alpha(Edge* a, Edge* b) {
}
}
+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;
+}
+
bool check_for_intersection(Edge* edge, Edge* other, EdgeList* activeEdges, Vertex** current,
VertexList* mesh, Comparator& c, SkArenaAlloc& alloc) {
if (!edge || !other) {
@@ -1086,6 +1097,12 @@ bool check_for_intersection(Edge* edge, Edge* other, EdgeList* activeEdges, Vert
SkPoint p;
uint8_t alpha;
if (edge->intersect(*other, &p, &alpha) && p.isFinite()) {
+ // 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;