diff options
Diffstat (limited to 'graphics/java')
21 files changed, 367 insertions, 137 deletions
diff --git a/graphics/java/android/graphics/BaseCanvas.java b/graphics/java/android/graphics/BaseCanvas.java index fd3773588299..31906781159b 100644 --- a/graphics/java/android/graphics/BaseCanvas.java +++ b/graphics/java/android/graphics/BaseCanvas.java @@ -240,7 +240,7 @@ public abstract class BaseCanvas { } public void drawColor(@ColorInt int color) { - nDrawColor(mNativeCanvasWrapper, color, PorterDuff.Mode.SRC_OVER.nativeInt); + nDrawColor(mNativeCanvasWrapper, color, BlendMode.SRC_OVER.getXfermode().porterDuffMode); } /** diff --git a/graphics/java/android/graphics/BaseRecordingCanvas.java b/graphics/java/android/graphics/BaseRecordingCanvas.java index 3e117411db01..2afc3d27fa27 100644 --- a/graphics/java/android/graphics/BaseRecordingCanvas.java +++ b/graphics/java/android/graphics/BaseRecordingCanvas.java @@ -200,7 +200,7 @@ public class BaseRecordingCanvas extends Canvas { @Override public final void drawColor(@ColorInt int color) { - nDrawColor(mNativeCanvasWrapper, color, PorterDuff.Mode.SRC_OVER.nativeInt); + nDrawColor(mNativeCanvasWrapper, color, BlendMode.SRC_OVER.getXfermode().porterDuffMode); } /** diff --git a/graphics/java/android/graphics/BlendMode.java b/graphics/java/android/graphics/BlendMode.java index 39392c89d170..0b267048d976 100644 --- a/graphics/java/android/graphics/BlendMode.java +++ b/graphics/java/android/graphics/BlendMode.java @@ -454,6 +454,64 @@ public enum BlendMode { return null; } + /** + * @hide + */ + public static int toValue(BlendMode mode) { + return mode.getXfermode().porterDuffMode; + } + + /** + * @hide + */ + public static @Nullable PorterDuff.Mode blendModeToPorterDuffMode(@Nullable BlendMode mode) { + if (mode != null) { + switch (mode) { + case CLEAR: + return PorterDuff.Mode.CLEAR; + case SRC: + return PorterDuff.Mode.SRC; + case DST: + return PorterDuff.Mode.DST; + case SRC_OVER: + return PorterDuff.Mode.SRC_OVER; + case DST_OVER: + return PorterDuff.Mode.DST_OVER; + case SRC_IN: + return PorterDuff.Mode.SRC_IN; + case DST_IN: + return PorterDuff.Mode.DST_IN; + case SRC_OUT: + return PorterDuff.Mode.SRC_OUT; + case DST_OUT: + return PorterDuff.Mode.DST_OUT; + case SRC_ATOP: + return PorterDuff.Mode.SRC_ATOP; + case DST_ATOP: + return PorterDuff.Mode.DST_ATOP; + case XOR: + return PorterDuff.Mode.XOR; + case DARKEN: + return PorterDuff.Mode.DARKEN; + case LIGHTEN: + return PorterDuff.Mode.LIGHTEN; + // b/73224934 PorterDuff Multiply maps to Skia Modulate + case MODULATE: + return PorterDuff.Mode.MULTIPLY; + case SCREEN: + return PorterDuff.Mode.SCREEN; + case PLUS: + return PorterDuff.Mode.ADD; + case OVERLAY: + return PorterDuff.Mode.OVERLAY; + default: + return null; + } + } else { + return null; + } + } + @NonNull private final Xfermode mXfermode; diff --git a/graphics/java/android/graphics/ComposeShader.java b/graphics/java/android/graphics/ComposeShader.java index 189e1746e644..93ddb10d24bc 100644 --- a/graphics/java/android/graphics/ComposeShader.java +++ b/graphics/java/android/graphics/ComposeShader.java @@ -39,7 +39,10 @@ public class ComposeShader extends Shader { * @param shaderB The colors from this shader are seen as the "src" by the mode * @param mode The mode that combines the colors from the two shaders. If mode * is null, then SRC_OVER is assumed. + * + * @deprecated use {@link #ComposeShader(Shader, Shader, BlendMode)} instead */ + @Deprecated public ComposeShader(@NonNull Shader shaderA, @NonNull Shader shaderB, @NonNull Xfermode mode) { this(shaderA, shaderB, mode.porterDuffMode); } @@ -52,12 +55,29 @@ public class ComposeShader extends Shader { * @param shaderA The colors from this shader are seen as the "dst" by the mode * @param shaderB The colors from this shader are seen as the "src" by the mode * @param mode The PorterDuff mode that combines the colors from the two shaders. - */ + * + * @deprecated use {@link #ComposeShader(Shader, Shader, BlendMode)} instead + */ + @Deprecated public ComposeShader(@NonNull Shader shaderA, @NonNull Shader shaderB, @NonNull PorterDuff.Mode mode) { this(shaderA, shaderB, mode.nativeInt); } + /** + * Create a new compose shader, given shaders A, B, and a combining PorterDuff mode. + * When the mode is applied, it will be given the result from shader A as its + * "dst", and the result from shader B as its "src". + * + * @param shaderA The colors from this shader are seen as the "dst" by the mode + * @param shaderB The colors from this shader are seen as the "src" by the mode + * @param blendMode The blend mode that combines the colors from the two shaders. + */ + public ComposeShader(@NonNull Shader shaderA, @NonNull Shader shaderB, + @NonNull BlendMode blendMode) { + this(shaderA, shaderB, blendMode.getXfermode().porterDuffMode); + } + private ComposeShader(Shader shaderA, Shader shaderB, int nativeMode) { if (shaderA == null || shaderB == null) { throw new IllegalArgumentException("Shader parameters must not be null"); diff --git a/graphics/java/android/graphics/PorterDuff.java b/graphics/java/android/graphics/PorterDuff.java index fba50430f2ef..459291b7565e 100644 --- a/graphics/java/android/graphics/PorterDuff.java +++ b/graphics/java/android/graphics/PorterDuff.java @@ -23,7 +23,10 @@ import android.annotation.UnsupportedAppUsage; * that can be passed to {@link PorterDuffXfermode}, a specialized implementation * of {@link Paint}'s {@link Paint#setXfermode(Xfermode) transfer mode}. * All the available modes can be found in the {@link Mode} enum.</p> + * + * @deprecated Use {@link BlendMode} with {@link Paint#setBlendMode(BlendMode)} instead */ +@Deprecated public class PorterDuff { /** * {@usesMathJax} diff --git a/graphics/java/android/graphics/PorterDuffXfermode.java b/graphics/java/android/graphics/PorterDuffXfermode.java index 84d953de91db..5b933c493162 100644 --- a/graphics/java/android/graphics/PorterDuffXfermode.java +++ b/graphics/java/android/graphics/PorterDuffXfermode.java @@ -21,6 +21,11 @@ package android.graphics; * {@link Paint#setXfermode(Xfermode) transfer mode}. Refer to the * documentation of the {@link PorterDuff.Mode} enum for more * information on the available alpha compositing and blending modes.</p> + * + * @deprecated Consider using {@link BlendMode} instead as it supports a wider + * set of blend modes than those defined in {@link PorterDuff.Mode} + * + * @see Paint#setBlendMode(BlendMode) */ public class PorterDuffXfermode extends Xfermode { /** diff --git a/graphics/java/android/graphics/Xfermode.java b/graphics/java/android/graphics/Xfermode.java index 6f4adfde7ff9..41cf79ad49fd 100644 --- a/graphics/java/android/graphics/Xfermode.java +++ b/graphics/java/android/graphics/Xfermode.java @@ -31,7 +31,7 @@ import android.annotation.UnsupportedAppUsage; * objects drawn with that paint have the xfermode applied. */ public class Xfermode { - static final int DEFAULT = PorterDuff.Mode.SRC_OVER.nativeInt; + static final int DEFAULT = BlendMode.SRC_OVER.getXfermode().porterDuffMode; @UnsupportedAppUsage int porterDuffMode = DEFAULT; } diff --git a/graphics/java/android/graphics/drawable/AdaptiveIconDrawable.java b/graphics/java/android/graphics/drawable/AdaptiveIconDrawable.java index cb12a7c6ba6b..7def322c1953 100644 --- a/graphics/java/android/graphics/drawable/AdaptiveIconDrawable.java +++ b/graphics/java/android/graphics/drawable/AdaptiveIconDrawable.java @@ -27,6 +27,7 @@ import android.content.res.Resources.Theme; import android.content.res.TypedArray; import android.graphics.Bitmap; import android.graphics.BitmapShader; +import android.graphics.BlendMode; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.ColorFilter; @@ -35,7 +36,6 @@ import android.graphics.Outline; import android.graphics.Paint; import android.graphics.Path; import android.graphics.PixelFormat; -import android.graphics.PorterDuff.Mode; import android.graphics.Rect; import android.graphics.Region; import android.graphics.Shader; @@ -701,13 +701,13 @@ public class AdaptiveIconDrawable extends Drawable implements Drawable.Callback } @Override - public void setTintMode(Mode tintMode) { + public void setTintMode(@NonNull BlendMode blendMode) { final ChildDrawable[] array = mLayerState.mChildren; final int N = mLayerState.N_CHILDREN; for (int i = 0; i < N; i++) { final Drawable dr = array[i].mDrawable; if (dr != null) { - dr.setTintMode(tintMode); + dr.setTintMode(blendMode); } } } diff --git a/graphics/java/android/graphics/drawable/AnimatedVectorDrawable.java b/graphics/java/android/graphics/drawable/AnimatedVectorDrawable.java index d9dab98c2be1..f45bf9b783e8 100644 --- a/graphics/java/android/graphics/drawable/AnimatedVectorDrawable.java +++ b/graphics/java/android/graphics/drawable/AnimatedVectorDrawable.java @@ -33,12 +33,12 @@ import android.content.res.ColorStateList; import android.content.res.Resources; import android.content.res.Resources.Theme; import android.content.res.TypedArray; +import android.graphics.BlendMode; import android.graphics.Canvas; import android.graphics.ColorFilter; import android.graphics.Insets; import android.graphics.Outline; import android.graphics.PixelFormat; -import android.graphics.PorterDuff; import android.graphics.RecordingCanvas; import android.graphics.Rect; import android.graphics.RenderNode; @@ -477,8 +477,8 @@ public class AnimatedVectorDrawable extends Drawable implements Animatable2 { } @Override - public void setTintMode(PorterDuff.Mode tintMode) { - mAnimatedVectorState.mVectorDrawable.setTintMode(tintMode); + public void setTintMode(@NonNull BlendMode blendMode) { + mAnimatedVectorState.mVectorDrawable.setTintMode(blendMode); } @Override diff --git a/graphics/java/android/graphics/drawable/BitmapDrawable.java b/graphics/java/android/graphics/drawable/BitmapDrawable.java index 976190109e7c..6b30158a183a 100644 --- a/graphics/java/android/graphics/drawable/BitmapDrawable.java +++ b/graphics/java/android/graphics/drawable/BitmapDrawable.java @@ -25,6 +25,8 @@ import android.content.res.Resources.Theme; import android.content.res.TypedArray; import android.graphics.Bitmap; import android.graphics.BitmapShader; +import android.graphics.BlendMode; +import android.graphics.BlendModeColorFilter; import android.graphics.Canvas; import android.graphics.ColorFilter; import android.graphics.ImageDecoder; @@ -33,9 +35,7 @@ import android.graphics.Matrix; import android.graphics.Outline; import android.graphics.Paint; import android.graphics.PixelFormat; -import android.graphics.PorterDuff; import android.graphics.PorterDuff.Mode; -import android.graphics.PorterDuffColorFilter; import android.graphics.Rect; import android.graphics.Shader; import android.graphics.Xfermode; @@ -90,7 +90,7 @@ public class BitmapDrawable extends Drawable { @UnsupportedAppUsage private BitmapState mBitmapState; - private PorterDuffColorFilter mTintFilter; + private BlendModeColorFilter mBlendModeFilter; @UnsupportedAppUsage private int mTargetDensity = DisplayMetrics.DENSITY_DEFAULT; @@ -527,8 +527,8 @@ public class BitmapDrawable extends Drawable { } final boolean clearColorFilter; - if (mTintFilter != null && paint.getColorFilter() == null) { - paint.setColorFilter(mTintFilter); + if (mBlendModeFilter != null && paint.getColorFilter() == null) { + paint.setColorFilter(mBlendModeFilter); clearColorFilter = true; } else { clearColorFilter = false; @@ -678,17 +678,19 @@ public class BitmapDrawable extends Drawable { final BitmapState state = mBitmapState; if (state.mTint != tint) { state.mTint = tint; - mTintFilter = updateTintFilter(mTintFilter, tint, mBitmapState.mTintMode); + mBlendModeFilter = updateBlendModeFilter(mBlendModeFilter, tint, + mBitmapState.mBlendMode); invalidateSelf(); } } @Override - public void setTintMode(PorterDuff.Mode tintMode) { + public void setTintMode(@NonNull BlendMode blendMode) { final BitmapState state = mBitmapState; - if (state.mTintMode != tintMode) { - state.mTintMode = tintMode; - mTintFilter = updateTintFilter(mTintFilter, mBitmapState.mTint, tintMode); + if (state.mBlendMode != blendMode) { + state.mBlendMode = blendMode; + mBlendModeFilter = updateBlendModeFilter(mBlendModeFilter, mBitmapState.mTint, + blendMode); invalidateSelf(); } } @@ -706,7 +708,7 @@ public class BitmapDrawable extends Drawable { */ @UnsupportedAppUsage public Mode getTintMode() { - return mBitmapState.mTintMode; + return BlendMode.blendModeToPorterDuffMode(mBitmapState.mBlendMode); } /** @@ -744,8 +746,9 @@ public class BitmapDrawable extends Drawable { @Override protected boolean onStateChange(int[] stateSet) { final BitmapState state = mBitmapState; - if (state.mTint != null && state.mTintMode != null) { - mTintFilter = updateTintFilter(mTintFilter, state.mTint, state.mTintMode); + if (state.mTint != null && state.mBlendMode != null) { + mBlendModeFilter = updateBlendModeFilter(mBlendModeFilter, state.mTint, + state.mBlendMode); return true; } return false; @@ -864,7 +867,7 @@ public class BitmapDrawable extends Drawable { final int tintMode = a.getInt(R.styleable.BitmapDrawable_tintMode, -1); if (tintMode != -1) { - state.mTintMode = Drawable.parseTintMode(tintMode, Mode.SRC_IN); + state.mBlendMode = Drawable.parseBlendMode(tintMode, BlendMode.SRC_IN); } final ColorStateList tint = a.getColorStateList(R.styleable.BitmapDrawable_tint); @@ -979,7 +982,8 @@ public class BitmapDrawable extends Drawable { int[] mThemeAttrs = null; Bitmap mBitmap = null; ColorStateList mTint = null; - Mode mTintMode = DEFAULT_TINT_MODE; + BlendMode mBlendMode = DEFAULT_BLEND_MODE; + int mGravity = Gravity.FILL; float mBaseAlpha = 1.0f; Shader.TileMode mTileModeX = null; @@ -1005,7 +1009,7 @@ public class BitmapDrawable extends Drawable { BitmapState(BitmapState bitmapState) { mBitmap = bitmapState.mBitmap; mTint = bitmapState.mTint; - mTintMode = bitmapState.mTintMode; + mBlendMode = bitmapState.mBlendMode; mThemeAttrs = bitmapState.mThemeAttrs; mChangingConfigurations = bitmapState.mChangingConfigurations; mGravity = bitmapState.mGravity; @@ -1065,7 +1069,8 @@ public class BitmapDrawable extends Drawable { */ private void updateLocalState(Resources res) { mTargetDensity = resolveDensity(res, mBitmapState.mTargetDensity); - mTintFilter = updateTintFilter(mTintFilter, mBitmapState.mTint, mBitmapState.mTintMode); + mBlendModeFilter = updateBlendModeFilter(mBlendModeFilter, mBitmapState.mTint, + mBitmapState.mBlendMode); computeBitmapSize(); } } diff --git a/graphics/java/android/graphics/drawable/ColorDrawable.java b/graphics/java/android/graphics/drawable/ColorDrawable.java index 3c449166d9d5..efa806afce70 100644 --- a/graphics/java/android/graphics/drawable/ColorDrawable.java +++ b/graphics/java/android/graphics/drawable/ColorDrawable.java @@ -26,13 +26,13 @@ import android.content.res.ColorStateList; import android.content.res.Resources; import android.content.res.Resources.Theme; import android.content.res.TypedArray; +import android.graphics.BlendMode; +import android.graphics.BlendModeColorFilter; import android.graphics.Canvas; import android.graphics.ColorFilter; import android.graphics.Outline; import android.graphics.Paint; import android.graphics.PixelFormat; -import android.graphics.PorterDuff.Mode; -import android.graphics.PorterDuffColorFilter; import android.graphics.Xfermode; import android.util.AttributeSet; import android.view.ViewDebug; @@ -58,7 +58,7 @@ public class ColorDrawable extends Drawable { @ViewDebug.ExportedProperty(deepExport = true, prefix = "state_") private ColorState mColorState; - private PorterDuffColorFilter mTintFilter; + private BlendModeColorFilter mBlendModeColorFilter; private boolean mMutated; @@ -111,9 +111,10 @@ public class ColorDrawable extends Drawable { @Override public void draw(Canvas canvas) { final ColorFilter colorFilter = mPaint.getColorFilter(); - if ((mColorState.mUseColor >>> 24) != 0 || colorFilter != null || mTintFilter != null) { + if ((mColorState.mUseColor >>> 24) != 0 || colorFilter != null + || mBlendModeColorFilter != null) { if (colorFilter == null) { - mPaint.setColorFilter(mTintFilter); + mPaint.setColorFilter(mBlendModeColorFilter); } mPaint.setColor(mColorState.mUseColor); @@ -208,22 +209,25 @@ public class ColorDrawable extends Drawable { @Override public void setTintList(ColorStateList tint) { mColorState.mTint = tint; - mTintFilter = updateTintFilter(mTintFilter, tint, mColorState.mTintMode); + mBlendModeColorFilter = updateBlendModeFilter(mBlendModeColorFilter, tint, + mColorState.mBlendMode); invalidateSelf(); } @Override - public void setTintMode(Mode tintMode) { - mColorState.mTintMode = tintMode; - mTintFilter = updateTintFilter(mTintFilter, mColorState.mTint, tintMode); + public void setTintMode(@NonNull BlendMode blendMode) { + mColorState.mBlendMode = blendMode; + mBlendModeColorFilter = updateBlendModeFilter(mBlendModeColorFilter, mColorState.mTint, + blendMode); invalidateSelf(); } @Override protected boolean onStateChange(int[] stateSet) { final ColorState state = mColorState; - if (state.mTint != null && state.mTintMode != null) { - mTintFilter = updateTintFilter(mTintFilter, state.mTint, state.mTintMode); + if (state.mTint != null && state.mBlendMode != null) { + mBlendModeColorFilter = updateBlendModeFilter(mBlendModeColorFilter, state.mTint, + state.mBlendMode); return true; } return false; @@ -261,7 +265,7 @@ public class ColorDrawable extends Drawable { @Override public int getOpacity() { - if (mTintFilter != null || mPaint.getColorFilter() != null) { + if (mBlendModeColorFilter != null || mPaint.getColorFilter() != null) { return PixelFormat.TRANSLUCENT; } @@ -348,7 +352,7 @@ public class ColorDrawable extends Drawable { int mUseColor; // basecolor modulated by setAlpha() @Config int mChangingConfigurations; ColorStateList mTint = null; - Mode mTintMode = DEFAULT_TINT_MODE; + BlendMode mBlendMode = DEFAULT_BLEND_MODE; ColorState() { // Empty constructor. @@ -360,7 +364,7 @@ public class ColorDrawable extends Drawable { mUseColor = state.mUseColor; mChangingConfigurations = state.mChangingConfigurations; mTint = state.mTint; - mTintMode = state.mTintMode; + mBlendMode = state.mBlendMode; } @Override @@ -398,6 +402,7 @@ public class ColorDrawable extends Drawable { * after inflating or applying a theme. */ private void updateLocalState(Resources r) { - mTintFilter = updateTintFilter(mTintFilter, mColorState.mTint, mColorState.mTintMode); + mBlendModeColorFilter = updateBlendModeFilter(mBlendModeColorFilter, mColorState.mTint, + mColorState.mBlendMode); } } diff --git a/graphics/java/android/graphics/drawable/ColorStateListDrawable.java b/graphics/java/android/graphics/drawable/ColorStateListDrawable.java index ee4d1e72c130..b94b11468371 100644 --- a/graphics/java/android/graphics/drawable/ColorStateListDrawable.java +++ b/graphics/java/android/graphics/drawable/ColorStateListDrawable.java @@ -21,10 +21,10 @@ import android.annotation.Nullable; import android.content.pm.ActivityInfo; import android.content.res.ColorStateList; import android.content.res.Resources; +import android.graphics.BlendMode; import android.graphics.Canvas; import android.graphics.ColorFilter; import android.graphics.PixelFormat; -import android.graphics.PorterDuff; import android.util.MathUtils; /** @@ -114,9 +114,9 @@ public class ColorStateListDrawable extends Drawable implements Drawable.Callbac } @Override - public void setTintMode(@NonNull PorterDuff.Mode tintMode) { - mState.mTintMode = tintMode; - mColorDrawable.setTintMode(tintMode); + public void setTintMode(@NonNull BlendMode blendMode) { + mState.mBlendMode = blendMode; + mColorDrawable.setTintMode(blendMode); onStateChange(getState()); } @@ -236,7 +236,7 @@ public class ColorStateListDrawable extends Drawable implements Drawable.Callbac ColorStateList mColor = null; ColorStateList mTint = null; int mAlpha = -1; - PorterDuff.Mode mTintMode = DEFAULT_TINT_MODE; + BlendMode mBlendMode = DEFAULT_BLEND_MODE; @ActivityInfo.Config int mChangingConfigurations = 0; ColorStateListDrawableState() { @@ -246,7 +246,7 @@ public class ColorStateListDrawable extends Drawable implements Drawable.Callbac mColor = state.mColor; mTint = state.mTint; mAlpha = state.mAlpha; - mTintMode = state.mTintMode; + mBlendMode = state.mBlendMode; mChangingConfigurations = state.mChangingConfigurations; } @@ -292,8 +292,8 @@ public class ColorStateListDrawable extends Drawable implements Drawable.Callbac mColorDrawable.setTintList(mState.mTint); } - if (mState.mTintMode != DEFAULT_TINT_MODE) { - mColorDrawable.setTintMode(mState.mTintMode); + if (mState.mBlendMode != DEFAULT_BLEND_MODE) { + mColorDrawable.setTintMode(mState.mBlendMode); } } } diff --git a/graphics/java/android/graphics/drawable/Drawable.java b/graphics/java/android/graphics/drawable/Drawable.java index 49d353057d59..e4142a933f0f 100644 --- a/graphics/java/android/graphics/drawable/Drawable.java +++ b/graphics/java/android/graphics/drawable/Drawable.java @@ -30,6 +30,8 @@ import android.content.res.Resources.Theme; import android.content.res.TypedArray; import android.graphics.Bitmap; import android.graphics.BitmapFactory; +import android.graphics.BlendMode; +import android.graphics.BlendModeColorFilter; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.ColorFilter; @@ -182,6 +184,7 @@ public abstract class Drawable { private static final Rect ZERO_BOUNDS_RECT = new Rect(); static final PorterDuff.Mode DEFAULT_TINT_MODE = PorterDuff.Mode.SRC_IN; + static final BlendMode DEFAULT_BLEND_MODE = BlendMode.SRC_IN; private int[] mStateSet = StateSet.WILD_CARD; private int mLevel = 0; @@ -210,6 +213,24 @@ public abstract class Drawable { protected int mSrcDensityOverride = 0; /** + * Flag used to break the recursive loop between setTintMode(PorterDuff.Mode) and + * setTintMode(BlendMode) as each default implementation invokes the other in order to + * support new use cases that utilize the new blending modes as well as support the legacy + * use cases. This flag tracks that {@link #setTintMode(BlendMode)} is only invoked once + * per invocation. + */ + private boolean mSetBlendModeInvoked = false; + + /** + * Flag used to break the recursive loop between setTintMode(PorterDuff.Mode) and + * setTintMode(BlendMode) as each default implementation invokes the other in order to + * support new use cases that utilize the new blending modes as well as support the legacy + * use cases. This flag tracks that {@link #setTintMode(Mode)} is only invoked once + * per invocation; + */ + private boolean mSetTintModeInvoked = false; + + /** * Draw in its bounds (set via setBounds) respecting optional effects such * as alpha (set via setAlpha) and color filter (set via setColorFilter). * @@ -630,6 +651,7 @@ public abstract class Drawable { * @param tintColor Color to use for tinting this drawable * @see #setTintList(ColorStateList) * @see #setTintMode(PorterDuff.Mode) + * @see #setTintMode(BlendMode) */ public void setTint(@ColorInt int tintColor) { setTintList(ColorStateList.valueOf(tintColor)); @@ -651,6 +673,7 @@ public abstract class Drawable { * {@code null} to clear the tint * @see #setTint(int) * @see #setTintMode(PorterDuff.Mode) + * @see #setTintMode(BlendMode) */ public void setTintList(@Nullable ColorStateList tint) {} @@ -668,8 +691,45 @@ public abstract class Drawable { * @param tintMode A Porter-Duff blending mode * @see #setTint(int) * @see #setTintList(ColorStateList) + * + * @deprecated use {@link #setTintMode(BlendMode)} instead + */ + @Deprecated + public void setTintMode(@NonNull PorterDuff.Mode tintMode) { + if (!mSetTintModeInvoked) { + mSetTintModeInvoked = true; + BlendMode mode = BlendMode.fromValue(tintMode.nativeInt); + if (mode != null) { + setTintMode(mode); + } + mSetTintModeInvoked = false; + } + } + + /** + * Specifies a tint blending mode for this drawable. + * <p> + * Defines how this drawable's tint color should be blended into the drawable + * before it is drawn to screen. Default tint mode is {@link BlendMode#SRC_IN}. + * </p> + * <p class="note"><strong>Note:</strong> Setting a color filter via + * {@link #setColorFilter(ColorFilter)} + * </p> + * + * @param blendMode + * @see #setTint(int) + * @see #setTintList(ColorStateList) */ - public void setTintMode(@NonNull PorterDuff.Mode tintMode) {} + public void setTintMode(@NonNull BlendMode blendMode) { + if (!mSetBlendModeInvoked) { + mSetBlendModeInvoked = true; + PorterDuff.Mode mode = BlendMode.blendModeToPorterDuffMode(blendMode); + if (mode != null) { + setTintMode(mode); + } + mSetBlendModeInvoked = false; + } + } /** * Returns the current color filter, or {@code null} if none set. @@ -1540,6 +1600,20 @@ public abstract class Drawable { return tintFilter; } + @Nullable BlendModeColorFilter updateBlendModeFilter(@Nullable BlendModeColorFilter blendFilter, + @Nullable ColorStateList tint, @Nullable BlendMode blendMode) { + if (tint == null || blendMode == null) { + return null; + } + + final int color = tint.getColorForState(getState(), Color.TRANSPARENT); + if (blendFilter == null || blendFilter.getColor() != color + || blendFilter.getMode() != blendMode) { + return new BlendModeColorFilter(color, blendMode); + } + return blendFilter; + } + /** * Obtains styled attributes from the theme, if available, or unstyled * resources if the theme is null. @@ -1642,5 +1716,26 @@ public abstract class Drawable { default: return defaultMode; } } + + /** + * Parses a {@link android.graphics.BlendMode} from a tintMode + * attribute's enum value. + * + * @hide + */ + @UnsupportedAppUsage + public static BlendMode parseBlendMode(int value, BlendMode defaultMode) { + switch (value) { + case 3: return BlendMode.SRC_OVER; + case 5: return BlendMode.SRC_IN; + case 9: return BlendMode.SRC_ATOP; + // b/73224934 PorterDuff Multiply maps to Skia Modulate so actually + // return BlendMode.MODULATE here + case 14: return BlendMode.MODULATE; + case 15: return BlendMode.SCREEN; + case 16: return BlendMode.PLUS; + default: return defaultMode; + } + } } diff --git a/graphics/java/android/graphics/drawable/DrawableContainer.java b/graphics/java/android/graphics/drawable/DrawableContainer.java index 77e77c49973c..3e0881aef9ed 100644 --- a/graphics/java/android/graphics/drawable/DrawableContainer.java +++ b/graphics/java/android/graphics/drawable/DrawableContainer.java @@ -22,12 +22,12 @@ import android.content.pm.ActivityInfo.Config; import android.content.res.ColorStateList; import android.content.res.Resources; import android.content.res.Resources.Theme; +import android.graphics.BlendMode; import android.graphics.Canvas; import android.graphics.ColorFilter; import android.graphics.Insets; import android.graphics.Outline; import android.graphics.PixelFormat; -import android.graphics.PorterDuff.Mode; import android.graphics.Rect; import android.os.Build; import android.os.SystemClock; @@ -196,14 +196,14 @@ public class DrawableContainer extends Drawable implements Drawable.Callback { } @Override - public void setTintMode(Mode tintMode) { + public void setTintMode(@NonNull BlendMode blendMode) { mDrawableContainerState.mHasTintMode = true; - if (mDrawableContainerState.mTintMode != tintMode) { - mDrawableContainerState.mTintMode = tintMode; + if (mDrawableContainerState.mBlendMode != blendMode) { + mDrawableContainerState.mBlendMode = blendMode; if (mCurrDrawable != null) { - mCurrDrawable.setTintMode(tintMode); + mCurrDrawable.setTintMode(blendMode); } } } @@ -544,7 +544,7 @@ public class DrawableContainer extends Drawable implements Drawable.Callback { d.setTintList(mDrawableContainerState.mTintList); } if (mDrawableContainerState.mHasTintMode) { - d.setTintMode(mDrawableContainerState.mTintMode); + d.setTintMode(mDrawableContainerState.mBlendMode); } } @@ -730,7 +730,7 @@ public class DrawableContainer extends Drawable implements Drawable.Callback { boolean mHasColorFilter; ColorStateList mTintList; - Mode mTintMode; + BlendMode mBlendMode; boolean mHasTintList; boolean mHasTintMode; @@ -762,7 +762,7 @@ public class DrawableContainer extends Drawable implements Drawable.Callback { mColorFilter = orig.mColorFilter; mHasColorFilter = orig.mHasColorFilter; mTintList = orig.mTintList; - mTintMode = orig.mTintMode; + mBlendMode = orig.mBlendMode; mHasTintList = orig.mHasTintList; mHasTintMode = orig.mHasTintMode; diff --git a/graphics/java/android/graphics/drawable/DrawableWrapper.java b/graphics/java/android/graphics/drawable/DrawableWrapper.java index 70c90eb05b17..d81401d451ca 100644 --- a/graphics/java/android/graphics/drawable/DrawableWrapper.java +++ b/graphics/java/android/graphics/drawable/DrawableWrapper.java @@ -24,12 +24,12 @@ import android.content.res.ColorStateList; import android.content.res.Resources; import android.content.res.Resources.Theme; import android.content.res.TypedArray; +import android.graphics.BlendMode; import android.graphics.Canvas; import android.graphics.ColorFilter; import android.graphics.Insets; import android.graphics.Outline; import android.graphics.PixelFormat; -import android.graphics.PorterDuff; import android.graphics.Rect; import android.graphics.Xfermode; import android.util.AttributeSet; @@ -324,9 +324,9 @@ public abstract class DrawableWrapper extends Drawable implements Drawable.Callb } @Override - public void setTintMode(@Nullable PorterDuff.Mode tintMode) { + public void setTintMode(@NonNull BlendMode blendMode) { if (mDrawable != null) { - mDrawable.setTintMode(tintMode); + mDrawable.setTintMode(blendMode); } } diff --git a/graphics/java/android/graphics/drawable/GradientDrawable.java b/graphics/java/android/graphics/drawable/GradientDrawable.java index e58e80225292..cdb3441d5225 100644 --- a/graphics/java/android/graphics/drawable/GradientDrawable.java +++ b/graphics/java/android/graphics/drawable/GradientDrawable.java @@ -28,6 +28,8 @@ import android.content.res.ColorStateList; import android.content.res.Resources; import android.content.res.Resources.Theme; import android.content.res.TypedArray; +import android.graphics.BlendMode; +import android.graphics.BlendModeColorFilter; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.ColorFilter; @@ -38,8 +40,6 @@ import android.graphics.Outline; 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; @@ -169,7 +169,7 @@ public class GradientDrawable extends Drawable { @UnsupportedAppUsage private Paint mStrokePaint; // optional, set by the caller private ColorFilter mColorFilter; // optional, set by the caller - private PorterDuffColorFilter mTintFilter; + private BlendModeColorFilter mBlendModeColorFilter; private int mAlpha = 0xFF; // modified by the caller private final Path mPath = new Path(); @@ -731,7 +731,7 @@ public class GradientDrawable extends Drawable { mStrokePaint.getStrokeWidth() > 0; final boolean haveFill = currFillAlpha > 0; final GradientState st = mGradientState; - final ColorFilter colorFilter = mColorFilter != null ? mColorFilter : mTintFilter; + final ColorFilter colorFilter = mColorFilter != null ? mColorFilter : mBlendModeColorFilter; /* we need a layer iff we're drawing both a fill and stroke, and the stroke is non-opaque, and our shapetype actually supports @@ -1130,8 +1130,9 @@ public class GradientDrawable extends Drawable { } } - if (s.mTint != null && s.mTintMode != null) { - mTintFilter = updateTintFilter(mTintFilter, s.mTint, s.mTintMode); + if (s.mTint != null && s.mBlendMode != null) { + mBlendModeColorFilter = updateBlendModeFilter(mBlendModeColorFilter, s.mTint, + s.mBlendMode); invalidateSelf = true; } @@ -1204,14 +1205,16 @@ public class GradientDrawable extends Drawable { @Override public void setTintList(@Nullable ColorStateList tint) { mGradientState.mTint = tint; - mTintFilter = updateTintFilter(mTintFilter, tint, mGradientState.mTintMode); + mBlendModeColorFilter = + updateBlendModeFilter(mBlendModeColorFilter, tint, mGradientState.mBlendMode); invalidateSelf(); } @Override - public void setTintMode(@Nullable PorterDuff.Mode tintMode) { - mGradientState.mTintMode = tintMode; - mTintFilter = updateTintFilter(mTintFilter, mGradientState.mTint, tintMode); + public void setTintMode(@NonNull BlendMode blendMode) { + mGradientState.mBlendMode = blendMode; + mBlendModeColorFilter = updateBlendModeFilter(mBlendModeColorFilter, mGradientState.mTint, + blendMode); invalidateSelf(); } @@ -1465,7 +1468,7 @@ public class GradientDrawable extends Drawable { final int tintMode = a.getInt(R.styleable.GradientDrawable_tintMode, -1); if (tintMode != -1) { - state.mTintMode = Drawable.parseTintMode(tintMode, PorterDuff.Mode.SRC_IN); + state.mBlendMode = Drawable.parseBlendMode(tintMode, BlendMode.SRC_IN); } final ColorStateList tint = a.getColorStateList(R.styleable.GradientDrawable_tint); @@ -2010,7 +2013,7 @@ public class GradientDrawable extends Drawable { boolean mOpaqueOverShape; ColorStateList mTint = null; - PorterDuff.Mode mTintMode = DEFAULT_TINT_MODE; + BlendMode mBlendMode = DEFAULT_BLEND_MODE; int mDensity = DisplayMetrics.DENSITY_DEFAULT; @@ -2068,7 +2071,7 @@ public class GradientDrawable extends Drawable { mOpaqueOverBounds = orig.mOpaqueOverBounds; mOpaqueOverShape = orig.mOpaqueOverShape; mTint = orig.mTint; - mTintMode = orig.mTintMode; + mBlendMode = orig.mBlendMode; mThemeAttrs = orig.mThemeAttrs; mAttrSize = orig.mAttrSize; mAttrGradient = orig.mAttrGradient; @@ -2355,7 +2358,8 @@ public class GradientDrawable extends Drawable { } } - mTintFilter = updateTintFilter(mTintFilter, state.mTint, state.mTintMode); + mBlendModeColorFilter = updateBlendModeFilter(mBlendModeColorFilter, state.mTint, + state.mBlendMode); mGradientIsDirty = true; state.computeOpacity(); diff --git a/graphics/java/android/graphics/drawable/Icon.java b/graphics/java/android/graphics/drawable/Icon.java index 71dd7a2f4800..5fd18a1431e0 100644 --- a/graphics/java/android/graphics/drawable/Icon.java +++ b/graphics/java/android/graphics/drawable/Icon.java @@ -30,6 +30,7 @@ import android.content.res.ColorStateList; import android.content.res.Resources; import android.graphics.Bitmap; import android.graphics.BitmapFactory; +import android.graphics.BlendMode; import android.graphics.PorterDuff; import android.net.Uri; import android.os.AsyncTask; @@ -105,8 +106,8 @@ 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; + static final BlendMode DEFAULT_BLEND_MODE = Drawable.DEFAULT_BLEND_MODE; // SRC_IN + private BlendMode mBlendMode = Drawable.DEFAULT_BLEND_MODE; // To avoid adding unnecessary overhead, we have a few basic objects that get repurposed // based on the value of mType. @@ -320,10 +321,10 @@ public final class Icon implements Parcelable { */ public Drawable loadDrawable(Context context) { final Drawable result = loadDrawableInner(context); - if (result != null && (mTintList != null || mTintMode != DEFAULT_TINT_MODE)) { + if (result != null && (mTintList != null || mBlendMode != DEFAULT_BLEND_MODE)) { result.mutate(); result.setTintList(mTintList); - result.setTintMode(mTintMode); + result.setTintMode(mBlendMode); } return result; } @@ -695,16 +696,30 @@ public final class Icon implements Parcelable { * * @param mode a blending mode, as in {@link Drawable#setTintMode(PorterDuff.Mode)}, may be null * @return this same object, for use in chained construction + * + * @deprecated use {@link #setTintMode(BlendMode)} instead + */ + @Deprecated + public @NonNull Icon setTintMode(@NonNull PorterDuff.Mode mode) { + mBlendMode = BlendMode.fromValue(mode.nativeInt); + 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; + public @NonNull Icon setTintMode(@NonNull BlendMode mode) { + mBlendMode = mode; return this; } /** @hide */ @UnsupportedAppUsage public boolean hasTint() { - return (mTintList != null) || (mTintMode != DEFAULT_TINT_MODE); + return (mTintList != null) || (mBlendMode != DEFAULT_BLEND_MODE); } /** @@ -757,7 +772,7 @@ public final class Icon implements Parcelable { sep = "|"; } } - if (mTintMode != DEFAULT_TINT_MODE) sb.append(" mode=").append(mTintMode); + if (mBlendMode != DEFAULT_BLEND_MODE) sb.append(" mode=").append(mBlendMode); sb.append(")"); return sb.toString(); } @@ -807,7 +822,7 @@ public final class Icon implements Parcelable { if (in.readInt() == 1) { mTintList = ColorStateList.CREATOR.createFromParcel(in); } - mTintMode = PorterDuff.intToMode(in.readInt()); + mBlendMode = BlendMode.fromValue(in.readInt()); } @Override @@ -837,7 +852,7 @@ public final class Icon implements Parcelable { dest.writeInt(1); mTintList.writeToParcel(dest, flags); } - dest.writeInt(PorterDuff.modeToInt(mTintMode)); + dest.writeInt(BlendMode.toValue(mBlendMode)); } public static final @android.annotation.NonNull Parcelable.Creator<Icon> CREATOR diff --git a/graphics/java/android/graphics/drawable/LayerDrawable.java b/graphics/java/android/graphics/drawable/LayerDrawable.java index b4392c8d023f..e2c84927b578 100644 --- a/graphics/java/android/graphics/drawable/LayerDrawable.java +++ b/graphics/java/android/graphics/drawable/LayerDrawable.java @@ -24,11 +24,11 @@ import android.content.res.ColorStateList; import android.content.res.Resources; import android.content.res.Resources.Theme; import android.content.res.TypedArray; +import android.graphics.BlendMode; import android.graphics.Canvas; import android.graphics.ColorFilter; import android.graphics.Outline; import android.graphics.PixelFormat; -import android.graphics.PorterDuff.Mode; import android.graphics.Rect; import android.util.AttributeSet; import android.util.DisplayMetrics; @@ -1397,13 +1397,13 @@ public class LayerDrawable extends Drawable implements Drawable.Callback { } @Override - public void setTintMode(Mode tintMode) { + public void setTintMode(@NonNull BlendMode blendMode) { final ChildDrawable[] array = mLayerState.mChildren; final int N = mLayerState.mNumChildren; for (int i = 0; i < N; i++) { final Drawable dr = array[i].mDrawable; if (dr != null) { - dr.setTintMode(tintMode); + dr.setTintMode(blendMode); } } } diff --git a/graphics/java/android/graphics/drawable/NinePatchDrawable.java b/graphics/java/android/graphics/drawable/NinePatchDrawable.java index b53477137331..4972e6a82b7d 100644 --- a/graphics/java/android/graphics/drawable/NinePatchDrawable.java +++ b/graphics/java/android/graphics/drawable/NinePatchDrawable.java @@ -25,6 +25,8 @@ import android.content.res.Resources; import android.content.res.Resources.Theme; import android.content.res.TypedArray; import android.graphics.Bitmap; +import android.graphics.BlendMode; +import android.graphics.BlendModeColorFilter; import android.graphics.Canvas; import android.graphics.ColorFilter; import android.graphics.ImageDecoder; @@ -33,9 +35,6 @@ import android.graphics.NinePatch; import android.graphics.Outline; import android.graphics.Paint; import android.graphics.PixelFormat; -import android.graphics.PorterDuff; -import android.graphics.PorterDuff.Mode; -import android.graphics.PorterDuffColorFilter; import android.graphics.Rect; import android.graphics.Region; import android.util.AttributeSet; @@ -73,7 +72,7 @@ public class NinePatchDrawable extends Drawable { @UnsupportedAppUsage private NinePatchState mNinePatchState; - private PorterDuffColorFilter mTintFilter; + private BlendModeColorFilter mBlendModeFilter; private Rect mPadding; private Insets mOpticalInsets = Insets.NONE; private Rect mOutlineInsets; @@ -198,8 +197,8 @@ public class NinePatchDrawable extends Drawable { int restoreToCount = -1; final boolean clearColorFilter; - if (mTintFilter != null && getPaint().getColorFilter() == null) { - mPaint.setColorFilter(mTintFilter); + if (mBlendModeFilter != null && getPaint().getColorFilter() == null) { + mPaint.setColorFilter(mBlendModeFilter); clearColorFilter = true; } else { clearColorFilter = false; @@ -344,14 +343,16 @@ public class NinePatchDrawable extends Drawable { @Override public void setTintList(@Nullable ColorStateList tint) { mNinePatchState.mTint = tint; - mTintFilter = updateTintFilter(mTintFilter, tint, mNinePatchState.mTintMode); + mBlendModeFilter = updateBlendModeFilter(mBlendModeFilter, tint, + mNinePatchState.mBlendMode); invalidateSelf(); } @Override - public void setTintMode(@Nullable PorterDuff.Mode tintMode) { - mNinePatchState.mTintMode = tintMode; - mTintFilter = updateTintFilter(mTintFilter, mNinePatchState.mTint, tintMode); + public void setTintMode(@Nullable BlendMode blendMode) { + mNinePatchState.mBlendMode = blendMode; + mBlendModeFilter = updateBlendModeFilter(mBlendModeFilter, mNinePatchState.mTint, + blendMode); invalidateSelf(); } @@ -467,7 +468,7 @@ public class NinePatchDrawable extends Drawable { final int tintMode = a.getInt(R.styleable.NinePatchDrawable_tintMode, -1); if (tintMode != -1) { - state.mTintMode = Drawable.parseTintMode(tintMode, Mode.SRC_IN); + state.mBlendMode = Drawable.parseBlendMode(tintMode, BlendMode.SRC_IN); } final ColorStateList tint = a.getColorStateList(R.styleable.NinePatchDrawable_tint); @@ -566,8 +567,9 @@ public class NinePatchDrawable extends Drawable { @Override protected boolean onStateChange(int[] stateSet) { final NinePatchState state = mNinePatchState; - if (state.mTint != null && state.mTintMode != null) { - mTintFilter = updateTintFilter(mTintFilter, state.mTint, state.mTintMode); + if (state.mTint != null && state.mBlendMode != null) { + mBlendModeFilter = updateBlendModeFilter(mBlendModeFilter, state.mTint, + state.mBlendMode); return true; } @@ -593,7 +595,7 @@ public class NinePatchDrawable extends Drawable { @UnsupportedAppUsage NinePatch mNinePatch = null; ColorStateList mTint = null; - Mode mTintMode = DEFAULT_TINT_MODE; + BlendMode mBlendMode = DEFAULT_BLEND_MODE; Rect mPadding = null; Insets mOpticalInsets = Insets.NONE; float mBaseAlpha = 1.0f; @@ -628,7 +630,7 @@ public class NinePatchDrawable extends Drawable { mChangingConfigurations = orig.mChangingConfigurations; mNinePatch = orig.mNinePatch; mTint = orig.mTint; - mTintMode = orig.mTintMode; + mBlendMode = orig.mBlendMode; mPadding = orig.mPadding; mOpticalInsets = orig.mOpticalInsets; mBaseAlpha = orig.mBaseAlpha; @@ -751,7 +753,7 @@ public class NinePatchDrawable extends Drawable { } else { mTargetDensity = Drawable.resolveDensity(res, mTargetDensity); } - mTintFilter = updateTintFilter(mTintFilter, state.mTint, state.mTintMode); + mBlendModeFilter = updateBlendModeFilter(mBlendModeFilter, state.mTint, state.mBlendMode); computeBitmapSize(); } } diff --git a/graphics/java/android/graphics/drawable/ShapeDrawable.java b/graphics/java/android/graphics/drawable/ShapeDrawable.java index 7bfb4c38d6c8..b5fe7f9e432d 100644 --- a/graphics/java/android/graphics/drawable/ShapeDrawable.java +++ b/graphics/java/android/graphics/drawable/ShapeDrawable.java @@ -24,14 +24,13 @@ import android.content.res.ColorStateList; import android.content.res.Resources; import android.content.res.Resources.Theme; import android.content.res.TypedArray; +import android.graphics.BlendMode; +import android.graphics.BlendModeColorFilter; import android.graphics.Canvas; import android.graphics.ColorFilter; import android.graphics.Outline; import android.graphics.Paint; import android.graphics.PixelFormat; -import android.graphics.PorterDuff; -import android.graphics.PorterDuff.Mode; -import android.graphics.PorterDuffColorFilter; import android.graphics.Rect; import android.graphics.Shader; import android.graphics.Xfermode; @@ -75,7 +74,7 @@ import java.io.IOException; */ public class ShapeDrawable extends Drawable { private @NonNull ShapeState mShapeState; - private PorterDuffColorFilter mTintFilter; + private BlendModeColorFilter mBlendModeColorFilter; private boolean mMutated; /** @@ -238,8 +237,8 @@ public class ShapeDrawable extends Drawable { // only draw shape if it may affect output if (paint.getAlpha() != 0 || paint.getXfermode() != null || paint.hasShadowLayer()) { final boolean clearColorFilter; - if (mTintFilter != null && paint.getColorFilter() == null) { - paint.setColorFilter(mTintFilter); + if (mBlendModeColorFilter != null && paint.getColorFilter() == null) { + paint.setColorFilter(mBlendModeColorFilter); clearColorFilter = true; } else { clearColorFilter = false; @@ -292,14 +291,16 @@ public class ShapeDrawable extends Drawable { @Override public void setTintList(ColorStateList tint) { mShapeState.mTint = tint; - mTintFilter = updateTintFilter(mTintFilter, tint, mShapeState.mTintMode); + mBlendModeColorFilter = updateBlendModeFilter(mBlendModeColorFilter, tint, + mShapeState.mBlendMode); invalidateSelf(); } @Override - public void setTintMode(PorterDuff.Mode tintMode) { - mShapeState.mTintMode = tintMode; - mTintFilter = updateTintFilter(mTintFilter, mShapeState.mTint, tintMode); + public void setTintMode(@NonNull BlendMode blendMode) { + mShapeState.mBlendMode = blendMode; + mBlendModeColorFilter = updateBlendModeFilter(mBlendModeColorFilter, mShapeState.mTint, + blendMode); invalidateSelf(); } @@ -352,8 +353,9 @@ public class ShapeDrawable extends Drawable { @Override protected boolean onStateChange(int[] stateSet) { final ShapeState state = mShapeState; - if (state.mTint != null && state.mTintMode != null) { - mTintFilter = updateTintFilter(mTintFilter, state.mTint, state.mTintMode); + if (state.mTint != null && state.mBlendMode != null) { + mBlendModeColorFilter = updateBlendModeFilter(mBlendModeColorFilter, state.mTint, + state.mBlendMode); return true; } return false; @@ -475,7 +477,7 @@ public class ShapeDrawable extends Drawable { final int tintMode = a.getInt(R.styleable.ShapeDrawable_tintMode, -1); if (tintMode != -1) { - state.mTintMode = Drawable.parseTintMode(tintMode, Mode.SRC_IN); + state.mBlendMode = Drawable.parseBlendMode(tintMode, BlendMode.SRC_IN); } final ColorStateList tint = a.getColorStateList(R.styleable.ShapeDrawable_tint); @@ -540,7 +542,7 @@ public class ShapeDrawable extends Drawable { int[] mThemeAttrs; Shape mShape; ColorStateList mTint; - Mode mTintMode = DEFAULT_TINT_MODE; + BlendMode mBlendMode = DEFAULT_BLEND_MODE; Rect mPadding; int mIntrinsicWidth; int mIntrinsicHeight; @@ -573,7 +575,7 @@ public class ShapeDrawable extends Drawable { } } mTint = orig.mTint; - mTintMode = orig.mTintMode; + mBlendMode = orig.mBlendMode; if (orig.mPadding != null) { mPadding = new Rect(orig.mPadding); } @@ -625,7 +627,8 @@ public class ShapeDrawable extends Drawable { * after inflating or applying a theme. */ private void updateLocalState() { - mTintFilter = updateTintFilter(mTintFilter, mShapeState.mTint, mShapeState.mTintMode); + mBlendModeColorFilter = updateBlendModeFilter(mBlendModeColorFilter, mShapeState.mTint, + mShapeState.mBlendMode); } /** diff --git a/graphics/java/android/graphics/drawable/VectorDrawable.java b/graphics/java/android/graphics/drawable/VectorDrawable.java index 7325b857f02c..43772ec20cf3 100644 --- a/graphics/java/android/graphics/drawable/VectorDrawable.java +++ b/graphics/java/android/graphics/drawable/VectorDrawable.java @@ -24,11 +24,13 @@ import android.content.res.GradientColor; import android.content.res.Resources; import android.content.res.Resources.Theme; import android.content.res.TypedArray; +import android.graphics.BlendMode; +import android.graphics.BlendModeColorFilter; import android.graphics.Canvas; import android.graphics.ColorFilter; import android.graphics.Insets; import android.graphics.PixelFormat; -import android.graphics.PorterDuff.Mode; +import android.graphics.PorterDuff; import android.graphics.PorterDuffColorFilter; import android.graphics.Rect; import android.graphics.Shader; @@ -324,6 +326,8 @@ public class VectorDrawable extends Drawable { @UnsupportedAppUsage private PorterDuffColorFilter mTintFilter; + + private BlendModeColorFilter mBlendModeColorFilter; private ColorFilter mColorFilter; private boolean mMutated; @@ -371,7 +375,7 @@ public class VectorDrawable extends Drawable { mDpiScaledDirty = true; } - mTintFilter = updateTintFilter(mTintFilter, mVectorState.mTint, mVectorState.mTintMode); + updateColorFilters(mVectorState.mBlendMode, mVectorState.mTint); } @Override @@ -413,7 +417,8 @@ public class VectorDrawable extends Drawable { } // Color filters always override tint filters. - final ColorFilter colorFilter = (mColorFilter == null ? mTintFilter : mColorFilter); + final ColorFilter colorFilter = (mColorFilter == null ? mBlendModeColorFilter : + mColorFilter); final long colorFilterNativeInstance = colorFilter == null ? 0 : colorFilter.getNativeInstance(); boolean canReuseCache = mVectorState.canReuseCache(); @@ -475,17 +480,19 @@ public class VectorDrawable extends Drawable { final VectorDrawableState state = mVectorState; if (state.mTint != tint) { state.mTint = tint; - mTintFilter = updateTintFilter(mTintFilter, tint, state.mTintMode); + + updateColorFilters(mVectorState.mBlendMode, tint); invalidateSelf(); } } @Override - public void setTintMode(Mode tintMode) { + public void setTintMode(@NonNull BlendMode blendMode) { final VectorDrawableState state = mVectorState; - if (state.mTintMode != tintMode) { - state.mTintMode = tintMode; - mTintFilter = updateTintFilter(mTintFilter, state.mTint, tintMode); + if (state.mBlendMode != blendMode) { + state.mBlendMode = blendMode; + + updateColorFilters(state.mBlendMode, state.mTint); invalidateSelf(); } } @@ -515,14 +522,22 @@ public class VectorDrawable extends Drawable { changed = true; state.mCacheDirty = true; } - if (state.mTint != null && state.mTintMode != null) { - mTintFilter = updateTintFilter(mTintFilter, state.mTint, state.mTintMode); + if (state.mTint != null && state.mBlendMode != null) { + BlendMode blendMode = state.mBlendMode; + ColorStateList tint = state.mTint; + updateColorFilters(blendMode, tint); changed = true; } return changed; } + private void updateColorFilters(@Nullable BlendMode blendMode, ColorStateList tint) { + PorterDuff.Mode mode = BlendMode.blendModeToPorterDuffMode(blendMode); + mTintFilter = updateTintFilter(mTintFilter, tint, mode); + mBlendModeColorFilter = updateBlendModeFilter(mBlendModeColorFilter, tint, blendMode); + } + @Override public int getOpacity() { // We can't tell whether the drawable is fully opaque unless we examine all the pixels, @@ -737,7 +752,7 @@ public class VectorDrawable extends Drawable { final int tintMode = a.getInt(R.styleable.VectorDrawable_tintMode, -1); if (tintMode != -1) { - state.mTintMode = Drawable.parseTintMode(tintMode, Mode.SRC_IN); + state.mBlendMode = Drawable.parseBlendMode(tintMode, BlendMode.SRC_IN); } final ColorStateList tint = a.getColorStateList(R.styleable.VectorDrawable_tint); @@ -911,7 +926,7 @@ public class VectorDrawable extends Drawable { int[] mThemeAttrs; @Config int mChangingConfigurations; ColorStateList mTint = null; - Mode mTintMode = DEFAULT_TINT_MODE; + BlendMode mBlendMode = DEFAULT_BLEND_MODE; boolean mAutoMirrored; int mBaseWidth = 0; @@ -929,7 +944,7 @@ public class VectorDrawable extends Drawable { // Fields for cache int[] mCachedThemeAttrs; ColorStateList mCachedTint; - Mode mCachedTintMode; + BlendMode mCachedBlendMode; boolean mCachedAutoMirrored; boolean mCacheDirty; @@ -970,7 +985,7 @@ public class VectorDrawable extends Drawable { mThemeAttrs = copy.mThemeAttrs; mChangingConfigurations = copy.mChangingConfigurations; mTint = copy.mTint; - mTintMode = copy.mTintMode; + mBlendMode = copy.mBlendMode; mAutoMirrored = copy.mAutoMirrored; mRootGroup = new VGroup(copy.mRootGroup, mVGTargetsMap); createNativeTreeFromCopy(copy, mRootGroup); @@ -1026,7 +1041,7 @@ public class VectorDrawable extends Drawable { if (!mCacheDirty && mCachedThemeAttrs == mThemeAttrs && mCachedTint == mTint - && mCachedTintMode == mTintMode + && mCachedBlendMode == mBlendMode && mCachedAutoMirrored == mAutoMirrored) { return true; } @@ -1039,7 +1054,7 @@ public class VectorDrawable extends Drawable { // likely hit cache miss more, but practically not much difference. mCachedThemeAttrs = mThemeAttrs; mCachedTint = mTint; - mCachedTintMode = mTintMode; + mCachedBlendMode = mBlendMode; mCachedAutoMirrored = mAutoMirrored; mCacheDirty = false; } |