From 4714359ec091b34a4f88eb9708868a58a22177d3 Mon Sep 17 00:00:00 2001 From: "tomhudson@google.com" Date: Wed, 28 Dec 2011 17:58:07 +0000 Subject: 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 --- src/core/SkBlitter.cpp | 10 +++++++--- src/core/SkScan_AntiPath.cpp | 33 ++++++++++++++++++--------------- 2 files changed, 25 insertions(+), 18 deletions(-) (limited to 'src/core') 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; -- cgit v1.2.3