| Index: src/codec/SkBmpRLECodec.cpp
|
| diff --git a/src/codec/SkBmpRLECodec.cpp b/src/codec/SkBmpRLECodec.cpp
|
| index fe499c6a6d402b2628f088be11738ec164daa338..37af47600b504d8a49efcaa3e66f093b9bb18b0c 100644
|
| --- a/src/codec/SkBmpRLECodec.cpp
|
| +++ b/src/codec/SkBmpRLECodec.cpp
|
| @@ -38,7 +38,8 @@ SkCodec::Result SkBmpRLECodec::onGetPixels(const SkImageInfo& dstInfo,
|
| void* dst, size_t dstRowBytes,
|
| const Options& opts,
|
| SkPMColor* inputColorPtr,
|
| - int* inputColorCount) {
|
| + int* inputColorCount,
|
| + int* rowsDecoded) {
|
| if (opts.fSubset) {
|
| // Subsets are not supported.
|
| return kUnimplemented;
|
| @@ -54,7 +55,16 @@ SkCodec::Result SkBmpRLECodec::onGetPixels(const SkImageInfo& dstInfo,
|
| }
|
|
|
| // Perform the decode
|
| - return this->decodeRows(dstInfo, dst, dstRowBytes, opts);
|
| + uint32_t rows = this->decodeRows(dstInfo, dst, dstRowBytes, opts);
|
| + if (rows != dstInfo.height()) {
|
| + // We set rowsDecoded equal to the height because the background has already
|
| + // been filled. RLE encodings sometimes skip pixels, so we always start by
|
| + // filling the background.
|
| + *rowsDecoded = dstInfo.height();
|
| + return kIncompleteInput;
|
| + }
|
| +
|
| + return kSuccess;
|
| }
|
|
|
| /*
|
| @@ -275,9 +285,8 @@ SkCodec::Result SkBmpRLECodec::prepareToDecode(const SkImageInfo& dstInfo,
|
| * Performs the bitmap decoding for RLE input format
|
| * RLE decoding is performed all at once, rather than a one row at a time
|
| */
|
| -SkCodec::Result SkBmpRLECodec::decodeRows(const SkImageInfo& info,
|
| - void* dst, size_t dstRowBytes,
|
| - const Options& opts) {
|
| +int SkBmpRLECodec::decodeRows(const SkImageInfo& info, void* dst, size_t dstRowBytes,
|
| + const Options& opts) {
|
| // Set RLE flags
|
| static const uint8_t RLE_ESCAPE = 0;
|
| static const uint8_t RLE_EOL = 0;
|
| @@ -300,24 +309,23 @@ SkCodec::Result SkBmpRLECodec::decodeRows(const SkImageInfo& info,
|
| // Because of the need for transparent pixels, kN32 is the only color
|
| // type that makes sense for the destination format.
|
| SkASSERT(kN32_SkColorType == dstInfo.colorType());
|
| - SkSwizzler::Fill(dst, dstInfo, dstRowBytes, height, SK_ColorTRANSPARENT,
|
| - NULL, opts.fZeroInitialized);
|
| + SkSampler::Fill(dstInfo, dst, dstRowBytes, SK_ColorTRANSPARENT, opts.fZeroInitialized);
|
|
|
| while (true) {
|
| // If we have reached a row that is beyond the requested height, we have
|
| // succeeded.
|
| if (y >= height) {
|
| - // It would be better to check for the EOF marker before returning
|
| + // It would be better to check for the EOF marker before indicating
|
| // success, but we may be performing a scanline decode, which
|
| - // may require us to stop before decoding the full height.
|
| - return kSuccess;
|
| + // would require us to stop before decoding the full height.
|
| + return height;
|
| }
|
|
|
| // Every entry takes at least two bytes
|
| if ((int) fRLEBytes - fCurrRLEByte < 2) {
|
| SkCodecPrintf("Warning: might be incomplete RLE input.\n");
|
| if (this->checkForMoreData() < 2) {
|
| - return kIncompleteInput;
|
| + return y;
|
| }
|
| }
|
|
|
| @@ -342,7 +350,7 @@ SkCodec::Result SkBmpRLECodec::decodeRows(const SkImageInfo& info,
|
| if ((int) fRLEBytes - fCurrRLEByte < 2) {
|
| SkCodecPrintf("Warning: might be incomplete RLE input.\n");
|
| if (this->checkForMoreData() < 2) {
|
| - return kIncompleteInput;
|
| + return y;
|
| }
|
| }
|
| // Modify x and y
|
| @@ -352,7 +360,7 @@ SkCodec::Result SkBmpRLECodec::decodeRows(const SkImageInfo& info,
|
| y += dy;
|
| if (x > width || y > height) {
|
| SkCodecPrintf("Warning: invalid RLE input.\n");
|
| - return kInvalidInput;
|
| + return y - dy;
|
| }
|
| break;
|
| }
|
| @@ -368,14 +376,14 @@ SkCodec::Result SkBmpRLECodec::decodeRows(const SkImageInfo& info,
|
| // image.
|
| if (x + numPixels > width) {
|
| SkCodecPrintf("Warning: invalid RLE input.\n");
|
| - return kInvalidInput;
|
| + return y;
|
| }
|
| // Also abort if there are not enough bytes
|
| // remaining in the stream to set numPixels.
|
| if ((int) fRLEBytes - fCurrRLEByte < SkAlign2(rowBytes)) {
|
| SkCodecPrintf("Warning: might be incomplete RLE input.\n");
|
| if (this->checkForMoreData() < SkAlign2(rowBytes)) {
|
| - return kIncompleteInput;
|
| + return y;
|
| }
|
| }
|
| // Set numPixels number of pixels
|
| @@ -411,7 +419,7 @@ SkCodec::Result SkBmpRLECodec::decodeRows(const SkImageInfo& info,
|
| }
|
| default:
|
| SkASSERT(false);
|
| - return kInvalidInput;
|
| + return y;
|
| }
|
| }
|
| // Skip a byte if necessary to maintain alignment
|
| @@ -434,7 +442,7 @@ SkCodec::Result SkBmpRLECodec::decodeRows(const SkImageInfo& info,
|
| if ((int) fRLEBytes - fCurrRLEByte < 2) {
|
| SkCodecPrintf("Warning: might be incomplete RLE input.\n");
|
| if (this->checkForMoreData() < 2) {
|
| - return kIncompleteInput;
|
| + return y;
|
| }
|
| }
|
|
|
| @@ -467,6 +475,9 @@ SkCodec::Result SkBmpRLECodec::decodeRows(const SkImageInfo& info,
|
| }
|
| }
|
|
|
| +// FIXME: Make SkBmpRLECodec have no knowledge of sampling.
|
| +// Or it should do all sampling natively.
|
| +// It currently is a hybrid that needs to know what SkScaledCodec is doing.
|
| class SkBmpRLESampler : public SkSampler {
|
| public:
|
| SkBmpRLESampler(SkBmpRLECodec* codec)
|
| @@ -476,7 +487,7 @@ public:
|
| }
|
|
|
| private:
|
| - int onSetSampleX(int sampleX) {
|
| + int onSetSampleX(int sampleX) override {
|
| return fCodec->setSampleX(sampleX);
|
| }
|
|
|
| @@ -484,15 +495,15 @@ private:
|
| SkBmpRLECodec* fCodec;
|
| };
|
|
|
| -SkSampler* SkBmpRLECodec::getSampler() {
|
| - if (!fSampler) {
|
| +SkSampler* SkBmpRLECodec::getSampler(bool createIfNecessary) {
|
| + if (!fSampler && createIfNecessary) {
|
| fSampler.reset(new SkBmpRLESampler(this));
|
| }
|
|
|
| return fSampler;
|
| }
|
|
|
| -int SkBmpRLECodec::setSampleX(int sampleX) {
|
| +int SkBmpRLECodec::setSampleX(int sampleX){
|
| fSampleX = sampleX;
|
| return get_scaled_dimension(this->getInfo().width(), sampleX);
|
| }
|
|
|