Skip to content

Commit

Permalink
Merge pull request #2133 from marunjar/fix_blurry_icons
Browse files Browse the repository at this point in the history
fix blurry icons
  • Loading branch information
marunjar authored Aug 1, 2023
2 parents 9a932e1 + ea1e18b commit 03496cc
Showing 1 changed file with 13 additions and 32 deletions.
45 changes: 13 additions & 32 deletions app/src/main/java/fr/neamar/kiss/utils/DrawableUtils.java
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
package fr.neamar.kiss.utils;

import android.annotation.SuppressLint;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Canvas;
Expand Down Expand Up @@ -127,7 +126,7 @@ public static Drawable applyIconMaskShape(@NonNull Context ctx, @NonNull Drawabl
outputBitmap = Bitmap.createBitmap(iconSize, iconSize, Bitmap.Config.ARGB_8888);
outputCanvas = new Canvas(outputBitmap);

setIconShape(outputCanvas, backgroundColor, shape);
setIconShapeAndDrawBackground(outputCanvas, backgroundColor, shape, false);

// Stretch adaptive layers because they are 108dp and the icon size is 48dp
if (bgDrawable != null) {
Expand Down Expand Up @@ -160,7 +159,7 @@ else if (icon != null) {
outputBitmap = Bitmap.createBitmap(iconSize, iconSize, Bitmap.Config.ARGB_8888);
outputCanvas = new Canvas(outputBitmap);

setIconShape(outputCanvas, backgroundColor, shape);
setIconShapeAndDrawBackground(outputCanvas, backgroundColor, shape, true);

// Shrink icon so that it fits the shape
int bottomRightCorner = iconSize - iconOffset;
Expand All @@ -172,27 +171,22 @@ else if (icon != null) {
outputBitmap = Bitmap.createBitmap(iconSize, iconSize, Bitmap.Config.ARGB_8888);
outputCanvas = new Canvas(outputBitmap);

setIconShape(outputCanvas, Color.BLACK, shape);
setIconShapeAndDrawBackground(outputCanvas, Color.BLACK, shape, true);
}
return new BitmapDrawable(ctx.getResources(), outputBitmap);
}

/**
* Set the shape of adaptive icons
* Set the shape of icons and draws background.
* 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_*
*/
private synchronized static void setIconShape(Canvas canvas, @ColorInt int backgroundColor, int shape) {
private synchronized static void setIconShapeAndDrawBackground(Canvas canvas, @ColorInt int backgroundColor, int shape, boolean drawBackground) {
int iconSize = canvas.getHeight();
final Path path = SHAPE_PATH;
path.rewind();

final Paint paint = PAINT;
paint.reset();
paint.setFlags(Paint.ANTI_ALIAS_FLAG);
paint.setColor(backgroundColor);

switch (shape) {
case SHAPE_SYSTEM: {
if (hasDeviceConfiguredMask()) {
Expand All @@ -204,13 +198,10 @@ private synchronized static void setIconShape(Canvas canvas, @ColorInt int backg
// This should never happen, use rect so nothing is clipped
path.addRect(0f, 0f, iconSize, iconSize, Path.Direction.CCW);
}
canvas.drawPath(path, paint);
break;
}
case SHAPE_CIRCLE: {
int radius = iconSize / 2;
canvas.drawCircle(radius, radius, radius, paint);

path.addCircle(radius, radius, radius, Path.Direction.CCW);
break;
}
Expand All @@ -223,19 +214,13 @@ private synchronized static void setIconShape(Canvas canvas, @ColorInt int backg
path.cubicTo(h - c, iconSize, 0, h + c, 0, h);
path.cubicTo(0, h - c, h - c, 0, h, 0);
path.close();

canvas.drawPath(path, paint);
break;
}
case SHAPE_SQUARE:
canvas.drawRect(0f, 0f, iconSize, iconSize, paint);

path.addRect(0f, 0f, iconSize, iconSize, Path.Direction.CCW);
break;
case SHAPE_ROUND_RECT:
RECT_F.set(0f, 0f, iconSize, iconSize);
canvas.drawRoundRect(RECT_F, iconSize / 8f, iconSize / 12f, paint);

path.addRoundRect(RECT_F, iconSize / 8f, iconSize / 12f, Path.Direction.CCW);
break;
case SHAPE_TEARDROP_RND: // this is handled before we get here
Expand All @@ -246,8 +231,6 @@ private synchronized static void setIconShape(Canvas canvas, @ColorInt int backg
RECT_F.set(iconSize * 0.70f, iconSize * 0.70f, iconSize, iconSize);
path.arcTo(RECT_F, 0, 90, false);
path.close();

canvas.drawPath(path, paint);
break;
case SHAPE_TEARDROP_BL:
RECT_F.set(0f, 0f, iconSize, iconSize);
Expand All @@ -256,8 +239,6 @@ private synchronized static void setIconShape(Canvas canvas, @ColorInt int backg
RECT_F.set(0f, iconSize * .7f, iconSize * .3f, iconSize);
path.arcTo(RECT_F, 90, 90, false);
path.close();

canvas.drawPath(path, paint);
break;
case SHAPE_TEARDROP_TL:
RECT_F.set(0f, 0f, iconSize, iconSize);
Expand All @@ -266,8 +247,6 @@ private synchronized static void setIconShape(Canvas canvas, @ColorInt int backg
RECT_F.set(0f, 0f, iconSize * .3f, iconSize * .3f);
path.arcTo(RECT_F, 180, 90, false);
path.close();

canvas.drawPath(path, paint);
break;
case SHAPE_TEARDROP_TR:
RECT_F.set(0f, 0f, iconSize, iconSize);
Expand All @@ -276,8 +255,6 @@ private synchronized static void setIconShape(Canvas canvas, @ColorInt int backg
RECT_F.set(iconSize * .7f, 0f, iconSize, iconSize * .3f);
path.arcTo(RECT_F, 270, 90, false);
path.close();

canvas.drawPath(path, paint);
break;
case SHAPE_HEXAGON:
for (int deg = 0; deg < 360; deg += 60) {
Expand All @@ -289,8 +266,6 @@ private synchronized static void setIconShape(Canvas canvas, @ColorInt int backg
path.lineTo(x, y);
}
path.close();

canvas.drawPath(path, paint);
break;
case SHAPE_OCTAGON:
for (int deg = 22; deg < 360; deg += 45) {
Expand All @@ -307,10 +282,16 @@ private synchronized static void setIconShape(Canvas canvas, @ColorInt int backg
path.lineTo(x, y);
}
path.close();

canvas.drawPath(path, paint);
break;
}
// draw background if applicable
if (drawBackground && backgroundColor != Color.TRANSPARENT) {
final Paint paint = PAINT;
paint.reset();
paint.setFlags(Paint.ANTI_ALIAS_FLAG);
paint.setColor(backgroundColor);
canvas.drawPath(path, paint);
}
// make sure we don't draw outside the shape
canvas.clipPath(path);
}
Expand Down

0 comments on commit 03496cc

Please sign in to comment.