From ac94e54f5ad733005ee5bea28cda2c92ae1e0be6 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 --- React/React.xcodeproj/project.pbxproj | 12 +- ReactCommon/yoga/yoga/CompactValue.h | 6 +- ReactCommon/yoga/yoga/Utils.h | 6 +- ReactCommon/yoga/yoga/YGNode.cpp | 119 ++++++++------- ReactCommon/yoga/yoga/YGNodePrint.cpp | 4 +- ReactCommon/yoga/yoga/YGStyle.h | 21 ++- ReactCommon/yoga/yoga/Yoga-internal.h | 18 ++- ReactCommon/yoga/yoga/Yoga.cpp | 212 ++++++++++++-------------- 8 files changed, 205 insertions(+), 193 deletions(-) diff --git a/React/React.xcodeproj/project.pbxproj b/React/React.xcodeproj/project.pbxproj index f458eb992..e2f7f4379 100644 --- a/React/React.xcodeproj/project.pbxproj +++ b/React/React.xcodeproj/project.pbxproj @@ -1084,6 +1084,10 @@ AC8360D121B025BC00FC46B9 /* YGConfig.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 5CE2080020772F7C009A43B3 /* YGConfig.cpp */; }; AC8360D221B025EF00FC46B9 /* YGConfig.h in Headers */ = {isa = PBXBuildFile; fileRef = 5CE2080120772F7C009A43B3 /* YGConfig.h */; }; AC8360D321B0263000FC46B9 /* YGMarker.h in Copy Headers */ = {isa = PBXBuildFile; fileRef = AC8360CC21B0256A00FC46B9 /* YGMarker.h */; }; + AC90463E21C91CC2005B24B3 /* CompactValue.h in Headers */ = {isa = PBXBuildFile; fileRef = AC90463D21C91CC2005B24B3 /* CompactValue.h */; }; + AC90463F21C91D02005B24B3 /* CompactValue.h in Headers */ = {isa = PBXBuildFile; fileRef = AC90463D21C91CC2005B24B3 /* CompactValue.h */; }; + AC90464021C91D14005B24B3 /* CompactValue.h in Headers */ = {isa = PBXBuildFile; fileRef = AC90463D21C91CC2005B24B3 /* CompactValue.h */; }; + AC90464121C91DB8005B24B3 /* YGConfig.h in Copy Headers */ = {isa = PBXBuildFile; fileRef = 5CE2080120772F7C009A43B3 /* YGConfig.h */; }; B233E6EA1D2D845D00BC68BA /* RCTI18nManager.m in Sources */ = {isa = PBXBuildFile; fileRef = B233E6E91D2D845D00BC68BA /* RCTI18nManager.m */; }; B95154321D1B34B200FE7B80 /* RCTActivityIndicatorView.m in Sources */ = {isa = PBXBuildFile; fileRef = B95154311D1B34B200FE7B80 /* RCTActivityIndicatorView.m */; }; BA0501AD2109DCF200A6BBC4 /* ReactMarker.h in Copy Headers */ = {isa = PBXBuildFile; fileRef = 13DA8A2F2097A90A00276ED4 /* ReactMarker.h */; }; @@ -1700,6 +1704,7 @@ dstPath = include/yoga; dstSubfolderSpec = 16; files = ( + AC90464121C91DB8005B24B3 /* YGConfig.h in Copy Headers */, AC6B69E621B146A500B2B68A /* YGValue.h in Copy Headers */, AC8360D321B0263000FC46B9 /* YGMarker.h in Copy Headers */, 3DE4F8681DF85D8E00B9E5A0 /* YGEnums.h in Copy Headers */, @@ -2102,7 +2107,6 @@ 53CBF1861FB4FE80002CBB31 /* YGEnums.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = YGEnums.cpp; sourceTree = ""; }; 53CBF1871FB4FE80002CBB31 /* Yoga.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Yoga.cpp; sourceTree = ""; }; 53D123831FBF1D49001B8A10 /* libyoga.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libyoga.a; path = "../../../../../../../../../Library/Developer/Xcode/DerivedData/yoga-hdfifpwsinitsibujacpiefkjfdy/Build/Products/Debug/libyoga.a"; sourceTree = ""; }; - 53DEF6E6205AE59B006A3890 /* YGFloatOptional.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = YGFloatOptional.cpp; sourceTree = ""; }; 53DEF6E7205AE59C006A3890 /* YGFloatOptional.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = YGFloatOptional.h; sourceTree = ""; }; 53EC85DE1FDEC75A0051B2B5 /* YGNode.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = YGNode.h; sourceTree = ""; }; 53EC85DF1FDEC75A0051B2B5 /* YGNode.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = YGNode.cpp; sourceTree = ""; }; @@ -2227,6 +2231,7 @@ AC70D2E81DE489E4002E6351 /* RCTJavaScriptLoader.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = RCTJavaScriptLoader.mm; sourceTree = ""; }; AC70D2EB1DE48A22002E6351 /* JSBundleType.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSBundleType.cpp; sourceTree = ""; }; AC8360CC21B0256A00FC46B9 /* YGMarker.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = YGMarker.h; sourceTree = ""; }; + AC90463D21C91CC2005B24B3 /* CompactValue.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CompactValue.h; sourceTree = ""; }; ACDD3FDA1BC7430D00E7DE33 /* RCTBorderStyle.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RCTBorderStyle.h; sourceTree = ""; }; B233E6E81D2D843200BC68BA /* RCTI18nManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; lineEnding = 0; path = RCTI18nManager.h; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.objcpp; }; B233E6E91D2D845D00BC68BA /* RCTI18nManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RCTI18nManager.m; sourceTree = ""; }; @@ -2349,12 +2354,12 @@ 130A77021DF767AF001F9587 /* yoga */ = { isa = PBXGroup; children = ( + AC90463D21C91CC2005B24B3 /* CompactValue.h */, AC6B69E121B1467C00B2B68A /* YGValue.cpp */, AC6B69E221B1467C00B2B68A /* YGValue.h */, AC8360CC21B0256A00FC46B9 /* YGMarker.h */, 5CE2080020772F7C009A43B3 /* YGConfig.cpp */, 5CE2080120772F7C009A43B3 /* YGConfig.h */, - 53DEF6E6205AE59B006A3890 /* YGFloatOptional.cpp */, 53DEF6E7205AE59C006A3890 /* YGFloatOptional.h */, 5343895E203905B6008E0CB3 /* YGLayout.cpp */, 5343895F203905B6008E0CB3 /* YGLayout.h */, @@ -3278,6 +3283,7 @@ isa = PBXHeadersBuildPhase; buildActionMask = 2147483647; files = ( + AC90463F21C91D02005B24B3 /* CompactValue.h in Headers */, AC6B69E821B146C500B2B68A /* YGValue.h in Headers */, AC8360D221B025EF00FC46B9 /* YGConfig.h in Headers */, AC8360CE21B0256A00FC46B9 /* YGMarker.h in Headers */, @@ -3342,6 +3348,7 @@ isa = PBXHeadersBuildPhase; buildActionMask = 2147483647; files = ( + AC90464021C91D14005B24B3 /* CompactValue.h in Headers */, AC6B69E521B1469A00B2B68A /* YGValue.h in Headers */, AC8360CF21B0258B00FC46B9 /* YGConfig.h in Headers */, AC8360CD21B0256A00FC46B9 /* YGMarker.h in Headers */, @@ -3457,6 +3464,7 @@ 3D80DA3E1DF820620028D040 /* RCTRootViewDelegate.h in Headers */, 3D80DA3F1DF820620028D040 /* RCTRootViewInternal.h in Headers */, 3D80DA401DF820620028D040 /* RCTTouchEvent.h in Headers */, + AC90463E21C91CC2005B24B3 /* CompactValue.h in Headers */, 3D80DA411DF820620028D040 /* RCTTouchHandler.h in Headers */, 59E604A61FE9CCE300BD90C5 /* RCTScrollContentViewManager.h in Headers */, 13134C8C1E296B2A00B9F3CB /* RCTMessageThread.h in Headers */, diff --git a/ReactCommon/yoga/yoga/CompactValue.h b/ReactCommon/yoga/yoga/CompactValue.h index 1ca9d619b..7120f1c1f 100644 --- a/ReactCommon/yoga/yoga/CompactValue.h +++ b/ReactCommon/yoga/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/ReactCommon/yoga/yoga/Utils.h b/ReactCommon/yoga/yoga/Utils.h index a0d492355..7e5a8636d 100644 --- a/ReactCommon/yoga/yoga/Utils.h +++ b/ReactCommon/yoga/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/ReactCommon/yoga/yoga/YGNode.cpp b/ReactCommon/yoga/yoga/YGNode.cpp index 1a08fab87..8e7e210bd 100644 --- a/ReactCommon/yoga/yoga/YGNode.cpp +++ b/ReactCommon/yoga/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/ReactCommon/yoga/yoga/YGNodePrint.cpp b/ReactCommon/yoga/yoga/YGNodePrint.cpp index 03bff15ae..4be2ff5af 100644 --- a/ReactCommon/yoga/yoga/YGNodePrint.cpp +++ b/ReactCommon/yoga/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/ReactCommon/yoga/yoga/YGStyle.h b/ReactCommon/yoga/yoga/YGStyle.h index 63b255dec..abcc7052f 100644 --- a/ReactCommon/yoga/yoga/YGStyle.h +++ b/ReactCommon/yoga/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/ReactCommon/yoga/yoga/Yoga-internal.h b/ReactCommon/yoga/yoga/Yoga-internal.h index 719d7b375..a182a4657 100644 --- a/ReactCommon/yoga/yoga/Yoga-internal.h +++ b/ReactCommon/yoga/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/ReactCommon/yoga/yoga/Yoga.cpp b/ReactCommon/yoga/yoga/Yoga.cpp index beb01c599..9b8aa8a4a 100644 --- a/ReactCommon/yoga/yoga/Yoga.cpp +++ b/ReactCommon/yoga/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