summaryrefslogtreecommitdiff
path: root/graphics/java
diff options
context:
space:
mode:
Diffstat (limited to 'graphics/java')
-rw-r--r--graphics/java/android/graphics/FontFamily.java36
-rw-r--r--graphics/java/android/graphics/ImageDecoder.java142
-rw-r--r--graphics/java/android/graphics/Typeface.java34
-rw-r--r--graphics/java/android/graphics/drawable/AdaptiveIconDrawable.java9
-rw-r--r--graphics/java/android/graphics/drawable/AnimatedImageDrawable.java116
5 files changed, 263 insertions, 74 deletions
diff --git a/graphics/java/android/graphics/FontFamily.java b/graphics/java/android/graphics/FontFamily.java
index e7cfcfdf7760..c69eb32148c0 100644
--- a/graphics/java/android/graphics/FontFamily.java
+++ b/graphics/java/android/graphics/FontFamily.java
@@ -24,6 +24,8 @@ import android.util.Log;
import dalvik.annotation.optimization.CriticalNative;
+import libcore.util.NativeAllocationRegistry;
+
import java.io.FileInputStream;
import java.io.IOException;
import java.nio.ByteBuffer;
@@ -38,6 +40,14 @@ public class FontFamily {
private static String TAG = "FontFamily";
+ private static final NativeAllocationRegistry sBuilderRegistry = new NativeAllocationRegistry(
+ FontFamily.class.getClassLoader(), nGetBuilderReleaseFunc(), 64);
+
+ private @Nullable Runnable mNativeBuilderCleaner;
+
+ private static final NativeAllocationRegistry sFamilyRegistry = new NativeAllocationRegistry(
+ FontFamily.class.getClassLoader(), nGetFamilyReleaseFunc(), 64);
+
/**
* @hide
*/
@@ -48,6 +58,7 @@ public class FontFamily {
public FontFamily() {
mBuilderPtr = nInitBuilder(null, 0);
+ mNativeBuilderCleaner = sBuilderRegistry.registerNativeAllocation(this, mBuilderPtr);
}
public FontFamily(@Nullable String[] langs, int variant) {
@@ -60,6 +71,7 @@ public class FontFamily {
langsString = TextUtils.join(",", langs);
}
mBuilderPtr = nInitBuilder(langsString, variant);
+ mNativeBuilderCleaner = sBuilderRegistry.registerNativeAllocation(this, mBuilderPtr);
}
/**
@@ -73,7 +85,11 @@ public class FontFamily {
throw new IllegalStateException("This FontFamily is already frozen");
}
mNativePtr = nCreateFamily(mBuilderPtr);
+ mNativeBuilderCleaner.run();
mBuilderPtr = 0;
+ if (mNativePtr != 0) {
+ sFamilyRegistry.registerNativeAllocation(this, mNativePtr);
+ }
return mNativePtr != 0;
}
@@ -81,24 +97,10 @@ public class FontFamily {
if (mBuilderPtr == 0) {
throw new IllegalStateException("This FontFamily is already frozen or abandoned");
}
- nAbort(mBuilderPtr);
+ mNativeBuilderCleaner.run();
mBuilderPtr = 0;
}
- @Override
- protected void finalize() throws Throwable {
- try {
- if (mNativePtr != 0) {
- nUnrefFamily(mNativePtr);
- }
- if (mBuilderPtr != 0) {
- nAbort(mBuilderPtr);
- }
- } finally {
- super.finalize();
- }
- }
-
public boolean addFont(String path, int ttcIndex, FontVariationAxis[] axes, int weight,
int italic) {
if (mBuilderPtr == 0) {
@@ -171,10 +173,10 @@ public class FontFamily {
private static native long nCreateFamily(long mBuilderPtr);
@CriticalNative
- private static native void nAbort(long mBuilderPtr);
+ private static native long nGetBuilderReleaseFunc();
@CriticalNative
- private static native void nUnrefFamily(long nativePtr);
+ private static native long nGetFamilyReleaseFunc();
// By passing -1 to weigth argument, the weight value is resolved by OS/2 table in the font.
// By passing -1 to italic argument, the italic value is resolved by OS/2 table in the font.
private static native boolean nAddFont(long builderPtr, ByteBuffer font, int ttcIndex,
diff --git a/graphics/java/android/graphics/ImageDecoder.java b/graphics/java/android/graphics/ImageDecoder.java
index 5abd31a0998a..88701fac66c7 100644
--- a/graphics/java/android/graphics/ImageDecoder.java
+++ b/graphics/java/android/graphics/ImageDecoder.java
@@ -493,7 +493,7 @@ public final class ImageDecoder implements AutoCloseable {
private boolean mRequireUnpremultiplied = false;
private boolean mMutable = false;
private boolean mConserveMemory = false;
- private boolean mAsAlphaMask = false;
+ private boolean mDecodeAsAlphaMask = false;
private Rect mCropRect;
private Rect mOutPaddingRect;
private Source mSource;
@@ -730,7 +730,7 @@ public final class ImageDecoder implements AutoCloseable {
* Will typically result in a {@link Bitmap.Config#HARDWARE}
* allocation, but may be software for small images. In addition, this will
* switch to software when HARDWARE is incompatible, e.g.
- * {@link #setMutable}, {@link #setAsAlphaMask}.
+ * {@link #setMutable}, {@link #setDecodeAsAlphaMask}.
*/
public static final int ALLOCATOR_DEFAULT = 0;
@@ -753,7 +753,7 @@ public final class ImageDecoder implements AutoCloseable {
* Require a {@link Bitmap.Config#HARDWARE} {@link Bitmap}.
*
* When this is combined with incompatible options, like
- * {@link #setMutable} or {@link #setAsAlphaMask}, {@link #decodeDrawable}
+ * {@link #setMutable} or {@link #setDecodeAsAlphaMask}, {@link #decodeDrawable}
* / {@link #decodeBitmap} will throw an
* {@link java.lang.IllegalStateException}.
*/
@@ -783,6 +783,14 @@ public final class ImageDecoder implements AutoCloseable {
}
/**
+ * Return the allocator for the pixel memory.
+ */
+ @Allocator
+ public int getAllocator() {
+ return mAllocator;
+ }
+
+ /**
* Specify whether the {@link Bitmap} should have unpremultiplied pixels.
*
* <p>By default, ImageDecoder will create a {@link Bitmap} with
@@ -803,6 +811,13 @@ public final class ImageDecoder implements AutoCloseable {
}
/**
+ * Return whether the {@link Bitmap} will have unpremultiplied pixels.
+ */
+ public boolean getRequireUnpremultiplied() {
+ return mRequireUnpremultiplied;
+ }
+
+ /**
* Modify the image after decoding and scaling.
*
* <p>This allows adding effects prior to returning a {@link Drawable} or
@@ -823,6 +838,14 @@ public final class ImageDecoder implements AutoCloseable {
}
/**
+ * Return the {@link PostProcessor} currently set.
+ */
+ @Nullable
+ public PostProcessor getPostProcessor() {
+ return mPostProcessor;
+ }
+
+ /**
* Set (replace) the {@link OnPartialImageListener} on this object.
*
* <p>Will be called if there is an error in the input. Without one, an
@@ -836,6 +859,14 @@ public final class ImageDecoder implements AutoCloseable {
}
/**
+ * Return the {@link OnPartialImageListener} currently set.
+ */
+ @Nullable
+ public OnPartialImageListener getOnPartialImageListener() {
+ return mOnPartialImageListener;
+ }
+
+ /**
* Crop the output to {@code subset} of the (possibly) scaled image.
*
* <p>{@code subset} must be contained within the size set by
@@ -855,6 +886,14 @@ public final class ImageDecoder implements AutoCloseable {
}
/**
+ * Return the cropping rectangle, if set.
+ */
+ @Nullable
+ public Rect getCrop() {
+ return mCropRect;
+ }
+
+ /**
* Set a Rect for retrieving nine patch padding.
*
* If the image is a nine patch, this Rect will be set to the padding
@@ -893,6 +932,13 @@ public final class ImageDecoder implements AutoCloseable {
}
/**
+ * Return whether the {@link Bitmap} will be mutable.
+ */
+ public boolean getMutable() {
+ return mMutable;
+ }
+
+ /**
* Specify whether to potentially save RAM at the expense of quality.
*
* <p>Setting this to {@code true} may result in a {@link Bitmap} with a
@@ -912,24 +958,62 @@ public final class ImageDecoder implements AutoCloseable {
}
/**
+ * Return whether this object will try to save RAM at the expense of quality.
+ *
+ * <p>This returns whether {@link #setConserveMemory} was set to {@code true}.
+ * It may still return {@code true} even if the {@code ImageDecoder} does not
+ * have a way to save RAM at the expense of quality for this image.</p>
+ */
+ public boolean getConserveMemory() {
+ return mConserveMemory;
+ }
+
+ /**
* Specify whether to potentially treat the output as an alpha mask.
*
* <p>If this is set to {@code true} and the image is encoded in a format
* with only one channel, treat that channel as alpha. Otherwise this call has
* no effect.</p>
*
- * <p>setAsAlphaMask is incompatible with {@link #ALLOCATOR_HARDWARE}. Trying to
+ * <p>setDecodeAsAlphaMask is incompatible with {@link #ALLOCATOR_HARDWARE}. Trying to
* combine them will result in {@link #decodeDrawable}/
* {@link #decodeBitmap} throwing an
* {@link java.lang.IllegalStateException}.</p>
*
* @return this object for chaining.
*/
- public ImageDecoder setAsAlphaMask(boolean asAlphaMask) {
- mAsAlphaMask = asAlphaMask;
+ public ImageDecoder setDecodeAsAlphaMask(boolean decodeAsAlphaMask) {
+ mDecodeAsAlphaMask = decodeAsAlphaMask;
return this;
}
+ /** @removed
+ * @deprecated Call {@link #setDecodeAsAlphaMask} instead.
+ */
+ @java.lang.Deprecated
+ public ImageDecoder setAsAlphaMask(boolean asAlphaMask) {
+ return this.setDecodeAsAlphaMask(asAlphaMask);
+ }
+
+ /**
+ * Return whether to treat single channel input as alpha.
+ *
+ * <p>This returns whether {@link #setDecodeAsAlphaMask} was set to {@code true}.
+ * It may still return {@code true} even if the image has more than one
+ * channel and therefore will not be treated as an alpha mask.</p>
+ */
+ public boolean getDecodeAsAlphaMask() {
+ return mDecodeAsAlphaMask;
+ }
+
+ /** @removed
+ * @deprecated Call {@link #getDecodeAsAlphaMask} instead.
+ */
+ @java.lang.Deprecated
+ public boolean getAsAlphaMask() {
+ return this.getDecodeAsAlphaMask();
+ }
+
@Override
public void close() {
mCloseGuard.close();
@@ -960,7 +1044,7 @@ public final class ImageDecoder implements AutoCloseable {
if (mMutable) {
throw new IllegalStateException("Cannot make mutable HARDWARE Bitmap!");
}
- if (mAsAlphaMask) {
+ if (mDecodeAsAlphaMask) {
throw new IllegalStateException("Cannot make HARDWARE Alpha mask Bitmap!");
}
}
@@ -981,7 +1065,7 @@ public final class ImageDecoder implements AutoCloseable {
}
@NonNull
- private Bitmap decodeBitmap() throws IOException {
+ private Bitmap decodeBitmapInternal() throws IOException {
checkState();
// nDecodeBitmap calls onPartialImage only if mOnPartialImageListener
// exists
@@ -992,7 +1076,7 @@ public final class ImageDecoder implements AutoCloseable {
return nDecodeBitmap(mNativePtr, partialImagePtr,
postProcessPtr, mDesiredWidth, mDesiredHeight, mCropRect,
mMutable, mAllocator, mRequireUnpremultiplied,
- mConserveMemory, mAsAlphaMask);
+ mConserveMemory, mDecodeAsAlphaMask);
}
private void callHeaderDecoded(@Nullable OnHeaderDecodedListener listener,
@@ -1012,15 +1096,24 @@ public final class ImageDecoder implements AutoCloseable {
*
* @param src representing the encoded image.
* @param listener for learning the {@link ImageInfo} and changing any
- * default settings on the {@code ImageDecoder}. If not {@code null},
- * this will be called on the same thread as {@code decodeDrawable}
- * before that method returns.
+ * default settings on the {@code ImageDecoder}. This will be called on
+ * the same thread as {@code decodeDrawable} before that method returns.
* @return Drawable for displaying the image.
* @throws IOException if {@code src} is not found, is an unsupported
* format, or cannot be decoded for any reason.
*/
@NonNull
public static Drawable decodeDrawable(@NonNull Source src,
+ @NonNull OnHeaderDecodedListener listener) throws IOException {
+ if (listener == null) {
+ throw new IllegalArgumentException("listener cannot be null! "
+ + "Use decodeDrawable(Source) to not have a listener");
+ }
+ return decodeDrawableImpl(src, listener);
+ }
+
+ @NonNull
+ private static Drawable decodeDrawableImpl(@NonNull Source src,
@Nullable OnHeaderDecodedListener listener) throws IOException {
try (ImageDecoder decoder = src.createImageDecoder()) {
decoder.mSource = src;
@@ -1057,7 +1150,7 @@ public final class ImageDecoder implements AutoCloseable {
return d;
}
- Bitmap bm = decoder.decodeBitmap();
+ Bitmap bm = decoder.decodeBitmapInternal();
bm.setDensity(srcDensity);
Resources res = src.getResources();
@@ -1084,7 +1177,7 @@ public final class ImageDecoder implements AutoCloseable {
@NonNull
public static Drawable decodeDrawable(@NonNull Source src)
throws IOException {
- return decodeDrawable(src, null);
+ return decodeDrawableImpl(src, null);
}
/**
@@ -1092,15 +1185,24 @@ public final class ImageDecoder implements AutoCloseable {
*
* @param src representing the encoded image.
* @param listener for learning the {@link ImageInfo} and changing any
- * default settings on the {@code ImageDecoder}. If not {@code null},
- * this will be called on the same thread as {@code decodeBitmap}
- * before that method returns.
+ * default settings on the {@code ImageDecoder}. This will be called on
+ * the same thread as {@code decodeBitmap} before that method returns.
* @return Bitmap containing the image.
* @throws IOException if {@code src} is not found, is an unsupported
* format, or cannot be decoded for any reason.
*/
@NonNull
public static Bitmap decodeBitmap(@NonNull Source src,
+ @NonNull OnHeaderDecodedListener listener) throws IOException {
+ if (listener == null) {
+ throw new IllegalArgumentException("listener cannot be null! "
+ + "Use decodeBitmap(Source) to not have a listener");
+ }
+ return decodeBitmapImpl(src, listener);
+ }
+
+ @NonNull
+ private static Bitmap decodeBitmapImpl(@NonNull Source src,
@Nullable OnHeaderDecodedListener listener) throws IOException {
try (ImageDecoder decoder = src.createImageDecoder()) {
decoder.mSource = src;
@@ -1109,7 +1211,7 @@ public final class ImageDecoder implements AutoCloseable {
// this call potentially manipulates the decoder so it must be performed prior to
// decoding the bitmap
final int srcDensity = computeDensity(src, decoder);
- Bitmap bm = decoder.decodeBitmap();
+ Bitmap bm = decoder.decodeBitmapInternal();
bm.setDensity(srcDensity);
Rect padding = decoder.mOutPaddingRect;
@@ -1167,7 +1269,7 @@ public final class ImageDecoder implements AutoCloseable {
*/
@NonNull
public static Bitmap decodeBitmap(@NonNull Source src) throws IOException {
- return decodeBitmap(src, null);
+ return decodeBitmapImpl(src, null);
}
/**
@@ -1206,7 +1308,7 @@ public final class ImageDecoder implements AutoCloseable {
int width, int height,
@Nullable Rect cropRect, boolean mutable,
int allocator, boolean requireUnpremul,
- boolean conserveMemory, boolean asAlphaMask)
+ boolean conserveMemory, boolean decodeAsAlphaMask)
throws IOException;
private static native Size nGetSampledSize(long nativePtr,
int sampleSize);
diff --git a/graphics/java/android/graphics/Typeface.java b/graphics/java/android/graphics/Typeface.java
index 38beebde4b14..f27c11dbf735 100644
--- a/graphics/java/android/graphics/Typeface.java
+++ b/graphics/java/android/graphics/Typeface.java
@@ -42,6 +42,10 @@ import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.util.Preconditions;
+import dalvik.annotation.optimization.CriticalNative;
+
+import libcore.util.NativeAllocationRegistry;
+
import org.xmlpull.v1.XmlPullParserException;
import java.io.File;
@@ -71,6 +75,9 @@ public class Typeface {
private static String TAG = "Typeface";
+ private static final NativeAllocationRegistry sRegistry = new NativeAllocationRegistry(
+ Typeface.class.getClassLoader(), nativeGetReleaseFunc(), 64);
+
/** The default NORMAL typeface object */
public static final Typeface DEFAULT;
/**
@@ -911,6 +918,7 @@ public class Typeface {
}
native_instance = ni;
+ sRegistry.registerNativeAllocation(this, native_instance);
mStyle = nativeGetStyle(ni);
mWeight = nativeGetWeight(ni);
}
@@ -1120,16 +1128,6 @@ public class Typeface {
}
@Override
- protected void finalize() throws Throwable {
- try {
- nativeUnref(native_instance);
- native_instance = 0; // Other finalizers can still call us.
- } finally {
- super.finalize();
- }
- }
-
- @Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
@@ -1173,10 +1171,18 @@ public class Typeface {
private static native long nativeCreateFromTypefaceWithVariation(
long native_instance, List<FontVariationAxis> axes);
private static native long nativeCreateWeightAlias(long native_instance, int weight);
- private static native void nativeUnref(long native_instance);
- private static native int nativeGetStyle(long native_instance);
- private static native int nativeGetWeight(long native_instance);
private static native long nativeCreateFromArray(long[] familyArray, int weight, int italic);
- private static native void nativeSetDefault(long native_instance);
private static native int[] nativeGetSupportedAxes(long native_instance);
+
+ @CriticalNative
+ private static native void nativeSetDefault(long nativePtr);
+
+ @CriticalNative
+ private static native int nativeGetStyle(long nativePtr);
+
+ @CriticalNative
+ private static native int nativeGetWeight(long nativePtr);
+
+ @CriticalNative
+ private static native long nativeGetReleaseFunc();
}
diff --git a/graphics/java/android/graphics/drawable/AdaptiveIconDrawable.java b/graphics/java/android/graphics/drawable/AdaptiveIconDrawable.java
index 1d0cfa5ff082..fdd638adba81 100644
--- a/graphics/java/android/graphics/drawable/AdaptiveIconDrawable.java
+++ b/graphics/java/android/graphics/drawable/AdaptiveIconDrawable.java
@@ -44,6 +44,7 @@ import android.util.DisplayMetrics;
import android.util.PathParser;
import com.android.internal.R;
+
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
@@ -668,13 +669,7 @@ public class AdaptiveIconDrawable extends Drawable implements Drawable.Callback
@Override
public void setAlpha(int alpha) {
- final ChildDrawable[] array = mLayerState.mChildren;
- for (int i = 0; i < mLayerState.N_CHILDREN; i++) {
- final Drawable dr = array[i].mDrawable;
- if (dr != null) {
- dr.setAlpha(alpha);
- }
- }
+ mPaint.setAlpha(alpha);
}
@Override
diff --git a/graphics/java/android/graphics/drawable/AnimatedImageDrawable.java b/graphics/java/android/graphics/drawable/AnimatedImageDrawable.java
index f70d6e1223df..c0f49208e27e 100644
--- a/graphics/java/android/graphics/drawable/AnimatedImageDrawable.java
+++ b/graphics/java/android/graphics/drawable/AnimatedImageDrawable.java
@@ -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;
@@ -77,6 +78,7 @@ public class AnimatedImageDrawable extends Drawable implements Animatable2 {
int[] mThemeAttrs = null;
boolean mAutoMirrored = false;
+ int mRepeatCount = REPEAT_UNDEFINED;
}
private State mState;
@@ -86,33 +88,87 @@ public class AnimatedImageDrawable extends Drawable implements Animatable2 {
private ColorFilter mColorFilter;
/**
- * Pass this to {@link #setLoopCount} to loop infinitely.
+ * Pass this to {@link #setRepeatCount} to repeat infinitely.
*
* <p>{@link Animatable2.AnimationCallback#onAnimationEnd} will never be
* called unless there is an error.</p>
*/
- public static final int LOOP_INFINITE = -1;
+ public static final int REPEAT_INFINITE = -1;
+
+ /** @removed
+ * @deprecated Replaced with REPEAT_INFINITE to match other APIs.
+ */
+ @java.lang.Deprecated
+ public static final int LOOP_INFINITE = REPEAT_INFINITE;
+
+ private static final int REPEAT_UNDEFINED = -2;
/**
- * Specify the number of times to loop the animation.
+ * Specify the number of times to repeat the animation.
+ *
+ * <p>By default, the repeat count in the encoded data is respected. If set
+ * to {@link #REPEAT_INFINITE}, the animation will repeat as long as it is
+ * displayed. If the value is {@code 0}, the animation will play once.</p>
*
- * <p>By default, the loop count in the encoded data is respected.</p>
+ * <p>This call replaces the current repeat count. If the encoded data
+ * specified a repeat count of {@code 2} (meaning that
+ * {@link #getRepeatCount()} returns {@code 2}, the animation will play
+ * three times. Calling {@code setRepeatCount(1)} will result in playing only
+ * twice and {@link #getRepeatCount()} returning {@code 1}.</p>
+ *
+ * <p>If the animation is already playing, the iterations that have already
+ * occurred count towards the new count. If the animation has already
+ * repeated the appropriate number of times (or more), it will finish its
+ * current iteration and then stop.</p>
*/
- public void setLoopCount(int loopCount) {
- if (mState.mNativePtr == 0) {
- throw new IllegalStateException("called setLoopCount on empty AnimatedImageDrawable");
+ public void setRepeatCount(@IntRange(from = REPEAT_INFINITE) int repeatCount) {
+ if (repeatCount < REPEAT_INFINITE) {
+ throw new IllegalArgumentException("invalid value passed to setRepeatCount"
+ + repeatCount);
+ }
+ if (mState.mRepeatCount != repeatCount) {
+ mState.mRepeatCount = repeatCount;
+ if (mState.mNativePtr != 0) {
+ nSetRepeatCount(mState.mNativePtr, repeatCount);
+ }
}
- nSetLoopCount(mState.mNativePtr, loopCount);
+ }
+
+ /** @removed
+ * @deprecated Replaced with setRepeatCount to match other APIs.
+ */
+ @java.lang.Deprecated
+ public void setLoopCount(int loopCount) {
+ setRepeatCount(loopCount);
}
/**
- * Retrieve the number of times the animation will loop.
+ * Retrieve the number of times the animation will repeat.
+ *
+ * <p>By default, the repeat count in the encoded data is respected. If the
+ * value is {@link #REPEAT_INFINITE}, the animation will repeat as long as
+ * it is displayed. If the value is {@code 0}, it will play once.</p>
+ *
+ * <p>Calling {@link #setRepeatCount} will make future calls to this method
+ * return the value passed to {@link #setRepeatCount}.</p>
*/
- public int getLoopCount() {
+ public int getRepeatCount() {
if (mState.mNativePtr == 0) {
- throw new IllegalStateException("called getLoopCount on empty AnimatedImageDrawable");
+ throw new IllegalStateException("called getRepeatCount on empty AnimatedImageDrawable");
+ }
+ if (mState.mRepeatCount == REPEAT_UNDEFINED) {
+ mState.mRepeatCount = nGetRepeatCount(mState.mNativePtr);
+
}
- return nGetLoopCount(mState.mNativePtr);
+ return mState.mRepeatCount;
+ }
+
+ /** @removed
+ * @deprecated Replaced with getRepeatCount to match other APIs.
+ */
+ @java.lang.Deprecated
+ public int getLoopCount(int loopCount) {
+ return getRepeatCount();
}
/**
@@ -176,12 +232,18 @@ public class AnimatedImageDrawable extends Drawable implements Animatable2 {
": <animated-image> did not decode animated");
}
+ // This may have previously been set without a src if we were waiting for a
+ // theme.
+ final int repeatCount = mState.mRepeatCount;
// Transfer the state of other to this one. other will be discarded.
AnimatedImageDrawable other = (AnimatedImageDrawable) drawable;
mState = other.mState;
other.mState = null;
mIntrinsicWidth = other.mIntrinsicWidth;
mIntrinsicHeight = other.mIntrinsicHeight;
+ if (repeatCount != REPEAT_UNDEFINED) {
+ this.setRepeatCount(repeatCount);
+ }
}
mState.mThemeAttrs = a.extractThemeAttrs();
@@ -193,6 +255,12 @@ public class AnimatedImageDrawable extends Drawable implements Animatable2 {
mState.mAutoMirrored = a.getBoolean(
R.styleable.AnimatedImageDrawable_autoMirrored, oldState.mAutoMirrored);
+
+ int repeatCount = a.getInt(
+ R.styleable.AnimatedImageDrawable_repeatCount, REPEAT_UNDEFINED);
+ if (repeatCount != REPEAT_UNDEFINED) {
+ this.setRepeatCount(repeatCount);
+ }
}
/**
@@ -271,7 +339,7 @@ public class AnimatedImageDrawable extends Drawable implements Animatable2 {
}
@Override
- public void setAlpha(@IntRange(from=0,to=255) int alpha) {
+ public void setAlpha(@IntRange(from = 0, to = 255) int alpha) {
if (alpha < 0 || alpha > 255) {
throw new IllegalArgumentException("Alpha must be between 0 and"
+ " 255! provided " + alpha);
@@ -322,11 +390,25 @@ 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;
}
@@ -508,9 +590,9 @@ public class AnimatedImageDrawable extends Drawable implements Animatable2 {
@FastNative
private static native boolean nStop(long nativePtr);
@FastNative
- private static native int nGetLoopCount(long nativePtr);
+ private static native int nGetRepeatCount(long nativePtr);
@FastNative
- private static native void nSetLoopCount(long nativePtr, int loopCount);
+ private static native void nSetRepeatCount(long nativePtr, int repeatCount);
// Pass the drawable down to native so it can call onAnimationEnd.
private static native void nSetOnAnimationEndListener(long nativePtr,
@Nullable AnimatedImageDrawable drawable);
@@ -518,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);
}