diff options
40 files changed, 714 insertions, 15 deletions
diff --git a/api/current.txt b/api/current.txt index ff78d481f4de..ebec9e385c31 100755 --- a/api/current.txt +++ b/api/current.txt @@ -13417,6 +13417,46 @@ package android.graphics { ctor public BitmapShader(android.graphics.Bitmap, android.graphics.Shader.TileMode, android.graphics.Shader.TileMode); } + public final class BlendMode extends java.lang.Enum { + method public static android.graphics.BlendMode valueOf(java.lang.String); + method public static final android.graphics.BlendMode[] values(); + enum_constant public static final android.graphics.BlendMode CLEAR; + enum_constant public static final android.graphics.BlendMode COLOR; + enum_constant public static final android.graphics.BlendMode COLOR_BURN; + enum_constant public static final android.graphics.BlendMode COLOR_DODGE; + enum_constant public static final android.graphics.BlendMode DARKEN; + enum_constant public static final android.graphics.BlendMode DIFFERENCE; + enum_constant public static final android.graphics.BlendMode DST; + enum_constant public static final android.graphics.BlendMode DST_ATOP; + enum_constant public static final android.graphics.BlendMode DST_IN; + enum_constant public static final android.graphics.BlendMode DST_OUT; + enum_constant public static final android.graphics.BlendMode DST_OVER; + enum_constant public static final android.graphics.BlendMode EXCLUSION; + enum_constant public static final android.graphics.BlendMode HARD_LIGHT; + enum_constant public static final android.graphics.BlendMode HUE; + enum_constant public static final android.graphics.BlendMode LIGHTEN; + enum_constant public static final android.graphics.BlendMode LUMINOSITY; + enum_constant public static final android.graphics.BlendMode MODULATE; + enum_constant public static final android.graphics.BlendMode MULTIPLY; + enum_constant public static final android.graphics.BlendMode OVERLAY; + enum_constant public static final android.graphics.BlendMode PLUS; + enum_constant public static final android.graphics.BlendMode SATURATION; + enum_constant public static final android.graphics.BlendMode SCREEN; + enum_constant public static final android.graphics.BlendMode SOFT_LIGHT; + enum_constant public static final android.graphics.BlendMode SRC; + enum_constant public static final android.graphics.BlendMode SRC_ATOP; + enum_constant public static final android.graphics.BlendMode SRC_IN; + enum_constant public static final android.graphics.BlendMode SRC_OUT; + enum_constant public static final android.graphics.BlendMode SRC_OVER; + enum_constant public static final android.graphics.BlendMode XOR; + } + + public final class BlendModeColorFilter extends android.graphics.ColorFilter { + ctor public BlendModeColorFilter(int, android.graphics.BlendMode); + method public int getColor(); + method public android.graphics.BlendMode getMode(); + } + public class BlurMaskFilter extends android.graphics.MaskFilter { ctor public BlurMaskFilter(float, android.graphics.BlurMaskFilter.Blur); } @@ -13479,7 +13519,8 @@ package android.graphics { method public void drawBitmapMesh(android.graphics.Bitmap, int, int, float[], int, int[], int, android.graphics.Paint); method public void drawCircle(float, float, float, android.graphics.Paint); method public void drawColor(int); - method public void drawColor(int, android.graphics.PorterDuff.Mode); + method public deprecated void drawColor(int, android.graphics.PorterDuff.Mode); + method public void drawColor(int, android.graphics.BlendMode); method public void drawDoubleRoundRect(android.graphics.RectF, float, float, android.graphics.RectF, float, float, android.graphics.Paint); method public void drawDoubleRoundRect(android.graphics.RectF, float[], android.graphics.RectF, float[], android.graphics.Paint); method public void drawLine(float, float, float, float, android.graphics.Paint); @@ -14098,6 +14139,7 @@ package android.graphics { method public float descent(); method public boolean equalsForTextMeasurement(android.graphics.Paint); method public int getAlpha(); + method public android.graphics.BlendMode getBlendMode(); method public int getColor(); method public android.graphics.ColorFilter getColorFilter(); method public boolean getFillPath(android.graphics.Path, android.graphics.Path); @@ -14152,7 +14194,7 @@ package android.graphics { method public float getUnderlinePosition(); method public float getUnderlineThickness(); method public float getWordSpacing(); - method public android.graphics.Xfermode getXfermode(); + method public deprecated android.graphics.Xfermode getXfermode(); method public boolean hasGlyph(java.lang.String); method public final boolean isAntiAlias(); method public final boolean isDither(); @@ -14172,6 +14214,7 @@ package android.graphics { method public void setARGB(int, int, int, int); method public void setAlpha(int); method public void setAntiAlias(boolean); + method public void setBlendMode(android.graphics.BlendMode); method public void setColor(int); method public android.graphics.ColorFilter setColorFilter(android.graphics.ColorFilter); method public void setDither(boolean); @@ -14205,7 +14248,7 @@ package android.graphics { method public android.graphics.Typeface setTypeface(android.graphics.Typeface); method public void setUnderlineText(boolean); method public void setWordSpacing(float); - method public android.graphics.Xfermode setXfermode(android.graphics.Xfermode); + method public deprecated android.graphics.Xfermode setXfermode(android.graphics.Xfermode); field public static final int ANTI_ALIAS_FLAG = 1; // 0x1 field public static final int CURSOR_AFTER = 0; // 0x0 field public static final int CURSOR_AT = 4; // 0x4 @@ -14487,7 +14530,7 @@ package android.graphics { enum_constant public static final android.graphics.PorterDuff.Mode XOR; } - public class PorterDuffColorFilter extends android.graphics.ColorFilter { + public deprecated class PorterDuffColorFilter extends android.graphics.ColorFilter { ctor public PorterDuffColorFilter(int, android.graphics.PorterDuff.Mode); } @@ -15040,7 +15083,7 @@ package android.graphics.drawable { method public final void setCallback(android.graphics.drawable.Drawable.Callback); method public void setChangingConfigurations(int); method public abstract void setColorFilter(android.graphics.ColorFilter); - method public void setColorFilter(int, android.graphics.PorterDuff.Mode); + method public deprecated void setColorFilter(int, android.graphics.PorterDuff.Mode); method public deprecated void setDither(boolean); method public void setFilterBitmap(boolean); method public void setHotspot(float, float); diff --git a/core/jni/android/graphics/ColorFilter.cpp b/core/jni/android/graphics/ColorFilter.cpp index 6ebf35c8e1dc..a54571b539da 100644 --- a/core/jni/android/graphics/ColorFilter.cpp +++ b/core/jni/android/graphics/ColorFilter.cpp @@ -36,7 +36,7 @@ public: return static_cast<jlong>(reinterpret_cast<uintptr_t>(&SafeUnref)); } - static jlong CreatePorterDuffFilter(JNIEnv* env, jobject, jint srcColor, jint modeHandle) { + static jlong CreateBlendModeFilter(JNIEnv* env, jobject, jint srcColor, jint modeHandle) { SkBlendMode mode = static_cast<SkBlendMode>(modeHandle); return reinterpret_cast<jlong>(SkColorFilter::MakeModeFilter(srcColor, mode).release()); } @@ -61,8 +61,8 @@ static const JNINativeMethod colorfilter_methods[] = { {"nativeGetFinalizer", "()J", (void*) SkColorFilterGlue::GetNativeFinalizer } }; -static const JNINativeMethod porterduff_methods[] = { - { "native_CreatePorterDuffFilter", "(II)J", (void*) SkColorFilterGlue::CreatePorterDuffFilter }, +static const JNINativeMethod blendmode_methods[] = { + { "native_CreateBlendModeFilter", "(II)J", (void*) SkColorFilterGlue::CreateBlendModeFilter }, }; static const JNINativeMethod lighting_methods[] = { @@ -76,8 +76,10 @@ static const JNINativeMethod colormatrix_methods[] = { int register_android_graphics_ColorFilter(JNIEnv* env) { android::RegisterMethodsOrDie(env, "android/graphics/ColorFilter", colorfilter_methods, NELEM(colorfilter_methods)); - android::RegisterMethodsOrDie(env, "android/graphics/PorterDuffColorFilter", porterduff_methods, - NELEM(porterduff_methods)); + android::RegisterMethodsOrDie(env, "android/graphics/PorterDuffColorFilter", blendmode_methods, + NELEM(blendmode_methods)); + android::RegisterMethodsOrDie(env, "android/graphics/BlendModeColorFilter", blendmode_methods, + NELEM(blendmode_methods)); android::RegisterMethodsOrDie(env, "android/graphics/LightingColorFilter", lighting_methods, NELEM(lighting_methods)); android::RegisterMethodsOrDie(env, "android/graphics/ColorMatrixColorFilter", diff --git a/core/jni/android/graphics/Paint.cpp b/core/jni/android/graphics/Paint.cpp index a8b0640c3a73..cd54268e2fab 100644 --- a/core/jni/android/graphics/Paint.cpp +++ b/core/jni/android/graphics/Paint.cpp @@ -845,12 +845,23 @@ namespace PaintGlue { static_assert(9 == static_cast<int>(SkBlendMode::kSrcATop), "xfermode_mismatch"); static_assert(10 == static_cast<int>(SkBlendMode::kDstATop), "xfermode_mismatch"); static_assert(11 == static_cast<int>(SkBlendMode::kXor), "xfermode_mismatch"); - static_assert(16 == static_cast<int>(SkBlendMode::kDarken), "xfermode_mismatch"); - static_assert(17 == static_cast<int>(SkBlendMode::kLighten), "xfermode_mismatch"); + static_assert(12 == static_cast<int>(SkBlendMode::kPlus), "xfermode_mismatch"); static_assert(13 == static_cast<int>(SkBlendMode::kModulate), "xfermode_mismatch"); static_assert(14 == static_cast<int>(SkBlendMode::kScreen), "xfermode_mismatch"); - static_assert(12 == static_cast<int>(SkBlendMode::kPlus), "xfermode_mismatch"); static_assert(15 == static_cast<int>(SkBlendMode::kOverlay), "xfermode_mismatch"); + static_assert(16 == static_cast<int>(SkBlendMode::kDarken), "xfermode_mismatch"); + static_assert(17 == static_cast<int>(SkBlendMode::kLighten), "xfermode_mismatch"); + static_assert(18 == static_cast<int>(SkBlendMode::kColorDodge), "xfermode mismatch"); + static_assert(19 == static_cast<int>(SkBlendMode::kColorBurn), "xfermode mismatch"); + static_assert(20 == static_cast<int>(SkBlendMode::kHardLight), "xfermode mismatch"); + static_assert(21 == static_cast<int>(SkBlendMode::kSoftLight), "xfermode mismatch"); + static_assert(22 == static_cast<int>(SkBlendMode::kDifference), "xfermode mismatch"); + static_assert(23 == static_cast<int>(SkBlendMode::kExclusion), "xfermode mismatch"); + static_assert(24 == static_cast<int>(SkBlendMode::kMultiply), "xfermode mismatch"); + static_assert(25 == static_cast<int>(SkBlendMode::kHue), "xfermode mismatch"); + static_assert(26 == static_cast<int>(SkBlendMode::kSaturation), "xfermode mismatch"); + static_assert(27 == static_cast<int>(SkBlendMode::kColor), "xfermode mismatch"); + static_assert(28 == static_cast<int>(SkBlendMode::kLuminosity), "xfermode mismatch"); SkBlendMode mode = static_cast<SkBlendMode>(xfermodeHandle); Paint* paint = reinterpret_cast<Paint*>(paintHandle); diff --git a/docs/html/reference/images/graphics/blendmode_CLEAR.png b/docs/html/reference/images/graphics/blendmode_CLEAR.png Binary files differnew file mode 100644 index 000000000000..979782adef58 --- /dev/null +++ b/docs/html/reference/images/graphics/blendmode_CLEAR.png diff --git a/docs/html/reference/images/graphics/blendmode_COLOR.png b/docs/html/reference/images/graphics/blendmode_COLOR.png Binary files differnew file mode 100644 index 000000000000..2f41bfb03cfb --- /dev/null +++ b/docs/html/reference/images/graphics/blendmode_COLOR.png diff --git a/docs/html/reference/images/graphics/blendmode_COLOR_BURN.png b/docs/html/reference/images/graphics/blendmode_COLOR_BURN.png Binary files differnew file mode 100644 index 000000000000..26059ce858ee --- /dev/null +++ b/docs/html/reference/images/graphics/blendmode_COLOR_BURN.png diff --git a/docs/html/reference/images/graphics/blendmode_COLOR_DODGE.png b/docs/html/reference/images/graphics/blendmode_COLOR_DODGE.png Binary files differnew file mode 100644 index 000000000000..922f1d9e474d --- /dev/null +++ b/docs/html/reference/images/graphics/blendmode_COLOR_DODGE.png diff --git a/docs/html/reference/images/graphics/blendmode_DARKEN.png b/docs/html/reference/images/graphics/blendmode_DARKEN.png Binary files differnew file mode 100644 index 000000000000..6c04aa3a129f --- /dev/null +++ b/docs/html/reference/images/graphics/blendmode_DARKEN.png diff --git a/docs/html/reference/images/graphics/blendmode_DIFFERENCE.png b/docs/html/reference/images/graphics/blendmode_DIFFERENCE.png Binary files differnew file mode 100644 index 000000000000..aab2bcb8833a --- /dev/null +++ b/docs/html/reference/images/graphics/blendmode_DIFFERENCE.png diff --git a/docs/html/reference/images/graphics/blendmode_DST.png b/docs/html/reference/images/graphics/blendmode_DST.png Binary files differnew file mode 100644 index 000000000000..16f96b4752b8 --- /dev/null +++ b/docs/html/reference/images/graphics/blendmode_DST.png diff --git a/docs/html/reference/images/graphics/blendmode_DST_ATOP.png b/docs/html/reference/images/graphics/blendmode_DST_ATOP.png Binary files differnew file mode 100644 index 000000000000..d0ae2cde7b0f --- /dev/null +++ b/docs/html/reference/images/graphics/blendmode_DST_ATOP.png diff --git a/docs/html/reference/images/graphics/blendmode_DST_IN.png b/docs/html/reference/images/graphics/blendmode_DST_IN.png Binary files differnew file mode 100644 index 000000000000..9befe279af73 --- /dev/null +++ b/docs/html/reference/images/graphics/blendmode_DST_IN.png diff --git a/docs/html/reference/images/graphics/blendmode_DST_OUT.png b/docs/html/reference/images/graphics/blendmode_DST_OUT.png Binary files differnew file mode 100644 index 000000000000..e9227e9f06d3 --- /dev/null +++ b/docs/html/reference/images/graphics/blendmode_DST_OUT.png diff --git a/docs/html/reference/images/graphics/blendmode_DST_OVER.png b/docs/html/reference/images/graphics/blendmode_DST_OVER.png Binary files differnew file mode 100644 index 000000000000..015be0a4a730 --- /dev/null +++ b/docs/html/reference/images/graphics/blendmode_DST_OVER.png diff --git a/docs/html/reference/images/graphics/blendmode_EXCLUSION.png b/docs/html/reference/images/graphics/blendmode_EXCLUSION.png Binary files differnew file mode 100644 index 000000000000..307dec90ec33 --- /dev/null +++ b/docs/html/reference/images/graphics/blendmode_EXCLUSION.png diff --git a/docs/html/reference/images/graphics/blendmode_HARD_LIGHT.png b/docs/html/reference/images/graphics/blendmode_HARD_LIGHT.png Binary files differnew file mode 100644 index 000000000000..3b62b9855bf4 --- /dev/null +++ b/docs/html/reference/images/graphics/blendmode_HARD_LIGHT.png diff --git a/docs/html/reference/images/graphics/blendmode_HUE.png b/docs/html/reference/images/graphics/blendmode_HUE.png Binary files differnew file mode 100644 index 000000000000..012bd3332358 --- /dev/null +++ b/docs/html/reference/images/graphics/blendmode_HUE.png diff --git a/docs/html/reference/images/graphics/blendmode_LIGHTEN.png b/docs/html/reference/images/graphics/blendmode_LIGHTEN.png Binary files differnew file mode 100644 index 000000000000..1c3be656e40a --- /dev/null +++ b/docs/html/reference/images/graphics/blendmode_LIGHTEN.png diff --git a/docs/html/reference/images/graphics/blendmode_LUMINOSITY.png b/docs/html/reference/images/graphics/blendmode_LUMINOSITY.png Binary files differnew file mode 100644 index 000000000000..3549082e4c62 --- /dev/null +++ b/docs/html/reference/images/graphics/blendmode_LUMINOSITY.png diff --git a/docs/html/reference/images/graphics/blendmode_MODULATE.png b/docs/html/reference/images/graphics/blendmode_MODULATE.png Binary files differnew file mode 100644 index 000000000000..ed1b59d140e8 --- /dev/null +++ b/docs/html/reference/images/graphics/blendmode_MODULATE.png diff --git a/docs/html/reference/images/graphics/blendmode_MULTIPLY.png b/docs/html/reference/images/graphics/blendmode_MULTIPLY.png Binary files differnew file mode 100644 index 000000000000..c8c7ccb1e21a --- /dev/null +++ b/docs/html/reference/images/graphics/blendmode_MULTIPLY.png diff --git a/docs/html/reference/images/graphics/blendmode_OVERLAY.png b/docs/html/reference/images/graphics/blendmode_OVERLAY.png Binary files differnew file mode 100644 index 000000000000..6962f928dc7e --- /dev/null +++ b/docs/html/reference/images/graphics/blendmode_OVERLAY.png diff --git a/docs/html/reference/images/graphics/blendmode_PLUS.png b/docs/html/reference/images/graphics/blendmode_PLUS.png Binary files differnew file mode 100644 index 000000000000..015fa2b5d0e4 --- /dev/null +++ b/docs/html/reference/images/graphics/blendmode_PLUS.png diff --git a/docs/html/reference/images/graphics/blendmode_SATURATION.png b/docs/html/reference/images/graphics/blendmode_SATURATION.png Binary files differnew file mode 100644 index 000000000000..5ac96c32f648 --- /dev/null +++ b/docs/html/reference/images/graphics/blendmode_SATURATION.png diff --git a/docs/html/reference/images/graphics/blendmode_SCREEN.png b/docs/html/reference/images/graphics/blendmode_SCREEN.png Binary files differnew file mode 100644 index 000000000000..d2d70d25850d --- /dev/null +++ b/docs/html/reference/images/graphics/blendmode_SCREEN.png diff --git a/docs/html/reference/images/graphics/blendmode_SOFT_LIGHT.png b/docs/html/reference/images/graphics/blendmode_SOFT_LIGHT.png Binary files differnew file mode 100644 index 000000000000..89fbacd24dcc --- /dev/null +++ b/docs/html/reference/images/graphics/blendmode_SOFT_LIGHT.png diff --git a/docs/html/reference/images/graphics/blendmode_SRC.png b/docs/html/reference/images/graphics/blendmode_SRC.png Binary files differnew file mode 100644 index 000000000000..990ec94301b3 --- /dev/null +++ b/docs/html/reference/images/graphics/blendmode_SRC.png diff --git a/docs/html/reference/images/graphics/blendmode_SRC_ATOP.png b/docs/html/reference/images/graphics/blendmode_SRC_ATOP.png Binary files differnew file mode 100644 index 000000000000..d574dfd923f2 --- /dev/null +++ b/docs/html/reference/images/graphics/blendmode_SRC_ATOP.png diff --git a/docs/html/reference/images/graphics/blendmode_SRC_IN.png b/docs/html/reference/images/graphics/blendmode_SRC_IN.png Binary files differnew file mode 100644 index 000000000000..dda45d7319a4 --- /dev/null +++ b/docs/html/reference/images/graphics/blendmode_SRC_IN.png diff --git a/docs/html/reference/images/graphics/blendmode_SRC_OUT.png b/docs/html/reference/images/graphics/blendmode_SRC_OUT.png Binary files differnew file mode 100644 index 000000000000..f5d43c103dc2 --- /dev/null +++ b/docs/html/reference/images/graphics/blendmode_SRC_OUT.png diff --git a/docs/html/reference/images/graphics/blendmode_SRC_OVER.png b/docs/html/reference/images/graphics/blendmode_SRC_OVER.png Binary files differnew file mode 100644 index 000000000000..b1a405bc878d --- /dev/null +++ b/docs/html/reference/images/graphics/blendmode_SRC_OVER.png diff --git a/docs/html/reference/images/graphics/blendmode_XOR.png b/docs/html/reference/images/graphics/blendmode_XOR.png Binary files differnew file mode 100644 index 000000000000..31c110d98d27 --- /dev/null +++ b/docs/html/reference/images/graphics/blendmode_XOR.png diff --git a/graphics/java/android/graphics/BaseCanvas.java b/graphics/java/android/graphics/BaseCanvas.java index 3db240b54299..ca9dc475f7a1 100644 --- a/graphics/java/android/graphics/BaseCanvas.java +++ b/graphics/java/android/graphics/BaseCanvas.java @@ -241,10 +241,22 @@ public abstract class BaseCanvas { nDrawColor(mNativeCanvasWrapper, color, PorterDuff.Mode.SRC_OVER.nativeInt); } + /** + * @deprecated use {@link Canvas#drawColor(int, BlendMode)} + */ + @Deprecated public void drawColor(@ColorInt int color, @NonNull PorterDuff.Mode mode) { nDrawColor(mNativeCanvasWrapper, color, mode.nativeInt); } + /** + * Make lint happy. + * See {@link Canvas#drawColor(int, BlendMode)} + */ + public void drawColor(@ColorInt int color, @NonNull BlendMode mode) { + nDrawColor(mNativeCanvasWrapper, color, mode.getXfermode().porterDuffMode); + } + public void drawLine(float startX, float startY, float stopX, float stopY, @NonNull Paint paint) { throwIfHasHwBitmapInSwMode(paint); diff --git a/graphics/java/android/graphics/BaseRecordingCanvas.java b/graphics/java/android/graphics/BaseRecordingCanvas.java index 4de7ca708eb6..901c2116884b 100644 --- a/graphics/java/android/graphics/BaseRecordingCanvas.java +++ b/graphics/java/android/graphics/BaseRecordingCanvas.java @@ -201,12 +201,21 @@ public class BaseRecordingCanvas extends Canvas { nDrawColor(mNativeCanvasWrapper, color, PorterDuff.Mode.SRC_OVER.nativeInt); } + /** + * @deprecated use {@link #drawColor(int, BlendMode)} instead + */ + @Deprecated @Override public final void drawColor(@ColorInt int color, @NonNull PorterDuff.Mode mode) { nDrawColor(mNativeCanvasWrapper, color, mode.nativeInt); } @Override + public final void drawColor(@ColorInt int color, @NonNull BlendMode mode) { + nDrawColor(mNativeCanvasWrapper, color, mode.getXfermode().porterDuffMode); + } + + @Override public final void drawLine(float startX, float startY, float stopX, float stopY, @NonNull Paint paint) { nDrawLine(mNativeCanvasWrapper, startX, startY, stopX, stopY, paint.getNativeInstance()); diff --git a/graphics/java/android/graphics/BlendMode.java b/graphics/java/android/graphics/BlendMode.java new file mode 100644 index 000000000000..39392c89d170 --- /dev/null +++ b/graphics/java/android/graphics/BlendMode.java @@ -0,0 +1,472 @@ +/* + * Copyright (C) 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.graphics; + +import android.annotation.NonNull; +import android.annotation.Nullable; + +public enum BlendMode { + + /** + * <p> + * <img src="{@docRoot}reference/android/images/graphics/blendmode_CLEAR.png" /> + * <figcaption>Destination pixels covered by the source are cleared to 0.</figcaption> + * </p> + * <p>\(\alpha_{out} = 0\)</p> + * <p>\(C_{out} = 0\)</p> + */ + CLEAR(0), + + /** + * <p> + * <img src="{@docRoot}reference/android/images/graphics/blendmode_SRC.png" /> + * <figcaption>The source pixels replace the destination pixels.</figcaption> + * </p> + * <p>\(\alpha_{out} = \alpha_{src}\)</p> + * <p>\(C_{out} = C_{src}\)</p> + */ + SRC(1), + + /** + * <p> + * <img src="{@docRoot}reference/android/images/graphics/blendmode_DST.png" /> + * <figcaption>The source pixels are discarded, leaving the destination intact.</figcaption> + * </p> + * <p>\(\alpha_{out} = \alpha_{dst}\)</p> + * <p>\(C_{out} = C_{dst}\)</p> + */ + DST(2), + + /** + * <p> + * <img src="{@docRoot}reference/android/images/graphics/blendmode_SRC_OVER.png" /> + * <figcaption>The source pixels are drawn over the destination pixels.</figcaption> + * </p> + * <p>\(\alpha_{out} = \alpha_{src} + (1 - \alpha_{src}) * \alpha_{dst}\)</p> + * <p>\(C_{out} = C_{src} + (1 - \alpha_{src}) * C_{dst}\)</p> + */ + SRC_OVER(3), + + /** + * <p> + * <img src="{@docRoot}reference/android/images/graphics/blendmode_DST_OVER.png" /> + * <figcaption>The source pixels are drawn behind the destination pixels.</figcaption> + * </p> + * <p>\(\alpha_{out} = \alpha_{dst} + (1 - \alpha_{dst}) * \alpha_{src}\)</p> + * <p>\(C_{out} = C_{dst} + (1 - \alpha_{dst}) * C_{src}\)</p> + */ + DST_OVER(4), + + /** + * <p> + * <img src="{@docRoot}reference/android/images/graphics/blendmode_SRC_IN.png" /> + * <figcaption>Keeps the source pixels that cover the destination pixels, + * discards the remaining source and destination pixels.</figcaption> + * </p> + * <p>\(\alpha_{out} = \alpha_{src} * \alpha_{dst}\)</p> + * <p>\(C_{out} = C_{src} * \alpha_{dst}\)</p> + */ + SRC_IN(5), + + /** + * <p> + * <img src="{@docRoot}reference/android/images/graphics/blendmode_DST_IN.png" /> + * <figcaption>Keeps the destination pixels that cover source pixels, + * discards the remaining source and destination pixels.</figcaption> + * </p> + * <p>\(\alpha_{out} = \alpha_{src} * \alpha_{dst}\)</p> + * <p>\(C_{out} = C_{dst} * \alpha_{src}\)</p> + */ + DST_IN(6), + + /** + * <p> + * <img src="{@docRoot}reference/android/images/graphics/blendmode_SRC_OUT.png" /> + * <figcaption>Keeps the source pixels that do not cover destination pixels. + * Discards source pixels that cover destination pixels. Discards all + * destination pixels.</figcaption> + * </p> + * <p>\(\alpha_{out} = (1 - \alpha_{dst}) * \alpha_{src}\)</p> + * <p>\(C_{out} = (1 - \alpha_{dst}) * C_{src}\)</p> + */ + SRC_OUT(7), + + /** + * <p> + * <img src="{@docRoot}reference/android/images/graphics/blendmode_DST_OUT.png" /> + * <figcaption>Keeps the destination pixels that are not covered by source pixels. + * Discards destination pixels that are covered by source pixels. Discards all + * source pixels.</figcaption> + * </p> + * <p>\(\alpha_{out} = (1 - \alpha_{src}) * \alpha_{dst}\)</p> + * <p>\(C_{out} = (1 - \alpha_{src}) * C_{dst}\)</p> + */ + DST_OUT(8), + + /** + * <p> + * <img src="{@docRoot}reference/android/images/graphics/blendmode_SRC_ATOP.png" /> + * <figcaption>Discards the source pixels that do not cover destination pixels. + * Draws remaining source pixels over destination pixels.</figcaption> + * </p> + * <p>\(\alpha_{out} = \alpha_{dst}\)</p> + * <p>\(C_{out} = \alpha_{dst} * C_{src} + (1 - \alpha_{src}) * C_{dst}\)</p> + */ + SRC_ATOP(9), + + /** + * <p> + * <img src="{@docRoot}reference/android/images/graphics/blendmode_DST_ATOP.png" /> + * <figcaption>Discards the destination pixels that are not covered by source pixels. + * Draws remaining destination pixels over source pixels.</figcaption> + * </p> + * <p>\(\alpha_{out} = \alpha_{src}\)</p> + * <p>\(C_{out} = \alpha_{src} * C_{dst} + (1 - \alpha_{dst}) * C_{src}\)</p> + */ + DST_ATOP(10), + + /** + * <p> + * <img src="{@docRoot}reference/android/images/graphics/blendmode_XOR.png" /> + * <figcaption>Discards the source and destination pixels where source pixels + * cover destination pixels. Draws remaining source pixels.</figcaption> + * </p> + * <p> + * \(\alpha_{out} = (1 - \alpha_{dst}) * \alpha_{src} + (1 - \alpha_{src}) * \alpha_{dst}\) + * </p> + * <p>\(C_{out} = (1 - \alpha_{dst}) * C_{src} + (1 - \alpha_{src}) * C_{dst}\)</p> + */ + XOR(11), + + /** + * <p> + * <img src="{@docRoot}reference/android/images/graphics/blendmode_PLUS.png" /> + * <figcaption>Adds the source pixels to the destination pixels and saturates + * the result.</figcaption> + * </p> + * <p>\(\alpha_{out} = max(0, min(\alpha_{src} + \alpha_{dst}, 1))\)</p> + * <p>\(C_{out} = max(0, min(C_{src} + C_{dst}, 1))\)</p> + */ + PLUS(12), + + /** + * <p> + * <img src="{@docRoot}reference/android/images/graphics/blendmode_MODULATE.png" /> + * <figcaption>Multiplies the source and destination pixels.</figcaption> + * </p> + * <p>\(\alpha_{out} = \alpha_{src} * \alpha_{dst}\)</p> + * <p>\(C_{out} = C_{src} * C_{dst}\)</p> + * + */ + MODULATE(13), + + /** + * <p> + * <img src="{@docRoot}reference/android/images/graphics/blendmode_SCREEN.png" /> + * <figcaption> + * Adds the source and destination pixels, then subtracts the + * source pixels multiplied by the destination. + * </figcaption> + * </p> + * <p>\(\alpha_{out} = \alpha_{src} + \alpha_{dst} - \alpha_{src} * \alpha_{dst}\)</p> + * <p>\(C_{out} = C_{src} + C_{dst} - C_{src} * C_{dst}\)</p> + */ + SCREEN(14), + + /** + * <p> + * <img src="{@docRoot}reference/android/images/graphics/blendmode_OVERLAY.png" /> + * <figcaption> + * Multiplies or screens the source and destination depending on the + * destination color. + * </figcaption> + * </p> + * <p>\(\alpha_{out} = \alpha_{src} + \alpha_{dst} - \alpha_{src} * \alpha_{dst}\)</p> + * <p>\(\begin{equation} + * C_{out} = \begin{cases} 2 * C_{src} * C_{dst} & 2 * C_{dst} \lt \alpha_{dst} \\ + * \alpha_{src} * \alpha_{dst} - 2 (\alpha_{dst} - C_{src}) (\alpha_{src} - C_{dst}) & + * otherwise \end{cases} + * \end{equation}\)</p> + */ + OVERLAY(15), + + /** + * <p> + * <img src="{@docRoot}reference/android/images/graphics/blendmode_DARKEN.png" /> + * <figcaption> + * Retains the smallest component of the source and + * destination pixels. + * </figcaption> + * </p> + * <p>\(\alpha_{out} = \alpha_{src} + \alpha_{dst} - \alpha_{src} * \alpha_{dst}\)</p> + * <p> + * \(C_{out} = + * (1 - \alpha_{dst}) * C_{src} + (1 - \alpha_{src}) * C_{dst} + min(C_{src}, C_{dst})\) + * </p> + */ + DARKEN(16), + + /** + * <p> + * <img src="{@docRoot}reference/android/images/graphics/blendmode_LIGHTEN.png" /> + * <figcaption>Retains the largest component of the source and + * destination pixel.</figcaption> + * </p> + * <p>\(\alpha_{out} = \alpha_{src} + \alpha_{dst} - \alpha_{src} * \alpha_{dst}\)</p> + * <p> + * \(C_{out} = + * (1 - \alpha_{dst}) * C_{src} + (1 - \alpha_{src}) * C_{dst} + max(C_{src}, C_{dst})\) + * </p> + */ + LIGHTEN(17), + + /** + * <p> + * <img src="{@docRoot}reference/android/images/graphics/blendmode_COLOR_DODGE.png" /> + * <figcaption>Makes destination brighter to reflect source.</figcaption> + * </p> + * <p> + * \(\alpha_{out} = \alpha_{src} + \alpha_{dst} - \alpha_{src} * \alpha_{dst}\) + * </p> + * <p> + * \begin{equation} + * C_{out} = + * \begin{cases} + * C_{src} * (1 - \alpha_{dst}) & C_{dst} = 0 \\ + * C_{src} + \alpha_{dst}*(1 - \alpha_{src}) & C_{src} = \alpha_{src} \\ + * \alpha_{src} * min(\alpha_{dst}, C_{dst} * \alpha_{src}/(\alpha_{src} - C_{src})) + * + C_{src} *(1 - \alpha_{dst} + \alpha_{dst}*(1 - \alpha_{src}) & otherwise + * \end{cases} + * \end{equation} + * </p> + */ + COLOR_DODGE(18), + + /** + * <p> + * <img src="{@docRoot}reference/android/images/graphics/blendmode_COLOR_BURN.png" /> + * <figcaption>Makes destination darker to reflect source.</figcaption> + * </p> + * <p> + * \(\alpha_{out} = \alpha_{src} + \alpha_{dst} - \alpha_{src} * \alpha_{dst}\) + * </p> + * <p> + * \begin{equation} + * C_{out} = + * \begin{cases} + * C_{dst} + C_{src}*(1 - \alpha_{dst}) & C_{dst} = \alpha_{dst} \\ + * \alpha_{dst}*(1 - \alpha_{src}) & C_{src} = 0 \\ + * \alpha_{src}*(\alpha_{dst} - min(\alpha_{dst}, (\alpha_{dst} + * - C_{dst})*\alpha_{src}/C_{src})) + * + C_{src} * (1 - \alpha_{dst}) + \alpha_{dst}*(1-\alpha_{src}) & otherwise + * \end{cases} + * \end{equation} + * </p> + */ + COLOR_BURN(19), + + /** + * <p> + * <img src="{@docRoot}reference/android/images/graphics/blendmode_HARD_LIGHT.png" /> + * <figcaption>Makes destination lighter or darker, depending on source.</figcaption> + * </p> + * <p> + * \(\alpha_{out} = \alpha_{src} + \alpha_{dst} - \alpha_{src} * \alpha_{dst}\) + * </p> + * <p> + * \begin{equation} + * C_{out} = + * \begin{cases} + * 2*C_{src}*C_{dst} & C_{src}*(1-\alpha_{dst}) + C_{dst}*(1-\alpha_{src}) + 2*C_{src} + * \leq \alpha_{src} \\ + * \alpha_{src}*\alpha_{dst}- 2*(\alpha_{dst} - C_{dst})*(\alpha_{src} - C_{src}) + * & otherwise + * \end{cases} + * \end{equation} + * </p> + */ + HARD_LIGHT(20), + + /** + * <p> + * <img src="{@docRoot}reference/android/images/graphics/blendmode_SOFT_LIGHT.png" /> + * <figcaption>Makes destination lighter or darker, depending on source.</figcaption> + * </p> + * <p> + * Where + * \begin{equation} + * m = + * \begin{cases} + * C_{dst} / \alpha_{dst} & \alpha_{dst} \gt 0 \\ + * 0 & otherwise + * \end{cases} + * \end{equation} + * </p> + * <p> + * \begin{equation} + * g = + * \begin{cases} + * (16 * m * m + 4 * m) * (m - 1) + 7 * m & 4 * C_{dst} \leq \alpha_{dst} \\ + * \sqrt m - m & otherwise + * \end{cases} + * \end{equation} + * </p> + * <p> + * \begin{equation} + * f = + * \begin{cases} + * C_{dst} * (\alpha_{src} + (2 * C_{src} - \alpha_{src}) * (1 - m)) + * & 2 * C_{src} \leq \alpha_{src} \\ + * C_{dst} * \alpha_{src} + \alpha_{dst} * (2 * C_{src} - \alpha_{src}) * g + * & otherwise + * \end{cases} + * \end{equation} + * </p> + * <p> + * \begin{equation} + * \alpha_{out} = \alpha_{src} + \alpha_{dst} - \alpha_{src} * \alpha_{dst} + * \end{equation} + * \begin{equation} + * C_{out} = C_{src} / \alpha_{dst} + C_{dst} / \alpha_{src} + f + * \end{equation} + * </p> + */ + SOFT_LIGHT(21), + + /** + * <p> + * <img src="{@docRoot}reference/android/images/graphics/blendmode_DIFFERENCE.png" /> + * <figcaption>Subtracts darker from lighter with higher contrast.</figcaption> + * </p> + * <p> + * \begin{equation} + * \alpha_{out} = \alpha_{src} + \alpha_{dst} - \alpha_{src} * \alpha_{dst} + * \end{equation} + * </p> + * <p> + * \begin{equation} + * C_{out} = C_{src} + C_{dst} - 2 * min(C_{src} + * * \alpha_{dst}, C_{dst} * \alpha_{src}) + * \end{equation} + * </p> + */ + DIFFERENCE(22), + + /** + * <p> + * <img src="{@docRoot}reference/android/images/graphics/blendmode_DIFFERENCE.png" /> + * <figcaption>Subtracts darker from lighter with lower contrast.</figcaption> + * </p> + * <p> + * \begin{equation} + * \alpha_{out} = \alpha_{src} + \alpha_{dst} - \alpha_{src} * \alpha_{dst} + * \end{equation} + * </p> + * <p> + * \begin{equation} + * C_{out} = C_{src} + C_{dst} - 2 * C_{src} * C_{dst} + * \end{equation} + * </p> + */ + EXCLUSION(23), + + /** + * <p> + * <img src="{@docRoot}reference/android/images/graphics/blendmode_MODULATE.png" /> + * <figcaption>Multiplies the source and destination pixels.</figcaption> + * </p> + * <p>\(\alpha_{out} = \alpha_{src} + \alpha_{dst} - \alpha_{src} * \alpha_{dst}\)</p> + * <p>\(C_{out} = + * C_{src} * (1 - \alpha_{dst}) + C_{dst} * (1 - \alpha_{src}) + (C_{src} * C_{dst})\) + * </p> + */ + MULTIPLY(24), + + /** + * <p> + * <img src="{@docRoot}reference/android/images/graphics/blendmode_HUE.png" /> + * <figcaption> + * Replaces hue of destination with hue of source, leaving saturation + * and luminosity unchanged. + * </figcaption> + * </p> + */ + HUE(25), + + /** + * <p> + * <img src="{@docRoot}reference/android/images/graphics/blendmode_SATURATION.png" /> + * <figcaption> + * Replaces saturation of destination saturation hue of source, leaving hue and + * luminosity unchanged. + * </figcaption> + * </p> + */ + SATURATION(26), + + /** + * <p> + * <img src="{@docRoot}reference/android/images/graphics/blendmode_COLOR.png" /> + * <figcaption> + * Replaces hue and saturation of destination with hue and saturation of source, + * leaving luminosity unchanged. + * </figcaption> + * </p> + */ + COLOR(27), + + /** + * <p> + * <img src="{@docRoot}reference/android/images/graphics/blendmode_LUMINOSITY.png" /> + * <figcaption> + * Replaces luminosity of destination with luminosity of source, leaving hue and + * saturation unchanged. + * </figcaption> + * </p> + */ + LUMINOSITY(28); + + private static final BlendMode[] BLEND_MODES = values(); + + /** + * @hide + */ + public static @Nullable BlendMode fromValue(int value) { + for (BlendMode mode : BLEND_MODES) { + if (mode.mXfermode.porterDuffMode == value) { + return mode; + } + } + return null; + } + + @NonNull + private final Xfermode mXfermode; + + BlendMode(int mode) { + mXfermode = new Xfermode(); + mXfermode.porterDuffMode = mode; + } + + /** + * @hide + */ + @NonNull + public Xfermode getXfermode() { + return mXfermode; + } +} diff --git a/graphics/java/android/graphics/BlendModeColorFilter.java b/graphics/java/android/graphics/BlendModeColorFilter.java new file mode 100644 index 000000000000..7caeb4267ad2 --- /dev/null +++ b/graphics/java/android/graphics/BlendModeColorFilter.java @@ -0,0 +1,84 @@ +/* + * Copyright (C) 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.graphics; + +import android.annotation.ColorInt; +import android.annotation.NonNull; + +/** + * A color filter that can be used to tint the source pixels using a single + * color and a specific {@link BlendMode}. + */ +public final class BlendModeColorFilter extends ColorFilter { + + @ColorInt final int mColor; + private final BlendMode mMode; + + public BlendModeColorFilter(@ColorInt int color, @NonNull BlendMode mode) { + mColor = color; + mMode = mode; + } + + + /** + * Returns the ARGB color used to tint the source pixels when this filter + * is applied. + * + * @see Color + * + */ + @ColorInt + public int getColor() { + return mColor; + } + + /** + * Returns the Porter-Duff mode used to composite this color filter's + * color with the source pixel when this filter is applied. + * + * @see BlendMode + * + */ + public BlendMode getMode() { + return mMode; + } + + @Override + long createNativeInstance() { + return native_CreateBlendModeFilter(mColor, mMode.getXfermode().porterDuffMode); + } + + @Override + public boolean equals(Object object) { + if (this == object) { + return true; + } + if (object == null || getClass() != object.getClass()) { + return false; + } + final BlendModeColorFilter other = (BlendModeColorFilter) object; + return other.mMode == mMode; + } + + @Override + public int hashCode() { + return 31 * mMode.hashCode() + mColor; + } + + private static native long native_CreateBlendModeFilter(int srcColor, int blendmode); + +} diff --git a/graphics/java/android/graphics/Canvas.java b/graphics/java/android/graphics/Canvas.java index 3b0dc9d9f125..f61890c18a14 100644 --- a/graphics/java/android/graphics/Canvas.java +++ b/graphics/java/android/graphics/Canvas.java @@ -1684,12 +1684,26 @@ public class Canvas extends BaseCanvas { * * @param color the color to draw with * @param mode the porter-duff mode to apply to the color + * + * @deprecated use {@link #drawColor(int, BlendMode)} instead */ + @Deprecated public void drawColor(@ColorInt int color, @NonNull PorterDuff.Mode mode) { super.drawColor(color, mode); } /** + * Fill the entire canvas' bitmap (restricted to the current clip) with the specified color and + * blendmode. + * + * @param color the color to draw with + * @param mode the blendmode to apply to the color + */ + public void drawColor(@ColorInt int color, @NonNull BlendMode mode) { + super.drawColor(color, mode); + } + + /** * Draw a line segment with the specified start and stop x,y coordinates, using the specified * paint. * <p> diff --git a/graphics/java/android/graphics/Paint.java b/graphics/java/android/graphics/Paint.java index 69ff3bca6528..6821282bd0a7 100644 --- a/graphics/java/android/graphics/Paint.java +++ b/graphics/java/android/graphics/Paint.java @@ -1168,12 +1168,29 @@ public class Paint { * Get the paint's transfer mode object. * * @return the paint's transfer mode (or null) + * + * @deprecated use {@link #getBlendMode()} instead */ + @Deprecated public Xfermode getXfermode() { return mXfermode; } /** + * Get the paint's blend mode object. + * + * @return the paint's blend mode (or null) + */ + @Nullable + public BlendMode getBlendMode() { + if (mXfermode == null) { + return null; + } else { + return BlendMode.fromValue(mXfermode.porterDuffMode); + } + } + + /** * Set or clear the transfer mode object. A transfer mode defines how * source pixels (generate by a drawing command) are composited with * the destination pixels (content of the render target). @@ -1185,8 +1202,17 @@ public class Paint { * * @param xfermode May be null. The xfermode to be installed in the paint * @return xfermode + * + * @deprecated Use {@link #setBlendMode} to apply a Xfermode directly + * through usage of {@link BlendMode} */ + @Deprecated public Xfermode setXfermode(Xfermode xfermode) { + return installXfermode(xfermode); + } + + @Nullable + private Xfermode installXfermode(Xfermode xfermode) { int newMode = xfermode != null ? xfermode.porterDuffMode : Xfermode.DEFAULT; int curMode = mXfermode != null ? mXfermode.porterDuffMode : Xfermode.DEFAULT; if (newMode != curMode) { @@ -1197,6 +1223,23 @@ public class Paint { } /** + * Set or clear the blend mode. A blend mode defines how source pixels + * (generated by a drawing command) are composited with the destination pixels + * (content of the render target). + * <p /> + * Pass null to clear any previous blend mode. + * As a convenience, the parameter passed is also returned. + * <p /> + * + * @see BlendMode + * + * @param blendmode May be null. The blend mode to be installed in the paint + */ + public void setBlendMode(@Nullable BlendMode blendmode) { + installXfermode(blendmode != null ? blendmode.getXfermode() : null); + } + + /** * Get the paint's patheffect object. * * @return the paint's patheffect (or null) diff --git a/graphics/java/android/graphics/PorterDuffColorFilter.java b/graphics/java/android/graphics/PorterDuffColorFilter.java index 6665220c293c..c2a8eb7dbab1 100644 --- a/graphics/java/android/graphics/PorterDuffColorFilter.java +++ b/graphics/java/android/graphics/PorterDuffColorFilter.java @@ -23,7 +23,11 @@ import android.annotation.UnsupportedAppUsage; /** * A color filter that can be used to tint the source pixels using a single * color and a specific {@link PorterDuff Porter-Duff composite mode}. + * + * @deprecated Consider using {@link BlendModeColorFilter} instead as it supports a wider + * set of blend modes than those defined in {@link PorterDuff.Mode} */ +@Deprecated public class PorterDuffColorFilter extends ColorFilter { @ColorInt private int mColor; @@ -71,7 +75,7 @@ public class PorterDuffColorFilter extends ColorFilter { @Override long createNativeInstance() { - return native_CreatePorterDuffFilter(mColor, mMode.nativeInt); + return native_CreateBlendModeFilter(mColor, mMode.nativeInt); } @Override @@ -91,5 +95,5 @@ public class PorterDuffColorFilter extends ColorFilter { return 31 * mMode.hashCode() + mColor; } - private static native long native_CreatePorterDuffFilter(int srcColor, int porterDuffMode); + private static native long native_CreateBlendModeFilter(int srcColor, int blendmode); } diff --git a/graphics/java/android/graphics/drawable/Drawable.java b/graphics/java/android/graphics/drawable/Drawable.java index caf610b8c236..a5482650c0e7 100644 --- a/graphics/java/android/graphics/drawable/Drawable.java +++ b/graphics/java/android/graphics/drawable/Drawable.java @@ -595,7 +595,12 @@ public abstract class Drawable { * <p class="note"><strong>Note:</strong> Setting a color filter disables * {@link #setTintList(ColorStateList) tint}. * </p> + * + * @see {@link #setColorFilter(ColorFilter)} } + * @deprecated use {@link #setColorFilter(ColorFilter)} with an instance + * of {@link android.graphics.BlendModeColorFilter} */ + @Deprecated public void setColorFilter(@ColorInt int color, @NonNull PorterDuff.Mode mode) { if (getColorFilter() instanceof PorterDuffColorFilter) { PorterDuffColorFilter existing = (PorterDuffColorFilter) getColorFilter(); |