Skip to content

Commit

Permalink
Introduce positionAbsoluteChild (#1473)
Browse files Browse the repository at this point in the history
Summary:

X-link: facebook/react-native#41491

To simplify the logic a bit I introduce a new function called `positionAbsoluteChild`. This function will, eventually, be the **sole function that matters** when determining the layout position of an absolute node. Because [absolute nodes do not participate in flex layout](https://drafts.csswg.org/css-flexbox/#abspos-items), we can determine the position of said node independently of its siblings. The only information we need are the node itself, its parent, and its containing block - which we have all of in `layoutAbsoluteChild`.

Right now, however, this is purely a BE change with no functionality different. There was a big set of if statements at the end of `layoutAbsoluteChild` that would position the node on the main and cross axis for certain cases. The old code had it so that the main and cross axis had basically the same logic but the code was repeated. This puts that logic, as is, in `positionAbsoluteChild` and calls that from `layoutAbsoluteChild`.

I will soon edit this function to actually do what it is envisioned to do (i.e. be the sole place that position is set for absolute nodes).

Reviewed By: NickGerleman

Differential Revision: D51272855
  • Loading branch information
Joe Vilches authored and facebook-github-bot committed Nov 21, 2023
1 parent a269480 commit 7051c97
Showing 1 changed file with 87 additions and 88 deletions.
175 changes: 87 additions & 88 deletions yoga/algorithm/CalculateLayout.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -317,6 +317,75 @@ static void computeFlexBasisForChild(
child->setLayoutComputedFlexBasisGeneration(generationCount);
}

// Absolutely positioned nodes do not participate in flex layout and thus their
// positions can be determined independently from the rest of their siblings.
// For each axis there are essentially two cases:
//
// 1) The node has insets defined. In this case we can just use these to
// determine the position of the node.
// 2) The node does not have insets defined. In this case we look at the style
// of the parent to position the node. Things like justify content and
// align content will move absolute children around. If none of these
// special properties are defined, the child is positioned at the start
// (defined by flex direction) of the leading flex line.
//
// This function does that positioning for the given axis.
static void positionAbsoluteChild(
const yoga::Node* const containingNode,
const yoga::Node* const parent,
yoga::Node* child,
const Direction direction,
const FlexDirection axis,
const bool isMainAxis,
const float containingBlockWidth,
const float containingBlockHeight) {
const bool isAxisRow = isRow(axis);
const bool shouldCenter = isMainAxis
? parent->getStyle().justifyContent() == Justify::Center
: resolveChildAlignment(parent, child) == Align::Center;
const bool shouldFlexEnd = isMainAxis
? parent->getStyle().justifyContent() == Justify::FlexEnd
: ((resolveChildAlignment(parent, child) == Align::FlexEnd) ^
(parent->getStyle().flexWrap() == Wrap::WrapReverse));

if (child->isFlexEndPositionDefined(axis) &&
!child->isFlexStartPositionDefined(axis)) {
child->setLayoutPosition(
containingNode->getLayout().measuredDimension(dimension(axis)) -
child->getLayout().measuredDimension(dimension(axis)) -
containingNode->getFlexEndBorder(axis, direction) -
child->getFlexEndMargin(
axis,
isAxisRow ? containingBlockWidth : containingBlockHeight) -
child->getFlexEndPosition(
axis, isAxisRow ? containingBlockWidth : containingBlockHeight),
flexStartEdge(axis));
} else if (!child->isFlexStartPositionDefined(axis) && shouldCenter) {
child->setLayoutPosition(
(parent->getLayout().measuredDimension(dimension(axis)) -
child->getLayout().measuredDimension(dimension(axis))) /
2.0f,
flexStartEdge(axis));
} else if (!child->isFlexStartPositionDefined(axis) && shouldFlexEnd) {
child->setLayoutPosition(
(parent->getLayout().measuredDimension(dimension(axis)) -
child->getLayout().measuredDimension(dimension(axis))),
flexStartEdge(axis));
} else if (
parent->getConfig()->isExperimentalFeatureEnabled(
ExperimentalFeature::AbsolutePercentageAgainstPaddingEdge) &&
child->isFlexStartPositionDefined(axis)) {
child->setLayoutPosition(
child->getFlexStartPosition(
axis,
containingNode->getLayout().measuredDimension(dimension(axis))) +
containingNode->getFlexStartBorder(axis, direction) +
child->getFlexStartMargin(
axis, isAxisRow ? containingBlockWidth : containingBlockHeight),
flexStartEdge(axis));
}
}

static void layoutAbsoluteChild(
const yoga::Node* const containingNode,
const yoga::Node* const node,
Expand Down Expand Up @@ -471,94 +540,24 @@ static void layoutAbsoluteChild(
depth,
generationCount);

if (child->isFlexEndPositionDefined(mainAxis) &&
!child->isFlexStartPositionDefined(mainAxis)) {
child->setLayoutPosition(
containingNode->getLayout().measuredDimension(dimension(mainAxis)) -
child->getLayout().measuredDimension(dimension(mainAxis)) -
containingNode->getFlexEndBorder(mainAxis, direction) -
child->getFlexEndMargin(
mainAxis,
isMainAxisRow ? containingBlockWidth : containingBlockHeight) -
child->getFlexEndPosition(
mainAxis,
isMainAxisRow ? containingBlockWidth : containingBlockHeight),
flexStartEdge(mainAxis));
} else if (
!child->isFlexStartPositionDefined(mainAxis) &&
node->getStyle().justifyContent() == Justify::Center) {
child->setLayoutPosition(
(node->getLayout().measuredDimension(dimension(mainAxis)) -
child->getLayout().measuredDimension(dimension(mainAxis))) /
2.0f,
flexStartEdge(mainAxis));
} else if (
!child->isFlexStartPositionDefined(mainAxis) &&
node->getStyle().justifyContent() == Justify::FlexEnd) {
child->setLayoutPosition(
(node->getLayout().measuredDimension(dimension(mainAxis)) -
child->getLayout().measuredDimension(dimension(mainAxis))),
flexStartEdge(mainAxis));
} else if (
node->getConfig()->isExperimentalFeatureEnabled(
ExperimentalFeature::AbsolutePercentageAgainstPaddingEdge) &&
child->isFlexStartPositionDefined(mainAxis)) {
child->setLayoutPosition(
child->getFlexStartPosition(
mainAxis,
containingNode->getLayout().measuredDimension(
dimension(mainAxis))) +
containingNode->getFlexStartBorder(mainAxis, direction) +
child->getFlexStartMargin(
mainAxis,
isMainAxisRow ? containingBlockWidth : containingBlockHeight),
flexStartEdge(mainAxis));
}

if (child->isFlexEndPositionDefined(crossAxis) &&
!child->isFlexStartPositionDefined(crossAxis)) {
child->setLayoutPosition(
containingNode->getLayout().measuredDimension(dimension(crossAxis)) -
child->getLayout().measuredDimension(dimension(crossAxis)) -
containingNode->getFlexEndBorder(crossAxis, direction) -
child->getFlexEndMargin(
crossAxis,
isMainAxisRow ? containingBlockHeight : containingBlockWidth) -
child->getFlexEndPosition(
crossAxis,
isMainAxisRow ? containingBlockHeight : containingBlockWidth),
flexStartEdge(crossAxis));
} else if (
!child->isFlexStartPositionDefined(crossAxis) &&
resolveChildAlignment(node, child) == Align::Center) {
child->setLayoutPosition(
(node->getLayout().measuredDimension(dimension(crossAxis)) -
child->getLayout().measuredDimension(dimension(crossAxis))) /
2.0f,
flexStartEdge(crossAxis));
} else if (
!child->isFlexStartPositionDefined(crossAxis) &&
((resolveChildAlignment(node, child) == Align::FlexEnd) ^
(node->getStyle().flexWrap() == Wrap::WrapReverse))) {
child->setLayoutPosition(
(node->getLayout().measuredDimension(dimension(crossAxis)) -
child->getLayout().measuredDimension(dimension(crossAxis))),
flexStartEdge(crossAxis));
} else if (
containingNode->getConfig()->isExperimentalFeatureEnabled(
ExperimentalFeature::AbsolutePercentageAgainstPaddingEdge) &&
child->isFlexStartPositionDefined(crossAxis)) {
child->setLayoutPosition(
child->getFlexStartPosition(
crossAxis,
containingNode->getLayout().measuredDimension(
dimension(crossAxis))) +
containingNode->getFlexStartBorder(crossAxis, direction) +
child->getFlexStartMargin(
crossAxis,
isMainAxisRow ? containingBlockHeight : containingBlockWidth),
flexStartEdge(crossAxis));
}
positionAbsoluteChild(
containingNode,
node,
child,
direction,
mainAxis,
true /*isMainAxis*/,
containingBlockWidth,
containingBlockHeight);
positionAbsoluteChild(
containingNode,
node,
child,
direction,
crossAxis,
false /*isMainAxis*/,
containingBlockWidth,
containingBlockHeight);
}

static void layoutAbsoluteDescendants(
Expand Down

0 comments on commit 7051c97

Please sign in to comment.