From f3c4cd5db78b2082eba3b3029d69302783d65e3d Mon Sep 17 00:00:00 2001 From: Prabir Pradhan Date: Wed, 10 Apr 2024 19:48:47 +0000 Subject: PointerIcon: Add leniency to hotspot validation for scaled icons When icons are loaded for the current display density, the icon bitmap is always scaled to an integer pixel size, but the hotspot can be scaled more precisely using floats. To account for the difference in precision, add leniency to the hotspot validation checks when the icons are scaled. Bug: 332973446 Test: adb shell wm density 142 Change-Id: I4af5d6619aa7f5245054047ad079694b11919754 --- core/java/android/view/PointerIcon.java | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/core/java/android/view/PointerIcon.java b/core/java/android/view/PointerIcon.java index 17d14042e468..7dc151d8f9ee 100644 --- a/core/java/android/view/PointerIcon.java +++ b/core/java/android/view/PointerIcon.java @@ -288,7 +288,7 @@ public final class PointerIcon implements Parcelable { if (bitmap == null) { throw new IllegalArgumentException("bitmap must not be null"); } - validateHotSpot(bitmap, hotSpotX, hotSpotY); + validateHotSpot(bitmap, hotSpotX, hotSpotY, false /* isScaled */); PointerIcon icon = new PointerIcon(TYPE_CUSTOM); icon.mBitmap = bitmap; @@ -521,7 +521,9 @@ public final class PointerIcon implements Parcelable { BitmapDrawable bitmapDrawable = (BitmapDrawable) drawable; final Bitmap bitmap = getBitmapFromDrawable(bitmapDrawable); - validateHotSpot(bitmap, hotSpotX, hotSpotY); + // The bitmap and hotspot are loaded from the context, which means it is implicitly scaled + // to the current display density, so treat this as a scaled icon when verifying hotspot. + validateHotSpot(bitmap, hotSpotX, hotSpotY, true /* isScaled */); // Set the properties now that we have successfully loaded the icon. mBitmap = bitmap; mHotSpotX = hotSpotX; @@ -535,11 +537,16 @@ public final class PointerIcon implements Parcelable { + ", hotspotX=" + mHotSpotX + ", hotspotY=" + mHotSpotY + "}"; } - private static void validateHotSpot(Bitmap bitmap, float hotSpotX, float hotSpotY) { - if (hotSpotX < 0 || hotSpotX >= bitmap.getWidth()) { + private static void validateHotSpot(Bitmap bitmap, float hotSpotX, float hotSpotY, + boolean isScaled) { + // Be more lenient when checking the hotspot for scaled icons to account for the restriction + // that bitmaps must have an integer size. + if (hotSpotX < 0 || (isScaled ? (int) hotSpotX > bitmap.getWidth() + : hotSpotX >= bitmap.getWidth())) { throw new IllegalArgumentException("x hotspot lies outside of the bitmap area"); } - if (hotSpotY < 0 || hotSpotY >= bitmap.getHeight()) { + if (hotSpotY < 0 || (isScaled ? (int) hotSpotY > bitmap.getHeight() + : hotSpotY >= bitmap.getHeight())) { throw new IllegalArgumentException("y hotspot lies outside of the bitmap area"); } } -- cgit v1.2.3-59-g8ed1b