diff options
author | reed@google.com <reed@google.com@2bbb7eff-a529-9590-31e7-b0007b416f81> | 2012-02-16 18:56:17 +0000 |
---|---|---|
committer | reed@google.com <reed@google.com@2bbb7eff-a529-9590-31e7-b0007b416f81> | 2012-02-16 18:56:17 +0000 |
commit | 80cdb9a2139bdc6cb15b5bfb06ed9fc3e33bb39b (patch) | |
tree | 6fc1bb9aed843eb74e0ac96e53092999ab48dc82 | |
parent | 897fc41934e6aecec62f89d093c93b917cfa5345 (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.cpp | 28 | ||||
-rw-r--r-- | tests/AAClipTest.cpp | 38 |
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" |