in lib/yoga/src/main/cpp/yoga/Yoga.cpp [1235:1432]
static void YGNodeComputeFlexBasisForChild(
const YGNodeRef node,
const YGNodeRef child,
const float width,
const YGMeasureMode widthMode,
const float height,
const float ownerWidth,
const float ownerHeight,
const YGMeasureMode heightMode,
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 bool isMainAxisRow = YGFlexDirectionIsRow(mainAxis);
const float mainAxisSize = isMainAxisRow ? width : height;
const float mainAxisownerSize = isMainAxisRow ? ownerWidth : ownerHeight;
float childWidth;
float childHeight;
YGMeasureMode childWidthMeasureMode;
YGMeasureMode childHeightMeasureMode;
const YGFloatOptional resolvedFlexBasis =
YGResolveValue(child->resolveFlexBasisPtr(), mainAxisownerSize);
const bool isRowStyleDimDefined =
YGNodeIsStyleDimDefined(child, YGFlexDirectionRow, ownerWidth);
const bool isColumnStyleDimDefined =
YGNodeIsStyleDimDefined(child, YGFlexDirectionColumn, ownerHeight);
if (!resolvedFlexBasis.isUndefined() && !YGFloatIsUndefined(mainAxisSize)) {
if (child->getLayout().computedFlexBasis.isUndefined() ||
(YGConfigIsExperimentalFeatureEnabled(
child->getConfig(), YGExperimentalFeatureWebFlexBasis) &&
child->getLayout().computedFlexBasisGeneration != generationCount)) {
const YGFloatOptional paddingAndBorder = YGFloatOptional(
YGNodePaddingAndBorderForAxis(child, mainAxis, ownerWidth));
child->setLayoutComputedFlexBasis(
YGFloatOptionalMax(resolvedFlexBasis, paddingAndBorder));
}
} else if (isMainAxisRow && isRowStyleDimDefined) {
// The width is definite, so use that as the flex basis.
const YGFloatOptional paddingAndBorder = YGFloatOptional(
YGNodePaddingAndBorderForAxis(child, YGFlexDirectionRow, ownerWidth));
child->setLayoutComputedFlexBasis(YGFloatOptionalMax(
YGResolveValue(
child->getResolvedDimensions()[YGDimensionWidth], ownerWidth),
paddingAndBorder));
} else if (!isMainAxisRow && isColumnStyleDimDefined) {
// The height is definite, so use that as the flex basis.
const YGFloatOptional paddingAndBorder =
YGFloatOptional(YGNodePaddingAndBorderForAxis(
child, YGFlexDirectionColumn, ownerWidth));
child->setLayoutComputedFlexBasis(YGFloatOptionalMax(
YGResolveValue(
child->getResolvedDimensions()[YGDimensionHeight], ownerHeight),
paddingAndBorder));
} else {
// Compute the flex basis and hypothetical main size (i.e. the clamped flex
// basis).
childWidth = YGUndefined;
childHeight = YGUndefined;
childWidthMeasureMode = YGMeasureModeUndefined;
childHeightMeasureMode = YGMeasureModeUndefined;
auto marginRow =
child->getMarginForAxis(YGFlexDirectionRow, ownerWidth).unwrap();
auto marginColumn =
child->getMarginForAxis(YGFlexDirectionColumn, ownerWidth).unwrap();
if (isRowStyleDimDefined) {
childWidth =
YGResolveValue(
child->getResolvedDimensions()[YGDimensionWidth], ownerWidth)
.unwrap() +
marginRow;
childWidthMeasureMode = YGMeasureModeExactly;
}
if (isColumnStyleDimDefined) {
childHeight =
YGResolveValue(
child->getResolvedDimensions()[YGDimensionHeight], ownerHeight)
.unwrap() +
marginColumn;
childHeightMeasureMode = YGMeasureModeExactly;
}
// The W3C spec doesn't say anything about the 'overflow' property, but all
// major browsers appear to implement the following logic.
if ((!isMainAxisRow && node->getStyle().overflow() == YGOverflowScroll) ||
node->getStyle().overflow() != YGOverflowScroll) {
if (YGFloatIsUndefined(childWidth) && !YGFloatIsUndefined(width)) {
childWidth = width;
childWidthMeasureMode = YGMeasureModeAtMost;
}
}
if ((isMainAxisRow && node->getStyle().overflow() == YGOverflowScroll) ||
node->getStyle().overflow() != YGOverflowScroll) {
if (YGFloatIsUndefined(childHeight) && !YGFloatIsUndefined(height)) {
childHeight = height;
childHeightMeasureMode = YGMeasureModeAtMost;
}
}
const auto& childStyle = child->getStyle();
if (!childStyle.aspectRatio().isUndefined()) {
if (!isMainAxisRow && childWidthMeasureMode == YGMeasureModeExactly) {
childHeight = marginColumn +
(childWidth - marginRow) / childStyle.aspectRatio().unwrap();
childHeightMeasureMode = YGMeasureModeExactly;
} else if (
isMainAxisRow && childHeightMeasureMode == YGMeasureModeExactly) {
childWidth = marginRow +
(childHeight - marginColumn) * childStyle.aspectRatio().unwrap();
childWidthMeasureMode = YGMeasureModeExactly;
}
}
// If child has no defined size in the cross axis and is set to stretch, set
// the cross axis to be measured exactly with the available inner width
const bool hasExactWidth =
!YGFloatIsUndefined(width) && widthMode == YGMeasureModeExactly;
const bool childWidthStretch =
YGNodeAlignItem(node, child) == YGAlignStretch &&
childWidthMeasureMode != YGMeasureModeExactly;
if (!isMainAxisRow && !isRowStyleDimDefined && hasExactWidth &&
childWidthStretch) {
childWidth = width;
childWidthMeasureMode = YGMeasureModeExactly;
if (!childStyle.aspectRatio().isUndefined()) {
childHeight =
(childWidth - marginRow) / childStyle.aspectRatio().unwrap();
childHeightMeasureMode = YGMeasureModeExactly;
}
}
const bool hasExactHeight =
!YGFloatIsUndefined(height) && heightMode == YGMeasureModeExactly;
const bool childHeightStretch =
YGNodeAlignItem(node, child) == YGAlignStretch &&
childHeightMeasureMode != YGMeasureModeExactly;
if (isMainAxisRow && !isColumnStyleDimDefined && hasExactHeight &&
childHeightStretch) {
childHeight = height;
childHeightMeasureMode = YGMeasureModeExactly;
if (!childStyle.aspectRatio().isUndefined()) {
childWidth =
(childHeight - marginColumn) * childStyle.aspectRatio().unwrap();
childWidthMeasureMode = YGMeasureModeExactly;
}
}
YGConstrainMaxSizeForMode(
child,
YGFlexDirectionRow,
ownerWidth,
ownerWidth,
&childWidthMeasureMode,
&childWidth);
YGConstrainMaxSizeForMode(
child,
YGFlexDirectionColumn,
ownerHeight,
ownerWidth,
&childHeightMeasureMode,
&childHeight);
// Measure the child
YGLayoutNodeInternal(
child,
childWidth,
childHeight,
direction,
childWidthMeasureMode,
childHeightMeasureMode,
ownerWidth,
ownerHeight,
false,
LayoutPassReason::kMeasureChild,
config,
layoutMarkerData,
layoutContext,
depth,
generationCount);
child->setLayoutComputedFlexBasis(YGFloatOptional(YGFloatMax(
child->getLayout().measuredDimensions[dim[mainAxis]],
YGNodePaddingAndBorderForAxis(child, mainAxis, ownerWidth))));
}
child->setLayoutComputedFlexBasisGeneration(generationCount);
}