blob: 10521632669dc0ec2f5e7d1d70489007c9bab9ef [file] [log] [blame]
// Copyright 2017 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_NG_NG_COLUMN_LAYOUT_ALGORITHM_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_NG_NG_COLUMN_LAYOUT_ALGORITHM_H_
#include "third_party/blink/renderer/core/layout/ng/ng_box_fragment_builder.h"
#include "third_party/blink/renderer/core/layout/ng/ng_layout_algorithm.h"
namespace blink {
enum class NGBreakStatus;
class NGBlockNode;
class NGBlockBreakToken;
class NGConstraintSpace;
struct LogicalSize;
struct NGMarginStrut;
class CORE_EXPORT NGColumnLayoutAlgorithm
: public NGLayoutAlgorithm<NGBlockNode,
NGBoxFragmentBuilder,
NGBlockBreakToken> {
public:
NGColumnLayoutAlgorithm(const NGLayoutAlgorithmParams& params);
scoped_refptr<const NGLayoutResult> Layout() override;
MinMaxSizesResult ComputeMinMaxSizes(const MinMaxSizesInput&) const override;
private:
// Lay out as many children as we can. If |kNeedsEarlierBreak| is returned, it
// means that we ran out of space at an unappealing location, and need to
// relayout and break earlier (because we have a better breakpoint there). If
// |kBrokeBefore| is returned, it means that we need to break before the
// multicol container, and retry in the next fragmentainer.
NGBreakStatus LayoutChildren();
// Lay out one row of columns. The layout result returned is for the last
// column that was laid out. The rows themselves don't create fragments. If
// we're in a nested fragmentation context and completely out of outer
// fragmentainer space, nullptr will be returned.
scoped_refptr<const NGLayoutResult> LayoutRow(
const NGBlockBreakToken* next_column_token,
NGMarginStrut*);
// Lay out a column spanner. The return value will tell whether to break
// before the spanner or not. If |NGBreakStatus::kContinue| is returned, and
// no break token was set, it means that we can proceed to the next row of
// columns.
NGBreakStatus LayoutSpanner(NGBlockNode spanner_node,
const NGBlockBreakToken* break_token,
NGMarginStrut*);
// Propagate the baseline from the given |child| if needed.
void PropagateBaselineFromChild(const NGPhysicalBoxFragment& child,
LayoutUnit block_offset);
LayoutUnit CalculateBalancedColumnBlockSize(
const LogicalSize& column_size,
const NGBlockBreakToken* child_break_token);
// Stretch the column length. We do this during column balancing, when we
// discover that the current length isn't large enough to fit all content.
LayoutUnit StretchColumnBlockSize(LayoutUnit minimal_space_shortage,
LayoutUnit current_column_size) const;
LayoutUnit ConstrainColumnBlockSize(LayoutUnit size) const;
LayoutUnit CurrentContentBlockOffset() const {
return intrinsic_block_size_ - BorderScrollbarPadding().block_start;
}
// Lay out again, this time with a predefined good breakpoint that we
// discovered in the first pass. This happens when we run out of space in a
// fragmentainer at an less-than-ideal location, due to breaking restrictions,
// such as break-before:avoid or break-after:avoid.
scoped_refptr<const NGLayoutResult> RelayoutAndBreakEarlier();
// Get the percentage resolution size to use for column content (i.e. not
// spanners).
LogicalSize ColumnPercentageResolutionSize() const {
// Percentage block-size on children is resolved against the content-box of
// the multicol container (just like in regular block layout), while
// percentage inline-size is restricted by the columns.
return LogicalSize(column_inline_size_, ChildAvailableSize().block_size);
}
NGConstraintSpace CreateConstraintSpaceForBalancing(
const LogicalSize& column_size) const;
NGConstraintSpace CreateConstraintSpaceForSpanner(
const NGBlockNode& spanner,
LayoutUnit block_offset) const;
NGConstraintSpace CreateConstraintSpaceForMinMax() const;
// When set, this will specify where to break before or inside.
const NGEarlyBreak* early_break_ = nullptr;
int used_column_count_;
LayoutUnit column_inline_size_;
LayoutUnit column_inline_progression_;
LayoutUnit column_block_size_;
LayoutUnit intrinsic_block_size_;
LayoutUnit tallest_unbreakable_block_size_;
bool is_constrained_by_outer_fragmentation_context_ = false;
// This will be set during (outer) block fragmentation once we've processed
// the first piece of content of the multicol container. It is used to check
// if we're at a valid class A breakpoint (between block-level siblings).
bool has_processed_first_child_ = false;
bool has_processed_first_column_ = false;
};
} // namespace blink
#endif // THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_NG_NG_COLUMN_LAYOUT_ALGORITHM_H_