diff options
Diffstat (limited to 'graphics/java')
46 files changed, 699 insertions, 1672 deletions
diff --git a/graphics/java/android/graphics/Bitmap.java b/graphics/java/android/graphics/Bitmap.java index f7877590869a..f41049058a62 100644 --- a/graphics/java/android/graphics/Bitmap.java +++ b/graphics/java/android/graphics/Bitmap.java @@ -23,7 +23,6 @@ import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.WorkerThread; import android.compat.annotation.UnsupportedAppUsage; -import android.content.res.ResourcesImpl; import android.hardware.HardwareBuffer; import android.os.Build; import android.os.Parcel; @@ -40,6 +39,7 @@ import dalvik.annotation.optimization.CriticalNative; import libcore.util.NativeAllocationRegistry; import java.io.OutputStream; +import java.lang.ref.WeakReference; import java.nio.Buffer; import java.nio.ByteBuffer; import java.nio.IntBuffer; @@ -86,21 +86,15 @@ public final class Bitmap implements Parcelable { private int mWidth; @UnsupportedAppUsage private int mHeight; + private WeakReference<HardwareBuffer> mHardwareBuffer; private boolean mRecycled; private ColorSpace mColorSpace; - /** @hide */ - public int mDensity = getDefaultDensity(); + /*package*/ int mDensity = getDefaultDensity(); private static volatile int sDefaultDensity = -1; - /** @hide Used only when ResourcesImpl.TRACE_FOR_DETAILED_PRELOAD is true. */ - public static volatile int sPreloadTracingNumInstantiatedBitmaps; - - /** @hide Used only when ResourcesImpl.TRACE_FOR_DETAILED_PRELOAD is true. */ - public static volatile long sPreloadTracingTotalBitmapsSize; - /** * For backwards compatibility, allows the app layer to change the default * density when running old apps. @@ -164,17 +158,14 @@ public final class Bitmap implements Parcelable { Bitmap.class.getClassLoader(), nativeGetNativeFinalizer(), allocationByteCount); } registry.registerNativeAllocation(this, nativeBitmap); - - if (ResourcesImpl.TRACE_FOR_DETAILED_PRELOAD) { - sPreloadTracingNumInstantiatedBitmaps++; - long nativeSize = NATIVE_ALLOCATION_SIZE + allocationByteCount; - sPreloadTracingTotalBitmapsSize += nativeSize; - } } /** * Return the pointer to the native object. + * * @hide + * Must be public for access from android.graphics.pdf, + * but must not be called from outside the UI module. */ public long getNativeInstance() { return mNativePtr; @@ -353,11 +344,9 @@ public final class Bitmap implements Parcelable { * Sets the nine patch chunk. * * @param chunk The definition of the nine patch - * - * @hide */ @UnsupportedAppUsage - public void setNinePatchChunk(byte[] chunk) { + private void setNinePatchChunk(byte[] chunk) { mNinePatchChunk = chunk; } @@ -377,6 +366,7 @@ public final class Bitmap implements Parcelable { nativeRecycle(mNativePtr); mNinePatchChunk = null; mRecycled = true; + mHardwareBuffer = null; } } @@ -694,14 +684,16 @@ public final class Bitmap implements Parcelable { return b; } + // FIXME: The maxTargetSdk should be R, once R is no longer set to + // CUR_DEVELOPMENT. /** * Creates a new immutable bitmap backed by ashmem which can efficiently - * be passed between processes. The bitmap is assumed to be in the sRGB - * color space. + * be passed between processes. * * @hide */ - @UnsupportedAppUsage + @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.Q, + publicAlternatives = "Use {@link #asShared()} instead") public Bitmap createAshmemBitmap() { checkRecycled("Can't copy a recycled bitmap"); noteHardwareBitmapSlowCall(); @@ -714,22 +706,21 @@ public final class Bitmap implements Parcelable { } /** - * Creates a new immutable bitmap backed by ashmem which can efficiently - * be passed between processes. The bitmap is assumed to be in the sRGB - * color space. + * Return an immutable bitmap backed by shared memory which can be + * efficiently passed between processes via Parcelable. * - * @hide + * <p>If this bitmap already meets these criteria it will return itself. */ - @UnsupportedAppUsage - public Bitmap createAshmemBitmap(Config config) { - checkRecycled("Can't copy a recycled bitmap"); - noteHardwareBitmapSlowCall(); - Bitmap b = nativeCopyAshmemConfig(mNativePtr, config.nativeInt); - if (b != null) { - b.setPremultiplied(mRequestPremultiplied); - b.mDensity = mDensity; + @NonNull + public Bitmap asShared() { + if (nativeIsBackedByAshmem(mNativePtr) && nativeIsImmutable(mNativePtr)) { + return this; } - return b; + Bitmap shared = createAshmemBitmap(); + if (shared == null) { + throw new RuntimeException("Failed to create shared Bitmap!"); + } + return shared; } /** @@ -759,19 +750,12 @@ public final class Bitmap implements Parcelable { if (colorSpace == null) { colorSpace = ColorSpace.get(ColorSpace.Named.SRGB); } - return nativeWrapHardwareBufferBitmap(hardwareBuffer, colorSpace.getNativeInstance()); - } - - /** - * Utility method to create a hardware backed bitmap using the graphics buffer. - * @hide - */ - @Nullable - public static Bitmap wrapHardwareBuffer(@NonNull GraphicBuffer graphicBuffer, - @Nullable ColorSpace colorSpace) { - try (HardwareBuffer hb = HardwareBuffer.createFromGraphicBuffer(graphicBuffer)) { - return wrapHardwareBuffer(hb, colorSpace); + Bitmap bitmap = nativeWrapHardwareBufferBitmap(hardwareBuffer, + colorSpace.getNativeInstance()); + if (bitmap != null) { + bitmap.mHardwareBuffer = new WeakReference<HardwareBuffer>(hardwareBuffer); } + return bitmap; } /** @@ -1340,7 +1324,10 @@ public final class Bitmap implements Parcelable { * Populates a rectangle with the bitmap's optical insets. * * @param outInsets Rect to populate with optical insets + * * @hide + * Must be public for access from android.graphics.drawable, + * but must not be called from outside the UI module. */ public void getOpticalInsets(@NonNull Rect outInsets) { if (mNinePatchInsets == null) { @@ -1350,7 +1337,11 @@ public final class Bitmap implements Parcelable { } } - /** @hide */ + /** + * @hide + * Must be public for access from android.graphics.drawable, + * but must not be called from outside the UI module. + */ public NinePatch.InsetStruct getNinePatchInsets() { return mNinePatchInsets; } @@ -1456,10 +1447,8 @@ public final class Bitmap implements Parcelable { * to {@link #reconfigure(int, int, Config)}, {@link #setPixel(int, int, int)}, * {@link #setPixels(int[], int, int, int, int, int, int)} and {@link #eraseColor(int)} will * fail and throw an IllegalStateException. - * - * @hide */ - public void setImmutable() { + private void setImmutable() { if (isMutable()) { nativeSetImmutable(mNativePtr); } @@ -1603,6 +1592,8 @@ public final class Bitmap implements Parcelable { /** * @hide + * Must be public for access from android.graphics.drawable, + * but must not be called from outside the UI module. */ @UnsupportedAppUsage static public int scaleFromDensity(int size, int sdensity, int tdensity) { @@ -2230,30 +2221,26 @@ public final class Bitmap implements Parcelable { } /** - * @return {@link GraphicBuffer} which is internally used by hardware bitmap - * - * Note: the GraphicBuffer does *not* have an associated {@link ColorSpace}. - * To render this object the same as its rendered with this Bitmap, you - * should also call {@link getColorSpace}. - * - * @hide - */ - @UnsupportedAppUsage - public GraphicBuffer createGraphicBufferHandle() { - return GraphicBuffer.createFromHardwareBuffer(getHardwareBuffer()); - } - - /** * @return {@link HardwareBuffer} which is internally used by hardware bitmap * * Note: the HardwareBuffer does *not* have an associated {@link ColorSpace}. * To render this object the same as its rendered with this Bitmap, you - * should also call {@link getColorSpace}. + * should also call {@link #getColorSpace()}.</p> * - * @hide + * Must not be modified while a wrapped Bitmap is accessing it. Doing so will + * result in undefined behavior.</p> + * + * @throws IllegalStateException if the bitmap's config is not {@link Config#HARDWARE} + * or if the bitmap has been recycled. */ - public HardwareBuffer getHardwareBuffer() { - return nativeGetHardwareBuffer(mNativePtr); + public @NonNull HardwareBuffer getHardwareBuffer() { + checkRecycled("Can't getHardwareBuffer from a recycled bitmap"); + HardwareBuffer hardwareBuffer = mHardwareBuffer == null ? null : mHardwareBuffer.get(); + if (hardwareBuffer == null || hardwareBuffer.isClosed()) { + hardwareBuffer = nativeGetHardwareBuffer(mNativePtr); + mHardwareBuffer = new WeakReference<HardwareBuffer>(hardwareBuffer); + } + return hardwareBuffer; } //////////// native methods @@ -2332,4 +2319,7 @@ public final class Bitmap implements Parcelable { @CriticalNative private static native boolean nativeIsImmutable(long nativePtr); + + @CriticalNative + private static native boolean nativeIsBackedByAshmem(long nativePtr); } diff --git a/graphics/java/android/graphics/BitmapRegionDecoder.java b/graphics/java/android/graphics/BitmapRegionDecoder.java index 34eba97819aa..29112af9516b 100644 --- a/graphics/java/android/graphics/BitmapRegionDecoder.java +++ b/graphics/java/android/graphics/BitmapRegionDecoder.java @@ -15,9 +15,12 @@ package android.graphics; +import android.annotation.NonNull; +import android.annotation.Nullable; import android.compat.annotation.UnsupportedAppUsage; import android.content.res.AssetManager; import android.os.Build; +import android.os.ParcelFileDescriptor; import java.io.FileDescriptor; import java.io.FileInputStream; @@ -43,113 +46,158 @@ public final class BitmapRegionDecoder { /** * Create a BitmapRegionDecoder from the specified byte array. - * Currently only the JPEG and PNG formats are supported. + * Currently only the JPEG, PNG, WebP and HEIF formats are supported. * * @param data byte array of compressed image data. * @param offset offset into data for where the decoder should begin * parsing. * @param length the number of bytes, beginning at offset, to parse - * @param isShareable If this is true, then the BitmapRegionDecoder may keep a - * shallow reference to the input. If this is false, - * then the BitmapRegionDecoder will explicitly make a copy of the - * input data, and keep that. Even if sharing is allowed, - * the implementation may still decide to make a deep - * copy of the input data. If an image is progressively encoded, - * allowing sharing may degrade the decoding speed. - * @return BitmapRegionDecoder, or null if the image data could not be decoded. + * @param isShareable This field has been ignored since + * {@link Build.VERSION_CODES#GINGERBREAD}. * @throws IOException if the image format is not supported or can not be decoded. + * @deprecated In favor of {@link #newInstance(byte[], int, int)} */ - public static BitmapRegionDecoder newInstance(byte[] data, + @Deprecated + @NonNull + public static BitmapRegionDecoder newInstance(@NonNull byte[] data, int offset, int length, boolean isShareable) throws IOException { + return newInstance(data, offset, length); + } + + /** + * Create a BitmapRegionDecoder from the specified byte array. + * Currently only the JPEG, PNG, WebP and HEIF formats are supported. + * + * @param data byte array of compressed image data. + * @param offset offset into data for where the decoder should begin + * parsing. + * @param length the number of bytes, beginning at offset, to parse + * @throws IOException if the image format is not supported or can not be decoded. + */ + @NonNull + public static BitmapRegionDecoder newInstance(@NonNull byte[] data, + int offset, int length) throws IOException { if ((offset | length) < 0 || data.length < offset + length) { throw new ArrayIndexOutOfBoundsException(); } - return nativeNewInstance(data, offset, length, isShareable); + return nativeNewInstance(data, offset, length); } /** * Create a BitmapRegionDecoder from the file descriptor. * The position within the descriptor will not be changed when * this returns, so the descriptor can be used again as is. - * Currently only the JPEG and PNG formats are supported. + * Currently only the JPEG, PNG, WebP and HEIF formats are supported. * * @param fd The file descriptor containing the data to decode - * @param isShareable If this is true, then the BitmapRegionDecoder may keep a - * shallow reference to the input. If this is false, - * then the BitmapRegionDecoder will explicitly make a copy of the - * input data, and keep that. Even if sharing is allowed, - * the implementation may still decide to make a deep - * copy of the input data. If an image is progressively encoded, - * allowing sharing may degrade the decoding speed. - * @return BitmapRegionDecoder, or null if the image data could not be decoded. + * @param isShareable This field has been ignored since + * {@link Build.VERSION_CODES#KITKAT}. + * @throws IOException if the image format is not supported or can not be decoded. + * @deprecated In favor of {@link #newInstance(ParcelFileDescriptor)} + */ + @Deprecated + @NonNull + public static BitmapRegionDecoder newInstance( + @NonNull FileDescriptor fd, boolean isShareable) throws IOException { + return nativeNewInstance(fd); + } + + /** + * Create a BitmapRegionDecoder from the file descriptor. + * The position within the descriptor will not be changed when + * this returns, so the descriptor can be used again as is. + * Currently only the JPEG, PNG, WebP and HEIF formats are supported. + * + * @param pfd The parcel file descriptor containing the data to decode * @throws IOException if the image format is not supported or can not be decoded. */ + @NonNull public static BitmapRegionDecoder newInstance( - FileDescriptor fd, boolean isShareable) throws IOException { - return nativeNewInstance(fd, isShareable); + @NonNull ParcelFileDescriptor pfd) throws IOException { + return nativeNewInstance(pfd.getFileDescriptor()); } /** * Create a BitmapRegionDecoder from an input stream. * The stream's position will be where ever it was after the encoded data * was read. - * Currently only the JPEG and PNG formats are supported. + * Currently only the JPEG, PNG, WebP and HEIF formats are supported. * * @param is The input stream that holds the raw data to be decoded into a * BitmapRegionDecoder. - * @param isShareable If this is true, then the BitmapRegionDecoder may keep a - * shallow reference to the input. If this is false, - * then the BitmapRegionDecoder will explicitly make a copy of the - * input data, and keep that. Even if sharing is allowed, - * the implementation may still decide to make a deep - * copy of the input data. If an image is progressively encoded, - * allowing sharing may degrade the decoding speed. - * @return BitmapRegionDecoder, or null if the image data could not be decoded. + * @param isShareable This field has always been ignored. + * @return A new BitmapRegionDecoder, or {@code null} if {@code is} is {@code null}. * @throws IOException if the image format is not supported or can not be decoded. + * @deprecated In favor of {@link #newInstance(InputStream)} * - * <p class="note">Prior to {@link android.os.Build.VERSION_CODES#KITKAT}, + * <p class="note">Prior to {@link Build.VERSION_CODES#KITKAT}, * if {@link InputStream#markSupported is.markSupported()} returns true, * <code>is.mark(1024)</code> would be called. As of - * {@link android.os.Build.VERSION_CODES#KITKAT}, this is no longer the case.</p> + * {@link Build.VERSION_CODES#KITKAT}, this is no longer the case.</p> */ - public static BitmapRegionDecoder newInstance(InputStream is, + @Deprecated + @Nullable + public static BitmapRegionDecoder newInstance(@NonNull InputStream is, boolean isShareable) throws IOException { + return newInstance(is); + } + + /** + * Create a BitmapRegionDecoder from an input stream. + * The stream's position will be where ever it was after the encoded data + * was read. + * Currently only the JPEG, PNG, WebP and HEIF formats are supported. + * + * @param is The input stream that holds the raw data to be decoded into a + * BitmapRegionDecoder. + * @return A new BitmapRegionDecoder, or {@code null} if {@code is} is {@code null}. + * @throws IOException if the image format is not supported or can not be decoded. + */ + @Nullable + public static BitmapRegionDecoder newInstance(@NonNull InputStream is) throws IOException { if (is instanceof AssetManager.AssetInputStream) { return nativeNewInstance( - ((AssetManager.AssetInputStream) is).getNativeAsset(), - isShareable); + ((AssetManager.AssetInputStream) is).getNativeAsset()); } else { // pass some temp storage down to the native code. 1024 is made up, // but should be large enough to avoid too many small calls back // into is.read(...). byte [] tempStorage = new byte[16 * 1024]; - return nativeNewInstance(is, tempStorage, isShareable); + return nativeNewInstance(is, tempStorage); } } /** * Create a BitmapRegionDecoder from a file path. - * Currently only the JPEG and PNG formats are supported. + * Currently only the JPEG, PNG, WebP and HEIF formats are supported. * * @param pathName complete path name for the file to be decoded. - * @param isShareable If this is true, then the BitmapRegionDecoder may keep a - * shallow reference to the input. If this is false, - * then the BitmapRegionDecoder will explicitly make a copy of the - * input data, and keep that. Even if sharing is allowed, - * the implementation may still decide to make a deep - * copy of the input data. If an image is progressively encoded, - * allowing sharing may degrade the decoding speed. - * @return BitmapRegionDecoder, or null if the image data could not be decoded. + * @param isShareable This field has always been ignored. * @throws IOException if the image format is not supported or can not be decoded. + * @deprecated In favor of {@link #newInstance(String)} */ - public static BitmapRegionDecoder newInstance(String pathName, + @Deprecated + @NonNull + public static BitmapRegionDecoder newInstance(@NonNull String pathName, boolean isShareable) throws IOException { + return newInstance(pathName); + } + + /** + * Create a BitmapRegionDecoder from a file path. + * Currently only the JPEG, PNG, WebP and HEIF formats are supported. + * + * @param pathName complete path name for the file to be decoded. + * @throws IOException if the image format is not supported or can not be decoded. + */ + @NonNull + public static BitmapRegionDecoder newInstance(@NonNull String pathName) throws IOException { BitmapRegionDecoder decoder = null; InputStream stream = null; try { stream = new FileInputStream(pathName); - decoder = newInstance(stream, isShareable); + decoder = newInstance(stream); } finally { if (stream != null) { try { @@ -273,13 +321,12 @@ public final class BitmapRegionDecoder { private static native int nativeGetHeight(long lbm); private static native void nativeClean(long lbm); - @UnsupportedAppUsage private static native BitmapRegionDecoder nativeNewInstance( - byte[] data, int offset, int length, boolean isShareable); + byte[] data, int offset, int length); private static native BitmapRegionDecoder nativeNewInstance( - FileDescriptor fd, boolean isShareable); + FileDescriptor fd); private static native BitmapRegionDecoder nativeNewInstance( - InputStream is, byte[] storage, boolean isShareable); + InputStream is, byte[] storage); private static native BitmapRegionDecoder nativeNewInstance( - long asset, boolean isShareable); + long asset); } diff --git a/graphics/java/android/graphics/BitmapShader.java b/graphics/java/android/graphics/BitmapShader.java index edf53c491311..1cb5912e7a54 100644 --- a/graphics/java/android/graphics/BitmapShader.java +++ b/graphics/java/android/graphics/BitmapShader.java @@ -17,7 +17,6 @@ package android.graphics; import android.annotation.NonNull; -import android.compat.annotation.UnsupportedAppUsage; /** * Shader used to draw a bitmap as a texture. The bitmap can be repeated or @@ -26,15 +25,10 @@ import android.compat.annotation.UnsupportedAppUsage; public class BitmapShader extends Shader { /** * Prevent garbage collection. - * @hide */ - @SuppressWarnings({"FieldCanBeLocal", "UnusedDeclaration"}) - @UnsupportedAppUsage - public Bitmap mBitmap; + /*package*/ Bitmap mBitmap; - @UnsupportedAppUsage private int mTileX; - @UnsupportedAppUsage private int mTileY; /** @@ -52,16 +46,14 @@ public class BitmapShader extends Shader { if (bitmap == null) { throw new IllegalArgumentException("Bitmap must be non-null"); } - if (bitmap == mBitmap && tileX == mTileX && tileY == mTileY) { - return; - } mBitmap = bitmap; mTileX = tileX; mTileY = tileY; } + /** @hide */ @Override - long createNativeInstance(long nativeMatrix) { + protected long createNativeInstance(long nativeMatrix) { return nativeCreate(nativeMatrix, mBitmap.getNativeInstance(), mTileX, mTileY); } diff --git a/graphics/java/android/graphics/Camera.java b/graphics/java/android/graphics/Camera.java index 80a3740d2f4e..46640d7222ca 100644 --- a/graphics/java/android/graphics/Camera.java +++ b/graphics/java/android/graphics/Camera.java @@ -16,8 +16,6 @@ package android.graphics; -import android.compat.annotation.UnsupportedAppUsage; - /** * A camera instance can be used to compute 3D transformations and * generate a matrix that can be applied, for instance, on a @@ -139,7 +137,7 @@ public class Camera { * @param matrix The matrix to copy the current transforms into */ public void getMatrix(Matrix matrix) { - nativeGetMatrix(matrix.native_instance); + nativeGetMatrix(matrix.ni()); } /** @@ -168,6 +166,5 @@ public class Camera { private native void nativeGetMatrix(long native_matrix); private native void nativeApplyToCanvas(long native_canvas); - @UnsupportedAppUsage - long native_instance; + private long native_instance; } diff --git a/graphics/java/android/graphics/Canvas.java b/graphics/java/android/graphics/Canvas.java index d949444d44d6..559571cb0271 100644 --- a/graphics/java/android/graphics/Canvas.java +++ b/graphics/java/android/graphics/Canvas.java @@ -34,8 +34,6 @@ import libcore.util.NativeAllocationRegistry; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; -import javax.microedition.khronos.opengles.GL; - /** * The Canvas class holds the "draw" calls. To draw something, you need * 4 basic components: A Bitmap to hold the pixels, a Canvas to host @@ -51,10 +49,8 @@ import javax.microedition.khronos.opengles.GL; */ public class Canvas extends BaseCanvas { private static int sCompatiblityVersion = 0; - /** @hide */ - public static boolean sCompatibilityRestore = false; - /** @hide */ - public static boolean sCompatibilitySetBitmap = false; + private static boolean sCompatibilityRestore = false; + private static boolean sCompatibilitySetBitmap = false; /** @hide */ @UnsupportedAppUsage @@ -62,9 +58,6 @@ public class Canvas extends BaseCanvas { return mNativeCanvasWrapper; } - /** @hide */ - public boolean isRecordingFor(Object o) { return false; } - // may be null @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 117521088) private Bitmap mBitmap; @@ -124,8 +117,10 @@ public class Canvas extends BaseCanvas { mDensity = bitmap.mDensity; } - /** @hide */ - @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023) + /** + * @hide Needed by android.graphics.pdf.PdfDocument, but should not be called from + * outside the UI rendering module. + */ public Canvas(long nativeCanvas) { if (nativeCanvas == 0) { throw new IllegalStateException(); @@ -137,19 +132,6 @@ public class Canvas extends BaseCanvas { } /** - * Returns null. - * - * @deprecated This method is not supported and should not be invoked. - * - * @hide - */ - @Deprecated - @UnsupportedAppUsage - protected GL getGL() { - return null; - } - - /** * Indicates whether this Canvas uses hardware acceleration. * * Note that this method does not define what type of hardware acceleration @@ -205,22 +187,6 @@ public class Canvas extends BaseCanvas { } /** - * @deprecated use {@link #enableZ()} instead - * @hide */ - @Deprecated - public void insertReorderBarrier() { - enableZ(); - } - - /** - * @deprecated use {@link #disableZ()} instead - * @hide */ - @Deprecated - public void insertInorderBarrier() { - disableZ(); - } - - /** * <p>Enables Z support which defaults to disabled. This allows for RenderNodes drawn with * {@link #drawRenderNode(RenderNode)} to be re-arranged based off of their * {@link RenderNode#getElevation()} and {@link RenderNode#getTranslationZ()} @@ -793,7 +759,7 @@ public class Canvas extends BaseCanvas { * @param matrix The matrix to preconcatenate with the current matrix */ public void concat(@Nullable Matrix matrix) { - if (matrix != null) nConcat(mNativeCanvasWrapper, matrix.native_instance); + if (matrix != null) nConcat(mNativeCanvasWrapper, matrix.ni()); } /** @@ -811,7 +777,7 @@ public class Canvas extends BaseCanvas { */ public void setMatrix(@Nullable Matrix matrix) { nSetMatrix(mNativeCanvasWrapper, - matrix == null ? 0 : matrix.native_instance); + matrix == null ? 0 : matrix.ni()); } /** @@ -826,7 +792,7 @@ public class Canvas extends BaseCanvas { */ @Deprecated public void getMatrix(@NonNull Matrix ctm) { - nGetMatrix(mNativeCanvasWrapper, ctm.native_instance); + nGetMatrix(mNativeCanvasWrapper, ctm.ni()); } /** @@ -1169,21 +1135,12 @@ public class Canvas extends BaseCanvas { /** * Black-and-White: Treat edges by just rounding to nearest pixel boundary */ - BW(0), //!< treat edges by just rounding to nearest pixel boundary + BW, /** * Antialiased: Treat edges by rounding-out, since they may be antialiased */ - AA(1); - - EdgeType(int nativeInt) { - this.nativeInt = nativeInt; - } - - /** - * @hide - */ - public final int nativeInt; + AA; } /** @@ -1386,10 +1343,7 @@ public class Canvas extends BaseCanvas { this.nativeInt = nativeInt; } - /** - * @hide - */ - public final int nativeInt; + /*package*/ final int nativeInt; } /** @@ -1426,9 +1380,10 @@ public class Canvas extends BaseCanvas { nFreeTextLayoutCaches(); } - /** @hide */ - public static void setCompatibilityVersion(int apiLevel) { + /*package*/ static void setCompatibilityVersion(int apiLevel) { sCompatiblityVersion = apiLevel; + sCompatibilityRestore = apiLevel < Build.VERSION_CODES.M; + sCompatibilitySetBitmap = apiLevel < Build.VERSION_CODES.O; nSetCompatibilityVersion(apiLevel); } @@ -1874,24 +1829,22 @@ public class Canvas extends BaseCanvas { } /** - * Draws the specified bitmap as an N-patch (most often, a 9-patches.) + * Draws the specified bitmap as an N-patch (most often, a 9-patch.) * * @param patch The ninepatch object to render * @param dst The destination rectangle. * @param paint The paint to draw the bitmap with. may be null - * @hide */ public void drawPatch(@NonNull NinePatch patch, @NonNull Rect dst, @Nullable Paint paint) { super.drawPatch(patch, dst, paint); } /** - * Draws the specified bitmap as an N-patch (most often, a 9-patches.) + * Draws the specified bitmap as an N-patch (most often, a 9-patch.) * * @param patch The ninepatch object to render * @param dst The destination rectangle. * @param paint The paint to draw the bitmap with. may be null - * @hide */ public void drawPatch(@NonNull NinePatch patch, @NonNull RectF dst, @Nullable Paint paint) { super.drawPatch(patch, dst, paint); diff --git a/graphics/java/android/graphics/Color.java b/graphics/java/android/graphics/Color.java index c4bf9d3123bf..87a805379b56 100644 --- a/graphics/java/android/graphics/Color.java +++ b/graphics/java/android/graphics/Color.java @@ -26,7 +26,6 @@ import android.annotation.Nullable; import android.annotation.Size; import android.annotation.SuppressAutoDoc; import android.util.Half; -import com.android.internal.util.XmlUtils; import java.util.Arrays; import java.util.HashMap; @@ -1476,29 +1475,6 @@ public class Color { private static native void nativeRGBToHSV(int red, int greed, int blue, float hsv[]); private static native int nativeHSVToColor(int alpha, float hsv[]); - /** - * Converts an HTML color (named or numeric) to an integer RGB value. - * - * @param color Non-null color string. - * - * @return A color value, or {@code -1} if the color string could not be interpreted. - * - * @hide - */ - @ColorInt - public static int getHtmlColor(@NonNull String color) { - Integer i = sColorNameMap.get(color.toLowerCase(Locale.ROOT)); - if (i != null) { - return i; - } else { - try { - return XmlUtils.convertValueToInt(color, -1); - } catch (NumberFormatException nfe) { - return -1; - } - } - } - private static final HashMap<String, Integer> sColorNameMap; static { sColorNameMap = new HashMap<>(); diff --git a/graphics/java/android/graphics/ColorMatrix.java b/graphics/java/android/graphics/ColorMatrix.java deleted file mode 100644 index 6299b2c47ea1..000000000000 --- a/graphics/java/android/graphics/ColorMatrix.java +++ /dev/null @@ -1,288 +0,0 @@ -/* - * Copyright (C) 2007 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 java.util.Arrays; - -/** - * 4x5 matrix for transforming the color and alpha components of a Bitmap. - * The matrix can be passed as single array, and is treated as follows: - * - * <pre> - * [ a, b, c, d, e, - * f, g, h, i, j, - * k, l, m, n, o, - * p, q, r, s, t ]</pre> - * - * <p> - * When applied to a color <code>[R, G, B, A]</code>, the resulting color - * is computed as: - * </p> - * - * <pre> - * R’ = a*R + b*G + c*B + d*A + e; - * G’ = f*R + g*G + h*B + i*A + j; - * B’ = k*R + l*G + m*B + n*A + o; - * A’ = p*R + q*G + r*B + s*A + t;</pre> - * - * <p> - * That resulting color <code>[R’, G’, B’, A’]</code> - * then has each channel clamped to the <code>0</code> to <code>255</code> - * range. - * </p> - * - * <p> - * The sample ColorMatrix below inverts incoming colors by scaling each - * channel by <code>-1</code>, and then shifting the result up by - * <code>255</code> to remain in the standard color space. - * </p> - * - * <pre> - * [ -1, 0, 0, 0, 255, - * 0, -1, 0, 0, 255, - * 0, 0, -1, 0, 255, - * 0, 0, 0, 1, 0 ]</pre> - */ -@SuppressWarnings({ "MismatchedReadAndWriteOfArray", "PointlessArithmeticExpression" }) -public class ColorMatrix { - private final float[] mArray = new float[20]; - - /** - * Create a new colormatrix initialized to identity (as if reset() had - * been called). - */ - public ColorMatrix() { - reset(); - } - - /** - * Create a new colormatrix initialized with the specified array of values. - */ - public ColorMatrix(float[] src) { - System.arraycopy(src, 0, mArray, 0, 20); - } - - /** - * Create a new colormatrix initialized with the specified colormatrix. - */ - public ColorMatrix(ColorMatrix src) { - System.arraycopy(src.mArray, 0, mArray, 0, 20); - } - - /** - * Return the array of floats representing this colormatrix. - */ - public final float[] getArray() { return mArray; } - - /** - * Set this colormatrix to identity: - * <pre> - * [ 1 0 0 0 0 - red vector - * 0 1 0 0 0 - green vector - * 0 0 1 0 0 - blue vector - * 0 0 0 1 0 ] - alpha vector - * </pre> - */ - public void reset() { - final float[] a = mArray; - Arrays.fill(a, 0); - a[0] = a[6] = a[12] = a[18] = 1; - } - - /** - * Assign the src colormatrix into this matrix, copying all of its values. - */ - public void set(ColorMatrix src) { - System.arraycopy(src.mArray, 0, mArray, 0, 20); - } - - /** - * Assign the array of floats into this matrix, copying all of its values. - */ - public void set(float[] src) { - System.arraycopy(src, 0, mArray, 0, 20); - } - - /** - * Set this colormatrix to scale by the specified values. - */ - public void setScale(float rScale, float gScale, float bScale, - float aScale) { - final float[] a = mArray; - - for (int i = 19; i > 0; --i) { - a[i] = 0; - } - a[0] = rScale; - a[6] = gScale; - a[12] = bScale; - a[18] = aScale; - } - - /** - * Set the rotation on a color axis by the specified values. - * <p> - * <code>axis=0</code> correspond to a rotation around the RED color - * <code>axis=1</code> correspond to a rotation around the GREEN color - * <code>axis=2</code> correspond to a rotation around the BLUE color - * </p> - */ - public void setRotate(int axis, float degrees) { - reset(); - double radians = degrees * Math.PI / 180d; - float cosine = (float) Math.cos(radians); - float sine = (float) Math.sin(radians); - switch (axis) { - // Rotation around the red color - case 0: - mArray[6] = mArray[12] = cosine; - mArray[7] = sine; - mArray[11] = -sine; - break; - // Rotation around the green color - case 1: - mArray[0] = mArray[12] = cosine; - mArray[2] = -sine; - mArray[10] = sine; - break; - // Rotation around the blue color - case 2: - mArray[0] = mArray[6] = cosine; - mArray[1] = sine; - mArray[5] = -sine; - break; - default: - throw new RuntimeException(); - } - } - - /** - * Set this colormatrix to the concatenation of the two specified - * colormatrices, such that the resulting colormatrix has the same effect - * as applying matB and then applying matA. - * <p> - * It is legal for either matA or matB to be the same colormatrix as this. - * </p> - */ - public void setConcat(ColorMatrix matA, ColorMatrix matB) { - float[] tmp; - if (matA == this || matB == this) { - tmp = new float[20]; - } else { - tmp = mArray; - } - - final float[] a = matA.mArray; - final float[] b = matB.mArray; - int index = 0; - for (int j = 0; j < 20; j += 5) { - for (int i = 0; i < 4; i++) { - tmp[index++] = a[j + 0] * b[i + 0] + a[j + 1] * b[i + 5] + - a[j + 2] * b[i + 10] + a[j + 3] * b[i + 15]; - } - tmp[index++] = a[j + 0] * b[4] + a[j + 1] * b[9] + - a[j + 2] * b[14] + a[j + 3] * b[19] + - a[j + 4]; - } - - if (tmp != mArray) { - System.arraycopy(tmp, 0, mArray, 0, 20); - } - } - - /** - * Concat this colormatrix with the specified prematrix. - * <p> - * This is logically the same as calling setConcat(this, prematrix); - * </p> - */ - public void preConcat(ColorMatrix prematrix) { - setConcat(this, prematrix); - } - - /** - * Concat this colormatrix with the specified postmatrix. - * <p> - * This is logically the same as calling setConcat(postmatrix, this); - * </p> - */ - public void postConcat(ColorMatrix postmatrix) { - setConcat(postmatrix, this); - } - - /////////////////////////////////////////////////////////////////////////// - - /** - * Set the matrix to affect the saturation of colors. - * - * @param sat A value of 0 maps the color to gray-scale. 1 is identity. - */ - public void setSaturation(float sat) { - reset(); - float[] m = mArray; - - final float invSat = 1 - sat; - final float R = 0.213f * invSat; - final float G = 0.715f * invSat; - final float B = 0.072f * invSat; - - m[0] = R + sat; m[1] = G; m[2] = B; - m[5] = R; m[6] = G + sat; m[7] = B; - m[10] = R; m[11] = G; m[12] = B + sat; - } - - /** - * Set the matrix to convert RGB to YUV - */ - public void setRGB2YUV() { - reset(); - float[] m = mArray; - // these coefficients match those in libjpeg - m[0] = 0.299f; m[1] = 0.587f; m[2] = 0.114f; - m[5] = -0.16874f; m[6] = -0.33126f; m[7] = 0.5f; - m[10] = 0.5f; m[11] = -0.41869f; m[12] = -0.08131f; - } - - /** - * Set the matrix to convert from YUV to RGB - */ - public void setYUV2RGB() { - reset(); - float[] m = mArray; - // these coefficients match those in libjpeg - m[2] = 1.402f; - m[5] = 1; m[6] = -0.34414f; m[7] = -0.71414f; - m[10] = 1; m[11] = 1.772f; m[12] = 0; - } - - @Override - public boolean equals(Object obj) { - // if (obj == this) return true; -- NaN value would mean matrix != itself - if (!(obj instanceof ColorMatrix)) { - return false; - } - - // we don't use Arrays.equals(), since that considers NaN == NaN - final float[] other = ((ColorMatrix) obj).mArray; - for (int i = 0; i < 20; i++) { - if (other[i] != mArray[i]) { - return false; - } - } - return true; - } -} diff --git a/graphics/java/android/graphics/ColorSpace.java b/graphics/java/android/graphics/ColorSpace.java index 1aeafa391b41..2f978fc1fc2d 100644 --- a/graphics/java/android/graphics/ColorSpace.java +++ b/graphics/java/android/graphics/ColorSpace.java @@ -17,19 +17,15 @@ package android.graphics; import android.annotation.AnyThread; -import android.annotation.ColorInt; import android.annotation.IntRange; import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.Size; import android.annotation.SuppressAutoDoc; -import android.util.Pair; import libcore.util.NativeAllocationRegistry; -import java.util.ArrayList; import java.util.Arrays; -import java.util.List; import java.util.function.DoubleUnaryOperator; /** @@ -872,8 +868,7 @@ public abstract class ColorSpace { } } - /** @hide */ - ColorSpace( + /*package*/ ColorSpace( @NonNull String name, @NonNull Model model, @IntRange(from = MIN_ID, to = MAX_ID) int id) { @@ -1441,22 +1436,6 @@ public abstract class ColorSpace { return null; } - /** - * <p>Creates a new {@link Renderer} that can be used to visualize and - * debug color spaces. See the documentation of {@link Renderer} for - * more information.</p> - * - * @return A new non-null {@link Renderer} instance - * - * @see Renderer - * - * @hide - */ - @NonNull - public static Renderer createRenderer() { - return new Renderer(); - } - static { sNamedColorSpaces[Named.SRGB.ordinal()] = new ColorSpace.Rgb( "sRGB IEC61966-2.1", @@ -1701,12 +1680,10 @@ public abstract class ColorSpace { * @param rhs 3x3 matrix, as a non-null array of 9 floats * @return A new array of 9 floats containing the result of the multiplication * of rhs by lhs - * - * @hide */ @NonNull @Size(9) - public static float[] mul3x3(@NonNull @Size(9) float[] lhs, @NonNull @Size(9) float[] rhs) { + private static float[] mul3x3(@NonNull @Size(9) float[] lhs, @NonNull @Size(9) float[] rhs) { float[] r = new float[9]; r[0] = lhs[0] * rhs[0] + lhs[3] * rhs[1] + lhs[6] * rhs[2]; r[1] = lhs[1] * rhs[0] + lhs[4] * rhs[1] + lhs[7] * rhs[2]; @@ -1775,28 +1752,6 @@ public abstract class ColorSpace { } /** - * Converts values from CIE xyY to CIE L*u*v*. Y is assumed to be 1 so the - * input xyY array only contains the x and y components. After this method - * returns, the xyY array contains the converted u and v components. - * - * @param xyY The xyY value to convert to XYZ, cannot be null, - * length must be a multiple of 2 - */ - private static void xyYToUv(@NonNull @Size(multiple = 2) float[] xyY) { - for (int i = 0; i < xyY.length; i += 2) { - float x = xyY[i]; - float y = xyY[i + 1]; - - float d = -2.0f * x + 12.0f * y + 3; - float u = (4.0f * x) / d; - float v = (9.0f * y) / d; - - xyY[i] = u; - xyY[i + 1] = v; - } - } - - /** * <p>Computes the chromatic adaptation transform from the specified * source white point to the specified destination white point.</p> * @@ -1834,8 +1789,6 @@ public abstract class ColorSpace { * @param cct The correlated color temperature, in Kelvin * @return Corresponding XYZ values * @throws IllegalArgumentException If cct is invalid - * - * @hide */ @NonNull @Size(3) @@ -1861,38 +1814,6 @@ public abstract class ColorSpace { } /** - * <p>Computes the chromaticity coordinates of a CIE series D illuminant - * from the specified correlated color temperature (CCT). The specified CCT - * must be greater than 0. A meaningful CCT range is [4000, 25000].</p> - * - * <p>The transform is computed using the methods referred to in Kang et - * al., <i>Design of Advanced Color - Temperature Control System for HDTV - * Applications</i>, Journal of Korean Physical Society 41, 865-871 - * (2002).</p> - * - * @param cct The correlated color temperature, in Kelvin - * @return Corresponding XYZ values - * @throws IllegalArgumentException If cct is invalid - * - * @hide - */ - @NonNull - @Size(3) - public static float[] cctToIlluminantdXyz(@IntRange(from = 1) int cct) { - if (cct < 1) { - throw new IllegalArgumentException("Temperature must be greater than 0"); - } - - final float icct = 1.0f / cct; - final float icct2 = icct * icct; - final float x = cct <= 7000.0f ? - 0.244063f + 0.09911e3f * icct + 2.9678e6f * icct2 - 4.6070e9f * icct2 * icct : - 0.237040f + 0.24748e3f * icct + 1.9018e6f * icct2 - 2.0064e9f * icct2 * icct; - final float y = -3.0f * x * x + 2.87f * x - 0.275f; - return xyYToXyz(new float[] {x, y}); - } - - /** * <p>Computes the chromatic adaptation transform from the specified * source white point to the specified destination white point.</p> * @@ -1905,14 +1826,16 @@ public abstract class ColorSpace { * @param srcWhitePoint The white point to adapt from * @param dstWhitePoint The white point to adapt to * @return A 3x3 matrix as a non-null array of 9 floats - * - * @hide */ @NonNull @Size(9) public static float[] chromaticAdaptation(@NonNull Adaptation adaptation, @NonNull @Size(min = 2, max = 3) float[] srcWhitePoint, @NonNull @Size(min = 2, max = 3) float[] dstWhitePoint) { + if ((srcWhitePoint.length != 2 && srcWhitePoint.length != 3) + || (dstWhitePoint.length != 2 && dstWhitePoint.length != 3)) { + throw new IllegalArgumentException("A white point array must have 2 or 3 floats"); + } float[] srcXyz = srcWhitePoint.length == 3 ? Arrays.copyOf(srcWhitePoint, 3) : xyYToXyz(srcWhitePoint); float[] dstXyz = dstWhitePoint.length == 3 ? @@ -3925,771 +3848,4 @@ public abstract class ColorSpace { }; } } - - /** - * <p>A color space renderer can be used to visualize and compare the gamut and - * white point of one or more color spaces. The output is an sRGB {@link Bitmap} - * showing a CIE 1931 xyY or a CIE 1976 UCS chromaticity diagram.</p> - * - * <p>The following code snippet shows how to compare the {@link Named#SRGB} - * and {@link Named#DCI_P3} color spaces in a CIE 1931 diagram:</p> - * - * <pre class="prettyprint"> - * Bitmap bitmap = ColorSpace.createRenderer() - * .size(768) - * .clip(true) - * .add(ColorSpace.get(ColorSpace.Named.SRGB), 0xffffffff) - * .add(ColorSpace.get(ColorSpace.Named.DCI_P3), 0xffffc845) - * .render(); - * </pre> - * <p> - * <img style="display: block; margin: 0 auto;" src="{@docRoot}reference/android/images/graphics/colorspace_clipped.png" /> - * <figcaption style="text-align: center;">sRGB vs DCI-P3</figcaption> - * </p> - * - * <p>A renderer can also be used to show the location of specific colors, - * associated with a color space, in the CIE 1931 xyY chromaticity diagram. - * See {@link #add(ColorSpace, float, float, float, int)} for more information.</p> - * - * @see ColorSpace#createRenderer() - * - * @hide - */ - public static class Renderer { - private static final int NATIVE_SIZE = 1440; - private static final float UCS_SCALE = 9.0f / 6.0f; - - // Number of subdivision of the inside of the spectral locus - private static final int CHROMATICITY_RESOLUTION = 32; - private static final double ONE_THIRD = 1.0 / 3.0; - - @IntRange(from = 128, to = Integer.MAX_VALUE) - private int mSize = 1024; - - private boolean mShowWhitePoint = true; - private boolean mClip = false; - private boolean mUcs = false; - - private final List<Pair<ColorSpace, Integer>> mColorSpaces = new ArrayList<>(2); - private final List<Point> mPoints = new ArrayList<>(0); - - private Renderer() { - } - - /** - * <p>Defines whether the chromaticity diagram should be clipped by the first - * registered color space. The default value is false.</p> - * - * <p>The following code snippet and image show the default behavior:</p> - * <pre class="prettyprint"> - * Bitmap bitmap = ColorSpace.createRenderer() - * .add(ColorSpace.get(ColorSpace.Named.SRGB), 0xffffffff) - * .add(ColorSpace.get(ColorSpace.Named.DCI_P3), 0xffffc845) - * .render(); - * </pre> - * <p> - * <img style="display: block; margin: 0 auto;" src="{@docRoot}reference/android/images/graphics/colorspace_comparison.png" /> - * <figcaption style="text-align: center;">Clipping disabled</figcaption> - * </p> - * - * <p>Here is the same example with clipping enabled:</p> - * <pre class="prettyprint"> - * Bitmap bitmap = ColorSpace.createRenderer() - * .clip(true) - * .add(ColorSpace.get(ColorSpace.Named.SRGB), 0xffffffff) - * .add(ColorSpace.get(ColorSpace.Named.DCI_P3), 0xffffc845) - * .render(); - * </pre> - * <p> - * <img style="display: block; margin: 0 auto;" src="{@docRoot}reference/android/images/graphics/colorspace_clipped.png" /> - * <figcaption style="text-align: center;">Clipping enabled</figcaption> - * </p> - * - * @param clip True to clip the chromaticity diagram to the first registered color space, - * false otherwise - * @return This instance of {@link Renderer} - */ - @NonNull - public Renderer clip(boolean clip) { - mClip = clip; - return this; - } - - /** - * <p>Defines whether the chromaticity diagram should use the uniform - * chromaticity scale (CIE 1976 UCS). When the uniform chromaticity scale - * is used, the distance between two points on the diagram is approximately - * proportional to the perceived color difference.</p> - * - * <p>The following code snippet shows how to enable the uniform chromaticity - * scale. The image below shows the result:</p> - * <pre class="prettyprint"> - * Bitmap bitmap = ColorSpace.createRenderer() - * .uniformChromaticityScale(true) - * .add(ColorSpace.get(ColorSpace.Named.SRGB), 0xffffffff) - * .add(ColorSpace.get(ColorSpace.Named.DCI_P3), 0xffffc845) - * .render(); - * </pre> - * <p> - * <img style="display: block; margin: 0 auto;" src="{@docRoot}reference/android/images/graphics/colorspace_ucs.png" /> - * <figcaption style="text-align: center;">CIE 1976 UCS diagram</figcaption> - * </p> - * - * @param ucs True to render the chromaticity diagram as the CIE 1976 UCS diagram - * @return This instance of {@link Renderer} - */ - @NonNull - public Renderer uniformChromaticityScale(boolean ucs) { - mUcs = ucs; - return this; - } - - /** - * Sets the dimensions (width and height) in pixels of the output bitmap. - * The size must be at least 128px and defaults to 1024px. - * - * @param size The size in pixels of the output bitmap - * @return This instance of {@link Renderer} - */ - @NonNull - public Renderer size(@IntRange(from = 128, to = Integer.MAX_VALUE) int size) { - mSize = Math.max(128, size); - return this; - } - - /** - * Shows or hides the white point of each color space in the output bitmap. - * The default is true. - * - * @param show True to show the white point of each color space, false - * otherwise - * @return This instance of {@link Renderer} - */ - @NonNull - public Renderer showWhitePoint(boolean show) { - mShowWhitePoint = show; - return this; - } - - /** - * <p>Adds a color space to represent on the output CIE 1931 chromaticity - * diagram. The color space is represented as a triangle showing the - * footprint of its color gamut and, optionally, the location of its - * white point.</p> - * - * <p class="note">Color spaces with a color model that is not RGB are - * accepted but ignored.</p> - * - * <p>The following code snippet and image show an example of calling this - * method to compare {@link Named#SRGB sRGB} and {@link Named#DCI_P3 DCI-P3}:</p> - * <pre class="prettyprint"> - * Bitmap bitmap = ColorSpace.createRenderer() - * .add(ColorSpace.get(ColorSpace.Named.SRGB), 0xffffffff) - * .add(ColorSpace.get(ColorSpace.Named.DCI_P3), 0xffffc845) - * .render(); - * </pre> - * <p> - * <img style="display: block; margin: 0 auto;" src="{@docRoot}reference/android/images/graphics/colorspace_comparison.png" /> - * <figcaption style="text-align: center;">sRGB vs DCI-P3</figcaption> - * </p> - * - * <p>Adding a color space extending beyond the boundaries of the - * spectral locus will alter the size of the diagram within the output - * bitmap as shown in this example:</p> - * <pre class="prettyprint"> - * Bitmap bitmap = ColorSpace.createRenderer() - * .add(ColorSpace.get(ColorSpace.Named.SRGB), 0xffffffff) - * .add(ColorSpace.get(ColorSpace.Named.DCI_P3), 0xffffc845) - * .add(ColorSpace.get(ColorSpace.Named.ACES), 0xff097ae9) - * .add(ColorSpace.get(ColorSpace.Named.EXTENDED_SRGB), 0xff000000) - * .render(); - * </pre> - * <p> - * <img style="display: block; margin: 0 auto;" src="{@docRoot}reference/android/images/graphics/colorspace_comparison2.png" /> - * <figcaption style="text-align: center;">sRGB, DCI-P3, ACES and scRGB</figcaption> - * </p> - * - * @param colorSpace The color space whose gamut to render on the diagram - * @param color The sRGB color to use to render the color space's gamut and white point - * @return This instance of {@link Renderer} - * - * @see #clip(boolean) - * @see #showWhitePoint(boolean) - */ - @NonNull - public Renderer add(@NonNull ColorSpace colorSpace, @ColorInt int color) { - mColorSpaces.add(new Pair<>(colorSpace, color)); - return this; - } - - /** - * <p>Adds a color to represent as a point on the chromaticity diagram. - * The color is associated with a color space which will be used to - * perform the conversion to CIE XYZ and compute the location of the point - * on the diagram. The point is rendered as a colored circle.</p> - * - * <p>The following code snippet and image show an example of calling this - * method to render the location of several sRGB colors as white circles:</p> - * <pre class="prettyprint"> - * Bitmap bitmap = ColorSpace.createRenderer() - * .clip(true) - * .add(ColorSpace.get(ColorSpace.Named.SRGB), 0xffffffff) - * .add(ColorSpace.get(ColorSpace.Named.SRGB), 0.1f, 0.0f, 0.1f, 0xffffffff) - * .add(ColorSpace.get(ColorSpace.Named.SRGB), 0.1f, 0.1f, 0.1f, 0xffffffff) - * .add(ColorSpace.get(ColorSpace.Named.SRGB), 0.1f, 0.2f, 0.1f, 0xffffffff) - * .add(ColorSpace.get(ColorSpace.Named.SRGB), 0.1f, 0.3f, 0.1f, 0xffffffff) - * .add(ColorSpace.get(ColorSpace.Named.SRGB), 0.1f, 0.4f, 0.1f, 0xffffffff) - * .add(ColorSpace.get(ColorSpace.Named.SRGB), 0.1f, 0.5f, 0.1f, 0xffffffff) - * .render(); - * </pre> - * <p> - * <img style="display: block; margin: 0 auto;" src="{@docRoot}reference/android/images/graphics/colorspace_points.png" /> - * <figcaption style="text-align: center;"> - * Locating colors on the chromaticity diagram - * </figcaption> - * </p> - * - * @param colorSpace The color space of the color to locate on the diagram - * @param r The first component of the color to locate on the diagram - * @param g The second component of the color to locate on the diagram - * @param b The third component of the color to locate on the diagram - * @param pointColor The sRGB color to use to render the point on the diagram - * @return This instance of {@link Renderer} - */ - @NonNull - public Renderer add(@NonNull ColorSpace colorSpace, float r, float g, float b, - @ColorInt int pointColor) { - mPoints.add(new Point(colorSpace, new float[] { r, g, b }, pointColor)); - return this; - } - - /** - * <p>Renders the {@link #add(ColorSpace, int) color spaces} and - * {@link #add(ColorSpace, float, float, float, int) points} registered - * with this renderer. The output bitmap is an sRGB image with the - * dimensions specified by calling {@link #size(int)} (1204x1024px by - * default).</p> - * - * @return A new non-null {@link Bitmap} with the dimensions specified - * by {@link #size(int)} (1024x1024 by default) - */ - @NonNull - public Bitmap render() { - Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG); - Bitmap bitmap = Bitmap.createBitmap(mSize, mSize, Bitmap.Config.ARGB_8888); - Canvas canvas = new Canvas(bitmap); - - float[] primaries = new float[6]; - float[] whitePoint = new float[2]; - - int width = NATIVE_SIZE; - int height = NATIVE_SIZE; - - Path path = new Path(); - - setTransform(canvas, width, height, primaries); - drawBox(canvas, width, height, paint, path); - setUcsTransform(canvas, height); - drawLocus(canvas, width, height, paint, path, primaries); - drawGamuts(canvas, width, height, paint, path, primaries, whitePoint); - drawPoints(canvas, width, height, paint); - - return bitmap; - } - - /** - * Draws registered points at their correct position in the xyY coordinates. - * Each point is positioned according to its associated color space. - * - * @param canvas The canvas to transform - * @param width Width in pixel of the final image - * @param height Height in pixel of the final image - * @param paint A pre-allocated paint used to avoid temporary allocations - */ - private void drawPoints(@NonNull Canvas canvas, int width, int height, - @NonNull Paint paint) { - - paint.setStyle(Paint.Style.FILL); - - float radius = 4.0f / (mUcs ? UCS_SCALE : 1.0f); - - float[] v = new float[3]; - float[] xy = new float[2]; - - for (final Point point : mPoints) { - v[0] = point.mRgb[0]; - v[1] = point.mRgb[1]; - v[2] = point.mRgb[2]; - point.mColorSpace.toXyz(v); - - paint.setColor(point.mColor); - - // XYZ to xyY, assuming Y=1.0, then to L*u*v* if needed - float sum = v[0] + v[1] + v[2]; - xy[0] = v[0] / sum; - xy[1] = v[1] / sum; - if (mUcs) xyYToUv(xy); - - canvas.drawCircle(width * xy[0], height - height * xy[1], radius, paint); - } - } - - /** - * Draws the color gamuts and white points of all the registered color - * spaces. Only color spaces with an RGB color model are rendered, the - * others are ignored. - * - * @param canvas The canvas to transform - * @param width Width in pixel of the final image - * @param height Height in pixel of the final image - * @param paint A pre-allocated paint used to avoid temporary allocations - * @param path A pre-allocated path used to avoid temporary allocations - * @param primaries A pre-allocated array of 6 floats to avoid temporary allocations - * @param whitePoint A pre-allocated array of 2 floats to avoid temporary allocations - */ - private void drawGamuts( - @NonNull Canvas canvas, int width, int height, - @NonNull Paint paint, @NonNull Path path, - @NonNull @Size(6) float[] primaries, @NonNull @Size(2) float[] whitePoint) { - - float radius = 4.0f / (mUcs ? UCS_SCALE : 1.0f); - - for (final Pair<ColorSpace, Integer> item : mColorSpaces) { - ColorSpace colorSpace = item.first; - int color = item.second; - - if (colorSpace.getModel() != Model.RGB) continue; - - Rgb rgb = (Rgb) colorSpace; - getPrimaries(rgb, primaries, mUcs); - - path.rewind(); - path.moveTo(width * primaries[0], height - height * primaries[1]); - path.lineTo(width * primaries[2], height - height * primaries[3]); - path.lineTo(width * primaries[4], height - height * primaries[5]); - path.close(); - - paint.setStyle(Paint.Style.STROKE); - paint.setColor(color); - canvas.drawPath(path, paint); - - // Draw the white point - if (mShowWhitePoint) { - rgb.getWhitePoint(whitePoint); - if (mUcs) xyYToUv(whitePoint); - - paint.setStyle(Paint.Style.FILL); - paint.setColor(color); - canvas.drawCircle( - width * whitePoint[0], height - height * whitePoint[1], radius, paint); - } - } - } - - /** - * Returns the primaries of the specified RGB color space. This method handles - * the special case of the {@link Named#EXTENDED_SRGB} family of color spaces. - * - * @param rgb The color space whose primaries to extract - * @param primaries A pre-allocated array of 6 floats that will hold the result - * @param asUcs True if the primaries should be returned in Luv, false for xyY - */ - @NonNull - @Size(6) - private static void getPrimaries(@NonNull Rgb rgb, - @NonNull @Size(6) float[] primaries, boolean asUcs) { - // TODO: We should find a better way to handle these cases - if (rgb.equals(ColorSpace.get(Named.EXTENDED_SRGB)) || - rgb.equals(ColorSpace.get(Named.LINEAR_EXTENDED_SRGB))) { - primaries[0] = 1.41f; - primaries[1] = 0.33f; - primaries[2] = 0.27f; - primaries[3] = 1.24f; - primaries[4] = -0.23f; - primaries[5] = -0.57f; - } else { - rgb.getPrimaries(primaries); - } - if (asUcs) xyYToUv(primaries); - } - - /** - * Draws the CIE 1931 chromaticity diagram: the spectral locus and its inside. - * This method respect the clip parameter. - * - * @param canvas The canvas to transform - * @param width Width in pixel of the final image - * @param height Height in pixel of the final image - * @param paint A pre-allocated paint used to avoid temporary allocations - * @param path A pre-allocated path used to avoid temporary allocations - * @param primaries A pre-allocated array of 6 floats to avoid temporary allocations - */ - private void drawLocus( - @NonNull Canvas canvas, int width, int height, @NonNull Paint paint, - @NonNull Path path, @NonNull @Size(6) float[] primaries) { - - int vertexCount = SPECTRUM_LOCUS_X.length * CHROMATICITY_RESOLUTION * 6; - float[] vertices = new float[vertexCount * 2]; - int[] colors = new int[vertices.length]; - computeChromaticityMesh(vertices, colors); - - if (mUcs) xyYToUv(vertices); - for (int i = 0; i < vertices.length; i += 2) { - vertices[i] *= width; - vertices[i + 1] = height - vertices[i + 1] * height; - } - - // Draw the spectral locus - if (mClip && mColorSpaces.size() > 0) { - for (final Pair<ColorSpace, Integer> item : mColorSpaces) { - ColorSpace colorSpace = item.first; - if (colorSpace.getModel() != Model.RGB) continue; - - Rgb rgb = (Rgb) colorSpace; - getPrimaries(rgb, primaries, mUcs); - - break; - } - - path.rewind(); - path.moveTo(width * primaries[0], height - height * primaries[1]); - path.lineTo(width * primaries[2], height - height * primaries[3]); - path.lineTo(width * primaries[4], height - height * primaries[5]); - path.close(); - - int[] solid = new int[colors.length]; - Arrays.fill(solid, 0xff6c6c6c); - canvas.drawVertices(Canvas.VertexMode.TRIANGLES, vertices.length, vertices, 0, - null, 0, solid, 0, null, 0, 0, paint); - - canvas.save(); - canvas.clipPath(path); - - canvas.drawVertices(Canvas.VertexMode.TRIANGLES, vertices.length, vertices, 0, - null, 0, colors, 0, null, 0, 0, paint); - - canvas.restore(); - } else { - canvas.drawVertices(Canvas.VertexMode.TRIANGLES, vertices.length, vertices, 0, - null, 0, colors, 0, null, 0, 0, paint); - } - - // Draw the non-spectral locus - int index = (CHROMATICITY_RESOLUTION - 1) * 12; - path.reset(); - path.moveTo(vertices[index], vertices[index + 1]); - for (int x = 2; x < SPECTRUM_LOCUS_X.length; x++) { - index += CHROMATICITY_RESOLUTION * 12; - path.lineTo(vertices[index], vertices[index + 1]); - } - path.close(); - - paint.setStrokeWidth(4.0f / (mUcs ? UCS_SCALE : 1.0f)); - paint.setStyle(Paint.Style.STROKE); - paint.setColor(0xff000000); - canvas.drawPath(path, paint); - } - - /** - * Draws the diagram box, including borders, tick marks, grid lines - * and axis labels. - * - * @param canvas The canvas to transform - * @param width Width in pixel of the final image - * @param height Height in pixel of the final image - * @param paint A pre-allocated paint used to avoid temporary allocations - * @param path A pre-allocated path used to avoid temporary allocations - */ - private void drawBox(@NonNull Canvas canvas, int width, int height, @NonNull Paint paint, - @NonNull Path path) { - - int lineCount = 10; - float scale = 1.0f; - if (mUcs) { - lineCount = 7; - scale = UCS_SCALE; - } - - // Draw the unit grid - paint.setStyle(Paint.Style.STROKE); - paint.setStrokeWidth(2.0f); - paint.setColor(0xffc0c0c0); - - for (int i = 1; i < lineCount - 1; i++) { - float v = i / 10.0f; - float x = (width * v) * scale; - float y = height - (height * v) * scale; - - canvas.drawLine(0.0f, y, 0.9f * width, y, paint); - canvas.drawLine(x, height, x, 0.1f * height, paint); - } - - // Draw tick marks - paint.setStrokeWidth(4.0f); - paint.setColor(0xff000000); - for (int i = 1; i < lineCount - 1; i++) { - float v = i / 10.0f; - float x = (width * v) * scale; - float y = height - (height * v) * scale; - - canvas.drawLine(0.0f, y, width / 100.0f, y, paint); - canvas.drawLine(x, height, x, height - (height / 100.0f), paint); - } - - // Draw the axis labels - paint.setStyle(Paint.Style.FILL); - paint.setTextSize(36.0f); - paint.setTypeface(Typeface.create("sans-serif-light", Typeface.NORMAL)); - - Rect bounds = new Rect(); - for (int i = 1; i < lineCount - 1; i++) { - String text = "0." + i; - paint.getTextBounds(text, 0, text.length(), bounds); - - float v = i / 10.0f; - float x = (width * v) * scale; - float y = height - (height * v) * scale; - - canvas.drawText(text, -0.05f * width + 10, y + bounds.height() / 2.0f, paint); - canvas.drawText(text, x - bounds.width() / 2.0f, - height + bounds.height() + 16, paint); - } - paint.setStyle(Paint.Style.STROKE); - - // Draw the diagram box - path.moveTo(0.0f, height); - path.lineTo(0.9f * width, height); - path.lineTo(0.9f * width, 0.1f * height); - path.lineTo(0.0f, 0.1f * height); - path.close(); - canvas.drawPath(path, paint); - } - - /** - * Computes and applies the Canvas transforms required to make the color - * gamut of each color space visible in the final image. - * - * @param canvas The canvas to transform - * @param width Width in pixel of the final image - * @param height Height in pixel of the final image - * @param primaries Array of 6 floats used to avoid temporary allocations - */ - private void setTransform(@NonNull Canvas canvas, int width, int height, - @NonNull @Size(6) float[] primaries) { - - RectF primariesBounds = new RectF(); - for (final Pair<ColorSpace, Integer> item : mColorSpaces) { - ColorSpace colorSpace = item.first; - if (colorSpace.getModel() != Model.RGB) continue; - - Rgb rgb = (Rgb) colorSpace; - getPrimaries(rgb, primaries, mUcs); - - primariesBounds.left = Math.min(primariesBounds.left, primaries[4]); - primariesBounds.top = Math.min(primariesBounds.top, primaries[5]); - primariesBounds.right = Math.max(primariesBounds.right, primaries[0]); - primariesBounds.bottom = Math.max(primariesBounds.bottom, primaries[3]); - } - - float max = mUcs ? 0.6f : 0.9f; - - primariesBounds.left = Math.min(0.0f, primariesBounds.left); - primariesBounds.top = Math.min(0.0f, primariesBounds.top); - primariesBounds.right = Math.max(max, primariesBounds.right); - primariesBounds.bottom = Math.max(max, primariesBounds.bottom); - - float scaleX = max / primariesBounds.width(); - float scaleY = max / primariesBounds.height(); - float scale = Math.min(scaleX, scaleY); - - canvas.scale(mSize / (float) NATIVE_SIZE, mSize / (float) NATIVE_SIZE); - canvas.scale(scale, scale); - canvas.translate( - (primariesBounds.width() - max) * width / 2.0f, - (primariesBounds.height() - max) * height / 2.0f); - - // The spectrum extends ~0.85 vertically and ~0.65 horizontally - // We shift the canvas a little bit to get nicer margins - canvas.translate(0.05f * width, -0.05f * height); - } - - /** - * Computes and applies the Canvas transforms required to render the CIE - * 197 UCS chromaticity diagram. - * - * @param canvas The canvas to transform - * @param height Height in pixel of the final image - */ - private void setUcsTransform(@NonNull Canvas canvas, int height) { - if (mUcs) { - canvas.translate(0.0f, (height - height * UCS_SCALE)); - canvas.scale(UCS_SCALE, UCS_SCALE); - } - } - - // X coordinates of the spectral locus in CIE 1931 - private static final float[] SPECTRUM_LOCUS_X = { - 0.175596f, 0.172787f, 0.170806f, 0.170085f, 0.160343f, - 0.146958f, 0.139149f, 0.133536f, 0.126688f, 0.115830f, - 0.109616f, 0.099146f, 0.091310f, 0.078130f, 0.068717f, - 0.054675f, 0.040763f, 0.027497f, 0.016270f, 0.008169f, - 0.004876f, 0.003983f, 0.003859f, 0.004646f, 0.007988f, - 0.013870f, 0.022244f, 0.027273f, 0.032820f, 0.038851f, - 0.045327f, 0.052175f, 0.059323f, 0.066713f, 0.074299f, - 0.089937f, 0.114155f, 0.138695f, 0.154714f, 0.192865f, - 0.229607f, 0.265760f, 0.301588f, 0.337346f, 0.373083f, - 0.408717f, 0.444043f, 0.478755f, 0.512467f, 0.544767f, - 0.575132f, 0.602914f, 0.627018f, 0.648215f, 0.665746f, - 0.680061f, 0.691487f, 0.700589f, 0.707901f, 0.714015f, - 0.719017f, 0.723016f, 0.734674f, 0.717203f, 0.699732f, - 0.682260f, 0.664789f, 0.647318f, 0.629847f, 0.612376f, - 0.594905f, 0.577433f, 0.559962f, 0.542491f, 0.525020f, - 0.507549f, 0.490077f, 0.472606f, 0.455135f, 0.437664f, - 0.420193f, 0.402721f, 0.385250f, 0.367779f, 0.350308f, - 0.332837f, 0.315366f, 0.297894f, 0.280423f, 0.262952f, - 0.245481f, 0.228010f, 0.210538f, 0.193067f, 0.175596f - }; - // Y coordinates of the spectral locus in CIE 1931 - private static final float[] SPECTRUM_LOCUS_Y = { - 0.005295f, 0.004800f, 0.005472f, 0.005976f, 0.014496f, - 0.026643f, 0.035211f, 0.042704f, 0.053441f, 0.073601f, - 0.086866f, 0.112037f, 0.132737f, 0.170464f, 0.200773f, - 0.254155f, 0.317049f, 0.387997f, 0.463035f, 0.538504f, - 0.587196f, 0.610526f, 0.654897f, 0.675970f, 0.715407f, - 0.750246f, 0.779682f, 0.792153f, 0.802971f, 0.812059f, - 0.819430f, 0.825200f, 0.829460f, 0.832306f, 0.833833f, - 0.833316f, 0.826231f, 0.814796f, 0.805884f, 0.781648f, - 0.754347f, 0.724342f, 0.692326f, 0.658867f, 0.624470f, - 0.589626f, 0.554734f, 0.520222f, 0.486611f, 0.454454f, - 0.424252f, 0.396516f, 0.372510f, 0.351413f, 0.334028f, - 0.319765f, 0.308359f, 0.299317f, 0.292044f, 0.285945f, - 0.280951f, 0.276964f, 0.265326f, 0.257200f, 0.249074f, - 0.240948f, 0.232822f, 0.224696f, 0.216570f, 0.208444f, - 0.200318f, 0.192192f, 0.184066f, 0.175940f, 0.167814f, - 0.159688f, 0.151562f, 0.143436f, 0.135311f, 0.127185f, - 0.119059f, 0.110933f, 0.102807f, 0.094681f, 0.086555f, - 0.078429f, 0.070303f, 0.062177f, 0.054051f, 0.045925f, - 0.037799f, 0.029673f, 0.021547f, 0.013421f, 0.005295f - }; - - /** - * Computes a 2D mesh representation of the CIE 1931 chromaticity - * diagram. - * - * @param vertices Array of floats that will hold the mesh vertices - * @param colors Array of floats that will hold the mesh colors - */ - private static void computeChromaticityMesh(@NonNull float[] vertices, - @NonNull int[] colors) { - - ColorSpace colorSpace = get(Named.SRGB); - - float[] color = new float[3]; - - int vertexIndex = 0; - int colorIndex = 0; - - for (int x = 0; x < SPECTRUM_LOCUS_X.length; x++) { - int nextX = (x % (SPECTRUM_LOCUS_X.length - 1)) + 1; - - float a1 = (float) Math.atan2( - SPECTRUM_LOCUS_Y[x] - ONE_THIRD, - SPECTRUM_LOCUS_X[x] - ONE_THIRD); - float a2 = (float) Math.atan2( - SPECTRUM_LOCUS_Y[nextX] - ONE_THIRD, - SPECTRUM_LOCUS_X[nextX] - ONE_THIRD); - - float radius1 = (float) Math.pow( - sqr(SPECTRUM_LOCUS_X[x] - ONE_THIRD) + - sqr(SPECTRUM_LOCUS_Y[x] - ONE_THIRD), - 0.5); - float radius2 = (float) Math.pow( - sqr(SPECTRUM_LOCUS_X[nextX] - ONE_THIRD) + - sqr(SPECTRUM_LOCUS_Y[nextX] - ONE_THIRD), - 0.5); - - // Compute patches; each patch is a quad with a different - // color associated with each vertex - for (int c = 1; c <= CHROMATICITY_RESOLUTION; c++) { - float f1 = c / (float) CHROMATICITY_RESOLUTION; - float f2 = (c - 1) / (float) CHROMATICITY_RESOLUTION; - - double cr1 = radius1 * Math.cos(a1); - double sr1 = radius1 * Math.sin(a1); - double cr2 = radius2 * Math.cos(a2); - double sr2 = radius2 * Math.sin(a2); - - // Compute the XYZ coordinates of the 4 vertices of the patch - float v1x = (float) (ONE_THIRD + cr1 * f1); - float v1y = (float) (ONE_THIRD + sr1 * f1); - float v1z = 1 - v1x - v1y; - - float v2x = (float) (ONE_THIRD + cr1 * f2); - float v2y = (float) (ONE_THIRD + sr1 * f2); - float v2z = 1 - v2x - v2y; - - float v3x = (float) (ONE_THIRD + cr2 * f2); - float v3y = (float) (ONE_THIRD + sr2 * f2); - float v3z = 1 - v3x - v3y; - - float v4x = (float) (ONE_THIRD + cr2 * f1); - float v4y = (float) (ONE_THIRD + sr2 * f1); - float v4z = 1 - v4x - v4y; - - // Compute the sRGB representation of each XYZ coordinate of the patch - colors[colorIndex ] = computeColor(color, v1x, v1y, v1z, colorSpace); - colors[colorIndex + 1] = computeColor(color, v2x, v2y, v2z, colorSpace); - colors[colorIndex + 2] = computeColor(color, v3x, v3y, v3z, colorSpace); - colors[colorIndex + 3] = colors[colorIndex]; - colors[colorIndex + 4] = colors[colorIndex + 2]; - colors[colorIndex + 5] = computeColor(color, v4x, v4y, v4z, colorSpace); - colorIndex += 6; - - // Flip the mesh upside down to match Canvas' coordinates system - vertices[vertexIndex++] = v1x; - vertices[vertexIndex++] = v1y; - vertices[vertexIndex++] = v2x; - vertices[vertexIndex++] = v2y; - vertices[vertexIndex++] = v3x; - vertices[vertexIndex++] = v3y; - vertices[vertexIndex++] = v1x; - vertices[vertexIndex++] = v1y; - vertices[vertexIndex++] = v3x; - vertices[vertexIndex++] = v3y; - vertices[vertexIndex++] = v4x; - vertices[vertexIndex++] = v4y; - } - } - } - - @ColorInt - private static int computeColor(@NonNull @Size(3) float[] color, - float x, float y, float z, @NonNull ColorSpace cs) { - color[0] = x; - color[1] = y; - color[2] = z; - cs.fromXyz(color); - return 0xff000000 | - (((int) (color[0] * 255.0f) & 0xff) << 16) | - (((int) (color[1] * 255.0f) & 0xff) << 8) | - (((int) (color[2] * 255.0f) & 0xff) ); - } - - private static double sqr(double v) { - return v * v; - } - - private static class Point { - @NonNull final ColorSpace mColorSpace; - @NonNull final float[] mRgb; - final int mColor; - - Point(@NonNull ColorSpace colorSpace, - @NonNull @Size(3) float[] rgb, @ColorInt int color) { - mColorSpace = colorSpace; - mRgb = rgb; - mColor = color; - } - } - } } diff --git a/graphics/java/android/graphics/Compatibility.java b/graphics/java/android/graphics/Compatibility.java new file mode 100644 index 000000000000..ed849127aedc --- /dev/null +++ b/graphics/java/android/graphics/Compatibility.java @@ -0,0 +1,51 @@ +/* + * Copyright 2020 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.SystemApi; + +/** + * Helper class for graphics classes to retrieve the targetSdkVersion, as + * specified by the app. + * @hide + */ +@SystemApi(client = SystemApi.Client.MODULE_LIBRARIES) +public final class Compatibility { + private Compatibility() {} + + private static int sTargetSdkVersion = 0; + + /** + * Exposed so that ActivityThread can set it correctly once when binding the + * application. No other code should call this. + * @hide + */ + @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES) + public static void setTargetSdkVersion(int targetSdkVersion) { + sTargetSdkVersion = targetSdkVersion; + Canvas.setCompatibilityVersion(targetSdkVersion); + } + + /** + * Public for access by other packages in the module (like android.graphics.drawable), + * but should not be accessed outside the module. + * @hide + */ + public static int getTargetSdkVersion() { + return sTargetSdkVersion; + } +} diff --git a/graphics/java/android/graphics/ComposeShader.java b/graphics/java/android/graphics/ComposeShader.java index 64ee6bf1f30c..279e2937a80a 100644 --- a/graphics/java/android/graphics/ComposeShader.java +++ b/graphics/java/android/graphics/ComposeShader.java @@ -84,8 +84,9 @@ public class ComposeShader extends Shader { mPorterDuffMode = nativeMode; } + /** @hide */ @Override - long createNativeInstance(long nativeMatrix) { + protected long createNativeInstance(long nativeMatrix) { mNativeInstanceShaderA = mShaderA.getNativeInstance(); mNativeInstanceShaderB = mShaderB.getNativeInstance(); return nativeCreate(nativeMatrix, diff --git a/graphics/java/android/graphics/GraphicBuffer.java b/graphics/java/android/graphics/GraphicBuffer.java index 0430847857b6..2c25f4546771 100644 --- a/graphics/java/android/graphics/GraphicBuffer.java +++ b/graphics/java/android/graphics/GraphicBuffer.java @@ -97,20 +97,6 @@ public class GraphicBuffer implements Parcelable { } /** - * For SurfaceControl JNI. - * @hide - */ - @UnsupportedAppUsage - public static GraphicBuffer createFromExisting(int width, int height, - int format, int usage, long unwrappedNativeObject) { - long nativeObject = nWrapGraphicBuffer(unwrappedNativeObject); - if (nativeObject != 0) { - return new GraphicBuffer(width, height, format, usage, nativeObject); - } - return null; - } - - /** * For Bitmap until all usages are updated to AHB * @hide */ @@ -313,6 +299,5 @@ public class GraphicBuffer implements Parcelable { private static native long nReadGraphicBufferFromParcel(Parcel in); private static native boolean nLockCanvas(long nativeObject, Canvas canvas, Rect dirty); private static native boolean nUnlockCanvasAndPost(long nativeObject, Canvas canvas); - private static native long nWrapGraphicBuffer(long nativeObject); private static native GraphicBuffer nCreateFromHardwareBuffer(HardwareBuffer buffer); } diff --git a/graphics/java/android/graphics/GraphicsProtos.java b/graphics/java/android/graphics/GraphicsProtos.java new file mode 100644 index 000000000000..6bc41d39ff98 --- /dev/null +++ b/graphics/java/android/graphics/GraphicsProtos.java @@ -0,0 +1,48 @@ +/* + * Copyright 2020 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.util.proto.ProtoOutputStream; + +/** + * Utility class for creating protos from parcelable Graphics classes. + * + * @hide + */ +public final class GraphicsProtos { + /** GraphicsProtos can never be an instance */ + private GraphicsProtos() {} + + /** + * Write to a protocol buffer output stream. + * Protocol buffer message definition at {@link android.graphics.PointProto} + * + * @param point Point to serialize into a protocol buffer + * @param protoOutputStream Stream to write the Point object to. + * @param fieldId Field Id of the Point as defined in the parent message + * @hide + */ + public static void dumpPointProto( + @NonNull Point point, @NonNull ProtoOutputStream protoOutputStream, long fieldId) { + final long token = protoOutputStream.start(fieldId); + protoOutputStream.write(PointProto.X, point.x); + protoOutputStream.write(PointProto.Y, point.y); + protoOutputStream.end(token); + } +} + diff --git a/graphics/java/android/graphics/HardwareRenderer.java b/graphics/java/android/graphics/HardwareRenderer.java index d08bfcf45a5c..6dd1f9939989 100644 --- a/graphics/java/android/graphics/HardwareRenderer.java +++ b/graphics/java/android/graphics/HardwareRenderer.java @@ -22,26 +22,33 @@ import android.annotation.NonNull; import android.annotation.Nullable; import android.app.Activity; import android.app.ActivityManager; +import android.content.Context; +import android.content.res.Configuration; +import android.hardware.display.DisplayManager; import android.os.IBinder; import android.os.ParcelFileDescriptor; import android.os.RemoteException; import android.os.ServiceManager; import android.util.Log; import android.util.TimeUtils; +import android.view.Display; +import android.view.Display.Mode; import android.view.IGraphicsStats; import android.view.IGraphicsStatsCallback; import android.view.NativeVectorDrawableAnimator; import android.view.PixelCopy; import android.view.Surface; import android.view.SurfaceHolder; -import android.view.TextureLayer; import android.view.animation.AnimationUtils; import java.io.File; import java.io.FileDescriptor; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; +import java.util.Arrays; +import java.util.Optional; import java.util.concurrent.Executor; +import java.util.stream.Stream; import sun.misc.Cleaner; @@ -143,6 +150,8 @@ public class HardwareRenderer { private static final String CACHE_PATH_SHADERS = "com.android.opengl.shaders_cache"; private static final String CACHE_PATH_SKIASHADERS = "com.android.skia.shaders_cache"; + private static int sDensityDpi = 0; + private final long mNativeProxy; /** @hide */ protected RenderNode mRootNode; @@ -155,6 +164,7 @@ public class HardwareRenderer { * to opaque with no light source configured. */ public HardwareRenderer() { + ProcessInitializer.sInstance.initDisplayInfo(); mRootNode = RenderNode.adopt(nCreateRootRenderNode()); mRootNode.setClipToBounds(false); mNativeProxy = nCreateProxy(!mOpaque, mIsWideGamut, mRootNode.mNativeRenderNode); @@ -904,6 +914,20 @@ public class HardwareRenderer { */ public static void setIsolatedProcess(boolean isIsolated) { nSetIsolatedProcess(isIsolated); + ProcessInitializer.sInstance.setIsolated(isIsolated); + } + + /** + * Sends device configuration changes to the render thread, for rendering profiling views. + * + * @hide + */ + public static void sendDeviceConfigurationForDebugging(Configuration config) { + if (config.densityDpi != Configuration.DENSITY_DPI_UNDEFINED + && config.densityDpi != sDensityDpi) { + sDensityDpi = config.densityDpi; + nSetDisplayDensityDpi(config.densityDpi); + } } /** @@ -975,6 +999,17 @@ public class HardwareRenderer { ProcessInitializer.sInstance.setPackageName(packageName); } + /** + * Gets a context for process initialization + * + * TODO: Remove this once there is a static method for retrieving an application's context. + * + * @hide + */ + public static void setContextForInit(Context context) { + ProcessInitializer.sInstance.setContext(context); + } + private static final class DestroyContextRunnable implements Runnable { private final long mNativeInstance; @@ -991,8 +1026,35 @@ public class HardwareRenderer { private static class ProcessInitializer { static ProcessInitializer sInstance = new ProcessInitializer(); + // Magic values from android/data_space.h + private static final int INTERNAL_DATASPACE_SRGB = 142671872; + private static final int INTERNAL_DATASPACE_DISPLAY_P3 = 143261696; + private static final int INTERNAL_DATASPACE_SCRGB = 411107328; + + private enum Dataspace { + DISPLAY_P3(ColorSpace.Named.DISPLAY_P3, INTERNAL_DATASPACE_DISPLAY_P3), + SCRGB(ColorSpace.Named.EXTENDED_SRGB, INTERNAL_DATASPACE_SCRGB), + SRGB(ColorSpace.Named.SRGB, INTERNAL_DATASPACE_SRGB); + + private final ColorSpace.Named mColorSpace; + private final int mNativeDataspace; + Dataspace(ColorSpace.Named colorSpace, int nativeDataspace) { + this.mColorSpace = colorSpace; + this.mNativeDataspace = nativeDataspace; + } + + static Optional<Dataspace> find(ColorSpace colorSpace) { + return Stream.of(Dataspace.values()) + .filter(d -> ColorSpace.get(d.mColorSpace).equals(colorSpace)) + .findFirst(); + } + } + private boolean mInitialized = false; + private boolean mDisplayInitialized = false; + private boolean mIsolated = false; + private Context mContext; private String mPackageName; private IGraphicsStats mGraphicsStatsService; private IGraphicsStatsCallback mGraphicsStatsCallback = new IGraphicsStatsCallback.Stub() { @@ -1010,6 +1072,16 @@ public class HardwareRenderer { mPackageName = name; } + synchronized void setIsolated(boolean isolated) { + if (mInitialized) return; + mIsolated = isolated; + } + + synchronized void setContext(Context context) { + if (mInitialized) return; + mContext = context; + } + synchronized void init(long renderProxy) { if (mInitialized) return; mInitialized = true; @@ -1040,6 +1112,61 @@ public class HardwareRenderer { } } + synchronized void initDisplayInfo() { + if (mDisplayInitialized) return; + if (mContext == null) return; + + // If we're in an isolated sandbox mode then we shouldn't try to communicate with DMS + if (mIsolated) { + // Defensively clear out the context in case we were passed a context that can leak + // if we live longer than it, e.g. an activity context. + mContext = null; + mDisplayInitialized = true; + return; + } + + DisplayManager dm = (DisplayManager) mContext.getSystemService(Context.DISPLAY_SERVICE); + if (dm == null) { + Log.d(LOG_TAG, "Failed to find DisplayManager for display-based configuration"); + return; + } + + Display display = dm.getDisplay(Display.DEFAULT_DISPLAY); + if (display == null) { + Log.d(LOG_TAG, "Failed to find default display for display-based configuration"); + return; + } + + Dataspace wideColorDataspace = + Optional.ofNullable(display.getPreferredWideGamutColorSpace()) + .flatMap(Dataspace::find) + // Default to SRGB if the display doesn't support wide color + .orElse(Dataspace.SRGB); + + float maxRefreshRate = + (float) Arrays.stream(display.getSupportedModes()) + .mapToDouble(Mode::getRefreshRate) + .max() + .orElseGet(() -> { + Log.i(LOG_TAG, "Failed to find the maximum display refresh rate"); + // Assume that the max refresh rate is 60hz if we can't find one. + return 60.0; + }); + // Grab the physical screen dimensions from the active display mode + // Strictly speaking the screen resolution may not always be constant - it is for + // sizing the font cache for the underlying rendering thread. Since it's a + // heuristic we don't need to be always 100% correct. + Mode activeMode = display.getMode(); + nInitDisplayInfo(activeMode.getPhysicalWidth(), activeMode.getPhysicalHeight(), + activeMode.getRefreshRate(), maxRefreshRate, + wideColorDataspace.mNativeDataspace, display.getAppVsyncOffsetNanos(), + display.getPresentationDeadlineNanos()); + + // Defensively clear out the context + mContext = null; + mDisplayInitialized = true; + } + private void rotateBuffer() { nRotateProcessStatsBuffer(); requestBuffer(); @@ -1189,4 +1316,10 @@ public class HardwareRenderer { private static native void nAllocateBuffers(long nativeProxy); private static native void nSetForceDark(long nativeProxy, boolean enabled); + + private static native void nSetDisplayDensityDpi(int densityDpi); + + private static native void nInitDisplayInfo(int width, int height, float refreshRate, + float maxRefreshRate, int wideColorDataspace, long appVsyncOffsetNanos, + long presentationDeadlineNanos); } diff --git a/graphics/java/android/graphics/ImageDecoder.java b/graphics/java/android/graphics/ImageDecoder.java index c8f065ad094c..ca37917f437f 100644 --- a/graphics/java/android/graphics/ImageDecoder.java +++ b/graphics/java/android/graphics/ImageDecoder.java @@ -27,9 +27,9 @@ import android.annotation.IntRange; import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.Px; +import android.annotation.SystemApi; import android.annotation.TestApi; import android.annotation.WorkerThread; -import android.compat.annotation.UnsupportedAppUsage; import android.content.ContentResolver; import android.content.res.AssetFileDescriptor; import android.content.res.AssetManager; @@ -171,9 +171,6 @@ import java.util.concurrent.atomic.AtomicBoolean; * </pre> */ public final class ImageDecoder implements AutoCloseable { - /** @hide **/ - public static int sApiLevel; - /** * Source of encoded image data. * @@ -195,14 +192,11 @@ public final class ImageDecoder implements AutoCloseable { public static abstract class Source { private Source() {} - /* @hide */ @Nullable Resources getResources() { return null; } - /* @hide */ int getDensity() { return Bitmap.DENSITY_NONE; } - /* @hide */ final int computeDstDensity() { Resources res = getResources(); if (res == null) { @@ -212,7 +206,6 @@ public final class ImageDecoder implements AutoCloseable { return res.getDisplayMetrics().densityDpi; } - /* @hide */ @NonNull abstract ImageDecoder createImageDecoder(boolean preferAnimation) throws IOException; }; @@ -923,8 +916,12 @@ public final class ImageDecoder implements AutoCloseable { /** * Provide Resources for density scaling. * + * This is a SystemApi to enable legacy behavior, so there is no need to + * make it public like the version above, which does not have a Resources + * parameter. * @hide */ + @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES) @AnyThread @NonNull public static Source createSource(@NonNull ContentResolver cr, @@ -944,6 +941,12 @@ public final class ImageDecoder implements AutoCloseable { /** * Create a new {@link Source Source} from a byte array. * + * <p>Note: If this {@code Source} is passed to {@link #decodeDrawable decodeDrawable}, + * and the encoded image is animated, the returned {@link AnimatedImageDrawable} + * will continue reading from {@code data}, so its contents must not + * be modified, even after the {@code AnimatedImageDrawable} is returned. + * {@code data}'s contents should never be modified during decode.</p> + * * @param data byte array of compressed image data. * @param offset offset into data for where the decoder should begin * parsing. @@ -954,7 +957,6 @@ public final class ImageDecoder implements AutoCloseable { * @throws NullPointerException if data is null. * @throws ArrayIndexOutOfBoundsException if offset and length are * not within data. - * @hide */ @AnyThread @NonNull @@ -972,8 +974,19 @@ public final class ImageDecoder implements AutoCloseable { } /** - * See {@link #createSource(byte[], int, int). - * @hide + * Create a new {@link Source Source} from a byte array. + * + * <p>Note: If this {@code Source} is passed to {@link #decodeDrawable decodeDrawable}, + * and the encoded image is animated, the returned {@link AnimatedImageDrawable} + * will continue reading from {@code data}, so its contents must not + * be modified, even after the {@code AnimatedImageDrawable} is returned. + * {@code data}'s contents should never be modified during decode.</p> + * + * @param data byte array of compressed image data. + * @return a new Source object, which can be passed to + * {@link #decodeDrawable decodeDrawable} or + * {@link #decodeBitmap decodeBitmap}. + * @throws NullPointerException if data is null. */ @AnyThread @NonNull @@ -1081,11 +1094,9 @@ public final class ImageDecoder implements AutoCloseable { * @param sampleSize Sampling rate of the encoded image. * @return {@link android.util.Size} of the width and height after * sampling. - * - * @hide */ @NonNull - public Size getSampledSize(int sampleSize) { + private Size getSampledSize(int sampleSize) { if (sampleSize <= 0) { throw new IllegalArgumentException("sampleSize must be positive! " + "provided " + sampleSize); @@ -1417,6 +1428,8 @@ public final class ImageDecoder implements AutoCloseable { * {@link OnHeaderDecodedListener#onHeaderDecoded onHeaderDecoded}.</p> * * @hide + * Must be public for access from android.graphics.drawable, + * but must not be called from outside the UI module. */ public void setOutPaddingRect(@NonNull Rect outPadding) { mOutPaddingRect = outPadding; @@ -1921,7 +1934,8 @@ public final class ImageDecoder implements AutoCloseable { // For P and above, only resize if it would be a downscale. Scale up prior // to P in case the app relies on the Bitmap's size without considering density. - if (srcDensity < dstDensity && sApiLevel >= Build.VERSION_CODES.P) { + if (srcDensity < dstDensity + && Compatibility.getTargetSdkVersion() >= Build.VERSION_CODES.P) { return srcDensity; } @@ -1964,7 +1978,6 @@ public final class ImageDecoder implements AutoCloseable { * Private method called by JNI. */ @SuppressWarnings("unused") - @UnsupportedAppUsage private int postProcessAndRelease(@NonNull Canvas canvas) { try { return mPostProcessor.onPostProcess(canvas); diff --git a/graphics/java/android/graphics/LargeBitmap.java b/graphics/java/android/graphics/LargeBitmap.java deleted file mode 100644 index 936c33813a86..000000000000 --- a/graphics/java/android/graphics/LargeBitmap.java +++ /dev/null @@ -1,118 +0,0 @@ -/* - * Copyright (C) 2006 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; - -/** - * LargeBitmap can be used to decode a rectangle region from an image. - * LargeBimap is particularly useful when an original image is large and - * you only need parts of the image. - * - * To create a LargeBitmap, call BitmapFactory.createLargeBitmap(). - * Given a LargeBitmap, users can call decodeRegion() repeatedly - * to get a decoded Bitmap of the specified region. - * @hide - */ -public final class LargeBitmap { - private long mNativeLargeBitmap; - private boolean mRecycled; - - /* Private constructor that must received an already allocated native - large bitmap int (pointer). - - This can be called from JNI code. - */ - private LargeBitmap(long nativeLbm) { - mNativeLargeBitmap = nativeLbm; - mRecycled = false; - } - - /** - * Decodes a rectangle region in the image specified by rect. - * - * @param rect The rectangle that specified the region to be decode. - * @param opts null-ok; Options that control downsampling. - * inPurgeable is not supported. - * @return The decoded bitmap, or null if the image data could not be - * decoded. - */ - public Bitmap decodeRegion(Rect rect, BitmapFactory.Options options) { - checkRecycled("decodeRegion called on recycled large bitmap"); - if (rect.left < 0 || rect.top < 0 || rect.right > getWidth() || rect.bottom > getHeight()) - throw new IllegalArgumentException("rectangle is not inside the image"); - return nativeDecodeRegion(mNativeLargeBitmap, rect.left, rect.top, - rect.right - rect.left, rect.bottom - rect.top, options); - } - - /** Returns the original image's width */ - public int getWidth() { - checkRecycled("getWidth called on recycled large bitmap"); - return nativeGetWidth(mNativeLargeBitmap); - } - - /** Returns the original image's height */ - public int getHeight() { - checkRecycled("getHeight called on recycled large bitmap"); - return nativeGetHeight(mNativeLargeBitmap); - } - - /** - * Frees up the memory associated with this large bitmap, and mark the - * large bitmap as "dead", meaning it will throw an exception if decodeRegion(), - * getWidth() or getHeight() is called. - * This operation cannot be reversed, so it should only be called if you are - * sure there are no further uses for the large bitmap. This is an advanced call, - * and normally need not be called, since the normal GC process will free up this - * memory when there are no more references to this bitmap. - */ - public void recycle() { - if (!mRecycled) { - nativeClean(mNativeLargeBitmap); - mRecycled = true; - } - } - - /** - * Returns true if this large bitmap has been recycled. - * If so, then it is an error to try use its method. - * - * @return true if the large bitmap has been recycled - */ - public final boolean isRecycled() { - return mRecycled; - } - - /** - * Called by methods that want to throw an exception if the bitmap - * has already been recycled. - */ - private void checkRecycled(String errorMessage) { - if (mRecycled) { - throw new IllegalStateException(errorMessage); - } - } - - protected void finalize() { - recycle(); - } - - private static native Bitmap nativeDecodeRegion(long nativeLbm, - int start_x, int start_y, int width, int height, - BitmapFactory.Options options); - private static native int nativeGetWidth(long nativeLbm); - private static native int nativeGetHeight(long nativeLbm); - private static native void nativeClean(long nativeLbm); -} diff --git a/graphics/java/android/graphics/LinearGradient.java b/graphics/java/android/graphics/LinearGradient.java index 3f3ad967fe97..ebe34cad0654 100644 --- a/graphics/java/android/graphics/LinearGradient.java +++ b/graphics/java/android/graphics/LinearGradient.java @@ -151,8 +151,9 @@ public class LinearGradient extends Shader { this(x0, y0, x1, y1, new long[] {color0, color1}, null, tile); } + /** @hide */ @Override - long createNativeInstance(long nativeMatrix) { + protected long createNativeInstance(long nativeMatrix) { return nativeCreate(nativeMatrix, mX0, mY0, mX1, mY1, mColorLongs, mPositions, mTileMode.nativeInt, colorSpace().getNativeInstance()); diff --git a/graphics/java/android/graphics/Matrix.java b/graphics/java/android/graphics/Matrix.java index cf914c2c3eae..bc58febc388b 100644 --- a/graphics/java/android/graphics/Matrix.java +++ b/graphics/java/android/graphics/Matrix.java @@ -16,7 +16,7 @@ package android.graphics; -import android.compat.annotation.UnsupportedAppUsage; +import android.annotation.NonNull; import dalvik.annotation.optimization.CriticalNative; import dalvik.annotation.optimization.FastNative; @@ -40,8 +40,11 @@ public class Matrix { public static final int MPERSP_1 = 7; //!< use with getValues/setValues public static final int MPERSP_2 = 8; //!< use with getValues/setValues - /** @hide */ - @UnsupportedAppUsage + /** + * The identity matrix. Multiplying by another matrix {@code M} returns {@code M}. This matrix + * is immutable, and attempting to modify it will throw an {@link IllegalStateException}. + */ + @NonNull public final static Matrix IDENTITY_MATRIX = new Matrix() { void oops() { throw new IllegalStateException("Matrix can not be modified"); @@ -229,11 +232,7 @@ public class Matrix { Matrix.class.getClassLoader(), nGetNativeFinalizer()); } - /** - * @hide - */ - @UnsupportedAppUsage - public final long native_instance; + private final long native_instance; /** * Create an identity matrix @@ -523,7 +522,7 @@ public class Matrix { } /** - * Controlls how the src rect should align into the dst rect for setRectToRect(). + * Controls how the src rect should align into the dst rect for setRectToRect(). */ public enum ScaleToFit { /** @@ -783,10 +782,7 @@ public class Matrix { return sb.toString(); } - /** - * @hide - */ - public void toShortString(StringBuilder sb) { + private void toShortString(StringBuilder sb) { float[] values = new float[9]; getValues(values); sb.append('['); @@ -811,11 +807,13 @@ public class Matrix { } /** - * Print short string, to optimize dumping. + * Dumps a human-readable shortened string of the matrix into the given + * stream * - * @hide + * @param pw The {@link PrintWriter} into which the string representation of + * the matrix will be written. */ - public void printShortString(PrintWriter pw) { + public final void dump(@NonNull PrintWriter pw) { float[] values = new float[9]; getValues(values); pw.print('['); @@ -840,7 +838,10 @@ public class Matrix { } - /** @hide */ + /** + * @hide For access by android.graphics.pdf but must not be accessed outside the module. + * FIXME: PdfRenderer accesses it, but the plan is to leave it out of the module. + */ public final long ni() { return native_instance; } diff --git a/graphics/java/android/graphics/NinePatch.java b/graphics/java/android/graphics/NinePatch.java index ff3239348240..af2095713ec2 100644 --- a/graphics/java/android/graphics/NinePatch.java +++ b/graphics/java/android/graphics/NinePatch.java @@ -39,11 +39,10 @@ public class NinePatch { * Present on a 9 patch bitmap if it optical insets were manually included, * or if outline insets were automatically included by aapt. * - * @hide + * @hide For use by NinePatchDrawable, but must not be used outside the module. */ public static class InsetStruct { @SuppressWarnings({"UnusedDeclaration"}) // called from JNI - @UnsupportedAppUsage InsetStruct(int opticalLeft, int opticalTop, int opticalRight, int opticalBottom, int outlineLeft, int outlineTop, int outlineRight, int outlineBottom, float outlineRadius, int outlineAlpha, float decodeScale) { @@ -86,7 +85,7 @@ public class NinePatch { /** * Used by native code. This pointer is an instance of Res_png_9patch*. * - * @hide + * @hide for use by android.graphics, but must not be used outside the module. */ @UnsupportedAppUsage public long mNativeChunk; @@ -119,20 +118,6 @@ public class NinePatch { mNativeChunk = validateNinePatchChunk(chunk); } - /** - * @hide - */ - public NinePatch(NinePatch patch) { - mBitmap = patch.mBitmap; - mSrcName = patch.mSrcName; - if (patch.mPaint != null) { - mPaint = new Paint(patch.mPaint); - } - // No need to validate the 9patch chunk again, it was done by - // the instance we're copying from - mNativeChunk = patch.mNativeChunk; - } - @Override protected void finalize() throws Throwable { try { diff --git a/graphics/java/android/graphics/Path.java b/graphics/java/android/graphics/Path.java index 84fe39290681..7811671b80d6 100644 --- a/graphics/java/android/graphics/Path.java +++ b/graphics/java/android/graphics/Path.java @@ -713,7 +713,7 @@ public class Path { */ public void addPath(@NonNull Path src, @NonNull Matrix matrix) { if (!src.isSimplePath) isSimplePath = false; - nAddPath(mNativePath, src.mNativePath, matrix.native_instance); + nAddPath(mNativePath, src.mNativePath, matrix.ni()); } /** @@ -777,7 +777,7 @@ public class Path { dst.isSimplePath = false; dstNative = dst.mNativePath; } - nTransform(mNativePath, matrix.native_instance, dstNative); + nTransform(mNativePath, matrix.ni(), dstNative); } /** @@ -787,7 +787,7 @@ public class Path { */ public void transform(@NonNull Matrix matrix) { isSimplePath = false; - nTransform(mNativePath, matrix.native_instance); + nTransform(mNativePath, matrix.ni()); } /** @hide */ diff --git a/graphics/java/android/graphics/PathMeasure.java b/graphics/java/android/graphics/PathMeasure.java index bf79656addc0..5500c5217de4 100644 --- a/graphics/java/android/graphics/PathMeasure.java +++ b/graphics/java/android/graphics/PathMeasure.java @@ -105,7 +105,7 @@ public class PathMeasure { * @param flags Specified what aspects should be returned in the matrix. */ public boolean getMatrix(float distance, Matrix matrix, int flags) { - return native_getMatrix(native_instance, distance, matrix.native_instance, flags); + return native_getMatrix(native_instance, distance, matrix.ni(), flags); } /** diff --git a/graphics/java/android/graphics/Point.java b/graphics/java/android/graphics/Point.java index 9f71a0fedd05..61a47493c2ff 100644 --- a/graphics/java/android/graphics/Point.java +++ b/graphics/java/android/graphics/Point.java @@ -19,12 +19,9 @@ package android.graphics; import android.annotation.NonNull; import android.os.Parcel; import android.os.Parcelable; -import android.util.Size; -import android.util.proto.ProtoOutputStream; import java.io.PrintWriter; - /** * Point holds two integer coordinates */ @@ -75,6 +72,17 @@ public class Point implements Parcelable { return this.x == x && this.y == y; } + /** + * Dumps a human-readable shortened string of the point into the given + * stream + * + * @param pw The {@link PrintWriter} into which the string representation of + * the point will be written. + */ + public final void dump(@NonNull PrintWriter pw) { + pw.print("["); pw.print(x); pw.print(","); pw.print(y); pw.print("]"); + } + @Override public boolean equals(Object o) { if (this == o) return true; @@ -100,11 +108,6 @@ public class Point implements Parcelable { return "Point(" + x + ", " + y + ")"; } - /** @hide */ - public void printShortString(@NonNull PrintWriter pw) { - pw.print("["); pw.print(x); pw.print(","); pw.print(y); pw.print("]"); - } - /** * Parcelable interface methods */ @@ -124,21 +127,6 @@ public class Point implements Parcelable { out.writeInt(y); } - /** - * Write to a protocol buffer output stream. - * Protocol buffer message definition at {@link android.graphics.PointProto} - * - * @param protoOutputStream Stream to write the Rect object to. - * @param fieldId Field Id of the Rect as defined in the parent message - * @hide - */ - public void dumpDebug(@NonNull ProtoOutputStream protoOutputStream, long fieldId) { - final long token = protoOutputStream.start(fieldId); - protoOutputStream.write(PointProto.X, x); - protoOutputStream.write(PointProto.Y, y); - protoOutputStream.end(token); - } - public static final @android.annotation.NonNull Parcelable.Creator<Point> CREATOR = new Parcelable.Creator<Point>() { /** * Return a new point from the data in the specified parcel. @@ -169,14 +157,4 @@ public class Point implements Parcelable { x = in.readInt(); y = in.readInt(); } - - /** {@hide} */ - public static @NonNull Point convert(@NonNull Size size) { - return new Point(size.getWidth(), size.getHeight()); - } - - /** {@hide} */ - public static @NonNull Size convert(@NonNull Point point) { - return new Size(point.x, point.y); - } } diff --git a/graphics/java/android/graphics/RadialGradient.java b/graphics/java/android/graphics/RadialGradient.java index 96b7b9a78ba8..089d6de44adb 100644 --- a/graphics/java/android/graphics/RadialGradient.java +++ b/graphics/java/android/graphics/RadialGradient.java @@ -147,8 +147,9 @@ public class RadialGradient extends Shader { this(centerX, centerY, radius, new long[] {centerColor, edgeColor}, null, tileMode); } + /** @hide */ @Override - long createNativeInstance(long nativeMatrix) { + protected long createNativeInstance(long nativeMatrix) { return nativeCreate(nativeMatrix, mX, mY, mRadius, mColorLongs, mPositions, mTileMode.nativeInt, colorSpace().getNativeInstance()); diff --git a/graphics/java/android/graphics/RecordingCanvas.java b/graphics/java/android/graphics/RecordingCanvas.java index c0e0a24583ec..22aacdecaf5d 100644 --- a/graphics/java/android/graphics/RecordingCanvas.java +++ b/graphics/java/android/graphics/RecordingCanvas.java @@ -19,8 +19,6 @@ package android.graphics; import android.annotation.NonNull; import android.annotation.Nullable; import android.util.Pools.SynchronizedPool; -import android.view.DisplayListCanvas; -import android.view.TextureLayer; import dalvik.annotation.optimization.CriticalNative; import dalvik.annotation.optimization.FastNative; @@ -35,13 +33,12 @@ import dalvik.annotation.optimization.FastNative; * {@link RenderNode#endRecording()} is called. It must not be retained beyond that as it is * internally reused. */ -public final class RecordingCanvas extends DisplayListCanvas { +public final class RecordingCanvas extends BaseRecordingCanvas { // The recording canvas pool should be large enough to handle a deeply nested // view hierarchy because display lists are generated recursively. private static final int POOL_LIMIT = 25; - /** @hide */ - public static final int MAX_BITMAP_SIZE = 100 * 1024 * 1024; // 100 MB + private static final int MAX_BITMAP_SIZE = 100 * 1024 * 1024; // 100 MB private static final SynchronizedPool<RecordingCanvas> sPool = new SynchronizedPool<>(POOL_LIMIT); @@ -53,7 +50,7 @@ public final class RecordingCanvas extends DisplayListCanvas { private int mWidth; private int mHeight; - /** @hide */ + /*package*/ static RecordingCanvas obtain(@NonNull RenderNode node, int width, int height) { if (node == null) throw new IllegalArgumentException("node cannot be null"); RecordingCanvas canvas = sPool.acquire(); @@ -69,29 +66,22 @@ public final class RecordingCanvas extends DisplayListCanvas { return canvas; } - /** @hide */ + /*package*/ void recycle() { mNode = null; sPool.release(this); } - /** @hide */ + /*package*/ long finishRecording() { return nFinishRecording(mNativeCanvasWrapper); } - /** @hide */ - @Override - public boolean isRecordingFor(Object o) { - return o == mNode; - } - /////////////////////////////////////////////////////////////////////////// // Constructors /////////////////////////////////////////////////////////////////////////// - /** @hide */ - protected RecordingCanvas(@NonNull RenderNode node, int width, int height) { + private RecordingCanvas(@NonNull RenderNode node, int width, int height) { super(nCreateDisplayListCanvas(node.mNativeRenderNode, width, height)); mDensity = 0; // disable bitmap density scaling } @@ -147,12 +137,12 @@ public final class RecordingCanvas extends DisplayListCanvas { @Override public void enableZ() { - nInsertReorderBarrier(mNativeCanvasWrapper, true); + nEnableZ(mNativeCanvasWrapper, true); } @Override public void disableZ() { - nInsertReorderBarrier(mNativeCanvasWrapper, false); + nEnableZ(mNativeCanvasWrapper, false); } /////////////////////////////////////////////////////////////////////////// @@ -223,9 +213,9 @@ public final class RecordingCanvas extends DisplayListCanvas { * Draws the specified layer onto this canvas. * * @param layer The layer to composite on this canvas - * @hide + * @hide TODO: Make this a SystemApi for b/155905258 */ - public void drawTextureLayer(TextureLayer layer) { + public void drawTextureLayer(@NonNull TextureLayer layer) { nDrawTextureLayer(mNativeCanvasWrapper, layer.getLayerHandle()); } @@ -302,7 +292,7 @@ public final class RecordingCanvas extends DisplayListCanvas { @CriticalNative private static native int nGetMaximumTextureHeight(); @CriticalNative - private static native void nInsertReorderBarrier(long renderer, boolean enableReorder); + private static native void nEnableZ(long renderer, boolean enableZ); @CriticalNative private static native long nFinishRecording(long renderer); @CriticalNative diff --git a/graphics/java/android/graphics/RenderNode.java b/graphics/java/android/graphics/RenderNode.java index 22f5489be3b1..8aacbc7bc109 100644 --- a/graphics/java/android/graphics/RenderNode.java +++ b/graphics/java/android/graphics/RenderNode.java @@ -481,7 +481,7 @@ public final class RenderNode { * @param outMatrix The matrix to store the transform of the RenderNode */ public void getMatrix(@NonNull Matrix outMatrix) { - nGetTransformMatrix(mNativeRenderNode, outMatrix.native_instance); + nGetTransformMatrix(mNativeRenderNode, outMatrix.ni()); } /** @@ -491,7 +491,7 @@ public final class RenderNode { * @param outMatrix The matrix to store the inverse transform of the RenderNode */ public void getInverseMatrix(@NonNull Matrix outMatrix) { - nGetInverseTransformMatrix(mNativeRenderNode, outMatrix.native_instance); + nGetInverseTransformMatrix(mNativeRenderNode, outMatrix.ni()); } /////////////////////////////////////////////////////////////////////////// @@ -797,7 +797,7 @@ public final class RenderNode { * @hide TODO Do we want this? */ public boolean setStaticMatrix(Matrix matrix) { - return nSetStaticMatrix(mNativeRenderNode, matrix.native_instance); + return nSetStaticMatrix(mNativeRenderNode, matrix.ni()); } /** @@ -813,7 +813,7 @@ public final class RenderNode { */ public boolean setAnimationMatrix(@Nullable Matrix matrix) { return nSetAnimationMatrix(mNativeRenderNode, - (matrix != null) ? matrix.native_instance : 0); + (matrix != null) ? matrix.ni() : 0); } /** @@ -830,7 +830,7 @@ public final class RenderNode { @Nullable public Matrix getAnimationMatrix() { Matrix output = new Matrix(); - if (nGetAnimationMatrix(mNativeRenderNode, output.native_instance)) { + if (nGetAnimationMatrix(mNativeRenderNode, output.ni())) { return output; } else { return null; diff --git a/graphics/java/android/graphics/RuntimeShader.java b/graphics/java/android/graphics/RuntimeShader.java index 5a3f2a96e31d..5a0b4a9b8086 100644 --- a/graphics/java/android/graphics/RuntimeShader.java +++ b/graphics/java/android/graphics/RuntimeShader.java @@ -74,8 +74,9 @@ public class RuntimeShader extends Shader { discardNativeInstance(); } + /** @hide */ @Override - long createNativeInstance(long nativeMatrix) { + protected long createNativeInstance(long nativeMatrix) { return nativeCreate(mNativeInstanceRuntimeShaderFactory, nativeMatrix, mUniforms, colorSpace().getNativeInstance(), mIsOpaque); } diff --git a/graphics/java/android/graphics/Shader.java b/graphics/java/android/graphics/Shader.java index 5335aa4725ad..fb15d0794dd7 100644 --- a/graphics/java/android/graphics/Shader.java +++ b/graphics/java/android/graphics/Shader.java @@ -20,12 +20,11 @@ import android.annotation.ColorInt; import android.annotation.ColorLong; import android.annotation.NonNull; import android.annotation.Nullable; -import android.compat.annotation.UnsupportedAppUsage; import libcore.util.NativeAllocationRegistry; /** - * Shader is the based class for objects that return horizontal spans of colors + * Shader is the base class for objects that return horizontal spans of colors * during drawing. A subclass of Shader is installed in a Paint calling * paint.setShader(shader). After that any object (other than a bitmap) that is * drawn with that paint will get its color(s) from the shader. @@ -47,9 +46,9 @@ public class Shader { } /** - * @hide + * @hide Only to be used by subclasses in android.graphics. */ - public Shader(ColorSpace colorSpace) { + protected Shader(ColorSpace colorSpace) { mColorSpace = colorSpace; if (colorSpace == null) { throw new IllegalArgumentException( @@ -63,7 +62,7 @@ public class Shader { private final ColorSpace mColorSpace; /** - * @hide + * @hide Only to be used by subclasses in android.graphics. */ protected ColorSpace colorSpace() { return mColorSpace; @@ -97,11 +96,10 @@ public class Shader { * mirror images so that adjacent images always seam */ MIRROR (2); - + TileMode(int nativeInt) { this.nativeInt = nativeInt; } - @UnsupportedAppUsage final int nativeInt; } @@ -142,11 +140,16 @@ public class Shader { } } - long createNativeInstance(long nativeMatrix) { + /** + * @hide Only to be used by subclasses in the graphics package. + */ + protected long createNativeInstance(long nativeMatrix) { return 0; } - /** @hide */ + /** + * @hide Only to be used by subclasses in the graphics package. + */ protected final void discardNativeInstance() { if (mNativeInstance != 0) { mCleaner.run(); @@ -158,14 +161,15 @@ public class Shader { /** * Callback for subclasses to call {@link #discardNativeInstance()} if the most recently * constructed native instance is no longer valid. - * @hide + * @hide Only to be used by subclasses in the graphics package. */ protected void verifyNativeInstance() { } /** - * @hide + * @hide so it can be called by android.graphics.drawable but must not be called from outside + * the module. */ public final long getNativeInstance() { // verify mNativeInstance is valid @@ -173,7 +177,7 @@ public class Shader { if (mNativeInstance == 0) { mNativeInstance = createNativeInstance(mLocalMatrix == null - ? 0 : mLocalMatrix.native_instance); + ? 0 : mLocalMatrix.ni()); if (mNativeInstance != 0) { mCleaner = NoImagePreloadHolder.sRegistry.registerNativeAllocation( this, mNativeInstance); @@ -183,9 +187,9 @@ public class Shader { } /** - * @hide + * @hide Only to be called by subclasses in the android.graphics package. */ - public static @ColorLong long[] convertColors(@NonNull @ColorInt int[] colors) { + protected static @ColorLong long[] convertColors(@NonNull @ColorInt int[] colors) { if (colors.length < 2) { throw new IllegalArgumentException("needs >= 2 number of colors"); } @@ -204,9 +208,9 @@ public class Shader { * @throws IllegalArgumentException if the colors do not all share the same, * valid ColorSpace, or if there are less than 2 colors. * - * @hide + * @hide Only to be called by subclasses in the android.graphics package. */ - public static ColorSpace detectColorSpace(@NonNull @ColorLong long[] colors) { + protected static ColorSpace detectColorSpace(@NonNull @ColorLong long[] colors) { if (colors.length < 2) { throw new IllegalArgumentException("needs >= 2 number of colors"); } diff --git a/graphics/java/android/graphics/SweepGradient.java b/graphics/java/android/graphics/SweepGradient.java index 08520048b787..f1ca1986bfa0 100644 --- a/graphics/java/android/graphics/SweepGradient.java +++ b/graphics/java/android/graphics/SweepGradient.java @@ -130,8 +130,9 @@ public class SweepGradient extends Shader { this(cx, cy, new long[] {color0, color1}, null); } + /** @hide */ @Override - long createNativeInstance(long nativeMatrix) { + protected long createNativeInstance(long nativeMatrix) { return nativeCreate(nativeMatrix, mCx, mCy, mColorLongs, mPositions, colorSpace().getNativeInstance()); } diff --git a/graphics/java/android/graphics/TextureLayer.java b/graphics/java/android/graphics/TextureLayer.java new file mode 100644 index 000000000000..ac1bd6902062 --- /dev/null +++ b/graphics/java/android/graphics/TextureLayer.java @@ -0,0 +1,153 @@ +/* + * Copyright (C) 2011 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; +import android.view.View; + +import com.android.internal.util.VirtualRefBasePtr; + +/** + * TextureLayer represents a SurfaceTexture that will be composited by RenderThread into the + * frame when drawn in a HW accelerated Canvas. This is backed by a DeferredLayerUpdater on + * the native side. + * + * @hide TODO: Make this a SystemApi for b/155905258 + */ +public final class TextureLayer implements AutoCloseable { + private HardwareRenderer mRenderer; + private VirtualRefBasePtr mFinalizer; + + private TextureLayer(@NonNull HardwareRenderer renderer, long deferredUpdater) { + if (renderer == null || deferredUpdater == 0) { + throw new IllegalArgumentException("Either hardware renderer: " + renderer + + " or deferredUpdater: " + deferredUpdater + " is invalid"); + } + mRenderer = renderer; + mFinalizer = new VirtualRefBasePtr(deferredUpdater); + } + + /** + * Update the paint used when drawing this layer. + * + * @param paint The paint used when the layer is drawn into the destination canvas. + * @see View#setLayerPaint(android.graphics.Paint) + */ + public void setLayerPaint(@Nullable Paint paint) { + nSetLayerPaint(mFinalizer.get(), paint != null ? paint.getNativeInstance() : 0); + mRenderer.pushLayerUpdate(this); + } + + /** + * Indicates whether this layer can be rendered. + * + * @return True if the layer can be rendered into, false otherwise + */ + private boolean isValid() { + return mFinalizer != null && mFinalizer.get() != 0; + } + + /** + * Destroys resources without waiting for a GC. + */ + @Override + public void close() { + if (!isValid()) { + // Already destroyed + return; + } + mRenderer.onLayerDestroyed(this); + mRenderer = null; + mFinalizer.release(); + mFinalizer = null; + } + + /*package*/ long getDeferredLayerUpdater() { + return mFinalizer.get(); + } + + /** + * Copies this layer into the specified bitmap. + * + * @param bitmap The bitmap to copy they layer into + * + * @return True if the copy was successful, false otherwise + */ + public boolean copyInto(@NonNull Bitmap bitmap) { + return mRenderer.copyLayerInto(this, bitmap); + } + + /** + * Update the layer's properties. Note that after calling this isValid() may + * return false if the requested width/height cannot be satisfied + * + * @param width The new width of this layer + * @param height The new height of this layer + * @param isOpaque Whether this layer is opaque + * + * @return true if the layer's properties will change, false if they already + * match the desired values. + */ + public boolean prepare(int width, int height, boolean isOpaque) { + return nPrepare(mFinalizer.get(), width, height, isOpaque); + } + + /** + * Sets an optional transform on this layer. + * + * @param matrix The transform to apply to the layer. + */ + public void setTransform(@NonNull Matrix matrix) { + nSetTransform(mFinalizer.get(), matrix.ni()); + mRenderer.pushLayerUpdate(this); + } + + /** + * Indicates that this layer has lost its texture. + */ + public void detachSurfaceTexture() { + mRenderer.detachSurfaceTexture(mFinalizer.get()); + } + + /*package*/ long getLayerHandle() { + return mFinalizer.get(); + } + + public void setSurfaceTexture(@NonNull SurfaceTexture surface) { + nSetSurfaceTexture(mFinalizer.get(), surface); + mRenderer.pushLayerUpdate(this); + } + + public void updateSurfaceTexture() { + nUpdateSurfaceTexture(mFinalizer.get()); + mRenderer.pushLayerUpdate(this); + } + + /*package*/ static TextureLayer adoptTextureLayer(@NonNull HardwareRenderer renderer, + long layer) { + return new TextureLayer(renderer, layer); + } + + private static native boolean nPrepare(long layerUpdater, int width, int height, + boolean isOpaque); + private static native void nSetLayerPaint(long layerUpdater, long paint); + private static native void nSetTransform(long layerUpdater, long matrix); + private static native void nSetSurfaceTexture(long layerUpdater, + @NonNull SurfaceTexture surface); + private static native void nUpdateSurfaceTexture(long layerUpdater); +} diff --git a/graphics/java/android/graphics/drawable/AdaptiveIconDrawable.java b/graphics/java/android/graphics/drawable/AdaptiveIconDrawable.java index 31ad81b9c346..0f356a6d2d3c 100644 --- a/graphics/java/android/graphics/drawable/AdaptiveIconDrawable.java +++ b/graphics/java/android/graphics/drawable/AdaptiveIconDrawable.java @@ -768,7 +768,6 @@ public class AdaptiveIconDrawable extends Drawable implements Drawable.Callback return mLayerState.isStateful(); } - /** @hide */ @Override public boolean hasFocusStateSpecified() { return mLayerState.hasFocusStateSpecified(); diff --git a/graphics/java/android/graphics/drawable/AnimatedImageDrawable.java b/graphics/java/android/graphics/drawable/AnimatedImageDrawable.java index d8946009483c..ebf7cea98a81 100644 --- a/graphics/java/android/graphics/drawable/AnimatedImageDrawable.java +++ b/graphics/java/android/graphics/drawable/AnimatedImageDrawable.java @@ -19,7 +19,6 @@ package android.graphics.drawable; import android.annotation.IntRange; import android.annotation.NonNull; import android.annotation.Nullable; -import android.compat.annotation.UnsupportedAppUsage; import android.content.res.AssetFileDescriptor; import android.content.res.Resources; import android.content.res.Resources.Theme; @@ -563,7 +562,6 @@ public class AnimatedImageDrawable extends Drawable implements Animatable2 { * callback, so no need to post. */ @SuppressWarnings("unused") - @UnsupportedAppUsage private void onAnimationEnd() { if (mAnimationCallbacks != null) { for (Animatable2.AnimationCallback callback : mAnimationCallbacks) { diff --git a/graphics/java/android/graphics/drawable/AnimatedVectorDrawable.java b/graphics/java/android/graphics/drawable/AnimatedVectorDrawable.java index 9fb72cf08b51..73dbe65bd25b 100644 --- a/graphics/java/android/graphics/drawable/AnimatedVectorDrawable.java +++ b/graphics/java/android/graphics/drawable/AnimatedVectorDrawable.java @@ -25,8 +25,6 @@ import android.animation.TimeInterpolator; import android.animation.ValueAnimator; import android.annotation.NonNull; import android.annotation.Nullable; -import android.app.ActivityThread; -import android.app.Application; import android.compat.annotation.UnsupportedAppUsage; import android.content.pm.ActivityInfo.Config; import android.content.res.ColorStateList; @@ -368,14 +366,7 @@ public class AnimatedVectorDrawable extends Drawable implements Animatable2 { * @return whether invalid animations for vector drawable should be ignored. */ private static boolean shouldIgnoreInvalidAnimation() { - Application app = ActivityThread.currentApplication(); - if (app == null || app.getApplicationInfo() == null) { - return true; - } - if (app.getApplicationInfo().targetSdkVersion < Build.VERSION_CODES.N) { - return true; - } - return false; + return android.graphics.Compatibility.getTargetSdkVersion() < Build.VERSION_CODES.N; } @Override diff --git a/graphics/java/android/graphics/drawable/BitmapDrawable.java b/graphics/java/android/graphics/drawable/BitmapDrawable.java index 4e768c9eddfb..b291f930da37 100644 --- a/graphics/java/android/graphics/drawable/BitmapDrawable.java +++ b/graphics/java/android/graphics/drawable/BitmapDrawable.java @@ -17,6 +17,7 @@ package android.graphics.drawable; import android.annotation.NonNull; +import android.annotation.Nullable; import android.compat.annotation.UnsupportedAppUsage; import android.content.pm.ActivityInfo.Config; import android.content.res.ColorStateList; @@ -92,7 +93,6 @@ public class BitmapDrawable extends Drawable { private BitmapState mBitmapState; private BlendModeColorFilter mBlendModeFilter; - @UnsupportedAppUsage private int mTargetDensity = DisplayMetrics.DENSITY_DEFAULT; private boolean mDstRectAndInsetsDirty = true; @@ -239,9 +239,10 @@ public class BitmapDrawable extends Drawable { } } - /** @hide */ - @UnsupportedAppUsage - public void setBitmap(Bitmap bitmap) { + /** + * Switch to a new Bitmap object. + */ + public void setBitmap(@Nullable Bitmap bitmap) { if (mBitmapState.mBitmap != bitmap) { mBitmapState.mBitmap = bitmap; computeBitmapSize(); @@ -696,18 +697,18 @@ public class BitmapDrawable extends Drawable { } /** - * @hide only needed by a hack within ProgressBar + * No longer needed by ProgressBar, but still here due to UnsupportedAppUsage. */ @UnsupportedAppUsage - public ColorStateList getTint() { + private ColorStateList getTint() { return mBitmapState.mTint; } /** - * @hide only needed by a hack within ProgressBar + * No longer needed by ProgressBar, but still here due to UnsupportedAppUsage. */ @UnsupportedAppUsage - public Mode getTintMode() { + private Mode getTintMode() { return BlendMode.blendModeToPorterDuffMode(mBitmapState.mBlendMode); } @@ -760,7 +761,6 @@ public class BitmapDrawable extends Drawable { || super.isStateful(); } - /** @hide */ @Override public boolean hasFocusStateSpecified() { return mBitmapState.mTint != null && mBitmapState.mTint.hasFocusStateSpecified(); diff --git a/graphics/java/android/graphics/drawable/ColorDrawable.java b/graphics/java/android/graphics/drawable/ColorDrawable.java index e93e7dfbe22c..2457ab85144f 100644 --- a/graphics/java/android/graphics/drawable/ColorDrawable.java +++ b/graphics/java/android/graphics/drawable/ColorDrawable.java @@ -238,7 +238,6 @@ public class ColorDrawable extends Drawable { return mColorState.mTint != null && mColorState.mTint.isStateful(); } - /** @hide */ @Override public boolean hasFocusStateSpecified() { return mColorState.mTint != null && mColorState.mTint.hasFocusStateSpecified(); diff --git a/graphics/java/android/graphics/drawable/Drawable.java b/graphics/java/android/graphics/drawable/Drawable.java index 9cf12f121e0a..ed210ab40b7a 100644 --- a/graphics/java/android/graphics/drawable/Drawable.java +++ b/graphics/java/android/graphics/drawable/Drawable.java @@ -21,7 +21,6 @@ import android.annotation.ColorInt; import android.annotation.IntRange; import android.annotation.NonNull; import android.annotation.Nullable; -import android.annotation.TestApi; import android.compat.annotation.UnsupportedAppUsage; import android.content.pm.ActivityInfo.Config; import android.content.res.ColorStateList; @@ -808,10 +807,7 @@ public abstract class Drawable { * * @return {@code true} if {@link android.R.attr#state_focused} is specified * for this drawable. - * - * @hide */ - @TestApi public boolean hasFocusStateSpecified() { return false; } diff --git a/graphics/java/android/graphics/drawable/DrawableContainer.java b/graphics/java/android/graphics/drawable/DrawableContainer.java index 51b299c9ee5e..89ebcbe817dd 100644 --- a/graphics/java/android/graphics/drawable/DrawableContainer.java +++ b/graphics/java/android/graphics/drawable/DrawableContainer.java @@ -243,7 +243,6 @@ public class DrawableContainer extends Drawable implements Drawable.Callback { return mDrawableContainerState.isStateful(); } - /** @hide */ @Override public boolean hasFocusStateSpecified() { if (mCurrDrawable != null) { diff --git a/graphics/java/android/graphics/drawable/DrawableWrapper.java b/graphics/java/android/graphics/drawable/DrawableWrapper.java index e197e7123fed..98c38214adab 100644 --- a/graphics/java/android/graphics/drawable/DrawableWrapper.java +++ b/graphics/java/android/graphics/drawable/DrawableWrapper.java @@ -345,7 +345,6 @@ public abstract class DrawableWrapper extends Drawable implements Drawable.Callb return mDrawable != null && mDrawable.isStateful(); } - /** @hide */ @Override public boolean hasFocusStateSpecified() { return mDrawable != null && mDrawable.hasFocusStateSpecified(); diff --git a/graphics/java/android/graphics/drawable/GradientDrawable.java b/graphics/java/android/graphics/drawable/GradientDrawable.java index f053f392b97e..24d73efebe54 100644 --- a/graphics/java/android/graphics/drawable/GradientDrawable.java +++ b/graphics/java/android/graphics/drawable/GradientDrawable.java @@ -1164,7 +1164,6 @@ public class GradientDrawable extends Drawable { || (s.mTint != null && s.mTint.isStateful()); } - /** @hide */ @Override public boolean hasFocusStateSpecified() { final GradientState s = mGradientState; diff --git a/graphics/java/android/graphics/drawable/Icon.java b/graphics/java/android/graphics/drawable/Icon.java index cc7182c3fd1c..90412f417f38 100644 --- a/graphics/java/android/graphics/drawable/Icon.java +++ b/graphics/java/android/graphics/drawable/Icon.java @@ -467,7 +467,7 @@ public final class Icon implements Parcelable { if ((mType == TYPE_BITMAP || mType == TYPE_ADAPTIVE_BITMAP) && getBitmap().isMutable() && getBitmap().getAllocationByteCount() >= MIN_ASHMEM_ICON_SIZE) { - setBitmap(getBitmap().createAshmemBitmap()); + setBitmap(getBitmap().asShared()); } } diff --git a/graphics/java/android/graphics/drawable/LayerDrawable.java b/graphics/java/android/graphics/drawable/LayerDrawable.java index fb4146f04bc9..19f29aed203f 100644 --- a/graphics/java/android/graphics/drawable/LayerDrawable.java +++ b/graphics/java/android/graphics/drawable/LayerDrawable.java @@ -1483,7 +1483,6 @@ public class LayerDrawable extends Drawable implements Drawable.Callback { return mLayerState.isStateful(); } - /** @hide */ @Override public boolean hasFocusStateSpecified() { return mLayerState.hasFocusStateSpecified(); diff --git a/graphics/java/android/graphics/drawable/NinePatchDrawable.java b/graphics/java/android/graphics/drawable/NinePatchDrawable.java index 99d27ba4c469..423025e8f418 100644 --- a/graphics/java/android/graphics/drawable/NinePatchDrawable.java +++ b/graphics/java/android/graphics/drawable/NinePatchDrawable.java @@ -114,7 +114,7 @@ public class NinePatchDrawable extends Drawable { * Create drawable from raw nine-patch data, setting initial target density * based on the display metrics of the resources. * - * @hide + * @hide for use by android.graphics.ImageDecoder, but must not be used outside the module. */ public NinePatchDrawable(Resources res, Bitmap bitmap, byte[] chunk, Rect padding, Rect opticalInsets, String srcName) { @@ -582,7 +582,6 @@ public class NinePatchDrawable extends Drawable { return super.isStateful() || (s.mTint != null && s.mTint.isStateful()); } - /** @hide */ @Override public boolean hasFocusStateSpecified() { return mNinePatchState.mTint != null && mNinePatchState.mTint.hasFocusStateSpecified(); diff --git a/graphics/java/android/graphics/drawable/RippleDrawable.java b/graphics/java/android/graphics/drawable/RippleDrawable.java index e5e4d4527fca..16ffd132a41b 100644 --- a/graphics/java/android/graphics/drawable/RippleDrawable.java +++ b/graphics/java/android/graphics/drawable/RippleDrawable.java @@ -378,7 +378,6 @@ public class RippleDrawable extends LayerDrawable { return true; } - /** @hide */ @Override public boolean hasFocusStateSpecified() { return true; diff --git a/graphics/java/android/graphics/drawable/ShapeDrawable.java b/graphics/java/android/graphics/drawable/ShapeDrawable.java index 9774b59f98a9..f264d0eb363f 100644 --- a/graphics/java/android/graphics/drawable/ShapeDrawable.java +++ b/graphics/java/android/graphics/drawable/ShapeDrawable.java @@ -367,7 +367,6 @@ public class ShapeDrawable extends Drawable { return super.isStateful() || (s.mTint != null && s.mTint.isStateful()); } - /** @hide */ @Override public boolean hasFocusStateSpecified() { return mShapeState.mTint != null && mShapeState.mTint.hasFocusStateSpecified(); diff --git a/graphics/java/android/graphics/drawable/StateListDrawable.java b/graphics/java/android/graphics/drawable/StateListDrawable.java index 2920acbe514c..88cd4625394b 100644 --- a/graphics/java/android/graphics/drawable/StateListDrawable.java +++ b/graphics/java/android/graphics/drawable/StateListDrawable.java @@ -94,7 +94,6 @@ public class StateListDrawable extends DrawableContainer { return true; } - /** @hide */ @Override public boolean hasFocusStateSpecified() { return mStateListState.hasFocusStateSpecified(); diff --git a/graphics/java/android/graphics/drawable/VectorDrawable.java b/graphics/java/android/graphics/drawable/VectorDrawable.java index e6fa866df3ab..a1ccc7b7b5e4 100644 --- a/graphics/java/android/graphics/drawable/VectorDrawable.java +++ b/graphics/java/android/graphics/drawable/VectorDrawable.java @@ -502,7 +502,6 @@ public class VectorDrawable extends Drawable { return super.isStateful() || (mVectorState != null && mVectorState.isStateful()); } - /** @hide */ @Override public boolean hasFocusStateSpecified() { return mVectorState != null && mVectorState.hasFocusStateSpecified(); diff --git a/graphics/java/android/graphics/pdf/PdfEditor.java b/graphics/java/android/graphics/pdf/PdfEditor.java index 21ce1b8392d2..3cd709ea10e5 100644 --- a/graphics/java/android/graphics/pdf/PdfEditor.java +++ b/graphics/java/android/graphics/pdf/PdfEditor.java @@ -139,12 +139,12 @@ public final class PdfEditor { getPageSize(pageIndex, size); synchronized (PdfRenderer.sPdfiumLock) { - nativeSetTransformAndClip(mNativeDocument, pageIndex, transform.native_instance, + nativeSetTransformAndClip(mNativeDocument, pageIndex, transform.ni(), 0, 0, size.x, size.y); } } else { synchronized (PdfRenderer.sPdfiumLock) { - nativeSetTransformAndClip(mNativeDocument, pageIndex, transform.native_instance, + nativeSetTransformAndClip(mNativeDocument, pageIndex, transform.ni(), clip.left, clip.top, clip.right, clip.bottom); } } diff --git a/graphics/java/android/graphics/pdf/PdfRenderer.java b/graphics/java/android/graphics/pdf/PdfRenderer.java index 54710e58687c..43de4699381f 100644 --- a/graphics/java/android/graphics/pdf/PdfRenderer.java +++ b/graphics/java/android/graphics/pdf/PdfRenderer.java @@ -434,7 +434,9 @@ public final class PdfRenderer implements AutoCloseable { transform.postTranslate(contentLeft, contentTop); } - final long transformPtr = transform.native_instance; + // FIXME: This code is planned to be outside the UI rendering module, so it should not + // be able to access native instances from Bitmap, Matrix, etc. + final long transformPtr = transform.ni(); synchronized (sPdfiumLock) { nativeRenderPage(mNativeDocument, mNativePage, destination.getNativeInstance(), |