Index: src/codec/SkScaledCodec.cpp |
diff --git a/src/codec/SkScaledCodec.cpp b/src/codec/SkScaledCodec.cpp |
index 0f0d12993c87f4acc645047d349e06b594cce73e..6db09fb5ceefaea49d0e97ef659d4bc9b8e8e076 100644 |
--- a/src/codec/SkScaledCodec.cpp |
+++ b/src/codec/SkScaledCodec.cpp |
@@ -139,6 +139,28 @@ static bool scaling_supported(const SkImageInfo& dstInfo, const SkImageInfo& src |
return true; |
} |
+inline int SkScaledCodec::GetStartCoord(int sampleFactor) { |
+ return sampleFactor / 2; |
+} |
+ |
+inline int SkScaledCodec::GetDstCoord(int srcCoord, int sampleFactor) { |
+ return srcCoord / sampleFactor; |
+} |
+ |
+bool SkScaledCodec::IsCoordNecessary(int srcCoord, int sampleFactor, int scaledDim) { |
scroggo
2015/08/27 20:14:23
Any idea whether calling all these functions slows
msarett
2015/08/27 21:21:46
We do special case on sample size == 1 by using th
scroggo
2015/08/28 13:28:47
Oh, that's even better!
|
+ // Get the first coordinate that we want to keep |
+ int startCoord = GetStartCoord(sampleFactor); |
+ |
+ // Return false on edge cases |
+ if (srcCoord < startCoord || |
+ SkScaledCodec::GetDstCoord(srcCoord, sampleFactor) >= scaledDim) { |
+ return false; |
+ } |
+ |
+ // Every sampleFactor rows are necessary |
+ return ((srcCoord - startCoord) % sampleFactor) == 0; |
+} |
+ |
// calculates sampleSize in x and y direction |
void SkScaledCodec::ComputeSampleSize(const SkImageInfo& dstInfo, const SkImageInfo& srcInfo, |
int* sampleXPtr, int* sampleYPtr) { |
@@ -198,7 +220,6 @@ SkCodec::Result SkScaledCodec::onGetPixels(const SkImageInfo& requestedInfo, voi |
if (kSuccess == result) { |
// native decode supported |
return fScanlineDecoder->getScanlines(dst, requestedInfo.height(), rowBytes); |
- |
} |
if (kInvalidScale != result) { |
@@ -213,7 +234,7 @@ SkCodec::Result SkScaledCodec::onGetPixels(const SkImageInfo& requestedInfo, voi |
return kInvalidScale; |
} |
// set first sample pixel in y direction |
- int Y0 = sampleY >> 1; |
+ int Y0 = SkScaledCodec::GetStartCoord(sampleY); |
int dstHeight = requestedInfo.height(); |
int srcHeight = fScanlineDecoder->getInfo().height(); |
@@ -227,41 +248,64 @@ SkCodec::Result SkScaledCodec::onGetPixels(const SkImageInfo& requestedInfo, voi |
if (kSuccess != result) { |
return result; |
} |
- |
- const bool requiresPostYSampling = fScanlineDecoder->requiresPostYSampling(); |
- |
- if (requiresPostYSampling) { |
- SkAutoMalloc storage(srcHeight * rowBytes); |
- uint8_t* storagePtr = static_cast<uint8_t*>(storage.get()); |
- result = fScanlineDecoder->getScanlines(storagePtr, srcHeight, rowBytes); |
- if (kSuccess != result) { |
- return result; |
- } |
- storagePtr += Y0 * rowBytes; |
- for (int y = 0; y < dstHeight; y++) { |
- memcpy(dst, storagePtr, rowBytes); |
- storagePtr += sampleY * rowBytes; |
- dst = SkTAddOffset<void>(dst, rowBytes); |
+ |
+ switch(fScanlineDecoder->getScanlineOrder()) { |
+ case SkScanlineDecoder::kTopDown_SkScanlineOrder: { |
+ result = fScanlineDecoder->skipScanlines(Y0); |
+ if (kSuccess != result && kIncompleteInput != result) { |
+ return result; |
+ } |
+ for (int y = 0; y < dstHeight; y++) { |
+ result = fScanlineDecoder->getScanlines(dst, 1, rowBytes); |
+ if (kSuccess != result && kIncompleteInput != result) { |
+ return result; |
+ } |
+ if (y < dstHeight - 1) { |
+ result = fScanlineDecoder->skipScanlines(sampleY - 1); |
+ if (kSuccess != result && kIncompleteInput != result) { |
+ return result; |
+ } |
+ } |
+ dst = SkTAddOffset<void>(dst, rowBytes); |
+ } |
+ return kSuccess; |
} |
- } else { |
- // does not require post y sampling |
- result = fScanlineDecoder->skipScanlines(Y0); |
- if (kSuccess != result) { |
- return result; |
+ case SkScanlineDecoder::kOutOfOrder_SkScanlineOrder: { |
+ for (int y = 0; y < srcHeight; y++) { |
+ int srcY = fScanlineDecoder->getY(); |
+ if (SkScaledCodec::IsCoordNecessary(srcY, sampleY, dstHeight)) { |
+ void* dstPtr = SkTAddOffset<void>(dst, |
+ rowBytes * SkScaledCodec::GetDstCoord(srcY, sampleY)); |
+ result = fScanlineDecoder->getScanlines(dstPtr, 1, rowBytes); |
+ if (kSuccess != result && kIncompleteInput != result) { |
+ return result; |
+ } |
+ } else { |
+ result = fScanlineDecoder->skipScanlines(1); |
+ if (kSuccess != result && kIncompleteInput != result) { |
+ return result; |
+ } |
+ } |
+ } |
+ return kSuccess; |
} |
- for (int y = 0; y < dstHeight; y++) { |
- result = fScanlineDecoder->getScanlines(dst, 1, rowBytes); |
+ 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) { |
return result; |
} |
- if (y < dstHeight - 1) { |
- result = fScanlineDecoder->skipScanlines(sampleY - 1); |
- if (kSuccess != result) { |
- return result; |
- } |
+ storagePtr += Y0 * rowBytes; |
+ for (int y = 0; y < dstHeight; y++) { |
+ memcpy(dst, storagePtr, rowBytes); |
+ storagePtr += sampleY * rowBytes; |
+ dst = SkTAddOffset<void>(dst, rowBytes); |
} |
- dst = SkTAddOffset<void>(dst, rowBytes); |
+ return kSuccess; |
} |
+ default: |
+ SkASSERT(false); |
+ return kUnimplemented; |
} |
- return kSuccess; |
} |