| Index: src/codec/SkBmpCodec.cpp
 | 
| diff --git a/src/codec/SkBmpCodec.cpp b/src/codec/SkBmpCodec.cpp
 | 
| index 20af2da06fe0db122b86b49bef63b5c7ba6da8bc..4ac0437ebc0106d7160e66496d7015ba396bd192 100644
 | 
| --- a/src/codec/SkBmpCodec.cpp
 | 
| +++ b/src/codec/SkBmpCodec.cpp
 | 
| @@ -11,6 +11,7 @@
 | 
|  #include "SkBmpStandardCodec.h"
 | 
|  #include "SkCodecPriv.h"
 | 
|  #include "SkColorPriv.h"
 | 
| +#include "SkScaledCodec.h"
 | 
|  #include "SkStream.h"
 | 
|  
 | 
|  /*
 | 
| @@ -540,6 +541,14 @@ bool SkBmpCodec::onRewind() {
 | 
|      return SkBmpCodec::ReadHeader(this->stream(), this->inIco(), NULL);
 | 
|  }
 | 
|  
 | 
| +int32_t SkBmpCodec::getDstRow(int32_t y, int32_t height) {
 | 
| +    if (SkBmpCodec::kTopDown_RowOrder == fRowOrder) {
 | 
| +        return y;
 | 
| +    } else {
 | 
| +        return height - y - 1;
 | 
| +    }
 | 
| +}
 | 
| +
 | 
|  /*
 | 
|   * Get the destination row to start filling from
 | 
|   * Used to fill the remainder of the image on incomplete input for bmps
 | 
| @@ -563,3 +572,77 @@ uint32_t SkBmpCodec::computeNumColors(uint32_t numColors) {
 | 
|      }
 | 
|      return numColors;
 | 
|  }
 | 
| +
 | 
| +/*
 | 
| + * Scanline decoder for bmps
 | 
| + */
 | 
| +class SkBmpScanlineDecoder : public SkScanlineDecoder {
 | 
| +public:
 | 
| +    SkBmpScanlineDecoder(SkBmpCodec* codec)
 | 
| +        : INHERITED(codec->getInfo())
 | 
| +        , fCodec(codec)
 | 
| +    {}
 | 
| +
 | 
| +    SkEncodedFormat onGetEncodedFormat() const override {
 | 
| +        return kBMP_SkEncodedFormat;
 | 
| +    }
 | 
| +
 | 
| +    SkCodec::Result onStart(const SkImageInfo& dstInfo, const SkCodec::Options& options,
 | 
| +                            SkPMColor inputColorPtr[], int* inputColorCount) override {
 | 
| +        if (!fCodec->rewindIfNeeded()) {
 | 
| +            return SkCodec::kCouldNotRewind;
 | 
| +        }
 | 
| +        if (options.fSubset) {
 | 
| +            // Subsets are not supported.
 | 
| +            return SkCodec::kUnimplemented;
 | 
| +        }
 | 
| +        if (dstInfo.dimensions() != this->getInfo().dimensions()) {
 | 
| +            if (!SkScaledCodec::DimensionsSupportedForSampling(this->getInfo(), dstInfo)) {
 | 
| +                return SkCodec::kInvalidScale;
 | 
| +            }
 | 
| +        }
 | 
| +        if (!conversion_possible(dstInfo, this->getInfo())) {
 | 
| +            SkCodecPrintf("Error: cannot convert input type to output type.\n");
 | 
| +            return SkCodec::kInvalidConversion;
 | 
| +        }
 | 
| +
 | 
| +        return fCodec->prepareToDecode(dstInfo, options, inputColorPtr, inputColorCount);
 | 
| +    }
 | 
| +
 | 
| +    SkCodec::Result onGetScanlines(void* dst, int count, size_t rowBytes) override {
 | 
| +        // Create a new image info representing the portion of the image to decode
 | 
| +        SkImageInfo rowInfo = this->dstInfo().makeWH(this->dstInfo().width(), count);
 | 
| +
 | 
| +        // Decode the requested rows
 | 
| +        return fCodec->decode(rowInfo, dst, rowBytes, this->options());
 | 
| +    }
 | 
| +
 | 
| +    SkScanlineOrder onGetScanlineOrder() const override {
 | 
| +        if (SkBmpCodec::kTopDown_RowOrder == fCodec->fRowOrder) {
 | 
| +            return kTopDown_SkScanlineOrder;
 | 
| +        } else {
 | 
| +            return kOutOfOrder_SkScanlineOrder;
 | 
| +        }
 | 
| +    }
 | 
| +
 | 
| +    int onGetY() const override {
 | 
| +        return fCodec->getDstRow(INHERITED::onGetY(), this->dstInfo().height());
 | 
| +    }
 | 
| +
 | 
| +    // TODO(msarett): Override default skipping with something more clever.
 | 
| +    // TODO(msarett): Consider other optimizations for this codec.
 | 
| +
 | 
| +private:
 | 
| +    SkAutoTDelete<SkBmpCodec> fCodec;
 | 
| +
 | 
| +    typedef SkScanlineDecoder INHERITED;
 | 
| +};
 | 
| +
 | 
| +SkScanlineDecoder* SkBmpCodec::NewSDFromStream(SkStream* stream) {
 | 
| +    SkAutoTDelete<SkBmpCodec> codec(static_cast<SkBmpCodec*>(SkBmpCodec::NewFromStream(stream)));
 | 
| +    if (!codec) {
 | 
| +        return NULL;
 | 
| +    }
 | 
| +
 | 
| +    return SkNEW_ARGS(SkBmpScanlineDecoder, (codec.detach()));
 | 
| +}
 | 
| 
 |