| Index: src/codec/SkCodec_libpng.cpp
|
| diff --git a/src/codec/SkCodec_libpng.cpp b/src/codec/SkCodec_libpng.cpp
|
| index a5d38343138acf1718bb4fc56320c71f760f9a52..699ab398d3a36df70cfbbb1c24c96886047d7f3c 100644
|
| --- a/src/codec/SkCodec_libpng.cpp
|
| +++ b/src/codec/SkCodec_libpng.cpp
|
| @@ -120,7 +120,7 @@ typedef uint32_t (*PackColorProc)(U8CPU a, U8CPU r, U8CPU g, U8CPU b);
|
|
|
| // Note: SkColorTable claims to store SkPMColors, which is not necessarily
|
| // the case here.
|
| -bool SkPngCodec::decodePalette(bool premultiply, int bitDepth, int* ctableCount) {
|
| +bool SkPngCodec::decodePalette(bool premultiply, int* ctableCount) {
|
| int numPalette;
|
| png_colorp palette;
|
| png_bytep trans;
|
| @@ -177,7 +177,7 @@ bool SkPngCodec::decodePalette(bool premultiply, int bitDepth, int* ctableCount)
|
| addressed by the bitdepth of the image and fill it with the last palette color or black if
|
| the palette is empty (really broken image).
|
| */
|
| - int colorCount = SkTMax(numPalette, 1 << SkTMin(bitDepth, 8));
|
| + int colorCount = SkTMax(numPalette, 1 << SkTMin(fBitDepth, 8));
|
| SkPMColor lastColor = index > 0 ? colorPtr[-1] : SkPackARGB32(0xFF, 0, 0, 0);
|
| for (; index < colorCount; index++) {
|
| *colorPtr++ = lastColor;
|
| @@ -374,12 +374,6 @@ SkPngCodec::SkPngCodec(const SkImageInfo& info, SkStream* stream,
|
| {}
|
|
|
| SkPngCodec::~SkPngCodec() {
|
| - // First, ensure that the scanline decoder is left in a finished state.
|
| - SkAutoTDelete<SkScanlineDecoder> decoder(this->detachScanlineDecoder());
|
| - if (NULL != decoder) {
|
| - this->finish();
|
| - }
|
| -
|
| this->destroyReadStruct();
|
| }
|
|
|
| @@ -454,7 +448,7 @@ SkCodec::Result SkPngCodec::initializeSwizzler(const SkImageInfo& requestedInfo,
|
| case kIndex_8_SkColorType:
|
| //decode palette to Skia format
|
| fSrcConfig = SkSwizzler::kIndex;
|
| - if (!this->decodePalette(kPremul_SkAlphaType == requestedInfo.alphaType(), fBitDepth,
|
| + if (!this->decodePalette(kPremul_SkAlphaType == requestedInfo.alphaType(),
|
| ctableCount)) {
|
| return kInvalidInput;
|
| }
|
| @@ -523,11 +517,6 @@ SkCodec::Result SkPngCodec::onGetPixels(const SkImageInfo& requestedInfo, void*
|
| if (!conversion_possible(requestedInfo, this->getInfo())) {
|
| return kInvalidConversion;
|
| }
|
| - // Do not allow a regular decode if the caller has asked for a scanline decoder
|
| - if (NULL != this->scanlineDecoder()) {
|
| - SkCodecPrintf("cannot getPixels() if a scanline decoder has been created\n");
|
| - return kInvalidParameters;
|
| - }
|
| if (requestedInfo.dimensions() != this->getInfo().dimensions()) {
|
| return kInvalidScale;
|
| }
|
| @@ -596,6 +585,7 @@ void SkPngCodec::finish() {
|
| // We've already read all the scanlines. This is a success.
|
| return;
|
| }
|
| + // FIXME: Is this necessary?
|
| /* read rest of file, and get additional chunks in info_ptr - REQUIRED */
|
| png_read_end(fPng_ptr, fInfo_ptr);
|
| }
|
| @@ -611,6 +601,10 @@ public:
|
| fSrcRow = static_cast<uint8_t*>(fStorage.get());
|
| }
|
|
|
| + ~SkPngScanlineDecoder() {
|
| + fCodec->finish();
|
| + }
|
| +
|
| SkCodec::Result onGetScanlines(void* dst, int count, size_t rowBytes) override {
|
| if (setjmp(png_jmpbuf(fCodec->fPng_ptr))) {
|
| SkCodecPrintf("setjmp long jump!\n");
|
| @@ -645,10 +639,10 @@ public:
|
| bool onReallyHasAlpha() const override { return fHasAlpha; }
|
|
|
| private:
|
| - SkPngCodec* fCodec; // Unowned.
|
| - bool fHasAlpha;
|
| - SkAutoMalloc fStorage;
|
| - uint8_t* fSrcRow;
|
| + SkAutoTDelete<SkPngCodec> fCodec;
|
| + bool fHasAlpha;
|
| + SkAutoMalloc fStorage;
|
| + uint8_t* fSrcRow;
|
|
|
| typedef SkScanlineDecoder INHERITED;
|
| };
|
| @@ -662,22 +656,21 @@ public:
|
| , fHasAlpha(false)
|
| , fCurrentRow(0)
|
| , fHeight(dstInfo.height())
|
| - , fRewindNeeded(false)
|
| {
|
| fSrcRowBytes = dstInfo.width() * SkSwizzler::BytesPerPixel(fCodec->fSrcConfig);
|
| fGarbageRow.reset(fSrcRowBytes);
|
| fGarbageRowPtr = static_cast<uint8_t*>(fGarbageRow.get());
|
| }
|
|
|
| + ~SkPngInterlacedScanlineDecoder() {
|
| + fCodec->finish();
|
| + }
|
| +
|
| SkCodec::Result onGetScanlines(void* dst, int count, size_t dstRowBytes) override {
|
| //rewind stream if have previously called onGetScanlines,
|
| //since we need entire progressive image to get scanlines
|
| - if (fRewindNeeded) {
|
| - if(false == fCodec->handleRewind()) {
|
| - return SkCodec::kCouldNotRewind;
|
| - }
|
| - } else {
|
| - fRewindNeeded = true;
|
| + if (!fCodec->handleRewind()) {
|
| + return SkCodec::kCouldNotRewind;
|
| }
|
| if (setjmp(png_jmpbuf(fCodec->fPng_ptr))) {
|
| SkCodecPrintf("setjmp long jump!\n");
|
| @@ -724,14 +717,13 @@ public:
|
| bool onReallyHasAlpha() const override { return fHasAlpha; }
|
|
|
| private:
|
| - SkPngCodec* fCodec; // Unowned.
|
| - bool fHasAlpha;
|
| - int fCurrentRow;
|
| - int fHeight;
|
| - size_t fSrcRowBytes;
|
| - bool fRewindNeeded;
|
| - SkAutoMalloc fGarbageRow;
|
| - uint8_t* fGarbageRowPtr;
|
| + SkAutoTDelete<SkPngCodec> fCodec;
|
| + bool fHasAlpha;
|
| + int fCurrentRow;
|
| + int fHeight;
|
| + size_t fSrcRowBytes;
|
| + SkAutoMalloc fGarbageRow;
|
| + uint8_t* fGarbageRowPtr;
|
|
|
| typedef SkScanlineDecoder INHERITED;
|
| };
|
| @@ -747,25 +739,31 @@ SkScanlineDecoder* SkPngCodec::onGetScanlineDecoder(const SkImageInfo& dstInfo,
|
| if (dstInfo.dimensions() != this->getInfo().dimensions()) {
|
| return NULL;
|
| }
|
| - if (!this->handleRewind()) {
|
| + // Create a new SkPngCodec, to be owned by the scanline decoder.
|
| + SkStream* stream = this->stream()->duplicate();
|
| + if (!stream) {
|
| + return NULL;
|
| + }
|
| + SkAutoTDelete<SkPngCodec> codec (static_cast<SkPngCodec*>(SkPngCodec::NewFromStream(stream)));
|
| + if (!codec) {
|
| return NULL;
|
| }
|
|
|
| // Note: We set dst to NULL since we do not know it yet. rowBytes is not needed,
|
| // since we'll be manually updating the dstRow, but the SkSwizzler requires it to
|
| // be at least dstInfo.minRowBytes.
|
| - if (this->initializeSwizzler(dstInfo, NULL, dstInfo.minRowBytes(), options, ctable,
|
| + if (codec->initializeSwizzler(dstInfo, NULL, dstInfo.minRowBytes(), options, ctable,
|
| ctableCount) != kSuccess) {
|
| SkCodecPrintf("failed to initialize the swizzler.\n");
|
| return NULL;
|
| }
|
|
|
| - SkASSERT(fNumberPasses != INVALID_NUMBER_PASSES);
|
| - if (fNumberPasses > 1) {
|
| + SkASSERT(codec->fNumberPasses != INVALID_NUMBER_PASSES);
|
| + if (codec->fNumberPasses > 1) {
|
| // interlaced image
|
| - return SkNEW_ARGS(SkPngInterlacedScanlineDecoder, (dstInfo, this));
|
| + return SkNEW_ARGS(SkPngInterlacedScanlineDecoder, (dstInfo, codec.detach()));
|
| }
|
|
|
| - return SkNEW_ARGS(SkPngScanlineDecoder, (dstInfo, this));
|
| + return SkNEW_ARGS(SkPngScanlineDecoder, (dstInfo, codec.detach()));
|
| }
|
|
|
|
|