add method to compute max count for a given buffer size in the bitmap shader.
fix bug in quad loop of fill_sequential where we were going one quad too far.



git-svn-id: http://skia.googlecode.com/svn/trunk@322 2bbb7eff-a529-9590-31e7-b0007b416f81
diff --git a/src/core/SkBitmapProcShader.cpp b/src/core/SkBitmapProcShader.cpp
index 44af0cc..7eb8ea1 100644
--- a/src/core/SkBitmapProcShader.cpp
+++ b/src/core/SkBitmapProcShader.cpp
@@ -140,10 +140,10 @@
         return;
     }
 
-    uint32_t buffer[BUF_MAX + 1];
+    uint32_t buffer[BUF_MAX];
     SkBitmapProcState::MatrixProc   mproc = state.fMatrixProc;
     SkBitmapProcState::SampleProc32 sproc = state.fSampleProc32;
-    int max = fState.fDoFilter ? (BUF_MAX >> 1) : BUF_MAX;
+    int max = fState.maxCountForBufferSize(sizeof(buffer));
 
     SkASSERT(state.fBitmap->getPixels());
     SkASSERT(state.fBitmap->pixelRef() == NULL ||
@@ -175,7 +175,7 @@
     uint32_t buffer[BUF_MAX];
     SkBitmapProcState::MatrixProc   mproc = state.fMatrixProc;
     SkBitmapProcState::SampleProc16 sproc = state.fSampleProc16;
-    int max = fState.fDoFilter ? (BUF_MAX >> 1) : BUF_MAX;
+    int max = fState.maxCountForBufferSize(sizeof(buffer));
 
     SkASSERT(state.fBitmap->getPixels());
     SkASSERT(state.fBitmap->pixelRef() == NULL ||
diff --git a/src/core/SkBitmapProcState.cpp b/src/core/SkBitmapProcState.cpp
index b999a0c..600b963 100644
--- a/src/core/SkBitmapProcState.cpp
+++ b/src/core/SkBitmapProcState.cpp
@@ -510,3 +510,31 @@
     return true;
 }
 
+///////////////////////////////////////////////////////////////////////////////
+/*
+    The storage requirements for the different matrix procs are as follows,
+    where each X or Y is 2 bytes, and N is the number of pixels/elements:
+ 
+    scale/translate     nofilter      Y(4bytes) + N * X
+    affine/perspective  nofilter      N * (X Y)
+    scale/translate     filter        Y Y + N * (X X)
+    affine/perspective  filter        N * (Y Y X X)
+ */
+int SkBitmapProcState::maxCountForBufferSize(size_t bufferSize) const {
+    int32_t size = static_cast<int32_t>(bufferSize);
+    int perElemShift;
+
+    size &= ~3; // only care about 4-byte aligned chunks
+    if (fInvType <= (SkMatrix::kTranslate_Mask | SkMatrix::kScale_Mask)) {
+        size -= 4;   // the shared Y (or YY) coordinate
+        if (size < 0) {
+            size = 0;
+        }
+        perElemShift = fDoFilter ? 2 : 1;
+    } else {
+        perElemShift = fDoFilter ? 3 : 2;
+    }
+
+    return size >> perElemShift;
+}
+
diff --git a/src/core/SkBitmapProcState.h b/src/core/SkBitmapProcState.h
index 2790a6c..9db62f0 100644
--- a/src/core/SkBitmapProcState.h
+++ b/src/core/SkBitmapProcState.h
@@ -91,6 +91,16 @@
      */
     void platformProcs();
 
+    /** Given the size of a buffer, to be used for calling the matrix and
+        sample procs, this return the maximum count that can be stored in the
+        buffer, taking into account that filtering and scale-vs-affine affect
+        this value.
+     
+        Only valid to call after chooseProcs (setContext) has been called. It is
+        safe to call this inside the shader's shadeSpan() method.
+     */
+    int maxCountForBufferSize(size_t bufferSize) const;
+
 private:
     friend class SkBitmapProcShader;
 
diff --git a/src/core/SkBitmapProcState_matrixProcs.cpp b/src/core/SkBitmapProcState_matrixProcs.cpp
index cf32d9b..bd924ca 100644
--- a/src/core/SkBitmapProcState_matrixProcs.cpp
+++ b/src/core/SkBitmapProcState_matrixProcs.cpp
@@ -202,7 +202,7 @@
             pattern0 += 0x40004;
             *xxptr++ = pattern1;
             pattern1 += 0x40004;
-        } while (--qcount >= 0);
+        } while (--qcount != 0);
         xptr = reinterpret_cast<uint16_t*>(xxptr);
         count &= 3;
     }