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

Commit 71421804 authored by TreeHugger Robot's avatar TreeHugger Robot Committed by Android (Google) Code Review
Browse files

Merge "Implement AnimatedImageDrawable#setBounds" into sc-dev

parents 8f046c76 be969efd
Loading
Loading
Loading
Loading
+9 −0
Original line number Diff line number Diff line
@@ -570,6 +570,13 @@ public class AnimatedImageDrawable extends Drawable implements Animatable2 {
        }
    }

    @Override
    protected void onBoundsChange(Rect bounds) {
        if (mState.mNativePtr != 0) {
            nSetBounds(mState.mNativePtr, bounds);
        }
    }


    private static native long nCreate(long nativeImageDecoder,
            @Nullable ImageDecoder decoder, int width, int height, long colorSpaceHandle,
@@ -601,4 +608,6 @@ public class AnimatedImageDrawable extends Drawable implements Animatable2 {
    private static native long nNativeByteSize(long nativePtr);
    @FastNative
    private static native void nSetMirrored(long nativePtr, boolean mirror);
    @FastNative
    private static native void nSetBounds(long nativePtr, Rect rect);
}
+57 −14
Original line number Diff line number Diff line
@@ -20,6 +20,7 @@
#endif

#include "utils/TraceUtils.h"
#include "pipeline/skia/SkiaUtils.h"

#include <SkPicture.h>
#include <SkRefCnt.h>
@@ -31,6 +32,7 @@ namespace android {
AnimatedImageDrawable::AnimatedImageDrawable(sk_sp<SkAnimatedImage> animatedImage, size_t bytesUsed)
        : mSkAnimatedImage(std::move(animatedImage)), mBytesUsed(bytesUsed) {
    mTimeToShowNextSnapshot = ms2ns(mSkAnimatedImage->currentFrameDuration());
    setStagingBounds(mSkAnimatedImage->getBounds());
}

void AnimatedImageDrawable::syncProperties() {
@@ -127,21 +129,38 @@ AnimatedImageDrawable::Snapshot AnimatedImageDrawable::reset() {
    return snap;
}

// Update the matrix to map from the intrinsic bounds of the SkAnimatedImage to
// the bounds specified by Drawable#setBounds.
static void handleBounds(SkMatrix* matrix, const SkRect& intrinsicBounds, const SkRect& bounds) {
    matrix->preTranslate(bounds.left(), bounds.top());
    matrix->preScale(bounds.width()  / intrinsicBounds.width(),
                     bounds.height() / intrinsicBounds.height());
}

// Only called on the RenderThread.
void AnimatedImageDrawable::onDraw(SkCanvas* canvas) {
    // Store the matrix used to handle bounds and mirroring separate from the
    // canvas. We may need to invert the matrix to determine the proper bounds
    // to pass to saveLayer, and this matrix (as opposed to, potentially, the
    // canvas' matrix) only uses scale and translate, so it must be invertible.
    SkMatrix matrix;
    SkAutoCanvasRestore acr(canvas, true);
    handleBounds(&matrix, mSkAnimatedImage->getBounds(), mProperties.mBounds);

    if (mProperties.mMirrored) {
        matrix.preTranslate(mSkAnimatedImage->getBounds().width(), 0);
        matrix.preScale(-1, 1);
    }

    std::optional<SkPaint> lazyPaint;
    SkAutoCanvasRestore acr(canvas, false);
    if (mProperties.mAlpha != SK_AlphaOPAQUE || mProperties.mColorFilter.get()) {
        lazyPaint.emplace();
        lazyPaint->setAlpha(mProperties.mAlpha);
        lazyPaint->setColorFilter(mProperties.mColorFilter);
        lazyPaint->setFilterQuality(kLow_SkFilterQuality);
    }
    if (mProperties.mMirrored) {
        canvas->save();
        canvas->translate(mSkAnimatedImage->getBounds().width(), 0);
        canvas->scale(-1, 1);
    }

    canvas->concat(matrix);

    const bool starting = mStarting;
    mStarting = false;
@@ -151,7 +170,11 @@ void AnimatedImageDrawable::onDraw(SkCanvas* canvas) {
        // The image is not animating, and never was. Draw directly from
        // mSkAnimatedImage.
        if (lazyPaint) {
            canvas->saveLayer(mSkAnimatedImage->getBounds(), &*lazyPaint);
            SkMatrix inverse;
            (void) matrix.invert(&inverse);
            SkRect r = mProperties.mBounds;
            inverse.mapRect(&r);
            canvas->saveLayer(r, &*lazyPaint);
        }

        std::unique_lock lock{mImageLock};
@@ -211,17 +234,31 @@ void AnimatedImageDrawable::onDraw(SkCanvas* canvas) {
}

int AnimatedImageDrawable::drawStaging(SkCanvas* canvas) {
    SkAutoCanvasRestore acr(canvas, false);
    // Store the matrix used to handle bounds and mirroring separate from the
    // canvas. We may need to invert the matrix to determine the proper bounds
    // to pass to saveLayer, and this matrix (as opposed to, potentially, the
    // canvas' matrix) only uses scale and translate, so it must be invertible.
    SkMatrix matrix;
    SkAutoCanvasRestore acr(canvas, true);
    handleBounds(&matrix, mSkAnimatedImage->getBounds(), mStagingProperties.mBounds);

    if (mStagingProperties.mMirrored) {
        matrix.preTranslate(mSkAnimatedImage->getBounds().width(), 0);
        matrix.preScale(-1, 1);
    }

    canvas->concat(matrix);

    if (mStagingProperties.mAlpha != SK_AlphaOPAQUE || mStagingProperties.mColorFilter.get()) {
        SkPaint paint;
        paint.setAlpha(mStagingProperties.mAlpha);
        paint.setColorFilter(mStagingProperties.mColorFilter);
        canvas->saveLayer(mSkAnimatedImage->getBounds(), &paint);
    }
    if (mStagingProperties.mMirrored) {
        canvas->save();
        canvas->translate(mSkAnimatedImage->getBounds().width(), 0);
        canvas->scale(-1, 1);

        SkMatrix inverse;
        (void) matrix.invert(&inverse);
        SkRect r = mStagingProperties.mBounds;
        inverse.mapRect(&r);
        canvas->saveLayer(r, &paint);
    }

    if (!mRunning) {
@@ -294,4 +331,10 @@ int AnimatedImageDrawable::drawStaging(SkCanvas* canvas) {
    return ns2ms(mTimeToShowNextSnapshot - mCurrentTime);
}

SkRect AnimatedImageDrawable::onGetBounds() {
    // This must return a bounds that is valid for all possible states,
    // including if e.g. the client calls setBounds.
    return SkRectMakeLargest();
}

}  // namespace android
+4 −2
Original line number Diff line number Diff line
@@ -67,9 +67,10 @@ public:
        mStagingProperties.mColorFilter = filter;
    }
    void setStagingMirrored(bool mirrored) { mStagingProperties.mMirrored = mirrored; }
    void setStagingBounds(const SkRect& bounds) { mStagingProperties.mBounds = bounds; }
    void syncProperties();

    virtual SkRect onGetBounds() override { return mSkAnimatedImage->getBounds(); }
    SkRect onGetBounds() override;

    // Draw to software canvas, and return time to next draw.
    // 0 means the animation is not running.
@@ -109,7 +110,7 @@ public:
    size_t byteSize() const { return sizeof(*this) + mBytesUsed; }

protected:
    virtual void onDraw(SkCanvas* canvas) override;
    void onDraw(SkCanvas* canvas) override;

private:
    sk_sp<SkAnimatedImage> mSkAnimatedImage;
@@ -145,6 +146,7 @@ private:
        int mAlpha = SK_AlphaOPAQUE;
        sk_sp<SkColorFilter> mColorFilter;
        bool mMirrored = false;
        SkRect mBounds;

        Properties() = default;
        Properties(Properties&) = default;
+9 −0
Original line number Diff line number Diff line
@@ -244,6 +244,14 @@ static void AnimatedImageDrawable_nSetMirrored(JNIEnv* env, jobject /*clazz*/, j
    drawable->setStagingMirrored(mirrored);
}

static void AnimatedImageDrawable_nSetBounds(JNIEnv* env, jobject /*clazz*/, jlong nativePtr,
                                             jobject jrect) {
    auto* drawable = reinterpret_cast<AnimatedImageDrawable*>(nativePtr);
    SkRect rect;
    GraphicsJNI::jrect_to_rect(env, jrect, &rect);
    drawable->setStagingBounds(rect);
}

static const JNINativeMethod gAnimatedImageDrawableMethods[] = {
    { "nCreate",             "(JLandroid/graphics/ImageDecoder;IIJZLandroid/graphics/Rect;)J",(void*) AnimatedImageDrawable_nCreate },
    { "nGetNativeFinalizer", "()J",                                                          (void*) AnimatedImageDrawable_nGetNativeFinalizer },
@@ -259,6 +267,7 @@ static const JNINativeMethod gAnimatedImageDrawableMethods[] = {
    { "nSetOnAnimationEndListener", "(JLandroid/graphics/drawable/AnimatedImageDrawable;)V", (void*) AnimatedImageDrawable_nSetOnAnimationEndListener },
    { "nNativeByteSize",     "(J)J",                                                         (void*) AnimatedImageDrawable_nNativeByteSize },
    { "nSetMirrored",        "(JZ)V",                                                        (void*) AnimatedImageDrawable_nSetMirrored },
    { "nSetBounds",          "(JLandroid/graphics/Rect;)V",                                  (void*) AnimatedImageDrawable_nSetBounds },
};

int register_android_graphics_drawable_AnimatedImageDrawable(JNIEnv* env) {