1 // Copyright 2016 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_OUT_OF_FLOW_LAYOUT_PART_H_
6 #define THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_NG_NG_OUT_OF_FLOW_LAYOUT_PART_H_
7 
8 #include "third_party/blink/renderer/core/core_export.h"
9 
10 #include "base/optional.h"
11 #include "third_party/blink/renderer/core/layout/geometry/physical_offset.h"
12 #include "third_party/blink/renderer/core/layout/ng/ng_absolute_utils.h"
13 #include "third_party/blink/renderer/core/layout/ng/ng_constraint_space.h"
14 #include "third_party/blink/renderer/core/style/computed_style_base_constants.h"
15 #include "third_party/blink/renderer/platform/wtf/hash_map.h"
16 #include "third_party/blink/renderer/platform/wtf/hash_set.h"
17 
18 namespace blink {
19 
20 class ComputedStyle;
21 class LayoutBox;
22 class LayoutObject;
23 class NGBlockBreakToken;
24 class NGBlockNode;
25 class NGBoxFragmentBuilder;
26 class NGLayoutResult;
27 class NGPhysicalContainerFragment;
28 struct NGLogicalOutOfFlowPositionedNode;
29 
30 // Helper class for positioning of out-of-flow blocks.
31 // It should be used together with NGBoxFragmentBuilder.
32 // See NGBoxFragmentBuilder::AddOutOfFlowChildCandidate documentation
33 // for example of using these classes together.
34 class CORE_EXPORT NGOutOfFlowLayoutPart {
35   STACK_ALLOCATED();
36 
37  public:
38   NGOutOfFlowLayoutPart(const NGBlockNode& container_node,
39                         const NGConstraintSpace& container_space,
40                         NGBoxFragmentBuilder* container_builder);
41 
42   // The |container_builder|, |container_space|, and |container_style|
43   // parameters are all with respect to the containing block of the relevant
44   // out-of-flow positioned descendants. If the CSS "containing block" of such
45   // an out-of-flow positioned descendant isn't a true block (e.g. a relatively
46   // positioned inline instead), the containing block here is the containing
47   // block of said non-block.
48   NGOutOfFlowLayoutPart(
49       bool is_absolute_container,
50       bool is_fixed_container,
51       const ComputedStyle& container_style,
52       const NGConstraintSpace& container_space,
53       NGBoxFragmentBuilder* container_builder,
54       base::Optional<LogicalSize> initial_containing_block_fixed_size =
55           base::nullopt);
56 
57   // Normally this function lays out and positions all out-of-flow objects from
58   // the container_builder and additional ones it discovers through laying out
59   // those objects. However, if only_layout is specified, only that object will
60   // get laid out; any additional ones will be stored as out-of-flow
61   // descendants in the builder for use via
62   // LayoutResult::OutOfFlowPositionedDescendants.
63   void Run(const LayoutBox* only_layout = nullptr);
64 
65  private:
66   // Information needed to position descendant within a containing block.
67   // Geometry expressed here is complicated:
68   // There are two types of containing blocks:
69   // 1) Default containing block (DCB)
70   //    Containing block passed in NGOutOfFlowLayoutPart constructor.
71   //    It is the block element inside which this algorighm runs.
72   //    All OOF descendants not in inline containing block are placed in DCB.
73   // 2) Inline containing block
74   //    OOF descendants might be positioned wrt inline containing block.
75   //    Inline containing block is positioned wrt default containing block.
76   struct ContainingBlockInfo {
77     STACK_ALLOCATED();
78 
79    public:
80     // The writing direction of the container.
81     WritingDirectionMode writing_direction = {WritingMode::kHorizontalTb,
82                                               TextDirection::kLtr};
83     // Logical in containing block coordinates.
84     LogicalSize content_size_for_absolute;
85     // Content size for fixed is different for the ICB.
86     LogicalSize content_size_for_fixed;
87 
88     // Offset of the container's padding-box.
89     LogicalOffset container_offset;
90 
ContentSizeContainingBlockInfo91     LogicalSize ContentSize(EPosition position) const {
92       return position == EPosition::kAbsolute ? content_size_for_absolute
93                                               : content_size_for_fixed;
94     }
95   };
96 
97   bool SweepLegacyCandidates(HashSet<const LayoutObject*>* placed_objects);
98 
99   const ContainingBlockInfo& GetContainingBlockInfo(
100       const NGLogicalOutOfFlowPositionedNode&,
101       const NGPhysicalContainerFragment* = nullptr);
102 
103   void ComputeInlineContainingBlocks(
104       const Vector<NGLogicalOutOfFlowPositionedNode>&);
105 
106   void LayoutCandidates(Vector<NGLogicalOutOfFlowPositionedNode>* candidates,
107                         const LayoutBox* only_layout,
108                         HashSet<const LayoutObject*>* placed_objects);
109 
110   scoped_refptr<const NGLayoutResult> LayoutCandidate(
111       const NGLogicalOutOfFlowPositionedNode&,
112       const LayoutBox* only_layout);
113 
114   void LayoutFragmentainerDescendants(
115       Vector<NGLogicalOutOfFlowPositionedNode>* descendants);
116 
117   void LayoutFragmentainerDescendant(const NGLogicalOutOfFlowPositionedNode&);
118 
119   scoped_refptr<const NGLayoutResult> Layout(
120       NGBlockNode,
121       const NGConstraintSpace&,
122       const NGLogicalStaticPosition&,
123       PhysicalSize container_physical_content_size,
124       const ContainingBlockInfo&,
125       const WritingDirectionMode,
126       const LayoutBox* only_layout,
127       bool is_fragmentainer_descendant = false);
128 
129   bool IsContainingBlockForCandidate(const NGLogicalOutOfFlowPositionedNode&);
130 
131   scoped_refptr<const NGLayoutResult> GenerateFragment(
132       NGBlockNode node,
133       const LogicalSize& container_content_size_in_child_writing_mode,
134       const base::Optional<LayoutUnit>& block_estimate,
135       const NGLogicalOutOfFlowDimensions& node_dimensions,
136       const LayoutUnit block_offset,
137       const NGBlockBreakToken* break_token,
138       const NGConstraintSpace* fragmentainer_constraint_space);
139   void AddOOFResultsToFragmentainer(
140       const Vector<scoped_refptr<const NGLayoutResult>>& results,
141       wtf_size_t index);
142   const NGConstraintSpace& GetFragmentainerConstraintSpace(wtf_size_t index);
143   void AddOOFResultToFragmentainerResults(
144       const scoped_refptr<const NGLayoutResult> result,
145       wtf_size_t index);
146   void ComputeStartFragmentIndexAndRelativeOffset(
147       const ContainingBlockInfo& container_info,
148       WritingMode default_writing_mode,
149       wtf_size_t* start_index,
150       LogicalOffset* offset) const;
151 
152   NGBoxFragmentBuilder* container_builder_;
153   ContainingBlockInfo default_containing_block_;
154   HashMap<const LayoutObject*, ContainingBlockInfo> containing_blocks_map_;
155   HashMap<wtf_size_t, NGConstraintSpace> fragmentainer_constraint_space_map_;
156   // Map of fragmentainer indexes to a list of descendant layout results to
157   // be added as children.
158   HashMap<wtf_size_t, Vector<scoped_refptr<const NGLayoutResult>>>
159       fragmentainer_descendant_results_;
160   const WritingMode writing_mode_;
161   LayoutUnit column_inline_progression_ = kIndefiniteSize;
162   // The block size of the multi-column (before adjustment for spanners, etc.)
163   // This is used to calculate the column size of any newly added proxy
164   // fragments when handling fragmentation for abspos elements.
165   LayoutUnit original_column_block_size_ = kIndefiniteSize;
166   bool is_absolute_container_;
167   bool is_fixed_container_;
168   bool allow_first_tier_oof_cache_;
169   bool has_block_fragmentation_;
170 };
171 
172 }  // namespace blink
173 
174 #endif  // THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_NG_NG_OUT_OF_FLOW_LAYOUT_PART_H_
175