Ensure Y->X ordering when building a region from a path

Our region-builder-blitter insists on being called in a Y->X sorted order,
which means (for example) if it is given a rect, then next blit call must
be below that rect.

However, we have helpers that blit rects "through" a region, and they iterate
through the region using Cliperator, which returns the minimum (mostly) number
of rects inside the region -- but these are not in strict Y->X order. Hence
the problem.

This CL avoids this by fixing it at the source. When we are asked to build a region
by drawing a path clipped to another region, we check if that clip is complex.
If it is, we first regionize the path against the clip's bounds (easy), and then
call a region-op to intersect that with the complex clip.

Bug: skia:7491
Change-Id: Ibf0a99e5bb38e369c4b263b0b07bfc04a572de63
Reviewed-on: https://skia-review.googlesource.com/113424
Reviewed-by: Cary Clark <caryclark@google.com>
Commit-Queue: Mike Reed <reed@google.com>
This commit is contained in:
Mike Reed 2018-03-09 14:09:31 -05:00 committed by Skia Commit-Bot
parent 37886ce8cd
commit 749efb6ee2

View File

@ -326,6 +326,16 @@ bool SkRegion::setPath(const SkPath& path, const SkRegion& clip) {
return check_inverse_on_empty_return(this, path, clip);
}
// Our builder is very fragile, and can't be called with spans/rects out of Y->X order.
// To ensure this, we only "fill" clipped to a rect (the clip's bounds), and if the
// clip is more complex than that, we just post-intersect the result with the clip.
if (clip.isComplex()) {
if (!this->setPath(path, SkRegion(clip.getBounds()))) {
return false;
}
return this->op(clip, kIntersect_Op);
}
// compute worst-case rgn-size for the path
int pathTop, pathBot;
int pathTransitions = count_path_runtype_values(path, &pathTop, &pathBot);