Index: src/codec/SkPngCodec.cpp |
diff --git a/src/codec/SkPngCodec.cpp b/src/codec/SkPngCodec.cpp |
index 83032e6c18cd35c5eabb67af1fd9404414d96dc4..429317dcebf2ad6f54ae22ed113814ffcd798426 100644 |
--- a/src/codec/SkPngCodec.cpp |
+++ b/src/codec/SkPngCodec.cpp |
@@ -458,7 +458,6 @@ public: |
SkPngNormalDecoder(const SkEncodedInfo& info, const SkImageInfo& imageInfo, SkStream* stream, |
SkPngChunkReader* reader, png_structp png_ptr, png_infop info_ptr, int bitDepth) |
: INHERITED(info, imageInfo, stream, reader, png_ptr, info_ptr, bitDepth) |
- , fLinesDecoded(0) |
, fRowsWrittenToOutput(0) |
, fDst(nullptr) |
, fRowBytes(0) |
@@ -481,12 +480,6 @@ public: |
#endif |
private: |
- // This represents the number of lines reported by libpng, minus any we skipped at the |
- // beginning. Only used when we are skipping lines (i.e. not in decodeAllRows). |
- int fLinesDecoded; |
- // While fLinesDecoded include lines that we skipped, this only includes lines written to the |
- // output so we can report it to the caller for filling. |
- // FIXME: Can we remove fLinesDecoded and just rely on fRowsWrittenToOutput? |
int fRowsWrittenToOutput; |
void* fDst; |
size_t fRowBytes; |
@@ -494,6 +487,7 @@ private: |
// Variables for partial decode |
int fFirstRow; // FIXME: Move to baseclass? |
int fLastRow; |
+ int fRowsNeeded; |
typedef SkPngCodec INHERITED; |
@@ -545,14 +539,18 @@ private: |
fLastRow = lastRow; |
fDst = dst; |
fRowBytes = rowBytes; |
- fLinesDecoded = 0; |
fRowsWrittenToOutput = 0; |
+ fRowsNeeded = fLastRow - fFirstRow + 1; |
} |
SkCodec::Result decode(int* rowsDecoded) override { |
+ if (this->swizzler()) { |
+ const int sampleY = this->swizzler()->sampleY(); |
+ fRowsNeeded = get_scaled_dimension(fLastRow - fFirstRow + 1, sampleY); |
+ } |
this->processData(); |
- if (fLinesDecoded == fLastRow - fFirstRow + 1) { |
+ if (fRowsWrittenToOutput == fRowsNeeded) { |
return SkCodec::kSuccess; |
} |
@@ -570,17 +568,16 @@ private: |
} |
SkASSERT(rowNum <= fLastRow); |
+ SkASSERT(fRowsWrittenToOutput < fRowsNeeded); |
// If there is no swizzler, all rows are needed. |
- if (!this->swizzler() || this->swizzler()->rowNeeded(fLinesDecoded)) { |
+ if (!this->swizzler() || this->swizzler()->rowNeeded(rowNum - fFirstRow)) { |
this->applyXformRow(fDst, row); |
fDst = SkTAddOffset<void>(fDst, fRowBytes); |
fRowsWrittenToOutput++; |
} |
- fLinesDecoded++; |
- |
- if (rowNum == fLastRow) { |
+ if (fRowsWrittenToOutput == fRowsNeeded) { |
// Fake error to stop decoding scanlines. |
longjmp(PNG_JMPBUF(this->png_ptr()), kStopDecoding); |
} |
@@ -722,17 +719,17 @@ private: |
} |
return SkCodec::kIncompleteInput; |
} |
- const int lastRow = fLinesDecoded + fFirstRow - 1; |
- SkASSERT(lastRow <= fLastRow); |
+ const int sampleY = this->swizzler() ? this->swizzler()->sampleY() : 1; |
+ const int rowsNeeded = get_scaled_dimension(fLastRow - fFirstRow + 1, sampleY); |
int rowsWrittenToOutput = 0; |
// FIXME: For resuming interlace, we may swizzle a row that hasn't changed. But it |
// may be too tricky/expensive to handle that correctly. |
png_bytep srcRow = fInterlaceBuffer.get(); |
- const int sampleY = this->swizzler() ? this->swizzler()->sampleY() : 1; |
void* dst = fDst; |
- for (int rowNum = fFirstRow; rowNum <= lastRow; rowNum += sampleY) { |
+ for (int rowNum = fFirstRow + get_start_coord(sampleY); rowsWrittenToOutput < rowsNeeded; |
+ rowNum += sampleY) { |
this->applyXformRow(dst, srcRow); |
dst = SkTAddOffset<void>(dst, fRowBytes); |
srcRow = SkTAddOffset<png_byte>(srcRow, fPng_rowbytes * sampleY); |