| 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_out_of_flow_layout_part.h" | 5 #include "core/layout/ng/ng_out_of_flow_layout_part.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_node.h" | 8 #include "core/layout/ng/ng_block_node.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_constraint_space_builder.h" | 10 #include "core/layout/ng/ng_constraint_space_builder.h" |
| 11 #include "core/layout/ng/ng_fragment.h" | 11 #include "core/layout/ng/ng_fragment.h" |
| 12 #include "core/layout/ng/ng_fragment_builder.h" |
| 12 #include "core/layout/ng/ng_length_utils.h" | 13 #include "core/layout/ng/ng_length_utils.h" |
| 13 #include "core/layout/ng/ng_physical_fragment.h" | 14 #include "core/layout/ng/ng_physical_fragment.h" |
| 14 #include "core/style/ComputedStyle.h" | 15 #include "core/style/ComputedStyle.h" |
| 15 | 16 |
| 16 namespace blink { | 17 namespace blink { |
| 17 | 18 |
| 19 namespace { |
| 20 |
| 21 // True if the container will contain an absolute descendant. |
| 22 bool IsContainingBlockForAbsoluteDescendant( |
| 23 const ComputedStyle& container_style, |
| 24 const ComputedStyle& descendant_style) { |
| 25 EPosition position = descendant_style.position(); |
| 26 bool contains_fixed = container_style.canContainFixedPositionObjects(); |
| 27 bool contains_absolute = |
| 28 container_style.canContainAbsolutePositionObjects() || contains_fixed; |
| 29 |
| 30 return (contains_absolute && position == AbsolutePosition) || |
| 31 (contains_fixed && position == FixedPosition); |
| 32 } |
| 33 |
| 34 } // namespace |
| 35 |
| 18 NGOutOfFlowLayoutPart::NGOutOfFlowLayoutPart( | 36 NGOutOfFlowLayoutPart::NGOutOfFlowLayoutPart( |
| 19 PassRefPtr<const ComputedStyle> container_style, | 37 const ComputedStyle& container_style, |
| 20 NGLogicalSize container_size) { | 38 NGFragmentBuilder* container_builder) |
| 39 : container_style_(container_style), container_builder_(container_builder) { |
| 21 NGWritingMode writing_mode( | 40 NGWritingMode writing_mode( |
| 22 FromPlatformWritingMode(container_style->getWritingMode())); | 41 FromPlatformWritingMode(container_style_.getWritingMode())); |
| 23 | 42 |
| 24 NGBoxStrut borders = ComputeBorders(*container_style); | 43 NGBoxStrut borders = ComputeBorders(container_style_); |
| 25 parent_border_offset_ = | 44 container_border_offset_ = |
| 26 NGLogicalOffset{borders.inline_start, borders.block_start}; | 45 NGLogicalOffset{borders.inline_start, borders.block_start}; |
| 27 parent_border_physical_offset_ = parent_border_offset_.ConvertToPhysical( | 46 container_border_physical_offset_ = |
| 28 writing_mode, container_style->direction(), | 47 container_border_offset_.ConvertToPhysical( |
| 29 container_size.ConvertToPhysical(writing_mode), NGPhysicalSize()); | 48 writing_mode, container_style_.direction(), |
| 49 container_builder_->Size().ConvertToPhysical(writing_mode), |
| 50 NGPhysicalSize()); |
| 30 | 51 |
| 31 NGLogicalSize space_size = container_size; | 52 NGLogicalSize space_size = container_builder_->Size(); |
| 32 space_size.block_size -= borders.BlockSum(); | 53 space_size.block_size -= borders.BlockSum(); |
| 33 space_size.inline_size -= borders.InlineSum(); | 54 space_size.inline_size -= borders.InlineSum(); |
| 34 | 55 |
| 35 // Initialize ConstraintSpace | 56 // Initialize ConstraintSpace |
| 36 NGConstraintSpaceBuilder space_builder(writing_mode); | 57 NGConstraintSpaceBuilder space_builder(writing_mode); |
| 37 space_builder.SetAvailableSize(space_size); | 58 space_builder.SetAvailableSize(space_size); |
| 38 space_builder.SetPercentageResolutionSize(space_size); | 59 space_builder.SetPercentageResolutionSize(space_size); |
| 39 space_builder.SetIsNewFormattingContext(true); | 60 space_builder.SetIsNewFormattingContext(true); |
| 40 space_builder.SetTextDirection(container_style->direction()); | 61 space_builder.SetTextDirection(container_style_.direction()); |
| 41 parent_space_ = space_builder.ToConstraintSpace(); | 62 container_space_ = space_builder.ToConstraintSpace(); |
| 42 } | 63 } |
| 43 | 64 |
| 44 void NGOutOfFlowLayoutPart::Layout(NGBlockNode& node, | 65 void NGOutOfFlowLayoutPart::Run() { |
| 45 NGStaticPosition static_position, | 66 HeapLinkedHashSet<WeakMember<NGBlockNode>> out_of_flow_candidates; |
| 46 NGFragment** fragment_out, | 67 Vector<NGStaticPosition> out_of_flow_candidate_positions; |
| 47 NGLogicalOffset* offset) { | 68 container_builder_->GetAndClearOutOfFlowDescendantCandidates( |
| 69 &out_of_flow_candidates, &out_of_flow_candidate_positions); |
| 70 |
| 71 size_t position_index = 0; |
| 72 |
| 73 for (auto& descendant : out_of_flow_candidates) { |
| 74 NGStaticPosition static_position = |
| 75 out_of_flow_candidate_positions[position_index++]; |
| 76 |
| 77 if (IsContainingBlockForAbsoluteDescendant(container_style_, |
| 78 *descendant->Style())) { |
| 79 NGLogicalOffset offset; |
| 80 NGFragment* fragment = |
| 81 LayoutDescendant(*descendant, static_position, &offset); |
| 82 // TODO(atotic) Need to adjust size of overflow rect per spec. |
| 83 container_builder_->AddChild(fragment, offset); |
| 84 } else { |
| 85 container_builder_->AddOutOfFlowDescendant(descendant, static_position); |
| 86 } |
| 87 } |
| 88 } |
| 89 |
| 90 NGFragment* NGOutOfFlowLayoutPart::LayoutDescendant( |
| 91 NGBlockNode& descendant, |
| 92 NGStaticPosition static_position, |
| 93 NGLogicalOffset* offset) { |
| 48 // Adjust the static_position origin. The static_position coordinate origin is | 94 // Adjust the static_position origin. The static_position coordinate origin is |
| 49 // relative to the parent's border box, ng_absolute_utils expects it to be | 95 // relative to the container's border box, ng_absolute_utils expects it to be |
| 50 // relative to the parent's padding box. | 96 // relative to the container's padding box. |
| 51 static_position.offset -= parent_border_physical_offset_; | 97 static_position.offset -= container_border_physical_offset_; |
| 52 | 98 |
| 53 NGFragment* fragment = nullptr; | 99 NGFragment* fragment = nullptr; |
| 54 Optional<MinAndMaxContentSizes> inline_estimate; | 100 Optional<MinAndMaxContentSizes> inline_estimate; |
| 55 Optional<LayoutUnit> block_estimate; | 101 Optional<LayoutUnit> block_estimate; |
| 56 | 102 |
| 57 if (AbsoluteNeedsChildInlineSize(*node.Style())) { | 103 if (AbsoluteNeedsChildInlineSize(*descendant.Style())) { |
| 58 inline_estimate = node.ComputeMinAndMaxContentSizesSync(); | 104 inline_estimate = descendant.ComputeMinAndMaxContentSizesSync(); |
| 59 } | 105 } |
| 60 | 106 |
| 61 NGAbsolutePhysicalPosition node_position = | 107 NGAbsolutePhysicalPosition node_position = |
| 62 ComputePartialAbsoluteWithChildInlineSize( | 108 ComputePartialAbsoluteWithChildInlineSize( |
| 63 *parent_space_, *node.Style(), static_position, inline_estimate); | 109 *container_space_, *descendant.Style(), static_position, |
| 110 inline_estimate); |
| 64 | 111 |
| 65 if (AbsoluteNeedsChildBlockSize(*node.Style())) { | 112 if (AbsoluteNeedsChildBlockSize(*descendant.Style())) { |
| 66 fragment = GenerateFragment(node, block_estimate, node_position); | 113 fragment = GenerateFragment(descendant, block_estimate, node_position); |
| 67 block_estimate = fragment->BlockSize(); | 114 block_estimate = fragment->BlockSize(); |
| 68 } | 115 } |
| 69 | 116 |
| 70 ComputeFullAbsoluteWithChildBlockSize(*parent_space_, *node.Style(), | 117 ComputeFullAbsoluteWithChildBlockSize(*container_space_, *descendant.Style(), |
| 71 static_position, block_estimate, | 118 static_position, block_estimate, |
| 72 &node_position); | 119 &node_position); |
| 73 | 120 |
| 74 // Skip this step if we produced a fragment when estimating the block size. | 121 // Skip this step if we produced a fragment when estimating the block size. |
| 75 if (!fragment) { | 122 if (!fragment) { |
| 76 block_estimate = | 123 block_estimate = |
| 77 node_position.size.ConvertToLogical(parent_space_->WritingMode()) | 124 node_position.size.ConvertToLogical(container_space_->WritingMode()) |
| 78 .block_size; | 125 .block_size; |
| 79 fragment = GenerateFragment(node, block_estimate, node_position); | 126 fragment = GenerateFragment(descendant, block_estimate, node_position); |
| 80 } | 127 } |
| 81 | 128 |
| 82 *fragment_out = fragment; | 129 // Compute logical offset, NGAbsolutePhysicalPosition is calculated relative |
| 130 // to the padding box so add back the container's borders. |
| 131 NGBoxStrut inset = node_position.inset.ConvertToLogical( |
| 132 container_space_->WritingMode(), container_space_->Direction()); |
| 133 offset->inline_offset = |
| 134 inset.inline_start + container_border_offset_.inline_offset; |
| 135 offset->block_offset = |
| 136 inset.block_start + container_border_offset_.block_offset; |
| 83 | 137 |
| 84 // Compute logical offset, NGAbsolutePhysicalPosition is calculated relative | 138 return fragment; |
| 85 // to the padding box so add back the parent's borders. | |
| 86 NGBoxStrut inset = node_position.inset.ConvertToLogical( | |
| 87 parent_space_->WritingMode(), parent_space_->Direction()); | |
| 88 offset->inline_offset = | |
| 89 inset.inline_start + parent_border_offset_.inline_offset; | |
| 90 offset->block_offset = inset.block_start + parent_border_offset_.block_offset; | |
| 91 } | 139 } |
| 92 | 140 |
| 93 NGFragment* NGOutOfFlowLayoutPart::GenerateFragment( | 141 NGFragment* NGOutOfFlowLayoutPart::GenerateFragment( |
| 94 NGBlockNode& node, | 142 NGBlockNode& descendant, |
| 95 const Optional<LayoutUnit>& block_estimate, | 143 const Optional<LayoutUnit>& block_estimate, |
| 96 const NGAbsolutePhysicalPosition node_position) { | 144 const NGAbsolutePhysicalPosition node_position) { |
| 97 // The fragment is generated in one of these two scenarios: | 145 // The fragment is generated in one of these two scenarios: |
| 98 // 1. To estimate child's block size, in this case block_size is parent's | 146 // 1. To estimate descendant's block size, in this case block_size is |
| 99 // available size. | 147 // container's available size. |
| 100 // 2. To compute final fragment, when block size is known from the absolute | 148 // 2. To compute final fragment, when block size is known from the absolute |
| 101 // position calculation. | 149 // position calculation. |
| 102 LayoutUnit inline_size = | 150 LayoutUnit inline_size = |
| 103 node_position.size.ConvertToLogical(parent_space_->WritingMode()) | 151 node_position.size.ConvertToLogical(container_space_->WritingMode()) |
| 104 .inline_size; | 152 .inline_size; |
| 105 LayoutUnit block_size = block_estimate | 153 LayoutUnit block_size = block_estimate |
| 106 ? *block_estimate | 154 ? *block_estimate |
| 107 : parent_space_->AvailableSize().block_size; | 155 : container_space_->AvailableSize().block_size; |
| 108 | 156 |
| 109 NGLogicalSize available_size{inline_size, block_size}; | 157 NGLogicalSize available_size{inline_size, block_size}; |
| 110 | 158 |
| 111 NGConstraintSpaceBuilder builder(parent_space_->WritingMode()); | 159 NGConstraintSpaceBuilder builder(container_space_->WritingMode()); |
| 112 builder.SetAvailableSize(available_size); | 160 builder.SetAvailableSize(available_size); |
| 113 builder.SetPercentageResolutionSize(parent_space_->AvailableSize()); | 161 builder.SetPercentageResolutionSize(container_space_->AvailableSize()); |
| 114 if (block_estimate) | 162 if (block_estimate) |
| 115 builder.SetIsFixedSizeBlock(true); | 163 builder.SetIsFixedSizeBlock(true); |
| 116 builder.SetIsFixedSizeInline(true); | 164 builder.SetIsFixedSizeInline(true); |
| 117 builder.SetIsNewFormattingContext(true); | 165 builder.SetIsNewFormattingContext(true); |
| 118 NGConstraintSpace* space = builder.ToConstraintSpace(); | 166 NGConstraintSpace* space = builder.ToConstraintSpace(); |
| 119 | 167 |
| 120 NGPhysicalFragment* fragment = node.Layout(space); | 168 NGPhysicalFragment* fragment = descendant.Layout(space); |
| 121 | 169 |
| 122 // TODO(ikilpatrick): the writing mode switching here looks wrong. | 170 // TODO(ikilpatrick): the writing mode switching here looks wrong. |
| 123 return new NGBoxFragment(parent_space_->WritingMode(), | 171 return new NGBoxFragment(container_space_->WritingMode(), |
| 124 parent_space_->Direction(), | 172 container_space_->Direction(), |
| 125 toNGPhysicalBoxFragment(fragment)); | 173 toNGPhysicalBoxFragment(fragment)); |
| 126 } | 174 } |
| 127 | 175 |
| 128 DEFINE_TRACE(NGOutOfFlowLayoutPart) { | |
| 129 visitor->trace(parent_space_); | |
| 130 } | |
| 131 | |
| 132 } // namespace blink | 176 } // namespace blink |
| OLD | NEW |