From 807b43f267a0fce7966c2cd61618f68604f1f3b9 Mon Sep 17 00:00:00 2001 From: Nick Gerleman Date: Thu, 25 Jul 2024 17:09:56 -0700 Subject: [PATCH 1/4] Expose string types for `boxShadow` and `filter` Summary: We built these to be able to parse web style string values, but the types only allow object form, and the TypeScript type is wrong. Changelog: [Internal] Differential Revision: D60263730 --- .../react-native/Libraries/StyleSheet/StyleSheetTypes.js | 4 ++-- .../__tests__/__snapshots__/public-api-test.js.snap | 4 ++-- packages/react-native/types/experimental.d.ts | 7 +++++-- 3 files changed, 9 insertions(+), 6 deletions(-) diff --git a/packages/react-native/Libraries/StyleSheet/StyleSheetTypes.js b/packages/react-native/Libraries/StyleSheet/StyleSheetTypes.js index 0f00224adfff..2db5431fc564 100644 --- a/packages/react-native/Libraries/StyleSheet/StyleSheetTypes.js +++ b/packages/react-native/Libraries/StyleSheet/StyleSheetTypes.js @@ -778,8 +778,8 @@ export type ____ViewStyle_InternalCore = $ReadOnly<{ elevation?: number, pointerEvents?: 'auto' | 'none' | 'box-none' | 'box-only', cursor?: CursorValue, - experimental_boxShadow?: $ReadOnlyArray, - experimental_filter?: $ReadOnlyArray, + experimental_boxShadow?: $ReadOnlyArray | string, + experimental_filter?: $ReadOnlyArray | string, experimental_mixBlendMode?: ____BlendMode_Internal, }>; diff --git a/packages/react-native/Libraries/__tests__/__snapshots__/public-api-test.js.snap b/packages/react-native/Libraries/__tests__/__snapshots__/public-api-test.js.snap index 910d0b3f0f4f..b5532794cb6d 100644 --- a/packages/react-native/Libraries/__tests__/__snapshots__/public-api-test.js.snap +++ b/packages/react-native/Libraries/__tests__/__snapshots__/public-api-test.js.snap @@ -8776,8 +8776,8 @@ export type ____ViewStyle_InternalCore = $ReadOnly<{ elevation?: number, pointerEvents?: \\"auto\\" | \\"none\\" | \\"box-none\\" | \\"box-only\\", cursor?: CursorValue, - experimental_boxShadow?: $ReadOnlyArray, - experimental_filter?: $ReadOnlyArray, + experimental_boxShadow?: $ReadOnlyArray | string, + experimental_filter?: $ReadOnlyArray | string, experimental_mixBlendMode?: ____BlendMode_Internal, }>; export type ____ViewStyle_Internal = $ReadOnly<{ diff --git a/packages/react-native/types/experimental.d.ts b/packages/react-native/types/experimental.d.ts index deea3034b457..859252932a97 100644 --- a/packages/react-native/types/experimental.d.ts +++ b/packages/react-native/types/experimental.d.ts @@ -149,8 +149,11 @@ declare module '.' { } export interface ViewStyle { - experimental_boxShadow?: BoxShadowPrimitive | undefined; - experimental_filter?: ReadonlyArray | undefined; + experimental_boxShadow?: + | ReadonlyArray + | string + | undefined; + experimental_filter?: ReadonlyArray | string | undefined; experimental_mixBlendMode?: BlendMode | undefined; } } From a1bbf1721b3137a084f7751f356e031d7d33779d Mon Sep 17 00:00:00 2001 From: Nick Gerleman Date: Thu, 25 Jul 2024 23:22:48 -0700 Subject: [PATCH 2/4] Add more style value types Differential Revision: D60252277 --- .../ReactAndroid/api/ReactAndroid.api | 84 +++++++++++++++++++ .../react/uimanager/style/BorderStyle.kt | 26 ++++++ .../react/uimanager/style/BoxShadow.kt | 50 +++++++++++ .../react/uimanager/style/LogicalEdge.kt | 79 +++++++++++++++++ .../react/uimanager/style/Overflow.kt | 26 ++++++ 5 files changed, 265 insertions(+) create mode 100644 packages/react-native/ReactAndroid/src/main/java/com/facebook/react/uimanager/style/BorderStyle.kt create mode 100644 packages/react-native/ReactAndroid/src/main/java/com/facebook/react/uimanager/style/BoxShadow.kt create mode 100644 packages/react-native/ReactAndroid/src/main/java/com/facebook/react/uimanager/style/LogicalEdge.kt create mode 100644 packages/react-native/ReactAndroid/src/main/java/com/facebook/react/uimanager/style/Overflow.kt diff --git a/packages/react-native/ReactAndroid/api/ReactAndroid.api b/packages/react-native/ReactAndroid/api/ReactAndroid.api index 8afeee79e05f..05f2a3eba089 100644 --- a/packages/react-native/ReactAndroid/api/ReactAndroid.api +++ b/packages/react-native/ReactAndroid/api/ReactAndroid.api @@ -5915,6 +5915,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 (FFLjava/lang/Integer;Ljava/lang/Float;Ljava/lang/Float;Ljava/lang/Boolean;)V + public synthetic fun (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 getSpreadDistance ()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 ()V public fun (FFFF)V @@ -5945,6 +5988,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 (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 ()V public static fun addViewListener (Lcom/facebook/react/uimanager/util/ReactFindViewUtil$OnViewFoundListener;)V diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/uimanager/style/BorderStyle.kt b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/uimanager/style/BorderStyle.kt new file mode 100644 index 000000000000..c23030b3fc90 --- /dev/null +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/uimanager/style/BorderStyle.kt @@ -0,0 +1,26 @@ +/* + * 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.style + +public enum class BorderStyle { + SOLID, + DASHED, + DOTTED; + + public companion object { + @JvmStatic + public fun fromString(borderStyle: String): BorderStyle? { + return when (borderStyle.lowercase()) { + "solid" -> SOLID + "dashed" -> DASHED + "dotted" -> DOTTED + else -> null + } + } + } +} diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/uimanager/style/BoxShadow.kt b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/uimanager/style/BoxShadow.kt new file mode 100644 index 000000000000..0282f4581a86 --- /dev/null +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/uimanager/style/BoxShadow.kt @@ -0,0 +1,50 @@ +/* + * 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.style + +import androidx.annotation.ColorInt +import com.facebook.react.bridge.ReadableMap + +/** Represents all logical properties and shorthands for border radius. */ +public data class BoxShadow( + val offsetX: Float, + val offsetY: Float, + @ColorInt val color: Int? = null, + val blurRadius: Float? = null, + val spreadDistance: Float? = null, + val inset: Boolean? = null, +) { + public companion object { + @JvmStatic + public fun parse(boxShadow: ReadableMap): BoxShadow? { + if (!(boxShadow.hasKey("offsetX") && boxShadow.hasKey("offsetY"))) { + return null + } + + val offsetX = boxShadow.getDouble("offsetX").toFloat() + val offsetY = boxShadow.getDouble("offsetY").toFloat() + + val color = if (boxShadow.hasKey("color")) boxShadow.getInt("color") else null + val blurRadius = + if (boxShadow.hasKey("blurRadius")) boxShadow.getDouble("blurRadius").toFloat() else null + val spreadDistance = + if (boxShadow.hasKey("spreadDistance")) boxShadow.getDouble("spreadDistance").toFloat() + else null + val inset = if (boxShadow.hasKey("inset")) boxShadow.getBoolean("inset") else null + + return BoxShadow( + offsetX = offsetX, + offsetY = offsetY, + color = color, + blurRadius = blurRadius, + spreadDistance = spreadDistance, + inset = inset, + ) + } + } +} diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/uimanager/style/LogicalEdge.kt b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/uimanager/style/LogicalEdge.kt new file mode 100644 index 000000000000..1f35909d6f00 --- /dev/null +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/uimanager/style/LogicalEdge.kt @@ -0,0 +1,79 @@ +/* + * 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.style + +import com.facebook.react.uimanager.Spacing +import java.lang.IllegalArgumentException + +/** Represents the collection of possible box edges and shorthands. */ +public enum class LogicalEdge { + ALL { + override fun toSpacingType(): Int = Spacing.ALL + }, + LEFT { + override fun toSpacingType(): Int = Spacing.LEFT + }, + RIGHT { + override fun toSpacingType(): Int = Spacing.RIGHT + }, + TOP { + override fun toSpacingType(): Int = Spacing.TOP + }, + BOTTOM { + override fun toSpacingType(): Int = Spacing.BOTTOM + }, + START { + override fun toSpacingType(): Int = Spacing.START + }, + END { + override fun toSpacingType(): Int = Spacing.END + }, + HORIZONTAL { + override fun toSpacingType(): Int = Spacing.HORIZONTAL + }, + VERTICAL { + override fun toSpacingType(): Int = Spacing.VERTICAL + }, + BLOCK_START { + override fun toSpacingType(): Int = Spacing.BLOCK_START + }, + BLOCK_END { + override fun toSpacingType(): Int = Spacing.BLOCK_END + }, + BLOCK { + override fun toSpacingType(): Int = Spacing.BLOCK + }; + + // TODO: not supported by Spacing users + // INLINE_START, + // INLINE_END, + // INLINE; + + abstract public fun toSpacingType(): Int + + public companion object { + @JvmStatic + public fun fromSpacingType(spacingType: Int): LogicalEdge { + return when (spacingType) { + Spacing.ALL -> ALL + Spacing.LEFT -> LEFT + Spacing.RIGHT -> RIGHT + Spacing.TOP -> TOP + Spacing.BOTTOM -> BOTTOM + Spacing.START -> START + Spacing.END -> END + Spacing.HORIZONTAL -> HORIZONTAL + Spacing.VERTICAL -> VERTICAL + Spacing.BLOCK_START -> BLOCK_START + Spacing.BLOCK_END -> BLOCK_END + Spacing.BLOCK -> BLOCK + else -> throw IllegalArgumentException("Unknown spacing type: $spacingType") + } + } + } +} diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/uimanager/style/Overflow.kt b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/uimanager/style/Overflow.kt new file mode 100644 index 000000000000..a057a79b144d --- /dev/null +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/uimanager/style/Overflow.kt @@ -0,0 +1,26 @@ +/* + * 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.style + +public enum class Overflow { + VISIBLE, + HIDDEN, + SCROLL; + + public companion object { + @JvmStatic + public fun fromString(overflow: String): Overflow { + return when (overflow.lowercase()) { + "visible" -> VISIBLE + "hidden" -> HIDDEN + "scroll" -> SCROLL + else -> throw IllegalArgumentException("Unknown overflow: $overflow") + } + } + } +} From 6dcb10d3eef020509d87bed03c87ac50ac5b8a37 Mon Sep 17 00:00:00 2001 From: Nick Gerleman Date: Thu, 25 Jul 2024 23:22:48 -0700 Subject: [PATCH 3/4] Expose more in CSSBackgroundDrawable Differential Revision: D60252276 --- .../drawable/CSSBackgroundDrawable.java | 59 +++++++++++-------- 1 file changed, 36 insertions(+), 23 deletions(-) diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/uimanager/drawable/CSSBackgroundDrawable.java b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/uimanager/drawable/CSSBackgroundDrawable.java index 7369bc9de442..6b3bea46ab28 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/uimanager/drawable/CSSBackgroundDrawable.java +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/uimanager/drawable/CSSBackgroundDrawable.java @@ -36,6 +36,7 @@ import com.facebook.react.uimanager.Spacing; import com.facebook.react.uimanager.style.BorderRadiusProp; import com.facebook.react.uimanager.style.BorderRadiusStyle; +import com.facebook.react.uimanager.style.BorderStyle; import com.facebook.react.uimanager.style.ComputedBorderRadius; import java.util.Locale; import java.util.Objects; @@ -64,29 +65,23 @@ public class CSSBackgroundDrawable extends Drawable { // 0 == 0x00000000, all bits set to 0. private static final int ALL_BITS_UNSET = 0; - private enum BorderStyle { - SOLID, - DASHED, - DOTTED; + private static @Nullable PathEffect getPathEffect(BorderStyle style, float borderWidth) { + switch (style) { + case SOLID: + return null; - public static @Nullable PathEffect getPathEffect(BorderStyle style, float borderWidth) { - switch (style) { - case SOLID: - return null; + case DASHED: + return new DashPathEffect( + new float[] {borderWidth * 3, borderWidth * 3, borderWidth * 3, borderWidth * 3}, 0); - case DASHED: - return new DashPathEffect( - new float[] {borderWidth * 3, borderWidth * 3, borderWidth * 3, borderWidth * 3}, 0); + case DOTTED: + return new DashPathEffect( + new float[] {borderWidth, borderWidth, borderWidth, borderWidth}, 0); - case DOTTED: - return new DashPathEffect( - new float[] {borderWidth, borderWidth, borderWidth, borderWidth}, 0); - - default: - return null; - } + default: + return null; } - }; + } /* Value at Spacing.ALL index used for rounded borders, whole array used by rectangular borders */ private @Nullable Spacing mBorderWidth; @@ -255,6 +250,10 @@ private void setBorderAlpha(int position, float alpha) { public void setBorderStyle(@Nullable String style) { BorderStyle borderStyle = style == null ? null : BorderStyle.valueOf(style.toUpperCase(Locale.US)); + setBorderStyle(borderStyle); + } + + public void setBorderStyle(@Nullable BorderStyle borderStyle) { if (mBorderStyle != borderStyle) { mBorderStyle = borderStyle; mNeedUpdatePathForBorderRadius = true; @@ -262,6 +261,10 @@ public void setBorderStyle(@Nullable String style) { } } + public @Nullable BorderStyle getBorderStyle() { + return mBorderStyle; + } + /** * @deprecated Use {@link #setBorderRadius(BorderRadiusProp, LengthPercentage)} instead. */ @@ -286,6 +289,7 @@ public void setRadius(float radius, int position) { if (boxedRadius == null) { mBorderRadius.set(BorderRadiusProp.values()[position], null); + invalidateSelf(); } else { setBorderRadius( BorderRadiusProp.values()[position], @@ -1012,14 +1016,23 @@ private static void getEllipseIntersectionWithLine( } public float getBorderWidthOrDefaultTo(final float defaultValue, final int spacingType) { - if (mBorderWidth == null) { + @Nullable Float width = getBorderWidth(spacingType); + if (width == null) { return defaultValue; } + return width; + } + + public @Nullable Float getBorderWidth(int spacingType) { + if (mBorderWidth == null) { + return null; + } + final float width = mBorderWidth.getRaw(spacingType); if (Float.isNaN(width)) { - return defaultValue; + return null; } return width; @@ -1029,7 +1042,7 @@ public float getBorderWidthOrDefaultTo(final float defaultValue, final int spaci private void updatePathEffect() { // Used for rounded border and rounded background PathEffect mPathEffectForBorderStyle = - mBorderStyle != null ? BorderStyle.getPathEffect(mBorderStyle, getFullBorderWidth()) : null; + mBorderStyle != null ? getPathEffect(mBorderStyle, getFullBorderWidth()) : null; mPaint.setPathEffect(mPathEffectForBorderStyle); } @@ -1037,7 +1050,7 @@ private void updatePathEffect() { private void updatePathEffect(int borderWidth) { PathEffect pathEffectForBorderStyle = null; if (mBorderStyle != null) { - pathEffectForBorderStyle = BorderStyle.getPathEffect(mBorderStyle, borderWidth); + pathEffectForBorderStyle = getPathEffect(mBorderStyle, borderWidth); } mPaint.setPathEffect(pathEffectForBorderStyle); } From 92e580504b5eedcbbbe8c9140b8719aa3eeea7a4 Mon Sep 17 00:00:00 2001 From: Nick Gerleman Date: Fri, 26 Jul 2024 00:43:13 -0700 Subject: [PATCH 4/4] Handle NaN values in PixelUtil (#45690) Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/45690 ViewManager layer often uses `YogaConstants.UNDEFINED` (`NaN`) as null-state value. Teaching PixelUtil how to handle `NaN` values makes glue code around easier. Changelog: [Internal] Differential Revision: D60265329 --- .../java/com/facebook/react/uimanager/PixelUtil.kt | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/uimanager/PixelUtil.kt b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/uimanager/PixelUtil.kt index 48f1f1e2f246..3d379268e8e9 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/uimanager/PixelUtil.kt +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/uimanager/PixelUtil.kt @@ -15,6 +15,10 @@ 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()) } @@ -29,6 +33,10 @@ public object PixelUtil { @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) @@ -48,6 +56,10 @@ public object PixelUtil { /** Convert from PX to DP */ @JvmStatic public fun toDIPFromPixel(value: Float): Float { + if (value.isNaN()) { + return Float.NaN + } + return value / DisplayMetricsHolder.getWindowDisplayMetrics().density }