Implement gap/row-gap/column-gap (within the C ABI)
Summary: This extracts the core changes from https://github.com/facebook/yoga/pull/1116, to support gap/row-gap/column-gap, mostly identical, apart from the rename of gaps -> gutters. The core functionality in this PR looks to be well tested from the fixtures added. I am not an expert in the internals of Yoga, but I am seeing everything that I would expect to. The space for the gap is accounted for in line-breaking, and the accumulated gaps limit the available line-length, before sizing flexible children, so items are sized correctly as to accommodate the gap. Then the gap is used for spacing during main axis and cross-axis justification. Changelog: [Genral][Added] - Implement gap/row-gap/column-gap (within the yoga C ABI) Reviewed By: javache Differential Revision: D39922410 fbshipit-source-id: 5850f22032169028bd8383b49dd240b335c11d3d
This commit is contained in:
committed by
Facebook GitHub Bot
parent
05dd228317
commit
582533dbc6
@@ -797,6 +797,27 @@ YOGA_EXPORT float YGNodeStyleGetBorder(
|
||||
return static_cast<YGValue>(border).value;
|
||||
}
|
||||
|
||||
YOGA_EXPORT void YGNodeStyleSetGap(
|
||||
const YGNodeRef node,
|
||||
const YGGutter gutter,
|
||||
const float gapLength) {
|
||||
auto length = detail::CompactValue::ofMaybe<YGUnitPoint>(gapLength);
|
||||
updateIndexedStyleProp<MSVC_HINT(gap)>(node, &YGStyle::gap, gutter, length);
|
||||
}
|
||||
|
||||
YOGA_EXPORT float YGNodeStyleGetGap(
|
||||
const YGNodeConstRef node,
|
||||
const YGGutter gutter) {
|
||||
auto gapLength = node->getStyle().gap()[gutter];
|
||||
if (gapLength.isUndefined() || gapLength.isAuto()) {
|
||||
// TODO(T26792433): Rather than returning YGUndefined, change the api to
|
||||
// return YGFloatOptional.
|
||||
return YGUndefined;
|
||||
}
|
||||
|
||||
return static_cast<YGValue>(gapLength).value;
|
||||
}
|
||||
|
||||
// Yoga specific properties, not compatible with flexbox specification
|
||||
|
||||
// TODO(T26792433): Change the API to accept YGFloatOptional.
|
||||
@@ -1972,6 +1993,7 @@ static YGCollectFlexItemsRowValues YGCalculateCollectFlexItemsRowValues(
|
||||
const YGFlexDirection mainAxis = YGResolveFlexDirection(
|
||||
node->getStyle().flexDirection(), node->resolveDirection(ownerDirection));
|
||||
const bool isNodeFlexWrap = node->getStyle().flexWrap() != YGWrapNoWrap;
|
||||
const float gap = node->getGapForAxis(mainAxis, availableInnerWidth).unwrap();
|
||||
|
||||
// Add items to the current line until it's full or we run out of items.
|
||||
uint32_t endOfLineIndex = startOfLineIndex;
|
||||
@@ -1981,9 +2003,13 @@ static YGCollectFlexItemsRowValues YGCalculateCollectFlexItemsRowValues(
|
||||
child->getStyle().positionType() == YGPositionTypeAbsolute) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const bool isFirstElementInLine = (endOfLineIndex - startOfLineIndex) == 0;
|
||||
|
||||
child->setLineIndex(lineCount);
|
||||
const float childMarginMainAxis =
|
||||
child->getMarginForAxis(mainAxis, availableInnerWidth).unwrap();
|
||||
const float childLeadingGapMainAxis = isFirstElementInLine ? 0.0f : gap;
|
||||
const float flexBasisWithMinAndMaxConstraints =
|
||||
YGNodeBoundAxisWithinMinAndMax(
|
||||
child,
|
||||
@@ -1996,16 +2022,19 @@ static YGCollectFlexItemsRowValues YGCalculateCollectFlexItemsRowValues(
|
||||
// size, we've hit the end of the current line. Break out of the loop and
|
||||
// lay out the current line.
|
||||
if (sizeConsumedOnCurrentLineIncludingMinConstraint +
|
||||
flexBasisWithMinAndMaxConstraints + childMarginMainAxis >
|
||||
flexBasisWithMinAndMaxConstraints + childMarginMainAxis +
|
||||
childLeadingGapMainAxis >
|
||||
availableInnerMainDim &&
|
||||
isNodeFlexWrap && flexAlgoRowMeasurement.itemsOnLine > 0) {
|
||||
break;
|
||||
}
|
||||
|
||||
sizeConsumedOnCurrentLineIncludingMinConstraint +=
|
||||
flexBasisWithMinAndMaxConstraints + childMarginMainAxis;
|
||||
flexBasisWithMinAndMaxConstraints + childMarginMainAxis +
|
||||
childLeadingGapMainAxis;
|
||||
flexAlgoRowMeasurement.sizeConsumedOnCurrentLine +=
|
||||
flexBasisWithMinAndMaxConstraints + childMarginMainAxis;
|
||||
flexBasisWithMinAndMaxConstraints + childMarginMainAxis +
|
||||
childLeadingGapMainAxis;
|
||||
flexAlgoRowMeasurement.itemsOnLine++;
|
||||
|
||||
if (child->isNodeFlexible()) {
|
||||
@@ -2415,6 +2444,7 @@ static void YGJustifyMainAxis(
|
||||
node->getLeadingPaddingAndBorder(mainAxis, ownerWidth).unwrap();
|
||||
const float trailingPaddingAndBorderMain =
|
||||
node->getTrailingPaddingAndBorder(mainAxis, ownerWidth).unwrap();
|
||||
const float gap = node->getGapForAxis(mainAxis, ownerWidth).unwrap();
|
||||
// If we are using "at most" rules in the main axis, make sure that
|
||||
// remainingFreeSpace is 0 when min main dimension is not given
|
||||
if (measureModeMainDim == YGMeasureModeAtMost &&
|
||||
@@ -2462,7 +2492,7 @@ static void YGJustifyMainAxis(
|
||||
// The space between the beginning and the first element and the space between
|
||||
// each two elements.
|
||||
float leadingMainDim = 0;
|
||||
float betweenMainDim = 0;
|
||||
float betweenMainDim = gap;
|
||||
const YGJustify justifyContent = node->getStyle().justifyContent();
|
||||
|
||||
if (numberOfAutoMarginsOnCurrentLine == 0) {
|
||||
@@ -2475,24 +2505,22 @@ static void YGJustifyMainAxis(
|
||||
break;
|
||||
case YGJustifySpaceBetween:
|
||||
if (collectedFlexItemsValues.itemsOnLine > 1) {
|
||||
betweenMainDim =
|
||||
betweenMainDim +=
|
||||
YGFloatMax(collectedFlexItemsValues.remainingFreeSpace, 0) /
|
||||
(collectedFlexItemsValues.itemsOnLine - 1);
|
||||
} else {
|
||||
betweenMainDim = 0;
|
||||
}
|
||||
break;
|
||||
case YGJustifySpaceEvenly:
|
||||
// Space is distributed evenly across all elements
|
||||
betweenMainDim = collectedFlexItemsValues.remainingFreeSpace /
|
||||
leadingMainDim = collectedFlexItemsValues.remainingFreeSpace /
|
||||
(collectedFlexItemsValues.itemsOnLine + 1);
|
||||
leadingMainDim = betweenMainDim;
|
||||
betweenMainDim += leadingMainDim;
|
||||
break;
|
||||
case YGJustifySpaceAround:
|
||||
// Space on the edges is half of the space between elements
|
||||
betweenMainDim = collectedFlexItemsValues.remainingFreeSpace /
|
||||
leadingMainDim = 0.5f * collectedFlexItemsValues.remainingFreeSpace /
|
||||
collectedFlexItemsValues.itemsOnLine;
|
||||
leadingMainDim = betweenMainDim / 2;
|
||||
betweenMainDim += leadingMainDim * 2;
|
||||
break;
|
||||
case YGJustifyFlexStart:
|
||||
break;
|
||||
@@ -2890,6 +2918,9 @@ static void YGNodelayoutImpl(
|
||||
// Accumulated cross dimensions of all lines so far.
|
||||
float totalLineCrossDim = 0;
|
||||
|
||||
const float crossAxisGap =
|
||||
node->getGapForAxis(crossAxis, availableInnerCrossDim).unwrap();
|
||||
|
||||
// Max main dimension of all the lines.
|
||||
float maxLineMainDim = 0;
|
||||
YGCollectFlexItemsRowValues collectedFlexItemsValues;
|
||||
@@ -3209,7 +3240,8 @@ static void YGNodelayoutImpl(
|
||||
}
|
||||
}
|
||||
|
||||
totalLineCrossDim += collectedFlexItemsValues.crossDim;
|
||||
const float appliedCrossGap = lineCount != 0 ? crossAxisGap : 0.0f;
|
||||
totalLineCrossDim += collectedFlexItemsValues.crossDim + appliedCrossGap;
|
||||
maxLineMainDim =
|
||||
YGFloatMax(maxLineMainDim, collectedFlexItemsValues.mainDim);
|
||||
}
|
||||
@@ -3304,6 +3336,7 @@ static void YGNodelayoutImpl(
|
||||
}
|
||||
endIndex = ii;
|
||||
lineHeight += crossDimLead;
|
||||
currentLead += i != 0 ? crossAxisGap : 0;
|
||||
|
||||
if (performLayout) {
|
||||
for (ii = startIndex; ii < endIndex; ii++) {
|
||||
|
Reference in New Issue
Block a user