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 0aeea6d344.

TBR=

Author: reed@google.com

Review URL: https://codereview.chromium.org/443353004
This commit is contained in:
reed 2014-08-07 11:48:10 -07:00 committed by Commit bot
parent 7b62448065
commit 202ab2a5ca
5 changed files with 71 additions and 3 deletions

View File

@ -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();

View File

@ -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);

View File

@ -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

View File

@ -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;
}

View File

@ -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);
}