Commit ab7fa607 authored by Christian Biesinger's avatar Christian Biesinger Committed by Commit Bot

[css-flexbox] More refactor: Store lines in the FlexibleBoxAlgorithm

R=eae@chromium.org

Change-Id: Ib267b515d4620ffa31de2ade2cdd4739c99027b9
Reviewed-on: https://chromium-review.googlesource.com/578391
Commit-Queue: Christian Biesinger <cbiesinger@chromium.org>
Commit-Queue: Emil A Eklund <eae@chromium.org>
Reviewed-by: default avatarEmil A Eklund <eae@chromium.org>
Cr-Commit-Position: refs/heads/master@{#488091}
parent bbd51398
......@@ -53,35 +53,40 @@ FlexLayoutAlgorithm::FlexLayoutAlgorithm(const ComputedStyle* style,
const Vector<FlexItem>& all_items)
: style_(style),
line_break_length_(line_break_length),
all_items_(all_items) {}
all_items_(all_items),
next_item_index_(0) {}
bool FlexLayoutAlgorithm::ComputeNextFlexLine(size_t* next_index,
FlexLine* line) {
line->Reset();
FlexLine* FlexLayoutAlgorithm::ComputeNextFlexLine() {
FlexLine new_line;
bool line_has_in_flow_item = false;
for (; *next_index < all_items_.size(); ++*next_index) {
const FlexItem& flex_item = all_items_[*next_index];
for (; next_item_index_ < all_items_.size(); ++next_item_index_) {
const FlexItem& flex_item = all_items_[next_item_index_];
DCHECK(!flex_item.box->IsOutOfFlowPositioned());
if (IsMultiline() &&
line->sum_hypothetical_main_size +
new_line.sum_hypothetical_main_size +
flex_item.HypotheticalMainAxisMarginBoxSize() >
line_break_length_ &&
line_has_in_flow_item)
break;
line->line_items.push_back(flex_item);
new_line.line_items.push_back(flex_item);
line_has_in_flow_item = true;
line->sum_flex_base_size += flex_item.FlexBaseMarginBoxSize();
line->total_flex_grow += flex_item.box->Style()->FlexGrow();
line->total_flex_shrink += flex_item.box->Style()->FlexShrink();
line->total_weighted_flex_shrink +=
new_line.sum_flex_base_size += flex_item.FlexBaseMarginBoxSize();
new_line.total_flex_grow += flex_item.box->Style()->FlexGrow();
new_line.total_flex_shrink += flex_item.box->Style()->FlexShrink();
new_line.total_weighted_flex_shrink +=
flex_item.box->Style()->FlexShrink() * flex_item.flex_base_content_size;
line->sum_hypothetical_main_size +=
new_line.sum_hypothetical_main_size +=
flex_item.HypotheticalMainAxisMarginBoxSize();
}
DCHECK(line->line_items.size() > 0 || *next_index == all_items_.size());
return line->line_items.size() > 0;
DCHECK(new_line.line_items.size() > 0 ||
next_item_index_ == all_items_.size());
if (new_line.line_items.size() > 0) {
flex_lines_.push_back(std::move(new_line));
return &flex_lines_.back();
}
return nullptr;
}
} // namespace blink
......@@ -75,12 +75,8 @@ class FlexItem {
};
struct FlexLine {
void Reset() {
line_items.clear();
sum_flex_base_size = LayoutUnit();
FlexLine() {
total_flex_grow = total_flex_shrink = total_weighted_flex_shrink = 0;
sum_hypothetical_main_size = LayoutUnit();
cross_axis_offset = cross_axis_extent = max_ascent = LayoutUnit();
}
// These fields get filled in by ComputeNextFlexLine.
......@@ -108,7 +104,11 @@ class FlexLayoutAlgorithm {
LayoutUnit line_break_length,
const Vector<FlexItem>& all_items);
bool ComputeNextFlexLine(size_t* next_index, FlexLine*);
Vector<FlexLine>& FlexLines() { return flex_lines_; }
// Computes the next flex line, stores it in FlexLines(), and returns a
// pointer to it. Returns nullptr if there are no more lines.
FlexLine* ComputeNextFlexLine();
private:
bool IsMultiline() const { return style_->FlexWrap() != EFlexWrap::kNowrap; }
......@@ -116,6 +116,8 @@ class FlexLayoutAlgorithm {
const ComputedStyle* style_;
LayoutUnit line_break_length_;
const Vector<FlexItem>& all_items_;
Vector<FlexLine> flex_lines_;
size_t next_item_index_;
};
} // namespace blink
......
......@@ -951,8 +951,6 @@ LayoutUnit LayoutFlexibleBox::ComputeInnerFlexBaseSizeForChild(
void LayoutFlexibleBox::LayoutFlexItems(bool relayout_children,
SubtreeLayoutScope& layout_scope) {
Vector<FlexLine> line_contexts;
PaintLayerScrollableArea::PreventRelayoutScope prevent_relayout_scope(
layout_scope);
......@@ -978,20 +976,19 @@ void LayoutFlexibleBox::LayoutFlexItems(bool relayout_children,
FlexLayoutAlgorithm flex_algorithm(Style(), line_break_length, all_items);
LayoutUnit cross_axis_offset =
FlowAwareBorderBefore() + FlowAwarePaddingBefore();
size_t next_index = 0;
FlexLine current_line;
while (flex_algorithm.ComputeNextFlexLine(&next_index, &current_line)) {
DCHECK_GE(current_line.line_items.size(), 0ULL);
FlexLine* current_line;
while ((current_line = flex_algorithm.ComputeNextFlexLine())) {
DCHECK_GE(current_line->line_items.size(), 0ULL);
LayoutUnit container_main_inner_size =
MainAxisContentExtent(current_line.sum_hypothetical_main_size);
MainAxisContentExtent(current_line->sum_hypothetical_main_size);
// availableFreeSpace is the initial amount of free space in this flexbox.
// remainingFreeSpace starts out at the same value but as we place and lay
// out flex items we subtract from it. Note that both values can be
// negative.
LayoutUnit remaining_free_space =
container_main_inner_size - current_line.sum_flex_base_size;
container_main_inner_size - current_line->sum_flex_base_size;
FlexSign flex_sign =
(current_line.sum_hypothetical_main_size < container_main_inner_size)
(current_line->sum_hypothetical_main_size < container_main_inner_size)
? kPositiveFlexibility
: kNegativeFlexibility;
FreezeInflexibleItems(flex_sign, current_line, remaining_free_space);
......@@ -1000,22 +997,21 @@ void LayoutFlexibleBox::LayoutFlexItems(bool relayout_children,
const LayoutUnit initial_free_space = remaining_free_space;
while (!ResolveFlexibleLengths(flex_sign, current_line, initial_free_space,
remaining_free_space)) {
DCHECK_GE(current_line.total_flex_grow, 0);
DCHECK_GE(current_line.total_weighted_flex_shrink, 0);
DCHECK_GE(current_line->total_flex_grow, 0);
DCHECK_GE(current_line->total_weighted_flex_shrink, 0);
}
// Recalculate the remaining free space. The adjustment for flex factors
// between 0..1 means we can't just use remainingFreeSpace here.
remaining_free_space = container_main_inner_size;
for (size_t i = 0; i < current_line.line_items.size(); ++i) {
FlexItem& flex_item = current_line.line_items[i];
for (size_t i = 0; i < current_line->line_items.size(); ++i) {
FlexItem& flex_item = current_line->line_items[i];
DCHECK(!flex_item.box->IsOutOfFlowPositioned());
remaining_free_space -= flex_item.FlexedMarginBoxSize();
}
LayoutAndPlaceChildren(cross_axis_offset, current_line,
remaining_free_space, relayout_children,
layout_scope);
line_contexts.push_back(current_line);
}
if (HasLineIfEmpty()) {
// Even if ComputeNextFlexLine returns true, the flexbox might not have
......@@ -1028,7 +1024,7 @@ void LayoutFlexibleBox::LayoutFlexItems(bool relayout_children,
}
UpdateLogicalHeight();
RepositionLogicalHeightDependentFlexItems(line_contexts);
RepositionLogicalHeightDependentFlexItems(flex_algorithm.FlexLines());
}
LayoutUnit LayoutFlexibleBox::AutoMarginOffsetInMainAxis(
......@@ -1399,14 +1395,14 @@ void LayoutFlexibleBox::FreezeViolations(Vector<FlexItem*>& violations,
void LayoutFlexibleBox::FreezeInflexibleItems(
FlexSign flex_sign,
FlexLine& line,
FlexLine* line,
LayoutUnit& remaining_free_space) {
// Per https://drafts.csswg.org/css-flexbox/#resolve-flexible-lengths step 2,
// we freeze all items with a flex factor of 0 as well as those with a min/max
// size violation.
Vector<FlexItem*> new_inflexible_items;
for (size_t i = 0; i < line.line_items.size(); ++i) {
FlexItem& flex_item = line.line_items[i];
for (size_t i = 0; i < line->line_items.size(); ++i) {
FlexItem& flex_item = line->line_items[i];
LayoutBox* child = flex_item.box;
DCHECK(!flex_item.box->IsOutOfFlowPositioned());
DCHECK(!flex_item.frozen) << i;
......@@ -1425,14 +1421,14 @@ void LayoutFlexibleBox::FreezeInflexibleItems(
}
}
FreezeViolations(new_inflexible_items, remaining_free_space,
line.total_flex_grow, line.total_flex_shrink,
line.total_weighted_flex_shrink);
line->total_flex_grow, line->total_flex_shrink,
line->total_weighted_flex_shrink);
}
// Returns true if we successfully ran the algorithm and sized the flex items.
bool LayoutFlexibleBox::ResolveFlexibleLengths(
FlexSign flex_sign,
FlexLine& line,
FlexLine* line,
LayoutUnit initial_free_space,
LayoutUnit& remaining_free_space) {
LayoutUnit total_violation;
......@@ -1441,16 +1437,16 @@ bool LayoutFlexibleBox::ResolveFlexibleLengths(
Vector<FlexItem*> max_violations;
double sum_flex_factors = (flex_sign == kPositiveFlexibility)
? line.total_flex_grow
: line.total_flex_shrink;
? line->total_flex_grow
: line->total_flex_shrink;
if (sum_flex_factors > 0 && sum_flex_factors < 1) {
LayoutUnit fractional(initial_free_space * sum_flex_factors);
if (fractional.Abs() < remaining_free_space.Abs())
remaining_free_space = fractional;
}
for (size_t i = 0; i < line.line_items.size(); ++i) {
FlexItem& flex_item = line.line_items[i];
for (size_t i = 0; i < line->line_items.size(); ++i) {
FlexItem& flex_item = line->line_items[i];
LayoutBox* child = flex_item.box;
// This check also covers out-of-flow children.
......@@ -1459,19 +1455,19 @@ bool LayoutFlexibleBox::ResolveFlexibleLengths(
LayoutUnit child_size = flex_item.flex_base_content_size;
double extra_space = 0;
if (remaining_free_space > 0 && line.total_flex_grow > 0 &&
if (remaining_free_space > 0 && line->total_flex_grow > 0 &&
flex_sign == kPositiveFlexibility &&
std::isfinite(line.total_flex_grow)) {
std::isfinite(line->total_flex_grow)) {
extra_space = remaining_free_space * child->Style()->FlexGrow() /
line.total_flex_grow;
line->total_flex_grow;
} else if (remaining_free_space < 0 &&
line.total_weighted_flex_shrink > 0 &&
line->total_weighted_flex_shrink > 0 &&
flex_sign == kNegativeFlexibility &&
std::isfinite(line.total_weighted_flex_shrink) &&
std::isfinite(line->total_weighted_flex_shrink) &&
child->Style()->FlexShrink()) {
extra_space = remaining_free_space * child->Style()->FlexShrink() *
flex_item.flex_base_content_size /
line.total_weighted_flex_shrink;
line->total_weighted_flex_shrink;
}
if (std::isfinite(extra_space))
child_size += LayoutUnit::FromFloatRound(extra_space);
......@@ -1492,8 +1488,8 @@ bool LayoutFlexibleBox::ResolveFlexibleLengths(
if (total_violation) {
FreezeViolations(total_violation < 0 ? max_violations : min_violations,
remaining_free_space, line.total_flex_grow,
line.total_flex_shrink, line.total_weighted_flex_shrink);
remaining_free_space, line->total_flex_grow,
line->total_flex_shrink, line->total_weighted_flex_shrink);
} else {
remaining_free_space -= used_free_space;
}
......@@ -1769,18 +1765,18 @@ EOverflow LayoutFlexibleBox::CrossAxisOverflowForChild(
DISABLE_CFI_PERF
void LayoutFlexibleBox::LayoutAndPlaceChildren(
LayoutUnit& cross_axis_offset,
FlexLine& current_line,
FlexLine* current_line,
LayoutUnit available_free_space,
bool relayout_children,
SubtreeLayoutScope& layout_scope) {
const StyleContentAlignmentData justify_content = ResolvedJustifyContent();
LayoutUnit auto_margin_offset =
AutoMarginOffsetInMainAxis(current_line.line_items, available_free_space);
LayoutUnit auto_margin_offset = AutoMarginOffsetInMainAxis(
current_line->line_items, available_free_space);
LayoutUnit main_axis_offset =
FlowAwareBorderStart() + FlowAwarePaddingStart();
main_axis_offset += InitialContentPositionOffset(
available_free_space, justify_content, current_line.line_items.size());
available_free_space, justify_content, current_line->line_items.size());
if (Style()->FlexDirection() == EFlexDirection::kRowReverse &&
ShouldPlaceBlockDirectionScrollbarOnLogicalLeft())
main_axis_offset += IsHorizontalFlow() ? VerticalScrollbarWidth()
......@@ -1794,8 +1790,8 @@ void LayoutFlexibleBox::LayoutAndPlaceChildren(
LayoutUnit max_child_cross_axis_extent;
bool should_flip_main_axis = !IsColumnFlow() && !IsLeftToRightFlow();
bool is_paginated = View()->GetLayoutState()->IsPaginated();
for (size_t i = 0; i < current_line.line_items.size(); ++i) {
const FlexItem& flex_item = current_line.line_items[i];
for (size_t i = 0; i < current_line->line_items.size(); ++i) {
const FlexItem& flex_item = current_line->line_items[i];
LayoutBox* child = flex_item.box;
DCHECK(!flex_item.box->IsOutOfFlowPositioned());
......@@ -1844,12 +1840,12 @@ void LayoutFlexibleBox::LayoutAndPlaceChildren(
CrossAxisExtentForChild(*child)) -
ascent;
current_line.max_ascent = std::max(current_line.max_ascent, ascent);
current_line->max_ascent = std::max(current_line->max_ascent, ascent);
max_descent = std::max(max_descent, descent);
// TODO(cbiesinger): Take scrollbar into account
child_cross_axis_margin_box_extent =
current_line.max_ascent + max_descent;
current_line->max_ascent + max_descent;
} else {
child_cross_axis_margin_box_extent =
CrossAxisIntrinsicExtentForChild(*child) +
......@@ -1876,11 +1872,11 @@ void LayoutFlexibleBox::LayoutAndPlaceChildren(
SetFlowAwareLocationForChild(*child, child_location);
main_axis_offset += child_main_extent + FlowAwareMarginEndForChild(*child);
if (i != current_line.line_items.size() - 1) {
if (i != current_line->line_items.size() - 1) {
// The last item does not get extra space added.
main_axis_offset += ContentDistributionSpaceBetweenChildren(
available_free_space, justify_content,
current_line.line_items.size());
current_line->line_items.size());
}
if (is_paginated)
......@@ -1897,14 +1893,14 @@ void LayoutFlexibleBox::LayoutAndPlaceChildren(
// items since the start depends on the height of the flexbox, which we
// only know after we've positioned all the flex items.
UpdateLogicalHeight();
LayoutColumnReverse(current_line.line_items, cross_axis_offset,
LayoutColumnReverse(current_line->line_items, cross_axis_offset,
available_free_space);
}
if (number_of_in_flow_children_on_first_line_ == -1)
number_of_in_flow_children_on_first_line_ = current_line.line_items.size();
current_line.cross_axis_offset = cross_axis_offset;
current_line.cross_axis_extent = max_child_cross_axis_extent;
number_of_in_flow_children_on_first_line_ = current_line->line_items.size();
current_line->cross_axis_offset = cross_axis_offset;
current_line->cross_axis_extent = max_child_cross_axis_extent;
cross_axis_offset += max_child_cross_axis_extent;
}
......
......@@ -198,10 +198,10 @@ class CORE_EXPORT LayoutFlexibleBox : public LayoutBlock {
FlexItem ConstructFlexItem(LayoutBox& child, ChildLayoutType);
void FreezeInflexibleItems(FlexSign,
FlexLine&,
FlexLine*,
LayoutUnit& remaining_free_space);
bool ResolveFlexibleLengths(FlexSign,
FlexLine&,
FlexLine*,
LayoutUnit initial_free_space,
LayoutUnit& remaining_free_space);
void FreezeViolations(Vector<FlexItem*>&,
......@@ -215,7 +215,7 @@ class CORE_EXPORT LayoutFlexibleBox : public LayoutBlock {
LayoutUnit child_preferred_size);
void PrepareChildForPositionedLayout(LayoutBox& child);
void LayoutAndPlaceChildren(LayoutUnit& cross_axis_offset,
FlexLine&,
FlexLine*,
LayoutUnit available_free_space,
bool relayout_children,
SubtreeLayoutScope&);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment