Chromium Code Reviews| 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; |
| } |