diff options
author | 2023-04-05 17:33:00 -0400 | |
---|---|---|
committer | 2023-04-06 14:51:29 -0400 | |
commit | 2be87bb707e2c6d75f668c4aff6697b85fbf5b15 (patch) | |
tree | 4f005875c4f3feeba74ca9e3deb3331b0410f1cf | |
parent | 7220f21ddd422e5b4d186f060bfd54445b4e7e77 (diff) |
Follow Firefox & Chrome GIF behavior
If a GIF animation has a duration <= 10ms then bump it to
100ms. This isn't correct behavior, but it's one that browsers
have been doing for so long that gifs are now authored to rely
on this behavior
Fixes: 192511662
Test: app in bug
Change-Id: Ia07f12aa15595193ed9e56910929dc6da9754128
-rw-r--r-- | libs/hwui/hwui/AnimatedImageDrawable.cpp | 33 | ||||
-rw-r--r-- | libs/hwui/hwui/AnimatedImageDrawable.h | 17 | ||||
-rw-r--r-- | libs/hwui/jni/AnimatedImageDrawable.cpp | 6 |
3 files changed, 39 insertions, 17 deletions
diff --git a/libs/hwui/hwui/AnimatedImageDrawable.cpp b/libs/hwui/hwui/AnimatedImageDrawable.cpp index d08bc5c583c2..8049dc946c9e 100644 --- a/libs/hwui/hwui/AnimatedImageDrawable.cpp +++ b/libs/hwui/hwui/AnimatedImageDrawable.cpp @@ -29,9 +29,10 @@ namespace android { -AnimatedImageDrawable::AnimatedImageDrawable(sk_sp<SkAnimatedImage> animatedImage, size_t bytesUsed) - : mSkAnimatedImage(std::move(animatedImage)), mBytesUsed(bytesUsed) { - mTimeToShowNextSnapshot = ms2ns(mSkAnimatedImage->currentFrameDuration()); +AnimatedImageDrawable::AnimatedImageDrawable(sk_sp<SkAnimatedImage> animatedImage, size_t bytesUsed, + SkEncodedImageFormat format) + : mSkAnimatedImage(std::move(animatedImage)), mBytesUsed(bytesUsed), mFormat(format) { + mTimeToShowNextSnapshot = ms2ns(currentFrameDuration()); setStagingBounds(mSkAnimatedImage->getBounds()); } @@ -92,7 +93,7 @@ bool AnimatedImageDrawable::isDirty(nsecs_t* outDelay) { // directly from mSkAnimatedImage. lock.unlock(); std::unique_lock imageLock{mImageLock}; - *outDelay = ms2ns(mSkAnimatedImage->currentFrameDuration()); + *outDelay = ms2ns(currentFrameDuration()); return true; } else { // The next snapshot has not yet been decoded, but we've already passed @@ -109,7 +110,7 @@ AnimatedImageDrawable::Snapshot AnimatedImageDrawable::decodeNextFrame() { Snapshot snap; { std::unique_lock lock{mImageLock}; - snap.mDurationMS = mSkAnimatedImage->decodeNextFrame(); + snap.mDurationMS = adjustFrameDuration(mSkAnimatedImage->decodeNextFrame()); snap.mPic.reset(mSkAnimatedImage->newPictureSnapshot()); } @@ -123,7 +124,7 @@ AnimatedImageDrawable::Snapshot AnimatedImageDrawable::reset() { std::unique_lock lock{mImageLock}; mSkAnimatedImage->reset(); snap.mPic.reset(mSkAnimatedImage->newPictureSnapshot()); - snap.mDurationMS = mSkAnimatedImage->currentFrameDuration(); + snap.mDurationMS = currentFrameDuration(); } return snap; @@ -274,7 +275,7 @@ int AnimatedImageDrawable::drawStaging(SkCanvas* canvas) { { std::unique_lock lock{mImageLock}; mSkAnimatedImage->reset(); - durationMS = mSkAnimatedImage->currentFrameDuration(); + durationMS = currentFrameDuration(); } { std::unique_lock lock{mSwapLock}; @@ -306,7 +307,7 @@ int AnimatedImageDrawable::drawStaging(SkCanvas* canvas) { { std::unique_lock lock{mImageLock}; if (update) { - durationMS = mSkAnimatedImage->decodeNextFrame(); + durationMS = adjustFrameDuration(mSkAnimatedImage->decodeNextFrame()); } canvas->drawDrawable(mSkAnimatedImage.get()); @@ -336,4 +337,20 @@ SkRect AnimatedImageDrawable::onGetBounds() { return SkRectMakeLargest(); } +int AnimatedImageDrawable::adjustFrameDuration(int durationMs) { + if (durationMs == SkAnimatedImage::kFinished) { + return SkAnimatedImage::kFinished; + } + + if (mFormat == SkEncodedImageFormat::kGIF) { + // Match Chrome & Firefox behavior that gifs with a duration <= 10ms is bumped to 100ms + return durationMs <= 10 ? 100 : durationMs; + } + return durationMs; +} + +int AnimatedImageDrawable::currentFrameDuration() { + return adjustFrameDuration(mSkAnimatedImage->currentFrameDuration()); +} + } // namespace android diff --git a/libs/hwui/hwui/AnimatedImageDrawable.h b/libs/hwui/hwui/AnimatedImageDrawable.h index 8ca3c7e125f1..1e965abc82b5 100644 --- a/libs/hwui/hwui/AnimatedImageDrawable.h +++ b/libs/hwui/hwui/AnimatedImageDrawable.h @@ -16,16 +16,16 @@ #pragma once -#include <cutils/compiler.h> -#include <utils/Macros.h> -#include <utils/RefBase.h> -#include <utils/Timers.h> - #include <SkAnimatedImage.h> #include <SkCanvas.h> #include <SkColorFilter.h> #include <SkDrawable.h> +#include <SkEncodedImageFormat.h> #include <SkPicture.h> +#include <cutils/compiler.h> +#include <utils/Macros.h> +#include <utils/RefBase.h> +#include <utils/Timers.h> #include <future> #include <mutex> @@ -48,7 +48,8 @@ class AnimatedImageDrawable : public SkDrawable { public: // bytesUsed includes the approximate sizes of the SkAnimatedImage and the SkPictures in the // Snapshots. - AnimatedImageDrawable(sk_sp<SkAnimatedImage> animatedImage, size_t bytesUsed); + AnimatedImageDrawable(sk_sp<SkAnimatedImage> animatedImage, size_t bytesUsed, + SkEncodedImageFormat format); /** * This updates the internal time and returns true if the image needs @@ -115,6 +116,7 @@ protected: private: sk_sp<SkAnimatedImage> mSkAnimatedImage; const size_t mBytesUsed; + const SkEncodedImageFormat mFormat; bool mRunning = false; bool mStarting = false; @@ -157,6 +159,9 @@ private: Properties mProperties; std::unique_ptr<OnAnimationEndListener> mEndListener; + + int adjustFrameDuration(int); + int currentFrameDuration(); }; } // namespace android diff --git a/libs/hwui/jni/AnimatedImageDrawable.cpp b/libs/hwui/jni/AnimatedImageDrawable.cpp index 373e893b9a25..a7f5aa83e624 100644 --- a/libs/hwui/jni/AnimatedImageDrawable.cpp +++ b/libs/hwui/jni/AnimatedImageDrawable.cpp @@ -97,7 +97,7 @@ static jlong AnimatedImageDrawable_nCreate(JNIEnv* env, jobject /*clazz*/, bytesUsed += picture->approximateBytesUsed(); } - + SkEncodedImageFormat format = imageDecoder->mCodec->getEncodedFormat(); sk_sp<SkAnimatedImage> animatedImg = SkAnimatedImage::Make(std::move(imageDecoder->mCodec), info, subset, std::move(picture)); @@ -108,8 +108,8 @@ static jlong AnimatedImageDrawable_nCreate(JNIEnv* env, jobject /*clazz*/, bytesUsed += sizeof(animatedImg.get()); - sk_sp<AnimatedImageDrawable> drawable(new AnimatedImageDrawable(std::move(animatedImg), - bytesUsed)); + sk_sp<AnimatedImageDrawable> drawable( + new AnimatedImageDrawable(std::move(animatedImg), bytesUsed, format)); return reinterpret_cast<jlong>(drawable.release()); } |