| 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())); | 
| } | 
|  | 
|  |