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; |
} |