diff options
author | 2024-10-14 19:46:40 +0000 | |
---|---|---|
committer | 2024-10-30 19:56:50 +0000 | |
commit | ae7c8354ab5e3c590e0b92c7809f2a50b3fe67e3 (patch) | |
tree | c4cb87e887f0e76e828f39a80dba0bc80fad1b4e | |
parent | 6b37ca81979168bf46421ba437ac4a5dab2cf1c1 (diff) |
Override the SetFilterBitmap and IsFilterBitmap functions for AnimatedImageDrawable API
This change in Skia (https://skia-review.googlesource.com/c/skia/+/909816) makes it so that the default sampling method for animated image drawables is linear sampling. This CL implements these drawable API's (https://developer.android.com/reference/android/graphics/drawable/Drawable#setFilterBitmap(boolean)) so that the user can choose to use nearest neighbor sampling if they want pixel perfect scaling.
Bug: 370523334
Bug: 355264141
Change-Id: I36b7154016e40f3c1f34fd98e347de9a980d0ad9
Test: atest CtsGraphicsTestCases:android.graphics.drawable.cts.AnimatedImageDrawableTest#testSetFilterBitmap -- --template:map preparers=template/preparers/feature-flags --flag-value core_graphics/com.android.graphics.hwui.flags.animated_image_drawable_filter_bitmap=true
Flag: com.android.graphics.hwui.flags.animated_image_drawable_filter_bitmap
-rw-r--r-- | graphics/java/android/graphics/drawable/AnimatedImageDrawable.java | 34 | ||||
-rw-r--r-- | libs/hwui/aconfig/hwui_flags.aconfig | 8 | ||||
-rw-r--r-- | libs/hwui/hwui/AnimatedImageDrawable.cpp | 22 | ||||
-rw-r--r-- | libs/hwui/hwui/AnimatedImageDrawable.h | 5 | ||||
-rw-r--r-- | libs/hwui/jni/AnimatedImageDrawable.cpp | 14 |
5 files changed, 83 insertions, 0 deletions
diff --git a/graphics/java/android/graphics/drawable/AnimatedImageDrawable.java b/graphics/java/android/graphics/drawable/AnimatedImageDrawable.java index 82b3f6875d67..71baed8219d5 100644 --- a/graphics/java/android/graphics/drawable/AnimatedImageDrawable.java +++ b/graphics/java/android/graphics/drawable/AnimatedImageDrawable.java @@ -37,6 +37,7 @@ import android.util.DisplayMetrics; import android.util.TypedValue; import android.view.View; +import com.android.graphics.hwui.flags.Flags; import com.android.internal.R; import dalvik.annotation.optimization.FastNative; @@ -525,6 +526,35 @@ public class AnimatedImageDrawable extends Drawable implements Animatable2 { } } + @Override + public void setFilterBitmap(boolean filterBitmap) { + if (!Flags.animatedImageDrawableFilterBitmap()) { + super.setFilterBitmap(filterBitmap); + return; + } + if (mState.mNativePtr == 0) { + throw new IllegalStateException( + "called setFilterBitmap on empty AnimatedImageDrawable" + ); + } + if (nSetFilterBitmap(mState.mNativePtr, filterBitmap)) { + invalidateSelf(); + } + } + + @Override + public boolean isFilterBitmap() { + if (!Flags.animatedImageDrawableFilterBitmap()) { + return super.isFilterBitmap(); + } + if (mState.mNativePtr == 0) { + throw new IllegalStateException( + "called isFilterBitmap on empty AnimatedImageDrawable" + ); + } + return nGetFilterBitmap(mState.mNativePtr); + } + private void postOnAnimationStart() { if (mAnimationCallbacks == null) { return; @@ -618,4 +648,8 @@ public class AnimatedImageDrawable extends Drawable implements Animatable2 { private static native void nSetMirrored(long nativePtr, boolean mirror); @FastNative private static native void nSetBounds(long nativePtr, Rect rect); + @FastNative + private static native boolean nSetFilterBitmap(long nativePtr, boolean filterBitmap); + @FastNative + private static native boolean nGetFilterBitmap(long nativePtr); } diff --git a/libs/hwui/aconfig/hwui_flags.aconfig b/libs/hwui/aconfig/hwui_flags.aconfig index f2559677c325..5ad788c67816 100644 --- a/libs/hwui/aconfig/hwui_flags.aconfig +++ b/libs/hwui/aconfig/hwui_flags.aconfig @@ -146,3 +146,11 @@ flag { description: "Whether to have more information in ashmem filenames for bitmaps" bug: "369619160" } + +flag { + name: "animated_image_drawable_filter_bitmap" + is_exported: true + namespace: "core_graphics" + description: "API's that enable animated image drawables to use nearest sampling when scaling." + bug: "370523334" +} diff --git a/libs/hwui/hwui/AnimatedImageDrawable.cpp b/libs/hwui/hwui/AnimatedImageDrawable.cpp index 69613c7d17cb..5e379aad9326 100644 --- a/libs/hwui/hwui/AnimatedImageDrawable.cpp +++ b/libs/hwui/hwui/AnimatedImageDrawable.cpp @@ -347,4 +347,26 @@ int AnimatedImageDrawable::currentFrameDuration() { return adjustFrameDuration(mSkAnimatedImage->currentFrameDuration()); } +bool AnimatedImageDrawable::getFilterBitmap() const { + const SkFilterMode kFilterBitmap = mSkAnimatedImage->getFilterMode(); + if (kFilterBitmap == SkFilterMode::kLinear) { + return true; + } + return false; +} + +bool AnimatedImageDrawable::setFilterBitmap(bool filterBitmap) { + if (filterBitmap) { + if (mSkAnimatedImage->getFilterMode() == SkFilterMode::kLinear) { + return false; + } + mSkAnimatedImage->setFilterMode(SkFilterMode::kLinear); + } else { + if (mSkAnimatedImage->getFilterMode() == SkFilterMode::kNearest) { + return false; + } + mSkAnimatedImage->setFilterMode(SkFilterMode::kNearest); + } + return true; +} } // namespace android diff --git a/libs/hwui/hwui/AnimatedImageDrawable.h b/libs/hwui/hwui/AnimatedImageDrawable.h index 1e965abc82b5..22123249b7d6 100644 --- a/libs/hwui/hwui/AnimatedImageDrawable.h +++ b/libs/hwui/hwui/AnimatedImageDrawable.h @@ -87,6 +87,11 @@ public: bool isRunning(); int getRepetitionCount() const { return mSkAnimatedImage->getRepetitionCount(); } void setRepetitionCount(int count) { mSkAnimatedImage->setRepetitionCount(count); } + // Returns true if the filter mode is set to linear sampling; false if it is + // set to nearest neighbor sampling. + bool getFilterBitmap() const; + // Returns true if the filter mode was changed; false otherwise. + bool setFilterBitmap(bool filterBitmap); void setOnAnimationEndListener(std::unique_ptr<OnAnimationEndListener> listener) { mEndListener = std::move(listener); diff --git a/libs/hwui/jni/AnimatedImageDrawable.cpp b/libs/hwui/jni/AnimatedImageDrawable.cpp index b01e38d014a9..2c8530d4daeb 100644 --- a/libs/hwui/jni/AnimatedImageDrawable.cpp +++ b/libs/hwui/jni/AnimatedImageDrawable.cpp @@ -276,6 +276,18 @@ static void AnimatedImageDrawable_nSetBounds(JNIEnv* env, jobject /*clazz*/, jlo drawable->setStagingBounds(rect); } +static jboolean AnimatedImageDrawable_nSetFilterBitmap(JNIEnv* env, jobject /*clazz*/, + jlong nativePtr, jboolean filterBitmap) { + auto* drawable = reinterpret_cast<AnimatedImageDrawable*>(nativePtr); + return drawable->setFilterBitmap(filterBitmap); +} + +static jboolean AnimatedImageDrawable_nGetFilterBitmap(JNIEnv* env, jobject /*clazz*/, + jlong nativePtr) { + auto* drawable = reinterpret_cast<AnimatedImageDrawable*>(nativePtr); + return drawable->getFilterBitmap(); +} + static const JNINativeMethod gAnimatedImageDrawableMethods[] = { {"nCreate", "(JLandroid/graphics/ImageDecoder;IIJZLandroid/graphics/Rect;)J", (void*)AnimatedImageDrawable_nCreate}, @@ -294,6 +306,8 @@ static const JNINativeMethod gAnimatedImageDrawableMethods[] = { {"nNativeByteSize", "(J)J", (void*)AnimatedImageDrawable_nNativeByteSize}, {"nSetMirrored", "(JZ)V", (void*)AnimatedImageDrawable_nSetMirrored}, {"nSetBounds", "(JLandroid/graphics/Rect;)V", (void*)AnimatedImageDrawable_nSetBounds}, + {"nSetFilterBitmap", "(JZ)Z", (void*)AnimatedImageDrawable_nSetFilterBitmap}, + {"nGetFilterBitmap", "(J)Z", (void*)AnimatedImageDrawable_nGetFilterBitmap}, }; int register_android_graphics_drawable_AnimatedImageDrawable(JNIEnv* env) { |