/* * 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 #include #include #include #include #include namespace facebook::yoga { class YOGA_EXPORT Style { template 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; size_t offset; operator T() const { return getEnumData(style.flags, offset); } BitfieldRef& operator=(T x) { setEnumData(style.flags, offset, x); return *this; } }; template struct Ref { Style& style; operator T() const { return style.*Prop; } Ref& operator=(T value) { style.*Prop = value; return *this; } }; template Style::*Prop> struct IdxRef { struct Ref { Style& style; Idx idx; operator CompactValue() const { return (style.*Prop)[idx]; } operator YGValue() const { return (style.*Prop)[idx]; } Ref& operator=(CompactValue value) { (style.*Prop)[idx] = value; return *this; } }; Style& style; IdxRef& operator=(const Values& values) { style.*Prop = values; return *this; } operator const Values&() const { return style.*Prop; } Ref operator[](Idx idx) { return {style, idx}; } CompactValue operator[](Idx idx) const { return (style.*Prop)[idx]; } }; Style() { alignContent() = YGAlignFlexStart; alignItems() = YGAlignStretch; } ~Style() = default; private: static constexpr size_t directionOffset = 0; static constexpr size_t flexdirectionOffset = directionOffset + minimumBitCount(); static constexpr size_t justifyContentOffset = flexdirectionOffset + minimumBitCount(); static constexpr size_t alignContentOffset = justifyContentOffset + minimumBitCount(); static constexpr size_t alignItemsOffset = alignContentOffset + minimumBitCount(); static constexpr size_t alignSelfOffset = alignItemsOffset + minimumBitCount(); static constexpr size_t positionTypeOffset = alignSelfOffset + minimumBitCount(); static constexpr size_t flexWrapOffset = positionTypeOffset + minimumBitCount(); static constexpr size_t overflowOffset = flexWrapOffset + minimumBitCount(); static constexpr size_t displayOffset = overflowOffset + minimumBitCount(); uint32_t flags = 0; FloatOptional flex_ = {}; FloatOptional flexGrow_ = {}; FloatOptional flexShrink_ = {}; CompactValue flexBasis_ = CompactValue::ofAuto(); Edges margin_ = {}; Edges position_ = {}; Edges padding_ = {}; Edges border_ = {}; Gutters gap_ = {}; Dimensions dimensions_{CompactValue::ofAuto(), CompactValue::ofAuto()}; Dimensions minDimensions_ = {}; Dimensions maxDimensions_ = {}; // Yoga specific properties, not compatible with flexbox specification FloatOptional aspectRatio_ = {}; public: // for library users needing a type using ValueRepr = std::remove_reference::type; YGDirection direction() const { return getEnumData(flags, directionOffset); } BitfieldRef direction() { return {*this, directionOffset}; } YGFlexDirection flexDirection() const { return getEnumData(flags, flexdirectionOffset); } BitfieldRef flexDirection() { return {*this, flexdirectionOffset}; } YGJustify justifyContent() const { return getEnumData(flags, justifyContentOffset); } BitfieldRef justifyContent() { return {*this, justifyContentOffset}; } YGAlign alignContent() const { return getEnumData(flags, alignContentOffset); } BitfieldRef alignContent() { return {*this, alignContentOffset}; } YGAlign alignItems() const { return getEnumData(flags, alignItemsOffset); } BitfieldRef alignItems() { return {*this, alignItemsOffset}; } YGAlign alignSelf() const { return getEnumData(flags, alignSelfOffset); } BitfieldRef alignSelf() { return {*this, alignSelfOffset}; } YGPositionType positionType() const { return getEnumData(flags, positionTypeOffset); } BitfieldRef positionType() { return {*this, positionTypeOffset}; } YGWrap flexWrap() const { return getEnumData(flags, flexWrapOffset); } BitfieldRef flexWrap() { return {*this, flexWrapOffset}; } YGOverflow overflow() const { return getEnumData(flags, overflowOffset); } BitfieldRef overflow() { return {*this, overflowOffset}; } YGDisplay display() const { return getEnumData(flags, displayOffset); } BitfieldRef display() { return {*this, displayOffset}; } FloatOptional flex() const { return flex_; } Ref flex() { return {*this}; } FloatOptional flexGrow() const { return flexGrow_; } Ref flexGrow() { return {*this}; } FloatOptional flexShrink() const { return flexShrink_; } Ref flexShrink() { return {*this}; } CompactValue flexBasis() const { return flexBasis_; } Ref flexBasis() { return {*this}; } const Edges& margin() const { return margin_; } IdxRef margin() { return {*this}; } const Edges& position() const { return position_; } IdxRef position() { return {*this}; } const Edges& padding() const { return padding_; } IdxRef padding() { return {*this}; } const Edges& border() const { return border_; } IdxRef border() { return {*this}; } const Gutters& gap() const { return gap_; } IdxRef gap() { return {*this}; } const Dimensions& dimensions() const { return dimensions_; } IdxRef dimensions() { return {*this}; } const Dimensions& minDimensions() const { return minDimensions_; } IdxRef minDimensions() { return {*this}; } const Dimensions& maxDimensions() const { return maxDimensions_; } IdxRef maxDimensions() { return {*this}; } // Yoga specific properties, not compatible with flexbox specification FloatOptional aspectRatio() const { return aspectRatio_; } Ref aspectRatio() { return {*this}; } }; YOGA_EXPORT bool operator==(const Style& lhs, const Style& rhs); YOGA_EXPORT inline bool operator!=(const Style& lhs, const Style& rhs) { return !(lhs == rhs); } } // namespace facebook::yoga