Merge "Add support for specifying Drawable color filter in XML"
diff --git a/api/current.txt b/api/current.txt
index 1495277..76c30fa 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -377,6 +377,8 @@
field public static final int colorActivatedHighlight = 16843664; // 0x1010390
field public static final int colorBackground = 16842801; // 0x1010031
field public static final int colorBackgroundCacheHint = 16843435; // 0x10102ab
+ field public static final int colorFilterColor = 16843767; // 0x10103f7
+ field public static final int colorFilterMode = 16843768; // 0x10103f8
field public static final int colorFocusedHighlight = 16843663; // 0x101038f
field public static final int colorForeground = 16842800; // 0x1010030
field public static final int colorForegroundInverse = 16843270; // 0x1010206
diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml
index 0f812f1..c603418 100644
--- a/core/res/res/values/attrs.xml
+++ b/core/res/res/values/attrs.xml
@@ -4060,6 +4060,19 @@
RTL (right-to-left). See
{@link android.graphics.drawable.Drawable#setAutoMirrored}. -->
<attr name="autoMirrored" format="boolean" />
+ <!-- If set, specifies the color to apply to the drawable as a color filter. By
+ default, no color filter is applied. -->
+ <attr name="colorFilterColor" format="color" />
+ <!-- When a color filter color is set, specifies its Porter-Duff blending mode.
+ The default value is multiply. -->
+ <attr name="colorFilterMode">
+ <!-- [Sa * Da, Sc * Dc] -->
+ <enum name="multiply" value="14" />
+ <!-- [Sa + Da - Sa * Da, Sc + Dc - Sc * Dc] -->
+ <enum name="screen" value="15" />
+ <!-- [Da, Sc * Da + (1 - Sa) * Dc] -->
+ <enum name="src_atop" value="9" />
+ </attr>
</declare-styleable>
<!-- Drawable used to render several states. Each state is represented by
@@ -4344,6 +4357,8 @@
<!-- Indicates if the drawable needs to be mirrored when its layout direction is
RTL (right-to-left). -->
<attr name="autoMirrored" />
+ <attr name="colorFilterColor" />
+ <attr name="colorFilterMode" />
</declare-styleable>
<!-- Drawable used to draw 9-patches. -->
@@ -4357,6 +4372,8 @@
<!-- Indicates if the drawable needs to be mirrored when its layout direction is
RTL (right-to-left). -->
<attr name="autoMirrored" />
+ <attr name="colorFilterColor" />
+ <attr name="colorFilterMode" />
</declare-styleable>
<!-- Drawable used to draw a single color. -->
diff --git a/core/res/res/values/public.xml b/core/res/res/values/public.xml
index a0d84c9..9a9b71a 100644
--- a/core/res/res/values/public.xml
+++ b/core/res/res/values/public.xml
@@ -2097,6 +2097,8 @@
<public type="attr" name="windowContentTransitions" />
<public type="attr" name="windowContentTransitionManager" />
<public type="attr" name="translationZ" />
+ <public type="attr" name="colorFilterColor" />
+ <public type="attr" name="colorFilterMode" />
<public type="style" name="Widget.Holo.FragmentBreadCrumbs" />
<public type="style" name="Widget.Holo.Light.FragmentBreadCrumbs" />
diff --git a/graphics/java/android/graphics/drawable/BitmapDrawable.java b/graphics/java/android/graphics/drawable/BitmapDrawable.java
index 98e3386..9360558 100644
--- a/graphics/java/android/graphics/drawable/BitmapDrawable.java
+++ b/graphics/java/android/graphics/drawable/BitmapDrawable.java
@@ -26,6 +26,8 @@
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.PixelFormat;
+import android.graphics.PorterDuff;
+import android.graphics.PorterDuff.Mode;
import android.graphics.Rect;
import android.graphics.Shader;
import android.graphics.Xfermode;
@@ -33,6 +35,7 @@
import android.util.DisplayMetrics;
import android.util.LayoutDirection;
import android.view.Gravity;
+
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
@@ -579,6 +582,18 @@
setAutoMirrored(a.getBoolean(com.android.internal.R.styleable.BitmapDrawable_autoMirrored,
false));
+ if (a.hasValue(com.android.internal.R.styleable.BitmapDrawable_colorFilterColor)) {
+ final int colorFilterColor = a.getColor(
+ com.android.internal.R.styleable.BitmapDrawable_colorFilterColor, 0);
+ final int modeValue = a.getInt(
+ com.android.internal.R.styleable.BitmapDrawable_colorFilterMode,
+ Mode.MULTIPLY.ordinal());
+ final Mode mode = Drawable.parseColorFilterMode(modeValue);
+ if (mode != null) {
+ setColorFilter(colorFilterColor, mode);
+ }
+ }
+
final Paint paint = mBitmapState.mPaint;
paint.setAntiAlias(a.getBoolean(com.android.internal.R.styleable.BitmapDrawable_antialias,
paint.isAntiAlias()));
@@ -647,7 +662,7 @@
}
BitmapState(BitmapState bitmapState) {
- this(bitmapState.mBitmap);
+ mBitmap = bitmapState.mBitmap;
mChangingConfigurations = bitmapState.mChangingConfigurations;
mGravity = bitmapState.mGravity;
mTileModeX = bitmapState.mTileModeX;
diff --git a/graphics/java/android/graphics/drawable/Drawable.java b/graphics/java/android/graphics/drawable/Drawable.java
index 630add7..b8365aa 100644
--- a/graphics/java/android/graphics/drawable/Drawable.java
+++ b/graphics/java/android/graphics/drawable/Drawable.java
@@ -83,7 +83,7 @@
* through the {@link Callback} interface. All clients should support this
* interface (via {@link #setCallback}) so that animations will work. A
* simple way to do this is through the system facilities such as
- * {@link android.view.View#setBackgroundDrawable(Drawable)} and
+ * {@link android.view.View#setBackground(Drawable)} and
* {@link android.widget.ImageView}.
* </ul>
*
@@ -438,9 +438,9 @@
}
/**
- * Specify an optional colorFilter for the drawable. Pass null to remove
- * any filters.
- */
+ * Specify an optional color filter for the drawable. Pass null to remove
+ * any existing color filter.
+ */
public abstract void setColorFilter(ColorFilter cf);
/**
@@ -453,13 +453,16 @@
}
/**
- * Specify a color and porterduff mode to be the colorfilter for this
+ * Specify a color and Porter-Duff mode to be the color filter for this
* drawable.
*/
public void setColorFilter(int color, PorterDuff.Mode mode) {
setColorFilter(new PorterDuffColorFilter(color, mode));
}
+ /**
+ * Removes the color filter for this drawable.
+ */
public void clearColorFilter() {
setColorFilter(null);
}
@@ -1089,7 +1092,7 @@
/**
* Return a {@link ConstantState} instance that holds the shared state of this Drawable.
- *q
+ *
* @return The ConstantState associated to that Drawable.
* @see ConstantState
* @see Drawable#mutate()
@@ -1107,5 +1110,17 @@
return new BitmapDrawable(res, bm);
}
+
+ /**
+ * Parses a {@link android.graphics.PorterDuff.Mode} from a colorFilterMode
+ * attribute's enum value.
+ */
+ static PorterDuff.Mode parseColorFilterMode(int value) {
+ final PorterDuff.Mode[] modes = PorterDuff.Mode.values();
+ if (value >= 0 && value < modes.length) {
+ return modes[value];
+ }
+ return null;
+ }
}
diff --git a/graphics/java/android/graphics/drawable/DrawableContainer.java b/graphics/java/android/graphics/drawable/DrawableContainer.java
index aac7876..a1e0772 100644
--- a/graphics/java/android/graphics/drawable/DrawableContainer.java
+++ b/graphics/java/android/graphics/drawable/DrawableContainer.java
@@ -49,7 +49,6 @@
private DrawableContainerState mDrawableContainerState;
private Drawable mCurrDrawable;
private int mAlpha = 0xFF;
- private ColorFilter mColorFilter;
private int mCurIndex = -1;
private boolean mMutated;
@@ -147,8 +146,8 @@
@Override
public void setColorFilter(ColorFilter cf) {
- if (mColorFilter != cf) {
- mColorFilter = cf;
+ if (mDrawableContainerState.mColorFilter != cf) {
+ mDrawableContainerState.mColorFilter = cf;
if (mCurrDrawable != null) {
mCurrDrawable.mutate().setColorFilter(cf);
}
@@ -359,7 +358,7 @@
}
d.setVisible(isVisible(), true);
d.setDither(mDrawableContainerState.mDither);
- d.setColorFilter(mColorFilter);
+ d.setColorFilter(mDrawableContainerState.mColorFilter);
d.setState(getState());
d.setLevel(getLevel());
d.setBounds(getBounds());
@@ -507,6 +506,8 @@
boolean mAutoMirrored;
+ ColorFilter mColorFilter;
+
DrawableContainerState(DrawableContainerState orig, DrawableContainer owner,
Resources res) {
mOwner = owner;
@@ -527,6 +528,7 @@
mEnterFadeDuration = orig.mEnterFadeDuration;
mExitFadeDuration = orig.mExitFadeDuration;
mAutoMirrored = orig.mAutoMirrored;
+ mColorFilter = orig.mColorFilter;
// Cloning the following values may require creating futures.
mConstantPadding = orig.getConstantPadding();
diff --git a/graphics/java/android/graphics/drawable/NinePatchDrawable.java b/graphics/java/android/graphics/drawable/NinePatchDrawable.java
index 9c57a2c..515d3c1 100644
--- a/graphics/java/android/graphics/drawable/NinePatchDrawable.java
+++ b/graphics/java/android/graphics/drawable/NinePatchDrawable.java
@@ -26,12 +26,15 @@
import android.graphics.NinePatch;
import android.graphics.Paint;
import android.graphics.PixelFormat;
+import android.graphics.PorterDuffColorFilter;
import android.graphics.Rect;
import android.graphics.Region;
+import android.graphics.PorterDuff.Mode;
import android.util.AttributeSet;
import android.util.DisplayMetrics;
import android.util.LayoutDirection;
import android.util.TypedValue;
+
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
@@ -133,6 +136,9 @@
// lazy allocation of a paint
setDither(state.mDither);
}
+ if (state.mColorFilter != null) {
+ setColorFilter(state.mColorFilter);
+ }
setAutoMirrored(state.mAutoMirrored);
if (mNinePatch != null) {
computeBitmapSize();
@@ -366,9 +372,25 @@
final boolean automirrored = a.getBoolean(
com.android.internal.R.styleable.NinePatchDrawable_autoMirrored, false);
+ final NinePatchState ninePatchState = new NinePatchState(
+ new NinePatch(bitmap, bitmap.getNinePatchChunk()), padding, opticalInsets, dither,
+ automirrored);
- setNinePatchState(new NinePatchState(new NinePatch(bitmap, bitmap.getNinePatchChunk()),
- padding, opticalInsets, dither, automirrored), r);
+ if (a.hasValue(com.android.internal.R.styleable.NinePatchDrawable_colorFilterColor)) {
+ final int colorFilterColor = a.getColor(
+ com.android.internal.R.styleable.NinePatchDrawable_colorFilterColor, 0);
+ final int modeValue = a.getInt(
+ com.android.internal.R.styleable.NinePatchDrawable_colorFilterMode,
+ Mode.MULTIPLY.ordinal());
+ final Mode mode = Drawable.parseColorFilterMode(modeValue);
+ if (mode != null) {
+ // This will be applied to the paint by setNinePatchState().
+ ninePatchState.mColorFilter = new PorterDuffColorFilter(colorFilterColor, mode);
+ }
+ }
+
+ setNinePatchState(ninePatchState, r);
+
mNinePatchState.mTargetDensity = mTargetDensity;
a.recycle();
@@ -447,6 +469,7 @@
int mChangingConfigurations;
int mTargetDensity = DisplayMetrics.DENSITY_DEFAULT;
boolean mAutoMirrored;
+ ColorFilter mColorFilter;
NinePatchState(NinePatch ninePatch, Rect padding) {
this(ninePatch, padding, new Rect(), DEFAULT_DITHER, false);
@@ -477,6 +500,7 @@
mChangingConfigurations = state.mChangingConfigurations;
mTargetDensity = state.mTargetDensity;
mAutoMirrored = state.mAutoMirrored;
+ mColorFilter = state.mColorFilter;
}
@Override