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

View File

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