From 0d10280190c411b18feb569a2248552047d1aa93 Mon Sep 17 00:00:00 2001 From: "reed@google.com" Date: Thu, 31 May 2012 18:28:59 +0000 Subject: [PATCH] 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 --- bench/RegionBench.cpp | 22 ++++++++++++++++++---- include/core/SkRect.h | 18 ++++++++++++++++-- src/core/SkRegion.cpp | 6 +++++- 3 files changed, 39 insertions(+), 7 deletions(-) diff --git a/bench/RegionBench.cpp b/bench/RegionBench.cpp index 51d389c75..5541a5c01 100644 --- a/bench/RegionBench.cpp +++ b/bench/RegionBench.cpp @@ -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); diff --git a/include/core/SkRect.h b/include/core/SkRect.h index e055c3d70..83ef2df35 100644 --- a/include/core/SkRect.h +++ b/include/core/SkRect.h @@ -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. @@ -273,10 +277,20 @@ struct SK_API SkIRect { } /** Returns true if a and b are not empty, and they intersect - */ + */ static bool Intersects(const SkIRect& a, const SkIRect& b) { return !a.isEmpty() && !b.isEmpty() && // check for empties - a.fLeft < b.fRight && b.fLeft < a.fRight && + a.fLeft < b.fRight && b.fLeft < a.fRight && + 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; } diff --git a/src/core/SkRegion.cpp b/src/core/SkRegion.cpp index cb370cacc..fac948db1 100644 --- a/src/core/SkRegion.cpp +++ b/src/core/SkRegion.cpp @@ -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: