diff options
-rw-r--r-- | gyp/tests.gyp | 1 | ||||
-rw-r--r-- | src/core/SkAAClip.cpp | 38 | ||||
-rw-r--r-- | tests/AAClipTest.cpp | 43 |
3 files changed, 81 insertions, 1 deletions
diff --git a/gyp/tests.gyp b/gyp/tests.gyp index ede5885864..d1904876f0 100644 --- a/gyp/tests.gyp +++ b/gyp/tests.gyp @@ -13,6 +13,7 @@ '../src/gpu', ], 'sources': [ + '../tests/AAClipTest.cpp', '../tests/BitmapCopyTest.cpp', '../tests/BitmapGetColorTest.cpp', '../tests/BitSetTest.cpp', diff --git a/src/core/SkAAClip.cpp b/src/core/SkAAClip.cpp index dd388950a9..d9cc181f74 100644 --- a/src/core/SkAAClip.cpp +++ b/src/core/SkAAClip.cpp @@ -478,12 +478,14 @@ class SkAAClip::Builder { Row* fCurrRow; int fPrevY; int fWidth; + int fMinY; public: Builder(const SkIRect& bounds) : fBounds(bounds) { fPrevY = -1; fWidth = bounds.width(); fCurrRow = NULL; + fMinY = bounds.fTop; } ~Builder() { @@ -550,6 +552,11 @@ public: return target->setEmpty(); } + SkASSERT(fMinY >= fBounds.fTop); + SkASSERT(fMinY < fBounds.fBottom); + int adjustY = fMinY - fBounds.fTop; + fBounds.fTop = fMinY; + RunHead* head = RunHead::Alloc(fRows.count(), dataSize); YOffset* yoffset = head->yoffsets(); uint8_t* data = head->data(); @@ -557,7 +564,7 @@ public: row = fRows.begin(); while (row < stop) { - yoffset->fY = row->fY; + yoffset->fY = row->fY - adjustY; yoffset->fOffset = data - baseData; yoffset += 1; @@ -614,7 +621,13 @@ public: #endif } + // only called by BuilderBlitter + void setMinY(int y) { + fMinY = y; + } + private: + Row* flushRow(bool readyForAnother) { Row* next = NULL; int count = fRows.count(); @@ -676,6 +689,13 @@ public: fBuilder = builder; fLeft = builder->getBounds().fLeft; fRight = builder->getBounds().fRight; + fMinY = SK_MaxS32; + } + + void finish() { + if (fMinY < SK_MaxS32) { + fBuilder->setMinY(fMinY); + } } virtual void blitV(int x, int y, int height, SkAlpha alpha) SK_OVERRIDE @@ -692,11 +712,13 @@ public: } virtual void blitH(int x, int y, int width) SK_OVERRIDE { + this->recordMinY(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); for (;;) { int count = *runs; if (count <= 0) { @@ -736,6 +758,19 @@ private: Builder* fBuilder; int fLeft; // cache of builder's bounds' left edge int fRight; + int fMinY; + + /* + * We track this, in case the scan converter skipped some number of + * scanlines at the (relative to the bounds it was given). This allows + * the builder, during its finish, to trip its bounds down to the "real" + * top. + */ + void recordMinY(int y) { + if (y < fMinY) { + fMinY = y; + } + } void unexpected() { SkDebugf("---- did not expect to get called here"); @@ -776,6 +811,7 @@ bool SkAAClip::setPath(const SkPath& path, const SkRegion* clip, bool doAA) { SkScan::FillPath(path, *clip, &blitter); } + blitter.finish(); return builder.finish(this); } diff --git a/tests/AAClipTest.cpp b/tests/AAClipTest.cpp new file mode 100644 index 0000000000..a66e69a5be --- /dev/null +++ b/tests/AAClipTest.cpp @@ -0,0 +1,43 @@ +/* + * Copyright 2011 Google Inc. + * + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "Test.h" +#include "SkAAClip.h" +#include "SkPath.h" + +static void test_trim_bounds(skiatest::Reporter* reporter) { + SkPath path; + SkAAClip clip; + const int height = 40; + const SkScalar sheight = SkIntToScalar(height); + + path.addOval(SkRect::MakeWH(sheight, sheight)); + REPORTER_ASSERT(reporter, sheight == path.getBounds().height()); + clip.setPath(path, NULL, true); + REPORTER_ASSERT(reporter, height == clip.getBounds().height()); + + // this is the trimmed height of this cubic (with aa). The critical thing + // for this test is that it is less than height, which represents just + // the bounds of the path's control-points. + // + // This used to fail until we tracked the MinY in the BuilderBlitter. + // + const int teardrop_height = 12; + path.reset(); + path.moveTo(0, 20); + path.cubicTo(40, 40, 40, 0, 0, 20); + REPORTER_ASSERT(reporter, sheight == path.getBounds().height()); + clip.setPath(path, NULL, true); + REPORTER_ASSERT(reporter, teardrop_height == clip.getBounds().height()); +} + +static void TestAAClip(skiatest::Reporter* reporter) { + test_trim_bounds(reporter); +} + +#include "TestClassDef.h" +DEFINE_TESTCLASS("AAClip", AAClipTestClass, TestAAClip) |