Summary: Pull Request resolved: https://github.com/facebook/yoga/pull/1374 X-link: https://github.com/facebook/react-native/pull/39396 Yoga today has a struct `CollectFlexItemsRowValues`, and function `calculateFlexItemsRowValues()`. These names have evolved over time into something not making much sense. The job of `calculateFlexItemsRowValues()` is a flex-wrap container into lines (i.e. line-breaking main-axis content, which may be row or column). It returns line-breaking results, but some other fields on `calculateFlexItemsRowValues()` are set much later in the process, and the struct is acting effectivelty as a holder for the line-specific values. This change: 1. Does some renaming (mainly to FlexLine) 2. Reconciles the count `itemsOnLine` and list `relativeChildren` to list `itemsInFlow` (`relativeChildren` is a lie, as it can include elements with `YGPositionTypeStatic` and exclude relative elements which have `display: "none"`. It really just means children which are included in the layout flow for the line) 3. Makes non-changing algorithm outputs const for clarity of what is a running value, and what is a result of line-breaking values with flex basis. 4. Moves working layout values to a substructure `flexLine.layout` 5. Replaces some dishonest documentation about `endOfLineIndex`. 6. Extracts this logic out of `CalculateLayout()` to a separate file 7. Extracts `boundAxis` wholesale into a separate file, to be usable outside of `CalculateLayout.cpp` Reviewed By: rshest Differential Revision: D49133837 fbshipit-source-id: ec68c5a3d2f01e7c9bd8d26e28298331a3fe2475
108 lines
3.6 KiB
C++
108 lines
3.6 KiB
C++
/*
|
|
* 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/Yoga.h>
|
|
|
|
#include <yoga/algorithm/BoundAxis.h>
|
|
#include <yoga/algorithm/FlexDirection.h>
|
|
#include <yoga/algorithm/FlexLine.h>
|
|
|
|
namespace facebook::yoga {
|
|
|
|
FlexLine calculateFlexLine(
|
|
yoga::Node* const node,
|
|
const YGDirection ownerDirection,
|
|
const float mainAxisownerSize,
|
|
const float availableInnerWidth,
|
|
const float availableInnerMainDim,
|
|
const size_t startOfLineIndex,
|
|
const size_t lineCount) {
|
|
std::vector<yoga::Node*> itemsInFlow;
|
|
itemsInFlow.reserve(node->getChildren().size());
|
|
|
|
float sizeConsumed = 0.0f;
|
|
float totalFlexGrowFactors = 0.0f;
|
|
float totalFlexShrinkScaledFactors = 0.0f;
|
|
size_t endOfLineIndex = startOfLineIndex;
|
|
|
|
float sizeConsumedIncludingMinConstraint = 0;
|
|
const YGFlexDirection mainAxis = resolveDirection(
|
|
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.
|
|
for (; endOfLineIndex < node->getChildren().size(); endOfLineIndex++) {
|
|
auto child = node->getChild(endOfLineIndex);
|
|
if (child->getStyle().display() == YGDisplayNone ||
|
|
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 =
|
|
boundAxisWithinMinAndMax(
|
|
child,
|
|
mainAxis,
|
|
child->getLayout().computedFlexBasis,
|
|
mainAxisownerSize)
|
|
.unwrap();
|
|
|
|
// If this is a multi-line flow and this item pushes us over the available
|
|
// size, we've hit the end of the current line. Break out of the loop and
|
|
// lay out the current line.
|
|
if (sizeConsumedIncludingMinConstraint + flexBasisWithMinAndMaxConstraints +
|
|
childMarginMainAxis + childLeadingGapMainAxis >
|
|
availableInnerMainDim &&
|
|
isNodeFlexWrap && itemsInFlow.size() > 0) {
|
|
break;
|
|
}
|
|
|
|
sizeConsumedIncludingMinConstraint += flexBasisWithMinAndMaxConstraints +
|
|
childMarginMainAxis + childLeadingGapMainAxis;
|
|
sizeConsumed += flexBasisWithMinAndMaxConstraints + childMarginMainAxis +
|
|
childLeadingGapMainAxis;
|
|
|
|
if (child->isNodeFlexible()) {
|
|
totalFlexGrowFactors += child->resolveFlexGrow();
|
|
|
|
// Unlike the grow factor, the shrink factor is scaled relative to the
|
|
// child dimension.
|
|
totalFlexShrinkScaledFactors += -child->resolveFlexShrink() *
|
|
child->getLayout().computedFlexBasis.unwrap();
|
|
}
|
|
|
|
itemsInFlow.push_back(child);
|
|
}
|
|
|
|
// The total flex factor needs to be floored to 1.
|
|
if (totalFlexGrowFactors > 0 && totalFlexGrowFactors < 1) {
|
|
totalFlexGrowFactors = 1;
|
|
}
|
|
|
|
// The total flex shrink factor needs to be floored to 1.
|
|
if (totalFlexShrinkScaledFactors > 0 && totalFlexShrinkScaledFactors < 1) {
|
|
totalFlexShrinkScaledFactors = 1;
|
|
}
|
|
|
|
return FlexLine{
|
|
std::move(itemsInFlow),
|
|
sizeConsumed,
|
|
endOfLineIndex,
|
|
FlexLineRunningLayout{
|
|
totalFlexGrowFactors,
|
|
totalFlexShrinkScaledFactors,
|
|
}};
|
|
}
|
|
|
|
} // namespace facebook::yoga
|