diff --git a/tests/CompactValueTest.cpp b/tests/CompactValueTest.cpp index 76281c51b4..cd5e628655 100644 --- a/tests/CompactValueTest.cpp +++ b/tests/CompactValueTest.cpp @@ -304,20 +304,11 @@ TEST(YogaTest, dedicated_unit_factories) { ASSERT_EQ( CompactValue::of(123.456f), CompactValue(YGValue{123.456f, YGUnitPercent})); -} - -TEST(YogaTest, dedicated_unit_maybe_factories) { - ASSERT_EQ( - CompactValue::ofMaybe(-9876.5f), - CompactValue(YGValue{-9876.5f, YGUnitPoint})); ASSERT_EQ( - CompactValue::ofMaybe(YGUndefined), + CompactValue::of(YGUndefined), CompactValue(YGValueUndefined)); ASSERT_EQ( - CompactValue::ofMaybe(123.456f), - CompactValue(YGValue{123.456f, YGUnitPercent})); - ASSERT_EQ( - CompactValue::ofMaybe(YGUndefined), + CompactValue::of(YGUndefined), CompactValue(YGValueUndefined)); } diff --git a/yoga/YGNodeStyle.cpp b/yoga/YGNodeStyle.cpp index 38a55f2c8c..6767e5e8e3 100644 --- a/yoga/YGNodeStyle.cpp +++ b/yoga/YGNodeStyle.cpp @@ -26,22 +26,22 @@ void updateStyle( } } -template -void updateStyle(YGNodeRef node, Ref (Style::*prop)(), T value) { +template +void updateStyle(YGNodeRef node, Ref (Style::*prop)(), ValueT value) { updateStyle( resolveRef(node), value, - [prop](Style& s, T x) { return (s.*prop)() != x; }, - [prop](Style& s, T x) { (s.*prop)() = x; }); + [prop](Style& s, ValueT x) { return (s.*prop)() != x; }, + [prop](Style& s, ValueT x) { (s.*prop)() = x; }); } -template -void updateIndexedStyleProp(YGNodeRef node, IdxT idx, CompactValue value) { +template +void updateIndexedStyleProp(YGNodeRef node, IdxT idx, ValueT value) { updateStyle( resolveRef(node), value, - [idx](Style& s, CompactValue x) { return (s.*GetterT)(idx) != x; }, - [idx](Style& s, CompactValue x) { (s.*SetterT)(idx, x); }); + [idx](Style& s, ValueT x) { return (s.*GetterT)(idx) != x; }, + [idx](Style& s, ValueT x) { (s.*SetterT)(idx, x); }); } } // namespace @@ -198,20 +198,19 @@ float YGNodeStyleGetFlexShrink(const YGNodeConstRef nodeRef) { } void YGNodeStyleSetFlexBasis(const YGNodeRef node, const float flexBasis) { - auto value = CompactValue::ofMaybe(flexBasis); - updateStyle(node, &Style::flexBasis, value); + updateStyle( + node, &Style::flexBasis, value::points(flexBasis)); } void YGNodeStyleSetFlexBasisPercent( const YGNodeRef node, const float flexBasisPercent) { - auto value = CompactValue::ofMaybe(flexBasisPercent); - updateStyle(node, &Style::flexBasis, value); + updateStyle( + node, &Style::flexBasis, value::percent(flexBasisPercent)); } void YGNodeStyleSetFlexBasisAuto(const YGNodeRef node) { - updateStyle( - node, &Style::flexBasis, CompactValue::ofAuto()); + updateStyle(node, &Style::flexBasis, value::ofAuto()); } YGValue YGNodeStyleGetFlexBasis(const YGNodeConstRef node) { @@ -223,15 +222,13 @@ YGValue YGNodeStyleGetFlexBasis(const YGNodeConstRef node) { } void YGNodeStyleSetPosition(YGNodeRef node, YGEdge edge, float points) { - auto value = CompactValue::ofMaybe(points); updateIndexedStyleProp<&Style::position, &Style::setPosition>( - node, edge, value); + node, edge, value::points(points)); } void YGNodeStyleSetPositionPercent(YGNodeRef node, YGEdge edge, float percent) { - auto value = CompactValue::ofMaybe(percent); updateIndexedStyleProp<&Style::position, &Style::setPosition>( - node, edge, value); + node, edge, value::percent(percent)); } YGValue YGNodeStyleGetPosition(YGNodeConstRef node, YGEdge edge) { @@ -239,18 +236,18 @@ YGValue YGNodeStyleGetPosition(YGNodeConstRef node, YGEdge edge) { } void YGNodeStyleSetMargin(YGNodeRef node, YGEdge edge, float points) { - auto value = CompactValue::ofMaybe(points); - updateIndexedStyleProp<&Style::margin, &Style::setMargin>(node, edge, value); + updateIndexedStyleProp<&Style::margin, &Style::setMargin>( + node, edge, value::points(points)); } void YGNodeStyleSetMarginPercent(YGNodeRef node, YGEdge edge, float percent) { - auto value = CompactValue::ofMaybe(percent); - updateIndexedStyleProp<&Style::margin, &Style::setMargin>(node, edge, value); + updateIndexedStyleProp<&Style::margin, &Style::setMargin>( + node, edge, value::percent(percent)); } void YGNodeStyleSetMarginAuto(YGNodeRef node, YGEdge edge) { updateIndexedStyleProp<&Style::margin, &Style::setMargin>( - node, edge, CompactValue::ofAuto()); + node, edge, value::ofAuto()); } YGValue YGNodeStyleGetMargin(YGNodeConstRef node, YGEdge edge) { @@ -258,15 +255,13 @@ YGValue YGNodeStyleGetMargin(YGNodeConstRef node, YGEdge edge) { } void YGNodeStyleSetPadding(YGNodeRef node, YGEdge edge, float points) { - auto value = CompactValue::ofMaybe(points); updateIndexedStyleProp<&Style::padding, &Style::setPadding>( - node, edge, value); + node, edge, value::points(points)); } void YGNodeStyleSetPaddingPercent(YGNodeRef node, YGEdge edge, float percent) { - auto value = CompactValue::ofMaybe(percent); updateIndexedStyleProp<&Style::padding, &Style::setPadding>( - node, edge, value); + node, edge, value::percent(percent)); } YGValue YGNodeStyleGetPadding(YGNodeConstRef node, YGEdge edge) { @@ -277,8 +272,8 @@ void YGNodeStyleSetBorder( const YGNodeRef node, const YGEdge edge, const float border) { - auto value = CompactValue::ofMaybe(border); - updateIndexedStyleProp<&Style::border, &Style::setBorder>(node, edge, value); + updateIndexedStyleProp<&Style::border, &Style::setBorder>( + node, edge, value::points(border)); } float YGNodeStyleGetBorder(const YGNodeConstRef node, const YGEdge edge) { @@ -294,9 +289,8 @@ void YGNodeStyleSetGap( const YGNodeRef node, const YGGutter gutter, const float gapLength) { - auto length = CompactValue::ofMaybe(gapLength); updateIndexedStyleProp<&Style::gap, &Style::setGap>( - node, scopedEnum(gutter), length); + node, scopedEnum(gutter), value::points(gapLength)); } float YGNodeStyleGetGap(const YGNodeConstRef node, const YGGutter gutter) { @@ -319,20 +313,18 @@ float YGNodeStyleGetAspectRatio(const YGNodeConstRef node) { } void YGNodeStyleSetWidth(YGNodeRef node, float points) { - auto value = CompactValue::ofMaybe(points); updateIndexedStyleProp<&Style::dimension, &Style::setDimension>( - node, Dimension::Width, value); + node, Dimension::Width, value::points(points)); } void YGNodeStyleSetWidthPercent(YGNodeRef node, float percent) { - auto value = CompactValue::ofMaybe(percent); updateIndexedStyleProp<&Style::dimension, &Style::setDimension>( - node, Dimension::Width, value); + node, Dimension::Width, value::percent(percent)); } void YGNodeStyleSetWidthAuto(YGNodeRef node) { updateIndexedStyleProp<&Style::dimension, &Style::setDimension>( - node, Dimension::Width, CompactValue::ofAuto()); + node, Dimension::Width, value::ofAuto()); } YGValue YGNodeStyleGetWidth(YGNodeConstRef node) { @@ -340,20 +332,18 @@ YGValue YGNodeStyleGetWidth(YGNodeConstRef node) { } void YGNodeStyleSetHeight(YGNodeRef node, float points) { - auto value = CompactValue::ofMaybe(points); updateIndexedStyleProp<&Style::dimension, &Style::setDimension>( - node, Dimension::Height, value); + node, Dimension::Height, value::points(points)); } void YGNodeStyleSetHeightPercent(YGNodeRef node, float percent) { - auto value = CompactValue::ofMaybe(percent); updateIndexedStyleProp<&Style::dimension, &Style::setDimension>( - node, Dimension::Height, value); + node, Dimension::Height, value::percent(percent)); } void YGNodeStyleSetHeightAuto(YGNodeRef node) { updateIndexedStyleProp<&Style::dimension, &Style::setDimension>( - node, Dimension::Height, CompactValue::ofAuto()); + node, Dimension::Height, value::ofAuto()); } YGValue YGNodeStyleGetHeight(YGNodeConstRef node) { @@ -361,15 +351,13 @@ YGValue YGNodeStyleGetHeight(YGNodeConstRef node) { } void YGNodeStyleSetMinWidth(const YGNodeRef node, const float minWidth) { - auto value = CompactValue::ofMaybe(minWidth); updateIndexedStyleProp<&Style::minDimension, &Style::setMinDimension>( - node, Dimension::Width, value); + node, Dimension::Width, value::points(minWidth)); } void YGNodeStyleSetMinWidthPercent(const YGNodeRef node, const float minWidth) { - auto value = CompactValue::ofMaybe(minWidth); updateIndexedStyleProp<&Style::minDimension, &Style::setMinDimension>( - node, Dimension::Width, value); + node, Dimension::Width, value::percent(minWidth)); } YGValue YGNodeStyleGetMinWidth(const YGNodeConstRef node) { @@ -377,17 +365,15 @@ YGValue YGNodeStyleGetMinWidth(const YGNodeConstRef node) { } void YGNodeStyleSetMinHeight(const YGNodeRef node, const float minHeight) { - auto value = CompactValue::ofMaybe(minHeight); updateIndexedStyleProp<&Style::minDimension, &Style::setMinDimension>( - node, Dimension::Height, value); + node, Dimension::Height, value::points(minHeight)); } void YGNodeStyleSetMinHeightPercent( const YGNodeRef node, const float minHeight) { - auto value = CompactValue::ofMaybe(minHeight); updateIndexedStyleProp<&Style::minDimension, &Style::setMinDimension>( - node, Dimension::Height, value); + node, Dimension::Height, value::percent(minHeight)); } YGValue YGNodeStyleGetMinHeight(const YGNodeConstRef node) { @@ -395,15 +381,13 @@ YGValue YGNodeStyleGetMinHeight(const YGNodeConstRef node) { } void YGNodeStyleSetMaxWidth(const YGNodeRef node, const float maxWidth) { - auto value = CompactValue::ofMaybe(maxWidth); updateIndexedStyleProp<&Style::maxDimension, &Style::setMaxDimension>( - node, Dimension::Width, value); + node, Dimension::Width, value::points(maxWidth)); } void YGNodeStyleSetMaxWidthPercent(const YGNodeRef node, const float maxWidth) { - auto value = CompactValue::ofMaybe(maxWidth); updateIndexedStyleProp<&Style::maxDimension, &Style::setMaxDimension>( - node, Dimension::Width, value); + node, Dimension::Width, value::percent(maxWidth)); } YGValue YGNodeStyleGetMaxWidth(const YGNodeConstRef node) { @@ -411,17 +395,15 @@ YGValue YGNodeStyleGetMaxWidth(const YGNodeConstRef node) { } void YGNodeStyleSetMaxHeight(const YGNodeRef node, const float maxHeight) { - auto value = CompactValue::ofMaybe(maxHeight); updateIndexedStyleProp<&Style::maxDimension, &Style::setMaxDimension>( - node, Dimension::Height, value); + node, Dimension::Height, value::points(maxHeight)); } void YGNodeStyleSetMaxHeightPercent( const YGNodeRef node, const float maxHeight) { - auto value = CompactValue::ofMaybe(maxHeight); updateIndexedStyleProp<&Style::maxDimension, &Style::setMaxDimension>( - node, Dimension::Height, value); + node, Dimension::Height, value::percent(maxHeight)); } YGValue YGNodeStyleGetMaxHeight(const YGNodeConstRef node) { diff --git a/yoga/algorithm/ResolveValue.h b/yoga/algorithm/ResolveValue.h index 4e03d0c50d..a2d650b237 100644 --- a/yoga/algorithm/ResolveValue.h +++ b/yoga/algorithm/ResolveValue.h @@ -10,7 +10,7 @@ #include #include -#include +#include namespace facebook::yoga { @@ -25,7 +25,7 @@ inline FloatOptional resolveValue(const YGValue value, const float ownerSize) { } } -inline FloatOptional resolveValue(CompactValue value, float ownerSize) { +inline FloatOptional resolveValue(Style::Length value, float ownerSize) { return resolveValue((YGValue)value, ownerSize); } diff --git a/yoga/node/Node.cpp b/yoga/node/Node.cpp index e5100ee281..0781b8e63a 100644 --- a/yoga/node/Node.cpp +++ b/yoga/node/Node.cpp @@ -58,7 +58,7 @@ void Node::print() { // TODO: Edge value resolution should be moved to `yoga::Style` template -CompactValue Node::computeEdgeValueForRow(YGEdge rowEdge, YGEdge edge) const { +Style::Length Node::computeEdgeValueForRow(YGEdge rowEdge, YGEdge edge) const { if ((style_.*Field)(rowEdge).isDefined()) { return (style_.*Field)(rowEdge); } else if ((style_.*Field)(edge).isDefined()) { @@ -72,7 +72,7 @@ CompactValue Node::computeEdgeValueForRow(YGEdge rowEdge, YGEdge edge) const { // TODO: Edge value resolution should be moved to `yoga::Style` template -CompactValue Node::computeEdgeValueForColumn(YGEdge edge) const { +Style::Length Node::computeEdgeValueForColumn(YGEdge edge) const { if ((style_.*Field)(edge).isDefined()) { return (style_.*Field)(edge); } else if ((style_.*Field)(YGEdgeVertical).isDefined()) { @@ -497,8 +497,8 @@ void Node::setLayoutHadOverflow(bool hadOverflow) { layout_.setHadOverflow(hadOverflow); } -void Node::setLayoutDimension(float dimensionValue, Dimension dimension) { - layout_.setDimension(dimension, dimensionValue); +void Node::setLayoutDimension(float LengthValue, Dimension dimension) { + layout_.setDimension(dimension, LengthValue); } // If both left and right are defined, then use left. Otherwise return +left or diff --git a/yoga/node/Node.h b/yoga/node/Node.h index 9fefcf15aa..1c9acbbe86 100644 --- a/yoga/node/Node.h +++ b/yoga/node/Node.h @@ -20,7 +20,6 @@ #include #include #include -#include #include // Tag struct used to form the opaque YGNodeRef for the public C API @@ -66,10 +65,10 @@ class YG_EXPORT Node : public ::YGNode { } template - CompactValue computeEdgeValueForColumn(YGEdge edge) const; + Style::Length computeEdgeValueForColumn(YGEdge edge) const; template - CompactValue computeEdgeValueForRow(YGEdge rowEdge, YGEdge edge) const; + Style::Length computeEdgeValueForRow(YGEdge rowEdge, YGEdge edge) const; // DANGER DANGER DANGER! // If the node assigned to has children, we'd either have to deallocate @@ -327,7 +326,7 @@ class YG_EXPORT Node : public ::YGNode { uint32_t computedFlexBasisGeneration); void setLayoutMeasuredDimension(float measuredDimension, Dimension dimension); void setLayoutHadOverflow(bool hadOverflow); - void setLayoutDimension(float dimensionValue, Dimension dimension); + void setLayoutDimension(float LengthValue, Dimension dimension); void setLayoutDirection(Direction direction); void setLayoutMargin(float margin, YGEdge edge); void setLayoutBorder(float border, YGEdge edge); diff --git a/yoga/style/CompactValue.h b/yoga/style/CompactValue.h index a6ca3f1283..c32dd9276f 100644 --- a/yoga/style/CompactValue.h +++ b/yoga/style/CompactValue.h @@ -52,6 +52,10 @@ class YG_EXPORT CompactValue { 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; @@ -71,16 +75,6 @@ class YG_EXPORT CompactValue { return {data}; } - template - static CompactValue ofMaybe(float value) noexcept { - return std::isnan(value) || std::isinf(value) ? ofUndefined() - : of(value); - } - - static constexpr CompactValue ofZero() noexcept { - return CompactValue{ZERO_BITS_POINT}; - } - static constexpr CompactValue ofUndefined() noexcept { return CompactValue{}; } @@ -168,10 +162,6 @@ template <> CompactValue CompactValue::of(float) noexcept = delete; template <> CompactValue CompactValue::of(float) noexcept = delete; -template <> -CompactValue CompactValue::ofMaybe(float) noexcept = delete; -template <> -CompactValue CompactValue::ofMaybe(float) noexcept = delete; constexpr bool operator==(CompactValue a, CompactValue b) noexcept { return a.repr_ == b.repr_; diff --git a/yoga/style/Style.h b/yoga/style/Style.h index 06fbe23bb8..835632edd5 100644 --- a/yoga/style/Style.h +++ b/yoga/style/Style.h @@ -19,6 +19,7 @@ #include #include #include +#include #include #include #include @@ -27,18 +28,29 @@ #include #include #include +#include namespace facebook::yoga { class YG_EXPORT Style { - template - using Values = std::array()>; - - using Dimensions = Values; - using Edges = Values; - using Gutters = Values; - 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; + static constexpr float DefaultFlexGrow = 0.0f; static constexpr float DefaultFlexShrink = 0.0f; static constexpr float WebDefaultFlexShrink = 1.0f; @@ -75,6 +87,10 @@ class YG_EXPORT Style { ~Style() = default; private: + using Dimensions = std::array()>; + using Edges = std::array()>; + using Gutters = std::array()>; + static constexpr uint8_t directionOffset = 0; static constexpr uint8_t flexdirectionOffset = directionOffset + minimumBitCount(); @@ -100,13 +116,13 @@ class YG_EXPORT Style { FloatOptional flex_ = {}; FloatOptional flexGrow_ = {}; FloatOptional flexShrink_ = {}; - CompactValue flexBasis_ = CompactValue::ofAuto(); + Style::Length flexBasis_ = value::ofAuto(); Edges margin_ = {}; Edges position_ = {}; Edges padding_ = {}; Edges border_ = {}; Gutters gap_ = {}; - Dimensions dimensions_{CompactValue::ofAuto(), CompactValue::ofAuto()}; + Dimensions dimensions_{value::ofAuto(), value::ofAuto()}; Dimensions minDimensions_ = {}; Dimensions maxDimensions_ = {}; // Yoga specific properties, not compatible with flexbox specification @@ -204,66 +220,66 @@ class YG_EXPORT Style { return {*this}; } - CompactValue flexBasis() const { + Style::Length flexBasis() const { return flexBasis_; } - Ref flexBasis() { + Ref flexBasis() { return {*this}; } - CompactValue margin(YGEdge edge) const { + Style::Length margin(YGEdge edge) const { return margin_[edge]; } - void setMargin(YGEdge edge, CompactValue value) { + void setMargin(YGEdge edge, Style::Length value) { margin_[edge] = value; } - CompactValue position(YGEdge edge) const { + Style::Length position(YGEdge edge) const { return position_[edge]; } - void setPosition(YGEdge edge, CompactValue value) { + void setPosition(YGEdge edge, Style::Length value) { position_[edge] = value; } - CompactValue padding(YGEdge edge) const { + Style::Length padding(YGEdge edge) const { return padding_[edge]; } - void setPadding(YGEdge edge, CompactValue value) { + void setPadding(YGEdge edge, Style::Length value) { padding_[edge] = value; } - CompactValue border(YGEdge edge) const { + Style::Length border(YGEdge edge) const { return border_[edge]; } - void setBorder(YGEdge edge, CompactValue value) { + void setBorder(YGEdge edge, Style::Length value) { border_[edge] = value; } - CompactValue gap(Gutter gutter) const { + Style::Length gap(Gutter gutter) const { return gap_[yoga::to_underlying(gutter)]; } - void setGap(Gutter gutter, CompactValue value) { + void setGap(Gutter gutter, Style::Length value) { gap_[yoga::to_underlying(gutter)] = value; } - CompactValue dimension(Dimension axis) const { + Style::Length dimension(Dimension axis) const { return dimensions_[yoga::to_underlying(axis)]; } - void setDimension(Dimension axis, CompactValue value) { + void setDimension(Dimension axis, Style::Length value) { dimensions_[yoga::to_underlying(axis)] = value; } - CompactValue minDimension(Dimension axis) const { + Style::Length minDimension(Dimension axis) const { return minDimensions_[yoga::to_underlying(axis)]; } - void setMinDimension(Dimension axis, CompactValue value) { + void setMinDimension(Dimension axis, Style::Length value) { minDimensions_[yoga::to_underlying(axis)] = value; } - CompactValue maxDimension(Dimension axis) const { + Style::Length maxDimension(Dimension axis) const { return maxDimensions_[yoga::to_underlying(axis)]; } - void setMaxDimension(Dimension axis, CompactValue value) { + void setMaxDimension(Dimension axis, Style::Length value) { maxDimensions_[yoga::to_underlying(axis)] = value; } @@ -275,7 +291,7 @@ class YG_EXPORT Style { return {*this}; } - CompactValue resolveColumnGap() const { + Length resolveColumnGap() const { if (gap_[yoga::to_underlying(Gutter::Column)].isDefined()) { return gap_[yoga::to_underlying(Gutter::Column)]; } else { @@ -283,7 +299,7 @@ class YG_EXPORT Style { } } - CompactValue resolveRowGap() const { + Style::Length resolveRowGap() const { if (gap_[yoga::to_underlying(Gutter::Row)].isDefined()) { return gap_[yoga::to_underlying(Gutter::Row)]; } else { diff --git a/yoga/style/ValueFactories.h b/yoga/style/ValueFactories.h new file mode 100644 index 0000000000..bdb87fcf24 --- /dev/null +++ b/yoga/style/ValueFactories.h @@ -0,0 +1,42 @@ +/* + * 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