| Index: src/codec/SkWebpCodec.cpp
|
| diff --git a/src/codec/SkWebpCodec.cpp b/src/codec/SkWebpCodec.cpp
|
| index 32a8b78b14f2487e69305c6d90c89533319435bb..fea557d21ed9ddb8e9a86ff475a2c996a8fa749d 100644
|
| --- a/src/codec/SkWebpCodec.cpp
|
| +++ b/src/codec/SkWebpCodec.cpp
|
| @@ -125,8 +125,26 @@ static WEBP_CSP_MODE webp_decode_mode(SkColorType ct, bool premultiply) {
|
| // is arbitrary.
|
| static const size_t BUFFER_SIZE = 4096;
|
|
|
| +bool SkWebpCodec::onGetValidSubset(SkIRect* desiredSubset) const {
|
| + if (!desiredSubset) {
|
| + return false;
|
| + }
|
| +
|
| + SkIRect bounds = SkIRect::MakeSize(this->getInfo().dimensions());
|
| + if (!desiredSubset->intersect(bounds)) {
|
| + return false;
|
| + }
|
| +
|
| + // As stated below, libwebp snaps to even left and top. Make sure top and left are even, so we
|
| + // decode this exact subset.
|
| + // Leave right and bottom unmodified, so we suggest a slightly larger subset than requested.
|
| + desiredSubset->fLeft = (desiredSubset->fLeft >> 1) << 1;
|
| + desiredSubset->fTop = (desiredSubset->fTop >> 1) << 1;
|
| + return true;
|
| +}
|
| +
|
| SkCodec::Result SkWebpCodec::onGetPixels(const SkImageInfo& dstInfo, void* dst, size_t rowBytes,
|
| - const Options&, SkPMColor*, int*) {
|
| + const Options& options, SkPMColor*, int*) {
|
| switch (this->rewindIfNeeded()) {
|
| case kCouldNotRewind_RewindState:
|
| return kCouldNotRewind;
|
| @@ -153,12 +171,48 @@ SkCodec::Result SkWebpCodec::onGetPixels(const SkImageInfo& dstInfo, void* dst,
|
| // Free any memory associated with the buffer. Must be called last, so we declare it first.
|
| SkAutoTCallVProc<WebPDecBuffer, WebPFreeDecBuffer> autoFree(&(config.output));
|
|
|
| - SkISize dimensions = dstInfo.dimensions();
|
| - if (this->getInfo().dimensions() != dimensions) {
|
| + SkIRect bounds = SkIRect::MakeSize(this->getInfo().dimensions());
|
| + if (options.fSubset) {
|
| + // Caller is requesting a subset.
|
| + if (!bounds.contains(*options.fSubset)) {
|
| + // The subset is out of bounds.
|
| + return kInvalidParameters;
|
| + }
|
| +
|
| + bounds = *options.fSubset;
|
| +
|
| + // This is tricky. libwebp snaps the top and left to even values. We could let libwebp
|
| + // do the snap, and return a subset which is a different one than requested. The problem
|
| + // with that approach is that the caller may try to stitch subsets together, and if we
|
| + // returned different subsets than requested, there would be artifacts at the boundaries.
|
| + // Instead, we report that we cannot support odd values for top and left..
|
| + if (!SkIsAlign2(bounds.fLeft) || !SkIsAlign2(bounds.fTop)) {
|
| + return kInvalidParameters;
|
| + }
|
| +
|
| +#ifdef SK_DEBUG
|
| + {
|
| + // Make a copy, since getValidSubset can change its input.
|
| + SkIRect subset(bounds);
|
| + // That said, getValidSubset should *not* change its input, in this case; otherwise
|
| + // getValidSubset does not match the actual subsets we can do.
|
| + SkASSERT(this->getValidSubset(&subset) && subset == bounds);
|
| + }
|
| +#endif
|
| +
|
| + config.options.use_cropping = 1;
|
| + config.options.crop_left = bounds.fLeft;
|
| + config.options.crop_top = bounds.fTop;
|
| + config.options.crop_width = bounds.width();
|
| + config.options.crop_height = bounds.height();
|
| + }
|
| +
|
| + SkISize dstDimensions = dstInfo.dimensions();
|
| + if (bounds.size() != dstDimensions) {
|
| // Caller is requesting scaling.
|
| config.options.use_scaling = 1;
|
| - config.options.scaled_width = dimensions.width();
|
| - config.options.scaled_height = dimensions.height();
|
| + config.options.scaled_width = dstDimensions.width();
|
| + config.options.scaled_height = dstDimensions.height();
|
| }
|
|
|
| config.output.colorspace = webp_decode_mode(dstInfo.colorType(),
|
|
|