Summary: If the first element of a line is not contributing (e.g. position absolute), an additional gap will be added to the line, because the first gap element of the line is never identified (wrong start index). Fix: raise the index of the first line element until we find an element that is contributing to the line. Pull Request resolved: https://github.com/facebook/yoga/pull/1408 Reviewed By: yungsters Differential Revision: D49722065 Pulled By: NickGerleman fbshipit-source-id: 1068cb0b11ae4b04ec8d063e70540cce06181d5a
114 lines
3.9 KiB
C++
114 lines
3.9 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 Direction 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;
|
|
size_t firstElementInLineIndex = startOfLineIndex;
|
|
|
|
float sizeConsumedIncludingMinConstraint = 0;
|
|
const FlexDirection mainAxis = resolveDirection(
|
|
node->getStyle().flexDirection(), node->resolveDirection(ownerDirection));
|
|
const bool isNodeFlexWrap = node->getStyle().flexWrap() != Wrap::NoWrap;
|
|
const float gap = node->getGapForAxis(mainAxis, availableInnerWidth);
|
|
|
|
// 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() == Display::None ||
|
|
child->getStyle().positionType() == PositionType::Absolute) {
|
|
if (firstElementInLineIndex == endOfLineIndex) {
|
|
// We haven't found the first contributing element in the line yet.
|
|
firstElementInLineIndex++;
|
|
}
|
|
continue;
|
|
}
|
|
|
|
const bool isFirstElementInLine =
|
|
(endOfLineIndex - firstElementInLineIndex) == 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
|