We often rgn-diff an area >= the other rgn. now we detect that and return empty

We do this when we update our devices in SkCanvas.cpp
Review URL: https://codereview.appspot.com/6249073

git-svn-id: http://skia.googlecode.com/svn/trunk@4101 2bbb7eff-a529-9590-31e7-b0007b416f81
This commit is contained in:
reed@google.com 2012-05-31 18:28:59 +00:00
parent 6f6efa90c4
commit 0d10280190
3 changed files with 39 additions and 7 deletions

View File

@ -25,6 +25,16 @@ static bool diff_proc(SkRegion& a, SkRegion& b) {
return result.op(a, b, SkRegion::kDifference_Op);
}
static bool diffrect_proc(SkRegion& a, SkRegion& b) {
SkRegion result;
return result.op(a, b.getBounds(), SkRegion::kDifference_Op);
}
static bool diffrectbig_proc(SkRegion& a, SkRegion& b) {
SkRegion result;
return result.op(a, a.getBounds(), SkRegion::kDifference_Op);
}
static bool containsrect_proc(SkRegion& a, SkRegion& b) {
SkIRect r = a.getBounds();
r.inset(r.width()/4, r.height()/4);
@ -112,10 +122,12 @@ private:
static SkBenchmark* gF0(void* p) { return SkNEW_ARGS(RegionBench, (p, SMALL, union_proc, "union")); }
static SkBenchmark* gF1(void* p) { return SkNEW_ARGS(RegionBench, (p, SMALL, sect_proc, "intersect")); }
static SkBenchmark* gF2(void* p) { return SkNEW_ARGS(RegionBench, (p, SMALL, diff_proc, "difference")); }
static SkBenchmark* gF3(void* p) { return SkNEW_ARGS(RegionBench, (p, SMALL, containsrect_proc, "containsrect", 100)); }
static SkBenchmark* gF4(void* p) { return SkNEW_ARGS(RegionBench, (p, SMALL, sectsrgn_proc, "intersectsrgn", 10)); }
static SkBenchmark* gF5(void* p) { return SkNEW_ARGS(RegionBench, (p, SMALL, sectsrect_proc, "intersectsrect", 200)); }
static SkBenchmark* gF6(void* p) { return SkNEW_ARGS(RegionBench, (p, SMALL, containsxy_proc, "containsxy")); }
static SkBenchmark* gF3(void* p) { return SkNEW_ARGS(RegionBench, (p, SMALL, diffrect_proc, "differencerect")); }
static SkBenchmark* gF4(void* p) { return SkNEW_ARGS(RegionBench, (p, SMALL, diffrectbig_proc, "differencerectbig")); }
static SkBenchmark* gF5(void* p) { return SkNEW_ARGS(RegionBench, (p, SMALL, containsrect_proc, "containsrect", 100)); }
static SkBenchmark* gF6(void* p) { return SkNEW_ARGS(RegionBench, (p, SMALL, sectsrgn_proc, "intersectsrgn", 10)); }
static SkBenchmark* gF7(void* p) { return SkNEW_ARGS(RegionBench, (p, SMALL, sectsrect_proc, "intersectsrect", 200)); }
static SkBenchmark* gF8(void* p) { return SkNEW_ARGS(RegionBench, (p, SMALL, containsxy_proc, "containsxy")); }
static BenchRegistry gR0(gF0);
static BenchRegistry gR1(gF1);
@ -124,3 +136,5 @@ static BenchRegistry gR3(gF3);
static BenchRegistry gR4(gF4);
static BenchRegistry gR5(gF5);
static BenchRegistry gR6(gF6);
static BenchRegistry gR7(gF7);
static BenchRegistry gR8(gF8);

View File

@ -206,6 +206,10 @@ struct SK_API SkIRect {
fRight >= right && fBottom >= bottom;
}
bool containsNoEmptyCheck(const SkIRect& r) const {
return containsNoEmptyCheck(r.fLeft, r.fTop, r.fRight, r.fBottom);
}
/** If r intersects this rectangle, return true and set this rectangle to that
intersection, otherwise return false and do not change this rectangle.
If either rectangle is empty, do nothing and return false.
@ -280,6 +284,16 @@ struct SK_API SkIRect {
a.fTop < b.fBottom && b.fTop < a.fBottom;
}
/**
* Returns true if a and b intersect. debug-asserts that neither are empty.
*/
static bool IntersectsNoEmptyCheck(const SkIRect& a, const SkIRect& b) {
SkASSERT(!a.isEmpty());
SkASSERT(!b.isEmpty());
return a.fLeft < b.fRight && b.fLeft < a.fRight &&
a.fTop < b.fBottom && b.fTop < a.fBottom;
}
/** Update this rectangle to enclose itself and the specified rectangle.
If this rectangle is empty, just set it to the specified rectangle. If the specified
rectangle is empty, do nothing.

View File

@ -992,9 +992,13 @@ bool SkRegion::Oper(const SkRegion& rgnaOrig, const SkRegion& rgnbOrig, Op op,
if (a_empty) {
return setEmptyCheck(result);
}
if (b_empty || !SkIRect::Intersects(rgna->fBounds, rgnb->fBounds)) {
if (b_empty || !SkIRect::IntersectsNoEmptyCheck(rgna->fBounds,
rgnb->fBounds)) {
return setRegionCheck(result, *rgna);
}
if (b_rect && rgnb->fBounds.containsNoEmptyCheck(rgna->fBounds)) {
return setEmptyCheck(result);
}
break;
case kIntersect_Op: