diff options
Diffstat (limited to 'src/codec')
-rw-r--r-- | src/codec/SkCodec.cpp | 63 |
1 files changed, 34 insertions, 29 deletions
diff --git a/src/codec/SkCodec.cpp b/src/codec/SkCodec.cpp index bf12ad2625..d9992c0cd9 100644 --- a/src/codec/SkCodec.cpp +++ b/src/codec/SkCodec.cpp @@ -208,16 +208,37 @@ bool SkCodec::rewindIfNeeded() { return this->onRewind(); } -static void zero_rect(const SkImageInfo& dstInfo, void* pixels, size_t rowBytes, - SkIRect frameRect) { - if (!frameRect.intersect(dstInfo.bounds())) { - return; +bool zero_rect(const SkImageInfo& dstInfo, void* pixels, size_t rowBytes, + SkISize srcDimensions, SkIRect prevRect) { + const auto dimensions = dstInfo.dimensions(); + if (dimensions != srcDimensions) { + SkRect src = SkRect::Make(srcDimensions); + SkRect dst = SkRect::Make(dimensions); + SkMatrix map = SkMatrix::MakeRectToRect(src, dst, SkMatrix::kCenter_ScaleToFit); + SkRect asRect = SkRect::Make(prevRect); + if (!map.mapRect(&asRect)) { + return false; + } + asRect.roundIn(&prevRect); + if (prevRect.isEmpty()) { + // Down-scaling shrank the empty portion to nothing, + // so nothing to zero. + return true; + } } - const auto info = dstInfo.makeWH(frameRect.width(), frameRect.height()); + + if (!prevRect.intersect(dstInfo.bounds())) { + SkCodecPrintf("rectangles do not intersect!"); + SkASSERT(false); + return true; + } + + const SkImageInfo info = dstInfo.makeWH(prevRect.width(), prevRect.height()); const size_t bpp = dstInfo.bytesPerPixel(); - const size_t offset = frameRect.x() * bpp + frameRect.y() * rowBytes; - auto* eraseDst = SkTAddOffset<void>(pixels, offset); + const size_t offset = prevRect.x() * bpp + prevRect.y() * rowBytes; + void* eraseDst = SkTAddOffset<void>(pixels, offset); SkSampler::Fill(info, eraseDst, rowBytes, 0, SkCodec::kNo_ZeroInitialized); + return true; } SkCodec::Result SkCodec::handleFrameIndex(const SkImageInfo& info, void* pixels, size_t rowBytes, @@ -276,28 +297,9 @@ SkCodec::Result SkCodec::handleFrameIndex(const SkImageInfo& info, void* pixels, // need to clear, since it must be covered by the desired frame. if (options.fPriorFrame == requiredFrame) { SkIRect prevRect = prevFrame->frameRect(); - if (info.dimensions() != fSrcInfo.dimensions()) { - auto src = SkRect::Make(fSrcInfo.dimensions()); - auto dst = SkRect::Make(info.dimensions()); - SkMatrix map = SkMatrix::MakeRectToRect(src, dst, - SkMatrix::kCenter_ScaleToFit); - SkRect asRect = SkRect::Make(prevRect); - if (!map.mapRect(&asRect)) { - return kInternalError; - } - asRect.roundIn(&prevRect); - if (prevRect.isEmpty()) { - // Down-scaling shrank the empty portion to nothing, - // so nothing to zero. - break; - } - if (!prevRect.intersect(SkIRect::MakeSize(info.dimensions()))) { - SkCodecPrintf("rectangles do not intersect!"); - SkASSERT(false); - break; - } + if (!zero_rect(info, pixels, rowBytes, fSrcInfo.dimensions(), prevRect)) { + return kInternalError; } - zero_rect(info, pixels, rowBytes, prevRect); } break; default: @@ -314,7 +316,10 @@ SkCodec::Result SkCodec::handleFrameIndex(const SkImageInfo& info, void* pixels, const auto* prevFrame = frameHolder->getFrame(requiredFrame); const auto disposalMethod = prevFrame->getDisposalMethod(); if (disposalMethod == SkCodecAnimation::DisposalMethod::kRestoreBGColor) { - zero_rect(info, pixels, rowBytes, prevFrame->frameRect()); + auto prevRect = prevFrame->frameRect(); + if (!zero_rect(info, pixels, rowBytes, fSrcInfo.dimensions(), prevRect)) { + return kInternalError; + } } } } |