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/ng_absolute_utils.h" | 7 #include "core/layout/ng/ng_absolute_utils.h" |
8 #include "core/layout/ng/ng_block_break_token.h" | 8 #include "core/layout/ng/ng_block_break_token.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" | 10 #include "core/layout/ng/ng_box_fragment.h" |
(...skipping 438 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
449 if (position == EPosition::kAbsolute || position == EPosition::kFixed) { | 449 if (position == EPosition::kAbsolute || position == EPosition::kFixed) { |
450 builder_.AddOutOfFlowChildCandidate(current_block_child, | 450 builder_.AddOutOfFlowChildCandidate(current_block_child, |
451 GetChildSpaceOffset()); | 451 GetChildSpaceOffset()); |
452 NGBlockChildIterator::Entry entry = child_iterator.NextChild(); | 452 NGBlockChildIterator::Entry entry = child_iterator.NextChild(); |
453 child = entry.node; | 453 child = entry.node; |
454 child_break_token = entry.token; | 454 child_break_token = entry.token; |
455 continue; | 455 continue; |
456 } | 456 } |
457 } | 457 } |
458 | 458 |
| 459 PrepareChildLayout(child); |
459 RefPtr<NGConstraintSpace> child_space = | 460 RefPtr<NGConstraintSpace> child_space = |
460 CreateConstraintSpaceForChild(child); | 461 CreateConstraintSpaceForChild(child); |
461 RefPtr<NGLayoutResult> layout_result = | 462 RefPtr<NGLayoutResult> layout_result = |
462 child->Layout(child_space.get(), child_break_token); | 463 child->Layout(child_space.get(), child_break_token); |
463 | 464 |
464 FinishChildLayout(child, child_space.get(), layout_result); | 465 FinishChildLayout(child, child_space.get(), layout_result); |
465 | 466 |
466 entry = child_iterator.NextChild(); | 467 entry = child_iterator.NextChild(); |
467 child = entry.node; | 468 child = entry.node; |
468 child_break_token = entry.token; | 469 child_break_token = entry.token; |
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
508 builder_.SetEndMarginStrut(curr_margin_strut_); | 509 builder_.SetEndMarginStrut(curr_margin_strut_); |
509 | 510 |
510 builder_.SetInlineOverflow(max_inline_size_).SetBlockOverflow(content_size_); | 511 builder_.SetInlineOverflow(max_inline_size_).SetBlockOverflow(content_size_); |
511 | 512 |
512 if (ConstraintSpace().HasBlockFragmentation()) | 513 if (ConstraintSpace().HasBlockFragmentation()) |
513 FinalizeForFragmentation(); | 514 FinalizeForFragmentation(); |
514 | 515 |
515 return builder_.ToBoxFragment(); | 516 return builder_.ToBoxFragment(); |
516 } | 517 } |
517 | 518 |
| 519 void NGBlockLayoutAlgorithm::PrepareChildLayout(NGLayoutInputNode* child) { |
| 520 DCHECK(child); |
| 521 |
| 522 // Margins collapsing: |
| 523 // - An inline node doesn't have any margins to collapse with, so always |
| 524 // can determine its position in space. |
| 525 if (child->Type() == NGLayoutInputNode::kLegacyInline) { |
| 526 curr_bfc_offset_.block_offset += curr_margin_strut_.Sum(); |
| 527 UpdateFragmentBfcOffset(curr_bfc_offset_); |
| 528 PositionPendingFloats(curr_bfc_offset_.block_offset, |
| 529 MutableConstraintSpace(), &builder_); |
| 530 curr_margin_strut_ = {}; |
| 531 curr_child_margins_ = {}; |
| 532 return; |
| 533 } |
| 534 |
| 535 NGBlockNode* block_child = toNGBlockNode(child); |
| 536 const ComputedStyle& child_style = block_child->Style(); |
| 537 |
| 538 // Calculate margins in parent's writing mode. |
| 539 curr_child_margins_ = CalculateMargins( |
| 540 block_child, *space_builder_.ToConstraintSpace( |
| 541 FromPlatformWritingMode(Style().getWritingMode()))); |
| 542 |
| 543 // Clearance: |
| 544 // - *Always* collapse margins and update *container*'s BFC offset. |
| 545 // - Position all pending floats since the fragment's BFC offset is known. |
| 546 if (child_style.clear() != EClear::kNone) { |
| 547 curr_bfc_offset_.block_offset += curr_margin_strut_.Sum(); |
| 548 UpdateFragmentBfcOffset(curr_bfc_offset_); |
| 549 // Only collapse margins if it's an adjoining block with clearance. |
| 550 if (!content_size_) { |
| 551 curr_margin_strut_ = {}; |
| 552 curr_child_margins_.block_start = LayoutUnit(); |
| 553 } |
| 554 PositionPendingFloats(curr_bfc_offset_.block_offset, |
| 555 MutableConstraintSpace(), &builder_); |
| 556 } |
| 557 |
| 558 // Set estimated BFC offset to the next child's constraint space. |
| 559 curr_bfc_offset_ = builder_.BfcOffset() ? builder_.BfcOffset().value() |
| 560 : ConstraintSpace().BfcOffset(); |
| 561 curr_bfc_offset_.block_offset += content_size_; |
| 562 curr_bfc_offset_.inline_offset += border_and_padding_.inline_start; |
| 563 |
| 564 // Floats margins are not included in child's space because: |
| 565 // 1) Floats do not participate in margins collapsing. |
| 566 // 2) Floats margins are used separately to calculate floating exclusions. |
| 567 if (!child_style.isFloating()) { |
| 568 curr_bfc_offset_.inline_offset += curr_child_margins_.inline_start; |
| 569 // Append the current margin strut with child's block start margin. |
| 570 // Non empty border/padding use cases are handled inside of the child's |
| 571 // layout. |
| 572 curr_margin_strut_.Append(curr_child_margins_.block_start); |
| 573 } |
| 574 } |
| 575 |
518 void NGBlockLayoutAlgorithm::FinishChildLayout( | 576 void NGBlockLayoutAlgorithm::FinishChildLayout( |
519 NGLayoutInputNode* child, | 577 NGLayoutInputNode* child, |
520 NGConstraintSpace* child_space, | 578 NGConstraintSpace* child_space, |
521 RefPtr<NGLayoutResult> layout_result) { | 579 RefPtr<NGLayoutResult> layout_result) { |
522 NGBoxFragment fragment( | 580 NGBoxFragment fragment( |
523 ConstraintSpace().WritingMode(), | 581 ConstraintSpace().WritingMode(), |
524 toNGPhysicalBoxFragment(layout_result->PhysicalFragment().get())); | 582 toNGPhysicalBoxFragment(layout_result->PhysicalFragment().get())); |
525 | 583 |
526 // Pull out unpositioned floats to the current fragment. This may needed if | 584 // Pull out unpositioned floats to the current fragment. This may needed if |
527 // for example the child fragment could not position its floats because it's | 585 // for example the child fragment could not position its floats because it's |
(...skipping 130 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
658 } | 716 } |
659 return margins; | 717 return margins; |
660 } | 718 } |
661 | 719 |
662 RefPtr<NGConstraintSpace> NGBlockLayoutAlgorithm::CreateConstraintSpaceForChild( | 720 RefPtr<NGConstraintSpace> NGBlockLayoutAlgorithm::CreateConstraintSpaceForChild( |
663 NGLayoutInputNode* child) { | 721 NGLayoutInputNode* child) { |
664 DCHECK(child); | 722 DCHECK(child); |
665 | 723 |
666 if (child->Type() == NGLayoutInputNode::kLegacyInline) { | 724 if (child->Type() == NGLayoutInputNode::kLegacyInline) { |
667 // TODO(kojii): Setup space_builder_ appropriately for inline child. | 725 // TODO(kojii): Setup space_builder_ appropriately for inline child. |
668 | |
669 // Margins collapsing: Inline block. | |
670 curr_bfc_offset_.block_offset += curr_margin_strut_.Sum(); | |
671 UpdateFragmentBfcOffset(curr_bfc_offset_); | |
672 PositionPendingFloats(curr_bfc_offset_.block_offset, | |
673 MutableConstraintSpace(), &builder_); | |
674 curr_margin_strut_ = {}; | |
675 space_builder_.SetBfcOffset(curr_bfc_offset_); | 726 space_builder_.SetBfcOffset(curr_bfc_offset_); |
676 | |
677 return space_builder_.ToConstraintSpace( | 727 return space_builder_.ToConstraintSpace( |
678 FromPlatformWritingMode(Style().getWritingMode())); | 728 FromPlatformWritingMode(Style().getWritingMode())); |
679 } | 729 } |
680 | 730 |
681 NGBlockNode* block_child = toNGBlockNode(child); | 731 const ComputedStyle& child_style = toNGBlockNode(child)->Style(); |
682 const ComputedStyle& child_style = block_child->Style(); | |
683 | |
684 // Calculate margins in parent's writing mode. | |
685 curr_child_margins_ = CalculateMargins( | |
686 block_child, *space_builder_.ToConstraintSpace( | |
687 FromPlatformWritingMode(Style().getWritingMode()))); | |
688 | 732 |
689 bool is_new_bfc = IsNewFormattingContextForInFlowBlockLevelChild( | 733 bool is_new_bfc = IsNewFormattingContextForInFlowBlockLevelChild( |
690 ConstraintSpace(), child_style); | 734 ConstraintSpace(), child_style); |
691 space_builder_.SetIsNewFormattingContext(is_new_bfc) | 735 space_builder_.SetIsNewFormattingContext(is_new_bfc) |
| 736 .SetBfcOffset(curr_bfc_offset_) |
| 737 .SetClearanceOffset( |
| 738 GetClearanceOffset(constraint_space_->Exclusions(), child_style)) |
692 .SetIsShrinkToFit(ShouldShrinkToFit(ConstraintSpace(), child_style)) | 739 .SetIsShrinkToFit(ShouldShrinkToFit(ConstraintSpace(), child_style)) |
693 .SetTextDirection(child_style.direction()); | 740 .SetTextDirection(child_style.direction()); |
694 | 741 |
695 // Clearance : | 742 // Float's margins are not included in child's space because: |
696 // - *Always* collapse margins and update *container*'s BFC offset. | 743 // 1) Floats do not participate in margins collapsing. |
697 // - Position all pending floats since the fragment's BFC offset is known. | |
698 // - Set the clearance offset on the constraint space's builder. | |
699 if (child_style.clear() != EClear::kNone) { | |
700 curr_bfc_offset_.block_offset += curr_margin_strut_.Sum(); | |
701 UpdateFragmentBfcOffset(curr_bfc_offset_); | |
702 // Only collapse margins if it's an adjoining block with clearance. | |
703 if (!content_size_) { | |
704 curr_margin_strut_ = NGMarginStrut(); | |
705 curr_child_margins_.block_start = LayoutUnit(); | |
706 } | |
707 PositionPendingFloats(curr_bfc_offset_.block_offset, | |
708 MutableConstraintSpace(), &builder_); | |
709 WTF::Optional<LayoutUnit> clearance_offset = | |
710 GetClearanceOffset(constraint_space_->Exclusions(), child_style); | |
711 space_builder_.SetClearanceOffset(clearance_offset); | |
712 } | |
713 | |
714 // Set estimated BFC offset to the next child's constraint space. | |
715 curr_bfc_offset_ = builder_.BfcOffset() ? builder_.BfcOffset().value() | |
716 : ConstraintSpace().BfcOffset(); | |
717 curr_bfc_offset_.block_offset += content_size_; | |
718 curr_bfc_offset_.inline_offset += border_and_padding_.inline_start; | |
719 | |
720 // Floats margins are not included in child's CS because | |
721 // 1) Floats do not participate in margins collapsing | |
722 // 2) Floats margins are used separately to calculate floating exclusions. | 744 // 2) Floats margins are used separately to calculate floating exclusions. |
723 if (!child_style.isFloating()) { | 745 space_builder_.SetMarginStrut(child_style.isFloating() ? NGMarginStrut() |
724 curr_bfc_offset_.inline_offset += curr_child_margins_.inline_start; | 746 : curr_margin_strut_); |
725 // Append the current margin strut with child's block start margin. | |
726 // Non empty border/padding use cases are handled inside of the child's | |
727 // layout. | |
728 curr_margin_strut_.Append(curr_child_margins_.block_start); | |
729 space_builder_.SetMarginStrut(curr_margin_strut_); | |
730 } | |
731 | |
732 space_builder_.SetBfcOffset(curr_bfc_offset_); | |
733 | 747 |
734 LayoutUnit space_available; | 748 LayoutUnit space_available; |
735 if (constraint_space_->HasBlockFragmentation()) { | 749 if (constraint_space_->HasBlockFragmentation()) { |
736 space_available = ConstraintSpace().FragmentainerSpaceAvailable(); | 750 space_available = ConstraintSpace().FragmentainerSpaceAvailable(); |
737 // If a block establishes a new formatting context we must know our | 751 // If a block establishes a new formatting context we must know our |
738 // position in the formatting context, and are able to adjust the | 752 // position in the formatting context, and are able to adjust the |
739 // fragmentation line. | 753 // fragmentation line. |
740 if (is_new_bfc) { | 754 if (is_new_bfc) { |
741 DCHECK(builder_.BfcOffset()); | 755 DCHECK(builder_.BfcOffset()); |
742 space_available -= curr_bfc_offset_.block_offset; | 756 space_available -= curr_bfc_offset_.block_offset; |
743 } | 757 } |
744 } | 758 } |
745 space_builder_.SetFragmentainerSpaceAvailable(space_available); | 759 space_builder_.SetFragmentainerSpaceAvailable(space_available); |
746 | 760 |
747 return space_builder_.ToConstraintSpace( | 761 return space_builder_.ToConstraintSpace( |
748 FromPlatformWritingMode(child_style.getWritingMode())); | 762 FromPlatformWritingMode(child_style.getWritingMode())); |
749 } | 763 } |
750 } // namespace blink | 764 } // namespace blink |
OLD | NEW |