diff options
author | Jean-Baptiste Queru <jbq@google.com> | 2009-07-21 11:16:54 -0700 |
---|---|---|
committer | Jean-Baptiste Queru <jbq@google.com> | 2009-07-21 11:16:54 -0700 |
commit | cf4550c3198d6b3d92cdc52707fe70d7cc0caa9f (patch) | |
tree | 6510f35ad004f1a4640b48264c290926e8596d7a /graphics | |
parent | 4cf03d381b2dff908857fceff0bec445f8d44f36 (diff) | |
download | frameworks_base-cf4550c3198d6b3d92cdc52707fe70d7cc0caa9f.zip frameworks_base-cf4550c3198d6b3d92cdc52707fe70d7cc0caa9f.tar.gz frameworks_base-cf4550c3198d6b3d92cdc52707fe70d7cc0caa9f.tar.bz2 |
donut snapshot
Diffstat (limited to 'graphics')
10 files changed, 471 insertions, 75 deletions
diff --git a/graphics/java/android/graphics/Bitmap.java b/graphics/java/android/graphics/Bitmap.java index fda584d..e2e93eb 100644 --- a/graphics/java/android/graphics/Bitmap.java +++ b/graphics/java/android/graphics/Bitmap.java @@ -16,14 +16,14 @@ package android.graphics; -import android.os.Parcelable; import android.os.Parcel; +import android.os.Parcelable; +import java.io.OutputStream; import java.nio.Buffer; import java.nio.ByteBuffer; -import java.nio.ShortBuffer; import java.nio.IntBuffer; -import java.io.OutputStream; +import java.nio.ShortBuffer; public final class Bitmap implements Parcelable { /** @@ -32,14 +32,14 @@ public final class Bitmap implements Parcelable { * @see Bitmap#getDensityScale() * @see Bitmap#setDensityScale(float) * - * @hide pending API council approval + * @hide pending API council approval */ public static final float DENSITY_SCALE_UNKNOWN = -1.0f; // Note: mNativeBitmap is used by FaceDetector_jni.cpp // Don't change/rename without updating FaceDetector_jni.cpp private final int mNativeBitmap; - + private final boolean mIsMutable; private byte[] mNinePatchChunk; // may be null private int mWidth = -1; @@ -63,7 +63,7 @@ public final class Bitmap implements Parcelable { if (nativeBitmap == 0) { throw new RuntimeException("internal error: native bitmap is 0"); } - + // we delete this in our finalizer mNativeBitmap = nativeBitmap; mIsMutable = isMutable; @@ -83,7 +83,7 @@ public final class Bitmap implements Parcelable { * * @see #setDensityScale(float) * @see #isAutoScalingEnabled() - * @see #setAutoScalingEnabled(boolean) + * @see #setAutoScalingEnabled(boolean) * @see android.util.DisplayMetrics#DEFAULT_DENSITY * @see android.util.DisplayMetrics#density * @see #DENSITY_SCALE_UNKNOWN @@ -105,7 +105,7 @@ public final class Bitmap implements Parcelable { * * @see #getDensityScale() * @see #isAutoScalingEnabled() - * @see #setAutoScalingEnabled(boolean) + * @see #setAutoScalingEnabled(boolean) * @see android.util.DisplayMetrics#DEFAULT_DENSITY * @see android.util.DisplayMetrics#density * @see #DENSITY_SCALE_UNKNOWN @@ -126,7 +126,7 @@ public final class Bitmap implements Parcelable { * <p>Auto scaling is turned off by default. If auto scaling is enabled but the * bitmap has an unknown density scale, then the bitmap will never be automatically * scaled at drawing time.</p> - * + * * @return True if the bitmap must be scaled at drawing time, false otherwise. * * @see #setAutoScalingEnabled(boolean) @@ -167,7 +167,7 @@ public final class Bitmap implements Parcelable { public void setNinePatchChunk(byte[] chunk) { mNinePatchChunk = chunk; } - + /** * Free up the memory associated with this bitmap's pixels, and mark the * bitmap as "dead", meaning it will throw an exception if getPixels() or @@ -194,7 +194,7 @@ public final class Bitmap implements Parcelable { public final boolean isRecycled() { return mRecycled; } - + /** * This is called by methods that want to throw an exception if the bitmap * has already been recycled. @@ -204,7 +204,7 @@ public final class Bitmap implements Parcelable { throw new IllegalStateException(errorMessage); } } - + /** * Common code for checking that x and y are >= 0 * @@ -246,16 +246,16 @@ public final class Bitmap implements Parcelable { this.nativeInt = ni; } final int nativeInt; - + /* package */ static Config nativeToConfig(int ni) { return sConfigs[ni]; } - + private static Config sConfigs[] = { null, null, ALPHA_8, null, RGB_565, ARGB_4444, ARGB_8888 }; } - + /** * Copy the bitmap's pixels into the specified buffer (allocated by the * caller). An exception is thrown if the buffer is not large enough to @@ -275,16 +275,16 @@ public final class Bitmap implements Parcelable { } else { throw new RuntimeException("unsupported Buffer subclass"); } - + long bufferSize = (long)elements << shift; long pixelSize = (long)getRowBytes() * getHeight(); - + if (bufferSize < pixelSize) { throw new RuntimeException("Buffer not large enough for pixels"); } - + nativeCopyPixelsToBuffer(mNativeBitmap, dst); - + // now update the buffer's position int position = dst.position(); position += pixelSize >> shift; @@ -299,7 +299,7 @@ public final class Bitmap implements Parcelable { */ public void copyPixelsFromBuffer(Buffer src) { checkRecycled("copyPixelsFromBuffer called on recycled bitmap"); - + int elements = src.remaining(); int shift; if (src instanceof ByteBuffer) { @@ -311,17 +311,17 @@ public final class Bitmap implements Parcelable { } else { throw new RuntimeException("unsupported Buffer subclass"); } - + long bufferBytes = (long)elements << shift; long bitmapBytes = (long)getRowBytes() * getHeight(); - + if (bufferBytes < bitmapBytes) { throw new RuntimeException("Buffer not large enough for pixels"); } - + nativeCopyPixelsFromBuffer(mNativeBitmap, src); } - + /** * Tries to make a new bitmap based on the dimensions of this bitmap, * setting the new bitmap's config to the one specified, and then copying @@ -350,7 +350,7 @@ public final class Bitmap implements Parcelable { if (m == null) { m = new Matrix(); } - + final int width = src.getWidth(); final int height = src.getHeight(); final float sx = dstWidth / (float)width; @@ -365,9 +365,9 @@ public final class Bitmap implements Parcelable { } } - return b; + return b; } - + /** * Returns an immutable bitmap from the source bitmap. The new bitmap may * be the same object as source, or a copy may have been made. @@ -390,7 +390,7 @@ public final class Bitmap implements Parcelable { public static Bitmap createBitmap(Bitmap source, int x, int y, int width, int height) { return createBitmap(source, x, y, width, height, null, false); } - + /** * Returns an immutable bitmap from subset of the source bitmap, * transformed by the optional matrix. @@ -425,7 +425,7 @@ public final class Bitmap implements Parcelable { height == source.getHeight() && (m == null || m.isIdentity())) { return source; } - + int neww = width; int newh = height; Canvas canvas = new Canvas(); @@ -470,7 +470,7 @@ public final class Bitmap implements Parcelable { return bitmap; } - + /** * Returns a mutable bitmap with the specified width and height. * @@ -484,7 +484,7 @@ public final class Bitmap implements Parcelable { bm.eraseColor(0); // start with black/transparent pixels return bm; } - + /** * Returns a immutable bitmap with the specified width and height, with each * pixel value set to the corresponding value in the colors array. @@ -593,7 +593,7 @@ public final class Bitmap implements Parcelable { return nativeCompress(mNativeBitmap, format.nativeInt, quality, stream, new byte[WORKING_COMPRESS_STORAGE]); } - + /** * Returns true if the bitmap is marked as mutable (i.e. can be drawn into) */ @@ -610,7 +610,7 @@ public final class Bitmap implements Parcelable { public final int getHeight() { return mHeight == -1 ? mHeight = nativeHeight(mNativeBitmap) : mHeight; } - + /** * Convenience method that returns the width of this bitmap divided * by the density scale factor. @@ -648,7 +648,7 @@ public final class Bitmap implements Parcelable { public final int getRowBytes() { return nativeRowBytes(mNativeBitmap); } - + /** * If the bitmap's internal config is in one of the public formats, return * that config, otherwise return null. @@ -690,7 +690,7 @@ public final class Bitmap implements Parcelable { checkPixelAccess(x, y); return nativeGetPixel(mNativeBitmap, x, y); } - + /** * Returns in pixels[] a copy of the data in the bitmap. Each value is * a packed int representing a {@link Color}. The stride parameter allows @@ -722,7 +722,7 @@ public final class Bitmap implements Parcelable { nativeGetPixels(mNativeBitmap, pixels, offset, stride, x, y, width, height); } - + /** * Shared code to check for illegal arguments passed to getPixel() * or setPixel() @@ -779,7 +779,7 @@ public final class Bitmap implements Parcelable { throw new ArrayIndexOutOfBoundsException(); } } - + /** * Write the specified {@link Color} into the bitmap (assuming it is * mutable) at the x,y coordinate. @@ -799,10 +799,10 @@ public final class Bitmap implements Parcelable { checkPixelAccess(x, y); nativeSetPixel(mNativeBitmap, x, y, color); } - + /** * Replace pixels in the bitmap with the colors in the array. Each element - * in the array is a packed int prepresenting a {@link Color} + * in the array is a packed int prepresenting a {@link Color} * * @param pixels The colors to write to the bitmap * @param offset The index of the first color to read from pixels[] @@ -834,7 +834,7 @@ public final class Bitmap implements Parcelable { nativeSetPixels(mNativeBitmap, pixels, offset, stride, x, y, width, height); } - + public static final Parcelable.Creator<Bitmap> CREATOR = new Parcelable.Creator<Bitmap>() { /** @@ -884,7 +884,7 @@ public final class Bitmap implements Parcelable { public Bitmap extractAlpha() { return extractAlpha(null, null); } - + /** * Returns a new bitmap that captures the alpha values of the original. * These values may be affected by the optional Paint parameter, which @@ -917,6 +917,22 @@ public final class Bitmap implements Parcelable { return bm; } + /** + * Rebuilds any caches associated with the bitmap that are used for + * drawing it. In the case of purgeable bitmaps, this call will attempt to + * ensure that the pixels have been decoded. + * If this is called on more than one bitmap in sequence, the priority is + * given in LRU order (i.e. the last bitmap called will be given highest + * priority). + * + * For bitmaps with no associated caches, this call is effectively a no-op, + * and therefore is harmless. + */ + public void prepareToDraw() { + nativePrepareToDraw(mNativeBitmap); + } + + @Override protected void finalize() throws Throwable { try { nativeDestructor(mNativeBitmap); @@ -924,7 +940,7 @@ public final class Bitmap implements Parcelable { super.finalize(); } } - + //////////// native methods private static native Bitmap nativeCreate(int[] colors, int offset, @@ -944,12 +960,12 @@ public final class Bitmap implements Parcelable { private static native int nativeRowBytes(int nativeBitmap); private static native int nativeConfig(int nativeBitmap); private static native boolean nativeHasAlpha(int nativeBitmap); - + private static native int nativeGetPixel(int nativeBitmap, int x, int y); private static native void nativeGetPixels(int nativeBitmap, int[] pixels, int offset, int stride, int x, int y, int width, int height); - + private static native void nativeSetPixel(int nativeBitmap, int x, int y, int color); private static native void nativeSetPixels(int nativeBitmap, int[] colors, @@ -969,6 +985,8 @@ public final class Bitmap implements Parcelable { int nativePaint, int[] offsetXY); + private static native void nativePrepareToDraw(int nativeBitmap); + /* package */ final int ni() { return mNativeBitmap; } diff --git a/graphics/java/android/graphics/BitmapFactory.java b/graphics/java/android/graphics/BitmapFactory.java index 9e88d7e..e5a9aab 100644 --- a/graphics/java/android/graphics/BitmapFactory.java +++ b/graphics/java/android/graphics/BitmapFactory.java @@ -18,18 +18,18 @@ package android.graphics; import android.content.res.AssetManager; import android.content.res.Resources; -import android.util.TypedValue; import android.util.DisplayMetrics; +import android.util.TypedValue; import java.io.BufferedInputStream; +import java.io.FileDescriptor; import java.io.FileInputStream; -import java.io.InputStream; import java.io.IOException; -import java.io.FileDescriptor; +import java.io.InputStream; /** - * Creates Bitmap objects from various sources, including files, streams, - * and byte-arrays. + * Creates Bitmap objects from various sources, including files, streams, + * and byte-arrays. */ public class BitmapFactory { public static class Options { @@ -62,7 +62,7 @@ public class BitmapFactory { * Also, powers of 2 are often faster/easier for the decoder to honor. */ public int inSampleSize; - + /** * If this is non-null, the decoder will try to decode into this * internal configuration. If it is null, or the request cannot be met, @@ -71,7 +71,7 @@ public class BitmapFactory { * as if it has per-pixel alpha (requiring a config that also does). */ public Bitmap.Config inPreferredConfig; - + /** * If dither is true, the decoder will atttempt to dither the decoded * image. @@ -117,8 +117,6 @@ public class BitmapFactory { * explicitly make a copy of the input data, and keep that. Even if * sharing is allowed, the implementation may still decide to make a * deep copy of the input data. - * - * @hide pending API council approval */ public boolean inPurgeable; @@ -127,8 +125,6 @@ public class BitmapFactory { * false, then this field is ignored. If inPurgeable is true, then this * field determines whether the bitmap can share a reference to the * input data (inputstream, array, etc.) or if it must make a deep copy. - * - * @hide pending API council approval */ public boolean inInputShareable; @@ -151,12 +147,12 @@ public class BitmapFactory { * If not know, or there is an error, it is set to null. */ public String outMimeType; - + /** * Temp storage to use for decoding. Suggest 16K or so. */ public byte[] inTempStorage; - + private native void requestCancel(); /** @@ -167,7 +163,7 @@ public class BitmapFactory { * if the operation is canceled. */ public boolean mCancel; - + /** * This can be called from another thread while this options object is * inside a decode... call. Calling this will notify the decoder that @@ -249,7 +245,7 @@ public class BitmapFactory { if (opts.inDensity == 0) { opts.inDensity = density == TypedValue.DENSITY_DEFAULT ? DisplayMetrics.DEFAULT_DENSITY : density; - } + } float scale = opts.inDensity / (float) DisplayMetrics.DEFAULT_DENSITY; if (opts.inScaled || isNinePatch) { @@ -291,7 +287,7 @@ public class BitmapFactory { */ public static Bitmap decodeResource(Resources res, int id, Options opts) { Bitmap bm = null; - + try { final TypedValue value = new TypedValue(); final InputStream is = res.openRawResource(id, value); @@ -306,7 +302,7 @@ public class BitmapFactory { } return bm; } - + /** * Decode an image referenced by a resource ID. * @@ -337,7 +333,7 @@ public class BitmapFactory { } return nativeDecodeByteArray(data, offset, length, opts); } - + /** * Decode an immutable bitmap from the specified byte array. * @@ -350,13 +346,13 @@ public class BitmapFactory { public static Bitmap decodeByteArray(byte[] data, int offset, int length) { return decodeByteArray(data, offset, length, null); } - + /** * Decode an input stream into a bitmap. If the input stream is null, or * cannot be used to decode a bitmap, the function returns null. * The stream's position will be where ever it was after the encoded data * was read. - * + * * @param is The input stream that holds the raw data to be decoded into a * bitmap. * @param outPadding If not null, return the padding rect for the bitmap if @@ -375,7 +371,7 @@ public class BitmapFactory { if (is == null) { return null; } - + // we need mark/reset to work properly if (!is.markSupported()) { @@ -413,7 +409,7 @@ public class BitmapFactory { * cannot be used to decode a bitmap, the function returns null. * The stream's position will be where ever it was after the encoded data * was read. - * + * * @param is The input stream that holds the raw data to be decoded into a * bitmap. * @return The decoded bitmap, or null if the image data could not be @@ -441,7 +437,7 @@ public class BitmapFactory { public static Bitmap decodeFileDescriptor(FileDescriptor fd, Rect outPadding, Options opts) { return nativeDecodeFileDescriptor(fd, outPadding, opts); } - + /** * Decode a bitmap from the file descriptor. If the bitmap cannot be decoded * return null. The position within the descriptor will not be changed when @@ -453,7 +449,7 @@ public class BitmapFactory { public static Bitmap decodeFileDescriptor(FileDescriptor fd) { return nativeDecodeFileDescriptor(fd, null, null); } - + private static native Bitmap nativeDecodeStream(InputStream is, byte[] storage, Rect padding, Options opts); private static native Bitmap nativeDecodeFileDescriptor(FileDescriptor fd, diff --git a/graphics/java/android/graphics/Canvas.java b/graphics/java/android/graphics/Canvas.java index 06d53e3..4498e1a 100644 --- a/graphics/java/android/graphics/Canvas.java +++ b/graphics/java/android/graphics/Canvas.java @@ -1404,7 +1404,11 @@ public class Canvas { protected void finalize() throws Throwable { super.finalize(); - finalizer(mNativeCanvas); + // If the constructor threw an exception before setting mNativeCanvas, the native finalizer + // must not be invoked. + if (mNativeCanvas != 0) { + finalizer(mNativeCanvas); + } } /** diff --git a/graphics/java/android/graphics/NinePatch.java b/graphics/java/android/graphics/NinePatch.java index 2b24ef2..778c903 100644 --- a/graphics/java/android/graphics/NinePatch.java +++ b/graphics/java/android/graphics/NinePatch.java @@ -57,7 +57,9 @@ public class NinePatch { mBitmap = patch.mBitmap; mChunk = patch.mChunk; mSrcName = patch.mSrcName; - mPaint = new Paint(patch.mPaint); + if (patch.mPaint != null) { + mPaint = new Paint(patch.mPaint); + } validateNinePatchChunk(mBitmap.ni(), mChunk); } @@ -120,7 +122,6 @@ public class NinePatch { public native static boolean isNinePatchChunk(byte[] chunk); - private final Rect mRect = new Rect(); private final Bitmap mBitmap; private final byte[] mChunk; private Paint mPaint; diff --git a/graphics/java/android/graphics/drawable/Animatable.java b/graphics/java/android/graphics/drawable/Animatable.java new file mode 100644 index 0000000..9dc62c3 --- /dev/null +++ b/graphics/java/android/graphics/drawable/Animatable.java @@ -0,0 +1,39 @@ +/* + * Copyright (C) 2009 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.graphics.drawable; + +/** + * Interface that drawables suporting animations should implement. + */ +public interface Animatable { + /** + * Starts the drawable's animation. + */ + void start(); + + /** + * Stops the drawable's animation. + */ + void stop(); + + /** + * Indicates whether the animation is running. + * + * @return True if the animation is running, false otherwise. + */ + boolean isRunning(); +} diff --git a/graphics/java/android/graphics/drawable/AnimatedRotateDrawable.java b/graphics/java/android/graphics/drawable/AnimatedRotateDrawable.java new file mode 100644 index 0000000..ac96f20 --- /dev/null +++ b/graphics/java/android/graphics/drawable/AnimatedRotateDrawable.java @@ -0,0 +1,332 @@ +/* + * Copyright (C) 2009 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.graphics.drawable; + +import android.graphics.Canvas; +import android.graphics.Rect; +import android.graphics.ColorFilter; +import android.content.res.Resources; +import android.content.res.TypedArray; +import android.util.AttributeSet; +import android.util.TypedValue; +import android.util.Log; +import android.os.SystemClock; +import org.xmlpull.v1.XmlPullParser; +import org.xmlpull.v1.XmlPullParserException; + +import java.io.IOException; + +import com.android.internal.R; + +/** + * @hide + */ +public class AnimatedRotateDrawable extends Drawable implements Drawable.Callback, Runnable, + Animatable { + + private AnimatedRotateState mState; + private boolean mMutated; + private float mCurrentDegrees; + private float mIncrement; + private boolean mRunning; + + public AnimatedRotateDrawable() { + this(null); + } + + private AnimatedRotateDrawable(AnimatedRotateState rotateState) { + mState = new AnimatedRotateState(rotateState, this); + init(); + } + + private void init() { + final AnimatedRotateState state = mState; + mIncrement = 360.0f / (float) state.mFramesCount; + final Drawable drawable = state.mDrawable; + if (drawable != null) { + drawable.setFilterBitmap(true); + if (drawable instanceof BitmapDrawable) { + ((BitmapDrawable) drawable).setAntiAlias(true); + } + } + } + + public void draw(Canvas canvas) { + int saveCount = canvas.save(); + + final AnimatedRotateState st = mState; + final Drawable drawable = st.mDrawable; + final Rect bounds = drawable.getBounds(); + + int w = bounds.right - bounds.left; + int h = bounds.bottom - bounds.top; + + float px = st.mPivotXRel ? (w * st.mPivotX) : st.mPivotX; + float py = st.mPivotYRel ? (h * st.mPivotY) : st.mPivotY; + + canvas.rotate(mCurrentDegrees, px, py); + + drawable.draw(canvas); + + canvas.restoreToCount(saveCount); + } + + public void start() { + if (!mRunning) { + mRunning = true; + nextFrame(); + } + } + + public void stop() { + mRunning = false; + unscheduleSelf(this); + } + + public boolean isRunning() { + return mRunning; + } + + private void nextFrame() { + unscheduleSelf(this); + scheduleSelf(this, SystemClock.uptimeMillis() + mState.mFrameDuration); + } + + public void run() { + // TODO: This should be computed in draw(Canvas), based on the amount + // of time since the last frame drawn + mCurrentDegrees += mIncrement; + if (mCurrentDegrees > (360.0f - mIncrement)) { + mCurrentDegrees = 0.0f; + } + invalidateSelf(); + nextFrame(); + } + + @Override + public boolean setVisible(boolean visible, boolean restart) { + mState.mDrawable.setVisible(visible, restart); + boolean changed = super.setVisible(visible, restart); + if (visible) { + if (changed || restart) { + mCurrentDegrees = 0.0f; + nextFrame(); + } + } else { + unscheduleSelf(this); + } + return changed; + } + + /** + * Returns the drawable rotated by this RotateDrawable. + */ + public Drawable getDrawable() { + return mState.mDrawable; + } + + @Override + public int getChangingConfigurations() { + return super.getChangingConfigurations() + | mState.mChangingConfigurations + | mState.mDrawable.getChangingConfigurations(); + } + + public void setAlpha(int alpha) { + mState.mDrawable.setAlpha(alpha); + } + + public void setColorFilter(ColorFilter cf) { + mState.mDrawable.setColorFilter(cf); + } + + public int getOpacity() { + return mState.mDrawable.getOpacity(); + } + + public void invalidateDrawable(Drawable who) { + if (mCallback != null) { + mCallback.invalidateDrawable(this); + } + } + + public void scheduleDrawable(Drawable who, Runnable what, long when) { + if (mCallback != null) { + mCallback.scheduleDrawable(this, what, when); + } + } + + public void unscheduleDrawable(Drawable who, Runnable what) { + if (mCallback != null) { + mCallback.unscheduleDrawable(this, what); + } + } + + @Override + public boolean getPadding(Rect padding) { + return mState.mDrawable.getPadding(padding); + } + + @Override + public boolean isStateful() { + return mState.mDrawable.isStateful(); + } + + @Override + protected void onBoundsChange(Rect bounds) { + mState.mDrawable.setBounds(bounds.left, bounds.top, bounds.right, bounds.bottom); + } + + @Override + public int getIntrinsicWidth() { + return mState.mDrawable.getIntrinsicWidth(); + } + + @Override + public int getIntrinsicHeight() { + return mState.mDrawable.getIntrinsicHeight(); + } + + @Override + public ConstantState getConstantState() { + if (mState.canConstantState()) { + mState.mChangingConfigurations = super.getChangingConfigurations(); + return mState; + } + return null; + } + + @Override + public void inflate(Resources r, XmlPullParser parser, AttributeSet attrs) + throws XmlPullParserException, IOException { + + final TypedArray a = r.obtainAttributes(attrs, R.styleable.AnimatedRotateDrawable); + + super.inflateWithAttributes(r, parser, a, R.styleable.AnimatedRotateDrawable_visible); + + TypedValue tv = a.peekValue(R.styleable.AnimatedRotateDrawable_pivotX); + final boolean pivotXRel = tv.type == TypedValue.TYPE_FRACTION; + final float pivotX = pivotXRel ? tv.getFraction(1.0f, 1.0f) : tv.getFloat(); + + tv = a.peekValue(R.styleable.AnimatedRotateDrawable_pivotY); + final boolean pivotYRel = tv.type == TypedValue.TYPE_FRACTION; + final float pivotY = pivotYRel ? tv.getFraction(1.0f, 1.0f) : tv.getFloat(); + + final int framesCount = a.getInt(R.styleable.AnimatedRotateDrawable_framesCount, 12); + final int frameDuration = a.getInt(R.styleable.AnimatedRotateDrawable_frameDuration, 150); + + final int res = a.getResourceId(R.styleable.AnimatedRotateDrawable_drawable, 0); + Drawable drawable = null; + if (res > 0) { + drawable = r.getDrawable(res); + } + + a.recycle(); + + int outerDepth = parser.getDepth(); + int type; + while ((type = parser.next()) != XmlPullParser.END_DOCUMENT && + (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) { + + if (type != XmlPullParser.START_TAG) { + continue; + } + + if ((drawable = Drawable.createFromXmlInner(r, parser, attrs)) == null) { + Log.w("drawable", "Bad element under <animated-rotate>: " + + parser .getName()); + } + } + + if (drawable == null) { + Log.w("drawable", "No drawable specified for <animated-rotate>"); + } + + final AnimatedRotateState rotateState = mState; + rotateState.mDrawable = drawable; + rotateState.mPivotXRel = pivotXRel; + rotateState.mPivotX = pivotX; + rotateState.mPivotYRel = pivotYRel; + rotateState.mPivotY = pivotY; + rotateState.mFramesCount = framesCount; + rotateState.mFrameDuration = frameDuration; + + init(); + + if (drawable != null) { + drawable.setCallback(this); + } + } + + @Override + public Drawable mutate() { + if (!mMutated && super.mutate() == this) { + mState.mDrawable.mutate(); + mMutated = true; + } + return this; + } + + final static class AnimatedRotateState extends Drawable.ConstantState { + Drawable mDrawable; + + int mChangingConfigurations; + + boolean mPivotXRel; + float mPivotX; + boolean mPivotYRel; + float mPivotY; + int mFrameDuration; + int mFramesCount; + + private boolean mCanConstantState; + private boolean mCheckedConstantState; + + public AnimatedRotateState(AnimatedRotateState source, AnimatedRotateDrawable owner) { + if (source != null) { + mDrawable = source.mDrawable.getConstantState().newDrawable(); + mDrawable.setCallback(owner); + mPivotXRel = source.mPivotXRel; + mPivotX = source.mPivotX; + mPivotYRel = source.mPivotYRel; + mPivotY = source.mPivotY; + mFramesCount = source.mFramesCount; + mFrameDuration = source.mFrameDuration; + mCanConstantState = mCheckedConstantState = true; + } + } + + @Override + public Drawable newDrawable() { + return new AnimatedRotateDrawable(this); + } + + @Override + public int getChangingConfigurations() { + return mChangingConfigurations; + } + + public boolean canConstantState() { + if (!mCheckedConstantState) { + mCanConstantState = mDrawable.getConstantState() != null; + mCheckedConstantState = true; + } + + return mCanConstantState; + } + } +} diff --git a/graphics/java/android/graphics/drawable/AnimationDrawable.java b/graphics/java/android/graphics/drawable/AnimationDrawable.java index bab1703..68718c9 100644 --- a/graphics/java/android/graphics/drawable/AnimationDrawable.java +++ b/graphics/java/android/graphics/drawable/AnimationDrawable.java @@ -71,7 +71,7 @@ import android.util.AttributeSet; * @attr ref android.R.styleable#AnimationDrawableItem_duration * @attr ref android.R.styleable#AnimationDrawableItem_drawable */ -public class AnimationDrawable extends DrawableContainer implements Runnable { +public class AnimationDrawable extends DrawableContainer implements Runnable, Animatable { private final AnimationState mAnimationState; private int mCurFrame = -1; private boolean mMutated; diff --git a/graphics/java/android/graphics/drawable/Drawable.java b/graphics/java/android/graphics/drawable/Drawable.java index f0d49f5..910e111 100644 --- a/graphics/java/android/graphics/drawable/Drawable.java +++ b/graphics/java/android/graphics/drawable/Drawable.java @@ -745,6 +745,8 @@ public abstract class Drawable { drawable = new ClipDrawable(); } else if (name.equals("rotate")) { drawable = new RotateDrawable(); + } else if (name.equals("animated-rotate")) { + drawable = new AnimatedRotateDrawable(); } else if (name.equals("animation-list")) { drawable = new AnimationDrawable(); } else if (name.equals("inset")) { diff --git a/graphics/java/android/graphics/drawable/DrawableContainer.java b/graphics/java/android/graphics/drawable/DrawableContainer.java index f8b88d0..376b1df 100644 --- a/graphics/java/android/graphics/drawable/DrawableContainer.java +++ b/graphics/java/android/graphics/drawable/DrawableContainer.java @@ -234,8 +234,10 @@ public class DrawableContainer extends Drawable implements Drawable.Callback { @Override public Drawable mutate() { if (!mMutated && super.mutate() == this) { - for (Drawable child : mDrawableContainerState.mDrawables) { - child.mutate(); + final int N = mDrawableContainerState.getChildCount(); + final Drawable[] drawables = mDrawableContainerState.getChildren(); + for (int i = 0; i < N; i++) { + drawables[i].mutate(); } mMutated = true; } diff --git a/graphics/java/android/graphics/drawable/GradientDrawable.java b/graphics/java/android/graphics/drawable/GradientDrawable.java index 3db45f0..a7a8708 100644 --- a/graphics/java/android/graphics/drawable/GradientDrawable.java +++ b/graphics/java/android/graphics/drawable/GradientDrawable.java @@ -880,7 +880,9 @@ public class GradientDrawable extends Drawable { mShape = state.mShape; mGradient = state.mGradient; mOrientation = state.mOrientation; - mColors = state.mColors.clone(); + if (state.mColors != null) { + mColors = state.mColors.clone(); + } if (state.mPositions != null) { mPositions = state.mPositions.clone(); } |