Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(387)

Side by Side Diff: third_party/WebKit/Source/core/layout/ng/ng_block_layout_algorithm.cc

Issue 2816933003: Use Layout Opportunity Iterator to position new FC blocks. (Closed)
Patch Set: fix block-formatting-contexts-{005|007} Created 3 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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_layout_algorithm.h" 5 #include "core/layout/ng/ng_block_layout_algorithm.h"
6 6
7 #include "core/layout/ng/inline/ng_inline_node.h" 7 #include "core/layout/ng/inline/ng_inline_node.h"
8 #include "core/layout/ng/ng_absolute_utils.h" 8 #include "core/layout/ng/ng_absolute_utils.h"
9 #include "core/layout/ng/ng_block_child_iterator.h" 9 #include "core/layout/ng/ng_block_child_iterator.h"
10 #include "core/layout/ng/ng_box_fragment.h"
11 #include "core/layout/ng/ng_constraint_space.h" 10 #include "core/layout/ng/ng_constraint_space.h"
12 #include "core/layout/ng/ng_constraint_space_builder.h" 11 #include "core/layout/ng/ng_constraint_space_builder.h"
13 #include "core/layout/ng/ng_floats_utils.h" 12 #include "core/layout/ng/ng_floats_utils.h"
14 #include "core/layout/ng/ng_fragment.h" 13 #include "core/layout/ng/ng_fragment.h"
15 #include "core/layout/ng/ng_fragment_builder.h" 14 #include "core/layout/ng/ng_fragment_builder.h"
16 #include "core/layout/ng/ng_layout_opportunity_iterator.h" 15 #include "core/layout/ng/ng_layout_opportunity_iterator.h"
17 #include "core/layout/ng/ng_length_utils.h" 16 #include "core/layout/ng/ng_length_utils.h"
18 #include "core/layout/ng/ng_out_of_flow_layout_part.h" 17 #include "core/layout/ng/ng_out_of_flow_layout_part.h"
19 #include "core/layout/ng/ng_space_utils.h" 18 #include "core/layout/ng/ng_space_utils.h"
20 #include "core/style/ComputedStyle.h" 19 #include "core/style/ComputedStyle.h"
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after
77 const NGLogicalOffset& offset, 76 const NGLogicalOffset& offset,
78 NGFragmentBuilder* builder) { 77 NGFragmentBuilder* builder) {
79 DCHECK(builder); 78 DCHECK(builder);
80 if (!builder->BfcOffset()) { 79 if (!builder->BfcOffset()) {
81 NGLogicalOffset mutable_offset(offset); 80 NGLogicalOffset mutable_offset(offset);
82 AdjustToClearance(space.ClearanceOffset(), &mutable_offset); 81 AdjustToClearance(space.ClearanceOffset(), &mutable_offset);
83 builder->SetBfcOffset(mutable_offset); 82 builder->SetBfcOffset(mutable_offset);
84 } 83 }
85 } 84 }
86 85
86 void PositionPendingFloats(LayoutUnit origin_block_offset,
87 NGFragmentBuilder* container_builder,
88 NGConstraintSpace* space) {
89 DCHECK(container_builder->BfcOffset())
90 << "Parent BFC offset should be known here";
91 const auto& floating_objects = container_builder->UnpositionedFloats();
92 PositionFloats(origin_block_offset,
93 container_builder->BfcOffset().value().block_offset,
94 floating_objects, space);
95 container_builder->MutablePositionedFloats().AppendVector(floating_objects);
96 container_builder->MutableUnpositionedFloats().clear();
97 }
98
87 NGBlockLayoutAlgorithm::NGBlockLayoutAlgorithm(NGBlockNode* node, 99 NGBlockLayoutAlgorithm::NGBlockLayoutAlgorithm(NGBlockNode* node,
88 NGConstraintSpace* space, 100 NGConstraintSpace* space,
89 NGBlockBreakToken* break_token) 101 NGBlockBreakToken* break_token)
90 : NGLayoutAlgorithm(node, space, break_token), 102 : NGLayoutAlgorithm(node, space, break_token),
91 space_builder_(constraint_space_) {} 103 space_builder_(constraint_space_) {}
92 104
93 Optional<MinMaxContentSize> NGBlockLayoutAlgorithm::ComputeMinMaxContentSize() 105 Optional<MinMaxContentSize> NGBlockLayoutAlgorithm::ComputeMinMaxContentSize()
94 const { 106 const {
95 MinMaxContentSize sizes; 107 MinMaxContentSize sizes;
96 108
(...skipping 26 matching lines...) Expand all
123 sizes.min_content = std::max(sizes.min_content, child_sizes.min_content); 135 sizes.min_content = std::max(sizes.min_content, child_sizes.min_content);
124 sizes.max_content = std::max(sizes.max_content, child_sizes.max_content); 136 sizes.max_content = std::max(sizes.max_content, child_sizes.max_content);
125 } 137 }
126 138
127 sizes.max_content = std::max(sizes.min_content, sizes.max_content); 139 sizes.max_content = std::max(sizes.min_content, sizes.max_content);
128 return sizes; 140 return sizes;
129 } 141 }
130 142
131 NGLogicalOffset NGBlockLayoutAlgorithm::CalculateLogicalOffset( 143 NGLogicalOffset NGBlockLayoutAlgorithm::CalculateLogicalOffset(
132 const WTF::Optional<NGLogicalOffset>& known_fragment_offset) { 144 const WTF::Optional<NGLogicalOffset>& known_fragment_offset) {
145 if (known_fragment_offset)
146 return known_fragment_offset.value() - ContainerBfcOffset();
133 LayoutUnit inline_offset = 147 LayoutUnit inline_offset =
134 border_and_padding_.inline_start + curr_child_margins_.inline_start; 148 border_and_padding_.inline_start + curr_child_margins_.inline_start;
135 LayoutUnit block_offset = content_size_; 149 return {inline_offset, content_size_};
136 if (known_fragment_offset) {
137 block_offset = known_fragment_offset.value().block_offset -
138 ContainerBfcOffset().block_offset;
139 }
140 return {inline_offset, block_offset};
141 } 150 }
142 151
143 RefPtr<NGLayoutResult> NGBlockLayoutAlgorithm::Layout() { 152 RefPtr<NGLayoutResult> NGBlockLayoutAlgorithm::Layout() {
144 WTF::Optional<MinMaxContentSize> min_max_size; 153 WTF::Optional<MinMaxContentSize> min_max_size;
145 if (NeedMinMaxContentSize(ConstraintSpace(), Style())) 154 if (NeedMinMaxContentSize(ConstraintSpace(), Style()))
146 min_max_size = ComputeMinMaxContentSize(); 155 min_max_size = ComputeMinMaxContentSize();
147 156
148 border_and_padding_ = ComputeBorders(ConstraintSpace(), Style()) + 157 border_and_padding_ = ComputeBorders(ConstraintSpace(), Style()) +
149 ComputePadding(ConstraintSpace(), Style()); 158 ComputePadding(ConstraintSpace(), Style());
150 159
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after
214 content_size_ + curr_margin_strut_.Sum()}; 223 content_size_ + curr_margin_strut_.Sum()};
215 container_builder_.AddOutOfFlowChildCandidate(ToNGBlockNode(child), 224 container_builder_.AddOutOfFlowChildCandidate(ToNGBlockNode(child),
216 offset); 225 offset);
217 NGBlockChildIterator::Entry entry = child_iterator.NextChild(); 226 NGBlockChildIterator::Entry entry = child_iterator.NextChild();
218 child = entry.node; 227 child = entry.node;
219 child_break_token = entry.token; 228 child_break_token = entry.token;
220 continue; 229 continue;
221 } 230 }
222 } 231 }
223 232
224 PrepareChildLayout(child); 233 NGLogicalOffset child_bfc_offset = PrepareChildLayout(child);
225 RefPtr<NGConstraintSpace> child_space = 234 RefPtr<NGConstraintSpace> child_space =
226 CreateConstraintSpaceForChild(child); 235 CreateConstraintSpaceForChild(child_bfc_offset, child);
227 RefPtr<NGLayoutResult> layout_result = 236 RefPtr<NGLayoutResult> layout_result =
228 child->Layout(child_space.Get(), child_break_token); 237 child->Layout(child_space.Get(), child_break_token);
229 238
230 FinishChildLayout(child, child_space.Get(), layout_result); 239 if (child->IsFloating())
240 FinishFloatChildLayout(child->Style(), *child_space, layout_result.Get());
241 else
242 FinishChildLayout(child_space.Get(), layout_result.Get());
231 243
232 entry = child_iterator.NextChild(); 244 entry = child_iterator.NextChild();
233 child = entry.node; 245 child = entry.node;
234 child_break_token = entry.token; 246 child_break_token = entry.token;
235 247
236 if (IsOutOfSpace(ConstraintSpace(), content_size_)) 248 if (IsOutOfSpace(ConstraintSpace(), content_size_))
237 break; 249 break;
238 } 250 }
239 251
240 // Margins collapsing: 252 // Margins collapsing:
(...skipping 13 matching lines...) Expand all
254 container_builder_.SetBlockSize(size.block_size); 266 container_builder_.SetBlockSize(size.block_size);
255 267
256 // Layout our absolute and fixed positioned children. 268 // Layout our absolute and fixed positioned children.
257 NGOutOfFlowLayoutPart(ConstraintSpace(), Style(), &container_builder_).Run(); 269 NGOutOfFlowLayoutPart(ConstraintSpace(), Style(), &container_builder_).Run();
258 270
259 // Non-empty blocks always know their position in space: 271 // Non-empty blocks always know their position in space:
260 if (size.block_size) { 272 if (size.block_size) {
261 curr_bfc_offset_.block_offset += curr_margin_strut_.Sum(); 273 curr_bfc_offset_.block_offset += curr_margin_strut_.Sum();
262 MaybeUpdateFragmentBfcOffset(ConstraintSpace(), curr_bfc_offset_, 274 MaybeUpdateFragmentBfcOffset(ConstraintSpace(), curr_bfc_offset_,
263 &container_builder_); 275 &container_builder_);
264 PositionPendingFloats(curr_bfc_offset_.block_offset, 276 PositionPendingFloats(curr_bfc_offset_.block_offset, &container_builder_,
265 MutableConstraintSpace(), &container_builder_); 277 MutableConstraintSpace());
266 } 278 }
267 279
268 // Margins collapsing: 280 // Margins collapsing:
269 // Do not collapse margins between the last in-flow child and bottom margin 281 // Do not collapse margins between the last in-flow child and bottom margin
270 // of its parent if the parent has height != auto() 282 // of its parent if the parent has height != auto()
271 if (!Style().LogicalHeight().IsAuto()) { 283 if (!Style().LogicalHeight().IsAuto()) {
272 // TODO(glebl): handle minLogicalHeight, maxLogicalHeight. 284 // TODO(glebl): handle minLogicalHeight, maxLogicalHeight.
273 curr_margin_strut_ = NGMarginStrut(); 285 curr_margin_strut_ = NGMarginStrut();
274 } 286 }
275 container_builder_.SetEndMarginStrut(curr_margin_strut_); 287 container_builder_.SetEndMarginStrut(curr_margin_strut_);
276 288
277 container_builder_.SetOverflowSize( 289 container_builder_.SetOverflowSize(
278 NGLogicalSize(max_inline_size_, content_size_)); 290 NGLogicalSize(max_inline_size_, content_size_));
279 291
280 if (ConstraintSpace().HasBlockFragmentation()) 292 if (ConstraintSpace().HasBlockFragmentation())
281 FinalizeForFragmentation(); 293 FinalizeForFragmentation();
282 294
283 return container_builder_.ToBoxFragment(); 295 return container_builder_.ToBoxFragment();
284 } 296 }
285 297
286 void NGBlockLayoutAlgorithm::PrepareChildLayout(NGLayoutInputNode* child) { 298 NGLogicalOffset NGBlockLayoutAlgorithm::PrepareChildLayout(
299 NGLayoutInputNode* child) {
287 DCHECK(child); 300 DCHECK(child);
288 301
302 curr_bfc_offset_ = container_builder_.BfcOffset()
303 ? container_builder_.BfcOffset().value()
304 : ConstraintSpace().BfcOffset();
305 curr_bfc_offset_.block_offset += content_size_;
306
289 // Calculate margins in parent's writing mode. 307 // Calculate margins in parent's writing mode.
290 curr_child_margins_ = CalculateMargins( 308 curr_child_margins_ = CalculateMargins(
291 child, *space_builder_.ToConstraintSpace( 309 child, *space_builder_.ToConstraintSpace(
292 FromPlatformWritingMode(Style().GetWritingMode()))); 310 FromPlatformWritingMode(Style().GetWritingMode())));
293 311
294 // Set estimated BFC offset to the next child's constraint space.
295 curr_bfc_offset_ = container_builder_.BfcOffset()
296 ? container_builder_.BfcOffset().value()
297 : ConstraintSpace().BfcOffset();
298 curr_bfc_offset_.block_offset += content_size_;
299 curr_bfc_offset_.inline_offset += border_and_padding_.inline_start;
300
301 bool is_floating = child->IsBlock() && child->Style().IsFloating();
302
303 bool should_position_pending_floats = 312 bool should_position_pending_floats =
304 child->IsBlock() && !is_floating && 313 !child->IsFloating() &&
305 !IsNewFormattingContextForBlockLevelChild(Style(), *child) && 314 !IsNewFormattingContextForBlockLevelChild(Style(), *child) &&
306 ClearanceMayAffectLayout(ConstraintSpace(), 315 ClearanceMayAffectLayout(ConstraintSpace(),
307 container_builder_.UnpositionedFloats(), 316 container_builder_.UnpositionedFloats(),
308 child->Style()); 317 child->Style());
309 318
310 // Children which may clear a float need to force all the pending floats to 319 // Children which may clear a float need to force all the pending floats to
311 // be positioned before layout. This also resolves the fragment's bfc offset. 320 // be positioned before layout. This also resolves the fragment's bfc offset.
312 if (should_position_pending_floats) { 321 if (should_position_pending_floats) {
313 LayoutUnit origin_point_block_offset = 322 LayoutUnit origin_point_block_offset =
314 curr_bfc_offset_.block_offset + curr_margin_strut_.Sum(); 323 curr_bfc_offset_.block_offset + curr_margin_strut_.Sum();
315 MaybeUpdateFragmentBfcOffset( 324 MaybeUpdateFragmentBfcOffset(
316 ConstraintSpace(), 325 ConstraintSpace(),
317 {curr_bfc_offset_.inline_offset, origin_point_block_offset}, 326 {curr_bfc_offset_.inline_offset, origin_point_block_offset},
318 &container_builder_); 327 &container_builder_);
319 PositionPendingFloats(origin_point_block_offset, MutableConstraintSpace(), 328 PositionPendingFloats(origin_point_block_offset, &container_builder_,
320 &container_builder_); 329 MutableConstraintSpace());
321 } 330 }
322 331
323 bool is_inflow = child->IsInline() || !is_floating; 332 bool is_inflow = child->IsInline() || !child->IsFloating();
324 333
334 NGLogicalOffset child_bfc_offset = curr_bfc_offset_;
335 child_bfc_offset.inline_offset += border_and_padding_.inline_start;
325 // Only inflow children (e.g. not floats) are included in the child's margin 336 // Only inflow children (e.g. not floats) are included in the child's margin
326 // strut as they do not participate in margin collapsing. 337 // strut as they do not participate in margin collapsing.
327 if (is_inflow) { 338 if (is_inflow) {
328 curr_bfc_offset_.inline_offset += curr_child_margins_.inline_start; 339 child_bfc_offset.inline_offset += curr_child_margins_.inline_start;
329 // Append the current margin strut with child's block start margin. 340 // Append the current margin strut with child's block start margin.
330 // Non empty border/padding use cases are handled inside of the child's 341 // Non empty border/padding, and new FC use cases are handled inside of the
331 // layout. 342 // child's layout.
332 curr_margin_strut_.Append(curr_child_margins_.block_start); 343 if (!IsNewFormattingContextForBlockLevelChild(Style(), *child))
344 curr_margin_strut_.Append(curr_child_margins_.block_start);
333 } 345 }
334 346
335 // TODO(ikilpatrick): Children which establish new formatting contexts need 347 // Should collapse margins if inline.
336 // to be placed using the opportunity iterator before we can collapse margins. 348 if (child->IsInline()) {
337 // If the child is placed at the block_start of this fragment, then its
338 // margins do impact the position of its parent, if not (its placed below a
339 // float for example) it doesn't. \o/
340
341 bool should_collapse_margins =
342 child->IsInline() ||
343 (!is_floating &&
344 IsNewFormattingContextForBlockLevelChild(Style(), *child));
345
346 // Inline children or children which establish a block formatting context
347 // collapse margins and position themselves immediately as they need to know
348 // their BFC offset for fragmentation purposes.
349 if (should_collapse_margins) {
350 curr_bfc_offset_.block_offset += curr_margin_strut_.Sum(); 349 curr_bfc_offset_.block_offset += curr_margin_strut_.Sum();
351 MaybeUpdateFragmentBfcOffset(ConstraintSpace(), curr_bfc_offset_, 350 MaybeUpdateFragmentBfcOffset(ConstraintSpace(), curr_bfc_offset_,
352 &container_builder_); 351 &container_builder_);
353 PositionPendingFloats(curr_bfc_offset_.block_offset, 352 PositionPendingFloats(curr_bfc_offset_.block_offset, &container_builder_,
354 MutableConstraintSpace(), &container_builder_); 353 MutableConstraintSpace());
355 curr_margin_strut_ = {}; 354 curr_margin_strut_ = {};
356 } 355 }
356 child_bfc_offset.block_offset = curr_bfc_offset_.block_offset;
357 return child_bfc_offset;
357 } 358 }
358 359
359 void NGBlockLayoutAlgorithm::FinishChildLayout( 360 void NGBlockLayoutAlgorithm::FinishChildLayout(
360 NGLayoutInputNode* child, 361 const NGConstraintSpace* child_space,
361 NGConstraintSpace* child_space, 362 NGLayoutResult* layout_result) {
362 RefPtr<NGLayoutResult> layout_result) {
363 NGBoxFragment fragment(
364 ConstraintSpace().WritingMode(),
365 ToNGPhysicalBoxFragment(layout_result->PhysicalFragment().Get()));
366
367 // Pull out unpositioned floats to the current fragment. This may needed if 363 // Pull out unpositioned floats to the current fragment. This may needed if
368 // for example the child fragment could not position its floats because it's 364 // for example the child fragment could not position its floats because it's
369 // empty and therefore couldn't determine its position in space. 365 // empty and therefore couldn't determine its position in space.
370 container_builder_.MutableUnpositionedFloats().AppendVector( 366 container_builder_.MutableUnpositionedFloats().AppendVector(
371 layout_result->UnpositionedFloats()); 367 layout_result->UnpositionedFloats());
372 368
373 if (child->IsBlock() && child->Style().IsFloating()) { 369 NGBoxFragment fragment(
374 NGLogicalOffset origin_offset = constraint_space_->BfcOffset(); 370 ConstraintSpace().WritingMode(),
375 origin_offset.inline_offset += border_and_padding_.inline_start; 371 ToNGPhysicalBoxFragment(layout_result->PhysicalFragment().Get()));
376 RefPtr<NGFloatingObject> floating_object = NGFloatingObject::Create(
377 child->Style(), child_space->WritingMode(),
378 child_space->AvailableSize(), origin_offset,
379 constraint_space_->BfcOffset(), curr_child_margins_,
380 layout_result->PhysicalFragment().Get());
381 container_builder_.AddUnpositionedFloat(floating_object);
382 // No need to postpone the positioning if we know the correct offset.
383 if (container_builder_.BfcOffset()) {
384 NGLogicalOffset origin_point = curr_bfc_offset_;
385 // Adjust origin point to the margins of the last child.
386 // Example: <div style="margin-bottom: 20px"><float></div>
387 // <div style="margin-bottom: 30px"></div>
388 origin_point.block_offset += curr_margin_strut_.Sum();
389 PositionPendingFloats(origin_point.block_offset, MutableConstraintSpace(),
390 &container_builder_);
391 }
392 return;
393 }
394 372
395 // Determine the fragment's position in the parent space either by using 373 // Determine the fragment's position in the parent space.
396 // content_size_ or known fragment's BFC offset. 374 WTF::Optional<NGLogicalOffset> child_bfc_offset;
397 WTF::Optional<NGLogicalOffset> bfc_offset; 375 if (child_space->IsNewFormattingContext())
398 if (child_space->IsNewFormattingContext()) { 376 child_bfc_offset = PositionNewFc(fragment, *child_space);
399 bfc_offset = curr_bfc_offset_; 377 else if (fragment.BfcOffset())
400 } else if (fragment.BfcOffset()) { 378 child_bfc_offset = PositionWithBfcOffset(fragment);
401 // Fragment that knows its offset can be used to set parent's BFC position. 379 else if (container_builder_.BfcOffset())
402 curr_bfc_offset_.block_offset = fragment.BfcOffset().value().block_offset; 380 child_bfc_offset = PositionWithParentBfc();
403 MaybeUpdateFragmentBfcOffset(ConstraintSpace(), curr_bfc_offset_, 381
404 &container_builder_); 382 NGLogicalOffset logical_offset = CalculateLogicalOffset(child_bfc_offset);
405 PositionPendingFloats(curr_bfc_offset_.block_offset,
406 MutableConstraintSpace(), &container_builder_);
407 bfc_offset = curr_bfc_offset_;
408 } else if (container_builder_.BfcOffset()) {
409 // Fragment doesn't know its offset but we can still calculate its BFC
410 // position because the parent fragment's BFC is known.
411 // Example:
412 // BFC Offset is known here because of the padding.
413 // <div style="padding: 1px">
414 // <div id="empty-div" style="margins: 1px"></div>
415 bfc_offset = curr_bfc_offset_;
416 bfc_offset.value().block_offset += curr_margin_strut_.Sum();
417 }
418 NGLogicalOffset logical_offset = CalculateLogicalOffset(bfc_offset);
419 383
420 // Update margin strut. 384 // Update margin strut.
421 curr_margin_strut_ = fragment.EndMarginStrut(); 385 curr_margin_strut_ = fragment.EndMarginStrut();
422 curr_margin_strut_.Append(curr_child_margins_.block_end); 386 curr_margin_strut_.Append(curr_child_margins_.block_end);
423 387
424 // Only modify content_size if BlockSize is not empty. It's needed to prevent 388 // Only modify content_size if BlockSize is not empty. It's needed to prevent
425 // the situation when logical_offset is included in content_size for empty 389 // the situation when logical_offset is included in content_size for empty
426 // blocks. Example: 390 // blocks. Example:
427 // <div style="overflow:hidden"> 391 // <div style="overflow:hidden">
428 // <div style="margin-top: 8px"></div> 392 // <div style="margin-top: 8px"></div>
429 // <div style="margin-top: 10px"></div> 393 // <div style="margin-top: 10px"></div>
430 // </div> 394 // </div>
431 if (fragment.BlockSize()) 395 if (fragment.BlockSize())
432 content_size_ = fragment.BlockSize() + logical_offset.block_offset; 396 content_size_ = fragment.BlockSize() + logical_offset.block_offset;
433 max_inline_size_ = 397 max_inline_size_ =
434 std::max(max_inline_size_, fragment.InlineSize() + 398 std::max(max_inline_size_, fragment.InlineSize() +
435 curr_child_margins_.InlineSum() + 399 curr_child_margins_.InlineSum() +
436 border_and_padding_.InlineSum()); 400 border_and_padding_.InlineSum());
437 401
438 container_builder_.AddChild(layout_result, logical_offset); 402 container_builder_.AddChild(layout_result, logical_offset);
439 } 403 }
440 404
405 NGLogicalOffset NGBlockLayoutAlgorithm::PositionNewFc(
406 const NGBoxFragment& fragment,
407 const NGConstraintSpace& child_space) {
408 // 1. Position all pending floats to a temporary space.
409 RefPtr<NGConstraintSpace> tmp_space =
410 NGConstraintSpaceBuilder(&child_space)
411 .SetIsNewFormattingContext(false)
412 .ToConstraintSpace(child_space.WritingMode());
413 PositionFloats(curr_bfc_offset_.block_offset, curr_bfc_offset_.block_offset,
414 container_builder_.UnpositionedFloats(), tmp_space.Get());
415
416 // 2. Find an estimated layout opportunity for our fragment.
417 NGLayoutOpportunity opportunity = FindLayoutOpportunityForFragment(
418 tmp_space->Exclusions().get(), child_space.AvailableSize(),
419 curr_bfc_offset_, curr_child_margins_, fragment);
420
421 // 3. If the found opportunity lies on the same line with our estimated
422 // child's BFC offset then merge fragment's margins with the current
423 // MarginStrut.
424 if (opportunity.offset.block_offset == curr_bfc_offset_.block_offset)
425 curr_margin_strut_.Append(curr_child_margins_.block_start);
426 curr_bfc_offset_.block_offset += curr_margin_strut_.Sum();
427 curr_margin_strut_ = {};
428
429 // 4. The child's BFC block offset is known here.
430 MaybeUpdateFragmentBfcOffset(ConstraintSpace(), curr_bfc_offset_,
431 &container_builder_);
432 PositionPendingFloats(curr_bfc_offset_.block_offset, &container_builder_,
433 MutableConstraintSpace());
434
435 // 5. Find the final layout opportunity for the fragment after all pending
436 // floats are positioned at the correct BFC block's offset.
437 opportunity = FindLayoutOpportunityForFragment(
438 MutableConstraintSpace()->Exclusions().get(), child_space.AvailableSize(),
439 curr_bfc_offset_, curr_child_margins_, fragment);
440
441 curr_bfc_offset_ = opportunity.offset;
442 return curr_bfc_offset_;
443 }
444
445 NGLogicalOffset NGBlockLayoutAlgorithm::PositionWithBfcOffset(
446 const NGBoxFragment& fragment) {
447 DCHECK(fragment.BfcOffset());
448 curr_bfc_offset_.block_offset = fragment.BfcOffset().value().block_offset;
449 MaybeUpdateFragmentBfcOffset(ConstraintSpace(), curr_bfc_offset_,
450 &container_builder_);
451 PositionPendingFloats(curr_bfc_offset_.block_offset, &container_builder_,
452 MutableConstraintSpace());
453 return fragment.BfcOffset().value();
454 }
455
456 NGLogicalOffset NGBlockLayoutAlgorithm::PositionWithParentBfc() {
457 curr_bfc_offset_ +=
458 {border_and_padding_.inline_start + curr_child_margins_.inline_start,
459 curr_margin_strut_.Sum()};
460 return curr_bfc_offset_;
461 }
462
463 void NGBlockLayoutAlgorithm::FinishFloatChildLayout(
464 const ComputedStyle& child_style,
465 const NGConstraintSpace& child_space,
466 const NGLayoutResult* layout_result) {
467 NGLogicalOffset origin_offset = constraint_space_->BfcOffset();
468 origin_offset.inline_offset += border_and_padding_.inline_start;
469 RefPtr<NGFloatingObject> floating_object = NGFloatingObject::Create(
470 child_style, child_space.WritingMode(), child_space.AvailableSize(),
471 origin_offset, constraint_space_->BfcOffset(), curr_child_margins_,
472 layout_result->PhysicalFragment().Get());
473 container_builder_.AddUnpositionedFloat(floating_object);
474
475 // No need to postpone the positioning if we know the correct offset.
476 if (container_builder_.BfcOffset()) {
477 NGLogicalOffset origin_point = curr_bfc_offset_;
478 // Adjust origin point to the margins of the last child.
479 // Example: <div style="margin-bottom: 20px"><float></div>
480 // <div style="margin-bottom: 30px"></div>
481 origin_point.block_offset += curr_margin_strut_.Sum();
482 PositionPendingFloats(origin_point.block_offset, &container_builder_,
483 MutableConstraintSpace());
484 }
485 }
486
441 void NGBlockLayoutAlgorithm::FinalizeForFragmentation() { 487 void NGBlockLayoutAlgorithm::FinalizeForFragmentation() {
442 LayoutUnit used_block_size = 488 LayoutUnit used_block_size =
443 BreakToken() ? BreakToken()->UsedBlockSize() : LayoutUnit(); 489 BreakToken() ? BreakToken()->UsedBlockSize() : LayoutUnit();
444 LayoutUnit block_size = ComputeBlockSizeForFragment( 490 LayoutUnit block_size = ComputeBlockSizeForFragment(
445 ConstraintSpace(), Style(), used_block_size + content_size_); 491 ConstraintSpace(), Style(), used_block_size + content_size_);
446 492
447 block_size -= used_block_size; 493 block_size -= used_block_size;
448 DCHECK_GE(block_size, LayoutUnit()) 494 DCHECK_GE(block_size, LayoutUnit())
449 << "Adding and subtracting the used_block_size shouldn't leave the " 495 << "Adding and subtracting the used_block_size shouldn't leave the "
450 "block_size for this fragment smaller than zero."; 496 "block_size for this fragment smaller than zero.";
(...skipping 22 matching lines...) Expand all
473 519
474 // The end of the block fits in the current fragmentainer. 520 // The end of the block fits in the current fragmentainer.
475 container_builder_.SetBlockSize(block_size); 521 container_builder_.SetBlockSize(block_size);
476 container_builder_.SetBlockOverflow(content_size_); 522 container_builder_.SetBlockOverflow(content_size_);
477 } 523 }
478 524
479 NGBoxStrut NGBlockLayoutAlgorithm::CalculateMargins( 525 NGBoxStrut NGBlockLayoutAlgorithm::CalculateMargins(
480 NGLayoutInputNode* child, 526 NGLayoutInputNode* child,
481 const NGConstraintSpace& space) { 527 const NGConstraintSpace& space) {
482 DCHECK(child); 528 DCHECK(child);
529 if (child->IsInline())
530 return {};
483 const ComputedStyle& child_style = child->Style(); 531 const ComputedStyle& child_style = child->Style();
484 532
485 WTF::Optional<MinMaxContentSize> sizes; 533 WTF::Optional<MinMaxContentSize> sizes;
486 if (NeedMinMaxContentSize(space, child_style)) 534 if (NeedMinMaxContentSize(space, child_style))
487 sizes = child->ComputeMinMaxContentSize(); 535 sizes = child->ComputeMinMaxContentSize();
488 536
489 LayoutUnit child_inline_size = 537 LayoutUnit child_inline_size =
490 ComputeInlineSizeForFragment(space, child_style, sizes); 538 ComputeInlineSizeForFragment(space, child_style, sizes);
491 NGBoxStrut margins = ComputeMargins(space, child_style, space.WritingMode(), 539 NGBoxStrut margins = ComputeMargins(space, child_style, space.WritingMode(),
492 space.Direction()); 540 space.Direction());
493 if (!child_style.IsFloating()) { 541 if (!child->IsFloating()) {
494 ApplyAutoMargins(space, child_style, child_inline_size, &margins); 542 ApplyAutoMargins(space, child_style, child_inline_size, &margins);
495 } 543 }
496 return margins; 544 return margins;
497 } 545 }
498 546
499 RefPtr<NGConstraintSpace> NGBlockLayoutAlgorithm::CreateConstraintSpaceForChild( 547 RefPtr<NGConstraintSpace> NGBlockLayoutAlgorithm::CreateConstraintSpaceForChild(
548 const NGLogicalOffset& child_bfc_offset,
500 NGLayoutInputNode* child) { 549 NGLayoutInputNode* child) {
501 DCHECK(child); 550 DCHECK(child);
502 551
503 const ComputedStyle& child_style = child->Style(); 552 const ComputedStyle& child_style = child->Style();
504 bool is_new_bfc = IsNewFormattingContextForBlockLevelChild(Style(), *child); 553 bool is_new_bfc = IsNewFormattingContextForBlockLevelChild(Style(), *child);
505 space_builder_.SetIsNewFormattingContext(is_new_bfc) 554 space_builder_.SetIsNewFormattingContext(is_new_bfc)
506 .SetBfcOffset(curr_bfc_offset_); 555 .SetBfcOffset(child_bfc_offset);
507 556
508 if (child->IsInline()) { 557 if (child->IsInline()) {
509 // TODO(kojii): Setup space_builder_ appropriately for inline child. 558 // TODO(kojii): Setup space_builder_ appropriately for inline child.
510 space_builder_.SetBfcOffset(curr_bfc_offset_) 559 space_builder_.SetClearanceOffset(ConstraintSpace().ClearanceOffset());
511 .SetClearanceOffset(ConstraintSpace().ClearanceOffset());
512 return space_builder_.ToConstraintSpace( 560 return space_builder_.ToConstraintSpace(
513 FromPlatformWritingMode(Style().GetWritingMode())); 561 FromPlatformWritingMode(Style().GetWritingMode()));
514 } 562 }
515 563
516 space_builder_ 564 space_builder_
517 .SetClearanceOffset( 565 .SetClearanceOffset(
518 GetClearanceOffset(constraint_space_->Exclusions(), child_style)) 566 GetClearanceOffset(constraint_space_->Exclusions(), child_style))
519 .SetIsShrinkToFit(ShouldShrinkToFit(Style(), child_style)) 567 .SetIsShrinkToFit(ShouldShrinkToFit(Style(), child_style))
520 .SetTextDirection(child_style.Direction()); 568 .SetTextDirection(child_style.Direction());
521 569
522 // Float's margins are not included in child's space because: 570 // Float's margins are not included in child's space because:
523 // 1) Floats do not participate in margins collapsing. 571 // 1) Floats do not participate in margins collapsing.
524 // 2) Floats margins are used separately to calculate floating exclusions. 572 // 2) Floats margins are used separately to calculate floating exclusions.
525 space_builder_.SetMarginStrut(child_style.IsFloating() ? NGMarginStrut() 573 space_builder_.SetMarginStrut(child->IsFloating() ? NGMarginStrut()
526 : curr_margin_strut_); 574 : curr_margin_strut_);
527 575
528 LayoutUnit space_available; 576 LayoutUnit space_available;
529 if (constraint_space_->HasBlockFragmentation()) { 577 if (constraint_space_->HasBlockFragmentation()) {
530 space_available = ConstraintSpace().FragmentainerSpaceAvailable(); 578 space_available = ConstraintSpace().FragmentainerSpaceAvailable();
531 // If a block establishes a new formatting context we must know our 579 // If a block establishes a new formatting context we must know our
532 // position in the formatting context, and are able to adjust the 580 // position in the formatting context, and are able to adjust the
533 // fragmentation line. 581 // fragmentation line.
534 if (is_new_bfc) { 582 if (is_new_bfc) {
535 space_available -= curr_bfc_offset_.block_offset; 583 space_available -= child_bfc_offset.block_offset;
536 } 584 }
537 } 585 }
538 space_builder_.SetFragmentainerSpaceAvailable(space_available); 586 space_builder_.SetFragmentainerSpaceAvailable(space_available);
539 587
540 return space_builder_.ToConstraintSpace( 588 return space_builder_.ToConstraintSpace(
541 FromPlatformWritingMode(child_style.GetWritingMode())); 589 FromPlatformWritingMode(child_style.GetWritingMode()));
542 } 590 }
543 } // namespace blink 591 } // namespace blink
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698