diff --git a/tests/YGStyleAccessorsTest.cpp b/tests/YGStyleAccessorsTest.cpp index d32ffc5d..8ef8896c 100644 --- a/tests/YGStyleAccessorsTest.cpp +++ b/tests/YGStyleAccessorsTest.cpp @@ -82,10 +82,10 @@ namespace facebook::yoga { ACCESSOR_TEST( direction, - YGDirectionInherit, - YGDirectionLTR, - YGDirectionRTL, - YGDirectionInherit); + Direction::Inherit, + Direction::LTR, + Direction::RTL, + Direction::Inherit); ACCESSOR_TEST( flexDirection, diff --git a/yoga/YGMacros.h b/yoga/YGMacros.h index d03116d0..07ddb190 100644 --- a/yoga/YGMacros.h +++ b/yoga/YGMacros.h @@ -90,10 +90,11 @@ #ifdef __cplusplus -namespace facebook::yoga::enums { +namespace facebook::yoga { template -constexpr int count(); // can't use `= delete` due to a defect in clang < 3.9 +constexpr int +ordinalCount(); // can't use `= delete` due to a defect in clang < 3.9 namespace detail { template @@ -102,7 +103,7 @@ constexpr int n() { } } // namespace detail -} // namespace facebook::yoga::enums +} // namespace facebook::yoga #endif #define YG_ENUM_DECL(NAME, ...) \ @@ -110,16 +111,16 @@ constexpr int n() { YG_EXPORT const char* NAME##ToString(NAME); #ifdef __cplusplus -#define YG_ENUM_SEQ_DECL(NAME, ...) \ - YG_ENUM_DECL(NAME, __VA_ARGS__) \ - YG_EXTERN_C_END \ - \ - namespace facebook::yoga::enums { \ - template <> \ - constexpr int count() { \ - return detail::n<__VA_ARGS__>(); \ - } \ - } \ +#define YG_ENUM_SEQ_DECL(NAME, ...) \ + YG_ENUM_DECL(NAME, __VA_ARGS__) \ + YG_EXTERN_C_END \ + \ + namespace facebook::yoga { \ + template <> \ + constexpr int ordinalCount() { \ + return detail::n<__VA_ARGS__>(); \ + } \ + } \ YG_EXTERN_C_BEGIN #else #define YG_ENUM_SEQ_DECL YG_ENUM_DECL diff --git a/yoga/Yoga.cpp b/yoga/Yoga.cpp index 6992ca0f..89c7e45f 100644 --- a/yoga/Yoga.cpp +++ b/yoga/Yoga.cpp @@ -429,10 +429,10 @@ void updateIndexedStyleProp( #define MSVC_HINT(PROP) decltype(Style{}.PROP()) void YGNodeStyleSetDirection(const YGNodeRef node, const YGDirection value) { - updateStyle(node, &Style::direction, value); + updateStyle(node, &Style::direction, scopedEnum(value)); } YGDirection YGNodeStyleGetDirection(const YGNodeConstRef node) { - return resolveRef(node)->getStyle().direction(); + return unscopedEnum(resolveRef(node)->getStyle().direction()); } void YGNodeStyleSetFlexDirection( @@ -754,51 +754,82 @@ YGValue YGNodeStyleGetMaxHeight(const YGNodeConstRef node) { return resolveRef(node)->getStyle().maxDimensions()[YGDimensionHeight]; } -#define YG_NODE_LAYOUT_PROPERTY_IMPL(type, name, instanceName) \ - type YGNodeLayoutGet##name(const YGNodeConstRef node) { \ - return resolveRef(node)->getLayout().instanceName; \ +namespace { + +template +float getResolvedLayoutProperty( + const YGNodeConstRef nodeRef, + const YGEdge edge) { + const auto node = resolveRef(nodeRef); + yoga::assertFatalWithNode( + node, + edge <= YGEdgeEnd, + "Cannot get layout properties of multi-edge shorthands"); + + if (edge == YGEdgeStart) { + if (node->getLayout().direction() == Direction::RTL) { + return (node->getLayout().*LayoutMember)[YGEdgeRight]; + } else { + return (node->getLayout().*LayoutMember)[YGEdgeLeft]; + } } -#define YG_NODE_LAYOUT_RESOLVED_PROPERTY_IMPL(type, name, instanceName) \ - type YGNodeLayoutGet##name( \ - const YGNodeConstRef nodeRef, const YGEdge edge) { \ - const auto node = resolveRef(nodeRef); \ - yoga::assertFatalWithNode( \ - node, \ - edge <= YGEdgeEnd, \ - "Cannot get layout properties of multi-edge shorthands"); \ - \ - if (edge == YGEdgeStart) { \ - if (node->getLayout().direction() == YGDirectionRTL) { \ - return node->getLayout().instanceName[YGEdgeRight]; \ - } else { \ - return node->getLayout().instanceName[YGEdgeLeft]; \ - } \ - } \ - \ - if (edge == YGEdgeEnd) { \ - if (node->getLayout().direction() == YGDirectionRTL) { \ - return node->getLayout().instanceName[YGEdgeLeft]; \ - } else { \ - return node->getLayout().instanceName[YGEdgeRight]; \ - } \ - } \ - \ - return node->getLayout().instanceName[edge]; \ + if (edge == YGEdgeEnd) { + if (node->getLayout().direction() == Direction::RTL) { + return (node->getLayout().*LayoutMember)[YGEdgeLeft]; + } else { + return (node->getLayout().*LayoutMember)[YGEdgeRight]; + } } -YG_NODE_LAYOUT_PROPERTY_IMPL(float, Left, position[YGEdgeLeft]) -YG_NODE_LAYOUT_PROPERTY_IMPL(float, Top, position[YGEdgeTop]) -YG_NODE_LAYOUT_PROPERTY_IMPL(float, Right, position[YGEdgeRight]) -YG_NODE_LAYOUT_PROPERTY_IMPL(float, Bottom, position[YGEdgeBottom]) -YG_NODE_LAYOUT_PROPERTY_IMPL(float, Width, dimensions[YGDimensionWidth]) -YG_NODE_LAYOUT_PROPERTY_IMPL(float, Height, dimensions[YGDimensionHeight]) -YG_NODE_LAYOUT_PROPERTY_IMPL(YGDirection, Direction, direction()) -YG_NODE_LAYOUT_PROPERTY_IMPL(bool, HadOverflow, hadOverflow()) + return (node->getLayout().*LayoutMember)[edge]; +} -YG_NODE_LAYOUT_RESOLVED_PROPERTY_IMPL(float, Margin, margin) -YG_NODE_LAYOUT_RESOLVED_PROPERTY_IMPL(float, Border, border) -YG_NODE_LAYOUT_RESOLVED_PROPERTY_IMPL(float, Padding, padding) +} // namespace + +float YGNodeLayoutGetLeft(const YGNodeConstRef node) { + return resolveRef(node)->getLayout().position[YGEdgeLeft]; +} + +float YGNodeLayoutGetTop(const YGNodeConstRef node) { + return resolveRef(node)->getLayout().position[YGEdgeTop]; +} + +float YGNodeLayoutGetRight(const YGNodeConstRef node) { + return resolveRef(node)->getLayout().position[YGEdgeRight]; +} + +float YGNodeLayoutGetBottom(const YGNodeConstRef node) { + return resolveRef(node)->getLayout().position[YGEdgeBottom]; +} + +float YGNodeLayoutGetWidth(const YGNodeConstRef node) { + return resolveRef(node)->getLayout().dimensions[YGDimensionWidth]; +} + +float YGNodeLayoutGetHeight(const YGNodeConstRef node) { + return resolveRef(node)->getLayout().dimensions[YGDimensionHeight]; +} + +YGDirection YGNodeLayoutGetDirection(const YGNodeConstRef node) { + return unscopedEnum(resolveRef(node)->getLayout().direction()); +} + +bool YGNodeLayoutGetHadOverflow(const YGNodeConstRef node) { + return resolveRef(node)->getLayout().hadOverflow(); +} + +float YGNodeLayoutGetMargin(YGNodeConstRef node, YGEdge edge) { + return getResolvedLayoutProperty<&LayoutResults::margin>(node, edge); +} + +float YGNodeLayoutGetBorder(YGNodeConstRef node, YGEdge edge) { + return getResolvedLayoutProperty<&LayoutResults::border>(node, edge); +} + +float YGNodeLayoutGetPadding(YGNodeConstRef node, YGEdge edge) { + return getResolvedLayoutProperty<&LayoutResults::padding>(node, edge); +} #ifdef DEBUG void YGNodePrint(const YGNodeConstRef node, const YGPrintOptions options) { @@ -926,5 +957,5 @@ void YGNodeCalculateLayout( const float ownerHeight, const YGDirection ownerDirection) { yoga::calculateLayout( - resolveRef(node), ownerWidth, ownerHeight, ownerDirection); + resolveRef(node), ownerWidth, ownerHeight, scopedEnum(ownerDirection)); } diff --git a/yoga/algorithm/CalculateLayout.cpp b/yoga/algorithm/CalculateLayout.cpp index 3f70ee3b..f50305b8 100644 --- a/yoga/algorithm/CalculateLayout.cpp +++ b/yoga/algorithm/CalculateLayout.cpp @@ -38,7 +38,7 @@ bool calculateLayoutInternal( yoga::Node* const node, const float availableWidth, const float availableHeight, - const YGDirection ownerDirection, + const Direction ownerDirection, const MeasureMode widthMeasureMode, const MeasureMode heightMeasureMode, const float ownerWidth, @@ -130,7 +130,7 @@ static void computeFlexBasisForChild( const float ownerWidth, const float ownerHeight, const MeasureMode heightMode, - const YGDirection direction, + const Direction direction, LayoutData& layoutMarkerData, const uint32_t depth, const uint32_t generationCount) { @@ -321,7 +321,7 @@ static void layoutAbsoluteChild( const float width, const MeasureMode widthMode, const float height, - const YGDirection direction, + const Direction direction, LayoutData& layoutMarkerData, const uint32_t depth, const uint32_t generationCount) { @@ -771,7 +771,7 @@ static float computeFlexBasisForChildren( const float availableInnerHeight, MeasureMode widthMeasureMode, MeasureMode heightMeasureMode, - YGDirection direction, + Direction direction, YGFlexDirection mainAxis, bool performLayout, LayoutData& layoutMarkerData, @@ -812,7 +812,7 @@ static float computeFlexBasisForChildren( } if (performLayout) { // Set the initial position (relative to the owner). - const YGDirection childDirection = child->resolveDirection(direction); + const Direction childDirection = child->resolveDirection(direction); const float mainDim = isRow(mainAxis) ? availableInnerWidth : availableInnerHeight; const float crossDim = @@ -1478,7 +1478,7 @@ static void calculateLayoutImpl( yoga::Node* const node, const float availableWidth, const float availableHeight, - const YGDirection ownerDirection, + const Direction ownerDirection, const MeasureMode widthMeasureMode, const MeasureMode heightMeasureMode, const float ownerWidth, @@ -1506,7 +1506,7 @@ static void calculateLayoutImpl( (performLayout ? layoutMarkerData.layouts : layoutMarkerData.measures) += 1; // Set the resolved resolution in the node's layout. - const YGDirection direction = node->resolveDirection(ownerDirection); + const Direction direction = node->resolveDirection(ownerDirection); node->setLayoutDirection(direction); const YGFlexDirection flexRowDirection = @@ -1515,8 +1515,8 @@ static void calculateLayoutImpl( resolveDirection(YGFlexDirectionColumn, direction); const YGEdge startEdge = - direction == YGDirectionLTR ? YGEdgeLeft : YGEdgeRight; - const YGEdge endEdge = direction == YGDirectionLTR ? YGEdgeRight : YGEdgeLeft; + direction == Direction::LTR ? YGEdgeLeft : YGEdgeRight; + const YGEdge endEdge = direction == Direction::LTR ? YGEdgeRight : YGEdgeLeft; const float marginRowLeading = node->getLeadingMargin(flexRowDirection, ownerWidth).unwrap(); @@ -2408,7 +2408,7 @@ bool calculateLayoutInternal( yoga::Node* const node, const float availableWidth, const float availableHeight, - const YGDirection ownerDirection, + const Direction ownerDirection, const MeasureMode widthMeasureMode, const MeasureMode heightMeasureMode, const float ownerWidth, @@ -2668,7 +2668,7 @@ void calculateLayout( yoga::Node* const node, const float ownerWidth, const float ownerHeight, - const YGDirection ownerDirection) { + const Direction ownerDirection) { Event::publish(node); LayoutData markerData = {}; diff --git a/yoga/algorithm/CalculateLayout.h b/yoga/algorithm/CalculateLayout.h index b93dd5da..47b05dbe 100644 --- a/yoga/algorithm/CalculateLayout.h +++ b/yoga/algorithm/CalculateLayout.h @@ -16,6 +16,6 @@ void calculateLayout( yoga::Node* const node, const float ownerWidth, const float ownerHeight, - const YGDirection ownerDirection); + const Direction ownerDirection); } // namespace facebook::yoga diff --git a/yoga/algorithm/FlexDirection.h b/yoga/algorithm/FlexDirection.h index 71afac41..2bd608ef 100644 --- a/yoga/algorithm/FlexDirection.h +++ b/yoga/algorithm/FlexDirection.h @@ -25,8 +25,8 @@ inline bool isColumn(const YGFlexDirection flexDirection) { inline YGFlexDirection resolveDirection( const YGFlexDirection flexDirection, - const YGDirection direction) { - if (direction == YGDirectionRTL) { + const Direction direction) { + if (direction == Direction::RTL) { if (flexDirection == YGFlexDirectionRow) { return YGFlexDirectionRowReverse; } else if (flexDirection == YGFlexDirectionRowReverse) { @@ -39,7 +39,7 @@ inline YGFlexDirection resolveDirection( inline YGFlexDirection resolveCrossDirection( const YGFlexDirection flexDirection, - const YGDirection direction) { + const Direction direction) { return isColumn(flexDirection) ? resolveDirection(YGFlexDirectionRow, direction) : YGFlexDirectionColumn; diff --git a/yoga/algorithm/FlexLine.cpp b/yoga/algorithm/FlexLine.cpp index 752908f2..f4dcf14d 100644 --- a/yoga/algorithm/FlexLine.cpp +++ b/yoga/algorithm/FlexLine.cpp @@ -15,7 +15,7 @@ namespace facebook::yoga { FlexLine calculateFlexLine( yoga::Node* const node, - const YGDirection ownerDirection, + const Direction ownerDirection, const float mainAxisownerSize, const float availableInnerWidth, const float availableInnerMainDim, diff --git a/yoga/algorithm/FlexLine.h b/yoga/algorithm/FlexLine.h index 66829310..161a1031 100644 --- a/yoga/algorithm/FlexLine.h +++ b/yoga/algorithm/FlexLine.h @@ -64,7 +64,7 @@ struct FlexLine { // computeFlexBasisForChildren function). FlexLine calculateFlexLine( yoga::Node* const node, - YGDirection ownerDirection, + Direction ownerDirection, float mainAxisownerSize, float availableInnerWidth, float availableInnerMainDim, diff --git a/yoga/bits/NumericBitfield.h b/yoga/bits/NumericBitfield.h index 9197a9b9..63f7eb65 100644 --- a/yoga/bits/NumericBitfield.h +++ b/yoga/bits/NumericBitfield.h @@ -10,8 +10,10 @@ #include #include #include +#include #include +#include namespace facebook::yoga::details { @@ -28,11 +30,11 @@ constexpr uint32_t mask(uint8_t bitWidth, uint8_t index) { namespace facebook::yoga { // The number of bits necessary to represent enums defined with YG_ENUM_SEQ_DECL -template +template < + typename Enum, + std::enable_if_t<(ordinalCount() > 0), bool> = true> constexpr uint8_t minimumBitCount() { - static_assert( - enums::count() > 0, "Enums must have at least one entries"); - return details::log2ceilFn(enums::count() - 1); + return details::log2ceilFn(ordinalCount() - 1); } template @@ -41,12 +43,13 @@ constexpr Enum getEnumData(uint32_t flags, uint8_t index) { (flags & details::mask(minimumBitCount(), index)) >> index); } -template -void setEnumData(uint32_t& flags, uint8_t index, uint32_t newValue) { +template +void setEnumData(uint32_t& flags, uint8_t index, Value newValue) { flags = (flags & ~static_cast(details::mask(minimumBitCount(), index))) | - ((newValue << index) & (details::mask(minimumBitCount(), index))); + ((static_cast(newValue) << index) & + (details::mask(minimumBitCount(), index))); } constexpr bool getBooleanData(uint32_t flags, uint8_t index) { diff --git a/yoga/node/LayoutResults.h b/yoga/node/LayoutResults.h index 2c0f36c1..3b2b76b1 100644 --- a/yoga/node/LayoutResults.h +++ b/yoga/node/LayoutResults.h @@ -10,6 +10,7 @@ #include #include +#include #include #include @@ -27,7 +28,7 @@ struct LayoutResults { std::array padding = {}; private: - uint32_t direction_ : 2 = static_cast(YGDirectionInherit) & 0x03; + Direction direction_ : bitCount() = Direction::Inherit; bool hadOverflow_ : 1 = false; public: @@ -37,7 +38,7 @@ struct LayoutResults { // Instead of recomputing the entire layout every single time, we cache some // information to break early when nothing changed uint32_t generationCount = 0; - YGDirection lastOwnerDirection = YGDirectionInherit; + Direction lastOwnerDirection = Direction::Inherit; uint32_t nextCachedMeasurementsIndex = 0; std::array cachedMeasurements = {}; @@ -45,12 +46,12 @@ struct LayoutResults { CachedMeasurement cachedLayout{}; - YGDirection direction() const { - return static_cast(direction_); + Direction direction() const { + return direction_; } - void setDirection(YGDirection direction) { - direction_ = static_cast(direction) & 0x03; + void setDirection(Direction direction) { + direction_ = direction; } bool hadOverflow() const { diff --git a/yoga/node/Node.cpp b/yoga/node/Node.cpp index 2763df90..7947de17 100644 --- a/yoga/node/Node.cpp +++ b/yoga/node/Node.cpp @@ -296,7 +296,7 @@ void Node::removeChild(size_t index) { children_.erase(children_.begin() + static_cast(index)); } -void Node::setLayoutDirection(YGDirection direction) { +void Node::setLayoutDirection(Direction direction) { layout_.setDirection(direction); } @@ -318,7 +318,7 @@ void Node::setLayoutPadding(float padding, YGEdge edge) { layout_.padding[edge] = padding; } -void Node::setLayoutLastOwnerDirection(YGDirection direction) { +void Node::setLayoutLastOwnerDirection(Direction direction) { layout_.lastOwnerDirection = direction; } @@ -369,14 +369,14 @@ FloatOptional Node::relativePosition( } void Node::setPosition( - const YGDirection direction, + const Direction direction, const float mainSize, const float crossSize, const float ownerWidth) { /* Root nodes should be always layouted as LTR, so we don't return negative * values. */ - const YGDirection directionRespectingRoot = - owner_ != nullptr ? direction : YGDirectionLTR; + const Direction directionRespectingRoot = + owner_ != nullptr ? direction : Direction::LTR; const YGFlexDirection mainAxis = yoga::resolveDirection(style_.flexDirection(), directionRespectingRoot); const YGFlexDirection crossAxis = @@ -447,10 +447,10 @@ void Node::resolveDimension() { } } -YGDirection Node::resolveDirection(const YGDirection ownerDirection) { - if (style_.direction() == YGDirectionInherit) { - return ownerDirection > YGDirectionInherit ? ownerDirection - : YGDirectionLTR; +Direction Node::resolveDirection(const Direction ownerDirection) { + if (style_.direction() == Direction::Inherit) { + return ownerDirection != Direction::Inherit ? ownerDirection + : Direction::LTR; } else { return style_.direction(); } diff --git a/yoga/node/Node.h b/yoga/node/Node.h index 8d2cd676..407a7ee9 100644 --- a/yoga/node/Node.h +++ b/yoga/node/Node.h @@ -14,6 +14,7 @@ #include #include +#include #include #include #include @@ -289,7 +290,7 @@ class YG_EXPORT Node : public ::YGNode { void setConfig(Config* config); void setDirty(bool isDirty); - void setLayoutLastOwnerDirection(YGDirection direction); + void setLayoutLastOwnerDirection(Direction direction); void setLayoutComputedFlexBasis(const FloatOptional computedFlexBasis); void setLayoutComputedFlexBasisGeneration( uint32_t computedFlexBasisGeneration); @@ -298,13 +299,13 @@ class YG_EXPORT Node : public ::YGNode { YGDimension dimension); void setLayoutHadOverflow(bool hadOverflow); void setLayoutDimension(float dimensionValue, YGDimension dimension); - void setLayoutDirection(YGDirection direction); + void setLayoutDirection(Direction direction); void setLayoutMargin(float margin, YGEdge edge); void setLayoutBorder(float border, YGEdge edge); void setLayoutPadding(float padding, YGEdge edge); void setLayoutPosition(float position, YGEdge edge); void setPosition( - const YGDirection direction, + const Direction direction, const float mainSize, const float crossSize, const float ownerWidth); @@ -315,7 +316,7 @@ class YG_EXPORT Node : public ::YGNode { YGValue marginTrailingValue(const YGFlexDirection axis) const; YGValue resolveFlexBasisPtr() const; void resolveDimension(); - YGDirection resolveDirection(const YGDirection ownerDirection); + Direction resolveDirection(const Direction ownerDirection); void clearChildren(); /// Replaces the occurrences of oldChild with newChild void replaceChild(Node* oldChild, Node* newChild); diff --git a/yoga/style/Style.h b/yoga/style/Style.h index a8191aa7..377f124b 100644 --- a/yoga/style/Style.h +++ b/yoga/style/Style.h @@ -15,6 +15,7 @@ #include #include +#include #include #include @@ -22,7 +23,7 @@ namespace facebook::yoga { class YG_EXPORT Style { template - using Values = std::array()>; + using Values = std::array()>; public: using Dimensions = Values; @@ -100,7 +101,7 @@ class YG_EXPORT Style { private: static constexpr uint8_t directionOffset = 0; static constexpr uint8_t flexdirectionOffset = - directionOffset + minimumBitCount(); + directionOffset + minimumBitCount(); static constexpr uint8_t justifyContentOffset = flexdirectionOffset + minimumBitCount(); static constexpr uint8_t alignContentOffset = @@ -139,10 +140,10 @@ class YG_EXPORT Style { // for library users needing a type using ValueRepr = std::remove_reference::type; - YGDirection direction() const { - return getEnumData(flags, directionOffset); + Direction direction() const { + return getEnumData(flags, directionOffset); } - BitfieldRef direction() { + BitfieldRef direction() { return {*this, directionOffset}; }