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

Commit 905262c1 authored by Sunny Goyal's avatar Sunny Goyal
Browse files

Adding utility method to get adaptive icon scale

Change-Id: I5ff190c3b794bb13309375782ccd420e85b59091
parent 1bdb0f40
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -78,7 +78,7 @@ public class BaseIconFactory implements AutoCloseable {

    public IconNormalizer getNormalizer() {
        if (mNormalizer == null) {
            mNormalizer = new IconNormalizer(mContext, mIconBitmapSize);
            mNormalizer = new IconNormalizer(mIconBitmapSize);
        }
        return mNormalizer;
    }
+13 −0
Original line number Diff line number Diff line
@@ -16,6 +16,9 @@
package com.android.launcher3.icons;

import android.graphics.Bitmap;
import android.graphics.Rect;
import android.graphics.Region;
import android.graphics.RegionIterator;
import android.util.Log;

import java.io.ByteArrayOutputStream;
@@ -60,4 +63,14 @@ public class GraphicsUtils {
            return null;
        }
    }

    public static int getArea(Region r) {
        RegionIterator itr = new RegionIterator(r);
        int area = 0;
        Rect tempRect = new Rect();
        while (itr.next(tempRect)) {
            area += tempRect.width() * tempRect.height();
        }
        return area;
    }
}
+59 −27
Original line number Diff line number Diff line
@@ -16,14 +16,18 @@

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.Path;
import android.graphics.Rect;
import android.graphics.RectF;
import android.graphics.Region;
import android.graphics.drawable.AdaptiveIconDrawable;
import android.graphics.drawable.Drawable;
import android.os.Build;

import java.nio.ByteBuffer;

@@ -57,7 +61,7 @@ public class IconNormalizer {
    private final Canvas mCanvas;
    private final byte[] mPixels;

    private final Rect mAdaptiveIconBounds;
    private final RectF mAdaptiveIconBounds;
    private float mAdaptiveIconScale;

    // for each y, stores the position of the leftmost x and the rightmost x
@@ -66,7 +70,7 @@ public class IconNormalizer {
    private final Rect mBounds;

    /** package private **/
    IconNormalizer(Context context, int iconBitmapSize) {
    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);
@@ -75,11 +79,53 @@ public class IconNormalizer {
        mLeftBorder = new float[mMaxSize];
        mRightBorder = new float[mMaxSize];
        mBounds = new Rect();
        mAdaptiveIconBounds = new Rect();
        mAdaptiveIconBounds = new RectF();

        mAdaptiveIconScale = SCALE_NOT_INITIALIZED;
    }

    private static float getScale(float hullArea, float boundingArea, float fullArea) {
        float hullByRect = hullArea / boundingArea;
        float scaleRequired;
        if (hullByRect < CIRCLE_AREA_BY_RECT) {
            scaleRequired = MAX_CIRCLE_AREA_FACTOR;
        } else {
            scaleRequired = MAX_SQUARE_AREA_FACTOR + LINEAR_SCALE_SLOPE * (1 - hullByRect);
        }

        float areaScale = hullArea / fullArea;
        // Use sqrt of the final ratio as the images is scaled across both width and height.
        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, @Nullable RectF outBounds) {
        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));

        Rect hullBounds = region.getBounds();
        int hullArea = GraphicsUtils.getArea(region);

        if (outBounds != null) {
            float sizeF = size;
            outBounds.set(
                    hullBounds.left / sizeF,
                    hullBounds.top / sizeF,
                    1 - (hullBounds.right / sizeF),
                    1 - (hullBounds.bottom / sizeF));
        }
        d.setBounds(tmpBounds);
        return getScale(hullArea, hullArea, size * size);
    }

    /**
     * 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.
@@ -96,13 +142,14 @@ public class IconNormalizer {
     */
    public synchronized float getScale(@NonNull Drawable d, @Nullable RectF outBounds) {
        if (BaseIconFactory.ATLEAST_OREO && d instanceof AdaptiveIconDrawable) {
            if (mAdaptiveIconScale != SCALE_NOT_INITIALIZED) {
            if (mAdaptiveIconScale == SCALE_NOT_INITIALIZED) {
                mAdaptiveIconScale = normalizeAdaptiveIcon(d, mMaxSize, mAdaptiveIconBounds);
            }
            if (outBounds != null) {
                outBounds.set(mAdaptiveIconBounds);
            }
            return mAdaptiveIconScale;
        }
        }
        int width = d.getIntrinsicWidth();
        int height = d.getIntrinsicHeight();
        if (width <= 0 || height <= 0) {
@@ -184,16 +231,6 @@ public class IconNormalizer {
            area += mRightBorder[y] - mLeftBorder[y] + 1;
        }

        // Area of the rectangle required to fit the convex hull
        float rectArea = (bottomY + 1 - topY) * (rightX + 1 - leftX);
        float hullByRect = area / rectArea;

        float scaleRequired;
        if (hullByRect < CIRCLE_AREA_BY_RECT) {
            scaleRequired = MAX_CIRCLE_AREA_FACTOR;
        } else {
            scaleRequired = MAX_SQUARE_AREA_FACTOR + LINEAR_SCALE_SLOPE * (1 - hullByRect);
        }
        mBounds.left = leftX;
        mBounds.right = rightX;

@@ -205,15 +242,10 @@ public class IconNormalizer {
                    1 - ((float) mBounds.right) / width,
                    1 - ((float) mBounds.bottom) / height);
        }
        float areaScale = area / (width * height);
        // Use sqrt of the final ratio as the images is scaled across both width and height.
        float scale = areaScale > scaleRequired ? (float) Math.sqrt(scaleRequired / areaScale) : 1;
        if (BaseIconFactory.ATLEAST_OREO && d instanceof AdaptiveIconDrawable &&
                mAdaptiveIconScale == SCALE_NOT_INITIALIZED) {
            mAdaptiveIconScale = scale;
            mAdaptiveIconBounds.set(mBounds);
        }
        return scale;

        // Area of the rectangle required to fit the convex hull
        float rectArea = (bottomY + 1 - topY) * (rightX + 1 - leftX);
        return getScale(area, rectArea, width * height);
    }

    /**
+2 −2
Original line number Diff line number Diff line
@@ -42,7 +42,7 @@ import android.util.Xml;
import android.view.Display;
import android.view.WindowManager;

import com.android.launcher3.folder.FolderShape;
import com.android.launcher3.graphics.IconShape;
import com.android.launcher3.util.ConfigMonitor;
import com.android.launcher3.util.IntArray;
import com.android.launcher3.util.MainThreadInitializedObject;
@@ -304,7 +304,7 @@ public class InvariantDeviceProfile {
            changeFlags |= CHANGE_FLAG_ICON_PARAMS;
        }
        if (!iconShapePath.equals(oldProfile.iconShapePath)) {
            FolderShape.init(context);
            IconShape.init(context);
        }

        apply(context, changeFlags);
+2 −2
Original line number Diff line number Diff line
@@ -19,7 +19,7 @@ package com.android.launcher3;
import android.content.Context;

import com.android.launcher3.config.FeatureFlags;
import com.android.launcher3.folder.FolderShape;
import com.android.launcher3.graphics.IconShape;
import com.android.launcher3.logging.FileLog;
import com.android.launcher3.util.ResourceBasedOverride;

@@ -38,6 +38,6 @@ public class MainProcessInitializer implements ResourceBasedOverride {
        FileLog.setDir(context.getApplicationContext().getFilesDir());
        FeatureFlags.initialize(context);
        SessionCommitReceiver.applyDefaultUserPrefs(context);
        FolderShape.init(context);
        IconShape.init(context);
    }
}
Loading