aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorGravatar reed@google.com <reed@google.com@2bbb7eff-a529-9590-31e7-b0007b416f81>2012-02-16 18:56:17 +0000
committerGravatar reed@google.com <reed@google.com@2bbb7eff-a529-9590-31e7-b0007b416f81>2012-02-16 18:56:17 +0000
commit80cdb9a2139bdc6cb15b5bfb06ed9fc3e33bb39b (patch)
tree6fc1bb9aed843eb74e0ac96e53092999ab48dc82
parent897fc41934e6aecec62f89d093c93b917cfa5345 (diff)
aaclip needs to handle paths with holes
Review URL: https://codereview.appspot.com/5671066 git-svn-id: http://skia.googlecode.com/svn/trunk@3209 2bbb7eff-a529-9590-31e7-b0007b416f81
-rw-r--r--src/core/SkAAClip.cpp28
-rw-r--r--tests/AAClipTest.cpp38
2 files changed, 64 insertions, 2 deletions
diff --git a/src/core/SkAAClip.cpp b/src/core/SkAAClip.cpp
index 096fd6bcf8..5402bcf832 100644
--- a/src/core/SkAAClip.cpp
+++ b/src/core/SkAAClip.cpp
@@ -893,10 +893,10 @@ public:
SkASSERT(count > 0);
SkASSERT(fBounds.contains(x, y));
SkASSERT(fBounds.contains(x + count - 1, y));
-
+
x -= fBounds.left();
y -= fBounds.top();
-
+
Row* row = fCurrRow;
if (y != fPrevY) {
SkASSERT(y > fPrevY);
@@ -1142,12 +1142,33 @@ private:
};
class SkAAClip::BuilderBlitter : public SkBlitter {
+ int fLastY;
+
+ /*
+ If we see a gap of 1 or more empty scanlines while building in Y-order,
+ we inject an explicit empty scanline (alpha==0)
+
+ See AAClipTest.cpp : test_path_with_hole()
+ */
+ void checkForYGap(int y) {
+ SkASSERT(y >= fLastY);
+ if (fLastY > -SK_MaxS32) {
+ int gap = y - fLastY;
+ if (gap > 1) {
+ fBuilder->addRun(fLeft, y - 1, 0, fRight - fLeft);
+ }
+ }
+ fLastY = y;
+ }
+
public:
+
BuilderBlitter(Builder* builder) {
fBuilder = builder;
fLeft = builder->getBounds().fLeft;
fRight = builder->getBounds().fRight;
fMinY = SK_MaxS32;
+ fLastY = -SK_MaxS32; // sentinel
}
void finish() {
@@ -1170,6 +1191,7 @@ public:
virtual void blitRect(int x, int y, int width, int height) SK_OVERRIDE {
this->recordMinY(y);
+ this->checkForYGap(y);
fBuilder->addRectRun(x, y, width, height);
}
@@ -1188,12 +1210,14 @@ public:
virtual void blitH(int x, int y, int width) SK_OVERRIDE {
this->recordMinY(y);
+ this->checkForYGap(y);
fBuilder->addRun(x, y, 0xFF, width);
}
virtual void blitAntiH(int x, int y, const SkAlpha alpha[],
const int16_t runs[]) SK_OVERRIDE {
this->recordMinY(y);
+ this->checkForYGap(y);
for (;;) {
int count = *runs;
if (count <= 0) {
diff --git a/tests/AAClipTest.cpp b/tests/AAClipTest.cpp
index b3051fdd82..194b92680c 100644
--- a/tests/AAClipTest.cpp
+++ b/tests/AAClipTest.cpp
@@ -272,15 +272,53 @@ static void test_irect(skiatest::Reporter* reporter) {
}
REPORTER_ASSERT(reporter, nonEmptyAA == nonEmptyBW);
REPORTER_ASSERT(reporter, clip2.getBounds() == rgn2.getBounds());
+
+ SkMask maskBW, maskAA;
+ copyToMask(rgn2, &maskBW);
+ clip2.copyToMask(&maskAA);
+ REPORTER_ASSERT(reporter, maskBW == maskAA);
}
}
}
+static void test_path_with_hole(skiatest::Reporter* reporter) {
+ static const uint8_t gExpectedImage[] = {
+ 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF,
+ 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00,
+ 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF,
+ };
+ SkMask expected;
+ expected.fBounds.set(0, 0, 4, 6);
+ expected.fRowBytes = 4;
+ expected.fFormat = SkMask::kA8_Format;
+ expected.fImage = (uint8_t*)gExpectedImage;
+
+ SkPath path;
+ path.addRect(SkRect::MakeXYWH(0, 0,
+ SkIntToScalar(4), SkIntToScalar(2)));
+ path.addRect(SkRect::MakeXYWH(0, SkIntToScalar(4),
+ SkIntToScalar(4), SkIntToScalar(2)));
+
+ for (int i = 0; i < 2; ++i) {
+ SkAAClip clip;
+ clip.setPath(path, NULL, 1 == i);
+
+ SkMask mask;
+ clip.copyToMask(&mask);
+
+ REPORTER_ASSERT(reporter, expected == mask);
+ }
+}
+
static void TestAAClip(skiatest::Reporter* reporter) {
test_empty(reporter);
test_path_bounds(reporter);
test_irect(reporter);
test_rgn(reporter);
+ test_path_with_hole(reporter);
}
#include "TestClassDef.h"