Merge "Implement AnimatedImageDrawable#setBounds" into sc-dev

This commit is contained in:
TreeHugger Robot
2021-01-28 18:50:25 +00:00
committed by Android (Google) Code Review
4 changed files with 79 additions and 16 deletions

View File

@@ -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);
}

View File

@@ -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

View File

@@ -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;

View File

@@ -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) {