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 <cstdint>
11#include <stdio.h>
12#include "CompactValue.h"
13#include "YGConfig.h"
14#include "YGLayout.h"
15#include "YGStyle.h"
16#include "Yoga-internal.h"
17
18YGConfigRef YGConfigGetDefault();
19
20#pragma pack(push)
21#pragma pack(1)
22struct YGNodeFlags {
23 bool hasNewLayout : 1;
24 bool isReferenceBaseline : 1;
25 bool isDirty : 1;
26 uint8_t nodeType : 1;
27 bool measureUsesContext : 1;
28 bool baselineUsesContext : 1;
29 bool printUsesContext : 1;
30};
31#pragma pack(pop)
32
33QT_YOGA_NAMESPACE_BEGIN
34
35struct YOGA_EXPORT YGNode {
36 using MeasureWithContextFn =
37 YGSize (*)(YGNode*, float, YGMeasureMode, float, YGMeasureMode, void*);
38 using BaselineWithContextFn = float (*)(YGNode*, float, float, void*);
39 using PrintWithContextFn = void (*)(YGNode*, void*);
40
41private:
42 void* context_ = nullptr;
43 YGNodeFlags flags_ = {};
44 union {
45 YGMeasureFunc noContext;
46 MeasureWithContextFn withContext;
47 } measure_ = {.noContext: nullptr};
48 union {
49 YGBaselineFunc noContext;
50 BaselineWithContextFn withContext;
51 } baseline_ = {.noContext: nullptr};
52 union {
53 YGPrintFunc noContext;
54 PrintWithContextFn withContext;
55 } print_ = {.noContext: nullptr};
56 YGDirtiedFunc dirtied_ = nullptr;
57 YGStyle style_ = {};
58 YGLayout layout_ = {};
59 uint32_t lineIndex_ = 0;
60 YGNodeRef owner_ = nullptr;
61 YGVector children_ = {};
62 YGConfigRef config_;
63 std::array<YGValue, 2> resolvedDimensions_ = {
64 ._M_elems: {YGValueUndefined, YGValueUndefined}};
65
66 YGFloatOptional relativePosition(
67 const YGFlexDirection axis,
68 const float axisSize) const;
69
70 void setMeasureFunc(decltype(measure_));
71 void setBaselineFunc(decltype(baseline_));
72
73 void useWebDefaults() {
74 style_.flexDirection() = YGFlexDirectionRow;
75 style_.alignContent() = YGAlignStretch;
76 }
77
78 // DANGER DANGER DANGER!
79 // If the node assigned to has children, we'd either have to deallocate
80 // them (potentially incorrect) or ignore them (danger of leaks). Only ever
81 // use this after checking that there are no children.
82 // DO NOT CHANGE THE VISIBILITY OF THIS METHOD!
83 YGNode& operator=(YGNode&&) = default;
84
85 using CompactValue = facebook::yoga::detail::CompactValue;
86
87public:
88 YGNode() : YGNode{YGConfigGetDefault()} { flags_.hasNewLayout = true; }
89 explicit YGNode(const YGConfigRef config);
90 ~YGNode() = default; // cleanup of owner/children relationships in YGNodeFree
91
92 YGNode(YGNode&&);
93
94 // Does not expose true value semantics, as children are not cloned eagerly.
95 // Should we remove this?
96 YGNode(const YGNode& node) = default;
97
98 // assignment means potential leaks of existing children, or alternatively
99 // freeing unowned memory, double free, or freeing stack memory.
100 YGNode& operator=(const YGNode&) = delete;
101
102 // Getters
103 void* getContext() const { return context_; }
104
105 void print(void*);
106
107 bool getHasNewLayout() const { return flags_.hasNewLayout; }
108
109 YGNodeType getNodeType() const {
110 return static_cast<YGNodeType>(flags_.nodeType);
111 }
112
113 bool hasMeasureFunc() const noexcept { return measure_.noContext != nullptr; }
114
115 YGSize measure(float, YGMeasureMode, float, YGMeasureMode, void*);
116
117 bool hasBaselineFunc() const noexcept {
118 return baseline_.noContext != nullptr;
119 }
120
121 float baseline(float width, float height, void* layoutContext);
122
123 bool hasErrata(YGErrata errata) const { return config_->hasErrata(errata); }
124
125 YGDirtiedFunc getDirtied() const { return dirtied_; }
126
127 // For Performance reasons passing as reference.
128 YGStyle& getStyle() { return style_; }
129
130 const YGStyle& getStyle() const { return style_; }
131
132 // For Performance reasons passing as reference.
133 YGLayout& getLayout() { return layout_; }
134
135 const YGLayout& getLayout() const { return layout_; }
136
137 uint32_t getLineIndex() const { return lineIndex_; }
138
139 bool isReferenceBaseline() { return flags_.isReferenceBaseline; }
140
141 // returns the YGNodeRef that owns this YGNode. An owner is used to identify
142 // the YogaTree that a YGNode belongs to. This method will return the parent
143 // of the YGNode when a YGNode only belongs to one YogaTree or nullptr when
144 // the YGNode is shared between two or more YogaTrees.
145 YGNodeRef getOwner() const { return owner_; }
146
147 // Deprecated, use getOwner() instead.
148 YGNodeRef getParent() const { return getOwner(); }
149
150 const YGVector& getChildren() const { return children_; }
151
152 // Applies a callback to all children, after cloning them if they are not
153 // owned.
154 template <typename T>
155 void iterChildrenAfterCloningIfNeeded(T callback, void* cloneContext) {
156 int i = 0;
157 for (YGNodeRef& child : children_) {
158 if (child->getOwner() != this) {
159 child = config_->cloneNode(node: child, owner: this, childIndex: i, cloneContext);
160 child->setOwner(this);
161 }
162 i += 1;
163
164 callback(child, cloneContext);
165 }
166 }
167
168 YGNodeRef getChild(uint32_t index) const { return children_.at(n: index); }
169
170 YGConfigRef getConfig() const { return config_; }
171
172 bool isDirty() const { return flags_.isDirty; }
173
174 std::array<YGValue, 2> getResolvedDimensions() const {
175 return resolvedDimensions_;
176 }
177
178 YGValue getResolvedDimension(int index) const {
179 return resolvedDimensions_[index];
180 }
181
182 static CompactValue computeEdgeValueForColumn(
183 const YGStyle::Edges& edges,
184 YGEdge edge,
185 CompactValue defaultValue);
186
187 static CompactValue computeEdgeValueForRow(
188 const YGStyle::Edges& edges,
189 YGEdge rowEdge,
190 YGEdge edge,
191 CompactValue defaultValue);
192
193 static CompactValue computeRowGap(
194 const YGStyle::Gutters& gutters,
195 CompactValue defaultValue);
196
197 static CompactValue computeColumnGap(
198 const YGStyle::Gutters& gutters,
199 CompactValue defaultValue);
200
201 // Methods related to positions, margin, padding and border
202 YGFloatOptional getLeadingPosition(
203 const YGFlexDirection axis,
204 const float axisSize) const;
205 bool isLeadingPositionDefined(const YGFlexDirection axis) const;
206 bool isTrailingPosDefined(const YGFlexDirection axis) const;
207 YGFloatOptional getTrailingPosition(
208 const YGFlexDirection axis,
209 const float axisSize) const;
210 YGFloatOptional getLeadingMargin(
211 const YGFlexDirection axis,
212 const float widthSize) const;
213 YGFloatOptional getTrailingMargin(
214 const YGFlexDirection axis,
215 const float widthSize) const;
216 float getLeadingBorder(const YGFlexDirection flexDirection) const;
217 float getTrailingBorder(const YGFlexDirection flexDirection) const;
218 YGFloatOptional getLeadingPadding(
219 const YGFlexDirection axis,
220 const float widthSize) const;
221 YGFloatOptional getTrailingPadding(
222 const YGFlexDirection axis,
223 const float widthSize) const;
224 YGFloatOptional getLeadingPaddingAndBorder(
225 const YGFlexDirection axis,
226 const float widthSize) const;
227 YGFloatOptional getTrailingPaddingAndBorder(
228 const YGFlexDirection axis,
229 const float widthSize) const;
230 YGFloatOptional getMarginForAxis(
231 const YGFlexDirection axis,
232 const float widthSize) const;
233 YGFloatOptional getGapForAxis(
234 const YGFlexDirection axis,
235 const float widthSize) const;
236 // Setters
237
238 void setContext(void* context) { context_ = context; }
239
240 void setPrintFunc(YGPrintFunc printFunc) {
241 print_.noContext = printFunc;
242 flags_.printUsesContext = false;
243 }
244 void setPrintFunc(PrintWithContextFn printFunc) {
245 print_.withContext = printFunc;
246 flags_.printUsesContext = true;
247 }
248 void setPrintFunc(std::nullptr_t) { setPrintFunc(YGPrintFunc{nullptr}); }
249
250 void setHasNewLayout(bool hasNewLayout) {
251 flags_.hasNewLayout = hasNewLayout;
252 }
253
254 void setNodeType(YGNodeType nodeType) {
255 flags_.nodeType = static_cast<uint8_t>(nodeType);
256 }
257
258 void setMeasureFunc(YGMeasureFunc measureFunc);
259 void setMeasureFunc(MeasureWithContextFn);
260 void setMeasureFunc(std::nullptr_t) {
261 return setMeasureFunc(YGMeasureFunc{nullptr});
262 }
263
264 void setBaselineFunc(YGBaselineFunc baseLineFunc) {
265 flags_.baselineUsesContext = false;
266 baseline_.noContext = baseLineFunc;
267 }
268 void setBaselineFunc(BaselineWithContextFn baseLineFunc) {
269 flags_.baselineUsesContext = true;
270 baseline_.withContext = baseLineFunc;
271 }
272 void setBaselineFunc(std::nullptr_t) {
273 return setBaselineFunc(YGBaselineFunc{nullptr});
274 }
275
276 void setDirtiedFunc(YGDirtiedFunc dirtiedFunc) { dirtied_ = dirtiedFunc; }
277
278 void setStyle(const YGStyle& style) { style_ = style; }
279
280 void setLayout(const YGLayout& layout) { layout_ = layout; }
281
282 void setLineIndex(uint32_t lineIndex) { lineIndex_ = lineIndex; }
283
284 void setIsReferenceBaseline(bool isReferenceBaseline) {
285 flags_.isReferenceBaseline = isReferenceBaseline;
286 }
287
288 void setOwner(YGNodeRef owner) { owner_ = owner; }
289
290 void setChildren(const YGVector& children) { children_ = children; }
291
292 // TODO: rvalue override for setChildren
293
294 void setConfig(YGConfigRef config);
295
296 void setDirty(bool isDirty);
297 void setLayoutLastOwnerDirection(YGDirection direction);
298 void setLayoutComputedFlexBasis(const YGFloatOptional computedFlexBasis);
299 void setLayoutComputedFlexBasisGeneration(
300 uint32_t computedFlexBasisGeneration);
301 void setLayoutMeasuredDimension(float measuredDimension, int index);
302 void setLayoutHadOverflow(bool hadOverflow);
303 void setLayoutDimension(float dimension, int index);
304 void setLayoutDirection(YGDirection direction);
305 void setLayoutMargin(float margin, int index);
306 void setLayoutBorder(float border, int index);
307 void setLayoutPadding(float padding, int index);
308 void setLayoutPosition(float position, int index);
309 void setPosition(
310 const YGDirection direction,
311 const float mainSize,
312 const float crossSize,
313 const float ownerWidth);
314 void markDirtyAndPropagateDownwards();
315
316 // Other methods
317 YGValue marginLeadingValue(const YGFlexDirection axis) const;
318 YGValue marginTrailingValue(const YGFlexDirection axis) const;
319 YGValue resolveFlexBasisPtr() const;
320 void resolveDimension();
321 YGDirection resolveDirection(const YGDirection ownerDirection);
322 void clearChildren();
323 /// Replaces the occurrences of oldChild with newChild
324 void replaceChild(YGNodeRef oldChild, YGNodeRef newChild);
325 void replaceChild(YGNodeRef child, uint32_t index);
326 void insertChild(YGNodeRef child, uint32_t index);
327 /// Removes the first occurrence of child
328 bool removeChild(YGNodeRef child);
329 void removeChild(uint32_t index);
330
331 void cloneChildrenIfNeeded(void*);
332 void markDirtyAndPropagate();
333 float resolveFlexGrow() const;
334 float resolveFlexShrink() const;
335 bool isNodeFlexible();
336 void reset();
337};
338
339QT_YOGA_NAMESPACE_END
340

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