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
diff --git a/libs/hwui/aconfig/hwui_flags.aconfig b/libs/hwui/aconfig/hwui_flags.aconfig
index f255967..5ad788c 100644
--- a/libs/hwui/aconfig/hwui_flags.aconfig
+++ b/libs/hwui/aconfig/hwui_flags.aconfig
@@ -146,3 +146,11 @@
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 69613c7..5e379aa 100644
--- a/libs/hwui/hwui/AnimatedImageDrawable.cpp
+++ b/libs/hwui/hwui/AnimatedImageDrawable.cpp
@@ -347,4 +347,26 @@
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 1e965ab..2212324 100644
--- a/libs/hwui/hwui/AnimatedImageDrawable.h
+++ b/libs/hwui/hwui/AnimatedImageDrawable.h
@@ -87,6 +87,11 @@
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 b01e38d..2c8530d 100644
--- a/libs/hwui/jni/AnimatedImageDrawable.cpp
+++ b/libs/hwui/jni/AnimatedImageDrawable.cpp
@@ -276,6 +276,18 @@
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 @@
{"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) {