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

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

Issue 2700683002: [LayoutNG] Fix incorrectly positioned empty blocks inside of new BFC (Closed)
Patch Set: Fix comments and some crashes in FloatingObjects Created 3 years, 10 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/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
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 }
426
427 // Block that establishes a new BFC knows its BFC offset == {}
428 // If a new formatting context hits the if branch above then the BFC offset is
429 // still {} as the margin strut from the constraint space must also be empty.
430 if (ConstraintSpace().IsNewFormattingContext()) {
431 UpdateFragmentBfcOffset(curr_bfc_offset_, builder_.get());
432 DCHECK_EQ(builder_->BfcOffset().value(), NGLogicalOffset());
433 DCHECK_EQ(curr_margin_strut_, NGMarginStrut());
434 }
435
427 curr_bfc_offset_.block_offset += content_size_; 436 curr_bfc_offset_.block_offset += content_size_;
428 437
429 while (current_child_) { 438 while (current_child_) {
430 if (current_child_->Type() == NGLayoutInputNode::kLegacyBlock) { 439 if (current_child_->Type() == NGLayoutInputNode::kLegacyBlock) {
431 NGBlockNode* current_block_child = toNGBlockNode(current_child_); 440 NGBlockNode* current_block_child = toNGBlockNode(current_child_);
432 EPosition position = current_block_child->Style().position(); 441 EPosition position = current_block_child->Style().position();
433 if (position == EPosition::kAbsolute || position == EPosition::kFixed) { 442 if (position == EPosition::kAbsolute || position == EPosition::kFixed) {
434 builder_->AddOutOfFlowChildCandidate(current_block_child, 443 builder_->AddOutOfFlowChildCandidate(current_block_child,
435 GetChildSpaceOffset()); 444 GetChildSpaceOffset());
436 current_child_ = current_block_child->NextSibling(); 445 current_child_ = current_block_child->NextSibling();
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
468 } 477 }
469 478
470 // Recompute the block-axis size now that we know our content size. 479 // Recompute the block-axis size now that we know our content size.
471 block_size = 480 block_size =
472 ComputeBlockSizeForFragment(ConstraintSpace(), Style(), content_size_); 481 ComputeBlockSizeForFragment(ConstraintSpace(), Style(), content_size_);
473 builder_->SetBlockSize(block_size); 482 builder_->SetBlockSize(block_size);
474 483
475 // Layout our absolute and fixed positioned children. 484 // Layout our absolute and fixed positioned children.
476 NGOutOfFlowLayoutPart(Style(), builder_.get()).Run(); 485 NGOutOfFlowLayoutPart(Style(), builder_.get()).Run();
477 486
478 // Non empty blocks always know their position in space: 487 // Non-empty blocks always know their position in space:
479 if (block_size) { 488 if (block_size) {
480 curr_bfc_offset_.block_offset += curr_margin_strut_.Sum(); 489 curr_bfc_offset_.block_offset += curr_margin_strut_.Sum();
481 UpdateFragmentBfcOffset(curr_bfc_offset_, builder_.get()); 490 UpdateFragmentBfcOffset(curr_bfc_offset_, builder_.get());
482 PositionPendingFloats(curr_bfc_offset_.block_offset, ConstraintSpace(), 491 PositionPendingFloats(curr_bfc_offset_.block_offset, ConstraintSpace(),
483 builder_.get()); 492 builder_.get());
484 } 493 }
485 494
486 // Margins collapsing: 495 // Margins collapsing:
487 // Do not collapse margins between the last in-flow child and bottom margin 496 // Do not collapse margins between the last in-flow child and bottom margin
488 // of its parent if the parent has height != auto() 497 // of its parent if the parent has height != auto()
(...skipping 26 matching lines...) Expand all
515 line_builder.CopyFragmentDataToLayoutBlockFlow(); 524 line_builder.CopyFragmentDataToLayoutBlockFlow();
516 FinishCurrentChildLayout(child_fragment.get()); 525 FinishCurrentChildLayout(child_fragment.get());
517 current_child_ = nullptr; 526 current_child_ = nullptr;
518 } 527 }
519 528
520 void NGBlockLayoutAlgorithm::FinishCurrentChildLayout( 529 void NGBlockLayoutAlgorithm::FinishCurrentChildLayout(
521 RefPtr<NGPhysicalBoxFragment> physical_fragment) { 530 RefPtr<NGPhysicalBoxFragment> physical_fragment) {
522 NGBoxFragment fragment(ConstraintSpace().WritingMode(), 531 NGBoxFragment fragment(ConstraintSpace().WritingMode(),
523 physical_fragment.get()); 532 physical_fragment.get());
524 533
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 534 // 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 535 // for example the child fragment could not position its floats because it's
529 // empty and therefore couldn't determine its position in space. 536 // empty and therefore couldn't determine its position in space.
530 builder_->MutableUnpositionedFloats().appendVector( 537 builder_->MutableUnpositionedFloats().appendVector(
531 physical_fragment->UnpositionedFloats()); 538 physical_fragment->UnpositionedFloats());
532 539
533 if (current_child_->Type() == NGLayoutInputNode::kLegacyBlock && 540 if (current_child_->Type() == NGLayoutInputNode::kLegacyBlock &&
534 CurrentChildStyle().isFloating()) { 541 CurrentChildStyle().isFloating()) {
535 NGFloatingObject* floating_object = 542 NGFloatingObject* floating_object =
536 new NGFloatingObject(physical_fragment.get(), space_for_current_child_, 543 new NGFloatingObject(physical_fragment.get(), space_for_current_child_,
(...skipping 16 matching lines...) Expand all
553 // Determine the fragment's position in the parent space either by using 560 // Determine the fragment's position in the parent space either by using
554 // content_size_ or known fragment's BFC offset. 561 // content_size_ or known fragment's BFC offset.
555 WTF::Optional<NGLogicalOffset> bfc_offset; 562 WTF::Optional<NGLogicalOffset> bfc_offset;
556 if (CurrentChildConstraintSpace().IsNewFormattingContext()) { 563 if (CurrentChildConstraintSpace().IsNewFormattingContext()) {
557 curr_bfc_offset_.block_offset += curr_margin_strut_.Sum(); 564 curr_bfc_offset_.block_offset += curr_margin_strut_.Sum();
558 bfc_offset = curr_bfc_offset_; 565 bfc_offset = curr_bfc_offset_;
559 } else if (fragment.BfcOffset()) { 566 } else if (fragment.BfcOffset()) {
560 // Fragment that knows its offset can be used to set parent's BFC position. 567 // 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; 568 curr_bfc_offset_.block_offset = fragment.BfcOffset().value().block_offset;
562 bfc_offset = curr_bfc_offset_; 569 bfc_offset = curr_bfc_offset_;
570 } else if (builder_->BfcOffset()) {
571 // Fragment doesn't know its offset but we can still calculate its BFC
572 // position because the parent fragment's BFC is known.
573 // Example:
574 // BFC Offset is known here because of the padding.
575 // <div style="padding: 1px">
576 // <div id="empty-div" style="margins: 1px"></div>
577 bfc_offset = curr_bfc_offset_;
578 bfc_offset.value().block_offset += curr_margin_strut_.Sum();
563 } 579 }
564 if (bfc_offset) { 580 if (bfc_offset) {
565 UpdateFragmentBfcOffset(curr_bfc_offset_, builder_.get()); 581 UpdateFragmentBfcOffset(curr_bfc_offset_, builder_.get());
566 PositionPendingFloats(curr_bfc_offset_.block_offset, ConstraintSpace(), 582 PositionPendingFloats(curr_bfc_offset_.block_offset, ConstraintSpace(),
567 builder_.get()); 583 builder_.get());
568 } 584 }
569 NGLogicalOffset logical_offset = CalculateLogicalOffset(bfc_offset); 585 NGLogicalOffset logical_offset = CalculateLogicalOffset(bfc_offset);
570 586
571 if (fragmentainer_mapper_) 587 if (fragmentainer_mapper_)
572 fragmentainer_mapper_->ToVisualOffset(logical_offset); 588 fragmentainer_mapper_->ToVisualOffset(logical_offset);
573 else 589 else
574 logical_offset.block_offset -= PreviousBreakOffset(); 590 logical_offset.block_offset -= PreviousBreakOffset();
575 591
576 // Update margin strut. 592 // Update margin strut.
577 curr_margin_strut_ = fragment.EndMarginStrut(); 593 curr_margin_strut_ = fragment.EndMarginStrut();
578 curr_margin_strut_.Append(curr_child_margins_.block_end); 594 curr_margin_strut_.Append(curr_child_margins_.block_end);
579 595
580 content_size_ = fragment.BlockSize() + logical_offset.block_offset; 596 // Only modify content_size if BlockSize is not empty. It's needed to prevent
597 // the situation when logical_offset is included in content_size for empty
598 // blocks. Example:
599 // <div style="overflow:hidden">
600 // <div style="margin-top: 8px"></div>
601 // <div style="margin-top: 10px"></div>
602 // </div>
603 if (fragment.BlockSize())
604 content_size_ = fragment.BlockSize() + logical_offset.block_offset;
581 max_inline_size_ = 605 max_inline_size_ =
582 std::max(max_inline_size_, fragment.InlineSize() + 606 std::max(max_inline_size_, fragment.InlineSize() +
583 curr_child_margins_.InlineSum() + 607 curr_child_margins_.InlineSum() +
584 border_and_padding_.InlineSum()); 608 border_and_padding_.InlineSum());
585 609
586 builder_->AddChild(std::move(physical_fragment), logical_offset); 610 builder_->AddChild(std::move(physical_fragment), logical_offset);
587 } 611 }
588 612
589 bool NGBlockLayoutAlgorithm::ProceedToNextUnfinishedSibling( 613 bool NGBlockLayoutAlgorithm::ProceedToNextUnfinishedSibling(
590 NGPhysicalFragment* child_fragment) { 614 NGPhysicalFragment* child_fragment) {
(...skipping 197 matching lines...) Expand 10 before | Expand all | Expand 10 after
788 if (!content_size_) { 812 if (!content_size_) {
789 curr_margin_strut_ = NGMarginStrut(); 813 curr_margin_strut_ = NGMarginStrut();
790 curr_child_margins_.block_start = LayoutUnit(); 814 curr_child_margins_.block_start = LayoutUnit();
791 } 815 }
792 PositionPendingFloats(curr_bfc_offset_.block_offset, ConstraintSpace(), 816 PositionPendingFloats(curr_bfc_offset_.block_offset, ConstraintSpace(),
793 builder_.get()); 817 builder_.get());
794 AdjustToClearance(constraint_space_->Exclusions(), current_child_style, 818 AdjustToClearance(constraint_space_->Exclusions(), current_child_style,
795 builder_->BfcOffset().value(), &content_size_); 819 builder_->BfcOffset().value(), &content_size_);
796 } 820 }
797 821
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. 822 // Set estimated BFC offset to the next child's constraint space.
805 curr_bfc_offset_ = builder_->BfcOffset() ? builder_->BfcOffset().value() 823 curr_bfc_offset_ = builder_->BfcOffset() ? builder_->BfcOffset().value()
806 : ConstraintSpace().BfcOffset(); 824 : ConstraintSpace().BfcOffset();
807 curr_bfc_offset_.block_offset += content_size_; 825 curr_bfc_offset_.block_offset += content_size_;
808 curr_bfc_offset_.inline_offset += border_and_padding_.inline_start; 826 curr_bfc_offset_.inline_offset += border_and_padding_.inline_start;
809 827
810 // Floats margins are not included in child's CS because they are used to 828 // Floats margins are not included in child's CS because
811 // calculate floating exclusions. 829 // 1) Floats do not participate in margins collapsing
830 // 2) Floats margins are used separately to calculate floating exclusions.
812 if (!CurrentChildStyle().isFloating()) { 831 if (!CurrentChildStyle().isFloating()) {
813 curr_bfc_offset_.inline_offset += curr_child_margins_.inline_start; 832 curr_bfc_offset_.inline_offset += curr_child_margins_.inline_start;
833 // Append the current margin strut with child's block start margin.
834 // Non empty border/padding use cases are handled inside of the child's
835 // layout.
836 curr_margin_strut_.Append(curr_child_margins_.block_start);
837 space_builder_->SetMarginStrut(curr_margin_strut_);
814 } 838 }
815 839
816 space_builder_->SetBfcOffset(curr_bfc_offset_); 840 space_builder_->SetBfcOffset(curr_bfc_offset_);
817 841
818 return space_builder_->ToConstraintSpace( 842 return space_builder_->ToConstraintSpace(
819 FromPlatformWritingMode(current_child_style.getWritingMode())); 843 FromPlatformWritingMode(current_child_style.getWritingMode()));
820 } 844 }
821 845
822 } // namespace blink 846 } // namespace blink
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698