Index: src/codec/SkScaledCodec.cpp |
diff --git a/src/codec/SkScaledCodec.cpp b/src/codec/SkScaledCodec.cpp |
index 951ab27b1c73def82b545237fe485e4dab58390a..75f783148f7af8ced99a82e80de34aa17435380f 100644 |
--- a/src/codec/SkScaledCodec.cpp |
+++ b/src/codec/SkScaledCodec.cpp |
@@ -178,7 +178,8 @@ void SkScaledCodec::ComputeSampleSize(const SkImageInfo& dstInfo, const SkImageI |
SkCodec::Result SkScaledCodec::onGetPixels(const SkImageInfo& requestedInfo, void* dst, |
size_t rowBytes, const Options& options, |
- SkPMColor ctable[], int* ctableCount) { |
+ SkPMColor ctable[], int* ctableCount, |
+ int* incompleteScanlines) { |
if (options.fSubset) { |
// Subsets are not supported. |
@@ -188,20 +189,33 @@ SkCodec::Result SkScaledCodec::onGetPixels(const SkImageInfo& requestedInfo, voi |
Result result = fScanlineDecoder->start(requestedInfo, &options, ctable, ctableCount); |
if (kSuccess == result) { |
// native decode supported |
+ uint32_t lines; |
switch (fScanlineDecoder->getScanlineOrder()) { |
case SkScanlineDecoder::kTopDown_SkScanlineOrder: |
case SkScanlineDecoder::kBottomUp_SkScanlineOrder: |
case SkScanlineDecoder::kNone_SkScanlineOrder: |
- return fScanlineDecoder->getScanlines(dst, requestedInfo.height(), rowBytes); |
+ lines = fScanlineDecoder->getScanlines(dst, requestedInfo.height(), rowBytes); |
+ if (lines != requestedInfo.height()) { |
+ *incompleteScanlines = requestedInfo.height() - lines; |
+ return kIncompleteInput; |
+ } |
+ return kSuccess; |
case SkScanlineDecoder::kOutOfOrder_SkScanlineOrder: { |
for (int y = 0; y < requestedInfo.height(); y++) { |
int dstY = fScanlineDecoder->getY(); |
void* dstPtr = SkTAddOffset<void>(dst, rowBytes * dstY); |
- result = fScanlineDecoder->getScanlines(dstPtr, 1, rowBytes); |
- // FIXME (msarett): Make the SkCodec base class take care of filling |
- // uninitialized pixels so we can return immediately on kIncompleteInput. |
- if (kSuccess != result && kIncompleteInput != result) { |
- return result; |
+ lines = fScanlineDecoder->getScanlines(dstPtr, 1, rowBytes); |
+ if (1 != lines) { |
+ // TODO (msarett): Can we share this code with SkGifCodec? |
+ const SkImageInfo fillInfo = requestedInfo.makeWH(requestedInfo.width(), 1); |
+ const uint32_t fillValue = this->getFillValue(fillInfo); |
+ for (; y < requestedInfo.height(); y++) { |
+ int dstY = fScanlineDecoder->getY(y); |
+ void* dstRow = SkTAddOffset<void>(dst, rowBytes * dstY); |
+ SkSwizzler::Fill(dstRow, fillInfo, rowBytes, fillValue, |
+ options.fZeroInitialized); |
+ } |
+ break; |
} |
} |
return result; |
@@ -236,41 +250,61 @@ SkCodec::Result SkScaledCodec::onGetPixels(const SkImageInfo& requestedInfo, voi |
return result; |
} |
+ uint32_t lines; |
switch(fScanlineDecoder->getScanlineOrder()) { |
case SkScanlineDecoder::kTopDown_SkScanlineOrder: { |
- result = fScanlineDecoder->skipScanlines(Y0); |
- if (kSuccess != result && kIncompleteInput != result) { |
- return result; |
+ if (!fScanlineDecoder->skipScanlines(Y0)) { |
+ *incompleteScanlines = dstHeight; |
+ return kIncompleteInput; |
} |
for (int y = 0; y < dstHeight; y++) { |
- result = fScanlineDecoder->getScanlines(dst, 1, rowBytes); |
- if (kSuccess != result && kIncompleteInput != result) { |
- return result; |
+ lines = fScanlineDecoder->getScanlines(dst, 1, rowBytes); |
+ if (1 != lines) { |
+ *incompleteScanlines = dstHeight - y; |
+ return kIncompleteInput; |
} |
if (y < dstHeight - 1) { |
- result = fScanlineDecoder->skipScanlines(sampleY - 1); |
- if (kSuccess != result && kIncompleteInput != result) { |
- return result; |
+ if (!fScanlineDecoder->skipScanlines(sampleY - 1)) { |
+ *incompleteScanlines = dstHeight - y; |
+ return kIncompleteInput; |
} |
} |
dst = SkTAddOffset<void>(dst, rowBytes); |
} |
- return result; |
+ return kSuccess; |
} |
case SkScanlineDecoder::kBottomUp_SkScanlineOrder: |
case SkScanlineDecoder::kOutOfOrder_SkScanlineOrder: { |
- for (int y = 0; y < srcHeight; y++) { |
+ Result result = kSuccess; |
+ int y; |
+ for (y = 0; y < srcHeight; y++) { |
int srcY = fScanlineDecoder->getY(); |
if (is_coord_necessary(srcY, sampleY, dstHeight)) { |
void* dstPtr = SkTAddOffset<void>(dst, rowBytes * get_dst_coord(srcY, sampleY)); |
- result = fScanlineDecoder->getScanlines(dstPtr, 1, rowBytes); |
- if (kSuccess != result && kIncompleteInput != result) { |
- return result; |
+ lines = fScanlineDecoder->getScanlines(dstPtr, 1, rowBytes); |
+ if (1 != lines) { |
+ result = kIncompleteInput; |
+ break; |
} |
} else { |
- result = fScanlineDecoder->skipScanlines(1); |
- if (kSuccess != result && kIncompleteInput != result) { |
- return result; |
+ if (!fScanlineDecoder->skipScanlines(1)) { |
+ result = kIncompleteInput; |
+ break; |
+ } |
+ } |
+ } |
+ |
+ // Fill the remaining rows on an incomplete input |
+ if (kIncompleteInput == result) { |
+ const SkImageInfo fillInfo = requestedInfo.makeWH(requestedInfo.width(), 1); |
+ const uint32_t fillValue = this->getFillValue(fillInfo); |
+ for (; y < srcHeight; y++) { |
+ int srcY = fScanlineDecoder->getY(y); |
+ if (is_coord_necessary(srcY, sampleY, dstHeight)) { |
+ void* dstRow = SkTAddOffset<void>(dst, |
+ rowBytes * get_dst_coord(srcY, sampleY)); |
+ SkSwizzler::Fill(dstRow, fillInfo, rowBytes, fillValue, |
+ options.fZeroInitialized); |
} |
} |
} |
@@ -279,20 +313,34 @@ SkCodec::Result SkScaledCodec::onGetPixels(const SkImageInfo& requestedInfo, voi |
case SkScanlineDecoder::kNone_SkScanlineOrder: { |
SkAutoMalloc storage(srcHeight * rowBytes); |
uint8_t* storagePtr = static_cast<uint8_t*>(storage.get()); |
- result = fScanlineDecoder->getScanlines(storagePtr, srcHeight, rowBytes); |
- if (kSuccess != result && kIncompleteInput != result) { |
- return result; |
- } |
+ int scanlines = (int) fScanlineDecoder->getScanlines(storagePtr, srcHeight, rowBytes); |
storagePtr += Y0 * rowBytes; |
- for (int y = 0; y < dstHeight; y++) { |
+ scanlines -= Y0; |
+ int y = 0; |
+ while(y < dstHeight && scanlines > 0) { |
memcpy(dst, storagePtr, rowBytes); |
storagePtr += sampleY * rowBytes; |
dst = SkTAddOffset<void>(dst, rowBytes); |
+ scanlines -= sampleY; |
+ y++; |
} |
- return result; |
+ if (y < dstHeight) { |
+ *incompleteScanlines = dstHeight - y; |
+ return kIncompleteInput; |
+ } |
+ return kSuccess; |
} |
default: |
SkASSERT(false); |
return kUnimplemented; |
} |
} |
+ |
+uint32_t SkScaledCodec::onGetFillValue(const SkImageInfo& dstInfo) const { |
+ return fScanlineDecoder->getFillValue(dstInfo); |
+} |
+ |
+void* SkScaledCodec::onGetFillDst(void* dst, size_t rowBytes, |
+ uint32_t decodedScanlines) const { |
+ return fScanlineDecoder->getFillDst(dst, rowBytes, decodedScanlines); |
+} |