From a78b6dcb82d2f6c940e9c0a6bc14853f846344d0 Mon Sep 17 00:00:00 2001 From: Nigel Tao Date: Sat, 28 Jul 2018 16:48:09 +1000 Subject: Move setAlphaAndRequiredFrame to src/codec The corresponding declaration is already in src/codec/SkFrameHolder.h That code is not solely used by third_party/gif, and in the future, we may have another GIF implementation. Bug: skia: Change-Id: If04cfd4a5b1106f380c89e11c34a8d854ce2b05a Reviewed-on: https://skia-review.googlesource.com/144240 Reviewed-by: Leon Scroggins Commit-Queue: Leon Scroggins --- src/codec/SkCodec.cpp | 101 +++++++++++++++++++++++++++++++++++ third_party/gif/SkGifImageReader.cpp | 100 ---------------------------------- 2 files changed, 101 insertions(+), 100 deletions(-) diff --git a/src/codec/SkCodec.cpp b/src/codec/SkCodec.cpp index 130fcd194f..d534be012f 100644 --- a/src/codec/SkCodec.cpp +++ b/src/codec/SkCodec.cpp @@ -734,3 +734,104 @@ const char* SkCodec::ResultToString(Result result) { return "bogus result value"; } } + +static SkIRect frame_rect_on_screen(SkIRect frameRect, + const SkIRect& screenRect) { + if (!frameRect.intersect(screenRect)) { + return SkIRect::MakeEmpty(); + } + + return frameRect; +} + +static bool independent(const SkFrame& frame) { + return frame.getRequiredFrame() == SkCodec::kNone; +} + +static bool restore_bg(const SkFrame& frame) { + return frame.getDisposalMethod() == SkCodecAnimation::DisposalMethod::kRestoreBGColor; +} + +void SkFrameHolder::setAlphaAndRequiredFrame(SkFrame* frame) { + const bool reportsAlpha = frame->reportedAlpha() != SkEncodedInfo::kOpaque_Alpha; + const auto screenRect = SkIRect::MakeWH(fScreenWidth, fScreenHeight); + const auto frameRect = frame_rect_on_screen(frame->frameRect(), screenRect); + + const int i = frame->frameId(); + if (0 == i) { + frame->setHasAlpha(reportsAlpha || frameRect != screenRect); + frame->setRequiredFrame(SkCodec::kNone); + return; + } + + + const bool blendWithPrevFrame = frame->getBlend() == SkCodecAnimation::Blend::kPriorFrame; + if ((!reportsAlpha || !blendWithPrevFrame) && frameRect == screenRect) { + frame->setHasAlpha(reportsAlpha); + frame->setRequiredFrame(SkCodec::kNone); + return; + } + + const SkFrame* prevFrame = this->getFrame(i-1); + while (prevFrame->getDisposalMethod() == SkCodecAnimation::DisposalMethod::kRestorePrevious) { + const int prevId = prevFrame->frameId(); + if (0 == prevId) { + frame->setHasAlpha(true); + frame->setRequiredFrame(SkCodec::kNone); + return; + } + + prevFrame = this->getFrame(prevId - 1); + } + + const bool clearPrevFrame = restore_bg(*prevFrame); + auto prevFrameRect = frame_rect_on_screen(prevFrame->frameRect(), screenRect); + + if (clearPrevFrame) { + if (prevFrameRect == screenRect || independent(*prevFrame)) { + frame->setHasAlpha(true); + frame->setRequiredFrame(SkCodec::kNone); + return; + } + } + + if (reportsAlpha && blendWithPrevFrame) { + // Note: We could be more aggressive here. If prevFrame clears + // to background color and covers its required frame (and that + // frame is independent), prevFrame could be marked independent. + // Would this extra complexity be worth it? + frame->setRequiredFrame(prevFrame->frameId()); + frame->setHasAlpha(prevFrame->hasAlpha() || clearPrevFrame); + return; + } + + while (frameRect.contains(prevFrameRect)) { + const int prevRequiredFrame = prevFrame->getRequiredFrame(); + if (prevRequiredFrame == SkCodec::kNone) { + frame->setRequiredFrame(SkCodec::kNone); + frame->setHasAlpha(true); + return; + } + + prevFrame = this->getFrame(prevRequiredFrame); + prevFrameRect = frame_rect_on_screen(prevFrame->frameRect(), screenRect); + } + + if (restore_bg(*prevFrame)) { + frame->setHasAlpha(true); + if (prevFrameRect == screenRect || independent(*prevFrame)) { + frame->setRequiredFrame(SkCodec::kNone); + } else { + // Note: As above, frame could still be independent, e.g. if + // prevFrame covers its required frame and that frame is + // independent. + frame->setRequiredFrame(prevFrame->frameId()); + } + return; + } + + SkASSERT(prevFrame->getDisposalMethod() == SkCodecAnimation::DisposalMethod::kKeep); + frame->setRequiredFrame(prevFrame->frameId()); + frame->setHasAlpha(prevFrame->hasAlpha() || (reportsAlpha && !blendWithPrevFrame)); +} + diff --git a/third_party/gif/SkGifImageReader.cpp b/third_party/gif/SkGifImageReader.cpp index a04f8e11d0..c62b788e82 100644 --- a/third_party/gif/SkGifImageReader.cpp +++ b/third_party/gif/SkGifImageReader.cpp @@ -862,23 +862,6 @@ void SkGifImageReader::addFrameIfNecessary() } } -static SkIRect frame_rect_on_screen(SkIRect frameRect, - const SkIRect& screenRect) { - if (!frameRect.intersect(screenRect)) { - return SkIRect::MakeEmpty(); - } - - return frameRect; -} - -static bool independent(const SkFrame& frame) { - return frame.getRequiredFrame() == SkCodec::kNone; -} - -static bool restore_bg(const SkFrame& frame) { - return frame.getDisposalMethod() == SkCodecAnimation::DisposalMethod::kRestoreBGColor; -} - SkEncodedInfo::Alpha SkGIFFrameContext::onReportedAlpha() const { // Note: We could correct these after decoding - i.e. some frames may turn out to be // independent and opaque if they do not use the transparent pixel, but that would require @@ -887,89 +870,6 @@ SkEncodedInfo::Alpha SkGIFFrameContext::onReportedAlpha() const { : SkEncodedInfo::kOpaque_Alpha; } -void SkFrameHolder::setAlphaAndRequiredFrame(SkFrame* frame) { - const bool reportsAlpha = frame->reportedAlpha() != SkEncodedInfo::kOpaque_Alpha; - const auto screenRect = SkIRect::MakeWH(fScreenWidth, fScreenHeight); - const auto frameRect = frame_rect_on_screen(frame->frameRect(), screenRect); - - const int i = frame->frameId(); - if (0 == i) { - frame->setHasAlpha(reportsAlpha || frameRect != screenRect); - frame->setRequiredFrame(SkCodec::kNone); - return; - } - - - const bool blendWithPrevFrame = frame->getBlend() == SkCodecAnimation::Blend::kPriorFrame; - if ((!reportsAlpha || !blendWithPrevFrame) && frameRect == screenRect) { - frame->setHasAlpha(reportsAlpha); - frame->setRequiredFrame(SkCodec::kNone); - return; - } - - const SkFrame* prevFrame = this->getFrame(i-1); - while (prevFrame->getDisposalMethod() == SkCodecAnimation::DisposalMethod::kRestorePrevious) { - const int prevId = prevFrame->frameId(); - if (0 == prevId) { - frame->setHasAlpha(true); - frame->setRequiredFrame(SkCodec::kNone); - return; - } - - prevFrame = this->getFrame(prevId - 1); - } - - const bool clearPrevFrame = restore_bg(*prevFrame); - auto prevFrameRect = frame_rect_on_screen(prevFrame->frameRect(), screenRect); - - if (clearPrevFrame) { - if (prevFrameRect == screenRect || independent(*prevFrame)) { - frame->setHasAlpha(true); - frame->setRequiredFrame(SkCodec::kNone); - return; - } - } - - if (reportsAlpha && blendWithPrevFrame) { - // Note: We could be more aggressive here. If prevFrame clears - // to background color and covers its required frame (and that - // frame is independent), prevFrame could be marked independent. - // Would this extra complexity be worth it? - frame->setRequiredFrame(prevFrame->frameId()); - frame->setHasAlpha(prevFrame->hasAlpha() || clearPrevFrame); - return; - } - - while (frameRect.contains(prevFrameRect)) { - const int prevRequiredFrame = prevFrame->getRequiredFrame(); - if (prevRequiredFrame == SkCodec::kNone) { - frame->setRequiredFrame(SkCodec::kNone); - frame->setHasAlpha(true); - return; - } - - prevFrame = this->getFrame(prevRequiredFrame); - prevFrameRect = frame_rect_on_screen(prevFrame->frameRect(), screenRect); - } - - if (restore_bg(*prevFrame)) { - frame->setHasAlpha(true); - if (prevFrameRect == screenRect || independent(*prevFrame)) { - frame->setRequiredFrame(SkCodec::kNone); - } else { - // Note: As above, frame could still be independent, e.g. if - // prevFrame covers its required frame and that frame is - // independent. - frame->setRequiredFrame(prevFrame->frameId()); - } - return; - } - - SkASSERT(prevFrame->getDisposalMethod() == SkCodecAnimation::DisposalMethod::kKeep); - frame->setRequiredFrame(prevFrame->frameId()); - frame->setHasAlpha(prevFrame->hasAlpha() || (reportsAlpha && !blendWithPrevFrame)); -} - // FIXME: Move this method to close to doLZW(). bool SkGIFLZWContext::prepareToDecode() { -- cgit v1.2.3