Index: dm/DMSrcSink.cpp |
diff --git a/dm/DMSrcSink.cpp b/dm/DMSrcSink.cpp |
index 2ea115bc9a445c9db7ed3054ecb479b2192f8d62..88371a8e28fdf68e1e0e5e041588a3a475e4adc1 100644 |
--- a/dm/DMSrcSink.cpp |
+++ b/dm/DMSrcSink.cpp |
@@ -28,6 +28,8 @@ |
#include "SkStream.h" |
#include "SkTLogic.h" |
#include "SkXMLWriter.h" |
+#include "SkScaledCodec.h" |
+#include "SkSwizzler.h" |
DEFINE_bool(multiPage, false, "For document-type backends, render the source" |
" into multiple pages"); |
@@ -340,36 +342,30 @@ Error CodecSrc::draw(SkCanvas* canvas) const { |
return Error::Nonfatal("Could not start scanline decoder"); |
} |
- SkCodec::Result result = SkCodec::kUnimplemented; |
+ void* dst = bitmap.getAddr(0, 0); |
+ size_t rowBytes = bitmap.rowBytes(); |
+ uint32_t height = decodeInfo.height(); |
switch (codec->getScanlineOrder()) { |
case SkCodec::kTopDown_SkScanlineOrder: |
case SkCodec::kBottomUp_SkScanlineOrder: |
case SkCodec::kNone_SkScanlineOrder: |
- result = codec->getScanlines(bitmap.getAddr(0, 0), |
- decodeInfo.height(), bitmap.rowBytes()); |
+ // 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->nextScanline(); |
+ int dstY = codec->outputScanline(y); |
void* dstPtr = bitmap.getAddr(0, dstY); |
- result = codec->getScanlines(dstPtr, 1, bitmap.rowBytes()); |
- if (SkCodec::kSuccess != result && SkCodec::kIncompleteInput != result) { |
- return SkStringPrintf("%s failed with error message %d", |
- fPath.c_str(), (int) result); |
- } |
+ // 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, bitmap.rowBytes()); |
} |
break; |
} |
} |
- switch (result) { |
- case SkCodec::kSuccess: |
- case SkCodec::kIncompleteInput: |
- break; |
- default: |
- return SkStringPrintf("%s failed with error message %d", |
- fPath.c_str(), (int) result); |
- } |
canvas->drawBitmap(bitmap, 0, 0); |
break; |
} |
@@ -429,41 +425,21 @@ Error CodecSrc::draw(SkCanvas* canvas) const { |
return "Error scanline decoder is nullptr"; |
} |
} |
- //skip to first line of subset |
- const SkCodec::Result skipResult = codec->skipScanlines(y); |
- switch (skipResult) { |
- case SkCodec::kSuccess: |
- case SkCodec::kIncompleteInput: |
- break; |
- default: |
- return SkStringPrintf("%s failed after attempting to skip %d scanlines" |
- "with error message %d", fPath.c_str(), y, (int) skipResult); |
- } |
+ // Skip to the first line of subset. We ignore the result value here. |
+ // If the skip value fails, this will indicate an incomplete image. |
+ // This means that the call to getScanlines() will also fail, but it |
+ // will fill the buffer with a default value, so we can still draw the |
+ // image. |
+ codec->skipScanlines(y); |
+ |
//create and set size of subsetBm |
SkBitmap subsetBm; |
SkIRect bounds = SkIRect::MakeWH(currentSubsetWidth, currentSubsetHeight); |
SkAssertResult(largestSubsetBm.extractSubset(&subsetBm, bounds)); |
SkAutoLockPixels autlockSubsetBm(subsetBm, true); |
- const SkCodec::Result subsetResult = |
- codec->getScanlines(buffer, currentSubsetHeight, rowBytes); |
- switch (subsetResult) { |
- case SkCodec::kSuccess: |
- case SkCodec::kIncompleteInput: |
- break; |
- default: |
- return SkStringPrintf("%s failed with error message %d", |
- fPath.c_str(), (int) subsetResult); |
- } |
+ codec->getScanlines(buffer, currentSubsetHeight, rowBytes); |
+ |
const size_t bpp = decodeInfo.bytesPerPixel(); |
- /* |
- * we copy all the lines at once becuase when calling getScanlines for |
- * interlaced pngs the entire image must be read regardless of the number |
- * of lines requested. Reading an interlaced png in a loop, line-by-line, would |
- * decode the entire image height times, which is very slow |
- * it is aknowledged that copying each line as you read it in a loop |
- * may be faster for other types of images. Since this is a correctness test |
- * that's okay. |
- */ |
char* bufferRow = buffer; |
for (int subsetY = 0; subsetY < currentSubsetHeight; ++subsetY) { |
memcpy(subsetBm.getAddr(0, subsetY), bufferRow + x*bpp, |
@@ -493,31 +469,17 @@ Error CodecSrc::draw(SkCanvas* canvas) const { |
// to run this test for image types that do not have this scanline ordering. |
return Error::Nonfatal("Could not start top-down scanline decoder"); |
} |
+ |
for (int i = 0; i < numStripes; i += 2) { |
// Skip a stripe |
const int linesToSkip = SkTMin(stripeHeight, height - i * stripeHeight); |
- SkCodec::Result result = codec->skipScanlines(linesToSkip); |
- switch (result) { |
- case SkCodec::kSuccess: |
- case SkCodec::kIncompleteInput: |
- break; |
- default: |
- return SkStringPrintf("Cannot skip scanlines for %s.", fPath.c_str()); |
- } |
+ codec->skipScanlines(linesToSkip); |
// Read a stripe |
const int startY = (i + 1) * stripeHeight; |
const int linesToRead = SkTMin(stripeHeight, height - startY); |
if (linesToRead > 0) { |
- result = codec->getScanlines(bitmap.getAddr(0, startY), |
- linesToRead, bitmap.rowBytes()); |
- switch (result) { |
- case SkCodec::kSuccess: |
- case SkCodec::kIncompleteInput: |
- break; |
- default: |
- return SkStringPrintf("Cannot get scanlines for %s.", fPath.c_str()); |
- } |
+ codec->getScanlines(bitmap.getAddr(0, startY), linesToRead, bitmap.rowBytes()); |
} |
} |
@@ -531,27 +493,12 @@ Error CodecSrc::draw(SkCanvas* canvas) const { |
// Read a stripe |
const int startY = i * stripeHeight; |
const int linesToRead = SkTMin(stripeHeight, height - startY); |
- SkCodec::Result result = codec->getScanlines(bitmap.getAddr(0, startY), |
- linesToRead, bitmap.rowBytes()); |
- switch (result) { |
- case SkCodec::kSuccess: |
- case SkCodec::kIncompleteInput: |
- break; |
- default: |
- return SkStringPrintf("Cannot get scanlines for %s.", fPath.c_str()); |
- } |
+ codec->getScanlines(bitmap.getAddr(0, startY), linesToRead, bitmap.rowBytes()); |
// Skip a stripe |
const int linesToSkip = SkTMin(stripeHeight, height - (i + 1) * stripeHeight); |
if (linesToSkip > 0) { |
- result = codec->skipScanlines(linesToSkip); |
- switch (result) { |
- case SkCodec::kSuccess: |
- case SkCodec::kIncompleteInput: |
- break; |
- default: |
- return SkStringPrintf("Cannot skip scanlines for %s.", fPath.c_str()); |
- } |
+ codec->skipScanlines(linesToSkip); |
} |
} |
canvas->drawBitmap(bitmap, 0, 0); |
@@ -592,8 +539,9 @@ Error CodecSrc::draw(SkCanvas* canvas) const { |
// And scale |
// FIXME: Should we have a version of getScaledDimensions that takes a subset |
// into account? |
- decodeInfo = decodeInfo.makeWH(SkScalarRoundToInt(preScaleW * fScale), |
- SkScalarRoundToInt(preScaleH * fScale)); |
+ decodeInfo = decodeInfo.makeWH( |
+ SkTMax(1, SkScalarRoundToInt(preScaleW * fScale)), |
+ SkTMax(1, SkScalarRoundToInt(preScaleH * fScale))); |
size_t rowBytes = decodeInfo.minRowBytes(); |
if (!subsetBm.installPixels(decodeInfo, pixels, rowBytes, colorTable.get(), |
nullptr, nullptr)) { |