Files
yoga/yoga/algorithm/FlexLine.cpp
jlmip 07cabca526 Fixed issue with first line element gap handling. (#1408)
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
2023-10-03 06:24:48 -07:00

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