1 // Copyright 2017 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #ifndef THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_NG_NG_COLUMN_LAYOUT_ALGORITHM_H_ 6 #define THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_NG_NG_COLUMN_LAYOUT_ALGORITHM_H_ 7 8 #include "third_party/blink/renderer/core/layout/ng/ng_box_fragment_builder.h" 9 #include "third_party/blink/renderer/core/layout/ng/ng_layout_algorithm.h" 10 11 namespace blink { 12 13 enum class NGBreakStatus; 14 class NGBlockNode; 15 class NGBlockBreakToken; 16 class NGConstraintSpace; 17 struct LogicalSize; 18 struct NGMarginStrut; 19 20 class CORE_EXPORT NGColumnLayoutAlgorithm 21 : public NGLayoutAlgorithm<NGBlockNode, 22 NGBoxFragmentBuilder, 23 NGBlockBreakToken> { 24 public: 25 NGColumnLayoutAlgorithm(const NGLayoutAlgorithmParams& params); 26 27 scoped_refptr<const NGLayoutResult> Layout() override; 28 29 base::Optional<MinMaxSizes> ComputeMinMaxSizes( 30 const MinMaxSizesInput&) const override; 31 32 private: 33 // Lay out as many children as we can. If |kNeedsEarlierBreak| is returned, it 34 // means that we ran out of space at an unappealing location, and need to 35 // relayout and break earlier (because we have a better breakpoint there). If 36 // |kBrokeBefore| is returned, it means that we need to break before the 37 // multicol container, and retry in the next fragmentainer. 38 NGBreakStatus LayoutChildren(); 39 40 // Lay out one row of columns. The layout result returned is for the last 41 // column that was laid out. The rows themselves don't create fragments. If 42 // we're in a nested fragmentation context and completely out of outer 43 // fragmentainer space, nullptr will be returned. 44 scoped_refptr<const NGLayoutResult> LayoutRow( 45 const NGBlockBreakToken* next_column_token, 46 NGMarginStrut*); 47 48 // Lay out a column spanner. The return value will tell whether to break 49 // before the spanner or not. If we're not to break before the spanner, but 50 // rather inside, |spanner_break_token| will be set, so that we know where to 51 // resume in the next outer fragmentainer. If |NGBreakStatus::kContinue| is 52 // returned, and no break token was set, it means that we can proceed to the 53 // next row of columns. 54 NGBreakStatus LayoutSpanner(NGBlockNode spanner_node, 55 const NGBlockBreakToken* break_token, 56 NGMarginStrut*, 57 scoped_refptr<const NGBlockBreakToken>*); 58 59 LayoutUnit CalculateBalancedColumnBlockSize( 60 const LogicalSize& column_size, 61 const NGBlockBreakToken* child_break_token); 62 63 // Stretch the column length. We do this during column balancing, when we 64 // discover that the current length isn't large enough to fit all content. 65 LayoutUnit StretchColumnBlockSize(LayoutUnit minimal_space_shortage, 66 LayoutUnit current_column_size) const; 67 68 LayoutUnit ConstrainColumnBlockSize(LayoutUnit size) const; CurrentContentBlockOffset()69 LayoutUnit CurrentContentBlockOffset() const { 70 return intrinsic_block_size_ - border_scrollbar_padding_.block_start; 71 } 72 73 // Finalize layout after breaking before column contents. 74 void FinishAfterBreakBeforeRow( 75 scoped_refptr<const NGBlockBreakToken> next_column_token); 76 77 // Finalize layout after breaking before a spanner. 78 void FinishAfterBreakBeforeSpanner( 79 scoped_refptr<const NGBlockBreakToken> next_column_token); 80 81 // Lay out again, this time with a predefined good breakpoint that we 82 // discovered in the first pass. This happens when we run out of space in a 83 // fragmentainer at an less-than-ideal location, due to breaking restrictions, 84 // such as break-before:avoid or break-after:avoid. 85 scoped_refptr<const NGLayoutResult> RelayoutAndBreakEarlier(); 86 87 NGConstraintSpace CreateConstraintSpaceForColumns( 88 const LogicalSize& column_size, 89 bool is_first_fragmentainer, 90 bool balance_columns) const; 91 NGConstraintSpace CreateConstraintSpaceForBalancing( 92 const LogicalSize& column_size) const; 93 NGConstraintSpace CreateConstraintSpaceForSpanner( 94 const NGBlockNode& spanner, 95 LayoutUnit block_offset) const; 96 NGConstraintSpace CreateConstraintSpaceForMinMax() const; 97 98 // When set, this will specify where to break before or inside. 99 const NGEarlyBreak* early_break_ = nullptr; 100 101 // Border + padding sum, resolved from the node's computed style. 102 const NGBoxStrut border_padding_; 103 104 // Border + scrollbar + padding sum for the fragment to be generated (most 105 // importantly, for non-first fragments, leading block border + scrollbar + 106 // padding is zero). 107 NGBoxStrut border_scrollbar_padding_; 108 109 LogicalSize content_box_size_; 110 int used_column_count_; 111 LayoutUnit column_inline_size_; 112 LayoutUnit column_inline_progression_; 113 LayoutUnit intrinsic_block_size_; 114 bool is_constrained_by_outer_fragmentation_context_ = false; 115 116 // This will be set during (outer) block fragmentation once we've processed 117 // the first piece of content of the multicol container. It is used to check 118 // if we're at a valid class A breakpoint (between block-level siblings). 119 bool has_processed_first_child_ = false; 120 }; 121 122 } // namespace blink 123 124 #endif // THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_NG_NG_COLUMN_LAYOUT_ALGORITHM_H_ 125