Our region blitter (invoked by region::setPath()) must have its scanlines
fed to it in scanline order (Y sorted, then X sorted). If, however, we call rgn->setPath(path, otherRgn) with path in inverse mode, then our scan converter code looks like this: if (inverse) blit_top scan_convert_path if (inverse) blit_bottom This is fine, unless otherRgn is complex. If it is, then blit_top will want to efficiently "blit" otherRgn (the part above the path), and that means calling blitRect in an iterator. That can result in chunks being passed to our blitter (which is really accumulating scanlines) out of scanline order. The change is to detect that otherRgn is complex, and if it is, just perform the op in two steps: 1. setPath on a tmp region, limited by the bounds of otherRgn (simple) 2. intersect this tmp region with the currRgn. This is effectively what we do for non-intersect ops. Intersect was different only because we could (sometimes) avoid the step of create a tmp region. git-svn-id: http://skia.googlecode.com/svn/trunk@879 2bbb7eff-a529-9590-31e7-b0007b416f81
This commit is contained in:
parent
d302f1401b
commit
759876a922
@ -954,10 +954,23 @@ bool SkCanvas::clipRect(const SkRect& rect, SkRegion::Op op) {
|
||||
|
||||
static bool clipPathHelper(const SkCanvas* canvas, SkRegion* currRgn,
|
||||
const SkPath& devPath, SkRegion::Op op) {
|
||||
// base is used to limit the size (and therefore memory allocation) of the
|
||||
// region that results from scan converting devPath.
|
||||
SkRegion base;
|
||||
|
||||
if (SkRegion::kIntersect_Op == op) {
|
||||
return currRgn->setPath(devPath, *currRgn);
|
||||
// since we are intersect, we can do better (tighter) with currRgn's
|
||||
// bounds, than just using the device. However, if currRgn is complex,
|
||||
// our region blitter may hork, so we do that case in two steps.
|
||||
if (currRgn->isRect()) {
|
||||
return currRgn->setPath(devPath, *currRgn);
|
||||
} else {
|
||||
base.setRect(currRgn->getBounds());
|
||||
SkRegion rgn;
|
||||
rgn.setPath(devPath, base);
|
||||
return currRgn->op(rgn, op);
|
||||
}
|
||||
} else {
|
||||
SkRegion base;
|
||||
const SkBitmap& bm = canvas->getDevice()->accessBitmap(false);
|
||||
base.setRect(0, 0, bm.width(), bm.height());
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user