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
This commit is contained in:
Jorge Cabiedes Acosta
2025-04-09 18:53:51 -07:00
committed by Facebook GitHub Bot
parent cbad8aafa5
commit b47bfcef5f
2 changed files with 22 additions and 20 deletions
@@ -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));
@@ -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)