From 42664099342c7a7e7e4765fbb3c2e0191d0269aa Mon Sep 17 00:00:00 2001 From: Jonathan Maurice Date: Thu, 2 Feb 2023 07:50:12 -0800 Subject: [PATCH] Fix negative value rounding issue for nodes across an axis (#688) Summary: This fix issue https://github.com/facebook/yoga/issues/683 the rounding calculation is incorrect if a node is crossing an axis and it will shrink it's width/height on layout calculation. The following test reproduce the issue : ``` TEST(YogaTest, node_shrink_on_axis) { const YGConfigRef config = YGConfigNew(); const YGNodeRef root = YGNodeNewWithConfig(config); const YGNodeRef child = YGNodeNewWithConfig(config); YGNodeInsertChild(root, child, 0); YGNodeStyleSetWidth(child, 10); YGNodeStyleSetHeight(child, 10); YGNodeStyleSetPosition(root, YGEdgeLeft, -0.75f); YGNodeStyleSetPosition(root, YGEdgeTop, -0.75f); YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR); ASSERT_FLOAT_EQ(YGNodeLayoutGetWidth(child), 10); ASSERT_FLOAT_EQ(YGNodeLayoutGetHeight(child), 10); YGNodeFreeRecursive(root); YGConfigFree(config); } ``` Pull Request resolved: https://github.com/facebook/yoga/pull/688 Reviewed By: NickGerleman Differential Revision: D13866122 Pulled By: rozele fbshipit-source-id: 4faf8a9efc86723c303f600d730660a2e13d8a73 --- tests/YGRoundingFunctionTest.cpp | 23 +++++++++++++++++++++++ yoga/Yoga.cpp | 10 +++------- 2 files changed, 26 insertions(+), 7 deletions(-) diff --git a/tests/YGRoundingFunctionTest.cpp b/tests/YGRoundingFunctionTest.cpp index e99ced89..65f487da 100644 --- a/tests/YGRoundingFunctionTest.cpp +++ b/tests/YGRoundingFunctionTest.cpp @@ -80,3 +80,26 @@ TEST(YogaTest, consistent_rounding_during_repeated_layouts) { YGConfigFree(config); } + +// Regression test for https://github.com/facebook/yoga/issues/683 +TEST(YogaTest, negative_value_rounding) { + const YGConfigRef config = YGConfigNew(); + const YGNodeRef root = YGNodeNewWithConfig(config); + const YGNodeRef child = YGNodeNewWithConfig(config); + + YGNodeInsertChild(root, child, 0); + + YGNodeStyleSetWidth(child, 10); + YGNodeStyleSetHeight(child, 10); + YGNodeStyleSetPosition(root, YGEdgeLeft, -0.75f); + YGNodeStyleSetPosition(root, YGEdgeTop, -0.75f); + + YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR); + + ASSERT_FLOAT_EQ(YGNodeLayoutGetWidth(child), 10); + ASSERT_FLOAT_EQ(YGNodeLayoutGetHeight(child), 10); + + YGNodeFreeRecursive(root); + + YGConfigFree(config); +} diff --git a/yoga/Yoga.cpp b/yoga/Yoga.cpp index 2c8f45b0..5072992d 100644 --- a/yoga/Yoga.cpp +++ b/yoga/Yoga.cpp @@ -3701,16 +3701,12 @@ YOGA_EXPORT float YGRoundValueToPixelGrid( scaledValue = scaledValue - fractial + 1.0; } else if (forceCeil) { // Next we check if we need to use forced rounding - scaledValue = scaledValue - fractial + 1.0; + scaledValue = ceil(scaledValue); } else if (forceFloor) { - scaledValue = scaledValue - fractial; + scaledValue = floor(scaledValue); } else { // Finally we just round the value - scaledValue = scaledValue - fractial + - (!YGDoubleIsUndefined(fractial) && - (fractial > 0.5 || YGDoubleEqual(fractial, 0.5)) - ? 1.0 - : 0.0); + scaledValue = round(scaledValue); } return (YGDoubleIsUndefined(scaledValue) || YGDoubleIsUndefined(pointScaleFactor))