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
This commit is contained in:
Jorge Cabiedes Acosta
2024-12-06 16:05:44 -08:00
committed by Facebook GitHub Bot
parent 0b40cb8b7f
commit 4102aa4a6b
@@ -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<float>(
radii.topLeft.horizontal *
std::min(insetsScale.top, insetsScale.left)),
static_cast<float>(
radii.topLeft.vertical *
std::min(insetsScale.top, insetsScale.left))},
std::min(topEdgeRadiiScale, leftEdgeRadiiScale)),
static_cast<float>(
radii.topLeft.horizontal *
std::min(topEdgeRadiiScale, leftEdgeRadiiScale))},
.topRight =
{static_cast<float>(
radii.topRight.horizontal *
std::min(insetsScale.top, insetsScale.right)),
static_cast<float>(
radii.topRight.vertical *
std::min(insetsScale.top, insetsScale.right))},
std::min(topEdgeRadiiScale, rightEdgeRadiiScale)),
static_cast<float>(
radii.topRight.horizontal *
std::min(topEdgeRadiiScale, rightEdgeRadiiScale))},
.bottomLeft =
{static_cast<float>(
radii.bottomLeft.horizontal *
std::min(insetsScale.bottom, insetsScale.left)),
static_cast<float>(
radii.bottomLeft.vertical *
std::min(insetsScale.bottom, insetsScale.left))},
std::min(bottomEdgeRadiiScale, leftEdgeRadiiScale)),
static_cast<float>(
radii.bottomLeft.horizontal *
std::min(bottomEdgeRadiiScale, leftEdgeRadiiScale))},
.bottomRight =
{static_cast<float>(
radii.bottomRight.horizontal *
std::min(insetsScale.bottom, insetsScale.right)),
static_cast<float>(
radii.bottomRight.vertical *
std::min(insetsScale.bottom, insetsScale.right))},
std::min(bottomEdgeRadiiScale, rightEdgeRadiiScale)),
static_cast<float>(
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)},
};
}