diff options
author | Jean-Baptiste Queru <jbq@google.com> | 2009-07-25 19:52:22 -0700 |
---|---|---|
committer | Jean-Baptiste Queru <jbq@google.com> | 2009-07-25 21:15:25 -0700 |
commit | 2af1b3db3d4f687d008db74b150f149e956b4bc6 (patch) | |
tree | 39d7d5bf15667c01f9b6dfe02bdd0e7fa36cd303 /graphics | |
parent | 8ecb36eec61f119f500a805b82438aadb3396a19 (diff) | |
parent | cf4550c3198d6b3d92cdc52707fe70d7cc0caa9f (diff) | |
download | frameworks_base-2af1b3db3d4f687d008db74b150f149e956b4bc6.zip frameworks_base-2af1b3db3d4f687d008db74b150f149e956b4bc6.tar.gz frameworks_base-2af1b3db3d4f687d008db74b150f149e956b4bc6.tar.bz2 |
Merge korg/donut into korg/master
Diffstat (limited to 'graphics')
-rw-r--r-- | graphics/java/android/graphics/Bitmap.java | 108 | ||||
-rw-r--r-- | graphics/java/android/graphics/BitmapFactory.java | 66 | ||||
-rw-r--r-- | graphics/java/android/graphics/Canvas.java | 18 | ||||
-rw-r--r-- | graphics/java/android/graphics/Matrix.java | 44 | ||||
-rw-r--r-- | graphics/java/android/graphics/NinePatch.java | 5 | ||||
-rw-r--r-- | graphics/java/android/graphics/Paint.java | 5 | ||||
-rw-r--r-- | graphics/java/android/graphics/Rect.java | 45 | ||||
-rw-r--r-- | graphics/java/android/graphics/Region.java | 33 | ||||
-rw-r--r-- | graphics/java/android/graphics/Typeface.java | 32 | ||||
-rw-r--r-- | graphics/java/android/graphics/drawable/Animatable.java | 39 | ||||
-rw-r--r-- | graphics/java/android/graphics/drawable/AnimatedRotateDrawable.java | 332 | ||||
-rw-r--r-- | graphics/java/android/graphics/drawable/AnimationDrawable.java | 2 | ||||
-rw-r--r-- | graphics/java/android/graphics/drawable/Drawable.java | 109 | ||||
-rw-r--r-- | graphics/java/android/graphics/drawable/DrawableContainer.java | 72 | ||||
-rw-r--r-- | graphics/java/android/graphics/drawable/GradientDrawable.java | 4 |
15 files changed, 739 insertions, 175 deletions
diff --git a/graphics/java/android/graphics/Bitmap.java b/graphics/java/android/graphics/Bitmap.java index 0b398bc..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. @@ -400,7 +400,7 @@ public final class Bitmap implements Parcelable { * @param y The y coordinate of the first pixel in source * @param width The number of pixels in each row * @param height The number of rows - * @param m Option matrix to be applied to the pixels + * @param m Optional matrix to be applied to the pixels * @param filter true if the source should be filtered. * Only applies if the matrix contains more than just * translation. @@ -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 3813d8f..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. @@ -103,6 +103,32 @@ public class BitmapFactory { public boolean inScaled; /** + * If this is set to true, then the resulting bitmap will allocate its + * pixels such that they can be purged if the system needs to reclaim + * memory. In that instance, when the pixels need to be accessed again + * (e.g. the bitmap is drawn, getPixels() is called), they will be + * automatically re-decoded. + * + * For the re-decode to happen, the bitmap must have access to the + * encoded data, either by sharing a reference to the input + * or by making a copy of it. This distinction is controlled by + * inInputShareable. If this is true, then the bitmap may keep a shallow + * reference to the input. If this is false, then the bitmap will + * 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. + */ + public boolean inPurgeable; + + /** + * This field works in conjuction with inPurgeable. If inPurgeable is + * 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. + */ + public boolean inInputShareable; + + /** * The resulting width of the bitmap, set independent of the state of * inJustDecodeBounds. However, if there is an error trying to decode, * outWidth will be set to -1. @@ -121,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(); /** @@ -137,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 @@ -219,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) { @@ -261,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); @@ -276,7 +302,7 @@ public class BitmapFactory { } return bm; } - + /** * Decode an image referenced by a resource ID. * @@ -307,7 +333,7 @@ public class BitmapFactory { } return nativeDecodeByteArray(data, offset, length, opts); } - + /** * Decode an immutable bitmap from the specified byte array. * @@ -320,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 @@ -345,7 +371,7 @@ public class BitmapFactory { if (is == null) { return null; } - + // we need mark/reset to work properly if (!is.markSupported()) { @@ -383,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 @@ -411,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 @@ -423,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 32ecd9f..4498e1a 100644 --- a/graphics/java/android/graphics/Canvas.java +++ b/graphics/java/android/graphics/Canvas.java @@ -112,7 +112,9 @@ public class Canvas { * on behalf of the Canvas. Any subsequent drawing with a GL-backed Canvas * will have to recreate those resources. */ - public static native void freeGlCaches(); + public static void freeGlCaches() { + freeCaches(); + } /** * Specify a bitmap for the canvas to draw into. @@ -1402,9 +1404,21 @@ 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); + } } + /** + * Free up as much memory as possible from private caches (e.g. fonts, + * images) + * + * @hide - for now + */ + public static native void freeCaches(); + private static native int initRaster(int nativeBitmapOrZero); private static native int initGL(); private static native void native_setBitmap(int nativeCanvas, int bitmap); diff --git a/graphics/java/android/graphics/Matrix.java b/graphics/java/android/graphics/Matrix.java index 2681eae..f549900 100644 --- a/graphics/java/android/graphics/Matrix.java +++ b/graphics/java/android/graphics/Matrix.java @@ -16,6 +16,8 @@ package android.graphics; +import java.io.PrintWriter; + /** * The Matrix class holds a 3x3 matrix for transforming coordinates. @@ -539,17 +541,49 @@ public class Matrix { } public String toString() { - return "Matrix{" + toShortString() + "}"; + StringBuilder sb = new StringBuilder(64); + sb.append("Matrix{"); + toShortString(sb); + sb.append('}'); + return sb.toString(); } public String toShortString() { + StringBuilder sb = new StringBuilder(64); + toShortString(sb); + return sb.toString(); + } + + /** + * @hide + */ + public void toShortString(StringBuilder sb) { + float[] values = new float[9]; + getValues(values); + sb.append('['); + sb.append(values[0]); sb.append(", "); sb.append(values[1]); sb.append(", "); + sb.append(values[2]); sb.append("]["); + sb.append(values[3]); sb.append(", "); sb.append(values[4]); sb.append(", "); + sb.append(values[5]); sb.append("]["); + sb.append(values[6]); sb.append(", "); sb.append(values[7]); sb.append(", "); + sb.append(values[8]); sb.append(']'); + } + + /** + * Print short string, to optimize dumping. + * @hide + */ + public void printShortString(PrintWriter pw) { float[] values = new float[9]; getValues(values); - return "[" + - values[0] + ", " + values[1] + ", " + values[2] + "][" + - values[3] + ", " + values[4] + ", " + values[5] + "][" + - values[6] + ", " + values[7] + ", " + values[8] + "]"; + pw.print('['); + pw.print(values[0]); pw.print(", "); pw.print(values[1]); pw.print(", "); + pw.print(values[2]); pw.print("]["); + pw.print(values[3]); pw.print(", "); pw.print(values[4]); pw.print(", "); + pw.print(values[5]); pw.print("]["); + pw.print(values[6]); pw.print(", "); pw.print(values[7]); pw.print(", "); + pw.print(values[8]); pw.print(']'); } 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/Paint.java b/graphics/java/android/graphics/Paint.java index 81980d9..862e827 100644 --- a/graphics/java/android/graphics/Paint.java +++ b/graphics/java/android/graphics/Paint.java @@ -1084,8 +1084,9 @@ public class Paint { * not null, return in it the actual width measured. * * @param text The text to measure - * @param measureForwards If true, measure forwards, starting at index. - * Otherwise, measure backwards, starting with the + * @param measureForwards If true, measure forwards, starting with the + * first character in the string. Otherwise, + * measure backwards, starting with the * last character in the string. * @param maxWidth The maximum width to accumulate. * @param measuredWidth Optional. If not null, returns the actual width diff --git a/graphics/java/android/graphics/Rect.java b/graphics/java/android/graphics/Rect.java index 2005344..50ab566 100644 --- a/graphics/java/android/graphics/Rect.java +++ b/graphics/java/android/graphics/Rect.java @@ -19,6 +19,8 @@ package android.graphics; import android.os.Parcel; import android.os.Parcelable; +import java.io.PrintWriter; + /** * Rect holds four integer coordinates for a rectangle. The rectangle is * represented by the coordinates of its 4 edges (left, top, right bottom). @@ -78,14 +80,40 @@ public final class Rect implements Parcelable { } public String toString() { - return "Rect(" + left + ", " + top + " - " + right + ", " + bottom + ")"; + StringBuilder sb = new StringBuilder(32); + sb.append("Rect("); sb.append(left); sb.append(", "); + sb.append(top); sb.append(" - "); sb.append(right); + sb.append(", "); sb.append(bottom); sb.append(")"); + return sb.toString(); } /** * Return a string representation of the rectangle in a compact form. */ public String toShortString() { - return "[" + left + "," + top + "][" + right + "," + bottom + "]"; + return toShortString(new StringBuilder(32)); + } + + /** + * Return a string representation of the rectangle in a compact form. + * @hide + */ + public String toShortString(StringBuilder sb) { + sb.setLength(0); + sb.append('['); sb.append(left); sb.append(','); + sb.append(top); sb.append("]["); sb.append(right); + sb.append(','); sb.append(bottom); sb.append(']'); + return sb.toString(); + } + + /** + * Print short representation to given writer. + * @hide + */ + public void printShortString(PrintWriter pw) { + pw.print('['); pw.print(left); pw.print(','); + pw.print(top); pw.print("]["); pw.print(right); + pw.print(','); pw.print(bottom); pw.print(']'); } /** @@ -517,4 +545,17 @@ public final class Rect implements Parcelable { right = in.readInt(); bottom = in.readInt(); } + + /** + * Scales up the rect by the given scale. + * @hide + */ + public void scale(float scale) { + if (scale != 1.0f) { + left *= scale; + top *= scale; + right *= scale; + bottom*= scale; + } + } } diff --git a/graphics/java/android/graphics/Region.java b/graphics/java/android/graphics/Region.java index 544ff4f..2b080aa 100644 --- a/graphics/java/android/graphics/Region.java +++ b/graphics/java/android/graphics/Region.java @@ -211,6 +211,26 @@ public class Region implements Parcelable { */ public native void translate(int dx, int dy, Region dst); + /** + * Scale the region by the given scale amount. This re-constructs new region by + * scaling the rects that this region consists of. New rectis are computed by scaling + * coordinates by float, then rounded by roundf() function to integers. This may results + * in less internal rects if 0 < scale < 1. Zero and Negative scale result in + * an empty region. If this region is empty, do nothing. + * + * @hide + */ + public void scale(float scale) { + scale(scale, null); + } + + /** + * Set the dst region to the result of scaling this region by the given scale amount. + * If this region is empty, then dst will be set to empty. + * @hide + */ + public native void scale(float scale, Region dst); + public final boolean union(Rect r) { return op(r, Op.UNION); } @@ -294,7 +314,16 @@ public class Region implements Parcelable { throw new RuntimeException(); } } - + + @Override + public boolean equals(Object obj) { + if (obj == null || !(obj instanceof Region)) { + return false; + } + Region peer = (Region) obj; + return nativeEquals(mNativeRegion, peer.mNativeRegion); + } + protected void finalize() throws Throwable { nativeDestructor(mNativeRegion); } @@ -340,5 +369,7 @@ public class Region implements Parcelable { private static native boolean nativeWriteToParcel(int native_region, Parcel p); + private static native boolean nativeEquals(int native_r1, int native_r2); + private final int mNativeRegion; } diff --git a/graphics/java/android/graphics/Typeface.java b/graphics/java/android/graphics/Typeface.java index c69c92c..e40e84a 100644 --- a/graphics/java/android/graphics/Typeface.java +++ b/graphics/java/android/graphics/Typeface.java @@ -18,6 +18,8 @@ package android.graphics; import android.content.res.AssetManager; +import java.io.File; + /** * The Typeface class specifies the typeface and intrinsic style of a font. * This is used in the paint, along with optionally Paint settings like @@ -118,7 +120,27 @@ public class Typeface { public static Typeface createFromAsset(AssetManager mgr, String path) { return new Typeface(nativeCreateFromAsset(mgr, path)); } - + + /** + * Create a new typeface from the specified font file. + * + * @param path The path to the font data. + * @return The new typeface. + */ + public static Typeface createFromFile(File path) { + return new Typeface(nativeCreateFromFile(path.getAbsolutePath())); + } + + /** + * Create a new typeface from the specified font file. + * + * @param path The full path to the font data. + * @return The new typeface. + */ + public static Typeface createFromFile(String path) { + return new Typeface(nativeCreateFromFile(path)); + } + // don't allow clients to call this directly private Typeface(int ni) { native_instance = ni; @@ -140,14 +162,14 @@ public class Typeface { } protected void finalize() throws Throwable { + super.finalize(); nativeUnref(native_instance); } private static native int nativeCreate(String familyName, int style); - private static native int nativeCreateFromTypeface(int native_instance, - int style); + private static native int nativeCreateFromTypeface(int native_instance, int style); private static native void nativeUnref(int native_instance); private static native int nativeGetStyle(int native_instance); - private static native int nativeCreateFromAsset(AssetManager mgr, - String path); + private static native int nativeCreateFromAsset(AssetManager mgr, String path); + private static native int nativeCreateFromFile(String path); } 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 ca0ed7e..4f58a0c 100644 --- a/graphics/java/android/graphics/drawable/Drawable.java +++ b/graphics/java/android/graphics/drawable/Drawable.java @@ -38,32 +38,32 @@ import android.util.TypedValue; * dealing with an underlying visual resource that may take a variety of forms. * Unlike a {@link android.view.View}, a Drawable does not have any facility to * receive events or otherwise interact with the user. - * + * * <p>In addition to simple drawing, Drawable provides a number of generic * mechanisms for its client to interact with what is being drawn: - * + * * <ul> * <li> The {@link #setBounds} method <var>must</var> be called to tell the * Drawable where it is drawn and how large it should be. All Drawables * should respect the requested size, often simply by scaling their * imagery. A client can find the preferred size for some Drawables with * the {@link #getIntrinsicHeight} and {@link #getIntrinsicWidth} methods. - * + * * <li> The {@link #getPadding} method can return from some Drawables * information about how to frame content that is placed inside of them. * For example, a Drawable that is intended to be the frame for a button * widget would need to return padding that correctly places the label * inside of itself. - * + * * <li> The {@link #setState} method allows the client to tell the Drawable * in which state it is to be drawn, such as "focused", "selected", etc. * Some drawables may modify their imagery based on the selected state. - * + * * <li> The {@link #setLevel} method allows the client to supply a single * continuous controller that can modify the Drawable is displayed, such as * a battery level or progress level. Some drawables may modify their * imagery based on the current level. - * + * * <li> A Drawable can perform animations by calling back to its client * through the {@link Callback} interface. All clients should support this * interface (via {@link #setCallback}) so that animations will work. A @@ -71,7 +71,7 @@ import android.util.TypedValue; * {@link android.view.View#setBackgroundDrawable(Drawable)} and * {@link android.widget.ImageView}. * </ul> - * + * * Though usually not visible to the application, Drawables may take a variety * of forms: * @@ -96,7 +96,6 @@ import android.util.TypedValue; * and Internationalization</a>. */ public abstract class Drawable { - private static final Rect ZERO_BOUNDS_RECT = new Rect(); private int[] mStateSet = StateSet.WILD_CARD; @@ -131,7 +130,7 @@ public abstract class Drawable { onBoundsChange(mBounds); } } - + /** * Specify a bounding rectangle for the Drawable. This is where the drawable * will draw when its draw() method is called. @@ -151,12 +150,12 @@ public abstract class Drawable { public final void copyBounds(Rect bounds) { bounds.set(mBounds); } - + /** * Return a copy of the drawable's bounds in a new Rect. This returns the * same values as getBounds(), but the returned object is guaranteed to not * be changed later by the drawable (i.e. it retains no reference to this - * rect). If the caller already has a Rect allocated, call copyBounds(rect) + * rect). If the caller already has a Rect allocated, call copyBounds(rect). * * @return A copy of the drawable's bounds */ @@ -169,27 +168,37 @@ public abstract class Drawable { * object may be the same object stored in the drawable (though this is not * guaranteed), so if a persistent copy of the bounds is needed, call * copyBounds(rect) instead. + * You should also not change the object returned by this method as it may + * be the same object stored in the drawable. * * @return The bounds of the drawable (which may change later, so caller - * beware). + * beware). DO NOT ALTER the returned object as it may change the + * stored bounds of this drawable. + * + * @see #copyBounds() + * @see #copyBounds(android.graphics.Rect) */ public final Rect getBounds() { + if (mBounds == ZERO_BOUNDS_RECT) { + mBounds = new Rect(); + } + return mBounds; } /** * Set a mask of the configuration parameters for which this drawable * may change, requiring that it be re-created. - * + * * @param configs A mask of the changing configuration parameters, as * defined by {@link android.content.res.Configuration}. - * + * * @see android.content.res.Configuration */ public void setChangingConfigurations(int configs) { mChangingConfigurations = configs; } - + /** * Return a mask of the configuration parameters for which this drawable * mau change, requiring that it be re-created. The default implementation @@ -197,23 +206,23 @@ public abstract class Drawable { * {@link #setChangingConfigurations(int)} or 0 by default. Subclasses * may extend this to or in the changing configurations of any other * drawables they hold. - * + * * @return Returns a mask of the changing configuration parameters, as * defined by {@link android.content.res.Configuration}. - * + * * @see android.content.res.Configuration */ public int getChangingConfigurations() { return mChangingConfigurations; } - + /** * Set to true to have the drawable dither its colors when drawn to a device * with fewer than 8-bits per color component. This can improve the look on * those devices, but can also slow down the drawing a little. */ public void setDither(boolean dither) {} - + /** * Set to true to have the drawable filter its bitmap when scaled or rotated * (for drawables that use bitmaps). If the drawable does not use bitmaps, @@ -235,7 +244,7 @@ public abstract class Drawable { * Called when the drawable needs to be redrawn. A view at this point * should invalidate itself (or at least the part of itself where the * drawable appears). - * + * * @param who The drawable that is requesting the update. */ public void invalidateDrawable(Drawable who); @@ -246,7 +255,7 @@ public abstract class Drawable { * {@link android.os.Handler#postAtTime(Runnable, Object, long)} with * the parameters <var>(what, who, when)</var> to perform the * scheduling. - * + * * @param who The drawable being scheduled. * @param what The action to execute. * @param when The time (in milliseconds) to run. The timebase is @@ -260,7 +269,7 @@ public abstract class Drawable { * generally simply call * {@link android.os.Handler#removeCallbacks(Runnable, Object)} with * the parameters <var>(what, who)</var> to unschedule the drawable. - * + * * @param who The drawable being unscheduled. * @param what The action being unscheduled. */ @@ -270,7 +279,7 @@ public abstract class Drawable { /** * Bind a {@link Callback} object to this Drawable. Required for clients * that want to support animated drawables. - * + * * @param cb The client's Callback implementation. */ public final void setCallback(Callback cb) { @@ -281,7 +290,7 @@ public abstract class Drawable { * Use the current {@link Callback} implementation to have this Drawable * redrawn. Does nothing if there is no Callback attached to the * Drawable. - * + * * @see Callback#invalidateDrawable */ public void invalidateSelf() @@ -295,10 +304,10 @@ public abstract class Drawable { * Use the current {@link Callback} implementation to have this Drawable * scheduled. Does nothing if there is no Callback attached to the * Drawable. - * + * * @param what The action being scheduled. * @param when The time (in milliseconds) to run. - * + * * @see Callback#scheduleDrawable */ public void scheduleSelf(Runnable what, long when) @@ -312,9 +321,9 @@ public abstract class Drawable { * Use the current {@link Callback} implementation to have this Drawable * unscheduled. Does nothing if there is no Callback attached to the * Drawable. - * + * * @param what The runnable that you no longer want called. - * + * * @see Callback#unscheduleDrawable */ public void unscheduleSelf(Runnable what) @@ -329,13 +338,13 @@ public abstract class Drawable { * 255 means fully opaque. */ public abstract void setAlpha(int alpha); - + /** * Specify an optional colorFilter for the drawable. Pass null to remove * any filters. */ public abstract void setColorFilter(ColorFilter cf); - + /** * Specify a color and porterduff mode to be the colorfilter for this * drawable. @@ -343,7 +352,7 @@ public abstract class Drawable { public void setColorFilter(int color, PorterDuff.Mode mode) { setColorFilter(new PorterDuffColorFilter(color, mode)); } - + public void clearColorFilter() { setColorFilter(null); } @@ -352,34 +361,34 @@ public abstract class Drawable { * Indicates whether this view will change its appearance based on state. * Clients can use this to determine whether it is necessary to calculate * their state and call setState. - * + * * @return True if this view changes its appearance based on state, false * otherwise. - * + * * @see #setState(int[]) */ public boolean isStateful() { return false; } - + /** * Specify a set of states for the drawable. These are use-case specific, * so see the relevant documentation. As an example, the background for * widgets like Button understand the following states: * [{@link android.R.attr#state_focused}, * {@link android.R.attr#state_pressed}]. - * + * * <p>If the new state you are supplying causes the appearance of the * Drawable to change, then it is responsible for calling * {@link #invalidateSelf} in order to have itself redrawn, <em>and</em> * true will be returned from this function. - * + * * <p>Note: The Drawable holds a reference on to <var>stateSet</var> * until a new state array is given to it, so you must not modify this * array during that time.</p> - * + * * @param stateSet The new set of states to be displayed. - * + * * @return Returns true if this change in state has caused the appearance * of the Drawable to change (hence requiring an invalidate), otherwise * returns false. @@ -402,7 +411,7 @@ public abstract class Drawable { public int[] getState() { return mStateSet; } - + /** * @return The current drawable that will be used by this drawable. For simple drawables, this * is just the drawable itself. For drawables that change state like @@ -422,9 +431,9 @@ public abstract class Drawable { * Drawable to change, then it is responsible for calling * {@link #invalidateSelf} in order to have itself redrawn, <em>and</em> * true will be returned from this function. - * + * * @param level The new level, from 0 (minimum) to 10000 (maximum). - * + * * @return Returns true if this change in level has caused the appearance * of the Drawable to change (hence requiring an invalidate), otherwise * returns false. @@ -535,7 +544,7 @@ public abstract class Drawable { * region; subclasses can optionally override this to return an actual * Region if they want to supply this optimization information, but it is * not required that they do so. - * + * * @return Returns null if the Drawables has no transparent region to * report, else a Region holding the parts of the Drawable's bounds that * are transparent. @@ -543,11 +552,11 @@ public abstract class Drawable { public Region getTransparentRegion() { return null; } - + /** * Override this in your subclass to change appearance if you recognize the * specified state. - * + * * @return Returns true if the state change has caused the appearance of * the Drawable to change (that is, it needs to be drawn), else false * if it looks the same and there is no need to redraw it since its @@ -583,13 +592,13 @@ public abstract class Drawable { public int getIntrinsicHeight() { return -1; } - + /** * Returns the minimum width suggested by this Drawable. If a View uses this * Drawable as a background, it is suggested that the View use at least this * value for its width. (There will be some scenarios where this will not be * possible.) This value should INCLUDE any padding. - * + * * @return The minimum width suggested by this Drawable. If this Drawable * doesn't have a suggested minimum width, 0 is returned. */ @@ -603,7 +612,7 @@ public abstract class Drawable { * Drawable as a background, it is suggested that the View use at least this * value for its height. (There will be some scenarios where this will not be * possible.) This value should INCLUDE any padding. - * + * * @return The minimum height suggested by this Drawable. If this Drawable * doesn't have a suggested minimum height, 0 is returned. */ @@ -611,7 +620,7 @@ public abstract class Drawable { final int intrinsicHeight = getIntrinsicHeight(); return intrinsicHeight > 0 ? intrinsicHeight : 0; } - + /** * Return in padding the insets suggested by this Drawable for placing * content inside the drawable's bounds. Positive values move toward the @@ -649,7 +658,7 @@ public abstract class Drawable { /** * Create a drawable from an inputstream - * + * * @hide pending API council approval */ public static Drawable createFromResourceStream(Resources res, TypedValue value, @@ -736,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 29f2a00..376b1df 100644 --- a/graphics/java/android/graphics/drawable/DrawableContainer.java +++ b/graphics/java/android/graphics/drawable/DrawableContainer.java @@ -181,7 +181,8 @@ public class DrawableContainer extends Drawable implements Drawable.Callback { @Override public int getOpacity() { - return mDrawableContainerState.getOpacity(); + return mCurrDrawable == null || !mCurrDrawable.isVisible() ? PixelFormat.TRANSPARENT : + mDrawableContainerState.getOpacity(); } public boolean selectDrawable(int idx) @@ -233,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; } @@ -336,13 +339,11 @@ public class DrawableContainer extends Drawable implements Drawable.Callback { return pos; } - public final int getChildCount() - { + public final int getChildCount() { return mNumChildren; } - public final Drawable[] getChildren() - { + public final Drawable[] getChildren() { return mDrawables; } @@ -350,13 +351,11 @@ public class DrawableContainer extends Drawable implements Drawable.Callback { * all frames in the set (false), or to use the padding value of the frame * being shown (true). Default value is false. */ - public final void setVariablePadding(boolean variable) - { + public final void setVariablePadding(boolean variable) { mVariablePadding = variable; } - public final Rect getConstantPadding() - { + public final Rect getConstantPadding() { if (mVariablePadding) { return null; } @@ -364,11 +363,12 @@ public class DrawableContainer extends Drawable implements Drawable.Callback { return mConstantPadding; } - Rect r = new Rect(0, 0, 0, 0); - Rect t = new Rect(); + final Rect r = new Rect(0, 0, 0, 0); + final Rect t = new Rect(); final int N = getChildCount(); - for (int i=0; i<N; i++) { - if (mDrawables[i].getPadding(t)) { + final Drawable[] drawables = mDrawables; + for (int i = 0; i < N; i++) { + if (drawables[i].getPadding(t)) { if (t.left > r.left) r.left = t.left; if (t.top > r.top) r.top = t.top; if (t.right > r.right) r.right = t.right; @@ -378,18 +378,15 @@ public class DrawableContainer extends Drawable implements Drawable.Callback { return (mConstantPadding=r); } - public final void setConstantSize(boolean constant) - { + public final void setConstantSize(boolean constant) { mConstantSize = constant; } - public final boolean isConstantSize() - { + public final boolean isConstantSize() { return mConstantSize; } - public final int getConstantWidth() - { + public final int getConstantWidth() { if (!mComputedConstantSize) { computeConstantSize(); } @@ -397,8 +394,7 @@ public class DrawableContainer extends Drawable implements Drawable.Callback { return mConstantWidth; } - public final int getConstantHeight() - { + public final int getConstantHeight() { if (!mComputedConstantSize) { computeConstantSize(); } @@ -406,8 +402,7 @@ public class DrawableContainer extends Drawable implements Drawable.Callback { return mConstantHeight; } - public final int getConstantMinimumWidth() - { + public final int getConstantMinimumWidth() { if (!mComputedConstantSize) { computeConstantSize(); } @@ -415,8 +410,7 @@ public class DrawableContainer extends Drawable implements Drawable.Callback { return mConstantMinimumWidth; } - public final int getConstantMinimumHeight() - { + public final int getConstantMinimumHeight() { if (!mComputedConstantSize) { computeConstantSize(); } @@ -424,15 +418,15 @@ public class DrawableContainer extends Drawable implements Drawable.Callback { return mConstantMinimumHeight; } - private void computeConstantSize() - { + private void computeConstantSize() { mComputedConstantSize = true; final int N = getChildCount(); + final Drawable[] drawables = mDrawables; mConstantWidth = mConstantHeight = 0; mConstantMinimumWidth = mConstantMinimumHeight = 0; - for (int i=0; i<N; i++) { - Drawable dr = mDrawables[i]; + for (int i = 0; i < N; i++) { + Drawable dr = drawables[i]; int s = dr.getIntrinsicWidth(); if (s > mConstantWidth) mConstantWidth = s; s = dr.getIntrinsicHeight(); @@ -444,23 +438,22 @@ public class DrawableContainer extends Drawable implements Drawable.Callback { } } - public final int getOpacity() - { + public final int getOpacity() { if (mHaveOpacity) { return mOpacity; } final int N = getChildCount(); - int op = N > 0 - ? mDrawables[0].getOpacity() : PixelFormat.TRANSPARENT; - for (int i=1; i<N; i++) { - op = Drawable.resolveOpacity(op, mDrawables[i].getOpacity()); + final Drawable[] drawables = mDrawables; + int op = N > 0 ? drawables[0].getOpacity() : PixelFormat.TRANSPARENT; + for (int i = 1; i < N; i++) { + op = Drawable.resolveOpacity(op, drawables[i].getOpacity()); } mOpacity = op; mHaveOpacity = true; return op; } - + public final boolean isStateful() { if (mHaveStateful) { return mStateful; @@ -480,8 +473,7 @@ public class DrawableContainer extends Drawable implements Drawable.Callback { return stateful; } - public void growArray(int oldSize, int newSize) - { + public void growArray(int oldSize, int newSize) { Drawable[] newDrawables = new Drawable[newSize]; System.arraycopy(mDrawables, 0, newDrawables, 0, oldSize); mDrawables = newDrawables; 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(); } |