From 4102aa4a6be9bf6fdbd7e3dbaaec15c96760269f Mon Sep 17 00:00:00 2001 From: Jorge Cabiedes Acosta Date: Fri, 6 Dec 2024 16:05:44 -0800 Subject: [PATCH] Revise iOS's implementation of `ensureNoOverlap` for borders (#48094) Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/48094 There were a few math inaccuracies in the algorithm for overlapping radii. After fixing there were also minor pixel differences on the unit tests but this is the most correct implementation. Also, improved the algorithm's verbiage since stuff like "EdgeInset" is not really related and is misleading to what the algorithm is actually doing. (Edge Insets play no part in this) Changelog: [Internal] Reviewed By: NickGerleman Differential Revision: D66728227 fbshipit-source-id: 56a6d59504e784fc245ed6fe306402a15cfd9611 --- .../components/view/BaseViewProps.cpp | 80 +++++++++---------- 1 file changed, 39 insertions(+), 41 deletions(-) diff --git a/packages/react-native/ReactCommon/react/renderer/components/view/BaseViewProps.cpp b/packages/react-native/ReactCommon/react/renderer/components/view/BaseViewProps.cpp index 22d543fcd82..cd785ced9bc 100644 --- a/packages/react-native/ReactCommon/react/renderer/components/view/BaseViewProps.cpp +++ b/packages/react-native/ReactCommon/react/renderer/components/view/BaseViewProps.cpp @@ -447,54 +447,52 @@ static BorderRadii ensureNoOverlap(const BorderRadii& radii, const Size& size) { // the used values of all border radii until none of them overlap." // Source: https://www.w3.org/TR/css-backgrounds-3/#corner-overlap - auto insets = EdgeInsets{ - .left = radii.topLeft.horizontal + radii.bottomLeft.horizontal, - .top = radii.topLeft.vertical + radii.topRight.vertical, - .right = radii.topRight.horizontal + radii.bottomRight.horizontal, - .bottom = radii.bottomLeft.vertical + radii.bottomRight.vertical, - }; + float leftEdgeRadii = radii.topLeft.vertical + radii.bottomLeft.vertical; + float topEdgeRadii = radii.topLeft.horizontal + radii.topRight.horizontal; + float rightEdgeRadii = radii.topRight.vertical + radii.bottomRight.vertical; + float bottomEdgeRadii = + radii.bottomLeft.horizontal + radii.bottomRight.horizontal; - auto insetsScale = EdgeInsets{ - .left = - insets.left > 0 ? std::min((Float)1.0, size.height / insets.left) : 0, - .top = insets.top > 0 ? std::min((Float)1.0, size.width / insets.top) : 0, - .right = insets.right > 0 - ? std::min((Float)1.0, size.height / insets.right) - : 0, - .bottom = insets.bottom > 0 - ? std::min((Float)1.0, size.width / insets.bottom) - : 0, - }; + float leftEdgeRadiiScale = + (leftEdgeRadii > 0) ? std::min(size.height / leftEdgeRadii, (Float)1) : 0; + float topEdgeRadiiScale = + (topEdgeRadii > 0) ? std::min(size.width / topEdgeRadii, (Float)1) : 0; + float rightEdgeRadiiScale = (rightEdgeRadii > 0) + ? std::min(size.height / rightEdgeRadii, (Float)1) + : 0; + float bottomEdgeRadiiScale = (bottomEdgeRadii > 0) + ? std::min(size.width / bottomEdgeRadii, (Float)1) + : 0; return BorderRadii{ .topLeft = {static_cast( - radii.topLeft.horizontal * - std::min(insetsScale.top, insetsScale.left)), - static_cast( radii.topLeft.vertical * - std::min(insetsScale.top, insetsScale.left))}, + std::min(topEdgeRadiiScale, leftEdgeRadiiScale)), + static_cast( + radii.topLeft.horizontal * + std::min(topEdgeRadiiScale, leftEdgeRadiiScale))}, .topRight = {static_cast( - radii.topRight.horizontal * - std::min(insetsScale.top, insetsScale.right)), - static_cast( radii.topRight.vertical * - std::min(insetsScale.top, insetsScale.right))}, + std::min(topEdgeRadiiScale, rightEdgeRadiiScale)), + static_cast( + radii.topRight.horizontal * + std::min(topEdgeRadiiScale, rightEdgeRadiiScale))}, .bottomLeft = {static_cast( - radii.bottomLeft.horizontal * - std::min(insetsScale.bottom, insetsScale.left)), - static_cast( radii.bottomLeft.vertical * - std::min(insetsScale.bottom, insetsScale.left))}, + std::min(bottomEdgeRadiiScale, leftEdgeRadiiScale)), + static_cast( + radii.bottomLeft.horizontal * + std::min(bottomEdgeRadiiScale, leftEdgeRadiiScale))}, .bottomRight = {static_cast( - radii.bottomRight.horizontal * - std::min(insetsScale.bottom, insetsScale.right)), - static_cast( radii.bottomRight.vertical * - std::min(insetsScale.bottom, insetsScale.right))}, + std::min(bottomEdgeRadiiScale, rightEdgeRadiiScale)), + static_cast( + radii.bottomRight.horizontal * + std::min(bottomEdgeRadiiScale, rightEdgeRadiiScale))}, }; } @@ -503,17 +501,17 @@ static BorderRadii radiiPercentToPoint( const Size& size) { return BorderRadii{ .topLeft = - {radii.topLeft.resolve(size.width), - radii.topLeft.resolve(size.height)}, + {radii.topLeft.resolve(size.height), + radii.topLeft.resolve(size.width)}, .topRight = - {radii.topRight.resolve(size.width), - radii.topRight.resolve(size.height)}, + {radii.topRight.resolve(size.height), + radii.topRight.resolve(size.width)}, .bottomLeft = - {radii.bottomLeft.resolve(size.width), - radii.bottomLeft.resolve(size.height)}, + {radii.bottomLeft.resolve(size.height), + radii.bottomLeft.resolve(size.width)}, .bottomRight = - {radii.bottomRight.resolve(size.width), - radii.bottomRight.resolve(size.height)}, + {radii.bottomRight.resolve(size.height), + radii.bottomRight.resolve(size.width)}, }; }