diff --git a/java/jni/YGJNIVanilla.cpp b/java/jni/YGJNIVanilla.cpp index b1cdc2dacf..5a712b0fa6 100644 --- a/java/jni/YGJNIVanilla.cpp +++ b/java/jni/YGJNIVanilla.cpp @@ -15,6 +15,8 @@ #include #include "YogaJniException.h" +#include + // TODO: Reconcile missing layoutContext functionality from callbacks in the C // API and use that #include diff --git a/yoga/Yoga-internal.h b/yoga/Yoga-internal.h index 3403282446..b10cf5d246 100644 --- a/yoga/Yoga-internal.h +++ b/yoga/Yoga-internal.h @@ -8,14 +8,11 @@ #pragma once #include -#include #include #include #include -#include - YG_EXTERN_C_BEGIN void YGNodeCalculateLayoutWithContext( @@ -30,120 +27,3 @@ void YGNodeCalculateLayoutWithContext( void YGNodeDeallocate(YGNodeRef node); YG_EXTERN_C_END - -namespace facebook::yoga { - -inline bool isUndefined(float value) { - return std::isnan(value); -} - -inline bool isUndefined(double value) { - return std::isnan(value); -} - -} // namespace facebook::yoga - -extern const std::array trailing; -extern const std::array leading; -extern const YGValue YGValueUndefined; -extern const YGValue YGValueAuto; -extern const YGValue YGValueZero; - -struct YGCachedMeasurement { - float availableWidth; - float availableHeight; - YGMeasureMode widthMeasureMode; - YGMeasureMode heightMeasureMode; - - float computedWidth; - float computedHeight; - - YGCachedMeasurement() - : availableWidth(-1), - availableHeight(-1), - widthMeasureMode(YGMeasureModeUndefined), - heightMeasureMode(YGMeasureModeUndefined), - computedWidth(-1), - computedHeight(-1) {} - - bool operator==(YGCachedMeasurement measurement) const { - using namespace facebook; - - bool isEqual = widthMeasureMode == measurement.widthMeasureMode && - heightMeasureMode == measurement.heightMeasureMode; - - if (!yoga::isUndefined(availableWidth) || - !yoga::isUndefined(measurement.availableWidth)) { - isEqual = isEqual && availableWidth == measurement.availableWidth; - } - if (!yoga::isUndefined(availableHeight) || - !yoga::isUndefined(measurement.availableHeight)) { - isEqual = isEqual && availableHeight == measurement.availableHeight; - } - if (!yoga::isUndefined(computedWidth) || - !yoga::isUndefined(measurement.computedWidth)) { - isEqual = isEqual && computedWidth == measurement.computedWidth; - } - if (!yoga::isUndefined(computedHeight) || - !yoga::isUndefined(measurement.computedHeight)) { - isEqual = isEqual && computedHeight == measurement.computedHeight; - } - - return isEqual; - } -}; - -// This value was chosen based on empirical data: -// 98% of analyzed layouts require less than 8 entries. -#define YG_MAX_CACHED_RESULT_COUNT 8 - -namespace facebook::yoga::detail { - -template -class Values { -private: - std::array values_; - -public: - Values() = default; - Values(const Values& other) = default; - - explicit Values(const YGValue& defaultValue) noexcept { - values_.fill(defaultValue); - } - - const CompactValue& operator[](size_t i) const noexcept { return values_[i]; } - CompactValue& operator[](size_t i) noexcept { return values_[i]; } - - template - YGValue get() const noexcept { - return std::get(values_); - } - - template - void set(YGValue& value) noexcept { - 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]) { - return false; - } - } - return true; - } - - Values& operator=(const Values& other) = default; -}; - -} // namespace facebook::yoga::detail - -static const float kDefaultFlexGrow = 0.0f; -static const float kDefaultFlexShrink = 0.0f; -static const float kWebDefaultFlexShrink = 1.0f; diff --git a/yoga/Yoga.cpp b/yoga/Yoga.cpp index dd65a264e4..38415f9ba9 100644 --- a/yoga/Yoga.cpp +++ b/yoga/Yoga.cpp @@ -8,6 +8,7 @@ #include #include #include +#include #include #include #include @@ -102,12 +103,8 @@ static int YGDefaultLog( #undef YG_UNUSED #endif -static inline bool YGDoubleIsUndefined(const double value) { - return facebook::yoga::isUndefined(value); -} - YOGA_EXPORT bool YGFloatIsUndefined(const float value) { - return facebook::yoga::isUndefined(value); + return yoga::isUndefined(value); } YOGA_EXPORT void* YGNodeGetContext(YGNodeRef node) { @@ -483,15 +480,15 @@ YOGA_EXPORT void YGNodeCopyStyle( YOGA_EXPORT float YGNodeStyleGetFlexGrow(const YGNodeConstRef nodeRef) { auto node = static_cast(nodeRef); return node->getStyle().flexGrow().isUndefined() - ? kDefaultFlexGrow + ? Style::DefaultFlexGrow : node->getStyle().flexGrow().unwrap(); } YOGA_EXPORT float YGNodeStyleGetFlexShrink(const YGNodeConstRef nodeRef) { auto node = static_cast(nodeRef); return node->getStyle().flexShrink().isUndefined() - ? (node->getConfig()->useWebDefaults() ? kWebDefaultFlexShrink - : kDefaultFlexShrink) + ? (node->getConfig()->useWebDefaults() ? Style::WebDefaultFlexShrink + : Style::DefaultFlexShrink) : node->getStyle().flexShrink().unwrap(); } @@ -1013,11 +1010,6 @@ YOGA_EXPORT void YGNodePrint( } #endif -const std::array leading = { - {YGEdgeTop, YGEdgeBottom, YGEdgeLeft, YGEdgeRight}}; - -const std::array trailing = { - {YGEdgeBottom, YGEdgeTop, YGEdgeRight, YGEdgeLeft}}; static const std::array pos = {{ YGEdgeTop, YGEdgeBottom, @@ -1063,7 +1055,7 @@ static float YGBaseline(yoga::Node* node, void* layoutContext) { YGAssertWithNode( node, - !YGFloatIsUndefined(baseline), + !yoga::isUndefined(baseline), "Expect custom baseline function to not return NaN"); return baseline; } @@ -1130,8 +1122,7 @@ static inline bool YGNodeIsStyleDimDefined( const yoga::Node* const node, const YGFlexDirection axis, const float ownerSize) { - bool isUndefined = - YGFloatIsUndefined(node->getResolvedDimension(dim[axis]).value); + bool isUndefined = yoga::isUndefined(node->getResolvedDimension(dim[axis]).value); return !( node->getResolvedDimension(dim[axis]).unit == YGUnitAuto || node->getResolvedDimension(dim[axis]).unit == YGUnitUndefined || @@ -1140,14 +1131,14 @@ static inline bool YGNodeIsStyleDimDefined( (node->getResolvedDimension(dim[axis]).unit == YGUnitPercent && !isUndefined && (node->getResolvedDimension(dim[axis]).value < 0.0f || - YGFloatIsUndefined(ownerSize)))); + yoga::isUndefined(ownerSize)))); } static inline bool YGNodeIsLayoutDimDefined( const yoga::Node* const node, const YGFlexDirection axis) { const float value = node->getLayout().measuredDimensions[dim[axis]]; - return !YGFloatIsUndefined(value) && value >= 0.0f; + return !yoga::isUndefined(value) && value >= 0.0f; } static FloatOptional YGNodeBoundAxisWithinMinAndMax( @@ -1203,7 +1194,7 @@ static void YGNodeSetChildTrailingPosition( child->setLayoutPosition( node->getLayout().measuredDimensions[dim[axis]] - size - child->getLayout().position[pos[axis]], - trailing[axis]); + trailingEdge(axis)); } static void YGConstrainMaxSizeForMode( @@ -1266,7 +1257,7 @@ static void YGNodeComputeFlexBasisForChild( const bool isColumnStyleDimDefined = YGNodeIsStyleDimDefined(child, YGFlexDirectionColumn, ownerHeight); - if (!resolvedFlexBasis.isUndefined() && !YGFloatIsUndefined(mainAxisSize)) { + if (!resolvedFlexBasis.isUndefined() && !yoga::isUndefined(mainAxisSize)) { if (child->getLayout().computedFlexBasis.isUndefined() || (child->getConfig()->isExperimentalFeatureEnabled( YGExperimentalFeatureWebFlexBasis) && @@ -1328,7 +1319,7 @@ static void YGNodeComputeFlexBasisForChild( // major browsers appear to implement the following logic. if ((!isMainAxisRow && node->getStyle().overflow() == YGOverflowScroll) || node->getStyle().overflow() != YGOverflowScroll) { - if (YGFloatIsUndefined(childWidth) && !YGFloatIsUndefined(width)) { + if (yoga::isUndefined(childWidth) && !yoga::isUndefined(width)) { childWidth = width; childWidthMeasureMode = YGMeasureModeAtMost; } @@ -1336,7 +1327,7 @@ static void YGNodeComputeFlexBasisForChild( if ((isMainAxisRow && node->getStyle().overflow() == YGOverflowScroll) || node->getStyle().overflow() != YGOverflowScroll) { - if (YGFloatIsUndefined(childHeight) && !YGFloatIsUndefined(height)) { + if (yoga::isUndefined(childHeight) && !yoga::isUndefined(height)) { childHeight = height; childHeightMeasureMode = YGMeasureModeAtMost; } @@ -1360,7 +1351,7 @@ static void YGNodeComputeFlexBasisForChild( // the cross axis to be measured exactly with the available inner width const bool hasExactWidth = - !YGFloatIsUndefined(width) && widthMode == YGMeasureModeExactly; + !yoga::isUndefined(width) && widthMode == YGMeasureModeExactly; const bool childWidthStretch = YGNodeAlignItem(node, child) == YGAlignStretch && childWidthMeasureMode != YGMeasureModeExactly; @@ -1376,7 +1367,7 @@ static void YGNodeComputeFlexBasisForChild( } const bool hasExactHeight = - !YGFloatIsUndefined(height) && heightMode == YGMeasureModeExactly; + !yoga::isUndefined(height) && heightMode == YGMeasureModeExactly; const bool childHeightStretch = YGNodeAlignItem(node, child) == YGAlignStretch && childHeightMeasureMode != YGMeasureModeExactly; @@ -1504,12 +1495,12 @@ static void YGNodeAbsoluteLayoutChild( // ratio calculation. One dimension being the anchor and the other being // flexible. const auto& childStyle = child->getStyle(); - if (YGFloatIsUndefined(childWidth) ^ YGFloatIsUndefined(childHeight)) { + if (yoga::isUndefined(childWidth) ^ yoga::isUndefined(childHeight)) { if (!childStyle.aspectRatio().isUndefined()) { - if (YGFloatIsUndefined(childWidth)) { + if (yoga::isUndefined(childWidth)) { childWidth = marginRow + (childHeight - marginColumn) * childStyle.aspectRatio().unwrap(); - } else if (YGFloatIsUndefined(childHeight)) { + } else if (yoga::isUndefined(childHeight)) { childHeight = marginColumn + (childWidth - marginRow) / childStyle.aspectRatio().unwrap(); } @@ -1517,20 +1508,18 @@ static void YGNodeAbsoluteLayoutChild( } // If we're still missing one or the other dimension, measure the content. - if (YGFloatIsUndefined(childWidth) || YGFloatIsUndefined(childHeight)) { - childWidthMeasureMode = YGFloatIsUndefined(childWidth) - ? YGMeasureModeUndefined - : YGMeasureModeExactly; - childHeightMeasureMode = YGFloatIsUndefined(childHeight) - ? YGMeasureModeUndefined - : YGMeasureModeExactly; + if (yoga::isUndefined(childWidth) || yoga::isUndefined(childHeight)) { + childWidthMeasureMode = + yoga::isUndefined(childWidth) ? YGMeasureModeUndefined : YGMeasureModeExactly; + childHeightMeasureMode = + yoga::isUndefined(childHeight) ? YGMeasureModeUndefined : YGMeasureModeExactly; // If the size of the owner is defined then try to constrain the absolute // child to that size as well. This allows text within the absolute child to // wrap to the size of its owner. This is the same behavior as many browsers // implement. - if (!isMainAxisRow && YGFloatIsUndefined(childWidth) && - widthMode != YGMeasureModeUndefined && !YGFloatIsUndefined(width) && + if (!isMainAxisRow && yoga::isUndefined(childWidth) && + widthMode != YGMeasureModeUndefined && !yoga::isUndefined(width) && width > 0) { childWidth = width; childWidthMeasureMode = YGMeasureModeAtMost; @@ -1585,7 +1574,7 @@ static void YGNodeAbsoluteLayoutChild( .unwrap() - child->getTrailingPosition(mainAxis, isMainAxisRow ? width : height) .unwrap(), - leading[mainAxis]); + leadingEdge(mainAxis)); } else if ( !child->isLeadingPositionDefined(mainAxis) && node->getStyle().justifyContent() == YGJustifyCenter) { @@ -1593,14 +1582,14 @@ static void YGNodeAbsoluteLayoutChild( (node->getLayout().measuredDimensions[dim[mainAxis]] - child->getLayout().measuredDimensions[dim[mainAxis]]) / 2.0f, - leading[mainAxis]); + leadingEdge(mainAxis)); } else if ( !child->isLeadingPositionDefined(mainAxis) && node->getStyle().justifyContent() == YGJustifyFlexEnd) { child->setLayoutPosition( (node->getLayout().measuredDimensions[dim[mainAxis]] - child->getLayout().measuredDimensions[dim[mainAxis]]), - leading[mainAxis]); + leadingEdge(mainAxis)); } else if ( node->getConfig()->isExperimentalFeatureEnabled( YGExperimentalFeatureAbsolutePercentageAgainstPaddingEdge) && @@ -1615,7 +1604,7 @@ static void YGNodeAbsoluteLayoutChild( mainAxis, node->getLayout().measuredDimensions[dim[mainAxis]]) .unwrap(), - leading[mainAxis]); + leadingEdge(mainAxis)); } if (child->isTrailingPosDefined(crossAxis) && @@ -1629,7 +1618,7 @@ static void YGNodeAbsoluteLayoutChild( child ->getTrailingPosition(crossAxis, isMainAxisRow ? height : width) .unwrap(), - leading[crossAxis]); + leadingEdge(crossAxis)); } else if ( !child->isLeadingPositionDefined(crossAxis) && @@ -1638,7 +1627,7 @@ static void YGNodeAbsoluteLayoutChild( (node->getLayout().measuredDimensions[dim[crossAxis]] - child->getLayout().measuredDimensions[dim[crossAxis]]) / 2.0f, - leading[crossAxis]); + leadingEdge(crossAxis)); } else if ( !child->isLeadingPositionDefined(crossAxis) && ((YGNodeAlignItem(node, child) == YGAlignFlexEnd) ^ @@ -1646,7 +1635,7 @@ static void YGNodeAbsoluteLayoutChild( child->setLayoutPosition( (node->getLayout().measuredDimensions[dim[crossAxis]] - child->getLayout().measuredDimensions[dim[crossAxis]]), - leading[crossAxis]); + leadingEdge(crossAxis)); } else if ( node->getConfig()->isExperimentalFeatureEnabled( YGExperimentalFeatureAbsolutePercentageAgainstPaddingEdge) && @@ -1662,7 +1651,7 @@ static void YGNodeAbsoluteLayoutChild( crossAxis, node->getLayout().measuredDimensions[dim[crossAxis]]) .unwrap(), - leading[crossAxis]); + leadingEdge(crossAxis)); } } @@ -1697,10 +1686,10 @@ static void YGNodeWithMeasureFuncSetMeasuredDimensions( padding[YGEdgeBottom] + border[YGEdgeTop] + border[YGEdgeBottom]; // We want to make sure we don't call measure with negative size - const float innerWidth = YGFloatIsUndefined(availableWidth) + const float innerWidth = yoga::isUndefined(availableWidth) ? availableWidth : yoga::maxOrDefined(0, availableWidth - paddingAndBorderAxisRow); - const float innerHeight = YGFloatIsUndefined(availableHeight) + const float innerHeight = yoga::isUndefined(availableHeight) ? availableHeight : yoga::maxOrDefined(0, availableHeight - paddingAndBorderAxisColumn); @@ -1814,9 +1803,9 @@ static bool YGNodeFixedSizeSetMeasuredDimensions( const YGMeasureMode heightMeasureMode, const float ownerWidth, const float ownerHeight) { - if ((!YGFloatIsUndefined(availableWidth) && - widthMeasureMode == YGMeasureModeAtMost && availableWidth <= 0.0f) || - (!YGFloatIsUndefined(availableHeight) && + if ((!yoga::isUndefined(availableWidth) && widthMeasureMode == YGMeasureModeAtMost && + availableWidth <= 0.0f) || + (!yoga::isUndefined(availableHeight) && heightMeasureMode == YGMeasureModeAtMost && availableHeight <= 0.0f) || (widthMeasureMode == YGMeasureModeExactly && heightMeasureMode == YGMeasureModeExactly)) { @@ -1824,7 +1813,7 @@ static bool YGNodeFixedSizeSetMeasuredDimensions( YGNodeBoundAxis( node, YGFlexDirectionRow, - YGFloatIsUndefined(availableWidth) || + yoga::isUndefined(availableWidth) || (widthMeasureMode == YGMeasureModeAtMost && availableWidth < 0.0f) ? 0.0f @@ -1837,7 +1826,7 @@ static bool YGNodeFixedSizeSetMeasuredDimensions( YGNodeBoundAxis( node, YGFlexDirectionColumn, - YGFloatIsUndefined(availableHeight) || + yoga::isUndefined(availableHeight) || (heightMeasureMode == YGMeasureModeAtMost && availableHeight < 0.0f) ? 0.0f @@ -1872,7 +1861,7 @@ static float YGNodeCalculateAvailableInnerDim( float availableInnerDim = availableDim - paddingAndBorder; // Max dimension overrides predefined dimension value; Min dimension in turn // overrides both of the above - if (!YGFloatIsUndefined(availableInnerDim)) { + if (!yoga::isUndefined(availableInnerDim)) { // We want to make sure our available height does not violate min and max // constraints const FloatOptional minDimensionOptional = yoga::resolveValue( @@ -2114,7 +2103,7 @@ static float YGDistributeFreeSpaceSecondPass( .unwrap(); float updatedMainSize = childFlexBasis; - if (!YGFloatIsUndefined(collectedFlexItemsValues.remainingFreeSpace) && + if (!yoga::isUndefined(collectedFlexItemsValues.remainingFreeSpace) && collectedFlexItemsValues.remainingFreeSpace < 0) { flexShrinkScaledFactor = -currentRelativeChild->resolveFlexShrink() * childFlexBasis; @@ -2122,7 +2111,7 @@ static float YGDistributeFreeSpaceSecondPass( if (flexShrinkScaledFactor != 0) { float childSize; - if (!YGFloatIsUndefined( + if (!yoga::isUndefined( collectedFlexItemsValues.totalFlexShrinkScaledFactors) && collectedFlexItemsValues.totalFlexShrinkScaledFactors == 0) { childSize = childFlexBasis + flexShrinkScaledFactor; @@ -2141,12 +2130,12 @@ static float YGDistributeFreeSpaceSecondPass( availableInnerWidth); } } else if ( - !YGFloatIsUndefined(collectedFlexItemsValues.remainingFreeSpace) && + !yoga::isUndefined(collectedFlexItemsValues.remainingFreeSpace) && collectedFlexItemsValues.remainingFreeSpace > 0) { flexGrowFactor = currentRelativeChild->resolveFlexGrow(); // Is this child able to grow? - if (!YGFloatIsUndefined(flexGrowFactor) && flexGrowFactor != 0) { + if (!yoga::isUndefined(flexGrowFactor) && flexGrowFactor != 0) { updatedMainSize = YGNodeBoundAxis( currentRelativeChild, mainAxis, @@ -2182,7 +2171,7 @@ static float YGDistributeFreeSpaceSecondPass( childCrossSize += marginCross; } else if ( - !YGFloatIsUndefined(availableInnerCrossDim) && + !yoga::isUndefined(availableInnerCrossDim) && !YGNodeIsStyleDimDefined( currentRelativeChild, crossAxis, availableInnerCrossDim) && measureModeCrossDim == YGMeasureModeExactly && @@ -2197,7 +2186,7 @@ static float YGDistributeFreeSpaceSecondPass( } else if (!YGNodeIsStyleDimDefined( currentRelativeChild, crossAxis, availableInnerCrossDim)) { childCrossSize = availableInnerCrossDim; - childCrossMeasureMode = YGFloatIsUndefined(childCrossSize) + childCrossMeasureMode = yoga::isUndefined(childCrossSize) ? YGMeasureModeUndefined : YGMeasureModeAtMost; } else { @@ -2212,7 +2201,7 @@ static float YGDistributeFreeSpaceSecondPass( YGUnitPercent && measureModeCrossDim != YGMeasureModeExactly; childCrossMeasureMode = - YGFloatIsUndefined(childCrossSize) || isLoosePercentageMeasurement + yoga::isUndefined(childCrossSize) || isLoosePercentageMeasurement ? YGMeasureModeUndefined : YGMeasureModeExactly; } @@ -2304,8 +2293,7 @@ static void YGDistributeFreeSpaceFirstPass( -currentRelativeChild->resolveFlexShrink() * childFlexBasis; // Is this child able to shrink? - if (!YGFloatIsUndefined(flexShrinkScaledFactor) && - flexShrinkScaledFactor != 0) { + if (!yoga::isUndefined(flexShrinkScaledFactor) && flexShrinkScaledFactor != 0) { baseMainSize = childFlexBasis + collectedFlexItemsValues.remainingFreeSpace / collectedFlexItemsValues.totalFlexShrinkScaledFactors * @@ -2316,8 +2304,7 @@ static void YGDistributeFreeSpaceFirstPass( baseMainSize, availableInnerMainDim, availableInnerWidth); - if (!YGFloatIsUndefined(baseMainSize) && - !YGFloatIsUndefined(boundMainSize) && + if (!yoga::isUndefined(baseMainSize) && !yoga::isUndefined(boundMainSize) && baseMainSize != boundMainSize) { // By excluding this item's size and flex factor from remaining, this // item's min/max constraints should also trigger in the second pass @@ -2330,12 +2317,12 @@ static void YGDistributeFreeSpaceFirstPass( } } } else if ( - !YGFloatIsUndefined(collectedFlexItemsValues.remainingFreeSpace) && + !yoga::isUndefined(collectedFlexItemsValues.remainingFreeSpace) && collectedFlexItemsValues.remainingFreeSpace > 0) { flexGrowFactor = currentRelativeChild->resolveFlexGrow(); // Is this child able to grow? - if (!YGFloatIsUndefined(flexGrowFactor) && flexGrowFactor != 0) { + if (!yoga::isUndefined(flexGrowFactor) && flexGrowFactor != 0) { baseMainSize = childFlexBasis + collectedFlexItemsValues.remainingFreeSpace / collectedFlexItemsValues.totalFlexGrowFactors * flexGrowFactor; @@ -2346,8 +2333,7 @@ static void YGDistributeFreeSpaceFirstPass( availableInnerMainDim, availableInnerWidth); - if (!YGFloatIsUndefined(baseMainSize) && - !YGFloatIsUndefined(boundMainSize) && + if (!yoga::isUndefined(baseMainSize) && !yoga::isUndefined(boundMainSize) && baseMainSize != boundMainSize) { // By excluding this item's size and flex factor from remaining, this // item's min/max constraints should also trigger in the second pass @@ -2741,16 +2727,14 @@ static void YGNodelayoutImpl( const LayoutPassReason reason) { YGAssertWithNode( node, - YGFloatIsUndefined(availableWidth) - ? widthMeasureMode == YGMeasureModeUndefined - : true, + yoga::isUndefined(availableWidth) ? widthMeasureMode == YGMeasureModeUndefined + : true, "availableWidth is indefinite so widthMeasureMode must be " "YGMeasureModeUndefined"); YGAssertWithNode( node, - YGFloatIsUndefined(availableHeight) - ? heightMeasureMode == YGMeasureModeUndefined - : true, + yoga::isUndefined(availableHeight) ? heightMeasureMode == YGMeasureModeUndefined + : true, "availableHeight is indefinite so heightMeasureMode must be " "YGMeasureModeUndefined"); @@ -3001,12 +2985,12 @@ static void YGNodelayoutImpl( const float maxInnerMainDim = isMainAxisRow ? maxInnerWidth : maxInnerHeight; - if (!YGFloatIsUndefined(minInnerMainDim) && + if (!yoga::isUndefined(minInnerMainDim) && collectedFlexItemsValues.sizeConsumedOnCurrentLine < minInnerMainDim) { availableInnerMainDim = minInnerMainDim; } else if ( - !YGFloatIsUndefined(maxInnerMainDim) && + !yoga::isUndefined(maxInnerMainDim) && collectedFlexItemsValues.sizeConsumedOnCurrentLine > maxInnerMainDim) { availableInnerMainDim = maxInnerMainDim; @@ -3015,10 +2999,9 @@ static void YGNodelayoutImpl( node->hasErrata(YGErrataStretchFlexBasis); if (!useLegacyStretchBehaviour && - ((!YGFloatIsUndefined( - collectedFlexItemsValues.totalFlexGrowFactors) && + ((!yoga::isUndefined(collectedFlexItemsValues.totalFlexGrowFactors) && collectedFlexItemsValues.totalFlexGrowFactors == 0) || - (!YGFloatIsUndefined(node->resolveFlexGrow()) && + (!yoga::isUndefined(node->resolveFlexGrow()) && node->resolveFlexGrow() == 0))) { // If we don't have any children to flex or we can't flex the node // itself, space we've used is all space we need. Root node also @@ -3031,7 +3014,7 @@ static void YGNodelayoutImpl( } } - if (!sizeBasedOnContent && !YGFloatIsUndefined(availableInnerMainDim)) { + if (!sizeBasedOnContent && !yoga::isUndefined(availableInnerMainDim)) { collectedFlexItemsValues.remainingFreeSpace = availableInnerMainDim - collectedFlexItemsValues.sizeConsumedOnCurrentLine; } else if (collectedFlexItemsValues.sizeConsumedOnCurrentLine < 0) { @@ -3146,7 +3129,7 @@ static void YGNodelayoutImpl( // If leading position is not defined or calculations result in Nan, // default to border + margin if (!isChildLeadingPosDefined || - YGFloatIsUndefined(child->getLayout().position[pos[crossAxis]])) { + yoga::isUndefined(child->getLayout().position[pos[crossAxis]])) { child->setLayoutPosition( node->getLeadingBorder(crossAxis) + child->getLeadingMargin(crossAxis, availableInnerWidth) @@ -3212,12 +3195,12 @@ static void YGNodelayoutImpl( auto crossAxisDoesNotGrow = alignContent != YGAlignStretch && isNodeFlexWrap; const YGMeasureMode childWidthMeasureMode = - YGFloatIsUndefined(childWidth) || + yoga::isUndefined(childWidth) || (!isMainAxisRow && crossAxisDoesNotGrow) ? YGMeasureModeUndefined : YGMeasureModeExactly; const YGMeasureMode childHeightMeasureMode = - YGFloatIsUndefined(childHeight) || + yoga::isUndefined(childHeight) || (isMainAxisRow && crossAxisDoesNotGrow) ? YGMeasureModeUndefined : YGMeasureModeExactly; @@ -3281,7 +3264,7 @@ static void YGNodelayoutImpl( if (performLayout && (isNodeFlexWrap || YGIsBaselineLayout(node))) { float crossDimLead = 0; float currentLead = leadingPaddingAndBorderCross; - if (!YGFloatIsUndefined(availableInnerCrossDim)) { + if (!yoga::isUndefined(availableInnerCrossDim)) { const float remainingAlignContentDim = availableInnerCrossDim - totalLineCrossDim; switch (node->getStyle().alignContent()) { @@ -3684,9 +3667,8 @@ static inline bool YGMeasureModeNewMeasureSizeIsStricterAndStillValid( float lastSize, float lastComputedSize) { return lastSizeMode == YGMeasureModeAtMost && - sizeMode == YGMeasureModeAtMost && !YGFloatIsUndefined(lastSize) && - !YGFloatIsUndefined(size) && !YGFloatIsUndefined(lastComputedSize) && - lastSize > size && + sizeMode == YGMeasureModeAtMost && !yoga::isUndefined(lastSize) && + !yoga::isUndefined(size) && !yoga::isUndefined(lastComputedSize) && lastSize > size && (lastComputedSize <= size || yoga::inexactEquals(size, lastComputedSize)); } @@ -3730,13 +3712,12 @@ YOGA_EXPORT float YGRoundValueToPixelGrid( } else { // Finally we just round the value scaledValue = scaledValue - fractial + - (!YGDoubleIsUndefined(fractial) && + (!yoga::isUndefined(fractial) && (fractial > 0.5 || yoga::inexactEquals(fractial, 0.5)) ? 1.0 : 0.0); } - return (YGDoubleIsUndefined(scaledValue) || - YGDoubleIsUndefined(pointScaleFactor)) + return (yoga::isUndefined(scaledValue) || yoga::isUndefined(pointScaleFactor)) ? YGUndefined : (float) (scaledValue / pointScaleFactor); } @@ -3755,8 +3736,8 @@ YOGA_EXPORT bool YGNodeCanUseCachedMeasurement( const float marginRow, const float marginColumn, const YGConfigRef config) { - if ((!YGFloatIsUndefined(lastComputedHeight) && lastComputedHeight < 0) || - (!YGFloatIsUndefined(lastComputedWidth) && lastComputedWidth < 0)) { + if ((!yoga::isUndefined(lastComputedHeight) && lastComputedHeight < 0) || + (!yoga::isUndefined(lastComputedWidth) && lastComputedWidth < 0)) { return false; } bool useRoundedComparison = @@ -3858,7 +3839,7 @@ bool YGLayoutNodeInternal( layout->cachedLayout.computedHeight = -1; } - YGCachedMeasurement* cachedResults = nullptr; + CachedMeasurement* cachedResults = nullptr; // Determine whether the results are already cached. We maintain a separate // cache for layouts and measurements. A layout operation modifies the @@ -4036,7 +4017,8 @@ bool YGLayoutNodeInternal( layoutMarkerData.maxMeasureCache = layout->nextCachedMeasurementsIndex + 1; } - if (layout->nextCachedMeasurementsIndex == YG_MAX_CACHED_RESULT_COUNT) { + if (layout->nextCachedMeasurementsIndex == + LayoutResults::MaxCachedMeasurements) { if (gPrintChanges) { yoga::log( node, YGLogLevelVerbose, nullptr, "Out of cache entries!\n"); @@ -4044,7 +4026,7 @@ bool YGLayoutNodeInternal( layout->nextCachedMeasurementsIndex = 0; } - YGCachedMeasurement* newCacheEntry; + CachedMeasurement* newCacheEntry; if (performLayout) { // Use the single layout cache entry. newCacheEntry = &layout->cachedLayout; @@ -4218,8 +4200,8 @@ YOGA_EXPORT void YGNodeCalculateLayoutWithContext( widthMeasureMode = YGMeasureModeAtMost; } else { width = ownerWidth; - widthMeasureMode = YGFloatIsUndefined(width) ? YGMeasureModeUndefined - : YGMeasureModeExactly; + widthMeasureMode = + yoga::isUndefined(width) ? YGMeasureModeUndefined : YGMeasureModeExactly; } float height = YGUndefined; @@ -4238,8 +4220,8 @@ YOGA_EXPORT void YGNodeCalculateLayoutWithContext( heightMeasureMode = YGMeasureModeAtMost; } else { height = ownerHeight; - heightMeasureMode = YGFloatIsUndefined(height) ? YGMeasureModeUndefined - : YGMeasureModeExactly; + heightMeasureMode = + yoga::isUndefined(height) ? YGMeasureModeUndefined : YGMeasureModeExactly; } if (YGLayoutNodeInternal( node, diff --git a/yoga/algorithm/FlexDirection.h b/yoga/algorithm/FlexDirection.h index ed17ce2bc9..9cb87462aa 100644 --- a/yoga/algorithm/FlexDirection.h +++ b/yoga/algorithm/FlexDirection.h @@ -43,4 +43,42 @@ inline YGFlexDirection resolveCrossDirection( : YGFlexDirectionColumn; } +inline YGEdge leadingEdge(const YGFlexDirection flexDirection) { + switch (flexDirection) { + case YGFlexDirectionColumn: + return YGEdgeTop; + case YGFlexDirectionColumnReverse: + return YGEdgeBottom; + case YGFlexDirectionRow: + return YGEdgeLeft; + case YGFlexDirectionRowReverse: + return YGEdgeRight; + } + + YGAssert(false, "Invalid YGFlexDirection"); + + // Avoid "not all control paths return a value" warning until next diff adds + // assert with [[noreturn]] + return YGEdgeTop; +} + +inline YGEdge trailingEdge(const YGFlexDirection flexDirection) { + switch (flexDirection) { + case YGFlexDirectionColumn: + return YGEdgeBottom; + case YGFlexDirectionColumnReverse: + return YGEdgeTop; + case YGFlexDirectionRow: + return YGEdgeRight; + case YGFlexDirectionRowReverse: + return YGEdgeLeft; + } + + YGAssert(false, "Invalid YGFlexDirection"); + + // Avoid "not all control paths return a value" warning until next diff adds + // assert with [[noreturn]] + return YGEdgeTop; +} + } // namespace facebook::yoga diff --git a/yoga/algorithm/ResolveValue.h b/yoga/algorithm/ResolveValue.h index 2ba4bfef5b..af04025d4c 100644 --- a/yoga/algorithm/ResolveValue.h +++ b/yoga/algorithm/ResolveValue.h @@ -8,7 +8,9 @@ #pragma once #include + #include +#include namespace facebook::yoga { diff --git a/yoga/config/Config.h b/yoga/config/Config.h index d0894b86be..ebf3f77f79 100644 --- a/yoga/config/Config.h +++ b/yoga/config/Config.h @@ -8,9 +8,7 @@ #pragma once #include - #include -#include // Tag struct used to form the opaque YGConfigRef for the public C API struct YGConfig {}; diff --git a/yoga/debug/NodeToString.cpp b/yoga/debug/NodeToString.cpp index 1b6d01d380..756f480098 100644 --- a/yoga/debug/NodeToString.cpp +++ b/yoga/debug/NodeToString.cpp @@ -13,7 +13,6 @@ #include #include -#include namespace facebook::yoga { diff --git a/yoga/node/CachedMeasurement.h b/yoga/node/CachedMeasurement.h new file mode 100644 index 0000000000..7542f0e519 --- /dev/null +++ b/yoga/node/CachedMeasurement.h @@ -0,0 +1,50 @@ +/* + * 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 +#include + +namespace facebook::yoga { + +struct CachedMeasurement { + float availableWidth{-1}; + float availableHeight{-1}; + YGMeasureMode widthMeasureMode{YGMeasureModeUndefined}; + YGMeasureMode heightMeasureMode{YGMeasureModeUndefined}; + + float computedWidth{-1}; + float computedHeight{-1}; + + bool operator==(CachedMeasurement measurement) const { + bool isEqual = widthMeasureMode == measurement.widthMeasureMode && + heightMeasureMode == measurement.heightMeasureMode; + + if (!yoga::isUndefined(availableWidth) || + !yoga::isUndefined(measurement.availableWidth)) { + isEqual = isEqual && availableWidth == measurement.availableWidth; + } + if (!yoga::isUndefined(availableHeight) || + !yoga::isUndefined(measurement.availableHeight)) { + isEqual = isEqual && availableHeight == measurement.availableHeight; + } + if (!yoga::isUndefined(computedWidth) || !yoga::isUndefined(measurement.computedWidth)) { + isEqual = isEqual && computedWidth == measurement.computedWidth; + } + if (!yoga::isUndefined(computedHeight) || + !yoga::isUndefined(measurement.computedHeight)) { + isEqual = isEqual && computedHeight == measurement.computedHeight; + } + + return isEqual; + } +}; + +} // namespace facebook::yoga diff --git a/yoga/node/LayoutResults.cpp b/yoga/node/LayoutResults.cpp index 6446b8cbc9..fb8b8527c5 100644 --- a/yoga/node/LayoutResults.cpp +++ b/yoga/node/LayoutResults.cpp @@ -5,6 +5,8 @@ * LICENSE file in the root directory of this source tree. */ +#include + #include #include @@ -23,7 +25,8 @@ bool LayoutResults::operator==(LayoutResults layout) const { cachedLayout == layout.cachedLayout && computedFlexBasis == layout.computedFlexBasis; - for (uint32_t i = 0; i < YG_MAX_CACHED_RESULT_COUNT && isEqual; ++i) { + for (uint32_t i = 0; i < LayoutResults::MaxCachedMeasurements && isEqual; + ++i) { isEqual = isEqual && cachedMeasurements[i] == layout.cachedMeasurements[i]; } diff --git a/yoga/node/LayoutResults.h b/yoga/node/LayoutResults.h index c0d2bee26d..95b4a21bf8 100644 --- a/yoga/node/LayoutResults.h +++ b/yoga/node/LayoutResults.h @@ -7,13 +7,19 @@ #pragma once +#include + #include #include -#include +#include namespace facebook::yoga { struct LayoutResults { + // This value was chosen based on empirical data: + // 98% of analyzed layouts require less than 8 entries. + static constexpr int32_t MaxCachedMeasurements = 8; + std::array position = {}; std::array dimensions = {{YGUndefined, YGUndefined}}; std::array margin = {}; @@ -36,11 +42,10 @@ struct LayoutResults { YGDirection lastOwnerDirection = YGDirectionInherit; uint32_t nextCachedMeasurementsIndex = 0; - std::array - cachedMeasurements = {}; + std::array cachedMeasurements = {}; std::array measuredDimensions = {{YGUndefined, YGUndefined}}; - YGCachedMeasurement cachedLayout = YGCachedMeasurement(); + CachedMeasurement cachedLayout{}; YGDirection direction() const { return getEnumData(flags, directionOffset); diff --git a/yoga/node/Node.cpp b/yoga/node/Node.cpp index 82132f54cb..0eca4e115e 100644 --- a/yoga/node/Node.cpp +++ b/yoga/node/Node.cpp @@ -117,10 +117,10 @@ FloatOptional Node::getLeadingPosition( ? computeEdgeValueForRow( style_.position(), YGEdgeStart, - leading[axis], + leadingEdge(axis), CompactValue::ofZero()) : computeEdgeValueForColumn( - style_.position(), leading[axis], CompactValue::ofZero()); + style_.position(), leadingEdge(axis), CompactValue::ofZero()); return yoga::resolveValue(leadingPosition, axisSize); } @@ -131,10 +131,10 @@ FloatOptional Node::getTrailingPosition( ? computeEdgeValueForRow( style_.position(), YGEdgeEnd, - trailing[axis], + trailingEdge(axis), CompactValue::ofZero()) : computeEdgeValueForColumn( - style_.position(), trailing[axis], CompactValue::ofZero()); + style_.position(), trailingEdge(axis), CompactValue::ofZero()); return yoga::resolveValue(trailingPosition, axisSize); } @@ -143,10 +143,10 @@ bool Node::isLeadingPositionDefined(const YGFlexDirection axis) const { ? computeEdgeValueForRow( style_.position(), YGEdgeStart, - leading[axis], + leadingEdge(axis), CompactValue::ofUndefined()) : computeEdgeValueForColumn( - style_.position(), leading[axis], CompactValue::ofUndefined()); + style_.position(), leadingEdge(axis), CompactValue::ofUndefined()); return !leadingPosition.isUndefined(); } @@ -155,10 +155,10 @@ bool Node::isTrailingPosDefined(const YGFlexDirection axis) const { ? computeEdgeValueForRow( style_.position(), YGEdgeEnd, - trailing[axis], + trailingEdge(axis), CompactValue::ofUndefined()) : computeEdgeValueForColumn( - style_.position(), trailing[axis], CompactValue::ofUndefined()); + style_.position(), trailingEdge(axis), CompactValue::ofUndefined()); return !trailingPosition.isUndefined(); } @@ -167,9 +167,12 @@ FloatOptional Node::getLeadingMargin( const float widthSize) const { auto leadingMargin = isRow(axis) ? computeEdgeValueForRow( - style_.margin(), YGEdgeStart, leading[axis], CompactValue::ofZero()) + style_.margin(), + YGEdgeStart, + leadingEdge(axis), + CompactValue::ofZero()) : computeEdgeValueForColumn( - style_.margin(), leading[axis], CompactValue::ofZero()); + style_.margin(), leadingEdge(axis), CompactValue::ofZero()); return leadingMargin.isAuto() ? FloatOptional{0} : yoga::resolveValue(leadingMargin, widthSize); } @@ -179,9 +182,12 @@ FloatOptional Node::getTrailingMargin( const float widthSize) const { auto trailingMargin = isRow(axis) ? computeEdgeValueForRow( - style_.margin(), YGEdgeEnd, trailing[axis], CompactValue::ofZero()) + style_.margin(), + YGEdgeEnd, + trailingEdge(axis), + CompactValue::ofZero()) : computeEdgeValueForColumn( - style_.margin(), trailing[axis], CompactValue::ofZero()); + style_.margin(), trailingEdge(axis), CompactValue::ofZero()); return trailingMargin.isAuto() ? FloatOptional{0} : yoga::resolveValue(trailingMargin, widthSize); @@ -390,25 +396,25 @@ void Node::setPosition( setLayoutPosition( (getLeadingMargin(mainAxis, ownerWidth) + relativePositionMain).unwrap(), - leading[mainAxis]); + leadingEdge(mainAxis)); setLayoutPosition( (getTrailingMargin(mainAxis, ownerWidth) + relativePositionMain).unwrap(), - trailing[mainAxis]); + trailingEdge(mainAxis)); setLayoutPosition( (getLeadingMargin(crossAxis, ownerWidth) + relativePositionCross) .unwrap(), - leading[crossAxis]); + leadingEdge(crossAxis)); setLayoutPosition( (getTrailingMargin(crossAxis, ownerWidth) + relativePositionCross) .unwrap(), - trailing[crossAxis]); + trailingEdge(crossAxis)); } YGValue Node::marginLeadingValue(const YGFlexDirection axis) const { if (isRow(axis) && !style_.margin()[YGEdgeStart].isUndefined()) { return style_.margin()[YGEdgeStart]; } else { - return style_.margin()[leading[axis]]; + return style_.margin()[leadingEdge(axis)]; } } @@ -416,7 +422,7 @@ YGValue Node::marginTrailingValue(const YGFlexDirection axis) const { if (isRow(axis) && !style_.margin()[YGEdgeEnd].isUndefined()) { return style_.margin()[YGEdgeEnd]; } else { - return style_.margin()[trailing[axis]]; + return style_.margin()[trailingEdge(axis)]; } } @@ -493,7 +499,7 @@ float Node::resolveFlexGrow() const { if (!style_.flex().isUndefined() && style_.flex().unwrap() > 0.0f) { return style_.flex().unwrap(); } - return kDefaultFlexGrow; + return Style::DefaultFlexGrow; } float Node::resolveFlexShrink() const { @@ -507,7 +513,8 @@ float Node::resolveFlexShrink() const { style_.flex().unwrap() < 0.0f) { return -style_.flex().unwrap(); } - return config_->useWebDefaults() ? kWebDefaultFlexShrink : kDefaultFlexShrink; + return config_->useWebDefaults() ? Style::WebDefaultFlexShrink + : Style::DefaultFlexShrink; } bool Node::isNodeFlexible() { @@ -519,18 +526,24 @@ bool Node::isNodeFlexible() { float Node::getLeadingBorder(const YGFlexDirection axis) const { YGValue leadingBorder = isRow(axis) ? computeEdgeValueForRow( - style_.border(), YGEdgeStart, leading[axis], CompactValue::ofZero()) + style_.border(), + YGEdgeStart, + leadingEdge(axis), + CompactValue::ofZero()) : computeEdgeValueForColumn( - style_.border(), leading[axis], CompactValue::ofZero()); + style_.border(), leadingEdge(axis), CompactValue::ofZero()); return fmaxf(leadingBorder.value, 0.0f); } float Node::getTrailingBorder(const YGFlexDirection axis) const { YGValue trailingBorder = isRow(axis) ? computeEdgeValueForRow( - style_.border(), YGEdgeEnd, trailing[axis], CompactValue::ofZero()) + style_.border(), + YGEdgeEnd, + trailingEdge(axis), + CompactValue::ofZero()) : computeEdgeValueForColumn( - style_.border(), trailing[axis], CompactValue::ofZero()); + style_.border(), trailingEdge(axis), CompactValue::ofZero()); return fmaxf(trailingBorder.value, 0.0f); } @@ -541,10 +554,10 @@ FloatOptional Node::getLeadingPadding( ? computeEdgeValueForRow( style_.padding(), YGEdgeStart, - leading[axis], + leadingEdge(axis), CompactValue::ofZero()) : computeEdgeValueForColumn( - style_.padding(), leading[axis], CompactValue::ofZero()); + style_.padding(), leadingEdge(axis), CompactValue::ofZero()); return yoga::maxOrDefined( yoga::resolveValue(leadingPadding, widthSize), FloatOptional(0.0f)); } @@ -554,9 +567,12 @@ FloatOptional Node::getTrailingPadding( const float widthSize) const { auto trailingPadding = isRow(axis) ? computeEdgeValueForRow( - style_.padding(), YGEdgeEnd, trailing[axis], CompactValue::ofZero()) + style_.padding(), + YGEdgeEnd, + trailingEdge(axis), + CompactValue::ofZero()) : computeEdgeValueForColumn( - style_.padding(), trailing[axis], CompactValue::ofZero()); + style_.padding(), trailingEdge(axis), CompactValue::ofZero()); return yoga::maxOrDefined( yoga::resolveValue(trailingPadding, widthSize), FloatOptional(0.0f)); } diff --git a/yoga/node/Node.h b/yoga/node/Node.h index 542d7c08ea..5401d90b6b 100644 --- a/yoga/node/Node.h +++ b/yoga/node/Node.h @@ -9,10 +9,10 @@ #include #include +#include + #include #include -#include - #include #include diff --git a/yoga/numeric/Comparison.h b/yoga/numeric/Comparison.h index 86ed16fa50..aa9f933efd 100644 --- a/yoga/numeric/Comparison.h +++ b/yoga/numeric/Comparison.h @@ -15,19 +15,24 @@ namespace facebook::yoga { +template +inline bool isUndefined(FloatT value) { + return std::isnan(value); +} + inline float maxOrDefined(const float a, const float b) { - if (!std::isnan(a) && !std::isnan(b)) { + if (!yoga::isUndefined(a) && !yoga::isUndefined(b)) { return fmaxf(a, b); } - return std::isnan(a) ? b : a; + return yoga::isUndefined(a) ? b : a; } inline float minOrDefined(const float a, const float b) { - if (!std::isnan(a) && !std::isnan(b)) { + if (!yoga::isUndefined(a) && !yoga::isUndefined(b)) { return fminf(a, b); } - return std::isnan(a) ? b : a; + return yoga::isUndefined(a) ? b : a; } inline FloatOptional maxOrDefined(FloatOptional op1, FloatOptional op2) { @@ -43,17 +48,17 @@ inline FloatOptional maxOrDefined(FloatOptional op1, FloatOptional op2) { // Custom equality functions using a hardcoded epsilon of 0.0001f, or returning // true if both floats are NaN. inline bool inexactEquals(const float a, const float b) { - if (!std::isnan(a) && !std::isnan(b)) { + if (!yoga::isUndefined(a) && !yoga::isUndefined(b)) { return fabs(a - b) < 0.0001f; } - return std::isnan(a) && std::isnan(b); + return yoga::isUndefined(a) && yoga::isUndefined(b); } inline bool inexactEquals(const double a, const double b) { - if (!std::isnan(a) && !std::isnan(b)) { + if (!yoga::isUndefined(a) && !yoga::isUndefined(b)) { return fabs(a - b) < 0.0001; } - return std::isnan(a) && std::isnan(b); + return yoga::isUndefined(a) && yoga::isUndefined(b); } inline bool inexactEquals(const YGValue& a, const YGValue& b) { @@ -62,7 +67,7 @@ inline bool inexactEquals(const YGValue& a, const YGValue& b) { } if (a.unit == YGUnitUndefined || - (std::isnan(a.value) && std::isnan(b.value))) { + (yoga::isUndefined(a.value) && yoga::isUndefined(b.value))) { return true; } diff --git a/yoga/numeric/FloatOptional.h b/yoga/numeric/FloatOptional.h index 89eff3b882..a36befe609 100644 --- a/yoga/numeric/FloatOptional.h +++ b/yoga/numeric/FloatOptional.h @@ -9,7 +9,6 @@ #include #include -#include namespace facebook::yoga { diff --git a/yoga/style/Style.h b/yoga/style/Style.h index 10854fd6fb..7b3ca9dd2d 100644 --- a/yoga/style/Style.h +++ b/yoga/style/Style.h @@ -13,7 +13,6 @@ #include #include -#include #include #include @@ -23,13 +22,17 @@ namespace facebook::yoga { class YOGA_EXPORT Style { template - using Values = detail::Values()>; + using Values = std::array()>; public: using Dimensions = Values; using Edges = Values; using Gutters = Values; + static constexpr float DefaultFlexGrow = 0.0f; + static constexpr float DefaultFlexShrink = 0.0f; + static constexpr float WebDefaultFlexShrink = 1.0f; + template struct BitfieldRef { Style& style; @@ -112,7 +115,7 @@ class YOGA_EXPORT Style { Edges padding_ = {}; Edges border_ = {}; Gutters gap_ = {}; - Dimensions dimensions_{CompactValue::ofAuto()}; + Dimensions dimensions_{CompactValue::ofAuto(), CompactValue::ofAuto()}; Dimensions minDimensions_ = {}; Dimensions maxDimensions_ = {}; // Yoga specific properties, not compatible with flexbox specification