From 885b4cbdfb73bad75edc53b73b6a076af74c94b0 Mon Sep 17 00:00:00 2001 From: David Aurelio Date: Tue, 18 Dec 2018 08:11:24 -0800 Subject: [PATCH] Switch storage in `YGStyle` to `CompactValue` Summary: @public Switches the storage in `facebook::yoga::detail::Values` from `YGValue` to `facebook::yoga::detail::CompactValue`. This cuts heap size for arrays of values in half. Reviewed By: SidharthGuglani Differential Revision: D13465586 fbshipit-source-id: 49a4d6d29a73bdd44843b1f3c57bf746050c94d6 --- yoga/CompactValue.h | 6 +- yoga/Utils.h | 6 +- yoga/YGNode.cpp | 119 ++++++++++++------------ yoga/YGNodePrint.cpp | 4 +- yoga/YGStyle.h | 21 +++-- yoga/Yoga-internal.h | 18 ++-- yoga/Yoga.cpp | 212 ++++++++++++++++++++----------------------- 7 files changed, 195 insertions(+), 191 deletions(-) diff --git a/yoga/CompactValue.h b/yoga/CompactValue.h index 1ca9d619..7120f1c1 100644 --- a/yoga/CompactValue.h +++ b/yoga/CompactValue.h @@ -6,7 +6,7 @@ */ #pragma once -#include +#include "YGValue.h" #include #include @@ -73,6 +73,10 @@ class CompactValue { return std::isnan(value) ? ofUndefined() : of(value); } + static constexpr CompactValue ofZero() noexcept { + return CompactValue{Payload{ZERO_BITS_POINT}}; + } + static constexpr CompactValue ofUndefined() noexcept { return CompactValue{}; } diff --git a/yoga/Utils.h b/yoga/Utils.h index a0d49235..7e5a8636 100644 --- a/yoga/Utils.h +++ b/yoga/Utils.h @@ -7,6 +7,7 @@ #pragma once #include "YGNode.h" #include "Yoga-internal.h" +#include "CompactValue.h" // This struct is an helper model to hold the data for step 4 of flexbox // algo, which is collecting the flex items in a line. @@ -124,8 +125,7 @@ inline YGFlexDirection YGResolveFlexDirection( } inline YGFloatOptional YGResolveValueMargin( - const YGValue value, + yoga::detail::CompactValue value, const float ownerSize) { - return value.unit == YGUnitAuto ? YGFloatOptional(0) - : YGResolveValue(value, ownerSize); + return value.isAuto() ? YGFloatOptional{0} : YGResolveValue(value, ownerSize); } diff --git a/yoga/YGNode.cpp b/yoga/YGNode.cpp index 1a08fab8..8e7e210b 100644 --- a/yoga/YGNode.cpp +++ b/yoga/YGNode.cpp @@ -6,87 +6,92 @@ */ #include "YGNode.h" #include +#include "CompactValue.h" #include "Utils.h" using namespace facebook; +using facebook::yoga::detail::CompactValue; YGFloatOptional YGNode::getLeadingPosition( const YGFlexDirection axis, const float axisSize) const { if (YGFlexDirectionIsRow(axis)) { - const YGValue* leadingPosition = - YGComputedEdgeValue(style_.position, YGEdgeStart, &YGValueUndefined); - if (leadingPosition->unit != YGUnitUndefined) { - return YGResolveValue(*leadingPosition, axisSize); + auto leadingPosition = YGComputedEdgeValue( + style_.position, YGEdgeStart, CompactValue::ofUndefined()); + if (!leadingPosition.isUndefined()) { + return YGResolveValue(leadingPosition, axisSize); } } - const YGValue* leadingPosition = - YGComputedEdgeValue(style_.position, leading[axis], &YGValueUndefined); + auto leadingPosition = YGComputedEdgeValue( + style_.position, leading[axis], CompactValue::ofUndefined()); - return leadingPosition->unit == YGUnitUndefined - ? YGFloatOptional(0) - : YGResolveValue(*leadingPosition, axisSize); + return leadingPosition.isUndefined() + ? YGFloatOptional{0} + : YGResolveValue(leadingPosition, axisSize); } YGFloatOptional YGNode::getTrailingPosition( const YGFlexDirection axis, const float axisSize) const { if (YGFlexDirectionIsRow(axis)) { - const YGValue* trailingPosition = - YGComputedEdgeValue(style_.position, YGEdgeEnd, &YGValueUndefined); - if (trailingPosition->unit != YGUnitUndefined) { - return YGResolveValue(*trailingPosition, axisSize); + auto trailingPosition = YGComputedEdgeValue( + style_.position, YGEdgeEnd, CompactValue::ofUndefined()); + if (!trailingPosition.isUndefined()) { + return YGResolveValue(trailingPosition, axisSize); } } - const YGValue* trailingPosition = - YGComputedEdgeValue(style_.position, trailing[axis], &YGValueUndefined); + auto trailingPosition = YGComputedEdgeValue( + style_.position, trailing[axis], CompactValue::ofUndefined()); - return trailingPosition->unit == YGUnitUndefined - ? YGFloatOptional(0) - : YGResolveValue(*trailingPosition, axisSize); + return trailingPosition.isUndefined() + ? YGFloatOptional{0} + : YGResolveValue(trailingPosition, axisSize); } bool YGNode::isLeadingPositionDefined(const YGFlexDirection axis) const { return (YGFlexDirectionIsRow(axis) && - YGComputedEdgeValue(style_.position, YGEdgeStart, &YGValueUndefined) - ->unit != YGUnitUndefined) || - YGComputedEdgeValue(style_.position, leading[axis], &YGValueUndefined) - ->unit != YGUnitUndefined; + !YGComputedEdgeValue( + style_.position, YGEdgeStart, CompactValue::ofUndefined()) + .isUndefined()) || + !YGComputedEdgeValue( + style_.position, leading[axis], CompactValue::ofUndefined()) + .isUndefined(); } bool YGNode::isTrailingPosDefined(const YGFlexDirection axis) const { return (YGFlexDirectionIsRow(axis) && - YGComputedEdgeValue(style_.position, YGEdgeEnd, &YGValueUndefined) - ->unit != YGUnitUndefined) || - YGComputedEdgeValue(style_.position, trailing[axis], &YGValueUndefined) - ->unit != YGUnitUndefined; + !YGComputedEdgeValue( + style_.position, YGEdgeEnd, CompactValue::ofUndefined()) + .isUndefined()) || + !YGComputedEdgeValue( + style_.position, trailing[axis], CompactValue::ofUndefined()) + .isUndefined(); } YGFloatOptional YGNode::getLeadingMargin( const YGFlexDirection axis, const float widthSize) const { - if (YGFlexDirectionIsRow(axis) && - style_.margin[YGEdgeStart].unit != YGUnitUndefined) { + if (YGFlexDirectionIsRow(axis) && !style_.margin[YGEdgeStart].isUndefined()) { return YGResolveValueMargin(style_.margin[YGEdgeStart], widthSize); } return YGResolveValueMargin( - *YGComputedEdgeValue(style_.margin, leading[axis], &YGValueZero), + YGComputedEdgeValue(style_.margin, leading[axis], CompactValue::ofZero()), widthSize); } YGFloatOptional YGNode::getTrailingMargin( const YGFlexDirection axis, const float widthSize) const { - if (YGFlexDirectionIsRow(axis) && - style_.margin[YGEdgeEnd].unit != YGUnitUndefined) { + if (YGFlexDirectionIsRow(axis) && !style_.margin[YGEdgeEnd].isUndefined()) { return YGResolveValueMargin(style_.margin[YGEdgeEnd], widthSize); } return YGResolveValueMargin( - *YGComputedEdgeValue(style_.margin, trailing[axis], &YGValueZero), + YGComputedEdgeValue( + style_.margin, trailing[axis], CompactValue::ofZero()), widthSize); } @@ -280,8 +285,7 @@ YGNode& YGNode::operator=(const YGNode& node) { } YGValue YGNode::marginLeadingValue(const YGFlexDirection axis) const { - if (YGFlexDirectionIsRow(axis) && - style_.margin[YGEdgeStart].unit != YGUnitUndefined) { + if (YGFlexDirectionIsRow(axis) && !style_.margin[YGEdgeStart].isUndefined()) { return style_.margin[YGEdgeStart]; } else { return style_.margin[leading[axis]]; @@ -289,8 +293,7 @@ YGValue YGNode::marginLeadingValue(const YGFlexDirection axis) const { } YGValue YGNode::marginTrailingValue(const YGFlexDirection axis) const { - if (YGFlexDirectionIsRow(axis) && - style_.margin[YGEdgeEnd].unit != YGUnitUndefined) { + if (YGFlexDirectionIsRow(axis) && !style_.margin[YGEdgeEnd].isUndefined()) { return style_.margin[YGEdgeEnd]; } else { return style_.margin[trailing[axis]]; @@ -310,7 +313,7 @@ YGValue YGNode::resolveFlexBasisPtr() const { void YGNode::resolveDimension() { for (uint32_t dim = YGDimensionWidth; dim < YGDimensionCount; dim++) { - if (getStyle().maxDimensions[dim].unit != YGUnitUndefined && + if (!getStyle().maxDimensions[dim].isUndefined() && YGValueEqual( getStyle().maxDimensions[dim], style_.minDimensions[dim])) { resolvedDimensions_[dim] = style_.maxDimensions[dim]; @@ -422,30 +425,32 @@ bool YGNode::isNodeFlexible() { } float YGNode::getLeadingBorder(const YGFlexDirection axis) const { - if (YGFlexDirectionIsRow(axis) && - style_.border[YGEdgeStart].unit != YGUnitUndefined && - !yoga::isUndefined(style_.border[YGEdgeStart].value) && - style_.border[YGEdgeStart].value >= 0.0f) { - return style_.border[YGEdgeStart].value; + YGValue leadingBorder; + if (YGFlexDirectionIsRow(axis) && !style_.border[YGEdgeStart].isUndefined()) { + leadingBorder = style_.border[YGEdgeStart]; + if (leadingBorder.value >= 0) { + return leadingBorder.value; + } } - float computedEdgeValue = - YGComputedEdgeValue(style_.border, leading[axis], &YGValueZero)->value; - return YGFloatMax(computedEdgeValue, 0.0f); + leadingBorder = + YGComputedEdgeValue(style_.border, leading[axis], CompactValue::ofZero()); + return YGFloatMax(leadingBorder.value, 0.0f); } float YGNode::getTrailingBorder(const YGFlexDirection flexDirection) const { + YGValue trailingBorder; if (YGFlexDirectionIsRow(flexDirection) && - style_.border[YGEdgeEnd].unit != YGUnitUndefined && - !yoga::isUndefined(style_.border[YGEdgeEnd].value) && - style_.border[YGEdgeEnd].value >= 0.0f) { - return style_.border[YGEdgeEnd].value; + !style_.border[YGEdgeEnd].isUndefined()) { + trailingBorder = style_.border[YGEdgeEnd]; + if (trailingBorder.value >= 0.0f) { + return trailingBorder.value; + } } - float computedEdgeValue = - YGComputedEdgeValue(style_.border, trailing[flexDirection], &YGValueZero) - ->value; - return YGFloatMax(computedEdgeValue, 0.0f); + trailingBorder = YGComputedEdgeValue( + style_.border, trailing[flexDirection], CompactValue::ofZero()); + return YGFloatMax(trailingBorder.value, 0.0f); } YGFloatOptional YGNode::getLeadingPadding( @@ -454,13 +459,14 @@ YGFloatOptional YGNode::getLeadingPadding( const YGFloatOptional paddingEdgeStart = YGResolveValue(style_.padding[YGEdgeStart], widthSize); if (YGFlexDirectionIsRow(axis) && - style_.padding[YGEdgeStart].unit != YGUnitUndefined && + !style_.padding[YGEdgeStart].isUndefined() && !paddingEdgeStart.isUndefined() && paddingEdgeStart.unwrap() >= 0.0f) { return paddingEdgeStart; } YGFloatOptional resolvedValue = YGResolveValue( - *YGComputedEdgeValue(style_.padding, leading[axis], &YGValueZero), + YGComputedEdgeValue( + style_.padding, leading[axis], CompactValue::ofZero()), widthSize); return YGFloatOptionalMax(resolvedValue, YGFloatOptional(0.0f)); } @@ -475,7 +481,8 @@ YGFloatOptional YGNode::getTrailingPadding( } YGFloatOptional resolvedValue = YGResolveValue( - *YGComputedEdgeValue(style_.padding, trailing[axis], &YGValueZero), + YGComputedEdgeValue( + style_.padding, trailing[axis], CompactValue::ofZero()), widthSize); return YGFloatOptionalMax(resolvedValue, YGFloatOptional(0.0f)); diff --git a/yoga/YGNodePrint.cpp b/yoga/YGNodePrint.cpp index 03bff15a..4be2ff5a 100644 --- a/yoga/YGNodePrint.cpp +++ b/yoga/YGNodePrint.cpp @@ -99,7 +99,9 @@ static void appendEdgeIfNotUndefined( const facebook::yoga::detail::Values& edges, const YGEdge edge) { appendNumberIfNotUndefined( - base, str, *YGComputedEdgeValue(edges, edge, &YGValueUndefined)); + base, + str, + YGComputedEdgeValue(edges, edge, detail::CompactValue::ofUndefined())); } void YGNodeToString( diff --git a/yoga/YGStyle.h b/yoga/YGStyle.h index 63b255de..abcc7052 100644 --- a/yoga/YGStyle.h +++ b/yoga/YGStyle.h @@ -8,6 +8,7 @@ #include #include #include +#include "CompactValue.h" #include "YGFloatOptional.h" #include "Yoga-internal.h" #include "Yoga.h" @@ -17,6 +18,10 @@ constexpr YGValue kYGValueUndefined = {0, YGUnitUndefined}; constexpr YGValue kYGValueAuto = {0, YGUnitAuto}; struct YGStyle { + private: + using CompactValue = facebook::yoga::detail::CompactValue; + + public: using Dimensions = facebook::yoga::detail::Values<2>; using Edges = facebook::yoga::detail::Values; @@ -33,14 +38,14 @@ struct YGStyle { YGFloatOptional flex = {}; YGFloatOptional flexGrow = {}; YGFloatOptional flexShrink = {}; - YGValue flexBasis = kYGValueAuto; - Edges margin{kYGValueUndefined}; - Edges position{kYGValueUndefined}; - Edges padding{kYGValueUndefined}; - Edges border{kYGValueUndefined}; - Dimensions dimensions{kYGValueAuto}; - Dimensions minDimensions{kYGValueUndefined}; - Dimensions maxDimensions{kYGValueUndefined}; + CompactValue flexBasis = CompactValue::ofAuto(); + Edges margin = {}; + Edges position = {}; + Edges padding = {}; + Edges border = {}; + Dimensions dimensions{CompactValue::ofAuto()}; + Dimensions minDimensions = {}; + Dimensions maxDimensions = {}; // Yoga specific properties, not compatible with flexbox specification YGFloatOptional aspectRatio = {}; diff --git a/yoga/Yoga-internal.h b/yoga/Yoga-internal.h index 719d7b37..a182a465 100644 --- a/yoga/Yoga-internal.h +++ b/yoga/Yoga-internal.h @@ -9,6 +9,7 @@ #include #include #include +#include "CompactValue.h" #include "Yoga.h" using YGVector = std::vector; @@ -95,7 +96,7 @@ namespace detail { template class Values { private: - std::array values_; + std::array values_; public: Values() = default; @@ -103,10 +104,10 @@ class Values { values_.fill(defaultValue); } - const YGValue& operator[](size_t i) const noexcept { + const CompactValue& operator[](size_t i) const noexcept { return values_[i]; } - YGValue& operator[](size_t i) noexcept { + CompactValue& operator[](size_t i) noexcept { return values_[i]; } @@ -120,6 +121,11 @@ class Values { std::get(values_) = value; } + template + void set(YGValue&& value) noexcept { + set(value); + } + bool operator==(const Values& other) const noexcept { for (size_t i = 0; i < Size; ++i) { if (values_[i] != other.values_[i]) { @@ -142,7 +148,7 @@ static const float kWebDefaultFlexShrink = 1.0f; extern bool YGFloatsEqual(const float a, const float b); extern bool YGValueEqual(const YGValue a, const YGValue b); -extern const YGValue* YGComputedEdgeValue( +extern facebook::yoga::detail::CompactValue YGComputedEdgeValue( const facebook::yoga::detail::Values& edges, - const YGEdge edge, - const YGValue* const defaultValue); + YGEdge edge, + facebook::yoga::detail::CompactValue defaultValue); diff --git a/yoga/Yoga.cpp b/yoga/Yoga.cpp index beb01c59..9b8aa8a4 100644 --- a/yoga/Yoga.cpp +++ b/yoga/Yoga.cpp @@ -23,6 +23,8 @@ __forceinline const float fmaxf(const float a, const float b) { #endif #endif +using namespace facebook::yoga; + #ifdef ANDROID static int YGAndroidLog( const YGConfigRef config, @@ -102,31 +104,31 @@ bool YGFloatIsUndefined(const float value) { return facebook::yoga::isUndefined(value); } -const YGValue* YGComputedEdgeValue( +detail::CompactValue YGComputedEdgeValue( const facebook::yoga::detail::Values& edges, - const YGEdge edge, - const YGValue* const defaultValue) { - if (edges[edge].unit != YGUnitUndefined) { - return &edges[edge]; + YGEdge edge, + detail::CompactValue defaultValue) { + if (!edges[edge].isUndefined()) { + return edges[edge]; } if ((edge == YGEdgeTop || edge == YGEdgeBottom) && - edges[YGEdgeVertical].unit != YGUnitUndefined) { - return &edges[YGEdgeVertical]; + !edges[YGEdgeVertical].isUndefined()) { + return edges[YGEdgeVertical]; } if ((edge == YGEdgeLeft || edge == YGEdgeRight || edge == YGEdgeStart || edge == YGEdgeEnd) && - edges[YGEdgeHorizontal].unit != YGUnitUndefined) { - return &edges[YGEdgeHorizontal]; + !edges[YGEdgeHorizontal].isUndefined()) { + return edges[YGEdgeHorizontal]; } - if (edges[YGEdgeAll].unit != YGUnitUndefined) { - return &edges[YGEdgeAll]; + if (!edges[YGEdgeAll].isUndefined()) { + return edges[YGEdgeAll]; } if (edge == YGEdgeStart || edge == YGEdgeEnd) { - return &YGValueUndefined; + return detail::CompactValue::ofUndefined(); } return defaultValue; @@ -595,14 +597,21 @@ namespace { struct Value { template - static YGValue create(float value) { - return { - YGFloatSanitize(value), - YGFloatIsUndefined(value) ? YGUnitUndefined : U, - }; + static detail::CompactValue create(float value) { + return detail::CompactValue::ofMaybe(value); } }; +template <> +inline detail::CompactValue Value::create(float) { + return detail::CompactValue::ofUndefined(); +} + +template <> +inline detail::CompactValue Value::create(float) { + return detail::CompactValue::ofAuto(); +} + template struct DimensionProp { template @@ -616,10 +625,8 @@ struct DimensionProp { template static void set(YGNodeRef node, float newValue) { - YGValue value = Value::create(newValue); - if (((node->getStyle().*P)[idx].value != value.value && - value.unit != YGUnitUndefined) || - (node->getStyle().*P)[idx].unit != value.unit) { + auto value = Value::create(newValue); + if ((node->getStyle().*P)[idx] != value) { (node->getStyle().*P)[idx] = value; node->markDirtyAndPropogate(); } @@ -628,37 +635,30 @@ struct DimensionProp { } // namespace -#define YG_NODE_STYLE_PROPERTY_SETTER_UNIT_AUTO_IMPL( \ - type, name, paramName, instanceName) \ - void YGNodeStyleSet##name(const YGNodeRef node, const type paramName) { \ - YGValue value = { \ - YGFloatSanitize(paramName), \ - YGFloatIsUndefined(paramName) ? YGUnitUndefined : YGUnitPoint, \ - }; \ - if ((node->getStyle().instanceName.value != value.value && \ - value.unit != YGUnitUndefined) || \ - node->getStyle().instanceName.unit != value.unit) { \ - node->getStyle().instanceName = value; \ - node->markDirtyAndPropogate(); \ - } \ - } \ - \ - void YGNodeStyleSet##name##Percent( \ - const YGNodeRef node, const type paramName) { \ - if (node->getStyle().instanceName.value != YGFloatSanitize(paramName) || \ - node->getStyle().instanceName.unit != YGUnitPercent) { \ - node->getStyle().instanceName = YGFloatIsUndefined(paramName) \ - ? YGValue{0, YGUnitAuto} \ - : YGValue{paramName, YGUnitPercent}; \ - node->markDirtyAndPropogate(); \ - } \ - } \ - \ - void YGNodeStyleSet##name##Auto(const YGNodeRef node) { \ - if (node->getStyle().instanceName.unit != YGUnitAuto) { \ - node->getStyle().instanceName = {0, YGUnitAuto}; \ - node->markDirtyAndPropogate(); \ - } \ +#define YG_NODE_STYLE_PROPERTY_SETTER_UNIT_AUTO_IMPL( \ + type, name, paramName, instanceName) \ + void YGNodeStyleSet##name(const YGNodeRef node, const type paramName) { \ + auto value = detail::CompactValue::ofMaybe(paramName); \ + if (node->getStyle().instanceName != value) { \ + node->getStyle().instanceName = value; \ + node->markDirtyAndPropogate(); \ + } \ + } \ + \ + void YGNodeStyleSet##name##Percent( \ + const YGNodeRef node, const type paramName) { \ + auto value = detail::CompactValue::ofMaybe(paramName); \ + if (node->getStyle().instanceName != value) { \ + node->getStyle().instanceName = value; \ + node->markDirtyAndPropogate(); \ + } \ + } \ + \ + void YGNodeStyleSet##name##Auto(const YGNodeRef node) { \ + if (node->getStyle().instanceName != detail::CompactValue::ofAuto()) { \ + node->getStyle().instanceName = detail::CompactValue::ofAuto(); \ + node->markDirtyAndPropogate(); \ + } \ } #define YG_NODE_STYLE_PROPERTY_UNIT_AUTO_IMPL( \ @@ -676,49 +676,40 @@ struct DimensionProp { #define YG_NODE_STYLE_EDGE_PROPERTY_UNIT_AUTO_IMPL(type, name, instanceName) \ void YGNodeStyleSet##name##Auto(const YGNodeRef node, const YGEdge edge) { \ - if (node->getStyle().instanceName[edge].unit != YGUnitAuto) { \ - node->getStyle().instanceName[edge] = {0, YGUnitAuto}; \ + if (node->getStyle().instanceName[edge] != \ + detail::CompactValue::ofAuto()) { \ + node->getStyle().instanceName[edge] = detail::CompactValue::ofAuto(); \ node->markDirtyAndPropogate(); \ } \ } -#define YG_NODE_STYLE_EDGE_PROPERTY_UNIT_IMPL( \ - type, name, paramName, instanceName) \ - void YGNodeStyleSet##name( \ - const YGNodeRef node, const YGEdge edge, const float paramName) { \ - YGValue value = { \ - YGFloatSanitize(paramName), \ - YGFloatIsUndefined(paramName) ? YGUnitUndefined : YGUnitPoint, \ - }; \ - if ((node->getStyle().instanceName[edge].value != value.value && \ - value.unit != YGUnitUndefined) || \ - node->getStyle().instanceName[edge].unit != value.unit) { \ - node->getStyle().instanceName[edge] = value; \ - node->markDirtyAndPropogate(); \ - } \ - } \ - \ - void YGNodeStyleSet##name##Percent( \ - const YGNodeRef node, const YGEdge edge, const float paramName) { \ - YGValue value = { \ - YGFloatSanitize(paramName), \ - YGFloatIsUndefined(paramName) ? YGUnitUndefined : YGUnitPercent, \ - }; \ - if ((node->getStyle().instanceName[edge].value != value.value && \ - value.unit != YGUnitUndefined) || \ - node->getStyle().instanceName[edge].unit != value.unit) { \ - node->getStyle().instanceName[edge] = value; \ - node->markDirtyAndPropogate(); \ - } \ - } \ - \ - WIN_STRUCT(type) \ - YGNodeStyleGet##name(const YGNodeRef node, const YGEdge edge) { \ - YGValue value = node->getStyle().instanceName[edge]; \ - if (value.unit == YGUnitUndefined || value.unit == YGUnitAuto) { \ - value.value = YGUndefined; \ - } \ - return WIN_STRUCT_REF(value); \ +#define YG_NODE_STYLE_EDGE_PROPERTY_UNIT_IMPL( \ + type, name, paramName, instanceName) \ + void YGNodeStyleSet##name( \ + const YGNodeRef node, const YGEdge edge, const float paramName) { \ + auto value = detail::CompactValue::ofMaybe(paramName); \ + if (node->getStyle().instanceName[edge] != value) { \ + node->getStyle().instanceName[edge] = value; \ + node->markDirtyAndPropogate(); \ + } \ + } \ + \ + void YGNodeStyleSet##name##Percent( \ + const YGNodeRef node, const YGEdge edge, const float paramName) { \ + auto value = detail::CompactValue::ofMaybe(paramName); \ + if (node->getStyle().instanceName[edge] != value) { \ + node->getStyle().instanceName[edge] = value; \ + node->markDirtyAndPropogate(); \ + } \ + } \ + \ + WIN_STRUCT(type) \ + YGNodeStyleGet##name(const YGNodeRef node, const YGEdge edge) { \ + YGValue value = node->getStyle().instanceName[edge]; \ + if (value.unit == YGUnitUndefined || value.unit == YGUnitAuto) { \ + value.value = YGUndefined; \ + } \ + return WIN_STRUCT_REF(value); \ } #define YG_NODE_LAYOUT_PROPERTY_IMPL(type, name, instanceName) \ @@ -881,13 +872,8 @@ YGValue YGNodeStyleGetFlexBasis(const YGNodeRef node) { } void YGNodeStyleSetFlexBasis(const YGNodeRef node, const float flexBasis) { - YGValue value = { - YGFloatSanitize(flexBasis), - YGFloatIsUndefined(flexBasis) ? YGUnitUndefined : YGUnitPoint, - }; - if ((node->getStyle().flexBasis.value != value.value && - value.unit != YGUnitUndefined) || - node->getStyle().flexBasis.unit != value.unit) { + auto value = detail::CompactValue::ofMaybe(flexBasis); + if (node->getStyle().flexBasis != value) { node->getStyle().flexBasis = value; node->markDirtyAndPropogate(); } @@ -896,18 +882,16 @@ void YGNodeStyleSetFlexBasis(const YGNodeRef node, const float flexBasis) { void YGNodeStyleSetFlexBasisPercent( const YGNodeRef node, const float flexBasisPercent) { - if (node->getStyle().flexBasis.value != flexBasisPercent || - node->getStyle().flexBasis.unit != YGUnitPercent) { - node->getStyle().flexBasis = YGFloatIsUndefined(flexBasisPercent) - ? YGValue{0, YGUnitAuto} - : YGValue{flexBasisPercent, YGUnitPercent}; + auto value = detail::CompactValue::ofMaybe(flexBasisPercent); + if (node->getStyle().flexBasis != value) { + node->getStyle().flexBasis = value; node->markDirtyAndPropogate(); } } void YGNodeStyleSetFlexBasisAuto(const YGNodeRef node) { - if (node->getStyle().flexBasis.unit != YGUnitAuto) { - node->getStyle().flexBasis = {0, YGUnitAuto}; + if (node->getStyle().flexBasis != detail::CompactValue::ofAuto()) { + node->getStyle().flexBasis = detail::CompactValue::ofAuto(); node->markDirtyAndPropogate(); } } @@ -922,27 +906,23 @@ void YGNodeStyleSetBorder( const YGNodeRef node, const YGEdge edge, const float border) { - YGValue value = { - YGFloatSanitize(border), - YGFloatIsUndefined(border) ? YGUnitUndefined : YGUnitPoint, - }; - if ((node->getStyle().border[edge].value != value.value && - value.unit != YGUnitUndefined) || - node->getStyle().border[edge].unit != value.unit) { + auto value = detail::CompactValue::ofMaybe(border); + if (node->getStyle().border[edge] != value) { node->getStyle().border[edge] = value; node->markDirtyAndPropogate(); } } float YGNodeStyleGetBorder(const YGNodeRef node, const YGEdge edge) { - if (node->getStyle().border[edge].unit == YGUnitUndefined || - node->getStyle().border[edge].unit == YGUnitAuto) { + if (node->getStyle().border[edge].isUndefined() || + node->getStyle().border[edge].isAuto()) { // TODO(T26792433): Rather than returning YGUndefined, change the api to // return YGFloatOptional. return YGUndefined; } - return node->getStyle().border[edge].value; + auto border = (YGValue)node->getStyle().border[edge]; + return border.value; } // Yoga specific properties, not compatible with flexbox specification @@ -2433,7 +2413,7 @@ static void YGJustifyMainAxis( // remainingFreeSpace is 0 when min main dimension is not given if (measureModeMainDim == YGMeasureModeAtMost && collectedFlexItemsValues.remainingFreeSpace > 0) { - if (style.minDimensions[dim[mainAxis]].unit != YGUnitUndefined && + if (!style.minDimensions[dim[mainAxis]].isUndefined() && !YGResolveValue(style.minDimensions[dim[mainAxis]], mainAxisownerSize) .isUndefined()) { // This condition makes sure that if the size of main dimension(after