1/*
2 * Copyright (C) 2016 The Qt Company Ltd.
3 * Copyright (c) Meta Platforms, Inc. and affiliates.
4 *
5 * SPDX-License-Identifier: MIT
6 */
7
8#pragma once
9
10#include <algorithm>
11#include <array>
12#include <cstdint>
13#include <type_traits>
14
15#include <yoga/Yoga.h>
16
17#include "CompactValue.h"
18#include "YGFloatOptional.h"
19#include "Yoga-internal.h"
20#include "BitUtils.h"
21
22QT_YOGA_NAMESPACE_BEGIN
23
24class YOGA_EXPORT YGStyle {
25 template <typename Enum>
26 using Values =
27 facebook::yoga::detail::Values<facebook::yoga::enums::count<Enum>()>;
28 using CompactValue = facebook::yoga::detail::CompactValue;
29
30public:
31 using Dimensions = Values<YGDimension>;
32 using Edges = Values<YGEdge>;
33 using Gutters = Values<YGGutter>;
34
35 template <typename T>
36 struct BitfieldRef {
37 YGStyle& style;
38 size_t offset;
39 operator T() const {
40 return facebook::yoga::detail::getEnumData<T>(style.flags, offset);
41 }
42 BitfieldRef<T>& operator=(T x) {
43 facebook::yoga::detail::setEnumData<T>(style.flags, offset, x);
44 return *this;
45 }
46 };
47
48 template <typename T, T YGStyle::*Prop>
49 struct Ref {
50 YGStyle& style;
51 operator T() const { return style.*Prop; }
52 Ref<T, Prop>& operator=(T value) {
53 style.*Prop = value;
54 return *this;
55 }
56 };
57
58 template <typename Idx, Values<Idx> YGStyle::*Prop>
59 struct IdxRef {
60 struct Ref {
61 YGStyle& style;
62 Idx idx;
63 operator CompactValue() const { return (style.*Prop)[idx]; }
64 operator YGValue() const { return (style.*Prop)[idx]; }
65 Ref& operator=(CompactValue value) {
66 (style.*Prop)[idx] = value;
67 return *this;
68 }
69 };
70
71 YGStyle& style;
72 IdxRef<Idx, Prop>& operator=(const Values<Idx>& values) {
73 style.*Prop = values;
74 return *this;
75 }
76 operator const Values<Idx>&() const { return style.*Prop; }
77 Ref operator[](Idx idx) { return {style, idx}; }
78 CompactValue operator[](Idx idx) const { return (style.*Prop)[idx]; }
79 };
80
81 YGStyle() {
82 alignContent() = YGAlignFlexStart;
83 alignItems() = YGAlignStretch;
84 }
85 ~YGStyle() = default;
86
87private:
88 static constexpr size_t directionOffset = 0;
89 static constexpr size_t flexdirectionOffset =
90 directionOffset + facebook::yoga::detail::bitWidthFn<YGDirection>();
91 static constexpr size_t justifyContentOffset = flexdirectionOffset +
92 facebook::yoga::detail::bitWidthFn<YGFlexDirection>();
93 static constexpr size_t alignContentOffset =
94 justifyContentOffset + facebook::yoga::detail::bitWidthFn<YGJustify>();
95 static constexpr size_t alignItemsOffset =
96 alignContentOffset + facebook::yoga::detail::bitWidthFn<YGAlign>();
97 static constexpr size_t alignSelfOffset =
98 alignItemsOffset + facebook::yoga::detail::bitWidthFn<YGAlign>();
99 static constexpr size_t positionTypeOffset =
100 alignSelfOffset + facebook::yoga::detail::bitWidthFn<YGAlign>();
101 static constexpr size_t flexWrapOffset =
102 positionTypeOffset + facebook::yoga::detail::bitWidthFn<YGPositionType>();
103 static constexpr size_t overflowOffset =
104 flexWrapOffset + facebook::yoga::detail::bitWidthFn<YGWrap>();
105 static constexpr size_t displayOffset =
106 overflowOffset + facebook::yoga::detail::bitWidthFn<YGOverflow>();
107
108 uint32_t flags = 0;
109
110 YGFloatOptional flex_ = {};
111 YGFloatOptional flexGrow_ = {};
112 YGFloatOptional flexShrink_ = {};
113 CompactValue flexBasis_ = CompactValue::ofAuto();
114 Edges margin_ = {};
115 Edges position_ = {};
116 Edges padding_ = {};
117 Edges border_ = {};
118 Gutters gap_ = {};
119 Dimensions dimensions_{CompactValue::ofAuto()};
120 Dimensions minDimensions_ = {};
121 Dimensions maxDimensions_ = {};
122 // Yoga specific properties, not compatible with flexbox specification
123 YGFloatOptional aspectRatio_ = {};
124
125public:
126 // for library users needing a type
127 using ValueRepr = std::remove_reference<decltype(margin_[0])>::type;
128
129 YGDirection direction() const {
130 return facebook::yoga::detail::getEnumData<YGDirection>(
131 flags, index: directionOffset);
132 }
133 BitfieldRef<YGDirection> direction() { return {.style: *this, .offset: directionOffset}; }
134
135 YGFlexDirection flexDirection() const {
136 return facebook::yoga::detail::getEnumData<YGFlexDirection>(
137 flags, index: flexdirectionOffset);
138 }
139 BitfieldRef<YGFlexDirection> flexDirection() {
140 return {.style: *this, .offset: flexdirectionOffset};
141 }
142
143 YGJustify justifyContent() const {
144 return facebook::yoga::detail::getEnumData<YGJustify>(
145 flags, index: justifyContentOffset);
146 }
147 BitfieldRef<YGJustify> justifyContent() {
148 return {.style: *this, .offset: justifyContentOffset};
149 }
150
151 YGAlign alignContent() const {
152 return facebook::yoga::detail::getEnumData<YGAlign>(
153 flags, index: alignContentOffset);
154 }
155 BitfieldRef<YGAlign> alignContent() { return {.style: *this, .offset: alignContentOffset}; }
156
157 YGAlign alignItems() const {
158 return facebook::yoga::detail::getEnumData<YGAlign>(
159 flags, index: alignItemsOffset);
160 }
161 BitfieldRef<YGAlign> alignItems() { return {.style: *this, .offset: alignItemsOffset}; }
162
163 YGAlign alignSelf() const {
164 return facebook::yoga::detail::getEnumData<YGAlign>(flags, index: alignSelfOffset);
165 }
166 BitfieldRef<YGAlign> alignSelf() { return {.style: *this, .offset: alignSelfOffset}; }
167
168 YGPositionType positionType() const {
169 return facebook::yoga::detail::getEnumData<YGPositionType>(
170 flags, index: positionTypeOffset);
171 }
172 BitfieldRef<YGPositionType> positionType() {
173 return {.style: *this, .offset: positionTypeOffset};
174 }
175
176 YGWrap flexWrap() const {
177 return facebook::yoga::detail::getEnumData<YGWrap>(flags, index: flexWrapOffset);
178 }
179 BitfieldRef<YGWrap> flexWrap() { return {.style: *this, .offset: flexWrapOffset}; }
180
181 YGOverflow overflow() const {
182 return facebook::yoga::detail::getEnumData<YGOverflow>(
183 flags, index: overflowOffset);
184 }
185 BitfieldRef<YGOverflow> overflow() { return {.style: *this, .offset: overflowOffset}; }
186
187 YGDisplay display() const {
188 return facebook::yoga::detail::getEnumData<YGDisplay>(flags, index: displayOffset);
189 }
190 BitfieldRef<YGDisplay> display() { return {.style: *this, .offset: displayOffset}; }
191
192 YGFloatOptional flex() const { return flex_; }
193 Ref<YGFloatOptional, &YGStyle::flex_> flex() { return {.style: *this}; }
194
195 YGFloatOptional flexGrow() const { return flexGrow_; }
196 Ref<YGFloatOptional, &YGStyle::flexGrow_> flexGrow() { return {.style: *this}; }
197
198 YGFloatOptional flexShrink() const { return flexShrink_; }
199 Ref<YGFloatOptional, &YGStyle::flexShrink_> flexShrink() { return {.style: *this}; }
200
201 CompactValue flexBasis() const { return flexBasis_; }
202 Ref<CompactValue, &YGStyle::flexBasis_> flexBasis() { return {.style: *this}; }
203
204 const Edges& margin() const { return margin_; }
205 IdxRef<YGEdge, &YGStyle::margin_> margin() { return {.style: *this}; }
206
207 const Edges& position() const { return position_; }
208 IdxRef<YGEdge, &YGStyle::position_> position() { return {.style: *this}; }
209
210 const Edges& padding() const { return padding_; }
211 IdxRef<YGEdge, &YGStyle::padding_> padding() { return {.style: *this}; }
212
213 const Edges& border() const { return border_; }
214 IdxRef<YGEdge, &YGStyle::border_> border() { return {.style: *this}; }
215
216 const Gutters& gap() const { return gap_; }
217 IdxRef<YGGutter, &YGStyle::gap_> gap() { return {.style: *this}; }
218
219 const Dimensions& dimensions() const { return dimensions_; }
220 IdxRef<YGDimension, &YGStyle::dimensions_> dimensions() { return {.style: *this}; }
221
222 const Dimensions& minDimensions() const { return minDimensions_; }
223 IdxRef<YGDimension, &YGStyle::minDimensions_> minDimensions() {
224 return {.style: *this};
225 }
226
227 const Dimensions& maxDimensions() const { return maxDimensions_; }
228 IdxRef<YGDimension, &YGStyle::maxDimensions_> maxDimensions() {
229 return {.style: *this};
230 }
231
232 // Yoga specific properties, not compatible with flexbox specification
233 YGFloatOptional aspectRatio() const { return aspectRatio_; }
234 Ref<YGFloatOptional, &YGStyle::aspectRatio_> aspectRatio() { return {.style: *this}; }
235};
236
237YOGA_EXPORT bool operator==(const YGStyle& lhs, const YGStyle& rhs);
238YOGA_EXPORT inline bool operator!=(const YGStyle& lhs, const YGStyle& rhs) {
239 return !(lhs == rhs);
240}
241
242QT_YOGA_NAMESPACE_END
243

source code of qtdeclarative/src/3rdparty/yoga/YGStyle.h