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_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_constraint_space.h" | 10 #include "core/layout/ng/ng_constraint_space.h" |
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
59 bool IsOutOfSpace(const NGConstraintSpace& space, LayoutUnit content_size) { | 59 bool IsOutOfSpace(const NGConstraintSpace& space, LayoutUnit content_size) { |
60 return space.HasBlockFragmentation() && | 60 return space.HasBlockFragmentation() && |
61 content_size >= space.FragmentainerSpaceAvailable(); | 61 content_size >= space.FragmentainerSpaceAvailable(); |
62 } | 62 } |
63 | 63 |
64 bool IsEmptyFragment(NGWritingMode writing_mode, | 64 bool IsEmptyFragment(NGWritingMode writing_mode, |
65 const NGLayoutResult& layout_result) { | 65 const NGLayoutResult& layout_result) { |
66 if (!layout_result.PhysicalFragment()) | 66 if (!layout_result.PhysicalFragment()) |
67 return true; | 67 return true; |
68 | 68 |
| 69 // TODO(ikilpatrick): This is kinda wrong, we need a bit on the |
| 70 // NGLayoutResult to properly determine if something is empty. |
69 NGFragment fragment(writing_mode, layout_result.PhysicalFragment().Get()); | 71 NGFragment fragment(writing_mode, layout_result.PhysicalFragment().Get()); |
70 if (!fragment.BlockSize()) | 72 if (!fragment.BlockSize()) |
71 return true; | 73 return true; |
72 | 74 |
73 return false; | 75 return false; |
74 } | 76 } |
75 | 77 |
76 } // namespace | 78 } // namespace |
77 | 79 |
78 bool MaybeUpdateFragmentBfcOffset(const NGConstraintSpace& space, | 80 bool MaybeUpdateFragmentBfcOffset(const NGConstraintSpace& space, |
(...skipping 19 matching lines...) Expand all Loading... |
98 DCHECK(container_builder->BfcOffset() || space->FloatsBfcOffset()) | 100 DCHECK(container_builder->BfcOffset() || space->FloatsBfcOffset()) |
99 << "Parent BFC offset should be known here"; | 101 << "Parent BFC offset should be known here"; |
100 LayoutUnit from_block_offset = | 102 LayoutUnit from_block_offset = |
101 container_builder->BfcOffset() | 103 container_builder->BfcOffset() |
102 ? container_builder->BfcOffset().value().block_offset | 104 ? container_builder->BfcOffset().value().block_offset |
103 : space->FloatsBfcOffset().value().block_offset; | 105 : space->FloatsBfcOffset().value().block_offset; |
104 | 106 |
105 const auto positioned_floats = PositionFloats( | 107 const auto positioned_floats = PositionFloats( |
106 origin_block_offset, from_block_offset, *unpositioned_floats, space); | 108 origin_block_offset, from_block_offset, *unpositioned_floats, space); |
107 | 109 |
| 110 // TODO(ikilpatrick): Add DCHECK that any positioned floats are children. |
| 111 |
108 for (const auto& positioned_float : positioned_floats) | 112 for (const auto& positioned_float : positioned_floats) |
109 container_builder->AddPositionedFloat(positioned_float); | 113 container_builder->AddPositionedFloat(positioned_float); |
110 | 114 |
111 unpositioned_floats->clear(); | 115 unpositioned_floats->clear(); |
112 } | 116 } |
113 | 117 |
114 NGBlockLayoutAlgorithm::NGBlockLayoutAlgorithm(NGBlockNode node, | 118 NGBlockLayoutAlgorithm::NGBlockLayoutAlgorithm(NGBlockNode node, |
115 NGConstraintSpace* space, | 119 NGConstraintSpace* space, |
116 NGBlockBreakToken* break_token) | 120 NGBlockBreakToken* break_token) |
117 : NGLayoutAlgorithm(node, space, break_token) {} | 121 : NGLayoutAlgorithm(node, space, break_token) {} |
(...skipping 142 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
260 WTF::Optional<NGPreviousInflowPosition> previous_inflow_position = | 264 WTF::Optional<NGPreviousInflowPosition> previous_inflow_position = |
261 NGPreviousInflowPosition{input_bfc_block_offset, content_size_, | 265 NGPreviousInflowPosition{input_bfc_block_offset, content_size_, |
262 input_margin_strut}; | 266 input_margin_strut}; |
263 | 267 |
264 while (child) { | 268 while (child) { |
265 if (child.IsOutOfFlowPositioned()) { | 269 if (child.IsOutOfFlowPositioned()) { |
266 DCHECK(!child_break_token); | 270 DCHECK(!child_break_token); |
267 HandleOutOfFlowPositioned(previous_inflow_position.value(), | 271 HandleOutOfFlowPositioned(previous_inflow_position.value(), |
268 ToNGBlockNode(child)); | 272 ToNGBlockNode(child)); |
269 } else if (child.IsFloating()) { | 273 } else if (child.IsFloating()) { |
270 HandleFloating(previous_inflow_position.value(), ToNGBlockNode(child), | 274 HandleFloat(previous_inflow_position.value(), ToNGBlockNode(child), |
271 ToNGBlockBreakToken(child_break_token)); | 275 ToNGBlockBreakToken(child_break_token)); |
272 } else { | 276 } else { |
273 // TODO(ikilpatrick): Refactor this else branch. | 277 previous_inflow_position = HandleInflow(previous_inflow_position.value(), |
274 WTF::Optional<NGInflowChildData> child_data = | 278 child, child_break_token); |
275 PrepareChildLayout(previous_inflow_position.value(), child); | |
276 | 279 |
277 // If PrepareChildLayout resolved our BFC offset, abort the layout. | 280 // If we didn't receive a NGPreviousInflowPosition from HandleInflow, we |
278 if (!child_data) { | 281 // need to abort the layout as our BFC offset was resolved. |
279 DCHECK(container_builder_.BfcOffset()); | |
280 container_builder_.SwapUnpositionedFloats(&unpositioned_floats_); | |
281 return container_builder_.Abort(NGLayoutResult::kBfcOffsetResolved); | |
282 } | |
283 | |
284 RefPtr<NGConstraintSpace> child_space = | |
285 CreateConstraintSpaceForChild(child, child_data.value()); | |
286 RefPtr<NGLayoutResult> layout_result = | |
287 child.Layout(child_space.Get(), child_break_token); | |
288 | |
289 // A child may have aborted its layout if it resolved its BFC offset. If | |
290 // we don't have a BFC offset yet, we need to propagate the abortion up | |
291 // to our parent. | |
292 if (layout_result->Status() == NGLayoutResult::kBfcOffsetResolved && | |
293 !container_builder_.BfcOffset()) { | |
294 MaybeUpdateFragmentBfcOffset( | |
295 ConstraintSpace(), layout_result->BfcOffset().value().block_offset, | |
296 &container_builder_); | |
297 container_builder_.SwapUnpositionedFloats(&unpositioned_floats_); | |
298 return container_builder_.Abort(NGLayoutResult::kBfcOffsetResolved); | |
299 } | |
300 | |
301 previous_inflow_position = FinishChildLayout( | |
302 *child_space, previous_inflow_position.value(), child_data.value(), | |
303 child, child_break_token, std::move(layout_result)); | |
304 | |
305 // If FinishChildLayout resolved our BFC offset, abort the layout. | |
306 if (!previous_inflow_position) { | 282 if (!previous_inflow_position) { |
307 container_builder_.SwapUnpositionedFloats(&unpositioned_floats_); | 283 container_builder_.SwapUnpositionedFloats(&unpositioned_floats_); |
308 return container_builder_.Abort(NGLayoutResult::kBfcOffsetResolved); | 284 return container_builder_.Abort(NGLayoutResult::kBfcOffsetResolved); |
309 } | 285 } |
310 } | 286 } |
311 | 287 |
312 entry = child_iterator.NextChild(); | 288 entry = child_iterator.NextChild(); |
313 child = entry.node; | 289 child = entry.node; |
314 child_break_token = entry.token; | 290 child_break_token = entry.token; |
315 | 291 |
(...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
413 previous_inflow_position.logical_block_offset}; | 389 previous_inflow_position.logical_block_offset}; |
414 | 390 |
415 // We only include the margin strut in the OOF static-position if we know we | 391 // We only include the margin strut in the OOF static-position if we know we |
416 // aren't going to be a zero-block-size fragment. | 392 // aren't going to be a zero-block-size fragment. |
417 if (container_builder_.BfcOffset()) | 393 if (container_builder_.BfcOffset()) |
418 offset.block_offset += previous_inflow_position.margin_strut.Sum(); | 394 offset.block_offset += previous_inflow_position.margin_strut.Sum(); |
419 | 395 |
420 container_builder_.AddOutOfFlowChildCandidate(child, offset); | 396 container_builder_.AddOutOfFlowChildCandidate(child, offset); |
421 } | 397 } |
422 | 398 |
423 void NGBlockLayoutAlgorithm::HandleFloating( | 399 void NGBlockLayoutAlgorithm::HandleFloat( |
424 const NGPreviousInflowPosition& previous_inflow_position, | 400 const NGPreviousInflowPosition& previous_inflow_position, |
425 NGBlockNode child, | 401 NGBlockNode child, |
426 NGBlockBreakToken* token) { | 402 NGBlockBreakToken* token) { |
427 // Calculate margins in the BFC's writing mode. | 403 // Calculate margins in the BFC's writing mode. |
428 NGBoxStrut margins = CalculateMargins(child); | 404 NGBoxStrut margins = CalculateMargins(child); |
429 | 405 |
430 LayoutUnit origin_inline_offset = | 406 LayoutUnit origin_inline_offset = |
431 constraint_space_->BfcOffset().inline_offset + | 407 constraint_space_->BfcOffset().inline_offset + |
432 border_scrollbar_padding_.inline_start; | 408 border_scrollbar_padding_.inline_start; |
433 | 409 |
(...skipping 14 matching lines...) Expand all Loading... |
448 LayoutUnit origin_block_offset = | 424 LayoutUnit origin_block_offset = |
449 container_builder_.BfcOffset() | 425 container_builder_.BfcOffset() |
450 ? previous_inflow_position.bfc_block_offset + | 426 ? previous_inflow_position.bfc_block_offset + |
451 previous_inflow_position.margin_strut.Sum() | 427 previous_inflow_position.margin_strut.Sum() |
452 : ConstraintSpace().FloatsBfcOffset().value().block_offset; | 428 : ConstraintSpace().FloatsBfcOffset().value().block_offset; |
453 PositionPendingFloats(origin_block_offset, &container_builder_, | 429 PositionPendingFloats(origin_block_offset, &container_builder_, |
454 &unpositioned_floats_, MutableConstraintSpace()); | 430 &unpositioned_floats_, MutableConstraintSpace()); |
455 } | 431 } |
456 } | 432 } |
457 | 433 |
458 WTF::Optional<NGInflowChildData> NGBlockLayoutAlgorithm::PrepareChildLayout( | 434 WTF::Optional<NGPreviousInflowPosition> NGBlockLayoutAlgorithm::HandleInflow( |
459 const NGPreviousInflowPosition& previous_inflow_position, | 435 const NGPreviousInflowPosition& previous_inflow_position, |
460 NGLayoutInputNode child) { | 436 NGLayoutInputNode child, |
| 437 NGBreakToken* child_break_token) { |
461 DCHECK(child); | 438 DCHECK(child); |
462 DCHECK(!child.IsFloating()); | 439 DCHECK(!child.IsFloating()); |
463 | 440 DCHECK(!child.IsOutOfFlowPositioned()); |
464 LayoutUnit bfc_block_offset = previous_inflow_position.bfc_block_offset; | |
465 | |
466 // Calculate margins in parent's writing mode. | |
467 NGBoxStrut margins = CalculateMargins(child); | |
468 NGMarginStrut margin_strut = previous_inflow_position.margin_strut; | |
469 | 441 |
470 bool should_position_pending_floats = | 442 bool should_position_pending_floats = |
471 !child.CreatesNewFormattingContext() && | 443 !child.CreatesNewFormattingContext() && |
472 ClearanceMayAffectLayout(ConstraintSpace(), unpositioned_floats_, | 444 ClearanceMayAffectLayout(ConstraintSpace(), unpositioned_floats_, |
473 child.Style()); | 445 child.Style()); |
474 | 446 |
475 // Children which may clear a float need to force all the pending floats to | 447 // Children which may clear a float need to force all the pending floats to |
476 // be positioned before layout. This also resolves the fragment's bfc offset. | 448 // be positioned before layout. This also resolves our BFC offset. |
477 if (should_position_pending_floats) { | 449 if (should_position_pending_floats) { |
478 LayoutUnit origin_point_block_offset = | 450 LayoutUnit origin_point_block_offset = |
479 bfc_block_offset + margin_strut.Sum(); | 451 previous_inflow_position.bfc_block_offset + |
| 452 previous_inflow_position.margin_strut.Sum(); |
480 bool updated = MaybeUpdateFragmentBfcOffset( | 453 bool updated = MaybeUpdateFragmentBfcOffset( |
481 ConstraintSpace(), origin_point_block_offset, &container_builder_); | 454 ConstraintSpace(), origin_point_block_offset, &container_builder_); |
482 | 455 |
483 if (updated && abort_when_bfc_resolved_) | 456 if (updated && abort_when_bfc_resolved_) |
484 return WTF::nullopt; | 457 return WTF::nullopt; |
485 | 458 |
486 // TODO(ikilpatrick): Check if origin_point_block_offset is correct - | 459 // TODO(ikilpatrick): Check if origin_point_block_offset is correct - |
487 // MaybeUpdateFragmentBfcOffset might have changed it due to clearance. | 460 // MaybeUpdateFragmentBfcOffset might have changed it due to clearance. |
488 PositionPendingFloats(origin_point_block_offset, &container_builder_, | 461 PositionPendingFloats(origin_point_block_offset, &container_builder_, |
489 &unpositioned_floats_, MutableConstraintSpace()); | 462 &unpositioned_floats_, MutableConstraintSpace()); |
490 } | 463 } |
491 | 464 |
492 NGLogicalOffset child_bfc_offset = { | 465 // Perform layout on the child. |
493 ConstraintSpace().BfcOffset().inline_offset + | 466 NGInflowChildData child_data = |
494 border_scrollbar_padding_.inline_start + margins.inline_start, | 467 ComputeChildData(previous_inflow_position, child); |
495 bfc_block_offset}; | 468 RefPtr<NGConstraintSpace> child_space = |
496 | 469 CreateConstraintSpaceForChild(child, child_data); |
497 // Append the current margin strut with child's block start margin. | 470 RefPtr<NGLayoutResult> layout_result = |
498 // Non empty border/padding, and new FC use cases are handled inside of the | 471 child.Layout(child_space.Get(), child_break_token); |
499 // child's layout | |
500 margin_strut.Append(margins.block_start); | |
501 | |
502 return NGInflowChildData{child_bfc_offset, margin_strut, margins}; | |
503 } | |
504 | |
505 WTF::Optional<NGPreviousInflowPosition> | |
506 NGBlockLayoutAlgorithm::FinishChildLayout( | |
507 const NGConstraintSpace& child_space, | |
508 const NGPreviousInflowPosition& previous_inflow_position, | |
509 const NGInflowChildData& child_data, | |
510 NGLayoutInputNode child, | |
511 NGBreakToken* child_break_token, | |
512 RefPtr<NGLayoutResult> layout_result) { | |
513 // TODO(ikilpatrick): Split this function into two - one for positioning, and | |
514 // the other for producing NGPreviousInflowPosition. | |
515 | 472 |
516 // If we don't know our BFC offset yet, we need to copy the list of | 473 // If we don't know our BFC offset yet, we need to copy the list of |
517 // unpositioned floats from the child's layout result. | 474 // unpositioned floats from the child's layout result. |
518 // | 475 // |
519 // If the child had any unpositioned floats, we need to abort our layout if | 476 // If the child had any unpositioned floats, we need to abort our layout if |
520 // we resolve our BFC offset. | 477 // we resolve our BFC offset. |
521 // | 478 // |
522 // If we are a new formatting context, the child will get re-laid out once it | 479 // If we are a new formatting context, the child will get re-laid out once it |
523 // has been positioned. | 480 // has been positioned. |
524 // | 481 // |
525 // TODO(ikilpatrick): a more optimal version of this is to set | 482 // TODO(ikilpatrick): a more optimal version of this is to set |
526 // abort_when_bfc_resolved_, if the child tree _added_ any floats. | 483 // abort_when_bfc_resolved_, if the child tree _added_ any floats. |
527 if (!container_builder_.BfcOffset() && | 484 if (!container_builder_.BfcOffset() && !child.CreatesNewFormattingContext()) { |
528 !child_space.IsNewFormattingContext()) { | |
529 unpositioned_floats_ = layout_result->UnpositionedFloats(); | 485 unpositioned_floats_ = layout_result->UnpositionedFloats(); |
530 abort_when_bfc_resolved_ |= !layout_result->UnpositionedFloats().IsEmpty(); | 486 abort_when_bfc_resolved_ |= !layout_result->UnpositionedFloats().IsEmpty(); |
531 if (child_space.FloatsBfcOffset()) | 487 if (child_space->FloatsBfcOffset()) |
532 DCHECK(layout_result->UnpositionedFloats().IsEmpty()); | 488 DCHECK(layout_result->UnpositionedFloats().IsEmpty()); |
533 } | 489 } |
534 | 490 |
535 // Determine the fragment's position in the parent space. | 491 // A child may have aborted its layout if it resolved its BFC offset. If |
| 492 // we don't have a BFC offset yet, we need to propagate the abortion up |
| 493 // to our parent. |
| 494 if (layout_result->Status() == NGLayoutResult::kBfcOffsetResolved && |
| 495 !container_builder_.BfcOffset()) { |
| 496 DCHECK(!child.CreatesNewFormattingContext()); |
| 497 |
| 498 MaybeUpdateFragmentBfcOffset( |
| 499 ConstraintSpace(), layout_result->BfcOffset().value().block_offset, |
| 500 &container_builder_); |
| 501 |
| 502 // NOTE: Unlike other aborts, we don't try check if we *should* abort with |
| 503 // abort_when_bfc_resolved_, this is simply propagating an abort up to a |
| 504 // node which is able to restart the layout (a node that has resolved its |
| 505 // BFC offset). |
| 506 return WTF::nullopt; |
| 507 } |
| 508 |
| 509 // We try and position the child within the block formatting context. This |
| 510 // may cause our BFC offset to be resolved, in which case we should abort our |
| 511 // layout if needed. |
536 WTF::Optional<NGLogicalOffset> child_bfc_offset; | 512 WTF::Optional<NGLogicalOffset> child_bfc_offset; |
537 if (child.CreatesNewFormattingContext()) { | 513 if (child.CreatesNewFormattingContext()) { |
538 if (!PositionNewFc(child, previous_inflow_position, *layout_result, | 514 if (!PositionNewFc(child, previous_inflow_position, *layout_result, |
539 child_data, child_space, &child_bfc_offset)) | 515 child_data, *child_space, &child_bfc_offset)) |
540 return WTF::nullopt; | 516 return WTF::nullopt; |
541 } else if (layout_result->BfcOffset()) { | 517 } else if (layout_result->BfcOffset()) { |
542 if (!PositionWithBfcOffset(layout_result->BfcOffset().value(), | 518 if (!PositionWithBfcOffset(layout_result->BfcOffset().value(), |
543 &child_bfc_offset)) | 519 &child_bfc_offset)) |
544 return WTF::nullopt; | 520 return WTF::nullopt; |
545 } else if (container_builder_.BfcOffset()) { | 521 } else if (container_builder_.BfcOffset()) { |
546 child_bfc_offset = | 522 child_bfc_offset = |
547 PositionWithParentBfc(child_space, child_data, *layout_result); | 523 PositionWithParentBfc(*child_space, child_data, *layout_result); |
548 } else | 524 } else |
549 DCHECK(IsEmptyFragment(ConstraintSpace().WritingMode(), *layout_result)); | 525 DCHECK(IsEmptyFragment(ConstraintSpace().WritingMode(), *layout_result)); |
550 | 526 |
| 527 // We need to layout a child if we know its BFC offset and: |
| 528 // - It aborted its layout as it resolved its BFC offset. |
| 529 // - It has some unpositioned floats. |
551 if ((layout_result->Status() == NGLayoutResult::kBfcOffsetResolved || | 530 if ((layout_result->Status() == NGLayoutResult::kBfcOffsetResolved || |
552 !layout_result->UnpositionedFloats().IsEmpty()) && | 531 !layout_result->UnpositionedFloats().IsEmpty()) && |
553 child_bfc_offset) { | 532 child_bfc_offset) { |
554 RefPtr<NGConstraintSpace> new_child_space = | 533 RefPtr<NGConstraintSpace> new_child_space = |
555 CreateConstraintSpaceForChild(child, child_data, child_bfc_offset); | 534 CreateConstraintSpaceForChild(child, child_data, child_bfc_offset); |
556 layout_result = child.Layout(new_child_space.Get(), child_break_token); | 535 layout_result = child.Layout(new_child_space.Get(), child_break_token); |
| 536 |
| 537 DCHECK_EQ(layout_result->Status(), NGLayoutResult::kSuccess); |
557 } | 538 } |
558 | 539 |
| 540 // We must have an actual fragment at this stage. |
| 541 DCHECK(layout_result->PhysicalFragment().Get()); |
| 542 |
559 NGBoxFragment fragment( | 543 NGBoxFragment fragment( |
560 ConstraintSpace().WritingMode(), | 544 ConstraintSpace().WritingMode(), |
561 ToNGPhysicalBoxFragment(layout_result->PhysicalFragment().Get())); | 545 ToNGPhysicalBoxFragment(layout_result->PhysicalFragment().Get())); |
562 | 546 |
563 NGLogicalOffset logical_offset = | 547 NGLogicalOffset logical_offset = |
564 CalculateLogicalOffset(child_data.margins, child_bfc_offset); | 548 CalculateLogicalOffset(child_data.margins, child_bfc_offset); |
565 | 549 |
566 NGMarginStrut margin_strut = layout_result->EndMarginStrut(); | |
567 margin_strut.Append(child_data.margins.block_end); | |
568 | |
569 // TODO(ikilpatrick): Refactor below such that we don't have to rely on the | |
570 // if (fragment) ... checks. | |
571 | |
572 // Only modify content_size_ if the fragment's BlockSize is not empty. This is | 550 // Only modify content_size_ if the fragment's BlockSize is not empty. This is |
573 // needed to prevent the situation when logical_offset is included in | 551 // needed to prevent the situation when logical_offset is included in |
574 // content_size_ for empty blocks. Example: | 552 // content_size_ for empty blocks. Example: |
575 // <div style="overflow:hidden"> | 553 // <div style="overflow:hidden"> |
576 // <div style="margin-top: 8px"></div> | 554 // <div style="margin-top: 8px"></div> |
577 // <div style="margin-top: 10px"></div> | 555 // <div style="margin-top: 10px"></div> |
578 // </div> | 556 // </div> |
579 if (fragment) { | 557 if (fragment.BlockSize()) { |
580 if (fragment.BlockSize()) { | 558 content_size_ = std::max( |
581 content_size_ = std::max( | 559 content_size_, logical_offset.block_offset + fragment.BlockSize()); |
582 content_size_, logical_offset.block_offset + fragment.BlockSize()); | |
583 } | |
584 max_inline_size_ = | |
585 std::max(max_inline_size_, fragment.InlineSize() + | |
586 child_data.margins.InlineSum() + | |
587 border_scrollbar_padding_.InlineSum()); | |
588 } | 560 } |
| 561 max_inline_size_ = std::max( |
| 562 max_inline_size_, fragment.InlineSize() + child_data.margins.InlineSum() + |
| 563 border_scrollbar_padding_.InlineSum()); |
589 | 564 |
590 if (fragment) | 565 container_builder_.AddChild(layout_result, logical_offset); |
591 container_builder_.AddChild(layout_result, logical_offset); | |
592 | 566 |
| 567 return ComputeInflowPosition(previous_inflow_position, child_data, |
| 568 child_bfc_offset, logical_offset, *layout_result, |
| 569 fragment); |
| 570 } |
| 571 |
| 572 NGInflowChildData NGBlockLayoutAlgorithm::ComputeChildData( |
| 573 const NGPreviousInflowPosition& previous_inflow_position, |
| 574 NGLayoutInputNode child) { |
| 575 DCHECK(child); |
| 576 DCHECK(!child.IsFloating()); |
| 577 |
| 578 // Calculate margins in parent's writing mode. |
| 579 NGBoxStrut margins = CalculateMargins(child); |
| 580 |
| 581 // Append the current margin strut with child's block start margin. |
| 582 // Non empty border/padding, and new FC use cases are handled inside of the |
| 583 // child's layout |
| 584 NGMarginStrut margin_strut = previous_inflow_position.margin_strut; |
| 585 margin_strut.Append(margins.block_start); |
| 586 |
| 587 NGLogicalOffset child_bfc_offset = { |
| 588 ConstraintSpace().BfcOffset().inline_offset + |
| 589 border_scrollbar_padding_.inline_start + margins.inline_start, |
| 590 previous_inflow_position.bfc_block_offset}; |
| 591 |
| 592 return {child_bfc_offset, margin_strut, margins}; |
| 593 } |
| 594 |
| 595 NGPreviousInflowPosition NGBlockLayoutAlgorithm::ComputeInflowPosition( |
| 596 const NGPreviousInflowPosition& previous_inflow_position, |
| 597 const NGInflowChildData& child_data, |
| 598 const WTF::Optional<NGLogicalOffset>& child_bfc_offset, |
| 599 const NGLogicalOffset& logical_offset, |
| 600 const NGLayoutResult& layout_result, |
| 601 const NGFragment& fragment) { |
593 // Determine the child's end BFC block offset and logical offset, for the | 602 // Determine the child's end BFC block offset and logical offset, for the |
594 // next child to use. | 603 // next child to use. |
595 LayoutUnit child_end_bfc_block_offset; | 604 LayoutUnit child_end_bfc_block_offset; |
596 LayoutUnit logical_block_offset; | 605 LayoutUnit logical_block_offset; |
597 | 606 |
598 if (child_bfc_offset) { | 607 if (child_bfc_offset) { |
599 // TODO(crbug.com/716930): I think the layout_result->BfcOffset() condition | 608 // TODO(crbug.com/716930): I think the layout_result->BfcOffset() condition |
600 // here can be removed once we've removed inline splitting. | 609 // here can be removed once we've removed inline splitting. |
601 if (fragment && (fragment.BlockSize() || layout_result->BfcOffset())) { | 610 if (fragment.BlockSize() || layout_result.BfcOffset()) { |
602 child_end_bfc_block_offset = | 611 child_end_bfc_block_offset = |
603 child_bfc_offset.value().block_offset + fragment.BlockSize(); | 612 child_bfc_offset.value().block_offset + fragment.BlockSize(); |
604 logical_block_offset = logical_offset.block_offset + fragment.BlockSize(); | 613 logical_block_offset = logical_offset.block_offset + fragment.BlockSize(); |
605 } else { | 614 } else { |
606 DCHECK(IsEmptyFragment(ConstraintSpace().WritingMode(), *layout_result)); | 615 DCHECK(IsEmptyFragment(ConstraintSpace().WritingMode(), layout_result)); |
607 | 616 |
608 child_end_bfc_block_offset = previous_inflow_position.bfc_block_offset; | 617 child_end_bfc_block_offset = previous_inflow_position.bfc_block_offset; |
609 logical_block_offset = previous_inflow_position.logical_block_offset; | 618 logical_block_offset = previous_inflow_position.logical_block_offset; |
610 } | 619 } |
611 } else { | 620 } else { |
612 child_end_bfc_block_offset = ConstraintSpace().BfcOffset().block_offset; | 621 child_end_bfc_block_offset = ConstraintSpace().BfcOffset().block_offset; |
613 logical_block_offset = LayoutUnit(); | 622 logical_block_offset = LayoutUnit(); |
614 } | 623 } |
615 | 624 |
616 return NGPreviousInflowPosition{child_end_bfc_block_offset, | 625 NGMarginStrut margin_strut = layout_result.EndMarginStrut(); |
617 logical_block_offset, margin_strut}; | 626 margin_strut.Append(child_data.margins.block_end); |
| 627 |
| 628 return {child_end_bfc_block_offset, logical_block_offset, margin_strut}; |
618 } | 629 } |
619 | 630 |
620 bool NGBlockLayoutAlgorithm::PositionNewFc( | 631 bool NGBlockLayoutAlgorithm::PositionNewFc( |
621 const NGLayoutInputNode& child, | 632 const NGLayoutInputNode& child, |
622 const NGPreviousInflowPosition& previous_inflow_position, | 633 const NGPreviousInflowPosition& previous_inflow_position, |
623 const NGLayoutResult& layout_result, | 634 const NGLayoutResult& layout_result, |
624 const NGInflowChildData& child_data, | 635 const NGInflowChildData& child_data, |
625 const NGConstraintSpace& child_space, | 636 const NGConstraintSpace& child_space, |
626 WTF::Optional<NGLogicalOffset>* child_bfc_offset) { | 637 WTF::Optional<NGLogicalOffset>* child_bfc_offset) { |
627 const ComputedStyle& child_style = child.Style(); | 638 const ComputedStyle& child_style = child.Style(); |
(...skipping 265 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
893 for (unsigned i = 0; i < container_builder_.Children().size(); i++) { | 904 for (unsigned i = 0; i < container_builder_.Children().size(); i++) { |
894 if (AddBaseline(request, i)) | 905 if (AddBaseline(request, i)) |
895 break; | 906 break; |
896 } | 907 } |
897 break; | 908 break; |
898 } | 909 } |
899 } | 910 } |
900 } | 911 } |
901 | 912 |
902 } // namespace blink | 913 } // namespace blink |
OLD | NEW |