diff --git a/api/current.txt b/api/current.txt index d1b77f2c10960..edb8d98ab5d51 100644 --- a/api/current.txt +++ b/api/current.txt @@ -14096,8 +14096,9 @@ package android.graphics { } public class ComposeShader extends android.graphics.Shader { - ctor public ComposeShader(@NonNull android.graphics.Shader, @NonNull android.graphics.Shader, @NonNull android.graphics.Xfermode); - ctor public ComposeShader(@NonNull android.graphics.Shader, @NonNull android.graphics.Shader, @NonNull android.graphics.PorterDuff.Mode); + ctor @Deprecated public ComposeShader(@NonNull android.graphics.Shader, @NonNull android.graphics.Shader, @NonNull android.graphics.Xfermode); + ctor @Deprecated public ComposeShader(@NonNull android.graphics.Shader, @NonNull android.graphics.Shader, @NonNull android.graphics.PorterDuff.Mode); + ctor public ComposeShader(@NonNull android.graphics.Shader, @NonNull android.graphics.Shader, @NonNull android.graphics.BlendMode); } public class CornerPathEffect extends android.graphics.PathEffect { @@ -14791,37 +14792,37 @@ package android.graphics { field public float y; } - public class PorterDuff { - ctor public PorterDuff(); + @Deprecated public class PorterDuff { + ctor @Deprecated public PorterDuff(); } - public enum PorterDuff.Mode { - enum_constant public static final android.graphics.PorterDuff.Mode ADD; - enum_constant public static final android.graphics.PorterDuff.Mode CLEAR; - enum_constant public static final android.graphics.PorterDuff.Mode DARKEN; - enum_constant public static final android.graphics.PorterDuff.Mode DST; - enum_constant public static final android.graphics.PorterDuff.Mode DST_ATOP; - enum_constant public static final android.graphics.PorterDuff.Mode DST_IN; - enum_constant public static final android.graphics.PorterDuff.Mode DST_OUT; - enum_constant public static final android.graphics.PorterDuff.Mode DST_OVER; - enum_constant public static final android.graphics.PorterDuff.Mode LIGHTEN; - enum_constant public static final android.graphics.PorterDuff.Mode MULTIPLY; - enum_constant public static final android.graphics.PorterDuff.Mode OVERLAY; - enum_constant public static final android.graphics.PorterDuff.Mode SCREEN; - enum_constant public static final android.graphics.PorterDuff.Mode SRC; - enum_constant public static final android.graphics.PorterDuff.Mode SRC_ATOP; - enum_constant public static final android.graphics.PorterDuff.Mode SRC_IN; - enum_constant public static final android.graphics.PorterDuff.Mode SRC_OUT; - enum_constant public static final android.graphics.PorterDuff.Mode SRC_OVER; - enum_constant public static final android.graphics.PorterDuff.Mode XOR; + @Deprecated public enum PorterDuff.Mode { + enum_constant @Deprecated public static final android.graphics.PorterDuff.Mode ADD; + enum_constant @Deprecated public static final android.graphics.PorterDuff.Mode CLEAR; + enum_constant @Deprecated public static final android.graphics.PorterDuff.Mode DARKEN; + enum_constant @Deprecated public static final android.graphics.PorterDuff.Mode DST; + enum_constant @Deprecated public static final android.graphics.PorterDuff.Mode DST_ATOP; + enum_constant @Deprecated public static final android.graphics.PorterDuff.Mode DST_IN; + enum_constant @Deprecated public static final android.graphics.PorterDuff.Mode DST_OUT; + enum_constant @Deprecated public static final android.graphics.PorterDuff.Mode DST_OVER; + enum_constant @Deprecated public static final android.graphics.PorterDuff.Mode LIGHTEN; + enum_constant @Deprecated public static final android.graphics.PorterDuff.Mode MULTIPLY; + enum_constant @Deprecated public static final android.graphics.PorterDuff.Mode OVERLAY; + enum_constant @Deprecated public static final android.graphics.PorterDuff.Mode SCREEN; + enum_constant @Deprecated public static final android.graphics.PorterDuff.Mode SRC; + enum_constant @Deprecated public static final android.graphics.PorterDuff.Mode SRC_ATOP; + enum_constant @Deprecated public static final android.graphics.PorterDuff.Mode SRC_IN; + enum_constant @Deprecated public static final android.graphics.PorterDuff.Mode SRC_OUT; + enum_constant @Deprecated public static final android.graphics.PorterDuff.Mode SRC_OVER; + enum_constant @Deprecated public static final android.graphics.PorterDuff.Mode XOR; } @Deprecated public class PorterDuffColorFilter extends android.graphics.ColorFilter { ctor @Deprecated public PorterDuffColorFilter(@ColorInt int, @NonNull android.graphics.PorterDuff.Mode); } - public class PorterDuffXfermode extends android.graphics.Xfermode { - ctor public PorterDuffXfermode(android.graphics.PorterDuff.Mode); + @Deprecated public class PorterDuffXfermode extends android.graphics.Xfermode { + ctor @Deprecated public PorterDuffXfermode(android.graphics.PorterDuff.Mode); } public interface PostProcessor { @@ -15383,7 +15384,8 @@ package android.graphics.drawable { method public boolean setState(@NonNull int[]); method public void setTint(@ColorInt int); method public void setTintList(@Nullable android.content.res.ColorStateList); - method public void setTintMode(@NonNull android.graphics.PorterDuff.Mode); + method @Deprecated public void setTintMode(@NonNull android.graphics.PorterDuff.Mode); + method public void setTintMode(@NonNull android.graphics.BlendMode); method public boolean setVisible(boolean, boolean); method public void unscheduleSelf(@NonNull Runnable); } @@ -15541,7 +15543,8 @@ package android.graphics.drawable { method public void loadDrawableAsync(android.content.Context, android.graphics.drawable.Icon.OnDrawableLoadedListener, android.os.Handler); method public android.graphics.drawable.Icon setTint(@ColorInt int); method public android.graphics.drawable.Icon setTintList(android.content.res.ColorStateList); - method public android.graphics.drawable.Icon setTintMode(android.graphics.PorterDuff.Mode); + method @Deprecated @NonNull public android.graphics.drawable.Icon setTintMode(@NonNull android.graphics.PorterDuff.Mode); + method @NonNull public android.graphics.drawable.Icon setTintMode(@NonNull android.graphics.BlendMode); method public void writeToParcel(android.os.Parcel, int); field @NonNull public static final android.os.Parcelable.Creator CREATOR; field public static final int TYPE_ADAPTIVE_BITMAP = 5; // 0x5 @@ -49683,8 +49686,9 @@ package android.view { method public default CharSequence getContentDescription(); method public int getGroupId(); method public android.graphics.drawable.Drawable getIcon(); + method @Nullable public default android.graphics.BlendMode getIconTintBlendMode(); method @Nullable public default android.content.res.ColorStateList getIconTintList(); - method @Nullable public default android.graphics.PorterDuff.Mode getIconTintMode(); + method @Deprecated @Nullable public default android.graphics.PorterDuff.Mode getIconTintMode(); method public android.content.Intent getIntent(); method public int getItemId(); method public android.view.ContextMenu.ContextMenuInfo getMenuInfo(); @@ -49713,7 +49717,8 @@ package android.view { method public android.view.MenuItem setIcon(android.graphics.drawable.Drawable); method public android.view.MenuItem setIcon(@DrawableRes int); method public default android.view.MenuItem setIconTintList(@Nullable android.content.res.ColorStateList); - method public default android.view.MenuItem setIconTintMode(@Nullable android.graphics.PorterDuff.Mode); + method @Deprecated @NonNull public default android.view.MenuItem setIconTintMode(@Nullable android.graphics.PorterDuff.Mode); + method @NonNull public default android.view.MenuItem setIconTintMode(@Nullable android.graphics.BlendMode); method public android.view.MenuItem setIntent(android.content.Intent); method public android.view.MenuItem setNumericShortcut(char); method public default android.view.MenuItem setNumericShortcut(char, int); @@ -50366,8 +50371,9 @@ package android.view { method public int getAutofillType(); method @Nullable public android.view.autofill.AutofillValue getAutofillValue(); method public android.graphics.drawable.Drawable getBackground(); + method @Nullable public android.graphics.BlendMode getBackgroundBlendMode(); method @Nullable public android.content.res.ColorStateList getBackgroundTintList(); - method @Nullable public android.graphics.PorterDuff.Mode getBackgroundTintMode(); + method @Deprecated @Nullable public android.graphics.PorterDuff.Mode getBackgroundTintMode(); method @android.view.ViewDebug.ExportedProperty(category="layout") public int getBaseline(); method @android.view.ViewDebug.CapturedViewProperty public final int getBottom(); method protected float getBottomFadingEdgeStrength(); @@ -50398,9 +50404,10 @@ package android.view { method public java.util.ArrayList getFocusables(int); method public void getFocusedRect(android.graphics.Rect); method public android.graphics.drawable.Drawable getForeground(); + method @Nullable public android.graphics.BlendMode getForegroundBlendMode(); method public int getForegroundGravity(); method @Nullable public android.content.res.ColorStateList getForegroundTintList(); - method @Nullable public android.graphics.PorterDuff.Mode getForegroundTintMode(); + method @Deprecated @Nullable public android.graphics.PorterDuff.Mode getForegroundTintMode(); method public boolean getGlobalVisibleRect(android.graphics.Rect, android.graphics.Point); method public final boolean getGlobalVisibleRect(android.graphics.Rect); method public android.os.Handler getHandler(); @@ -50715,7 +50722,8 @@ package android.view { method @Deprecated public void setBackgroundDrawable(android.graphics.drawable.Drawable); method public void setBackgroundResource(@DrawableRes int); method public void setBackgroundTintList(@Nullable android.content.res.ColorStateList); - method public void setBackgroundTintMode(@Nullable android.graphics.PorterDuff.Mode); + method @Deprecated public void setBackgroundTintMode(@Nullable android.graphics.PorterDuff.Mode); + method public void setBackgroundTintMode(@Nullable android.graphics.BlendMode); method public final void setBottom(int); method public void setCameraDistance(float); method public void setClickable(boolean); @@ -50742,7 +50750,8 @@ package android.view { method public void setForeground(android.graphics.drawable.Drawable); method public void setForegroundGravity(int); method public void setForegroundTintList(@Nullable android.content.res.ColorStateList); - method public void setForegroundTintMode(@Nullable android.graphics.PorterDuff.Mode); + method @Deprecated public void setForegroundTintMode(@Nullable android.graphics.PorterDuff.Mode); + method public void setForegroundTintMode(@Nullable android.graphics.BlendMode); method public void setHapticFeedbackEnabled(boolean); method public void setHasTransientState(boolean); method public void setHorizontalFadingEdgeEnabled(boolean); diff --git a/core/java/android/view/MenuInflater.java b/core/java/android/view/MenuInflater.java index a3cd0ba4b8236..8b3b10f48a4a0 100644 --- a/core/java/android/view/MenuInflater.java +++ b/core/java/android/view/MenuInflater.java @@ -23,7 +23,7 @@ import android.content.ContextWrapper; import android.content.res.ColorStateList; import android.content.res.TypedArray; import android.content.res.XmlResourceParser; -import android.graphics.PorterDuff; +import android.graphics.BlendMode; import android.graphics.drawable.Drawable; import android.util.AttributeSet; import android.util.Log; @@ -308,7 +308,7 @@ public class MenuInflater { private CharSequence itemTitleCondensed; private int itemIconResId; private ColorStateList itemIconTintList = null; - private PorterDuff.Mode itemIconTintMode = null; + private BlendMode mItemIconBlendMode = null; private char itemAlphabeticShortcut; private int itemAlphabeticModifiers; private char itemNumericShortcut; @@ -401,12 +401,12 @@ public class MenuInflater { itemTitleCondensed = a.getText(com.android.internal.R.styleable.MenuItem_titleCondensed); itemIconResId = a.getResourceId(com.android.internal.R.styleable.MenuItem_icon, 0); if (a.hasValue(com.android.internal.R.styleable.MenuItem_iconTintMode)) { - itemIconTintMode = Drawable.parseTintMode(a.getInt( + mItemIconBlendMode = Drawable.parseBlendMode(a.getInt( com.android.internal.R.styleable.MenuItem_iconTintMode, -1), - itemIconTintMode); + mItemIconBlendMode); } else { // Reset to null so that it's not carried over to the next item - itemIconTintMode = null; + mItemIconBlendMode = null; } if (a.hasValue(com.android.internal.R.styleable.MenuItem_iconTint)) { itemIconTintList = a.getColorStateList( @@ -487,8 +487,8 @@ public class MenuInflater { item.setShowAsAction(itemShowAsAction); } - if (itemIconTintMode != null) { - item.setIconTintMode(itemIconTintMode); + if (mItemIconBlendMode != null) { + item.setIconTintMode(mItemIconBlendMode); } if (itemIconTintList != null) { diff --git a/core/java/android/view/MenuItem.java b/core/java/android/view/MenuItem.java index ad160cbf41eb4..37853103ce02f 100644 --- a/core/java/android/view/MenuItem.java +++ b/core/java/android/view/MenuItem.java @@ -18,11 +18,13 @@ package android.view; import android.annotation.DrawableRes; import android.annotation.LayoutRes; +import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.StringRes; import android.app.Activity; import android.content.Intent; import android.content.res.ColorStateList; +import android.graphics.BlendMode; import android.graphics.PorterDuff; import android.graphics.drawable.Drawable; import android.view.ContextMenu.ContextMenuInfo; @@ -268,8 +270,33 @@ public interface MenuItem { * @attr ref android.R.styleable#MenuItem_iconTintMode * @see #setIconTintList(ColorStateList) * @see Drawable#setTintMode(PorterDuff.Mode) + * @see Drawable#setTintMode(BlendMode) + * + * @deprecated use {@link #setIconTintMode(BlendMode)} instead */ - public default MenuItem setIconTintMode(@Nullable PorterDuff.Mode tintMode) { return this; } + @Deprecated + default @NonNull MenuItem setIconTintMode(@Nullable PorterDuff.Mode tintMode) { + return this; + } + + /** + * Specifies the blending mode used to apply the tint specified by + * {@link #setIconTintList(ColorStateList)} to this item's icon. The default mode is + * {@link BlendMode#SRC_IN}. + * + * @param blendMode the blending mode used to apply the tint, may be + * {@code null} to clear tint + * @attr ref android.R.styleable#MenuItem_iconTintMode + * @see #setIconTintList(ColorStateList) + */ + default @NonNull MenuItem setIconTintMode(@Nullable BlendMode blendMode) { + PorterDuff.Mode mode = BlendMode.blendModeToPorterDuffMode(blendMode); + if (mode != null) { + return setIconTintMode(mode); + } else { + return this; + } + } /** * Returns the blending mode used to apply the tint to this item's icon, if specified. @@ -277,9 +304,31 @@ public interface MenuItem { * @return the blending mode used to apply the tint to this item's icon * @attr ref android.R.styleable#MenuItem_iconTintMode * @see #setIconTintMode(PorterDuff.Mode) + * @see #setIconTintMode(BlendMode) + * + * @deprecated Use {@link #getIconTintBlendMode()} instead */ + @Deprecated @Nullable public default PorterDuff.Mode getIconTintMode() { return null; } + + /** + * Returns the blending mode used to apply the tint to this item's icon, if specified. + * + * @return the blending mode used to apply the tint to this item's icon + * @attr ref android.R.styleable#MenuItem_iconTintMode + * @see #setIconTintMode(BlendMode) + * + */ + @Nullable + default BlendMode getIconTintBlendMode() { + PorterDuff.Mode mode = getIconTintMode(); + if (mode != null) { + return BlendMode.fromValue(mode.nativeInt); + } else { + return null; + } + } /** * Change the Intent associated with this item. By default there is no diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java index b857f1ed99969..92cfbbaaef9f2 100644 --- a/core/java/android/view/View.java +++ b/core/java/android/view/View.java @@ -50,6 +50,7 @@ import android.content.res.Configuration; import android.content.res.Resources; import android.content.res.TypedArray; import android.graphics.Bitmap; +import android.graphics.BlendMode; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Insets; @@ -4506,7 +4507,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback, static class TintInfo { ColorStateList mTintList; - PorterDuff.Mode mTintMode; + BlendMode mBlendMode; boolean mHasTintMode; boolean mHasTintList; } @@ -5687,7 +5688,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback, if (mBackgroundTint == null) { mBackgroundTint = new TintInfo(); } - mBackgroundTint.mTintMode = Drawable.parseTintMode(a.getInt( + mBackgroundTint.mBlendMode = Drawable.parseBlendMode(a.getInt( R.styleable.View_backgroundTintMode, -1), null); mBackgroundTint.mHasTintMode = true; break; @@ -5707,7 +5708,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback, break; case R.styleable.View_foregroundTintMode: if (targetSdkVersion >= Build.VERSION_CODES.M || this instanceof FrameLayout) { - setForegroundTintMode(Drawable.parseTintMode(a.getInt(attr, -1), null)); + setForegroundTintMode(Drawable.parseBlendMode(a.getInt(attr, -1), null)); } break; case R.styleable.View_foregroundTint: @@ -23267,7 +23268,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback, /** * Applies a tint to the background drawable. Does not modify the current tint - * mode, which is {@link PorterDuff.Mode#SRC_IN} by default. + * mode, which is {@link BlendMode#SRC_IN} by default. *

* Subsequent calls to {@link #setBackground(Drawable)} will automatically * mutate the drawable and apply the specified tint and tint mode using @@ -23312,12 +23313,36 @@ public class View implements Drawable.Callback, KeyEvent.Callback, * @attr ref android.R.styleable#View_backgroundTintMode * @see #getBackgroundTintMode() * @see Drawable#setTintMode(PorterDuff.Mode) + * + * @deprecated use @setBackgroundTintMode(BlendMode) instead */ + @Deprecated public void setBackgroundTintMode(@Nullable PorterDuff.Mode tintMode) { + BlendMode mode = null; + if (tintMode != null) { + mode = BlendMode.fromValue(tintMode.nativeInt); + } + + setBackgroundTintMode(mode); + } + + /** + * Specifies the blending mode used to apply the tint specified by + * {@link #setBackgroundTintList(ColorStateList)}} to the background + * drawable. The default mode is {@link BlendMode#SRC_IN}. + * + * @param blendMode the blending mode used to apply the tint, may be + * {@code null} to clear tint + * @attr ref android.R.styleable#View_backgroundTintMode + * @see #getBackgroundTintMode() + * @see Drawable#setTintMode(BlendMode) + */ + public void setBackgroundTintMode(@Nullable BlendMode blendMode) { if (mBackgroundTint == null) { mBackgroundTint = new TintInfo(); } - mBackgroundTint.mTintMode = tintMode; + + mBackgroundTint.mBlendMode = blendMode; mBackgroundTint.mHasTintMode = true; applyBackgroundTint(); @@ -23330,12 +23355,34 @@ public class View implements Drawable.Callback, KeyEvent.Callback, * @return the blending mode used to apply the tint to the background * drawable * @attr ref android.R.styleable#View_backgroundTintMode - * @see #setBackgroundTintMode(PorterDuff.Mode) + * @see #setBackgroundTintMode(BlendMode) + * + * @deprecated use #getBackgroundBlendMode() instead */ @Nullable @InspectableProperty + @Deprecated public PorterDuff.Mode getBackgroundTintMode() { - return mBackgroundTint != null ? mBackgroundTint.mTintMode : null; + PorterDuff.Mode porterDuffMode; + if (mBackgroundTint != null && mBackgroundTint.mBlendMode != null) { + porterDuffMode = BlendMode.blendModeToPorterDuffMode(mBackgroundTint.mBlendMode); + } else { + porterDuffMode = null; + } + return porterDuffMode; + } + + /** + * Return the blending mode used to apply the tint to the background + * drawable, if specified. + * + * @return the blending mode used to apply the tint to the background + * drawable, null if no blend has previously been configured + * @attr ref android.R.styleable#View_backgroundTintMode + * @see #setBackgroundTintMode(BlendMode) + */ + public @Nullable BlendMode getBackgroundBlendMode() { + return mBackgroundTint != null ? mBackgroundTint.mBlendMode : null; } private void applyBackgroundTint() { @@ -23349,7 +23396,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback, } if (tintInfo.mHasTintMode) { - mBackground.setTintMode(tintInfo.mTintMode); + mBackground.setTintMode(tintInfo.mBlendMode); } // The drawable (or one of its children) may not have been @@ -23533,15 +23580,37 @@ public class View implements Drawable.Callback, KeyEvent.Callback, * @attr ref android.R.styleable#View_foregroundTintMode * @see #getForegroundTintMode() * @see Drawable#setTintMode(PorterDuff.Mode) + * + * @deprecated use #setForegroundTintMode(BlendMode) */ + @Deprecated public void setForegroundTintMode(@Nullable PorterDuff.Mode tintMode) { + BlendMode mode = null; + if (tintMode != null) { + mode = BlendMode.fromValue(tintMode.nativeInt); + } + setForegroundTintMode(mode); + } + + /** + * Specifies the blending mode used to apply the tint specified by + * {@link #setForegroundTintList(ColorStateList)}} to the background + * drawable. The default mode is {@link BlendMode#SRC_IN}. + * + * @param blendMode the blending mode used to apply the tint, may be + * {@code null} to clear tint + * @attr ref android.R.styleable#View_foregroundTintMode + * @see #getForegroundTintMode() + * @see Drawable#setTintMode(BlendMode) + */ + public void setForegroundTintMode(@Nullable BlendMode blendMode) { if (mForegroundInfo == null) { mForegroundInfo = new ForegroundInfo(); } if (mForegroundInfo.mTintInfo == null) { mForegroundInfo.mTintInfo = new TintInfo(); } - mForegroundInfo.mTintInfo.mTintMode = tintMode; + mForegroundInfo.mTintInfo.mBlendMode = blendMode; mForegroundInfo.mTintInfo.mHasTintMode = true; applyForegroundTint(); @@ -23555,12 +23624,35 @@ public class View implements Drawable.Callback, KeyEvent.Callback, * drawable * @attr ref android.R.styleable#View_foregroundTintMode * @see #setForegroundTintMode(PorterDuff.Mode) + * + * @deprecated use #getForegroundBlendMode() instead */ @InspectableProperty @Nullable + @Deprecated public PorterDuff.Mode getForegroundTintMode() { + BlendMode blendMode = mForegroundInfo != null && mForegroundInfo.mTintInfo != null + ? mForegroundInfo.mTintInfo.mBlendMode : null; + if (blendMode != null) { + return BlendMode.blendModeToPorterDuffMode(blendMode); + } else { + return null; + } + } + + /** + * Return the blending mode used to apply the tint to the foreground + * drawable, if specified. + * + * @return the blending mode used to apply the tint to the foreground + * drawable + * @attr ref android.R.styleable#View_foregroundTintMode + * @see #setForegroundTintMode(BlendMode) + * + */ + public @Nullable BlendMode getForegroundBlendMode() { return mForegroundInfo != null && mForegroundInfo.mTintInfo != null - ? mForegroundInfo.mTintInfo.mTintMode : null; + ? mForegroundInfo.mTintInfo.mBlendMode : null; } private void applyForegroundTint() { @@ -23575,7 +23667,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback, } if (tintInfo.mHasTintMode) { - mForegroundInfo.mDrawable.setTintMode(tintInfo.mTintMode); + mForegroundInfo.mDrawable.setTintMode(tintInfo.mBlendMode); } // The drawable (or one of its children) may not have been diff --git a/graphics/java/android/graphics/BaseCanvas.java b/graphics/java/android/graphics/BaseCanvas.java index fd37735882997..31906781159b0 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 3e117411db01b..2afc3d27fa279 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 39392c89d170f..0b267048d976a 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 189e1746e6446..93ddb10d24bc3 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 fba50430f2ef2..459291b7565e6 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.

+ * + * @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 84d953de91db9..5b933c493162f 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.

+ * + * @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 6f4adfde7ff9e..41cf79ad49fd0 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 cb12a7c6ba6ba..7def322c1953a 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 d9dab98c2be10..f45bf9b783e8d 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 976190109e7c9..6b30158a183ad 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 3c449166d9d50..efa806afce70d 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 ee4d1e72c1300..b94b114683717 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 49d353057d59d..e4142a933f0f8 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; @@ -209,6 +212,24 @@ public abstract class Drawable { @UnsupportedAppUsage 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 */ - public void setTintMode(@NonNull PorterDuff.Mode tintMode) {} + @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. + *

+ * 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}. + *

+ *

Note: Setting a color filter via + * {@link #setColorFilter(ColorFilter)} + *

+ * + * @param blendMode + * @see #setTint(int) + * @see #setTintList(ColorStateList) + */ + 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 77e77c49973c1..3e0881aef9edc 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 70c90eb05b171..d81401d451ca1 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 e58e80225292b..cdb3441d5225c 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 71dd7a2f48001..5fd18a1431e00 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 */ - public Icon setTintMode(PorterDuff.Mode mode) { - mTintMode = mode; + @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 @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 CREATOR diff --git a/graphics/java/android/graphics/drawable/LayerDrawable.java b/graphics/java/android/graphics/drawable/LayerDrawable.java index b4392c8d023f7..e2c84927b5781 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 b53477137331e..4972e6a82b7df 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 7bfb4c38d6c80..b5fe7f9e432d4 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 7325b857f02c5..43772ec20cf39 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; }