362 lines
10 KiB
C++
362 lines
10 KiB
C++
/**
|
|
* Copyright (c) Facebook, Inc. and its 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 <stdio.h>
|
|
#include "YGConfig.h"
|
|
#include "YGLayout.h"
|
|
#include "YGStyle.h"
|
|
#include "Yoga-internal.h"
|
|
|
|
struct YGNode {
|
|
using MeasureWithContextFn =
|
|
YGSize (*)(YGNode*, float, YGMeasureMode, float, YGMeasureMode, void*);
|
|
using BaselineWithContextFn = float (*)(YGNode*, float, float, void*);
|
|
using PrintWithContextFn = void (*)(YGNode*, void*);
|
|
|
|
private:
|
|
void* context_ = nullptr;
|
|
bool hasNewLayout_ : 1;
|
|
bool isReferenceBaseline_ : 1;
|
|
bool isDirty_ : 1;
|
|
YGNodeType nodeType_ : 1;
|
|
bool measureUsesContext_ : 1;
|
|
bool baselineUsesContext_ : 1;
|
|
bool printUsesContext_ : 1;
|
|
union {
|
|
YGMeasureFunc noContext;
|
|
MeasureWithContextFn withContext;
|
|
} measure_ = {nullptr};
|
|
union {
|
|
YGBaselineFunc noContext;
|
|
BaselineWithContextFn withContext;
|
|
} baseline_ = {nullptr};
|
|
union {
|
|
YGPrintFunc noContext;
|
|
PrintWithContextFn withContext;
|
|
} print_ = {nullptr};
|
|
YGDirtiedFunc dirtied_ = nullptr;
|
|
YGStyle style_ = {};
|
|
YGLayout layout_ = {};
|
|
uint32_t lineIndex_ = 0;
|
|
YGNodeRef owner_ = nullptr;
|
|
YGVector children_ = {};
|
|
YGConfigRef config_ = nullptr;
|
|
std::array<YGValue, 2> resolvedDimensions_ = {
|
|
{YGValueUndefined, YGValueUndefined}};
|
|
|
|
YGFloatOptional relativePosition(
|
|
const YGFlexDirection axis,
|
|
const float axisSize) const;
|
|
|
|
void setMeasureFunc(decltype(measure_));
|
|
void setBaselineFunc(decltype(baseline_));
|
|
|
|
// DANGER DANGER DANGER!
|
|
// If the the node assigned to has children, we'd either have to deallocate
|
|
// them (potentially incorrect) or ignore them (danger of leaks). Only ever
|
|
// use this after checking that there are no children.
|
|
// DO NOT CHANGE THE VISIBILITY OF THIS METHOD!
|
|
YGNode& operator=(YGNode&&) = default;
|
|
|
|
public:
|
|
YGNode()
|
|
: hasNewLayout_{true},
|
|
isReferenceBaseline_{false},
|
|
isDirty_{false},
|
|
nodeType_{YGNodeTypeDefault},
|
|
measureUsesContext_{false},
|
|
baselineUsesContext_{false},
|
|
printUsesContext_{false} {}
|
|
~YGNode() = default; // cleanup of owner/children relationships in YGNodeFree
|
|
explicit YGNode(const YGConfigRef newConfig) : config_(newConfig){};
|
|
|
|
YGNode(YGNode&&);
|
|
|
|
// Does not expose true value semantics, as children are not cloned eagerly.
|
|
// Should we remove this?
|
|
YGNode(const YGNode& node) = default;
|
|
|
|
// assignment means potential leaks of existing children, or alternatively
|
|
// freeing unowned memory, double free, or freeing stack memory.
|
|
YGNode& operator=(const YGNode&) = delete;
|
|
|
|
// Getters
|
|
void* getContext() const {
|
|
return context_;
|
|
}
|
|
|
|
void print(void*);
|
|
|
|
bool getHasNewLayout() const {
|
|
return hasNewLayout_;
|
|
}
|
|
|
|
YGNodeType getNodeType() const {
|
|
return nodeType_;
|
|
}
|
|
|
|
bool hasMeasureFunc() const noexcept {
|
|
return measure_.noContext != nullptr;
|
|
}
|
|
|
|
YGSize measure(float, YGMeasureMode, float, YGMeasureMode, void*);
|
|
|
|
bool hasBaselineFunc() const noexcept {
|
|
return baseline_.noContext != nullptr;
|
|
}
|
|
|
|
float baseline(float width, float height, void* layoutContext);
|
|
|
|
YGDirtiedFunc getDirtied() const {
|
|
return dirtied_;
|
|
}
|
|
|
|
// For Performance reasons passing as reference.
|
|
YGStyle& getStyle() {
|
|
return style_;
|
|
}
|
|
|
|
const YGStyle& getStyle() const {
|
|
return style_;
|
|
}
|
|
|
|
// For Performance reasons passing as reference.
|
|
YGLayout& getLayout() {
|
|
return layout_;
|
|
}
|
|
|
|
const YGLayout& getLayout() const {
|
|
return layout_;
|
|
}
|
|
|
|
uint32_t getLineIndex() const {
|
|
return lineIndex_;
|
|
}
|
|
|
|
bool isReferenceBaseline() {
|
|
return isReferenceBaseline_;
|
|
}
|
|
|
|
// 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
|
|
// of the YGNode when a YGNode only belongs to one YogaTree or nullptr when
|
|
// the YGNode is shared between two or more YogaTrees.
|
|
YGNodeRef getOwner() const {
|
|
return owner_;
|
|
}
|
|
|
|
// Deprecated, use getOwner() instead.
|
|
YGNodeRef getParent() const {
|
|
return getOwner();
|
|
}
|
|
|
|
const YGVector& getChildren() const {
|
|
return children_;
|
|
}
|
|
|
|
// Applies a callback to all children, after cloning them if they are not
|
|
// owned.
|
|
template <typename T>
|
|
void iterChildrenAfterCloningIfNeeded(T callback, void* cloneContext) {
|
|
int i = 0;
|
|
for (YGNodeRef& child : children_) {
|
|
if (child->getOwner() != this) {
|
|
child = config_->cloneNode(child, this, i, cloneContext);
|
|
child->setOwner(this);
|
|
}
|
|
i += 1;
|
|
|
|
callback(child, cloneContext);
|
|
}
|
|
}
|
|
|
|
YGNodeRef getChild(uint32_t index) const {
|
|
return children_.at(index);
|
|
}
|
|
|
|
YGConfigRef getConfig() const {
|
|
return config_;
|
|
}
|
|
|
|
bool isDirty() const {
|
|
return isDirty_;
|
|
}
|
|
|
|
std::array<YGValue, 2> getResolvedDimensions() const {
|
|
return resolvedDimensions_;
|
|
}
|
|
|
|
YGValue getResolvedDimension(int index) const {
|
|
return resolvedDimensions_[index];
|
|
}
|
|
|
|
// Methods related to positions, margin, padding and border
|
|
YGFloatOptional getLeadingPosition(
|
|
const YGFlexDirection axis,
|
|
const float axisSize) const;
|
|
bool isLeadingPositionDefined(const YGFlexDirection axis) const;
|
|
bool isTrailingPosDefined(const YGFlexDirection axis) const;
|
|
YGFloatOptional getTrailingPosition(
|
|
const YGFlexDirection axis,
|
|
const float axisSize) const;
|
|
YGFloatOptional getLeadingMargin(
|
|
const YGFlexDirection axis,
|
|
const float widthSize) const;
|
|
YGFloatOptional getTrailingMargin(
|
|
const YGFlexDirection axis,
|
|
const float widthSize) const;
|
|
float getLeadingBorder(const YGFlexDirection flexDirection) const;
|
|
float getTrailingBorder(const YGFlexDirection flexDirection) const;
|
|
YGFloatOptional getLeadingPadding(
|
|
const YGFlexDirection axis,
|
|
const float widthSize) const;
|
|
YGFloatOptional getTrailingPadding(
|
|
const YGFlexDirection axis,
|
|
const float widthSize) const;
|
|
YGFloatOptional getLeadingPaddingAndBorder(
|
|
const YGFlexDirection axis,
|
|
const float widthSize) const;
|
|
YGFloatOptional getTrailingPaddingAndBorder(
|
|
const YGFlexDirection axis,
|
|
const float widthSize) const;
|
|
YGFloatOptional getMarginForAxis(
|
|
const YGFlexDirection axis,
|
|
const float widthSize) const;
|
|
// Setters
|
|
|
|
void setContext(void* context) {
|
|
context_ = context;
|
|
}
|
|
|
|
void setPrintFunc(YGPrintFunc printFunc) {
|
|
print_.noContext = printFunc;
|
|
printUsesContext_ = false;
|
|
}
|
|
void setPrintFunc(PrintWithContextFn printFunc) {
|
|
print_.withContext = printFunc;
|
|
printUsesContext_ = true;
|
|
}
|
|
void setPrintFunc(std::nullptr_t) {
|
|
setPrintFunc(YGPrintFunc{nullptr});
|
|
}
|
|
|
|
void setHasNewLayout(bool hasNewLayout) {
|
|
hasNewLayout_ = hasNewLayout;
|
|
}
|
|
|
|
void setNodeType(YGNodeType nodeType) {
|
|
nodeType_ = nodeType;
|
|
}
|
|
|
|
void setStyleFlexDirection(YGFlexDirection direction) {
|
|
style_.flexDirection = direction;
|
|
}
|
|
|
|
void setStyleAlignContent(YGAlign alignContent) {
|
|
style_.alignContent = alignContent;
|
|
}
|
|
|
|
void setMeasureFunc(YGMeasureFunc measureFunc);
|
|
void setMeasureFunc(MeasureWithContextFn);
|
|
void setMeasureFunc(std::nullptr_t) {
|
|
return setMeasureFunc(YGMeasureFunc{nullptr});
|
|
}
|
|
|
|
void setBaselineFunc(YGBaselineFunc baseLineFunc) {
|
|
baselineUsesContext_ = false;
|
|
baseline_.noContext = baseLineFunc;
|
|
}
|
|
void setBaselineFunc(BaselineWithContextFn baseLineFunc) {
|
|
baselineUsesContext_ = true;
|
|
baseline_.withContext = baseLineFunc;
|
|
}
|
|
void setBaselineFunc(std::nullptr_t) {
|
|
return setBaselineFunc(YGBaselineFunc{nullptr});
|
|
}
|
|
|
|
void setDirtiedFunc(YGDirtiedFunc dirtiedFunc) {
|
|
dirtied_ = dirtiedFunc;
|
|
}
|
|
|
|
void setStyle(const YGStyle& style) {
|
|
style_ = style;
|
|
}
|
|
|
|
void setLayout(const YGLayout& layout) {
|
|
layout_ = layout;
|
|
}
|
|
|
|
void setLineIndex(uint32_t lineIndex) {
|
|
lineIndex_ = lineIndex;
|
|
}
|
|
|
|
void setIsReferenceBaseline(bool isReferenceBaseline) {
|
|
isReferenceBaseline_ = isReferenceBaseline;
|
|
}
|
|
|
|
void setOwner(YGNodeRef owner) {
|
|
owner_ = owner;
|
|
}
|
|
|
|
void setChildren(const YGVector& children) {
|
|
children_ = children;
|
|
}
|
|
|
|
// TODO: rvalue override for setChildren
|
|
|
|
void setConfig(YGConfigRef config) {
|
|
config_ = config;
|
|
}
|
|
|
|
void setDirty(bool isDirty);
|
|
void setLayoutLastOwnerDirection(YGDirection direction);
|
|
void setLayoutComputedFlexBasis(const YGFloatOptional computedFlexBasis);
|
|
void setLayoutComputedFlexBasisGeneration(
|
|
uint32_t computedFlexBasisGeneration);
|
|
void setLayoutMeasuredDimension(float measuredDimension, int index);
|
|
void setLayoutHadOverflow(bool hadOverflow);
|
|
void setLayoutDimension(float dimension, int index);
|
|
void setLayoutDirection(YGDirection direction);
|
|
void setLayoutMargin(float margin, int index);
|
|
void setLayoutBorder(float border, int index);
|
|
void setLayoutPadding(float padding, int index);
|
|
void setLayoutPosition(float position, int index);
|
|
void setPosition(
|
|
const YGDirection direction,
|
|
const float mainSize,
|
|
const float crossSize,
|
|
const float ownerWidth);
|
|
void setAndPropogateUseLegacyFlag(bool useLegacyFlag);
|
|
void setLayoutDoesLegacyFlagAffectsLayout(bool doesLegacyFlagAffectsLayout);
|
|
void setLayoutDidUseLegacyFlag(bool didUseLegacyFlag);
|
|
void markDirtyAndPropogateDownwards();
|
|
|
|
// Other methods
|
|
YGValue marginLeadingValue(const YGFlexDirection axis) const;
|
|
YGValue marginTrailingValue(const YGFlexDirection axis) const;
|
|
YGValue resolveFlexBasisPtr() const;
|
|
void resolveDimension();
|
|
YGDirection resolveDirection(const YGDirection ownerDirection);
|
|
void clearChildren();
|
|
/// Replaces the occurrences of oldChild with newChild
|
|
void replaceChild(YGNodeRef oldChild, YGNodeRef newChild);
|
|
void replaceChild(YGNodeRef child, uint32_t index);
|
|
void insertChild(YGNodeRef child, uint32_t index);
|
|
/// Removes the first occurrence of child
|
|
bool removeChild(YGNodeRef child);
|
|
void removeChild(uint32_t index);
|
|
|
|
void cloneChildrenIfNeeded(void*);
|
|
void markDirtyAndPropogate();
|
|
float resolveFlexGrow();
|
|
float resolveFlexShrink();
|
|
bool isNodeFlexible();
|
|
bool didUseLegacyFlag();
|
|
bool isLayoutTreeEqualToNode(const YGNode& node) const;
|
|
void reset();
|
|
};
|