Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit ae7c8354 authored by Daniel Dilan's avatar Daniel Dilan
Browse files

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
parent 6b37ca81
Loading
Loading
Loading
Loading
+34 −0
Original line number Diff line number Diff line
@@ -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);
}
+8 −0
Original line number Diff line number Diff line
@@ -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"
}
+22 −0
Original line number Diff line number Diff line
@@ -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
+5 −0
Original line number Diff line number Diff line
@@ -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);
+14 −0
Original line number Diff line number Diff line
@@ -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) {