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 26 matching lines...) Expand all Loading... |
37 bool is_in_parallel_flow = | 37 bool is_in_parallel_flow = |
38 (parent_space.WritingMode() == kHorizontalTopBottom) == | 38 (parent_space.WritingMode() == kHorizontalTopBottom) == |
39 (child_writing_mode == kHorizontalTopBottom); | 39 (child_writing_mode == kHorizontalTopBottom); |
40 | 40 |
41 return child_style.display() == EDisplay::InlineBlock || | 41 return child_style.display() == EDisplay::InlineBlock || |
42 child_style.isFloating() || !is_in_parallel_flow; | 42 child_style.isFloating() || !is_in_parallel_flow; |
43 } | 43 } |
44 | 44 |
45 // 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. |
46 void UpdateFragmentBfcOffset(const NGLogicalOffset& offset, | 46 void UpdateFragmentBfcOffset(const NGLogicalOffset& offset, |
47 const NGConstraintSpace& space, | |
48 NGFragmentBuilder* builder) { | 47 NGFragmentBuilder* builder) { |
49 NGLogicalOffset fragment_offset = | |
50 space.IsNewFormattingContext() ? space.BfcOffset() : offset; | |
51 if (!builder->BfcOffset()) | 48 if (!builder->BfcOffset()) |
52 builder->SetBfcOffset(fragment_offset); | 49 builder->SetBfcOffset(offset); |
53 } | 50 } |
54 | 51 |
55 // Adjusts content_size to respect the CSS "clear" property. | 52 // Adjusts content_size to respect the CSS "clear" property. |
56 // Picks up the maximum between left/right exclusions and content_size depending | 53 // Picks up the maximum between left/right exclusions and content_size depending |
57 // on the value of style.clear() property. | 54 // on the value of style.clear() property. |
58 void AdjustToClearance(const std::shared_ptr<NGExclusions>& exclusions, | 55 void AdjustToClearance(const std::shared_ptr<NGExclusions>& exclusions, |
59 const ComputedStyle& style, | 56 const ComputedStyle& style, |
60 const NGLogicalOffset& from_offset, | 57 const NGLogicalOffset& from_offset, |
61 LayoutUnit* content_size) { | 58 LayoutUnit* content_size) { |
62 DCHECK(content_size) << "content_size cannot be null here"; | 59 DCHECK(content_size) << "content_size cannot be null here"; |
(...skipping 255 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
318 ComputeMinAndMaxContentContribution(block_child->Style(), child_minmax); | 315 ComputeMinAndMaxContentContribution(block_child->Style(), child_minmax); |
319 | 316 |
320 sizes.min_content = std::max(sizes.min_content, child_sizes.min_content); | 317 sizes.min_content = std::max(sizes.min_content, child_sizes.min_content); |
321 sizes.max_content = std::max(sizes.max_content, child_sizes.max_content); | 318 sizes.max_content = std::max(sizes.max_content, child_sizes.max_content); |
322 } | 319 } |
323 | 320 |
324 sizes.max_content = std::max(sizes.min_content, sizes.max_content); | 321 sizes.max_content = std::max(sizes.min_content, sizes.max_content); |
325 return sizes; | 322 return sizes; |
326 } | 323 } |
327 | 324 |
328 NGLogicalOffset NGBlockLayoutAlgorithm::CalculateRelativeOffset( | 325 NGLogicalOffset NGBlockLayoutAlgorithm::CalculateLogicalOffset( |
329 const NGBoxFragment& fragment) { | 326 const WTF::Optional<NGLogicalOffset>& known_fragment_offset) { |
330 LayoutUnit inline_offset = | 327 LayoutUnit inline_offset = |
331 border_and_padding_.inline_start + curr_child_margins_.inline_start; | 328 border_and_padding_.inline_start + curr_child_margins_.inline_start; |
332 LayoutUnit block_offset = content_size_; | 329 LayoutUnit block_offset = content_size_; |
333 if (fragment.BfcOffset()) { | 330 if (known_fragment_offset) { |
334 block_offset = fragment.BfcOffset().value().block_offset - | 331 block_offset = known_fragment_offset.value().block_offset - |
335 builder_->BfcOffset().value().block_offset; | 332 builder_->BfcOffset().value().block_offset; |
336 } | 333 } |
337 return {inline_offset, block_offset}; | 334 return {inline_offset, block_offset}; |
338 } | 335 } |
339 | 336 |
340 RefPtr<NGPhysicalFragment> NGBlockLayoutAlgorithm::Layout() { | 337 RefPtr<NGPhysicalFragment> NGBlockLayoutAlgorithm::Layout() { |
341 WTF::Optional<MinAndMaxContentSizes> sizes; | 338 WTF::Optional<MinAndMaxContentSizes> sizes; |
342 if (NeedMinAndMaxContentSizes(ConstraintSpace(), Style())) | 339 if (NeedMinAndMaxContentSizes(ConstraintSpace(), Style())) |
343 sizes = ComputeMinAndMaxContentSizes(); | 340 sizes = ComputeMinAndMaxContentSizes(); |
344 | 341 |
(...skipping 104 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
449 block_size = | 446 block_size = |
450 ComputeBlockSizeForFragment(ConstraintSpace(), Style(), content_size_); | 447 ComputeBlockSizeForFragment(ConstraintSpace(), Style(), content_size_); |
451 builder_->SetBlockSize(block_size); | 448 builder_->SetBlockSize(block_size); |
452 | 449 |
453 // Layout our absolute and fixed positioned children. | 450 // Layout our absolute and fixed positioned children. |
454 NGOutOfFlowLayoutPart(Style(), builder_.get()).Run(); | 451 NGOutOfFlowLayoutPart(Style(), builder_.get()).Run(); |
455 | 452 |
456 // Non empty blocks always know their position in space: | 453 // Non empty blocks always know their position in space: |
457 if (block_size) { | 454 if (block_size) { |
458 curr_bfc_offset_.block_offset += curr_margin_strut_.Sum(); | 455 curr_bfc_offset_.block_offset += curr_margin_strut_.Sum(); |
459 UpdateFragmentBfcOffset(curr_bfc_offset_, ConstraintSpace(), | 456 UpdateFragmentBfcOffset(curr_bfc_offset_, builder_.get()); |
460 builder_.get()); | |
461 PositionPendingFloats(curr_bfc_offset_, builder_.get()); | 457 PositionPendingFloats(curr_bfc_offset_, builder_.get()); |
462 } | 458 } |
463 | 459 |
464 // Margins collapsing: | 460 // Margins collapsing: |
465 // Do not collapse margins between the last in-flow child and bottom margin | 461 // Do not collapse margins between the last in-flow child and bottom margin |
466 // of its parent if the parent has height != auto() | 462 // of its parent if the parent has height != auto() |
467 if (!Style().logicalHeight().isAuto()) { | 463 if (!Style().logicalHeight().isAuto()) { |
468 // TODO(glebl): handle minLogicalHeight, maxLogicalHeight. | 464 // TODO(glebl): handle minLogicalHeight, maxLogicalHeight. |
469 curr_margin_strut_ = NGMarginStrut(); | 465 curr_margin_strut_ = NGMarginStrut(); |
470 } | 466 } |
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
520 NGLogicalOffset origin_point = curr_bfc_offset_; | 516 NGLogicalOffset origin_point = curr_bfc_offset_; |
521 // Adjust origin point to the margins of the last child. | 517 // Adjust origin point to the margins of the last child. |
522 // Example: <div style="margin-bottom: 20px"><float></div> | 518 // Example: <div style="margin-bottom: 20px"><float></div> |
523 // <div style="margin-bottom: 30px"></div> | 519 // <div style="margin-bottom: 30px"></div> |
524 origin_point.block_offset += curr_margin_strut_.Sum(); | 520 origin_point.block_offset += curr_margin_strut_.Sum(); |
525 PositionPendingFloats(origin_point, builder_.get()); | 521 PositionPendingFloats(origin_point, builder_.get()); |
526 } | 522 } |
527 return; | 523 return; |
528 } | 524 } |
529 | 525 |
530 // Fragment that knows its offset can be used to set parent's BFC position. | 526 // Determine the fragment's position in the parent space either by using |
531 if (fragment.BfcOffset()) { | 527 // content_size_ or known fragment's BFC offset. |
| 528 WTF::Optional<NGLogicalOffset> bfc_offset; |
| 529 if (CurrentChildConstraintSpace().IsNewFormattingContext()) { |
| 530 curr_bfc_offset_.block_offset += curr_margin_strut_.Sum(); |
| 531 bfc_offset = curr_bfc_offset_; |
| 532 } else if (fragment.BfcOffset()) { |
| 533 // Fragment that knows its offset can be used to set parent's BFC position. |
532 curr_bfc_offset_.block_offset = fragment.BfcOffset().value().block_offset; | 534 curr_bfc_offset_.block_offset = fragment.BfcOffset().value().block_offset; |
533 UpdateFragmentBfcOffset(curr_bfc_offset_, ConstraintSpace(), | 535 bfc_offset = curr_bfc_offset_; |
534 builder_.get()); | 536 } |
| 537 if (bfc_offset) { |
| 538 UpdateFragmentBfcOffset(curr_bfc_offset_, builder_.get()); |
535 PositionPendingFloats(curr_bfc_offset_, builder_.get()); | 539 PositionPendingFloats(curr_bfc_offset_, builder_.get()); |
536 } | 540 } |
537 NGLogicalOffset fragment_offset = CalculateRelativeOffset(fragment); | 541 NGLogicalOffset logical_offset = CalculateLogicalOffset(bfc_offset); |
538 | 542 |
539 if (fragmentainer_mapper_) | 543 if (fragmentainer_mapper_) |
540 fragmentainer_mapper_->ToVisualOffset(fragment_offset); | 544 fragmentainer_mapper_->ToVisualOffset(logical_offset); |
541 else | 545 else |
542 fragment_offset.block_offset -= PreviousBreakOffset(); | 546 logical_offset.block_offset -= PreviousBreakOffset(); |
543 | 547 |
544 // Update margin strut. | 548 // Update margin strut. |
545 curr_margin_strut_ = fragment.EndMarginStrut(); | 549 curr_margin_strut_ = fragment.EndMarginStrut(); |
546 curr_margin_strut_.Append(curr_child_margins_.block_end); | 550 curr_margin_strut_.Append(curr_child_margins_.block_end); |
547 | 551 |
548 content_size_ = fragment.BlockSize() + fragment_offset.block_offset; | 552 content_size_ = fragment.BlockSize() + logical_offset.block_offset; |
549 max_inline_size_ = | 553 max_inline_size_ = |
550 std::max(max_inline_size_, fragment.InlineSize() + | 554 std::max(max_inline_size_, fragment.InlineSize() + |
551 curr_child_margins_.InlineSum() + | 555 curr_child_margins_.InlineSum() + |
552 border_and_padding_.InlineSum()); | 556 border_and_padding_.InlineSum()); |
553 | 557 |
554 builder_->AddChild(std::move(physical_fragment), fragment_offset); | 558 builder_->AddChild(std::move(physical_fragment), logical_offset); |
555 } | 559 } |
556 | 560 |
557 bool NGBlockLayoutAlgorithm::ProceedToNextUnfinishedSibling( | 561 bool NGBlockLayoutAlgorithm::ProceedToNextUnfinishedSibling( |
558 NGPhysicalFragment* child_fragment) { | 562 NGPhysicalFragment* child_fragment) { |
559 DCHECK(current_child_); | 563 DCHECK(current_child_); |
560 NGBlockNode* finished_child = toNGBlockNode(current_child_); | 564 NGBlockNode* finished_child = toNGBlockNode(current_child_); |
561 current_child_ = current_child_->NextSibling(); | 565 current_child_ = current_child_->NextSibling(); |
562 if (!ConstraintSpace().HasBlockFragmentation() && !fragmentainer_mapper_) | 566 if (!ConstraintSpace().HasBlockFragmentation() && !fragmentainer_mapper_) |
563 return true; | 567 return true; |
564 // If we're resuming layout after a fragmentainer break, we need to skip | 568 // If we're resuming layout after a fragmentainer break, we need to skip |
(...skipping 177 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
742 space_builder_->SetFragmentainerSpaceAvailable(space_available); | 746 space_builder_->SetFragmentainerSpaceAvailable(space_available); |
743 | 747 |
744 // Clearance : | 748 // Clearance : |
745 // - Collapse margins | 749 // - Collapse margins |
746 // - Update curr_bfc_offset and parent BFC offset if needed. | 750 // - Update curr_bfc_offset and parent BFC offset if needed. |
747 // - Position all pending floats as position is known now. | 751 // - Position all pending floats as position is known now. |
748 // TODO(glebl): Fix the use case with clear: left and an intruding right. | 752 // TODO(glebl): Fix the use case with clear: left and an intruding right. |
749 // https://software.hixie.ch/utilities/js/live-dom-viewer/saved/4847 | 753 // https://software.hixie.ch/utilities/js/live-dom-viewer/saved/4847 |
750 if (current_child_style.clear() != EClear::kNone) { | 754 if (current_child_style.clear() != EClear::kNone) { |
751 curr_bfc_offset_.block_offset += curr_margin_strut_.Sum(); | 755 curr_bfc_offset_.block_offset += curr_margin_strut_.Sum(); |
752 UpdateFragmentBfcOffset(curr_bfc_offset_, ConstraintSpace(), | 756 UpdateFragmentBfcOffset(curr_bfc_offset_, builder_.get()); |
753 builder_.get()); | |
754 // Only collapse margins if it's an adjoining block with clearance. | 757 // Only collapse margins if it's an adjoining block with clearance. |
755 if (!content_size_) { | 758 if (!content_size_) { |
756 curr_margin_strut_ = NGMarginStrut(); | 759 curr_margin_strut_ = NGMarginStrut(); |
757 curr_child_margins_.block_start = LayoutUnit(); | 760 curr_child_margins_.block_start = LayoutUnit(); |
758 } | 761 } |
759 PositionPendingFloats(curr_bfc_offset_, builder_.get()); | 762 PositionPendingFloats(curr_bfc_offset_, builder_.get()); |
760 AdjustToClearance(constraint_space_->Exclusions(), current_child_style, | 763 AdjustToClearance(constraint_space_->Exclusions(), current_child_style, |
761 builder_->BfcOffset().value(), &content_size_); | 764 builder_->BfcOffset().value(), &content_size_); |
762 } | 765 } |
763 | 766 |
(...skipping 10 matching lines...) Expand all Loading... |
774 curr_bfc_offset_.inline_offset += border_and_padding_.inline_start; | 777 curr_bfc_offset_.inline_offset += border_and_padding_.inline_start; |
775 if (ConstraintSpace().IsNewFormattingContext()) { | 778 if (ConstraintSpace().IsNewFormattingContext()) { |
776 curr_bfc_offset_.inline_offset += curr_child_margins_.inline_start; | 779 curr_bfc_offset_.inline_offset += curr_child_margins_.inline_start; |
777 } | 780 } |
778 space_builder_->SetBfcOffset(curr_bfc_offset_); | 781 space_builder_->SetBfcOffset(curr_bfc_offset_); |
779 | 782 |
780 return space_builder_->ToConstraintSpace(); | 783 return space_builder_->ToConstraintSpace(); |
781 } | 784 } |
782 | 785 |
783 } // namespace blink | 786 } // namespace blink |
OLD | NEW |