Loading core/res/res/values/attrs.xml +6 −0 Original line number Original line Diff line number Diff line Loading @@ -4869,6 +4869,12 @@ <attr name="thickness" format="dimension" /> <attr name="thickness" format="dimension" /> <!-- Indicates whether the drawable's level affects the way the gradient is drawn. --> <!-- Indicates whether the drawable's level affects the way the gradient is drawn. --> <attr name="useLevel" /> <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> </declare-styleable> <!-- Used to specify the size of the shape for GradientDrawable. --> <!-- Used to specify the size of the shape for GradientDrawable. --> Loading graphics/java/android/graphics/drawable/GradientDrawable.java +50 −8 Original line number Original line Diff line number Diff line Loading @@ -29,6 +29,8 @@ import android.graphics.Outline; import android.graphics.Paint; import android.graphics.Paint; import android.graphics.Path; import android.graphics.Path; import android.graphics.PixelFormat; import android.graphics.PixelFormat; import android.graphics.PorterDuff; import android.graphics.PorterDuffColorFilter; import android.graphics.RadialGradient; import android.graphics.RadialGradient; import android.graphics.Rect; import android.graphics.Rect; import android.graphics.RectF; import android.graphics.RectF; Loading Loading @@ -134,6 +136,7 @@ public class GradientDrawable extends Drawable { private Rect mPadding; private Rect mPadding; private Paint mStrokePaint; // optional, set by the caller private Paint mStrokePaint; // optional, set by the caller private ColorFilter mColorFilter; // 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 int mAlpha = 0xFF; // modified by the caller private final Path mPath = new Path(); private final Path mPath = new Path(); Loading Loading @@ -523,13 +526,15 @@ public class GradientDrawable extends Drawable { mStrokePaint.getStrokeWidth() > 0; mStrokePaint.getStrokeWidth() > 0; final boolean haveFill = currFillAlpha > 0; final boolean haveFill = currFillAlpha > 0; final GradientState st = mGradientState; 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 /* we need a layer iff we're drawing both a fill and stroke, and the stroke is non-opaque, and our shapetype actually supports stroke is non-opaque, and our shapetype actually supports fill+stroke. Otherwise we can just draw the stroke (if any) on top fill+stroke. Otherwise we can just draw the stroke (if any) on top of the fill (if any) without worrying about blending artifacts. of the fill (if any) without worrying about blending artifacts. */ */ final boolean useLayer = haveStroke && haveFill && st.mShape != LINE && final boolean useLayer = haveStroke && haveFill && st.mShape != LINE && currStrokeAlpha < 255 && (mAlpha < 255 || mColorFilter != null); currStrokeAlpha < 255 && (mAlpha < 255 || colorFilter != null); /* Drawing with a layer is slower than direct drawing, but it /* Drawing with a layer is slower than direct drawing, but it allows us to apply paint effects like alpha and colorfilter to allows us to apply paint effects like alpha and colorfilter to Loading @@ -544,7 +549,7 @@ public class GradientDrawable extends Drawable { } } mLayerPaint.setDither(st.mDither); mLayerPaint.setDither(st.mDither); mLayerPaint.setAlpha(mAlpha); mLayerPaint.setAlpha(mAlpha); mLayerPaint.setColorFilter(mColorFilter); mLayerPaint.setColorFilter(colorFilter); float rad = mStrokePaint.getStrokeWidth(); float rad = mStrokePaint.getStrokeWidth(); canvas.saveLayer(mRect.left - rad, mRect.top - rad, canvas.saveLayer(mRect.left - rad, mRect.top - rad, Loading @@ -561,14 +566,14 @@ public class GradientDrawable extends Drawable { */ */ mFillPaint.setAlpha(currFillAlpha); mFillPaint.setAlpha(currFillAlpha); mFillPaint.setDither(st.mDither); mFillPaint.setDither(st.mDither); mFillPaint.setColorFilter(mColorFilter); mFillPaint.setColorFilter(colorFilter); if (mColorFilter != null && st.mColorStateList == null) { if (colorFilter != null && st.mColorStateList == null) { mFillPaint.setColor(mAlpha << 24); mFillPaint.setColor(mAlpha << 24); } } if (haveStroke) { if (haveStroke) { mStrokePaint.setAlpha(currStrokeAlpha); mStrokePaint.setAlpha(currStrokeAlpha); mStrokePaint.setDither(st.mDither); mStrokePaint.setDither(st.mDither); mStrokePaint.setColorFilter(mColorFilter); mStrokePaint.setColorFilter(colorFilter); } } } } Loading @@ -593,7 +598,7 @@ public class GradientDrawable extends Drawable { canvas.drawRoundRect(mRect, rad, rad, mStrokePaint); canvas.drawRoundRect(mRect, rad, rad, mStrokePaint); } } } else { } else { if (mFillPaint.getColor() != 0 || mColorFilter != null || if (mFillPaint.getColor() != 0 || colorFilter != null || mFillPaint.getShader() != null) { mFillPaint.getShader() != null) { canvas.drawRect(mRect, mFillPaint); canvas.drawRect(mRect, mFillPaint); } } Loading Loading @@ -768,6 +773,11 @@ public class GradientDrawable extends Drawable { } } } } if (s.mTint != null && s.mTintMode != null) { mTintFilter = updateTintFilter(mTintFilter, s.mTint, s.mTintMode); invalidateSelf = true; } if (invalidateSelf) { if (invalidateSelf) { invalidateSelf(); invalidateSelf(); return true; return true; Loading @@ -781,7 +791,8 @@ public class GradientDrawable extends Drawable { final GradientState s = mGradientState; final GradientState s = mGradientState; return super.isStateful() return super.isStateful() || (s.mColorStateList != null && s.mColorStateList.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 @Override Loading Loading @@ -823,6 +834,20 @@ public class GradientDrawable extends Drawable { } } } } @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 @Override public int getOpacity() { public int getOpacity() { return (mAlpha == 255 && mGradientState.mOpaqueOverBounds && isOpaqueForState()) ? return (mAlpha == 255 && mGradientState.mOpaqueOverBounds && isOpaqueForState()) ? Loading Loading @@ -1045,6 +1070,18 @@ public class GradientDrawable extends Drawable { state.mUseLevelForShape = a.getBoolean( state.mUseLevelForShape = a.getBoolean( R.styleable.GradientDrawable_useLevel, state.mUseLevelForShape); 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 @Override Loading Loading @@ -1522,6 +1559,9 @@ public class GradientDrawable extends Drawable { private boolean mOpaqueOverBounds; private boolean mOpaqueOverBounds; private boolean mOpaqueOverShape; private boolean mOpaqueOverShape; ColorStateList mTint = null; PorterDuff.Mode mTintMode = DEFAULT_TINT_MODE; int[] mThemeAttrs; int[] mThemeAttrs; int[] mAttrSize; int[] mAttrSize; int[] mAttrGradient; int[] mAttrGradient; Loading Loading @@ -1574,6 +1614,8 @@ public class GradientDrawable extends Drawable { mUseLevelForShape = state.mUseLevelForShape; mUseLevelForShape = state.mUseLevelForShape; mOpaqueOverBounds = state.mOpaqueOverBounds; mOpaqueOverBounds = state.mOpaqueOverBounds; mOpaqueOverShape = state.mOpaqueOverShape; mOpaqueOverShape = state.mOpaqueOverShape; mTint = state.mTint; mTintMode = state.mTintMode; mThemeAttrs = state.mThemeAttrs; mThemeAttrs = state.mThemeAttrs; mAttrSize = state.mAttrSize; mAttrSize = state.mAttrSize; mAttrGradient = state.mAttrGradient; mAttrGradient = state.mAttrGradient; Loading Loading
core/res/res/values/attrs.xml +6 −0 Original line number Original line Diff line number Diff line Loading @@ -4869,6 +4869,12 @@ <attr name="thickness" format="dimension" /> <attr name="thickness" format="dimension" /> <!-- Indicates whether the drawable's level affects the way the gradient is drawn. --> <!-- Indicates whether the drawable's level affects the way the gradient is drawn. --> <attr name="useLevel" /> <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> </declare-styleable> <!-- Used to specify the size of the shape for GradientDrawable. --> <!-- Used to specify the size of the shape for GradientDrawable. --> Loading
graphics/java/android/graphics/drawable/GradientDrawable.java +50 −8 Original line number Original line Diff line number Diff line Loading @@ -29,6 +29,8 @@ import android.graphics.Outline; import android.graphics.Paint; import android.graphics.Paint; import android.graphics.Path; import android.graphics.Path; import android.graphics.PixelFormat; import android.graphics.PixelFormat; import android.graphics.PorterDuff; import android.graphics.PorterDuffColorFilter; import android.graphics.RadialGradient; import android.graphics.RadialGradient; import android.graphics.Rect; import android.graphics.Rect; import android.graphics.RectF; import android.graphics.RectF; Loading Loading @@ -134,6 +136,7 @@ public class GradientDrawable extends Drawable { private Rect mPadding; private Rect mPadding; private Paint mStrokePaint; // optional, set by the caller private Paint mStrokePaint; // optional, set by the caller private ColorFilter mColorFilter; // 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 int mAlpha = 0xFF; // modified by the caller private final Path mPath = new Path(); private final Path mPath = new Path(); Loading Loading @@ -523,13 +526,15 @@ public class GradientDrawable extends Drawable { mStrokePaint.getStrokeWidth() > 0; mStrokePaint.getStrokeWidth() > 0; final boolean haveFill = currFillAlpha > 0; final boolean haveFill = currFillAlpha > 0; final GradientState st = mGradientState; 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 /* we need a layer iff we're drawing both a fill and stroke, and the stroke is non-opaque, and our shapetype actually supports stroke is non-opaque, and our shapetype actually supports fill+stroke. Otherwise we can just draw the stroke (if any) on top fill+stroke. Otherwise we can just draw the stroke (if any) on top of the fill (if any) without worrying about blending artifacts. of the fill (if any) without worrying about blending artifacts. */ */ final boolean useLayer = haveStroke && haveFill && st.mShape != LINE && final boolean useLayer = haveStroke && haveFill && st.mShape != LINE && currStrokeAlpha < 255 && (mAlpha < 255 || mColorFilter != null); currStrokeAlpha < 255 && (mAlpha < 255 || colorFilter != null); /* Drawing with a layer is slower than direct drawing, but it /* Drawing with a layer is slower than direct drawing, but it allows us to apply paint effects like alpha and colorfilter to allows us to apply paint effects like alpha and colorfilter to Loading @@ -544,7 +549,7 @@ public class GradientDrawable extends Drawable { } } mLayerPaint.setDither(st.mDither); mLayerPaint.setDither(st.mDither); mLayerPaint.setAlpha(mAlpha); mLayerPaint.setAlpha(mAlpha); mLayerPaint.setColorFilter(mColorFilter); mLayerPaint.setColorFilter(colorFilter); float rad = mStrokePaint.getStrokeWidth(); float rad = mStrokePaint.getStrokeWidth(); canvas.saveLayer(mRect.left - rad, mRect.top - rad, canvas.saveLayer(mRect.left - rad, mRect.top - rad, Loading @@ -561,14 +566,14 @@ public class GradientDrawable extends Drawable { */ */ mFillPaint.setAlpha(currFillAlpha); mFillPaint.setAlpha(currFillAlpha); mFillPaint.setDither(st.mDither); mFillPaint.setDither(st.mDither); mFillPaint.setColorFilter(mColorFilter); mFillPaint.setColorFilter(colorFilter); if (mColorFilter != null && st.mColorStateList == null) { if (colorFilter != null && st.mColorStateList == null) { mFillPaint.setColor(mAlpha << 24); mFillPaint.setColor(mAlpha << 24); } } if (haveStroke) { if (haveStroke) { mStrokePaint.setAlpha(currStrokeAlpha); mStrokePaint.setAlpha(currStrokeAlpha); mStrokePaint.setDither(st.mDither); mStrokePaint.setDither(st.mDither); mStrokePaint.setColorFilter(mColorFilter); mStrokePaint.setColorFilter(colorFilter); } } } } Loading @@ -593,7 +598,7 @@ public class GradientDrawable extends Drawable { canvas.drawRoundRect(mRect, rad, rad, mStrokePaint); canvas.drawRoundRect(mRect, rad, rad, mStrokePaint); } } } else { } else { if (mFillPaint.getColor() != 0 || mColorFilter != null || if (mFillPaint.getColor() != 0 || colorFilter != null || mFillPaint.getShader() != null) { mFillPaint.getShader() != null) { canvas.drawRect(mRect, mFillPaint); canvas.drawRect(mRect, mFillPaint); } } Loading Loading @@ -768,6 +773,11 @@ public class GradientDrawable extends Drawable { } } } } if (s.mTint != null && s.mTintMode != null) { mTintFilter = updateTintFilter(mTintFilter, s.mTint, s.mTintMode); invalidateSelf = true; } if (invalidateSelf) { if (invalidateSelf) { invalidateSelf(); invalidateSelf(); return true; return true; Loading @@ -781,7 +791,8 @@ public class GradientDrawable extends Drawable { final GradientState s = mGradientState; final GradientState s = mGradientState; return super.isStateful() return super.isStateful() || (s.mColorStateList != null && s.mColorStateList.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 @Override Loading Loading @@ -823,6 +834,20 @@ public class GradientDrawable extends Drawable { } } } } @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 @Override public int getOpacity() { public int getOpacity() { return (mAlpha == 255 && mGradientState.mOpaqueOverBounds && isOpaqueForState()) ? return (mAlpha == 255 && mGradientState.mOpaqueOverBounds && isOpaqueForState()) ? Loading Loading @@ -1045,6 +1070,18 @@ public class GradientDrawable extends Drawable { state.mUseLevelForShape = a.getBoolean( state.mUseLevelForShape = a.getBoolean( R.styleable.GradientDrawable_useLevel, state.mUseLevelForShape); 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 @Override Loading Loading @@ -1522,6 +1559,9 @@ public class GradientDrawable extends Drawable { private boolean mOpaqueOverBounds; private boolean mOpaqueOverBounds; private boolean mOpaqueOverShape; private boolean mOpaqueOverShape; ColorStateList mTint = null; PorterDuff.Mode mTintMode = DEFAULT_TINT_MODE; int[] mThemeAttrs; int[] mThemeAttrs; int[] mAttrSize; int[] mAttrSize; int[] mAttrGradient; int[] mAttrGradient; Loading Loading @@ -1574,6 +1614,8 @@ public class GradientDrawable extends Drawable { mUseLevelForShape = state.mUseLevelForShape; mUseLevelForShape = state.mUseLevelForShape; mOpaqueOverBounds = state.mOpaqueOverBounds; mOpaqueOverBounds = state.mOpaqueOverBounds; mOpaqueOverShape = state.mOpaqueOverShape; mOpaqueOverShape = state.mOpaqueOverShape; mTint = state.mTint; mTintMode = state.mTintMode; mThemeAttrs = state.mThemeAttrs; mThemeAttrs = state.mThemeAttrs; mAttrSize = state.mAttrSize; mAttrSize = state.mAttrSize; mAttrGradient = state.mAttrGradient; mAttrGradient = state.mAttrGradient; Loading