Skip to content
This repository was archived by the owner on Feb 25, 2025. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from 11 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions lib/ui/painting/image_generator_apng.cc
Original file line number Diff line number Diff line change
Expand Up @@ -536,6 +536,13 @@ bool APNGImageGenerator::DemuxNextImageInternal() {
SkCodecAnimation::DisposalMethod::kKeep) {
// Mark the required frame as the previous frame in all cases.
image->frame_info->required_frame = images_.size() - 1;
} else if (images_.size() > (first_frame_index_ + 1) &&
images_.back().frame_info->disposal_method ==
SkCodecAnimation::DisposalMethod::kRestorePrevious) {
// Mark the required frame as the last previous frame
// It is not valid if there are 2 or above frames set |disposal_method| to
// |kRestorePrevious|. But it also works in MultiFrameCodec.
image->frame_info->required_frame = images_.size() - 2;
}

// Calling SkCodec::getInfo at least once prior to decoding is mandatory.
Expand Down
17 changes: 11 additions & 6 deletions lib/ui/painting/multi_frame_codec.cc
Original file line number Diff line number Diff line change
Expand Up @@ -116,9 +116,9 @@ MultiFrameCodec::State::GetNextFrameImage(
std::optional<unsigned int> prior_frame_index = std::nullopt;

if (requiredFrameIndex != SkCodec::kNoFrame) {
// We currently assume that frames can only ever depend on the immediately
// previous frame, if any. This means that
// `DisposalMethod::kRestorePrevious` is not supported.
// We are here when the frame said |disposal_method| is
// `DisposalMethod::kKeep` or `DisposalMethod::kRestorePrevious` and
// |requiredFrameIndex| is set to ex-frame or ex-ex-frame.
if (lastRequiredFrame_ == nullptr) {
FML_DLOG(INFO)
<< "Frame " << nextFrameIndex_ << " depends on frame "
Expand Down Expand Up @@ -146,9 +146,14 @@ MultiFrameCodec::State::GetNextFrameImage(
return std::make_pair(nullptr, decode_error);
}

// Hold onto this if we need it to decode future frames.
if (frameInfo.disposal_method == SkCodecAnimation::DisposalMethod::kKeep ||
lastRequiredFrame_) {
// Hold onto this if we need it to decode future frames except that current
// frame's disposal_method is kRestorePrevious.
const bool dont_keep_current_frame =
frameInfo.disposal_method ==
SkCodecAnimation::DisposalMethod::kRestorePrevious;
if (!dont_keep_current_frame &&
(frameInfo.disposal_method == SkCodecAnimation::DisposalMethod::kKeep ||
lastRequiredFrame_)) {
lastRequiredFrame_ = std::make_unique<SkBitmap>(bitmap);
lastRequiredFrameIndex_ = nextFrameIndex_;
}
Expand Down