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

Commit 71469725 authored by Treehugger Robot's avatar Treehugger Robot Committed by Android (Google) Code Review
Browse files

Merge "Fixing incorrect shadow size when generating IconShape" into main

parents 1fea2b29 4b3bca9d
Loading
Loading
Loading
Loading
+28 −25
Original line number Diff line number Diff line
@@ -10,7 +10,6 @@ import static com.android.launcher3.icons.BitmapInfo.FLAG_FULL_BLEED;
import static com.android.launcher3.icons.BitmapInfo.FLAG_INSTANT;
import static com.android.launcher3.icons.GraphicsUtils.generateIconShape;
import static com.android.launcher3.icons.IconNormalizer.ICON_VISIBLE_AREA_FACTOR;
import static com.android.launcher3.icons.ShadowGenerator.BLUR_FACTOR;

import static java.lang.annotation.RetentionPolicy.SOURCE;

@@ -446,35 +445,39 @@ public class BaseIconFactory implements AutoCloseable {
            @Nullable Bitmap targetBitmap, boolean isFullBleed) {
        final int size = mIconBitmapSize;
        mOldBounds.set(icon.getBounds());
        boolean isFullBleedEnabled = isFullBleed
                && Flags.enableLauncherIconShapes();
        if (icon instanceof AdaptiveIconDrawable aid) {
            // We are ignoring KEY_SHADOW_DISTANCE because regular icons ignore this at the
            // moment b/298203449
            int offset = isFullBleedEnabled
                    ? 0
                    : Math.max((int) Math.ceil(BLUR_FACTOR * size),
                            Math.round(size * (1 - scale) / 2));
            // b/211896569: AdaptiveIconDrawable do not work properly for non top-left bounds
            int newBounds = size - offset * 2;
            icon.setBounds(0, 0, newBounds, newBounds);
            int count = canvas.save();
            canvas.translate(offset, offset);

            if ((bitmapGenerationMode == MODE_WITH_SHADOW
                    || bitmapGenerationMode == MODE_HARDWARE_WITH_SHADOW)
                    && !isFullBleedEnabled) {
                getShadowGenerator().addPathShadow(aid.getIconMask(), canvas);
            }
        if (icon instanceof AdaptiveIconDrawable aid) {
            icon.setBounds(0, 0, size, size);
            if (icon instanceof Extender extender) {
                extender.drawForPersistence();
            }

            drawAdaptiveIcon(canvas, aid, isFullBleedEnabled, getShapePath(aid, icon.getBounds()));
            canvas.restoreToCount(count);
            if (isFullBleed && Flags.enableLauncherIconShapes()) {
                canvas.drawColor(Color.BLACK);
                if (aid.getBackground() != null) {
                    aid.getBackground().draw(canvas);
                }
                if (aid.getForeground() != null) {
                    aid.getForeground().draw(canvas);
                }
            } else {
                GraphicsUtils.resizeToContentSize(canvas, icon.getBounds(), size, size, c -> {
                    if ((bitmapGenerationMode == MODE_WITH_SHADOW
                            || bitmapGenerationMode == MODE_HARDWARE_WITH_SHADOW)) {
                        getShadowGenerator().addPathShadow(aid.getIconMask(), c);
                    }
                    boolean shouldDrawDefaultShape = !isFullBleed && mDrawFullBleedIcons;
                    // TODO: b/421884219 Temporarily keep old implementation until migrated
                    if (shouldDrawDefaultShape) {
                        // New Icon shapes path, used for non-full bleed icons
                        icon.draw(canvas);
                    } else {
                        drawShapedAdaptiveIcon(canvas, aid, getShapePath(aid, icon.getBounds()));
                    }
                    return null;
                });
            }
        } else {
            if (icon instanceof BitmapDrawable) {
                BitmapDrawable bitmapDrawable = (BitmapDrawable) icon;
            if (icon instanceof BitmapDrawable bitmapDrawable) {
                Bitmap b = bitmapDrawable.getBitmap();
                if (b != null && b.getDensity() == Bitmap.DENSITY_NONE) {
                    bitmapDrawable.setTargetDensity(mContext.getResources().getDisplayMetrics());
+13 −23
Original line number Diff line number Diff line
@@ -35,13 +35,10 @@ import android.graphics.RegionIterator
import android.util.Log
import androidx.annotation.ColorInt
import androidx.core.graphics.ColorUtils.compositeColors
import com.android.launcher3.icons.GraphicsUtils.resize
import com.android.launcher3.icons.BitmapRenderer.createHardwareBitmap
import com.android.launcher3.icons.IconNormalizer.ICON_VISIBLE_AREA_FACTOR
import com.android.launcher3.icons.ShadowGenerator.BLUR_FACTOR
import java.io.ByteArrayOutputStream
import java.io.IOException
import kotlin.math.ceil
import kotlin.math.max

object GraphicsUtils {
    private const val TAG = "GraphicsUtils"
@@ -133,6 +130,7 @@ object GraphicsUtils {
     * the [block]. It also scales down the drawing by [ICON_VISIBLE_AREA_FACTOR] to account for
     * icon normalization.
     */
    @JvmStatic
    inline fun Canvas.resizeToContentSize(
        bounds: Rect,
        sizeX: Float,
@@ -150,25 +148,17 @@ object GraphicsUtils {
     * [size]]
     */
    @JvmStatic
    fun generateIconShape(size: Int, shapePath: Path): IconShape {
        // Generate shadow layer:
        // Based on adaptive icon drawing in BaseIconFactory
        val offset =
            max(
                ceil((BLUR_FACTOR * size)).toInt(),
                Math.round(size * (1 - ICON_VISIBLE_AREA_FACTOR) / 2),
    fun generateIconShape(size: Int, shapePath: Path): IconShape =
        IconShape(
            pathSize = size,
            path = shapePath,
            shadowLayer =
                createHardwareBitmap(size, size) {
                    it.resizeToContentSize(Rect(0, 0, size, size), size.toFloat()) {
                        ShadowGenerator(size).addPathShadow(shapePath, this)
                    }
                },
        )
        val shadowLayer =
            BitmapRenderer.createHardwareBitmap(size, size) { canvas: Canvas ->
                canvas.transformed {
                    canvas.translate(offset.toFloat(), offset.toFloat())
                    val drawnPathSize = size - offset * 2
                    val drawnPath = shapePath.resize(size, drawnPathSize)
                    ShadowGenerator(size).addPathShadow(drawnPath, canvas)
                }
            }
        return IconShape(pathSize = size, path = shapePath, shadowLayer = shadowLayer)
    }

    /** Returns a color filter which is equivalent to [filter] x BlendModeFilter with [color] */
    fun getColorMultipliedFilter(color: Int, filter: ColorFilter?): ColorFilter? {