aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--gyp/tests.gyp1
-rw-r--r--src/core/SkAAClip.cpp38
-rw-r--r--tests/AAClipTest.cpp43
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)