OLD | NEW |
1 // Copyright 2016 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "core/layout/ng/ng_out_of_flow_layout_part.h" | 5 #include "core/layout/ng/ng_out_of_flow_layout_part.h" |
6 | 6 |
7 #include "core/layout/ng/ng_absolute_utils.h" | 7 #include "core/layout/ng/ng_absolute_utils.h" |
8 #include "core/layout/ng/ng_block_node.h" | 8 #include "core/layout/ng/ng_block_node.h" |
9 #include "core/layout/ng/ng_box_fragment.h" | 9 #include "core/layout/ng/ng_box_fragment.h" |
10 #include "core/layout/ng/ng_constraint_space_builder.h" | 10 #include "core/layout/ng/ng_constraint_space_builder.h" |
11 #include "core/layout/ng/ng_fragment.h" | 11 #include "core/layout/ng/ng_fragment.h" |
| 12 #include "core/layout/ng/ng_fragment_builder.h" |
12 #include "core/layout/ng/ng_length_utils.h" | 13 #include "core/layout/ng/ng_length_utils.h" |
13 #include "core/layout/ng/ng_physical_fragment.h" | 14 #include "core/layout/ng/ng_physical_fragment.h" |
14 #include "core/style/ComputedStyle.h" | 15 #include "core/style/ComputedStyle.h" |
15 | 16 |
16 namespace blink { | 17 namespace blink { |
17 | 18 |
| 19 namespace { |
| 20 |
| 21 // True if the container will contain an absolute descendant. |
| 22 bool IsContainingBlockForAbsoluteDescendant( |
| 23 const ComputedStyle& container_style, |
| 24 const ComputedStyle& descendant_style) { |
| 25 EPosition position = descendant_style.position(); |
| 26 bool contains_fixed = container_style.canContainFixedPositionObjects(); |
| 27 bool contains_absolute = |
| 28 container_style.canContainAbsolutePositionObjects() || contains_fixed; |
| 29 |
| 30 return (contains_absolute && position == AbsolutePosition) || |
| 31 (contains_fixed && position == FixedPosition); |
| 32 } |
| 33 |
| 34 } // namespace |
| 35 |
18 NGOutOfFlowLayoutPart::NGOutOfFlowLayoutPart( | 36 NGOutOfFlowLayoutPart::NGOutOfFlowLayoutPart( |
19 PassRefPtr<const ComputedStyle> container_style, | 37 const ComputedStyle& container_style, |
20 NGLogicalSize container_size) { | 38 NGFragmentBuilder* container_builder) |
| 39 : container_style_(container_style), container_builder_(container_builder) { |
21 NGWritingMode writing_mode( | 40 NGWritingMode writing_mode( |
22 FromPlatformWritingMode(container_style->getWritingMode())); | 41 FromPlatformWritingMode(container_style_.getWritingMode())); |
23 | 42 |
24 NGBoxStrut borders = ComputeBorders(*container_style); | 43 NGBoxStrut borders = ComputeBorders(container_style_); |
25 parent_border_offset_ = | 44 container_border_offset_ = |
26 NGLogicalOffset{borders.inline_start, borders.block_start}; | 45 NGLogicalOffset{borders.inline_start, borders.block_start}; |
27 parent_border_physical_offset_ = parent_border_offset_.ConvertToPhysical( | 46 container_border_physical_offset_ = |
28 writing_mode, container_style->direction(), | 47 container_border_offset_.ConvertToPhysical( |
29 container_size.ConvertToPhysical(writing_mode), NGPhysicalSize()); | 48 writing_mode, container_style_.direction(), |
| 49 container_builder_->Size().ConvertToPhysical(writing_mode), |
| 50 NGPhysicalSize()); |
30 | 51 |
31 NGLogicalSize space_size = container_size; | 52 NGLogicalSize space_size = container_builder_->Size(); |
32 space_size.block_size -= borders.BlockSum(); | 53 space_size.block_size -= borders.BlockSum(); |
33 space_size.inline_size -= borders.InlineSum(); | 54 space_size.inline_size -= borders.InlineSum(); |
34 | 55 |
35 // Initialize ConstraintSpace | 56 // Initialize ConstraintSpace |
36 NGConstraintSpaceBuilder space_builder(writing_mode); | 57 NGConstraintSpaceBuilder space_builder(writing_mode); |
37 space_builder.SetAvailableSize(space_size); | 58 space_builder.SetAvailableSize(space_size); |
38 space_builder.SetPercentageResolutionSize(space_size); | 59 space_builder.SetPercentageResolutionSize(space_size); |
39 space_builder.SetIsNewFormattingContext(true); | 60 space_builder.SetIsNewFormattingContext(true); |
40 space_builder.SetTextDirection(container_style->direction()); | 61 space_builder.SetTextDirection(container_style_.direction()); |
41 parent_space_ = space_builder.ToConstraintSpace(); | 62 container_space_ = space_builder.ToConstraintSpace(); |
42 } | 63 } |
43 | 64 |
44 void NGOutOfFlowLayoutPart::Layout(NGBlockNode& node, | 65 void NGOutOfFlowLayoutPart::Run() { |
45 NGStaticPosition static_position, | 66 HeapLinkedHashSet<WeakMember<NGBlockNode>> out_of_flow_candidates; |
46 NGFragment** fragment_out, | 67 Vector<NGStaticPosition> out_of_flow_candidate_positions; |
47 NGLogicalOffset* offset) { | 68 container_builder_->GetAndClearOutOfFlowDescendantCandidates( |
| 69 &out_of_flow_candidates, &out_of_flow_candidate_positions); |
| 70 |
| 71 size_t position_index = 0; |
| 72 |
| 73 for (auto& descendant : out_of_flow_candidates) { |
| 74 NGStaticPosition static_position = |
| 75 out_of_flow_candidate_positions[position_index++]; |
| 76 |
| 77 if (IsContainingBlockForAbsoluteDescendant(container_style_, |
| 78 *descendant->Style())) { |
| 79 NGLogicalOffset offset; |
| 80 NGFragment* fragment = |
| 81 LayoutDescendant(*descendant, static_position, &offset); |
| 82 // TODO(atotic) Need to adjust size of overflow rect per spec. |
| 83 container_builder_->AddChild(fragment, offset); |
| 84 } else { |
| 85 container_builder_->AddOutOfFlowDescendant(descendant, static_position); |
| 86 } |
| 87 } |
| 88 } |
| 89 |
| 90 NGFragment* NGOutOfFlowLayoutPart::LayoutDescendant( |
| 91 NGBlockNode& descendant, |
| 92 NGStaticPosition static_position, |
| 93 NGLogicalOffset* offset) { |
48 // Adjust the static_position origin. The static_position coordinate origin is | 94 // Adjust the static_position origin. The static_position coordinate origin is |
49 // relative to the parent's border box, ng_absolute_utils expects it to be | 95 // relative to the container's border box, ng_absolute_utils expects it to be |
50 // relative to the parent's padding box. | 96 // relative to the container's padding box. |
51 static_position.offset -= parent_border_physical_offset_; | 97 static_position.offset -= container_border_physical_offset_; |
52 | 98 |
53 NGFragment* fragment = nullptr; | 99 NGFragment* fragment = nullptr; |
54 Optional<MinAndMaxContentSizes> inline_estimate; | 100 Optional<MinAndMaxContentSizes> inline_estimate; |
55 Optional<LayoutUnit> block_estimate; | 101 Optional<LayoutUnit> block_estimate; |
56 | 102 |
57 if (AbsoluteNeedsChildInlineSize(*node.Style())) { | 103 if (AbsoluteNeedsChildInlineSize(*descendant.Style())) { |
58 inline_estimate = node.ComputeMinAndMaxContentSizesSync(); | 104 inline_estimate = descendant.ComputeMinAndMaxContentSizesSync(); |
59 } | 105 } |
60 | 106 |
61 NGAbsolutePhysicalPosition node_position = | 107 NGAbsolutePhysicalPosition node_position = |
62 ComputePartialAbsoluteWithChildInlineSize( | 108 ComputePartialAbsoluteWithChildInlineSize( |
63 *parent_space_, *node.Style(), static_position, inline_estimate); | 109 *container_space_, *descendant.Style(), static_position, |
| 110 inline_estimate); |
64 | 111 |
65 if (AbsoluteNeedsChildBlockSize(*node.Style())) { | 112 if (AbsoluteNeedsChildBlockSize(*descendant.Style())) { |
66 fragment = GenerateFragment(node, block_estimate, node_position); | 113 fragment = GenerateFragment(descendant, block_estimate, node_position); |
67 block_estimate = fragment->BlockSize(); | 114 block_estimate = fragment->BlockSize(); |
68 } | 115 } |
69 | 116 |
70 ComputeFullAbsoluteWithChildBlockSize(*parent_space_, *node.Style(), | 117 ComputeFullAbsoluteWithChildBlockSize(*container_space_, *descendant.Style(), |
71 static_position, block_estimate, | 118 static_position, block_estimate, |
72 &node_position); | 119 &node_position); |
73 | 120 |
74 // Skip this step if we produced a fragment when estimating the block size. | 121 // Skip this step if we produced a fragment when estimating the block size. |
75 if (!fragment) { | 122 if (!fragment) { |
76 block_estimate = | 123 block_estimate = |
77 node_position.size.ConvertToLogical(parent_space_->WritingMode()) | 124 node_position.size.ConvertToLogical(container_space_->WritingMode()) |
78 .block_size; | 125 .block_size; |
79 fragment = GenerateFragment(node, block_estimate, node_position); | 126 fragment = GenerateFragment(descendant, block_estimate, node_position); |
80 } | 127 } |
81 | 128 |
82 *fragment_out = fragment; | 129 // Compute logical offset, NGAbsolutePhysicalPosition is calculated relative |
| 130 // to the padding box so add back the container's borders. |
| 131 NGBoxStrut inset = node_position.inset.ConvertToLogical( |
| 132 container_space_->WritingMode(), container_space_->Direction()); |
| 133 offset->inline_offset = |
| 134 inset.inline_start + container_border_offset_.inline_offset; |
| 135 offset->block_offset = |
| 136 inset.block_start + container_border_offset_.block_offset; |
83 | 137 |
84 // Compute logical offset, NGAbsolutePhysicalPosition is calculated relative | 138 return fragment; |
85 // to the padding box so add back the parent's borders. | |
86 NGBoxStrut inset = node_position.inset.ConvertToLogical( | |
87 parent_space_->WritingMode(), parent_space_->Direction()); | |
88 offset->inline_offset = | |
89 inset.inline_start + parent_border_offset_.inline_offset; | |
90 offset->block_offset = inset.block_start + parent_border_offset_.block_offset; | |
91 } | 139 } |
92 | 140 |
93 NGFragment* NGOutOfFlowLayoutPart::GenerateFragment( | 141 NGFragment* NGOutOfFlowLayoutPart::GenerateFragment( |
94 NGBlockNode& node, | 142 NGBlockNode& descendant, |
95 const Optional<LayoutUnit>& block_estimate, | 143 const Optional<LayoutUnit>& block_estimate, |
96 const NGAbsolutePhysicalPosition node_position) { | 144 const NGAbsolutePhysicalPosition node_position) { |
97 // The fragment is generated in one of these two scenarios: | 145 // The fragment is generated in one of these two scenarios: |
98 // 1. To estimate child's block size, in this case block_size is parent's | 146 // 1. To estimate descendant's block size, in this case block_size is |
99 // available size. | 147 // container's available size. |
100 // 2. To compute final fragment, when block size is known from the absolute | 148 // 2. To compute final fragment, when block size is known from the absolute |
101 // position calculation. | 149 // position calculation. |
102 LayoutUnit inline_size = | 150 LayoutUnit inline_size = |
103 node_position.size.ConvertToLogical(parent_space_->WritingMode()) | 151 node_position.size.ConvertToLogical(container_space_->WritingMode()) |
104 .inline_size; | 152 .inline_size; |
105 LayoutUnit block_size = block_estimate | 153 LayoutUnit block_size = block_estimate |
106 ? *block_estimate | 154 ? *block_estimate |
107 : parent_space_->AvailableSize().block_size; | 155 : container_space_->AvailableSize().block_size; |
108 | 156 |
109 NGLogicalSize available_size{inline_size, block_size}; | 157 NGLogicalSize available_size{inline_size, block_size}; |
110 | 158 |
111 NGConstraintSpaceBuilder builder(parent_space_->WritingMode()); | 159 NGConstraintSpaceBuilder builder(container_space_->WritingMode()); |
112 builder.SetAvailableSize(available_size); | 160 builder.SetAvailableSize(available_size); |
113 builder.SetPercentageResolutionSize(parent_space_->AvailableSize()); | 161 builder.SetPercentageResolutionSize(container_space_->AvailableSize()); |
114 if (block_estimate) | 162 if (block_estimate) |
115 builder.SetIsFixedSizeBlock(true); | 163 builder.SetIsFixedSizeBlock(true); |
116 builder.SetIsFixedSizeInline(true); | 164 builder.SetIsFixedSizeInline(true); |
117 builder.SetIsNewFormattingContext(true); | 165 builder.SetIsNewFormattingContext(true); |
118 NGConstraintSpace* space = builder.ToConstraintSpace(); | 166 NGConstraintSpace* space = builder.ToConstraintSpace(); |
119 | 167 |
120 NGPhysicalFragment* fragment = node.Layout(space); | 168 NGPhysicalFragment* fragment = descendant.Layout(space); |
121 | 169 |
122 // TODO(ikilpatrick): the writing mode switching here looks wrong. | 170 // TODO(ikilpatrick): the writing mode switching here looks wrong. |
123 return new NGBoxFragment(parent_space_->WritingMode(), | 171 return new NGBoxFragment(container_space_->WritingMode(), |
124 parent_space_->Direction(), | 172 container_space_->Direction(), |
125 toNGPhysicalBoxFragment(fragment)); | 173 toNGPhysicalBoxFragment(fragment)); |
126 } | 174 } |
127 | 175 |
128 DEFINE_TRACE(NGOutOfFlowLayoutPart) { | |
129 visitor->trace(parent_space_); | |
130 } | |
131 | |
132 } // namespace blink | 176 } // namespace blink |
OLD | NEW |