diff options
Diffstat (limited to 'graphics/java')
31 files changed, 533 insertions, 271 deletions
diff --git a/graphics/java/android/graphics/BaseCanvas.java b/graphics/java/android/graphics/BaseCanvas.java index fd3773588299..c9431e3178f0 100644 --- a/graphics/java/android/graphics/BaseCanvas.java +++ b/graphics/java/android/graphics/BaseCanvas.java @@ -112,14 +112,14 @@ public abstract class BaseCanvas { public void drawBitmap(@NonNull Bitmap bitmap, float left, float top, @Nullable Paint paint) { throwIfCannotDraw(bitmap); throwIfHasHwBitmapInSwMode(paint); - nDrawBitmap(mNativeCanvasWrapper, bitmap, left, top, + nDrawBitmap(mNativeCanvasWrapper, bitmap.getNativeInstance(), left, top, paint != null ? paint.getNativeInstance() : 0, mDensity, mScreenDensity, bitmap.mDensity); } public void drawBitmap(@NonNull Bitmap bitmap, @NonNull Matrix matrix, @Nullable Paint paint) { throwIfHasHwBitmapInSwMode(paint); - nDrawBitmapMatrix(mNativeCanvasWrapper, bitmap, matrix.ni(), + nDrawBitmapMatrix(mNativeCanvasWrapper, bitmap.getNativeInstance(), matrix.ni(), paint != null ? paint.getNativeInstance() : 0); } @@ -144,7 +144,7 @@ public abstract class BaseCanvas { bottom = src.bottom; } - nDrawBitmap(mNativeCanvasWrapper, bitmap, left, top, right, bottom, + nDrawBitmap(mNativeCanvasWrapper, bitmap.getNativeInstance(), left, top, right, bottom, dst.left, dst.top, dst.right, dst.bottom, nativePaint, mScreenDensity, bitmap.mDensity); } @@ -170,7 +170,7 @@ public abstract class BaseCanvas { bottom = src.bottom; } - nDrawBitmap(mNativeCanvasWrapper, bitmap, left, top, right, bottom, + nDrawBitmap(mNativeCanvasWrapper, bitmap.getNativeInstance(), left, top, right, bottom, dst.left, dst.top, dst.right, dst.bottom, nativePaint, mScreenDensity, bitmap.mDensity); } @@ -229,7 +229,7 @@ public abstract class BaseCanvas { // no mul by 2, since we need only 1 color per vertex checkRange(colors.length, colorOffset, count); } - nDrawBitmapMesh(mNativeCanvasWrapper, bitmap, meshWidth, meshHeight, + nDrawBitmapMesh(mNativeCanvasWrapper, bitmap.getNativeInstance(), meshWidth, meshHeight, verts, vertOffset, colors, colorOffset, paint != null ? paint.getNativeInstance() : 0); } @@ -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); } /** @@ -664,10 +664,11 @@ public abstract class BaseCanvas { } } - private static native void nDrawBitmap(long nativeCanvas, Bitmap bitmap, float left, float top, - long nativePaintOrZero, int canvasDensity, int screenDensity, int bitmapDensity); + private static native void nDrawBitmap(long nativeCanvas, long bitmapHandle, float left, + float top, long nativePaintOrZero, int canvasDensity, int screenDensity, + int bitmapDensity); - private static native void nDrawBitmap(long nativeCanvas, Bitmap bitmap, float srcLeft, + private static native void nDrawBitmap(long nativeCanvas, long bitmapHandle, float srcLeft, float srcTop, float srcRight, float srcBottom, float dstLeft, float dstTop, float dstRight, float dstBottom, long nativePaintOrZero, int screenDensity, int bitmapDensity); @@ -726,10 +727,10 @@ public abstract class BaseCanvas { float dstLeft, float dstTop, float dstRight, float dstBottom, long nativePaintOrZero, int screenDensity, int bitmapDensity); - private static native void nDrawBitmapMatrix(long nativeCanvas, Bitmap bitmap, + private static native void nDrawBitmapMatrix(long nativeCanvas, long bitmapHandle, long nativeMatrix, long nativePaint); - private static native void nDrawBitmapMesh(long nativeCanvas, Bitmap bitmap, int meshWidth, + private static native void nDrawBitmapMesh(long nativeCanvas, long bitmapHandle, int meshWidth, int meshHeight, float[] verts, int vertOffset, int[] colors, int colorOffset, long nativePaint); diff --git a/graphics/java/android/graphics/BaseRecordingCanvas.java b/graphics/java/android/graphics/BaseRecordingCanvas.java index 3e117411db01..028b784d24c2 100644 --- a/graphics/java/android/graphics/BaseRecordingCanvas.java +++ b/graphics/java/android/graphics/BaseRecordingCanvas.java @@ -67,7 +67,7 @@ public class BaseRecordingCanvas extends Canvas { public final void drawBitmap(@NonNull Bitmap bitmap, float left, float top, @Nullable Paint paint) { throwIfCannotDraw(bitmap); - nDrawBitmap(mNativeCanvasWrapper, bitmap, left, top, + nDrawBitmap(mNativeCanvasWrapper, bitmap.getNativeInstance(), left, top, paint != null ? paint.getNativeInstance() : 0, mDensity, mScreenDensity, bitmap.mDensity); } @@ -75,7 +75,7 @@ public class BaseRecordingCanvas extends Canvas { @Override public final void drawBitmap(@NonNull Bitmap bitmap, @NonNull Matrix matrix, @Nullable Paint paint) { - nDrawBitmapMatrix(mNativeCanvasWrapper, bitmap, matrix.ni(), + nDrawBitmapMatrix(mNativeCanvasWrapper, bitmap.getNativeInstance(), matrix.ni(), paint != null ? paint.getNativeInstance() : 0); } @@ -100,7 +100,7 @@ public class BaseRecordingCanvas extends Canvas { bottom = src.bottom; } - nDrawBitmap(mNativeCanvasWrapper, bitmap, left, top, right, bottom, + nDrawBitmap(mNativeCanvasWrapper, bitmap.getNativeInstance(), left, top, right, bottom, dst.left, dst.top, dst.right, dst.bottom, nativePaint, mScreenDensity, bitmap.mDensity); } @@ -126,7 +126,7 @@ public class BaseRecordingCanvas extends Canvas { bottom = src.bottom; } - nDrawBitmap(mNativeCanvasWrapper, bitmap, left, top, right, bottom, + nDrawBitmap(mNativeCanvasWrapper, bitmap.getNativeInstance(), left, top, right, bottom, dst.left, dst.top, dst.right, dst.bottom, nativePaint, mScreenDensity, bitmap.mDensity); } @@ -188,7 +188,7 @@ public class BaseRecordingCanvas extends Canvas { // no mul by 2, since we need only 1 color per vertex checkRange(colors.length, colorOffset, count); } - nDrawBitmapMesh(mNativeCanvasWrapper, bitmap, meshWidth, meshHeight, + nDrawBitmapMesh(mNativeCanvasWrapper, bitmap.getNativeInstance(), meshWidth, meshHeight, verts, vertOffset, colors, colorOffset, paint != null ? paint.getNativeInstance() : 0); } @@ -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); } /** @@ -581,11 +581,12 @@ public class BaseRecordingCanvas extends Canvas { } @FastNative - private static native void nDrawBitmap(long nativeCanvas, Bitmap bitmap, float left, float top, - long nativePaintOrZero, int canvasDensity, int screenDensity, int bitmapDensity); + private static native void nDrawBitmap(long nativeCanvas, long bitmapHandle, float left, + float top, long nativePaintOrZero, int canvasDensity, int screenDensity, + int bitmapDensity); @FastNative - private static native void nDrawBitmap(long nativeCanvas, Bitmap bitmap, + private static native void nDrawBitmap(long nativeCanvas, long bitmapHandle, float srcLeft, float srcTop, float srcRight, float srcBottom, float dstLeft, float dstTop, float dstRight, float dstBottom, long nativePaintOrZero, int screenDensity, int bitmapDensity); @@ -663,11 +664,11 @@ public class BaseRecordingCanvas extends Canvas { int screenDensity, int bitmapDensity); @FastNative - private static native void nDrawBitmapMatrix(long nativeCanvas, Bitmap bitmap, + private static native void nDrawBitmapMatrix(long nativeCanvas, long bitmapHandle, long nativeMatrix, long nativePaint); @FastNative - private static native void nDrawBitmapMesh(long nativeCanvas, Bitmap bitmap, int meshWidth, + private static native void nDrawBitmapMesh(long nativeCanvas, long bitmapHandle, int meshWidth, int meshHeight, float[] verts, int vertOffset, int[] colors, int colorOffset, long nativePaint); diff --git a/graphics/java/android/graphics/Bitmap.java b/graphics/java/android/graphics/Bitmap.java index 4bd344f1964f..170dec26f361 100644 --- a/graphics/java/android/graphics/Bitmap.java +++ b/graphics/java/android/graphics/Bitmap.java @@ -1813,21 +1813,22 @@ public final class Bitmap implements Parcelable { } /** - * Fills the bitmap's pixels with the specified {@link Color}. + * Fills the bitmap's pixels with the specified {@code ColorLong}. * + * @param color The color to fill as packed by the {@link Color} class. * @throws IllegalStateException if the bitmap is not mutable. - * @throws IllegalArgumentException if the color space encoded in the long - * is invalid or unknown. + * @throws IllegalArgumentException if the color space encoded in the + * {@code ColorLong} is invalid or unknown. * */ - public void eraseColor(@ColorLong long c) { + public void eraseColor(@ColorLong long color) { checkRecycled("Can't erase a recycled bitmap"); if (!isMutable()) { throw new IllegalStateException("cannot erase immutable bitmaps"); } - ColorSpace cs = Color.colorSpace(c); - nativeErase(mNativePtr, cs.getNativeInstance(), c); + ColorSpace cs = Color.colorSpace(color); + nativeErase(mNativePtr, cs.getNativeInstance(), color); } /** diff --git a/graphics/java/android/graphics/BitmapFactory.java b/graphics/java/android/graphics/BitmapFactory.java index 49c3a3ba68b8..5623a8a49b35 100644 --- a/graphics/java/android/graphics/BitmapFactory.java +++ b/graphics/java/android/graphics/BitmapFactory.java @@ -436,9 +436,15 @@ public class BitmapFactory { static void validate(Options opts) { if (opts == null) return; - if (opts.inBitmap != null && opts.inBitmap.getConfig() == Bitmap.Config.HARDWARE) { - throw new IllegalArgumentException( - "Bitmaps with Config.HARDWARE are always immutable"); + if (opts.inBitmap != null) { + if (opts.inBitmap.getConfig() == Bitmap.Config.HARDWARE) { + throw new IllegalArgumentException( + "Bitmaps with Config.HARDWARE are always immutable"); + } + if (opts.inBitmap.isRecycled()) { + throw new IllegalArgumentException( + "Cannot reuse a recycled Bitmap"); + } } if (opts.inMutable && opts.inPreferredConfig == Bitmap.Config.HARDWARE) { @@ -459,6 +465,17 @@ public class BitmapFactory { } /** + * Helper for passing inBitmap's native pointer to native. + */ + static long nativeInBitmap(Options opts) { + if (opts == null || opts.inBitmap == null) { + return 0; + } + + return opts.inBitmap.getNativeInstance(); + } + + /** * Helper for passing SkColorSpace pointer to native. * * @throws IllegalArgumentException if the ColorSpace is not Rgb or does @@ -646,6 +663,7 @@ public class BitmapFactory { Trace.traceBegin(Trace.TRACE_TAG_GRAPHICS, "decodeBitmap"); try { bm = nativeDecodeByteArray(data, offset, length, opts, + Options.nativeInBitmap(opts), Options.nativeColorSpace(opts)); if (bm == null && opts != null && opts.inBitmap != null) { @@ -741,7 +759,8 @@ public class BitmapFactory { try { if (is instanceof AssetManager.AssetInputStream) { final long asset = ((AssetManager.AssetInputStream) is).getNativeAsset(); - bm = nativeDecodeAsset(asset, outPadding, opts, Options.nativeColorSpace(opts)); + bm = nativeDecodeAsset(asset, outPadding, opts, Options.nativeInBitmap(opts), + Options.nativeColorSpace(opts)); } else { bm = decodeStreamInternal(is, outPadding, opts); } @@ -769,6 +788,7 @@ public class BitmapFactory { if (opts != null) tempStorage = opts.inTempStorage; if (tempStorage == null) tempStorage = new byte[DECODE_BUFFER_SIZE]; return nativeDecodeStream(is, tempStorage, outPadding, opts, + Options.nativeInBitmap(opts), Options.nativeColorSpace(opts)); } @@ -813,6 +833,7 @@ public class BitmapFactory { try { if (nativeIsSeekable(fd)) { bm = nativeDecodeFileDescriptor(fd, outPadding, opts, + Options.nativeInBitmap(opts), Options.nativeColorSpace(opts)); } else { FileInputStream fis = new FileInputStream(fd); @@ -850,15 +871,15 @@ public class BitmapFactory { @UnsupportedAppUsage private static native Bitmap nativeDecodeStream(InputStream is, byte[] storage, - Rect padding, Options opts, long colorSpaceHandle); + Rect padding, Options opts, long inBitmapHandle, long colorSpaceHandle); @UnsupportedAppUsage private static native Bitmap nativeDecodeFileDescriptor(FileDescriptor fd, - Rect padding, Options opts, long colorSpaceHandle); + Rect padding, Options opts, long inBitmapHandle, long colorSpaceHandle); @UnsupportedAppUsage private static native Bitmap nativeDecodeAsset(long nativeAsset, Rect padding, Options opts, - long colorSpaceHandle); + long inBitmapHandle, long colorSpaceHandle); @UnsupportedAppUsage private static native Bitmap nativeDecodeByteArray(byte[] data, int offset, - int length, Options opts, long colorSpaceHandle); + int length, Options opts, long inBitmapHandle, long colorSpaceHandle); private static native boolean nativeIsSeekable(FileDescriptor fd); } diff --git a/graphics/java/android/graphics/BitmapRegionDecoder.java b/graphics/java/android/graphics/BitmapRegionDecoder.java index 1410423eafac..629d8c131b68 100644 --- a/graphics/java/android/graphics/BitmapRegionDecoder.java +++ b/graphics/java/android/graphics/BitmapRegionDecoder.java @@ -196,6 +196,7 @@ public final class BitmapRegionDecoder { throw new IllegalArgumentException("rectangle is outside the image"); return nativeDecodeRegion(mNativeBitmapRegionDecoder, rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top, options, + BitmapFactory.Options.nativeInBitmap(options), BitmapFactory.Options.nativeColorSpace(options)); } } @@ -266,7 +267,8 @@ public final class BitmapRegionDecoder { private static native Bitmap nativeDecodeRegion(long lbm, int start_x, int start_y, int width, int height, - BitmapFactory.Options options, long colorSpaceHandle); + BitmapFactory.Options options, long inBitmapHandle, + long colorSpaceHandle); private static native int nativeGetWidth(long lbm); private static native int nativeGetHeight(long lbm); private static native void nativeClean(long lbm); diff --git a/graphics/java/android/graphics/BitmapShader.java b/graphics/java/android/graphics/BitmapShader.java index eb0f2e1e18f2..198d1e7bc956 100644 --- a/graphics/java/android/graphics/BitmapShader.java +++ b/graphics/java/android/graphics/BitmapShader.java @@ -62,9 +62,9 @@ public class BitmapShader extends Shader { @Override long createNativeInstance(long nativeMatrix) { - return nativeCreate(nativeMatrix, mBitmap, mTileX, mTileY); + return nativeCreate(nativeMatrix, mBitmap.getNativeInstance(), mTileX, mTileY); } - private static native long nativeCreate(long nativeMatrix, Bitmap bitmap, + private static native long nativeCreate(long nativeMatrix, long bitmapHandle, int shaderTileModeX, int shaderTileModeY); } diff --git a/graphics/java/android/graphics/BlendMode.java b/graphics/java/android/graphics/BlendMode.java index 39392c89d170..0b267048d976 100644 --- a/graphics/java/android/graphics/BlendMode.java +++ b/graphics/java/android/graphics/BlendMode.java @@ -454,6 +454,64 @@ public enum BlendMode { return null; } + /** + * @hide + */ + public static int toValue(BlendMode mode) { + return mode.getXfermode().porterDuffMode; + } + + /** + * @hide + */ + public static @Nullable PorterDuff.Mode blendModeToPorterDuffMode(@Nullable BlendMode mode) { + if (mode != null) { + switch (mode) { + case CLEAR: + return PorterDuff.Mode.CLEAR; + case SRC: + return PorterDuff.Mode.SRC; + case DST: + return PorterDuff.Mode.DST; + case SRC_OVER: + return PorterDuff.Mode.SRC_OVER; + case DST_OVER: + return PorterDuff.Mode.DST_OVER; + case SRC_IN: + return PorterDuff.Mode.SRC_IN; + case DST_IN: + return PorterDuff.Mode.DST_IN; + case SRC_OUT: + return PorterDuff.Mode.SRC_OUT; + case DST_OUT: + return PorterDuff.Mode.DST_OUT; + case SRC_ATOP: + return PorterDuff.Mode.SRC_ATOP; + case DST_ATOP: + return PorterDuff.Mode.DST_ATOP; + case XOR: + return PorterDuff.Mode.XOR; + case DARKEN: + return PorterDuff.Mode.DARKEN; + case LIGHTEN: + return PorterDuff.Mode.LIGHTEN; + // b/73224934 PorterDuff Multiply maps to Skia Modulate + case MODULATE: + return PorterDuff.Mode.MULTIPLY; + case SCREEN: + return PorterDuff.Mode.SCREEN; + case PLUS: + return PorterDuff.Mode.ADD; + case OVERLAY: + return PorterDuff.Mode.OVERLAY; + default: + return null; + } + } else { + return null; + } + } + @NonNull private final Xfermode mXfermode; diff --git a/graphics/java/android/graphics/Canvas.java b/graphics/java/android/graphics/Canvas.java index 7b3f3da111d5..6f00fc907849 100644 --- a/graphics/java/android/graphics/Canvas.java +++ b/graphics/java/android/graphics/Canvas.java @@ -95,7 +95,7 @@ public class Canvas extends BaseCanvas { public Canvas() { if (!isHardwareAccelerated()) { // 0 means no native bitmap - mNativeCanvasWrapper = nInitRaster(null); + mNativeCanvasWrapper = nInitRaster(0); mFinalizer = NoImagePreloadHolder.sRegistry.registerNativeAllocation( this, mNativeCanvasWrapper); } else { @@ -117,7 +117,7 @@ public class Canvas extends BaseCanvas { throw new IllegalStateException("Immutable bitmap passed to Canvas constructor"); } throwIfCannotDraw(bitmap); - mNativeCanvasWrapper = nInitRaster(bitmap); + mNativeCanvasWrapper = nInitRaster(bitmap.getNativeInstance()); mFinalizer = NoImagePreloadHolder.sRegistry.registerNativeAllocation( this, mNativeCanvasWrapper); mBitmap = bitmap; @@ -185,7 +185,7 @@ public class Canvas extends BaseCanvas { } if (bitmap == null) { - nSetBitmap(mNativeCanvasWrapper, null); + nSetBitmap(mNativeCanvasWrapper, 0); mDensity = Bitmap.DENSITY_NONE; } else { if (!bitmap.isMutable()) { @@ -193,7 +193,7 @@ public class Canvas extends BaseCanvas { } throwIfCannotDraw(bitmap); - nSetBitmap(mNativeCanvasWrapper, bitmap); + nSetBitmap(mNativeCanvasWrapper, bitmap.getNativeInstance()); mDensity = bitmap.mDensity; } @@ -1364,14 +1364,16 @@ public class Canvas extends BaseCanvas { private static native void nFreeCaches(); private static native void nFreeTextLayoutCaches(); - private static native long nInitRaster(Bitmap bitmap); private static native long nGetNativeFinalizer(); private static native void nSetCompatibilityVersion(int apiLevel); // ---------------- @FastNative ------------------- @FastNative - private static native void nSetBitmap(long canvasHandle, Bitmap bitmap); + private static native long nInitRaster(long bitmapHandle); + + @FastNative + private static native void nSetBitmap(long canvasHandle, long bitmapHandle); @FastNative private static native boolean nGetClipBounds(long nativeCanvas, Rect bounds); @@ -1683,8 +1685,9 @@ public class Canvas extends BaseCanvas { * Fill the entire canvas' bitmap (restricted to the current clip) with the specified color, * using srcover porterduff mode. * - * @param color the color to draw onto the canvas - * @throws IllegalArgumentException if the color space encoded in the long + * @param color the {@code ColorLong} to draw onto the canvas. See the {@link Color} + * class for details about {@code ColorLong}s. + * @throws IllegalArgumentException if the color space encoded in the {@code ColorLong} * is invalid or unknown. */ public void drawColor(@ColorLong long color) { @@ -1695,7 +1698,7 @@ public class Canvas extends BaseCanvas { * Fill the entire canvas' bitmap (restricted to the current clip) with the specified color and * porter-duff xfermode. * - * @param color the color to draw with + * @param color the color to draw onto the canvas * @param mode the porter-duff mode to apply to the color * * @deprecated use {@link #drawColor(int, BlendMode)} instead @@ -1709,7 +1712,7 @@ public class Canvas extends BaseCanvas { * Fill the entire canvas' bitmap (restricted to the current clip) with the specified color and * blendmode. * - * @param color the color to draw with + * @param color the color to draw onto the canvas * @param mode the blendmode to apply to the color */ public void drawColor(@ColorInt int color, @NonNull BlendMode mode) { @@ -1720,9 +1723,10 @@ public class Canvas extends BaseCanvas { * Fill the entire canvas' bitmap (restricted to the current clip) with the specified color and * blendmode. * - * @param color the color to draw with + * @param color the {@code ColorLong} to draw onto the canvas. See the {@link Color} + * class for details about {@code ColorLong}s. * @param mode the blendmode to apply to the color - * @throws IllegalArgumentException if the color space encoded in the long + * @throws IllegalArgumentException if the color space encoded in the {@code ColorLong} * is invalid or unknown. */ public void drawColor(@ColorLong long color, @NonNull BlendMode mode) { diff --git a/graphics/java/android/graphics/ComposeShader.java b/graphics/java/android/graphics/ComposeShader.java index 189e1746e644..93ddb10d24bc 100644 --- a/graphics/java/android/graphics/ComposeShader.java +++ b/graphics/java/android/graphics/ComposeShader.java @@ -39,7 +39,10 @@ public class ComposeShader extends Shader { * @param shaderB The colors from this shader are seen as the "src" by the mode * @param mode The mode that combines the colors from the two shaders. If mode * is null, then SRC_OVER is assumed. + * + * @deprecated use {@link #ComposeShader(Shader, Shader, BlendMode)} instead */ + @Deprecated public ComposeShader(@NonNull Shader shaderA, @NonNull Shader shaderB, @NonNull Xfermode mode) { this(shaderA, shaderB, mode.porterDuffMode); } @@ -52,12 +55,29 @@ public class ComposeShader extends Shader { * @param shaderA The colors from this shader are seen as the "dst" by the mode * @param shaderB The colors from this shader are seen as the "src" by the mode * @param mode The PorterDuff mode that combines the colors from the two shaders. - */ + * + * @deprecated use {@link #ComposeShader(Shader, Shader, BlendMode)} instead + */ + @Deprecated public ComposeShader(@NonNull Shader shaderA, @NonNull Shader shaderB, @NonNull PorterDuff.Mode mode) { this(shaderA, shaderB, mode.nativeInt); } + /** + * Create a new compose shader, given shaders A, B, and a combining PorterDuff mode. + * When the mode is applied, it will be given the result from shader A as its + * "dst", and the result from shader B as its "src". + * + * @param shaderA The colors from this shader are seen as the "dst" by the mode + * @param shaderB The colors from this shader are seen as the "src" by the mode + * @param blendMode The blend mode that combines the colors from the two shaders. + */ + public ComposeShader(@NonNull Shader shaderA, @NonNull Shader shaderB, + @NonNull BlendMode blendMode) { + this(shaderA, shaderB, blendMode.getXfermode().porterDuffMode); + } + private ComposeShader(Shader shaderA, Shader shaderB, int nativeMode) { if (shaderA == null || shaderB == null) { throw new IllegalArgumentException("Shader parameters must not be null"); diff --git a/graphics/java/android/graphics/HardwareRenderer.java b/graphics/java/android/graphics/HardwareRenderer.java index bc744cc7af3d..b6b2d4e1c46a 100644 --- a/graphics/java/android/graphics/HardwareRenderer.java +++ b/graphics/java/android/graphics/HardwareRenderer.java @@ -682,8 +682,8 @@ public class HardwareRenderer { /** @hide */ public boolean copyLayerInto(final TextureLayer layer, final Bitmap bitmap) { - return nCopyLayerInto(mNativeProxy, - layer.getDeferredLayerUpdater(), bitmap); + return nCopyLayerInto(mNativeProxy, layer.getDeferredLayerUpdater(), + bitmap.getNativeInstance()); } /** @@ -910,10 +910,10 @@ public class HardwareRenderer { public static int copySurfaceInto(Surface surface, Rect srcRect, Bitmap bitmap) { if (srcRect == null) { // Empty rect means entire surface - return nCopySurfaceInto(surface, 0, 0, 0, 0, bitmap); + return nCopySurfaceInto(surface, 0, 0, 0, 0, bitmap.getNativeInstance()); } else { return nCopySurfaceInto(surface, srcRect.left, srcRect.top, - srcRect.right, srcRect.bottom, bitmap); + srcRect.right, srcRect.bottom, bitmap.getNativeInstance()); } } @@ -1115,7 +1115,7 @@ public class HardwareRenderer { private static native void nBuildLayer(long nativeProxy, long node); - private static native boolean nCopyLayerInto(long nativeProxy, long layer, Bitmap bitmap); + private static native boolean nCopyLayerInto(long nativeProxy, long layer, long bitmapHandle); private static native void nPushLayerUpdate(long nativeProxy, long layer); @@ -1162,7 +1162,7 @@ public class HardwareRenderer { private static native void nRemoveFrameMetricsObserver(long nativeProxy, long nativeObserver); private static native int nCopySurfaceInto(Surface surface, - int srcLeft, int srcTop, int srcRight, int srcBottom, Bitmap bitmap); + int srcLeft, int srcTop, int srcRight, int srcBottom, long bitmapHandle); private static native Bitmap nCreateHardwareBitmap(long renderNode, int width, int height); diff --git a/graphics/java/android/graphics/NinePatch.java b/graphics/java/android/graphics/NinePatch.java index 800247af4927..c4c1eaceb4fc 100644 --- a/graphics/java/android/graphics/NinePatch.java +++ b/graphics/java/android/graphics/NinePatch.java @@ -261,7 +261,8 @@ public class NinePatch { * that are transparent. */ public final Region getTransparentRegion(Rect bounds) { - long r = nativeGetTransparentRegion(mBitmap, mNativeChunk, bounds); + long r = nativeGetTransparentRegion(mBitmap.getNativeInstance(), + mNativeChunk, bounds); return r != 0 ? new Region(r) : null; } @@ -282,5 +283,6 @@ public class NinePatch { */ private static native long validateNinePatchChunk(byte[] chunk); private static native void nativeFinalize(long chunk); - private static native long nativeGetTransparentRegion(Bitmap bitmap, long chunk, Rect location); + private static native long nativeGetTransparentRegion(long bitmapHandle, long chunk, + Rect location); } diff --git a/graphics/java/android/graphics/Paint.java b/graphics/java/android/graphics/Paint.java index c48546103a6f..db5f06524c18 100644 --- a/graphics/java/android/graphics/Paint.java +++ b/graphics/java/android/graphics/Paint.java @@ -1029,9 +1029,8 @@ public class Paint { * premultiplied, meaning that alpha can be any value, regardless of the * values of r,g,b. See the {@link Color} class for more details. * - * @see Color for APIs that help manipulate a color long. - * - * @return the paint's color (and alpha). + * @return the paint's color, alpha, and {@code ColorSpace} encoded as a + * {@code ColorLong} */ @ColorLong public long getColorLong() { @@ -1052,7 +1051,7 @@ public class Paint { } /** - * Set the paint's color with a {@link ColorLong}. Note that the color is + * Set the paint's color with a {@code ColorLong}. Note that the color is * a long with an encoded {@link ColorSpace} as well as alpha and r,g,b. * These values are not premultiplied, meaning that alpha can be any value, * regardless of the values of r,g,b. See the {@link Color} class for more @@ -1060,8 +1059,8 @@ public class Paint { * * @param color The new color (including alpha and {@link ColorSpace}) * to set in the paint. - * @throws IllegalArgumentException if the color space encoded in the long - * is invalid or unknown. + * @throws IllegalArgumentException if the color space encoded in the + * {@code ColorLong} is invalid or unknown. */ public void setColor(@ColorLong long color) { ColorSpace cs = Color.colorSpace(color); @@ -1491,8 +1490,8 @@ public class Paint { * The alpha of the shadow will be the paint's alpha if the shadow color is * opaque, or the alpha from the shadow color if not. * - * @throws IllegalArgumentException if the color space encoded in the long - * is invalid or unknown. + * @throws IllegalArgumentException if the color space encoded in the + * {@code ColorLong} is invalid or unknown. */ public void setShadowLayer(float radius, float dx, float dy, @ColorLong long shadowColor) { ColorSpace cs = Color.colorSpace(shadowColor); @@ -1559,8 +1558,11 @@ public class Paint { /** * Returns the color of the shadow layer. + * + * @return the shadow layer's color encoded as a {@link ColorLong}. * @see #setShadowLayer(float,float,float,int) * @see #setShadowLayer(float,float,float,long) + * @see Color */ public @ColorLong long getShadowLayerColorLong() { return mShadowLayerColor; diff --git a/graphics/java/android/graphics/PorterDuff.java b/graphics/java/android/graphics/PorterDuff.java index fba50430f2ef..459291b7565e 100644 --- a/graphics/java/android/graphics/PorterDuff.java +++ b/graphics/java/android/graphics/PorterDuff.java @@ -23,7 +23,10 @@ import android.annotation.UnsupportedAppUsage; * that can be passed to {@link PorterDuffXfermode}, a specialized implementation * of {@link Paint}'s {@link Paint#setXfermode(Xfermode) transfer mode}. * All the available modes can be found in the {@link Mode} enum.</p> + * + * @deprecated Use {@link BlendMode} with {@link Paint#setBlendMode(BlendMode)} instead */ +@Deprecated public class PorterDuff { /** * {@usesMathJax} diff --git a/graphics/java/android/graphics/PorterDuffXfermode.java b/graphics/java/android/graphics/PorterDuffXfermode.java index 84d953de91db..5b933c493162 100644 --- a/graphics/java/android/graphics/PorterDuffXfermode.java +++ b/graphics/java/android/graphics/PorterDuffXfermode.java @@ -21,6 +21,11 @@ package android.graphics; * {@link Paint#setXfermode(Xfermode) transfer mode}. Refer to the * documentation of the {@link PorterDuff.Mode} enum for more * information on the available alpha compositing and blending modes.</p> + * + * @deprecated Consider using {@link BlendMode} instead as it supports a wider + * set of blend modes than those defined in {@link PorterDuff.Mode} + * + * @see Paint#setBlendMode(BlendMode) */ public class PorterDuffXfermode extends Xfermode { /** diff --git a/graphics/java/android/graphics/RenderNode.java b/graphics/java/android/graphics/RenderNode.java index 9b4f2c1b51d5..ae7fe6c46f2f 100644 --- a/graphics/java/android/graphics/RenderNode.java +++ b/graphics/java/android/graphics/RenderNode.java @@ -284,9 +284,10 @@ public final class RenderNode { private static final class CompositePositionUpdateListener implements PositionUpdateListener { private final PositionUpdateListener[] mListeners; + private static final PositionUpdateListener[] sEmpty = new PositionUpdateListener[0]; CompositePositionUpdateListener(PositionUpdateListener... listeners) { - mListeners = listeners; + mListeners = listeners != null ? listeners : sEmpty; } public CompositePositionUpdateListener with(PositionUpdateListener listener) { diff --git a/graphics/java/android/graphics/drawable/AdaptiveIconDrawable.java b/graphics/java/android/graphics/drawable/AdaptiveIconDrawable.java index cb12a7c6ba6b..7def322c1953 100644 --- a/graphics/java/android/graphics/drawable/AdaptiveIconDrawable.java +++ b/graphics/java/android/graphics/drawable/AdaptiveIconDrawable.java @@ -27,6 +27,7 @@ import android.content.res.Resources.Theme; import android.content.res.TypedArray; import android.graphics.Bitmap; import android.graphics.BitmapShader; +import android.graphics.BlendMode; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.ColorFilter; @@ -35,7 +36,6 @@ import android.graphics.Outline; import android.graphics.Paint; import android.graphics.Path; import android.graphics.PixelFormat; -import android.graphics.PorterDuff.Mode; import android.graphics.Rect; import android.graphics.Region; import android.graphics.Shader; @@ -701,13 +701,13 @@ public class AdaptiveIconDrawable extends Drawable implements Drawable.Callback } @Override - public void setTintMode(Mode tintMode) { + public void setTintMode(@NonNull BlendMode blendMode) { final ChildDrawable[] array = mLayerState.mChildren; final int N = mLayerState.N_CHILDREN; for (int i = 0; i < N; i++) { final Drawable dr = array[i].mDrawable; if (dr != null) { - dr.setTintMode(tintMode); + dr.setTintMode(blendMode); } } } diff --git a/graphics/java/android/graphics/drawable/AnimatedVectorDrawable.java b/graphics/java/android/graphics/drawable/AnimatedVectorDrawable.java index d9dab98c2be1..f45bf9b783e8 100644 --- a/graphics/java/android/graphics/drawable/AnimatedVectorDrawable.java +++ b/graphics/java/android/graphics/drawable/AnimatedVectorDrawable.java @@ -33,12 +33,12 @@ import android.content.res.ColorStateList; import android.content.res.Resources; import android.content.res.Resources.Theme; import android.content.res.TypedArray; +import android.graphics.BlendMode; import android.graphics.Canvas; import android.graphics.ColorFilter; import android.graphics.Insets; import android.graphics.Outline; import android.graphics.PixelFormat; -import android.graphics.PorterDuff; import android.graphics.RecordingCanvas; import android.graphics.Rect; import android.graphics.RenderNode; @@ -477,8 +477,8 @@ public class AnimatedVectorDrawable extends Drawable implements Animatable2 { } @Override - public void setTintMode(PorterDuff.Mode tintMode) { - mAnimatedVectorState.mVectorDrawable.setTintMode(tintMode); + public void setTintMode(@NonNull BlendMode blendMode) { + mAnimatedVectorState.mVectorDrawable.setTintMode(blendMode); } @Override diff --git a/graphics/java/android/graphics/drawable/BitmapDrawable.java b/graphics/java/android/graphics/drawable/BitmapDrawable.java index 976190109e7c..6b30158a183a 100644 --- a/graphics/java/android/graphics/drawable/BitmapDrawable.java +++ b/graphics/java/android/graphics/drawable/BitmapDrawable.java @@ -25,6 +25,8 @@ import android.content.res.Resources.Theme; import android.content.res.TypedArray; import android.graphics.Bitmap; import android.graphics.BitmapShader; +import android.graphics.BlendMode; +import android.graphics.BlendModeColorFilter; import android.graphics.Canvas; import android.graphics.ColorFilter; import android.graphics.ImageDecoder; @@ -33,9 +35,7 @@ import android.graphics.Matrix; import android.graphics.Outline; import android.graphics.Paint; import android.graphics.PixelFormat; -import android.graphics.PorterDuff; import android.graphics.PorterDuff.Mode; -import android.graphics.PorterDuffColorFilter; import android.graphics.Rect; import android.graphics.Shader; import android.graphics.Xfermode; @@ -90,7 +90,7 @@ public class BitmapDrawable extends Drawable { @UnsupportedAppUsage private BitmapState mBitmapState; - private PorterDuffColorFilter mTintFilter; + private BlendModeColorFilter mBlendModeFilter; @UnsupportedAppUsage private int mTargetDensity = DisplayMetrics.DENSITY_DEFAULT; @@ -527,8 +527,8 @@ public class BitmapDrawable extends Drawable { } final boolean clearColorFilter; - if (mTintFilter != null && paint.getColorFilter() == null) { - paint.setColorFilter(mTintFilter); + if (mBlendModeFilter != null && paint.getColorFilter() == null) { + paint.setColorFilter(mBlendModeFilter); clearColorFilter = true; } else { clearColorFilter = false; @@ -678,17 +678,19 @@ public class BitmapDrawable extends Drawable { final BitmapState state = mBitmapState; if (state.mTint != tint) { state.mTint = tint; - mTintFilter = updateTintFilter(mTintFilter, tint, mBitmapState.mTintMode); + mBlendModeFilter = updateBlendModeFilter(mBlendModeFilter, tint, + mBitmapState.mBlendMode); invalidateSelf(); } } @Override - public void setTintMode(PorterDuff.Mode tintMode) { + public void setTintMode(@NonNull BlendMode blendMode) { final BitmapState state = mBitmapState; - if (state.mTintMode != tintMode) { - state.mTintMode = tintMode; - mTintFilter = updateTintFilter(mTintFilter, mBitmapState.mTint, tintMode); + if (state.mBlendMode != blendMode) { + state.mBlendMode = blendMode; + mBlendModeFilter = updateBlendModeFilter(mBlendModeFilter, mBitmapState.mTint, + blendMode); invalidateSelf(); } } @@ -706,7 +708,7 @@ public class BitmapDrawable extends Drawable { */ @UnsupportedAppUsage public Mode getTintMode() { - return mBitmapState.mTintMode; + return BlendMode.blendModeToPorterDuffMode(mBitmapState.mBlendMode); } /** @@ -744,8 +746,9 @@ public class BitmapDrawable extends Drawable { @Override protected boolean onStateChange(int[] stateSet) { final BitmapState state = mBitmapState; - if (state.mTint != null && state.mTintMode != null) { - mTintFilter = updateTintFilter(mTintFilter, state.mTint, state.mTintMode); + if (state.mTint != null && state.mBlendMode != null) { + mBlendModeFilter = updateBlendModeFilter(mBlendModeFilter, state.mTint, + state.mBlendMode); return true; } return false; @@ -864,7 +867,7 @@ public class BitmapDrawable extends Drawable { final int tintMode = a.getInt(R.styleable.BitmapDrawable_tintMode, -1); if (tintMode != -1) { - state.mTintMode = Drawable.parseTintMode(tintMode, Mode.SRC_IN); + state.mBlendMode = Drawable.parseBlendMode(tintMode, BlendMode.SRC_IN); } final ColorStateList tint = a.getColorStateList(R.styleable.BitmapDrawable_tint); @@ -979,7 +982,8 @@ public class BitmapDrawable extends Drawable { int[] mThemeAttrs = null; Bitmap mBitmap = null; ColorStateList mTint = null; - Mode mTintMode = DEFAULT_TINT_MODE; + BlendMode mBlendMode = DEFAULT_BLEND_MODE; + int mGravity = Gravity.FILL; float mBaseAlpha = 1.0f; Shader.TileMode mTileModeX = null; @@ -1005,7 +1009,7 @@ public class BitmapDrawable extends Drawable { BitmapState(BitmapState bitmapState) { mBitmap = bitmapState.mBitmap; mTint = bitmapState.mTint; - mTintMode = bitmapState.mTintMode; + mBlendMode = bitmapState.mBlendMode; mThemeAttrs = bitmapState.mThemeAttrs; mChangingConfigurations = bitmapState.mChangingConfigurations; mGravity = bitmapState.mGravity; @@ -1065,7 +1069,8 @@ public class BitmapDrawable extends Drawable { */ private void updateLocalState(Resources res) { mTargetDensity = resolveDensity(res, mBitmapState.mTargetDensity); - mTintFilter = updateTintFilter(mTintFilter, mBitmapState.mTint, mBitmapState.mTintMode); + mBlendModeFilter = updateBlendModeFilter(mBlendModeFilter, mBitmapState.mTint, + mBitmapState.mBlendMode); computeBitmapSize(); } } diff --git a/graphics/java/android/graphics/drawable/ColorDrawable.java b/graphics/java/android/graphics/drawable/ColorDrawable.java index 3c449166d9d5..efa806afce70 100644 --- a/graphics/java/android/graphics/drawable/ColorDrawable.java +++ b/graphics/java/android/graphics/drawable/ColorDrawable.java @@ -26,13 +26,13 @@ import android.content.res.ColorStateList; import android.content.res.Resources; import android.content.res.Resources.Theme; import android.content.res.TypedArray; +import android.graphics.BlendMode; +import android.graphics.BlendModeColorFilter; import android.graphics.Canvas; import android.graphics.ColorFilter; import android.graphics.Outline; import android.graphics.Paint; import android.graphics.PixelFormat; -import android.graphics.PorterDuff.Mode; -import android.graphics.PorterDuffColorFilter; import android.graphics.Xfermode; import android.util.AttributeSet; import android.view.ViewDebug; @@ -58,7 +58,7 @@ public class ColorDrawable extends Drawable { @ViewDebug.ExportedProperty(deepExport = true, prefix = "state_") private ColorState mColorState; - private PorterDuffColorFilter mTintFilter; + private BlendModeColorFilter mBlendModeColorFilter; private boolean mMutated; @@ -111,9 +111,10 @@ public class ColorDrawable extends Drawable { @Override public void draw(Canvas canvas) { final ColorFilter colorFilter = mPaint.getColorFilter(); - if ((mColorState.mUseColor >>> 24) != 0 || colorFilter != null || mTintFilter != null) { + if ((mColorState.mUseColor >>> 24) != 0 || colorFilter != null + || mBlendModeColorFilter != null) { if (colorFilter == null) { - mPaint.setColorFilter(mTintFilter); + mPaint.setColorFilter(mBlendModeColorFilter); } mPaint.setColor(mColorState.mUseColor); @@ -208,22 +209,25 @@ public class ColorDrawable extends Drawable { @Override public void setTintList(ColorStateList tint) { mColorState.mTint = tint; - mTintFilter = updateTintFilter(mTintFilter, tint, mColorState.mTintMode); + mBlendModeColorFilter = updateBlendModeFilter(mBlendModeColorFilter, tint, + mColorState.mBlendMode); invalidateSelf(); } @Override - public void setTintMode(Mode tintMode) { - mColorState.mTintMode = tintMode; - mTintFilter = updateTintFilter(mTintFilter, mColorState.mTint, tintMode); + public void setTintMode(@NonNull BlendMode blendMode) { + mColorState.mBlendMode = blendMode; + mBlendModeColorFilter = updateBlendModeFilter(mBlendModeColorFilter, mColorState.mTint, + blendMode); invalidateSelf(); } @Override protected boolean onStateChange(int[] stateSet) { final ColorState state = mColorState; - if (state.mTint != null && state.mTintMode != null) { - mTintFilter = updateTintFilter(mTintFilter, state.mTint, state.mTintMode); + if (state.mTint != null && state.mBlendMode != null) { + mBlendModeColorFilter = updateBlendModeFilter(mBlendModeColorFilter, state.mTint, + state.mBlendMode); return true; } return false; @@ -261,7 +265,7 @@ public class ColorDrawable extends Drawable { @Override public int getOpacity() { - if (mTintFilter != null || mPaint.getColorFilter() != null) { + if (mBlendModeColorFilter != null || mPaint.getColorFilter() != null) { return PixelFormat.TRANSLUCENT; } @@ -348,7 +352,7 @@ public class ColorDrawable extends Drawable { int mUseColor; // basecolor modulated by setAlpha() @Config int mChangingConfigurations; ColorStateList mTint = null; - Mode mTintMode = DEFAULT_TINT_MODE; + BlendMode mBlendMode = DEFAULT_BLEND_MODE; ColorState() { // Empty constructor. @@ -360,7 +364,7 @@ public class ColorDrawable extends Drawable { mUseColor = state.mUseColor; mChangingConfigurations = state.mChangingConfigurations; mTint = state.mTint; - mTintMode = state.mTintMode; + mBlendMode = state.mBlendMode; } @Override @@ -398,6 +402,7 @@ public class ColorDrawable extends Drawable { * after inflating or applying a theme. */ private void updateLocalState(Resources r) { - mTintFilter = updateTintFilter(mTintFilter, mColorState.mTint, mColorState.mTintMode); + mBlendModeColorFilter = updateBlendModeFilter(mBlendModeColorFilter, mColorState.mTint, + mColorState.mBlendMode); } } diff --git a/graphics/java/android/graphics/drawable/ColorStateListDrawable.java b/graphics/java/android/graphics/drawable/ColorStateListDrawable.java index ee4d1e72c130..b94b11468371 100644 --- a/graphics/java/android/graphics/drawable/ColorStateListDrawable.java +++ b/graphics/java/android/graphics/drawable/ColorStateListDrawable.java @@ -21,10 +21,10 @@ import android.annotation.Nullable; import android.content.pm.ActivityInfo; import android.content.res.ColorStateList; import android.content.res.Resources; +import android.graphics.BlendMode; import android.graphics.Canvas; import android.graphics.ColorFilter; import android.graphics.PixelFormat; -import android.graphics.PorterDuff; import android.util.MathUtils; /** @@ -114,9 +114,9 @@ public class ColorStateListDrawable extends Drawable implements Drawable.Callbac } @Override - public void setTintMode(@NonNull PorterDuff.Mode tintMode) { - mState.mTintMode = tintMode; - mColorDrawable.setTintMode(tintMode); + public void setTintMode(@NonNull BlendMode blendMode) { + mState.mBlendMode = blendMode; + mColorDrawable.setTintMode(blendMode); onStateChange(getState()); } @@ -236,7 +236,7 @@ public class ColorStateListDrawable extends Drawable implements Drawable.Callbac ColorStateList mColor = null; ColorStateList mTint = null; int mAlpha = -1; - PorterDuff.Mode mTintMode = DEFAULT_TINT_MODE; + BlendMode mBlendMode = DEFAULT_BLEND_MODE; @ActivityInfo.Config int mChangingConfigurations = 0; ColorStateListDrawableState() { @@ -246,7 +246,7 @@ public class ColorStateListDrawable extends Drawable implements Drawable.Callbac mColor = state.mColor; mTint = state.mTint; mAlpha = state.mAlpha; - mTintMode = state.mTintMode; + mBlendMode = state.mBlendMode; mChangingConfigurations = state.mChangingConfigurations; } @@ -292,8 +292,8 @@ public class ColorStateListDrawable extends Drawable implements Drawable.Callbac mColorDrawable.setTintList(mState.mTint); } - if (mState.mTintMode != DEFAULT_TINT_MODE) { - mColorDrawable.setTintMode(mState.mTintMode); + if (mState.mBlendMode != DEFAULT_BLEND_MODE) { + mColorDrawable.setTintMode(mState.mBlendMode); } } } diff --git a/graphics/java/android/graphics/drawable/Drawable.java b/graphics/java/android/graphics/drawable/Drawable.java index 49d353057d59..adc04fb03e2a 100644 --- a/graphics/java/android/graphics/drawable/Drawable.java +++ b/graphics/java/android/graphics/drawable/Drawable.java @@ -30,6 +30,8 @@ import android.content.res.Resources.Theme; import android.content.res.TypedArray; import android.graphics.Bitmap; import android.graphics.BitmapFactory; +import android.graphics.BlendMode; +import android.graphics.BlendModeColorFilter; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.ColorFilter; @@ -182,6 +184,7 @@ public abstract class Drawable { private static final Rect ZERO_BOUNDS_RECT = new Rect(); static final PorterDuff.Mode DEFAULT_TINT_MODE = PorterDuff.Mode.SRC_IN; + static final BlendMode DEFAULT_BLEND_MODE = BlendMode.SRC_IN; private int[] mStateSet = StateSet.WILD_CARD; private int mLevel = 0; @@ -210,6 +213,24 @@ public abstract class Drawable { protected int mSrcDensityOverride = 0; /** + * Flag used to break the recursive loop between setTintMode(PorterDuff.Mode) and + * setTintMode(BlendMode) as each default implementation invokes the other in order to + * support new use cases that utilize the new blending modes as well as support the legacy + * use cases. This flag tracks that {@link #setTintMode(BlendMode)} is only invoked once + * per invocation. + */ + private boolean mSetBlendModeInvoked = false; + + /** + * Flag used to break the recursive loop between setTintMode(PorterDuff.Mode) and + * setTintMode(BlendMode) as each default implementation invokes the other in order to + * support new use cases that utilize the new blending modes as well as support the legacy + * use cases. This flag tracks that {@link #setTintMode(Mode)} is only invoked once + * per invocation; + */ + private boolean mSetTintModeInvoked = false; + + /** * Draw in its bounds (set via setBounds) respecting optional effects such * as alpha (set via setAlpha) and color filter (set via setColorFilter). * @@ -630,6 +651,7 @@ public abstract class Drawable { * @param tintColor Color to use for tinting this drawable * @see #setTintList(ColorStateList) * @see #setTintMode(PorterDuff.Mode) + * @see #setTintMode(BlendMode) */ public void setTint(@ColorInt int tintColor) { setTintList(ColorStateList.valueOf(tintColor)); @@ -651,6 +673,7 @@ public abstract class Drawable { * {@code null} to clear the tint * @see #setTint(int) * @see #setTintMode(PorterDuff.Mode) + * @see #setTintMode(BlendMode) */ public void setTintList(@Nullable ColorStateList tint) {} @@ -665,11 +688,47 @@ public abstract class Drawable { * {@link #setColorFilter(int, PorterDuff.Mode)} overrides tint. * </p> * - * @param tintMode A Porter-Duff blending mode + * @param tintMode A Porter-Duff blending mode to apply to the drawable, a value of null sets + * the default Porter-Diff blending mode value + * of {@link PorterDuff.Mode#SRC_IN} + * @see #setTint(int) + * @see #setTintList(ColorStateList) + * + * @deprecated use {@link #setTintMode(BlendMode)} instead + */ + @Deprecated + public void setTintMode(@Nullable PorterDuff.Mode tintMode) { + if (!mSetTintModeInvoked) { + mSetTintModeInvoked = true; + BlendMode mode = tintMode != null ? BlendMode.fromValue(tintMode.nativeInt) : null; + setTintMode(mode != null ? mode : Drawable.DEFAULT_BLEND_MODE); + mSetTintModeInvoked = false; + } + } + + /** + * Specifies a tint blending mode for this drawable. + * <p> + * Defines how this drawable's tint color should be blended into the drawable + * before it is drawn to screen. Default tint mode is {@link BlendMode#SRC_IN}. + * </p> + * <p class="note"><strong>Note:</strong> Setting a color filter via + * {@link #setColorFilter(ColorFilter)} + * </p> + * + * @param blendMode BlendMode to apply to the drawable, a value of null sets the default + * blend mode value of {@link BlendMode#SRC_IN} * @see #setTint(int) * @see #setTintList(ColorStateList) */ - public void setTintMode(@NonNull PorterDuff.Mode tintMode) {} + public void setTintMode(@Nullable BlendMode blendMode) { + if (!mSetBlendModeInvoked) { + mSetBlendModeInvoked = true; + PorterDuff.Mode mode = BlendMode.blendModeToPorterDuffMode(blendMode); + setTintMode(mode != null ? mode : Drawable.DEFAULT_TINT_MODE); + mSetBlendModeInvoked = false; + } + } /** * Returns the current color filter, or {@code null} if none set. @@ -1540,6 +1599,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 +1715,26 @@ public abstract class Drawable { default: return defaultMode; } } + + /** + * Parses a {@link android.graphics.BlendMode} from a tintMode + * attribute's enum value. + * + * @hide + */ + @UnsupportedAppUsage + public static BlendMode parseBlendMode(int value, BlendMode defaultMode) { + switch (value) { + case 3: return BlendMode.SRC_OVER; + case 5: return BlendMode.SRC_IN; + case 9: return BlendMode.SRC_ATOP; + // b/73224934 PorterDuff Multiply maps to Skia Modulate so actually + // return BlendMode.MODULATE here + case 14: return BlendMode.MODULATE; + case 15: return BlendMode.SCREEN; + case 16: return BlendMode.PLUS; + default: return defaultMode; + } + } } diff --git a/graphics/java/android/graphics/drawable/DrawableContainer.java b/graphics/java/android/graphics/drawable/DrawableContainer.java index 77e77c49973c..3e0881aef9ed 100644 --- a/graphics/java/android/graphics/drawable/DrawableContainer.java +++ b/graphics/java/android/graphics/drawable/DrawableContainer.java @@ -22,12 +22,12 @@ import android.content.pm.ActivityInfo.Config; import android.content.res.ColorStateList; import android.content.res.Resources; import android.content.res.Resources.Theme; +import android.graphics.BlendMode; import android.graphics.Canvas; import android.graphics.ColorFilter; import android.graphics.Insets; import android.graphics.Outline; import android.graphics.PixelFormat; -import android.graphics.PorterDuff.Mode; import android.graphics.Rect; import android.os.Build; import android.os.SystemClock; @@ -196,14 +196,14 @@ public class DrawableContainer extends Drawable implements Drawable.Callback { } @Override - public void setTintMode(Mode tintMode) { + public void setTintMode(@NonNull BlendMode blendMode) { mDrawableContainerState.mHasTintMode = true; - if (mDrawableContainerState.mTintMode != tintMode) { - mDrawableContainerState.mTintMode = tintMode; + if (mDrawableContainerState.mBlendMode != blendMode) { + mDrawableContainerState.mBlendMode = blendMode; if (mCurrDrawable != null) { - mCurrDrawable.setTintMode(tintMode); + mCurrDrawable.setTintMode(blendMode); } } } @@ -544,7 +544,7 @@ public class DrawableContainer extends Drawable implements Drawable.Callback { d.setTintList(mDrawableContainerState.mTintList); } if (mDrawableContainerState.mHasTintMode) { - d.setTintMode(mDrawableContainerState.mTintMode); + d.setTintMode(mDrawableContainerState.mBlendMode); } } @@ -730,7 +730,7 @@ public class DrawableContainer extends Drawable implements Drawable.Callback { boolean mHasColorFilter; ColorStateList mTintList; - Mode mTintMode; + BlendMode mBlendMode; boolean mHasTintList; boolean mHasTintMode; @@ -762,7 +762,7 @@ public class DrawableContainer extends Drawable implements Drawable.Callback { mColorFilter = orig.mColorFilter; mHasColorFilter = orig.mHasColorFilter; mTintList = orig.mTintList; - mTintMode = orig.mTintMode; + mBlendMode = orig.mBlendMode; mHasTintList = orig.mHasTintList; mHasTintMode = orig.mHasTintMode; diff --git a/graphics/java/android/graphics/drawable/DrawableWrapper.java b/graphics/java/android/graphics/drawable/DrawableWrapper.java index 70c90eb05b17..d81401d451ca 100644 --- a/graphics/java/android/graphics/drawable/DrawableWrapper.java +++ b/graphics/java/android/graphics/drawable/DrawableWrapper.java @@ -24,12 +24,12 @@ import android.content.res.ColorStateList; import android.content.res.Resources; import android.content.res.Resources.Theme; import android.content.res.TypedArray; +import android.graphics.BlendMode; import android.graphics.Canvas; import android.graphics.ColorFilter; import android.graphics.Insets; import android.graphics.Outline; import android.graphics.PixelFormat; -import android.graphics.PorterDuff; import android.graphics.Rect; import android.graphics.Xfermode; import android.util.AttributeSet; @@ -324,9 +324,9 @@ public abstract class DrawableWrapper extends Drawable implements Drawable.Callb } @Override - public void setTintMode(@Nullable PorterDuff.Mode tintMode) { + public void setTintMode(@NonNull BlendMode blendMode) { if (mDrawable != null) { - mDrawable.setTintMode(tintMode); + mDrawable.setTintMode(blendMode); } } diff --git a/graphics/java/android/graphics/drawable/GradientDrawable.java b/graphics/java/android/graphics/drawable/GradientDrawable.java index e58e80225292..6948bc4fd61b 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(); } @@ -1309,6 +1312,10 @@ public class GradientDrawable extends Drawable { y0 = r.top + (r.bottom - r.top) * st.mCenterY; float radius = st.mGradientRadius; + if (Float.compare(radius, 0.0f) == -1 || Float.isNaN(radius)) { + throw new IllegalArgumentException("Gradient radius must be a valid " + + "number greater than or equal to 0"); + } if (st.mGradientRadiusType == RADIUS_TYPE_FRACTION) { // Fall back to parent width or height if intrinsic // size is not specified. @@ -1465,7 +1472,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); @@ -1756,75 +1763,68 @@ public class GradientDrawable extends Drawable { st.mGradientColors[1] = endColor; } - if (st.mGradient == LINEAR_GRADIENT) { - int angle = (int) a.getFloat(R.styleable.GradientDrawableGradient_angle, st.mAngle); - angle %= 360; + int angle = (int) a.getFloat(R.styleable.GradientDrawableGradient_angle, st.mAngle); + angle %= 360; - if (angle % 45 != 0) { - throw new XmlPullParserException(a.getPositionDescription() - + "<gradient> tag requires 'angle' attribute to " - + "be a multiple of 45"); - } + if (angle % 45 != 0) { + throw new XmlPullParserException(a.getPositionDescription() + + "<gradient> tag requires 'angle' attribute to " + + "be a multiple of 45"); + } - st.mAngle = angle; - - switch (angle) { - case 0: - st.mOrientation = Orientation.LEFT_RIGHT; - break; - case 45: - st.mOrientation = Orientation.BL_TR; - break; - case 90: - st.mOrientation = Orientation.BOTTOM_TOP; - break; - case 135: - st.mOrientation = Orientation.BR_TL; - break; - case 180: - st.mOrientation = Orientation.RIGHT_LEFT; - break; - case 225: - st.mOrientation = Orientation.TR_BL; - break; - case 270: - st.mOrientation = Orientation.TOP_BOTTOM; - break; - case 315: - st.mOrientation = Orientation.TL_BR; - break; - } - } else { - final TypedValue tv = a.peekValue(R.styleable.GradientDrawableGradient_gradientRadius); - if (tv != null) { - final float radius; - final @RadiusType int radiusType; - if (tv.type == TypedValue.TYPE_FRACTION) { - radius = tv.getFraction(1.0f, 1.0f); - - final int unit = (tv.data >> TypedValue.COMPLEX_UNIT_SHIFT) - & TypedValue.COMPLEX_UNIT_MASK; - if (unit == TypedValue.COMPLEX_UNIT_FRACTION_PARENT) { - radiusType = RADIUS_TYPE_FRACTION_PARENT; - } else { - radiusType = RADIUS_TYPE_FRACTION; - } - } else if (tv.type == TypedValue.TYPE_DIMENSION) { - radius = tv.getDimension(r.getDisplayMetrics()); - radiusType = RADIUS_TYPE_PIXELS; + st.mAngle = angle; + + switch (angle) { + case 0: + st.mOrientation = Orientation.LEFT_RIGHT; + break; + case 45: + st.mOrientation = Orientation.BL_TR; + break; + case 90: + st.mOrientation = Orientation.BOTTOM_TOP; + break; + case 135: + st.mOrientation = Orientation.BR_TL; + break; + case 180: + st.mOrientation = Orientation.RIGHT_LEFT; + break; + case 225: + st.mOrientation = Orientation.TR_BL; + break; + case 270: + st.mOrientation = Orientation.TOP_BOTTOM; + break; + case 315: + st.mOrientation = Orientation.TL_BR; + break; + } + + final TypedValue tv = a.peekValue(R.styleable.GradientDrawableGradient_gradientRadius); + if (tv != null) { + final float radius; + final @RadiusType int radiusType; + if (tv.type == TypedValue.TYPE_FRACTION) { + radius = tv.getFraction(1.0f, 1.0f); + + final int unit = (tv.data >> TypedValue.COMPLEX_UNIT_SHIFT) + & TypedValue.COMPLEX_UNIT_MASK; + if (unit == TypedValue.COMPLEX_UNIT_FRACTION_PARENT) { + radiusType = RADIUS_TYPE_FRACTION_PARENT; } else { - radius = tv.getFloat(); - radiusType = RADIUS_TYPE_PIXELS; + radiusType = RADIUS_TYPE_FRACTION; } - - st.mGradientRadius = radius; - st.mGradientRadiusType = radiusType; - } else if (st.mGradient == RADIAL_GRADIENT) { - throw new XmlPullParserException( - a.getPositionDescription() - + "<gradient> tag requires 'gradientRadius' " - + "attribute with radial type"); + } else if (tv.type == TypedValue.TYPE_DIMENSION) { + radius = tv.getDimension(r.getDisplayMetrics()); + radiusType = RADIUS_TYPE_PIXELS; + } else { + radius = tv.getFloat(); + radiusType = RADIUS_TYPE_PIXELS; } + + st.mGradientRadius = radius; + st.mGradientRadiusType = radiusType; } } @@ -2010,7 +2010,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 +2068,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 +2355,8 @@ public class GradientDrawable extends Drawable { } } - mTintFilter = updateTintFilter(mTintFilter, state.mTint, state.mTintMode); + mBlendModeColorFilter = updateBlendModeFilter(mBlendModeColorFilter, state.mTint, + state.mBlendMode); mGradientIsDirty = true; state.computeOpacity(); diff --git a/graphics/java/android/graphics/drawable/Icon.java b/graphics/java/android/graphics/drawable/Icon.java index 71dd7a2f4800..5fd18a1431e0 100644 --- a/graphics/java/android/graphics/drawable/Icon.java +++ b/graphics/java/android/graphics/drawable/Icon.java @@ -30,6 +30,7 @@ import android.content.res.ColorStateList; import android.content.res.Resources; import android.graphics.Bitmap; import android.graphics.BitmapFactory; +import android.graphics.BlendMode; import android.graphics.PorterDuff; import android.net.Uri; import android.os.AsyncTask; @@ -105,8 +106,8 @@ public final class Icon implements Parcelable { private final int mType; private ColorStateList mTintList; - static final PorterDuff.Mode DEFAULT_TINT_MODE = Drawable.DEFAULT_TINT_MODE; // SRC_IN - private PorterDuff.Mode mTintMode = DEFAULT_TINT_MODE; + static final BlendMode DEFAULT_BLEND_MODE = Drawable.DEFAULT_BLEND_MODE; // SRC_IN + private BlendMode mBlendMode = Drawable.DEFAULT_BLEND_MODE; // To avoid adding unnecessary overhead, we have a few basic objects that get repurposed // based on the value of mType. @@ -320,10 +321,10 @@ public final class Icon implements Parcelable { */ public Drawable loadDrawable(Context context) { final Drawable result = loadDrawableInner(context); - if (result != null && (mTintList != null || mTintMode != DEFAULT_TINT_MODE)) { + if (result != null && (mTintList != null || mBlendMode != DEFAULT_BLEND_MODE)) { result.mutate(); result.setTintList(mTintList); - result.setTintMode(mTintMode); + result.setTintMode(mBlendMode); } return result; } @@ -695,16 +696,30 @@ public final class Icon implements Parcelable { * * @param mode a blending mode, as in {@link Drawable#setTintMode(PorterDuff.Mode)}, may be null * @return this same object, for use in chained construction + * + * @deprecated use {@link #setTintMode(BlendMode)} instead + */ + @Deprecated + public @NonNull Icon setTintMode(@NonNull PorterDuff.Mode mode) { + mBlendMode = BlendMode.fromValue(mode.nativeInt); + return this; + } + + /** + * Store a blending mode to use whenever this Icon is drawn. + * + * @param mode a blending mode, as in {@link Drawable#setTintMode(PorterDuff.Mode)}, may be null + * @return this same object, for use in chained construction */ - public Icon setTintMode(PorterDuff.Mode mode) { - mTintMode = mode; + public @NonNull Icon setTintMode(@NonNull BlendMode mode) { + mBlendMode = mode; return this; } /** @hide */ @UnsupportedAppUsage public boolean hasTint() { - return (mTintList != null) || (mTintMode != DEFAULT_TINT_MODE); + return (mTintList != null) || (mBlendMode != DEFAULT_BLEND_MODE); } /** @@ -757,7 +772,7 @@ public final class Icon implements Parcelable { sep = "|"; } } - if (mTintMode != DEFAULT_TINT_MODE) sb.append(" mode=").append(mTintMode); + if (mBlendMode != DEFAULT_BLEND_MODE) sb.append(" mode=").append(mBlendMode); sb.append(")"); return sb.toString(); } @@ -807,7 +822,7 @@ public final class Icon implements Parcelable { if (in.readInt() == 1) { mTintList = ColorStateList.CREATOR.createFromParcel(in); } - mTintMode = PorterDuff.intToMode(in.readInt()); + mBlendMode = BlendMode.fromValue(in.readInt()); } @Override @@ -837,7 +852,7 @@ public final class Icon implements Parcelable { dest.writeInt(1); mTintList.writeToParcel(dest, flags); } - dest.writeInt(PorterDuff.modeToInt(mTintMode)); + dest.writeInt(BlendMode.toValue(mBlendMode)); } public static final @android.annotation.NonNull Parcelable.Creator<Icon> CREATOR diff --git a/graphics/java/android/graphics/drawable/LayerDrawable.java b/graphics/java/android/graphics/drawable/LayerDrawable.java index b4392c8d023f..e2c84927b578 100644 --- a/graphics/java/android/graphics/drawable/LayerDrawable.java +++ b/graphics/java/android/graphics/drawable/LayerDrawable.java @@ -24,11 +24,11 @@ import android.content.res.ColorStateList; import android.content.res.Resources; import android.content.res.Resources.Theme; import android.content.res.TypedArray; +import android.graphics.BlendMode; import android.graphics.Canvas; import android.graphics.ColorFilter; import android.graphics.Outline; import android.graphics.PixelFormat; -import android.graphics.PorterDuff.Mode; import android.graphics.Rect; import android.util.AttributeSet; import android.util.DisplayMetrics; @@ -1397,13 +1397,13 @@ public class LayerDrawable extends Drawable implements Drawable.Callback { } @Override - public void setTintMode(Mode tintMode) { + public void setTintMode(@NonNull BlendMode blendMode) { final ChildDrawable[] array = mLayerState.mChildren; final int N = mLayerState.mNumChildren; for (int i = 0; i < N; i++) { final Drawable dr = array[i].mDrawable; if (dr != null) { - dr.setTintMode(tintMode); + dr.setTintMode(blendMode); } } } diff --git a/graphics/java/android/graphics/drawable/NinePatchDrawable.java b/graphics/java/android/graphics/drawable/NinePatchDrawable.java index b53477137331..4972e6a82b7d 100644 --- a/graphics/java/android/graphics/drawable/NinePatchDrawable.java +++ b/graphics/java/android/graphics/drawable/NinePatchDrawable.java @@ -25,6 +25,8 @@ import android.content.res.Resources; import android.content.res.Resources.Theme; import android.content.res.TypedArray; import android.graphics.Bitmap; +import android.graphics.BlendMode; +import android.graphics.BlendModeColorFilter; import android.graphics.Canvas; import android.graphics.ColorFilter; import android.graphics.ImageDecoder; @@ -33,9 +35,6 @@ import android.graphics.NinePatch; import android.graphics.Outline; import android.graphics.Paint; import android.graphics.PixelFormat; -import android.graphics.PorterDuff; -import android.graphics.PorterDuff.Mode; -import android.graphics.PorterDuffColorFilter; import android.graphics.Rect; import android.graphics.Region; import android.util.AttributeSet; @@ -73,7 +72,7 @@ public class NinePatchDrawable extends Drawable { @UnsupportedAppUsage private NinePatchState mNinePatchState; - private PorterDuffColorFilter mTintFilter; + private BlendModeColorFilter mBlendModeFilter; private Rect mPadding; private Insets mOpticalInsets = Insets.NONE; private Rect mOutlineInsets; @@ -198,8 +197,8 @@ public class NinePatchDrawable extends Drawable { int restoreToCount = -1; final boolean clearColorFilter; - if (mTintFilter != null && getPaint().getColorFilter() == null) { - mPaint.setColorFilter(mTintFilter); + if (mBlendModeFilter != null && getPaint().getColorFilter() == null) { + mPaint.setColorFilter(mBlendModeFilter); clearColorFilter = true; } else { clearColorFilter = false; @@ -344,14 +343,16 @@ public class NinePatchDrawable extends Drawable { @Override public void setTintList(@Nullable ColorStateList tint) { mNinePatchState.mTint = tint; - mTintFilter = updateTintFilter(mTintFilter, tint, mNinePatchState.mTintMode); + mBlendModeFilter = updateBlendModeFilter(mBlendModeFilter, tint, + mNinePatchState.mBlendMode); invalidateSelf(); } @Override - public void setTintMode(@Nullable PorterDuff.Mode tintMode) { - mNinePatchState.mTintMode = tintMode; - mTintFilter = updateTintFilter(mTintFilter, mNinePatchState.mTint, tintMode); + public void setTintMode(@Nullable BlendMode blendMode) { + mNinePatchState.mBlendMode = blendMode; + mBlendModeFilter = updateBlendModeFilter(mBlendModeFilter, mNinePatchState.mTint, + blendMode); invalidateSelf(); } @@ -467,7 +468,7 @@ public class NinePatchDrawable extends Drawable { final int tintMode = a.getInt(R.styleable.NinePatchDrawable_tintMode, -1); if (tintMode != -1) { - state.mTintMode = Drawable.parseTintMode(tintMode, Mode.SRC_IN); + state.mBlendMode = Drawable.parseBlendMode(tintMode, BlendMode.SRC_IN); } final ColorStateList tint = a.getColorStateList(R.styleable.NinePatchDrawable_tint); @@ -566,8 +567,9 @@ public class NinePatchDrawable extends Drawable { @Override protected boolean onStateChange(int[] stateSet) { final NinePatchState state = mNinePatchState; - if (state.mTint != null && state.mTintMode != null) { - mTintFilter = updateTintFilter(mTintFilter, state.mTint, state.mTintMode); + if (state.mTint != null && state.mBlendMode != null) { + mBlendModeFilter = updateBlendModeFilter(mBlendModeFilter, state.mTint, + state.mBlendMode); return true; } @@ -593,7 +595,7 @@ public class NinePatchDrawable extends Drawable { @UnsupportedAppUsage NinePatch mNinePatch = null; ColorStateList mTint = null; - Mode mTintMode = DEFAULT_TINT_MODE; + BlendMode mBlendMode = DEFAULT_BLEND_MODE; Rect mPadding = null; Insets mOpticalInsets = Insets.NONE; float mBaseAlpha = 1.0f; @@ -628,7 +630,7 @@ public class NinePatchDrawable extends Drawable { mChangingConfigurations = orig.mChangingConfigurations; mNinePatch = orig.mNinePatch; mTint = orig.mTint; - mTintMode = orig.mTintMode; + mBlendMode = orig.mBlendMode; mPadding = orig.mPadding; mOpticalInsets = orig.mOpticalInsets; mBaseAlpha = orig.mBaseAlpha; @@ -751,7 +753,7 @@ public class NinePatchDrawable extends Drawable { } else { mTargetDensity = Drawable.resolveDensity(res, mTargetDensity); } - mTintFilter = updateTintFilter(mTintFilter, state.mTint, state.mTintMode); + mBlendModeFilter = updateBlendModeFilter(mBlendModeFilter, state.mTint, state.mBlendMode); computeBitmapSize(); } } diff --git a/graphics/java/android/graphics/drawable/ShapeDrawable.java b/graphics/java/android/graphics/drawable/ShapeDrawable.java index 7bfb4c38d6c8..b5fe7f9e432d 100644 --- a/graphics/java/android/graphics/drawable/ShapeDrawable.java +++ b/graphics/java/android/graphics/drawable/ShapeDrawable.java @@ -24,14 +24,13 @@ import android.content.res.ColorStateList; import android.content.res.Resources; import android.content.res.Resources.Theme; import android.content.res.TypedArray; +import android.graphics.BlendMode; +import android.graphics.BlendModeColorFilter; import android.graphics.Canvas; import android.graphics.ColorFilter; import android.graphics.Outline; import android.graphics.Paint; import android.graphics.PixelFormat; -import android.graphics.PorterDuff; -import android.graphics.PorterDuff.Mode; -import android.graphics.PorterDuffColorFilter; import android.graphics.Rect; import android.graphics.Shader; import android.graphics.Xfermode; @@ -75,7 +74,7 @@ import java.io.IOException; */ public class ShapeDrawable extends Drawable { private @NonNull ShapeState mShapeState; - private PorterDuffColorFilter mTintFilter; + private BlendModeColorFilter mBlendModeColorFilter; private boolean mMutated; /** @@ -238,8 +237,8 @@ public class ShapeDrawable extends Drawable { // only draw shape if it may affect output if (paint.getAlpha() != 0 || paint.getXfermode() != null || paint.hasShadowLayer()) { final boolean clearColorFilter; - if (mTintFilter != null && paint.getColorFilter() == null) { - paint.setColorFilter(mTintFilter); + if (mBlendModeColorFilter != null && paint.getColorFilter() == null) { + paint.setColorFilter(mBlendModeColorFilter); clearColorFilter = true; } else { clearColorFilter = false; @@ -292,14 +291,16 @@ public class ShapeDrawable extends Drawable { @Override public void setTintList(ColorStateList tint) { mShapeState.mTint = tint; - mTintFilter = updateTintFilter(mTintFilter, tint, mShapeState.mTintMode); + mBlendModeColorFilter = updateBlendModeFilter(mBlendModeColorFilter, tint, + mShapeState.mBlendMode); invalidateSelf(); } @Override - public void setTintMode(PorterDuff.Mode tintMode) { - mShapeState.mTintMode = tintMode; - mTintFilter = updateTintFilter(mTintFilter, mShapeState.mTint, tintMode); + public void setTintMode(@NonNull BlendMode blendMode) { + mShapeState.mBlendMode = blendMode; + mBlendModeColorFilter = updateBlendModeFilter(mBlendModeColorFilter, mShapeState.mTint, + blendMode); invalidateSelf(); } @@ -352,8 +353,9 @@ public class ShapeDrawable extends Drawable { @Override protected boolean onStateChange(int[] stateSet) { final ShapeState state = mShapeState; - if (state.mTint != null && state.mTintMode != null) { - mTintFilter = updateTintFilter(mTintFilter, state.mTint, state.mTintMode); + if (state.mTint != null && state.mBlendMode != null) { + mBlendModeColorFilter = updateBlendModeFilter(mBlendModeColorFilter, state.mTint, + state.mBlendMode); return true; } return false; @@ -475,7 +477,7 @@ public class ShapeDrawable extends Drawable { final int tintMode = a.getInt(R.styleable.ShapeDrawable_tintMode, -1); if (tintMode != -1) { - state.mTintMode = Drawable.parseTintMode(tintMode, Mode.SRC_IN); + state.mBlendMode = Drawable.parseBlendMode(tintMode, BlendMode.SRC_IN); } final ColorStateList tint = a.getColorStateList(R.styleable.ShapeDrawable_tint); @@ -540,7 +542,7 @@ public class ShapeDrawable extends Drawable { int[] mThemeAttrs; Shape mShape; ColorStateList mTint; - Mode mTintMode = DEFAULT_TINT_MODE; + BlendMode mBlendMode = DEFAULT_BLEND_MODE; Rect mPadding; int mIntrinsicWidth; int mIntrinsicHeight; @@ -573,7 +575,7 @@ public class ShapeDrawable extends Drawable { } } mTint = orig.mTint; - mTintMode = orig.mTintMode; + mBlendMode = orig.mBlendMode; if (orig.mPadding != null) { mPadding = new Rect(orig.mPadding); } @@ -625,7 +627,8 @@ public class ShapeDrawable extends Drawable { * after inflating or applying a theme. */ private void updateLocalState() { - mTintFilter = updateTintFilter(mTintFilter, mShapeState.mTint, mShapeState.mTintMode); + mBlendModeColorFilter = updateBlendModeFilter(mBlendModeColorFilter, mShapeState.mTint, + mShapeState.mBlendMode); } /** diff --git a/graphics/java/android/graphics/drawable/VectorDrawable.java b/graphics/java/android/graphics/drawable/VectorDrawable.java index 7325b857f02c..43772ec20cf3 100644 --- a/graphics/java/android/graphics/drawable/VectorDrawable.java +++ b/graphics/java/android/graphics/drawable/VectorDrawable.java @@ -24,11 +24,13 @@ import android.content.res.GradientColor; import android.content.res.Resources; import android.content.res.Resources.Theme; import android.content.res.TypedArray; +import android.graphics.BlendMode; +import android.graphics.BlendModeColorFilter; import android.graphics.Canvas; import android.graphics.ColorFilter; import android.graphics.Insets; import android.graphics.PixelFormat; -import android.graphics.PorterDuff.Mode; +import android.graphics.PorterDuff; import android.graphics.PorterDuffColorFilter; import android.graphics.Rect; import android.graphics.Shader; @@ -324,6 +326,8 @@ public class VectorDrawable extends Drawable { @UnsupportedAppUsage private PorterDuffColorFilter mTintFilter; + + private BlendModeColorFilter mBlendModeColorFilter; private ColorFilter mColorFilter; private boolean mMutated; @@ -371,7 +375,7 @@ public class VectorDrawable extends Drawable { mDpiScaledDirty = true; } - mTintFilter = updateTintFilter(mTintFilter, mVectorState.mTint, mVectorState.mTintMode); + updateColorFilters(mVectorState.mBlendMode, mVectorState.mTint); } @Override @@ -413,7 +417,8 @@ public class VectorDrawable extends Drawable { } // Color filters always override tint filters. - final ColorFilter colorFilter = (mColorFilter == null ? mTintFilter : mColorFilter); + final ColorFilter colorFilter = (mColorFilter == null ? mBlendModeColorFilter : + mColorFilter); final long colorFilterNativeInstance = colorFilter == null ? 0 : colorFilter.getNativeInstance(); boolean canReuseCache = mVectorState.canReuseCache(); @@ -475,17 +480,19 @@ public class VectorDrawable extends Drawable { final VectorDrawableState state = mVectorState; if (state.mTint != tint) { state.mTint = tint; - mTintFilter = updateTintFilter(mTintFilter, tint, state.mTintMode); + + updateColorFilters(mVectorState.mBlendMode, tint); invalidateSelf(); } } @Override - public void setTintMode(Mode tintMode) { + public void setTintMode(@NonNull BlendMode blendMode) { final VectorDrawableState state = mVectorState; - if (state.mTintMode != tintMode) { - state.mTintMode = tintMode; - mTintFilter = updateTintFilter(mTintFilter, state.mTint, tintMode); + if (state.mBlendMode != blendMode) { + state.mBlendMode = blendMode; + + updateColorFilters(state.mBlendMode, state.mTint); invalidateSelf(); } } @@ -515,14 +522,22 @@ public class VectorDrawable extends Drawable { changed = true; state.mCacheDirty = true; } - if (state.mTint != null && state.mTintMode != null) { - mTintFilter = updateTintFilter(mTintFilter, state.mTint, state.mTintMode); + if (state.mTint != null && state.mBlendMode != null) { + BlendMode blendMode = state.mBlendMode; + ColorStateList tint = state.mTint; + updateColorFilters(blendMode, tint); changed = true; } return changed; } + private void updateColorFilters(@Nullable BlendMode blendMode, ColorStateList tint) { + PorterDuff.Mode mode = BlendMode.blendModeToPorterDuffMode(blendMode); + mTintFilter = updateTintFilter(mTintFilter, tint, mode); + mBlendModeColorFilter = updateBlendModeFilter(mBlendModeColorFilter, tint, blendMode); + } + @Override public int getOpacity() { // We can't tell whether the drawable is fully opaque unless we examine all the pixels, @@ -737,7 +752,7 @@ public class VectorDrawable extends Drawable { final int tintMode = a.getInt(R.styleable.VectorDrawable_tintMode, -1); if (tintMode != -1) { - state.mTintMode = Drawable.parseTintMode(tintMode, Mode.SRC_IN); + state.mBlendMode = Drawable.parseBlendMode(tintMode, BlendMode.SRC_IN); } final ColorStateList tint = a.getColorStateList(R.styleable.VectorDrawable_tint); @@ -911,7 +926,7 @@ public class VectorDrawable extends Drawable { int[] mThemeAttrs; @Config int mChangingConfigurations; ColorStateList mTint = null; - Mode mTintMode = DEFAULT_TINT_MODE; + BlendMode mBlendMode = DEFAULT_BLEND_MODE; boolean mAutoMirrored; int mBaseWidth = 0; @@ -929,7 +944,7 @@ public class VectorDrawable extends Drawable { // Fields for cache int[] mCachedThemeAttrs; ColorStateList mCachedTint; - Mode mCachedTintMode; + BlendMode mCachedBlendMode; boolean mCachedAutoMirrored; boolean mCacheDirty; @@ -970,7 +985,7 @@ public class VectorDrawable extends Drawable { mThemeAttrs = copy.mThemeAttrs; mChangingConfigurations = copy.mChangingConfigurations; mTint = copy.mTint; - mTintMode = copy.mTintMode; + mBlendMode = copy.mBlendMode; mAutoMirrored = copy.mAutoMirrored; mRootGroup = new VGroup(copy.mRootGroup, mVGTargetsMap); createNativeTreeFromCopy(copy, mRootGroup); @@ -1026,7 +1041,7 @@ public class VectorDrawable extends Drawable { if (!mCacheDirty && mCachedThemeAttrs == mThemeAttrs && mCachedTint == mTint - && mCachedTintMode == mTintMode + && mCachedBlendMode == mBlendMode && mCachedAutoMirrored == mAutoMirrored) { return true; } @@ -1039,7 +1054,7 @@ public class VectorDrawable extends Drawable { // likely hit cache miss more, but practically not much difference. mCachedThemeAttrs = mThemeAttrs; mCachedTint = mTint; - mCachedTintMode = mTintMode; + mCachedBlendMode = mBlendMode; mCachedAutoMirrored = mAutoMirrored; mCacheDirty = false; } diff --git a/graphics/java/android/graphics/pdf/PdfRenderer.java b/graphics/java/android/graphics/pdf/PdfRenderer.java index 1836f009f86b..bd1a49205fd5 100644 --- a/graphics/java/android/graphics/pdf/PdfRenderer.java +++ b/graphics/java/android/graphics/pdf/PdfRenderer.java @@ -435,8 +435,9 @@ public final class PdfRenderer implements AutoCloseable { final long transformPtr = transform.native_instance; synchronized (sPdfiumLock) { - nativeRenderPage(mNativeDocument, mNativePage, destination, contentLeft, - contentTop, contentRight, contentBottom, transformPtr, renderMode); + nativeRenderPage(mNativeDocument, mNativePage, destination.getNativeInstance(), + contentLeft, contentTop, contentRight, contentBottom, transformPtr, + renderMode); } } @@ -487,7 +488,7 @@ public final class PdfRenderer implements AutoCloseable { private static native void nativeClose(long documentPtr); private static native int nativeGetPageCount(long documentPtr); private static native boolean nativeScaleForPrinting(long documentPtr); - private static native void nativeRenderPage(long documentPtr, long pagePtr, Bitmap dest, + private static native void nativeRenderPage(long documentPtr, long pagePtr, long bitmapHandle, int clipLeft, int clipTop, int clipRight, int clipBottom, long transformPtr, int renderMode); private static native long nativeOpenPageAndGetSize(long documentPtr, int pageIndex, diff --git a/graphics/java/android/graphics/text/MeasuredText.java b/graphics/java/android/graphics/text/MeasuredText.java index 9db7533044e2..b6d8fa19fca8 100644 --- a/graphics/java/android/graphics/text/MeasuredText.java +++ b/graphics/java/android/graphics/text/MeasuredText.java @@ -42,7 +42,7 @@ import libcore.util.NativeAllocationRegistry; * String text = "Hello, Android."; * MeasuredText mt = new MeasuredText.Builder(text.toCharArray()) * .appendStyleRun(paint, 7, false) // Use paint for "Hello, " - * .appendStyleRun(bigPaint, 8, false) // Use bigPaint for "Hello, " + * .appendStyleRun(bigPaint, 8, false) // Use bigPaint for "Android." * .build(); * </code> * </pre> |