Chromium Code Reviews| Index: src/codec/SkCodec.cpp |
| diff --git a/src/codec/SkCodec.cpp b/src/codec/SkCodec.cpp |
| index 56f6a8de9e4c6f6d9c72abef44d1402d5586828c..00fcb9656e75fd273632fcefc146307714681de3 100644 |
| --- a/src/codec/SkCodec.cpp |
| +++ b/src/codec/SkCodec.cpp |
| @@ -111,6 +111,94 @@ bool SkCodec::rewindIfNeeded() { |
| return this->onRewind(); |
| } |
| +bool SkCodec::getScaledSubsetDimensions(float desiredScale, const Options& options) const { |
| + // Negative and zero scales are errors. |
| + SkASSERT(desiredScale > 0.0f); |
| + if (desiredScale <= 0.0f) { |
| + return false; |
| + } |
| + |
| + // Upscaling is not supported. We will suggest a full decode if |
| + // upscaling is requested. |
| + if (desiredScale >= 1.0f) { |
| + desiredScale = 1.0f; |
| + } |
| + |
| + // If the client is not requesting a subset decode, |
| + // getScaledDimensions() should be used. |
| + if (!options.fSubset || !options.fScaledDimensions || !options.fScaledSubset) { |
| + return false; |
| + } |
| + |
| + if (!is_valid_subset(*options.fSubset, this->getInfo().dimensions())) { |
| + return false; |
| + } |
| + |
| + return this->onGetScaledSubsetDimensions(desiredScale, options); |
| +} |
| + |
| +bool SkCodec::subsetSupported(const SkIRect& subset, bool isScanlineDecode) { |
| + if (!is_valid_subset(subset, this->getInfo().dimensions())) { |
|
scroggo
2015/10/12 20:47:07
nit: fInfo.dimensions()
No need to call the acces
|
| + return false; |
| + } |
| + |
| + return this->onSubsetSupported(subset, isScanlineDecode); |
| +} |
| + |
| +bool SkCodec::onSubsetSupported(const SkIRect& subset, bool isScanlineDecode) { |
| + if (!isScanlineDecode) { |
| + return false; |
| + } |
| + |
| + // We support subsetting in the x-dimension for the scanline decoder. |
| + // Subsetting in the y-dimension can be accomplished using skipScanlines(). |
| + return subset.top() == 0 && subset.height() == this->getInfo().height(); |
| +} |
| + |
| +bool SkCodec::scaledSubsetSupported(const SkISize& dstSize, const Options& options, |
| + bool isScanlineDecode) { |
| + SkIRect* subset = options.fSubset; |
| + |
| + // If there is no subsetting, we simply check if we can scale to dstSize |
| + if (!subset) { |
| + return this->dimensionsSupported(dstSize); |
| + } |
| + |
| + SkISize* scaledDimensions = options.fScaledDimensions; |
| + SkIRect* scaledSubset = options.fScaledSubset; |
| + if (!scaledDimensions && !scaledSubset) { |
| + // If there is no scaling, check if we support the subset requested |
| + return this->subsetSupported(*subset, isScanlineDecode); |
| + } |
| + |
| + if (!scaledDimensions || !scaledSubset) { |
| + // Both scaledDimensions and scaledSubset must be non-NULL to perform |
| + // a scaled subset decode. |
| + return false; |
| + } |
| + |
| + if (!is_valid_subset(*scaledSubset, *scaledDimensions)) { |
| + return false; |
| + } |
| + |
| + return this->onScaledSubsetSupported(options, isScanlineDecode); |
| +} |
| + |
| +bool SkCodec::onScaledSubsetSupported(const Options& options, bool isScanlineDecode) { |
| + if (!isScanlineDecode) { |
| + return false; |
| + } |
| + |
| + if (!this->dimensionsSupported(*options.fScaledDimensions)) { |
| + return false; |
| + } |
| + |
| + // We support subsetting in the x-dimension for the scanline decoder. |
| + // Subsetting in the y-dimension can be accomplished using skipScanlines(). |
| + return options.fSubset->top() == 0 && |
| + options.fSubset->height() == options.fScaledDimensions->height(); |
| +} |
| + |
| SkCodec::Result SkCodec::getPixels(const SkImageInfo& info, void* pixels, size_t rowBytes, |
| const Options* options, SkPMColor ctable[], int* ctableCount) { |
| if (kUnknown_SkColorType == info.colorType()) { |
| @@ -152,18 +240,9 @@ SkCodec::Result SkCodec::getPixels(const SkImageInfo& info, void* pixels, size_t |
| Options optsStorage; |
| if (nullptr == options) { |
| options = &optsStorage; |
| - } else if (options->fSubset) { |
| - SkIRect subset(*options->fSubset); |
| - if (!this->onGetValidSubset(&subset) || subset != *options->fSubset) { |
| - // FIXME: How to differentiate between not supporting subset at all |
| - // and not supporting this particular subset? |
| - return kUnimplemented; |
| - } |
| } |
| - // FIXME: Support subsets somehow? Note that this works for SkWebpCodec |
| - // because it supports arbitrary scaling/subset combinations. |
| - if (!this->dimensionsSupported(info.dimensions())) { |
| + if (!this->scaledSubsetSupported(info.dimensions(), *options, false)) { |
| return kInvalidScale; |
| } |
| @@ -219,21 +298,9 @@ SkCodec::Result SkCodec::startScanlineDecode(const SkImageInfo& dstInfo, |
| Options optsStorage; |
| if (nullptr == options) { |
| options = &optsStorage; |
| - } else if (options->fSubset) { |
| - SkIRect size = SkIRect::MakeSize(dstInfo.dimensions()); |
| - if (!size.contains(*options->fSubset)) { |
| - return kInvalidInput; |
| - } |
| - |
| - // We only support subsetting in the x-dimension for scanline decoder. |
| - // Subsetting in the y-dimension can be accomplished using skipScanlines(). |
| - if (options->fSubset->top() != 0 || options->fSubset->height() != dstInfo.height()) { |
| - return kInvalidInput; |
| - } |
| } |
| - // FIXME: Support subsets somehow? |
| - if (!this->dimensionsSupported(dstInfo.dimensions())) { |
| + if (!this->scaledSubsetSupported(dstInfo.dimensions(), *options, true)) { |
| return kInvalidScale; |
| } |