add isRect() check to AAClip, to detect if a soft-clip is really just an irect
taken from (https://codereview.chromium.org/445233006/)
fix: don't assume that the first yoffset is 0, since we may have performed a translate and not
re-alloced our data.
This reverts commit 0aeea6d344f12e35e29a79f4bbc48af88f913204.
TBR=
Author: reed@google.com
Review URL: https://codereview.chromium.org/443353004
diff --git a/src/core/SkAAClip.cpp b/src/core/SkAAClip.cpp
index 14152f8..5d21a47 100644
--- a/src/core/SkAAClip.cpp
+++ b/src/core/SkAAClip.cpp
@@ -684,6 +684,34 @@
#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 f2cde62..c36a3e9 100644
--- a/src/core/SkAAClip.h
+++ b/src/core/SkAAClip.h
@@ -29,6 +29,10 @@
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 664211f..d1615a3 100644
--- a/src/core/SkRasterClip.cpp
+++ b/src/core/SkRasterClip.cpp
@@ -222,7 +222,10 @@
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 0c27233..29a925f 100644
--- a/src/core/SkRasterClip.h
+++ b/src/core/SkRasterClip.h
@@ -89,11 +89,19 @@
}
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;
}