From b47bfcef5f85ed1b4d713bec9be76efd1b485d3d Mon Sep 17 00:00:00 2001 From: Jorge Cabiedes Acosta Date: Wed, 9 Apr 2025 18:53:51 -0700 Subject: [PATCH] Fix border-radius with outline-offset Summary: This is not mentioned on the spec https://drafts.csswg.org/css-ui/#outline-offset but web adds the outline-offset to the border-radius of the outline. With this change now we render outline in this case like web Related issue: https://github.com/facebook/react-native/issues/50582 Changelog: [General][Fixed] - Outline now takes into account outline-offset to calculate its border-radius, same as web. Reviewed By: joevilches Differential Revision: D72749009 fbshipit-source-id: b3cd39e09e7856b6ccd45aab541cd51f05559832 --- .../View/RCTViewComponentView.mm | 22 ++++++++++--------- .../uimanager/drawable/OutlineDrawable.kt | 20 ++++++++--------- 2 files changed, 22 insertions(+), 20 deletions(-) diff --git a/packages/react-native/React/Fabric/Mounting/ComponentViews/View/RCTViewComponentView.mm b/packages/react-native/React/Fabric/Mounting/ComponentViews/View/RCTViewComponentView.mm index 249e91217be..005667f4c38 100644 --- a/packages/react-native/React/Fabric/Mounting/ComponentViews/View/RCTViewComponentView.mm +++ b/packages/react-native/React/Fabric/Mounting/ComponentViews/View/RCTViewComponentView.mm @@ -674,17 +674,18 @@ static RCTCornerRadii RCTCornerRadiiFromBorderRadii(BorderRadii borderRadii) .bottomRightVertical = (CGFloat)borderRadii.bottomRight.vertical}; } -static RCTCornerRadii RCTCreateOutlineCornerRadiiFromBorderRadii(const BorderRadii &borderRadii, CGFloat outlineWidth) +static RCTCornerRadii +RCTCreateOutlineCornerRadiiFromBorderRadii(const BorderRadii &borderRadii, CGFloat outlineWidth, CGFloat outlineOffset) { return RCTCornerRadii{ - borderRadii.topLeft.horizontal != 0 ? borderRadii.topLeft.horizontal + outlineWidth : 0, - borderRadii.topLeft.vertical != 0 ? borderRadii.topLeft.vertical + outlineWidth : 0, - borderRadii.topRight.horizontal != 0 ? borderRadii.topRight.horizontal + outlineWidth : 0, - borderRadii.topRight.vertical != 0 ? borderRadii.topRight.vertical + outlineWidth : 0, - borderRadii.bottomLeft.horizontal != 0 ? borderRadii.bottomLeft.horizontal + outlineWidth : 0, - borderRadii.bottomLeft.vertical != 0 ? borderRadii.bottomLeft.vertical + outlineWidth : 0, - borderRadii.bottomRight.horizontal != 0 ? borderRadii.bottomRight.horizontal + outlineWidth : 0, - borderRadii.bottomRight.vertical != 0 ? borderRadii.bottomRight.vertical + outlineWidth : 0}; + borderRadii.topLeft.horizontal != 0 ? borderRadii.topLeft.horizontal + outlineWidth + outlineOffset : 0, + borderRadii.topLeft.vertical != 0 ? borderRadii.topLeft.vertical + outlineWidth + outlineOffset : 0, + borderRadii.topRight.horizontal != 0 ? borderRadii.topRight.horizontal + outlineWidth + outlineOffset : 0, + borderRadii.topRight.vertical != 0 ? borderRadii.topRight.vertical + outlineWidth + outlineOffset : 0, + borderRadii.bottomLeft.horizontal != 0 ? borderRadii.bottomLeft.horizontal + outlineWidth + outlineOffset : 0, + borderRadii.bottomLeft.vertical != 0 ? borderRadii.bottomLeft.vertical + outlineWidth + outlineOffset : 0, + borderRadii.bottomRight.horizontal != 0 ? borderRadii.bottomRight.horizontal + outlineWidth + outlineOffset : 0, + borderRadii.bottomRight.vertical != 0 ? borderRadii.bottomRight.vertical + outlineWidth + outlineOffset : 0}; } // To be used for CSS properties like `border` and `outline`. @@ -958,7 +959,8 @@ static RCTBorderStyle RCTBorderStyleFromOutlineStyle(OutlineStyle outlineStyle) RCTAddContourEffectToLayer( _outlineLayer, - RCTCreateOutlineCornerRadiiFromBorderRadii(borderMetrics.borderRadii, _props->outlineWidth), + RCTCreateOutlineCornerRadiiFromBorderRadii( + borderMetrics.borderRadii, _props->outlineWidth, _props->outlineOffset), RCTBorderColors{outlineColor, outlineColor, outlineColor, outlineColor}, UIEdgeInsets{_props->outlineWidth, _props->outlineWidth, _props->outlineWidth, _props->outlineWidth}, RCTBorderStyleFromOutlineStyle(_props->outlineStyle)); diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/uimanager/drawable/OutlineDrawable.kt b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/uimanager/drawable/OutlineDrawable.kt index 9275523c83d..48d8befc7c9 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/uimanager/drawable/OutlineDrawable.kt +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/uimanager/drawable/OutlineDrawable.kt @@ -154,8 +154,8 @@ internal class OutlineDrawable( } } - private fun calculateRadius(radius: Float, outlineWidth: Float) = - if (radius != 0f) radius + outlineWidth * 0.5f else 0f + private fun calculateRadius(radius: Float, outlineWidth: Float, outlineOffset: Float) = + if (radius != 0f) radius + (outlineWidth * 0.5f) + outlineOffset else 0f private fun drawRectangularOutline(canvas: Canvas) { pathForOutline.addRect(tempRectForOutline, Path.Direction.CW) @@ -173,14 +173,14 @@ internal class OutlineDrawable( pathForOutline.addRoundRect( tempRectForOutline, floatArrayOf( - calculateRadius(topLeftRadius.horizontal, outlineWidth), - calculateRadius(topLeftRadius.vertical, outlineWidth), - calculateRadius(topRightRadius.horizontal, outlineWidth), - calculateRadius(topRightRadius.vertical, outlineWidth), - calculateRadius(bottomRightRadius.horizontal, outlineWidth), - calculateRadius(bottomRightRadius.vertical, outlineWidth), - calculateRadius(bottomLeftRadius.horizontal, outlineWidth), - calculateRadius(bottomLeftRadius.vertical, outlineWidth), + calculateRadius(topLeftRadius.horizontal, outlineWidth, outlineOffset), + calculateRadius(topLeftRadius.vertical, outlineWidth, outlineOffset), + calculateRadius(topRightRadius.horizontal, outlineWidth, outlineOffset), + calculateRadius(topRightRadius.vertical, outlineWidth, outlineOffset), + calculateRadius(bottomRightRadius.horizontal, outlineWidth, outlineOffset), + calculateRadius(bottomRightRadius.vertical, outlineWidth, outlineOffset), + calculateRadius(bottomLeftRadius.horizontal, outlineWidth, outlineOffset), + calculateRadius(bottomLeftRadius.vertical, outlineWidth, outlineOffset), ), Path.Direction.CW)