Merge "Implement AnimatedImageDrawable#setBounds" into sc-dev
This commit is contained in:
committed by
Android (Google) Code Review
commit
7142180435
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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) {
|
||||
|
||||
Reference in New Issue
Block a user