diff options
author | tomhudson@google.com <tomhudson@google.com@2bbb7eff-a529-9590-31e7-b0007b416f81> | 2011-12-28 17:58:07 +0000 |
---|---|---|
committer | tomhudson@google.com <tomhudson@google.com@2bbb7eff-a529-9590-31e7-b0007b416f81> | 2011-12-28 17:58:07 +0000 |
commit | 4714359ec091b34a4f88eb9708868a58a22177d3 (patch) | |
tree | 540246da2514658a244eed3bf6c7d53fd2a628b5 | |
parent | 6fc7cc23a9c33960b879f69d92d6fb0e1373e556 (diff) |
Bugfixes to antialiased blitting.
More details of blitter contracts in function headers.
New precautionary assert in one high-level default blitter.
git-svn-id: http://skia.googlecode.com/svn/trunk@2928 2bbb7eff-a529-9590-31e7-b0007b416f81
-rw-r--r-- | include/core/SkBlitter.h | 9 | ||||
-rw-r--r-- | src/core/SkBlitter.cpp | 10 | ||||
-rw-r--r-- | src/core/SkScan_AntiPath.cpp | 33 |
3 files changed, 30 insertions, 22 deletions
diff --git a/include/core/SkBlitter.h b/include/core/SkBlitter.h index beaebfeccd..e784ef5e23 100644 --- a/include/core/SkBlitter.h +++ b/include/core/SkBlitter.h @@ -24,7 +24,7 @@ class SkBlitter { public: virtual ~SkBlitter(); - /// Blit a horizontal run of pixels. + /// Blit a horizontal run of zero or more pixels. virtual void blitH(int x, int y, int width); /// Blit a horizontal run of antialiased pixels; runs[] is a *sparse* /// zero-terminated run-length encoding of spans of constant alpha values. @@ -32,11 +32,12 @@ public: const int16_t runs[]); /// Blit a vertical run of pixels with a constant alpha value. virtual void blitV(int x, int y, int height, SkAlpha alpha); - /// Blit a solid rectangle. + /// Blit a solid rectangle zero or more pixels wide. virtual void blitRect(int x, int y, int width, int height); /** Blit a rectangle with one alpha-blended column on the left, - width opaque pixels, and one alpha-blended column on the right. - Note that the result will always be at least two pixels wide. + width (zero or more) opaque pixels, and one alpha-blended column + on the right. + The result will always be at least two pixels wide. */ virtual void blitAntiRect(int x, int y, int width, int height, SkAlpha leftAlpha, SkAlpha rightAlpha); diff --git a/src/core/SkBlitter.cpp b/src/core/SkBlitter.cpp index 6d2d51201c..265ae6b6ef 100644 --- a/src/core/SkBlitter.cpp +++ b/src/core/SkBlitter.cpp @@ -47,6 +47,7 @@ void SkBlitter::blitV(int x, int y, int height, SkAlpha alpha) { } void SkBlitter::blitRect(int x, int y, int width, int height) { + SkASSERT(width >= 0); while (--height >= 0) { this->blitH(x, y++, width); } @@ -57,9 +58,12 @@ void SkBlitter::blitRect(int x, int y, int width, int height) { /// may not support. void SkBlitter::blitAntiRect(int x, int y, int width, int height, SkAlpha leftAlpha, SkAlpha rightAlpha) { - this->blitV(x, y, height, leftAlpha); - this->blitRect(x + 1, y, width, height); - this->blitV(x + width + 1, y, height, rightAlpha); + this->blitV(x++, y, height, leftAlpha); + if (width >= 0) { + this->blitRect(x, y, width, height); + x += width; + } + this->blitV(x, y, height, rightAlpha); } ////////////////////////////////////////////////////////////////////////////// diff --git a/src/core/SkScan_AntiPath.cpp b/src/core/SkScan_AntiPath.cpp index 4136636a66..fc7f737e13 100644 --- a/src/core/SkScan_AntiPath.cpp +++ b/src/core/SkScan_AntiPath.cpp @@ -307,8 +307,15 @@ void SuperBlitter::blitRect(int x, int y, int width, int height) { irite--; } + // Need to call flush() to clean up pending draws before we + // even consider blitV(), since otherwise it can look nonmonotonic. + SkASSERT(start_y > fCurrIY); + this->flush(); + int n = irite - ileft - 1; if (n < 0) { + // If n < 0, we'll only have a single partially-transparent column + // of pixels to render. xleft = xrite - xleft; SkASSERT(xleft <= SCALE); SkASSERT(xleft > 0); @@ -316,25 +323,21 @@ void SuperBlitter::blitRect(int x, int y, int width, int height) { fRealBlitter->blitV(ileft + fLeft, start_y, count, coverage_to_exact_alpha(xleft)); } else { + // With n = 0, we have two possibly-transparent columns of pixels + // to render; with n > 0, we have opaque columns between them. + xleft = SCALE - xleft; - } + // Using coverage_to_exact_alpha is not consistent with blitH() + const int coverageL = coverage_to_exact_alpha(xleft); + const int coverageR = coverage_to_exact_alpha(xrite); - // here we go - SkASSERT(start_y > fCurrIY); - this->flush(); + SkASSERT(coverageL > 0 || n > 0 || coverageR > 0); + SkASSERT((coverageL != 0) + n + (coverageR != 0) <= fWidth); - // to be compatible with the blitH() version, we just shift these - // values up. If we didn't care about that, we could be more precise - // and compute these exactly (e.g. 2->128 instead of 2->124) - // - const int coverageL = coverage_to_exact_alpha(xleft); - const int coverageR = coverage_to_exact_alpha(xrite); - SkASSERT(n + (coverageR != 0) <= fWidth); - - SkASSERT(coverageL > 0 || n > 0 || coverageR > 0); - fRealBlitter->blitAntiRect(ileft + fLeft, start_y, n, count, - coverageL, coverageR); + fRealBlitter->blitAntiRect(ileft + fLeft, start_y, n, count, + coverageL, coverageR); + } // preamble for our next call to blitH() fCurrIY = stop_y - 1; |