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_box_fragment.h" | 9 #include "core/layout/ng/ng_box_fragment.h" |
10 #include "core/layout/ng/ng_column_mapper.h" | 10 #include "core/layout/ng/ng_column_mapper.h" |
(...skipping 400 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
411 content_size_ = border_and_padding_.block_start; | 411 content_size_ = border_and_padding_.block_start; |
412 current_child_ = first_child_; | 412 current_child_ = first_child_; |
413 } | 413 } |
414 | 414 |
415 curr_margin_strut_ = ConstraintSpace().MarginStrut(); | 415 curr_margin_strut_ = ConstraintSpace().MarginStrut(); |
416 curr_bfc_offset_ = ConstraintSpace().BfcOffset(); | 416 curr_bfc_offset_ = ConstraintSpace().BfcOffset(); |
417 | 417 |
418 // Margins collapsing: | 418 // Margins collapsing: |
419 // Do not collapse margins between parent and its child if there is | 419 // Do not collapse margins between parent and its child if there is |
420 // border/padding between them. | 420 // border/padding between them. |
421 if (border_and_padding_.block_start || | 421 if (border_and_padding_.block_start) { |
422 ConstraintSpace().IsNewFormattingContext()) { | |
423 curr_bfc_offset_.block_offset += curr_margin_strut_.Sum(); | 422 curr_bfc_offset_.block_offset += curr_margin_strut_.Sum(); |
424 builder_->SetBfcOffset(curr_bfc_offset_); | 423 UpdateFragmentBfcOffset(curr_bfc_offset_, builder_.get()); |
425 curr_margin_strut_ = NGMarginStrut(); | 424 curr_margin_strut_ = NGMarginStrut(); |
426 } | 425 } |
ikilpatrick
2017/02/16 17:27:37
.nit nl below this?
Gleb Lanbin
2017/02/16 20:08:27
Done.
| |
426 // Block that establishes new BFC knows its BFC offset == {}. | |
ikilpatrick
2017/02/16 17:27:37
Maybe some additional comments:
Block that establ
Gleb Lanbin
2017/02/16 20:08:27
Done.
| |
427 if (ConstraintSpace().IsNewFormattingContext()) { | |
428 UpdateFragmentBfcOffset(curr_bfc_offset_, builder_.get()); | |
429 DCHECK_EQ(builder_->BfcOffset().value(), NGLogicalOffset()); | |
430 DCHECK_EQ(curr_margin_strut_, NGMarginStrut()); | |
431 } | |
432 | |
427 curr_bfc_offset_.block_offset += content_size_; | 433 curr_bfc_offset_.block_offset += content_size_; |
428 | 434 |
429 while (current_child_) { | 435 while (current_child_) { |
430 if (current_child_->Type() == NGLayoutInputNode::kLegacyBlock) { | 436 if (current_child_->Type() == NGLayoutInputNode::kLegacyBlock) { |
431 NGBlockNode* current_block_child = toNGBlockNode(current_child_); | 437 NGBlockNode* current_block_child = toNGBlockNode(current_child_); |
432 EPosition position = current_block_child->Style().position(); | 438 EPosition position = current_block_child->Style().position(); |
433 if (position == EPosition::kAbsolute || position == EPosition::kFixed) { | 439 if (position == EPosition::kAbsolute || position == EPosition::kFixed) { |
434 builder_->AddOutOfFlowChildCandidate(current_block_child, | 440 builder_->AddOutOfFlowChildCandidate(current_block_child, |
435 GetChildSpaceOffset()); | 441 GetChildSpaceOffset()); |
436 current_child_ = current_block_child->NextSibling(); | 442 current_child_ = current_block_child->NextSibling(); |
(...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
515 line_builder.CopyFragmentDataToLayoutBlockFlow(); | 521 line_builder.CopyFragmentDataToLayoutBlockFlow(); |
516 FinishCurrentChildLayout(child_fragment.get()); | 522 FinishCurrentChildLayout(child_fragment.get()); |
517 current_child_ = nullptr; | 523 current_child_ = nullptr; |
518 } | 524 } |
519 | 525 |
520 void NGBlockLayoutAlgorithm::FinishCurrentChildLayout( | 526 void NGBlockLayoutAlgorithm::FinishCurrentChildLayout( |
521 RefPtr<NGPhysicalBoxFragment> physical_fragment) { | 527 RefPtr<NGPhysicalBoxFragment> physical_fragment) { |
522 NGBoxFragment fragment(ConstraintSpace().WritingMode(), | 528 NGBoxFragment fragment(ConstraintSpace().WritingMode(), |
523 physical_fragment.get()); | 529 physical_fragment.get()); |
524 | 530 |
525 if (!physical_fragment->UnpositionedFloats().isEmpty()) | |
526 DCHECK(!builder_->BfcOffset()) << "Parent BFC offset shouldn't be set here"; | |
527 // Pull out unpositioned floats to the current fragment. This may needed if | 531 // Pull out unpositioned floats to the current fragment. This may needed if |
528 // for example the child fragment could not position its floats because it's | 532 // for example the child fragment could not position its floats because it's |
529 // empty and therefore couldn't determine its position in space. | 533 // empty and therefore couldn't determine its position in space. |
530 builder_->MutableUnpositionedFloats().appendVector( | 534 builder_->MutableUnpositionedFloats().appendVector( |
531 physical_fragment->UnpositionedFloats()); | 535 physical_fragment->UnpositionedFloats()); |
532 | 536 |
533 if (current_child_->Type() == NGLayoutInputNode::kLegacyBlock && | 537 if (current_child_->Type() == NGLayoutInputNode::kLegacyBlock && |
534 CurrentChildStyle().isFloating()) { | 538 CurrentChildStyle().isFloating()) { |
535 NGFloatingObject* floating_object = | 539 NGFloatingObject* floating_object = |
536 new NGFloatingObject(physical_fragment.get(), space_for_current_child_, | 540 new NGFloatingObject(physical_fragment.get(), space_for_current_child_, |
(...skipping 16 matching lines...) Expand all Loading... | |
553 // Determine the fragment's position in the parent space either by using | 557 // Determine the fragment's position in the parent space either by using |
554 // content_size_ or known fragment's BFC offset. | 558 // content_size_ or known fragment's BFC offset. |
555 WTF::Optional<NGLogicalOffset> bfc_offset; | 559 WTF::Optional<NGLogicalOffset> bfc_offset; |
556 if (CurrentChildConstraintSpace().IsNewFormattingContext()) { | 560 if (CurrentChildConstraintSpace().IsNewFormattingContext()) { |
557 curr_bfc_offset_.block_offset += curr_margin_strut_.Sum(); | 561 curr_bfc_offset_.block_offset += curr_margin_strut_.Sum(); |
558 bfc_offset = curr_bfc_offset_; | 562 bfc_offset = curr_bfc_offset_; |
559 } else if (fragment.BfcOffset()) { | 563 } else if (fragment.BfcOffset()) { |
560 // Fragment that knows its offset can be used to set parent's BFC position. | 564 // Fragment that knows its offset can be used to set parent's BFC position. |
561 curr_bfc_offset_.block_offset = fragment.BfcOffset().value().block_offset; | 565 curr_bfc_offset_.block_offset = fragment.BfcOffset().value().block_offset; |
562 bfc_offset = curr_bfc_offset_; | 566 bfc_offset = curr_bfc_offset_; |
567 } else if (builder_->BfcOffset()) { | |
ikilpatrick
2017/02/16 17:27:37
can you add a comment for when this will get hit,
Gleb Lanbin
2017/02/16 20:08:27
Done.
| |
568 bfc_offset = curr_bfc_offset_; | |
569 bfc_offset.value().block_offset += curr_margin_strut_.Sum(); | |
563 } | 570 } |
564 if (bfc_offset) { | 571 if (bfc_offset) { |
565 UpdateFragmentBfcOffset(curr_bfc_offset_, builder_.get()); | 572 UpdateFragmentBfcOffset(curr_bfc_offset_, builder_.get()); |
566 PositionPendingFloats(curr_bfc_offset_.block_offset, ConstraintSpace(), | 573 PositionPendingFloats(curr_bfc_offset_.block_offset, ConstraintSpace(), |
567 builder_.get()); | 574 builder_.get()); |
568 } | 575 } |
569 NGLogicalOffset logical_offset = CalculateLogicalOffset(bfc_offset); | 576 NGLogicalOffset logical_offset = CalculateLogicalOffset(bfc_offset); |
570 | 577 |
571 if (fragmentainer_mapper_) | 578 if (fragmentainer_mapper_) |
572 fragmentainer_mapper_->ToVisualOffset(logical_offset); | 579 fragmentainer_mapper_->ToVisualOffset(logical_offset); |
573 else | 580 else |
574 logical_offset.block_offset -= PreviousBreakOffset(); | 581 logical_offset.block_offset -= PreviousBreakOffset(); |
575 | 582 |
576 // Update margin strut. | 583 // Update margin strut. |
577 curr_margin_strut_ = fragment.EndMarginStrut(); | 584 curr_margin_strut_ = fragment.EndMarginStrut(); |
578 curr_margin_strut_.Append(curr_child_margins_.block_end); | 585 curr_margin_strut_.Append(curr_child_margins_.block_end); |
579 | 586 |
580 content_size_ = fragment.BlockSize() + logical_offset.block_offset; | 587 // Only modify content_size if BlockSize is not empty. It's needed to prevent |
588 // the situation when logical_offset is included in content_size for empty | |
589 // blocks. Example: | |
590 // <div style="overflow:hidden"> | |
591 // <div style="margin-top: 8px"></div> | |
592 // <div style="margin-top: 10px"></div> | |
593 // </div> | |
594 if (fragment.BlockSize()) | |
595 content_size_ = fragment.BlockSize() + logical_offset.block_offset; | |
581 max_inline_size_ = | 596 max_inline_size_ = |
582 std::max(max_inline_size_, fragment.InlineSize() + | 597 std::max(max_inline_size_, fragment.InlineSize() + |
583 curr_child_margins_.InlineSum() + | 598 curr_child_margins_.InlineSum() + |
584 border_and_padding_.InlineSum()); | 599 border_and_padding_.InlineSum()); |
585 | 600 |
586 builder_->AddChild(std::move(physical_fragment), logical_offset); | 601 builder_->AddChild(std::move(physical_fragment), logical_offset); |
587 } | 602 } |
588 | 603 |
589 bool NGBlockLayoutAlgorithm::ProceedToNextUnfinishedSibling( | 604 bool NGBlockLayoutAlgorithm::ProceedToNextUnfinishedSibling( |
590 NGPhysicalFragment* child_fragment) { | 605 NGPhysicalFragment* child_fragment) { |
(...skipping 197 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
788 if (!content_size_) { | 803 if (!content_size_) { |
789 curr_margin_strut_ = NGMarginStrut(); | 804 curr_margin_strut_ = NGMarginStrut(); |
790 curr_child_margins_.block_start = LayoutUnit(); | 805 curr_child_margins_.block_start = LayoutUnit(); |
791 } | 806 } |
792 PositionPendingFloats(curr_bfc_offset_.block_offset, ConstraintSpace(), | 807 PositionPendingFloats(curr_bfc_offset_.block_offset, ConstraintSpace(), |
793 builder_.get()); | 808 builder_.get()); |
794 AdjustToClearance(constraint_space_->Exclusions(), current_child_style, | 809 AdjustToClearance(constraint_space_->Exclusions(), current_child_style, |
795 builder_->BfcOffset().value(), &content_size_); | 810 builder_->BfcOffset().value(), &content_size_); |
796 } | 811 } |
797 | 812 |
798 // Append the current margin strut with child's block start margin. | |
799 // Non empty border/padding use cases are handled inside of the child's | |
800 // layout. | |
801 curr_margin_strut_.Append(curr_child_margins_.block_start); | |
802 space_builder_->SetMarginStrut(curr_margin_strut_); | |
803 | |
804 // Set estimated BFC offset to the next child's constraint space. | 813 // Set estimated BFC offset to the next child's constraint space. |
805 curr_bfc_offset_ = builder_->BfcOffset() ? builder_->BfcOffset().value() | 814 curr_bfc_offset_ = builder_->BfcOffset() ? builder_->BfcOffset().value() |
806 : ConstraintSpace().BfcOffset(); | 815 : ConstraintSpace().BfcOffset(); |
807 curr_bfc_offset_.block_offset += content_size_; | 816 curr_bfc_offset_.block_offset += content_size_; |
808 curr_bfc_offset_.inline_offset += border_and_padding_.inline_start; | 817 curr_bfc_offset_.inline_offset += border_and_padding_.inline_start; |
809 | 818 |
810 // Floats margins are not included in child's CS because they are used to | 819 // Floats margins are not included in child's CS because |
811 // calculate floating exclusions. | 820 // 1) Floats do not participate in margins collapsing |
821 // 2) Floats margins are used separately to calculate floating exclusions. | |
812 if (!CurrentChildStyle().isFloating()) { | 822 if (!CurrentChildStyle().isFloating()) { |
813 curr_bfc_offset_.inline_offset += curr_child_margins_.inline_start; | 823 curr_bfc_offset_.inline_offset += curr_child_margins_.inline_start; |
824 // Append the current margin strut with child's block start margin. | |
825 // Non empty border/padding use cases are handled inside of the child's | |
ikilpatrick
2017/02/16 17:27:38
.nit Non-empty?
Gleb Lanbin
2017/02/16 20:08:27
Done.
| |
826 // layout. | |
827 curr_margin_strut_.Append(curr_child_margins_.block_start); | |
828 space_builder_->SetMarginStrut(curr_margin_strut_); | |
814 } | 829 } |
815 | 830 |
816 space_builder_->SetBfcOffset(curr_bfc_offset_); | 831 space_builder_->SetBfcOffset(curr_bfc_offset_); |
817 | 832 |
818 return space_builder_->ToConstraintSpace( | 833 return space_builder_->ToConstraintSpace( |
819 FromPlatformWritingMode(current_child_style.getWritingMode())); | 834 FromPlatformWritingMode(current_child_style.getWritingMode())); |
820 } | 835 } |
821 | 836 |
822 } // namespace blink | 837 } // namespace blink |
OLD | NEW |