From aca714c68154a1890a3216b61332961e4416f8f7 Mon Sep 17 00:00:00 2001 From: marunjar Date: Sat, 6 Jan 2024 21:19:42 +0100 Subject: [PATCH 1/4] use enum for icon shape - create new enum - use where applicable --- .../java/fr/neamar/kiss/IconsHandler.java | 53 ++++++++++--------- .../fr/neamar/kiss/icons/SystemIconPack.java | 8 +-- .../fr/neamar/kiss/utils/DrawableUtils.java | 48 ++++++----------- .../java/fr/neamar/kiss/utils/IconShape.java | 50 +++++++++++++++++ 4 files changed, 99 insertions(+), 60 deletions(-) create mode 100644 app/src/main/java/fr/neamar/kiss/utils/IconShape.java diff --git a/app/src/main/java/fr/neamar/kiss/IconsHandler.java b/app/src/main/java/fr/neamar/kiss/IconsHandler.java index 007482adb2..8d6bdd1535 100644 --- a/app/src/main/java/fr/neamar/kiss/IconsHandler.java +++ b/app/src/main/java/fr/neamar/kiss/IconsHandler.java @@ -38,6 +38,7 @@ import fr.neamar.kiss.result.AppResult; import fr.neamar.kiss.result.TagDummyResult; import fr.neamar.kiss.utils.DrawableUtils; +import fr.neamar.kiss.utils.IconShape; import fr.neamar.kiss.utils.UserHandle; import fr.neamar.kiss.utils.Utilities; @@ -57,7 +58,7 @@ public class IconsHandler { private final SystemIconPack mSystemPack = new SystemIconPack(); private boolean mForceAdaptive = false; private boolean mContactPackMask = false; - private int mContactsShape = DrawableUtils.SHAPE_SYSTEM; + private IconShape mContactsShape = IconShape.SHAPE_SYSTEM; private boolean mForceShape = false; private Utilities.AsyncRun mLoadIconsPackTask = null; private volatile Map customIconIds = null; @@ -101,11 +102,13 @@ public void onPrefChanged(SharedPreferences pref, String key) { } } - private static int getAdaptiveShape(SharedPreferences pref, String key) { + @NonNull + private static IconShape getAdaptiveShape(SharedPreferences pref, String key) { try { - return Integer.parseInt(pref.getString(key, String.valueOf(DrawableUtils.SHAPE_SYSTEM))); + int shapeId = Integer.parseInt(pref.getString(key, String.valueOf(IconShape.SHAPE_SYSTEM.getId()))); + return IconShape.valueById(shapeId); } catch (Exception e) { - return DrawableUtils.SHAPE_SYSTEM; + return IconShape.SHAPE_SYSTEM; } } @@ -222,7 +225,7 @@ public Drawable getBackgroundDrawable(@ColorInt int backgroundColor) { return null; } - final int shape = getShapeForGeneratingDrawable(); + final IconShape shape = getShapeForGeneratingDrawable(); Drawable drawable = DrawableUtils.generateBackgroundDrawable(ctx, backgroundColor, shape); return forceIconMask(drawable, shape); } @@ -232,7 +235,7 @@ public Drawable getDrawableIconForCodepoint(int codePoint, @ColorInt int textCol if (mIconPack != null && !mIconPack.isLoaded()) { return null; } - final int shape = getShapeForGeneratingDrawable(); + final IconShape shape = getShapeForGeneratingDrawable(); Drawable drawable = DrawableUtils.generateCodepointDrawable(ctx, codePoint, textColor, backgroundColor, shape); return forceIconMask(drawable, shape); } @@ -272,7 +275,7 @@ public Drawable applyBadge(@NonNull Drawable drawable, @NonNull UserHandle userH } public Drawable applyContactMask(@NonNull Context ctx, @NonNull Drawable drawable) { - final int shape = getContactsShape(); + final IconShape shape = getContactsShape(); if (mContactPackMask && mIconPack != null && mIconPack.hasMask()) { // if the icon pack has a mask, use that instead of the adaptive shape @@ -292,7 +295,7 @@ public Drawable applyContactMask(@NonNull Context ctx, @NonNull Drawable drawabl * @param drawable drawable to mask * @return masked drawable */ - private Drawable forceIconMask(@NonNull Drawable drawable, int shape) { + private Drawable forceIconMask(@NonNull Drawable drawable, @NonNull IconShape shape) { // apply mask if (mIconPack != null && mIconPack.hasMask()) { // if the icon pack has a mask, use that instead of the adaptive shape @@ -305,40 +308,42 @@ private Drawable forceIconMask(@NonNull Drawable drawable, int shape) { /** * Get shape used for contact icons with fallbacks. - * If contacts shape is {@link DrawableUtils#SHAPE_SYSTEM} app shape is used. - * If app shape is {@link DrawableUtils#SHAPE_SYSTEM} too and no icon mask can be configured for device, used shape is a circle. + * If contacts shape is {@link IconShape#SHAPE_SYSTEM} app shape is used. + * If app shape is {@link IconShape#SHAPE_SYSTEM} too and no icon mask can be configured for device, used shape is a circle. * * @return shape */ - private int getContactsShape() { - int shape = mContactsShape; - if (shape == DrawableUtils.SHAPE_SYSTEM) { + @NonNull + private IconShape getContactsShape() { + IconShape shape = mContactsShape; + if (shape == IconShape.SHAPE_SYSTEM) { shape = mSystemPack.getAdaptiveShape(); } - if (shape == DrawableUtils.SHAPE_SYSTEM && !DrawableUtils.hasDeviceConfiguredMask()) { - shape = DrawableUtils.SHAPE_CIRCLE; + if (shape == IconShape.SHAPE_SYSTEM && !DrawableUtils.hasDeviceConfiguredMask()) { + shape = IconShape.SHAPE_CIRCLE; } return shape; } /** * Get shape used for generating drawables with fallbacks. - * If icon pack has mask then {@link DrawableUtils#SHAPE_SYSTEM} is used. - * If shape is {@link DrawableUtils#SHAPE_SYSTEM} too and no icon mask can be configured for device, used shape is a circle. + * If icon pack has mask then {@link IconShape#SHAPE_SYSTEM} is used. + * If shape is {@link IconShape#SHAPE_SYSTEM} too and no icon mask can be configured for device, used shape is a circle. * * @return shape */ - private int getShapeForGeneratingDrawable() { - int shape = mSystemPack.getAdaptiveShape(); + @NonNull + private IconShape getShapeForGeneratingDrawable() { + IconShape shape = mSystemPack.getAdaptiveShape(); if (mIconPack != null && mIconPack.hasMask()) { - shape = DrawableUtils.SHAPE_SYSTEM; + shape = IconShape.SHAPE_SYSTEM; } - if (shape == DrawableUtils.SHAPE_SYSTEM && !DrawableUtils.hasDeviceConfiguredMask()) { - shape = DrawableUtils.SHAPE_CIRCLE; + if (shape == IconShape.SHAPE_SYSTEM && !DrawableUtils.hasDeviceConfiguredMask()) { + shape = IconShape.SHAPE_CIRCLE; } - if (shape == DrawableUtils.SHAPE_TEARDROP_RND) { + if (shape == IconShape.SHAPE_TEARDROP_RND) { Random r = new Random(); - shape = DrawableUtils.SHAPE_TEARDROP_BR + r.nextInt(4); + shape = shape.getFinalShape(r.nextInt(4)); } return shape; diff --git a/app/src/main/java/fr/neamar/kiss/icons/SystemIconPack.java b/app/src/main/java/fr/neamar/kiss/icons/SystemIconPack.java index dbf599ea30..a9c200290b 100644 --- a/app/src/main/java/fr/neamar/kiss/icons/SystemIconPack.java +++ b/app/src/main/java/fr/neamar/kiss/icons/SystemIconPack.java @@ -13,6 +13,7 @@ import fr.neamar.kiss.ui.GoogleCalendarIcon; import fr.neamar.kiss.utils.DrawableUtils; +import fr.neamar.kiss.utils.IconShape; import fr.neamar.kiss.utils.PackageManagerUtils; import fr.neamar.kiss.utils.UserHandle; @@ -20,7 +21,7 @@ public class SystemIconPack implements IconPack { private static final String TAG = SystemIconPack.class.getSimpleName(); private final String packageName; - private int mAdaptiveShape = DrawableUtils.SHAPE_SYSTEM; + private IconShape mAdaptiveShape = IconShape.SHAPE_SYSTEM; public SystemIconPack(String packageName) { this.packageName = packageName; @@ -40,11 +41,12 @@ public String getPackPackageName() { public void load(PackageManager packageManager) { } - public int getAdaptiveShape() { + @NonNull + public IconShape getAdaptiveShape() { return mAdaptiveShape; } - public void setAdaptiveShape(int shape) { + public void setAdaptiveShape(@NonNull IconShape shape) { mAdaptiveShape = shape; } diff --git a/app/src/main/java/fr/neamar/kiss/utils/DrawableUtils.java b/app/src/main/java/fr/neamar/kiss/utils/DrawableUtils.java index c8cb594249..795ed57459 100644 --- a/app/src/main/java/fr/neamar/kiss/utils/DrawableUtils.java +++ b/app/src/main/java/fr/neamar/kiss/utils/DrawableUtils.java @@ -29,19 +29,6 @@ public class DrawableUtils { - public static final int SHAPE_SYSTEM = 0; - public static final int SHAPE_CIRCLE = 1; - public static final int SHAPE_SQUARE = 2; - public static final int SHAPE_SQUIRCLE = 3; - public static final int SHAPE_ROUND_RECT = 4; - public static final int SHAPE_TEARDROP_BR = 5; - private static final int SHAPE_TEARDROP_BL = 6; - private static final int SHAPE_TEARDROP_TL = 7; - private static final int SHAPE_TEARDROP_TR = 8; - public static final int SHAPE_TEARDROP_RND = 9; - public static final int SHAPE_HEXAGON = 10; - public static final int SHAPE_OCTAGON = 11; - private static final Paint PAINT = new Paint(); private static final Path SHAPE_PATH = new Path(); private static final RectF RECT_F = new RectF(); @@ -78,7 +65,7 @@ public static Bitmap drawableToBitmap(@NonNull Drawable drawable) { * @param shape from SHAPE_* * @return margin size */ - private static float getScaleToFit(int shape) { + private static float getScaleToFit(IconShape shape) { switch (shape) { case SHAPE_SYSTEM: case SHAPE_CIRCLE: @@ -110,16 +97,18 @@ private static float getScaleToFit(int shape) { * @return shaped icon */ @NonNull - public static Drawable applyIconMaskShape(@NonNull Context ctx, @NonNull Drawable icon, int shape, boolean fitInside, @ColorInt int backgroundColor) { - if (shape == SHAPE_SYSTEM && !hasDeviceConfiguredMask()) + public static Drawable applyIconMaskShape(@NonNull Context ctx, @NonNull Drawable icon, @NonNull IconShape shape, boolean fitInside, @ColorInt int backgroundColor) { + if (shape == IconShape.SHAPE_SYSTEM && !hasDeviceConfiguredMask()) { // if no icon mask can be configured for device, then use icon as is return icon; - if (shape == SHAPE_TEARDROP_RND) - shape = SHAPE_TEARDROP_BR + (icon.hashCode() % 4); + } + if (shape == IconShape.SHAPE_TEARDROP_RND) { + shape = shape.getFinalShape(icon.hashCode()); + } Bitmap outputBitmap; Canvas outputCanvas; - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O && isAdaptiveIconDrawable(icon)) { + if (isAdaptiveIconDrawable(icon)) { AdaptiveIconDrawable adaptiveIcon = (AdaptiveIconDrawable) icon; Drawable bgDrawable = adaptiveIcon.getBackground(); Drawable fgDrawable = adaptiveIcon.getForeground(); @@ -148,7 +137,7 @@ public static Drawable applyIconMaskShape(@NonNull Context ctx, @NonNull Drawabl } } // If icon is not adaptive, put it in a colored canvas to make it have a unified shape - else if (icon != null) { + else { // Shrink icon fit inside the shape int iconSize; int iconOffset = 0; @@ -173,13 +162,6 @@ else if (icon != null) { int bottomRightCorner = iconSize - iconOffset; icon.setBounds(iconOffset, iconOffset, bottomRightCorner, bottomRightCorner); icon.draw(outputCanvas); - } else { - int iconSize = ctx.getResources().getDimensionPixelSize(R.dimen.result_icon_size); - - outputBitmap = Bitmap.createBitmap(iconSize, iconSize, Bitmap.Config.ARGB_8888); - outputCanvas = new Canvas(outputBitmap); - - setIconShapeAndDrawBackground(outputCanvas, Color.BLACK, shape, true); } return new BitmapDrawable(ctx.getResources(), outputBitmap); } @@ -190,7 +172,7 @@ else if (icon != null) { * * @param shape type of shape: DrawableUtils.SHAPE_* */ - private synchronized static void setIconShapeAndDrawBackground(Canvas canvas, @ColorInt int backgroundColor, int shape, boolean drawBackground) { + private synchronized static void setIconShapeAndDrawBackground(Canvas canvas, @ColorInt int backgroundColor, @NonNull IconShape shape, boolean drawBackground) { int iconSize = canvas.getHeight(); final Path path = SHAPE_PATH; path.rewind(); @@ -348,13 +330,13 @@ public static boolean isThemedIconEnabled(Context ctx) { } @NonNull - public synchronized static Drawable generateBackgroundDrawable(@NonNull Context ctx, @ColorInt int backgroundColor, int shape) { + public synchronized static Drawable generateBackgroundDrawable(@NonNull Context ctx, @ColorInt int backgroundColor, @NonNull IconShape shape) { Bitmap bitmap = generateBackgroundBitmap(ctx, backgroundColor, shape); return new BitmapDrawable(ctx.getResources(), bitmap); } @NonNull - public static Drawable generateCodepointDrawable(@NonNull Context ctx, int codepoint, @ColorInt int textColor, @ColorInt int backgroundColor, int shape) { + public static Drawable generateCodepointDrawable(@NonNull Context ctx, int codepoint, @ColorInt int textColor, @ColorInt int backgroundColor, @NonNull IconShape shape) { int iconSize = ctx.getResources().getDimensionPixelSize(R.dimen.result_icon_size); Bitmap bitmap = generateBackgroundBitmap(ctx, backgroundColor, shape); @@ -422,14 +404,14 @@ else if (!Character.UnicodeBlock.BASIC_LATIN.toString().equals(blockString)) { } @NonNull - private synchronized static Bitmap generateBackgroundBitmap(@NonNull Context ctx, @ColorInt int backgroundColor, int shape) { + private synchronized static Bitmap generateBackgroundBitmap(@NonNull Context ctx, @ColorInt int backgroundColor, @NonNull IconShape shape) { int iconSize = ctx.getResources().getDimensionPixelSize(R.dimen.result_icon_size); // create a canvas from a bitmap Bitmap bitmap = Bitmap.createBitmap(iconSize, iconSize, Bitmap.Config.ARGB_8888); Canvas canvas = new Canvas(bitmap); - if (shape == SHAPE_SYSTEM && !hasDeviceConfiguredMask()) { - shape = SHAPE_CIRCLE; + if (shape == IconShape.SHAPE_SYSTEM && !hasDeviceConfiguredMask()) { + shape = IconShape.SHAPE_CIRCLE; } setIconShapeAndDrawBackground(canvas, backgroundColor, shape, true); diff --git a/app/src/main/java/fr/neamar/kiss/utils/IconShape.java b/app/src/main/java/fr/neamar/kiss/utils/IconShape.java new file mode 100644 index 0000000000..b86f1e55c7 --- /dev/null +++ b/app/src/main/java/fr/neamar/kiss/utils/IconShape.java @@ -0,0 +1,50 @@ +package fr.neamar.kiss.utils; + +public enum IconShape { + + SHAPE_SYSTEM(0), + SHAPE_CIRCLE(1), + SHAPE_SQUARE(2), + SHAPE_SQUIRCLE(3), + SHAPE_ROUND_RECT(4), + SHAPE_TEARDROP_BR(5), + SHAPE_TEARDROP_BL(6), + SHAPE_TEARDROP_TL(7), + SHAPE_TEARDROP_TR(8), + SHAPE_TEARDROP_RND(9), + SHAPE_HEXAGON(10), + SHAPE_OCTAGON(11); + + private final int id; + + IconShape(int id) { + this.id = id; + } + + public static IconShape valueById(int shapeId) { + for (IconShape shape : values()) { + if (shape.getId() == shapeId) { + return shape; + } + } + return SHAPE_SYSTEM; + } + + public int getId() { + return id; + } + + public IconShape getFinalShape(int hash) { + switch (this) { + case SHAPE_SYSTEM: + if (!DrawableUtils.hasDeviceConfiguredMask()) { + return IconShape.SHAPE_CIRCLE; + } + break; + case SHAPE_TEARDROP_RND: + IconShape[] shapes = {SHAPE_TEARDROP_BL, SHAPE_TEARDROP_BR, SHAPE_TEARDROP_TL, SHAPE_TEARDROP_TR}; + return shapes[hash % 4]; + } + return this; + } +} From aeadceadb098e785b585b2ad9269f27df776821d Mon Sep 17 00:00:00 2001 From: marunjar Date: Sat, 6 Jan 2024 22:14:49 +0100 Subject: [PATCH 2/4] simplify code - remove randomness - remove some unnecessary conditions - fix possible crash --- .../main/java/fr/neamar/kiss/IconsHandler.java | 18 +++++------------- .../fr/neamar/kiss/utils/DrawableUtils.java | 4 +--- .../java/fr/neamar/kiss/utils/IconShape.java | 12 ++++++++---- 3 files changed, 14 insertions(+), 20 deletions(-) diff --git a/app/src/main/java/fr/neamar/kiss/IconsHandler.java b/app/src/main/java/fr/neamar/kiss/IconsHandler.java index 8d6bdd1535..4767a87af8 100644 --- a/app/src/main/java/fr/neamar/kiss/IconsHandler.java +++ b/app/src/main/java/fr/neamar/kiss/IconsHandler.java @@ -27,7 +27,6 @@ import java.util.HashMap; import java.util.List; import java.util.Map; -import java.util.Random; import fr.neamar.kiss.db.AppRecord; import fr.neamar.kiss.db.DBHelper; @@ -225,7 +224,7 @@ public Drawable getBackgroundDrawable(@ColorInt int backgroundColor) { return null; } - final IconShape shape = getShapeForGeneratingDrawable(); + final IconShape shape = getShapeForGeneratingDrawable(backgroundColor); Drawable drawable = DrawableUtils.generateBackgroundDrawable(ctx, backgroundColor, shape); return forceIconMask(drawable, shape); } @@ -235,7 +234,7 @@ public Drawable getDrawableIconForCodepoint(int codePoint, @ColorInt int textCol if (mIconPack != null && !mIconPack.isLoaded()) { return null; } - final IconShape shape = getShapeForGeneratingDrawable(); + final IconShape shape = getShapeForGeneratingDrawable(codePoint); Drawable drawable = DrawableUtils.generateCodepointDrawable(ctx, codePoint, textColor, backgroundColor, shape); return forceIconMask(drawable, shape); } @@ -330,23 +329,16 @@ private IconShape getContactsShape() { * If icon pack has mask then {@link IconShape#SHAPE_SYSTEM} is used. * If shape is {@link IconShape#SHAPE_SYSTEM} too and no icon mask can be configured for device, used shape is a circle. * + * @param hash, for pseudo random shape if applicable * @return shape */ @NonNull - private IconShape getShapeForGeneratingDrawable() { + private IconShape getShapeForGeneratingDrawable(int hash) { IconShape shape = mSystemPack.getAdaptiveShape(); if (mIconPack != null && mIconPack.hasMask()) { shape = IconShape.SHAPE_SYSTEM; } - if (shape == IconShape.SHAPE_SYSTEM && !DrawableUtils.hasDeviceConfiguredMask()) { - shape = IconShape.SHAPE_CIRCLE; - } - if (shape == IconShape.SHAPE_TEARDROP_RND) { - Random r = new Random(); - shape = shape.getFinalShape(r.nextInt(4)); - } - - return shape; + return shape.getFinalShape(hash); } diff --git a/app/src/main/java/fr/neamar/kiss/utils/DrawableUtils.java b/app/src/main/java/fr/neamar/kiss/utils/DrawableUtils.java index 795ed57459..62a737d691 100644 --- a/app/src/main/java/fr/neamar/kiss/utils/DrawableUtils.java +++ b/app/src/main/java/fr/neamar/kiss/utils/DrawableUtils.java @@ -102,9 +102,7 @@ public static Drawable applyIconMaskShape(@NonNull Context ctx, @NonNull Drawabl // if no icon mask can be configured for device, then use icon as is return icon; } - if (shape == IconShape.SHAPE_TEARDROP_RND) { - shape = shape.getFinalShape(icon.hashCode()); - } + shape = shape.getFinalShape(icon.hashCode()); Bitmap outputBitmap; Canvas outputCanvas; diff --git a/app/src/main/java/fr/neamar/kiss/utils/IconShape.java b/app/src/main/java/fr/neamar/kiss/utils/IconShape.java index b86f1e55c7..afe8f79f68 100644 --- a/app/src/main/java/fr/neamar/kiss/utils/IconShape.java +++ b/app/src/main/java/fr/neamar/kiss/utils/IconShape.java @@ -1,5 +1,7 @@ package fr.neamar.kiss.utils; +import androidx.annotation.NonNull; + public enum IconShape { SHAPE_SYSTEM(0), @@ -21,6 +23,7 @@ public enum IconShape { this.id = id; } + @NonNull public static IconShape valueById(int shapeId) { for (IconShape shape : values()) { if (shape.getId() == shapeId) { @@ -40,11 +43,12 @@ public IconShape getFinalShape(int hash) { if (!DrawableUtils.hasDeviceConfiguredMask()) { return IconShape.SHAPE_CIRCLE; } - break; + return this; case SHAPE_TEARDROP_RND: - IconShape[] shapes = {SHAPE_TEARDROP_BL, SHAPE_TEARDROP_BR, SHAPE_TEARDROP_TL, SHAPE_TEARDROP_TR}; - return shapes[hash % 4]; + IconShape[] shapes = {SHAPE_TEARDROP_BR, SHAPE_TEARDROP_BL, SHAPE_TEARDROP_TL, SHAPE_TEARDROP_TR}; + return shapes[Math.abs(hash % 4)]; + default: + return this; } - return this; } } From c3aabcfd48f28aaf8ff59aa35bfa7f9c7b82e915 Mon Sep 17 00:00:00 2001 From: marunjar Date: Tue, 30 Jan 2024 16:35:24 +0100 Subject: [PATCH 3/4] cleanup code - try to calculate real shape in single place - introduce TEARDROP_SHAPES --- .../java/fr/neamar/kiss/IconsHandler.java | 10 ++--- .../fr/neamar/kiss/utils/DrawableUtils.java | 38 +++++++++++++------ .../java/fr/neamar/kiss/utils/IconShape.java | 14 ------- 3 files changed, 31 insertions(+), 31 deletions(-) diff --git a/app/src/main/java/fr/neamar/kiss/IconsHandler.java b/app/src/main/java/fr/neamar/kiss/IconsHandler.java index 4767a87af8..176293fa2e 100644 --- a/app/src/main/java/fr/neamar/kiss/IconsHandler.java +++ b/app/src/main/java/fr/neamar/kiss/IconsHandler.java @@ -224,7 +224,7 @@ public Drawable getBackgroundDrawable(@ColorInt int backgroundColor) { return null; } - final IconShape shape = getShapeForGeneratingDrawable(backgroundColor); + final IconShape shape = getShapeForGeneratingDrawable(); Drawable drawable = DrawableUtils.generateBackgroundDrawable(ctx, backgroundColor, shape); return forceIconMask(drawable, shape); } @@ -234,7 +234,7 @@ public Drawable getDrawableIconForCodepoint(int codePoint, @ColorInt int textCol if (mIconPack != null && !mIconPack.isLoaded()) { return null; } - final IconShape shape = getShapeForGeneratingDrawable(codePoint); + final IconShape shape = getShapeForGeneratingDrawable(); Drawable drawable = DrawableUtils.generateCodepointDrawable(ctx, codePoint, textColor, backgroundColor, shape); return forceIconMask(drawable, shape); } @@ -318,6 +318,7 @@ private IconShape getContactsShape() { if (shape == IconShape.SHAPE_SYSTEM) { shape = mSystemPack.getAdaptiveShape(); } + // contacts have square images, so fallback to circle explicitly if (shape == IconShape.SHAPE_SYSTEM && !DrawableUtils.hasDeviceConfiguredMask()) { shape = IconShape.SHAPE_CIRCLE; } @@ -329,16 +330,15 @@ private IconShape getContactsShape() { * If icon pack has mask then {@link IconShape#SHAPE_SYSTEM} is used. * If shape is {@link IconShape#SHAPE_SYSTEM} too and no icon mask can be configured for device, used shape is a circle. * - * @param hash, for pseudo random shape if applicable * @return shape */ @NonNull - private IconShape getShapeForGeneratingDrawable(int hash) { + private IconShape getShapeForGeneratingDrawable() { IconShape shape = mSystemPack.getAdaptiveShape(); if (mIconPack != null && mIconPack.hasMask()) { shape = IconShape.SHAPE_SYSTEM; } - return shape.getFinalShape(hash); + return shape; } diff --git a/app/src/main/java/fr/neamar/kiss/utils/DrawableUtils.java b/app/src/main/java/fr/neamar/kiss/utils/DrawableUtils.java index 62a737d691..488ba883f4 100644 --- a/app/src/main/java/fr/neamar/kiss/utils/DrawableUtils.java +++ b/app/src/main/java/fr/neamar/kiss/utils/DrawableUtils.java @@ -34,6 +34,7 @@ public class DrawableUtils { private static final RectF RECT_F = new RectF(); public static final String KEY_THEMED_ICONS = "themed-icons"; private static final String TAG = DrawableUtils.class.getSimpleName(); + private static final IconShape[] TEARDROP_SHAPES = {IconShape.SHAPE_TEARDROP_BR, IconShape.SHAPE_TEARDROP_BL, IconShape.SHAPE_TEARDROP_TL, IconShape.SHAPE_TEARDROP_TR}; // https://stackoverflow.com/questions/3035692/how-to-convert-a-drawable-to-a-bitmap public static Bitmap drawableToBitmap(@NonNull Drawable drawable) { @@ -102,7 +103,6 @@ public static Drawable applyIconMaskShape(@NonNull Context ctx, @NonNull Drawabl // if no icon mask can be configured for device, then use icon as is return icon; } - shape = shape.getFinalShape(icon.hashCode()); Bitmap outputBitmap; Canvas outputCanvas; @@ -121,7 +121,7 @@ public static Drawable applyIconMaskShape(@NonNull Context ctx, @NonNull Drawabl outputBitmap = Bitmap.createBitmap(iconSize, iconSize, Bitmap.Config.ARGB_8888); outputCanvas = new Canvas(outputBitmap); - setIconShapeAndDrawBackground(outputCanvas, backgroundColor, shape, false); + setIconShapeAndDrawBackground(outputCanvas, backgroundColor, shape, false, icon.hashCode()); // Stretch adaptive layers because they are 108dp and the icon size is 48dp if (bgDrawable != null) { @@ -154,7 +154,7 @@ public static Drawable applyIconMaskShape(@NonNull Context ctx, @NonNull Drawabl outputBitmap = Bitmap.createBitmap(iconSize, iconSize, Bitmap.Config.ARGB_8888); outputCanvas = new Canvas(outputBitmap); - setIconShapeAndDrawBackground(outputCanvas, backgroundColor, shape, true); + setIconShapeAndDrawBackground(outputCanvas, backgroundColor, shape, true, icon.hashCode()); // Shrink icon so that it fits the shape int bottomRightCorner = iconSize - iconOffset; @@ -169,8 +169,11 @@ public static Drawable applyIconMaskShape(@NonNull Context ctx, @NonNull Drawabl * Synchronized because class fields like {@link DrawableUtils#SHAPE_PATH}, {@link DrawableUtils#RECT_F} and {@link DrawableUtils#PAINT} are reused for every call, which may result in unexpected behaviour if method is called from different threads running in parallel. * * @param shape type of shape: DrawableUtils.SHAPE_* + * @param hash, for pseudo random shape if applicable */ - private synchronized static void setIconShapeAndDrawBackground(Canvas canvas, @ColorInt int backgroundColor, @NonNull IconShape shape, boolean drawBackground) { + private synchronized static void setIconShapeAndDrawBackground(Canvas canvas, @ColorInt int backgroundColor, @NonNull IconShape shape, boolean drawBackground, int hash) { + shape = getFinalShape(shape, hash); + int iconSize = canvas.getHeight(); final Path path = SHAPE_PATH; path.rewind(); @@ -329,7 +332,7 @@ public static boolean isThemedIconEnabled(Context ctx) { @NonNull public synchronized static Drawable generateBackgroundDrawable(@NonNull Context ctx, @ColorInt int backgroundColor, @NonNull IconShape shape) { - Bitmap bitmap = generateBackgroundBitmap(ctx, backgroundColor, shape); + Bitmap bitmap = generateBackgroundBitmap(ctx, backgroundColor, shape, backgroundColor); return new BitmapDrawable(ctx.getResources(), bitmap); } @@ -337,7 +340,7 @@ public synchronized static Drawable generateBackgroundDrawable(@NonNull Context public static Drawable generateCodepointDrawable(@NonNull Context ctx, int codepoint, @ColorInt int textColor, @ColorInt int backgroundColor, @NonNull IconShape shape) { int iconSize = ctx.getResources().getDimensionPixelSize(R.dimen.result_icon_size); - Bitmap bitmap = generateBackgroundBitmap(ctx, backgroundColor, shape); + Bitmap bitmap = generateBackgroundBitmap(ctx, backgroundColor, shape, codepoint); // create a canvas from a bitmap Canvas canvas = new Canvas(bitmap); @@ -402,19 +405,30 @@ else if (!Character.UnicodeBlock.BASIC_LATIN.toString().equals(blockString)) { } @NonNull - private synchronized static Bitmap generateBackgroundBitmap(@NonNull Context ctx, @ColorInt int backgroundColor, @NonNull IconShape shape) { + private synchronized static Bitmap generateBackgroundBitmap(@NonNull Context ctx, @ColorInt int backgroundColor, @NonNull IconShape shape, int hash) { int iconSize = ctx.getResources().getDimensionPixelSize(R.dimen.result_icon_size); // create a canvas from a bitmap Bitmap bitmap = Bitmap.createBitmap(iconSize, iconSize, Bitmap.Config.ARGB_8888); Canvas canvas = new Canvas(bitmap); - if (shape == IconShape.SHAPE_SYSTEM && !hasDeviceConfiguredMask()) { - shape = IconShape.SHAPE_CIRCLE; - } - - setIconShapeAndDrawBackground(canvas, backgroundColor, shape, true); + setIconShapeAndDrawBackground(canvas, backgroundColor, shape, true, hash); return bitmap; } + public static IconShape getFinalShape(IconShape shape, int hash) { + switch (shape) { + case SHAPE_SYSTEM: + if (!hasDeviceConfiguredMask()) { + return IconShape.SHAPE_CIRCLE; + } + return shape; + case SHAPE_TEARDROP_RND: + return TEARDROP_SHAPES[Math.abs(hash % 4)]; + default: + return shape; + } + } + + } diff --git a/app/src/main/java/fr/neamar/kiss/utils/IconShape.java b/app/src/main/java/fr/neamar/kiss/utils/IconShape.java index afe8f79f68..309f7d9d5f 100644 --- a/app/src/main/java/fr/neamar/kiss/utils/IconShape.java +++ b/app/src/main/java/fr/neamar/kiss/utils/IconShape.java @@ -37,18 +37,4 @@ public int getId() { return id; } - public IconShape getFinalShape(int hash) { - switch (this) { - case SHAPE_SYSTEM: - if (!DrawableUtils.hasDeviceConfiguredMask()) { - return IconShape.SHAPE_CIRCLE; - } - return this; - case SHAPE_TEARDROP_RND: - IconShape[] shapes = {SHAPE_TEARDROP_BR, SHAPE_TEARDROP_BL, SHAPE_TEARDROP_TL, SHAPE_TEARDROP_TR}; - return shapes[Math.abs(hash % 4)]; - default: - return this; - } - } } From 155a69787dd423b696a98fcb03e33b991b8c9c01 Mon Sep 17 00:00:00 2001 From: marunjar Date: Tue, 30 Jan 2024 21:53:39 +0100 Subject: [PATCH 4/4] fix lint errors --- app/src/main/java/fr/neamar/kiss/utils/DrawableUtils.java | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/app/src/main/java/fr/neamar/kiss/utils/DrawableUtils.java b/app/src/main/java/fr/neamar/kiss/utils/DrawableUtils.java index 488ba883f4..cf86c56f49 100644 --- a/app/src/main/java/fr/neamar/kiss/utils/DrawableUtils.java +++ b/app/src/main/java/fr/neamar/kiss/utils/DrawableUtils.java @@ -83,8 +83,9 @@ private static float getScaleToFit(IconShape shape) { return 0.26f; case SHAPE_OCTAGON: return 0.25f; + default: + return 0f; } - return 0.f; } /** @@ -106,7 +107,7 @@ public static Drawable applyIconMaskShape(@NonNull Context ctx, @NonNull Drawabl Bitmap outputBitmap; Canvas outputCanvas; - if (isAdaptiveIconDrawable(icon)) { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O && isAdaptiveIconDrawable(icon)) { AdaptiveIconDrawable adaptiveIcon = (AdaptiveIconDrawable) icon; Drawable bgDrawable = adaptiveIcon.getBackground(); Drawable fgDrawable = adaptiveIcon.getForeground();