in ReactCommon/yoga/yoga/Yoga.cpp [1434:1633]
static void YGNodeAbsoluteLayoutChild(
const YGNodeRef node,
const YGNodeRef child,
const float width,
const YGMeasureMode widthMode,
const float height,
const YGDirection direction,
const YGConfigRef config,
LayoutData& layoutMarkerData,
void* const layoutContext,
const uint32_t depth,
const uint32_t generationCount) {
const YGFlexDirection mainAxis =
YGResolveFlexDirection(node->getStyle().flexDirection(), direction);
const YGFlexDirection crossAxis = YGFlexDirectionCross(mainAxis, direction);
const bool isMainAxisRow = YGFlexDirectionIsRow(mainAxis);
float childWidth = YGUndefined;
float childHeight = YGUndefined;
YGMeasureMode childWidthMeasureMode = YGMeasureModeUndefined;
YGMeasureMode childHeightMeasureMode = YGMeasureModeUndefined;
auto marginRow = child->getMarginForAxis(YGFlexDirectionRow, width).unwrap();
auto marginColumn =
child->getMarginForAxis(YGFlexDirectionColumn, width).unwrap();
if (YGNodeIsStyleDimDefined(child, YGFlexDirectionRow, width)) {
childWidth =
YGResolveValue(child->getResolvedDimensions()[YGDimensionWidth], width)
.unwrap() +
marginRow;
} else {
// If the child doesn't have a specified width, compute the width based on
// the left/right offsets if they're defined.
if (child->isLeadingPositionDefined(YGFlexDirectionRow) &&
child->isTrailingPosDefined(YGFlexDirectionRow)) {
childWidth = node->getLayout().measuredDimensions[YGDimensionWidth] -
(node->getLeadingBorder(YGFlexDirectionRow) +
node->getTrailingBorder(YGFlexDirectionRow)) -
(child->getLeadingPosition(YGFlexDirectionRow, width) +
child->getTrailingPosition(YGFlexDirectionRow, width))
.unwrap();
childWidth =
YGNodeBoundAxis(child, YGFlexDirectionRow, childWidth, width, width);
}
}
if (YGNodeIsStyleDimDefined(child, YGFlexDirectionColumn, height)) {
childHeight = YGResolveValue(
child->getResolvedDimensions()[YGDimensionHeight], height)
.unwrap() +
marginColumn;
} else {
// If the child doesn't have a specified height, compute the height based on
// the top/bottom offsets if they're defined.
if (child->isLeadingPositionDefined(YGFlexDirectionColumn) &&
child->isTrailingPosDefined(YGFlexDirectionColumn)) {
childHeight = node->getLayout().measuredDimensions[YGDimensionHeight] -
(node->getLeadingBorder(YGFlexDirectionColumn) +
node->getTrailingBorder(YGFlexDirectionColumn)) -
(child->getLeadingPosition(YGFlexDirectionColumn, height) +
child->getTrailingPosition(YGFlexDirectionColumn, height))
.unwrap();
childHeight = YGNodeBoundAxis(
child, YGFlexDirectionColumn, childHeight, height, width);
}
}
// Exactly one dimension needs to be defined for us to be able to do aspect
// ratio calculation. One dimension being the anchor and the other being
// flexible.
const auto& childStyle = child->getStyle();
if (YGFloatIsUndefined(childWidth) ^ YGFloatIsUndefined(childHeight)) {
if (!childStyle.aspectRatio().isUndefined()) {
if (YGFloatIsUndefined(childWidth)) {
childWidth = marginRow +
(childHeight - marginColumn) * childStyle.aspectRatio().unwrap();
} else if (YGFloatIsUndefined(childHeight)) {
childHeight = marginColumn +
(childWidth - marginRow) / childStyle.aspectRatio().unwrap();
}
}
}
// If we're still missing one or the other dimension, measure the content.
if (YGFloatIsUndefined(childWidth) || YGFloatIsUndefined(childHeight)) {
childWidthMeasureMode = YGFloatIsUndefined(childWidth)
? YGMeasureModeUndefined
: YGMeasureModeExactly;
childHeightMeasureMode = YGFloatIsUndefined(childHeight)
? YGMeasureModeUndefined
: YGMeasureModeExactly;
// If the size of the owner is defined then try to constrain the absolute
// child to that size as well. This allows text within the absolute child to
// wrap to the size of its owner. This is the same behavior as many browsers
// implement.
if (!isMainAxisRow && YGFloatIsUndefined(childWidth) &&
widthMode != YGMeasureModeUndefined && !YGFloatIsUndefined(width) &&
width > 0) {
childWidth = width;
childWidthMeasureMode = YGMeasureModeAtMost;
}
YGLayoutNodeInternal(
child,
childWidth,
childHeight,
direction,
childWidthMeasureMode,
childHeightMeasureMode,
childWidth,
childHeight,
false,
LayoutPassReason::kAbsMeasureChild,
config,
layoutMarkerData,
layoutContext,
depth,
generationCount);
childWidth = child->getLayout().measuredDimensions[YGDimensionWidth] +
child->getMarginForAxis(YGFlexDirectionRow, width).unwrap();
childHeight = child->getLayout().measuredDimensions[YGDimensionHeight] +
child->getMarginForAxis(YGFlexDirectionColumn, width).unwrap();
}
YGLayoutNodeInternal(
child,
childWidth,
childHeight,
direction,
YGMeasureModeExactly,
YGMeasureModeExactly,
childWidth,
childHeight,
true,
LayoutPassReason::kAbsLayout,
config,
layoutMarkerData,
layoutContext,
depth,
generationCount);
if (child->isTrailingPosDefined(mainAxis) &&
!child->isLeadingPositionDefined(mainAxis)) {
child->setLayoutPosition(
node->getLayout().measuredDimensions[dim[mainAxis]] -
child->getLayout().measuredDimensions[dim[mainAxis]] -
node->getTrailingBorder(mainAxis) -
child->getTrailingMargin(mainAxis, width).unwrap() -
child->getTrailingPosition(mainAxis, isMainAxisRow ? width : height)
.unwrap(),
leading[mainAxis]);
} else if (
!child->isLeadingPositionDefined(mainAxis) &&
node->getStyle().justifyContent() == YGJustifyCenter) {
child->setLayoutPosition(
(node->getLayout().measuredDimensions[dim[mainAxis]] -
child->getLayout().measuredDimensions[dim[mainAxis]]) /
2.0f,
leading[mainAxis]);
} else if (
!child->isLeadingPositionDefined(mainAxis) &&
node->getStyle().justifyContent() == YGJustifyFlexEnd) {
child->setLayoutPosition(
(node->getLayout().measuredDimensions[dim[mainAxis]] -
child->getLayout().measuredDimensions[dim[mainAxis]]),
leading[mainAxis]);
}
if (child->isTrailingPosDefined(crossAxis) &&
!child->isLeadingPositionDefined(crossAxis)) {
child->setLayoutPosition(
node->getLayout().measuredDimensions[dim[crossAxis]] -
child->getLayout().measuredDimensions[dim[crossAxis]] -
node->getTrailingBorder(crossAxis) -
child->getTrailingMargin(crossAxis, width).unwrap() -
child
->getTrailingPosition(crossAxis, isMainAxisRow ? height : width)
.unwrap(),
leading[crossAxis]);
} else if (
!child->isLeadingPositionDefined(crossAxis) &&
YGNodeAlignItem(node, child) == YGAlignCenter) {
child->setLayoutPosition(
(node->getLayout().measuredDimensions[dim[crossAxis]] -
child->getLayout().measuredDimensions[dim[crossAxis]]) /
2.0f,
leading[crossAxis]);
} else if (
!child->isLeadingPositionDefined(crossAxis) &&
((YGNodeAlignItem(node, child) == YGAlignFlexEnd) ^
(node->getStyle().flexWrap() == YGWrapWrapReverse))) {
child->setLayoutPosition(
(node->getLayout().measuredDimensions[dim[crossAxis]] -
child->getLayout().measuredDimensions[dim[crossAxis]]),
leading[crossAxis]);
}
}