diff options
Diffstat (limited to 'graphics')
13 files changed, 192 insertions, 90 deletions
diff --git a/graphics/java/android/graphics/Picture.java b/graphics/java/android/graphics/Picture.java index 39272b9..0e55089 100644 --- a/graphics/java/android/graphics/Picture.java +++ b/graphics/java/android/graphics/Picture.java @@ -135,8 +135,8 @@ public class Picture { * properly and are highly discouraged. * * <p> - * <strong>Note:</strong> a picture created from an input stream cannot be - * replayed on a hardware accelerated canvas. + * <strong>Note:</strong> Prior to API level 23 a picture created from an + * input stream cannot be replayed on a hardware accelerated canvas. * * @see #writeToStream(java.io.OutputStream) * @deprecated The recommended alternative is to not use writeToStream and @@ -155,8 +155,8 @@ public class Picture { * there is no guarantee that the Picture can be successfully reconstructed. * * <p> - * <strong>Note:</strong> a picture created from an input stream cannot be - * replayed on a hardware accelerated canvas. + * <strong>Note:</strong> Prior to API level 23 a picture created from an + * input stream cannot be replayed on a hardware accelerated canvas. * * @see #createFromStream(java.io.InputStream) * @deprecated The recommended alternative is to draw the picture into a diff --git a/graphics/java/android/graphics/PorterDuff.java b/graphics/java/android/graphics/PorterDuff.java index dcccf35..2bbbff3 100644 --- a/graphics/java/android/graphics/PorterDuff.java +++ b/graphics/java/android/graphics/PorterDuff.java @@ -67,4 +67,38 @@ public class PorterDuff { */ public final int nativeInt; } + + /** + * @hide + */ + public static final int modeToInt(Mode mode) { + return mode.nativeInt; + } + + /** + * @hide + */ + public static final Mode intToMode(int val) { + switch (val) { + default: + case 0: return Mode.CLEAR; + case 1: return Mode.SRC; + case 2: return Mode.DST; + case 3: return Mode.SRC_OVER; + case 4: return Mode.DST_OVER; + case 5: return Mode.SRC_IN; + case 6: return Mode.DST_IN; + case 7: return Mode.SRC_OUT; + case 8: return Mode.DST_OUT; + case 9: return Mode.SRC_ATOP; + case 10: return Mode.DST_ATOP; + case 11: return Mode.XOR; + case 16: return Mode.DARKEN; + case 17: return Mode.LIGHTEN; + case 13: return Mode.MULTIPLY; + case 14: return Mode.SCREEN; + case 12: return Mode.ADD; + case 15: return Mode.OVERLAY; + } + } } diff --git a/graphics/java/android/graphics/drawable/AnimatedStateListDrawable.java b/graphics/java/android/graphics/drawable/AnimatedStateListDrawable.java index 2c603e2..e235a99 100644 --- a/graphics/java/android/graphics/drawable/AnimatedStateListDrawable.java +++ b/graphics/java/android/graphics/drawable/AnimatedStateListDrawable.java @@ -575,7 +575,7 @@ public class AnimatedStateListDrawable extends StateListDrawable { } } - private void mutate() { + void mutate() { mTransitions = mTransitions.clone(); mStateIds = mStateIds.clone(); } diff --git a/graphics/java/android/graphics/drawable/BitmapDrawable.java b/graphics/java/android/graphics/drawable/BitmapDrawable.java index f059727..fcd7f63 100644 --- a/graphics/java/android/graphics/drawable/BitmapDrawable.java +++ b/graphics/java/android/graphics/drawable/BitmapDrawable.java @@ -362,11 +362,6 @@ public class BitmapDrawable extends Drawable { invalidateSelf(); } - @Override - public boolean isDither() { - return mBitmapState.mPaint.isDither(); - } - /** * Indicates the repeat behavior of this drawable on the X axis. * diff --git a/graphics/java/android/graphics/drawable/Drawable.java b/graphics/java/android/graphics/drawable/Drawable.java index 6090cf0..32af59a 100644 --- a/graphics/java/android/graphics/drawable/Drawable.java +++ b/graphics/java/android/graphics/drawable/Drawable.java @@ -269,30 +269,29 @@ public abstract class Drawable { } /** - * 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. + * Set to true to have the drawable dither its colors when drawn to a + * device with fewer than 8-bits per color component. + * + * @see android.graphics.Paint#setDither(boolean); + * @deprecated This property is ignored. */ + @Deprecated public void setDither(boolean dither) {} /** - * @return whether this drawable dithers its colors - * @see #setDither(boolean) - */ - public boolean isDither() { - return false; - } - - /** - * 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, - * this call is ignored. This can improve the look when scaled or rotated, - * but also slows down the drawing. + * Set to true to have the drawable filter its bitmaps with bilinear + * sampling when they are scaled or rotated. + * + * <p>This can improve appearance when bitmaps are rotated. If the drawable + * does not use bitmaps, this call is ignored.</p> + * + * @see #isFilterBitmap() + * @see android.graphics.Paint#setFilterBitmap(boolean); */ public void setFilterBitmap(boolean filter) {} /** - * @return whether this drawable filters its bitmap + * @return whether this drawable filters its bitmaps * @see #setFilterBitmap(boolean) */ public boolean isFilterBitmap() { @@ -433,7 +432,7 @@ public abstract class Drawable { /** * Set the layout direction for this drawable. Should be a resolved - * layout direction, as the Drawable as no capacity to do the resolution on + * layout direction, as the Drawable has no capacity to do the resolution on * its own. * * @param layoutDirection the resolved layout direction for the drawable, diff --git a/graphics/java/android/graphics/drawable/DrawableContainer.java b/graphics/java/android/graphics/drawable/DrawableContainer.java index 1759f53..1915dd7 100644 --- a/graphics/java/android/graphics/drawable/DrawableContainer.java +++ b/graphics/java/android/graphics/drawable/DrawableContainer.java @@ -167,11 +167,6 @@ public class DrawableContainer extends Drawable implements Drawable.Callback { } @Override - public boolean isDither() { - return mDrawableContainerState.mDither; - } - - @Override public void setColorFilter(ColorFilter colorFilter) { mDrawableContainerState.mHasColorFilter = true; @@ -735,7 +730,7 @@ public class DrawableContainer extends Drawable implements Drawable.Callback { if (origDf != null) { mDrawableFutures = origDf.clone(); } else { - mDrawableFutures = new SparseArray<ConstantStateFuture>(mNumChildren); + mDrawableFutures = new SparseArray<>(mNumChildren); } // Create futures for drawables with constant states. If a @@ -828,6 +823,9 @@ public class DrawableContainer extends Drawable implements Drawable.Callback { final Drawable prepared = mDrawableFutures.valueAt(keyIndex).get(this); mDrawables[index] = prepared; mDrawableFutures.removeAt(keyIndex); + if (mDrawableFutures.size() == 0) { + mDrawableFutures = null; + } return prepared; } } diff --git a/graphics/java/android/graphics/drawable/GradientDrawable.java b/graphics/java/android/graphics/drawable/GradientDrawable.java index 626991d..a11b2cd 100644 --- a/graphics/java/android/graphics/drawable/GradientDrawable.java +++ b/graphics/java/android/graphics/drawable/GradientDrawable.java @@ -826,11 +826,6 @@ public class GradientDrawable extends Drawable { } @Override - public boolean isDither() { - return mGradientState.mDither; - } - - @Override public ColorFilter getColorFilter() { return mColorFilter; } diff --git a/graphics/java/android/graphics/drawable/Icon.java b/graphics/java/android/graphics/drawable/Icon.java index 7b4329a..7c9b30b 100644 --- a/graphics/java/android/graphics/drawable/Icon.java +++ b/graphics/java/android/graphics/drawable/Icon.java @@ -16,19 +16,23 @@ package android.graphics.drawable; +import android.annotation.ColorInt; import android.annotation.DrawableRes; +import android.content.res.ColorStateList; import android.content.ContentResolver; import android.content.Context; import android.content.pm.PackageManager; import android.content.res.Resources; import android.graphics.Bitmap; import android.graphics.BitmapFactory; +import android.graphics.PorterDuff; import android.net.Uri; import android.os.AsyncTask; import android.os.Handler; import android.os.Message; import android.os.Parcel; import android.os.Parcelable; +import android.text.TextUtils; import android.util.Log; import java.io.DataInputStream; @@ -66,6 +70,10 @@ public final class Icon implements Parcelable { private final int mType; + private ColorStateList mTintList; + static final PorterDuff.Mode DEFAULT_TINT_MODE = Drawable.DEFAULT_TINT_MODE; // SRC_IN + private PorterDuff.Mode mTintMode = DEFAULT_TINT_MODE; + // To avoid adding unnecessary overhead, we have a few basic objects that get repurposed // based on the value of mType. @@ -108,6 +116,10 @@ public final class Icon implements Parcelable { return (Bitmap) mObj1; } + private void setBitmap(Bitmap b) { + mObj1 = b; + } + /** * @return The length of the compressed bitmap byte array held by this {@link #TYPE_DATA} Icon. * @hide @@ -253,21 +265,39 @@ public final class Icon implements Parcelable { * @return A fresh instance of a drawable for this image, yours to keep. */ public Drawable loadDrawable(Context context) { + final Drawable result = loadDrawableInner(context); + if (result != null && (mTintList != null || mTintMode != DEFAULT_TINT_MODE)) { + result.mutate(); + result.setTintList(mTintList); + result.setTintMode(mTintMode); + } + return result; + } + + /** + * Do the heavy lifting of loading the drawable, but stop short of applying any tint. + */ + private Drawable loadDrawableInner(Context context) { switch (mType) { case TYPE_BITMAP: return new BitmapDrawable(context.getResources(), getBitmap()); case TYPE_RESOURCE: if (getResources() == null) { - if (getResPackage() == null || "android".equals(getResPackage())) { + // figure out where to load resources from + String resPackage = getResPackage(); + if (TextUtils.isEmpty(resPackage)) { + // if none is specified, try the given context + resPackage = context.getPackageName(); + } + if ("android".equals(resPackage)) { mObj1 = Resources.getSystem(); } else { final PackageManager pm = context.getPackageManager(); try { - mObj1 = pm.getResourcesForApplication(getResPackage()); + mObj1 = pm.getResourcesForApplication(resPackage); } catch (PackageManager.NameNotFoundException e) { - Log.e(TAG, String.format("Unable to find pkg=%s", - getResPackage()), - e); + Log.e(TAG, String.format("Unable to find pkg=%s for icon %s", + resPackage, this), e); break; } } @@ -320,12 +350,15 @@ public final class Icon implements Parcelable { */ public Drawable loadDrawableAsUser(Context context, int userId) { if (mType == TYPE_RESOURCE) { - if (getResources() == null - && getResPackage() != null - && !(getResPackage().equals("android"))) { + String resPackage = getResPackage(); + if (TextUtils.isEmpty(resPackage)) { + resPackage = context.getPackageName(); + } + if (getResources() == null && !(getResPackage().equals("android"))) { final PackageManager pm = context.getPackageManager(); try { - mObj1 = pm.getResourcesForApplicationAsUser(getResPackage(), userId); + // assign getResources() as the correct user + mObj1 = pm.getResourcesForApplicationAsUser(resPackage, userId); } catch (PackageManager.NameNotFoundException e) { Log.e(TAG, String.format("Unable to find pkg=%s user=%d", getResPackage(), @@ -338,6 +371,16 @@ public final class Icon implements Parcelable { } /** + * Puts the memory used by this instance into Ashmem memory, if possible. + * @hide + */ + public void convertToAshmem() { + if (mType == TYPE_BITMAP && getBitmap().isMutable()) { + setBitmap(getBitmap().createAshmemBitmap()); + } + } + + /** * Writes a serialized version of an Icon to the specified stream. * * @param stream The stream on which to serialize the Icon. @@ -410,6 +453,9 @@ public final class Icon implements Parcelable { * @param resId ID of the drawable resource */ public static Icon createWithResource(Context context, @DrawableRes int resId) { + if (context == null) { + throw new IllegalArgumentException("Context must not be null."); + } final Icon rep = new Icon(TYPE_RESOURCE); rep.mInt1 = resId; rep.mString1 = context.getPackageName(); @@ -454,7 +500,7 @@ public final class Icon implements Parcelable { throw new IllegalArgumentException("Bitmap must not be null."); } final Icon rep = new Icon(TYPE_BITMAP); - rep.mObj1 = bits; + rep.setBitmap(bits); return rep; } @@ -506,6 +552,38 @@ public final class Icon implements Parcelable { } /** + * Store a color to use whenever this Icon is drawn. + * + * @param tint a color, as in {@link Drawable#setTint(int)} + * @return this same object, for use in chained construction + */ + public Icon setTint(@ColorInt int tint) { + return setTintList(ColorStateList.valueOf(tint)); + } + + /** + * Store a color to use whenever this Icon is drawn. + * + * @param tintList as in {@link Drawable#setTintList(ColorStateList)}, null to remove tint + * @return this same object, for use in chained construction + */ + public Icon setTintList(ColorStateList tintList) { + mTintList = tintList; + return this; + } + + /** + * Store a blending mode to use whenever this Icon is drawn. + * + * @param mode a blending mode, as in {@link Drawable#setTintMode(PorterDuff.Mode)}, may be null + * @return this same object, for use in chained construction + */ + public Icon setTintMode(PorterDuff.Mode mode) { + mTintMode = mode; + return this; + } + + /** * Create an Icon pointing to an image file specified by path. * * @param path A path to a file that contains compressed bitmap data of @@ -546,6 +624,15 @@ public final class Icon implements Parcelable { sb.append(" uri=").append(getUriString()); break; } + if (mTintList != null) { + sb.append(" tint="); + String sep = ""; + for (int c : mTintList.getColors()) { + sb.append(String.format("%s0x%08x", sep, c)); + sep = "|"; + } + } + if (mTintMode != DEFAULT_TINT_MODE) sb.append(" mode=").append(mTintMode); sb.append(")"); return sb.toString(); } @@ -591,31 +678,39 @@ public final class Icon implements Parcelable { throw new RuntimeException("invalid " + this.getClass().getSimpleName() + " type in parcel: " + mType); } + if (in.readInt() == 1) { + mTintList = ColorStateList.CREATOR.createFromParcel(in); + } + mTintMode = PorterDuff.intToMode(in.readInt()); } @Override public void writeToParcel(Parcel dest, int flags) { + dest.writeInt(mType); switch (mType) { case TYPE_BITMAP: final Bitmap bits = getBitmap(); - dest.writeInt(TYPE_BITMAP); getBitmap().writeToParcel(dest, flags); break; case TYPE_RESOURCE: - dest.writeInt(TYPE_RESOURCE); dest.writeString(getResPackage()); dest.writeInt(getResId()); break; case TYPE_DATA: - dest.writeInt(TYPE_DATA); dest.writeInt(getDataLength()); dest.writeBlob(getDataBytes(), getDataOffset(), getDataLength()); break; case TYPE_URI: - dest.writeInt(TYPE_URI); dest.writeString(getUriString()); break; } + if (mTintList == null) { + dest.writeInt(0); + } else { + dest.writeInt(1); + mTintList.writeToParcel(dest, flags); + } + dest.writeInt(PorterDuff.modeToInt(mTintMode)); } public static final Parcelable.Creator<Icon> CREATOR diff --git a/graphics/java/android/graphics/drawable/LayerDrawable.java b/graphics/java/android/graphics/drawable/LayerDrawable.java index 90891f6..d9469d4 100644 --- a/graphics/java/android/graphics/drawable/LayerDrawable.java +++ b/graphics/java/android/graphics/drawable/LayerDrawable.java @@ -133,6 +133,7 @@ public class LayerDrawable extends Drawable implements Drawable.Callback { mLayerState.mChildren = r; ensurePadding(); + refreshPadding(); } LayerDrawable() { @@ -143,6 +144,7 @@ public class LayerDrawable extends Drawable implements Drawable.Callback { mLayerState = createConstantState(state, res); if (mLayerState.mNum > 0) { ensurePadding(); + refreshPadding(); } } @@ -162,6 +164,7 @@ public class LayerDrawable extends Drawable implements Drawable.Callback { inflateLayers(r, parser, attrs, theme); ensurePadding(); + refreshPadding(); } /** @@ -431,6 +434,7 @@ public class LayerDrawable extends Drawable implements Drawable.Callback { final ChildDrawable layer = createLayer(dr); final int index = addLayer(layer); ensurePadding(); + refreshChildPadding(index, layer); return index; } @@ -568,6 +572,8 @@ public class LayerDrawable extends Drawable implements Drawable.Callback { childDrawable.mDrawable = drawable; mLayerState.invalidateCache(); + + refreshChildPadding(index, childDrawable); } /** @@ -1248,16 +1254,6 @@ public class LayerDrawable extends Drawable implements Drawable.Callback { } @Override - public boolean isDither() { - final Drawable dr = getFirstNonNullDrawable(); - if (dr != null) { - return dr.isDither(); - } else { - return super.isDither(); - } - } - - @Override public void setAlpha(int alpha) { final ChildDrawable[] array = mLayerState.mChildren; final int N = mLayerState.mNum; @@ -1633,6 +1629,14 @@ public class LayerDrawable extends Drawable implements Drawable.Callback { mPaddingB = new int[N]; } + void refreshPadding() { + final int N = mLayerState.mNum; + final ChildDrawable[] array = mLayerState.mChildren; + for (int i = 0; i < N; i++) { + refreshChildPadding(i, array[i]); + } + } + @Override public ConstantState getConstantState() { if (mLayerState.canConstantState()) { diff --git a/graphics/java/android/graphics/drawable/NinePatchDrawable.java b/graphics/java/android/graphics/drawable/NinePatchDrawable.java index adf53e3..152fe6a 100644 --- a/graphics/java/android/graphics/drawable/NinePatchDrawable.java +++ b/graphics/java/android/graphics/drawable/NinePatchDrawable.java @@ -374,11 +374,6 @@ public class NinePatchDrawable extends Drawable { } @Override - public boolean isDither() { - return mPaint == null ? DEFAULT_DITHER : mPaint.isDither(); - } - - @Override public void setAutoMirrored(boolean mirrored) { mNinePatchState.mAutoMirrored = mirrored; } diff --git a/graphics/java/android/graphics/drawable/RippleDrawable.java b/graphics/java/android/graphics/drawable/RippleDrawable.java index 134451b..bf069d3 100644 --- a/graphics/java/android/graphics/drawable/RippleDrawable.java +++ b/graphics/java/android/graphics/drawable/RippleDrawable.java @@ -198,6 +198,7 @@ public class RippleDrawable extends LayerDrawable { setColor(color); ensurePadding(); + refreshPadding(); updateLocalState(); } @@ -423,6 +424,7 @@ public class RippleDrawable extends LayerDrawable { if (super.setDrawableByLayerId(id, drawable)) { if (id == R.id.mask) { mMask = drawable; + mHasValidMask = false; } return true; @@ -1012,6 +1014,7 @@ public class RippleDrawable extends LayerDrawable { if (mState.mNum > 0) { ensurePadding(); + refreshPadding(); } if (res != null) { diff --git a/graphics/java/android/graphics/drawable/ShapeDrawable.java b/graphics/java/android/graphics/drawable/ShapeDrawable.java index a669d3c..30b588e 100644 --- a/graphics/java/android/graphics/drawable/ShapeDrawable.java +++ b/graphics/java/android/graphics/drawable/ShapeDrawable.java @@ -328,11 +328,6 @@ public class ShapeDrawable extends Drawable { } @Override - public boolean isDither() { - return mShapeState.mPaint.isDither(); - } - - @Override protected void onBoundsChange(Rect bounds) { super.onBoundsChange(bounds); updateShape(); diff --git a/graphics/java/android/graphics/drawable/StateListDrawable.java b/graphics/java/android/graphics/drawable/StateListDrawable.java index c83af11..758410a 100644 --- a/graphics/java/android/graphics/drawable/StateListDrawable.java +++ b/graphics/java/android/graphics/drawable/StateListDrawable.java @@ -59,22 +59,10 @@ import android.util.StateSet; * @attr ref android.R.styleable#DrawableStates_state_pressed */ public class StateListDrawable extends DrawableContainer { - private static final String TAG = StateListDrawable.class.getSimpleName(); + private static final String TAG = "StateListDrawable"; private static final boolean DEBUG = false; - /** - * To be proper, we should have a getter for dither (and alpha, etc.) - * so that proxy classes like this can save/restore their delegates' - * values, but we don't have getters. Since we do have setters - * (e.g. setDither), which this proxy forwards on, we have to have some - * default/initial setting. - * - * The initial setting for dither is now true, since it almost always seems - * to improve the quality at negligible cost. - */ - private static final boolean DEFAULT_DITHER = true; - private StateListState mStateListState; private boolean mMutated; @@ -104,16 +92,16 @@ public class StateListDrawable extends DrawableContainer { @Override protected boolean onStateChange(int[] stateSet) { + final boolean changed = super.onStateChange(stateSet); + int idx = mStateListState.indexOfStateSet(stateSet); if (DEBUG) android.util.Log.i(TAG, "onStateChange " + this + " states " + Arrays.toString(stateSet) + " found " + idx); if (idx < 0) { idx = mStateListState.indexOfStateSet(StateSet.WILD_CARD); } - if (selectDrawable(idx)) { - return true; - } - return super.onStateChange(stateSet); + + return selectDrawable(idx) || changed; } @Override @@ -326,13 +314,14 @@ public class StateListDrawable extends DrawableContainer { } } - private void mutate() { + void mutate() { mThemeAttrs = mThemeAttrs != null ? mThemeAttrs.clone() : null; final int[][] stateSets = new int[mStateSets.length][]; for (int i = mStateSets.length - 1; i >= 0; i--) { stateSets[i] = mStateSets[i] != null ? mStateSets[i].clone() : null; } + mStateSets = stateSets; } int addStateSet(int[] stateSet, Drawable drawable) { |