diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml index 9d7432ec3c267..0b3321109b223 100644 --- a/core/res/res/values/attrs.xml +++ b/core/res/res/values/attrs.xml @@ -5905,6 +5905,9 @@ + + diff --git a/graphics/java/android/graphics/drawable/AnimatedImageDrawable.java b/graphics/java/android/graphics/drawable/AnimatedImageDrawable.java index 598807d0309dd..796d008acf06a 100644 --- a/graphics/java/android/graphics/drawable/AnimatedImageDrawable.java +++ b/graphics/java/android/graphics/drawable/AnimatedImageDrawable.java @@ -72,11 +72,14 @@ public class AnimatedImageDrawable extends Drawable implements Animatable2 { mAssetFd = afd; } - public final long mNativePtr; + final long mNativePtr; // These just keep references so the native code can continue using them. private final InputStream mInputStream; private final AssetFileDescriptor mAssetFd; + + int[] mThemeAttrs = null; + boolean mAutoMirrored = false; } private State mState; @@ -99,7 +102,7 @@ public class AnimatedImageDrawable extends Drawable implements Animatable2 { *

By default, the loop count in the encoded data is respected.

*/ public void setLoopCount(int loopCount) { - if (mState == null) { + if (mState.mNativePtr == 0) { throw new IllegalStateException("called setLoopCount on empty AnimatedImageDrawable"); } nSetLoopCount(mState.mNativePtr, loopCount); @@ -109,7 +112,7 @@ public class AnimatedImageDrawable extends Drawable implements Animatable2 { * Create an empty AnimatedImageDrawable. */ public AnimatedImageDrawable() { - mState = null; + mState = new State(0, null, null); } @Override @@ -123,6 +126,7 @@ public class AnimatedImageDrawable extends Drawable implements Animatable2 { private void updateStateFromTypedArray(TypedArray a, int srcDensityOverride) throws XmlPullParserException { + State oldState = mState; final Resources r = a.getResources(); final int srcResId = a.getResourceId(R.styleable.AnimatedImageDrawable_src, 0); if (srcResId != 0) { @@ -172,6 +176,16 @@ public class AnimatedImageDrawable extends Drawable implements Animatable2 { mIntrinsicWidth = other.mIntrinsicWidth; mIntrinsicHeight = other.mIntrinsicHeight; } + + mState.mThemeAttrs = a.extractThemeAttrs(); + if (mState.mNativePtr == 0 && (mState.mThemeAttrs == null + || mState.mThemeAttrs[R.styleable.AnimatedImageDrawable_src] == 0)) { + throw new XmlPullParserException(a.getPositionDescription() + + ": requires a valid 'src' attribute"); + } + + mState.mAutoMirrored = a.getBoolean( + R.styleable.AnimatedImageDrawable_autoMirrored, oldState.mAutoMirrored); } /** @@ -225,7 +239,7 @@ public class AnimatedImageDrawable extends Drawable implements Animatable2 { @Override public void draw(@NonNull Canvas canvas) { - if (mState == null) { + if (mState.mNativePtr == 0) { throw new IllegalStateException("called draw on empty AnimatedImageDrawable"); } @@ -256,7 +270,7 @@ public class AnimatedImageDrawable extends Drawable implements Animatable2 { + " 255! provided " + alpha); } - if (mState == null) { + if (mState.mNativePtr == 0) { throw new IllegalStateException("called setAlpha on empty AnimatedImageDrawable"); } @@ -266,7 +280,7 @@ public class AnimatedImageDrawable extends Drawable implements Animatable2 { @Override public int getAlpha() { - if (mState == null) { + if (mState.mNativePtr == 0) { throw new IllegalStateException("called getAlpha on empty AnimatedImageDrawable"); } return nGetAlpha(mState.mNativePtr); @@ -274,7 +288,7 @@ public class AnimatedImageDrawable extends Drawable implements Animatable2 { @Override public void setColorFilter(@Nullable ColorFilter colorFilter) { - if (mState == null) { + if (mState.mNativePtr == 0) { throw new IllegalStateException("called setColorFilter on empty AnimatedImageDrawable"); } @@ -297,12 +311,29 @@ public class AnimatedImageDrawable extends Drawable implements Animatable2 { return PixelFormat.TRANSLUCENT; } + @Override + public void setAutoMirrored(boolean mirrored) { + if (mState.mAutoMirrored != mirrored) { + mState.mAutoMirrored = mirrored; + invalidateSelf(); + } + } + + @Override + public final boolean isAutoMirrored() { + return mState.mAutoMirrored; + } + @Override public boolean setVisible(boolean visible, boolean restart) { if (!super.setVisible(visible, restart)) { return false; } + if (mState.mNativePtr == 0) { + throw new IllegalStateException("called setVisible on empty AnimatedImageDrawable"); + } + if (!visible) { nMarkInvisible(mState.mNativePtr); } @@ -319,7 +350,7 @@ public class AnimatedImageDrawable extends Drawable implements Animatable2 { */ @Override public boolean isRunning() { - if (mState == null) { + if (mState.mNativePtr == 0) { throw new IllegalStateException("called isRunning on empty AnimatedImageDrawable"); } return nIsRunning(mState.mNativePtr); @@ -336,7 +367,7 @@ public class AnimatedImageDrawable extends Drawable implements Animatable2 { */ @Override public void start() { - if (mState == null) { + if (mState.mNativePtr == 0) { throw new IllegalStateException("called start on empty AnimatedImageDrawable"); } @@ -354,7 +385,7 @@ public class AnimatedImageDrawable extends Drawable implements Animatable2 { */ @Override public void stop() { - if (mState == null) { + if (mState.mNativePtr == 0) { throw new IllegalStateException("called stop on empty AnimatedImageDrawable"); } if (nStop(mState.mNativePtr)) {