From d810366d1fad942de7dfb900652d7fd4fc4ab48b Mon Sep 17 00:00:00 2001 From: Amit Kumar Date: Mon, 11 May 2020 18:12:25 +0530 Subject: [PATCH 1/2] Add AdaptiveIconGenerator with ColorExtractor to match icon looks --- .../e/blisslauncher/FixedScaleDrawable.java | 55 +++++ .../core/AdaptiveIconGenerator.java | 232 ++++++++++++++++++ .../core/AdaptiveIconProvider.java | 34 ++- .../e/blisslauncher/core/ColorExtractor.java | 178 ++++++++++++++ .../e/blisslauncher/core/IconsHandler.java | 12 +- .../AdaptiveIconDrawableCompat.java | 2 +- .../core/utils/GraphicsUtil.java | 2 - 7 files changed, 497 insertions(+), 18 deletions(-) create mode 100644 app/src/main/java/foundation/e/blisslauncher/FixedScaleDrawable.java create mode 100644 app/src/main/java/foundation/e/blisslauncher/core/AdaptiveIconGenerator.java create mode 100644 app/src/main/java/foundation/e/blisslauncher/core/ColorExtractor.java diff --git a/app/src/main/java/foundation/e/blisslauncher/FixedScaleDrawable.java b/app/src/main/java/foundation/e/blisslauncher/FixedScaleDrawable.java new file mode 100644 index 0000000000..1f40317c45 --- /dev/null +++ b/app/src/main/java/foundation/e/blisslauncher/FixedScaleDrawable.java @@ -0,0 +1,55 @@ +package foundation.e.blisslauncher; + +import android.annotation.TargetApi; +import android.content.res.Resources; +import android.graphics.Canvas; +import android.graphics.drawable.ColorDrawable; +import android.graphics.drawable.DrawableWrapper; +import android.os.Build; +import android.util.AttributeSet; + +import org.xmlpull.v1.XmlPullParser; + +/** + * Extension of {@link DrawableWrapper} which scales the child drawables by a fixed amount. + */ +@TargetApi(Build.VERSION_CODES.N) +public class FixedScaleDrawable extends DrawableWrapper { + + // TODO b/33553066 use the constant defined in MaskableIconDrawable + public static final float LEGACY_ICON_SCALE = .7f * .6667f; + private float mScaleX, mScaleY; + + public FixedScaleDrawable() { + super(new ColorDrawable()); + mScaleX = LEGACY_ICON_SCALE; + mScaleY = LEGACY_ICON_SCALE; + } + + @Override + public void draw(Canvas canvas) { + int saveCount = canvas.save(); + canvas.scale(mScaleX, mScaleY, + getBounds().exactCenterX(), getBounds().exactCenterY()); + super.draw(canvas); + canvas.restoreToCount(saveCount); + } + + @Override + public void inflate(Resources r, XmlPullParser parser, AttributeSet attrs) { } + + @Override + public void inflate(Resources r, XmlPullParser parser, AttributeSet attrs, Resources.Theme theme) { } + + public void setScale(float scale) { + float h = getIntrinsicHeight(); + float w = getIntrinsicWidth(); + mScaleX = scale * LEGACY_ICON_SCALE; + mScaleY = scale * LEGACY_ICON_SCALE; + if (h > w && w > 0) { + mScaleX *= w / h; + } else if (w > h && h > 0) { + mScaleY *= h / w; + } + } +} diff --git a/app/src/main/java/foundation/e/blisslauncher/core/AdaptiveIconGenerator.java b/app/src/main/java/foundation/e/blisslauncher/core/AdaptiveIconGenerator.java new file mode 100644 index 0000000000..e2998917c3 --- /dev/null +++ b/app/src/main/java/foundation/e/blisslauncher/core/AdaptiveIconGenerator.java @@ -0,0 +1,232 @@ +package foundation.e.blisslauncher.core; + +import android.content.Context; +import android.graphics.Bitmap; +import android.graphics.Color; +import android.graphics.RectF; +import android.graphics.drawable.ColorDrawable; +import android.graphics.drawable.Drawable; +import android.util.Log; +import android.util.SparseIntArray; + +import androidx.annotation.NonNull; +import androidx.core.graphics.ColorUtils; + +import foundation.e.blisslauncher.FixedScaleDrawable; +import foundation.e.blisslauncher.core.customviews.AdaptiveIconDrawableCompat; + +import static java.lang.Math.max; +import static java.lang.Math.min; +import static java.lang.Math.round; + +public class AdaptiveIconGenerator { + + // Average number of derived colors (based on averages with ~100 icons and performance testing) + private static final int NUMBER_OF_COLORS_GUESSTIMATE = 45; + + // Found after some experimenting, might be improved with some more testing + private static final float FULL_BLEED_ICON_SCALE = 1.44f; + // Found after some experimenting, might be improved with some more testing + private static final float NO_MIXIN_ICON_SCALE = 1.40f; + // Icons with less than 5 colors are considered as "single color" + private static final int SINGLE_COLOR_LIMIT = 5; + // Minimal alpha to be considered opaque + private static final int MIN_VISIBLE_ALPHA = 0xEF; + + private Context context; + private Drawable icon; + + private boolean ranLoop; + private boolean shouldWrap; + private int backgroundColor = Color.WHITE; + private boolean isFullBleed; + private boolean noMixinNeeded; + private boolean fullBleedChecked; + private boolean matchesMaskShape; + private boolean isBackgroundWhite; + private float scale; + private int height; + private float aHeight; + private int width; + private float aWidth; + private Drawable result; + + public AdaptiveIconGenerator(Context context, @NonNull Drawable icon) { + this.context = context; + this.icon = icon; + } + + private void loop() { + Drawable extractee = icon; + + if (extractee == null) { + Log.e("AdaptiveIconGenerator", "extractee is null, skipping."); + onExitLoop(); + return; + } + + RectF bounds = new RectF(); + + scale = 1.0f; + + if (extractee instanceof ColorDrawable) { + isFullBleed = true; + fullBleedChecked = true; + } + + width = extractee.getIntrinsicWidth(); + height = extractee.getIntrinsicHeight(); + aWidth = width * (1 - (bounds.left + bounds.right)); + aHeight = height * (1 - (bounds.top + bounds.bottom)); + + // Check if the icon is squarish + final float ratio = aHeight / aWidth; + boolean isSquarish = 0.999 < ratio && ratio < 1.0001; + boolean almostSquarish = isSquarish || (0.97 < ratio && ratio < 1.005); + if (!isSquarish) { + isFullBleed = false; + fullBleedChecked = true; + } + + final Bitmap bitmap = Utilities.drawableToBitmap(extractee); + if (bitmap == null) { + onExitLoop(); + return; + } + + if (!bitmap.hasAlpha()) { + isFullBleed = true; + fullBleedChecked = true; + } + + final int size = height * width; + SparseIntArray rgbScoreHistogram = new SparseIntArray(NUMBER_OF_COLORS_GUESSTIMATE); + final int[] pixels = new int[size]; + bitmap.getPixels(pixels, 0, width, 0, 0, width, height); + + /* + * Calculate the number of padding pixels around the actual icon (i) + * +----------------+ + * | top | + * +---+--------+---+ + * | | | | + * | l | i | r | + * | | | | + * +---+--------+---+ + * | bottom | + * +----------------+ + */ + float adjHeight = height - bounds.top - bounds.bottom; + float l = bounds.left * width * adjHeight; + float top = bounds.top * height * width; + float r = bounds.right * width * adjHeight; + float bottom = bounds.bottom * height * width; + int addPixels = round(l + top + r + bottom); + + // Any icon with less than 10% transparent pixels (padding excluded) is considered "full-bleed-ish" + final int maxTransparent = (int) (round(size * .10) + addPixels); + // Any icon with less than 27% transparent pixels (padding excluded) doesn't need a color mix-in + final int noMixinScore = (int) (round(size * .27) + addPixels); + + int highScore = 0; + int bestRGB = 0; + int transparentScore = 0; + for (int pixel : pixels) { + int alpha = 0xFF & (pixel >> 24); + if (alpha < MIN_VISIBLE_ALPHA) { + // Drop mostly-transparent pixels. + transparentScore++; + if (transparentScore > maxTransparent) { + isFullBleed = false; + fullBleedChecked = true; + } + continue; + } + // Reduce color complexity. + int rgb = ColorExtractor.posterize(pixel); + if (rgb < 0) { + // Defensively avoid array bounds violations. + continue; + } + int currentScore = rgbScoreHistogram.get(rgb) + 1; + rgbScoreHistogram.append(rgb, currentScore); + if (currentScore > highScore) { + highScore = currentScore; + bestRGB = rgb; + } + } + // add back the alpha channel + bestRGB |= 0xff << 24; + + // not yet checked = not set to false = has to be full bleed, isBackgroundWhite = true = is adaptive + isFullBleed |= !fullBleedChecked && !isBackgroundWhite; + + // return early if a mix-in isnt needed + noMixinNeeded = !isFullBleed && !isBackgroundWhite && almostSquarish && transparentScore <= noMixinScore; + if (isFullBleed || noMixinNeeded) { + backgroundColor = bestRGB; + onExitLoop(); + return; + } + + // "single color" + final int numColors = rgbScoreHistogram.size(); + boolean singleColor = numColors <= SINGLE_COLOR_LIMIT; + + // Convert to HSL to get the lightness and adjust the color + final float[] hsl = new float[3]; + ColorUtils.colorToHSL(bestRGB, hsl); + float lightness = hsl[2]; + + boolean light = lightness > .5; + // Apply dark background to mostly white icons + boolean veryLight = lightness > .75 && singleColor; + // Apply light background to mostly dark icons + boolean veryDark = lightness < .35 && singleColor; + + // Adjust color to reach suitable contrast depending on the relationship between the colors + final int opaqueSize = size - transparentScore; + final float pxPerColor = opaqueSize / (float) numColors; + float mixRatio = min(max(pxPerColor / highScore, .15f), .7f); + + // Vary color mix-in based on lightness and amount of colors + int fill = (light && !veryLight) || veryDark ? 0xFFFFFFFF : 0xFF333333; + backgroundColor = ColorUtils.blendARGB(bestRGB, fill, mixRatio); + onExitLoop(); + } + + private void onExitLoop() { + ranLoop = true; + result = genResult(); + } + + private Drawable genResult() { + AdaptiveIconDrawableCompat tmp = new AdaptiveIconDrawableCompat( + new ColorDrawable(), + new FixedScaleDrawable() + ); + ((FixedScaleDrawable) tmp.getForeground()).setDrawable(icon); + if (isFullBleed || noMixinNeeded) { + float scale; + if (noMixinNeeded) { + float upScale = min(width / aWidth, height / aHeight); + scale = NO_MIXIN_ICON_SCALE * upScale; + } else { + float upScale = max(width / aWidth, height / aHeight); + scale = FULL_BLEED_ICON_SCALE * upScale; + } + ((FixedScaleDrawable) tmp.getForeground()).setScale(scale); + } else { + ((FixedScaleDrawable) tmp.getForeground()).setScale(scale); + } + ((ColorDrawable) tmp.getBackground()).setColor(backgroundColor); + return tmp; + } + + public Drawable getResult() { + if (!ranLoop) { + loop(); + } + return result; + } +} diff --git a/app/src/main/java/foundation/e/blisslauncher/core/AdaptiveIconProvider.java b/app/src/main/java/foundation/e/blisslauncher/core/AdaptiveIconProvider.java index 573887f2e6..7986be8021 100755 --- a/app/src/main/java/foundation/e/blisslauncher/core/AdaptiveIconProvider.java +++ b/app/src/main/java/foundation/e/blisslauncher/core/AdaptiveIconProvider.java @@ -32,6 +32,7 @@ public class AdaptiveIconProvider { "Loader.with(Context) must be called before loading an icon."); } + PackageManager packageManager = context.getPackageManager(); Drawable background = null, foreground = null; @@ -53,15 +54,20 @@ public class AdaptiveIconProvider { while ((eventType = manifestParser.nextToken()) != XmlPullParser.END_DOCUMENT) { if (eventType == XmlPullParser.START_TAG && manifestParser.getName().equals( matcher)) { + Log.d(TAG, "Manifest Parser Count: " + manifestParser.getAttributeCount()); + for (int i = 0; i < manifestParser.getAttributeCount(); i++) { + Log.d(TAG, "Icon parser: " + manifestParser.getAttributeName(i)); if (manifestParser.getAttributeName(i).equalsIgnoreCase("icon")) { iconId = Integer.parseInt( manifestParser.getAttributeValue(i).substring(1)); + Log.d(TAG, "Iconid:" + iconId); break; } } if (iconId != 0) { iconName = resources.getResourceName(iconId); + Log.d("AdaptiveIcon", "Iconname: " + iconName); if (iconName.contains("/")) { iconName = iconName.split("/")[1]; } @@ -77,13 +83,18 @@ public class AdaptiveIconProvider { XmlResourceParser parser = null; if (iconId != 0) { - parser = resources.getXml(iconId); + try { + parser = resources.getXml(iconId); + } catch (Resources.NotFoundException e) { + e.printStackTrace(); + parser = null; + } } - for (int dir = 0; dir < IC_DIRS.length && parser == null; dir++) { + /*for (int dir = 0; dir < IC_DIRS.length && parser == null; dir++) { for (int config = 0; config < IC_CONFIGS.length && parser == null; config++) { - for (String name : iconName != null && !iconName.equals("ic_launcher") - ? new String[]{iconName, "ic_launcher"} : new String[]{"ic_launcher"}) { + for (String name : (iconName != null && !iconName.equals("ic_launcher")) + ? new String[]{iconName, "ic_launcher", "ic_launcher_round"} : new String[]{"ic_launcher", "ic_launcher_round"}) { try { String path = "res/" + IC_DIRS[dir] + IC_CONFIGS[config] + "/" + name + ".xml"; @@ -91,7 +102,6 @@ public class AdaptiveIconProvider { parser = assetManager.openXmlResourceParser(path); } catch (Exception e) { e.printStackTrace(); - continue; } if (parser != null) { @@ -99,7 +109,7 @@ public class AdaptiveIconProvider { } } } - } + }*/ int backgroundRes = -1, foregroundRes = -1; if (parser != null) { @@ -146,10 +156,13 @@ public class AdaptiveIconProvider { } if (backgroundRes != -1) { + Log.d(TAG, "BackgroundRes: " + backgroundRes); + Log.d(TAG, "BackgroundResName: " + resources.getResourceName(backgroundRes)); try { background = ResourcesCompat.getDrawable(resources, backgroundRes, theme); } catch (Resources.NotFoundException e) { - try { + e.printStackTrace(); + /*try { background = ResourcesCompat.getDrawable(resources, resources.getIdentifier("ic_launcher_background", "mipmap", packageName), theme); @@ -160,7 +173,7 @@ public class AdaptiveIconProvider { packageName), theme); } catch (Resources.NotFoundException ignored) { } - } + }*/ } } @@ -168,7 +181,8 @@ public class AdaptiveIconProvider { try { foreground = ResourcesCompat.getDrawable(resources, foregroundRes, theme); } catch (Resources.NotFoundException e) { - try { + e.printStackTrace(); + /*try { foreground = ResourcesCompat.getDrawable(resources, resources.getIdentifier("ic_launcher_foreground", "mipmap", packageName), theme); @@ -179,7 +193,7 @@ public class AdaptiveIconProvider { packageName), theme); } catch (Resources.NotFoundException ignored) { } - } + }*/ } } } catch (Exception e) { diff --git a/app/src/main/java/foundation/e/blisslauncher/core/ColorExtractor.java b/app/src/main/java/foundation/e/blisslauncher/core/ColorExtractor.java new file mode 100644 index 0000000000..f3b4b69798 --- /dev/null +++ b/app/src/main/java/foundation/e/blisslauncher/core/ColorExtractor.java @@ -0,0 +1,178 @@ +package foundation.e.blisslauncher.core; + + +/* + * Copyright (C) 2017 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. + */ + +import android.graphics.Bitmap; +import android.graphics.Color; +import android.graphics.drawable.ColorDrawable; +import android.graphics.drawable.Drawable; +import android.util.SparseArray; + +import java.util.HashSet; +import java.util.Set; + +import kotlin.collections.ArraysKt; + +/** + * Utility class for extracting colors from a bitmap. + */ +public class ColorExtractor { + + private static final String TAG = "ColorExtractor"; + + public static int findDominantColorByHue(Bitmap bitmap) { + return findDominantColorByHue(bitmap, 20); + } + + /** + * This picks a dominant color, looking for high-saturation, high-value, repeated hues. + * + * @param bitmap The bitmap to scan + * @param samples The approximate max number of samples to use. + */ + public static int findDominantColorByHue(Bitmap bitmap, int samples) { + final int height = bitmap.getHeight(); + final int width = bitmap.getWidth(); + int sampleStride = (int) Math.sqrt((height * width) / samples); + if (sampleStride < 1) { + sampleStride = 1; + } + + // This is an out-param, for getting the hsv values for an rgb + float[] hsv = new float[3]; + + // First get the best hue, by creating a histogram over 360 hue buckets, + // where each pixel contributes a score weighted by saturation, value, and alpha. + float[] hueScoreHistogram = new float[360]; + float highScore = -1; + int bestHue = -1; + + int[] pixels = new int[samples]; + int pixelCount = 0; + + for (int y = 0; y < height; y += sampleStride) { + for (int x = 0; x < width; x += sampleStride) { + int argb = bitmap.getPixel(x, y); + int alpha = 0xFF & (argb >> 24); + if (alpha < 0x80) { + // Drop mostly-transparent pixels. + continue; + } + // Remove the alpha channel. + int rgb = argb | 0xFF000000; + Color.colorToHSV(rgb, hsv); + // Bucket colors by the 360 integer hues. + int hue = (int) hsv[0]; + if (hue < 0 || hue >= hueScoreHistogram.length) { + // Defensively avoid array bounds violations. + continue; + } + if (pixelCount < samples) { + pixels[pixelCount++] = rgb; + } + float score = hsv[1] * hsv[2]; + hueScoreHistogram[hue] += score; + if (hueScoreHistogram[hue] > highScore) { + highScore = hueScoreHistogram[hue]; + bestHue = hue; + } + } + } + + SparseArray rgbScores = new SparseArray<>(); + int bestColor = 0xff000000; + highScore = -1; + // Go back over the RGB colors that match the winning hue, + // creating a histogram of weighted s*v scores, for up to 100*100 [s,v] buckets. + // The highest-scoring RGB color wins. + for (int i = 0; i < pixelCount; i++) { + int rgb = pixels[i]; + Color.colorToHSV(rgb, hsv); + int hue = (int) hsv[0]; + if (hue == bestHue) { + float s = hsv[1]; + float v = hsv[2]; + int bucket = (int) (s * 100) + (int) (v * 10000); + // Score by cumulative saturation * value. + float score = s * v; + Float oldTotal = rgbScores.get(bucket); + float newTotal = oldTotal == null ? score : oldTotal + score; + rgbScores.put(bucket, newTotal); + if (newTotal > highScore) { + highScore = newTotal; + // All the colors in the winning bucket are very similar. Last in wins. + bestColor = rgb; + } + } + } + return bestColor; + } + + public static boolean isSingleColor(Drawable drawable, int color) { + if (drawable == null) return true; + final int testColor = posterize(color); + if (drawable instanceof ColorDrawable) { + return posterize(((ColorDrawable) drawable).getColor()) == testColor; + } + final Bitmap bitmap = Utilities.drawableToBitmap(drawable); + if (bitmap == null) { + return false; + } + final int height = bitmap.getHeight(); + final int width = bitmap.getWidth(); + + int[] pixels = new int[height * width]; + bitmap.getPixels(pixels, 0, width, 0, 0, width, height); + Set set = new HashSet<>(ArraysKt.asList(pixels)); + Integer[] distinctPixels = new Integer[set.size()]; + set.toArray(distinctPixels); + + for (int pixel : distinctPixels) { + if (testColor != posterize(pixel)) { + return false; + } + } + return true; + } + + private static final int MAGIC_NUMBER = 25; + + /* + * References: + * https://www.cs.umb.edu/~jreyes/csit114-fall-2007/project4/filters.html#posterize + * https://github.com/gitgraghu/image-processing/blob/master/src/Effects/Posterize.java + */ + public static int posterize(int rgb) { + int red = (0xff & (rgb >> 16)); + int green = (0xff & (rgb >> 8)); + int blue = (0xff & rgb); + red -= red % MAGIC_NUMBER; + green -= green % MAGIC_NUMBER; + blue -= blue % MAGIC_NUMBER; + if (red < 0) { + red = 0; + } + if (green < 0) { + green = 0; + } + if (blue < 0) { + blue = 0; + } + return red << 16 | green << 8 | blue; + } +} diff --git a/app/src/main/java/foundation/e/blisslauncher/core/IconsHandler.java b/app/src/main/java/foundation/e/blisslauncher/core/IconsHandler.java index 9f01de588a..c2b6abfab5 100644 --- a/app/src/main/java/foundation/e/blisslauncher/core/IconsHandler.java +++ b/app/src/main/java/foundation/e/blisslauncher/core/IconsHandler.java @@ -175,7 +175,8 @@ public class IconsHandler { // Search first in cache Drawable systemIcon = cacheGetDrawable(key); - if (systemIcon != null) { + if (systemIcon != null + && !activityInfo.getApplicationInfo().packageName.equalsIgnoreCase("com.app.restclient")) { return systemIcon; } @@ -184,14 +185,16 @@ public class IconsHandler { systemIcon = new AdaptiveIconDrawableCompat( ((AdaptiveIconDrawable) systemIcon).getBackground(), ((AdaptiveIconDrawable) systemIcon).getForeground()); + return systemIcon; } else { + // Icon is not adaptive, try to load using reflection. Drawable adaptiveIcon = new AdaptiveIconProvider().load(ctx, componentName.getPackageName()); if (adaptiveIcon != null) { systemIcon = adaptiveIcon; } else { - systemIcon = graphicsUtil.convertToRoundedCorner(ctx, - graphicsUtil.addBackground(systemIcon, false)); + // Failed to load adaptive icon, Generate an adaptive icon from app default icon. + systemIcon = new AdaptiveIconGenerator(ctx, getDefaultAppDrawable(activityInfo, userHandle)).getResult(); } } @@ -317,8 +320,7 @@ public class IconsHandler { } public Drawable convertIcon(Drawable icon) { - return graphicsUtil.convertToRoundedCorner(ctx, - graphicsUtil.addBackground(icon, false)); + return new AdaptiveIconGenerator(ctx, icon).getResult(); } /** diff --git a/app/src/main/java/foundation/e/blisslauncher/core/customviews/AdaptiveIconDrawableCompat.java b/app/src/main/java/foundation/e/blisslauncher/core/customviews/AdaptiveIconDrawableCompat.java index f3f6603c7c..844adbee1d 100755 --- a/app/src/main/java/foundation/e/blisslauncher/core/customviews/AdaptiveIconDrawableCompat.java +++ b/app/src/main/java/foundation/e/blisslauncher/core/customviews/AdaptiveIconDrawableCompat.java @@ -153,7 +153,7 @@ public class AdaptiveIconDrawableCompat extends Drawable implements Drawable.Cal mTransparentRegion = new Region(); } - @SuppressLint("PrivateApi") + @SuppressLint({"PrivateApi", "DiscouragedPrivateApi"}) private void initReflections() { try { Class pathParser = getClass().getClassLoader().loadClass("android.util.PathParser"); diff --git a/app/src/main/java/foundation/e/blisslauncher/core/utils/GraphicsUtil.java b/app/src/main/java/foundation/e/blisslauncher/core/utils/GraphicsUtil.java index 5fc02caba4..73353637ba 100755 --- a/app/src/main/java/foundation/e/blisslauncher/core/utils/GraphicsUtil.java +++ b/app/src/main/java/foundation/e/blisslauncher/core/utils/GraphicsUtil.java @@ -198,8 +198,6 @@ public class GraphicsUtil { if (Color.alpha(bitmap.getPixel(x, y)) == 255) { int color = bitmap.getPixel(x, y); colors.put(color, (colors.containsKey(color) ? colors.get(color) : 0) + 1); - } else if ((Color.alpha(bitmap.getPixel(x, y)) < 0xF9)) { - count++; } } } -- GitLab From 638e5da8d77a282ee5e7b9a7029bd822b7f8ff23 Mon Sep 17 00:00:00 2001 From: Amit Kumar Date: Tue, 12 May 2020 18:46:31 +0530 Subject: [PATCH 2/2] Change non-adaptive icon background color to 50% white --- .../core/AdaptiveIconGenerator.java | 10 ++++++ .../e/blisslauncher/core/IconsHandler.java | 3 +- .../AdaptiveIconDrawableCompat.java | 31 +++---------------- 3 files changed, 16 insertions(+), 28 deletions(-) diff --git a/app/src/main/java/foundation/e/blisslauncher/core/AdaptiveIconGenerator.java b/app/src/main/java/foundation/e/blisslauncher/core/AdaptiveIconGenerator.java index e2998917c3..1eccc03f74 100644 --- a/app/src/main/java/foundation/e/blisslauncher/core/AdaptiveIconGenerator.java +++ b/app/src/main/java/foundation/e/blisslauncher/core/AdaptiveIconGenerator.java @@ -39,6 +39,7 @@ public class AdaptiveIconGenerator { private boolean ranLoop; private boolean shouldWrap; private int backgroundColor = Color.WHITE; + private boolean useWhiteBackground = true; private boolean isFullBleed; private boolean noMixinNeeded; private boolean fullBleedChecked; @@ -163,6 +164,15 @@ public class AdaptiveIconGenerator { // return early if a mix-in isnt needed noMixinNeeded = !isFullBleed && !isBackgroundWhite && almostSquarish && transparentScore <= noMixinScore; + + // Currently, it's set to true so a white background is used for all the icons. + if(useWhiteBackground) { + //backgroundColor = Color.WHITE; + backgroundColor = Color.WHITE & 0x80FFFFFF; + onExitLoop(); + return; + } + if (isFullBleed || noMixinNeeded) { backgroundColor = bestRGB; onExitLoop(); diff --git a/app/src/main/java/foundation/e/blisslauncher/core/IconsHandler.java b/app/src/main/java/foundation/e/blisslauncher/core/IconsHandler.java index c2b6abfab5..83bd9fa9d9 100644 --- a/app/src/main/java/foundation/e/blisslauncher/core/IconsHandler.java +++ b/app/src/main/java/foundation/e/blisslauncher/core/IconsHandler.java @@ -175,8 +175,7 @@ public class IconsHandler { // Search first in cache Drawable systemIcon = cacheGetDrawable(key); - if (systemIcon != null - && !activityInfo.getApplicationInfo().packageName.equalsIgnoreCase("com.app.restclient")) { + if (systemIcon != null) { return systemIcon; } diff --git a/app/src/main/java/foundation/e/blisslauncher/core/customviews/AdaptiveIconDrawableCompat.java b/app/src/main/java/foundation/e/blisslauncher/core/customviews/AdaptiveIconDrawableCompat.java index 844adbee1d..549687e33a 100755 --- a/app/src/main/java/foundation/e/blisslauncher/core/customviews/AdaptiveIconDrawableCompat.java +++ b/app/src/main/java/foundation/e/blisslauncher/core/customviews/AdaptiveIconDrawableCompat.java @@ -366,7 +366,7 @@ public class AdaptiveIconDrawableCompat extends Drawable implements Drawable.Cal // mMaskBitmap bound [0, w] x [0, h] mCanvas.setBitmap(mMaskBitmap); mPaint.setShader(null); - mPaint.setColor(0xFFFFFFFF); + mPaint.setColor(Color.WHITE); mCanvas.drawPath(mMask, mPaint); // mMask bound [left, top, right, bottom] @@ -385,7 +385,7 @@ public class AdaptiveIconDrawableCompat extends Drawable implements Drawable.Cal } if (mLayersShader == null) { mCanvas.setBitmap(mLayersBitmap); - mCanvas.drawColor(Color.BLACK); + //mCanvas.drawColor(Color.BLACK); for (int i = 0; i < LayerState.N_CHILDREN; i++) { if (mLayerState.mChildren[i] == null) { continue; @@ -396,33 +396,12 @@ public class AdaptiveIconDrawableCompat extends Drawable implements Drawable.Cal } } mLayersShader = new BitmapShader(mLayersBitmap, TileMode.CLAMP, TileMode.CLAMP); - if (mUseMyUglyWorkaround) { - // TODO: remove this ugly and slow code - if (mMaskBitmap != null) { - int width = mLayersBitmap.getWidth(); - int height = mLayersBitmap.getHeight(); - int[] colors = new int[width * height]; - int[] alphas = new int[width * height]; - mLayersBitmap.getPixels(colors, 0, width, 0, 0, width, height); - mMaskBitmap.getPixels(alphas, 0, width, 0, 0, width, height); - int color, alpha, index; - for (int i = 0; i < width; i++) { - for (int j = 0; j < height; j++) { - index = i * height + j; - color = colors[index]; - alpha = alphas[index]; - colors[index] = color & 0x00FFFFFF | alpha & 0xFF000000; - } - } - mLayersBitmap.setPixels(colors, 0, width, 0, 0, width, height); - } - } else { - mPaint.setShader(mLayersShader); - } + mPaint.setShader(mLayersShader); } if (mMaskBitmap != null) { Rect bounds = getBounds(); - canvas.drawBitmap(mUseMyUglyWorkaround ? mLayersBitmap : mMaskBitmap, bounds.left, + //mPaint.setXfermode(new PorterDuffXfermode(Mode.SRC_IN)); + canvas.drawBitmap(mMaskBitmap, bounds.left, bounds.top, mPaint); } } -- GitLab