Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions packages/react-native/Libraries/StyleSheet/StyleSheetTypes.js
Original file line number Diff line number Diff line change
Expand Up @@ -778,8 +778,8 @@ export type ____ViewStyle_InternalCore = $ReadOnly<{
elevation?: number,
pointerEvents?: 'auto' | 'none' | 'box-none' | 'box-only',
cursor?: CursorValue,
experimental_boxShadow?: $ReadOnlyArray<BoxShadowPrimitive>,
experimental_filter?: $ReadOnlyArray<FilterFunction>,
experimental_boxShadow?: $ReadOnlyArray<BoxShadowPrimitive> | string,
experimental_filter?: $ReadOnlyArray<FilterFunction> | string,
experimental_mixBlendMode?: ____BlendMode_Internal,
}>;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8776,8 +8776,8 @@ export type ____ViewStyle_InternalCore = $ReadOnly<{
elevation?: number,
pointerEvents?: \\"auto\\" | \\"none\\" | \\"box-none\\" | \\"box-only\\",
cursor?: CursorValue,
experimental_boxShadow?: $ReadOnlyArray<BoxShadowPrimitive>,
experimental_filter?: $ReadOnlyArray<FilterFunction>,
experimental_boxShadow?: $ReadOnlyArray<BoxShadowPrimitive> | string,
experimental_filter?: $ReadOnlyArray<FilterFunction> | string,
experimental_mixBlendMode?: ____BlendMode_Internal,
}>;
export type ____ViewStyle_Internal = $ReadOnly<{
Expand Down
100 changes: 100 additions & 0 deletions packages/react-native/ReactAndroid/api/ReactAndroid.api
Original file line number Diff line number Diff line change
Expand Up @@ -3969,6 +3969,22 @@ public abstract interface class com/facebook/react/turbomodule/core/interfaces/T
public abstract fun getBindingsInstaller ()Lcom/facebook/react/turbomodule/core/interfaces/BindingsInstallerHolder;
}

public final class com/facebook/react/uimanager/BackgroundStyleApplicator {
public static final field INSTANCE Lcom/facebook/react/uimanager/BackgroundStyleApplicator;
public static final fun clipToPaddingBox (Landroid/view/View;Landroid/graphics/Canvas;)V
public static final fun getBackgroundColor (Landroid/view/View;)Ljava/lang/Integer;
public static final fun getBorderColor (Landroid/view/View;Lcom/facebook/react/uimanager/style/LogicalEdge;)Ljava/lang/Integer;
public static final fun getBorderRadius (Landroid/view/View;Lcom/facebook/react/uimanager/style/BorderRadiusProp;)Lcom/facebook/react/uimanager/LengthPercentage;
public static final fun getBorderStyle (Landroid/view/View;)Lcom/facebook/react/uimanager/style/BorderStyle;
public static final fun getBorderWidth (Landroid/view/View;Lcom/facebook/react/uimanager/style/LogicalEdge;)Ljava/lang/Float;
public static final fun setBackgroundColor (Landroid/view/View;Ljava/lang/Integer;)V
public static final fun setBorderColor (Landroid/view/View;Lcom/facebook/react/uimanager/style/LogicalEdge;Ljava/lang/Integer;)V
public static final fun setBorderRadius (Landroid/view/View;Lcom/facebook/react/uimanager/style/BorderRadiusProp;Lcom/facebook/react/uimanager/LengthPercentage;)V
public static final fun setBorderStyle (Landroid/view/View;Lcom/facebook/react/uimanager/style/BorderStyle;)V
public static final fun setBorderWidth (Landroid/view/View;Lcom/facebook/react/uimanager/style/LogicalEdge;Ljava/lang/Float;)V
public static final fun setShadows (Landroid/view/View;Ljava/util/List;)V
}

public abstract class com/facebook/react/uimanager/BaseViewManager : com/facebook/react/uimanager/ViewManager, android/view/View$OnLayoutChangeListener, com/facebook/react/uimanager/BaseViewManagerInterface {
public fun <init> ()V
public fun <init> (Lcom/facebook/react/bridge/ReactApplicationContext;)V
Expand Down Expand Up @@ -5915,6 +5931,49 @@ public final class com/facebook/react/uimanager/style/BorderRadiusStyle {
public fun toString ()Ljava/lang/String;
}

public final class com/facebook/react/uimanager/style/BorderStyle : java/lang/Enum {
public static final field Companion Lcom/facebook/react/uimanager/style/BorderStyle$Companion;
public static final field DASHED Lcom/facebook/react/uimanager/style/BorderStyle;
public static final field DOTTED Lcom/facebook/react/uimanager/style/BorderStyle;
public static final field SOLID Lcom/facebook/react/uimanager/style/BorderStyle;
public static final fun fromString (Ljava/lang/String;)Lcom/facebook/react/uimanager/style/BorderStyle;
public static fun getEntries ()Lkotlin/enums/EnumEntries;
public static fun valueOf (Ljava/lang/String;)Lcom/facebook/react/uimanager/style/BorderStyle;
public static fun values ()[Lcom/facebook/react/uimanager/style/BorderStyle;
}

public final class com/facebook/react/uimanager/style/BorderStyle$Companion {
public final fun fromString (Ljava/lang/String;)Lcom/facebook/react/uimanager/style/BorderStyle;
}

public final class com/facebook/react/uimanager/style/BoxShadow {
public static final field Companion Lcom/facebook/react/uimanager/style/BoxShadow$Companion;
public fun <init> (FFLjava/lang/Integer;Ljava/lang/Float;Ljava/lang/Float;Ljava/lang/Boolean;)V
public synthetic fun <init> (FFLjava/lang/Integer;Ljava/lang/Float;Ljava/lang/Float;Ljava/lang/Boolean;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
public final fun component1 ()F
public final fun component2 ()F
public final fun component3 ()Ljava/lang/Integer;
public final fun component4 ()Ljava/lang/Float;
public final fun component5 ()Ljava/lang/Float;
public final fun component6 ()Ljava/lang/Boolean;
public final fun copy (FFLjava/lang/Integer;Ljava/lang/Float;Ljava/lang/Float;Ljava/lang/Boolean;)Lcom/facebook/react/uimanager/style/BoxShadow;
public static synthetic fun copy$default (Lcom/facebook/react/uimanager/style/BoxShadow;FFLjava/lang/Integer;Ljava/lang/Float;Ljava/lang/Float;Ljava/lang/Boolean;ILjava/lang/Object;)Lcom/facebook/react/uimanager/style/BoxShadow;
public fun equals (Ljava/lang/Object;)Z
public final fun getBlurRadius ()Ljava/lang/Float;
public final fun getColor ()Ljava/lang/Integer;
public final fun getInset ()Ljava/lang/Boolean;
public final fun getOffsetX ()F
public final fun getOffsetY ()F
public final fun getSpreadRadius ()Ljava/lang/Float;
public fun hashCode ()I
public static final fun parse (Lcom/facebook/react/bridge/ReadableMap;)Lcom/facebook/react/uimanager/style/BoxShadow;
public fun toString ()Ljava/lang/String;
}

public final class com/facebook/react/uimanager/style/BoxShadow$Companion {
public final fun parse (Lcom/facebook/react/bridge/ReadableMap;)Lcom/facebook/react/uimanager/style/BoxShadow;
}

public final class com/facebook/react/uimanager/style/ComputedBorderRadius {
public fun <init> ()V
public fun <init> (FFFF)V
Expand Down Expand Up @@ -5945,6 +6004,47 @@ public final class com/facebook/react/uimanager/style/ComputedBorderRadiusProp :
public static fun values ()[Lcom/facebook/react/uimanager/style/ComputedBorderRadiusProp;
}

public abstract class com/facebook/react/uimanager/style/LogicalEdge : java/lang/Enum {
public static final field ALL Lcom/facebook/react/uimanager/style/LogicalEdge;
public static final field BLOCK Lcom/facebook/react/uimanager/style/LogicalEdge;
public static final field BLOCK_END Lcom/facebook/react/uimanager/style/LogicalEdge;
public static final field BLOCK_START Lcom/facebook/react/uimanager/style/LogicalEdge;
public static final field BOTTOM Lcom/facebook/react/uimanager/style/LogicalEdge;
public static final field Companion Lcom/facebook/react/uimanager/style/LogicalEdge$Companion;
public static final field END Lcom/facebook/react/uimanager/style/LogicalEdge;
public static final field HORIZONTAL Lcom/facebook/react/uimanager/style/LogicalEdge;
public static final field LEFT Lcom/facebook/react/uimanager/style/LogicalEdge;
public static final field RIGHT Lcom/facebook/react/uimanager/style/LogicalEdge;
public static final field START Lcom/facebook/react/uimanager/style/LogicalEdge;
public static final field TOP Lcom/facebook/react/uimanager/style/LogicalEdge;
public static final field VERTICAL Lcom/facebook/react/uimanager/style/LogicalEdge;
public synthetic fun <init> (Ljava/lang/String;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
public static final fun fromSpacingType (I)Lcom/facebook/react/uimanager/style/LogicalEdge;
public static fun getEntries ()Lkotlin/enums/EnumEntries;
public abstract fun toSpacingType ()I
public static fun valueOf (Ljava/lang/String;)Lcom/facebook/react/uimanager/style/LogicalEdge;
public static fun values ()[Lcom/facebook/react/uimanager/style/LogicalEdge;
}

public final class com/facebook/react/uimanager/style/LogicalEdge$Companion {
public final fun fromSpacingType (I)Lcom/facebook/react/uimanager/style/LogicalEdge;
}

public final class com/facebook/react/uimanager/style/Overflow : java/lang/Enum {
public static final field Companion Lcom/facebook/react/uimanager/style/Overflow$Companion;
public static final field HIDDEN Lcom/facebook/react/uimanager/style/Overflow;
public static final field SCROLL Lcom/facebook/react/uimanager/style/Overflow;
public static final field VISIBLE Lcom/facebook/react/uimanager/style/Overflow;
public static final fun fromString (Ljava/lang/String;)Lcom/facebook/react/uimanager/style/Overflow;
public static fun getEntries ()Lkotlin/enums/EnumEntries;
public static fun valueOf (Ljava/lang/String;)Lcom/facebook/react/uimanager/style/Overflow;
public static fun values ()[Lcom/facebook/react/uimanager/style/Overflow;
}

public final class com/facebook/react/uimanager/style/Overflow$Companion {
public final fun fromString (Ljava/lang/String;)Lcom/facebook/react/uimanager/style/Overflow;
}

public class com/facebook/react/uimanager/util/ReactFindViewUtil {
public fun <init> ()V
public static fun addViewListener (Lcom/facebook/react/uimanager/util/ReactFindViewUtil$OnViewFoundListener;)V
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,184 @@
/*
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/

package com.facebook.react.uimanager

import android.graphics.Canvas
import android.graphics.Color
import android.graphics.Rect
import android.view.View
import androidx.annotation.ColorInt
import androidx.annotation.RequiresApi
import com.facebook.react.common.annotations.UnstableReactNativeAPI
import com.facebook.react.uimanager.drawable.CSSBackgroundDrawable
import com.facebook.react.uimanager.drawable.CompositeBackgroundDrawable
import com.facebook.react.uimanager.drawable.InsetBoxShadowDrawable
import com.facebook.react.uimanager.drawable.OutsetBoxShadowDrawable
import com.facebook.react.uimanager.style.BorderRadiusProp
import com.facebook.react.uimanager.style.BorderStyle
import com.facebook.react.uimanager.style.BoxShadow
import com.facebook.react.uimanager.style.LogicalEdge

/**
* BackgroundStyleApplicator is responsible for applying backgrounds, borders, and related effects,
* to an Android view
*/
@OptIn(UnstableReactNativeAPI::class)
public object BackgroundStyleApplicator {

@JvmStatic
public fun setBackgroundColor(view: View, @ColorInt color: Int?): Unit {
// No color to set, and no color already set
if ((color == null || color == Color.TRANSPARENT) &&
view.background !is CompositeBackgroundDrawable) {
return
}

ensureCSSBackground(view).color = color ?: Color.TRANSPARENT
}

@JvmStatic
@ColorInt
public fun getBackgroundColor(view: View): Int? = getCSSBackground(view)?.color

@JvmStatic
public fun setBorderWidth(view: View, edge: LogicalEdge, width: Float?): Unit =
ensureCSSBackground(view)
.setBorderWidth(edge.toSpacingType(), PixelUtil.toPixelFromDIP(width ?: Float.NaN))

@JvmStatic
public fun getBorderWidth(view: View, edge: LogicalEdge): Float? {
val width = getCSSBackground(view)?.getBorderWidth(edge.toSpacingType())
return if (width == null || width.isNaN()) null else PixelUtil.toDIPFromPixel((width))
}

@JvmStatic
public fun setBorderColor(view: View, edge: LogicalEdge, @ColorInt color: Int?): Unit =
ensureCSSBackground(view).setBorderColor(edge.toSpacingType(), color)

@JvmStatic
@ColorInt
public fun getBorderColor(view: View, edge: LogicalEdge): Int? =
getCSSBackground(view)?.getBorderColor(edge.toSpacingType())

@JvmStatic
public fun setBorderRadius(
view: View,
corner: BorderRadiusProp,
// TODO: LengthPercentage silently converts from pixels to DIPs before here already
radius: LengthPercentage?
): Unit = ensureCSSBackground(view).setBorderRadius(corner, radius)

@JvmStatic
public fun getBorderRadius(view: View, corner: BorderRadiusProp): LengthPercentage? =
getCSSBackground(view)?.borderRadius?.get(corner)

@JvmStatic
public fun setBorderStyle(view: View, borderStyle: BorderStyle?): Unit {
ensureCSSBackground(view).borderStyle = borderStyle
}

@JvmStatic
public fun getBorderStyle(view: View): BorderStyle? = getCSSBackground(view)?.borderStyle

@JvmStatic
@RequiresApi(31)
public fun setShadows(view: View, shadows: List<BoxShadow>): Unit {
val shadowDrawables =
shadows.map { boxShadow ->
val offsetX = boxShadow.offsetX
val offsetY = boxShadow.offsetY
val color = boxShadow.color ?: Color.TRANSPARENT
val blurRadius = boxShadow.blurRadius ?: 0f
val spreadRadius = boxShadow.spreadRadius ?: 0f
val inset = boxShadow.inset ?: false

if (inset)
InsetBoxShadowDrawable(
view.context,
ensureCSSBackground(view),
color,
offsetX,
offsetY,
blurRadius,
spreadRadius)
else
OutsetBoxShadowDrawable(
view.context,
ensureCSSBackground(view),
color,
offsetX,
offsetY,
blurRadius,
spreadRadius)
}

updateCompositeDrawable(
view,
ensureCompositeBackgroundDrawable(view).withNewShadows(shadowDrawables.toTypedArray()))
}

@JvmStatic
public fun clipToPaddingBox(view: View, canvas: Canvas): Unit {
// The canvas may be scrolled, so we need to offset
val drawingRect = Rect()
view.getDrawingRect(drawingRect)

val cssBackground = getCSSBackground(view)
if (cssBackground == null) {
canvas.clipRect(drawingRect)
return
}

val paddingBoxPath = cssBackground.paddingBoxPath
if (paddingBoxPath != null) {
paddingBoxPath.offset(drawingRect.left.toFloat(), drawingRect.top.toFloat())
canvas.clipPath(paddingBoxPath)
} else {
val paddingBoxRect = cssBackground.paddingBoxRect
paddingBoxRect.offset(drawingRect.left.toFloat(), drawingRect.top.toFloat())
canvas.clipRect(paddingBoxRect)
}
}

private fun updateCompositeDrawable(
view: View,
compositeDrawable: CompositeBackgroundDrawable
): Unit {
view.background = null
view.background = compositeDrawable
view.invalidate()
}

private fun ensureCompositeBackgroundDrawable(view: View): CompositeBackgroundDrawable {
if (view.background is CompositeBackgroundDrawable) {
return view.background as CompositeBackgroundDrawable
}

val compositeDrawable = CompositeBackgroundDrawable(view.background, null, emptyArray(), null)
updateCompositeDrawable(view, compositeDrawable)
return compositeDrawable
}

private fun ensureCSSBackground(view: View): CSSBackgroundDrawable {
val compositeBackgroundDrawable = ensureCompositeBackgroundDrawable(view)
if (compositeBackgroundDrawable.cssBackground != null) {
return compositeBackgroundDrawable.cssBackground
} else {
val cssBackground = CSSBackgroundDrawable(view.context)
updateCompositeDrawable(view, compositeBackgroundDrawable.withNewCssBackground(cssBackground))
return cssBackground
}
}

private fun getCSSBackground(view: View): CSSBackgroundDrawable? {
if (view.background is CompositeBackgroundDrawable) {
return (view.background as CompositeBackgroundDrawable).cssBackground
}
return null
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -15,20 +15,32 @@ public object PixelUtil {
/** Convert from DIP to PX */
@JvmStatic
public fun toPixelFromDIP(value: Float): Float {
if (value.isNaN()) {
return Float.NaN
}

return TypedValue.applyDimension(
TypedValue.COMPLEX_UNIT_DIP, value, DisplayMetricsHolder.getWindowDisplayMetrics())
}

/** Convert from DIP to PX */
@JvmStatic
public fun toPixelFromDIP(value: Double): Float {
if (value.isNaN()) {
return Float.NaN
}

return toPixelFromDIP(value.toFloat())
}

/** Convert from SP to PX */
@JvmOverloads
@JvmStatic
public fun toPixelFromSP(value: Float, maxFontScale: Float = Float.NaN): Float {
if (value.isNaN()) {
return Float.NaN
}

val displayMetrics = DisplayMetricsHolder.getWindowDisplayMetrics()
val scaledValue = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP, value, displayMetrics)

Expand All @@ -42,12 +54,20 @@ public object PixelUtil {
/** Convert from SP to PX */
@JvmStatic
public fun toPixelFromSP(value: Double): Float {
if (value.isNaN()) {
return Float.NaN
}

return toPixelFromSP(value.toFloat())
}

/** Convert from PX to DP */
@JvmStatic
public fun toDIPFromPixel(value: Float): Float {
if (value.isNaN()) {
return Float.NaN
}

return value / DisplayMetricsHolder.getWindowDisplayMetrics().density
}

Expand Down
Loading