Index: dm/DMSrcSink.cpp |
diff --git a/dm/DMSrcSink.cpp b/dm/DMSrcSink.cpp |
index e35bbad24e6c0981cbc9ab9a5c2c1f7937a2a7d8..ae21a5becbfd33d495dc60ca733aded079b9933a 100644 |
--- a/dm/DMSrcSink.cpp |
+++ b/dm/DMSrcSink.cpp |
@@ -446,31 +446,55 @@ Error CodecSrc::draw(SkCanvas* canvas) const { |
break; |
} |
case kScanline_Mode: { |
- if (SkCodec::kSuccess != codec->startScanlineDecode(decodeInfo, NULL, colorPtr, |
- &colorCount)) { |
- return "Could not start scanline decoder"; |
- } |
- |
void* dst = pixels.get(); |
uint32_t height = decodeInfo.height(); |
- switch (codec->getScanlineOrder()) { |
- case SkCodec::kTopDown_SkScanlineOrder: |
- case SkCodec::kBottomUp_SkScanlineOrder: |
- case SkCodec::kNone_SkScanlineOrder: |
- // We do not need to check the return value. On an incomplete |
- // image, memory will be filled with a default value. |
- codec->getScanlines(dst, height, rowBytes); |
- break; |
- case SkCodec::kOutOfOrder_SkScanlineOrder: { |
- for (int y = 0; y < decodeInfo.height(); y++) { |
- int dstY = codec->outputScanline(y); |
- void* dstPtr = SkTAddOffset<void>(dst, rowBytes * dstY); |
- // We complete the loop, even if this call begins to fail |
- // due to an incomplete image. This ensures any uninitialized |
- // memory will be filled with the proper value. |
- codec->getScanlines(dstPtr, 1, rowBytes); |
+ const bool png = fPath.endsWith("png"); |
+ const bool ico = fPath.endsWith("ico"); |
+ bool useOldScanlineMethod = !png && !ico; |
+ if (png || ico) { |
+ if (SkCodec::kSuccess == codec->startIncrementalDecode(decodeInfo, dst, |
+ rowBytes, nullptr, colorPtr, &colorCount)) { |
+ int rowsDecoded; |
+ if (SkCodec::kIncompleteInput == codec->incrementalDecode(&rowsDecoded)) { |
+ codec->fillIncompleteImage(decodeInfo, dst, rowBytes, |
+ SkCodec::kNo_ZeroInitialized, height, |
+ rowsDecoded); |
+ } |
+ } else { |
+ if (png) { |
+ // Error: PNG should support incremental decode. |
+ return "Could not start incremental decode"; |
+ } |
+ // Otherwise, this is an ICO. Since incremental failed, it must contain a BMP, |
+ // which should work via startScanlineDecode |
+ useOldScanlineMethod = true; |
+ } |
+ } |
+ |
+ if (useOldScanlineMethod) { |
+ if (SkCodec::kSuccess != codec->startScanlineDecode(decodeInfo, NULL, colorPtr, |
+ &colorCount)) { |
+ return "Could not start scanline decoder"; |
+ } |
+ |
+ switch (codec->getScanlineOrder()) { |
+ case SkCodec::kTopDown_SkScanlineOrder: |
+ case SkCodec::kBottomUp_SkScanlineOrder: |
+ // We do not need to check the return value. On an incomplete |
+ // image, memory will be filled with a default value. |
+ codec->getScanlines(dst, height, rowBytes); |
+ break; |
+ case SkCodec::kOutOfOrder_SkScanlineOrder: { |
+ for (int y = 0; y < decodeInfo.height(); y++) { |
+ int dstY = codec->outputScanline(y); |
+ void* dstPtr = SkTAddOffset<void>(dst, rowBytes * dstY); |
+ // We complete the loop, even if this call begins to fail |
+ // due to an incomplete image. This ensures any uninitialized |
+ // memory will be filled with the proper value. |
+ codec->getScanlines(dstPtr, 1, rowBytes); |
+ } |
+ break; |
} |
- break; |
} |
} |