diff --git a/yoga/Bitfield.h b/yoga/Bitfield.h index e5b40267..da85a5bf 100644 --- a/yoga/Bitfield.h +++ b/yoga/Bitfield.h @@ -95,6 +95,20 @@ class Bitfield { template using TypeAt = typename detail::IndexedType::Type; + template + static constexpr Storage initStorage(Value value, Values... values) { + return ((value << BitTraits::shift(Idx)) & BitTraits::mask(Idx)) | + initStorage(values...); + } + + template + static constexpr Storage initStorage() { + return Storage{0}; + } + + Storage storage_ = 0; + +public: template class Ref { Bitfield& bitfield_; @@ -111,20 +125,6 @@ class Bitfield { } }; - template - static constexpr Storage initStorage(Value value, Values... values) { - return ((value << BitTraits::shift(Idx)) & BitTraits::mask(Idx)) | - initStorage(values...); - } - - template - static constexpr Storage initStorage() { - return Storage{0}; - } - - Storage storage_ = 0; - -public: constexpr Bitfield() = default; constexpr Bitfield(Fields... values) : storage_{initStorage<0>(values...)} {} diff --git a/yoga/YGNode.cpp b/yoga/YGNode.cpp index 8941487f..969d1752 100644 --- a/yoga/YGNode.cpp +++ b/yoga/YGNode.cpp @@ -15,14 +15,7 @@ using facebook::yoga::detail::CompactValue; YGNode::YGNode(YGNode&& node) { context_ = node.context_; - hasNewLayout_ = node.hasNewLayout_; - isReferenceBaseline_ = node.isReferenceBaseline_; - isDirty_ = node.isDirty_; - nodeType_ = node.nodeType_; - measureUsesContext_ = node.measureUsesContext_; - baselineUsesContext_ = node.baselineUsesContext_; - printUsesContext_ = node.printUsesContext_; - useWebDefaults_ = node.useWebDefaults_; + flags_ = node.flags_; measure_ = node.measure_; baseline_ = node.baseline_; print_ = node.print_; @@ -48,7 +41,7 @@ YGNode::YGNode(const YGNode& node, YGConfigRef config) : YGNode{node} { void YGNode::print(void* printContext) { if (print_.noContext != nullptr) { - if (printUsesContext_) { + if (flags_.at()) { print_.withContext(this, printContext); } else { print_.noContext(this); @@ -154,14 +147,14 @@ YGSize YGNode::measure( YGMeasureMode heightMode, void* layoutContext) { - return measureUsesContext_ + return flags_.at() ? measure_.withContext( this, width, widthMode, height, heightMode, layoutContext) : measure_.noContext(this, width, widthMode, height, heightMode); } float YGNode::baseline(float width, float height, void* layoutContext) { - return baselineUsesContext_ + return flags_.at() ? baseline_.withContext(this, width, height, layoutContext) : baseline_.noContext(this, width, height); } @@ -172,7 +165,7 @@ void YGNode::setMeasureFunc(decltype(YGNode::measure_) measureFunc) { if (measureFunc.noContext == nullptr) { // TODO: t18095186 Move nodeType to opt-in function and mark appropriate // places in Litho - nodeType_ = YGNodeTypeDefault; + flags_.at() = YGNodeTypeDefault; } else { YGAssertWithNode( this, @@ -188,14 +181,14 @@ void YGNode::setMeasureFunc(decltype(YGNode::measure_) measureFunc) { } void YGNode::setMeasureFunc(YGMeasureFunc measureFunc) { - measureUsesContext_ = false; + flags_.at() = false; decltype(YGNode::measure_) m; m.noContext = measureFunc; setMeasureFunc(m); } void YGNode::setMeasureFunc(MeasureWithContextFn measureFunc) { - measureUsesContext_ = true; + flags_.at() = true; decltype(YGNode::measure_) m; m.withContext = measureFunc; setMeasureFunc(m); @@ -214,10 +207,10 @@ void YGNode::insertChild(YGNodeRef child, uint32_t index) { } void YGNode::setDirty(bool isDirty) { - if (isDirty == isDirty_) { + if (isDirty == flags_.at()) { return; } - isDirty_ = isDirty; + flags_.at() = isDirty; if (isDirty && dirtied_) { dirtied_(this); } @@ -357,7 +350,7 @@ YGValue YGNode::resolveFlexBasisPtr() const { return flexBasis; } if (!style_.flex().isUndefined() && style_.flex().unwrap() > 0.0f) { - return useWebDefaults_ ? YGValueAuto : YGValueZero; + return flags_.at() ? YGValueAuto : YGValueZero; } return YGValueAuto; } @@ -396,7 +389,7 @@ void YGNode::cloneChildrenIfNeeded(void* cloneContext) { } void YGNode::markDirtyAndPropogate() { - if (!isDirty_) { + if (!flags_.at()) { setDirty(true); setLayoutComputedFlexBasis(YGFloatOptional()); if (owner_) { @@ -406,7 +399,7 @@ void YGNode::markDirtyAndPropogate() { } void YGNode::markDirtyAndPropogateDownwards() { - isDirty_ = true; + flags_.at() = true; for_each(children_.begin(), children_.end(), [](YGNodeRef childNode) { childNode->markDirtyAndPropogateDownwards(); }); @@ -433,11 +426,12 @@ float YGNode::resolveFlexShrink() const { if (!style_.flexShrink().isUndefined()) { return style_.flexShrink().unwrap(); } - if (!useWebDefaults_ && !style_.flex().isUndefined() && + if (!flags_.at() && !style_.flex().isUndefined() && style_.flex().unwrap() < 0.0f) { return -style_.flex().unwrap(); } - return useWebDefaults_ ? kWebDefaultFlexShrink : kDefaultFlexShrink; + return flags_.at() ? kWebDefaultFlexShrink + : kDefaultFlexShrink; } bool YGNode::isNodeFlexible() { @@ -582,7 +576,7 @@ void YGNode::reset() { clearChildren(); - auto webDefaults = useWebDefaults_; + auto webDefaults = flags_.at(); *this = YGNode{getConfig()}; if (webDefaults) { useWebDefaults(); diff --git a/yoga/YGNode.h b/yoga/YGNode.h index cc11cc88..cc5f3686 100644 --- a/yoga/YGNode.h +++ b/yoga/YGNode.h @@ -7,6 +7,7 @@ #pragma once #include #include +#include "Bitfield.h" #include "CompactValue.h" #include "YGConfig.h" #include "YGLayout.h" @@ -23,15 +24,20 @@ struct YGNode { using PrintWithContextFn = void (*)(YGNode*, void*); private: + static constexpr size_t hasNewLayout_ = 0; + static constexpr size_t isReferenceBaseline_ = 1; + static constexpr size_t isDirty_ = 2; + static constexpr size_t nodeType_ = 3; + static constexpr size_t measureUsesContext_ = 4; + static constexpr size_t baselineUsesContext_ = 5; + static constexpr size_t printUsesContext_ = 6; + static constexpr size_t useWebDefaults_ = 7; + void* context_ = nullptr; - bool hasNewLayout_ : 1; - bool isReferenceBaseline_ : 1; - bool isDirty_ : 1; - YGNodeType nodeType_ : 1; - bool measureUsesContext_ : 1; - bool baselineUsesContext_ : 1; - bool printUsesContext_ : 1; - bool useWebDefaults_ : 1; + using Flags = facebook::yoga:: + Bitfield; + Flags flags_ = + {true, false, false, YGNodeTypeDefault, false, false, false, false}; uint8_t reserved_ = 0; union { YGMeasureFunc noContext; @@ -63,7 +69,7 @@ private: void setBaselineFunc(decltype(baseline_)); void useWebDefaults() { - useWebDefaults_ = true; + flags_.at() = true; style_.flexDirection() = YGFlexDirectionRow; style_.alignContent() = YGAlignStretch; } @@ -79,17 +85,8 @@ private: public: YGNode() : YGNode{YGConfigGetDefault()} {} - explicit YGNode(const YGConfigRef config) - : hasNewLayout_{true}, - isReferenceBaseline_{false}, - isDirty_{false}, - nodeType_{YGNodeTypeDefault}, - measureUsesContext_{false}, - baselineUsesContext_{false}, - printUsesContext_{false}, - useWebDefaults_{config->useWebDefaults}, - config_{config} { - if (useWebDefaults_) { + explicit YGNode(const YGConfigRef config) : config_{config} { + if (config->useWebDefaults) { useWebDefaults(); } }; @@ -116,9 +113,9 @@ public: void print(void*); - bool getHasNewLayout() const { return hasNewLayout_; } + bool getHasNewLayout() const { return flags_.at(); } - YGNodeType getNodeType() const { return nodeType_; } + YGNodeType getNodeType() const { return flags_.at(); } bool hasMeasureFunc() const noexcept { return measure_.noContext != nullptr; } @@ -144,7 +141,7 @@ public: uint32_t getLineIndex() const { return lineIndex_; } - bool isReferenceBaseline() { return isReferenceBaseline_; } + bool isReferenceBaseline() { return flags_.at(); } // returns the YGNodeRef that owns this YGNode. An owner is used to identify // the YogaTree that a YGNode belongs to. This method will return the parent @@ -177,7 +174,7 @@ public: YGConfigRef getConfig() const { return config_; } - bool isDirty() const { return isDirty_; } + bool isDirty() const { return flags_.at(); } std::array getResolvedDimensions() const { return resolvedDimensions_; @@ -225,17 +222,19 @@ public: void setPrintFunc(YGPrintFunc printFunc) { print_.noContext = printFunc; - printUsesContext_ = false; + flags_.at() = false; } void setPrintFunc(PrintWithContextFn printFunc) { print_.withContext = printFunc; - printUsesContext_ = true; + flags_.at() = true; } void setPrintFunc(std::nullptr_t) { setPrintFunc(YGPrintFunc{nullptr}); } - void setHasNewLayout(bool hasNewLayout) { hasNewLayout_ = hasNewLayout; } + void setHasNewLayout(bool hasNewLayout) { + flags_.at() = hasNewLayout; + } - void setNodeType(YGNodeType nodeType) { nodeType_ = nodeType; } + void setNodeType(YGNodeType nodeType) { flags_.at() = nodeType; } void setMeasureFunc(YGMeasureFunc measureFunc); void setMeasureFunc(MeasureWithContextFn); @@ -244,11 +243,11 @@ public: } void setBaselineFunc(YGBaselineFunc baseLineFunc) { - baselineUsesContext_ = false; + flags_.at() = false; baseline_.noContext = baseLineFunc; } void setBaselineFunc(BaselineWithContextFn baseLineFunc) { - baselineUsesContext_ = true; + flags_.at() = true; baseline_.withContext = baseLineFunc; } void setBaselineFunc(std::nullptr_t) { @@ -264,7 +263,7 @@ public: void setLineIndex(uint32_t lineIndex) { lineIndex_ = lineIndex; } void setIsReferenceBaseline(bool isReferenceBaseline) { - isReferenceBaseline_ = isReferenceBaseline; + flags_.at() = isReferenceBaseline; } void setOwner(YGNodeRef owner) { owner_ = owner; } diff --git a/yoga/YGStyle.h b/yoga/YGStyle.h index 22196556..b497b5c1 100644 --- a/yoga/YGStyle.h +++ b/yoga/YGStyle.h @@ -9,25 +9,13 @@ #include #include #include +#include "Bitfield.h" #include "CompactValue.h" #include "YGEnums.h" #include "YGFloatOptional.h" #include "Yoga-internal.h" #include "Yoga.h" -#if !defined(ENUM_BITFIELDS_NOT_SUPPORTED) -#define BITFIELD_ENUM_SIZED(num) : num -#else -#define BITFIELD_ENUM_SIZED(num) -#endif - -#define BITFIELD_ACCESSORS(FIELD) \ - decltype(FIELD##_) get_##FIELD() const { return FIELD##_; } \ - void set_##FIELD(decltype(FIELD##_) x) { FIELD##_ = x; } - -#define BITFIELD_REF(FIELD) \ - BitfieldRef - class YGStyle { template using Values = @@ -71,53 +59,43 @@ public: CompactValue operator[](Idx idx) const { return (style.*Prop)[idx]; } }; - template - struct BitfieldRef { - YGStyle& style; - - operator T() const { return (style.*Get)(); } - BitfieldRef& operator=(T x) { - (style.*Set)(x); - return *this; - } - }; - -#ifdef __clang__ -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wbitfield-constant-conversion" -#endif - - YGStyle() - : direction_(YGDirectionInherit), - flexDirection_(YGFlexDirectionColumn), - justifyContent_(YGJustifyFlexStart), - alignContent_(YGAlignFlexStart), - alignItems_(YGAlignStretch), - alignSelf_(YGAlignAuto), - positionType_(YGPositionTypeRelative), - flexWrap_(YGWrapNoWrap), - overflow_(YGOverflowVisible), - display_(YGDisplayFlex) {} - -#ifdef __clang__ -#pragma clang diagnostic pop -#endif - + YGStyle() = default; ~YGStyle() = default; private: - /* Some platforms don't support enum bitfields, - so please use BITFIELD_ENUM_SIZED(BITS_COUNT) */ - YGDirection direction_ BITFIELD_ENUM_SIZED(2); - YGFlexDirection flexDirection_ BITFIELD_ENUM_SIZED(2); - YGJustify justifyContent_ BITFIELD_ENUM_SIZED(3); - YGAlign alignContent_ BITFIELD_ENUM_SIZED(3); - YGAlign alignItems_ BITFIELD_ENUM_SIZED(3); - YGAlign alignSelf_ BITFIELD_ENUM_SIZED(3); - YGPositionType positionType_ BITFIELD_ENUM_SIZED(1); - YGWrap flexWrap_ BITFIELD_ENUM_SIZED(2); - YGOverflow overflow_ BITFIELD_ENUM_SIZED(2); - YGDisplay display_ BITFIELD_ENUM_SIZED(1); + static constexpr size_t directionIdx = 0; + static constexpr size_t flexDirectionIdx = 1; + static constexpr size_t justifyContentIdx = 2; + static constexpr size_t alignContentIdx = 3; + static constexpr size_t alignItemsIdx = 4; + static constexpr size_t alignSelfIdx = 5; + static constexpr size_t positionTypeIdx = 6; + static constexpr size_t flexWrapIdx = 7; + static constexpr size_t overflowIdx = 8; + static constexpr size_t displayIdx = 9; + using Flags = facebook::yoga::Bitfield< + uint32_t, + YGDirection, + YGFlexDirection, + YGJustify, + YGAlign, + YGAlign, + YGAlign, + YGPositionType, + YGWrap, + YGOverflow, + YGDisplay>; + + Flags flags_ = {YGDirectionInherit, + YGFlexDirectionColumn, + YGJustifyFlexStart, + YGAlignFlexStart, + YGAlignStretch, + YGAlignAuto, + YGPositionTypeRelative, + YGWrapNoWrap, + YGOverflowVisible, + YGDisplayFlex}; YGFloatOptional flex_ = {}; YGFloatOptional flexGrow_ = {}; YGFloatOptional flexShrink_ = {}; @@ -132,50 +110,49 @@ private: // Yoga specific properties, not compatible with flexbox specification YGFloatOptional aspectRatio_ = {}; - BITFIELD_ACCESSORS(direction) - BITFIELD_ACCESSORS(flexDirection) - BITFIELD_ACCESSORS(justifyContent) - BITFIELD_ACCESSORS(alignContent); - BITFIELD_ACCESSORS(alignItems); - BITFIELD_ACCESSORS(alignSelf); - BITFIELD_ACCESSORS(positionType); - BITFIELD_ACCESSORS(flexWrap); - BITFIELD_ACCESSORS(overflow); - BITFIELD_ACCESSORS(display); - public: // for library users needing a type using ValueRepr = std::remove_reference::type; - YGDirection direction() const { return direction_; } - BITFIELD_REF(direction) direction() { return {*this}; } + YGDirection direction() const { return flags_.at(); } + Flags::Ref direction() { return flags_.at(); } - YGFlexDirection flexDirection() const { return flexDirection_; } - BITFIELD_REF(flexDirection) flexDirection() { return {*this}; } + YGFlexDirection flexDirection() const { + return flags_.at(); + } + Flags::Ref flexDirection() { + return flags_.at(); + } - YGJustify justifyContent() const { return justifyContent_; } - BITFIELD_REF(justifyContent) justifyContent() { return {*this}; } + YGJustify justifyContent() const { return flags_.at(); } + Flags::Ref justifyContent() { + return flags_.at(); + } - YGAlign alignContent() const { return alignContent_; } - BITFIELD_REF(alignContent) alignContent() { return {*this}; } + YGAlign alignContent() const { return flags_.at(); } + Flags::Ref alignContent() { + return flags_.at(); + } - YGAlign alignItems() const { return alignItems_; } - BITFIELD_REF(alignItems) alignItems() { return {*this}; } + YGAlign alignItems() const { return flags_.at(); } + Flags::Ref alignItems() { return flags_.at(); } - YGAlign alignSelf() const { return alignSelf_; } - BITFIELD_REF(alignSelf) alignSelf() { return {*this}; } + YGAlign alignSelf() const { return flags_.at(); } + Flags::Ref alignSelf() { return flags_.at(); } - YGPositionType positionType() const { return positionType_; } - BITFIELD_REF(positionType) positionType() { return {*this}; } + YGPositionType positionType() const { return flags_.at(); } + Flags::Ref positionType() { + return flags_.at(); + } - YGWrap flexWrap() const { return flexWrap_; } - BITFIELD_REF(flexWrap) flexWrap() { return {*this}; } + YGWrap flexWrap() const { return flags_.at(); } + Flags::Ref flexWrap() { return flags_.at(); } - YGOverflow overflow() const { return overflow_; } - BITFIELD_REF(overflow) overflow() { return {*this}; } + YGOverflow overflow() const { return flags_.at(); } + Flags::Ref overflow() { return flags_.at(); } - YGDisplay display() const { return display_; } - BITFIELD_REF(display) display() { return {*this}; } + YGDisplay display() const { return flags_.at(); } + Flags::Ref display() { return flags_.at(); } YGFloatOptional flex() const { return flex_; } Ref flex() { return {*this}; } @@ -223,7 +200,3 @@ bool operator==(const YGStyle& lhs, const YGStyle& rhs); inline bool operator!=(const YGStyle& lhs, const YGStyle& rhs) { return !(lhs == rhs); } - -#undef BITFIELD_ENUM_SIZED -#undef BITFIELD_ACCESSORS -#undef BITFIELD_REF