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_constraint_space_builder.h" | 9 #include "core/layout/ng/ng_constraint_space_builder.h" |
10 #include "core/layout/ng/ng_fragment.h" | 10 #include "core/layout/ng/ng_fragment.h" |
11 #include "core/layout/ng/ng_length_utils.h" | 11 #include "core/layout/ng/ng_length_utils.h" |
12 #include "core/layout/ng/ng_physical_fragment.h" | 12 #include "core/layout/ng/ng_physical_fragment.h" |
13 #include "core/style/ComputedStyle.h" | 13 #include "core/style/ComputedStyle.h" |
14 | 14 |
15 namespace blink { | 15 namespace blink { |
16 | 16 |
17 NGOutOfFlowLayoutPart::NGOutOfFlowLayoutPart( | 17 NGOutOfFlowLayoutPart::NGOutOfFlowLayoutPart( |
18 PassRefPtr<const ComputedStyle> container_style, | 18 PassRefPtr<const ComputedStyle> container_style, |
19 NGLogicalSize container_size) { | 19 NGLogicalSize container_size) { |
20 contains_fixed_ = container_style->canContainFixedPositionObjects(); | 20 NGWritingMode writing_mode( |
21 contains_absolute_ = | 21 FromPlatformWritingMode(container_style->getWritingMode())); |
22 container_style->canContainAbsolutePositionObjects() || contains_fixed_; | 22 |
23 // Initialize ConstraintSpace | 23 NGBoxStrut borders = ComputeBorders(*container_style); |
| 24 parent_border_offset_ = |
| 25 NGLogicalOffset{borders.inline_start, borders.block_start}; |
| 26 parent_border_physical_offset_ = parent_border_offset_.ConvertToPhysical( |
| 27 writing_mode, container_style->direction(), |
| 28 container_size.ConvertToPhysical(writing_mode), NGPhysicalSize()); |
| 29 |
24 NGLogicalSize space_size = container_size; | 30 NGLogicalSize space_size = container_size; |
25 NGBoxStrut borders = ComputeBorders(*container_style); | |
26 space_size.block_size -= borders.BlockSum(); | 31 space_size.block_size -= borders.BlockSum(); |
27 space_size.inline_size -= borders.InlineSum(); | 32 space_size.inline_size -= borders.InlineSum(); |
28 parent_offset_ = NGLogicalOffset{borders.inline_start, borders.block_start}; | 33 |
29 parent_physical_offset_ = parent_offset_.ConvertToPhysical( | 34 // Initialize ConstraintSpace |
30 FromPlatformWritingMode(container_style->getWritingMode()), | 35 NGConstraintSpaceBuilder space_builder(writing_mode); |
31 container_style->direction(), | |
32 container_size.ConvertToPhysical( | |
33 FromPlatformWritingMode(container_style->getWritingMode())), | |
34 NGPhysicalSize()); | |
35 NGConstraintSpaceBuilder space_builder( | |
36 FromPlatformWritingMode(container_style->getWritingMode())); | |
37 space_builder.SetAvailableSize(space_size); | 36 space_builder.SetAvailableSize(space_size); |
38 space_builder.SetPercentageResolutionSize(space_size); | 37 space_builder.SetPercentageResolutionSize(space_size); |
39 space_builder.SetIsNewFormattingContext(true); | 38 space_builder.SetIsNewFormattingContext(true); |
40 space_builder.SetTextDirection(container_style->direction()); | 39 space_builder.SetTextDirection(container_style->direction()); |
41 parent_space_ = space_builder.ToConstraintSpace(); | 40 parent_space_ = space_builder.ToConstraintSpace(); |
42 } | 41 } |
43 | 42 |
44 bool NGOutOfFlowLayoutPart::StartLayout( | 43 void NGOutOfFlowLayoutPart::Layout(NGBlockNode& node, |
45 NGBlockNode* node, | 44 NGStaticPosition static_position, |
46 const NGStaticPosition& static_position) { | 45 NGFragment** fragment_out, |
47 EPosition position = node->Style()->position(); | 46 NGLogicalOffset* offset) { |
48 if ((contains_absolute_ && position == AbsolutePosition) || | 47 // Adjust the static_position origin. The static_position coordinate origin is |
49 (contains_fixed_ && position == FixedPosition)) { | 48 // relative to the parent's border box, ng_absolute_utils expects it to be |
50 node_ = node; | 49 // relative to the parent's padding box. |
51 static_position_ = static_position; | 50 static_position.offset -= parent_border_physical_offset_; |
52 // Adjust static_position origin. static_position coordinate origin is | 51 |
53 // border_box, absolute position coordinate origin is padding box. | 52 NGFragment* fragment = nullptr; |
54 static_position_.offset -= parent_physical_offset_; | 53 Optional<MinAndMaxContentSizes> inline_estimate; |
55 node_fragment_ = nullptr; | 54 Optional<LayoutUnit> block_estimate; |
56 node_position_ = NGAbsolutePhysicalPosition(); | 55 |
57 inline_estimate_.reset(); | 56 if (AbsoluteNeedsChildInlineSize(*node.Style())) { |
58 block_estimate_.reset(); | 57 inline_estimate = node.ComputeMinAndMaxContentSizesSync(); |
59 state_ = kComputeInlineEstimate; | |
60 return true; | |
61 } | 58 } |
62 return false; | 59 |
| 60 NGAbsolutePhysicalPosition node_position = |
| 61 ComputePartialAbsoluteWithChildInlineSize( |
| 62 *parent_space_, *node.Style(), static_position, inline_estimate); |
| 63 |
| 64 if (AbsoluteNeedsChildBlockSize(*node.Style())) { |
| 65 fragment = GenerateFragment(node, block_estimate, node_position); |
| 66 block_estimate = fragment->BlockSize(); |
| 67 } |
| 68 |
| 69 ComputeFullAbsoluteWithChildBlockSize(*parent_space_, *node.Style(), |
| 70 static_position, block_estimate, |
| 71 &node_position); |
| 72 |
| 73 // Skip this step if we produced a fragment when estimating the block size. |
| 74 if (!fragment) { |
| 75 block_estimate = |
| 76 node_position.size.ConvertToLogical(parent_space_->WritingMode()) |
| 77 .block_size; |
| 78 fragment = GenerateFragment(node, block_estimate, node_position); |
| 79 } |
| 80 |
| 81 *fragment_out = fragment; |
| 82 |
| 83 // Compute logical offset, NGAbsolutePhysicalPosition is calculated relative |
| 84 // to the padding box so add back the parent's borders. |
| 85 NGBoxStrut inset = node_position.inset.ConvertToLogical( |
| 86 parent_space_->WritingMode(), parent_space_->Direction()); |
| 87 offset->inline_offset = |
| 88 inset.inline_start + parent_border_offset_.inline_offset; |
| 89 offset->block_offset = inset.block_start + parent_border_offset_.block_offset; |
63 } | 90 } |
64 | 91 |
65 NGLayoutStatus NGOutOfFlowLayoutPart::Layout(NGFragment** fragment, | 92 NGFragment* NGOutOfFlowLayoutPart::GenerateFragment( |
66 NGLogicalOffset* offset) { | 93 NGBlockNode& node, |
67 DCHECK(node_); | 94 const Optional<LayoutUnit>& block_estimate, |
68 switch (state_) { | 95 const NGAbsolutePhysicalPosition node_position) { |
69 case kComputeInlineEstimate: | 96 // The fragment is generated in one of these two scenarios: |
70 if (ComputeInlineSizeEstimate()) | 97 // 1. To estimate child's block size, in this case block_size is parent's |
71 state_ = kPartialPosition; | 98 // available size. |
72 break; | 99 // 2. To compute final fragment, when block size is known from the absolute |
73 case kPartialPosition: | 100 // position calculation. |
74 node_position_ = ComputePartialAbsoluteWithChildInlineSize( | 101 LayoutUnit inline_size = |
75 *parent_space_, *node_->Style(), static_position_, inline_estimate_); | 102 node_position.size.ConvertToLogical(parent_space_->WritingMode()) |
76 state_ = kComputeBlockEstimate; | 103 .inline_size; |
77 break; | 104 LayoutUnit block_size = block_estimate |
78 case kComputeBlockEstimate: | 105 ? *block_estimate |
79 if (ComputeBlockSizeEstimate()) | 106 : parent_space_->AvailableSize().block_size; |
80 state_ = kFullPosition; | |
81 break; | |
82 case kFullPosition: | |
83 ComputeFullAbsoluteWithChildBlockSize(*parent_space_, *node_->Style(), | |
84 static_position_, block_estimate_, | |
85 &node_position_); | |
86 state_ = kGenerateFragment; | |
87 break; | |
88 case kGenerateFragment: | |
89 block_estimate_ = | |
90 node_position_.size.ConvertToLogical(parent_space_->WritingMode()) | |
91 .block_size; | |
92 if (!ComputeNodeFragment()) | |
93 return kNotFinished; | |
94 state_ = kDone; | |
95 break; | |
96 case kDone: | |
97 *fragment = node_fragment_; | |
98 // Compute offset | |
99 NGBoxStrut inset = node_position_.inset.ConvertToLogical( | |
100 parent_space_->WritingMode(), parent_space_->Direction()); | |
101 offset->inline_offset = inset.inline_start + parent_offset_.inline_offset; | |
102 offset->block_offset = inset.block_start + parent_offset_.block_offset; | |
103 return kNewFragment; | |
104 } | |
105 return kNotFinished; | |
106 } | |
107 | 107 |
108 bool NGOutOfFlowLayoutPart::ComputeInlineSizeEstimate() { | 108 NGLogicalSize available_size{inline_size, block_size}; |
109 if (AbsoluteNeedsChildInlineSize(*node_->Style())) { | |
110 MinAndMaxContentSizes size; | |
111 if (node_->ComputeMinAndMaxContentSizes(&size)) { | |
112 inline_estimate_ = size; | |
113 return true; | |
114 } | |
115 return false; | |
116 } | |
117 return true; | |
118 } | |
119 | 109 |
120 bool NGOutOfFlowLayoutPart::ComputeBlockSizeEstimate() { | 110 NGConstraintSpaceBuilder builder(parent_space_->WritingMode()); |
121 if (AbsoluteNeedsChildBlockSize(*node_->Style())) { | 111 builder.SetAvailableSize(available_size); |
122 if (ComputeNodeFragment()) { | 112 builder.SetPercentageResolutionSize(parent_space_->AvailableSize()); |
123 block_estimate_ = node_fragment_->BlockSize(); | 113 if (block_estimate) |
124 return true; | 114 builder.SetIsFixedSizeBlock(true); |
125 } | 115 builder.SetIsFixedSizeInline(true); |
126 return false; | 116 builder.SetIsNewFormattingContext(true); |
127 } | 117 NGConstraintSpace* space = builder.ToConstraintSpace(); |
128 return true; | |
129 } | |
130 | 118 |
131 bool NGOutOfFlowLayoutPart::ComputeNodeFragment() { | |
132 if (node_fragment_) | |
133 return true; | |
134 if (!node_space_) { | |
135 NGConstraintSpaceBuilder builder(parent_space_->WritingMode()); | |
136 LayoutUnit inline_width = | |
137 node_position_.size.ConvertToLogical(parent_space_->WritingMode()) | |
138 .inline_size; | |
139 // Node fragment is computed in one of these two scenarios: | |
140 // 1. To estimate block size | |
141 // In this case, available block_size is parent's size. | |
142 // 2. To compute final block fragment, when block size is known. | |
143 | |
144 NGLogicalSize available_size = | |
145 NGLogicalSize(inline_width, parent_space_->AvailableSize().block_size); | |
146 if (block_estimate_) | |
147 available_size.block_size = *block_estimate_; | |
148 builder.SetAvailableSize(available_size); | |
149 builder.SetPercentageResolutionSize(parent_space_->AvailableSize()); | |
150 if (block_estimate_) | |
151 builder.SetIsFixedSizeBlock(true); | |
152 builder.SetIsFixedSizeInline(true); | |
153 builder.SetIsNewFormattingContext(true); | |
154 node_space_ = builder.ToConstraintSpace(); | |
155 } | |
156 NGFragment* fragment; | 119 NGFragment* fragment; |
157 if (node_->Layout(node_space_, &fragment)) { | 120 node.LayoutSync(space, &fragment); |
158 node_fragment_ = fragment; | 121 return fragment; |
159 return true; | |
160 } | |
161 return false; | |
162 } | 122 } |
163 | 123 |
164 DEFINE_TRACE(NGOutOfFlowLayoutPart) { | 124 DEFINE_TRACE(NGOutOfFlowLayoutPart) { |
165 visitor->trace(node_); | |
166 visitor->trace(parent_space_); | 125 visitor->trace(parent_space_); |
167 visitor->trace(node_fragment_); | |
168 visitor->trace(node_space_); | |
169 } | 126 } |
170 } | 127 |
| 128 } // namespace blink |
OLD | NEW |