Merge "Draw AnimatedImageDrawable mirrored if desired" into pi-dev

This commit is contained in:
Leon Scroggins
2018-03-07 18:51:16 +00:00
committed by Android (Google) Code Review
4 changed files with 60 additions and 17 deletions

View File

@@ -213,6 +213,12 @@ static void AnimatedImageDrawable_nMarkInvisible(JNIEnv* env, jobject /*clazz*/,
drawable->markInvisible();
}
static void AnimatedImageDrawable_nSetMirrored(JNIEnv* env, jobject /*clazz*/, jlong nativePtr,
jboolean mirrored) {
auto* drawable = reinterpret_cast<AnimatedImageDrawable*>(nativePtr);
drawable->setStagingMirrored(mirrored);
}
static const JNINativeMethod gAnimatedImageDrawableMethods[] = {
{ "nCreate", "(JLandroid/graphics/ImageDecoder;IILandroid/graphics/Rect;)J", (void*) AnimatedImageDrawable_nCreate },
{ "nGetNativeFinalizer", "()J", (void*) AnimatedImageDrawable_nGetNativeFinalizer },
@@ -228,6 +234,7 @@ static const JNINativeMethod gAnimatedImageDrawableMethods[] = {
{ "nSetOnAnimationEndListener", "(JLandroid/graphics/drawable/AnimatedImageDrawable;)V", (void*) AnimatedImageDrawable_nSetOnAnimationEndListener },
{ "nNativeByteSize", "(J)J", (void*) AnimatedImageDrawable_nNativeByteSize },
{ "nMarkInvisible", "(J)V", (void*) AnimatedImageDrawable_nMarkInvisible },
{ "nSetMirrored", "(JZ)V", (void*) AnimatedImageDrawable_nSetMirrored },
};
int register_android_graphics_drawable_AnimatedImageDrawable(JNIEnv* env) {

View File

@@ -34,6 +34,7 @@ import android.os.Looper;
import android.util.AttributeSet;
import android.util.DisplayMetrics;
import android.util.TypedValue;
import android.view.View;
import com.android.internal.R;
@@ -389,10 +390,24 @@ public class AnimatedImageDrawable extends Drawable implements Animatable2 {
public void setAutoMirrored(boolean mirrored) {
if (mState.mAutoMirrored != mirrored) {
mState.mAutoMirrored = mirrored;
invalidateSelf();
if (getLayoutDirection() == View.LAYOUT_DIRECTION_RTL && mState.mNativePtr != 0) {
nSetMirrored(mState.mNativePtr, mirrored);
invalidateSelf();
}
}
}
@Override
public boolean onLayoutDirectionChanged(int layoutDirection) {
if (!mState.mAutoMirrored || mState.mNativePtr == 0) {
return false;
}
final boolean mirror = layoutDirection == View.LAYOUT_DIRECTION_RTL;
nSetMirrored(mState.mNativePtr, mirror);
return true;
}
@Override
public final boolean isAutoMirrored() {
return mState.mAutoMirrored;
@@ -585,4 +600,6 @@ public class AnimatedImageDrawable extends Drawable implements Animatable2 {
private static native long nNativeByteSize(long nativePtr);
@FastNative
private static native void nMarkInvisible(long nativePtr);
@FastNative
private static native void nSetMirrored(long nativePtr, boolean mirror);
}

View File

@@ -32,8 +32,7 @@ AnimatedImageDrawable::AnimatedImageDrawable(sk_sp<SkAnimatedImage> animatedImag
}
void AnimatedImageDrawable::syncProperties() {
mAlpha = mStagingAlpha;
mColorFilter = mStagingColorFilter;
mProperties = mStagingProperties;
}
bool AnimatedImageDrawable::start() {
@@ -115,12 +114,18 @@ AnimatedImageDrawable::Snapshot AnimatedImageDrawable::reset() {
// Only called on the RenderThread.
void AnimatedImageDrawable::onDraw(SkCanvas* canvas) {
SkTLazy<SkPaint> lazyPaint;
if (mAlpha != SK_AlphaOPAQUE || mColorFilter.get()) {
SkAutoCanvasRestore acr(canvas, false);
if (mProperties.mAlpha != SK_AlphaOPAQUE || mProperties.mColorFilter.get()) {
lazyPaint.init();
lazyPaint.get()->setAlpha(mAlpha);
lazyPaint.get()->setColorFilter(mColorFilter);
lazyPaint.get()->setAlpha(mProperties.mAlpha);
lazyPaint.get()->setColorFilter(mProperties.mColorFilter);
lazyPaint.get()->setFilterQuality(kLow_SkFilterQuality);
}
if (mProperties.mMirrored) {
canvas->save();
canvas->translate(mSkAnimatedImage->getBounds().width(), 0);
canvas->scale(-1, 1);
}
mDidDraw = true;
@@ -131,7 +136,6 @@ void AnimatedImageDrawable::onDraw(SkCanvas* canvas) {
if (drawDirectly) {
// The image is not animating, and never was. Draw directly from
// mSkAnimatedImage.
SkAutoCanvasRestore acr(canvas, false);
if (lazyPaint.isValid()) {
canvas->saveLayer(mSkAnimatedImage->getBounds(), lazyPaint.get());
}
@@ -190,12 +194,17 @@ void AnimatedImageDrawable::onDraw(SkCanvas* canvas) {
double AnimatedImageDrawable::drawStaging(SkCanvas* canvas) {
SkAutoCanvasRestore acr(canvas, false);
if (mStagingAlpha != SK_AlphaOPAQUE || mStagingColorFilter.get()) {
if (mStagingProperties.mAlpha != SK_AlphaOPAQUE || mStagingProperties.mColorFilter.get()) {
SkPaint paint;
paint.setAlpha(mStagingAlpha);
paint.setColorFilter(mStagingColorFilter);
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);
}
if (!mRunning) {
// Continue drawing the current frame, and return 0 to indicate no need

View File

@@ -55,9 +55,12 @@ public:
*/
bool isDirty();
int getStagingAlpha() const { return mStagingAlpha; }
void setStagingAlpha(int alpha) { mStagingAlpha = alpha; }
void setStagingColorFilter(sk_sp<SkColorFilter> filter) { mStagingColorFilter = filter; }
int getStagingAlpha() const { return mStagingProperties.mAlpha; }
void setStagingAlpha(int alpha) { mStagingProperties.mAlpha = alpha; }
void setStagingColorFilter(sk_sp<SkColorFilter> filter) {
mStagingProperties.mColorFilter = filter;
}
void setStagingMirrored(bool mirrored) { mStagingProperties.mMirrored = mirrored; }
void syncProperties();
virtual SkRect onGetBounds() override { return mSkAnimatedImage->getBounds(); }
@@ -131,11 +134,18 @@ private:
// Locked when mSkAnimatedImage is being updated or drawn.
std::mutex mImageLock;
int mStagingAlpha = SK_AlphaOPAQUE;
sk_sp<SkColorFilter> mStagingColorFilter;
struct Properties {
int mAlpha = SK_AlphaOPAQUE;
sk_sp<SkColorFilter> mColorFilter;
bool mMirrored = false;
int mAlpha = SK_AlphaOPAQUE;
sk_sp<SkColorFilter> mColorFilter;
Properties() = default;
Properties(Properties&) = default;
Properties& operator=(Properties&) = default;
};
Properties mStagingProperties;
Properties mProperties;
std::unique_ptr<OnAnimationEndListener> mEndListener;
};