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

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

Issue 2711803007: Add ClearanceOffset to LayoutNG Constraint space. (Closed)
Patch Set: update TestExpectations Created 3 years, 9 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 23 matching lines...) Expand all
34 FromPlatformWritingMode(child_style.getWritingMode()); 34 FromPlatformWritingMode(child_style.getWritingMode());
35 // Whether the child and the containing block are parallel to each other. 35 // Whether the child and the containing block are parallel to each other.
36 // Example: vertical-rl and vertical-lr 36 // Example: vertical-rl and vertical-lr
37 bool is_in_parallel_flow = 37 bool is_in_parallel_flow =
38 IsParallelWritingMode(parent_space.WritingMode(), child_writing_mode); 38 IsParallelWritingMode(parent_space.WritingMode(), child_writing_mode);
39 39
40 return child_style.display() == EDisplay::InlineBlock || 40 return child_style.display() == EDisplay::InlineBlock ||
41 child_style.isFloating() || !is_in_parallel_flow; 41 child_style.isFloating() || !is_in_parallel_flow;
42 } 42 }
43 43
44 // Updates the fragment's BFC offset if it's not already set. 44 // Returns max of 2 {@code WTF::Optional} values.
45 void UpdateFragmentBfcOffset(const NGLogicalOffset& offset, 45 template <typename T>
46 NGFragmentBuilder* builder) { 46 WTF::Optional<T> OptionalMax(const WTF::Optional<T>& value1,
47 if (!builder->BfcOffset()) 47 const WTF::Optional<T>& value2) {
48 builder->SetBfcOffset(offset); 48 if (value1 && value2) {
49 return std::max(value1.value(), value2.value());
50 } else if (value1) {
51 return value1;
52 }
53 return value2;
49 } 54 }
50 55
51 // Adjusts content_size to respect the CSS "clear" property. 56 WTF::Optional<LayoutUnit> GetClearanceOffset(
52 // Picks up the maximum between left/right exclusions and content_size depending 57 const std::shared_ptr<NGExclusions>& exclusions,
53 // on the value of style.clear() property. 58 const ComputedStyle& style) {
54 void AdjustToClearance(const std::shared_ptr<NGExclusions>& exclusions,
55 const ComputedStyle& style,
56 const NGLogicalOffset& from_offset,
57 LayoutUnit* content_size) {
58 DCHECK(content_size) << "content_size cannot be null here";
59 const NGExclusion* right_exclusion = exclusions->last_right_float; 59 const NGExclusion* right_exclusion = exclusions->last_right_float;
60 const NGExclusion* left_exclusion = exclusions->last_left_float; 60 const NGExclusion* left_exclusion = exclusions->last_left_float;
61 61
62 LayoutUnit left_block_end_offset = *content_size; 62 WTF::Optional<LayoutUnit> left_offset;
63 if (left_exclusion) { 63 if (left_exclusion) {
64 left_block_end_offset = std::max( 64 left_offset = left_exclusion->rect.BlockEndOffset();
65 left_exclusion->rect.BlockEndOffset() - from_offset.block_offset,
66 *content_size);
67 } 65 }
68 LayoutUnit right_block_end_offset = *content_size; 66 WTF::Optional<LayoutUnit> right_offset;
69 if (right_exclusion) { 67 if (right_exclusion) {
70 right_block_end_offset = std::max( 68 right_offset = right_exclusion->rect.BlockEndOffset();
71 right_exclusion->rect.BlockEndOffset() - from_offset.block_offset,
72 *content_size);
73 } 69 }
74 70
75 switch (style.clear()) { 71 switch (style.clear()) {
76 case EClear::kNone: 72 case EClear::kNone:
77 return; // nothing to do here. 73 return WTF::nullopt; // nothing to do here.
78 case EClear::kLeft: 74 case EClear::kLeft:
79 *content_size = left_block_end_offset; 75 return left_offset;
80 break;
81 case EClear::kRight: 76 case EClear::kRight:
82 *content_size = right_block_end_offset; 77 return right_offset;
83 break;
84 case EClear::kBoth: 78 case EClear::kBoth:
85 *content_size = std::max(left_block_end_offset, right_block_end_offset); 79 return OptionalMax<LayoutUnit>(left_offset, right_offset);
86 break;
87 default: 80 default:
88 ASSERT_NOT_REACHED(); 81 ASSERT_NOT_REACHED();
89 } 82 }
83 return WTF::nullopt;
90 } 84 }
91 85
92 // Creates an exclusion from the fragment that will be placed in the provided 86 // Creates an exclusion from the fragment that will be placed in the provided
93 // layout opportunity. 87 // layout opportunity.
94 NGExclusion CreateExclusion(const NGFragment& fragment, 88 NGExclusion CreateExclusion(const NGFragment& fragment,
95 const NGLayoutOpportunity& opportunity, 89 const NGLayoutOpportunity& opportunity,
96 const LayoutUnit float_offset, 90 const LayoutUnit float_offset,
97 const NGBoxStrut& margins, 91 const NGBoxStrut& margins,
98 NGExclusion::Type exclusion_type) { 92 NGExclusion::Type exclusion_type) {
99 NGExclusion exclusion; 93 NGExclusion exclusion;
(...skipping 249 matching lines...) Expand 10 before | Expand all | Expand 10 after
349 LayoutUnit inline_offset = 343 LayoutUnit inline_offset =
350 border_and_padding_.inline_start + curr_child_margins_.inline_start; 344 border_and_padding_.inline_start + curr_child_margins_.inline_start;
351 LayoutUnit block_offset = content_size_; 345 LayoutUnit block_offset = content_size_;
352 if (known_fragment_offset) { 346 if (known_fragment_offset) {
353 block_offset = known_fragment_offset.value().block_offset - 347 block_offset = known_fragment_offset.value().block_offset -
354 builder_->BfcOffset().value().block_offset; 348 builder_->BfcOffset().value().block_offset;
355 } 349 }
356 return {inline_offset, block_offset}; 350 return {inline_offset, block_offset};
357 } 351 }
358 352
353 void NGBlockLayoutAlgorithm::UpdateFragmentBfcOffset(
354 const NGLogicalOffset& offset) {
355 if (!builder_->BfcOffset()) {
356 NGLogicalOffset bfc_offset = offset;
357 if (ConstraintSpace().ClearanceOffset()) {
358 bfc_offset.block_offset = std::max(
359 ConstraintSpace().ClearanceOffset().value(), offset.block_offset);
360 }
361 builder_->SetBfcOffset(bfc_offset);
362 }
363 }
364
359 RefPtr<NGLayoutResult> NGBlockLayoutAlgorithm::Layout() { 365 RefPtr<NGLayoutResult> NGBlockLayoutAlgorithm::Layout() {
360 WTF::Optional<MinAndMaxContentSizes> sizes; 366 WTF::Optional<MinAndMaxContentSizes> sizes;
361 if (NeedMinAndMaxContentSizes(ConstraintSpace(), Style())) 367 if (NeedMinAndMaxContentSizes(ConstraintSpace(), Style()))
362 sizes = ComputeMinAndMaxContentSizes(); 368 sizes = ComputeMinAndMaxContentSizes();
363 369
364 border_and_padding_ = 370 border_and_padding_ =
365 ComputeBorders(Style()) + ComputePadding(ConstraintSpace(), Style()); 371 ComputeBorders(Style()) + ComputePadding(ConstraintSpace(), Style());
366 372
367 LayoutUnit inline_size = 373 LayoutUnit inline_size =
368 ComputeInlineSizeForFragment(ConstraintSpace(), Style(), sizes); 374 ComputeInlineSizeForFragment(ConstraintSpace(), Style(), sizes);
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after
410 } 416 }
411 417
412 curr_margin_strut_ = ConstraintSpace().MarginStrut(); 418 curr_margin_strut_ = ConstraintSpace().MarginStrut();
413 curr_bfc_offset_ = ConstraintSpace().BfcOffset(); 419 curr_bfc_offset_ = ConstraintSpace().BfcOffset();
414 420
415 // Margins collapsing: 421 // Margins collapsing:
416 // Do not collapse margins between parent and its child if there is 422 // Do not collapse margins between parent and its child if there is
417 // border/padding between them. 423 // border/padding between them.
418 if (border_and_padding_.block_start) { 424 if (border_and_padding_.block_start) {
419 curr_bfc_offset_.block_offset += curr_margin_strut_.Sum(); 425 curr_bfc_offset_.block_offset += curr_margin_strut_.Sum();
420 UpdateFragmentBfcOffset(curr_bfc_offset_, builder_.get()); 426 UpdateFragmentBfcOffset(curr_bfc_offset_);
421 curr_margin_strut_ = NGMarginStrut(); 427 curr_margin_strut_ = NGMarginStrut();
422 } 428 }
423 429
424 // Block that establishes a new BFC knows its BFC offset == {} 430 // Block that establishes a new BFC knows its BFC offset == {}
425 // If a new formatting context hits the if branch above then the BFC offset is 431 // If a new formatting context hits the if branch above then the BFC offset is
426 // still {} as the margin strut from the constraint space must also be empty. 432 // still {} as the margin strut from the constraint space must also be empty.
427 if (ConstraintSpace().IsNewFormattingContext()) { 433 if (ConstraintSpace().IsNewFormattingContext()) {
428 UpdateFragmentBfcOffset(curr_bfc_offset_, builder_.get()); 434 UpdateFragmentBfcOffset(curr_bfc_offset_);
429 DCHECK_EQ(builder_->BfcOffset().value(), NGLogicalOffset()); 435 DCHECK_EQ(builder_->BfcOffset().value(), NGLogicalOffset());
430 DCHECK_EQ(curr_margin_strut_, NGMarginStrut()); 436 DCHECK_EQ(curr_margin_strut_, NGMarginStrut());
431 } 437 }
432 438
433 curr_bfc_offset_.block_offset += content_size_; 439 curr_bfc_offset_.block_offset += content_size_;
434 440
435 while (current_child_) { 441 while (current_child_) {
436 if (current_child_->Type() == NGLayoutInputNode::kLegacyBlock) { 442 if (current_child_->Type() == NGLayoutInputNode::kLegacyBlock) {
437 NGBlockNode* current_block_child = toNGBlockNode(current_child_); 443 NGBlockNode* current_block_child = toNGBlockNode(current_child_);
438 EPosition position = current_block_child->Style().position(); 444 EPosition position = current_block_child->Style().position();
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after
478 block_size = 484 block_size =
479 ComputeBlockSizeForFragment(ConstraintSpace(), Style(), content_size_); 485 ComputeBlockSizeForFragment(ConstraintSpace(), Style(), content_size_);
480 builder_->SetBlockSize(block_size); 486 builder_->SetBlockSize(block_size);
481 487
482 // Layout our absolute and fixed positioned children. 488 // Layout our absolute and fixed positioned children.
483 NGOutOfFlowLayoutPart(Style(), builder_.get()).Run(); 489 NGOutOfFlowLayoutPart(Style(), builder_.get()).Run();
484 490
485 // Non-empty blocks always know their position in space: 491 // Non-empty blocks always know their position in space:
486 if (block_size) { 492 if (block_size) {
487 curr_bfc_offset_.block_offset += curr_margin_strut_.Sum(); 493 curr_bfc_offset_.block_offset += curr_margin_strut_.Sum();
488 UpdateFragmentBfcOffset(curr_bfc_offset_, builder_.get()); 494 UpdateFragmentBfcOffset(curr_bfc_offset_);
489 PositionPendingFloats(curr_bfc_offset_.block_offset, ConstraintSpace(), 495 PositionPendingFloats(curr_bfc_offset_.block_offset, ConstraintSpace(),
490 builder_.get()); 496 builder_.get());
491 } 497 }
492 498
493 // Margins collapsing: 499 // Margins collapsing:
494 // Do not collapse margins between the last in-flow child and bottom margin 500 // Do not collapse margins between the last in-flow child and bottom margin
495 // of its parent if the parent has height != auto() 501 // of its parent if the parent has height != auto()
496 if (!Style().logicalHeight().isAuto()) { 502 if (!Style().logicalHeight().isAuto()) {
497 // TODO(glebl): handle minLogicalHeight, maxLogicalHeight. 503 // TODO(glebl): handle minLogicalHeight, maxLogicalHeight.
498 curr_margin_strut_ = NGMarginStrut(); 504 curr_margin_strut_ = NGMarginStrut();
(...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after
570 // Fragment doesn't know its offset but we can still calculate its BFC 576 // Fragment doesn't know its offset but we can still calculate its BFC
571 // position because the parent fragment's BFC is known. 577 // position because the parent fragment's BFC is known.
572 // Example: 578 // Example:
573 // BFC Offset is known here because of the padding. 579 // BFC Offset is known here because of the padding.
574 // <div style="padding: 1px"> 580 // <div style="padding: 1px">
575 // <div id="empty-div" style="margins: 1px"></div> 581 // <div id="empty-div" style="margins: 1px"></div>
576 bfc_offset = curr_bfc_offset_; 582 bfc_offset = curr_bfc_offset_;
577 bfc_offset.value().block_offset += curr_margin_strut_.Sum(); 583 bfc_offset.value().block_offset += curr_margin_strut_.Sum();
578 } 584 }
579 if (bfc_offset) { 585 if (bfc_offset) {
580 UpdateFragmentBfcOffset(curr_bfc_offset_, builder_.get()); 586 UpdateFragmentBfcOffset(curr_bfc_offset_);
581 PositionPendingFloats(curr_bfc_offset_.block_offset, ConstraintSpace(), 587 PositionPendingFloats(curr_bfc_offset_.block_offset, ConstraintSpace(),
582 builder_.get()); 588 builder_.get());
583 } 589 }
584 NGLogicalOffset logical_offset = CalculateLogicalOffset(bfc_offset); 590 NGLogicalOffset logical_offset = CalculateLogicalOffset(bfc_offset);
585 591
586 if (fragmentainer_mapper_) 592 if (fragmentainer_mapper_)
587 fragmentainer_mapper_->ToVisualOffset(logical_offset); 593 fragmentainer_mapper_->ToVisualOffset(logical_offset);
588 else 594 else
589 logical_offset.block_offset -= PreviousBreakOffset(); 595 logical_offset.block_offset -= PreviousBreakOffset();
590 596
(...skipping 201 matching lines...) Expand 10 before | Expand all | Expand 10 after
792 bool is_new_bfc = IsNewFormattingContextForInFlowBlockLevelChild( 798 bool is_new_bfc = IsNewFormattingContextForInFlowBlockLevelChild(
793 ConstraintSpace(), current_child_style); 799 ConstraintSpace(), current_child_style);
794 space_builder_->SetIsNewFormattingContext(is_new_bfc) 800 space_builder_->SetIsNewFormattingContext(is_new_bfc)
795 .SetIsShrinkToFit( 801 .SetIsShrinkToFit(
796 ShouldShrinkToFit(ConstraintSpace(), CurrentChildStyle())) 802 ShouldShrinkToFit(ConstraintSpace(), CurrentChildStyle()))
797 .SetTextDirection(current_child_style.direction()); 803 .SetTextDirection(current_child_style.direction());
798 LayoutUnit space_available = SpaceAvailableForCurrentChild(); 804 LayoutUnit space_available = SpaceAvailableForCurrentChild();
799 space_builder_->SetFragmentainerSpaceAvailable(space_available); 805 space_builder_->SetFragmentainerSpaceAvailable(space_available);
800 806
801 // Clearance : 807 // Clearance :
802 // - Collapse margins 808 // - *Always* collapse margins and update *container*'s BFC offset.
803 // - Update curr_bfc_offset and parent BFC offset if needed. 809 // - Position all pending floats since the fragment's BFC offset is known.
804 // - Position all pending floats as position is known now. 810 // - Set the clearance offset on the constraint space's builder.
805 // TODO(glebl): Fix the use case with clear: left and an intruding right.
806 // https://software.hixie.ch/utilities/js/live-dom-viewer/saved/4847
807 if (current_child_style.clear() != EClear::kNone) { 811 if (current_child_style.clear() != EClear::kNone) {
808 curr_bfc_offset_.block_offset += curr_margin_strut_.Sum(); 812 curr_bfc_offset_.block_offset += curr_margin_strut_.Sum();
809 UpdateFragmentBfcOffset(curr_bfc_offset_, builder_.get()); 813 UpdateFragmentBfcOffset(curr_bfc_offset_);
810 // Only collapse margins if it's an adjoining block with clearance. 814 // Only collapse margins if it's an adjoining block with clearance.
811 if (!content_size_) { 815 if (!content_size_) {
812 curr_margin_strut_ = NGMarginStrut(); 816 curr_margin_strut_ = NGMarginStrut();
813 curr_child_margins_.block_start = LayoutUnit(); 817 curr_child_margins_.block_start = LayoutUnit();
814 } 818 }
815 PositionPendingFloats(curr_bfc_offset_.block_offset, ConstraintSpace(), 819 PositionPendingFloats(curr_bfc_offset_.block_offset, ConstraintSpace(),
816 builder_.get()); 820 builder_.get());
817 AdjustToClearance(constraint_space_->Exclusions(), current_child_style, 821 WTF::Optional<LayoutUnit> clearance_offset = GetClearanceOffset(
818 builder_->BfcOffset().value(), &content_size_); 822 constraint_space_->Exclusions(), current_child_style);
823 space_builder_->SetClearanceOffset(clearance_offset);
819 } 824 }
820 825
821 // Set estimated BFC offset to the next child's constraint space. 826 // Set estimated BFC offset to the next child's constraint space.
822 curr_bfc_offset_ = builder_->BfcOffset() ? builder_->BfcOffset().value() 827 curr_bfc_offset_ = builder_->BfcOffset() ? builder_->BfcOffset().value()
823 : ConstraintSpace().BfcOffset(); 828 : ConstraintSpace().BfcOffset();
824 curr_bfc_offset_.block_offset += content_size_; 829 curr_bfc_offset_.block_offset += content_size_;
825 curr_bfc_offset_.inline_offset += border_and_padding_.inline_start; 830 curr_bfc_offset_.inline_offset += border_and_padding_.inline_start;
826 831
827 // Floats margins are not included in child's CS because 832 // Floats margins are not included in child's CS because
828 // 1) Floats do not participate in margins collapsing 833 // 1) Floats do not participate in margins collapsing
829 // 2) Floats margins are used separately to calculate floating exclusions. 834 // 2) Floats margins are used separately to calculate floating exclusions.
830 if (!CurrentChildStyle().isFloating()) { 835 if (!CurrentChildStyle().isFloating()) {
831 curr_bfc_offset_.inline_offset += curr_child_margins_.inline_start; 836 curr_bfc_offset_.inline_offset += curr_child_margins_.inline_start;
832 // Append the current margin strut with child's block start margin. 837 // Append the current margin strut with child's block start margin.
833 // Non empty border/padding use cases are handled inside of the child's 838 // Non empty border/padding use cases are handled inside of the child's
834 // layout. 839 // layout.
835 curr_margin_strut_.Append(curr_child_margins_.block_start); 840 curr_margin_strut_.Append(curr_child_margins_.block_start);
836 space_builder_->SetMarginStrut(curr_margin_strut_); 841 space_builder_->SetMarginStrut(curr_margin_strut_);
837 } 842 }
838 843
839 space_builder_->SetBfcOffset(curr_bfc_offset_); 844 space_builder_->SetBfcOffset(curr_bfc_offset_);
840 845
841 return space_builder_->ToConstraintSpace( 846 return space_builder_->ToConstraintSpace(
842 FromPlatformWritingMode(current_child_style.getWritingMode())); 847 FromPlatformWritingMode(current_child_style.getWritingMode()));
843 } 848 }
844
845 } // namespace blink 849 } // namespace blink
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698