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); |
atotic
2017/01/18 18:48:49
SetIsNewFormattingContext() has been removed. Why?
ikilpatrick
2017/01/18 19:32:13
Yeah NewFormattingContext means basically this:
ht
| |
39 space_builder.SetIsNewFormattingContext(true); | |
40 space_builder.SetTextDirection(container_style->direction()); | 38 space_builder.SetTextDirection(container_style->direction()); |
41 parent_space_ = space_builder.ToConstraintSpace(); | 39 parent_space_ = space_builder.ToConstraintSpace(); |
42 } | 40 } |
43 | 41 |
44 bool NGOutOfFlowLayoutPart::StartLayout( | 42 void NGOutOfFlowLayoutPart::Layout(NGBlockNode& node, |
45 NGBlockNode* node, | 43 NGStaticPosition static_position, |
46 const NGStaticPosition& static_position) { | 44 NGFragment** fragment_out, |
47 EPosition position = node->Style()->position(); | 45 NGLogicalOffset* offset) { |
48 if ((contains_absolute_ && position == AbsolutePosition) || | 46 // Adjust the static_position origin. The static_position coordinate origin is |
49 (contains_fixed_ && position == FixedPosition)) { | 47 // relative to the parent's border box, ng_absolute_utils expects it to be |
50 node_ = node; | 48 // relative to the parent's padding box. |
51 static_position_ = static_position; | 49 static_position.offset -= parent_border_physical_offset_; |
52 // Adjust static_position origin. static_position coordinate origin is | 50 |
53 // border_box, absolute position coordinate origin is padding box. | 51 NGFragment* fragment = nullptr; |
54 static_position_.offset -= parent_physical_offset_; | 52 Optional<MinAndMaxContentSizes> inline_estimate; |
55 node_fragment_ = nullptr; | 53 Optional<LayoutUnit> block_estimate; |
56 node_position_ = NGAbsolutePhysicalPosition(); | 54 |
57 inline_estimate_.reset(); | 55 if (AbsoluteNeedsChildInlineSize(*node.Style())) { |
58 block_estimate_.reset(); | 56 inline_estimate = node.ComputeMinAndMaxContentSizesSync(); |
59 state_ = kComputeInlineEstimate; | |
60 return true; | |
61 } | 57 } |
62 return false; | 58 |
59 NGAbsolutePhysicalPosition node_position = | |
60 ComputePartialAbsoluteWithChildInlineSize( | |
61 *parent_space_, *node.Style(), static_position, inline_estimate); | |
62 | |
63 if (AbsoluteNeedsChildBlockSize(*node.Style())) { | |
64 fragment = GenerateFragment(node, block_estimate, node_position); | |
65 block_estimate = fragment->BlockSize(); | |
66 } | |
67 | |
68 ComputeFullAbsoluteWithChildBlockSize(*parent_space_, *node.Style(), | |
69 static_position, block_estimate, | |
70 &node_position); | |
71 | |
72 // Skip this step if we produced a fragment when estimating the block size. | |
73 if (!fragment) { | |
74 block_estimate = | |
75 node_position.size.ConvertToLogical(parent_space_->WritingMode()) | |
76 .block_size; | |
77 fragment = GenerateFragment(node, block_estimate, node_position); | |
78 } | |
79 | |
80 *fragment_out = fragment; | |
81 | |
82 // Compute logical offset, NGAbsolutePhysicalPosition is calculated relative | |
83 // to the padding box so add back the parent's borders. | |
84 NGBoxStrut inset = node_position.inset.ConvertToLogical( | |
85 parent_space_->WritingMode(), parent_space_->Direction()); | |
86 offset->inline_offset = | |
87 inset.inline_start + parent_border_offset_.inline_offset; | |
88 offset->block_offset = inset.block_start + parent_border_offset_.block_offset; | |
63 } | 89 } |
64 | 90 |
65 NGLayoutStatus NGOutOfFlowLayoutPart::Layout(NGFragment** fragment, | 91 NGFragment* NGOutOfFlowLayoutPart::GenerateFragment( |
66 NGLogicalOffset* offset) { | 92 NGBlockNode& node, |
67 DCHECK(node_); | 93 const Optional<LayoutUnit>& block_estimate, |
68 switch (state_) { | 94 const NGAbsolutePhysicalPosition node_position) { |
69 case kComputeInlineEstimate: | 95 // The fragment is generated in one of these two scenarios: |
70 if (ComputeInlineSizeEstimate()) | 96 // 1. To estimate child's block size, in this case block_size is parent's |
71 state_ = kPartialPosition; | 97 // available size. |
72 break; | 98 // 2. To compute final fragment, when block size is known from the absolute |
73 case kPartialPosition: | 99 // position calculation. |
74 node_position_ = ComputePartialAbsoluteWithChildInlineSize( | 100 LayoutUnit inline_size = |
75 *parent_space_, *node_->Style(), static_position_, inline_estimate_); | 101 node_position.size.ConvertToLogical(parent_space_->WritingMode()) |
76 state_ = kComputeBlockEstimate; | 102 .inline_size; |
77 break; | 103 LayoutUnit block_size = block_estimate |
78 case kComputeBlockEstimate: | 104 ? *block_estimate |
79 if (ComputeBlockSizeEstimate()) | 105 : 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 | 106 |
108 bool NGOutOfFlowLayoutPart::ComputeInlineSizeEstimate() { | 107 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 | 108 |
120 bool NGOutOfFlowLayoutPart::ComputeBlockSizeEstimate() { | 109 NGConstraintSpaceBuilder builder(parent_space_->WritingMode()); |
121 if (AbsoluteNeedsChildBlockSize(*node_->Style())) { | 110 builder.SetAvailableSize(available_size); |
122 if (ComputeNodeFragment()) { | 111 builder.SetPercentageResolutionSize(parent_space_->AvailableSize()); |
123 block_estimate_ = node_fragment_->BlockSize(); | 112 if (block_estimate) |
124 return true; | 113 builder.SetIsFixedSizeBlock(true); |
125 } | 114 builder.SetIsFixedSizeInline(true); |
126 return false; | 115 builder.SetIsNewFormattingContext(true); |
127 } | 116 NGConstraintSpace* space = builder.ToConstraintSpace(); |
128 return true; | |
129 } | |
130 | 117 |
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; | 118 NGFragment* fragment; |
157 if (node_->Layout(node_space_, &fragment)) { | 119 node.LayoutSync(space, &fragment); |
158 node_fragment_ = fragment; | 120 return fragment; |
159 return true; | |
160 } | |
161 return false; | |
162 } | 121 } |
163 | 122 |
164 DEFINE_TRACE(NGOutOfFlowLayoutPart) { | 123 DEFINE_TRACE(NGOutOfFlowLayoutPart) { |
165 visitor->trace(node_); | |
166 visitor->trace(parent_space_); | 124 visitor->trace(parent_space_); |
167 visitor->trace(node_fragment_); | |
168 visitor->trace(node_space_); | |
169 } | 125 } |
170 } | 126 |
127 } // namespace blink | |
OLD | NEW |