Revert D48712710: C++ Cleanup 3/N: Reorganize YGNode
Differential Revision: D48712710 Original commit changeset: d28eae38469a Original Phabricator Diff: D48712710 fbshipit-source-id: 7a10b071edcf045ce98bbf8f9deca0d0e2e80a14
This commit is contained in:
committed by
Facebook GitHub Bot
parent
6ca56e87ce
commit
ea7f61a3db
@@ -1,44 +0,0 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include <yoga/node/LayoutResults.h>
|
||||
#include <yoga/Utils.h>
|
||||
|
||||
namespace facebook::yoga {
|
||||
|
||||
bool LayoutResults::operator==(LayoutResults layout) const {
|
||||
bool isEqual = YGFloatArrayEqual(position, layout.position) &&
|
||||
YGFloatArrayEqual(dimensions, layout.dimensions) &&
|
||||
YGFloatArrayEqual(margin, layout.margin) &&
|
||||
YGFloatArrayEqual(border, layout.border) &&
|
||||
YGFloatArrayEqual(padding, layout.padding) &&
|
||||
direction() == layout.direction() &&
|
||||
hadOverflow() == layout.hadOverflow() &&
|
||||
lastOwnerDirection == layout.lastOwnerDirection &&
|
||||
nextCachedMeasurementsIndex == layout.nextCachedMeasurementsIndex &&
|
||||
cachedLayout == layout.cachedLayout &&
|
||||
computedFlexBasis == layout.computedFlexBasis;
|
||||
|
||||
for (uint32_t i = 0; i < YG_MAX_CACHED_RESULT_COUNT && isEqual; ++i) {
|
||||
isEqual = isEqual && cachedMeasurements[i] == layout.cachedMeasurements[i];
|
||||
}
|
||||
|
||||
if (!yoga::isUndefined(measuredDimensions[0]) ||
|
||||
!yoga::isUndefined(layout.measuredDimensions[0])) {
|
||||
isEqual =
|
||||
isEqual && (measuredDimensions[0] == layout.measuredDimensions[0]);
|
||||
}
|
||||
if (!yoga::isUndefined(measuredDimensions[1]) ||
|
||||
!yoga::isUndefined(layout.measuredDimensions[1])) {
|
||||
isEqual =
|
||||
isEqual && (measuredDimensions[1] == layout.measuredDimensions[1]);
|
||||
}
|
||||
|
||||
return isEqual;
|
||||
}
|
||||
|
||||
} // namespace facebook::yoga
|
@@ -1,67 +0,0 @@
|
||||
/*
|
||||
* 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 <yoga/BitUtils.h>
|
||||
#include <yoga/YGFloatOptional.h>
|
||||
#include <yoga/Yoga-internal.h>
|
||||
|
||||
namespace facebook::yoga {
|
||||
|
||||
struct LayoutResults {
|
||||
std::array<float, 4> position = {};
|
||||
std::array<float, 2> dimensions = {{YGUndefined, YGUndefined}};
|
||||
std::array<float, 4> margin = {};
|
||||
std::array<float, 4> border = {};
|
||||
std::array<float, 4> padding = {};
|
||||
|
||||
private:
|
||||
static constexpr size_t directionOffset = 0;
|
||||
static constexpr size_t hadOverflowOffset =
|
||||
directionOffset + facebook::yoga::detail::bitWidthFn<YGDirection>();
|
||||
uint8_t flags = 0;
|
||||
|
||||
public:
|
||||
uint32_t computedFlexBasisGeneration = 0;
|
||||
YGFloatOptional computedFlexBasis = {};
|
||||
|
||||
// Instead of recomputing the entire layout every single time, we cache some
|
||||
// information to break early when nothing changed
|
||||
uint32_t generationCount = 0;
|
||||
YGDirection lastOwnerDirection = YGDirectionInherit;
|
||||
|
||||
uint32_t nextCachedMeasurementsIndex = 0;
|
||||
std::array<YGCachedMeasurement, YG_MAX_CACHED_RESULT_COUNT>
|
||||
cachedMeasurements = {};
|
||||
std::array<float, 2> measuredDimensions = {{YGUndefined, YGUndefined}};
|
||||
|
||||
YGCachedMeasurement cachedLayout = YGCachedMeasurement();
|
||||
|
||||
YGDirection direction() const {
|
||||
return facebook::yoga::detail::getEnumData<YGDirection>(
|
||||
flags, directionOffset);
|
||||
}
|
||||
|
||||
void setDirection(YGDirection direction) {
|
||||
facebook::yoga::detail::setEnumData<YGDirection>(
|
||||
flags, directionOffset, direction);
|
||||
}
|
||||
|
||||
bool hadOverflow() const {
|
||||
return facebook::yoga::detail::getBooleanData(flags, hadOverflowOffset);
|
||||
}
|
||||
void setHadOverflow(bool hadOverflow) {
|
||||
facebook::yoga::detail::setBooleanData(
|
||||
flags, hadOverflowOffset, hadOverflow);
|
||||
}
|
||||
|
||||
bool operator==(LayoutResults layout) const;
|
||||
bool operator!=(LayoutResults layout) const { return !(*this == layout); }
|
||||
};
|
||||
|
||||
} // namespace facebook::yoga
|
@@ -1,583 +0,0 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include <yoga/node/Node.h>
|
||||
#include <algorithm>
|
||||
#include <iostream>
|
||||
#include <yoga/Utils.h>
|
||||
|
||||
namespace facebook::yoga {
|
||||
|
||||
Node::Node(yoga::Config* config) : config_{config} {
|
||||
YGAssert(config != nullptr, "Attempting to construct Node with null config");
|
||||
|
||||
flags_.hasNewLayout = true;
|
||||
if (config->useWebDefaults()) {
|
||||
useWebDefaults();
|
||||
}
|
||||
}
|
||||
|
||||
Node::Node(Node&& node) {
|
||||
context_ = node.context_;
|
||||
flags_ = node.flags_;
|
||||
measure_ = node.measure_;
|
||||
baseline_ = node.baseline_;
|
||||
print_ = node.print_;
|
||||
dirtied_ = node.dirtied_;
|
||||
style_ = node.style_;
|
||||
layout_ = node.layout_;
|
||||
lineIndex_ = node.lineIndex_;
|
||||
owner_ = node.owner_;
|
||||
children_ = std::move(node.children_);
|
||||
config_ = node.config_;
|
||||
resolvedDimensions_ = node.resolvedDimensions_;
|
||||
for (auto c : children_) {
|
||||
c->setOwner(this);
|
||||
}
|
||||
}
|
||||
|
||||
void Node::print(void* printContext) {
|
||||
if (print_.noContext != nullptr) {
|
||||
if (flags_.printUsesContext) {
|
||||
print_.withContext(this, printContext);
|
||||
} else {
|
||||
print_.noContext(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
CompactValue Node::computeEdgeValueForRow(
|
||||
const Style::Edges& edges,
|
||||
YGEdge rowEdge,
|
||||
YGEdge edge,
|
||||
CompactValue defaultValue) {
|
||||
if (!edges[rowEdge].isUndefined()) {
|
||||
return edges[rowEdge];
|
||||
} else if (!edges[edge].isUndefined()) {
|
||||
return edges[edge];
|
||||
} else if (!edges[YGEdgeHorizontal].isUndefined()) {
|
||||
return edges[YGEdgeHorizontal];
|
||||
} else if (!edges[YGEdgeAll].isUndefined()) {
|
||||
return edges[YGEdgeAll];
|
||||
} else {
|
||||
return defaultValue;
|
||||
}
|
||||
}
|
||||
|
||||
CompactValue Node::computeEdgeValueForColumn(
|
||||
const Style::Edges& edges,
|
||||
YGEdge edge,
|
||||
CompactValue defaultValue) {
|
||||
if (!edges[edge].isUndefined()) {
|
||||
return edges[edge];
|
||||
} else if (!edges[YGEdgeVertical].isUndefined()) {
|
||||
return edges[YGEdgeVertical];
|
||||
} else if (!edges[YGEdgeAll].isUndefined()) {
|
||||
return edges[YGEdgeAll];
|
||||
} else {
|
||||
return defaultValue;
|
||||
}
|
||||
}
|
||||
|
||||
CompactValue Node::computeRowGap(
|
||||
const Style::Gutters& gutters,
|
||||
CompactValue defaultValue) {
|
||||
if (!gutters[YGGutterRow].isUndefined()) {
|
||||
return gutters[YGGutterRow];
|
||||
} else if (!gutters[YGGutterAll].isUndefined()) {
|
||||
return gutters[YGGutterAll];
|
||||
} else {
|
||||
return defaultValue;
|
||||
}
|
||||
}
|
||||
|
||||
CompactValue Node::computeColumnGap(
|
||||
const Style::Gutters& gutters,
|
||||
CompactValue defaultValue) {
|
||||
if (!gutters[YGGutterColumn].isUndefined()) {
|
||||
return gutters[YGGutterColumn];
|
||||
} else if (!gutters[YGGutterAll].isUndefined()) {
|
||||
return gutters[YGGutterAll];
|
||||
} else {
|
||||
return defaultValue;
|
||||
}
|
||||
}
|
||||
|
||||
YGFloatOptional Node::getLeadingPosition(
|
||||
const YGFlexDirection axis,
|
||||
const float axisSize) const {
|
||||
auto leadingPosition = YGFlexDirectionIsRow(axis)
|
||||
? computeEdgeValueForRow(
|
||||
style_.position(),
|
||||
YGEdgeStart,
|
||||
leading[axis],
|
||||
CompactValue::ofZero())
|
||||
: computeEdgeValueForColumn(
|
||||
style_.position(), leading[axis], CompactValue::ofZero());
|
||||
return YGResolveValue(leadingPosition, axisSize);
|
||||
}
|
||||
|
||||
YGFloatOptional Node::getTrailingPosition(
|
||||
const YGFlexDirection axis,
|
||||
const float axisSize) const {
|
||||
auto trailingPosition = YGFlexDirectionIsRow(axis)
|
||||
? computeEdgeValueForRow(
|
||||
style_.position(),
|
||||
YGEdgeEnd,
|
||||
trailing[axis],
|
||||
CompactValue::ofZero())
|
||||
: computeEdgeValueForColumn(
|
||||
style_.position(), trailing[axis], CompactValue::ofZero());
|
||||
return YGResolveValue(trailingPosition, axisSize);
|
||||
}
|
||||
|
||||
bool Node::isLeadingPositionDefined(const YGFlexDirection axis) const {
|
||||
auto leadingPosition = YGFlexDirectionIsRow(axis)
|
||||
? computeEdgeValueForRow(
|
||||
style_.position(),
|
||||
YGEdgeStart,
|
||||
leading[axis],
|
||||
CompactValue::ofUndefined())
|
||||
: computeEdgeValueForColumn(
|
||||
style_.position(), leading[axis], CompactValue::ofUndefined());
|
||||
return !leadingPosition.isUndefined();
|
||||
}
|
||||
|
||||
bool Node::isTrailingPosDefined(const YGFlexDirection axis) const {
|
||||
auto trailingPosition = YGFlexDirectionIsRow(axis)
|
||||
? computeEdgeValueForRow(
|
||||
style_.position(),
|
||||
YGEdgeEnd,
|
||||
trailing[axis],
|
||||
CompactValue::ofUndefined())
|
||||
: computeEdgeValueForColumn(
|
||||
style_.position(), trailing[axis], CompactValue::ofUndefined());
|
||||
return !trailingPosition.isUndefined();
|
||||
}
|
||||
|
||||
YGFloatOptional Node::getLeadingMargin(
|
||||
const YGFlexDirection axis,
|
||||
const float widthSize) const {
|
||||
auto leadingMargin = YGFlexDirectionIsRow(axis)
|
||||
? computeEdgeValueForRow(
|
||||
style_.margin(), YGEdgeStart, leading[axis], CompactValue::ofZero())
|
||||
: computeEdgeValueForColumn(
|
||||
style_.margin(), leading[axis], CompactValue::ofZero());
|
||||
return YGResolveValueMargin(leadingMargin, widthSize);
|
||||
}
|
||||
|
||||
YGFloatOptional Node::getTrailingMargin(
|
||||
const YGFlexDirection axis,
|
||||
const float widthSize) const {
|
||||
auto trailingMargin = YGFlexDirectionIsRow(axis)
|
||||
? computeEdgeValueForRow(
|
||||
style_.margin(), YGEdgeEnd, trailing[axis], CompactValue::ofZero())
|
||||
: computeEdgeValueForColumn(
|
||||
style_.margin(), trailing[axis], CompactValue::ofZero());
|
||||
return YGResolveValueMargin(trailingMargin, widthSize);
|
||||
}
|
||||
|
||||
YGFloatOptional Node::getMarginForAxis(
|
||||
const YGFlexDirection axis,
|
||||
const float widthSize) const {
|
||||
return getLeadingMargin(axis, widthSize) + getTrailingMargin(axis, widthSize);
|
||||
}
|
||||
|
||||
YGFloatOptional Node::getGapForAxis(
|
||||
const YGFlexDirection axis,
|
||||
const float widthSize) const {
|
||||
auto gap = YGFlexDirectionIsRow(axis)
|
||||
? computeColumnGap(style_.gap(), CompactValue::ofZero())
|
||||
: computeRowGap(style_.gap(), CompactValue::ofZero());
|
||||
return YGResolveValue(gap, widthSize);
|
||||
}
|
||||
|
||||
YGSize Node::measure(
|
||||
float width,
|
||||
YGMeasureMode widthMode,
|
||||
float height,
|
||||
YGMeasureMode heightMode,
|
||||
void* layoutContext) {
|
||||
return flags_.measureUsesContext
|
||||
? measure_.withContext(
|
||||
this, width, widthMode, height, heightMode, layoutContext)
|
||||
: measure_.noContext(this, width, widthMode, height, heightMode);
|
||||
}
|
||||
|
||||
float Node::baseline(float width, float height, void* layoutContext) {
|
||||
return flags_.baselineUsesContext
|
||||
? baseline_.withContext(this, width, height, layoutContext)
|
||||
: baseline_.noContext(this, width, height);
|
||||
}
|
||||
|
||||
// Setters
|
||||
|
||||
void Node::setMeasureFunc(decltype(Node::measure_) measureFunc) {
|
||||
if (measureFunc.noContext == nullptr) {
|
||||
// TODO: t18095186 Move nodeType to opt-in function and mark appropriate
|
||||
// places in Litho
|
||||
setNodeType(YGNodeTypeDefault);
|
||||
} else {
|
||||
YGAssertWithNode(
|
||||
this,
|
||||
children_.size() == 0,
|
||||
"Cannot set measure function: Nodes with measure functions cannot have "
|
||||
"children.");
|
||||
// TODO: t18095186 Move nodeType to opt-in function and mark appropriate
|
||||
// places in Litho
|
||||
setNodeType(YGNodeTypeText);
|
||||
}
|
||||
|
||||
measure_ = measureFunc;
|
||||
}
|
||||
|
||||
void Node::setMeasureFunc(YGMeasureFunc measureFunc) {
|
||||
flags_.measureUsesContext = false;
|
||||
decltype(Node::measure_) m;
|
||||
m.noContext = measureFunc;
|
||||
setMeasureFunc(m);
|
||||
}
|
||||
|
||||
YOGA_EXPORT void Node::setMeasureFunc(MeasureWithContextFn measureFunc) {
|
||||
flags_.measureUsesContext = true;
|
||||
decltype(Node::measure_) m;
|
||||
m.withContext = measureFunc;
|
||||
setMeasureFunc(m);
|
||||
}
|
||||
|
||||
void Node::replaceChild(Node* child, uint32_t index) {
|
||||
children_[index] = child;
|
||||
}
|
||||
|
||||
void Node::replaceChild(Node* oldChild, Node* newChild) {
|
||||
std::replace(children_.begin(), children_.end(), oldChild, newChild);
|
||||
}
|
||||
|
||||
void Node::insertChild(Node* child, uint32_t index) {
|
||||
children_.insert(children_.begin() + index, child);
|
||||
}
|
||||
|
||||
void Node::setConfig(yoga::Config* config) {
|
||||
YGAssert(config != nullptr, "Attempting to set a null config on a Node");
|
||||
YGAssertWithConfig(
|
||||
config,
|
||||
config->useWebDefaults() == config_->useWebDefaults(),
|
||||
"UseWebDefaults may not be changed after constructing a Node");
|
||||
|
||||
if (yoga::configUpdateInvalidatesLayout(config_, config)) {
|
||||
markDirtyAndPropagate();
|
||||
}
|
||||
|
||||
config_ = config;
|
||||
}
|
||||
|
||||
void Node::setDirty(bool isDirty) {
|
||||
if (isDirty == flags_.isDirty) {
|
||||
return;
|
||||
}
|
||||
flags_.isDirty = isDirty;
|
||||
if (isDirty && dirtied_) {
|
||||
dirtied_(this);
|
||||
}
|
||||
}
|
||||
|
||||
bool Node::removeChild(Node* child) {
|
||||
std::vector<Node*>::iterator p =
|
||||
std::find(children_.begin(), children_.end(), child);
|
||||
if (p != children_.end()) {
|
||||
children_.erase(p);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void Node::removeChild(uint32_t index) {
|
||||
children_.erase(children_.begin() + index);
|
||||
}
|
||||
|
||||
void Node::setLayoutDirection(YGDirection direction) {
|
||||
layout_.setDirection(direction);
|
||||
}
|
||||
|
||||
void Node::setLayoutMargin(float margin, int index) {
|
||||
layout_.margin[index] = margin;
|
||||
}
|
||||
|
||||
void Node::setLayoutBorder(float border, int index) {
|
||||
layout_.border[index] = border;
|
||||
}
|
||||
|
||||
void Node::setLayoutPadding(float padding, int index) {
|
||||
layout_.padding[index] = padding;
|
||||
}
|
||||
|
||||
void Node::setLayoutLastOwnerDirection(YGDirection direction) {
|
||||
layout_.lastOwnerDirection = direction;
|
||||
}
|
||||
|
||||
void Node::setLayoutComputedFlexBasis(const YGFloatOptional computedFlexBasis) {
|
||||
layout_.computedFlexBasis = computedFlexBasis;
|
||||
}
|
||||
|
||||
void Node::setLayoutPosition(float position, int index) {
|
||||
layout_.position[index] = position;
|
||||
}
|
||||
|
||||
void Node::setLayoutComputedFlexBasisGeneration(
|
||||
uint32_t computedFlexBasisGeneration) {
|
||||
layout_.computedFlexBasisGeneration = computedFlexBasisGeneration;
|
||||
}
|
||||
|
||||
void Node::setLayoutMeasuredDimension(float measuredDimension, int index) {
|
||||
layout_.measuredDimensions[index] = measuredDimension;
|
||||
}
|
||||
|
||||
void Node::setLayoutHadOverflow(bool hadOverflow) {
|
||||
layout_.setHadOverflow(hadOverflow);
|
||||
}
|
||||
|
||||
void Node::setLayoutDimension(float dimension, int index) {
|
||||
layout_.dimensions[index] = dimension;
|
||||
}
|
||||
|
||||
// If both left and right are defined, then use left. Otherwise return +left or
|
||||
// -right depending on which is defined.
|
||||
YGFloatOptional Node::relativePosition(
|
||||
const YGFlexDirection axis,
|
||||
const float axisSize) const {
|
||||
if (isLeadingPositionDefined(axis)) {
|
||||
return getLeadingPosition(axis, axisSize);
|
||||
}
|
||||
|
||||
YGFloatOptional trailingPosition = getTrailingPosition(axis, axisSize);
|
||||
if (!trailingPosition.isUndefined()) {
|
||||
trailingPosition = YGFloatOptional{-1 * trailingPosition.unwrap()};
|
||||
}
|
||||
return trailingPosition;
|
||||
}
|
||||
|
||||
void Node::setPosition(
|
||||
const YGDirection direction,
|
||||
const float mainSize,
|
||||
const float crossSize,
|
||||
const float ownerWidth) {
|
||||
/* Root nodes should be always layouted as LTR, so we don't return negative
|
||||
* values. */
|
||||
const YGDirection directionRespectingRoot =
|
||||
owner_ != nullptr ? direction : YGDirectionLTR;
|
||||
const YGFlexDirection mainAxis =
|
||||
YGResolveFlexDirection(style_.flexDirection(), directionRespectingRoot);
|
||||
const YGFlexDirection crossAxis =
|
||||
YGFlexDirectionCross(mainAxis, directionRespectingRoot);
|
||||
|
||||
// Here we should check for `YGPositionTypeStatic` and in this case zero inset
|
||||
// properties (left, right, top, bottom, begin, end).
|
||||
// https://www.w3.org/TR/css-position-3/#valdef-position-static
|
||||
const YGFloatOptional relativePositionMain =
|
||||
relativePosition(mainAxis, mainSize);
|
||||
const YGFloatOptional relativePositionCross =
|
||||
relativePosition(crossAxis, crossSize);
|
||||
|
||||
setLayoutPosition(
|
||||
(getLeadingMargin(mainAxis, ownerWidth) + relativePositionMain).unwrap(),
|
||||
leading[mainAxis]);
|
||||
setLayoutPosition(
|
||||
(getTrailingMargin(mainAxis, ownerWidth) + relativePositionMain).unwrap(),
|
||||
trailing[mainAxis]);
|
||||
setLayoutPosition(
|
||||
(getLeadingMargin(crossAxis, ownerWidth) + relativePositionCross)
|
||||
.unwrap(),
|
||||
leading[crossAxis]);
|
||||
setLayoutPosition(
|
||||
(getTrailingMargin(crossAxis, ownerWidth) + relativePositionCross)
|
||||
.unwrap(),
|
||||
trailing[crossAxis]);
|
||||
}
|
||||
|
||||
YGValue Node::marginLeadingValue(const YGFlexDirection axis) const {
|
||||
if (YGFlexDirectionIsRow(axis) &&
|
||||
!style_.margin()[YGEdgeStart].isUndefined()) {
|
||||
return style_.margin()[YGEdgeStart];
|
||||
} else {
|
||||
return style_.margin()[leading[axis]];
|
||||
}
|
||||
}
|
||||
|
||||
YGValue Node::marginTrailingValue(const YGFlexDirection axis) const {
|
||||
if (YGFlexDirectionIsRow(axis) && !style_.margin()[YGEdgeEnd].isUndefined()) {
|
||||
return style_.margin()[YGEdgeEnd];
|
||||
} else {
|
||||
return style_.margin()[trailing[axis]];
|
||||
}
|
||||
}
|
||||
|
||||
YGValue Node::resolveFlexBasisPtr() const {
|
||||
YGValue flexBasis = style_.flexBasis();
|
||||
if (flexBasis.unit != YGUnitAuto && flexBasis.unit != YGUnitUndefined) {
|
||||
return flexBasis;
|
||||
}
|
||||
if (!style_.flex().isUndefined() && style_.flex().unwrap() > 0.0f) {
|
||||
return config_->useWebDefaults() ? YGValueAuto : YGValueZero;
|
||||
}
|
||||
return YGValueAuto;
|
||||
}
|
||||
|
||||
void Node::resolveDimension() {
|
||||
using namespace yoga;
|
||||
const Style& style = getStyle();
|
||||
for (auto dim : {YGDimensionWidth, YGDimensionHeight}) {
|
||||
if (!style.maxDimensions()[dim].isUndefined() &&
|
||||
YGValueEqual(style.maxDimensions()[dim], style.minDimensions()[dim])) {
|
||||
resolvedDimensions_[dim] = style.maxDimensions()[dim];
|
||||
} else {
|
||||
resolvedDimensions_[dim] = style.dimensions()[dim];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
YGDirection Node::resolveDirection(const YGDirection ownerDirection) {
|
||||
if (style_.direction() == YGDirectionInherit) {
|
||||
return ownerDirection > YGDirectionInherit ? ownerDirection
|
||||
: YGDirectionLTR;
|
||||
} else {
|
||||
return style_.direction();
|
||||
}
|
||||
}
|
||||
|
||||
YOGA_EXPORT void Node::clearChildren() {
|
||||
children_.clear();
|
||||
children_.shrink_to_fit();
|
||||
}
|
||||
|
||||
// Other Methods
|
||||
|
||||
void Node::cloneChildrenIfNeeded(void* cloneContext) {
|
||||
iterChildrenAfterCloningIfNeeded([](Node*, void*) {}, cloneContext);
|
||||
}
|
||||
|
||||
void Node::markDirtyAndPropagate() {
|
||||
if (!flags_.isDirty) {
|
||||
setDirty(true);
|
||||
setLayoutComputedFlexBasis(YGFloatOptional());
|
||||
if (owner_) {
|
||||
owner_->markDirtyAndPropagate();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Node::markDirtyAndPropagateDownwards() {
|
||||
flags_.isDirty = true;
|
||||
for_each(children_.begin(), children_.end(), [](Node* childNode) {
|
||||
childNode->markDirtyAndPropagateDownwards();
|
||||
});
|
||||
}
|
||||
|
||||
float Node::resolveFlexGrow() const {
|
||||
// Root nodes flexGrow should always be 0
|
||||
if (owner_ == nullptr) {
|
||||
return 0.0;
|
||||
}
|
||||
if (!style_.flexGrow().isUndefined()) {
|
||||
return style_.flexGrow().unwrap();
|
||||
}
|
||||
if (!style_.flex().isUndefined() && style_.flex().unwrap() > 0.0f) {
|
||||
return style_.flex().unwrap();
|
||||
}
|
||||
return kDefaultFlexGrow;
|
||||
}
|
||||
|
||||
float Node::resolveFlexShrink() const {
|
||||
if (owner_ == nullptr) {
|
||||
return 0.0;
|
||||
}
|
||||
if (!style_.flexShrink().isUndefined()) {
|
||||
return style_.flexShrink().unwrap();
|
||||
}
|
||||
if (!config_->useWebDefaults() && !style_.flex().isUndefined() &&
|
||||
style_.flex().unwrap() < 0.0f) {
|
||||
return -style_.flex().unwrap();
|
||||
}
|
||||
return config_->useWebDefaults() ? kWebDefaultFlexShrink : kDefaultFlexShrink;
|
||||
}
|
||||
|
||||
bool Node::isNodeFlexible() {
|
||||
return (
|
||||
(style_.positionType() != YGPositionTypeAbsolute) &&
|
||||
(resolveFlexGrow() != 0 || resolveFlexShrink() != 0));
|
||||
}
|
||||
|
||||
float Node::getLeadingBorder(const YGFlexDirection axis) const {
|
||||
YGValue leadingBorder = YGFlexDirectionIsRow(axis)
|
||||
? computeEdgeValueForRow(
|
||||
style_.border(), YGEdgeStart, leading[axis], CompactValue::ofZero())
|
||||
: computeEdgeValueForColumn(
|
||||
style_.border(), leading[axis], CompactValue::ofZero());
|
||||
return fmaxf(leadingBorder.value, 0.0f);
|
||||
}
|
||||
|
||||
float Node::getTrailingBorder(const YGFlexDirection axis) const {
|
||||
YGValue trailingBorder = YGFlexDirectionIsRow(axis)
|
||||
? computeEdgeValueForRow(
|
||||
style_.border(), YGEdgeEnd, trailing[axis], CompactValue::ofZero())
|
||||
: computeEdgeValueForColumn(
|
||||
style_.border(), trailing[axis], CompactValue::ofZero());
|
||||
return fmaxf(trailingBorder.value, 0.0f);
|
||||
}
|
||||
|
||||
YGFloatOptional Node::getLeadingPadding(
|
||||
const YGFlexDirection axis,
|
||||
const float widthSize) const {
|
||||
auto leadingPadding = YGFlexDirectionIsRow(axis)
|
||||
? computeEdgeValueForRow(
|
||||
style_.padding(),
|
||||
YGEdgeStart,
|
||||
leading[axis],
|
||||
CompactValue::ofZero())
|
||||
: computeEdgeValueForColumn(
|
||||
style_.padding(), leading[axis], CompactValue::ofZero());
|
||||
return YGFloatOptionalMax(
|
||||
YGResolveValue(leadingPadding, widthSize), YGFloatOptional(0.0f));
|
||||
}
|
||||
|
||||
YGFloatOptional Node::getTrailingPadding(
|
||||
const YGFlexDirection axis,
|
||||
const float widthSize) const {
|
||||
auto trailingPadding = YGFlexDirectionIsRow(axis)
|
||||
? computeEdgeValueForRow(
|
||||
style_.padding(), YGEdgeEnd, trailing[axis], CompactValue::ofZero())
|
||||
: computeEdgeValueForColumn(
|
||||
style_.padding(), trailing[axis], CompactValue::ofZero());
|
||||
return YGFloatOptionalMax(
|
||||
YGResolveValue(trailingPadding, widthSize), YGFloatOptional(0.0f));
|
||||
}
|
||||
|
||||
YGFloatOptional Node::getLeadingPaddingAndBorder(
|
||||
const YGFlexDirection axis,
|
||||
const float widthSize) const {
|
||||
return getLeadingPadding(axis, widthSize) +
|
||||
YGFloatOptional(getLeadingBorder(axis));
|
||||
}
|
||||
|
||||
YGFloatOptional Node::getTrailingPaddingAndBorder(
|
||||
const YGFlexDirection axis,
|
||||
const float widthSize) const {
|
||||
return getTrailingPadding(axis, widthSize) +
|
||||
YGFloatOptional(getTrailingBorder(axis));
|
||||
}
|
||||
|
||||
void Node::reset() {
|
||||
YGAssertWithNode(
|
||||
this,
|
||||
children_.size() == 0,
|
||||
"Cannot reset a node which still has children attached");
|
||||
YGAssertWithNode(
|
||||
this, owner_ == nullptr, "Cannot reset a node still attached to a owner");
|
||||
|
||||
*this = Node{getConfig()};
|
||||
}
|
||||
|
||||
} // namespace facebook::yoga
|
343
yoga/node/Node.h
343
yoga/node/Node.h
@@ -1,343 +0,0 @@
|
||||
/*
|
||||
* 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 <cstdint>
|
||||
#include <stdio.h>
|
||||
#include <yoga/config/Config.h>
|
||||
#include <yoga/node/LayoutResults.h>
|
||||
#include <yoga/Yoga-internal.h>
|
||||
|
||||
#include <yoga/style/CompactValue.h>
|
||||
#include <yoga/style/Style.h>
|
||||
|
||||
// Tag struct used to form the opaque YGNodeRef for the public C API
|
||||
struct YGNode {};
|
||||
|
||||
namespace facebook::yoga {
|
||||
|
||||
#pragma pack(push)
|
||||
#pragma pack(1)
|
||||
struct NodeFlags {
|
||||
bool hasNewLayout : 1;
|
||||
bool isReferenceBaseline : 1;
|
||||
bool isDirty : 1;
|
||||
uint8_t nodeType : 1;
|
||||
bool measureUsesContext : 1;
|
||||
bool baselineUsesContext : 1;
|
||||
bool printUsesContext : 1;
|
||||
};
|
||||
#pragma pack(pop)
|
||||
|
||||
class YOGA_EXPORT Node : public ::YGNode {
|
||||
public:
|
||||
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;
|
||||
NodeFlags flags_ = {};
|
||||
union {
|
||||
YGMeasureFunc noContext;
|
||||
MeasureWithContextFn withContext;
|
||||
} measure_ = {nullptr};
|
||||
union {
|
||||
YGBaselineFunc noContext;
|
||||
BaselineWithContextFn withContext;
|
||||
} baseline_ = {nullptr};
|
||||
union {
|
||||
YGPrintFunc noContext;
|
||||
PrintWithContextFn withContext;
|
||||
} print_ = {nullptr};
|
||||
YGDirtiedFunc dirtied_ = nullptr;
|
||||
Style style_ = {};
|
||||
LayoutResults layout_ = {};
|
||||
uint32_t lineIndex_ = 0;
|
||||
Node* owner_ = nullptr;
|
||||
std::vector<Node*> children_ = {};
|
||||
Config* config_;
|
||||
std::array<YGValue, 2> resolvedDimensions_ = {
|
||||
{YGValueUndefined, YGValueUndefined}};
|
||||
|
||||
YGFloatOptional relativePosition(
|
||||
const YGFlexDirection axis,
|
||||
const float axisSize) const;
|
||||
|
||||
void setMeasureFunc(decltype(measure_));
|
||||
void setBaselineFunc(decltype(baseline_));
|
||||
|
||||
void useWebDefaults() {
|
||||
style_.flexDirection() = YGFlexDirectionRow;
|
||||
style_.alignContent() = YGAlignStretch;
|
||||
}
|
||||
|
||||
// DANGER DANGER DANGER!
|
||||
// If 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!
|
||||
Node& operator=(Node&&) = default;
|
||||
|
||||
public:
|
||||
Node() : Node{static_cast<Config*>(YGConfigGetDefault())} {
|
||||
flags_.hasNewLayout = true;
|
||||
}
|
||||
explicit Node(Config* config);
|
||||
~Node() = default; // cleanup of owner/children relationships in YGNodeFree
|
||||
|
||||
Node(Node&&);
|
||||
|
||||
// Does not expose true value semantics, as children are not cloned eagerly.
|
||||
// Should we remove this?
|
||||
Node(const Node& node) = default;
|
||||
|
||||
// assignment means potential leaks of existing children, or alternatively
|
||||
// freeing unowned memory, double free, or freeing stack memory.
|
||||
Node& operator=(const Node&) = delete;
|
||||
|
||||
// Getters
|
||||
void* getContext() const { return context_; }
|
||||
|
||||
void print(void*);
|
||||
|
||||
bool getHasNewLayout() const { return flags_.hasNewLayout; }
|
||||
|
||||
YGNodeType getNodeType() const {
|
||||
return static_cast<YGNodeType>(flags_.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);
|
||||
|
||||
bool hasErrata(YGErrata errata) const { return config_->hasErrata(errata); }
|
||||
|
||||
YGDirtiedFunc getDirtied() const { return dirtied_; }
|
||||
|
||||
// For Performance reasons passing as reference.
|
||||
Style& getStyle() { return style_; }
|
||||
|
||||
const Style& getStyle() const { return style_; }
|
||||
|
||||
// For Performance reasons passing as reference.
|
||||
LayoutResults& getLayout() { return layout_; }
|
||||
|
||||
const LayoutResults& getLayout() const { return layout_; }
|
||||
|
||||
uint32_t getLineIndex() const { return lineIndex_; }
|
||||
|
||||
bool isReferenceBaseline() { return flags_.isReferenceBaseline; }
|
||||
|
||||
// returns the Node that owns this Node. An owner is used to identify
|
||||
// the YogaTree that a Node belongs to. This method will return the parent
|
||||
// of the Node when a Node only belongs to one YogaTree or nullptr when
|
||||
// the Node is shared between two or more YogaTrees.
|
||||
Node* getOwner() const { return owner_; }
|
||||
|
||||
// Deprecated, use getOwner() instead.
|
||||
Node* getParent() const { return getOwner(); }
|
||||
|
||||
const std::vector<Node*>& 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 (Node*& child : children_) {
|
||||
if (child->getOwner() != this) {
|
||||
child = static_cast<Node*>(
|
||||
config_->cloneNode(child, this, i, cloneContext));
|
||||
child->setOwner(this);
|
||||
}
|
||||
i += 1;
|
||||
|
||||
callback(child, cloneContext);
|
||||
}
|
||||
}
|
||||
|
||||
Node* getChild(uint32_t index) const { return children_.at(index); }
|
||||
|
||||
Config* getConfig() const { return config_; }
|
||||
|
||||
bool isDirty() const { return flags_.isDirty; }
|
||||
|
||||
std::array<YGValue, 2> getResolvedDimensions() const {
|
||||
return resolvedDimensions_;
|
||||
}
|
||||
|
||||
YGValue getResolvedDimension(int index) const {
|
||||
return resolvedDimensions_[index];
|
||||
}
|
||||
|
||||
static CompactValue computeEdgeValueForColumn(
|
||||
const Style::Edges& edges,
|
||||
YGEdge edge,
|
||||
CompactValue defaultValue);
|
||||
|
||||
static CompactValue computeEdgeValueForRow(
|
||||
const Style::Edges& edges,
|
||||
YGEdge rowEdge,
|
||||
YGEdge edge,
|
||||
CompactValue defaultValue);
|
||||
|
||||
static CompactValue computeRowGap(
|
||||
const Style::Gutters& gutters,
|
||||
CompactValue defaultValue);
|
||||
|
||||
static CompactValue computeColumnGap(
|
||||
const Style::Gutters& gutters,
|
||||
CompactValue defaultValue);
|
||||
|
||||
// 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;
|
||||
YGFloatOptional getGapForAxis(
|
||||
const YGFlexDirection axis,
|
||||
const float widthSize) const;
|
||||
// Setters
|
||||
|
||||
void setContext(void* context) { context_ = context; }
|
||||
|
||||
void setPrintFunc(YGPrintFunc printFunc) {
|
||||
print_.noContext = printFunc;
|
||||
flags_.printUsesContext = false;
|
||||
}
|
||||
void setPrintFunc(PrintWithContextFn printFunc) {
|
||||
print_.withContext = printFunc;
|
||||
flags_.printUsesContext = true;
|
||||
}
|
||||
void setPrintFunc(std::nullptr_t) { setPrintFunc(YGPrintFunc{nullptr}); }
|
||||
|
||||
void setHasNewLayout(bool hasNewLayout) {
|
||||
flags_.hasNewLayout = hasNewLayout;
|
||||
}
|
||||
|
||||
void setNodeType(YGNodeType nodeType) {
|
||||
flags_.nodeType = static_cast<uint8_t>(nodeType);
|
||||
}
|
||||
|
||||
void setMeasureFunc(YGMeasureFunc measureFunc);
|
||||
void setMeasureFunc(MeasureWithContextFn);
|
||||
void setMeasureFunc(std::nullptr_t) {
|
||||
return setMeasureFunc(YGMeasureFunc{nullptr});
|
||||
}
|
||||
|
||||
void setBaselineFunc(YGBaselineFunc baseLineFunc) {
|
||||
flags_.baselineUsesContext = false;
|
||||
baseline_.noContext = baseLineFunc;
|
||||
}
|
||||
void setBaselineFunc(BaselineWithContextFn baseLineFunc) {
|
||||
flags_.baselineUsesContext = true;
|
||||
baseline_.withContext = baseLineFunc;
|
||||
}
|
||||
void setBaselineFunc(std::nullptr_t) {
|
||||
return setBaselineFunc(YGBaselineFunc{nullptr});
|
||||
}
|
||||
|
||||
void setDirtiedFunc(YGDirtiedFunc dirtiedFunc) { dirtied_ = dirtiedFunc; }
|
||||
|
||||
void setStyle(const Style& style) { style_ = style; }
|
||||
|
||||
void setLayout(const LayoutResults& layout) { layout_ = layout; }
|
||||
|
||||
void setLineIndex(uint32_t lineIndex) { lineIndex_ = lineIndex; }
|
||||
|
||||
void setIsReferenceBaseline(bool isReferenceBaseline) {
|
||||
flags_.isReferenceBaseline = isReferenceBaseline;
|
||||
}
|
||||
|
||||
void setOwner(Node* owner) { owner_ = owner; }
|
||||
|
||||
void setChildren(const std::vector<Node*>& children) { children_ = children; }
|
||||
|
||||
// TODO: rvalue override for setChildren
|
||||
|
||||
void setConfig(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 markDirtyAndPropagateDownwards();
|
||||
|
||||
// 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(Node* oldChild, Node* newChild);
|
||||
void replaceChild(Node* child, uint32_t index);
|
||||
void insertChild(Node* child, uint32_t index);
|
||||
/// Removes the first occurrence of child
|
||||
bool removeChild(Node* child);
|
||||
void removeChild(uint32_t index);
|
||||
|
||||
void cloneChildrenIfNeeded(void*);
|
||||
void markDirtyAndPropagate();
|
||||
float resolveFlexGrow() const;
|
||||
float resolveFlexShrink() const;
|
||||
bool isNodeFlexible();
|
||||
void reset();
|
||||
};
|
||||
|
||||
} // namespace facebook::yoga
|
Reference in New Issue
Block a user