Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit e50102de authored by Android Build Coastguard Worker's avatar Android Build Coastguard Worker
Browse files

Snap for 13147095 from 550c9145 to 25Q3-release

Change-Id: Id68a73dbc1b56685dd357c34843ac62f512003a9
parents aa821005 550c9145
Loading
Loading
Loading
Loading
+8 −0
Original line number Diff line number Diff line
@@ -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"
+3 −0
Original line number Diff line number Diff line
@@ -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
+28 −18
Original line number Diff line number Diff line
@@ -92,9 +92,6 @@ public class BaseIconFactory implements AutoCloseable {

    protected IconThemeController mThemeController;

    @Nullable
    private IconNormalizer mNormalizer;

    @Nullable
    private ShadowGenerator mShadowGenerator;

@@ -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);
@@ -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() {
@@ -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;
@@ -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;
@@ -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();
@@ -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) {
@@ -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);
    }

    /**
@@ -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;
        }
+3 −0
Original line number Diff line number Diff line
@@ -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();
        }
    }
+2 −136
Original line number Diff line number Diff line
@@ -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;

@@ -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
@@ -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);
@@ -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) {
@@ -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.
@@ -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();
@@ -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