am 882d5cd0: am d9a2b99d: am 42e96769: Merge "Add support for tint and tintMode to GradientDrawable" into lmp-mr1-dev

* commit '882d5cd051b2081e27f97dcf35a695737e00b434':
  Add support for tint and tintMode to GradientDrawable
diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml
index c75c0de..747cb14 100644
--- a/core/res/res/values/attrs.xml
+++ b/core/res/res/values/attrs.xml
@@ -4869,6 +4869,12 @@
         <attr name="thickness" format="dimension" />
         <!-- Indicates whether the drawable's level affects the way the gradient is drawn. -->
         <attr name="useLevel" />
+        <!-- If set, specifies the color to apply to the drawable as a tint. By default,
+             no tint is applied. May be a color state list. -->
+        <attr name="tint" />
+        <!-- When a tint color is set, specifies its Porter-Duff blending mode. The
+             default value is src_in, which treats the drawable as an alpha mask. -->
+        <attr name="tintMode" />
     </declare-styleable>
 
     <!-- Used to specify the size of the shape for GradientDrawable. -->
diff --git a/graphics/java/android/graphics/drawable/GradientDrawable.java b/graphics/java/android/graphics/drawable/GradientDrawable.java
index 43358b7..9d6a94d 100644
--- a/graphics/java/android/graphics/drawable/GradientDrawable.java
+++ b/graphics/java/android/graphics/drawable/GradientDrawable.java
@@ -29,6 +29,8 @@
 import android.graphics.Paint;
 import android.graphics.Path;
 import android.graphics.PixelFormat;
+import android.graphics.PorterDuff;
+import android.graphics.PorterDuffColorFilter;
 import android.graphics.RadialGradient;
 import android.graphics.Rect;
 import android.graphics.RectF;
@@ -134,6 +136,7 @@
     private Rect mPadding;
     private Paint mStrokePaint;   // optional, set by the caller
     private ColorFilter mColorFilter;   // optional, set by the caller
+    private PorterDuffColorFilter mTintFilter;
     private int mAlpha = 0xFF;  // modified by the caller
 
     private final Path mPath = new Path();
@@ -523,13 +526,15 @@
                 mStrokePaint.getStrokeWidth() > 0;
         final boolean haveFill = currFillAlpha > 0;
         final GradientState st = mGradientState;
+        final ColorFilter colorFilter = mColorFilter != null ? mColorFilter : mTintFilter;
+
         /*  we need a layer iff we're drawing both a fill and stroke, and the
             stroke is non-opaque, and our shapetype actually supports
             fill+stroke. Otherwise we can just draw the stroke (if any) on top
             of the fill (if any) without worrying about blending artifacts.
          */
-         final boolean useLayer = haveStroke && haveFill && st.mShape != LINE &&
-                 currStrokeAlpha < 255 && (mAlpha < 255 || mColorFilter != null);
+        final boolean useLayer = haveStroke && haveFill && st.mShape != LINE &&
+                 currStrokeAlpha < 255 && (mAlpha < 255 || colorFilter != null);
 
         /*  Drawing with a layer is slower than direct drawing, but it
             allows us to apply paint effects like alpha and colorfilter to
@@ -544,7 +549,7 @@
             }
             mLayerPaint.setDither(st.mDither);
             mLayerPaint.setAlpha(mAlpha);
-            mLayerPaint.setColorFilter(mColorFilter);
+            mLayerPaint.setColorFilter(colorFilter);
 
             float rad = mStrokePaint.getStrokeWidth();
             canvas.saveLayer(mRect.left - rad, mRect.top - rad,
@@ -561,14 +566,14 @@
             */
             mFillPaint.setAlpha(currFillAlpha);
             mFillPaint.setDither(st.mDither);
-            mFillPaint.setColorFilter(mColorFilter);
-            if (mColorFilter != null && st.mColorStateList == null) {
+            mFillPaint.setColorFilter(colorFilter);
+            if (colorFilter != null && st.mColorStateList == null) {
                 mFillPaint.setColor(mAlpha << 24);
             }
             if (haveStroke) {
                 mStrokePaint.setAlpha(currStrokeAlpha);
                 mStrokePaint.setDither(st.mDither);
-                mStrokePaint.setColorFilter(mColorFilter);
+                mStrokePaint.setColorFilter(colorFilter);
             }
         }
 
@@ -593,7 +598,7 @@
                         canvas.drawRoundRect(mRect, rad, rad, mStrokePaint);
                     }
                 } else {
-                    if (mFillPaint.getColor() != 0 || mColorFilter != null ||
+                    if (mFillPaint.getColor() != 0 || colorFilter != null ||
                             mFillPaint.getShader() != null) {
                         canvas.drawRect(mRect, mFillPaint);
                     }
@@ -768,6 +773,11 @@
             }
         }
 
+        if (s.mTint != null && s.mTintMode != null) {
+            mTintFilter = updateTintFilter(mTintFilter, s.mTint, s.mTintMode);
+            invalidateSelf = true;
+        }
+
         if (invalidateSelf) {
             invalidateSelf();
             return true;
@@ -781,7 +791,8 @@
         final GradientState s = mGradientState;
         return super.isStateful()
                 || (s.mColorStateList != null && s.mColorStateList.isStateful())
-                || (s.mStrokeColorStateList != null && s.mStrokeColorStateList.isStateful());
+                || (s.mStrokeColorStateList != null && s.mStrokeColorStateList.isStateful())
+                || (s.mTint != null && s.mTint.isStateful());
     }
 
     @Override
@@ -824,6 +835,20 @@
     }
 
     @Override
+    public void setTintList(ColorStateList tint) {
+        mGradientState.mTint = tint;
+        mTintFilter = updateTintFilter(mTintFilter, tint, mGradientState.mTintMode);
+        invalidateSelf();
+    }
+
+    @Override
+    public void setTintMode(PorterDuff.Mode tintMode) {
+        mGradientState.mTintMode = tintMode;
+        mTintFilter = updateTintFilter(mTintFilter, mGradientState.mTint, tintMode);
+        invalidateSelf();
+    }
+
+    @Override
     public int getOpacity() {
         return (mAlpha == 255 && mGradientState.mOpaqueOverBounds && isOpaqueForState()) ?
                 PixelFormat.OPAQUE : PixelFormat.TRANSLUCENT;
@@ -1045,6 +1070,18 @@
             state.mUseLevelForShape = a.getBoolean(
                     R.styleable.GradientDrawable_useLevel, state.mUseLevelForShape);
         }
+
+        final int tintMode = a.getInt(R.styleable.GradientDrawable_tintMode, -1);
+        if (tintMode != -1) {
+            state.mTintMode = Drawable.parseTintMode(tintMode, PorterDuff.Mode.SRC_IN);
+        }
+
+        final ColorStateList tint = a.getColorStateList(R.styleable.GradientDrawable_tint);
+        if (tint != null) {
+            state.mTint = tint;
+        }
+
+        mTintFilter = updateTintFilter(mTintFilter, state.mTint, state.mTintMode);
     }
 
     @Override
@@ -1522,6 +1559,9 @@
         private boolean mOpaqueOverBounds;
         private boolean mOpaqueOverShape;
 
+        ColorStateList mTint = null;
+        PorterDuff.Mode mTintMode = DEFAULT_TINT_MODE;
+
         int[] mThemeAttrs;
         int[] mAttrSize;
         int[] mAttrGradient;
@@ -1574,6 +1614,8 @@
             mUseLevelForShape = state.mUseLevelForShape;
             mOpaqueOverBounds = state.mOpaqueOverBounds;
             mOpaqueOverShape = state.mOpaqueOverShape;
+            mTint = state.mTint;
+            mTintMode = state.mTintMode;
             mThemeAttrs = state.mThemeAttrs;
             mAttrSize = state.mAttrSize;
             mAttrGradient = state.mAttrGradient;