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_block_node.h" | 5 #include "core/layout/ng/ng_block_node.h" |
6 | 6 |
7 #include "core/layout/LayoutBlockFlow.h" | 7 #include "core/layout/LayoutBlockFlow.h" |
8 #include "core/layout/api/LineLayoutAPIShim.h" | 8 #include "core/layout/api/LineLayoutAPIShim.h" |
9 #include "core/layout/line/InlineIterator.h" | 9 #include "core/layout/line/InlineIterator.h" |
10 #include "core/layout/ng/layout_ng_block_flow.h" | 10 #include "core/layout/ng/layout_ng_block_flow.h" |
11 #include "core/layout/ng/ng_block_layout_algorithm.h" | 11 #include "core/layout/ng/ng_block_layout_algorithm.h" |
12 #include "core/layout/ng/ng_box_fragment.h" | 12 #include "core/layout/ng/ng_box_fragment.h" |
13 #include "core/layout/ng/ng_constraint_space.h" | 13 #include "core/layout/ng/ng_constraint_space.h" |
14 #include "core/layout/ng/ng_constraint_space_builder.h" | 14 #include "core/layout/ng/ng_constraint_space_builder.h" |
15 #include "core/layout/ng/ng_fragment_builder.h" | 15 #include "core/layout/ng/ng_fragment_builder.h" |
16 #include "core/layout/ng/ng_inline_node.h" | 16 #include "core/layout/ng/ng_inline_node.h" |
| 17 #include "core/layout/ng/ng_layout_result.h" |
17 #include "core/layout/ng/ng_length_utils.h" | 18 #include "core/layout/ng/ng_length_utils.h" |
18 #include "core/layout/ng/ng_writing_mode.h" | 19 #include "core/layout/ng/ng_writing_mode.h" |
19 #include "core/paint/PaintLayer.h" | 20 #include "core/paint/PaintLayer.h" |
20 #include "platform/RuntimeEnabledFeatures.h" | 21 #include "platform/RuntimeEnabledFeatures.h" |
21 | 22 |
22 namespace blink { | 23 namespace blink { |
23 | 24 |
24 namespace { | 25 namespace { |
25 | 26 |
26 // Copies data back to the legacy layout tree for a given child fragment. | 27 // Copies data back to the legacy layout tree for a given child fragment. |
27 void FragmentPositionUpdated(const NGPhysicalBoxFragment& box_fragment) { | 28 void FragmentPositionUpdated(const NGPhysicalFragment& fragment) { |
28 LayoutBox* layout_box = toLayoutBox(box_fragment.GetLayoutObject()); | 29 LayoutBox* layout_box = toLayoutBox(fragment.GetLayoutObject()); |
29 if (!layout_box) | 30 if (!layout_box) |
30 return; | 31 return; |
31 | 32 |
32 DCHECK(layout_box->parent()) << "Should be called on children only."; | 33 DCHECK(layout_box->parent()) << "Should be called on children only."; |
33 | 34 |
34 layout_box->setX(box_fragment.LeftOffset()); | 35 layout_box->setX(fragment.LeftOffset()); |
35 layout_box->setY(box_fragment.TopOffset()); | 36 layout_box->setY(fragment.TopOffset()); |
36 } | 37 } |
37 | 38 |
38 // Similar to FragmentPositionUpdated but for floats. | 39 // Similar to FragmentPositionUpdated but for floats. |
39 // - Updates layout object's geometric information. | 40 // - Updates layout object's geometric information. |
40 // - Creates legacy FloatingObject and attached it to the provided parent. | 41 // - Creates legacy FloatingObject and attached it to the provided parent. |
41 void FloatingObjectPositionedUpdated(NGFloatingObject* ng_floating_object, | 42 void FloatingObjectPositionedUpdated(NGFloatingObject* ng_floating_object, |
42 LayoutBox* parent) { | 43 LayoutBox* parent) { |
43 NGPhysicalBoxFragment* box_fragment = | 44 NGPhysicalBoxFragment* box_fragment = |
44 toNGPhysicalBoxFragment(ng_floating_object->fragment.get()); | 45 toNGPhysicalBoxFragment(ng_floating_object->fragment.get()); |
45 FragmentPositionUpdated(*box_fragment); | 46 FragmentPositionUpdated(*box_fragment); |
(...skipping 23 matching lines...) Expand all Loading... |
69 layout_box_(nullptr), | 70 layout_box_(nullptr), |
70 style_(style) { | 71 style_(style) { |
71 DCHECK(style_); | 72 DCHECK(style_); |
72 } | 73 } |
73 | 74 |
74 // Need an explicit destructor in the .cc file, or the MSWIN compiler will | 75 // Need an explicit destructor in the .cc file, or the MSWIN compiler will |
75 // produce an error when attempting to generate a default one, if the .h file is | 76 // produce an error when attempting to generate a default one, if the .h file is |
76 // included from a compilation unit that lacks the ComputedStyle definition. | 77 // included from a compilation unit that lacks the ComputedStyle definition. |
77 NGBlockNode::~NGBlockNode() {} | 78 NGBlockNode::~NGBlockNode() {} |
78 | 79 |
79 RefPtr<NGPhysicalFragment> NGBlockNode::Layout( | 80 RefPtr<NGLayoutResult> NGBlockNode::Layout( |
80 NGConstraintSpace* constraint_space) { | 81 NGConstraintSpace* constraint_space) { |
81 // Use the old layout code and synthesize a fragment. | 82 // Use the old layout code and synthesize a fragment. |
82 if (!CanUseNewLayout()) { | 83 if (!CanUseNewLayout()) { |
83 DCHECK(layout_box_); | 84 DCHECK(layout_box_); |
84 fragment_ = RunOldLayout(*constraint_space); | 85 layout_result_ = RunOldLayout(*constraint_space); |
85 return fragment_; | 86 return layout_result_; |
86 } | 87 } |
87 | 88 |
88 RefPtr<NGPhysicalFragment> fragment = | 89 layout_result_ = |
89 NGBlockLayoutAlgorithm(GetLayoutObject(), &Style(), FirstChild(), | 90 NGBlockLayoutAlgorithm(GetLayoutObject(), &Style(), FirstChild(), |
90 constraint_space, CurrentBreakToken()) | 91 constraint_space, CurrentBreakToken()) |
91 .Layout(); | 92 .Layout(); |
92 | 93 |
93 fragment_ = toNGPhysicalBoxFragment(fragment.get()); | |
94 CopyFragmentDataToLayoutBox(*constraint_space); | 94 CopyFragmentDataToLayoutBox(*constraint_space); |
95 return fragment_; | 95 return layout_result_; |
96 } | 96 } |
97 | 97 |
98 MinAndMaxContentSizes NGBlockNode::ComputeMinAndMaxContentSizes() { | 98 MinAndMaxContentSizes NGBlockNode::ComputeMinAndMaxContentSizes() { |
99 MinAndMaxContentSizes sizes; | 99 MinAndMaxContentSizes sizes; |
100 if (!CanUseNewLayout()) { | 100 if (!CanUseNewLayout()) { |
101 DCHECK(layout_box_); | 101 DCHECK(layout_box_); |
102 // TODO(layout-ng): This could be somewhat optimized by directly calling | 102 // TODO(layout-ng): This could be somewhat optimized by directly calling |
103 // computeIntrinsicLogicalWidths, but that function is currently private. | 103 // computeIntrinsicLogicalWidths, but that function is currently private. |
104 // Consider doing that if this becomes a performance issue. | 104 // Consider doing that if this becomes a performance issue. |
105 LayoutUnit borderAndPadding = layout_box_->borderAndPaddingLogicalWidth(); | 105 LayoutUnit borderAndPadding = layout_box_->borderAndPaddingLogicalWidth(); |
(...skipping 16 matching lines...) Expand all Loading... |
122 | 122 |
123 // TODO(cbiesinger): For orthogonal children, we need to always synthesize. | 123 // TODO(cbiesinger): For orthogonal children, we need to always synthesize. |
124 NGBlockLayoutAlgorithm minmax_algorithm(layout_box_, &Style(), FirstChild(), | 124 NGBlockLayoutAlgorithm minmax_algorithm(layout_box_, &Style(), FirstChild(), |
125 constraint_space); | 125 constraint_space); |
126 Optional<MinAndMaxContentSizes> maybe_sizes = | 126 Optional<MinAndMaxContentSizes> maybe_sizes = |
127 minmax_algorithm.ComputeMinAndMaxContentSizes(); | 127 minmax_algorithm.ComputeMinAndMaxContentSizes(); |
128 if (maybe_sizes.has_value()) | 128 if (maybe_sizes.has_value()) |
129 return *maybe_sizes; | 129 return *maybe_sizes; |
130 | 130 |
131 // Have to synthesize this value. | 131 // Have to synthesize this value. |
132 RefPtr<NGPhysicalFragment> physical_fragment = Layout(constraint_space); | 132 RefPtr<NGLayoutResult> layout_result = Layout(constraint_space); |
| 133 NGPhysicalFragment* physical_fragment = |
| 134 layout_result->PhysicalFragment().get(); |
133 NGBoxFragment min_fragment(FromPlatformWritingMode(Style().getWritingMode()), | 135 NGBoxFragment min_fragment(FromPlatformWritingMode(Style().getWritingMode()), |
134 toNGPhysicalBoxFragment(physical_fragment.get())); | 136 toNGPhysicalBoxFragment(physical_fragment)); |
135 sizes.min_content = min_fragment.InlineOverflow(); | 137 sizes.min_content = min_fragment.InlineOverflow(); |
136 | 138 |
137 // Now, redo with infinite space for max_content | 139 // Now, redo with infinite space for max_content |
138 constraint_space = | 140 constraint_space = |
139 NGConstraintSpaceBuilder( | 141 NGConstraintSpaceBuilder( |
140 FromPlatformWritingMode(Style().getWritingMode())) | 142 FromPlatformWritingMode(Style().getWritingMode())) |
141 .SetTextDirection(Style().direction()) | 143 .SetTextDirection(Style().direction()) |
142 .SetAvailableSize({LayoutUnit::max(), LayoutUnit()}) | 144 .SetAvailableSize({LayoutUnit::max(), LayoutUnit()}) |
143 .SetPercentageResolutionSize({LayoutUnit(), LayoutUnit()}) | 145 .SetPercentageResolutionSize({LayoutUnit(), LayoutUnit()}) |
144 .ToConstraintSpace(FromPlatformWritingMode(Style().getWritingMode())); | 146 .ToConstraintSpace(FromPlatformWritingMode(Style().getWritingMode())); |
145 | 147 |
146 physical_fragment = Layout(constraint_space); | 148 layout_result = Layout(constraint_space); |
| 149 physical_fragment = layout_result->PhysicalFragment().get(); |
147 NGBoxFragment max_fragment(FromPlatformWritingMode(Style().getWritingMode()), | 150 NGBoxFragment max_fragment(FromPlatformWritingMode(Style().getWritingMode()), |
148 toNGPhysicalBoxFragment(physical_fragment.get())); | 151 toNGPhysicalBoxFragment(physical_fragment)); |
149 sizes.max_content = max_fragment.InlineOverflow(); | 152 sizes.max_content = max_fragment.InlineOverflow(); |
150 return sizes; | 153 return sizes; |
151 } | 154 } |
152 | 155 |
153 const ComputedStyle& NGBlockNode::Style() const { | 156 const ComputedStyle& NGBlockNode::Style() const { |
154 if (style_) | 157 if (style_) |
155 return *style_.get(); | 158 return *style_.get(); |
156 DCHECK(layout_box_); | 159 DCHECK(layout_box_); |
157 return layout_box_->styleRef(); | 160 return layout_box_->styleRef(); |
158 } | 161 } |
(...skipping 28 matching lines...) Expand all Loading... |
187 | 190 |
188 void NGBlockNode::SetNextSibling(NGBlockNode* sibling) { | 191 void NGBlockNode::SetNextSibling(NGBlockNode* sibling) { |
189 next_sibling_ = sibling; | 192 next_sibling_ = sibling; |
190 } | 193 } |
191 | 194 |
192 void NGBlockNode::SetFirstChild(NGLayoutInputNode* child) { | 195 void NGBlockNode::SetFirstChild(NGLayoutInputNode* child) { |
193 first_child_ = child; | 196 first_child_ = child; |
194 } | 197 } |
195 | 198 |
196 NGBreakToken* NGBlockNode::CurrentBreakToken() const { | 199 NGBreakToken* NGBlockNode::CurrentBreakToken() const { |
197 return fragment_ ? fragment_->BreakToken() : nullptr; | 200 return layout_result_ ? layout_result_->PhysicalFragment()->BreakToken() |
| 201 : nullptr; |
198 } | 202 } |
199 | 203 |
200 DEFINE_TRACE(NGBlockNode) { | 204 DEFINE_TRACE(NGBlockNode) { |
201 visitor->trace(next_sibling_); | 205 visitor->trace(next_sibling_); |
202 visitor->trace(first_child_); | 206 visitor->trace(first_child_); |
203 NGLayoutInputNode::trace(visitor); | 207 NGLayoutInputNode::trace(visitor); |
204 } | 208 } |
205 | 209 |
206 bool NGBlockNode::CanUseNewLayout() { | 210 bool NGBlockNode::CanUseNewLayout() { |
207 if (!layout_box_) | 211 if (!layout_box_) |
(...skipping 20 matching lines...) Expand all Loading... |
228 | 232 |
229 return false; | 233 return false; |
230 } | 234 } |
231 | 235 |
232 void NGBlockNode::CopyFragmentDataToLayoutBox( | 236 void NGBlockNode::CopyFragmentDataToLayoutBox( |
233 const NGConstraintSpace& constraint_space) { | 237 const NGConstraintSpace& constraint_space) { |
234 // We may not have a layout_box_ during unit tests. | 238 // We may not have a layout_box_ during unit tests. |
235 if (!layout_box_) | 239 if (!layout_box_) |
236 return; | 240 return; |
237 | 241 |
238 layout_box_->setWidth(fragment_->Width()); | 242 NGPhysicalBoxFragment* fragment = |
239 layout_box_->setHeight(fragment_->Height()); | 243 toNGPhysicalBoxFragment(layout_result_->PhysicalFragment().get()); |
| 244 |
| 245 layout_box_->setWidth(fragment->Width()); |
| 246 layout_box_->setHeight(fragment->Height()); |
240 NGBoxStrut border_and_padding = | 247 NGBoxStrut border_and_padding = |
241 ComputeBorders(Style()) + ComputePadding(constraint_space, Style()); | 248 ComputeBorders(Style()) + ComputePadding(constraint_space, Style()); |
242 LayoutUnit intrinsic_logical_height = | 249 LayoutUnit intrinsic_logical_height = |
243 layout_box_->style()->isHorizontalWritingMode() | 250 layout_box_->style()->isHorizontalWritingMode() |
244 ? fragment_->HeightOverflow() | 251 ? fragment->HeightOverflow() |
245 : fragment_->WidthOverflow(); | 252 : fragment->WidthOverflow(); |
246 intrinsic_logical_height -= border_and_padding.BlockSum(); | 253 intrinsic_logical_height -= border_and_padding.BlockSum(); |
247 layout_box_->setIntrinsicContentLogicalHeight(intrinsic_logical_height); | 254 layout_box_->setIntrinsicContentLogicalHeight(intrinsic_logical_height); |
248 | 255 |
249 // TODO(layout-dev): Currently we are not actually performing layout on | 256 // TODO(layout-dev): Currently we are not actually performing layout on |
250 // inline children. For now just clear the needsLayout bit so that we can | 257 // inline children. For now just clear the needsLayout bit so that we can |
251 // run unittests. | 258 // run unittests. |
252 if (HasInlineChildren()) { | 259 if (HasInlineChildren()) { |
253 for (InlineWalker walker( | 260 for (InlineWalker walker( |
254 LineLayoutBlockFlow(toLayoutBlockFlow(layout_box_))); | 261 LineLayoutBlockFlow(toLayoutBlockFlow(layout_box_))); |
255 !walker.atEnd(); walker.advance()) { | 262 !walker.atEnd(); walker.advance()) { |
256 LayoutObject* o = LineLayoutAPIShim::layoutObjectFrom(walker.current()); | 263 LayoutObject* o = LineLayoutAPIShim::layoutObjectFrom(walker.current()); |
257 o->clearNeedsLayout(); | 264 o->clearNeedsLayout(); |
258 } | 265 } |
259 | 266 |
260 // Ensure the position of the children are copied across to the | 267 // Ensure the position of the children are copied across to the |
261 // LayoutObject tree. | 268 // LayoutObject tree. |
262 } else { | 269 } else { |
263 for (const auto& child_fragment : fragment_->Children()) { | 270 for (const auto& child_fragment : fragment->Children()) { |
264 if (child_fragment->IsPlaced()) | 271 if (child_fragment->IsPlaced()) |
265 FragmentPositionUpdated(toNGPhysicalBoxFragment(*child_fragment)); | 272 FragmentPositionUpdated(toNGPhysicalBoxFragment(*child_fragment)); |
266 | 273 |
267 for (const auto& floating_object : child_fragment->PositionedFloats()) { | 274 for (const auto& floating_object : |
| 275 toNGPhysicalBoxFragment(child_fragment.get())->PositionedFloats()) { |
268 FloatingObjectPositionedUpdated(floating_object, layout_box_); | 276 FloatingObjectPositionedUpdated(floating_object, layout_box_); |
269 } | 277 } |
270 } | 278 } |
271 } | 279 } |
272 | 280 |
273 if (layout_box_->isLayoutBlock()) | 281 if (layout_box_->isLayoutBlock()) |
274 toLayoutBlock(layout_box_)->layoutPositionedObjects(true); | 282 toLayoutBlock(layout_box_)->layoutPositionedObjects(true); |
275 layout_box_->clearNeedsLayout(); | 283 layout_box_->clearNeedsLayout(); |
276 if (layout_box_->isLayoutBlockFlow()) { | 284 if (layout_box_->isLayoutBlockFlow()) { |
277 toLayoutBlockFlow(layout_box_)->updateIsSelfCollapsing(); | 285 toLayoutBlockFlow(layout_box_)->updateIsSelfCollapsing(); |
278 } | 286 } |
279 } | 287 } |
280 | 288 |
281 RefPtr<NGPhysicalBoxFragment> NGBlockNode::RunOldLayout( | 289 RefPtr<NGLayoutResult> NGBlockNode::RunOldLayout( |
282 const NGConstraintSpace& constraint_space) { | 290 const NGConstraintSpace& constraint_space) { |
283 NGLogicalSize available_size = constraint_space.PercentageResolutionSize(); | 291 NGLogicalSize available_size = constraint_space.PercentageResolutionSize(); |
284 layout_box_->setOverrideContainingBlockContentLogicalWidth( | 292 layout_box_->setOverrideContainingBlockContentLogicalWidth( |
285 available_size.inline_size); | 293 available_size.inline_size); |
286 layout_box_->setOverrideContainingBlockContentLogicalHeight( | 294 layout_box_->setOverrideContainingBlockContentLogicalHeight( |
287 available_size.block_size); | 295 available_size.block_size); |
288 // TODO(layout-ng): Does this handle scrollbars correctly? | 296 // TODO(layout-ng): Does this handle scrollbars correctly? |
289 if (constraint_space.IsFixedSizeInline()) { | 297 if (constraint_space.IsFixedSizeInline()) { |
290 layout_box_->setOverrideLogicalContentWidth( | 298 layout_box_->setOverrideLogicalContentWidth( |
291 constraint_space.AvailableSize().inline_size - | 299 constraint_space.AvailableSize().inline_size - |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
325 // Save static position for legacy AbsPos layout. | 333 // Save static position for legacy AbsPos layout. |
326 void NGBlockNode::SaveStaticOffsetForLegacy(const NGLogicalOffset& offset) { | 334 void NGBlockNode::SaveStaticOffsetForLegacy(const NGLogicalOffset& offset) { |
327 DCHECK(layout_box_); | 335 DCHECK(layout_box_); |
328 DCHECK(layout_box_->isOutOfFlowPositioned()); | 336 DCHECK(layout_box_->isOutOfFlowPositioned()); |
329 DCHECK(layout_box_->layer()); | 337 DCHECK(layout_box_->layer()); |
330 layout_box_->layer()->setStaticBlockPosition(offset.block_offset); | 338 layout_box_->layer()->setStaticBlockPosition(offset.block_offset); |
331 layout_box_->layer()->setStaticInlinePosition(offset.inline_offset); | 339 layout_box_->layer()->setStaticInlinePosition(offset.inline_offset); |
332 } | 340 } |
333 | 341 |
334 } // namespace blink | 342 } // namespace blink |
OLD | NEW |