aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--src/core/SkAAClip.cpp28
-rw-r--r--src/core/SkAAClip.h4
-rw-r--r--src/core/SkRasterClip.cpp5
-rw-r--r--src/core/SkRasterClip.h12
-rw-r--r--tests/AAClipTest.cpp25
5 files changed, 71 insertions, 3 deletions
diff --git a/src/core/SkAAClip.cpp b/src/core/SkAAClip.cpp
index 14152f8317..5d21a47a49 100644
--- a/src/core/SkAAClip.cpp
+++ b/src/core/SkAAClip.cpp
@@ -684,6 +684,34 @@ bool SkAAClip::setRect(const SkIRect& bounds) {
#endif
}
+bool SkAAClip::isRect() const {
+ if (this->isEmpty()) {
+ return false;
+ }
+
+ const RunHead* head = fRunHead;
+ if (head->fRowCount != 1) {
+ return false;
+ }
+ const YOffset* yoff = head->yoffsets();
+ if (yoff->fY != fBounds.fBottom - 1) {
+ return false;
+ }
+
+ const uint8_t* row = head->data() + yoff->fOffset;
+ int width = fBounds.width();
+ do {
+ if (row[1] != 0xFF) {
+ return false;
+ }
+ int n = row[0];
+ SkASSERT(n <= width);
+ width -= n;
+ row += 2;
+ } while (width > 0);
+ return true;
+}
+
bool SkAAClip::setRect(const SkRect& r, bool doAA) {
if (r.isEmpty()) {
return this->setEmpty();
diff --git a/src/core/SkAAClip.h b/src/core/SkAAClip.h
index f2cde62dbc..c36a3e98ce 100644
--- a/src/core/SkAAClip.h
+++ b/src/core/SkAAClip.h
@@ -29,6 +29,10 @@ public:
bool isEmpty() const { return NULL == fRunHead; }
const SkIRect& getBounds() const { return fBounds; }
+ // Returns true iff the clip is not empty, and is just a hard-edged rect (no partial alpha).
+ // If true, getBounds() can be used in place of this clip.
+ bool isRect() const;
+
bool setEmpty();
bool setRect(const SkIRect&);
bool setRect(const SkRect&, bool doAA = true);
diff --git a/src/core/SkRasterClip.cpp b/src/core/SkRasterClip.cpp
index 664211f64f..d1615a3445 100644
--- a/src/core/SkRasterClip.cpp
+++ b/src/core/SkRasterClip.cpp
@@ -222,7 +222,10 @@ void SkRasterClip::convertToAA() {
SkASSERT(fIsBW);
fAA.setRegion(fBW);
fIsBW = false;
- (void)this->updateCacheAndReturnNonEmpty();
+
+ // since we are being explicitly asked to convert-to-aa, we pass false so we don't "optimize"
+ // ourselves back to BW.
+ (void)this->updateCacheAndReturnNonEmpty(false);
}
#ifdef SK_DEBUG
diff --git a/src/core/SkRasterClip.h b/src/core/SkRasterClip.h
index 0c2723314c..29a925f2a2 100644
--- a/src/core/SkRasterClip.h
+++ b/src/core/SkRasterClip.h
@@ -89,11 +89,19 @@ private:
}
bool computeIsRect() const {
- return fIsBW ? fBW.isRect() : false;
+ return fIsBW ? fBW.isRect() : fAA.isRect();
}
- bool updateCacheAndReturnNonEmpty() {
+ bool updateCacheAndReturnNonEmpty(bool detectAARect = true) {
fIsEmpty = this->computeIsEmpty();
+
+ // detect that our computed AA is really just a (hard-edged) rect
+ if (detectAARect && !fIsEmpty && !fIsBW && fAA.isRect()) {
+ fBW.setRect(fAA.getBounds());
+ fAA.setEmpty(); // don't need this guy anymore
+ fIsBW = true;
+ }
+
fIsRect = this->computeIsRect();
return !fIsEmpty;
}
diff --git a/tests/AAClipTest.cpp b/tests/AAClipTest.cpp
index 26c1ec1d0e..776cd5267a 100644
--- a/tests/AAClipTest.cpp
+++ b/tests/AAClipTest.cpp
@@ -318,6 +318,30 @@ static void test_path_with_hole(skiatest::Reporter* reporter) {
}
}
+static void test_really_a_rect(skiatest::Reporter* reporter) {
+ SkRRect rrect;
+ rrect.setRectXY(SkRect::MakeWH(100, 100), 5, 5);
+
+ SkPath path;
+ path.addRRect(rrect);
+
+ SkAAClip clip;
+ clip.setPath(path);
+
+ REPORTER_ASSERT(reporter, clip.getBounds() == SkIRect::MakeWH(100, 100));
+ REPORTER_ASSERT(reporter, !clip.isRect());
+
+ // This rect should intersect the clip, but slice-out all of the "soft" parts,
+ // leaving just a rect.
+ const SkIRect ir = SkIRect::MakeLTRB(10, -10, 50, 90);
+
+ clip.op(ir, SkRegion::kIntersect_Op);
+
+ REPORTER_ASSERT(reporter, clip.getBounds() == SkIRect::MakeLTRB(10, 0, 50, 90));
+ // the clip recognized that that it is just a rect!
+ REPORTER_ASSERT(reporter, clip.isRect());
+}
+
#include "SkRasterClip.h"
static void copyToMask(const SkRasterClip& rc, SkMask* mask) {
@@ -404,4 +428,5 @@ DEF_TEST(AAClip, reporter) {
test_path_with_hole(reporter);
test_regressions();
test_nearly_integral(reporter);
+ test_really_a_rect(reporter);
}