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

Commit 7f4aa09e authored by Lucas Silva's avatar Lucas Silva Committed by Automerger Merge Worker
Browse files

Merge "Implement DoubleShadowIconDrawable for use in dream complications" into...

Merge "Implement DoubleShadowIconDrawable for use in dream complications" into tm-qpr-dev am: 6bf07ae2 am: 1fd117dd

Original change: https://googleplex-android-review.googlesource.com/c/platform/frameworks/base/+/19993115



Change-Id: Ide1c234da66e84559ee4e641c365f99752293f8e
Signed-off-by: default avatarAutomerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
parents b31b31c8 1fd117dd
Loading
Loading
Loading
Loading
+12 −2
Original line number Diff line number Diff line
@@ -14,8 +14,9 @@
  ~ See the License for the specific language governing permissions and
  ~ limitations under the License.
-->
<com.android.systemui.dreams.complication.DoubleShadowTextClock
<com.android.systemui.shared.shadow.DoubleShadowTextClock
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:id="@+id/time_view"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
@@ -25,4 +26,13 @@
    android:format24Hour="@string/dream_time_complication_24_hr_time_format"
    android:fontFeatureSettings="pnum, lnum"
    android:letterSpacing="0.02"
    android:textSize="@dimen/dream_overlay_complication_clock_time_text_size"/>
    android:textSize="@dimen/dream_overlay_complication_clock_time_text_size"
    app:keyShadowBlur="@dimen/dream_overlay_clock_key_text_shadow_radius"
    app:keyShadowOffsetX="@dimen/dream_overlay_clock_key_text_shadow_dx"
    app:keyShadowOffsetY="@dimen/dream_overlay_clock_key_text_shadow_dy"
    app:keyShadowAlpha="0.3"
    app:ambientShadowBlur="@dimen/dream_overlay_clock_ambient_text_shadow_radius"
    app:ambientShadowOffsetX="@dimen/dream_overlay_clock_ambient_text_shadow_dx"
    app:ambientShadowOffsetY="@dimen/dream_overlay_clock_ambient_text_shadow_dy"
    app:ambientShadowAlpha="0.3"
/>
+35 −0
Original line number Diff line number Diff line
@@ -25,4 +25,39 @@
        <attr name="lockScreenWeight" format="integer" />
        <attr name="chargeAnimationDelay" format="integer" />
    </declare-styleable>

    <declare-styleable name="DoubleShadowAttrDeclare">
        <attr name="keyShadowBlur" format="dimension" />
        <attr name="keyShadowOffsetX" format="dimension" />
        <attr name="keyShadowOffsetY" format="dimension" />
        <attr name="keyShadowAlpha" format="float" />
        <attr name="ambientShadowBlur" format="dimension" />
        <attr name="ambientShadowOffsetX" format="dimension" />
        <attr name="ambientShadowOffsetY" format="dimension" />
        <attr name="ambientShadowAlpha" format="float" />
    </declare-styleable>

    <declare-styleable name="DoubleShadowTextClock">
        <attr name="keyShadowBlur" />
        <attr name="keyShadowOffsetX" />
        <attr name="keyShadowOffsetY" />
        <attr name="keyShadowAlpha" />
        <attr name="ambientShadowBlur" />
        <attr name="ambientShadowOffsetX" />
        <attr name="ambientShadowOffsetY" />
        <attr name="ambientShadowAlpha" />
    </declare-styleable>

    <declare-styleable name="DoubleShadowTextView">
        <attr name="keyShadowBlur" />
        <attr name="keyShadowOffsetX" />
        <attr name="keyShadowOffsetY" />
        <attr name="keyShadowAlpha" />
        <attr name="ambientShadowBlur" />
        <attr name="ambientShadowOffsetX" />
        <attr name="ambientShadowOffsetY" />
        <attr name="ambientShadowAlpha" />
        <attr name="drawableIconSize" format="dimension" />
        <attr name="drawableIconInsetSize" format="dimension" />
    </declare-styleable>
</resources>
+124 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2022 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.systemui.shared.shadow

import android.graphics.BlendMode
import android.graphics.Canvas
import android.graphics.Color
import android.graphics.ColorFilter
import android.graphics.PixelFormat
import android.graphics.PorterDuff
import android.graphics.PorterDuffColorFilter
import android.graphics.RenderEffect
import android.graphics.RenderNode
import android.graphics.Shader
import android.graphics.drawable.Drawable
import android.graphics.drawable.InsetDrawable
import com.android.systemui.shared.shadow.DoubleShadowTextHelper.ShadowInfo

/** A component to draw an icon with two layers of shadows. */
class DoubleShadowIconDrawable(
    keyShadowInfo: ShadowInfo,
    ambientShadowInfo: ShadowInfo,
    iconDrawable: Drawable,
    iconSize: Int,
    val iconInsetSize: Int
) : Drawable() {
    private val mAmbientShadowInfo: ShadowInfo
    private val mCanvasSize: Int
    private val mKeyShadowInfo: ShadowInfo
    private val mIconDrawable: InsetDrawable
    private val mDoubleShadowNode: RenderNode

    init {
        mCanvasSize = iconSize + iconInsetSize * 2
        mKeyShadowInfo = keyShadowInfo
        mAmbientShadowInfo = ambientShadowInfo
        setBounds(0, 0, mCanvasSize, mCanvasSize)
        mIconDrawable = InsetDrawable(iconDrawable, iconInsetSize)
        mIconDrawable.setBounds(0, 0, mCanvasSize, mCanvasSize)
        mDoubleShadowNode = createShadowRenderNode()
    }

    private fun createShadowRenderNode(): RenderNode {
        val renderNode = RenderNode("DoubleShadowNode")
        renderNode.setPosition(0, 0, mCanvasSize, mCanvasSize)
        // Create render effects
        val ambientShadow =
            createShadowRenderEffect(
                mAmbientShadowInfo.blur,
                mAmbientShadowInfo.offsetX,
                mAmbientShadowInfo.offsetY,
                mAmbientShadowInfo.alpha
            )
        val keyShadow =
            createShadowRenderEffect(
                mKeyShadowInfo.blur,
                mKeyShadowInfo.offsetX,
                mKeyShadowInfo.offsetY,
                mKeyShadowInfo.alpha
            )
        val blend = RenderEffect.createBlendModeEffect(ambientShadow, keyShadow, BlendMode.DARKEN)
        renderNode.setRenderEffect(blend)
        return renderNode
    }

    private fun createShadowRenderEffect(
        radius: Float,
        offsetX: Float,
        offsetY: Float,
        alpha: Float
    ): RenderEffect {
        return RenderEffect.createColorFilterEffect(
            PorterDuffColorFilter(Color.argb(alpha, 0f, 0f, 0f), PorterDuff.Mode.MULTIPLY),
            RenderEffect.createOffsetEffect(
                offsetX,
                offsetY,
                RenderEffect.createBlurEffect(radius, radius, Shader.TileMode.CLAMP)
            )
        )
    }

    override fun draw(canvas: Canvas) {
        if (canvas.isHardwareAccelerated) {
            if (!mDoubleShadowNode.hasDisplayList()) {
                // Record render node if its display list is not recorded or discarded
                // (which happens when it's no longer drawn by anything).
                val recordingCanvas = mDoubleShadowNode.beginRecording()
                mIconDrawable.draw(recordingCanvas)
                mDoubleShadowNode.endRecording()
            }
            canvas.drawRenderNode(mDoubleShadowNode)
        }
        mIconDrawable.draw(canvas)
    }

    override fun getOpacity(): Int {
        return PixelFormat.TRANSPARENT
    }

    override fun setAlpha(alpha: Int) {
        mIconDrawable.alpha = alpha
    }

    override fun setColorFilter(colorFilter: ColorFilter?) {
        mIconDrawable.colorFilter = colorFilter
    }

    override fun setTint(color: Int) {
        mIconDrawable.setTint(color)
    }
}
+100 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2022 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.systemui.shared.shadow

import android.content.Context
import android.graphics.Canvas
import android.util.AttributeSet
import android.widget.TextClock
import com.android.systemui.shared.R
import com.android.systemui.shared.shadow.DoubleShadowTextHelper.ShadowInfo
import com.android.systemui.shared.shadow.DoubleShadowTextHelper.applyShadows

/** Extension of [TextClock] which draws two shadows on the text (ambient and key shadows) */
class DoubleShadowTextClock
@JvmOverloads
constructor(
    context: Context,
    attrs: AttributeSet? = null,
    defStyleAttr: Int = 0,
    defStyleRes: Int = 0
) : TextClock(context, attrs, defStyleAttr, defStyleRes) {
    private val mAmbientShadowInfo: ShadowInfo
    private val mKeyShadowInfo: ShadowInfo

    init {
        val attributes =
            context.obtainStyledAttributes(
                attrs,
                R.styleable.DoubleShadowTextClock,
                defStyleAttr,
                defStyleRes
            )
        try {
            val keyShadowBlur =
                attributes.getDimensionPixelSize(R.styleable.DoubleShadowTextClock_keyShadowBlur, 0)
            val keyShadowOffsetX =
                attributes.getDimensionPixelSize(
                    R.styleable.DoubleShadowTextClock_keyShadowOffsetX,
                    0
                )
            val keyShadowOffsetY =
                attributes.getDimensionPixelSize(
                    R.styleable.DoubleShadowTextClock_keyShadowOffsetY,
                    0
                )
            val keyShadowAlpha =
                attributes.getFloat(R.styleable.DoubleShadowTextClock_keyShadowAlpha, 0f)
            mKeyShadowInfo =
                ShadowInfo(
                    keyShadowBlur.toFloat(),
                    keyShadowOffsetX.toFloat(),
                    keyShadowOffsetY.toFloat(),
                    keyShadowAlpha
                )
            val ambientShadowBlur =
                attributes.getDimensionPixelSize(
                    R.styleable.DoubleShadowTextClock_ambientShadowBlur,
                    0
                )
            val ambientShadowOffsetX =
                attributes.getDimensionPixelSize(
                    R.styleable.DoubleShadowTextClock_ambientShadowOffsetX,
                    0
                )
            val ambientShadowOffsetY =
                attributes.getDimensionPixelSize(
                    R.styleable.DoubleShadowTextClock_ambientShadowOffsetY,
                    0
                )
            val ambientShadowAlpha =
                attributes.getFloat(R.styleable.DoubleShadowTextClock_ambientShadowAlpha, 0f)
            mAmbientShadowInfo =
                ShadowInfo(
                    ambientShadowBlur.toFloat(),
                    ambientShadowOffsetX.toFloat(),
                    ambientShadowOffsetY.toFloat(),
                    ambientShadowAlpha
                )
        } finally {
            attributes.recycle()
        }
    }

    public override fun onDraw(canvas: Canvas) {
        applyShadows(mKeyShadowInfo, mAmbientShadowInfo, this, canvas) { super.onDraw(canvas) }
    }
}
+13 −11
Original line number Diff line number Diff line
@@ -14,31 +14,33 @@
 * limitations under the License.
 */

package com.android.systemui.dreams.complication
package com.android.systemui.shared.shadow

import android.graphics.Canvas
import android.graphics.Color
import android.widget.TextView
import androidx.annotation.ColorInt

class DoubleShadowTextHelper
constructor(
    private val keyShadowInfo: ShadowInfo,
    private val ambientShadowInfo: ShadowInfo,
) {
object DoubleShadowTextHelper {
    data class ShadowInfo(
        val blur: Float,
        val offsetX: Float = 0f,
        val offsetY: Float = 0f,
        @ColorInt val color: Int
        val alpha: Float
    )

    fun applyShadows(view: TextView, canvas: Canvas, onDrawCallback: () -> Unit) {
    fun applyShadows(
        keyShadowInfo: ShadowInfo,
        ambientShadowInfo: ShadowInfo,
        view: TextView,
        canvas: Canvas,
        onDrawCallback: () -> Unit
    ) {
        // We enhance the shadow by drawing the shadow twice
        view.paint.setShadowLayer(
            ambientShadowInfo.blur,
            ambientShadowInfo.offsetX,
            ambientShadowInfo.offsetY,
            ambientShadowInfo.color
            Color.argb(ambientShadowInfo.alpha, 0f, 0f, 0f)
        )
        onDrawCallback()
        canvas.save()
@@ -53,7 +55,7 @@ constructor(
            keyShadowInfo.blur,
            keyShadowInfo.offsetX,
            keyShadowInfo.offsetY,
            keyShadowInfo.color
            Color.argb(keyShadowInfo.alpha, 0f, 0f, 0f)
        )
        onDrawCallback()
        canvas.restore()
Loading