diff options
Diffstat (limited to 'graphics')
49 files changed, 549 insertions, 734 deletions
diff --git a/graphics/java/Android.bp b/graphics/java/Android.bp index ece453d1a70e..f4abd0ab582c 100644 --- a/graphics/java/Android.bp +++ b/graphics/java/Android.bp @@ -11,6 +11,7 @@ package { aconfig_declarations { name: "framework_graphics_flags", package: "com.android.graphics.flags", + container: "system", srcs: ["android/framework_graphics.aconfig"], } diff --git a/graphics/java/android/framework_graphics.aconfig b/graphics/java/android/framework_graphics.aconfig index 6c81a608241c..0b9e72d6ffdd 100644 --- a/graphics/java/android/framework_graphics.aconfig +++ b/graphics/java/android/framework_graphics.aconfig @@ -1,7 +1,9 @@ package: "com.android.graphics.flags" +container: "system" flag { name: "exact_compute_bounds" + is_exported: true namespace: "core_graphics" description: "Add a function without unused exact param for computeBounds." bug: "304478551" @@ -9,7 +11,16 @@ flag { flag { name: "yuv_image_compress_to_ultra_hdr" + is_exported: true namespace: "core_graphics" description: "Feature flag for YUV image compress to Ultra HDR." bug: "308978825" -}
\ No newline at end of file +} + +flag { + name: "icon_load_drawable_return_null_when_uri_decode_fails" + is_exported: true + namespace: "core_graphics" + description: "Return null when decode from URI fails in Icon.loadDrawable()" + bug: "335878768" +} diff --git a/graphics/java/android/graphics/BaseCanvas.java b/graphics/java/android/graphics/BaseCanvas.java index a7acaf924c15..a2a0f4936888 100644 --- a/graphics/java/android/graphics/BaseCanvas.java +++ b/graphics/java/android/graphics/BaseCanvas.java @@ -333,6 +333,11 @@ public abstract class BaseCanvas { nDrawPath(mNativeCanvasWrapper, path.readOnlyNI(), paint.getNativeInstance()); } + public void drawRegion(@NonNull Region region, @NonNull Paint paint) { + throwIfHasHwFeaturesInSwMode(paint); + nDrawRegion(mNativeCanvasWrapper, region.mNativeRegion, paint.getNativeInstance()); + } + public void drawPoint(float x, float y, @NonNull Paint paint) { throwIfHasHwFeaturesInSwMode(paint); nDrawPoint(mNativeCanvasWrapper, x, y, paint.getNativeInstance()); diff --git a/graphics/java/android/graphics/BaseRecordingCanvas.java b/graphics/java/android/graphics/BaseRecordingCanvas.java index 4e88b0efd3e5..5b1fa7b15e6d 100644 --- a/graphics/java/android/graphics/BaseRecordingCanvas.java +++ b/graphics/java/android/graphics/BaseRecordingCanvas.java @@ -290,6 +290,11 @@ public class BaseRecordingCanvas extends Canvas { } @Override + public void drawRegion(@NonNull Region region, @NonNull Paint paint) { + nDrawRegion(mNativeCanvasWrapper, region.mNativeRegion, paint.getNativeInstance()); + } + + @Override public final void drawPicture(@NonNull Picture picture) { picture.endRecording(); int restoreCount = save(); diff --git a/graphics/java/android/graphics/Bitmap.java b/graphics/java/android/graphics/Bitmap.java index 250362b1e1e3..6d31578ac020 100644 --- a/graphics/java/android/graphics/Bitmap.java +++ b/graphics/java/android/graphics/Bitmap.java @@ -41,12 +41,15 @@ import dalvik.annotation.optimization.CriticalNative; import libcore.util.NativeAllocationRegistry; import java.io.IOException; +import java.io.ByteArrayOutputStream; import java.io.OutputStream; import java.lang.ref.WeakReference; import java.nio.Buffer; import java.nio.ByteBuffer; import java.nio.IntBuffer; import java.nio.ShortBuffer; +import java.util.ArrayList; +import java.util.WeakHashMap; public final class Bitmap implements Parcelable { private static final String TAG = "Bitmap"; @@ -120,6 +123,11 @@ public final class Bitmap implements Parcelable { } /** + * @hide + */ + private static final WeakHashMap<Bitmap, Void> sAllBitmaps = new WeakHashMap<>(); + + /** * Private constructor that must receive an already allocated native bitmap * int (pointer). */ @@ -162,6 +170,9 @@ public final class Bitmap implements Parcelable { Bitmap.class.getClassLoader(), nativeGetNativeFinalizer(), allocationByteCount); } registry.registerNativeAllocation(this, nativeBitmap); + synchronized (Bitmap.class) { + sAllBitmaps.put(this, null); + } } /** @@ -454,6 +465,11 @@ public final class Bitmap implements Parcelable { * how pixels are stored. This affects the quality (color depth) as * well as the ability to display transparent/translucent colors. */ + // It's touched by Graphics.cpp, so we need to make this enum usable on Ravenwood. + // Otherwise, all the ctors would throw, which would make the class unloadable + // because the static initializer needs the enum members because of `sConfigs`. + // TODO: Remove it once we expose the outer class. + @android.ravenwood.annotation.RavenwoodKeepWholeClass public enum Config { // these native values must match up with the enum in SkBitmap.h @@ -1510,6 +1526,86 @@ public final class Bitmap implements Parcelable { } /** + * @hide + */ + private static final class DumpData { + private int count; + private int format; + private long[] natives; + private byte[][] buffers; + private int max; + + public DumpData(@NonNull CompressFormat format, int max) { + this.max = max; + this.format = format.nativeInt; + this.natives = new long[max]; + this.buffers = new byte[max][]; + this.count = 0; + } + + public void add(long nativePtr, byte[] buffer) { + natives[count] = nativePtr; + buffers[count] = buffer; + count = (count >= max) ? max : count + 1; + } + + public int size() { + return count; + } + } + + /** + * @hide + */ + private static DumpData dumpData = null; + + + /** + * @hide + * + * Dump all the bitmaps with their contents compressed into dumpData + * + * @param format format of the compressed image, null to clear dump data + */ + public static void dumpAll(@Nullable String format) { + if (format == null) { + /* release the dump data */ + dumpData = null; + return; + } + final CompressFormat fmt; + if (format.equals("jpg") || format.equals("jpeg")) { + fmt = CompressFormat.JPEG; + } else if (format.equals("png")) { + fmt = CompressFormat.PNG; + } else if (format.equals("webp")) { + fmt = CompressFormat.WEBP_LOSSLESS; + } else { + Log.w(TAG, "No bitmaps dumped: unrecognized format " + format); + return; + } + + final ArrayList<Bitmap> allBitmaps; + synchronized (Bitmap.class) { + allBitmaps = new ArrayList<>(sAllBitmaps.size()); + for (Bitmap bitmap : sAllBitmaps.keySet()) { + if (bitmap != null && !bitmap.isRecycled()) { + allBitmaps.add(bitmap); + } + } + } + + dumpData = new DumpData(fmt, allBitmaps.size()); + for (Bitmap bitmap : allBitmaps) { + ByteArrayOutputStream bas = new ByteArrayOutputStream(); + if (bitmap.compress(fmt, 90, bas)) { + dumpData.add(bitmap.getNativeInstance(), bas.toByteArray()); + } + } + Log.i(TAG, dumpData.size() + "/" + allBitmaps.size() + " bitmaps dumped"); + } + + /** * Number of bytes of temp storage we use for communicating between the * native compressor and the java OutputStream. */ diff --git a/graphics/java/android/graphics/BitmapFactory.java b/graphics/java/android/graphics/BitmapFactory.java index d915b746e0cc..1c2014183bb7 100644 --- a/graphics/java/android/graphics/BitmapFactory.java +++ b/graphics/java/android/graphics/BitmapFactory.java @@ -143,7 +143,7 @@ public class BitmapFactory { * the decoder will try to pick the best matching config based on the * system's screen depth, and characteristics of the original image such * as if it has per-pixel alpha (requiring a config that also does). - * + * * Image are loaded with the {@link Bitmap.Config#ARGB_8888} config by * default. */ @@ -183,7 +183,7 @@ public class BitmapFactory { /** * If true (which is the default), the resulting bitmap will have its - * color channels pre-multipled by the alpha channel. + * color channels pre-multiplied by the alpha channel. * * <p>This should NOT be set to false for images to be directly drawn by * the view system or through a {@link Canvas}. The view system and @@ -221,9 +221,9 @@ public class BitmapFactory { * if {@link #inScaled} is set (which it is by default} and this * density does not match {@link #inTargetDensity}, then the bitmap * will be scaled to the target density before being returned. - * + * * <p>If this is 0, - * {@link BitmapFactory#decodeResource(Resources, int)}, + * {@link BitmapFactory#decodeResource(Resources, int)}, * {@link BitmapFactory#decodeResource(Resources, int, android.graphics.BitmapFactory.Options)}, * and {@link BitmapFactory#decodeResourceStream} * will fill in the density associated with the resource. The other @@ -242,29 +242,29 @@ public class BitmapFactory { * This is used in conjunction with {@link #inDensity} and * {@link #inScaled} to determine if and how to scale the bitmap before * returning it. - * + * * <p>If this is 0, - * {@link BitmapFactory#decodeResource(Resources, int)}, + * {@link BitmapFactory#decodeResource(Resources, int)}, * {@link BitmapFactory#decodeResource(Resources, int, android.graphics.BitmapFactory.Options)}, * and {@link BitmapFactory#decodeResourceStream} * will fill in the density associated the Resources object's * DisplayMetrics. The other * functions will leave it as-is and no scaling for density will be * performed. - * + * * @see #inDensity * @see #inScreenDensity * @see #inScaled * @see android.util.DisplayMetrics#densityDpi */ public int inTargetDensity; - + /** * The pixel density of the actual screen that is being used. This is * purely for applications running in density compatibility code, where * {@link #inTargetDensity} is actually the density the application * sees rather than the real screen density. - * + * * <p>By setting this, you * allow the loading code to avoid scaling a bitmap that is currently * in the screen density up/down to the compatibility density. Instead, @@ -274,18 +274,18 @@ public class BitmapFactory { * Bitmap.getScaledWidth} and {@link Bitmap#getScaledHeight * Bitmap.getScaledHeight} to account for any different between the * bitmap's density and the target's density. - * + * * <p>This is never set automatically for the caller by * {@link BitmapFactory} itself. It must be explicitly set, since the * caller must deal with the resulting bitmap in a density-aware way. - * + * * @see #inDensity * @see #inTargetDensity * @see #inScaled * @see android.util.DisplayMetrics#densityDpi */ public int inScreenDensity; - + /** * When this flag is set, if {@link #inDensity} and * {@link #inTargetDensity} are not 0, the @@ -345,7 +345,7 @@ public class BitmapFactory { * ignored. * * In {@link android.os.Build.VERSION_CODES#KITKAT} and below, this - * field works in conjuction with inPurgeable. If inPurgeable is false, + * field works in conjunction with inPurgeable. If inPurgeable is false, * then this field is ignored. If inPurgeable is true, then this field * determines whether the bitmap can share a reference to the input * data (inputstream, array, etc.) or if it must make a deep copy. @@ -583,11 +583,11 @@ public class BitmapFactory { opts.inDensity = density; } } - + if (opts.inTargetDensity == 0 && res != null) { opts.inTargetDensity = res.getDisplayMetrics().densityDpi; } - + return decodeStream(is, pad, opts); } @@ -611,8 +611,8 @@ public class BitmapFactory { public static Bitmap decodeResource(Resources res, int id, Options opts) { validate(opts); Bitmap bm = null; - InputStream is = null; - + InputStream is = null; + try { final TypedValue value = new TypedValue(); is = res.openRawResource(id, value); diff --git a/graphics/java/android/graphics/Canvas.java b/graphics/java/android/graphics/Canvas.java index b6ce9b64323b..0b3e5456d81c 100644 --- a/graphics/java/android/graphics/Canvas.java +++ b/graphics/java/android/graphics/Canvas.java @@ -55,7 +55,7 @@ import java.lang.annotation.RetentionPolicy; * Canvas and Drawables</a> developer guide.</p></div> */ public class Canvas extends BaseCanvas { - private static int sCompatiblityVersion = 0; + private static int sCompatibilityVersion = 0; private static boolean sCompatibilityRestore = false; private static boolean sCompatibilitySetBitmap = false; @@ -74,7 +74,7 @@ public class Canvas extends BaseCanvas { // Maximum bitmap size as defined in Skia's native code // (see SkCanvas.cpp, SkDraw.cpp) - private static final int MAXMIMUM_BITMAP_SIZE = 32766; + private static final int MAXIMUM_BITMAP_SIZE = 32766; // Use a Holder to allow static initialization of Canvas in the boot image. private static class NoImagePreloadHolder { @@ -331,7 +331,7 @@ public class Canvas extends BaseCanvas { * @see #getMaximumBitmapHeight() */ public int getMaximumBitmapWidth() { - return MAXMIMUM_BITMAP_SIZE; + return MAXIMUM_BITMAP_SIZE; } /** @@ -342,7 +342,7 @@ public class Canvas extends BaseCanvas { * @see #getMaximumBitmapWidth() */ public int getMaximumBitmapHeight() { - return MAXMIMUM_BITMAP_SIZE; + return MAXIMUM_BITMAP_SIZE; } // the SAVE_FLAG constants must match their native equivalents @@ -423,7 +423,7 @@ public class Canvas extends BaseCanvas { public static final int ALL_SAVE_FLAG = 0x1F; private static void checkValidSaveFlags(int saveFlags) { - if (sCompatiblityVersion >= Build.VERSION_CODES.P + if (sCompatibilityVersion >= Build.VERSION_CODES.P && saveFlags != ALL_SAVE_FLAG) { throw new IllegalArgumentException( "Invalid Layer Save Flag - only ALL_SAVE_FLAGS is allowed"); @@ -789,10 +789,8 @@ public class Canvas extends BaseCanvas { * @param m The 4x4 matrix to preconcatenate with the current matrix */ @FlaggedApi(Flags.FLAG_MATRIX_44) - public void concat44(@Nullable Matrix44 m) { - if (m != null) { - nConcat(mNativeCanvasWrapper, m.mBackingArray); - } + public void concat(@Nullable Matrix44 m) { + if (m != null) nConcat(mNativeCanvasWrapper, m.mBackingArray); } /** @@ -847,7 +845,7 @@ public class Canvas extends BaseCanvas { } private static void checkValidClipOp(@NonNull Region.Op op) { - if (sCompatiblityVersion >= Build.VERSION_CODES.P + if (sCompatibilityVersion >= Build.VERSION_CODES.P && op != Region.Op.INTERSECT && op != Region.Op.DIFFERENCE) { throw new IllegalArgumentException( "Invalid Region.Op - only INTERSECT and DIFFERENCE are allowed"); @@ -1437,7 +1435,7 @@ public class Canvas extends BaseCanvas { } /*package*/ static void setCompatibilityVersion(int apiLevel) { - sCompatiblityVersion = apiLevel; + sCompatibilityVersion = apiLevel; sCompatibilityRestore = apiLevel < Build.VERSION_CODES.M; sCompatibilitySetBitmap = apiLevel < Build.VERSION_CODES.O; nSetCompatibilityVersion(apiLevel); @@ -1933,6 +1931,17 @@ public class Canvas extends BaseCanvas { } /** + * Draws the given region using the given paint. + * + * @param region The region to be drawn + * @param paint The paint used to draw the region + */ + @FlaggedApi(Flags.FLAG_DRAW_REGION) + public void drawRegion(@NonNull Region region, @NonNull Paint paint) { + super.drawRegion(region, paint); + } + + /** * Helper for drawPoints() for drawing a single point. */ public void drawPoint(float x, float y, @NonNull Paint paint) { diff --git a/graphics/java/android/graphics/Color.java b/graphics/java/android/graphics/Color.java index 0f2f8797b896..c1edafc16274 100644 --- a/graphics/java/android/graphics/Color.java +++ b/graphics/java/android/graphics/Color.java @@ -289,6 +289,9 @@ import java.util.function.DoubleUnaryOperator; */ @AnyThread @SuppressAutoDoc +@android.ravenwood.annotation.RavenwoodKeepWholeClass +@android.ravenwood.annotation.RavenwoodClassLoadHook( + android.ravenwood.annotation.RavenwoodClassLoadHook.LIBANDROID_LOADING_HOOK) public class Color { @ColorInt public static final int BLACK = 0xFF000000; @ColorInt public static final int DKGRAY = 0xFF444444; diff --git a/graphics/java/android/graphics/ColorSpace.java b/graphics/java/android/graphics/ColorSpace.java index a2319a53a659..4bc3ecebb067 100644 --- a/graphics/java/android/graphics/ColorSpace.java +++ b/graphics/java/android/graphics/ColorSpace.java @@ -135,6 +135,9 @@ import java.util.function.DoubleUnaryOperator; @AnyThread @SuppressWarnings("StaticInitializerReferencesSubClass") @SuppressAutoDoc +@android.ravenwood.annotation.RavenwoodKeepWholeClass +@android.ravenwood.annotation.RavenwoodClassLoadHook( + android.ravenwood.annotation.RavenwoodClassLoadHook.LIBANDROID_LOADING_HOOK) public abstract class ColorSpace { /** * Standard CIE 1931 2° illuminant A, encoded in xyY. @@ -2490,9 +2493,16 @@ public abstract class ColorSpace { return mNativePtr; } - private static native long nativeGetNativeFinalizer(); - private static native long nativeCreate(float a, float b, float c, float d, - float e, float f, float g, float[] xyz); + /** + * These methods can't be put in the Rgb class directly, because ColorSpace's + * static initializer instantiates Rgb, whose constructor needs them, which is a variation + * of b/337329128. + */ + static class Native { + static native long nativeGetNativeFinalizer(); + static native long nativeCreate(float a, float b, float c, float d, + float e, float f, float g, float[] xyz); + } private static DoubleUnaryOperator generateOETF(TransferParameters function) { if (function.isHLGish()) { @@ -2959,7 +2969,7 @@ public abstract class ColorSpace { // This mimics the old code that was in native. float[] nativeTransform = adaptToIlluminantD50(mWhitePoint, mTransform); - mNativePtr = nativeCreate((float) mTransferParameters.a, + mNativePtr = Native.nativeCreate((float) mTransferParameters.a, (float) mTransferParameters.b, (float) mTransferParameters.c, (float) mTransferParameters.d, @@ -2975,7 +2985,7 @@ public abstract class ColorSpace { private static class NoImagePreloadHolder { public static final NativeAllocationRegistry sRegistry = new NativeAllocationRegistry( - ColorSpace.Rgb.class.getClassLoader(), nativeGetNativeFinalizer(), 0); + ColorSpace.Rgb.class.getClassLoader(), Native.nativeGetNativeFinalizer(), 0); } /** diff --git a/graphics/java/android/graphics/ComposePathEffect.java b/graphics/java/android/graphics/ComposePathEffect.java index 3fc9eb5aea15..7d59ecea948e 100644 --- a/graphics/java/android/graphics/ComposePathEffect.java +++ b/graphics/java/android/graphics/ComposePathEffect.java @@ -20,13 +20,13 @@ public class ComposePathEffect extends PathEffect { /** * Construct a PathEffect whose effect is to apply first the inner effect - * and the the outer pathEffect (e.g. outer(inner(path))). + * and the outer pathEffect (e.g. outer(inner(path))). */ public ComposePathEffect(PathEffect outerpe, PathEffect innerpe) { native_instance = nativeCreate(outerpe.native_instance, innerpe.native_instance); } - + private static native long nativeCreate(long nativeOuterpe, long nativeInnerpe); } diff --git a/graphics/java/android/graphics/FontFamily.java b/graphics/java/android/graphics/FontFamily.java index f50de1665453..88f0e8ef8a94 100644 --- a/graphics/java/android/graphics/FontFamily.java +++ b/graphics/java/android/graphics/FontFamily.java @@ -45,15 +45,17 @@ public class FontFamily { private static String TAG = "FontFamily"; - private static final NativeAllocationRegistry sBuilderRegistry = - NativeAllocationRegistry.createMalloced( - FontFamily.class.getClassLoader(), nGetBuilderReleaseFunc()); - private @Nullable Runnable mNativeBuilderCleaner; - private static final NativeAllocationRegistry sFamilyRegistry = - NativeAllocationRegistry.createMalloced( - FontFamily.class.getClassLoader(), nGetFamilyReleaseFunc()); + private static class NoImagePreloadHolder { + private static final NativeAllocationRegistry sBuilderRegistry = + NativeAllocationRegistry.createMalloced( + FontFamily.class.getClassLoader(), nGetBuilderReleaseFunc()); + + private static final NativeAllocationRegistry sFamilyRegistry = + NativeAllocationRegistry.createMalloced( + FontFamily.class.getClassLoader(), nGetFamilyReleaseFunc()); + } /** * @hide @@ -74,7 +76,8 @@ public class FontFamily { publicAlternatives = "Use {@link android.graphics.fonts.FontFamily} instead.") public FontFamily() { mBuilderPtr = nInitBuilder(null, 0); - mNativeBuilderCleaner = sBuilderRegistry.registerNativeAllocation(this, mBuilderPtr); + mNativeBuilderCleaner = NoImagePreloadHolder.sBuilderRegistry.registerNativeAllocation(this, + mBuilderPtr); } /** @@ -92,7 +95,8 @@ public class FontFamily { langsString = TextUtils.join(",", langs); } mBuilderPtr = nInitBuilder(langsString, variant); - mNativeBuilderCleaner = sBuilderRegistry.registerNativeAllocation(this, mBuilderPtr); + mNativeBuilderCleaner = NoImagePreloadHolder.sBuilderRegistry.registerNativeAllocation(this, + mBuilderPtr); } /** @@ -113,7 +117,7 @@ public class FontFamily { mNativeBuilderCleaner.run(); mBuilderPtr = 0; if (mNativePtr != 0) { - sFamilyRegistry.registerNativeAllocation(this, mNativePtr); + NoImagePreloadHolder.sFamilyRegistry.registerNativeAllocation(this, mNativePtr); } return mNativePtr != 0; } @@ -215,7 +219,7 @@ public class FontFamily { @CriticalNative private static native long nGetFamilyReleaseFunc(); - // By passing -1 to weigth argument, the weight value is resolved by OS/2 table in the font. + // By passing -1 to weight argument, the weight value is resolved by OS/2 table in the font. // By passing -1 to italic argument, the italic value is resolved by OS/2 table in the font. private static native boolean nAddFont(long builderPtr, ByteBuffer font, int ttcIndex, int weight, int isItalic); diff --git a/graphics/java/android/graphics/FontListParser.java b/graphics/java/android/graphics/FontListParser.java index 17c2dd94cd36..13c4a94cb9b6 100644 --- a/graphics/java/android/graphics/FontListParser.java +++ b/graphics/java/android/graphics/FontListParser.java @@ -127,7 +127,7 @@ public class FontListParser { parser.setInput(is, null); parser.nextTag(); return readFamilies(parser, systemFontDir, oemCustomization, updatableFontMap, - lastModifiedDate, configVersion, false /* filter out the non-exising files */); + lastModifiedDate, configVersion, false /* filter out the non-existing files */); } } @@ -254,7 +254,7 @@ public class FontListParser { * @param parser An XML parser. * @param fontDir a font directory name. * @param updatableFontMap a updated font file map. - * @param allowNonExistingFile true to allow font file that doesn't exists + * @param allowNonExistingFile true to allow font file that doesn't exist. * @return a FontFamily instance. null if no font files are available in this FontFamily. */ public static @Nullable FontConfig.FontFamily readFamily(XmlPullParser parser, String fontDir, diff --git a/graphics/java/android/graphics/FrameInfo.java b/graphics/java/android/graphics/FrameInfo.java index b3615ff60bce..8f1282897780 100644 --- a/graphics/java/android/graphics/FrameInfo.java +++ b/graphics/java/android/graphics/FrameInfo.java @@ -24,7 +24,7 @@ import java.lang.annotation.RetentionPolicy; /** * Class that contains all the timing information for the current frame. This * is used in conjunction with the hardware renderer to provide - * continous-monitoring jank events + * continuous-monitoring jank events * * All times in nanoseconds from CLOCK_MONOTONIC/System.nanoTime() * diff --git a/graphics/java/android/graphics/HardwareRenderer.java b/graphics/java/android/graphics/HardwareRenderer.java index 20e393eaee6d..940cd93c53f2 100644 --- a/graphics/java/android/graphics/HardwareRenderer.java +++ b/graphics/java/android/graphics/HardwareRenderer.java @@ -25,6 +25,8 @@ import android.app.ActivityManager; import android.content.Context; import android.content.pm.ActivityInfo; import android.content.res.Configuration; +import android.hardware.DataSpace; +import android.hardware.HardwareBuffer; import android.hardware.OverlayProperties; import android.hardware.display.DisplayManager; import android.os.IBinder; @@ -1417,7 +1419,14 @@ public class HardwareRenderer { nInitDisplayInfo(largestWidth, largestHeight, defaultDisplay.getRefreshRate(), wideColorDataspace, defaultDisplay.getAppVsyncOffsetNanos(), defaultDisplay.getPresentationDeadlineNanos(), - overlayProperties.isFp16SupportedForHdr(), + overlayProperties.isCombinationSupported( + DataSpace.DATASPACE_SCRGB, HardwareBuffer.RGBA_FP16), + overlayProperties.isCombinationSupported( + DataSpace.pack( + DataSpace.STANDARD_DCI_P3, + DataSpace.TRANSFER_SRGB, + DataSpace.RANGE_EXTENDED), + HardwareBuffer.RGBA_10101010), overlayProperties.isMixedColorSpacesSupported()); mDisplayInitialized = true; @@ -1603,7 +1612,8 @@ public class HardwareRenderer { private static native void nInitDisplayInfo(int width, int height, float refreshRate, int wideColorDataspace, long appVsyncOffsetNanos, long presentationDeadlineNanos, - boolean supportsFp16ForHdr, boolean nInitDisplayInfo); + boolean supportsFp16ForHdr, boolean isRgba10101010SupportedForHdr, + boolean nSupportMixedColorSpaces); private static native void nSetDrawingEnabled(boolean drawingEnabled); diff --git a/graphics/java/android/graphics/Interpolator.java b/graphics/java/android/graphics/Interpolator.java index 104546454fa9..28f296d3621d 100644 --- a/graphics/java/android/graphics/Interpolator.java +++ b/graphics/java/android/graphics/Interpolator.java @@ -18,6 +18,9 @@ package android.graphics; import android.os.SystemClock; +@android.ravenwood.annotation.RavenwoodKeepWholeClass +@android.ravenwood.annotation.RavenwoodClassLoadHook( + android.ravenwood.annotation.RavenwoodClassLoadHook.LIBANDROID_LOADING_HOOK) public class Interpolator { public Interpolator(int valueCount) { @@ -25,13 +28,13 @@ public class Interpolator { mFrameCount = 2; native_instance = nativeConstructor(valueCount, 2); } - + public Interpolator(int valueCount, int frameCount) { mValueCount = valueCount; mFrameCount = frameCount; native_instance = nativeConstructor(valueCount, frameCount); } - + /** * Reset the Interpolator to have the specified number of values and an * implicit keyFrame count of 2 (just a start and end). After this call the @@ -40,7 +43,7 @@ public class Interpolator { public void reset(int valueCount) { reset(valueCount, 2); } - + /** * Reset the Interpolator to have the specified number of values and * keyFrames. After this call the values for each keyFrame must be assigned @@ -51,20 +54,20 @@ public class Interpolator { mFrameCount = frameCount; nativeReset(native_instance, valueCount, frameCount); } - + public final int getKeyFrameCount() { return mFrameCount; } - + public final int getValueCount() { return mValueCount; } - + /** * Assign the keyFrame (specified by index) a time value and an array of key - * values (with an implicity blend array of [0, 0, 1, 1] giving linear + * values (with an implicitly blend array of [0, 0, 1, 1] giving linear * transition to the next set of key values). - * + * * @param index The index of the key frame to assign * @param msec The time (in mililiseconds) for this key frame. Based on the * SystemClock.uptimeMillis() clock @@ -77,7 +80,7 @@ public class Interpolator { /** * Assign the keyFrame (specified by index) a time value and an array of key * values and blend array. - * + * * @param index The index of the key frame to assign * @param msec The time (in mililiseconds) for this key frame. Based on the * SystemClock.uptimeMillis() clock @@ -96,7 +99,7 @@ public class Interpolator { } nativeSetKeyFrame(native_instance, index, msec, values, blend); } - + /** * Set a repeat count (which may be fractional) for the interpolator, and * whether the interpolator should mirror its repeats. The default settings @@ -107,7 +110,7 @@ public class Interpolator { nativeSetRepeatMirror(native_instance, repeatCount, mirror); } } - + public enum Result { NORMAL, FREEZE_START, @@ -127,7 +130,7 @@ public class Interpolator { * return whether the specified time was within the range of key times * (NORMAL), was before the first key time (FREEZE_START) or after the last * key time (FREEZE_END). In any event, computed values are always returned. - * + * * @param msec The time (in milliseconds) used to sample into the * Interpolator. Based on the SystemClock.uptimeMillis() clock * @param values Where to write the computed values (may be NULL). @@ -143,13 +146,13 @@ public class Interpolator { default: return Result.FREEZE_END; } } - + @Override protected void finalize() throws Throwable { nativeDestructor(native_instance); native_instance = 0; // Other finalizers can still call us. } - + private int mValueCount; private int mFrameCount; private long native_instance; diff --git a/graphics/java/android/graphics/LightingColorFilter.java b/graphics/java/android/graphics/LightingColorFilter.java index 0aa6f1282c1a..fe73a1a70b9c 100644 --- a/graphics/java/android/graphics/LightingColorFilter.java +++ b/graphics/java/android/graphics/LightingColorFilter.java @@ -16,8 +16,8 @@ // This file was generated from the C++ include file: SkColorFilter.h // Any changes made to this file will be discarded by the build. -// To change this file, either edit the include, or device/tools/gluemaker/main.cpp, -// or one of the auxilary file specifications in device/tools/gluemaker. +// To change this file, either edit the include, or device/tools/gluemaker/main.cpp, +// or one of the auxiliary file specifications in device/tools/gluemaker. package android.graphics; diff --git a/graphics/java/android/graphics/LinearGradient.java b/graphics/java/android/graphics/LinearGradient.java index 56d912b1eada..087937144b97 100644 --- a/graphics/java/android/graphics/LinearGradient.java +++ b/graphics/java/android/graphics/LinearGradient.java @@ -63,7 +63,7 @@ public class LinearGradient extends Shader { * @param colors The sRGB colors to be distributed along the gradient line * @param positions May be null. The relative positions [0..1] of * each corresponding color in the colors array. If this is null, - * the the colors are distributed evenly along the gradient line. + * the colors are distributed evenly along the gradient line. * @param tile The Shader tiling mode */ public LinearGradient(float x0, float y0, float x1, float y1, @NonNull @ColorInt int[] colors, @@ -82,7 +82,7 @@ public class LinearGradient extends Shader { * @param colors The colors to be distributed along the gradient line * @param positions May be null. The relative positions [0..1] of * each corresponding color in the colors array. If this is null, - * the the colors are distributed evenly along the gradient line. + * the colors are distributed evenly along the gradient line. * @param tile The Shader tiling mode * * @throws IllegalArgumentException if there are less than two colors, the colors do diff --git a/graphics/java/android/graphics/Matrix.java b/graphics/java/android/graphics/Matrix.java index bc58febc388b..748e9dd98e10 100644 --- a/graphics/java/android/graphics/Matrix.java +++ b/graphics/java/android/graphics/Matrix.java @@ -28,6 +28,9 @@ import java.io.PrintWriter; /** * The Matrix class holds a 3x3 matrix for transforming coordinates. */ +@android.ravenwood.annotation.RavenwoodKeepWholeClass +@android.ravenwood.annotation.RavenwoodClassLoadHook( + android.ravenwood.annotation.RavenwoodClassLoadHook.LIBANDROID_LOADING_HOOK) public class Matrix { public static final int MSCALE_X = 0; //!< use with getValues/setValues @@ -229,7 +232,7 @@ public class Matrix { private static class NoImagePreloadHolder { public static final NativeAllocationRegistry sRegistry = NativeAllocationRegistry.createMalloced( - Matrix.class.getClassLoader(), nGetNativeFinalizer()); + Matrix.class.getClassLoader(), ExtraNatives.nGetNativeFinalizer()); } private final long native_instance; @@ -238,7 +241,7 @@ public class Matrix { * Create an identity matrix */ public Matrix() { - native_instance = nCreate(0); + native_instance = ExtraNatives.nCreate(0); NoImagePreloadHolder.sRegistry.registerNativeAllocation(this, native_instance); } @@ -248,7 +251,7 @@ public class Matrix { * @param src The matrix to copy into this matrix */ public Matrix(Matrix src) { - native_instance = nCreate(src != null ? src.native_instance : 0); + native_instance = ExtraNatives.nCreate(src != null ? src.native_instance : 0); NoImagePreloadHolder.sRegistry.registerNativeAllocation(this, native_instance); } @@ -559,7 +562,7 @@ public class Matrix { /** * Set the matrix to the scale and translate values that map the source rectangle to the - * destination rectangle, returning true if the the result can be represented. + * destination rectangle, returning true if the result can be represented. * * @param src the source rectangle to map from. * @param dst the destination rectangle to map to. @@ -846,12 +849,6 @@ public class Matrix { return native_instance; } - // ------------------ Regular JNI ------------------------ - - private static native long nCreate(long nSrc_or_zero); - private static native long nGetNativeFinalizer(); - - // ------------------ Fast JNI ------------------------ @FastNative @@ -943,4 +940,17 @@ public class Matrix { private static native float nMapRadius(long nObject, float radius); @CriticalNative private static native boolean nEquals(long nA, long nB); + + /** + * Due to b/337329128, native methods that are called by the static initializers cannot be + * in the same class when running on a host side JVM (such as on Ravenwood and Android Studio). + * + * There are two methods that are called by the static initializers (either directly or + * indirectly) in this class, namely nCreate() and nGetNativeFinalizer(). On Ravenwood + * these methods can't be on the Matrix class itself, so we use a nested class to host them. + */ + private static class ExtraNatives { + static native long nCreate(long nSrc_or_zero); + static native long nGetNativeFinalizer(); + } } diff --git a/graphics/java/android/graphics/Matrix44.java b/graphics/java/android/graphics/Matrix44.java index 7cc0eb7a6728..a99e20101c3b 100644 --- a/graphics/java/android/graphics/Matrix44.java +++ b/graphics/java/android/graphics/Matrix44.java @@ -17,6 +17,7 @@ package android.graphics; import android.annotation.FlaggedApi; +import android.annotation.IntRange; import android.annotation.NonNull; import com.android.graphics.hwui.flags.Flags; @@ -98,11 +99,11 @@ public class Matrix44 { /** * Gets the value at the matrix's row and column. * - * @param row An integer from 0 to 4 indicating the row of the value to get - * @param col An integer from 0 to 4 indicating the column of the value to get + * @param row An integer from 0 to 3 indicating the row of the value to get + * @param col An integer from 0 to 3 indicating the column of the value to get */ @FlaggedApi(Flags.FLAG_MATRIX_44) - public float get(int row, int col) { + public float get(@IntRange(from = 0, to = 3) int row, @IntRange(from = 0, to = 3) int col) { if (row >= 0 && row < 4 && col >= 0 && col < 4) { return mBackingArray[row * 4 + col]; } @@ -112,12 +113,13 @@ public class Matrix44 { /** * Sets the value at the matrix's row and column to the provided value. * - * @param row An integer from 0 to 4 indicating the row of the value to change - * @param col An integer from 0 to 4 indicating the column of the value to change + * @param row An integer from 0 to 3 indicating the row of the value to change + * @param col An integer from 0 to 3 indicating the column of the value to change * @param val The value the element at the specified index will be set to */ @FlaggedApi(Flags.FLAG_MATRIX_44) - public void set(int row, int col, float val) { + public void set(@IntRange(from = 0, to = 3) int row, @IntRange(from = 0, to = 3) int col, + float val) { if (row >= 0 && row < 4 && col >= 0 && col < 4) { mBackingArray[row * 4 + col] = val; } else { diff --git a/graphics/java/android/graphics/Mesh.java b/graphics/java/android/graphics/Mesh.java index a4bce9eb5e88..6be8332e784b 100644 --- a/graphics/java/android/graphics/Mesh.java +++ b/graphics/java/android/graphics/Mesh.java @@ -271,7 +271,7 @@ public class Mesh { * not have a uniform with that name or if the uniform is declared with a type other than int * or int[1] then an IllegalArgumentException is thrown. * - * @param uniformName name matching the int uniform delcared in the shader program. + * @param uniformName name matching the int uniform declared in the shader program. * @param value value corresponding to the int uniform with the given name. */ public void setIntUniform(@NonNull String uniformName, int value) { @@ -283,7 +283,7 @@ public class Mesh { * not have a uniform with that name or if the uniform is declared with a type other than ivec2 * or int[2] then an IllegalArgumentException is thrown. * - * @param uniformName name matching the int uniform delcared in the shader program. + * @param uniformName name matching the int uniform declared in the shader program. * @param value1 first value corresponding to the int uniform with the given name. * @param value2 second value corresponding to the int uniform with the given name. */ @@ -296,7 +296,7 @@ public class Mesh { * not have a uniform with that name or if the uniform is declared with a type other than ivec3 * or int[3] then an IllegalArgumentException is thrown. * - * @param uniformName name matching the int uniform delcared in the shader program. + * @param uniformName name matching the int uniform declared in the shader program. * @param value1 first value corresponding to the int uniform with the given name. * @param value2 second value corresponding to the int uniform with the given name. * @param value3 third value corresponding to the int uniform with the given name. @@ -310,7 +310,7 @@ public class Mesh { * not have a uniform with that name or if the uniform is declared with a type other than ivec4 * or int[4] then an IllegalArgumentException is thrown. * - * @param uniformName name matching the int uniform delcared in the shader program. + * @param uniformName name matching the int uniform declared in the shader program. * @param value1 first value corresponding to the int uniform with the given name. * @param value2 second value corresponding to the int uniform with the given name. * @param value3 third value corresponding to the int uniform with the given name. @@ -327,7 +327,7 @@ public class Mesh { * int (for N=1), ivecN, or int[N], where N is the length of the values param, then an * IllegalArgumentException is thrown. * - * @param uniformName name matching the int uniform delcared in the shader program. + * @param uniformName name matching the int uniform declared in the shader program. * @param values int values corresponding to the vec4 int uniform with the given name. */ public void setIntUniform(@NonNull String uniformName, @NonNull int[] values) { diff --git a/graphics/java/android/graphics/NinePatch.java b/graphics/java/android/graphics/NinePatch.java index af2095713ec2..382269f74366 100644 --- a/graphics/java/android/graphics/NinePatch.java +++ b/graphics/java/android/graphics/NinePatch.java @@ -22,12 +22,12 @@ import android.compat.annotation.UnsupportedAppUsage; * The NinePatch class permits drawing a bitmap in nine or more sections. * Essentially, it allows the creation of custom graphics that will scale the * way that you define, when content added within the image exceeds the normal - * bounds of the graphic. For a thorough explanation of a NinePatch image, - * read the discussion in the + * bounds of the graphic. For a thorough explanation of a NinePatch image, + * read the discussion in the * <a href="{@docRoot}guide/topics/graphics/2d-graphics.html#nine-patch">2D * Graphics</a> document. * <p> - * The <a href="{@docRoot}guide/developing/tools/draw9patch.html">Draw 9-Patch</a> + * The <a href="{@docRoot}guide/developing/tools/draw9patch.html">Draw 9-Patch</a> * tool offers an extremely handy way to create your NinePatch images, * using a WYSIWYG graphics editor. * </p> @@ -104,7 +104,7 @@ public class NinePatch { this(bitmap, chunk, null); } - /** + /** * Create a drawable projection from a bitmap to nine patches. * * @param bitmap The bitmap describing the patches. @@ -122,7 +122,7 @@ public class NinePatch { protected void finalize() throws Throwable { try { if (mNativeChunk != 0) { - // only attempt to destroy correctly initilized chunks + // only attempt to destroy correctly initialized chunks nativeFinalize(mNativeChunk); mNativeChunk = 0; } @@ -169,8 +169,8 @@ public class NinePatch { public Bitmap getBitmap() { return mBitmap; } - - /** + + /** * Draws the NinePatch. This method will use the paint returned by {@link #getPaint()}. * * @param canvas A container for the current matrix and clip used to draw the NinePatch. @@ -180,7 +180,7 @@ public class NinePatch { canvas.drawPatch(this, location, mPaint); } - /** + /** * Draws the NinePatch. This method will use the paint returned by {@link #getPaint()}. * * @param canvas A container for the current matrix and clip used to draw the NinePatch. @@ -190,7 +190,7 @@ public class NinePatch { canvas.drawPatch(this, location, mPaint); } - /** + /** * Draws the NinePatch. This method will ignore the paint returned * by {@link #getPaint()} and use the specified paint instead. * diff --git a/graphics/java/android/graphics/Path.java b/graphics/java/android/graphics/Path.java index deb89faf3419..073307c7a2e8 100644 --- a/graphics/java/android/graphics/Path.java +++ b/graphics/java/android/graphics/Path.java @@ -36,11 +36,16 @@ import libcore.util.NativeAllocationRegistry; * (based on the paint's Style), or it can be used for clipping or to draw * text on a path. */ +@android.ravenwood.annotation.RavenwoodKeepWholeClass +@android.ravenwood.annotation.RavenwoodClassLoadHook( + android.ravenwood.annotation.RavenwoodClassLoadHook.LIBANDROID_LOADING_HOOK) public class Path { - - private static final NativeAllocationRegistry sRegistry = - NativeAllocationRegistry.createMalloced( - Path.class.getClassLoader(), nGetFinalizer()); + // See b/337329128 for why we need an inner class here. + private static class NoImagePreloadHolder { + static final NativeAllocationRegistry sRegistry = + NativeAllocationRegistry.createMalloced( + Path.class.getClassLoader(), nGetFinalizer()); + } /** * @hide @@ -52,7 +57,7 @@ public class Path { */ public Path() { mNativePath = nInit(); - sRegistry.registerNativeAllocation(this, mNativePath); + NoImagePreloadHolder.sRegistry.registerNativeAllocation(this, mNativePath); } /** @@ -62,7 +67,7 @@ public class Path { */ public Path(@Nullable Path src) { mNativePath = nInit(src != null ? src.mNativePath : 0); - sRegistry.registerNativeAllocation(this, mNativePath); + NoImagePreloadHolder.sRegistry.registerNativeAllocation(this, mNativePath); } /** diff --git a/graphics/java/android/graphics/PathMeasure.java b/graphics/java/android/graphics/PathMeasure.java index 5500c5217de4..2c6cfa5c2e3d 100644 --- a/graphics/java/android/graphics/PathMeasure.java +++ b/graphics/java/android/graphics/PathMeasure.java @@ -25,14 +25,14 @@ public class PathMeasure { * setPath. * * Note that once a path is associated with the measure object, it is - * undefined if the path is subsequently modified and the the measure object + * undefined if the path is subsequently modified and the measure object * is used. If the path is modified, you must call setPath with the path. */ public PathMeasure() { mPath = null; native_instance = native_create(0, false); } - + /** * Create a PathMeasure object associated with the specified path object * (already created and specified). The measure object can now return the @@ -40,7 +40,7 @@ public class PathMeasure { * path. * * Note that once a path is associated with the measure object, it is - * undefined if the path is subsequently modified and the the measure object + * undefined if the path is subsequently modified and the measure object * is used. If the path is modified, you must call setPath with the path. * * @param path The path that will be measured by this object @@ -121,7 +121,7 @@ public class PathMeasure { * such as <code>dst.rLineTo(0, 0)</code>.</p> */ public boolean getSegment(float startD, float stopD, Path dst, boolean startWithMoveTo) { - // Skia used to enforce this as part of it's API, but has since relaxed that restriction + // Skia used to enforce this as part of its API, but has since relaxed that restriction // so to maintain consistency in our API we enforce the preconditions here. float length = getLength(); if (startD < 0) { diff --git a/graphics/java/android/graphics/Rasterizer.java b/graphics/java/android/graphics/Rasterizer.java index 29d82fa1d98b..575095426563 100644 --- a/graphics/java/android/graphics/Rasterizer.java +++ b/graphics/java/android/graphics/Rasterizer.java @@ -16,8 +16,8 @@ // This file was generated from the C++ include file: SkRasterizer.h // Any changes made to this file will be discarded by the build. -// To change this file, either edit the include, or device/tools/gluemaker/main.cpp, -// or one of the auxilary file specifications in device/tools/gluemaker. +// To change this file, either edit the include, or device/tools/gluemaker/main.cpp, +// or one of the auxiliary file specifications in device/tools/gluemaker. package android.graphics; diff --git a/graphics/java/android/graphics/RecordingCanvas.java b/graphics/java/android/graphics/RecordingCanvas.java index 635e78e674be..cc5b3b94e0fa 100644 --- a/graphics/java/android/graphics/RecordingCanvas.java +++ b/graphics/java/android/graphics/RecordingCanvas.java @@ -40,7 +40,7 @@ public final class RecordingCanvas extends BaseRecordingCanvas { /** @hide */ private static int getPanelFrameSize() { - final int DefaultSize = 100 * 1024 * 1024; // 100 MB; + final int DefaultSize = 150 * 1024 * 1024; // 150 MB; return Math.max(SystemProperties.getInt("ro.hwui.max_texture_allocation_size", DefaultSize), DefaultSize); } @@ -262,7 +262,7 @@ public final class RecordingCanvas extends BaseRecordingCanvas { protected void throwIfCannotDraw(Bitmap bitmap) { super.throwIfCannotDraw(bitmap); int bitmapSize = bitmap.getByteCount(); - if (bitmapSize > MAX_BITMAP_SIZE) { + if (bitmap.getConfig() != Bitmap.Config.HARDWARE && bitmapSize > MAX_BITMAP_SIZE) { throw new RuntimeException( "Canvas: trying to draw too large(" + bitmapSize + "bytes) bitmap."); } diff --git a/graphics/java/android/graphics/Rect.java b/graphics/java/android/graphics/Rect.java index 411a10b85bd2..5211e3a75d09 100644 --- a/graphics/java/android/graphics/Rect.java +++ b/graphics/java/android/graphics/Rect.java @@ -165,7 +165,7 @@ public final class Rect implements Parcelable { public String toShortString() { return toShortString(new StringBuilder(32)); } - + /** * Return a string representation of the rectangle in a compact form. * @hide @@ -184,7 +184,7 @@ public final class Rect implements Parcelable { * * <p>You can later recover the Rect from this string through * {@link #unflattenFromString(String)}. - * + * * @return Returns a new String of the form "left top right bottom" */ @NonNull @@ -314,7 +314,7 @@ public final class Rect implements Parcelable { public final int height() { return bottom - top; } - + /** * @return the horizontal center of the rectangle. If the computed value * is fractional, this method returns the largest integer that is @@ -323,7 +323,7 @@ public final class Rect implements Parcelable { public final int centerX() { return (left + right) >> 1; } - + /** * @return the vertical center of the rectangle. If the computed value * is fractional, this method returns the largest integer that is @@ -332,14 +332,14 @@ public final class Rect implements Parcelable { public final int centerY() { return (top + bottom) >> 1; } - + /** * @return the exact horizontal center of the rectangle as a float. */ public final float exactCenterX() { return (left + right) * 0.5f; } - + /** * @return the exact vertical center of the rectangle as a float. */ @@ -493,7 +493,7 @@ public final class Rect implements Parcelable { * @param top The top of the rectangle being tested for containment * @param right The right side of the rectangle being tested for containment * @param bottom The bottom of the rectangle being tested for containment - * @return true iff the the 4 specified sides of a rectangle are inside or + * @return true iff the 4 specified sides of a rectangle are inside or * equal to this rectangle */ public boolean contains(int left, int top, int right, int bottom) { @@ -548,7 +548,7 @@ public final class Rect implements Parcelable { } return false; } - + /** * If the specified rectangle intersects this rectangle, return true and set * this rectangle to that intersection, otherwise return false and do not @@ -670,7 +670,7 @@ public final class Rect implements Parcelable { public void union(@NonNull Rect r) { union(r.left, r.top, r.right, r.bottom); } - + /** * Update this Rect to enclose itself and the [x,y] coordinate. There is no * check to see that this rectangle is non-empty. diff --git a/graphics/java/android/graphics/RectF.java b/graphics/java/android/graphics/RectF.java index ff50a0c55e6c..5b9b7641111b 100644 --- a/graphics/java/android/graphics/RectF.java +++ b/graphics/java/android/graphics/RectF.java @@ -38,7 +38,7 @@ public class RectF implements Parcelable { public float top; public float right; public float bottom; - + /** * Create a new empty RectF. All coordinates are initialized to 0. */ @@ -78,7 +78,7 @@ public class RectF implements Parcelable { bottom = r.bottom; } } - + public RectF(@Nullable Rect r) { if (r == null) { left = top = right = bottom = 0.0f; @@ -121,7 +121,7 @@ public class RectF implements Parcelable { public String toShortString() { return toShortString(new StringBuilder(32)); } - + /** * Return a string representation of the rectangle in a compact form. * @hide @@ -134,7 +134,7 @@ public class RectF implements Parcelable { sb.append(','); sb.append(bottom); sb.append(']'); return sb.toString(); } - + /** * Print short representation to given writer. * @hide @@ -183,14 +183,14 @@ public class RectF implements Parcelable { public final float centerY() { return (top + bottom) * 0.5f; } - + /** * Set the rectangle to (0,0,0,0) */ public void setEmpty() { left = right = top = bottom = 0; } - + /** * Set the rectangle's coordinates to the specified values. Note: no range * checking is performed, so it is up to the caller to ensure that @@ -220,7 +220,7 @@ public class RectF implements Parcelable { this.right = src.right; this.bottom = src.bottom; } - + /** * Copy the coordinates from src into this rectangle. * @@ -261,7 +261,7 @@ public class RectF implements Parcelable { left = newLeft; top = newTop; } - + /** * Inset the rectangle by (dx,dy). If dx is positive, then the sides are * moved inwards, making the rectangle narrower. If dx is negative, then the @@ -293,7 +293,7 @@ public class RectF implements Parcelable { return left < right && top < bottom // check for empty first && x >= left && x < right && y >= top && y < bottom; } - + /** * Returns true iff the 4 specified sides of a rectangle are inside or equal * to this rectangle. i.e. is this rectangle a superset of the specified @@ -303,7 +303,7 @@ public class RectF implements Parcelable { * @param top The top of the rectangle being tested for containment * @param right The right side of the rectangle being tested for containment * @param bottom The bottom of the rectangle being tested for containment - * @return true iff the the 4 specified sides of a rectangle are inside or + * @return true iff the 4 specified sides of a rectangle are inside or * equal to this rectangle */ public boolean contains(float left, float top, float right, float bottom) { @@ -313,7 +313,7 @@ public class RectF implements Parcelable { && this.left <= left && this.top <= top && this.right >= right && this.bottom >= bottom; } - + /** * Returns true iff the specified rectangle r is inside or equal to this * rectangle. An empty rectangle never contains another rectangle. @@ -329,7 +329,7 @@ public class RectF implements Parcelable { && left <= r.left && top <= r.top && right >= r.right && bottom >= r.bottom; } - + /** * If the rectangle specified by left,top,right,bottom intersects this * rectangle, return true and set this rectangle to that intersection, @@ -367,7 +367,7 @@ public class RectF implements Parcelable { } return false; } - + /** * If the specified rectangle intersects this rectangle, return true and set * this rectangle to that intersection, otherwise return false and do not @@ -382,7 +382,7 @@ public class RectF implements Parcelable { public boolean intersect(@NonNull RectF r) { return intersect(r.left, r.top, r.right, r.bottom); } - + /** * If rectangles a and b intersect, return true and set this rectangle to * that intersection, otherwise return false and do not change this @@ -406,7 +406,7 @@ public class RectF implements Parcelable { } return false; } - + /** * Returns true if this rectangle intersects the specified rectangle. * In no event is this rectangle modified. No check is performed to see @@ -426,7 +426,7 @@ public class RectF implements Parcelable { return this.left < right && left < this.right && this.top < bottom && top < this.bottom; } - + /** * Returns true iff the two specified rectangles intersect. In no event are * either of the rectangles modified. To record the intersection, @@ -441,7 +441,7 @@ public class RectF implements Parcelable { return a.left < b.right && b.left < a.right && a.top < b.bottom && b.top < a.bottom; } - + /** * Set the dst integer Rect by rounding this rectangle's coordinates * to their nearest integer values. @@ -489,7 +489,7 @@ public class RectF implements Parcelable { } } } - + /** * Update this Rect to enclose itself and the specified rectangle. If the * specified rectangle is empty, nothing is done. If this rectangle is empty @@ -500,7 +500,7 @@ public class RectF implements Parcelable { public void union(@NonNull RectF r) { union(r.left, r.top, r.right, r.bottom); } - + /** * Update this Rect to enclose itself and the [x,y] coordinate. There is no * check to see that this rectangle is non-empty. @@ -520,7 +520,7 @@ public class RectF implements Parcelable { bottom = y; } } - + /** * Swap top/bottom or left/right if there are flipped (i.e. left > right * and/or top > bottom). This can be called if @@ -548,7 +548,7 @@ public class RectF implements Parcelable { public int describeContents() { return 0; } - + /** * Write this rectangle to the specified parcel. To restore a rectangle from * a parcel, use readFromParcel() @@ -561,7 +561,7 @@ public class RectF implements Parcelable { out.writeFloat(right); out.writeFloat(bottom); } - + public static final @android.annotation.NonNull Parcelable.Creator<RectF> CREATOR = new Parcelable.Creator<RectF>() { /** * Return a new rectangle from the data in the specified parcel. @@ -572,7 +572,7 @@ public class RectF implements Parcelable { r.readFromParcel(in); return r; } - + /** * Return an array of rectangles of the specified size. */ @@ -581,7 +581,7 @@ public class RectF implements Parcelable { return new RectF[size]; } }; - + /** * Set the rectangle's coordinates from the data stored in the specified * parcel. To write a rectangle to a parcel, call writeToParcel(). diff --git a/graphics/java/android/graphics/RenderNode.java b/graphics/java/android/graphics/RenderNode.java index 27325694073c..211f74a47bdd 100644 --- a/graphics/java/android/graphics/RenderNode.java +++ b/graphics/java/android/graphics/RenderNode.java @@ -16,6 +16,7 @@ package android.graphics; +import android.animation.Animator; import android.annotation.BytesLong; import android.annotation.ColorInt; import android.annotation.FloatRange; @@ -765,12 +766,12 @@ public final class RenderNode { * Default value is false. See * {@link #setProjectBackwards(boolean)} for a description of what this entails. * - * @param shouldRecieve True if this RenderNode is a projection receiver, false otherwise. + * @param shouldReceive True if this RenderNode is a projection receiver, false otherwise. * Default is false. * @return True if the value changed, false if the new value was the same as the previous value. */ - public boolean setProjectionReceiver(boolean shouldRecieve) { - return nSetProjectionReceiver(mNativeRenderNode, shouldRecieve); + public boolean setProjectionReceiver(boolean shouldReceive) { + return nSetProjectionReceiver(mNativeRenderNode, shouldReceive); } /** @@ -1639,7 +1640,7 @@ public final class RenderNode { */ public interface AnimationHost { /** @hide */ - void registerAnimatingRenderNode(RenderNode animator); + void registerAnimatingRenderNode(RenderNode renderNode, Animator animator); /** @hide */ void registerVectorDrawableAnimator(NativeVectorDrawableAnimator animator); @@ -1654,7 +1655,7 @@ public final class RenderNode { throw new IllegalStateException("Cannot start this animator on a detached view!"); } nAddAnimator(mNativeRenderNode, animator.getNativeAnimator()); - mAnimationHost.registerAnimatingRenderNode(this); + mAnimationHost.registerAnimatingRenderNode(this, animator); } /** @hide */ @@ -1799,7 +1800,7 @@ public final class RenderNode { private static native boolean nSetProjectBackwards(long renderNode, boolean shouldProject); @CriticalNative - private static native boolean nSetProjectionReceiver(long renderNode, boolean shouldRecieve); + private static native boolean nSetProjectionReceiver(long renderNode, boolean shouldReceive); @CriticalNative private static native boolean nSetOutlineRoundRect(long renderNode, int left, int top, diff --git a/graphics/java/android/graphics/SurfaceTexture.java b/graphics/java/android/graphics/SurfaceTexture.java index 50b167ef9f46..3256f31bdc93 100644 --- a/graphics/java/android/graphics/SurfaceTexture.java +++ b/graphics/java/android/graphics/SurfaceTexture.java @@ -318,7 +318,7 @@ public class SurfaceTexture { } /** - * Releases the the texture content. This is needed in single buffered mode to allow the image + * Releases the texture content. This is needed in single buffered mode to allow the image * content producer to take ownership of the image buffer. * <p> * For more information see {@link #SurfaceTexture(int, boolean)}. @@ -431,7 +431,7 @@ public class SurfaceTexture { * error. * <p> * Note that while calling this method causes all the buffers to be freed - * from the perspective of the the SurfaceTexture, if there are additional + * from the perspective of the SurfaceTexture, if there are additional * references on the buffers (e.g. if a buffer is referenced by a client or * by OpenGL ES as a texture) then those buffer will remain allocated. * <p> diff --git a/graphics/java/android/graphics/Typeface.java b/graphics/java/android/graphics/Typeface.java index 4c4e8fa9c088..fd788167a0d8 100644 --- a/graphics/java/android/graphics/Typeface.java +++ b/graphics/java/android/graphics/Typeface.java @@ -600,7 +600,7 @@ public class Typeface { * {@link #setWeight} and {@link #setItalic}. * * If {@link #setWeight} is not called, the fallback family keeps the default weight. - * Similary, if {@link #setItalic} is not called, the fallback family keeps the default + * Similarly, if {@link #setItalic} is not called, the fallback family keeps the default * italic information. For example, calling {@code builder.setFallback("sans-serif-light")} * is equivalent to calling {@code builder.setFallback("sans-serif").setWeight(300)} in * terms of fallback. The default weight and italic information are overridden by calling @@ -794,7 +794,7 @@ public class Typeface { /** * Returns the maximum capacity of custom fallback families. * - * This includes the the first font family passed to the constructor. + * This includes the first font family passed to the constructor. * It is guaranteed that the value will be greater than or equal to 64. * * @return the maximum number of font families for the custom fallback @@ -816,7 +816,7 @@ public class Typeface { /** * Sets a system fallback by name. * - * You can specify generic font familiy names or OEM specific family names. If the system + * You can specify generic font family names or OEM specific family names. If the system * don't have a specified fallback, the default fallback is used instead. * For more information about generic font families, see <a * href="https://www.w3.org/TR/css-fonts-4/#generic-font-families">CSS specification</a> diff --git a/graphics/java/android/graphics/Xfermode.java b/graphics/java/android/graphics/Xfermode.java index 81769e2e21bf..6bb22a12280e 100644 --- a/graphics/java/android/graphics/Xfermode.java +++ b/graphics/java/android/graphics/Xfermode.java @@ -16,8 +16,8 @@ // This file was generated from the C++ include file: SkXfermode.h // Any changes made to this file will be discarded by the build. -// To change this file, either edit the include, or device/tools/gluemaker/main.cpp, -// or one of the auxilary file specifications in device/tools/gluemaker. +// To change this file, either edit the include, or device/tools/gluemaker/main.cpp, +// or one of the auxiliary file specifications in device/tools/gluemaker. package android.graphics; @@ -28,7 +28,7 @@ import android.os.Build; * Xfermode is the base class for objects that are called to implement custom * "transfer-modes" in the drawing pipeline. The static function Create(Modes) * can be called to return an instance of any of the predefined subclasses as - * specified in the Modes enum. When an Xfermode is assigned to an Paint, then + * specified in the Modes enum. When an Xfermode is assigned to a Paint, then * objects drawn with that paint have the xfermode applied. */ public class Xfermode { diff --git a/graphics/java/android/graphics/YuvImage.java b/graphics/java/android/graphics/YuvImage.java index ce35b55d526f..b0c7f202f23a 100644 --- a/graphics/java/android/graphics/YuvImage.java +++ b/graphics/java/android/graphics/YuvImage.java @@ -63,7 +63,7 @@ public class YuvImage { private int mWidth; /** - * The height of the the image. + * The height of the image. */ private int mHeight; diff --git a/graphics/java/android/graphics/drawable/AdaptiveIconDrawable.java b/graphics/java/android/graphics/drawable/AdaptiveIconDrawable.java index 688425a77ab5..7ee7d6beec78 100644 --- a/graphics/java/android/graphics/drawable/AdaptiveIconDrawable.java +++ b/graphics/java/android/graphics/drawable/AdaptiveIconDrawable.java @@ -98,7 +98,7 @@ public class AdaptiveIconDrawable extends Drawable implements Drawable.Callback * extra content to reveal within the clip path when performing affine transformations on the * layers. * - * Each layers will reserve 25% of it's width and height. + * Each layers will reserve 25% of its width and height. * * As a result, the view port of the layers is smaller than their intrinsic width and height. */ diff --git a/graphics/java/android/graphics/drawable/AnimatedVectorDrawable.java b/graphics/java/android/graphics/drawable/AnimatedVectorDrawable.java index 55f205bb14a6..d4bb461c284e 100644 --- a/graphics/java/android/graphics/drawable/AnimatedVectorDrawable.java +++ b/graphics/java/android/graphics/drawable/AnimatedVectorDrawable.java @@ -1266,6 +1266,7 @@ public class AnimatedVectorDrawable extends Drawable implements Animatable2 { private final IntArray mPendingAnimationActions = new IntArray(); private final AnimatedVectorDrawable mDrawable; private long mTotalDuration; + private AnimatorListener mThreadedRendererAnimatorListener; VectorDrawableAnimatorRT(AnimatedVectorDrawable drawable) { mDrawable = drawable; @@ -1689,6 +1690,9 @@ public class AnimatedVectorDrawable extends Drawable implements Animatable2 { if (mListener != null) { mListener.onAnimationStart(null); } + if (mThreadedRendererAnimatorListener != null) { + mThreadedRendererAnimatorListener.onAnimationStart(null); + } } // This should only be called after animator has been added to the RenderNode target. @@ -1717,6 +1721,9 @@ public class AnimatedVectorDrawable extends Drawable implements Animatable2 { if (mListener != null) { mListener.onAnimationStart(null); } + if (mThreadedRendererAnimatorListener != null) { + mThreadedRendererAnimatorListener.onAnimationStart(null); + } } @Override @@ -1725,6 +1732,11 @@ public class AnimatedVectorDrawable extends Drawable implements Animatable2 { } @Override + public void setThreadedRendererAnimatorListener(AnimatorListener animatorListener) { + mThreadedRendererAnimatorListener = animatorListener; + } + + @Override public boolean canReverse() { return mIsReversible; } @@ -1788,6 +1800,9 @@ public class AnimatedVectorDrawable extends Drawable implements Animatable2 { if (mListener != null) { mListener.onAnimationEnd(null); } + if (mThreadedRendererAnimatorListener != null) { + mThreadedRendererAnimatorListener.onAnimationEnd(null); + } } // onFinished: should be called from native diff --git a/graphics/java/android/graphics/drawable/BitmapDrawable.java b/graphics/java/android/graphics/drawable/BitmapDrawable.java index b291f930da37..579ac60d5a86 100644 --- a/graphics/java/android/graphics/drawable/BitmapDrawable.java +++ b/graphics/java/android/graphics/drawable/BitmapDrawable.java @@ -43,6 +43,7 @@ import android.graphics.Xfermode; import android.util.AttributeSet; import android.util.DisplayMetrics; import android.util.LayoutDirection; +import android.util.Log; import android.util.TypedValue; import android.view.Gravity; @@ -138,6 +139,9 @@ public class BitmapDrawable extends Drawable { */ @Deprecated public BitmapDrawable(Bitmap bitmap) { + if (bitmap == null) { + Log.w(TAG, "BitmapDrawable created with null Bitmap"); + } init(new BitmapState(bitmap), null); } @@ -146,6 +150,9 @@ public class BitmapDrawable extends Drawable { * the display metrics of the resources. */ public BitmapDrawable(Resources res, Bitmap bitmap) { + if (bitmap == null) { + Log.w(TAG, "BitmapDrawable created with null Bitmap"); + } init(new BitmapState(bitmap), res); } @@ -177,7 +184,7 @@ public class BitmapDrawable extends Drawable { } finally { init(new BitmapState(bitmap), res); if (mBitmapState.mBitmap == null) { - android.util.Log.w("BitmapDrawable", "BitmapDrawable cannot decode " + filepath); + Log.w(TAG, "BitmapDrawable cannot decode " + filepath); } } } @@ -210,7 +217,7 @@ public class BitmapDrawable extends Drawable { } finally { init(new BitmapState(bitmap), res); if (mBitmapState.mBitmap == null) { - android.util.Log.w("BitmapDrawable", "BitmapDrawable cannot decode " + is); + Log.w(TAG, "BitmapDrawable cannot decode " + is); } } } @@ -1073,4 +1080,6 @@ public class BitmapDrawable extends Drawable { mBitmapState.mBlendMode); computeBitmapSize(); } + + private static final String TAG = "BitmapDrawable"; } diff --git a/graphics/java/android/graphics/drawable/Drawable.java b/graphics/java/android/graphics/drawable/Drawable.java index 4972e928dd22..7f2feac2278d 100644 --- a/graphics/java/android/graphics/drawable/Drawable.java +++ b/graphics/java/android/graphics/drawable/Drawable.java @@ -839,7 +839,7 @@ public abstract class Drawable { } /** - * Describes the current state, as a union of primitve states, such as + * Describes the current state, as a union of primitive states, such as * {@link android.R.attr#state_focused}, * {@link android.R.attr#state_selected}, etc. * Some drawables may modify their imagery based on the selected state. diff --git a/graphics/java/android/graphics/drawable/GradientDrawable.java b/graphics/java/android/graphics/drawable/GradientDrawable.java index 166a795e1661..29d033e64aea 100644 --- a/graphics/java/android/graphics/drawable/GradientDrawable.java +++ b/graphics/java/android/graphics/drawable/GradientDrawable.java @@ -936,7 +936,7 @@ public class GradientDrawable extends Drawable { } /** - * Retrn the inner radius of the ring + * Return the inner radius of the ring * * @see #setInnerRadius(int) * @attr ref android.R.styleable#GradientDrawable_innerRadius diff --git a/graphics/java/android/graphics/drawable/Icon.java b/graphics/java/android/graphics/drawable/Icon.java index f359025f4b46..c3aaf983711d 100644 --- a/graphics/java/android/graphics/drawable/Icon.java +++ b/graphics/java/android/graphics/drawable/Icon.java @@ -19,6 +19,8 @@ package android.graphics.drawable; import static android.content.Context.CONTEXT_INCLUDE_CODE; import static android.content.Context.CONTEXT_RESTRICTED; +import static com.android.graphics.flags.Flags.iconLoadDrawableReturnNullWhenUriDecodeFails; + import android.annotation.ColorInt; import android.annotation.DrawableRes; import android.annotation.IntDef; @@ -494,15 +496,28 @@ public final class Icon implements Parcelable { case TYPE_URI: InputStream is = getUriInputStream(context); if (is != null) { - return new BitmapDrawable(context.getResources(), - fixMaxBitmapSize(BitmapFactory.decodeStream(is))); + final Bitmap bitmap = BitmapFactory.decodeStream(is); + if (bitmap == null) { + Log.w(TAG, "Unable to decode image from URI: " + getUriString()); + if (iconLoadDrawableReturnNullWhenUriDecodeFails()) { + return null; + } + } + return new BitmapDrawable(context.getResources(), fixMaxBitmapSize(bitmap)); } break; case TYPE_URI_ADAPTIVE_BITMAP: is = getUriInputStream(context); if (is != null) { + final Bitmap bitmap = BitmapFactory.decodeStream(is); + if (bitmap == null) { + Log.w(TAG, "Unable to decode image from URI: " + getUriString()); + if (iconLoadDrawableReturnNullWhenUriDecodeFails()) { + return null; + } + } return new AdaptiveIconDrawable(null, new BitmapDrawable(context.getResources(), - fixMaxBitmapSize(BitmapFactory.decodeStream(is)))); + fixMaxBitmapSize(bitmap))); } break; } diff --git a/graphics/java/android/graphics/drawable/shapes/PathShape.java b/graphics/java/android/graphics/drawable/shapes/PathShape.java index 393fdee87bb8..299f6d5cddfa 100644 --- a/graphics/java/android/graphics/drawable/shapes/PathShape.java +++ b/graphics/java/android/graphics/drawable/shapes/PathShape.java @@ -93,7 +93,7 @@ public class PathShape extends Shape { && Float.compare(pathShape.mStdHeight, mStdHeight) == 0 && Float.compare(pathShape.mScaleX, mScaleX) == 0 && Float.compare(pathShape.mScaleY, mScaleY) == 0 - // Path does not have equals implementation but incase it gains one, use it here + // Path does not have equals implementation but in case it gains one, use it here && Objects.equals(mPath, pathShape.mPath); } diff --git a/graphics/java/android/graphics/fonts/Font.java b/graphics/java/android/graphics/fonts/Font.java index 28cc05162cbb..2893177aafc5 100644 --- a/graphics/java/android/graphics/fonts/Font.java +++ b/graphics/java/android/graphics/fonts/Font.java @@ -61,13 +61,15 @@ public final class Font { private static final int STYLE_ITALIC = 1; private static final int STYLE_NORMAL = 0; - private static final NativeAllocationRegistry BUFFER_REGISTRY = - NativeAllocationRegistry.createMalloced( - ByteBuffer.class.getClassLoader(), nGetReleaseNativeFont()); - - private static final NativeAllocationRegistry FONT_REGISTRY = - NativeAllocationRegistry.createMalloced(Font.class.getClassLoader(), - nGetReleaseNativeFont()); + private static class NoImagePreloadHolder { + private static final NativeAllocationRegistry BUFFER_REGISTRY = + NativeAllocationRegistry.createMalloced( + ByteBuffer.class.getClassLoader(), nGetReleaseNativeFont()); + + private static final NativeAllocationRegistry FONT_REGISTRY = + NativeAllocationRegistry.createMalloced(Font.class.getClassLoader(), + nGetReleaseNativeFont()); + } /** * A builder class for creating new Font. @@ -530,7 +532,7 @@ public final class Font { public Font(long nativePtr) { mNativePtr = nativePtr; - FONT_REGISTRY.registerNativeAllocation(this, mNativePtr); + NoImagePreloadHolder.FONT_REGISTRY.registerNativeAllocation(this, mNativePtr); } /** @@ -551,7 +553,7 @@ public final class Font { ByteBuffer fromNative = nNewByteBuffer(mNativePtr); // Bind ByteBuffer's lifecycle with underlying font object. - BUFFER_REGISTRY.registerNativeAllocation(fromNative, ref); + NoImagePreloadHolder.BUFFER_REGISTRY.registerNativeAllocation(fromNative, ref); // JNI NewDirectBuffer creates writable ByteBuffer even if it is mmaped readonly. mBuffer = fromNative.asReadOnlyBuffer(); @@ -787,7 +789,7 @@ public final class Font { return false; } - // ByteBuffer#equals compares all bytes which is not performant for e.g HashMap. Since + // ByteBuffer#equals compares all bytes which is not performant for e.g. HashMap. Since // underlying native font object holds buffer address, check if this buffer points exactly // the same address as a shortcut of equality. For being compatible with of API30 or before, // check buffer position even if the buffer points the same address. diff --git a/graphics/java/android/graphics/fonts/FontFamily.java b/graphics/java/android/graphics/fonts/FontFamily.java index 685fd825d43e..5a7b0bbca399 100644 --- a/graphics/java/android/graphics/fonts/FontFamily.java +++ b/graphics/java/android/graphics/fonts/FontFamily.java @@ -25,6 +25,7 @@ import android.annotation.IntDef; import android.annotation.IntRange; import android.annotation.NonNull; import android.annotation.Nullable; +import android.annotation.SuppressLint; import android.text.FontConfig; import android.util.SparseIntArray; @@ -73,9 +74,11 @@ public final class FontFamily { * A builder class for creating new FontFamily. */ public static final class Builder { - private static final NativeAllocationRegistry sFamilyRegistory = - NativeAllocationRegistry.createMalloced(FontFamily.class.getClassLoader(), - nGetReleaseNativeFamily()); + private static class NoImagePreloadHolder { + private static final NativeAllocationRegistry sFamilyRegistry = + NativeAllocationRegistry.createMalloced(FontFamily.class.getClassLoader(), + nGetReleaseNativeFamily()); + } private final ArrayList<Font> mFonts = new ArrayList<>(); // Most FontFamily only has regular, bold, italic, bold-italic. Thus 4 should be good for @@ -140,11 +143,16 @@ public final class FontFamily { * value of the supported `wght`axis, the maximum supported `wght` value is used. The weight * value of the font is ignored. * - * If none of the above conditions are met, this function return {@code null}. + * If none of the above conditions are met, the provided font files cannot be used for + * variable font family and this function returns {@code null}. Even if this function + * returns {@code null}, you can still use {@link #build()} method for creating FontFamily + * instance with manually specifying variation settings by using + * {@link Font.Builder#setFontVariationSettings(String)}. * * @return A variable font family. null if a variable font cannot be built from the given * fonts. */ + @SuppressLint("BuilderSetStyle") @FlaggedApi(FLAG_NEW_FONTS_FALLBACK_XML) public @Nullable FontFamily buildVariableFamily() { int variableFamilyType = analyzeAndResolveVariableType(mFonts); @@ -179,7 +187,7 @@ public final class FontFamily { final long ptr = nBuild(builderPtr, langTags, variant, isCustomFallback, isDefaultFallback, variableFamilyType); final FontFamily family = new FontFamily(ptr); - sFamilyRegistory.registerNativeAllocation(family, ptr); + NoImagePreloadHolder.sFamilyRegistry.registerNativeAllocation(family, ptr); return family; } diff --git a/graphics/java/android/graphics/fonts/FontFileUtil.java b/graphics/java/android/graphics/fonts/FontFileUtil.java index ff38282255f2..abcafb666576 100644 --- a/graphics/java/android/graphics/fonts/FontFileUtil.java +++ b/graphics/java/android/graphics/fonts/FontFileUtil.java @@ -34,7 +34,7 @@ import java.util.Set; */ public class FontFileUtil { - private FontFileUtil() {} // Do not instanciate + private FontFileUtil() {} // Do not instantiate /** * Unpack the weight value from packed integer. @@ -87,7 +87,7 @@ public class FontFileUtil { } if (weight != -1 && italic != -1) { - // Both weight/italic style are specifeid by variation settings. + // Both weight/italic style are specified by variation settings. // No need to look into OS/2 table. // TODO: Good to look HVAR table to check if this font supports wght/ital axes. return pack(weight, italic == 1); diff --git a/graphics/java/android/graphics/fonts/SystemFonts.java b/graphics/java/android/graphics/fonts/SystemFonts.java index a90961eb6d2e..f727f5b076a1 100644 --- a/graphics/java/android/graphics/fonts/SystemFonts.java +++ b/graphics/java/android/graphics/fonts/SystemFonts.java @@ -216,7 +216,7 @@ public final class SystemFonts { } else if (defaultFamily != null) { familyListSet.familyList.add(defaultFamily); } else { - // There is no valid for for default fallback. Ignore. + // There is no valid for default fallback. Ignore. } } } diff --git a/graphics/java/android/graphics/pdf/PdfEditor.java b/graphics/java/android/graphics/pdf/PdfEditor.java index 3cd709ea10e5..69e19824da26 100644 --- a/graphics/java/android/graphics/pdf/PdfEditor.java +++ b/graphics/java/android/graphics/pdf/PdfEditor.java @@ -25,7 +25,9 @@ import android.os.ParcelFileDescriptor; import android.system.ErrnoException; import android.system.Os; import android.system.OsConstants; + import dalvik.system.CloseGuard; + import libcore.io.IoUtils; import java.io.IOException; @@ -37,6 +39,12 @@ import java.io.IOException; */ public final class PdfEditor { + /** + * Any call the native pdfium code has to be single threaded as the library does not support + * parallel use. + */ + private static final Object sPdfiumLock = new Object(); + private final CloseGuard mCloseGuard = CloseGuard.get(); private long mNativeDocument; @@ -79,7 +87,7 @@ public final class PdfEditor { } mInput = input; - synchronized (PdfRenderer.sPdfiumLock) { + synchronized (sPdfiumLock) { mNativeDocument = nativeOpen(mInput.getFd(), size); try { mPageCount = nativeGetPageCount(mNativeDocument); @@ -112,7 +120,7 @@ public final class PdfEditor { throwIfClosed(); throwIfPageNotInDocument(pageIndex); - synchronized (PdfRenderer.sPdfiumLock) { + synchronized (sPdfiumLock) { mPageCount = nativeRemovePage(mNativeDocument, pageIndex); } } @@ -138,12 +146,12 @@ public final class PdfEditor { Point size = new Point(); getPageSize(pageIndex, size); - synchronized (PdfRenderer.sPdfiumLock) { + synchronized (sPdfiumLock) { nativeSetTransformAndClip(mNativeDocument, pageIndex, transform.ni(), 0, 0, size.x, size.y); } } else { - synchronized (PdfRenderer.sPdfiumLock) { + synchronized (sPdfiumLock) { nativeSetTransformAndClip(mNativeDocument, pageIndex, transform.ni(), clip.left, clip.top, clip.right, clip.bottom); } @@ -161,7 +169,7 @@ public final class PdfEditor { throwIfOutSizeNull(outSize); throwIfPageNotInDocument(pageIndex); - synchronized (PdfRenderer.sPdfiumLock) { + synchronized (sPdfiumLock) { nativeGetPageSize(mNativeDocument, pageIndex, outSize); } } @@ -177,7 +185,7 @@ public final class PdfEditor { throwIfOutMediaBoxNull(outMediaBox); throwIfPageNotInDocument(pageIndex); - synchronized (PdfRenderer.sPdfiumLock) { + synchronized (sPdfiumLock) { return nativeGetPageMediaBox(mNativeDocument, pageIndex, outMediaBox); } } @@ -193,7 +201,7 @@ public final class PdfEditor { throwIfMediaBoxNull(mediaBox); throwIfPageNotInDocument(pageIndex); - synchronized (PdfRenderer.sPdfiumLock) { + synchronized (sPdfiumLock) { nativeSetPageMediaBox(mNativeDocument, pageIndex, mediaBox); } } @@ -209,7 +217,7 @@ public final class PdfEditor { throwIfOutCropBoxNull(outCropBox); throwIfPageNotInDocument(pageIndex); - synchronized (PdfRenderer.sPdfiumLock) { + synchronized (sPdfiumLock) { return nativeGetPageCropBox(mNativeDocument, pageIndex, outCropBox); } } @@ -225,7 +233,7 @@ public final class PdfEditor { throwIfCropBoxNull(cropBox); throwIfPageNotInDocument(pageIndex); - synchronized (PdfRenderer.sPdfiumLock) { + synchronized (sPdfiumLock) { nativeSetPageCropBox(mNativeDocument, pageIndex, cropBox); } } @@ -238,7 +246,7 @@ public final class PdfEditor { public boolean shouldScaleForPrinting() { throwIfClosed(); - synchronized (PdfRenderer.sPdfiumLock) { + synchronized (sPdfiumLock) { return nativeScaleForPrinting(mNativeDocument); } } @@ -255,7 +263,7 @@ public final class PdfEditor { try { throwIfClosed(); - synchronized (PdfRenderer.sPdfiumLock) { + synchronized (sPdfiumLock) { nativeWrite(mNativeDocument, output.getFd()); } } finally { @@ -287,7 +295,7 @@ public final class PdfEditor { private void doClose() { if (mNativeDocument != 0) { - synchronized (PdfRenderer.sPdfiumLock) { + synchronized (sPdfiumLock) { nativeClose(mNativeDocument); } mNativeDocument = 0; diff --git a/graphics/java/android/graphics/pdf/PdfRenderer.java b/graphics/java/android/graphics/pdf/PdfRenderer.java deleted file mode 100644 index 4666963b5dd4..000000000000 --- a/graphics/java/android/graphics/pdf/PdfRenderer.java +++ /dev/null @@ -1,502 +0,0 @@ -/* - * Copyright (C) 2014 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.pdf; - -import android.annotation.IntDef; -import android.annotation.NonNull; -import android.annotation.Nullable; -import android.compat.annotation.UnsupportedAppUsage; -import android.graphics.Bitmap; -import android.graphics.Bitmap.Config; -import android.graphics.Matrix; -import android.graphics.Point; -import android.graphics.Rect; -import android.os.Build; -import android.os.ParcelFileDescriptor; -import android.system.ErrnoException; -import android.system.Os; -import android.system.OsConstants; - -import com.android.internal.util.Preconditions; - -import dalvik.system.CloseGuard; - -import libcore.io.IoUtils; - -import java.io.IOException; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; - -/** - * <p> - * This class enables rendering a PDF document. This class is not thread safe. - * </p> - * <p> - * If you want to render a PDF, you create a renderer and for every page you want - * to render, you open the page, render it, and close the page. After you are done - * with rendering, you close the renderer. After the renderer is closed it should not - * be used anymore. Note that the pages are rendered one by one, i.e. you can have - * only a single page opened at any given time. - * </p> - * <p> - * A typical use of the APIs to render a PDF looks like this: - * </p> - * <pre> - * // create a new renderer - * PdfRenderer renderer = new PdfRenderer(getSeekableFileDescriptor()); - * - * // let us just render all pages - * final int pageCount = renderer.getPageCount(); - * for (int i = 0; i < pageCount; i++) { - * Page page = renderer.openPage(i); - * - * // say we render for showing on the screen - * page.render(mBitmap, null, null, Page.RENDER_MODE_FOR_DISPLAY); - * - * // do stuff with the bitmap - * - * // close the page - * page.close(); - * } - * - * // close the renderer - * renderer.close(); - * </pre> - * - * <h3>Print preview and print output</h3> - * <p> - * If you are using this class to rasterize a PDF for printing or show a print - * preview, it is recommended that you respect the following contract in order - * to provide a consistent user experience when seeing a preview and printing, - * i.e. the user sees a preview that is the same as the printout. - * </p> - * <ul> - * <li> - * Respect the property whether the document would like to be scaled for printing - * as per {@link #shouldScaleForPrinting()}. - * </li> - * <li> - * When scaling a document for printing the aspect ratio should be preserved. - * </li> - * <li> - * Do not inset the content with any margins from the {@link android.print.PrintAttributes} - * as the application is responsible to render it such that the margins are respected. - * </li> - * <li> - * If document page size is greater than the printed media size the content should - * be anchored to the upper left corner of the page for left-to-right locales and - * top right corner for right-to-left locales. - * </li> - * </ul> - * - * @see #close() - */ -public final class PdfRenderer implements AutoCloseable { - /** - * Any call the native pdfium code has to be single threaded as the library does not support - * parallel use. - */ - final static Object sPdfiumLock = new Object(); - - private final CloseGuard mCloseGuard = CloseGuard.get(); - - private final Point mTempPoint = new Point(); - - private long mNativeDocument; - - private final int mPageCount; - - private ParcelFileDescriptor mInput; - - @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) - private Page mCurrentPage; - - /** @hide */ - @IntDef({ - Page.RENDER_MODE_FOR_DISPLAY, - Page.RENDER_MODE_FOR_PRINT - }) - @Retention(RetentionPolicy.SOURCE) - public @interface RenderMode {} - - /** - * Creates a new instance. - * <p> - * <strong>Note:</strong> The provided file descriptor must be <strong>seekable</strong>, - * i.e. its data being randomly accessed, e.g. pointing to a file. - * </p> - * <p> - * <strong>Note:</strong> This class takes ownership of the passed in file descriptor - * and is responsible for closing it when the renderer is closed. - * </p> - * <p> - * If the file is from an untrusted source it is recommended to run the renderer in a separate, - * isolated process with minimal permissions to limit the impact of security exploits. - * </p> - * - * @param input Seekable file descriptor to read from. - * - * @throws java.io.IOException If an error occurs while reading the file. - * @throws java.lang.SecurityException If the file requires a password or - * the security scheme is not supported. - */ - public PdfRenderer(@NonNull ParcelFileDescriptor input) throws IOException { - if (input == null) { - throw new NullPointerException("input cannot be null"); - } - - final long size; - try { - Os.lseek(input.getFileDescriptor(), 0, OsConstants.SEEK_SET); - size = Os.fstat(input.getFileDescriptor()).st_size; - } catch (ErrnoException ee) { - throw new IllegalArgumentException("file descriptor not seekable"); - } - mInput = input; - - synchronized (sPdfiumLock) { - mNativeDocument = nativeCreate(mInput.getFd(), size); - try { - mPageCount = nativeGetPageCount(mNativeDocument); - } catch (Throwable t) { - nativeClose(mNativeDocument); - mNativeDocument = 0; - throw t; - } - } - - mCloseGuard.open("close"); - } - - /** - * Closes this renderer. You should not use this instance - * after this method is called. - */ - public void close() { - throwIfClosed(); - throwIfPageOpened(); - doClose(); - } - - /** - * Gets the number of pages in the document. - * - * @return The page count. - */ - public int getPageCount() { - throwIfClosed(); - return mPageCount; - } - - /** - * Gets whether the document prefers to be scaled for printing. - * You should take this info account if the document is rendered - * for printing and the target media size differs from the page - * size. - * - * @return If to scale the document. - */ - public boolean shouldScaleForPrinting() { - throwIfClosed(); - - synchronized (sPdfiumLock) { - return nativeScaleForPrinting(mNativeDocument); - } - } - - /** - * Opens a page for rendering. - * - * @param index The page index. - * @return A page that can be rendered. - * - * @see android.graphics.pdf.PdfRenderer.Page#close() PdfRenderer.Page.close() - */ - public Page openPage(int index) { - throwIfClosed(); - throwIfPageOpened(); - throwIfPageNotInDocument(index); - mCurrentPage = new Page(index); - return mCurrentPage; - } - - @Override - protected void finalize() throws Throwable { - try { - if (mCloseGuard != null) { - mCloseGuard.warnIfOpen(); - } - - doClose(); - } finally { - super.finalize(); - } - } - - @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) - private void doClose() { - if (mCurrentPage != null) { - mCurrentPage.close(); - mCurrentPage = null; - } - - if (mNativeDocument != 0) { - synchronized (sPdfiumLock) { - nativeClose(mNativeDocument); - } - mNativeDocument = 0; - } - - if (mInput != null) { - IoUtils.closeQuietly(mInput); - mInput = null; - } - mCloseGuard.close(); - } - - private void throwIfClosed() { - if (mInput == null) { - throw new IllegalStateException("Already closed"); - } - } - - private void throwIfPageOpened() { - if (mCurrentPage != null) { - throw new IllegalStateException("Current page not closed"); - } - } - - private void throwIfPageNotInDocument(int pageIndex) { - if (pageIndex < 0 || pageIndex >= mPageCount) { - throw new IllegalArgumentException("Invalid page index"); - } - } - - /** - * This class represents a PDF document page for rendering. - */ - public final class Page implements AutoCloseable { - - private final CloseGuard mCloseGuard = CloseGuard.get(); - - /** - * Mode to render the content for display on a screen. - */ - public static final int RENDER_MODE_FOR_DISPLAY = 1; - - /** - * Mode to render the content for printing. - */ - public static final int RENDER_MODE_FOR_PRINT = 2; - - private final int mIndex; - private final int mWidth; - private final int mHeight; - - private long mNativePage; - - private Page(int index) { - Point size = mTempPoint; - synchronized (sPdfiumLock) { - mNativePage = nativeOpenPageAndGetSize(mNativeDocument, index, size); - } - mIndex = index; - mWidth = size.x; - mHeight = size.y; - mCloseGuard.open("close"); - } - - /** - * Gets the page index. - * - * @return The index. - */ - public int getIndex() { - return mIndex; - } - - /** - * Gets the page width in points (1/72"). - * - * @return The width in points. - */ - public int getWidth() { - return mWidth; - } - - /** - * Gets the page height in points (1/72"). - * - * @return The height in points. - */ - public int getHeight() { - return mHeight; - } - - /** - * Renders a page to a bitmap. - * <p> - * You may optionally specify a rectangular clip in the bitmap bounds. No rendering - * outside the clip will be performed, hence it is your responsibility to initialize - * the bitmap outside the clip. - * </p> - * <p> - * You may optionally specify a matrix to transform the content from page coordinates - * which are in points (1/72") to bitmap coordinates which are in pixels. If this - * matrix is not provided this method will apply a transformation that will fit the - * whole page to the destination clip if provided or the destination bitmap if no - * clip is provided. - * </p> - * <p> - * The clip and transformation are useful for implementing tile rendering where the - * destination bitmap contains a portion of the image, for example when zooming. - * Another useful application is for printing where the size of the bitmap holding - * the page is too large and a client can render the page in stripes. - * </p> - * <p> - * <strong>Note: </strong> The destination bitmap format must be - * {@link Config#ARGB_8888 ARGB}. - * </p> - * <p> - * <strong>Note: </strong> The optional transformation matrix must be affine as per - * {@link android.graphics.Matrix#isAffine() Matrix.isAffine()}. Hence, you can specify - * rotation, scaling, translation but not a perspective transformation. - * </p> - * - * @param destination Destination bitmap to which to render. - * @param destClip Optional clip in the bitmap bounds. - * @param transform Optional transformation to apply when rendering. - * @param renderMode The render mode. - * - * @see #RENDER_MODE_FOR_DISPLAY - * @see #RENDER_MODE_FOR_PRINT - */ - public void render(@NonNull Bitmap destination, @Nullable Rect destClip, - @Nullable Matrix transform, @RenderMode int renderMode) { - if (mNativePage == 0) { - throw new NullPointerException(); - } - - destination = Preconditions.checkNotNull(destination, "bitmap null"); - - if (destination.getConfig() != Config.ARGB_8888) { - throw new IllegalArgumentException("Unsupported pixel format"); - } - - if (destClip != null) { - if (destClip.left < 0 || destClip.top < 0 - || destClip.right > destination.getWidth() - || destClip.bottom > destination.getHeight()) { - throw new IllegalArgumentException("destBounds not in destination"); - } - } - - if (transform != null && !transform.isAffine()) { - throw new IllegalArgumentException("transform not affine"); - } - - if (renderMode != RENDER_MODE_FOR_PRINT && renderMode != RENDER_MODE_FOR_DISPLAY) { - throw new IllegalArgumentException("Unsupported render mode"); - } - - if (renderMode == RENDER_MODE_FOR_PRINT && renderMode == RENDER_MODE_FOR_DISPLAY) { - throw new IllegalArgumentException("Only single render mode supported"); - } - - final int contentLeft = (destClip != null) ? destClip.left : 0; - final int contentTop = (destClip != null) ? destClip.top : 0; - final int contentRight = (destClip != null) ? destClip.right - : destination.getWidth(); - final int contentBottom = (destClip != null) ? destClip.bottom - : destination.getHeight(); - - // If transform is not set, stretch page to whole clipped area - if (transform == null) { - int clipWidth = contentRight - contentLeft; - int clipHeight = contentBottom - contentTop; - - transform = new Matrix(); - transform.postScale((float)clipWidth / getWidth(), - (float)clipHeight / getHeight()); - transform.postTranslate(contentLeft, contentTop); - } - - // 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(), - contentLeft, contentTop, contentRight, contentBottom, transformPtr, - renderMode); - } - } - - /** - * Closes this page. - * - * @see android.graphics.pdf.PdfRenderer#openPage(int) - */ - @Override - public void close() { - throwIfClosed(); - doClose(); - } - - @Override - protected void finalize() throws Throwable { - try { - if (mCloseGuard != null) { - mCloseGuard.warnIfOpen(); - } - - doClose(); - } finally { - super.finalize(); - } - } - - private void doClose() { - if (mNativePage != 0) { - synchronized (sPdfiumLock) { - nativeClosePage(mNativePage); - } - mNativePage = 0; - } - - mCloseGuard.close(); - mCurrentPage = null; - } - - private void throwIfClosed() { - if (mNativePage == 0) { - throw new IllegalStateException("Already closed"); - } - } - } - - private static native long nativeCreate(int fd, long size); - private static native void nativeClose(long documentPtr); - private static native int nativeGetPageCount(long documentPtr); - private static native boolean nativeScaleForPrinting(long documentPtr); - private static native void nativeRenderPage(long documentPtr, long pagePtr, long bitmapHandle, - int clipLeft, int clipTop, int clipRight, int clipBottom, long transformPtr, - int renderMode); - private static native long nativeOpenPageAndGetSize(long documentPtr, int pageIndex, - Point outSize); - private static native void nativeClosePage(long pagePtr); -} diff --git a/graphics/java/android/graphics/text/LineBreakConfig.java b/graphics/java/android/graphics/text/LineBreakConfig.java index 7d55928aa656..5a1086cef407 100644 --- a/graphics/java/android/graphics/text/LineBreakConfig.java +++ b/graphics/java/android/graphics/text/LineBreakConfig.java @@ -23,6 +23,7 @@ import android.annotation.FlaggedApi; import android.annotation.IntDef; import android.annotation.NonNull; import android.annotation.Nullable; +import android.annotation.SuppressLint; import android.app.ActivityThread; import android.os.Build; import android.os.LocaleList; @@ -314,6 +315,7 @@ public final class LineBreakConfig implements Parcelable { * @param config an override line break config * @return This {@code Builder}. */ + @SuppressLint("BuilderSetStyle") @FlaggedApi(FLAG_NO_BREAK_NO_HYPHENATION_SPAN) public @NonNull Builder merge(@NonNull LineBreakConfig config) { if (config.mLineBreakStyle != LINE_BREAK_STYLE_UNSPECIFIED) { diff --git a/graphics/java/android/graphics/text/LineBreaker.java b/graphics/java/android/graphics/text/LineBreaker.java index 0e9f29db8cb5..94de066c9182 100644 --- a/graphics/java/android/graphics/text/LineBreaker.java +++ b/graphics/java/android/graphics/text/LineBreaker.java @@ -18,6 +18,8 @@ package android.graphics.text; import static com.android.text.flags.Flags.FLAG_USE_BOUNDS_FOR_WIDTH; import static com.android.text.flags.Flags.FLAG_LETTER_SPACING_JUSTIFICATION; +import static com.android.text.flags.Flags.FLAG_MISSING_GETTER_APIS; + import android.annotation.FlaggedApi; import android.annotation.FloatRange; @@ -376,8 +378,8 @@ public class LineBreaker { * @see LineBreaker#computeLineBreaks */ public static class Result { - // Following two contstant must be synced with minikin's line breaker. - // TODO(nona): Remove these constatns by introducing native methods. + // Following two constants must be synced with minikin's line breaker. + // TODO(nona): Remove these constants by introducing native methods. private static final int TAB_MASK = 0x20000000; private static final int HYPHEN_MASK = 0xFF; private static final int START_HYPHEN_MASK = 0x18; // 0b11000 @@ -480,12 +482,20 @@ public class LineBreaker { } } - private static final NativeAllocationRegistry sRegistry = - NativeAllocationRegistry.createMalloced( - LineBreaker.class.getClassLoader(), nGetReleaseFunc()); + private static class NoImagePreloadHolder { + private static final NativeAllocationRegistry sRegistry = + NativeAllocationRegistry.createMalloced( + LineBreaker.class.getClassLoader(), nGetReleaseFunc()); + } private final long mNativePtr; + private final @BreakStrategy int mBreakStrategy; + private final @HyphenationFrequency int mHyphenationFrequency; + private final @JustificationMode int mJustificationMode; + private final int[] mIndents; + private final boolean mUseBoundsForWidth; + /** * Use Builder instead. */ @@ -494,7 +504,68 @@ public class LineBreaker { @Nullable int[] indents, boolean useBoundsForWidth) { mNativePtr = nInit(breakStrategy, hyphenationFrequency, justify == JUSTIFICATION_MODE_INTER_WORD, indents, useBoundsForWidth); - sRegistry.registerNativeAllocation(this, mNativePtr); + NoImagePreloadHolder.sRegistry.registerNativeAllocation(this, mNativePtr); + + mBreakStrategy = breakStrategy; + mHyphenationFrequency = hyphenationFrequency; + mJustificationMode = justify; + mIndents = indents; + mUseBoundsForWidth = useBoundsForWidth; + } + + /** + * Returns the break strategy used for this line breaker. + * + * @return the break strategy used for this line breaker. + * @see Builder#setBreakStrategy(int) + */ + @FlaggedApi(FLAG_MISSING_GETTER_APIS) + public @BreakStrategy int getBreakStrategy() { + return mBreakStrategy; + } + + /** + * Returns the hyphenation frequency used for this line breaker. + * + * @return the hyphenation frequency used for this line breaker. + * @see Builder#setHyphenationFrequency(int) + */ + @FlaggedApi(FLAG_MISSING_GETTER_APIS) + public @HyphenationFrequency int getHyphenationFrequency() { + return mHyphenationFrequency; + } + + /** + * Returns the justification mode used for this line breaker. + * + * @return the justification mode used for this line breaker. + * @see Builder#setJustificationMode(int) + */ + @FlaggedApi(FLAG_MISSING_GETTER_APIS) + public @JustificationMode int getJustificationMode() { + return mJustificationMode; + } + + /** + * Returns the indents used for this line breaker. + * + * @return the indents used for this line breaker. + * @see Builder#setIndents(int[]) + */ + @FlaggedApi(FLAG_MISSING_GETTER_APIS) + public @Nullable int[] getIndents() { + return mIndents; + } + + /** + * Returns true if this line breaker uses bounds as width for line breaking. + * + * @return true if this line breaker uses bounds as width for line breaking. + * @see Builder#setUseBoundsForWidth(boolean) + */ + @FlaggedApi(FLAG_MISSING_GETTER_APIS) + public boolean getUseBoundsForWidth() { + return mUseBoundsForWidth; } /** diff --git a/graphics/java/android/graphics/text/MeasuredText.java b/graphics/java/android/graphics/text/MeasuredText.java index 6da07198c3ad..884268a4b85c 100644 --- a/graphics/java/android/graphics/text/MeasuredText.java +++ b/graphics/java/android/graphics/text/MeasuredText.java @@ -29,11 +29,13 @@ import android.util.Log; import com.android.internal.util.Preconditions; import dalvik.annotation.optimization.CriticalNative; +import dalvik.annotation.optimization.NeverInline; import libcore.util.NativeAllocationRegistry; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; +import java.util.Locale; import java.util.Objects; /** @@ -85,6 +87,30 @@ public class MeasuredText { return mChars; } + private void rangeCheck(int start, int end) { + if (start < 0 || start > end || end > mChars.length) { + throwRangeError(start, end); + } + } + + @NeverInline + private void throwRangeError(int start, int end) { + throw new IllegalArgumentException(String.format(Locale.US, + "start(%d) end(%d) length(%d) out of bounds", start, end, mChars.length)); + } + + private void offsetCheck(int offset) { + if (offset < 0 || offset >= mChars.length) { + throwOffsetError(offset); + } + } + + @NeverInline + private void throwOffsetError(int offset) { + throw new IllegalArgumentException(String.format(Locale.US, + "offset (%d) length(%d) out of bounds", offset, mChars.length)); + } + /** * Returns the width of a given range. * @@ -93,12 +119,7 @@ public class MeasuredText { */ public @FloatRange(from = 0.0) @Px float getWidth( @IntRange(from = 0) int start, @IntRange(from = 0) int end) { - Preconditions.checkArgument(0 <= start && start <= mChars.length, - "start(%d) must be 0 <= start <= %d", start, mChars.length); - Preconditions.checkArgument(0 <= end && end <= mChars.length, - "end(%d) must be 0 <= end <= %d", end, mChars.length); - Preconditions.checkArgument(start <= end, - "start(%d) is larger than end(%d)", start, end); + rangeCheck(start, end); return nGetWidth(mNativePtr, start, end); } @@ -120,12 +141,7 @@ public class MeasuredText { */ public void getBounds(@IntRange(from = 0) int start, @IntRange(from = 0) int end, @NonNull Rect rect) { - Preconditions.checkArgument(0 <= start && start <= mChars.length, - "start(%d) must be 0 <= start <= %d", start, mChars.length); - Preconditions.checkArgument(0 <= end && end <= mChars.length, - "end(%d) must be 0 <= end <= %d", end, mChars.length); - Preconditions.checkArgument(start <= end, - "start(%d) is larger than end(%d)", start, end); + rangeCheck(start, end); Preconditions.checkNotNull(rect); nGetBounds(mNativePtr, mChars, start, end, rect); } @@ -139,12 +155,7 @@ public class MeasuredText { */ public void getFontMetricsInt(@IntRange(from = 0) int start, @IntRange(from = 0) int end, @NonNull Paint.FontMetricsInt outMetrics) { - Preconditions.checkArgument(0 <= start && start <= mChars.length, - "start(%d) must be 0 <= start <= %d", start, mChars.length); - Preconditions.checkArgument(0 <= end && end <= mChars.length, - "end(%d) must be 0 <= end <= %d", end, mChars.length); - Preconditions.checkArgument(start <= end, - "start(%d) is larger than end(%d)", start, end); + rangeCheck(start, end); Objects.requireNonNull(outMetrics); long packed = nGetExtent(mNativePtr, mChars, start, end); @@ -160,8 +171,7 @@ public class MeasuredText { * @param offset an offset of the character. */ public @FloatRange(from = 0.0f) @Px float getCharWidthAt(@IntRange(from = 0) int offset) { - Preconditions.checkArgument(0 <= offset && offset < mChars.length, - "offset(%d) is larger than text length %d" + offset, mChars.length); + offsetCheck(offset); return nGetCharWidthAt(mNativePtr, offset); } diff --git a/graphics/java/android/graphics/text/PositionedGlyphs.java b/graphics/java/android/graphics/text/PositionedGlyphs.java index 7932e3334063..671eb6e514c5 100644 --- a/graphics/java/android/graphics/text/PositionedGlyphs.java +++ b/graphics/java/android/graphics/text/PositionedGlyphs.java @@ -46,9 +46,11 @@ import java.util.Objects; * @see TextRunShaper#shapeTextRun(CharSequence, int, int, int, int, float, float, boolean, Paint) */ public final class PositionedGlyphs { - private static final NativeAllocationRegistry REGISTRY = - NativeAllocationRegistry.createMalloced( - Typeface.class.getClassLoader(), nReleaseFunc()); + private static class NoImagePreloadHolder { + private static final NativeAllocationRegistry REGISTRY = + NativeAllocationRegistry.createMalloced( + Typeface.class.getClassLoader(), nReleaseFunc()); + } private final long mLayoutPtr; private final float mXOffset; @@ -137,7 +139,7 @@ public final class PositionedGlyphs { * Returns the glyph ID used for drawing the glyph at the given index. * * @param index the glyph index - * @return An glyph ID of the font. + * @return A glyph ID of the font. */ @IntRange(from = 0) public int getGlyphId(@IntRange(from = 0) int index) { @@ -259,7 +261,7 @@ public final class PositionedGlyphs { mFonts.add(prevFont); } - REGISTRY.registerNativeAllocation(this, layoutPtr); + NoImagePreloadHolder.REGISTRY.registerNativeAllocation(this, layoutPtr); } @CriticalNative |