Change type of shadows from array to LayerDrawable (#46818)

Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/46818

Before we were using lists which meant `CompositeBackgroundDrawable` had a `LayerDrawable` of variable length.

This meant that our layers were not consistent and made it hard to optimize `CompositeBackgroundDrawable` to not create a new instance every time we set a new Layer.

With this change `CompositeBackgroundDrawable` has a consistent amount of layers which will allow us to more easily mutate it and land the optimization present on D63287222

Changelog: [Internal]

Reviewed By: NickGerleman

Differential Revision: D63798842

fbshipit-source-id: bf0b9ee91ff2083b89ca90ace4de00c71bf3153c
This commit is contained in:
Jorge Cabiedes Acosta 2024-11-19 12:13:42 -08:00 committed by Facebook GitHub Bot
parent abeee154d5
commit fd2ce35172
2 changed files with 44 additions and 25 deletions

View File

@ -13,6 +13,7 @@ import android.graphics.Path
import android.graphics.Rect
import android.graphics.RectF
import android.graphics.drawable.Drawable
import android.graphics.drawable.LayerDrawable
import android.os.Build
import android.view.View
import android.widget.ImageView
@ -106,12 +107,13 @@ public object BackgroundStyleApplicator {
composite.borderInsets = composite.borderInsets ?: BorderInsets()
composite.borderInsets?.setBorderWidth(edge, width)
if (Build.VERSION.SDK_INT >= MIN_INSET_BOX_SHADOW_SDK_VERSION) {
composite.borderInsets = composite.borderInsets ?: BorderInsets()
composite.borderInsets?.setBorderWidth(edge, width)
for (shadow in composite.innerShadows) {
(shadow as InsetBoxShadowDrawable).borderInsets = composite.borderInsets
shadow.invalidateSelf()
val innerShadows = composite.innerShadows
if (innerShadows != null) {
for (i in 0 until innerShadows.numberOfLayers) {
val shadow = innerShadows.getDrawable(i)
(shadow as InsetBoxShadowDrawable).borderInsets = composite.borderInsets
shadow.invalidateSelf()
}
}
}
}
@ -172,17 +174,29 @@ public object BackgroundStyleApplicator {
}
if (Build.VERSION.SDK_INT >= MIN_OUTSET_BOX_SHADOW_SDK_VERSION) {
for (shadow in compositeBackgroundDrawable.outerShadows) {
if (shadow is OutsetBoxShadowDrawable) {
shadow.borderRadius = compositeBackgroundDrawable.borderRadius
val outerShadows = compositeBackgroundDrawable.outerShadows
if (outerShadows != null) {
for (i in 0 until outerShadows.numberOfLayers) {
val shadow = outerShadows.getDrawable(i)
if (shadow is OutsetBoxShadowDrawable) {
shadow.borderRadius = shadow.borderRadius ?: BorderRadiusStyle()
shadow.borderRadius?.set(corner, radius)
shadow.invalidateSelf()
}
}
}
}
if (Build.VERSION.SDK_INT >= MIN_INSET_BOX_SHADOW_SDK_VERSION) {
for (shadow in compositeBackgroundDrawable.innerShadows) {
if (shadow is InsetBoxShadowDrawable) {
shadow.borderRadius = compositeBackgroundDrawable.borderRadius
val innerShadows = compositeBackgroundDrawable.innerShadows
if (innerShadows != null) {
for (i in 0 until innerShadows.numberOfLayers) {
val shadow = innerShadows.getDrawable(i)
if (shadow is InsetBoxShadowDrawable) {
shadow.borderRadius = shadow.borderRadius ?: BorderRadiusStyle()
shadow.borderRadius?.set(corner, radius)
shadow.invalidateSelf()
}
}
}
}
@ -277,14 +291,14 @@ public object BackgroundStyleApplicator {
return
}
val outerShadows = mutableListOf<OutsetBoxShadowDrawable>()
val innerShadows = mutableListOf<InsetBoxShadowDrawable>()
var innerShadows: LayerDrawable? = null
var outerShadows: LayerDrawable? = null
val compositeBackgroundDrawable = ensureCompositeBackgroundDrawable(view)
val borderInsets = compositeBackgroundDrawable.borderInsets
val borderRadius = compositeBackgroundDrawable.borderRadius
for (boxShadow in shadows) {
for (boxShadow in shadows.asReversed()) {
val offsetX = boxShadow.offsetX
val offsetY = boxShadow.offsetY
val color = boxShadow.color ?: Color.BLACK
@ -293,7 +307,10 @@ public object BackgroundStyleApplicator {
val inset = boxShadow.inset ?: false
if (inset && Build.VERSION.SDK_INT >= MIN_INSET_BOX_SHADOW_SDK_VERSION) {
innerShadows.add(
if (innerShadows == null) {
innerShadows = LayerDrawable(emptyArray())
}
innerShadows.addLayer(
InsetBoxShadowDrawable(
context = view.context,
borderRadius = borderRadius,
@ -304,7 +321,10 @@ public object BackgroundStyleApplicator {
blurRadius = blurRadius,
spread = spreadDistance))
} else if (!inset && Build.VERSION.SDK_INT >= MIN_OUTSET_BOX_SHADOW_SDK_VERSION) {
outerShadows.add(
if (outerShadows == null) {
outerShadows = LayerDrawable(emptyArray())
}
outerShadows.addLayer(
OutsetBoxShadowDrawable(
context = view.context,
borderRadius = borderRadius,

View File

@ -32,7 +32,7 @@ internal class CompositeBackgroundDrawable(
public val originalBackground: Drawable? = null,
/** Non-inset box shadows */
public val outerShadows: List<Drawable> = emptyList(),
public val outerShadows: LayerDrawable? = null,
/**
* CSS background layer and border rendering
@ -52,26 +52,25 @@ internal class CompositeBackgroundDrawable(
public val feedbackUnderlay: Drawable? = null,
/** Inset box-shadows */
public val innerShadows: List<Drawable> = emptyList(),
public val innerShadows: LayerDrawable? = null,
/** Outline */
public val outline: OutlineDrawable? = null,
) :
LayerDrawable(
listOfNotNull(
listOf(
originalBackground,
// z-ordering of user-provided shadow-list is opposite direction of LayerDrawable
// z-ordering
// https://drafts.csswg.org/css-backgrounds/#shadow-layers
*outerShadows.asReversed().toTypedArray(),
outerShadows,
cssBackground,
background,
border,
feedbackUnderlay,
*innerShadows.asReversed().toTypedArray(),
innerShadows,
outline)
.toTypedArray()) {
// Holder value for currently set insets
public var borderInsets: BorderInsets? = null
// Holder value for currently set border radius
@ -121,8 +120,8 @@ internal class CompositeBackgroundDrawable(
}
public fun withNewShadows(
outerShadows: List<Drawable>,
innerShadows: List<Drawable>
outerShadows: LayerDrawable?,
innerShadows: LayerDrawable?
): CompositeBackgroundDrawable {
return CompositeBackgroundDrawable(
context,