| 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_constraint_space_builder.h" | 9 #include "core/layout/ng/ng_constraint_space_builder.h" |
| 10 #include "core/layout/ng/ng_fragment.h" | 10 #include "core/layout/ng/ng_fragment.h" |
| 11 #include "core/layout/ng/ng_length_utils.h" | 11 #include "core/layout/ng/ng_length_utils.h" |
| 12 #include "core/layout/ng/ng_physical_fragment.h" | 12 #include "core/layout/ng/ng_physical_fragment.h" |
| 13 #include "core/style/ComputedStyle.h" | 13 #include "core/style/ComputedStyle.h" |
| 14 | 14 |
| 15 namespace blink { | 15 namespace blink { |
| 16 | 16 |
| 17 NGOutOfFlowLayoutPart::NGOutOfFlowLayoutPart( | 17 NGOutOfFlowLayoutPart::NGOutOfFlowLayoutPart( |
| 18 PassRefPtr<const ComputedStyle> container_style, | 18 PassRefPtr<const ComputedStyle> container_style, |
| 19 NGLogicalSize container_size) { | 19 NGLogicalSize container_size) { |
| 20 contains_fixed_ = container_style->canContainFixedPositionObjects(); | 20 NGWritingMode writing_mode( |
| 21 contains_absolute_ = | 21 FromPlatformWritingMode(container_style->getWritingMode())); |
| 22 container_style->canContainAbsolutePositionObjects() || contains_fixed_; | 22 |
| 23 // Initialize ConstraintSpace | 23 NGBoxStrut borders = ComputeBorders(*container_style); |
| 24 parent_border_offset_ = |
| 25 NGLogicalOffset{borders.inline_start, borders.block_start}; |
| 26 parent_border_physical_offset_ = parent_border_offset_.ConvertToPhysical( |
| 27 writing_mode, container_style->direction(), |
| 28 container_size.ConvertToPhysical(writing_mode), NGPhysicalSize()); |
| 29 |
| 24 NGLogicalSize space_size = container_size; | 30 NGLogicalSize space_size = container_size; |
| 25 NGBoxStrut borders = ComputeBorders(*container_style); | |
| 26 space_size.block_size -= borders.BlockSum(); | 31 space_size.block_size -= borders.BlockSum(); |
| 27 space_size.inline_size -= borders.InlineSum(); | 32 space_size.inline_size -= borders.InlineSum(); |
| 28 parent_offset_ = NGLogicalOffset{borders.inline_start, borders.block_start}; | 33 |
| 29 parent_physical_offset_ = parent_offset_.ConvertToPhysical( | 34 // Initialize ConstraintSpace |
| 30 FromPlatformWritingMode(container_style->getWritingMode()), | 35 NGConstraintSpaceBuilder space_builder(writing_mode); |
| 31 container_style->direction(), | |
| 32 container_size.ConvertToPhysical( | |
| 33 FromPlatformWritingMode(container_style->getWritingMode())), | |
| 34 NGPhysicalSize()); | |
| 35 NGConstraintSpaceBuilder space_builder( | |
| 36 FromPlatformWritingMode(container_style->getWritingMode())); | |
| 37 space_builder.SetAvailableSize(space_size); | 36 space_builder.SetAvailableSize(space_size); |
| 38 space_builder.SetPercentageResolutionSize(space_size); | 37 space_builder.SetPercentageResolutionSize(space_size); |
| 39 space_builder.SetIsNewFormattingContext(true); | 38 space_builder.SetIsNewFormattingContext(true); |
| 40 space_builder.SetTextDirection(container_style->direction()); | 39 space_builder.SetTextDirection(container_style->direction()); |
| 41 parent_space_ = space_builder.ToConstraintSpace(); | 40 parent_space_ = space_builder.ToConstraintSpace(); |
| 42 } | 41 } |
| 43 | 42 |
| 44 bool NGOutOfFlowLayoutPart::StartLayout( | 43 void NGOutOfFlowLayoutPart::Layout(NGBlockNode& node, |
| 45 NGBlockNode* node, | 44 NGStaticPosition static_position, |
| 46 const NGStaticPosition& static_position) { | 45 NGFragment** fragment_out, |
| 47 EPosition position = node->Style()->position(); | 46 NGLogicalOffset* offset) { |
| 48 if ((contains_absolute_ && position == AbsolutePosition) || | 47 // Adjust the static_position origin. The static_position coordinate origin is |
| 49 (contains_fixed_ && position == FixedPosition)) { | 48 // relative to the parent's border box, ng_absolute_utils expects it to be |
| 50 node_ = node; | 49 // relative to the parent's padding box. |
| 51 static_position_ = static_position; | 50 static_position.offset -= parent_border_physical_offset_; |
| 52 // Adjust static_position origin. static_position coordinate origin is | 51 |
| 53 // border_box, absolute position coordinate origin is padding box. | 52 NGFragment* fragment = nullptr; |
| 54 static_position_.offset -= parent_physical_offset_; | 53 Optional<MinAndMaxContentSizes> inline_estimate; |
| 55 node_fragment_ = nullptr; | 54 Optional<LayoutUnit> block_estimate; |
| 56 node_position_ = NGAbsolutePhysicalPosition(); | 55 |
| 57 inline_estimate_.reset(); | 56 if (AbsoluteNeedsChildInlineSize(*node.Style())) { |
| 58 block_estimate_.reset(); | 57 inline_estimate = node.ComputeMinAndMaxContentSizesSync(); |
| 59 state_ = kComputeInlineEstimate; | |
| 60 return true; | |
| 61 } | 58 } |
| 62 return false; | 59 |
| 60 NGAbsolutePhysicalPosition node_position = |
| 61 ComputePartialAbsoluteWithChildInlineSize( |
| 62 *parent_space_, *node.Style(), static_position, inline_estimate); |
| 63 |
| 64 if (AbsoluteNeedsChildBlockSize(*node.Style())) { |
| 65 fragment = GenerateFragment(node, block_estimate, node_position); |
| 66 block_estimate = fragment->BlockSize(); |
| 67 } |
| 68 |
| 69 ComputeFullAbsoluteWithChildBlockSize(*parent_space_, *node.Style(), |
| 70 static_position, block_estimate, |
| 71 &node_position); |
| 72 |
| 73 // Skip this step if we produced a fragment when estimating the block size. |
| 74 if (!fragment) { |
| 75 block_estimate = |
| 76 node_position.size.ConvertToLogical(parent_space_->WritingMode()) |
| 77 .block_size; |
| 78 fragment = GenerateFragment(node, block_estimate, node_position); |
| 79 } |
| 80 |
| 81 *fragment_out = fragment; |
| 82 |
| 83 // Compute logical offset, NGAbsolutePhysicalPosition is calculated relative |
| 84 // to the padding box so add back the parent's borders. |
| 85 NGBoxStrut inset = node_position.inset.ConvertToLogical( |
| 86 parent_space_->WritingMode(), parent_space_->Direction()); |
| 87 offset->inline_offset = |
| 88 inset.inline_start + parent_border_offset_.inline_offset; |
| 89 offset->block_offset = inset.block_start + parent_border_offset_.block_offset; |
| 63 } | 90 } |
| 64 | 91 |
| 65 NGLayoutStatus NGOutOfFlowLayoutPart::Layout(NGFragment** fragment, | 92 NGFragment* NGOutOfFlowLayoutPart::GenerateFragment( |
| 66 NGLogicalOffset* offset) { | 93 NGBlockNode& node, |
| 67 DCHECK(node_); | 94 const Optional<LayoutUnit>& block_estimate, |
| 68 switch (state_) { | 95 const NGAbsolutePhysicalPosition node_position) { |
| 69 case kComputeInlineEstimate: | 96 // The fragment is generated in one of these two scenarios: |
| 70 if (ComputeInlineSizeEstimate()) | 97 // 1. To estimate child's block size, in this case block_size is parent's |
| 71 state_ = kPartialPosition; | 98 // available size. |
| 72 break; | 99 // 2. To compute final fragment, when block size is known from the absolute |
| 73 case kPartialPosition: | 100 // position calculation. |
| 74 node_position_ = ComputePartialAbsoluteWithChildInlineSize( | 101 LayoutUnit inline_size = |
| 75 *parent_space_, *node_->Style(), static_position_, inline_estimate_); | 102 node_position.size.ConvertToLogical(parent_space_->WritingMode()) |
| 76 state_ = kComputeBlockEstimate; | 103 .inline_size; |
| 77 break; | 104 LayoutUnit block_size = block_estimate |
| 78 case kComputeBlockEstimate: | 105 ? *block_estimate |
| 79 if (ComputeBlockSizeEstimate()) | 106 : parent_space_->AvailableSize().block_size; |
| 80 state_ = kFullPosition; | |
| 81 break; | |
| 82 case kFullPosition: | |
| 83 ComputeFullAbsoluteWithChildBlockSize(*parent_space_, *node_->Style(), | |
| 84 static_position_, block_estimate_, | |
| 85 &node_position_); | |
| 86 state_ = kGenerateFragment; | |
| 87 break; | |
| 88 case kGenerateFragment: | |
| 89 block_estimate_ = | |
| 90 node_position_.size.ConvertToLogical(parent_space_->WritingMode()) | |
| 91 .block_size; | |
| 92 if (!ComputeNodeFragment()) | |
| 93 return kNotFinished; | |
| 94 state_ = kDone; | |
| 95 break; | |
| 96 case kDone: | |
| 97 *fragment = node_fragment_; | |
| 98 // Compute offset | |
| 99 NGBoxStrut inset = node_position_.inset.ConvertToLogical( | |
| 100 parent_space_->WritingMode(), parent_space_->Direction()); | |
| 101 offset->inline_offset = inset.inline_start + parent_offset_.inline_offset; | |
| 102 offset->block_offset = inset.block_start + parent_offset_.block_offset; | |
| 103 return kNewFragment; | |
| 104 } | |
| 105 return kNotFinished; | |
| 106 } | |
| 107 | 107 |
| 108 bool NGOutOfFlowLayoutPart::ComputeInlineSizeEstimate() { | 108 NGLogicalSize available_size{inline_size, block_size}; |
| 109 if (AbsoluteNeedsChildInlineSize(*node_->Style())) { | |
| 110 MinAndMaxContentSizes size; | |
| 111 if (node_->ComputeMinAndMaxContentSizes(&size)) { | |
| 112 inline_estimate_ = size; | |
| 113 return true; | |
| 114 } | |
| 115 return false; | |
| 116 } | |
| 117 return true; | |
| 118 } | |
| 119 | 109 |
| 120 bool NGOutOfFlowLayoutPart::ComputeBlockSizeEstimate() { | 110 NGConstraintSpaceBuilder builder(parent_space_->WritingMode()); |
| 121 if (AbsoluteNeedsChildBlockSize(*node_->Style())) { | 111 builder.SetAvailableSize(available_size); |
| 122 if (ComputeNodeFragment()) { | 112 builder.SetPercentageResolutionSize(parent_space_->AvailableSize()); |
| 123 block_estimate_ = node_fragment_->BlockSize(); | 113 if (block_estimate) |
| 124 return true; | 114 builder.SetIsFixedSizeBlock(true); |
| 125 } | 115 builder.SetIsFixedSizeInline(true); |
| 126 return false; | 116 builder.SetIsNewFormattingContext(true); |
| 127 } | 117 NGConstraintSpace* space = builder.ToConstraintSpace(); |
| 128 return true; | |
| 129 } | |
| 130 | 118 |
| 131 bool NGOutOfFlowLayoutPart::ComputeNodeFragment() { | |
| 132 if (node_fragment_) | |
| 133 return true; | |
| 134 if (!node_space_) { | |
| 135 NGConstraintSpaceBuilder builder(parent_space_->WritingMode()); | |
| 136 LayoutUnit inline_width = | |
| 137 node_position_.size.ConvertToLogical(parent_space_->WritingMode()) | |
| 138 .inline_size; | |
| 139 // Node fragment is computed in one of these two scenarios: | |
| 140 // 1. To estimate block size | |
| 141 // In this case, available block_size is parent's size. | |
| 142 // 2. To compute final block fragment, when block size is known. | |
| 143 | |
| 144 NGLogicalSize available_size = | |
| 145 NGLogicalSize(inline_width, parent_space_->AvailableSize().block_size); | |
| 146 if (block_estimate_) | |
| 147 available_size.block_size = *block_estimate_; | |
| 148 builder.SetAvailableSize(available_size); | |
| 149 builder.SetPercentageResolutionSize(parent_space_->AvailableSize()); | |
| 150 if (block_estimate_) | |
| 151 builder.SetIsFixedSizeBlock(true); | |
| 152 builder.SetIsFixedSizeInline(true); | |
| 153 builder.SetIsNewFormattingContext(true); | |
| 154 node_space_ = builder.ToConstraintSpace(); | |
| 155 } | |
| 156 NGFragment* fragment; | 119 NGFragment* fragment; |
| 157 if (node_->Layout(node_space_, &fragment)) { | 120 node.LayoutSync(space, &fragment); |
| 158 node_fragment_ = fragment; | 121 return fragment; |
| 159 return true; | |
| 160 } | |
| 161 return false; | |
| 162 } | 122 } |
| 163 | 123 |
| 164 DEFINE_TRACE(NGOutOfFlowLayoutPart) { | 124 DEFINE_TRACE(NGOutOfFlowLayoutPart) { |
| 165 visitor->trace(node_); | |
| 166 visitor->trace(parent_space_); | 125 visitor->trace(parent_space_); |
| 167 visitor->trace(node_fragment_); | |
| 168 visitor->trace(node_space_); | |
| 169 } | 126 } |
| 170 } | 127 |
| 128 } // namespace blink |
| OLD | NEW |