diff --git a/tests/CompactValueTest.cpp b/tests/CompactValueTest.cpp index cd5e6286..32e31cd0 100644 --- a/tests/CompactValueTest.cpp +++ b/tests/CompactValueTest.cpp @@ -11,7 +11,7 @@ #include #include -using facebook::yoga::CompactValue; +using namespace facebook::yoga; const auto tooSmall = nextafterf(CompactValue::LOWER_BOUND, -INFINITY); const auto tooLargePoints = @@ -20,112 +20,109 @@ const auto tooLargePercent = nextafterf(CompactValue::UPPER_BOUND_PERCENT, INFINITY); TEST(YogaTest, compact_value_can_represent_undefined) { - auto c = CompactValue{YGValue{12.5f, YGUnitUndefined}}; - YGValue v = c; - ASSERT_EQ(v, YGValueUndefined); - ASSERT_NE(v, YGValueAuto); - ASSERT_NE(v, (YGValue{-1.25, YGUnitPoint})); - ASSERT_NE(v, (YGValue{25, YGUnitPercent})); + auto c = CompactValue{value::undefined()}; + auto v = (StyleLength)c; + ASSERT_EQ(v, value::undefined()); + ASSERT_NE(v, value::ofAuto()); + ASSERT_NE(v, value::points(-1.25)); + ASSERT_NE(v, value::percent(25)); ASSERT_TRUE(c.isUndefined()); ASSERT_FALSE(c.isAuto()); } TEST(YogaTest, compact_value_manages_infinity_as_undefined) { - auto c = CompactValue{ - YGValue{std::numeric_limits::infinity(), YGUnitUndefined}}; - YGValue v = c; - ASSERT_EQ(v, YGValueUndefined); - ASSERT_NE(v, YGValueAuto); - ASSERT_NE(v, (YGValue{-1.25, YGUnitPoint})); - ASSERT_NE(v, (YGValue{25, YGUnitPercent})); + auto c = CompactValue{value::points(std::numeric_limits::infinity())}; + auto v = (StyleLength)c; + ASSERT_EQ(v, value::undefined()); + ASSERT_NE(v, value::ofAuto()); + ASSERT_NE(v, value::points(-1.25)); + ASSERT_NE(v, value::percent(25)); ASSERT_TRUE(c.isUndefined()); ASSERT_FALSE(c.isAuto()); } TEST(YogaTest, compact_value_can_represent_auto) { - auto c = CompactValue{YGValue{0, YGUnitAuto}}; - YGValue v = c; - ASSERT_NE(v, YGValueUndefined); - ASSERT_EQ(v, YGValueAuto); - ASSERT_NE(v, (YGValue{-1.25, YGUnitPoint})); - ASSERT_NE(v, (YGValue{25, YGUnitPercent})); + auto c = CompactValue{value::ofAuto()}; + auto v = (StyleLength)c; + ASSERT_NE(v, value::undefined()); + ASSERT_EQ(v, value::ofAuto()); + ASSERT_NE(v, value::points(-1.25)); + ASSERT_NE(v, value::percent(25)); ASSERT_FALSE(c.isUndefined()); ASSERT_TRUE(c.isAuto()); } TEST(YogaTest, compact_value_can_represent_zero_points) { - auto c = CompactValue{YGValue{0, YGUnitPoint}}; - YGValue v = c; - ASSERT_NE(v, YGValueUndefined); - ASSERT_NE(v, YGValueAuto); - ASSERT_EQ(v, (YGValue{0, YGUnitPoint})); - ASSERT_NE(v, (YGValue{0, YGUnitPercent})); + auto c = CompactValue{value::points(0)}; + auto v = (StyleLength)c; + ASSERT_NE(v, value::undefined()); + ASSERT_NE(v, value::ofAuto()); + ASSERT_EQ(v, value::points(0)); + ASSERT_NE(v, value::percent(0)); ASSERT_FALSE(c.isUndefined()); ASSERT_FALSE(c.isAuto()); } TEST(YogaTest, compact_value_can_represent_lower_bound_points) { - auto c = CompactValue({YGValue{CompactValue::LOWER_BOUND, YGUnitPoint}}); - YGValue v = c; - ASSERT_NE(v, YGValueUndefined); - ASSERT_NE(v, YGValueAuto); - ASSERT_EQ(v, (YGValue{CompactValue::LOWER_BOUND, YGUnitPoint})); - ASSERT_NE(v, (YGValue{CompactValue::LOWER_BOUND, YGUnitPercent})); + auto c = CompactValue({value::points(CompactValue::LOWER_BOUND)}); + auto v = (StyleLength)c; + ASSERT_NE(v, value::undefined()); + ASSERT_NE(v, value::ofAuto()); + ASSERT_EQ(v, value::points(CompactValue::LOWER_BOUND)); + ASSERT_NE(v, value::percent(CompactValue::LOWER_BOUND)); ASSERT_FALSE(c.isUndefined()); ASSERT_FALSE(c.isAuto()); } TEST(YogaTest, compact_value_can_represent_negative_lower_bound_points) { - auto c = CompactValue({YGValue{-CompactValue::LOWER_BOUND, YGUnitPoint}}); - YGValue v = c; - ASSERT_NE(v, YGValueUndefined); - ASSERT_NE(v, YGValueAuto); - ASSERT_EQ(v, (YGValue{-CompactValue::LOWER_BOUND, YGUnitPoint})); - ASSERT_NE(v, (YGValue{-CompactValue::LOWER_BOUND, YGUnitPercent})); + auto c = CompactValue({value::points(-CompactValue::LOWER_BOUND)}); + auto v = (StyleLength)c; + ASSERT_NE(v, value::undefined()); + ASSERT_NE(v, value::ofAuto()); + ASSERT_EQ(v, value::points(-CompactValue::LOWER_BOUND)); + ASSERT_NE(v, value::percent(-CompactValue::LOWER_BOUND)); ASSERT_FALSE(c.isUndefined()); ASSERT_FALSE(c.isAuto()); } TEST(YogaTest, compact_value_clamps_smaller_than_lower_bound_points_to_zero) { - auto c = CompactValue({YGValue{tooSmall, YGUnitPoint}}); - YGValue v = c; - ASSERT_NE(v, YGValueUndefined); - ASSERT_NE(v, YGValueAuto); - ASSERT_EQ(v, (YGValue{0, YGUnitPoint})); - ASSERT_NE(v, (YGValue{0, YGUnitPercent})); + auto c = CompactValue({value::points(tooSmall)}); + auto v = (StyleLength)c; + ASSERT_NE(v, value::undefined()); + ASSERT_NE(v, value::ofAuto()); + ASSERT_EQ(v, value::points(0)); + ASSERT_NE(v, value::percent(0)); } TEST( YogaTest, compact_value_clamps_greater_than_negative_lower_bound_points_to_zero) { - auto c = CompactValue({YGValue{-tooSmall, YGUnitPoint}}); - YGValue v = c; - ASSERT_NE(v, YGValueUndefined); - ASSERT_NE(v, YGValueAuto); - ASSERT_EQ(v, (YGValue{0, YGUnitPoint})); - ASSERT_NE(v, (YGValue{0, YGUnitPercent})); + auto c = CompactValue({value::points(-tooSmall)}); + auto v = (StyleLength)c; + ASSERT_NE(v, value::undefined()); + ASSERT_NE(v, value::ofAuto()); + ASSERT_EQ(v, value::points(0)); + ASSERT_NE(v, value::percent(0)); } TEST(YogaTest, compact_value_can_represent_upper_bound_points) { - auto c = - CompactValue({YGValue{CompactValue::UPPER_BOUND_POINT, YGUnitPoint}}); - YGValue v = c; - ASSERT_NE(v, YGValueUndefined); - ASSERT_NE(v, YGValueAuto); - ASSERT_EQ(v, (YGValue{CompactValue::UPPER_BOUND_POINT, YGUnitPoint})); - ASSERT_NE(v, (YGValue{CompactValue::UPPER_BOUND_POINT, YGUnitPercent})); + auto c = CompactValue({value::points(CompactValue::UPPER_BOUND_POINT)}); + auto v = (StyleLength)c; + ASSERT_NE(v, value::undefined()); + ASSERT_NE(v, value::ofAuto()); + ASSERT_EQ(v, value::points(CompactValue::UPPER_BOUND_POINT)); + ASSERT_NE(v, value::percent(CompactValue::UPPER_BOUND_POINT)); ASSERT_FALSE(c.isUndefined()); ASSERT_FALSE(c.isAuto()); } TEST(YogaTest, compact_value_can_represent_negative_upper_bound_points) { - auto c = - CompactValue({YGValue{-CompactValue::UPPER_BOUND_POINT, YGUnitPoint}}); - YGValue v = c; - ASSERT_NE(v, YGValueUndefined); - ASSERT_NE(v, YGValueAuto); - ASSERT_EQ(v, (YGValue{-CompactValue::UPPER_BOUND_POINT, YGUnitPoint})); - ASSERT_NE(v, (YGValue{-CompactValue::UPPER_BOUND_POINT, YGUnitPercent})); + auto c = CompactValue({value::points(-CompactValue::UPPER_BOUND_POINT)}); + auto v = (StyleLength)c; + ASSERT_NE(v, value::undefined()); + ASSERT_NE(v, value::ofAuto()); + ASSERT_EQ(v, value::points(-CompactValue::UPPER_BOUND_POINT)); + ASSERT_NE(v, value::percent(-CompactValue::UPPER_BOUND_POINT)); ASSERT_FALSE(c.isUndefined()); ASSERT_FALSE(c.isAuto()); } @@ -133,120 +130,118 @@ TEST(YogaTest, compact_value_can_represent_negative_upper_bound_points) { TEST( YogaTest, compact_value_clamps_greater_than__upper_bound_points_to_upper_bound) { - auto c = CompactValue({YGValue{tooLargePoints, YGUnitPoint}}); - YGValue v = c; - ASSERT_NE(v, YGValueUndefined); - ASSERT_NE(v, YGValueAuto); - ASSERT_EQ(v, (YGValue{CompactValue::UPPER_BOUND_POINT, YGUnitPoint})); - ASSERT_NE(v, (YGValue{CompactValue::UPPER_BOUND_POINT, YGUnitPercent})); + auto c = CompactValue({value::points(tooLargePoints)}); + auto v = (StyleLength)c; + ASSERT_NE(v, value::undefined()); + ASSERT_NE(v, value::ofAuto()); + ASSERT_EQ(v, value::points(CompactValue::UPPER_BOUND_POINT)); + ASSERT_NE(v, value::percent(CompactValue::UPPER_BOUND_POINT)); } TEST( YogaTest, compact_value_clamps_smaller_than_negative_upper_bound_points_to_upper_bound) { - auto c = CompactValue({YGValue{-tooLargePoints, YGUnitPoint}}); - YGValue v = c; - ASSERT_NE(v, YGValueUndefined); - ASSERT_NE(v, YGValueAuto); - ASSERT_EQ(v, (YGValue{-CompactValue::UPPER_BOUND_POINT, YGUnitPoint})); - ASSERT_NE(v, (YGValue{-CompactValue::UPPER_BOUND_POINT, YGUnitPercent})); + auto c = CompactValue({value::points(-tooLargePoints)}); + auto v = (StyleLength)c; + ASSERT_NE(v, value::undefined()); + ASSERT_NE(v, value::ofAuto()); + ASSERT_EQ(v, value::points(-CompactValue::UPPER_BOUND_POINT)); + ASSERT_NE(v, value::percent(-CompactValue::UPPER_BOUND_POINT)); } TEST(YogaTest, compact_value_can_represent_one_point) { - auto c = CompactValue({YGValue{1, YGUnitPoint}}); - YGValue v = c; - ASSERT_NE(v, YGValueUndefined); - ASSERT_NE(v, YGValueAuto); - ASSERT_EQ(v, (YGValue{1, YGUnitPoint})); - ASSERT_NE(v, (YGValue{1, YGUnitPercent})); + auto c = CompactValue({value::points(1)}); + auto v = (StyleLength)c; + ASSERT_NE(v, value::undefined()); + ASSERT_NE(v, value::ofAuto()); + ASSERT_EQ(v, value::points(1)); + ASSERT_NE(v, value::percent(1)); ASSERT_FALSE(c.isUndefined()); ASSERT_FALSE(c.isAuto()); } TEST(YogaTest, compact_value_can_represent_negative_one_point) { - auto c = CompactValue({YGValue{-1, YGUnitPoint}}); - YGValue v = c; - ASSERT_NE(v, YGValueUndefined); - ASSERT_NE(v, YGValueAuto); - ASSERT_EQ(v, (YGValue{-1, YGUnitPoint})); - ASSERT_NE(v, (YGValue{-1, YGUnitPercent})); + auto c = CompactValue({value::points(-1)}); + auto v = (StyleLength)c; + ASSERT_NE(v, value::undefined()); + ASSERT_NE(v, value::ofAuto()); + ASSERT_EQ(v, value::points(-1)); + ASSERT_NE(v, value::percent(-1)); ASSERT_FALSE(c.isUndefined()); ASSERT_FALSE(c.isAuto()); } TEST(YogaTest, compact_value_can_represent_zero_percent) { - auto c = CompactValue{YGValue{0, YGUnitPercent}}; - YGValue v = c; - ASSERT_NE(v, YGValueUndefined); - ASSERT_NE(v, YGValueAuto); - ASSERT_NE(v, (YGValue{0, YGUnitPoint})); - ASSERT_EQ(v, (YGValue{0, YGUnitPercent})); + auto c = CompactValue{value::percent(0)}; + auto v = (StyleLength)c; + ASSERT_NE(v, value::undefined()); + ASSERT_NE(v, value::ofAuto()); + ASSERT_NE(v, value::points(0)); + ASSERT_EQ(v, value::percent(0)); ASSERT_FALSE(c.isUndefined()); ASSERT_FALSE(c.isAuto()); } TEST(YogaTest, compact_value_can_represent_lower_bound_percent) { - auto c = CompactValue({YGValue{CompactValue::LOWER_BOUND, YGUnitPercent}}); - YGValue v = c; - ASSERT_NE(v, YGValueUndefined); - ASSERT_NE(v, YGValueAuto); - ASSERT_NE(v, (YGValue{CompactValue::LOWER_BOUND, YGUnitPoint})); - ASSERT_EQ(v, (YGValue{CompactValue::LOWER_BOUND, YGUnitPercent})); + auto c = CompactValue({value::percent(CompactValue::LOWER_BOUND)}); + auto v = (StyleLength)c; + ASSERT_NE(v, value::undefined()); + ASSERT_NE(v, value::ofAuto()); + ASSERT_NE(v, value::points(CompactValue::LOWER_BOUND)); + ASSERT_EQ(v, value::percent(CompactValue::LOWER_BOUND)); ASSERT_FALSE(c.isUndefined()); ASSERT_FALSE(c.isAuto()); } TEST(YogaTest, compact_value_can_represent_negative_lower_bound_percent) { - auto c = CompactValue({YGValue{-CompactValue::LOWER_BOUND, YGUnitPercent}}); - YGValue v = c; - ASSERT_NE(v, YGValueUndefined); - ASSERT_NE(v, YGValueAuto); - ASSERT_NE(v, (YGValue{-CompactValue::LOWER_BOUND, YGUnitPoint})); - ASSERT_EQ(v, (YGValue{-CompactValue::LOWER_BOUND, YGUnitPercent})); + auto c = CompactValue({value::percent(-CompactValue::LOWER_BOUND)}); + auto v = (StyleLength)c; + ASSERT_NE(v, value::undefined()); + ASSERT_NE(v, value::ofAuto()); + ASSERT_NE(v, value::points(-CompactValue::LOWER_BOUND)); + ASSERT_EQ(v, value::percent(-CompactValue::LOWER_BOUND)); ASSERT_FALSE(c.isUndefined()); ASSERT_FALSE(c.isAuto()); } TEST(YogaTest, compact_value_clamps_smaller_than_lower_bound_percent_to_zero) { - auto c = CompactValue({YGValue{tooSmall, YGUnitPercent}}); - YGValue v = c; - ASSERT_NE(v, YGValueUndefined); - ASSERT_NE(v, YGValueAuto); - ASSERT_NE(v, (YGValue{0, YGUnitPoint})); - ASSERT_EQ(v, (YGValue{0, YGUnitPercent})); + auto c = CompactValue({value::percent(tooSmall)}); + auto v = (StyleLength)c; + ASSERT_NE(v, value::undefined()); + ASSERT_NE(v, value::ofAuto()); + ASSERT_NE(v, value::points(0)); + ASSERT_EQ(v, value::percent(0)); } TEST( YogaTest, compact_value_clamps_greater_than_negative_lower_bound_percent_to_zero) { - auto c = CompactValue({YGValue{-tooSmall, YGUnitPercent}}); - YGValue v = c; - ASSERT_NE(v, YGValueUndefined); - ASSERT_NE(v, YGValueAuto); - ASSERT_NE(v, (YGValue{0, YGUnitPoint})); - ASSERT_EQ(v, (YGValue{0, YGUnitPercent})); + auto c = CompactValue({value::percent(-tooSmall)}); + auto v = (StyleLength)c; + ASSERT_NE(v, value::undefined()); + ASSERT_NE(v, value::ofAuto()); + ASSERT_NE(v, value::points(0)); + ASSERT_EQ(v, value::percent(0)); } TEST(YogaTest, compact_value_can_represent_upper_bound_percent) { - auto c = - CompactValue({YGValue{CompactValue::UPPER_BOUND_PERCENT, YGUnitPercent}}); - YGValue v = c; - ASSERT_NE(v, YGValueUndefined); - ASSERT_NE(v, YGValueAuto); - ASSERT_NE(v, (YGValue{CompactValue::UPPER_BOUND_PERCENT, YGUnitPoint})); - ASSERT_EQ(v, (YGValue{CompactValue::UPPER_BOUND_PERCENT, YGUnitPercent})); + auto c = CompactValue({value::percent(CompactValue::UPPER_BOUND_PERCENT)}); + auto v = (StyleLength)c; + ASSERT_NE(v, value::undefined()); + ASSERT_NE(v, value::ofAuto()); + ASSERT_NE(v, value::points(CompactValue::UPPER_BOUND_PERCENT)); + ASSERT_EQ(v, value::percent(CompactValue::UPPER_BOUND_PERCENT)); ASSERT_FALSE(c.isUndefined()); ASSERT_FALSE(c.isAuto()); } TEST(YogaTest, compact_value_can_represent_negative_upper_bound_percent) { - auto c = CompactValue( - {YGValue{-CompactValue::UPPER_BOUND_PERCENT, YGUnitPercent}}); - YGValue v = c; - ASSERT_NE(v, YGValueUndefined); - ASSERT_NE(v, YGValueAuto); - ASSERT_NE(v, (YGValue{-CompactValue::UPPER_BOUND_PERCENT, YGUnitPoint})); - ASSERT_EQ(v, (YGValue{-CompactValue::UPPER_BOUND_PERCENT, YGUnitPercent})); + auto c = CompactValue({value::percent(-CompactValue::UPPER_BOUND_PERCENT)}); + auto v = (StyleLength)c; + ASSERT_NE(v, value::undefined()); + ASSERT_NE(v, value::ofAuto()); + ASSERT_NE(v, value::points(-CompactValue::UPPER_BOUND_PERCENT)); + ASSERT_EQ(v, value::percent(-CompactValue::UPPER_BOUND_PERCENT)); ASSERT_FALSE(c.isUndefined()); ASSERT_FALSE(c.isAuto()); } @@ -254,100 +249,43 @@ TEST(YogaTest, compact_value_can_represent_negative_upper_bound_percent) { TEST( YogaTest, compact_value_clamps_greater_than_upper_bound_percent_to_upper_bound) { - auto c = CompactValue({YGValue{tooLargePercent, YGUnitPercent}}); - YGValue v = c; - ASSERT_NE(v, YGValueUndefined); - ASSERT_NE(v, YGValueAuto); - ASSERT_NE(v, (YGValue{CompactValue::UPPER_BOUND_PERCENT, YGUnitPoint})); - ASSERT_EQ(v, (YGValue{CompactValue::UPPER_BOUND_PERCENT, YGUnitPercent})); + auto c = CompactValue({value::percent(tooLargePercent)}); + auto v = (StyleLength)c; + ASSERT_NE(v, value::undefined()); + ASSERT_NE(v, value::ofAuto()); + ASSERT_NE(v, value::points(CompactValue::UPPER_BOUND_PERCENT)); + ASSERT_EQ(v, value::percent(CompactValue::UPPER_BOUND_PERCENT)); } TEST( YogaTest, compact_value_clamps_smaller_than_negative_upper_bound_percent_to_upper_bound) { - auto c = CompactValue({YGValue{-tooLargePercent, YGUnitPercent}}); - YGValue v = c; - ASSERT_NE(v, YGValueUndefined); - ASSERT_NE(v, YGValueAuto); - ASSERT_NE(v, (YGValue{-CompactValue::UPPER_BOUND_PERCENT, YGUnitPoint})); - ASSERT_EQ(v, (YGValue{-CompactValue::UPPER_BOUND_PERCENT, YGUnitPercent})); + auto c = CompactValue({value::percent(-tooLargePercent)}); + auto v = (StyleLength)c; + ASSERT_NE(v, value::undefined()); + ASSERT_NE(v, value::ofAuto()); + ASSERT_NE(v, value::points(-CompactValue::UPPER_BOUND_PERCENT)); + ASSERT_EQ(v, value::percent(-CompactValue::UPPER_BOUND_PERCENT)); } TEST(YogaTest, compact_value_can_represent_one_percent) { - auto c = CompactValue({YGValue{1, YGUnitPercent}}); - YGValue v = c; - ASSERT_NE(v, YGValueUndefined); - ASSERT_NE(v, YGValueAuto); - ASSERT_NE(v, (YGValue{1, YGUnitPoint})); - ASSERT_EQ(v, (YGValue{1, YGUnitPercent})); + auto c = CompactValue({value::percent(1)}); + auto v = (StyleLength)c; + ASSERT_NE(v, value::undefined()); + ASSERT_NE(v, value::ofAuto()); + ASSERT_NE(v, value::points(1)); + ASSERT_EQ(v, value::percent(1)); ASSERT_FALSE(c.isUndefined()); ASSERT_FALSE(c.isAuto()); } TEST(YogaTest, compact_value_can_represent_negative_one_percent) { - auto c = CompactValue({YGValue{-1, YGUnitPercent}}); - YGValue v = c; - ASSERT_NE(v, YGValueUndefined); - ASSERT_NE(v, YGValueAuto); - ASSERT_NE(v, (YGValue{-1, YGUnitPoint})); - ASSERT_EQ(v, (YGValue{-1, YGUnitPercent})); + auto c = CompactValue({value::percent(-1)}); + auto v = (StyleLength)c; + ASSERT_NE(v, value::undefined()); + ASSERT_NE(v, value::ofAuto()); + ASSERT_NE(v, value::points(-1)); + ASSERT_EQ(v, value::percent(-1)); ASSERT_FALSE(c.isUndefined()); ASSERT_FALSE(c.isAuto()); } - -TEST(YogaTest, dedicated_unit_factories) { - ASSERT_EQ(CompactValue::ofUndefined(), CompactValue(YGValueUndefined)); - ASSERT_EQ(CompactValue::ofAuto(), CompactValue(YGValueAuto)); - ASSERT_EQ( - CompactValue::of(-9876.5f), - CompactValue(YGValue{-9876.5f, YGUnitPoint})); - ASSERT_EQ( - CompactValue::of(123.456f), - CompactValue(YGValue{123.456f, YGUnitPercent})); - ASSERT_EQ( - CompactValue::of(YGUndefined), - CompactValue(YGValueUndefined)); - ASSERT_EQ( - CompactValue::of(YGUndefined), - CompactValue(YGValueUndefined)); -} - -TEST(YogaTest, can_be_assigned_from_YGValue) { - CompactValue c{}; - - YGValue v{2.0f, YGUnitPercent}; - c = v; - ASSERT_EQ((YGValue)c, v); - - c = YGValue{123, YGUnitPoint}; - ASSERT_EQ((YGValue)c, (YGValue{123, YGUnitPoint})); -} - -TEST(YogaTest, compact_value_bound_representations) { - ASSERT_EQ( - CompactValue::of(CompactValue::LOWER_BOUND).repr(), - uint32_t{0}); - ASSERT_EQ( - CompactValue::of(CompactValue::UPPER_BOUND_POINT).repr(), - uint32_t{0x3fffffff}); - ASSERT_EQ( - CompactValue::of(CompactValue::LOWER_BOUND).repr(), - uint32_t{0x40000000}); - ASSERT_EQ( - CompactValue::of(CompactValue::UPPER_BOUND_PERCENT).repr(), - uint32_t{0x7f7fffff}); - - ASSERT_EQ( - CompactValue::of(-CompactValue::LOWER_BOUND).repr(), - uint32_t{0x80000000}); - ASSERT_EQ( - CompactValue::of(-CompactValue::UPPER_BOUND_POINT).repr(), - uint32_t{0xbfffffff}); - ASSERT_EQ( - CompactValue::of(-CompactValue::LOWER_BOUND).repr(), - uint32_t{0xc0000000}); - ASSERT_EQ( - CompactValue::of(-CompactValue::UPPER_BOUND_PERCENT) - .repr(), - uint32_t{0xff7fffff}); -} diff --git a/yoga/YGNodeStyle.cpp b/yoga/YGNodeStyle.cpp index 14f2dc30..8ccb94e3 100644 --- a/yoga/YGNodeStyle.cpp +++ b/yoga/YGNodeStyle.cpp @@ -195,11 +195,7 @@ void YGNodeStyleSetFlexBasisAuto(const YGNodeRef node) { } YGValue YGNodeStyleGetFlexBasis(const YGNodeConstRef node) { - YGValue flexBasis = resolveRef(node)->getStyle().flexBasis(); - if (flexBasis.unit == YGUnitUndefined || flexBasis.unit == YGUnitAuto) { - flexBasis.value = YGUndefined; - } - return flexBasis; + return (YGValue)resolveRef(node)->getStyle().flexBasis(); } void YGNodeStyleSetPosition(YGNodeRef node, YGEdge edge, float points) { @@ -213,7 +209,7 @@ void YGNodeStyleSetPositionPercent(YGNodeRef node, YGEdge edge, float percent) { } YGValue YGNodeStyleGetPosition(YGNodeConstRef node, YGEdge edge) { - return resolveRef(node)->getStyle().position(scopedEnum(edge)); + return (YGValue)resolveRef(node)->getStyle().position(scopedEnum(edge)); } void YGNodeStyleSetMargin(YGNodeRef node, YGEdge edge, float points) { @@ -232,7 +228,7 @@ void YGNodeStyleSetMarginAuto(YGNodeRef node, YGEdge edge) { } YGValue YGNodeStyleGetMargin(YGNodeConstRef node, YGEdge edge) { - return resolveRef(node)->getStyle().margin(scopedEnum(edge)); + return (YGValue)resolveRef(node)->getStyle().margin(scopedEnum(edge)); } void YGNodeStyleSetPadding(YGNodeRef node, YGEdge edge, float points) { @@ -246,7 +242,7 @@ void YGNodeStyleSetPaddingPercent(YGNodeRef node, YGEdge edge, float percent) { } YGValue YGNodeStyleGetPadding(YGNodeConstRef node, YGEdge edge) { - return resolveRef(node)->getStyle().padding(scopedEnum(edge)); + return (YGValue)resolveRef(node)->getStyle().padding(scopedEnum(edge)); } void YGNodeStyleSetBorder( @@ -309,7 +305,7 @@ void YGNodeStyleSetWidthAuto(YGNodeRef node) { } YGValue YGNodeStyleGetWidth(YGNodeConstRef node) { - return resolveRef(node)->getStyle().dimension(Dimension::Width); + return (YGValue)resolveRef(node)->getStyle().dimension(Dimension::Width); } void YGNodeStyleSetHeight(YGNodeRef node, float points) { @@ -328,7 +324,7 @@ void YGNodeStyleSetHeightAuto(YGNodeRef node) { } YGValue YGNodeStyleGetHeight(YGNodeConstRef node) { - return resolveRef(node)->getStyle().dimension(Dimension::Height); + return (YGValue)resolveRef(node)->getStyle().dimension(Dimension::Height); } void YGNodeStyleSetMinWidth(const YGNodeRef node, const float minWidth) { @@ -342,7 +338,7 @@ void YGNodeStyleSetMinWidthPercent(const YGNodeRef node, const float minWidth) { } YGValue YGNodeStyleGetMinWidth(const YGNodeConstRef node) { - return resolveRef(node)->getStyle().minDimension(Dimension::Width); + return (YGValue)resolveRef(node)->getStyle().minDimension(Dimension::Width); } void YGNodeStyleSetMinHeight(const YGNodeRef node, const float minHeight) { @@ -358,7 +354,7 @@ void YGNodeStyleSetMinHeightPercent( } YGValue YGNodeStyleGetMinHeight(const YGNodeConstRef node) { - return resolveRef(node)->getStyle().minDimension(Dimension::Height); + return (YGValue)resolveRef(node)->getStyle().minDimension(Dimension::Height); } void YGNodeStyleSetMaxWidth(const YGNodeRef node, const float maxWidth) { @@ -372,7 +368,7 @@ void YGNodeStyleSetMaxWidthPercent(const YGNodeRef node, const float maxWidth) { } YGValue YGNodeStyleGetMaxWidth(const YGNodeConstRef node) { - return resolveRef(node)->getStyle().maxDimension(Dimension::Width); + return (YGValue)resolveRef(node)->getStyle().maxDimension(Dimension::Width); } void YGNodeStyleSetMaxHeight(const YGNodeRef node, const float maxHeight) { @@ -388,5 +384,5 @@ void YGNodeStyleSetMaxHeightPercent( } YGValue YGNodeStyleGetMaxHeight(const YGNodeConstRef node) { - return resolveRef(node)->getStyle().maxDimension(Dimension::Height); + return (YGValue)resolveRef(node)->getStyle().maxDimension(Dimension::Height); } diff --git a/yoga/algorithm/CalculateLayout.cpp b/yoga/algorithm/CalculateLayout.cpp index ea7a0903..0d970ca9 100644 --- a/yoga/algorithm/CalculateLayout.cpp +++ b/yoga/algorithm/CalculateLayout.cpp @@ -687,9 +687,9 @@ static float distributeFreeSpaceSecondPass( sizingModeCrossDim == SizingMode::StretchFit && !(isNodeFlexWrap && mainAxisOverflows) && resolveChildAlignment(node, currentLineChild) == Align::Stretch && - currentLineChild->getFlexStartMarginValue(crossAxis).unit != - YGUnitAuto && - currentLineChild->marginTrailingValue(crossAxis).unit != YGUnitAuto) { + currentLineChild->getFlexStartMarginValue(crossAxis).unit() != + Unit::Auto && + currentLineChild->marginTrailingValue(crossAxis).unit() != Unit::Auto) { childCrossSize = availableInnerCrossDim; childCrossSizingMode = SizingMode::StretchFit; } else if (!currentLineChild->styleDefinesDimension( @@ -706,8 +706,8 @@ static float distributeFreeSpaceSecondPass( .unwrap() + marginCross; const bool isLoosePercentageMeasurement = - currentLineChild->getResolvedDimension(dimension(crossAxis)).unit == - YGUnitPercent && + currentLineChild->getResolvedDimension(dimension(crossAxis)).unit() == + Unit::Percent && sizingModeCrossDim != SizingMode::StretchFit; childCrossSizingMode = yoga::isUndefined(childCrossSize) || isLoosePercentageMeasurement @@ -733,9 +733,9 @@ static float distributeFreeSpaceSecondPass( const bool requiresStretchLayout = !currentLineChild->styleDefinesDimension( crossAxis, availableInnerCrossDim) && resolveChildAlignment(node, currentLineChild) == Align::Stretch && - currentLineChild->getFlexStartMarginValue(crossAxis).unit != - YGUnitAuto && - currentLineChild->marginTrailingValue(crossAxis).unit != YGUnitAuto; + currentLineChild->getFlexStartMarginValue(crossAxis).unit() != + Unit::Auto && + currentLineChild->marginTrailingValue(crossAxis).unit() != Unit::Auto; const float childWidth = isMainAxisRow ? childMainSize : childCrossSize; const float childHeight = !isMainAxisRow ? childMainSize : childCrossSize; @@ -982,10 +982,10 @@ static void justifyMainAxis( for (size_t i = startOfLineIndex; i < flexLine.endOfLineIndex; i++) { auto child = node->getChild(i); if (child->getStyle().positionType() != PositionType::Absolute) { - if (child->getFlexStartMarginValue(mainAxis).unit == YGUnitAuto) { + if (child->getFlexStartMarginValue(mainAxis).unit() == Unit::Auto) { numberOfAutoMarginsOnCurrentLine++; } - if (child->marginTrailingValue(mainAxis).unit == YGUnitAuto) { + if (child->marginTrailingValue(mainAxis).unit() == Unit::Auto) { numberOfAutoMarginsOnCurrentLine++; } } @@ -1062,7 +1062,7 @@ static void justifyMainAxis( // We need to do that only for relative elements. Absolute elements do not // take part in that phase. if (childStyle.positionType() != PositionType::Absolute) { - if (child->getFlexStartMarginValue(mainAxis).unit == YGUnitAuto) { + if (child->getFlexStartMarginValue(mainAxis).unit() == Unit::Auto) { flexLine.layout.mainDim += flexLine.layout.remainingFreeSpace / static_cast(numberOfAutoMarginsOnCurrentLine); } @@ -1078,7 +1078,7 @@ static void justifyMainAxis( flexLine.layout.mainDim += betweenMainDim; } - if (child->marginTrailingValue(mainAxis).unit == YGUnitAuto) { + if (child->marginTrailingValue(mainAxis).unit() == Unit::Auto) { flexLine.layout.mainDim += flexLine.layout.remainingFreeSpace / static_cast(numberOfAutoMarginsOnCurrentLine); } @@ -1630,8 +1630,8 @@ static void calculateLayoutImpl( // time, this time forcing the cross-axis size to be the computed // cross size for the current line. if (alignItem == Align::Stretch && - child->getFlexStartMarginValue(crossAxis).unit != YGUnitAuto && - child->marginTrailingValue(crossAxis).unit != YGUnitAuto) { + child->getFlexStartMarginValue(crossAxis).unit() != Unit::Auto && + child->marginTrailingValue(crossAxis).unit() != Unit::Auto) { // If the child defines a definite size for its cross axis, there's // no need to stretch. if (!child->styleDefinesDimension( @@ -1704,15 +1704,17 @@ static void calculateLayoutImpl( const float remainingCrossDim = containerCrossAxis - child->dimensionWithMargin(crossAxis, availableInnerWidth); - if (child->getFlexStartMarginValue(crossAxis).unit == YGUnitAuto && - child->marginTrailingValue(crossAxis).unit == YGUnitAuto) { + if (child->getFlexStartMarginValue(crossAxis).unit() == + Unit::Auto && + child->marginTrailingValue(crossAxis).unit() == Unit::Auto) { leadingCrossDim += yoga::maxOrDefined(0.0f, remainingCrossDim / 2); } else if ( - child->marginTrailingValue(crossAxis).unit == YGUnitAuto) { + child->marginTrailingValue(crossAxis).unit() == Unit::Auto) { // No-Op } else if ( - child->getFlexStartMarginValue(crossAxis).unit == YGUnitAuto) { + child->getFlexStartMarginValue(crossAxis).unit() == + Unit::Auto) { leadingCrossDim += yoga::maxOrDefined(0.0f, remainingCrossDim); } else if (alignItem == Align::FlexStart) { // No-Op diff --git a/yoga/algorithm/ResolveValue.h b/yoga/algorithm/ResolveValue.h index a2d650b2..4ff89184 100644 --- a/yoga/algorithm/ResolveValue.h +++ b/yoga/algorithm/ResolveValue.h @@ -14,19 +14,15 @@ namespace facebook::yoga { -inline FloatOptional resolveValue(const YGValue value, const float ownerSize) { - switch (value.unit) { - case YGUnitPoint: - return FloatOptional{value.value}; - case YGUnitPercent: - return FloatOptional{value.value * ownerSize * 0.01f}; +inline FloatOptional resolveValue(Style::Length length, float ownerSize) { + switch (length.unit()) { + case Unit::Point: + return length.value(); + case Unit::Percent: + return FloatOptional{length.value().unwrap() * ownerSize * 0.01f}; default: return FloatOptional{}; } } -inline FloatOptional resolveValue(Style::Length value, float ownerSize) { - return resolveValue((YGValue)value, ownerSize); -} - } // namespace facebook::yoga diff --git a/yoga/debug/NodeToString.cpp b/yoga/debug/NodeToString.cpp index 18e8aeec..c084c5a7 100644 --- a/yoga/debug/NodeToString.cpp +++ b/yoga/debug/NodeToString.cpp @@ -46,14 +46,18 @@ static void appendFloatOptionalIfDefined( static void appendNumberIfNotUndefined( std::string& base, const std::string key, - const YGValue number) { - if (number.unit != YGUnitUndefined) { - if (number.unit == YGUnitAuto) { + const Style::Length& number) { + if (number.unit() != Unit::Undefined) { + if (number.unit() == Unit::Auto) { base.append(key + ": auto; "); } else { - std::string unit = number.unit == YGUnitPoint ? "px" : "%%"; + std::string unit = number.unit() == Unit::Point ? "px" : "%%"; appendFormattedString( - base, "%s: %g%s; ", key.c_str(), number.value, unit.c_str()); + base, + "%s: %g%s; ", + key.c_str(), + number.value().unwrap(), + unit.c_str()); } } } @@ -61,8 +65,8 @@ static void appendNumberIfNotUndefined( static void appendNumberIfNotAuto( std::string& base, const std::string& key, - const YGValue number) { - if (number.unit != YGUnitAuto) { + const Style::Length& number) { + if (number.unit() != Unit::Auto) { appendNumberIfNotUndefined(base, key, number); } } @@ -70,10 +74,10 @@ static void appendNumberIfNotAuto( static void appendNumberIfNotZero( std::string& base, const std::string& str, - const YGValue number) { - if (number.unit == YGUnitAuto) { + const Style::Length& number) { + if (number.unit() == Unit::Auto) { base.append(str + ": auto; "); - } else if (!yoga::inexactEquals(number.value, 0)) { + } else if (!yoga::inexactEquals(number.value().unwrap(), 0)) { appendNumberIfNotUndefined(base, str, number); } } diff --git a/yoga/node/Node.cpp b/yoga/node/Node.cpp index 36eefbb5..0af0aea6 100644 --- a/yoga/node/Node.cpp +++ b/yoga/node/Node.cpp @@ -127,8 +127,8 @@ bool Node::isFlexStartPositionDefined(FlexDirection axis, Direction direction) bool Node::isInlineStartPositionDefined(FlexDirection axis, Direction direction) const { - const Edge startEdge = getInlineStartEdgeUsingErrata(axis, direction); - auto leadingPosition = isRow(axis) + Edge startEdge = getInlineStartEdgeUsingErrata(axis, direction); + Style::Length leadingPosition = isRow(axis) ? computeEdgeValueForRow<&Style::position>(Edge::Start, startEdge) : computeEdgeValueForColumn<&Style::position>(startEdge); @@ -148,8 +148,8 @@ bool Node::isFlexEndPositionDefined(FlexDirection axis, Direction direction) bool Node::isInlineEndPositionDefined(FlexDirection axis, Direction direction) const { - const Edge endEdge = getInlineEndEdgeUsingErrata(axis, direction); - auto trailingPosition = isRow(axis) + Edge endEdge = getInlineEndEdgeUsingErrata(axis, direction); + Style::Length trailingPosition = isRow(axis) ? computeEdgeValueForRow<&Style::position>(Edge::End, endEdge) : computeEdgeValueForColumn<&Style::position>(endEdge); @@ -173,8 +173,8 @@ float Node::getInlineStartPosition( FlexDirection axis, Direction direction, float axisSize) const { - const Edge startEdge = getInlineStartEdgeUsingErrata(axis, direction); - auto leadingPosition = isRow(axis) + Edge startEdge = getInlineStartEdgeUsingErrata(axis, direction); + Style::Length leadingPosition = isRow(axis) ? computeEdgeValueForRow<&Style::position>(Edge::Start, startEdge) : computeEdgeValueForColumn<&Style::position>(startEdge); @@ -198,8 +198,8 @@ float Node::getInlineEndPosition( FlexDirection axis, Direction direction, float axisSize) const { - const Edge endEdge = getInlineEndEdgeUsingErrata(axis, direction); - auto trailingPosition = isRow(axis) + Edge endEdge = getInlineEndEdgeUsingErrata(axis, direction); + Style::Length trailingPosition = isRow(axis) ? computeEdgeValueForRow<&Style::position>(Edge::End, endEdge) : computeEdgeValueForColumn<&Style::position>(endEdge); @@ -223,8 +223,8 @@ float Node::getInlineStartMargin( FlexDirection axis, Direction direction, float widthSize) const { - const Edge startEdge = getInlineStartEdgeUsingErrata(axis, direction); - auto leadingMargin = isRow(axis) + Edge startEdge = getInlineStartEdgeUsingErrata(axis, direction); + Style::Length leadingMargin = isRow(axis) ? computeEdgeValueForRow<&Style::margin>(Edge::Start, startEdge) : computeEdgeValueForColumn<&Style::margin>(startEdge); @@ -248,8 +248,8 @@ float Node::getInlineEndMargin( FlexDirection axis, Direction direction, float widthSize) const { - const Edge endEdge = getInlineEndEdgeUsingErrata(axis, direction); - auto trailingMargin = isRow(axis) + Edge endEdge = getInlineEndEdgeUsingErrata(axis, direction); + Style::Length trailingMargin = isRow(axis) ? computeEdgeValueForRow<&Style::margin>(Edge::End, endEdge) : computeEdgeValueForColumn<&Style::margin>(endEdge); @@ -258,49 +258,49 @@ float Node::getInlineEndMargin( float Node::getInlineStartBorder(FlexDirection axis, Direction direction) const { - const Edge startEdge = getInlineStartEdgeUsingErrata(axis, direction); - YGValue leadingBorder = isRow(axis) + Edge startEdge = getInlineStartEdgeUsingErrata(axis, direction); + Style::Length leadingBorder = isRow(axis) ? computeEdgeValueForRow<&Style::border>(Edge::Start, startEdge) : computeEdgeValueForColumn<&Style::border>(startEdge); - return maxOrDefined(leadingBorder.value, 0.0f); + return maxOrDefined(leadingBorder.value().unwrap(), 0.0f); } float Node::getFlexStartBorder(FlexDirection axis, Direction direction) const { - YGValue leadingBorder = isRow(axis) + Style::Length leadingBorder = isRow(axis) ? computeEdgeValueForRow<&Style::border>( getFlexStartRelativeEdgeUsingErrata(axis, direction), flexStartEdge(axis)) : computeEdgeValueForColumn<&Style::border>(flexStartEdge(axis)); - return maxOrDefined(leadingBorder.value, 0.0f); + return maxOrDefined(leadingBorder.value().unwrap(), 0.0f); } float Node::getInlineEndBorder(FlexDirection axis, Direction direction) const { - const Edge endEdge = getInlineEndEdgeUsingErrata(axis, direction); - YGValue trailingBorder = isRow(axis) + Edge endEdge = getInlineEndEdgeUsingErrata(axis, direction); + Style::Length trailingBorder = isRow(axis) ? computeEdgeValueForRow<&Style::border>(Edge::End, endEdge) : computeEdgeValueForColumn<&Style::border>(endEdge); - return maxOrDefined(trailingBorder.value, 0.0f); + return maxOrDefined(trailingBorder.value().unwrap(), 0.0f); } float Node::getFlexEndBorder(FlexDirection axis, Direction direction) const { - YGValue trailingBorder = isRow(axis) + Style::Length trailingBorder = isRow(axis) ? computeEdgeValueForRow<&Style::border>( getFlexEndRelativeEdgeUsingErrata(axis, direction), flexEndEdge(axis)) : computeEdgeValueForColumn<&Style::border>(flexEndEdge(axis)); - return maxOrDefined(trailingBorder.value, 0.0f); + return maxOrDefined(trailingBorder.value().unwrap(), 0.0f); } float Node::getInlineStartPadding( FlexDirection axis, Direction direction, float widthSize) const { - const Edge startEdge = getInlineStartEdgeUsingErrata(axis, direction); - auto leadingPadding = isRow(axis) + Edge startEdge = getInlineStartEdgeUsingErrata(axis, direction); + Style::Length leadingPadding = isRow(axis) ? computeEdgeValueForRow<&Style::padding>(Edge::Start, startEdge) : computeEdgeValueForColumn<&Style::padding>(startEdge); @@ -324,8 +324,8 @@ float Node::getInlineEndPadding( FlexDirection axis, Direction direction, float widthSize) const { - const Edge endEdge = getInlineEndEdgeUsingErrata(axis, direction); - auto trailingPadding = isRow(axis) + Edge endEdge = getInlineEndEdgeUsingErrata(axis, direction); + Style::Length trailingPadding = isRow(axis) ? computeEdgeValueForRow<&Style::padding>(Edge::End, endEdge) : computeEdgeValueForColumn<&Style::padding>(endEdge); @@ -424,16 +424,18 @@ bool Node::isLayoutDimensionDefined(const FlexDirection axis) { bool Node::styleDefinesDimension( const FlexDirection axis, const float ownerSize) { - bool isDefined = yoga::isDefined(getResolvedDimension(dimension(axis)).value); - auto resolvedDimension = getResolvedDimension(dimension(axis)); + if (!resolvedDimension.isDefined()) { + return false; + } + return !( - resolvedDimension.unit == YGUnitAuto || - resolvedDimension.unit == YGUnitUndefined || - (resolvedDimension.unit == YGUnitPoint && isDefined && - resolvedDimension.value < 0.0f) || - (resolvedDimension.unit == YGUnitPercent && isDefined && - (resolvedDimension.value < 0.0f || yoga::isUndefined(ownerSize)))); + resolvedDimension.isAuto() || + (resolvedDimension.unit() == Unit::Point && + resolvedDimension.value().unwrap() < 0.0f) || + (resolvedDimension.unit() == Unit::Percent && + (resolvedDimension.value().unwrap() < 0.0f || + yoga::isUndefined(ownerSize)))); } // Setters @@ -621,7 +623,7 @@ void Node::setPosition( crossAxisTrailingEdge); } -YGValue Node::getFlexStartMarginValue(FlexDirection axis) const { +Style::Length Node::getFlexStartMarginValue(FlexDirection axis) const { if (isRow(axis) && style_.margin(Edge::Start).isDefined()) { return style_.margin(Edge::Start); } else { @@ -629,7 +631,7 @@ YGValue Node::getFlexStartMarginValue(FlexDirection axis) const { } } -YGValue Node::marginTrailingValue(FlexDirection axis) const { +Style::Length Node::marginTrailingValue(FlexDirection axis) const { if (isRow(axis) && style_.margin(Edge::End).isDefined()) { return style_.margin(Edge::End); } else { @@ -637,15 +639,15 @@ YGValue Node::marginTrailingValue(FlexDirection axis) const { } } -YGValue Node::resolveFlexBasisPtr() const { - YGValue flexBasis = style_.flexBasis(); - if (flexBasis.unit != YGUnitAuto && flexBasis.unit != YGUnitUndefined) { +Style::Length Node::resolveFlexBasisPtr() const { + Style::Length flexBasis = style_.flexBasis(); + if (flexBasis.unit() != Unit::Auto && flexBasis.unit() != Unit::Undefined) { return flexBasis; } if (style_.flex().isDefined() && style_.flex().unwrap() > 0.0f) { - return config_->useWebDefaults() ? YGValueAuto : YGValueZero; + return config_->useWebDefaults() ? value::ofAuto() : value::points(0); } - return YGValueAuto; + return value::ofAuto(); } void Node::resolveDimension() { diff --git a/yoga/node/Node.h b/yoga/node/Node.h index bbde5eac..19a52668 100644 --- a/yoga/node/Node.h +++ b/yoga/node/Node.h @@ -45,8 +45,8 @@ class YG_EXPORT Node : public ::YGNode { Node* owner_ = nullptr; std::vector children_ = {}; const Config* config_; - std::array resolvedDimensions_ = { - {YGValueUndefined, YGValueUndefined}}; + std::array resolvedDimensions_ = { + {value::undefined(), value::undefined()}}; float relativePosition( FlexDirection axis, @@ -199,11 +199,11 @@ class YG_EXPORT Node : public ::YGNode { return isDirty_; } - std::array getResolvedDimensions() const { + std::array getResolvedDimensions() const { return resolvedDimensions_; } - YGValue getResolvedDimension(Dimension dimension) const { + Style::Length getResolvedDimension(Dimension dimension) const { return resolvedDimensions_[static_cast(dimension)]; } @@ -366,9 +366,9 @@ class YG_EXPORT Node : public ::YGNode { const float ownerWidth); // Other methods - YGValue getFlexStartMarginValue(FlexDirection axis) const; - YGValue marginTrailingValue(FlexDirection axis) const; - YGValue resolveFlexBasisPtr() const; + Style::Length getFlexStartMarginValue(FlexDirection axis) const; + Style::Length marginTrailingValue(FlexDirection axis) const; + Style::Length resolveFlexBasisPtr() const; void resolveDimension(); Direction resolveDirection(const Direction ownerDirection); void clearChildren(); diff --git a/yoga/numeric/Comparison.h b/yoga/numeric/Comparison.h index 729589b9..0e23a837 100644 --- a/yoga/numeric/Comparison.h +++ b/yoga/numeric/Comparison.h @@ -24,6 +24,14 @@ constexpr bool isDefined(std::floating_point auto value) { return !isUndefined(value); } +/** + * Constexpr version of `std::isinf` before C++ 23 + */ +constexpr bool isinf(auto value) { + return value == +std::numeric_limits::infinity() || + value == -std::numeric_limits::infinity(); +} + constexpr auto maxOrDefined( std::floating_point auto a, std::floating_point auto b) { @@ -59,19 +67,6 @@ inline bool inexactEquals(double a, double b) { return yoga::isUndefined(a) && yoga::isUndefined(b); } -inline bool inexactEquals(const YGValue& a, const YGValue& b) { - if (a.unit != b.unit) { - return false; - } - - if (a.unit == YGUnitUndefined || - (yoga::isUndefined(a.value) && yoga::isUndefined(b.value))) { - return true; - } - - return fabs(a.value - b.value) < 0.0001f; -} - template bool inexactEquals( const std::array& val1, diff --git a/yoga/style/CompactValue.h b/yoga/style/CompactValue.h index d7884e1d..e80f2a9f 100644 --- a/yoga/style/CompactValue.h +++ b/yoga/style/CompactValue.h @@ -16,6 +16,7 @@ #include #include +#include static_assert( std::numeric_limits::is_iec559, @@ -42,7 +43,7 @@ namespace facebook::yoga { // 0x40000000 0x7f7fffff // - Zero is supported, negative zero is not // - values outside of the representable range are clamped -class YG_EXPORT CompactValue { +class CompactValue { friend constexpr bool operator==(CompactValue, CompactValue) noexcept; public: @@ -50,31 +51,6 @@ class YG_EXPORT CompactValue { static constexpr auto UPPER_BOUND_POINT = 36893485948395847680.0f; static constexpr auto UPPER_BOUND_PERCENT = 18446742974197923840.0f; - template - static CompactValue of(float value) noexcept { - if (yoga::isUndefined(value) || std::isinf(value)) { - return ofUndefined(); - } - - if (value == 0.0f || (value < LOWER_BOUND && value > -LOWER_BOUND)) { - constexpr auto zero = - Unit == YGUnitPercent ? ZERO_BITS_PERCENT : ZERO_BITS_POINT; - return {zero}; - } - - constexpr auto upperBound = - Unit == YGUnitPercent ? UPPER_BOUND_PERCENT : UPPER_BOUND_POINT; - if (value > upperBound || value < -upperBound) { - value = copysignf(upperBound, value); - } - - uint32_t unitBit = Unit == YGUnitPercent ? PERCENT_BIT : 0; - auto data = std::bit_cast(value); - data -= BIAS; - data |= unitBit; - return {data}; - } - static constexpr CompactValue ofUndefined() noexcept { return CompactValue{}; } @@ -83,46 +59,48 @@ class YG_EXPORT CompactValue { return CompactValue{AUTO_BITS}; } - constexpr CompactValue() noexcept : repr_(0x7FC00000) {} + constexpr CompactValue() noexcept = default; - CompactValue(const YGValue& x) noexcept : repr_(uint32_t{0}) { - switch (x.unit) { - case YGUnitUndefined: + explicit constexpr CompactValue(const StyleLength& x) noexcept { + switch (x.unit()) { + case Unit::Undefined: *this = ofUndefined(); break; - case YGUnitAuto: + case Unit::Auto: *this = ofAuto(); break; - case YGUnitPoint: - *this = of(x.value); + case Unit::Point: + *this = of(x.value().unwrap()); break; - case YGUnitPercent: - *this = of(x.value); + case Unit::Percent: + *this = of(x.value().unwrap()); break; } } - operator YGValue() const noexcept { - switch (repr_) { - case AUTO_BITS: - return YGValueAuto; - case ZERO_BITS_POINT: - return YGValue{0.0f, YGUnitPoint}; - case ZERO_BITS_PERCENT: - return YGValue{0.0f, YGUnitPercent}; + explicit operator StyleLength() const noexcept { + if (repr_ == 0x7FC00000) { + return value::undefined(); } - if (std::isnan(std::bit_cast(repr_))) { - return YGValueUndefined; + switch (repr_) { + case AUTO_BITS: + return value::ofAuto(); + case ZERO_BITS_POINT: + return value::points(0); + case ZERO_BITS_PERCENT: + return value::percent(0); } auto data = repr_; data &= ~PERCENT_BIT; data += BIAS; - return YGValue{ - std::bit_cast(data), - repr_ & 0x40000000 ? YGUnitPercent : YGUnitPoint}; + if (repr_ & 0x40000000) { + return value::percent(std::bit_cast(data)); + } else { + return value::points(std::bit_cast(data)); + } } bool isUndefined() const noexcept { @@ -140,7 +118,28 @@ class YG_EXPORT CompactValue { } private: - uint32_t repr_; + template + static CompactValue of(float value) noexcept { + if (value == 0.0f || (value < LOWER_BOUND && value > -LOWER_BOUND)) { + constexpr auto zero = + UnitT == Unit::Percent ? ZERO_BITS_PERCENT : ZERO_BITS_POINT; + return {zero}; + } + + constexpr auto upperBound = + UnitT == Unit::Percent ? UPPER_BOUND_PERCENT : UPPER_BOUND_POINT; + if (value > upperBound || value < -upperBound) { + value = copysignf(upperBound, value); + } + + uint32_t unitBit = UnitT == Unit::Percent ? PERCENT_BIT : 0; + auto data = std::bit_cast(value); + data -= BIAS; + data |= unitBit; + return {data}; + } + + uint32_t repr_{0x7FC00000}; static constexpr uint32_t BIAS = 0x20000000; static constexpr uint32_t PERCENT_BIT = 0x40000000; @@ -159,9 +158,9 @@ class YG_EXPORT CompactValue { }; template <> -CompactValue CompactValue::of(float) noexcept = delete; +CompactValue CompactValue::of(float) noexcept = delete; template <> -CompactValue CompactValue::of(float) noexcept = delete; +CompactValue CompactValue::of(float) noexcept = delete; constexpr bool operator==(CompactValue a, CompactValue b) noexcept { return a.repr_ == b.repr_; @@ -172,7 +171,7 @@ constexpr bool operator!=(CompactValue a, CompactValue b) noexcept { } inline bool inexactEquals(CompactValue a, CompactValue b) { - return inexactEquals((YGValue)a, (YGValue)b); + return inexactEquals((StyleLength)a, (StyleLength)b); } } // namespace facebook::yoga diff --git a/yoga/style/Style.h b/yoga/style/Style.h index b7fd8335..29933375 100644 --- a/yoga/style/Style.h +++ b/yoga/style/Style.h @@ -24,31 +24,17 @@ #include #include #include +#include #include #include #include -#include +#include namespace facebook::yoga { class YG_EXPORT Style { public: - /** - * Style::Length represents a CSS Value which may be one of: - * 1. Undefined - * 2. A keyword (e.g. auto) - * 3. A CSS value: - * a. value (e.g. 10px) - * b. value of a reference - * 4. (soon) A math function which returns a value - * - * References: - * 1. https://www.w3.org/TR/css-values-4/#lengths - * 2. https://www.w3.org/TR/css-values-4/#percentage-value - * 3. https://www.w3.org/TR/css-values-4/#mixed-percentages - * 4. https://www.w3.org/TR/css-values-4/#math - */ - using Length = CompactValue; + using Length = StyleLength; static constexpr float DefaultFlexGrow = 0.0f; static constexpr float DefaultFlexShrink = 0.0f; @@ -146,66 +132,66 @@ class YG_EXPORT Style { } Style::Length flexBasis() const { - return flexBasis_; + return (Style::Length)flexBasis_; } void setFlexBasis(Style::Length value) { - flexBasis_ = value; + flexBasis_ = CompactValue(value); } Style::Length margin(Edge edge) const { - return margin_[yoga::to_underlying(edge)]; + return (Style::Length)margin_[yoga::to_underlying(edge)]; } void setMargin(Edge edge, Style::Length value) { - margin_[yoga::to_underlying(edge)] = value; + margin_[yoga::to_underlying(edge)] = CompactValue(value); } Style::Length position(Edge edge) const { - return position_[yoga::to_underlying(edge)]; + return (Style::Length)position_[yoga::to_underlying(edge)]; } void setPosition(Edge edge, Style::Length value) { - position_[yoga::to_underlying(edge)] = value; + position_[yoga::to_underlying(edge)] = CompactValue(value); } Style::Length padding(Edge edge) const { - return padding_[yoga::to_underlying(edge)]; + return (Style::Length)padding_[yoga::to_underlying(edge)]; } void setPadding(Edge edge, Style::Length value) { - padding_[yoga::to_underlying(edge)] = value; + padding_[yoga::to_underlying(edge)] = CompactValue(value); } Style::Length border(Edge edge) const { - return border_[yoga::to_underlying(edge)]; + return (Style::Length)border_[yoga::to_underlying(edge)]; } void setBorder(Edge edge, Style::Length value) { - border_[yoga::to_underlying(edge)] = value; + border_[yoga::to_underlying(edge)] = CompactValue(value); } Style::Length gap(Gutter gutter) const { - return gap_[yoga::to_underlying(gutter)]; + return (Style::Length)gap_[yoga::to_underlying(gutter)]; } void setGap(Gutter gutter, Style::Length value) { - gap_[yoga::to_underlying(gutter)] = value; + gap_[yoga::to_underlying(gutter)] = CompactValue(value); } Style::Length dimension(Dimension axis) const { - return dimensions_[yoga::to_underlying(axis)]; + return (Style::Length)dimensions_[yoga::to_underlying(axis)]; } void setDimension(Dimension axis, Style::Length value) { - dimensions_[yoga::to_underlying(axis)] = value; + dimensions_[yoga::to_underlying(axis)] = CompactValue(value); } Style::Length minDimension(Dimension axis) const { - return minDimensions_[yoga::to_underlying(axis)]; + return (Style::Length)minDimensions_[yoga::to_underlying(axis)]; } void setMinDimension(Dimension axis, Style::Length value) { - minDimensions_[yoga::to_underlying(axis)] = value; + minDimensions_[yoga::to_underlying(axis)] = CompactValue(value); } Style::Length maxDimension(Dimension axis) const { - return maxDimensions_[yoga::to_underlying(axis)]; + return (Style::Length)maxDimensions_[yoga::to_underlying(axis)]; } void setMaxDimension(Dimension axis, Style::Length value) { - maxDimensions_[yoga::to_underlying(axis)] = value; + maxDimensions_[yoga::to_underlying(axis)] = CompactValue(value); } FloatOptional aspectRatio() const { @@ -217,17 +203,17 @@ class YG_EXPORT Style { Style::Length resolveColumnGap() const { if (gap_[yoga::to_underlying(Gutter::Column)].isDefined()) { - return gap_[yoga::to_underlying(Gutter::Column)]; + return (Style::Length)gap_[yoga::to_underlying(Gutter::Column)]; } else { - return gap_[yoga::to_underlying(Gutter::All)]; + return (Style::Length)gap_[yoga::to_underlying(Gutter::All)]; } } Style::Length resolveRowGap() const { if (gap_[yoga::to_underlying(Gutter::Row)].isDefined()) { - return gap_[yoga::to_underlying(Gutter::Row)]; + return (Style::Length)gap_[yoga::to_underlying(Gutter::Row)]; } else { - return gap_[yoga::to_underlying(Gutter::All)]; + return (Style::Length)gap_[yoga::to_underlying(Gutter::All)]; } } @@ -275,9 +261,9 @@ class YG_EXPORT Style { } private: - using Dimensions = std::array()>; - using Edges = std::array()>; - using Gutters = std::array()>; + using Dimensions = std::array()>; + using Edges = std::array()>; + using Gutters = std::array()>; Direction direction_ : bitCount() = Direction::Inherit; FlexDirection flexDirection_ @@ -295,13 +281,13 @@ class YG_EXPORT Style { FloatOptional flex_{}; FloatOptional flexGrow_{}; FloatOptional flexShrink_{}; - Style::Length flexBasis_{value::ofAuto()}; + CompactValue flexBasis_{CompactValue::ofAuto()}; Edges margin_{}; Edges position_{}; Edges padding_{}; Edges border_{}; Gutters gap_{}; - Dimensions dimensions_{value::ofAuto(), value::ofAuto()}; + Dimensions dimensions_{CompactValue::ofAuto(), CompactValue::ofAuto()}; Dimensions minDimensions_{}; Dimensions maxDimensions_{}; FloatOptional aspectRatio_{}; diff --git a/yoga/style/StyleLength.h b/yoga/style/StyleLength.h new file mode 100644 index 00000000..7212e573 --- /dev/null +++ b/yoga/style/StyleLength.h @@ -0,0 +1,128 @@ +/* + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +#pragma once + +#include +#include + +namespace facebook::yoga { + +/** + * Style::Length represents a CSS Value which may be one of: + * 1. Undefined + * 2. A keyword (e.g. auto) + * 3. A CSS value: + * a. value (e.g. 10px) + * b. value of a reference + * 4. (soon) A math function which returns a value + * + * References: + * 1. https://www.w3.org/TR/css-values-4/#lengths + * 2. https://www.w3.org/TR/css-values-4/#percentage-value + * 3. https://www.w3.org/TR/css-values-4/#mixed-percentages + * 4. https://www.w3.org/TR/css-values-4/#math + */ +class StyleLength { + public: + constexpr StyleLength() = default; + + constexpr static StyleLength points(float value) { + return yoga::isUndefined(value) || yoga::isinf(value) + ? undefined() + : StyleLength{FloatOptional{value}, Unit::Point}; + } + + constexpr static StyleLength percent(float value) { + return yoga::isUndefined(value) || yoga::isinf(value) + ? undefined() + : StyleLength{FloatOptional{value}, Unit::Percent}; + } + + constexpr static StyleLength ofAuto() { + return StyleLength{{}, Unit::Auto}; + } + + constexpr static StyleLength undefined() { + return StyleLength{{}, Unit::Undefined}; + } + + constexpr bool isAuto() const { + return unit_ == Unit::Auto; + } + + constexpr bool isUndefined() const { + return unit_ == Unit::Undefined; + } + + constexpr bool isDefined() const { + return !isUndefined(); + } + + constexpr FloatOptional value() const { + return value_; + } + + constexpr Unit unit() const { + return unit_; + } + + explicit constexpr operator YGValue() const { + return YGValue{value_.unwrap(), unscopedEnum(unit_)}; + } + + constexpr bool operator==(const StyleLength& rhs) const { + return value_ == rhs.value_ && unit_ == rhs.unit_; + } + + private: + // We intentionally do not allow direct construction using value and unit, to + // avoid invalid, or redundant combinations. + constexpr StyleLength(FloatOptional value, Unit unit) + : value_(value), unit_(unit) {} + + FloatOptional value_{}; + Unit unit_{Unit::Undefined}; +}; + +inline bool inexactEquals(const StyleLength& a, const StyleLength& b) { + return a.unit() == b.unit() && inexactEquals(a.value(), b.value()); +} + +namespace value { + +/** + * Canonical unit (one YGUnitPoint) + */ +constexpr StyleLength points(float value) { + return StyleLength::points(value); +} + +/** + * Percent of reference + */ +constexpr StyleLength percent(float value) { + return StyleLength::percent(value); +} + +/** + * "auto" keyword + */ +constexpr StyleLength ofAuto() { + return StyleLength::ofAuto(); +} + +/** + * Undefined + */ +constexpr StyleLength undefined() { + return StyleLength::undefined(); +} + +} // namespace value + +} // namespace facebook::yoga diff --git a/yoga/style/ValueFactories.h b/yoga/style/ValueFactories.h deleted file mode 100644 index 65486347..00000000 --- a/yoga/style/ValueFactories.h +++ /dev/null @@ -1,42 +0,0 @@ -/* - * Copyright (c) Meta Platforms, Inc. and affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - */ - -#pragma once - -#include - -namespace facebook::yoga::value { - -/** - * Canonical unit (one YGUnitPoint) - */ -inline CompactValue points(float value) { - return CompactValue::of(value); -} - -/** - * Percent of reference - */ -inline CompactValue percent(float value) { - return CompactValue::of(value); -} - -/** - * "auto" keyword - */ -inline CompactValue ofAuto() { - return CompactValue::ofAuto(); -} - -/** - * Undefined - */ -inline CompactValue undefined() { - return CompactValue::ofUndefined(); -} - -} // namespace facebook::yoga::value