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

Commit f9cb2a05 authored by Charlie Anderson's avatar Charlie Anderson
Browse files

optimize drawing simple icon shapes

Bug: 372884380
Bug: 426259519
Test: v2/android-crystalball-eng/health/microbench/bootup/idle/system-processes-memory-direct-aosp
Flag: com.android.launcher3.enable_launcher_icon_shapes

Change-Id: Ib54ab5bb78bb5d84343529fe6d243c2f93723a55
parent 3c1bde99
Loading
Loading
Loading
Loading
+2 −1
Original line number Diff line number Diff line
@@ -270,7 +270,8 @@ public class BaseIconFactory implements AutoCloseable {
        AdaptiveIconDrawable tempAdaptiveIcon =
                new AdaptiveIconDrawable(new ColorDrawable(BLACK), null);
        tempAdaptiveIcon.setBounds(0, 0, mIconBitmapSize, mIconBitmapSize);
        mDefaultIconShape = generateIconShape(mIconBitmapSize, tempAdaptiveIcon.getIconMask());
        mDefaultIconShape = generateIconShape(mIconBitmapSize, tempAdaptiveIcon.getIconMask(),
                DefaultRenderer.INSTANCE);
        return mDefaultIconShape;
    }

+1 −1
Original line number Diff line number Diff line
@@ -136,7 +136,7 @@ constructor(

        canvas.resizeToContentSize(bounds, iconShape.pathSize.toFloat()) {
            paint.shader = shader
            drawPath(iconShape.path, paint)
            iconShape.shapeRenderer.render(iconShape.path, canvas, paint)
            paint.shader = null
        }
    }
+11 −2
Original line number Diff line number Diff line
@@ -165,7 +165,11 @@ object GraphicsUtils {
     * [size]]
     */
    @JvmStatic
    fun generateIconShape(size: Int, shapePath: Path): IconShape {
    fun generateIconShape(
        size: Int,
        shapePath: Path,
        shapeRenderer: ShapeRenderer = DefaultRenderer
    ): IconShape {
        // Generate shadow layer:
        // Based on adaptive icon drawing in BaseIconFactory
        val offset =
@@ -182,7 +186,12 @@ object GraphicsUtils {
                    ShadowGenerator(size).addPathShadow(drawnPath, canvas)
                }
            }
        return IconShape(pathSize = size, path = shapePath, shadowLayer = shadowLayer)
        return IconShape(
            pathSize = size,
            path = shapePath,
            shadowLayer = shadowLayer,
            shapeRenderer = shapeRenderer
        )
    }

    /** Returns a color filter which is equivalent to [filter] x BlendModeFilter with [color] */
+2 −1
Original line number Diff line number Diff line
@@ -30,8 +30,9 @@ data class IconShape(
    @JvmField val path: Path,
    /** Shadow layer to draw behind icon. Should use the same shape and scale as [path] */
    @JvmField val shadowLayer: Bitmap,
    /** Renderer for customizing how shapes are drawn to canvas */
    @JvmField val shapeRenderer: ShapeRenderer = DefaultRenderer
) {

    companion object {
        private const val DEFAULT_PATH_SIZE = 100

+40 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2025 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.
 */

package com.android.launcher3.icons

import android.graphics.Canvas
import android.graphics.Paint
import android.graphics.Path

interface ShapeRenderer {
    /**
     * Draws shape to the canvas using the provided parameters. This is used in draw methods,
     * so operations should be fast, with no new objects initialized.
     * @param path path of the icon shape to be drawn.
     * @param radius Half-width of the shape path to be drawn.
     * @param canvas Canvas to draw shape on.
     * @param paint Paint to draw on the Canvas with.
     */
    fun render(path: Path, canvas: Canvas, paint: Paint) =
        canvas.drawPath(path, paint)
}

object DefaultRenderer: ShapeRenderer {
    override fun render(path: Path, canvas: Canvas, paint: Paint) {
        canvas.drawPath(path, paint)
    }
}
 No newline at end of file