Loading aconfig/systemui.aconfig +8 −0 Original line number Diff line number Diff line Loading @@ -129,6 +129,14 @@ flag { bug: "334125919" } flag { name: "use_preferred_image_editor" namespace: "systemui" description: "Prefer the editor in config_preferredScreenshotEditor if component is present/enabled on the system" bug: "391401141" } flag { name: "enable_lpp_squeeze_effect" namespace: "systemui" Loading iconloaderlib/res/values/config.xml +3 −0 Original line number Diff line number Diff line Loading @@ -27,4 +27,7 @@ <string name="calendar_component_name" translatable="false"></string> <string name="clock_component_name" translatable="false"></string> <!-- Configures whether to enable forced theme icon, disabled by default --> <bool name="enable_forced_themed_icon">false</bool> </resources> No newline at end of file iconloaderlib/src/com/android/launcher3/icons/BaseIconFactory.java +28 −18 Original line number Diff line number Diff line Loading @@ -92,9 +92,6 @@ public class BaseIconFactory implements AutoCloseable { protected IconThemeController mThemeController; @Nullable private IconNormalizer mNormalizer; @Nullable private ShadowGenerator mShadowGenerator; Loading @@ -105,6 +102,8 @@ public class BaseIconFactory implements AutoCloseable { private static int PLACEHOLDER_BACKGROUND_COLOR = Color.rgb(245, 245, 245); private final boolean mShouldForceThemeIcon; protected BaseIconFactory(Context context, int fullResIconDpi, int iconBitmapSize, boolean unused) { this(context, fullResIconDpi, iconBitmapSize); Loading @@ -121,6 +120,9 @@ public class BaseIconFactory implements AutoCloseable { mCanvas = new Canvas(); mCanvas.setDrawFilter(new PaintFlagsDrawFilter(DITHER_FLAG, FILTER_BITMAP_FLAG)); clear(); mShouldForceThemeIcon = mContext.getResources().getBoolean( R.bool.enable_forced_themed_icon); } protected void clear() { Loading @@ -135,14 +137,6 @@ public class BaseIconFactory implements AutoCloseable { return mShadowGenerator; } @NonNull public IconNormalizer getNormalizer() { if (mNormalizer == null) { mNormalizer = new IconNormalizer(mContext, mIconBitmapSize); } return mNormalizer; } @Nullable public IconThemeController getThemeController() { return mThemeController; Loading Loading @@ -242,8 +236,14 @@ public class BaseIconFactory implements AutoCloseable { if (adaptiveIcon instanceof Extender extender) { info = extender.getExtendedInfo(bitmap, color, this, scale[0]); } else if (IconProvider.ATLEAST_T && mThemeController != null && adaptiveIcon != null) { info.setThemedBitmap(mThemeController.createThemedBitmap( adaptiveIcon, info, this, options == null ? null : options.mSourceHint)); info.setThemedBitmap( mThemeController.createThemedBitmap( adaptiveIcon, info, this, options == null ? null : options.mSourceHint ) ); } info = info.withFlags(getBitmapFlagOp(options)); return info; Loading @@ -268,6 +268,13 @@ public class BaseIconFactory implements AutoCloseable { return op; } /** * @return True if forced theme icon is enabled */ public boolean shouldForceThemeIcon() { return mShouldForceThemeIcon; } @NonNull protected UserIconInfo getUserInfo(@NonNull UserHandle user) { int key = user.hashCode(); Loading @@ -287,10 +294,14 @@ public class BaseIconFactory implements AutoCloseable { } @NonNull protected Path getShapePath(AdaptiveIconDrawable drawable, Rect iconBounds) { public Path getShapePath(AdaptiveIconDrawable drawable, Rect iconBounds) { return drawable.getIconMask(); } public float getIconScale() { return 1f; } @NonNull public Bitmap getWhiteShadowLayer() { if (mWhiteShadowLayer == null) { Loading Loading @@ -322,9 +333,8 @@ public class BaseIconFactory implements AutoCloseable { return null; } AdaptiveIconDrawable adaptiveIcon = wrapToAdaptiveIcon(icon); outScale[0] = getNormalizer().getScale(adaptiveIcon); return adaptiveIcon; outScale[0] = IconNormalizer.ICON_VISIBLE_AREA_FACTOR; return wrapToAdaptiveIcon(icon); } /** Loading Loading @@ -356,7 +366,7 @@ public class BaseIconFactory implements AutoCloseable { AdaptiveIconDrawable dr = new AdaptiveIconDrawable( new ColorDrawable(mWrapperBackgroundColor), foreground); dr.setBounds(0, 0, 1, 1); float scale = getNormalizer().getScale(icon); float scale = new IconNormalizer(mIconBitmapSize).getScale(icon); foreground.setDrawable(createScaledDrawable(icon, scale * LEGACY_ICON_SCALE)); return dr; } Loading iconloaderlib/src/com/android/launcher3/icons/FastBitmapDrawable.java +3 −0 Original line number Diff line number Diff line Loading @@ -301,6 +301,9 @@ public class FastBitmapDrawable extends Drawable implements Drawable.Callback { public void setIsDisabled(boolean isDisabled) { if (mIsDisabled != isDisabled) { mIsDisabled = isDisabled; if (mBadge instanceof FastBitmapDrawable fbd) { fbd.setIsDisabled(isDisabled); } updateFilter(); } } Loading iconloaderlib/src/com/android/launcher3/icons/IconNormalizer.java +2 −136 Original line number Diff line number Diff line Loading @@ -16,22 +16,12 @@ package com.android.launcher3.icons; import android.annotation.TargetApi; import android.content.Context; import android.graphics.Bitmap; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Matrix; import android.graphics.Paint; import android.graphics.Path; import android.graphics.PorterDuff; import android.graphics.PorterDuffXfermode; import android.graphics.Rect; import android.graphics.Region; import android.graphics.drawable.AdaptiveIconDrawable; import android.graphics.drawable.Drawable; import android.os.Build; import android.util.Log; import androidx.annotation.NonNull; Loading @@ -39,8 +29,6 @@ import java.nio.ByteBuffer; public class IconNormalizer { private static final String TAG = "IconNormalizer"; private static final boolean DEBUG = false; // Ratio of icon visible area to full icon size for a square shaped icon private static final float MAX_SQUARE_AREA_FACTOR = 375.0f / 576; // Ratio of icon visible area to full icon size for a circular shaped icon Loading @@ -54,32 +42,21 @@ public class IconNormalizer { private static final int MIN_VISIBLE_ALPHA = 40; // Shape detection related constants private static final float BOUND_RATIO_MARGIN = .05f; private static final float PIXEL_DIFF_PERCENTAGE_THRESHOLD = 0.005f; private static final float SCALE_NOT_INITIALIZED = 0; // Ratio of the diameter of an normalized circular icon to the actual icon size. public static final float ICON_VISIBLE_AREA_FACTOR = 0.92f; private final int mMaxSize; private final Bitmap mBitmap; private final Canvas mCanvas; private final Paint mPaintMaskShape; private final Paint mPaintMaskShapeOutline; private final byte[] mPixels; private float mAdaptiveIconScale; // for each y, stores the position of the leftmost x and the rightmost x private final float[] mLeftBorder; private final float[] mRightBorder; private final Rect mBounds; private final Path mShapePath; private final Matrix mMatrix; /** package private **/ IconNormalizer(Context context, int iconBitmapSize) { public IconNormalizer(int iconBitmapSize) { // Use twice the icon size as maximum size to avoid scaling down twice. mMaxSize = iconBitmapSize * 2; mBitmap = Bitmap.createBitmap(mMaxSize, mMaxSize, Bitmap.Config.ALPHA_8); Loading @@ -88,22 +65,6 @@ public class IconNormalizer { mLeftBorder = new float[mMaxSize]; mRightBorder = new float[mMaxSize]; mBounds = new Rect(); mPaintMaskShape = new Paint(); mPaintMaskShape.setColor(Color.RED); mPaintMaskShape.setStyle(Paint.Style.FILL); mPaintMaskShape.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.XOR)); mPaintMaskShapeOutline = new Paint(); mPaintMaskShapeOutline.setStrokeWidth( 2 * context.getResources().getDisplayMetrics().density); mPaintMaskShapeOutline.setStyle(Paint.Style.STROKE); mPaintMaskShapeOutline.setColor(Color.BLACK); mPaintMaskShapeOutline.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR)); mShapePath = new Path(); mMatrix = new Matrix(); mAdaptiveIconScale = SCALE_NOT_INITIALIZED; } private static float getScale(float hullArea, float boundingArea, float fullArea) { Loading @@ -120,90 +81,6 @@ public class IconNormalizer { return areaScale > scaleRequired ? (float) Math.sqrt(scaleRequired / areaScale) : 1; } /** * @param d Should be AdaptiveIconDrawable * @param size Canvas size to use */ @TargetApi(Build.VERSION_CODES.O) public static float normalizeAdaptiveIcon(Drawable d, int size) { Rect tmpBounds = new Rect(d.getBounds()); d.setBounds(0, 0, size, size); Path path = ((AdaptiveIconDrawable) d).getIconMask(); Region region = new Region(); region.setPath(path, new Region(0, 0, size, size)); int hullArea = GraphicsUtils.getArea(region); d.setBounds(tmpBounds); return getScale(hullArea, hullArea, size * size); } /** * Returns if the shape of the icon is same as the path. * For this method to work, the shape path bounds should be in [0,1]x[0,1] bounds. */ private boolean isShape(Path maskPath) { // Condition1: // If width and height of the path not close to a square, then the icon shape is // not same as the mask shape. float iconRatio = ((float) mBounds.width()) / mBounds.height(); if (Math.abs(iconRatio - 1) > BOUND_RATIO_MARGIN) { if (DEBUG) { Log.d(TAG, "Not same as mask shape because width != height. " + iconRatio); } return false; } // Condition 2: // Actual icon (white) and the fitted shape (e.g., circle)(red) XOR operation // should generate transparent image, if the actual icon is equivalent to the shape. // Fit the shape within the icon's bounding box mMatrix.reset(); mMatrix.setScale(mBounds.width(), mBounds.height()); mMatrix.postTranslate(mBounds.left, mBounds.top); maskPath.transform(mMatrix, mShapePath); // XOR operation mCanvas.drawPath(mShapePath, mPaintMaskShape); // DST_OUT operation around the mask path outline mCanvas.drawPath(mShapePath, mPaintMaskShapeOutline); // Check if the result is almost transparent return isTransparentBitmap(); } /** * Used to determine if certain the bitmap is transparent. */ private boolean isTransparentBitmap() { ByteBuffer buffer = ByteBuffer.wrap(mPixels); buffer.rewind(); mBitmap.copyPixelsToBuffer(buffer); int y = mBounds.top; // buffer position int index = y * mMaxSize; // buffer shift after every row, width of buffer = mMaxSize int rowSizeDiff = mMaxSize - mBounds.right; int sum = 0; for (; y < mBounds.bottom; y++) { index += mBounds.left; for (int x = mBounds.left; x < mBounds.right; x++) { if ((mPixels[index] & 0xFF) > MIN_VISIBLE_ALPHA) { sum++; } index++; } index += rowSizeDiff; } float percentageDiffPixels = ((float) sum) / (mBounds.width() * mBounds.height()); return percentageDiffPixels < PIXEL_DIFF_PERCENTAGE_THRESHOLD; } /** * Returns the amount by which the {@param d} should be scaled (in both dimensions) so that it * matches the design guidelines for a launcher icon. Loading @@ -218,10 +95,7 @@ public class IconNormalizer { */ public synchronized float getScale(@NonNull Drawable d) { if (d instanceof AdaptiveIconDrawable) { if (mAdaptiveIconScale == SCALE_NOT_INITIALIZED) { mAdaptiveIconScale = normalizeAdaptiveIcon(d, mMaxSize); } return mAdaptiveIconScale; return ICON_VISIBLE_AREA_FACTOR; } int width = d.getIntrinsicWidth(); int height = d.getIntrinsicHeight(); Loading Loading @@ -368,12 +242,4 @@ public class IconNormalizer { last = i; } } /** * @return The diameter of the normalized circle that fits inside of the square (size x size). */ public static int getNormalizedCircleSize(int size) { float area = size * size * MAX_CIRCLE_AREA_FACTOR; return (int) Math.round(Math.sqrt((4 * area) / Math.PI)); } } Loading
aconfig/systemui.aconfig +8 −0 Original line number Diff line number Diff line Loading @@ -129,6 +129,14 @@ flag { bug: "334125919" } flag { name: "use_preferred_image_editor" namespace: "systemui" description: "Prefer the editor in config_preferredScreenshotEditor if component is present/enabled on the system" bug: "391401141" } flag { name: "enable_lpp_squeeze_effect" namespace: "systemui" Loading
iconloaderlib/res/values/config.xml +3 −0 Original line number Diff line number Diff line Loading @@ -27,4 +27,7 @@ <string name="calendar_component_name" translatable="false"></string> <string name="clock_component_name" translatable="false"></string> <!-- Configures whether to enable forced theme icon, disabled by default --> <bool name="enable_forced_themed_icon">false</bool> </resources> No newline at end of file
iconloaderlib/src/com/android/launcher3/icons/BaseIconFactory.java +28 −18 Original line number Diff line number Diff line Loading @@ -92,9 +92,6 @@ public class BaseIconFactory implements AutoCloseable { protected IconThemeController mThemeController; @Nullable private IconNormalizer mNormalizer; @Nullable private ShadowGenerator mShadowGenerator; Loading @@ -105,6 +102,8 @@ public class BaseIconFactory implements AutoCloseable { private static int PLACEHOLDER_BACKGROUND_COLOR = Color.rgb(245, 245, 245); private final boolean mShouldForceThemeIcon; protected BaseIconFactory(Context context, int fullResIconDpi, int iconBitmapSize, boolean unused) { this(context, fullResIconDpi, iconBitmapSize); Loading @@ -121,6 +120,9 @@ public class BaseIconFactory implements AutoCloseable { mCanvas = new Canvas(); mCanvas.setDrawFilter(new PaintFlagsDrawFilter(DITHER_FLAG, FILTER_BITMAP_FLAG)); clear(); mShouldForceThemeIcon = mContext.getResources().getBoolean( R.bool.enable_forced_themed_icon); } protected void clear() { Loading @@ -135,14 +137,6 @@ public class BaseIconFactory implements AutoCloseable { return mShadowGenerator; } @NonNull public IconNormalizer getNormalizer() { if (mNormalizer == null) { mNormalizer = new IconNormalizer(mContext, mIconBitmapSize); } return mNormalizer; } @Nullable public IconThemeController getThemeController() { return mThemeController; Loading Loading @@ -242,8 +236,14 @@ public class BaseIconFactory implements AutoCloseable { if (adaptiveIcon instanceof Extender extender) { info = extender.getExtendedInfo(bitmap, color, this, scale[0]); } else if (IconProvider.ATLEAST_T && mThemeController != null && adaptiveIcon != null) { info.setThemedBitmap(mThemeController.createThemedBitmap( adaptiveIcon, info, this, options == null ? null : options.mSourceHint)); info.setThemedBitmap( mThemeController.createThemedBitmap( adaptiveIcon, info, this, options == null ? null : options.mSourceHint ) ); } info = info.withFlags(getBitmapFlagOp(options)); return info; Loading @@ -268,6 +268,13 @@ public class BaseIconFactory implements AutoCloseable { return op; } /** * @return True if forced theme icon is enabled */ public boolean shouldForceThemeIcon() { return mShouldForceThemeIcon; } @NonNull protected UserIconInfo getUserInfo(@NonNull UserHandle user) { int key = user.hashCode(); Loading @@ -287,10 +294,14 @@ public class BaseIconFactory implements AutoCloseable { } @NonNull protected Path getShapePath(AdaptiveIconDrawable drawable, Rect iconBounds) { public Path getShapePath(AdaptiveIconDrawable drawable, Rect iconBounds) { return drawable.getIconMask(); } public float getIconScale() { return 1f; } @NonNull public Bitmap getWhiteShadowLayer() { if (mWhiteShadowLayer == null) { Loading Loading @@ -322,9 +333,8 @@ public class BaseIconFactory implements AutoCloseable { return null; } AdaptiveIconDrawable adaptiveIcon = wrapToAdaptiveIcon(icon); outScale[0] = getNormalizer().getScale(adaptiveIcon); return adaptiveIcon; outScale[0] = IconNormalizer.ICON_VISIBLE_AREA_FACTOR; return wrapToAdaptiveIcon(icon); } /** Loading Loading @@ -356,7 +366,7 @@ public class BaseIconFactory implements AutoCloseable { AdaptiveIconDrawable dr = new AdaptiveIconDrawable( new ColorDrawable(mWrapperBackgroundColor), foreground); dr.setBounds(0, 0, 1, 1); float scale = getNormalizer().getScale(icon); float scale = new IconNormalizer(mIconBitmapSize).getScale(icon); foreground.setDrawable(createScaledDrawable(icon, scale * LEGACY_ICON_SCALE)); return dr; } Loading
iconloaderlib/src/com/android/launcher3/icons/FastBitmapDrawable.java +3 −0 Original line number Diff line number Diff line Loading @@ -301,6 +301,9 @@ public class FastBitmapDrawable extends Drawable implements Drawable.Callback { public void setIsDisabled(boolean isDisabled) { if (mIsDisabled != isDisabled) { mIsDisabled = isDisabled; if (mBadge instanceof FastBitmapDrawable fbd) { fbd.setIsDisabled(isDisabled); } updateFilter(); } } Loading
iconloaderlib/src/com/android/launcher3/icons/IconNormalizer.java +2 −136 Original line number Diff line number Diff line Loading @@ -16,22 +16,12 @@ package com.android.launcher3.icons; import android.annotation.TargetApi; import android.content.Context; import android.graphics.Bitmap; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Matrix; import android.graphics.Paint; import android.graphics.Path; import android.graphics.PorterDuff; import android.graphics.PorterDuffXfermode; import android.graphics.Rect; import android.graphics.Region; import android.graphics.drawable.AdaptiveIconDrawable; import android.graphics.drawable.Drawable; import android.os.Build; import android.util.Log; import androidx.annotation.NonNull; Loading @@ -39,8 +29,6 @@ import java.nio.ByteBuffer; public class IconNormalizer { private static final String TAG = "IconNormalizer"; private static final boolean DEBUG = false; // Ratio of icon visible area to full icon size for a square shaped icon private static final float MAX_SQUARE_AREA_FACTOR = 375.0f / 576; // Ratio of icon visible area to full icon size for a circular shaped icon Loading @@ -54,32 +42,21 @@ public class IconNormalizer { private static final int MIN_VISIBLE_ALPHA = 40; // Shape detection related constants private static final float BOUND_RATIO_MARGIN = .05f; private static final float PIXEL_DIFF_PERCENTAGE_THRESHOLD = 0.005f; private static final float SCALE_NOT_INITIALIZED = 0; // Ratio of the diameter of an normalized circular icon to the actual icon size. public static final float ICON_VISIBLE_AREA_FACTOR = 0.92f; private final int mMaxSize; private final Bitmap mBitmap; private final Canvas mCanvas; private final Paint mPaintMaskShape; private final Paint mPaintMaskShapeOutline; private final byte[] mPixels; private float mAdaptiveIconScale; // for each y, stores the position of the leftmost x and the rightmost x private final float[] mLeftBorder; private final float[] mRightBorder; private final Rect mBounds; private final Path mShapePath; private final Matrix mMatrix; /** package private **/ IconNormalizer(Context context, int iconBitmapSize) { public IconNormalizer(int iconBitmapSize) { // Use twice the icon size as maximum size to avoid scaling down twice. mMaxSize = iconBitmapSize * 2; mBitmap = Bitmap.createBitmap(mMaxSize, mMaxSize, Bitmap.Config.ALPHA_8); Loading @@ -88,22 +65,6 @@ public class IconNormalizer { mLeftBorder = new float[mMaxSize]; mRightBorder = new float[mMaxSize]; mBounds = new Rect(); mPaintMaskShape = new Paint(); mPaintMaskShape.setColor(Color.RED); mPaintMaskShape.setStyle(Paint.Style.FILL); mPaintMaskShape.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.XOR)); mPaintMaskShapeOutline = new Paint(); mPaintMaskShapeOutline.setStrokeWidth( 2 * context.getResources().getDisplayMetrics().density); mPaintMaskShapeOutline.setStyle(Paint.Style.STROKE); mPaintMaskShapeOutline.setColor(Color.BLACK); mPaintMaskShapeOutline.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR)); mShapePath = new Path(); mMatrix = new Matrix(); mAdaptiveIconScale = SCALE_NOT_INITIALIZED; } private static float getScale(float hullArea, float boundingArea, float fullArea) { Loading @@ -120,90 +81,6 @@ public class IconNormalizer { return areaScale > scaleRequired ? (float) Math.sqrt(scaleRequired / areaScale) : 1; } /** * @param d Should be AdaptiveIconDrawable * @param size Canvas size to use */ @TargetApi(Build.VERSION_CODES.O) public static float normalizeAdaptiveIcon(Drawable d, int size) { Rect tmpBounds = new Rect(d.getBounds()); d.setBounds(0, 0, size, size); Path path = ((AdaptiveIconDrawable) d).getIconMask(); Region region = new Region(); region.setPath(path, new Region(0, 0, size, size)); int hullArea = GraphicsUtils.getArea(region); d.setBounds(tmpBounds); return getScale(hullArea, hullArea, size * size); } /** * Returns if the shape of the icon is same as the path. * For this method to work, the shape path bounds should be in [0,1]x[0,1] bounds. */ private boolean isShape(Path maskPath) { // Condition1: // If width and height of the path not close to a square, then the icon shape is // not same as the mask shape. float iconRatio = ((float) mBounds.width()) / mBounds.height(); if (Math.abs(iconRatio - 1) > BOUND_RATIO_MARGIN) { if (DEBUG) { Log.d(TAG, "Not same as mask shape because width != height. " + iconRatio); } return false; } // Condition 2: // Actual icon (white) and the fitted shape (e.g., circle)(red) XOR operation // should generate transparent image, if the actual icon is equivalent to the shape. // Fit the shape within the icon's bounding box mMatrix.reset(); mMatrix.setScale(mBounds.width(), mBounds.height()); mMatrix.postTranslate(mBounds.left, mBounds.top); maskPath.transform(mMatrix, mShapePath); // XOR operation mCanvas.drawPath(mShapePath, mPaintMaskShape); // DST_OUT operation around the mask path outline mCanvas.drawPath(mShapePath, mPaintMaskShapeOutline); // Check if the result is almost transparent return isTransparentBitmap(); } /** * Used to determine if certain the bitmap is transparent. */ private boolean isTransparentBitmap() { ByteBuffer buffer = ByteBuffer.wrap(mPixels); buffer.rewind(); mBitmap.copyPixelsToBuffer(buffer); int y = mBounds.top; // buffer position int index = y * mMaxSize; // buffer shift after every row, width of buffer = mMaxSize int rowSizeDiff = mMaxSize - mBounds.right; int sum = 0; for (; y < mBounds.bottom; y++) { index += mBounds.left; for (int x = mBounds.left; x < mBounds.right; x++) { if ((mPixels[index] & 0xFF) > MIN_VISIBLE_ALPHA) { sum++; } index++; } index += rowSizeDiff; } float percentageDiffPixels = ((float) sum) / (mBounds.width() * mBounds.height()); return percentageDiffPixels < PIXEL_DIFF_PERCENTAGE_THRESHOLD; } /** * Returns the amount by which the {@param d} should be scaled (in both dimensions) so that it * matches the design guidelines for a launcher icon. Loading @@ -218,10 +95,7 @@ public class IconNormalizer { */ public synchronized float getScale(@NonNull Drawable d) { if (d instanceof AdaptiveIconDrawable) { if (mAdaptiveIconScale == SCALE_NOT_INITIALIZED) { mAdaptiveIconScale = normalizeAdaptiveIcon(d, mMaxSize); } return mAdaptiveIconScale; return ICON_VISIBLE_AREA_FACTOR; } int width = d.getIntrinsicWidth(); int height = d.getIntrinsicHeight(); Loading Loading @@ -368,12 +242,4 @@ public class IconNormalizer { last = i; } } /** * @return The diameter of the normalized circle that fits inside of the square (size x size). */ public static int getNormalizedCircleSize(int size) { float area = size * size * MAX_CIRCLE_AREA_FACTOR; return (int) Math.round(Math.sqrt((4 * area) / Math.PI)); } }