| Index: src/codec/SkBmpStandardCodec.cpp | 
| diff --git a/src/codec/SkBmpStandardCodec.cpp b/src/codec/SkBmpStandardCodec.cpp | 
| index 210498eb00f7439b8da7719e008d9fe5347371de..83222ac1feacdd5471c99066a9ef5688645eab6c 100644 | 
| --- a/src/codec/SkBmpStandardCodec.cpp | 
| +++ b/src/codec/SkBmpStandardCodec.cpp | 
| @@ -18,14 +18,15 @@ | 
| SkBmpStandardCodec::SkBmpStandardCodec(const SkImageInfo& info, SkStream* stream, | 
| uint16_t bitsPerPixel, uint32_t numColors, | 
| uint32_t bytesPerColor, uint32_t offset, | 
| -                                       SkBmpCodec::RowOrder rowOrder, bool inIco) | 
| +                                       SkScanlineDecoder::SkScanlineOrder rowOrder, bool inIco) | 
| : INHERITED(info, stream, bitsPerPixel, rowOrder) | 
| , fColorTable(nullptr) | 
| , fNumColors(this->computeNumColors(numColors)) | 
| , fBytesPerColor(bytesPerColor) | 
| , fOffset(offset) | 
| , fSwizzler(nullptr) | 
| -    , fSrcBuffer(nullptr) | 
| +    , fSrcRowBytes(SkAlign4(compute_row_bytes(this->getInfo().width(), this->bitsPerPixel()))) | 
| +    , fSrcBuffer(new uint8_t [fSrcRowBytes]) | 
| , fInIco(inIco) | 
| {} | 
|  | 
| @@ -53,23 +54,18 @@ SkCodec::Result SkBmpStandardCodec::onGetPixels(const SkImageInfo& dstInfo, | 
| return kInvalidConversion; | 
| } | 
|  | 
| -    // Create the color table if necessary and prepare the stream for decode | 
| -    // Note that if it is non-nullptr, inputColorCount will be modified | 
| -    if (!this->createColorTable(dstInfo.alphaType(), inputColorCount)) { | 
| -        SkCodecPrintf("Error: could not create color table.\n"); | 
| -        return kInvalidInput; | 
| +    Result result = this->prepareToDecode(dstInfo, opts, inputColorPtr, inputColorCount); | 
| +    if (kSuccess != result) { | 
| +        return result; | 
| } | 
| - | 
| -    // Copy the color table to the client if necessary | 
| -    copy_color_table(dstInfo, fColorTable, inputColorPtr, inputColorCount); | 
| - | 
| -    // Initialize a swizzler if necessary | 
| -    if (!this->initializeSwizzler(dstInfo, opts)) { | 
| -        SkCodecPrintf("Error: cannot initialize swizzler.\n"); | 
| -        return kInvalidConversion; | 
| +    result = this->decodeRows(dstInfo, dst, dstRowBytes, opts); | 
| +    if (kSuccess != result) { | 
| +        return result; | 
| } | 
| - | 
| -    return this->decode(dstInfo, dst, dstRowBytes, opts); | 
| +    if (fInIco) { | 
| +        return this->decodeIcoMask(dstInfo, dst, dstRowBytes); | 
| +    } | 
| +    return kSuccess; | 
| } | 
|  | 
| /* | 
| @@ -169,10 +165,6 @@ SkCodec::Result SkBmpStandardCodec::onGetPixels(const SkImageInfo& dstInfo, | 
|  | 
| bool SkBmpStandardCodec::initializeSwizzler(const SkImageInfo& dstInfo, | 
| const Options& opts) { | 
| -    // Allocate space for a row buffer | 
| -    const size_t rowBytes = SkAlign4(compute_row_bytes(dstInfo.width(), this->bitsPerPixel())); | 
| -    fSrcBuffer.reset(new uint8_t[rowBytes]); | 
| - | 
| // Get swizzler configuration | 
| SkSwizzler::SrcConfig config; | 
| switch (this->bitsPerPixel()) { | 
| @@ -216,122 +208,91 @@ bool SkBmpStandardCodec::initializeSwizzler(const SkImageInfo& dstInfo, | 
| return true; | 
| } | 
|  | 
| -/* | 
| - * Choose a fill for failures due to an incomplete image.  We will use zero as | 
| - * the default palette index, black for opaque images, and transparent for | 
| - * non-opaque images. | 
| - */ | 
| -static uint32_t get_fill_color_or_index(uint16_t bitsPerPixels, SkAlphaType alphaType) { | 
| -    uint32_t fillColorOrIndex; | 
| -    switch (bitsPerPixels) { | 
| -        case 1: | 
| -        case 2: | 
| -        case 4: | 
| -        case 8: | 
| -            fillColorOrIndex = 0; | 
| -            break; | 
| -        case 24: | 
| -            fillColorOrIndex = SK_ColorBLACK; | 
| -            break; | 
| -        case 32: | 
| -            if (kOpaque_SkAlphaType == alphaType) { | 
| -                fillColorOrIndex = SK_ColorBLACK; | 
| -            } else { | 
| -                fillColorOrIndex = SK_ColorTRANSPARENT; | 
| -            } | 
| -            break; | 
| -        default: | 
| -            SkASSERT(false); | 
| -            return 0; | 
| +SkCodec::Result SkBmpStandardCodec::prepareToDecode(const SkImageInfo& dstInfo, | 
| +        const SkCodec::Options& options, SkPMColor inputColorPtr[], int* inputColorCount) { | 
| +    // Create the color table if necessary and prepare the stream for decode | 
| +    // Note that if it is non-NULL, inputColorCount will be modified | 
| +    if (!this->createColorTable(dstInfo.alphaType(), inputColorCount)) { | 
| +        SkCodecPrintf("Error: could not create color table.\n"); | 
| +        return SkCodec::kInvalidInput; | 
| } | 
| -    return fillColorOrIndex; | 
| + | 
| +    // Copy the color table to the client if necessary | 
| +    copy_color_table(dstInfo, this->fColorTable, inputColorPtr, inputColorCount); | 
| + | 
| +    // Initialize a swizzler if necessary | 
| +    if (!this->initializeSwizzler(dstInfo, options)) { | 
| +        SkCodecPrintf("Error: cannot initialize swizzler.\n"); | 
| +        return SkCodec::kInvalidConversion; | 
| +    } | 
| +    return SkCodec::kSuccess; | 
| } | 
|  | 
| /* | 
| * Performs the bitmap decoding for standard input format | 
| */ | 
| -SkCodec::Result SkBmpStandardCodec::decode(const SkImageInfo& dstInfo, | 
| -                                   void* dst, size_t dstRowBytes, | 
| -                                   const Options& opts) { | 
| -    // Set constant values | 
| -    const int width = dstInfo.width(); | 
| -    const int height = dstInfo.height(); | 
| -    const size_t rowBytes = SkAlign4(compute_row_bytes(width, this->bitsPerPixel())); | 
| - | 
| +SkCodec::Result SkBmpStandardCodec::decodeRows(const SkImageInfo& dstInfo, | 
| +                                               void* dst, size_t dstRowBytes, | 
| +                                               const Options& opts) { | 
| // Iterate over rows of the image | 
| +    const int height = dstInfo.height(); | 
| for (int y = 0; y < height; y++) { | 
| // Read a row of the input | 
| -        if (this->stream()->read(fSrcBuffer.get(), rowBytes) != rowBytes) { | 
| +        if (this->stream()->read(fSrcBuffer.get(), fSrcRowBytes) != fSrcRowBytes) { | 
| SkCodecPrintf("Warning: incomplete input stream.\n"); | 
| // Fill the destination image on failure | 
| -            // Get the fill color/index and check if it is 0 | 
| -            uint32_t fillColorOrIndex = get_fill_color_or_index(this->bitsPerPixel(), | 
| -                    dstInfo.alphaType()); | 
| -            bool zeroFill = (0 == fillColorOrIndex); | 
| - | 
| -            if (kNo_ZeroInitialized == opts.fZeroInitialized || !zeroFill) { | 
| -                // Get a pointer to the color table if it exists | 
| -                const SkPMColor* colorPtr = get_color_ptr(fColorTable.get()); | 
| - | 
| -                void* dstStart = this->getDstStartRow(dst, dstRowBytes, y); | 
| -                SkSwizzler::Fill(dstStart, dstInfo, dstRowBytes, dstInfo.height() - y, | 
| -                        fillColorOrIndex, colorPtr); | 
| -            } | 
| +            void* dstStart = this->getDstStartRow(dst, dstRowBytes, y); | 
| +            const SkPMColor* colorPtr = get_color_ptr(fColorTable.get()); | 
| +            uint32_t fillColorOrIndex = get_fill_color_or_index(dstInfo.alphaType()); | 
| +            SkSwizzler::Fill(dstStart, dstInfo, dstRowBytes, dstInfo.height() - y, | 
| +                    fillColorOrIndex, colorPtr, opts.fZeroInitialized); | 
| return kIncompleteInput; | 
| } | 
|  | 
| // Decode the row in destination format | 
| -        uint32_t row; | 
| -        if (SkBmpCodec::kTopDown_RowOrder == this->rowOrder()) { | 
| -            row = y; | 
| -        } else { | 
| -            row = height - 1 - y; | 
| -        } | 
| +        uint32_t row = this->getDstRow(y, dstInfo.height()); | 
|  | 
| void* dstRow = SkTAddOffset<void>(dst, row * dstRowBytes); | 
| fSwizzler->swizzle(dstRow, fSrcBuffer.get()); | 
| } | 
|  | 
| -    // Finally, apply the AND mask for bmp-in-ico images | 
| -    if (fInIco) { | 
| -        // BMP in ICO have transparency, so this cannot be 565, and this mask | 
| -        // prevents us from using kIndex8. The below code depends on the output | 
| -        // being an SkPMColor. | 
| -        SkASSERT(dstInfo.colorType() == kN32_SkColorType); | 
| - | 
| -        // The AND mask is always 1 bit per pixel | 
| -        const size_t rowBytes = SkAlign4(compute_row_bytes(width, 1)); | 
| +    // Finished decoding the entire image | 
| +    return kSuccess; | 
| +} | 
|  | 
| -        SkPMColor* dstPtr = (SkPMColor*) dst; | 
| -        for (int y = 0; y < height; y++) { | 
| -            // The srcBuffer will at least be large enough | 
| -            if (stream()->read(fSrcBuffer.get(), rowBytes) != rowBytes) { | 
| -                SkCodecPrintf("Warning: incomplete AND mask for bmp-in-ico.\n"); | 
| -                return kIncompleteInput; | 
| -            } | 
| +SkCodec::Result SkBmpStandardCodec::decodeIcoMask(const SkImageInfo& dstInfo, | 
| +        void* dst, size_t dstRowBytes) { | 
| +    // BMP in ICO have transparency, so this cannot be 565, and this mask | 
| +    // prevents us from using kIndex8. The below code depends on the output | 
| +    // being an SkPMColor. | 
| +    SkASSERT(dstInfo.colorType() == kN32_SkColorType); | 
| + | 
| +    // The AND mask is always 1 bit per pixel | 
| +    const uint32_t width = this->getInfo().width(); | 
| +    const size_t rowBytes = SkAlign4(compute_row_bytes(width, 1)); | 
| + | 
| +    SkPMColor* dstPtr = (SkPMColor*) dst; | 
| +    for (int y = 0; y < dstInfo.height(); y++) { | 
| +        // The srcBuffer will at least be large enough | 
| +        if (stream()->read(fSrcBuffer.get(), rowBytes) != rowBytes) { | 
| +            SkCodecPrintf("Warning: incomplete AND mask for bmp-in-ico.\n"); | 
| +            return kIncompleteInput; | 
| +        } | 
|  | 
| -            int row; | 
| -            if (SkBmpCodec::kBottomUp_RowOrder == this->rowOrder()) { | 
| -                row = height - y - 1; | 
| -            } else { | 
| -                row = y; | 
| -            } | 
| +        int row = this->getDstRow(y, dstInfo.height()); | 
|  | 
| -            SkPMColor* dstRow = | 
| -                    SkTAddOffset<SkPMColor>(dstPtr, row * dstRowBytes); | 
| +        SkPMColor* dstRow = | 
| +                SkTAddOffset<SkPMColor>(dstPtr, row * dstRowBytes); | 
|  | 
| -            for (int x = 0; x < width; x++) { | 
| -                int quotient; | 
| -                int modulus; | 
| -                SkTDivMod(x, 8, "ient, &modulus); | 
| -                uint32_t shift = 7 - modulus; | 
| -                uint32_t alphaBit = | 
| -                        (fSrcBuffer.get()[quotient] >> shift) & 0x1; | 
| -                dstRow[x] &= alphaBit - 1; | 
| -            } | 
| +        for (int x = 0; x < width; x++) { | 
| +            int quotient; | 
| +            int modulus; | 
| +            SkTDivMod(x, 8, "ient, &modulus); | 
| +            uint32_t shift = 7 - modulus; | 
| +            uint32_t alphaBit = | 
| +                    (fSrcBuffer.get()[quotient] >> shift) & 0x1; | 
| +            dstRow[x] &= alphaBit - 1; | 
| } | 
| } | 
| - | 
| -    // Finished decoding the entire image | 
| return kSuccess; | 
| } | 
|  |