mirror of
https://github.com/facebook/react-native.git
synced 2025-11-01 09:14:26 +00:00
Nullable borderRadius optimization on shadows and outline (#46819)
Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/46819 Just some preparation to implement the new `BackgroundDrawable` and `BorderDrawable`. This makes shadows and outline rely on `CompositeBackgroundDrawable` to set the state of `BorderRadiusStyle` and also makes them have a nullable borderRadius variable and initialize it only if we have it set saving a bit of overhead and performance Changelog: [Internal] Reviewed By: NickGerleman Differential Revision: D63798853 fbshipit-source-id: 994327415ba160cf8e5ccb3135c4917809499f81
This commit is contained in:
committed by
Facebook GitHub Bot
parent
892ce1b980
commit
02e4f3e16a
+13
-16
@@ -105,13 +105,14 @@ public object BackgroundStyleApplicator {
|
||||
): Unit {
|
||||
ensureCSSBackground(view).setBorderRadius(corner, radius)
|
||||
val compositeBackgroundDrawable = ensureCompositeBackgroundDrawable(view)
|
||||
compositeBackgroundDrawable.borderRadius =
|
||||
compositeBackgroundDrawable.borderRadius ?: BorderRadiusStyle()
|
||||
compositeBackgroundDrawable.borderRadius?.set(corner, radius)
|
||||
|
||||
if (Build.VERSION.SDK_INT >= MIN_OUTSET_BOX_SHADOW_SDK_VERSION) {
|
||||
for (shadow in compositeBackgroundDrawable.outerShadows) {
|
||||
if (shadow is OutsetBoxShadowDrawable) {
|
||||
shadow.borderRadius = shadow.borderRadius ?: BorderRadiusStyle()
|
||||
shadow.borderRadius?.set(corner, radius)
|
||||
shadow.invalidateSelf()
|
||||
shadow.borderRadius = compositeBackgroundDrawable.borderRadius
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -119,19 +120,13 @@ public object BackgroundStyleApplicator {
|
||||
if (Build.VERSION.SDK_INT >= MIN_INSET_BOX_SHADOW_SDK_VERSION) {
|
||||
for (shadow in compositeBackgroundDrawable.innerShadows) {
|
||||
if (shadow is InsetBoxShadowDrawable) {
|
||||
shadow.borderRadius = shadow.borderRadius ?: BorderRadiusStyle()
|
||||
shadow.borderRadius?.set(corner, radius)
|
||||
shadow.invalidateSelf()
|
||||
shadow.borderRadius = compositeBackgroundDrawable.borderRadius
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
val outline = compositeBackgroundDrawable.outline
|
||||
if (outline != null) {
|
||||
outline.borderRadius = outline.borderRadius ?: BorderRadiusStyle()
|
||||
outline.borderRadius?.set(corner, radius)
|
||||
outline.invalidateSelf()
|
||||
}
|
||||
compositeBackgroundDrawable.outline?.borderRadius = compositeBackgroundDrawable.borderRadius
|
||||
compositeBackgroundDrawable.invalidateSelf()
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
@@ -207,7 +202,9 @@ public object BackgroundStyleApplicator {
|
||||
val outerShadows = mutableListOf<OutsetBoxShadowDrawable>()
|
||||
val innerShadows = mutableListOf<InsetBoxShadowDrawable>()
|
||||
|
||||
val borderInsets = ensureCompositeBackgroundDrawable(view).borderInsets
|
||||
val compositeBackgroundDrawable = ensureCompositeBackgroundDrawable(view)
|
||||
val borderInsets = compositeBackgroundDrawable.borderInsets
|
||||
val borderRadius = compositeBackgroundDrawable.borderRadius
|
||||
|
||||
for (boxShadow in shadows) {
|
||||
val offsetX = boxShadow.offsetX
|
||||
@@ -221,7 +218,7 @@ public object BackgroundStyleApplicator {
|
||||
innerShadows.add(
|
||||
InsetBoxShadowDrawable(
|
||||
context = view.context,
|
||||
borderRadius = ensureCSSBackground(view).borderRadius,
|
||||
borderRadius = borderRadius,
|
||||
borderInsets = borderInsets,
|
||||
shadowColor = color,
|
||||
offsetX = offsetX,
|
||||
@@ -232,7 +229,7 @@ public object BackgroundStyleApplicator {
|
||||
outerShadows.add(
|
||||
OutsetBoxShadowDrawable(
|
||||
context = view.context,
|
||||
borderRadius = ensureCSSBackground(view).borderRadius,
|
||||
borderRadius = borderRadius,
|
||||
shadowColor = color,
|
||||
offsetX = offsetX,
|
||||
offsetY = offsetY,
|
||||
@@ -329,7 +326,7 @@ public object BackgroundStyleApplicator {
|
||||
outline =
|
||||
OutlineDrawable(
|
||||
context = view.context,
|
||||
borderRadius = ensureCSSBackground(view).borderRadius.copy(),
|
||||
borderRadius = compositeBackgroundDrawable.borderRadius,
|
||||
outlineColor = Color.BLACK,
|
||||
outlineOffset = 0f,
|
||||
outlineStyle = OutlineStyle.SOLID,
|
||||
|
||||
+38
-4
@@ -11,6 +11,7 @@ import android.graphics.drawable.Drawable
|
||||
import android.graphics.drawable.LayerDrawable
|
||||
import com.facebook.react.common.annotations.UnstableReactNativeAPI
|
||||
import com.facebook.react.uimanager.style.BorderInsets
|
||||
import com.facebook.react.uimanager.style.BorderRadiusStyle
|
||||
|
||||
/**
|
||||
* CompositeBackgroundDrawable can overlay multiple different layers, shadows, and native effects
|
||||
@@ -59,6 +60,8 @@ internal class CompositeBackgroundDrawable(
|
||||
|
||||
// Holder value for currently set insets
|
||||
public var borderInsets: BorderInsets? = null
|
||||
// Holder value for currently set border radius
|
||||
public var borderRadius: BorderRadiusStyle? = null
|
||||
|
||||
init {
|
||||
// We want to overlay drawables, instead of placing future drawables within the content area of
|
||||
@@ -71,7 +74,16 @@ internal class CompositeBackgroundDrawable(
|
||||
cssBackground: CSSBackgroundDrawable?
|
||||
): CompositeBackgroundDrawable {
|
||||
return CompositeBackgroundDrawable(
|
||||
originalBackground, outerShadows, cssBackground, feedbackUnderlay, innerShadows, outline)
|
||||
originalBackground,
|
||||
outerShadows,
|
||||
cssBackground,
|
||||
feedbackUnderlay,
|
||||
innerShadows,
|
||||
outline)
|
||||
.also { composite ->
|
||||
composite.borderInsets = this.borderInsets
|
||||
composite.borderRadius = this.borderRadius
|
||||
}
|
||||
}
|
||||
|
||||
public fun withNewShadows(
|
||||
@@ -79,16 +91,38 @@ internal class CompositeBackgroundDrawable(
|
||||
innerShadows: List<Drawable>
|
||||
): CompositeBackgroundDrawable {
|
||||
return CompositeBackgroundDrawable(
|
||||
originalBackground, outerShadows, cssBackground, feedbackUnderlay, innerShadows, outline)
|
||||
originalBackground,
|
||||
outerShadows,
|
||||
cssBackground,
|
||||
feedbackUnderlay,
|
||||
innerShadows,
|
||||
outline)
|
||||
.also { composite ->
|
||||
composite.borderInsets = this.borderInsets
|
||||
composite.borderRadius = this.borderRadius
|
||||
}
|
||||
}
|
||||
|
||||
public fun withNewOutline(outline: OutlineDrawable): CompositeBackgroundDrawable {
|
||||
return CompositeBackgroundDrawable(
|
||||
originalBackground, outerShadows, cssBackground, feedbackUnderlay, innerShadows, outline)
|
||||
originalBackground,
|
||||
outerShadows,
|
||||
cssBackground,
|
||||
feedbackUnderlay,
|
||||
innerShadows,
|
||||
outline)
|
||||
.also { composite ->
|
||||
composite.borderInsets = this.borderInsets
|
||||
composite.borderRadius = this.borderRadius
|
||||
}
|
||||
}
|
||||
|
||||
public fun withNewFeedbackUnderlay(newUnderlay: Drawable?): CompositeBackgroundDrawable {
|
||||
return CompositeBackgroundDrawable(
|
||||
originalBackground, outerShadows, cssBackground, newUnderlay, innerShadows, outline)
|
||||
originalBackground, outerShadows, cssBackground, newUnderlay, innerShadows, outline)
|
||||
.apply {
|
||||
borderInsets = this@CompositeBackgroundDrawable.borderInsets
|
||||
borderRadius = this@CompositeBackgroundDrawable.borderRadius
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+6
-18
@@ -40,30 +40,18 @@ private val ZERO_RADII = floatArrayOf(0f, 0f, 0f, 0f, 0f, 0f, 0f, 0f)
|
||||
@RequiresApi(MIN_INSET_BOX_SHADOW_SDK_VERSION)
|
||||
internal class InsetBoxShadowDrawable(
|
||||
private val context: Context,
|
||||
borderRadius: BorderRadiusStyle? = null,
|
||||
borderInsets: BorderInsets? = null,
|
||||
private val shadowColor: Int,
|
||||
private val offsetX: Float,
|
||||
private val offsetY: Float,
|
||||
private val blurRadius: Float,
|
||||
private val spread: Float,
|
||||
/*
|
||||
* We assume borderRadius & borderInsets to be shared across multiple drawables
|
||||
* therefore user should invalidate this drawable when changing either of them
|
||||
*/
|
||||
var borderInsets: BorderInsets? = null,
|
||||
var borderRadius: BorderRadiusStyle? = null,
|
||||
) : Drawable() {
|
||||
public var borderRadius = borderRadius
|
||||
set(value) {
|
||||
if (value != field) {
|
||||
field = value
|
||||
invalidateSelf()
|
||||
}
|
||||
}
|
||||
|
||||
public var borderInsets = borderInsets
|
||||
set(value) {
|
||||
if (value != field) {
|
||||
field = value
|
||||
invalidateSelf()
|
||||
}
|
||||
}
|
||||
|
||||
private val shadowPaint =
|
||||
Paint().apply {
|
||||
color = shadowColor
|
||||
|
||||
+11
-13
@@ -23,14 +23,15 @@ import com.facebook.react.uimanager.style.ComputedBorderRadius
|
||||
import com.facebook.react.uimanager.style.CornerRadii
|
||||
import com.facebook.react.uimanager.style.OutlineStyle
|
||||
import kotlin.math.roundToInt
|
||||
import kotlin.properties.ObservableProperty
|
||||
import kotlin.properties.ReadWriteProperty
|
||||
import kotlin.reflect.KProperty
|
||||
|
||||
/** Draws outline https://drafts.csswg.org/css-ui/#outline */
|
||||
internal class OutlineDrawable(
|
||||
private val context: Context,
|
||||
borderRadius: BorderRadiusStyle? = null,
|
||||
/*
|
||||
* We assume borderRadius to be shared across multiple drawables
|
||||
* therefore we should manually invalidate this drawable when changing it
|
||||
*/
|
||||
var borderRadius: BorderRadiusStyle? = null,
|
||||
outlineColor: Int,
|
||||
outlineOffset: Float,
|
||||
outlineStyle: OutlineStyle,
|
||||
@@ -43,17 +44,14 @@ internal class OutlineDrawable(
|
||||
*/
|
||||
private val gapBetweenPaths = 0.8f
|
||||
|
||||
private fun <T> invalidatingChange(initialValue: T): ReadWriteProperty<Any?, T> =
|
||||
object : ObservableProperty<T>(initialValue) {
|
||||
override fun afterChange(property: KProperty<*>, oldValue: T, newValue: T) {
|
||||
if (oldValue != newValue) {
|
||||
invalidateSelf()
|
||||
}
|
||||
}
|
||||
public var outlineOffset: Float = outlineOffset
|
||||
set(value) {
|
||||
if (value != field) {
|
||||
field = value
|
||||
invalidateSelf()
|
||||
}
|
||||
}
|
||||
|
||||
public var borderRadius: BorderRadiusStyle? by invalidatingChange(borderRadius)
|
||||
public var outlineOffset: Float by invalidatingChange(outlineOffset)
|
||||
public var outlineStyle: OutlineStyle = outlineStyle
|
||||
set(value) {
|
||||
if (value != field) {
|
||||
|
||||
+5
-9
@@ -37,21 +37,17 @@ private const val BLUR_RADIUS_SIGMA_SCALE = 0.5f
|
||||
@RequiresApi(MIN_OUTSET_BOX_SHADOW_SDK_VERSION)
|
||||
internal class OutsetBoxShadowDrawable(
|
||||
private val context: Context,
|
||||
borderRadius: BorderRadiusStyle? = null,
|
||||
private val shadowColor: Int,
|
||||
private val offsetX: Float,
|
||||
private val offsetY: Float,
|
||||
private val blurRadius: Float,
|
||||
private val spread: Float,
|
||||
/*
|
||||
* We assume borderRadius to be shared across multiple drawables
|
||||
* therefore we should manually invalidate this drawable when changing it
|
||||
*/
|
||||
var borderRadius: BorderRadiusStyle? = null,
|
||||
) : Drawable() {
|
||||
public var borderRadius = borderRadius
|
||||
set(value) {
|
||||
if (value != field) {
|
||||
field = value
|
||||
invalidateSelf()
|
||||
}
|
||||
}
|
||||
|
||||
private val shadowPaint =
|
||||
Paint().apply {
|
||||
color = shadowColor
|
||||
|
||||
Reference in New Issue
Block a user