| 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" |
| 11 #include "core/layout/ng/ng_constraint_space.h" | 11 #include "core/layout/ng/ng_constraint_space.h" |
| 12 #include "core/layout/ng/ng_constraint_space_builder.h" | 12 #include "core/layout/ng/ng_constraint_space_builder.h" |
| 13 #include "core/layout/ng/ng_fragment.h" | 13 #include "core/layout/ng/ng_fragment.h" |
| 14 #include "core/layout/ng/ng_fragment_builder.h" | 14 #include "core/layout/ng/ng_fragment_builder.h" |
| 15 #include "core/layout/ng/ng_inline_node.h" | 15 #include "core/layout/ng/ng_inline_node.h" |
| 16 #include "core/layout/ng/ng_layout_opportunity_iterator.h" | 16 #include "core/layout/ng/ng_layout_opportunity_iterator.h" |
| 17 #include "core/layout/ng/ng_length_utils.h" | 17 #include "core/layout/ng/ng_length_utils.h" |
| 18 #include "core/layout/ng/ng_line_builder.h" | 18 #include "core/layout/ng/ng_line_builder.h" |
| 19 #include "core/layout/ng/ng_out_of_flow_layout_part.h" | 19 #include "core/layout/ng/ng_out_of_flow_layout_part.h" |
| 20 #include "core/layout/ng/ng_units.h" | 20 #include "core/layout/ng/ng_units.h" |
| 21 #include "core/style/ComputedStyle.h" | 21 #include "core/style/ComputedStyle.h" |
| 22 #include "platform/LengthFunctions.h" | 22 #include "platform/LengthFunctions.h" |
| 23 #include "wtf/Optional.h" | 23 #include "wtf/Optional.h" |
| 24 | 24 |
| 25 namespace blink { | 25 namespace blink { |
| 26 namespace { | 26 namespace { |
| 27 | 27 |
| 28 // Whether child's constraint space should shrink to its intrinsic width. |
| 29 // This is needed for buttons, select, input, floats and orthogonal children. |
| 30 // See LayoutBox::sizesLogicalWidthToFitContent for the rationale behind this. |
| 31 bool ShouldShrinkToFit(const NGConstraintSpace& parent_space, |
| 32 const ComputedStyle& child_style) { |
| 33 NGWritingMode child_writing_mode = |
| 34 FromPlatformWritingMode(child_style.getWritingMode()); |
| 35 // Whether the child and the containing block are parallel to each other. |
| 36 // Example: vertical-rl and vertical-lr |
| 37 bool is_in_parallel_flow = |
| 38 (parent_space.WritingMode() == kHorizontalTopBottom) == |
| 39 (child_writing_mode == kHorizontalTopBottom); |
| 40 |
| 41 return child_style.display() == EDisplay::InlineBlock || |
| 42 child_style.isFloating() || !is_in_parallel_flow; |
| 43 } |
| 44 |
| 28 // Updates the fragment's BFC offset if it's not already set. | 45 // Updates the fragment's BFC offset if it's not already set. |
| 29 void UpdateFragmentBfcOffset(const NGLogicalOffset& offset, | 46 void UpdateFragmentBfcOffset(const NGLogicalOffset& offset, |
| 30 const NGConstraintSpace& space, | 47 const NGConstraintSpace& space, |
| 31 NGFragmentBuilder* builder) { | 48 NGFragmentBuilder* builder) { |
| 32 NGLogicalOffset fragment_offset = | 49 NGLogicalOffset fragment_offset = |
| 33 space.IsNewFormattingContext() ? NGLogicalOffset() : offset; | 50 space.IsNewFormattingContext() ? space.BfcOffset() : offset; |
| 34 if (!builder->BfcOffset()) | 51 if (!builder->BfcOffset()) |
| 35 builder->SetBfcOffset(fragment_offset); | 52 builder->SetBfcOffset(fragment_offset); |
| 36 } | 53 } |
| 37 | 54 |
| 38 // Adjusts content_size to respect the CSS "clear" property. | 55 // Adjusts content_size to respect the CSS "clear" property. |
| 39 // Picks up the maximum between left/right exclusions and content_size depending | 56 // Picks up the maximum between left/right exclusions and content_size depending |
| 40 // on the value of style.clear() property. | 57 // on the value of style.clear() property. |
| 41 void AdjustToClearance(const std::shared_ptr<NGExclusions>& exclusions, | 58 void AdjustToClearance(const std::shared_ptr<NGExclusions>& exclusions, |
| 42 const ComputedStyle& style, | 59 const ComputedStyle& style, |
| 43 const NGLogicalOffset& from_offset, | 60 const NGLogicalOffset& from_offset, |
| (...skipping 328 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 372 content_size_ = border_and_padding_.block_start; | 389 content_size_ = border_and_padding_.block_start; |
| 373 current_child_ = first_child_; | 390 current_child_ = first_child_; |
| 374 } | 391 } |
| 375 | 392 |
| 376 curr_margin_strut_ = ConstraintSpace().MarginStrut(); | 393 curr_margin_strut_ = ConstraintSpace().MarginStrut(); |
| 377 curr_bfc_offset_ = ConstraintSpace().BfcOffset(); | 394 curr_bfc_offset_ = ConstraintSpace().BfcOffset(); |
| 378 | 395 |
| 379 // Margins collapsing: | 396 // Margins collapsing: |
| 380 // Do not collapse margins between parent and its child if there is | 397 // Do not collapse margins between parent and its child if there is |
| 381 // border/padding between them. | 398 // border/padding between them. |
| 382 if (border_and_padding_.block_start) { | 399 if (border_and_padding_.block_start || |
| 400 ConstraintSpace().IsNewFormattingContext()) { |
| 383 curr_bfc_offset_.block_offset += curr_margin_strut_.Sum(); | 401 curr_bfc_offset_.block_offset += curr_margin_strut_.Sum(); |
| 384 builder_->SetBfcOffset(curr_bfc_offset_); | 402 builder_->SetBfcOffset(curr_bfc_offset_); |
| 385 curr_margin_strut_ = NGMarginStrut(); | 403 curr_margin_strut_ = NGMarginStrut(); |
| 386 } | 404 } |
| 387 curr_bfc_offset_.block_offset += content_size_; | 405 curr_bfc_offset_.block_offset += content_size_; |
| 388 | 406 |
| 389 while (current_child_) { | 407 while (current_child_) { |
| 390 if (current_child_->Type() == NGLayoutInputNode::kLegacyBlock) { | 408 if (current_child_->Type() == NGLayoutInputNode::kLegacyBlock) { |
| 391 NGBlockNode* current_block_child = toNGBlockNode(current_child_); | 409 NGBlockNode* current_block_child = toNGBlockNode(current_child_); |
| 392 EPosition position = current_block_child->Style().position(); | 410 EPosition position = current_block_child->Style().position(); |
| (...skipping 302 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 695 NGBoxStrut margins = | 713 NGBoxStrut margins = |
| 696 ComputeMargins(space, style, space.WritingMode(), space.Direction()); | 714 ComputeMargins(space, style, space.WritingMode(), space.Direction()); |
| 697 if (!style.isFloating()) { | 715 if (!style.isFloating()) { |
| 698 ApplyAutoMargins(space, style, child_inline_size, &margins); | 716 ApplyAutoMargins(space, style, child_inline_size, &margins); |
| 699 } | 717 } |
| 700 return margins; | 718 return margins; |
| 701 } | 719 } |
| 702 | 720 |
| 703 NGConstraintSpace* | 721 NGConstraintSpace* |
| 704 NGBlockLayoutAlgorithm::CreateConstraintSpaceForCurrentChild() { | 722 NGBlockLayoutAlgorithm::CreateConstraintSpaceForCurrentChild() { |
| 705 // TODO(layout-ng): Orthogonal children should also shrink to fit (in *their* | |
| 706 // inline axis) | |
| 707 DCHECK(current_child_); | 723 DCHECK(current_child_); |
| 708 if (current_child_->Type() == NGLayoutInputNode::kLegacyInline) { | 724 if (current_child_->Type() == NGLayoutInputNode::kLegacyInline) { |
| 709 // TODO(kojii): Setup space_builder_ appropriately for inline child. | 725 // TODO(kojii): Setup space_builder_ appropriately for inline child. |
| 710 return space_builder_->ToConstraintSpace(); | 726 return space_builder_->ToConstraintSpace(); |
| 727 // Calculate margins in parent's writing mode. |
| 711 } | 728 } |
| 729 curr_child_margins_ = CalculateMargins(*space_builder_->ToConstraintSpace(), |
| 730 CurrentChildStyle()); |
| 712 | 731 |
| 713 const ComputedStyle& current_child_style = CurrentChildStyle(); | 732 const ComputedStyle& current_child_style = CurrentChildStyle(); |
| 714 bool shrink_to_fit = current_child_style.display() == EDisplay::InlineBlock || | |
| 715 current_child_style.isFloating(); | |
| 716 bool is_new_bfc = IsNewFormattingContextForInFlowBlockLevelChild( | 733 bool is_new_bfc = IsNewFormattingContextForInFlowBlockLevelChild( |
| 717 ConstraintSpace(), current_child_style); | 734 ConstraintSpace(), current_child_style); |
| 718 space_builder_->SetIsNewFormattingContext(is_new_bfc) | 735 space_builder_->SetIsNewFormattingContext(is_new_bfc) |
| 719 .SetIsShrinkToFit(shrink_to_fit) | 736 .SetIsShrinkToFit( |
| 737 ShouldShrinkToFit(ConstraintSpace(), CurrentChildStyle())) |
| 720 .SetWritingMode( | 738 .SetWritingMode( |
| 721 FromPlatformWritingMode(current_child_style.getWritingMode())) | 739 FromPlatformWritingMode(current_child_style.getWritingMode())) |
| 722 .SetTextDirection(current_child_style.direction()); | 740 .SetTextDirection(current_child_style.direction()); |
| 723 LayoutUnit space_available = SpaceAvailableForCurrentChild(); | 741 LayoutUnit space_available = SpaceAvailableForCurrentChild(); |
| 724 space_builder_->SetFragmentainerSpaceAvailable(space_available); | 742 space_builder_->SetFragmentainerSpaceAvailable(space_available); |
| 725 | 743 |
| 726 curr_child_margins_ = CalculateMargins(*space_builder_->ToConstraintSpace(), | |
| 727 current_child_style); | |
| 728 | |
| 729 // Clearance : | 744 // Clearance : |
| 730 // - Collapse margins | 745 // - Collapse margins |
| 731 // - Update curr_bfc_offset and parent BFC offset if needed. | 746 // - Update curr_bfc_offset and parent BFC offset if needed. |
| 732 // - Position all pending floats as position is known now. | 747 // - Position all pending floats as position is known now. |
| 733 // TODO(glebl): Fix the use case with clear: left and an intruding right. | 748 // TODO(glebl): Fix the use case with clear: left and an intruding right. |
| 734 // https://software.hixie.ch/utilities/js/live-dom-viewer/saved/4847 | 749 // https://software.hixie.ch/utilities/js/live-dom-viewer/saved/4847 |
| 735 if (current_child_style.clear() != EClear::kNone) { | 750 if (current_child_style.clear() != EClear::kNone) { |
| 736 curr_bfc_offset_.block_offset += curr_margin_strut_.Sum(); | 751 curr_bfc_offset_.block_offset += curr_margin_strut_.Sum(); |
| 737 UpdateFragmentBfcOffset(curr_bfc_offset_, ConstraintSpace(), | 752 UpdateFragmentBfcOffset(curr_bfc_offset_, ConstraintSpace(), |
| 738 builder_.get()); | 753 builder_.get()); |
| (...skipping 20 matching lines...) Expand all Loading... |
| 759 curr_bfc_offset_.inline_offset += border_and_padding_.inline_start; | 774 curr_bfc_offset_.inline_offset += border_and_padding_.inline_start; |
| 760 if (ConstraintSpace().IsNewFormattingContext()) { | 775 if (ConstraintSpace().IsNewFormattingContext()) { |
| 761 curr_bfc_offset_.inline_offset += curr_child_margins_.inline_start; | 776 curr_bfc_offset_.inline_offset += curr_child_margins_.inline_start; |
| 762 } | 777 } |
| 763 space_builder_->SetBfcOffset(curr_bfc_offset_); | 778 space_builder_->SetBfcOffset(curr_bfc_offset_); |
| 764 | 779 |
| 765 return space_builder_->ToConstraintSpace(); | 780 return space_builder_->ToConstraintSpace(); |
| 766 } | 781 } |
| 767 | 782 |
| 768 } // namespace blink | 783 } // namespace blink |
| OLD | NEW |