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

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

Snap for 13362916 from b164d52b to 25Q3-release

Change-Id: Ie3e38ea425c554c38e115b0cc49215b71a92ac0e
parents cbd52405 b164d52b
Loading
Loading
Loading
Loading
+56 −17
Original line number Diff line number Diff line
@@ -7,6 +7,7 @@ import static android.graphics.Paint.FILTER_BITMAP_FLAG;
import static android.graphics.drawable.AdaptiveIconDrawable.getExtraInsetFraction;

import static com.android.launcher3.icons.BitmapInfo.FLAG_INSTANT;
import static com.android.launcher3.icons.IconNormalizer.ICON_VISIBLE_AREA_FACTOR;
import static com.android.launcher3.icons.ShadowGenerator.BLUR_FACTOR;
import static com.android.launcher3.icons.ShadowGenerator.ICON_SCALE_FOR_SHADOWS;

@@ -19,12 +20,14 @@ import android.content.pm.PackageManager;
import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.Bitmap.Config;
import android.graphics.BitmapShader;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.PaintFlagsDrawFilter;
import android.graphics.Path;
import android.graphics.Rect;
import android.graphics.Shader.TileMode;
import android.graphics.drawable.AdaptiveIconDrawable;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.ColorDrawable;
@@ -91,8 +94,10 @@ public class BaseIconFactory implements AutoCloseable {
    @Nullable
    private ShadowGenerator mShadowGenerator;

    // Shadow bitmap used as background for theme icons
    /** Shadow bitmap used as background for theme icons */
    private Bitmap mWhiteShadowLayer;
    /** Bitmap used for {@link BitmapShader} to mask Adaptive Icons when drawing */
    private Bitmap mShaderBitmap;

    private int mWrapperBackgroundColor = DEFAULT_WRAPPER_BACKGROUND;

@@ -170,7 +175,7 @@ public class BaseIconFactory implements AutoCloseable {
        AdaptiveIconDrawable drawable = new AdaptiveIconDrawable(
                new ColorDrawable(PLACEHOLDER_BACKGROUND_COLOR),
                new CenterTextDrawable(placeholder, color));
        Bitmap icon = createIconBitmap(drawable, IconNormalizer.ICON_VISIBLE_AREA_FACTOR);
        Bitmap icon = createIconBitmap(drawable, ICON_VISIBLE_AREA_FACTOR);
        return BitmapInfo.of(icon, color);
    }

@@ -224,7 +229,6 @@ public class BaseIconFactory implements AutoCloseable {
        AdaptiveIconDrawable adaptiveIcon = normalizeAndWrapToAdaptiveIcon(tempIcon, scale);
        Bitmap bitmap = createIconBitmap(adaptiveIcon, scale[0],
                options == null ? MODE_WITH_SHADOW : options.mGenerationMode);

        int color = (options != null && options.mExtractedColor != null)
                ? options.mExtractedColor : ColorExtractor.findDominantColorByHue(bitmap);
        BitmapInfo info = BitmapInfo.of(bitmap, color);
@@ -308,6 +312,42 @@ public class BaseIconFactory implements AutoCloseable {
        return mWhiteShadowLayer;
    }

    /**
     * Takes an {@link AdaptiveIconDrawable} and uses it to create a new Shader Bitmap.
     * {@link mShaderBitmap} will be used to create a {@link BitmapShader} for masking,
     * such as for icon shapes. Will reuse underlying Bitmap where possible.
     *
     * @param adaptiveIcon AdaptiveIconDrawable to draw with shader
     */
    @NonNull
    private Bitmap getAdaptiveShaderBitmap(AdaptiveIconDrawable adaptiveIcon) {
        Rect bounds = adaptiveIcon.getBounds();
        int iconWidth = bounds.width();
        int iconHeight = bounds.width();

        BitmapRenderer shaderRenderer = new BitmapRenderer() {
            @Override
            public void draw(Canvas canvas) {
                canvas.translate(-bounds.left, -bounds.top);
                canvas.drawColor(BLACK);
                if (adaptiveIcon.getBackground() != null) {
                    adaptiveIcon.getBackground().draw(canvas);
                }
                if (adaptiveIcon.getForeground() != null) {
                    adaptiveIcon.getForeground().draw(canvas);
                }
            }
        };
        if (mShaderBitmap == null || iconWidth != mShaderBitmap.getWidth()
                || iconHeight != mShaderBitmap.getHeight()) {
            mShaderBitmap = BitmapRenderer.createSoftwareBitmap(iconWidth, iconHeight,
                    shaderRenderer);
        } else {
            shaderRenderer.draw(new Canvas(mShaderBitmap));
        }
        return mShaderBitmap;
    }

    @NonNull
    public Bitmap createScaledBitmap(@NonNull Drawable icon, @BitmapGenerationMode int mode) {
        float[] scale = new float[1];
@@ -329,7 +369,7 @@ public class BaseIconFactory implements AutoCloseable {
            return null;
        }

        outScale[0] = IconNormalizer.ICON_VISIBLE_AREA_FACTOR;
        outScale[0] = ICON_VISIBLE_AREA_FACTOR;
        return wrapToAdaptiveIcon(icon);
    }

@@ -426,6 +466,7 @@ public class BaseIconFactory implements AutoCloseable {
            } else {
                drawAdaptiveIcon(canvas, aid, shapePath);
            }

            canvas.restoreToCount(count);
        } else {
            if (icon instanceof BitmapDrawable) {
@@ -473,28 +514,26 @@ public class BaseIconFactory implements AutoCloseable {
    }

    /**
     * Draws AdaptiveIconDrawable onto canvas.
     * Draws AdaptiveIconDrawable onto canvas using provided Path
     * and {@link mShaderBitmap} as a shader.
     *
     * @param canvas    canvas to draw on
     * @param drawable  AdaptiveIconDrawable to draw
     * @param overridePath path to clip icon with for shapes
     * @param shapePath path to clip icon with for shapes
     */
    protected void drawAdaptiveIcon(
            @NonNull Canvas canvas,
            @NonNull AdaptiveIconDrawable drawable,
            @NonNull Path overridePath
            @NonNull Path shapePath
    ) {
        if (!Flags.enableLauncherIconShapes()) {
            drawable.draw(canvas);
            return;
        }
        canvas.clipPath(overridePath);
        canvas.drawColor(BLACK);
        if (drawable.getBackground() != null) {
            drawable.getBackground().draw(canvas);
        }
        if (drawable.getForeground() != null) {
            drawable.getForeground().draw(canvas);
        }
        Bitmap shaderBitmap = getAdaptiveShaderBitmap(drawable);
        Paint paint = new Paint();
        paint.setShader(new BitmapShader(shaderBitmap, TileMode.CLAMP, TileMode.CLAMP));
        canvas.drawPath(shapePath, paint);
    }

    @Override
+15 −6
Original line number Diff line number Diff line
@@ -30,8 +30,8 @@ uniform mat3 transformMatrixWeather;

#include "shaders/lens_flare.agsl"

const vec2 sunCenter = vec2(0.57, -0.8);
const vec3 godRaysColor = vec3(1., 0.857, 0.71428);
const vec2 sunCenter = vec2(0.67, -1.0);

float calculateRay(float angle, float time) {
    /*
@@ -94,16 +94,25 @@ float checkBrightnessGodRaysAtCenter(
}

vec4 main(float2 fragCoord) {
    float2 aspectRatioAdj = vec2(1.);
    if (screenAspectRatio > 1) {
        aspectRatioAdj.x = screenAspectRatio;
    } else {
        aspectRatioAdj.y = 1. / screenAspectRatio;
    }
    // Apply transform matrix to fragCoord
    float2 adjustedUv = transformPoint(transformMatrixBitmap, fragCoord);

    float2 uv = transformPoint(transformMatrixWeather, fragCoord) / screenSize;
    uv -= vec2(0.5, 0.5);
    uv.y /= screenAspectRatio;
    vec2 sunVariation = vec2(0.1 * sin(time * 0.3), 0.14 * cos(time * 0.5));
    sunVariation += 0.1 * (0.5 * sin(time * 0.456) + 0.5) * sunCenter / vec2(1., screenAspectRatio);
    vec2 sunPos = sunVariation + sunCenter / vec2(1., screenAspectRatio);
    //TODO(b/375214506): fix the uv position of the sun
    uv *= aspectRatioAdj;
    // Random sun variation based on sin/cos signal.
    vec2 sunVariation = 0.08 * vec2(sin(time * 0.3), cos(time * 0.5));
    // Variation that moves sun on the same direction than the vector that goes from (0,0)
    // to sunCenter, but scaling distance.
    sunVariation += 0.1 * (0.5 * sin(time * 0.456) + 0.5) * sunCenter;
    vec2 sunPos = sunVariation + sunCenter;
    sunPos *= aspectRatioAdj;

    vec4 colorForeground = foreground.eval(adjustedUv);
    vec4 color = background.eval(adjustedUv);
+32 −8
Original line number Diff line number Diff line
@@ -24,9 +24,9 @@ import android.graphics.RuntimeShader
import android.graphics.Shader
import android.util.SizeF
import com.google.android.wallpaper.weathereffects.graphics.utils.GraphicsUtils
import com.google.android.wallpaper.weathereffects.graphics.utils.MatrixUtils.calculateTransformDifference
import com.google.android.wallpaper.weathereffects.graphics.utils.MatrixUtils.calculateTranslationDifference
import com.google.android.wallpaper.weathereffects.graphics.utils.MatrixUtils.centerCropMatrix
import com.google.android.wallpaper.weathereffects.graphics.utils.MatrixUtils.getScale
import com.google.android.wallpaper.weathereffects.graphics.utils.MatrixUtils.getScaleFromMatrixValues
import com.google.android.wallpaper.weathereffects.graphics.utils.MatrixUtils.invertAndTransposeMatrix
import kotlin.random.Random

@@ -42,13 +42,22 @@ abstract class WeatherEffectBase(
            surfaceSize,
            SizeF(background.width.toFloat(), background.height.toFloat()),
        )
        set(value) {
            field = value
            value.getValues(centerCropMatrixValues)
        }

    protected var parallaxMatrix = Matrix(centerCropMatrix)
    private val centerCropMatrixValues: FloatArray =
        FloatArray(9).apply { centerCropMatrix.getValues(this) }
    private val parallaxMatrixValues: FloatArray =
        FloatArray(9).apply { parallaxMatrix.getValues(this) }
    // Currently, we use same transform for both foreground and background
    protected open val transformMatrixBitmap: FloatArray = FloatArray(9)
    // Apply to weather components not rely on image textures
    // Should be identity matrix in editor, and only change when parallax applied in homescreen
    private val transformMatrixWeather: FloatArray = FloatArray(9)
    protected var bitmapScale = getScale(centerCropMatrix)
    protected var bitmapScale = getScaleFromMatrixValues(centerCropMatrixValues)
    protected var elapsedTime: Float = 0f

    abstract val shader: RuntimeShader
@@ -57,14 +66,19 @@ abstract class WeatherEffectBase(
    abstract val colorGradingIntensity: Float

    override fun setMatrix(matrix: Matrix) {
        this.parallaxMatrix.set(matrix)
        bitmapScale = getScale(parallaxMatrix)
        this.parallaxMatrix.setAndUpdateFloatArray(matrix, parallaxMatrixValues)
        bitmapScale = getScaleFromMatrixValues(parallaxMatrixValues)
        adjustCropping(surfaceSize)
    }

    /** This function will be called every time parallax changes, don't do heavy things here */
    open fun adjustCropping(newSurfaceSize: SizeF) {
        invertAndTransposeMatrix(parallaxMatrix, transformMatrixBitmap)
        calculateTransformDifference(centerCropMatrix, parallaxMatrix, transformMatrixWeather)
        calculateTranslationDifference(
            centerCropMatrixValues,
            parallaxMatrixValues,
            transformMatrixWeather,
        )
        shader.setFloatUniform("transformMatrixBitmap", transformMatrixBitmap)
        shader.setFloatUniform("transformMatrixWeather", transformMatrixWeather)
        shader.setFloatUniform("screenSize", newSurfaceSize.width, newSurfaceSize.height)
@@ -75,6 +89,11 @@ abstract class WeatherEffectBase(

    override fun resize(newSurfaceSize: SizeF) {
        surfaceSize = newSurfaceSize
        centerCropMatrix =
            centerCropMatrix(
                surfaceSize,
                SizeF(background.width.toFloat(), background.height.toFloat()),
            )
        adjustCropping(newSurfaceSize)
        updateGridSize(newSurfaceSize)
    }
@@ -113,8 +132,8 @@ abstract class WeatherEffectBase(
                surfaceSize,
                SizeF(background.width.toFloat(), background.height.toFloat()),
            )
        parallaxMatrix.set(centerCropMatrix)
        bitmapScale = getScale(centerCropMatrix)
        parallaxMatrix.setAndUpdateFloatArray(centerCropMatrix, parallaxMatrixValues)
        bitmapScale = getScaleFromMatrixValues(centerCropMatrixValues)
        shader.setInputBuffer(
            "background",
            BitmapShader(this.background, Shader.TileMode.MIRROR, Shader.TileMode.MIRROR),
@@ -139,6 +158,11 @@ abstract class WeatherEffectBase(
        )
    }

    private fun Matrix.setAndUpdateFloatArray(src: Matrix, targetFloatArray: FloatArray) {
        set(src)
        src.getValues(targetFloatArray)
    }

    companion object {
        // When extracting the scale from the parallax matrix, there will be a very small difference
        // due to floating-point precision.
+51 −0
Original line number Diff line number Diff line
@@ -55,6 +55,10 @@ object MatrixUtils {
        return matrixValues[0]
    }

    fun getScaleFromMatrixValues(matrixValuesArray: FloatArray): Float {
        return matrixValuesArray[0]
    }

    /**
     * Calculates the transformation matrix that, when applied to `originMatrix`, results in
     * `targetMatrix`. Current use case: Calculating parallax effect for the homescreen compared
@@ -77,6 +81,53 @@ object MatrixUtils {
        return transposeMatrixArray(matrixValues, outArray)
    }

    /**
     * Calculates the difference in translation between two transformation matrices, represented as
     * FloatArrays (`centerCropMatrixValues` and `parallaxMatrixValues`), after scaling
     * `parallaxMatrixValues` to match the scale of `centerCropMatrixValues`. The resulting
     * translation difference is then stored in the provided `outArray` as a 3x3 translation matrix
     * (in column-major order).
     *
     * @param centerCropMatrixValues A FloatArray of length 9 representing the reference
     *   transformation matrix (center-cropped view) in row-major order.
     * @param parallaxMatrixValues A FloatArray of length 9 representing the transformation matrix
     *   whose translation difference relative to `centerCropMatrixValues` is to be calculated, also
     *   in row-major order. This array will be scaled to match the scale of
     *   `centerCropMatrixValues`.
     * @param outArray A FloatArray of length 9 to store the resulting 3x3 translation matrix. The
     *   translation components (deltaX, deltaY) will be placed in the appropriate positions for a
     *   column-major matrix.
     */
    fun calculateTranslationDifference(
        centerCropMatrixValues: FloatArray,
        parallaxMatrixValues: FloatArray,
        outArray: FloatArray,
    ): FloatArray {
        val scaleX = centerCropMatrixValues[0] / parallaxMatrixValues[0]
        val scaleY = centerCropMatrixValues[4] / parallaxMatrixValues[4]

        val scaledParallaxTransX = parallaxMatrixValues[2] * scaleX
        val scaledParallaxTransY = parallaxMatrixValues[5] * scaleY

        val originTransX = centerCropMatrixValues[2]
        val originTransY = centerCropMatrixValues[5]

        val deltaTransX = originTransX - scaledParallaxTransX
        val deltaTransY = originTransY - scaledParallaxTransY

        outArray[0] = 1f
        outArray[1] = 0f
        outArray[2] = 0f
        outArray[3] = 0f
        outArray[4] = 1f
        outArray[5] = 0f
        outArray[6] = deltaTransX
        outArray[7] = deltaTransY
        outArray[8] = 1f

        return outArray
    }

    // Transpose 3x3 matrix values as a FloatArray[9], write results to outArray
    private fun transposeMatrixArray(inMatrixArray: FloatArray, outArray: FloatArray): FloatArray {
        for (i in 0 until 3) {