Scanline decoding for bmp

Redesigns SkScanlineDecoder.h to indicate the ordering
in which the scanlines are provided

Refactors SkSwizzler::Fill() to include the zeroInit check
and to actually be correct.

BUG=skia:3257
BUG=skia:4198

Review URL: https://codereview.chromium.org/1287423002
diff --git a/src/codec/SkMaskSwizzler.cpp b/src/codec/SkMaskSwizzler.cpp
index 58be0c6..6ca9b58 100644
--- a/src/codec/SkMaskSwizzler.cpp
+++ b/src/codec/SkMaskSwizzler.cpp
@@ -8,57 +8,64 @@
 #include "SkCodecPriv.h"
 #include "SkColorPriv.h"
 #include "SkMaskSwizzler.h"
+#include "SkScaledCodec.h"
 
 static SkSwizzler::ResultAlpha swizzle_mask16_to_n32_opaque(
-        void* dstRow, const uint8_t* srcRow, int width, SkMasks* masks) {
+        void* dstRow, const uint8_t* srcRow, int width, SkMasks* masks,
+        uint32_t startX, uint32_t sampleX) {
 
     // Use the masks to decode to the destination
-    uint16_t* srcPtr = (uint16_t*) srcRow;
+    uint16_t* srcPtr = ((uint16_t*) srcRow) + startX;
     SkPMColor* dstPtr = (SkPMColor*) dstRow;
     for (int i = 0; i < width; i++) {
-        uint16_t p = srcPtr[i];
+        uint16_t p = srcPtr[0];
         uint8_t red = masks->getRed(p);
         uint8_t green = masks->getGreen(p);
         uint8_t blue = masks->getBlue(p);
         dstPtr[i] = SkPackARGB32NoCheck(0xFF, red, green, blue);
+        srcPtr += sampleX;
     }
     return SkSwizzler::kOpaque_ResultAlpha;
 }
 
 static SkSwizzler::ResultAlpha swizzle_mask16_to_n32_unpremul(
-        void* dstRow, const uint8_t* srcRow, int width, SkMasks* masks) {
+        void* dstRow, const uint8_t* srcRow, int width, SkMasks* masks,
+        uint32_t startX, uint32_t sampleX) {
 
     // Use the masks to decode to the destination
-    uint16_t* srcPtr = (uint16_t*) srcRow;
+    uint16_t* srcPtr = ((uint16_t*) srcRow) + startX;
     SkPMColor* dstPtr = (SkPMColor*) dstRow;
     INIT_RESULT_ALPHA;
     for (int i = 0; i < width; i++) {
-        uint16_t p = srcPtr[i];
+        uint16_t p = srcPtr[0];
         uint8_t red = masks->getRed(p);
         uint8_t green = masks->getGreen(p);
         uint8_t blue = masks->getBlue(p);
         uint8_t alpha = masks->getAlpha(p);
         UPDATE_RESULT_ALPHA(alpha);
         dstPtr[i] = SkPackARGB32NoCheck(alpha, red, green, blue);
+        srcPtr += sampleX;
     }
     return COMPUTE_RESULT_ALPHA;
 }
 
 static SkSwizzler::ResultAlpha swizzle_mask16_to_n32_premul(
-        void* dstRow, const uint8_t* srcRow, int width, SkMasks* masks) {
+        void* dstRow, const uint8_t* srcRow, int width, SkMasks* masks,
+        uint32_t startX, uint32_t sampleX) {
 
     // Use the masks to decode to the destination
-    uint16_t* srcPtr = (uint16_t*) srcRow;
+    uint16_t* srcPtr = ((uint16_t*) srcRow) + startX;
     SkPMColor* dstPtr = (SkPMColor*) dstRow;
     INIT_RESULT_ALPHA;
     for (int i = 0; i < width; i++) {
-        uint16_t p = srcPtr[i];
+        uint16_t p = srcPtr[0];
         uint8_t red = masks->getRed(p);
         uint8_t green = masks->getGreen(p);
         uint8_t blue = masks->getBlue(p);
         uint8_t alpha = masks->getAlpha(p);
         UPDATE_RESULT_ALPHA(alpha);
         dstPtr[i] = SkPreMultiplyARGB(alpha, red, green, blue);
+        srcPtr += sampleX;
     }
     return COMPUTE_RESULT_ALPHA;
 }
@@ -66,152 +73,174 @@
 // TODO (msarett): We have promoted a two byte per pixel image to 8888, only to
 // convert it back to 565. Instead, we should swizzle to 565 directly.
 static SkSwizzler::ResultAlpha swizzle_mask16_to_565(
-        void* dstRow, const uint8_t* srcRow, int width, SkMasks* masks) {
+        void* dstRow, const uint8_t* srcRow, int width, SkMasks* masks,
+        uint32_t startX, uint32_t sampleX) {
 
     // Use the masks to decode to the destination
-    uint16_t* srcPtr = (uint16_t*) srcRow;
+    uint16_t* srcPtr = ((uint16_t*) srcRow) + startX;
     uint16_t* dstPtr = (uint16_t*) dstRow;
     for (int i = 0; i < width; i++) {
-        uint16_t p = srcPtr[i];
+        uint16_t p = srcPtr[0];
         uint8_t red = masks->getRed(p);
         uint8_t green = masks->getGreen(p);
         uint8_t blue = masks->getBlue(p);
         dstPtr[i] = SkPack888ToRGB16(red, green, blue);
+        srcPtr += sampleX;
     }
     return SkSwizzler::kOpaque_ResultAlpha;
 }
 
 static SkSwizzler::ResultAlpha swizzle_mask24_to_n32_opaque(
-        void* dstRow, const uint8_t* srcRow, int width, SkMasks* masks) {
+        void* dstRow, const uint8_t* srcRow, int width, SkMasks* masks,
+        uint32_t startX, uint32_t sampleX) {
 
     // Use the masks to decode to the destination
+    srcRow += 3 * startX;
     SkPMColor* dstPtr = (SkPMColor*) dstRow;
-    for (int i = 0; i < 3*width; i += 3) {
-        uint32_t p = srcRow[i] | (srcRow[i + 1] << 8) | srcRow[i + 2] << 16;
+    for (int i = 0; i < width; i++) {
+        uint32_t p = srcRow[0] | (srcRow[1] << 8) | srcRow[2] << 16;
         uint8_t red = masks->getRed(p);
         uint8_t green = masks->getGreen(p);
         uint8_t blue = masks->getBlue(p);
-        dstPtr[i/3] = SkPackARGB32NoCheck(0xFF, red, green, blue);
+        dstPtr[i] = SkPackARGB32NoCheck(0xFF, red, green, blue);
+        srcRow += 3 * sampleX;
     }
     return SkSwizzler::kOpaque_ResultAlpha;
 }
 
 static SkSwizzler::ResultAlpha swizzle_mask24_to_n32_unpremul(
-        void* dstRow, const uint8_t* srcRow, int width, SkMasks* masks) {
+        void* dstRow, const uint8_t* srcRow, int width, SkMasks* masks,
+        uint32_t startX, uint32_t sampleX) {
 
     // Use the masks to decode to the destination
-    SkPMColor* dstPtr = (SkPMColor*) dstRow;
-    INIT_RESULT_ALPHA;
-    for (int i = 0; i < 3*width; i += 3) {
-        uint32_t p = srcRow[i] | (srcRow[i + 1] << 8) | srcRow[i + 2] << 16;
-        uint8_t red = masks->getRed(p);
-        uint8_t green = masks->getGreen(p);
-        uint8_t blue = masks->getBlue(p);
-        uint8_t alpha = masks->getAlpha(p);
-        UPDATE_RESULT_ALPHA(alpha);
-        dstPtr[i/3] = SkPackARGB32NoCheck(alpha, red, green, blue);
-    }
-    return COMPUTE_RESULT_ALPHA;
-}
-
-static SkSwizzler::ResultAlpha swizzle_mask24_to_n32_premul(
-        void* dstRow, const uint8_t* srcRow, int width, SkMasks* masks) {
-
-    // Use the masks to decode to the destination
-    SkPMColor* dstPtr = (SkPMColor*) dstRow;
-    INIT_RESULT_ALPHA;
-    for (int i = 0; i < 3*width; i += 3) {
-        uint32_t p = srcRow[i] | (srcRow[i + 1] << 8) | srcRow[i + 2] << 16;
-        uint8_t red = masks->getRed(p);
-        uint8_t green = masks->getGreen(p);
-        uint8_t blue = masks->getBlue(p);
-        uint8_t alpha = masks->getAlpha(p);
-        UPDATE_RESULT_ALPHA(alpha);
-        dstPtr[i/3] = SkPreMultiplyARGB(alpha, red, green, blue);
-    }
-    return COMPUTE_RESULT_ALPHA;
-}
-
-static SkSwizzler::ResultAlpha swizzle_mask24_to_565(
-        void* dstRow, const uint8_t* srcRow, int width, SkMasks* masks) {
-
-    // Use the masks to decode to the destination
-    uint16_t* dstPtr = (uint16_t*) dstRow;
-    for (int i = 0; i < 3*width; i += 3) {
-        uint32_t p = srcRow[i] | (srcRow[i + 1] << 8) | srcRow[i + 2] << 16;
-        uint8_t red = masks->getRed(p);
-        uint8_t green = masks->getGreen(p);
-        uint8_t blue = masks->getBlue(p);
-        dstPtr[i/3] = SkPack888ToRGB16(red, green, blue);
-    }
-    return SkSwizzler::kOpaque_ResultAlpha;
-}
-
-static SkSwizzler::ResultAlpha swizzle_mask32_to_n32_opaque(
-        void* dstRow, const uint8_t* srcRow, int width, SkMasks* masks) {
-
-    // Use the masks to decode to the destination
-    uint32_t* srcPtr = (uint32_t*) srcRow;
-    SkPMColor* dstPtr = (SkPMColor*) dstRow;
-    for (int i = 0; i < width; i++) {
-        uint32_t p = srcPtr[i];
-        uint8_t red = masks->getRed(p);
-        uint8_t green = masks->getGreen(p);
-        uint8_t blue = masks->getBlue(p);
-        dstPtr[i] = SkPackARGB32NoCheck(0xFF, red, green, blue);
-    }
-    return SkSwizzler::kOpaque_ResultAlpha;
-}
-
-static SkSwizzler::ResultAlpha swizzle_mask32_to_n32_unpremul(
-        void* dstRow, const uint8_t* srcRow, int width, SkMasks* masks) {
-
-    // Use the masks to decode to the destination
-    uint32_t* srcPtr = (uint32_t*) srcRow;
+    srcRow += 3 * startX;
     SkPMColor* dstPtr = (SkPMColor*) dstRow;
     INIT_RESULT_ALPHA;
     for (int i = 0; i < width; i++) {
-        uint32_t p = srcPtr[i];
+        uint32_t p = srcRow[0] | (srcRow[1] << 8) | srcRow[2] << 16;
         uint8_t red = masks->getRed(p);
         uint8_t green = masks->getGreen(p);
         uint8_t blue = masks->getBlue(p);
         uint8_t alpha = masks->getAlpha(p);
         UPDATE_RESULT_ALPHA(alpha);
         dstPtr[i] = SkPackARGB32NoCheck(alpha, red, green, blue);
+        srcRow += 3 * sampleX;
     }
     return COMPUTE_RESULT_ALPHA;
 }
 
-static SkSwizzler::ResultAlpha swizzle_mask32_to_n32_premul(
-        void* dstRow, const uint8_t* srcRow, int width, SkMasks* masks) {
+static SkSwizzler::ResultAlpha swizzle_mask24_to_n32_premul(
+        void* dstRow, const uint8_t* srcRow, int width, SkMasks* masks,
+        uint32_t startX, uint32_t sampleX) {
 
     // Use the masks to decode to the destination
-    uint32_t* srcPtr = (uint32_t*) srcRow;
+    srcRow += 3 * startX;
     SkPMColor* dstPtr = (SkPMColor*) dstRow;
     INIT_RESULT_ALPHA;
     for (int i = 0; i < width; i++) {
-        uint32_t p = srcPtr[i];
+        uint32_t p = srcRow[0] | (srcRow[1] << 8) | srcRow[2] << 16;
         uint8_t red = masks->getRed(p);
         uint8_t green = masks->getGreen(p);
         uint8_t blue = masks->getBlue(p);
         uint8_t alpha = masks->getAlpha(p);
         UPDATE_RESULT_ALPHA(alpha);
         dstPtr[i] = SkPreMultiplyARGB(alpha, red, green, blue);
+        srcRow += 3 * sampleX;
+    }
+    return COMPUTE_RESULT_ALPHA;
+}
+
+static SkSwizzler::ResultAlpha swizzle_mask24_to_565(
+        void* dstRow, const uint8_t* srcRow, int width, SkMasks* masks,
+        uint32_t startX, uint32_t sampleX) {
+
+    // Use the masks to decode to the destination
+    srcRow += 3 * startX;
+    uint16_t* dstPtr = (uint16_t*) dstRow;
+    for (int i = 0; i < width; i++) {
+        uint32_t p = srcRow[0] | (srcRow[1] << 8) | srcRow[2] << 16;
+        uint8_t red = masks->getRed(p);
+        uint8_t green = masks->getGreen(p);
+        uint8_t blue = masks->getBlue(p);
+        dstPtr[i] = SkPack888ToRGB16(red, green, blue);
+        srcRow += 3 * sampleX;
+    }
+    return SkSwizzler::kOpaque_ResultAlpha;
+}
+
+static SkSwizzler::ResultAlpha swizzle_mask32_to_n32_opaque(
+        void* dstRow, const uint8_t* srcRow, int width, SkMasks* masks,
+        uint32_t startX, uint32_t sampleX) {
+
+    // Use the masks to decode to the destination
+    uint32_t* srcPtr = ((uint32_t*) srcRow) + startX;
+    SkPMColor* dstPtr = (SkPMColor*) dstRow;
+    for (int i = 0; i < width; i++) {
+        uint32_t p = srcPtr[0];
+        uint8_t red = masks->getRed(p);
+        uint8_t green = masks->getGreen(p);
+        uint8_t blue = masks->getBlue(p);
+        dstPtr[i] = SkPackARGB32NoCheck(0xFF, red, green, blue);
+        srcPtr += sampleX;
+    }
+    return SkSwizzler::kOpaque_ResultAlpha;
+}
+
+static SkSwizzler::ResultAlpha swizzle_mask32_to_n32_unpremul(
+        void* dstRow, const uint8_t* srcRow, int width, SkMasks* masks,
+        uint32_t startX, uint32_t sampleX) {
+
+    // Use the masks to decode to the destination
+    uint32_t* srcPtr = ((uint32_t*) srcRow) + startX;
+    SkPMColor* dstPtr = (SkPMColor*) dstRow;
+    INIT_RESULT_ALPHA;
+    for (int i = 0; i < width; i++) {
+        uint32_t p = srcPtr[0];
+        uint8_t red = masks->getRed(p);
+        uint8_t green = masks->getGreen(p);
+        uint8_t blue = masks->getBlue(p);
+        uint8_t alpha = masks->getAlpha(p);
+        UPDATE_RESULT_ALPHA(alpha);
+        dstPtr[i] = SkPackARGB32NoCheck(alpha, red, green, blue);
+        srcPtr += sampleX;
+    }
+    return COMPUTE_RESULT_ALPHA;
+}
+
+static SkSwizzler::ResultAlpha swizzle_mask32_to_n32_premul(
+        void* dstRow, const uint8_t* srcRow, int width, SkMasks* masks,
+        uint32_t startX, uint32_t sampleX) {
+
+    // Use the masks to decode to the destination
+    uint32_t* srcPtr = ((uint32_t*) srcRow) + startX;
+    SkPMColor* dstPtr = (SkPMColor*) dstRow;
+    INIT_RESULT_ALPHA;
+    for (int i = 0; i < width; i++) {
+        uint32_t p = srcPtr[0];
+        uint8_t red = masks->getRed(p);
+        uint8_t green = masks->getGreen(p);
+        uint8_t blue = masks->getBlue(p);
+        uint8_t alpha = masks->getAlpha(p);
+        UPDATE_RESULT_ALPHA(alpha);
+        dstPtr[i] = SkPreMultiplyARGB(alpha, red, green, blue);
+        srcPtr += sampleX;
     }
     return COMPUTE_RESULT_ALPHA;
 }
 
 static SkSwizzler::ResultAlpha swizzle_mask32_to_565(
-        void* dstRow, const uint8_t* srcRow, int width, SkMasks* masks) {
+        void* dstRow, const uint8_t* srcRow, int width, SkMasks* masks,
+        uint32_t startX, uint32_t sampleX) {
     // Use the masks to decode to the destination
-    uint32_t* srcPtr = (uint32_t*) srcRow;
+    uint32_t* srcPtr = ((uint32_t*) srcRow) + startX;
     uint16_t* dstPtr = (uint16_t*) dstRow;
     for (int i = 0; i < width; i++) {
-        uint32_t p = srcPtr[i];
+        uint32_t p = srcPtr[0];
         uint8_t red = masks->getRed(p);
         uint8_t green = masks->getGreen(p);
         uint8_t blue = masks->getBlue(p);
         dstPtr[i] = SkPack888ToRGB16(red, green, blue);
+        srcPtr += sampleX;
     }
     return SkSwizzler::kOpaque_ResultAlpha;
 }
@@ -222,15 +251,16 @@
  *
  */
 SkMaskSwizzler* SkMaskSwizzler::CreateMaskSwizzler(
-        const SkImageInfo& info, SkMasks* masks, uint32_t bitsPerPixel) {
+        const SkImageInfo& dstInfo, const SkImageInfo& srcInfo, SkMasks* masks,
+        uint32_t bitsPerPixel) {
 
     // Choose the appropriate row procedure
     RowProc proc = nullptr;
     switch (bitsPerPixel) {
         case 16:
-            switch (info.colorType()) {
+            switch (dstInfo.colorType()) {
                 case kN32_SkColorType:
-                    switch (info.alphaType()) {
+                    switch (dstInfo.alphaType()) {
                         case kUnpremul_SkAlphaType:
                             proc = &swizzle_mask16_to_n32_unpremul;
                             break;
@@ -245,7 +275,7 @@
                     }
                     break;
                 case kRGB_565_SkColorType:
-                    switch (info.alphaType()) {
+                    switch (dstInfo.alphaType()) {
                         case kOpaque_SkAlphaType:
                             proc = &swizzle_mask16_to_565;
                             break;
@@ -258,9 +288,9 @@
             }
             break;
         case 24:
-            switch (info.colorType()) {
+            switch (dstInfo.colorType()) {
                 case kN32_SkColorType:
-                    switch (info.alphaType()) {
+                    switch (dstInfo.alphaType()) {
                         case kUnpremul_SkAlphaType:
                             proc = &swizzle_mask24_to_n32_unpremul;
                             break;
@@ -275,7 +305,7 @@
                     }
                     break;
                 case kRGB_565_SkColorType:
-                    switch (info.alphaType()) {
+                    switch (dstInfo.alphaType()) {
                         case kOpaque_SkAlphaType:
                             proc = &swizzle_mask24_to_565;
                             break;
@@ -288,9 +318,9 @@
             }
             break;
         case 32:
-            switch (info.colorType()) {
+            switch (dstInfo.colorType()) {
                 case kN32_SkColorType:
-                    switch (info.alphaType()) {
+                    switch (dstInfo.alphaType()) {
                         case kUnpremul_SkAlphaType:
                             proc = &swizzle_mask32_to_n32_unpremul;
                             break;
@@ -305,7 +335,7 @@
                     }
                     break;
                 case kRGB_565_SkColorType:
-                    switch (info.alphaType()) {
+                    switch (dstInfo.alphaType()) {
                         case kOpaque_SkAlphaType:
                             proc = &swizzle_mask32_to_565;
                             break;
@@ -321,7 +351,12 @@
             SkASSERT(false);
             return nullptr;
     }
-    return new SkMaskSwizzler(info, masks, proc);
+
+    // Get the sample size
+    int sampleX;
+    SkScaledCodec::ComputeSampleSize(dstInfo, srcInfo, &sampleX, NULL);
+
+    return new SkMaskSwizzler(dstInfo, masks, proc, sampleX);
 }
 
 /*
@@ -330,10 +365,12 @@
  *
  */
 SkMaskSwizzler::SkMaskSwizzler(const SkImageInfo& dstInfo, SkMasks* masks,
-                               RowProc proc)
+                               RowProc proc, uint32_t sampleX)
     : fDstInfo(dstInfo)
     , fMasks(masks)
     , fRowProc(proc)
+    , fSampleX(sampleX)
+    , fStartX(get_start_coord(sampleX))
 {}
 
 /*
@@ -343,5 +380,5 @@
  */
 SkSwizzler::ResultAlpha SkMaskSwizzler::swizzle(void* dst, const uint8_t* SK_RESTRICT src) {
     SkASSERT(nullptr != dst && nullptr != src);
-    return fRowProc(dst, src, fDstInfo.width(), fMasks);
+    return fRowProc(dst, src, fDstInfo.width(), fMasks, fStartX, fSampleX);
 }