/* * 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 #include #include #include #include #include #include #include #include namespace facebook::yoga { class YG_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; uint8_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() = Align::FlexStart; alignItems() = Align::Stretch; } ~Style() = default; private: static constexpr uint8_t directionOffset = 0; static constexpr uint8_t flexdirectionOffset = directionOffset + minimumBitCount(); static constexpr uint8_t justifyContentOffset = flexdirectionOffset + minimumBitCount(); static constexpr uint8_t alignContentOffset = justifyContentOffset + minimumBitCount(); static constexpr uint8_t alignItemsOffset = alignContentOffset + minimumBitCount(); static constexpr uint8_t alignSelfOffset = alignItemsOffset + minimumBitCount(); static constexpr uint8_t positionTypeOffset = alignSelfOffset + minimumBitCount(); static constexpr uint8_t flexWrapOffset = positionTypeOffset + minimumBitCount(); static constexpr uint8_t overflowOffset = flexWrapOffset + minimumBitCount(); static constexpr uint8_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; Direction direction() const { return getEnumData(flags, directionOffset); } BitfieldRef direction() { return {*this, directionOffset}; } FlexDirection flexDirection() const { return getEnumData(flags, flexdirectionOffset); } BitfieldRef flexDirection() { return {*this, flexdirectionOffset}; } Justify justifyContent() const { return getEnumData(flags, justifyContentOffset); } BitfieldRef justifyContent() { return {*this, justifyContentOffset}; } Align alignContent() const { return getEnumData(flags, alignContentOffset); } BitfieldRef alignContent() { return {*this, alignContentOffset}; } Align alignItems() const { return getEnumData(flags, alignItemsOffset); } BitfieldRef alignItems() { return {*this, alignItemsOffset}; } Align alignSelf() const { return getEnumData(flags, alignSelfOffset); } BitfieldRef alignSelf() { return {*this, alignSelfOffset}; } PositionType positionType() const { return getEnumData(flags, positionTypeOffset); } BitfieldRef positionType() { return {*this, positionTypeOffset}; } Wrap flexWrap() const { return getEnumData(flags, flexWrapOffset); } BitfieldRef flexWrap() { return {*this, flexWrapOffset}; } Overflow overflow() const { return getEnumData(flags, overflowOffset); } BitfieldRef overflow() { return {*this, overflowOffset}; } Display 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}; } CompactValue dimension(YGDimension axis) const { return dimensions_[axis]; } void setDimension(YGDimension axis, CompactValue value) { dimensions_[axis] = value; } CompactValue minDimension(YGDimension axis) const { return minDimensions_[axis]; } void setMinDimension(YGDimension axis, CompactValue value) { minDimensions_[axis] = value; } CompactValue maxDimension(YGDimension axis) const { return maxDimensions_[axis]; } void setMaxDimension(YGDimension axis, CompactValue value) { maxDimensions_[axis] = value; } // Yoga specific properties, not compatible with flexbox specification FloatOptional aspectRatio() const { return aspectRatio_; } Ref aspectRatio() { return {*this}; } bool operator==(const Style& other) const { return flags == other.flags && inexactEquals(flex_, other.flex_) && inexactEquals(flexGrow_, other.flexGrow_) && inexactEquals(flexShrink_, other.flexShrink_) && inexactEquals(flexBasis_, other.flexBasis_) && inexactEquals(margin_, other.margin_) && inexactEquals(position_, other.position_) && inexactEquals(padding_, other.padding_) && inexactEquals(border_, other.border_) && inexactEquals(gap_, other.gap_) && inexactEquals(dimensions_, other.dimensions_) && inexactEquals(minDimensions_, other.minDimensions_) && inexactEquals(maxDimensions_, other.maxDimensions_) && inexactEquals(aspectRatio_, other.aspectRatio_); } bool operator!=(const Style& other) const { return !(*this == other); } }; } // namespace facebook::yoga