GrTessellator: fix for collinear out-of-range intersections.
Change 3b5a3fa8b1
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>
This commit is contained in:
parent
4c72b266da
commit
3f5301b284
@ -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;
|
||||
|
@ -347,6 +347,21 @@ static SkPath create_path_22() {
|
||||
return path;
|
||||
}
|
||||
|
||||
// A path which contains out-of-range colinear intersections.
|
||||
static SkPath create_path_23() {
|
||||
SkPath path;
|
||||
path.moveTo( 0, 63.39080047607421875);
|
||||
path.lineTo(-0.70804601907730102539, 63.14350128173828125);
|
||||
path.lineTo(-7.8608899287380243391e-17, 64.14080047607421875);
|
||||
path.moveTo( 0, 64.14080047607421875);
|
||||
path.lineTo(44.285900115966796875, 64.14080047607421875);
|
||||
path.lineTo( 0, 62.64080047607421875);
|
||||
path.moveTo(21.434900283813476562, -0.24732701480388641357);
|
||||
path.lineTo(-0.70804601907730102539, 63.14350128173828125);
|
||||
path.lineTo(0.70804601907730102539, 63.6381988525390625);
|
||||
return path;
|
||||
}
|
||||
|
||||
static std::unique_ptr<GrFragmentProcessor> create_linear_gradient_processor(GrContext* ctx) {
|
||||
SkPoint pts[2] = { {0, 0}, {1, 1} };
|
||||
SkColor colors[2] = { SK_ColorGREEN, SK_ColorBLUE };
|
||||
@ -427,5 +442,6 @@ DEF_GPUTEST_FOR_ALL_CONTEXTS(TessellatingPathRendererTests, reporter, ctxInfo) {
|
||||
test_path(ctx, rtc.get(), create_path_20(), SkMatrix(), GrAAType::kCoverage);
|
||||
test_path(ctx, rtc.get(), create_path_21(), SkMatrix(), GrAAType::kCoverage);
|
||||
test_path(ctx, rtc.get(), create_path_22());
|
||||
test_path(ctx, rtc.get(), create_path_23());
|
||||
}
|
||||
#endif
|
||||
|
Loading…
Reference in New Issue
Block a user