mirror of
https://github.com/facebook/react-native.git
synced 2025-11-01 09:14:26 +00:00
Do not implicitly convert parsed LengthPercentage to pixels (#45987)
Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/45987 This is a confusing public API, because styles layer deals with DIPs, conversion only happens when parsing dynamic, and `POINT` (the `LengthPercentageType`) also maps to DIPs instead of physical pixels. This moves conversion to physical pixels to drawing layer, so everything above `BackgroundStyleApplicator` works with `style` types which are all in DIPs. To preserve compatibility with existing APIs using raw radii, we keep it so that (most) views operate in pixel units, while view managers operate under DIPs. Changelog: [Android][Breaking] Do not implicitly convert parsed LengthPercentage to pixels Reviewed By: rshest Differential Revision: D60507151 fbshipit-source-id: b90066af7b221304aded374627fc0e2165dfc08f
This commit is contained in:
committed by
Facebook GitHub Bot
parent
3ee94174b4
commit
9e48976bc2
@@ -4359,9 +4359,15 @@ public final class com/facebook/react/uimanager/LengthPercentage {
|
||||
public static final field Companion Lcom/facebook/react/uimanager/LengthPercentage$Companion;
|
||||
public fun <init> ()V
|
||||
public fun <init> (FLcom/facebook/react/uimanager/LengthPercentageType;)V
|
||||
public final fun getUnit ()Lcom/facebook/react/uimanager/LengthPercentageType;
|
||||
public final fun component2 ()Lcom/facebook/react/uimanager/LengthPercentageType;
|
||||
public final fun copy (FLcom/facebook/react/uimanager/LengthPercentageType;)Lcom/facebook/react/uimanager/LengthPercentage;
|
||||
public static synthetic fun copy$default (Lcom/facebook/react/uimanager/LengthPercentage;FLcom/facebook/react/uimanager/LengthPercentageType;ILjava/lang/Object;)Lcom/facebook/react/uimanager/LengthPercentage;
|
||||
public fun equals (Ljava/lang/Object;)Z
|
||||
public final fun getType ()Lcom/facebook/react/uimanager/LengthPercentageType;
|
||||
public fun hashCode ()I
|
||||
public final fun resolve (FF)F
|
||||
public static final fun setFromDynamic (Lcom/facebook/react/bridge/Dynamic;)Lcom/facebook/react/uimanager/LengthPercentage;
|
||||
public fun toString ()Ljava/lang/String;
|
||||
}
|
||||
|
||||
public final class com/facebook/react/uimanager/LengthPercentage$Companion {
|
||||
|
||||
-1
@@ -74,7 +74,6 @@ public object BackgroundStyleApplicator {
|
||||
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)
|
||||
|
||||
+4
-4
@@ -18,9 +18,9 @@ public enum class LengthPercentageType {
|
||||
PERCENT,
|
||||
}
|
||||
|
||||
public class LengthPercentage(
|
||||
public data class LengthPercentage(
|
||||
private val value: Float,
|
||||
public val unit: LengthPercentageType,
|
||||
public val type: LengthPercentageType,
|
||||
) {
|
||||
public companion object {
|
||||
@JvmStatic
|
||||
@@ -29,7 +29,7 @@ public class LengthPercentage(
|
||||
ReadableType.Number -> {
|
||||
val value = dynamic.asDouble()
|
||||
if (value >= 0f) {
|
||||
LengthPercentage(PixelUtil.toPixelFromDIP(value), LengthPercentageType.POINT)
|
||||
LengthPercentage(value.toFloat(), LengthPercentageType.POINT)
|
||||
} else {
|
||||
null
|
||||
}
|
||||
@@ -62,7 +62,7 @@ public class LengthPercentage(
|
||||
}
|
||||
|
||||
public fun resolve(width: Float, height: Float): Float {
|
||||
if (unit == LengthPercentageType.PERCENT) {
|
||||
if (type == LengthPercentageType.PERCENT) {
|
||||
return (value / 100) * Math.min(width, height)
|
||||
}
|
||||
|
||||
|
||||
+10
-6
@@ -36,6 +36,7 @@ import com.facebook.react.modules.i18nmanager.I18nUtil;
|
||||
import com.facebook.react.uimanager.FloatUtil;
|
||||
import com.facebook.react.uimanager.LengthPercentage;
|
||||
import com.facebook.react.uimanager.LengthPercentageType;
|
||||
import com.facebook.react.uimanager.PixelUtil;
|
||||
import com.facebook.react.uimanager.Spacing;
|
||||
import com.facebook.react.uimanager.style.BorderRadiusProp;
|
||||
import com.facebook.react.uimanager.style.BorderRadiusStyle;
|
||||
@@ -324,6 +325,9 @@ public class CSSBackgroundDrawable extends Drawable {
|
||||
return Math.max(computedRadius - borderWidth, 0);
|
||||
}
|
||||
|
||||
// TODO: This API is unsafe and should be removed when
|
||||
// BackgroundStyleApplicator is rolled out
|
||||
@Deprecated(forRemoval = true, since = "0.76.0")
|
||||
public ComputedBorderRadius getComputedBorderRadius() {
|
||||
return mComputedBorderRadius;
|
||||
}
|
||||
@@ -660,12 +664,12 @@ public class CSSBackgroundDrawable extends Drawable {
|
||||
mBorderRadius.resolve(
|
||||
getLayoutDirection(),
|
||||
mContext,
|
||||
mOuterClipTempRectForBorderRadius.width(),
|
||||
mOuterClipTempRectForBorderRadius.height());
|
||||
float topLeftRadius = mComputedBorderRadius.getTopLeft();
|
||||
float topRightRadius = mComputedBorderRadius.getTopRight();
|
||||
float bottomLeftRadius = mComputedBorderRadius.getBottomLeft();
|
||||
float bottomRightRadius = mComputedBorderRadius.getBottomRight();
|
||||
PixelUtil.toDIPFromPixel(mOuterClipTempRectForBorderRadius.width()),
|
||||
PixelUtil.toDIPFromPixel(mOuterClipTempRectForBorderRadius.height()));
|
||||
float topLeftRadius = PixelUtil.toPixelFromDIP(mComputedBorderRadius.getTopLeft());
|
||||
float topRightRadius = PixelUtil.toPixelFromDIP(mComputedBorderRadius.getTopRight());
|
||||
float bottomLeftRadius = PixelUtil.toPixelFromDIP(mComputedBorderRadius.getBottomLeft());
|
||||
float bottomRightRadius = PixelUtil.toPixelFromDIP(mComputedBorderRadius.getBottomRight());
|
||||
|
||||
final float innerTopLeftRadiusX = getInnerBorderRadius(topLeftRadius, borderWidth.left);
|
||||
final float innerTopLeftRadiusY = getInnerBorderRadius(topLeftRadius, borderWidth.top);
|
||||
|
||||
+8
-4
@@ -130,17 +130,21 @@ internal class InsetBoxShadowDrawable(
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: Remove usage of unsafe `CSSBackgroundDrawable.getComputedBorderRadius`
|
||||
@Suppress("DEPRECATION")
|
||||
private fun getClearRegionBorderRadii(
|
||||
spread: Int,
|
||||
background: CSSBackgroundDrawable,
|
||||
): BorderRadiusStyle {
|
||||
// Accessing this is super duper unsafe and only works because the CSSBackgroundDrawable renders
|
||||
// first
|
||||
val computedBorderRadii = background.computedBorderRadius
|
||||
val borderWidth = background.getDirectionAwareBorderInsets()
|
||||
|
||||
val topLeftRadius = computedBorderRadii.topLeft
|
||||
val topRightRadius = computedBorderRadii.topRight
|
||||
val bottomLeftRadius = computedBorderRadii.bottomLeft
|
||||
val bottomRightRadius = computedBorderRadii.bottomRight
|
||||
val topLeftRadius = PixelUtil.toPixelFromDIP(computedBorderRadii.topLeft)
|
||||
val topRightRadius = PixelUtil.toPixelFromDIP(computedBorderRadii.topRight)
|
||||
val bottomLeftRadius = PixelUtil.toPixelFromDIP(computedBorderRadii.bottomLeft)
|
||||
val bottomRightRadius = PixelUtil.toPixelFromDIP(computedBorderRadii.bottomRight)
|
||||
|
||||
val innerTopLeftRadius = background.getInnerBorderRadius(topLeftRadius, borderWidth.left)
|
||||
val innerTopRightRadius = background.getInnerBorderRadius(topRightRadius, borderWidth.right)
|
||||
|
||||
+10
-3
@@ -86,10 +86,17 @@ internal class OutsetBoxShadowDrawable(
|
||||
val shadowShapeFrame = Rect(bounds).apply { inset(-spreadExtent, -spreadExtent) }
|
||||
val shadowShapeBounds = Rect(0, 0, shadowShapeFrame.width(), shadowShapeFrame.height())
|
||||
|
||||
val resolutionWidth = bounds.width().toFloat()
|
||||
val resolutionHeight = bounds.height().toFloat()
|
||||
val resolutionWidth = PixelUtil.toDIPFromPixel(bounds.width().toFloat())
|
||||
val resolutionHeight = PixelUtil.toDIPFromPixel(bounds.height().toFloat())
|
||||
val computedBorderRadii =
|
||||
borderRadius?.resolve(layoutDirection, context, resolutionWidth, resolutionHeight)
|
||||
borderRadius?.resolve(layoutDirection, context, resolutionWidth, resolutionHeight)?.let {
|
||||
ComputedBorderRadius(
|
||||
topLeft = PixelUtil.toPixelFromDIP(it.topLeft),
|
||||
topRight = PixelUtil.toPixelFromDIP(it.topRight),
|
||||
bottomLeft = PixelUtil.toPixelFromDIP(it.bottomLeft),
|
||||
bottomRight = PixelUtil.toPixelFromDIP(it.bottomRight))
|
||||
}
|
||||
|
||||
val shadowBorderRadii =
|
||||
computedBorderRadii?.let { radii ->
|
||||
ComputedBorderRadius(
|
||||
|
||||
+1
-1
@@ -183,7 +183,7 @@ public constructor(
|
||||
if (ReactNativeFeatureFlags.enableBackgroundStyleApplicator()) {
|
||||
val radius =
|
||||
if (borderRadius.isNaN()) null
|
||||
else LengthPercentage(toPixelFromDIP(borderRadius), LengthPercentageType.POINT)
|
||||
else LengthPercentage(borderRadius, LengthPercentageType.POINT)
|
||||
BackgroundStyleApplicator.setBorderRadius(view, BorderRadiusProp.values()[index], radius)
|
||||
} else {
|
||||
val convertedBorderRadius =
|
||||
|
||||
+3
-2
@@ -57,6 +57,7 @@ import com.facebook.react.uimanager.BackgroundStyleApplicator
|
||||
import com.facebook.react.uimanager.FloatUtil.floatsEqual
|
||||
import com.facebook.react.uimanager.LengthPercentage
|
||||
import com.facebook.react.uimanager.LengthPercentageType
|
||||
import com.facebook.react.uimanager.PixelUtil.toDIPFromPixel
|
||||
import com.facebook.react.uimanager.PixelUtil.toPixelFromDIP
|
||||
import com.facebook.react.uimanager.Spacing
|
||||
import com.facebook.react.uimanager.UIManagerHelper
|
||||
@@ -257,7 +258,7 @@ public class ReactImageView(
|
||||
if (enableBackgroundStyleApplicator()) {
|
||||
val radius =
|
||||
if (borderRadius.isNaN()) null
|
||||
else LengthPercentage(borderRadius, LengthPercentageType.POINT)
|
||||
else LengthPercentage(toDIPFromPixel(borderRadius), LengthPercentageType.POINT)
|
||||
BackgroundStyleApplicator.setBorderRadius(this, BorderRadiusProp.BORDER_RADIUS, radius)
|
||||
} else if (useNewReactImageViewBackgroundDrawing()) {
|
||||
reactBackgroundManager.setBorderRadius(borderRadius)
|
||||
@@ -271,7 +272,7 @@ public class ReactImageView(
|
||||
if (enableBackgroundStyleApplicator()) {
|
||||
val radius =
|
||||
if (borderRadius.isNaN()) null
|
||||
else LengthPercentage(borderRadius, LengthPercentageType.POINT)
|
||||
else LengthPercentage(toDIPFromPixel(borderRadius), LengthPercentageType.POINT)
|
||||
BackgroundStyleApplicator.setBorderRadius(this, BorderRadiusProp.values()[position], radius)
|
||||
} else if (useNewReactImageViewBackgroundDrawing()) {
|
||||
reactBackgroundManager.setBorderRadius(borderRadius, position + 1)
|
||||
|
||||
+2
-1
@@ -1351,7 +1351,8 @@ public class ReactHorizontalScrollView extends HorizontalScrollView
|
||||
LengthPercentage radius =
|
||||
Float.isNaN(borderRadius)
|
||||
? null
|
||||
: new LengthPercentage(borderRadius, LengthPercentageType.POINT);
|
||||
: new LengthPercentage(
|
||||
PixelUtil.toDIPFromPixel(borderRadius), LengthPercentageType.POINT);
|
||||
BackgroundStyleApplicator.setBorderRadius(this, BorderRadiusProp.values()[position], radius);
|
||||
} else {
|
||||
mReactBackgroundManager.setBorderRadius(borderRadius, position);
|
||||
|
||||
+1
-2
@@ -269,8 +269,7 @@ public class ReactHorizontalScrollViewManager extends ViewGroupManager<ReactHori
|
||||
LengthPercentage radius =
|
||||
Float.isNaN(borderRadius)
|
||||
? null
|
||||
: new LengthPercentage(
|
||||
PixelUtil.toPixelFromDIP(borderRadius), LengthPercentageType.POINT);
|
||||
: new LengthPercentage(borderRadius, LengthPercentageType.POINT);
|
||||
BackgroundStyleApplicator.setBorderRadius(view, BorderRadiusProp.values()[index], radius);
|
||||
} else {
|
||||
if (!Float.isNaN(borderRadius)) {
|
||||
|
||||
+2
-1
@@ -1283,7 +1283,8 @@ public class ReactScrollView extends ScrollView
|
||||
LengthPercentage radius =
|
||||
Float.isNaN(borderRadius)
|
||||
? null
|
||||
: new LengthPercentage(borderRadius, LengthPercentageType.POINT);
|
||||
: new LengthPercentage(
|
||||
PixelUtil.toDIPFromPixel(borderRadius), LengthPercentageType.POINT);
|
||||
BackgroundStyleApplicator.setBorderRadius(this, BorderRadiusProp.values()[position], radius);
|
||||
} else {
|
||||
mReactBackgroundManager.setBorderRadius(borderRadius, position);
|
||||
|
||||
+1
-2
@@ -250,8 +250,7 @@ public class ReactScrollViewManager extends ViewGroupManager<ReactScrollView>
|
||||
LengthPercentage radius =
|
||||
Float.isNaN(borderRadius)
|
||||
? null
|
||||
: new LengthPercentage(
|
||||
PixelUtil.toPixelFromDIP(borderRadius), LengthPercentageType.POINT);
|
||||
: new LengthPercentage(borderRadius, LengthPercentageType.POINT);
|
||||
BackgroundStyleApplicator.setBorderRadius(view, BorderRadiusProp.values()[index], radius);
|
||||
} else {
|
||||
if (!Float.isNaN(borderRadius)) {
|
||||
|
||||
+1
-2
@@ -158,8 +158,7 @@ public abstract class ReactTextAnchorViewManager<T extends View, C extends React
|
||||
LengthPercentage radius =
|
||||
Float.isNaN(borderRadius)
|
||||
? null
|
||||
: new LengthPercentage(
|
||||
PixelUtil.toPixelFromDIP(borderRadius), LengthPercentageType.POINT);
|
||||
: new LengthPercentage(borderRadius, LengthPercentageType.POINT);
|
||||
BackgroundStyleApplicator.setBorderRadius(view, BorderRadiusProp.values()[index], radius);
|
||||
} else {
|
||||
if (!Float.isNaN(borderRadius)) {
|
||||
|
||||
+2
-1
@@ -731,7 +731,8 @@ public class ReactTextView extends AppCompatTextView implements ReactCompoundVie
|
||||
LengthPercentage radius =
|
||||
Float.isNaN(borderRadius)
|
||||
? null
|
||||
: new LengthPercentage(borderRadius, LengthPercentageType.POINT);
|
||||
: new LengthPercentage(
|
||||
PixelUtil.toDIPFromPixel(borderRadius), LengthPercentageType.POINT);
|
||||
BackgroundStyleApplicator.setBorderRadius(this, BorderRadiusProp.values()[position], radius);
|
||||
} else {
|
||||
mReactBackgroundManager.setBorderRadius(borderRadius, position);
|
||||
|
||||
+2
-1
@@ -1132,7 +1132,8 @@ public class ReactEditText extends AppCompatEditText {
|
||||
LengthPercentage radius =
|
||||
Float.isNaN(borderRadius)
|
||||
? null
|
||||
: new LengthPercentage(borderRadius, LengthPercentageType.POINT);
|
||||
: new LengthPercentage(
|
||||
PixelUtil.toDIPFromPixel(borderRadius), LengthPercentageType.POINT);
|
||||
BackgroundStyleApplicator.setBorderRadius(this, BorderRadiusProp.values()[position], radius);
|
||||
} else {
|
||||
mReactBackgroundManager.setBorderRadius(borderRadius, position);
|
||||
|
||||
+1
-2
@@ -962,8 +962,7 @@ public class ReactTextInputManager extends BaseViewManager<ReactEditText, Layout
|
||||
LengthPercentage radius =
|
||||
Float.isNaN(borderRadius)
|
||||
? null
|
||||
: new LengthPercentage(
|
||||
PixelUtil.toPixelFromDIP(borderRadius), LengthPercentageType.POINT);
|
||||
: new LengthPercentage(borderRadius, LengthPercentageType.POINT);
|
||||
BackgroundStyleApplicator.setBorderRadius(view, BorderRadiusProp.values()[index], radius);
|
||||
} else {
|
||||
if (!Float.isNaN(borderRadius)) {
|
||||
|
||||
+13
-8
@@ -994,18 +994,23 @@ public class ReactViewGroup extends ViewGroup
|
||||
mPath = new Path();
|
||||
}
|
||||
|
||||
float topLeftRadius = PixelUtil.toPixelFromDIP(borderRadius.getTopLeft());
|
||||
float topRightRadius = PixelUtil.toPixelFromDIP(borderRadius.getTopRight());
|
||||
float bottomLeftRadius = PixelUtil.toPixelFromDIP(borderRadius.getBottomLeft());
|
||||
float bottomRightRadius = PixelUtil.toPixelFromDIP(borderRadius.getBottomRight());
|
||||
|
||||
mPath.rewind();
|
||||
mPath.addRoundRect(
|
||||
new RectF(left, top, right, bottom),
|
||||
new float[] {
|
||||
Math.max(borderRadius.getTopLeft() - borderWidth.left, 0),
|
||||
Math.max(borderRadius.getTopLeft() - borderWidth.top, 0),
|
||||
Math.max(borderRadius.getTopRight() - borderWidth.right, 0),
|
||||
Math.max(borderRadius.getTopRight() - borderWidth.top, 0),
|
||||
Math.max(borderRadius.getBottomRight() - borderWidth.right, 0),
|
||||
Math.max(borderRadius.getBottomRight() - borderWidth.bottom, 0),
|
||||
Math.max(borderRadius.getBottomLeft() - borderWidth.left, 0),
|
||||
Math.max(borderRadius.getBottomLeft() - borderWidth.bottom, 0),
|
||||
Math.max(topLeftRadius - borderWidth.left, 0),
|
||||
Math.max(topLeftRadius - borderWidth.top, 0),
|
||||
Math.max(topRightRadius - borderWidth.right, 0),
|
||||
Math.max(topRightRadius - borderWidth.top, 0),
|
||||
Math.max(bottomRightRadius - borderWidth.right, 0),
|
||||
Math.max(bottomRightRadius - borderWidth.bottom, 0),
|
||||
Math.max(bottomLeftRadius - borderWidth.left, 0),
|
||||
Math.max(bottomLeftRadius - borderWidth.bottom, 0),
|
||||
},
|
||||
Path.Direction.CW);
|
||||
canvas.clipPath(mPath);
|
||||
|
||||
+1
-1
@@ -162,7 +162,7 @@ public class ReactViewManager extends ReactClippingViewManager<ReactViewGroup> {
|
||||
// avoid developer surprise if it works on one platform but not another).
|
||||
if (ViewUtil.getUIManagerType(view) != UIManagerType.FABRIC
|
||||
&& borderRadius != null
|
||||
&& borderRadius.getUnit() == LengthPercentageType.PERCENT) {
|
||||
&& borderRadius.getType() == LengthPercentageType.PERCENT) {
|
||||
borderRadius = null;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user