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_layout_opportunity_iterator.h" | 15 #include "core/layout/ng/ng_layout_opportunity_iterator.h" |
16 #include "core/layout/ng/ng_length_utils.h" | 16 #include "core/layout/ng/ng_length_utils.h" |
17 #include "core/layout/ng/ng_out_of_flow_layout_part.h" | 17 #include "core/layout/ng/ng_out_of_flow_layout_part.h" |
18 #include "core/layout/ng/ng_units.h" | 18 #include "core/layout/ng/ng_units.h" |
19 #include "core/style/ComputedStyle.h" | 19 #include "core/style/ComputedStyle.h" |
20 #include "platform/LengthFunctions.h" | 20 #include "platform/LengthFunctions.h" |
21 #include "wtf/Optional.h" | 21 #include "wtf/Optional.h" |
22 | 22 |
23 namespace blink { | 23 namespace blink { |
24 namespace { | 24 namespace { |
25 | 25 |
26 // Adjusts content's offset to CSS "clear" property. | 26 // Adjusts content_size to CSS "clear" property. |
27 // TODO(glebl): Support margin collapsing edge cases, e.g. margin collapsing | 27 // Picks up the maximum between left/right exclusions and content_size depending |
28 // should not occur if "clear" is applied to non-floating blocks. | 28 // on the value of style.clear() property. |
29 // TODO(layout-ng): the call to AdjustToClearance should be moved to | 29 void AdjustToClearance(const std::shared_ptr<NGExclusions>& exclusions, |
30 // CreateConstraintSpaceForChild once ConstraintSpaceBuilder is sharing the | |
31 // exclusion information between constraint spaces. | |
32 void AdjustToClearance(const NGConstraintSpace& space, | |
33 const ComputedStyle& style, | 30 const ComputedStyle& style, |
31 const NGLogicalOffset& from_offset, | |
34 LayoutUnit* content_size) { | 32 LayoutUnit* content_size) { |
35 const NGExclusion* right_exclusion = space.Exclusions()->last_right_float; | 33 DCHECK(content_size) << "content_size cannot be null here"; |
36 const NGExclusion* left_exclusion = space.Exclusions()->last_left_float; | 34 const NGExclusion* right_exclusion = exclusions->last_right_float; |
35 const NGExclusion* left_exclusion = exclusions->last_left_float; | |
37 | 36 |
38 // Calculates Left/Right block end offset from left/right float exclusions or | 37 // Exclusions(stored in BFC coordinates), content_size can be negative or 0 |
39 // use the default content offset position. | 38 // If left or right exclusion are available then convert them to the relative |
40 LayoutUnit left_block_end_offset = | 39 // offset(exclusion.BlockEnd - from_offset) and compare them with content_size |
41 left_exclusion ? left_exclusion->rect.BlockEndOffset() : *content_size; | 40 LayoutUnit left_block_end_offset = *content_size; |
42 LayoutUnit right_block_end_offset = | 41 if (left_exclusion) { |
43 right_exclusion ? right_exclusion->rect.BlockEndOffset() : *content_size; | 42 left_block_end_offset = std::max( |
43 left_exclusion->rect.BlockEndOffset() - from_offset.block_offset, | |
44 *content_size); | |
45 } | |
46 LayoutUnit right_block_end_offset = *content_size; | |
47 if (right_exclusion) { | |
48 right_block_end_offset = std::max( | |
49 right_exclusion->rect.BlockEndOffset() - from_offset.block_offset, | |
50 *content_size); | |
51 } | |
44 | 52 |
45 switch (style.clear()) { | 53 switch (style.clear()) { |
46 case EClear::ClearNone: | 54 case EClear::ClearNone: |
47 return; // nothing to do here. | 55 return; // nothing to do here. |
48 case EClear::ClearLeft: | 56 case EClear::ClearLeft: |
49 *content_size = left_block_end_offset; | 57 *content_size = left_block_end_offset; |
50 break; | 58 break; |
51 case EClear::ClearRight: | 59 case EClear::ClearRight: |
52 *content_size = right_block_end_offset; | 60 *content_size = right_block_end_offset; |
53 break; | 61 break; |
54 case EClear::ClearBoth: | 62 case EClear::ClearBoth: |
55 *content_size = std::max(left_block_end_offset, right_block_end_offset); | 63 *content_size = std::max(left_block_end_offset, right_block_end_offset); |
56 break; | 64 break; |
57 default: | 65 default: |
58 ASSERT_NOT_REACHED(); | 66 ASSERT_NOT_REACHED(); |
59 } | 67 } |
60 } | 68 } |
61 | 69 |
62 LayoutUnit ComputeCollapsedMarginBlockStart( | |
63 const NGDeprecatedMarginStrut& prev_margin_strut, | |
64 const NGDeprecatedMarginStrut& curr_margin_strut) { | |
65 return std::max(prev_margin_strut.margin_block_end, | |
66 curr_margin_strut.margin_block_start) - | |
67 std::max(prev_margin_strut.negative_margin_block_end.abs(), | |
68 curr_margin_strut.negative_margin_block_start.abs()); | |
69 } | |
70 | |
71 // Creates an exclusion from the fragment that will be placed in the provided | 70 // Creates an exclusion from the fragment that will be placed in the provided |
72 // layout opportunity. | 71 // layout opportunity. |
73 NGExclusion CreateExclusion(const NGFragment& fragment, | 72 NGExclusion CreateExclusion(const NGFragment& fragment, |
74 const NGLayoutOpportunity& opportunity, | 73 const NGLayoutOpportunity& opportunity, |
75 LayoutUnit float_offset, | 74 const LayoutUnit& float_offset, |
ikilpatrick
2017/01/26 04:37:25
drop reference.
Gleb Lanbin
2017/01/31 00:25:01
Done.
| |
76 NGBoxStrut margins, | 75 const NGBoxStrut& margins, |
77 NGExclusion::Type exclusion_type) { | 76 NGExclusion::Type exclusion_type) { |
78 NGExclusion exclusion; | 77 NGExclusion exclusion; |
79 exclusion.type = exclusion_type; | 78 exclusion.type = exclusion_type; |
80 NGLogicalRect& rect = exclusion.rect; | 79 NGLogicalRect& rect = exclusion.rect; |
81 rect.offset = opportunity.offset; | 80 rect.offset = opportunity.offset; |
82 rect.offset.inline_offset += float_offset; | 81 rect.offset.inline_offset += float_offset; |
83 | 82 |
84 rect.size.inline_size = fragment.InlineSize(); | 83 rect.size.inline_size = fragment.InlineSize() + margins.InlineSum(); |
85 rect.size.block_size = fragment.BlockSize(); | 84 rect.size.block_size = fragment.BlockSize() + margins.BlockSum(); |
85 return exclusion; | |
86 } | |
86 | 87 |
87 // Adjust to child's margin. | 88 // Adjusts the provided offset to the top edge alignment rule. |
88 rect.size.block_size += margins.BlockSum(); | 89 // Top edge alignment rule: the outer top of a floating box may not be higher |
89 rect.size.inline_size += margins.InlineSum(); | 90 // than the outer top of any block or floated box generated by an element |
90 | 91 // earlier in the source document |
91 return exclusion; | 92 NGLogicalOffset AdjustToTopEdgeAlignmentRule(const NGConstraintSpace& space, |
93 const NGLogicalOffset& offset) { | |
94 NGLogicalOffset adjusted_offset = offset; | |
95 LayoutUnit& adjusted_block_offset = adjusted_offset.block_offset; | |
96 if (space.Exclusions()->last_left_float) | |
97 adjusted_block_offset = | |
98 std::max(adjusted_block_offset, | |
99 space.Exclusions()->last_left_float->rect.BlockStartOffset()); | |
100 if (space.Exclusions()->last_right_float) | |
101 adjusted_block_offset = | |
102 std::max(adjusted_block_offset, | |
103 space.Exclusions()->last_right_float->rect.BlockStartOffset()); | |
104 return adjusted_offset; | |
92 } | 105 } |
93 | 106 |
94 // Finds a layout opportunity for the fragment. | 107 // Finds a layout opportunity for the fragment. |
95 // It iterates over all layout opportunities in the constraint space and returns | 108 // It iterates over all layout opportunities in the constraint space and returns |
96 // the first layout opportunity that is wider than the fragment or returns the | 109 // the first layout opportunity that is wider than the fragment or returns the |
97 // last one which is always the widest. | 110 // last one which is always the widest. |
98 // | 111 // |
99 // @param space Constraint space that is used to find layout opportunity for | 112 // @param space Constraint space that is used to find layout opportunity for |
100 // the fragment. | 113 // the fragment. |
101 // @param fragment Fragment that needs to be placed. | 114 // @param fragment Fragment that needs to be placed. |
115 // @param origin_point {@code space}'s offset relative to the space that | |
116 // establishes a new formatting context that we're currently | |
117 // in and where all our exclusions reside. | |
102 // @param margins Margins of the fragment. | 118 // @param margins Margins of the fragment. |
103 // @return Layout opportunity for the fragment. | 119 // @return Layout opportunity for the fragment. |
104 const NGLayoutOpportunity FindLayoutOpportunityForFragment( | 120 const NGLayoutOpportunity FindLayoutOpportunityForFragment( |
105 NGConstraintSpace* space, | 121 NGConstraintSpace* space, |
106 const NGFragment& fragment, | 122 const NGFragment& fragment, |
123 const NGLogicalOffset& origin_point, | |
107 const NGBoxStrut& margins) { | 124 const NGBoxStrut& margins) { |
108 NGLayoutOpportunityIterator* opportunity_iter = space->LayoutOpportunities(); | 125 NGLogicalOffset adjusted_origin_point = |
126 AdjustToTopEdgeAlignmentRule(*space, origin_point); | |
127 | |
128 NGLayoutOpportunityIterator* opportunity_iter = | |
129 space->LayoutOpportunities(adjusted_origin_point); | |
109 NGLayoutOpportunity opportunity; | 130 NGLayoutOpportunity opportunity; |
110 NGLayoutOpportunity opportunity_candidate = opportunity_iter->Next(); | 131 NGLayoutOpportunity opportunity_candidate = opportunity_iter->Next(); |
111 | 132 |
112 while (!opportunity_candidate.IsEmpty()) { | 133 while (!opportunity_candidate.IsEmpty()) { |
113 opportunity = opportunity_candidate; | 134 opportunity = opportunity_candidate; |
114 // Checking opportunity's block size is not necessary as a float cannot be | 135 // Checking opportunity's block size is not necessary as a float cannot be |
115 // positioned on top of another float inside of the same constraint space. | 136 // positioned on top of another float inside of the same constraint space. |
116 auto fragment_inline_size = fragment.InlineSize() + margins.InlineSum(); | 137 auto fragment_inline_size = fragment.InlineSize() + margins.InlineSum(); |
117 if (opportunity.size.inline_size > fragment_inline_size) | 138 if (opportunity.size.inline_size >= fragment_inline_size) |
118 break; | 139 break; |
119 | |
120 opportunity_candidate = opportunity_iter->Next(); | 140 opportunity_candidate = opportunity_iter->Next(); |
121 } | 141 } |
122 | |
123 return opportunity; | 142 return opportunity; |
124 } | 143 } |
125 | 144 |
126 // Calculates the logical offset for opportunity. | 145 // Calculates the logical offset for opportunity. |
127 NGLogicalOffset CalculateLogicalOffsetForOpportunity( | 146 NGLogicalOffset CalculateLogicalOffsetForOpportunity( |
128 const NGLayoutOpportunity& opportunity, | 147 const NGLayoutOpportunity& opportunity, |
129 LayoutUnit float_offset, | 148 const LayoutUnit& float_offset, |
ikilpatrick
2017/01/26 04:37:26
drop the reference, this is a single int basically
Gleb Lanbin
2017/01/31 00:25:01
Done.
| |
130 NGBoxStrut margins) { | 149 const NGBoxStrut& margins, |
150 const NGLogicalOffset& space_offset) { | |
131 // Adjust to child's margin. | 151 // Adjust to child's margin. |
132 LayoutUnit inline_offset = margins.inline_start; | 152 LayoutUnit inline_offset = margins.inline_start; |
133 LayoutUnit block_offset = margins.block_start; | 153 LayoutUnit block_offset = margins.block_start; |
134 | 154 |
135 // Offset from the opportunity's block/inline start. | 155 // Offset from the opportunity's block/inline start. |
136 inline_offset += opportunity.offset.inline_offset; | 156 inline_offset += opportunity.offset.inline_offset; |
137 block_offset += opportunity.offset.block_offset; | 157 block_offset += opportunity.offset.block_offset; |
138 | 158 |
139 inline_offset += float_offset; | 159 inline_offset += float_offset; |
140 | 160 |
161 block_offset -= space_offset.block_offset; | |
162 inline_offset -= space_offset.inline_offset; | |
163 | |
141 return NGLogicalOffset(inline_offset, block_offset); | 164 return NGLogicalOffset(inline_offset, block_offset); |
142 } | 165 } |
143 | 166 |
167 // Calculates the relative position(from {@code from_offset}) of the | |
ikilpatrick
2017/01/26 04:37:25
.nit space "position ("
Gleb Lanbin
2017/01/31 00:25:01
Done.
| |
168 // floating object that is requested to be positioned from {@code origin_point}. | |
169 NGLogicalOffset PositionFloat(const NGLogicalOffset& origin_point, | |
170 const NGLogicalOffset& from_offset, | |
171 NGFloatingObject* floating_object) { | |
172 NGConstraintSpace* float_space = floating_object->space; | |
173 NGBoxFragment* float_fragment = | |
174 new NGBoxFragment(float_space->WritingMode(), float_space->Direction(), | |
175 toNGPhysicalBoxFragment(floating_object->fragment)); | |
ikilpatrick
2017/01/26 04:37:25
DCHECK(floating_object->fragment) ?
Gleb Lanbin
2017/01/31 00:25:01
Done.
| |
176 // Find a layout opportunity that will fit our float. | |
177 const NGLayoutOpportunity opportunity = | |
178 FindLayoutOpportunityForFragment(floating_object->space, *float_fragment, | |
179 origin_point, floating_object->margins); | |
180 DCHECK(!opportunity.IsEmpty()) << "Opportunity is empty but it shouldn't be"; | |
181 | |
182 // Calculate the float offset if needed. | |
183 LayoutUnit float_offset; | |
184 if (floating_object->exclusion_type == NGExclusion::kFloatRight) { | |
185 float_offset = opportunity.size.inline_size - float_fragment->InlineSize(); | |
186 } | |
187 | |
188 // Add the float as an exclusion. | |
189 const NGExclusion exclusion = CreateExclusion( | |
190 *float_fragment, opportunity, float_offset, floating_object->margins, | |
191 floating_object->exclusion_type); | |
192 float_space->AddExclusion(exclusion); | |
193 | |
194 return CalculateLogicalOffsetForOpportunity( | |
195 opportunity, float_offset, floating_object->margins, from_offset); | |
196 } | |
197 | |
198 // Positions pending floats stored on the fragment builder starting from | |
199 // {@code origin_point}. | |
200 void PositionFloats(const NGLogicalOffset& origin_point, | |
ikilpatrick
2017/01/26 04:37:26
is "Pending" floats a better name than unpositione
Gleb Lanbin
2017/01/31 00:25:01
I thought about that. Here is my rationale behind
| |
201 NGFragmentBuilder* builder) { | |
202 DCHECK(builder->BfcOffset()) << "Parent BFC offset should be known here"; | |
203 NGLogicalOffset from_offset = builder->BfcOffset().value(); | |
204 | |
205 for (auto& floating_object : builder->UnpositionedFloats()) { | |
206 NGLogicalOffset float_fragment_offset = | |
207 PositionFloat(origin_point, from_offset, floating_object); | |
208 builder->AddFloatingObject(floating_object, float_fragment_offset); | |
209 } | |
210 builder->MutableUnpositionedFloats().clear(); | |
211 } | |
212 | |
144 // Whether an in-flow block-level child creates a new formatting context. | 213 // Whether an in-flow block-level child creates a new formatting context. |
145 // | 214 // |
146 // This will *NOT* check the following cases: | 215 // This will *NOT* check the following cases: |
147 // - The child is out-of-flow, e.g. floating or abs-pos. | 216 // - The child is out-of-flow, e.g. floating or abs-pos. |
148 // - The child is a inline-level, e.g. "display: inline-block". | 217 // - The child is a inline-level, e.g. "display: inline-block". |
149 // - The child establishes a new formatting context, but should be a child of | 218 // - The child establishes a new formatting context, but should be a child of |
150 // another layout algorithm, e.g. "display: table-caption" or flex-item. | 219 // another layout algorithm, e.g. "display: table-caption" or flex-item. |
151 bool IsNewFormattingContextForInFlowBlockLevelChild( | 220 bool IsNewFormattingContextForInFlowBlockLevelChild( |
152 const NGConstraintSpace& space, | 221 const NGConstraintSpace& space, |
153 const ComputedStyle& style) { | 222 const ComputedStyle& style) { |
(...skipping 29 matching lines...) Expand all Loading... | |
183 PassRefPtr<const ComputedStyle> style, | 252 PassRefPtr<const ComputedStyle> style, |
184 NGBlockNode* first_child, | 253 NGBlockNode* first_child, |
185 NGConstraintSpace* constraint_space, | 254 NGConstraintSpace* constraint_space, |
186 NGBreakToken* break_token) | 255 NGBreakToken* break_token) |
187 : NGLayoutAlgorithm(kBlockLayoutAlgorithm), | 256 : NGLayoutAlgorithm(kBlockLayoutAlgorithm), |
188 style_(style), | 257 style_(style), |
189 first_child_(first_child), | 258 first_child_(first_child), |
190 constraint_space_(constraint_space), | 259 constraint_space_(constraint_space), |
191 break_token_(break_token), | 260 break_token_(break_token), |
192 builder_(new NGFragmentBuilder(NGPhysicalFragment::kFragmentBox, | 261 builder_(new NGFragmentBuilder(NGPhysicalFragment::kFragmentBox, |
193 layout_object)), | 262 layout_object)) { |
194 is_fragment_margin_strut_block_start_updated_(false) { | |
195 DCHECK(style_); | 263 DCHECK(style_); |
196 } | 264 } |
197 | 265 |
198 bool NGBlockLayoutAlgorithm::ComputeMinAndMaxContentSizes( | 266 bool NGBlockLayoutAlgorithm::ComputeMinAndMaxContentSizes( |
199 MinAndMaxContentSizes* sizes) const { | 267 MinAndMaxContentSizes* sizes) const { |
200 sizes->min_content = LayoutUnit(); | 268 sizes->min_content = LayoutUnit(); |
201 sizes->max_content = LayoutUnit(); | 269 sizes->max_content = LayoutUnit(); |
202 | 270 |
203 // Size-contained elements don't consider their contents for intrinsic sizing. | 271 // Size-contained elements don't consider their contents for intrinsic sizing. |
204 if (Style().containsSize()) | 272 if (Style().containsSize()) |
(...skipping 10 matching lines...) Expand all Loading... | |
215 ComputeMinAndMaxContentContribution(*node->Style(), child_minmax); | 283 ComputeMinAndMaxContentContribution(*node->Style(), child_minmax); |
216 | 284 |
217 sizes->min_content = std::max(sizes->min_content, child_sizes.min_content); | 285 sizes->min_content = std::max(sizes->min_content, child_sizes.min_content); |
218 sizes->max_content = std::max(sizes->max_content, child_sizes.max_content); | 286 sizes->max_content = std::max(sizes->max_content, child_sizes.max_content); |
219 } | 287 } |
220 | 288 |
221 sizes->max_content = std::max(sizes->min_content, sizes->max_content); | 289 sizes->max_content = std::max(sizes->min_content, sizes->max_content); |
222 return true; | 290 return true; |
223 } | 291 } |
224 | 292 |
293 NGLogicalOffset NGBlockLayoutAlgorithm::PositionFragmentWithKnownBfcOffset( | |
294 const NGLogicalOffset& offset) { | |
295 curr_bfc_offset_.block_offset = offset.block_offset; | |
296 // First block that knows its position. Update the parent's BFC offset. | |
297 if (!builder_->BfcOffset()) { | |
298 NGLogicalOffset parent_bfc_offset = | |
299 ConstraintSpace().IsNewFormattingContext() ? NGLogicalOffset() | |
300 : curr_bfc_offset_; | |
301 builder_->SetBfcOffset(parent_bfc_offset); | |
302 } | |
303 | |
304 // OK to position pending floats. curr_bfc_offset_ and parent's BFC offset | |
305 // are accurate here. | |
306 PositionFloats(curr_bfc_offset_, builder_); | |
307 | |
308 LayoutUnit block_offset = | |
309 offset.block_offset - builder_->BfcOffset().value().block_offset; | |
310 LayoutUnit inline_offset = | |
311 border_and_padding_.inline_start + curr_child_margins_.inline_start; | |
312 return {inline_offset, block_offset}; | |
313 } | |
314 | |
225 NGPhysicalFragment* NGBlockLayoutAlgorithm::Layout() { | 315 NGPhysicalFragment* NGBlockLayoutAlgorithm::Layout() { |
226 WTF::Optional<MinAndMaxContentSizes> sizes; | 316 WTF::Optional<MinAndMaxContentSizes> sizes; |
227 if (NeedMinAndMaxContentSizes(ConstraintSpace(), Style())) { | 317 if (NeedMinAndMaxContentSizes(ConstraintSpace(), Style())) { |
228 // TODO(ikilpatrick): Change ComputeMinAndMaxContentSizes to return | 318 // TODO(ikilpatrick): Change ComputeMinAndMaxContentSizes to return |
229 // MinAndMaxContentSizes. | 319 // MinAndMaxContentSizes. |
230 sizes = MinAndMaxContentSizes(); | 320 sizes = MinAndMaxContentSizes(); |
231 ComputeMinAndMaxContentSizes(&*sizes); | 321 ComputeMinAndMaxContentSizes(&*sizes); |
232 } | 322 } |
233 | 323 |
234 border_and_padding_ = | 324 border_and_padding_ = |
(...skipping 26 matching lines...) Expand all Loading... | |
261 } | 351 } |
262 space_builder_->SetAvailableSize( | 352 space_builder_->SetAvailableSize( |
263 NGLogicalSize(adjusted_inline_size, adjusted_block_size)); | 353 NGLogicalSize(adjusted_inline_size, adjusted_block_size)); |
264 space_builder_->SetPercentageResolutionSize( | 354 space_builder_->SetPercentageResolutionSize( |
265 NGLogicalSize(adjusted_inline_size, adjusted_block_size)); | 355 NGLogicalSize(adjusted_inline_size, adjusted_block_size)); |
266 | 356 |
267 builder_->SetDirection(constraint_space_->Direction()); | 357 builder_->SetDirection(constraint_space_->Direction()); |
268 builder_->SetWritingMode(constraint_space_->WritingMode()); | 358 builder_->SetWritingMode(constraint_space_->WritingMode()); |
269 builder_->SetInlineSize(inline_size).SetBlockSize(block_size); | 359 builder_->SetInlineSize(inline_size).SetBlockSize(block_size); |
270 | 360 |
361 // TODO(glebl): fix multicol after the new margin collapsing/floats algorithm | |
362 // based on BFCOffset is checked in. | |
271 if (NGBlockBreakToken* token = CurrentBlockBreakToken()) { | 363 if (NGBlockBreakToken* token = CurrentBlockBreakToken()) { |
272 // Resume after a previous break. | 364 // Resume after a previous break. |
273 content_size_ = token->BreakOffset(); | 365 content_size_ = token->BreakOffset(); |
274 current_child_ = token->InputNode(); | 366 current_child_ = token->InputNode(); |
275 } else { | 367 } else { |
276 content_size_ = border_and_padding_.block_start; | 368 content_size_ = border_and_padding_.block_start; |
277 current_child_ = first_child_; | 369 current_child_ = first_child_; |
278 } | 370 } |
279 | 371 |
372 curr_margin_strut_ = constraint_space_->MarginStrut(); | |
ikilpatrick
2017/01/26 00:49:58
ConstraintSpace() instead?
Gleb Lanbin
2017/01/31 00:25:01
Done.
| |
373 curr_bfc_offset_ = ConstraintSpace().BfcOffset(); | |
374 | |
375 // Margins collapsing: | |
376 // Do not collapse margins between parent and its child if there is | |
377 // border/padding between them | |
ikilpatrick
2017/01/26 00:49:58
.nit period.
Gleb Lanbin
2017/01/31 00:25:01
Done.
| |
378 if (border_and_padding_.block_start) { | |
379 curr_bfc_offset_.block_offset += curr_margin_strut_.Collapse(); | |
380 builder_->SetBfcOffset(curr_bfc_offset_); | |
381 curr_margin_strut_ = NGMarginStrut(); | |
382 } | |
383 curr_bfc_offset_.block_offset += content_size_; | |
384 | |
280 while (current_child_) { | 385 while (current_child_) { |
281 EPosition position = current_child_->Style()->position(); | 386 EPosition position = current_child_->Style()->position(); |
282 if (position == AbsolutePosition || position == FixedPosition) { | 387 if (position == AbsolutePosition || position == FixedPosition) { |
283 builder_->AddOutOfFlowChildCandidate(current_child_, | 388 builder_->AddOutOfFlowChildCandidate(current_child_, |
284 GetChildSpaceOffset()); | 389 GetChildSpaceOffset()); |
285 current_child_ = current_child_->NextSibling(); | 390 current_child_ = current_child_->NextSibling(); |
286 continue; | 391 continue; |
287 } | 392 } |
288 | 393 |
289 DCHECK(!ConstraintSpace().HasBlockFragmentation() || | 394 DCHECK(!ConstraintSpace().HasBlockFragmentation() || |
290 SpaceAvailableForCurrentChild() > LayoutUnit()); | 395 SpaceAvailableForCurrentChild() > LayoutUnit()); |
291 space_for_current_child_ = CreateConstraintSpaceForCurrentChild(); | 396 space_for_current_child_ = CreateConstraintSpaceForCurrentChild(); |
292 | 397 |
293 NGPhysicalFragment* child_fragment = | 398 NGPhysicalFragment* child_fragment = |
294 current_child_->Layout(space_for_current_child_); | 399 current_child_->Layout(space_for_current_child_); |
295 | 400 |
296 FinishCurrentChildLayout(new NGBoxFragment( | 401 FinishCurrentChildLayout(new NGBoxFragment( |
297 ConstraintSpace().WritingMode(), ConstraintSpace().Direction(), | 402 ConstraintSpace().WritingMode(), ConstraintSpace().Direction(), |
298 toNGPhysicalBoxFragment(child_fragment))); | 403 toNGPhysicalBoxFragment(child_fragment))); |
299 | 404 |
300 if (!ProceedToNextUnfinishedSibling(child_fragment)) | 405 if (!ProceedToNextUnfinishedSibling(child_fragment)) |
301 break; | 406 break; |
302 } | 407 } |
303 | 408 |
409 // Margins collapsing: | |
410 // Bottom margins of an in-flow block box doesn't collapse with its last | |
411 // in-flow block-level child's bottom margin if the box has bottom | |
412 // border/padding. | |
304 content_size_ += border_and_padding_.block_end; | 413 content_size_ += border_and_padding_.block_end; |
414 if (border_and_padding_.block_end || | |
415 ConstraintSpace().IsNewFormattingContext()) { | |
416 content_size_ += curr_margin_strut_.Collapse(); | |
417 curr_margin_strut_ = NGMarginStrut(); | |
418 } | |
305 | 419 |
306 // Recompute the block-axis size now that we know our content size. | 420 // Recompute the block-axis size now that we know our content size. |
307 block_size = | 421 block_size = |
308 ComputeBlockSizeForFragment(ConstraintSpace(), Style(), content_size_); | 422 ComputeBlockSizeForFragment(ConstraintSpace(), Style(), content_size_); |
309 builder_->SetBlockSize(block_size); | 423 builder_->SetBlockSize(block_size); |
310 | 424 |
311 LayoutOutOfFlowChildren(); | 425 LayoutOutOfFlowChildren(); |
312 | 426 |
427 // Set offset if the size is not empty. | |
ikilpatrick
2017/01/26 00:49:57
Set our BFC offset if ... ? (up to you)
Gleb Lanbin
2017/01/31 00:25:01
Done.
| |
428 if (block_size && !builder_->BfcOffset()) { | |
429 curr_bfc_offset_.block_offset += curr_margin_strut_.Collapse(); | |
430 builder_->SetBfcOffset(curr_bfc_offset_); | |
431 } | |
432 | |
433 if (!Style().logicalHeight().isAuto()) { | |
ikilpatrick
2017/01/26 00:49:57
add comment explaining what's going on here.
ikilpatrick
2017/01/26 00:49:58
TODO(glebl): handle minLogicalHeight, maxLogicalHe
Gleb Lanbin
2017/01/31 00:25:01
Done.
Gleb Lanbin
2017/01/31 00:25:01
Done.
| |
434 curr_margin_strut_ = NGMarginStrut(); | |
435 } | |
436 builder_->SetEndMarginStrut(curr_margin_strut_); | |
437 | |
313 builder_->SetInlineOverflow(max_inline_size_).SetBlockOverflow(content_size_); | 438 builder_->SetInlineOverflow(max_inline_size_).SetBlockOverflow(content_size_); |
314 | 439 |
315 if (ConstraintSpace().HasBlockFragmentation()) | 440 if (ConstraintSpace().HasBlockFragmentation()) |
316 FinalizeForFragmentation(); | 441 FinalizeForFragmentation(); |
317 | 442 |
318 NGPhysicalFragment* fragment = builder_->ToBoxFragment(); | 443 NGPhysicalFragment* fragment = builder_->ToBoxFragment(); |
319 | 444 |
320 return fragment; | 445 return fragment; |
321 } | 446 } |
322 | 447 |
323 void NGBlockLayoutAlgorithm::FinishCurrentChildLayout(NGFragment* fragment) { | 448 void NGBlockLayoutAlgorithm::FinishCurrentChildLayout( |
324 NGBoxStrut child_margins = ComputeMargins( | 449 NGFragment* base_fragment) { |
325 *space_for_current_child_, CurrentChildStyle(), | 450 const NGBoxFragment& fragment = *toNGBoxFragment(base_fragment); |
326 constraint_space_->WritingMode(), constraint_space_->Direction()); | 451 // Pull out unpositioned floats to the current fragment. This may needed if |
327 NGLogicalOffset fragment_offset; | 452 // for example the child fragment could not position its floats because it's |
453 // empty and therefore couldn't determine its position in space. | |
454 builder_->MutableUnpositionedFloats().appendVector( | |
455 fragment.PhysicalFragment()->UnpositionedFloats()); | |
456 | |
328 if (CurrentChildStyle().isFloating()) { | 457 if (CurrentChildStyle().isFloating()) { |
329 fragment_offset = PositionFloatFragment(*fragment, child_margins); | 458 NGFloatingObject* floating_object = new NGFloatingObject( |
330 } else { | 459 fragment.PhysicalFragment(), space_for_current_child_, current_child_, |
331 ApplyAutoMargins(*space_for_current_child_, CurrentChildStyle(), | 460 CurrentChildStyle(), curr_child_margins_); |
332 fragment->InlineSize(), &child_margins); | 461 builder_->AddUnpositionedFloat(floating_object); |
333 fragment_offset = PositionFragment(*fragment, child_margins); | 462 // No need to postpone the positioning as we know the correct offset. |
463 if (builder_->BfcOffset()) { | |
464 NGLogicalOffset origin_point = curr_bfc_offset_; | |
465 // Adjust origin point to the margins of the last child. | |
466 // Example: <div style="margin-bottom: 20px"><float></div> | |
467 // <div style="margin-bottom: 30px"></div> | |
468 origin_point.block_offset += curr_margin_strut_.Collapse(); | |
469 PositionFloats(origin_point, builder_); | |
470 } | |
471 return; | |
334 } | 472 } |
473 | |
474 // Collapse empty block's margins. | |
475 if (!fragment.BlockSize()) { | |
476 curr_margin_strut_.Append(curr_child_margins_.block_end); | |
477 } | |
478 | |
479 NGLogicalOffset fragment_offset = { | |
480 border_and_padding_.inline_start + curr_child_margins_.inline_start, | |
481 content_size_}; | |
482 if (fragment.BfcOffset()) | |
483 fragment_offset = | |
484 PositionFragmentWithKnownBfcOffset(fragment.BfcOffset().value()); | |
485 | |
335 if (fragmentainer_mapper_) | 486 if (fragmentainer_mapper_) |
336 fragmentainer_mapper_->ToVisualOffset(fragment_offset); | 487 fragmentainer_mapper_->ToVisualOffset(fragment_offset); |
337 else | 488 else |
338 fragment_offset.block_offset -= PreviousBreakOffset(); | 489 fragment_offset.block_offset -= PreviousBreakOffset(); |
339 builder_->AddChild(fragment, fragment_offset); | 490 |
491 builder_->AddChild(base_fragment, fragment_offset); | |
492 | |
493 // Update margin strut. | |
494 curr_margin_strut_ = fragment.EndMarginStrut(); | |
495 curr_margin_strut_.Append(curr_child_margins_.block_end); | |
496 | |
497 content_size_ = fragment.BlockSize() + fragment_offset.block_offset; | |
498 max_inline_size_ = | |
499 std::max(max_inline_size_, fragment.InlineSize() + | |
500 curr_child_margins_.InlineSum() + | |
501 border_and_padding_.InlineSum()); | |
340 } | 502 } |
341 | 503 |
342 void NGBlockLayoutAlgorithm::LayoutOutOfFlowChildren() { | 504 void NGBlockLayoutAlgorithm::LayoutOutOfFlowChildren() { |
343 HeapLinkedHashSet<WeakMember<NGBlockNode>> out_of_flow_candidates; | 505 HeapLinkedHashSet<WeakMember<NGBlockNode>> out_of_flow_candidates; |
344 Vector<NGStaticPosition> out_of_flow_candidate_positions; | 506 Vector<NGStaticPosition> out_of_flow_candidate_positions; |
345 builder_->GetAndClearOutOfFlowDescendantCandidates( | 507 builder_->GetAndClearOutOfFlowDescendantCandidates( |
346 &out_of_flow_candidates, &out_of_flow_candidate_positions); | 508 &out_of_flow_candidates, &out_of_flow_candidate_positions); |
347 | 509 |
348 Member<NGOutOfFlowLayoutPart> out_of_flow_layout = | 510 Member<NGOutOfFlowLayoutPart> out_of_flow_layout = |
349 new NGOutOfFlowLayoutPart(&Style(), builder_->Size()); | 511 new NGOutOfFlowLayoutPart(&Style(), builder_->Size()); |
(...skipping 148 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
498 if (fragmentainer_mapper_) | 660 if (fragmentainer_mapper_) |
499 space_left = fragmentainer_mapper_->BlockSize(); | 661 space_left = fragmentainer_mapper_->BlockSize(); |
500 else if (ConstraintSpace().HasBlockFragmentation()) | 662 else if (ConstraintSpace().HasBlockFragmentation()) |
501 space_left = ConstraintSpace().FragmentainerSpaceAvailable(); | 663 space_left = ConstraintSpace().FragmentainerSpaceAvailable(); |
502 else | 664 else |
503 return NGSizeIndefinite; | 665 return NGSizeIndefinite; |
504 space_left -= BorderEdgeForCurrentChild() - PreviousBreakOffset(); | 666 space_left -= BorderEdgeForCurrentChild() - PreviousBreakOffset(); |
505 return space_left; | 667 return space_left; |
506 } | 668 } |
507 | 669 |
508 NGBoxStrut NGBlockLayoutAlgorithm::CollapseMargins( | |
509 const NGBoxStrut& margins, | |
510 const NGBoxFragment& fragment) { | |
511 bool is_zero_height_box = !fragment.BlockSize() && margins.IsEmpty() && | |
512 fragment.MarginStrut().IsEmpty(); | |
513 // Create the current child's margin strut from its children's margin strut or | |
514 // use margin strut from the the last non-empty child. | |
515 NGDeprecatedMarginStrut curr_margin_strut = | |
516 is_zero_height_box ? prev_child_margin_strut_ : fragment.MarginStrut(); | |
517 | |
518 // Calculate borders and padding for the current child. | |
519 NGBoxStrut border_and_padding = | |
520 ComputeBorders(CurrentChildStyle()) + | |
521 ComputePadding(ConstraintSpace(), CurrentChildStyle()); | |
522 | |
523 // Collapse BLOCK-START margins if there is no padding or border between | |
524 // parent (current child) and its first in-flow child. | |
525 if (border_and_padding.block_start) { | |
526 curr_margin_strut.SetMarginBlockStart(margins.block_start); | |
527 } else { | |
528 curr_margin_strut.AppendMarginBlockStart(margins.block_start); | |
529 } | |
530 | |
531 // Collapse BLOCK-END margins if | |
532 // 1) there is no padding or border between parent (current child) and its | |
533 // first/last in-flow child | |
534 // 2) parent's logical height is auto. | |
535 if (CurrentChildStyle().logicalHeight().isAuto() && | |
536 !border_and_padding.block_end) { | |
537 curr_margin_strut.AppendMarginBlockEnd(margins.block_end); | |
538 } else { | |
539 curr_margin_strut.SetMarginBlockEnd(margins.block_end); | |
540 } | |
541 | |
542 NGBoxStrut result_margins; | |
543 // Margins of the newly established formatting context do not participate | |
544 // in Collapsing Margins: | |
545 // - Compute margins block start for adjoining blocks *including* 1st block. | |
546 // - Compute margins block end for the last block. | |
547 // - Do not set the computed margins to the parent fragment. | |
548 if (constraint_space_->IsNewFormattingContext()) { | |
549 result_margins.block_start = ComputeCollapsedMarginBlockStart( | |
550 prev_child_margin_strut_, curr_margin_strut); | |
551 bool is_last_child = !current_child_->NextSibling(); | |
552 if (is_last_child) | |
553 result_margins.block_end = curr_margin_strut.BlockEndSum(); | |
554 return result_margins; | |
555 } | |
556 | |
557 // Zero-height boxes are ignored and do not participate in margin collapsing. | |
558 if (is_zero_height_box) | |
559 return result_margins; | |
560 | |
561 // Compute the margin block start for adjoining blocks *excluding* 1st block | |
562 if (is_fragment_margin_strut_block_start_updated_) { | |
563 result_margins.block_start = ComputeCollapsedMarginBlockStart( | |
564 prev_child_margin_strut_, curr_margin_strut); | |
565 } | |
566 | |
567 // Update the parent fragment's margin strut | |
568 UpdateMarginStrut(curr_margin_strut); | |
569 | |
570 prev_child_margin_strut_ = curr_margin_strut; | |
571 return result_margins; | |
572 } | |
573 | |
574 NGLogicalOffset NGBlockLayoutAlgorithm::PositionFragment( | |
575 const NGFragment& fragment, | |
576 const NGBoxStrut& margins) { | |
577 const NGBoxStrut collapsed_margins = | |
578 CollapseMargins(margins, toNGBoxFragment(fragment)); | |
579 | |
580 AdjustToClearance(ConstraintSpace(), CurrentChildStyle(), &content_size_); | |
581 | |
582 LayoutUnit inline_offset = | |
583 border_and_padding_.inline_start + margins.inline_start; | |
584 LayoutUnit block_offset = content_size_ + collapsed_margins.block_start; | |
585 | |
586 content_size_ += fragment.BlockSize() + collapsed_margins.BlockSum(); | |
587 max_inline_size_ = | |
588 std::max(max_inline_size_, fragment.InlineSize() + margins.InlineSum() + | |
589 border_and_padding_.InlineSum()); | |
590 return NGLogicalOffset(inline_offset, block_offset); | |
591 } | |
592 | |
593 NGLogicalOffset NGBlockLayoutAlgorithm::PositionFloatFragment( | |
594 const NGFragment& fragment, | |
595 const NGBoxStrut& margins) { | |
596 // TODO(glebl@chromium.org): Support the top edge alignment rule. | |
597 // Find a layout opportunity that will fit our float. | |
598 | |
599 // Update offset if there is a clearance. | |
600 NGLogicalOffset offset = CurrentChildConstraintSpace().Offset(); | |
601 AdjustToClearance(ConstraintSpace(), CurrentChildStyle(), | |
602 &offset.block_offset); | |
603 space_for_current_child_->SetOffset(offset); | |
604 | |
605 const NGLayoutOpportunity opportunity = FindLayoutOpportunityForFragment( | |
606 space_for_current_child_, fragment, margins); | |
607 DCHECK(!opportunity.IsEmpty()) << "Opportunity is empty but it shouldn't be"; | |
608 | |
609 NGExclusion::Type exclusion_type = NGExclusion::kFloatLeft; | |
610 // Calculate the float offset if needed. | |
611 LayoutUnit float_offset; | |
612 if (CurrentChildStyle().floating() == EFloat::kRight) { | |
613 float_offset = opportunity.size.inline_size - fragment.InlineSize(); | |
614 exclusion_type = NGExclusion::kFloatRight; | |
615 } | |
616 | |
617 // Add the float as an exclusion. | |
618 const NGExclusion exclusion = CreateExclusion( | |
619 fragment, opportunity, float_offset, margins, exclusion_type); | |
620 constraint_space_->AddExclusion(exclusion); | |
621 | |
622 return CalculateLogicalOffsetForOpportunity(opportunity, float_offset, | |
623 margins); | |
624 } | |
625 | |
626 void NGBlockLayoutAlgorithm::UpdateMarginStrut( | |
627 const NGDeprecatedMarginStrut& from) { | |
628 if (!is_fragment_margin_strut_block_start_updated_) { | |
629 builder_->SetMarginStrutBlockStart(from); | |
630 is_fragment_margin_strut_block_start_updated_ = true; | |
631 } | |
632 builder_->SetMarginStrutBlockEnd(from); | |
633 } | |
634 | |
635 NGBoxStrut NGBlockLayoutAlgorithm::CalculateMargins( | 670 NGBoxStrut NGBlockLayoutAlgorithm::CalculateMargins( |
636 const NGConstraintSpace& space, | 671 const NGConstraintSpace& space, |
637 const ComputedStyle& style) { | 672 const ComputedStyle& style) { |
638 WTF::Optional<MinAndMaxContentSizes> sizes; | 673 WTF::Optional<MinAndMaxContentSizes> sizes; |
639 if (NeedMinAndMaxContentSizes(space, style)) { | 674 if (NeedMinAndMaxContentSizes(space, style)) { |
640 // TODO(ikilpatrick): Change ComputeMinAndMaxContentSizes to return | 675 // TODO(ikilpatrick): Change ComputeMinAndMaxContentSizes to return |
641 // MinAndMaxContentSizes. | 676 // MinAndMaxContentSizes. |
642 sizes = current_child_->ComputeMinAndMaxContentSizesSync(); | 677 sizes = current_child_->ComputeMinAndMaxContentSizesSync(); |
643 } | 678 } |
644 LayoutUnit child_inline_size = | 679 LayoutUnit child_inline_size = |
645 ComputeInlineSizeForFragment(space, style, sizes); | 680 ComputeInlineSizeForFragment(space, style, sizes); |
646 NGBoxStrut margins = | 681 NGBoxStrut margins = |
647 ComputeMargins(space, style, space.WritingMode(), space.Direction()); | 682 ComputeMargins(space, style, space.WritingMode(), space.Direction()); |
648 if (!style.isFloating()) { | 683 if (!style.isFloating()) { |
649 ApplyAutoMargins(space, style, child_inline_size, &margins); | 684 ApplyAutoMargins(space, style, child_inline_size, &margins); |
650 } | 685 } |
651 return margins; | 686 return margins; |
652 } | 687 } |
653 | 688 |
654 NGConstraintSpace* | 689 NGConstraintSpace* |
655 NGBlockLayoutAlgorithm::CreateConstraintSpaceForCurrentChild() { | 690 NGBlockLayoutAlgorithm::CreateConstraintSpaceForCurrentChild() { |
656 // TODO(layout-ng): Orthogonal children should also shrink to fit (in *their* | 691 // TODO(layout-ng): Orthogonal children should also shrink to fit (in *their* |
657 // inline axis) | 692 // inline axis) |
658 // We have to keep this commented out for now until we correctly compute | 693 // We have to keep this commented out for now until we correctly compute |
659 // min/max content sizes in Layout(). | 694 // min/max content sizes in Layout(). |
660 bool shrink_to_fit = CurrentChildStyle().display() == EDisplay::InlineBlock || | 695 bool shrink_to_fit = CurrentChildStyle().display() == EDisplay::InlineBlock || |
661 CurrentChildStyle().isFloating(); | 696 CurrentChildStyle().isFloating(); |
662 DCHECK(current_child_); | 697 DCHECK(current_child_); |
663 space_builder_ | 698 bool is_new_bfc = IsNewFormattingContextForInFlowBlockLevelChild( |
664 ->SetIsNewFormattingContext( | 699 ConstraintSpace(), CurrentChildStyle()); |
665 IsNewFormattingContextForInFlowBlockLevelChild(ConstraintSpace(), | 700 space_builder_->SetIsNewFormattingContext(is_new_bfc) |
666 CurrentChildStyle())) | |
667 .SetIsShrinkToFit(shrink_to_fit) | 701 .SetIsShrinkToFit(shrink_to_fit) |
668 .SetWritingMode( | 702 .SetWritingMode( |
669 FromPlatformWritingMode(CurrentChildStyle().getWritingMode())) | 703 FromPlatformWritingMode(CurrentChildStyle().getWritingMode())) |
670 .SetTextDirection(CurrentChildStyle().direction()); | 704 .SetTextDirection(CurrentChildStyle().direction()); |
671 LayoutUnit space_available = SpaceAvailableForCurrentChild(); | 705 LayoutUnit space_available = SpaceAvailableForCurrentChild(); |
672 space_builder_->SetFragmentainerSpaceAvailable(space_available); | 706 space_builder_->SetFragmentainerSpaceAvailable(space_available); |
673 | 707 |
674 curr_child_margins_ = CalculateMargins(*space_builder_->ToConstraintSpace(), | 708 curr_child_margins_ = CalculateMargins(*space_builder_->ToConstraintSpace(), |
675 CurrentChildStyle()); | 709 CurrentChildStyle()); |
676 | 710 |
677 NGConstraintSpace* child_space = space_builder_->ToConstraintSpace(); | 711 // Clearance : |
712 // - Collapse margins | |
713 // - Update curr_bfc_offset and parent BFC offset if needed. | |
714 // - Position all pending floats as position is known now. | |
ikilpatrick
2017/01/26 04:37:25
maybe a note/todo that we don't think this will wo
Gleb Lanbin
2017/01/31 00:25:01
Done.
| |
715 if (CurrentChildStyle().clear()) { | |
716 curr_bfc_offset_.block_offset += curr_margin_strut_.Collapse(); | |
717 if (!builder_->BfcOffset()) { | |
718 builder_->SetBfcOffset(curr_bfc_offset_); | |
719 } | |
720 // Only collapse margins if it's an adjoining block with clearance. | |
721 if (!content_size_) { | |
722 curr_margin_strut_ = NGMarginStrut(); | |
723 curr_child_margins_.block_start = LayoutUnit(); | |
724 } | |
725 PositionFloats(curr_bfc_offset_, builder_); | |
726 AdjustToClearance(constraint_space_->Exclusions(), CurrentChildStyle(), | |
727 builder_->BfcOffset().value(), &content_size_); | |
728 } | |
678 | 729 |
679 // TODO(layout-ng): Set offset through the space builder. | 730 // Collapse the current margin strut with child's block start margin. |
ikilpatrick
2017/01/26 04:37:25
s/Collapse/Append? or maybe we should rename NGMar
Gleb Lanbin
2017/01/31 00:25:01
Done.
| |
680 child_space->SetOffset(GetChildSpaceOffset()); | 731 // non empty border/padding use cases are handled inside of the child's layout |
ikilpatrick
2017/01/26 04:37:26
.nit capital N, period.
Gleb Lanbin
2017/01/31 00:25:01
Done.
| |
681 return child_space; | 732 curr_margin_strut_.Append(curr_child_margins_.block_start); |
733 space_builder_->SetMarginStrut(curr_margin_strut_); | |
734 | |
735 // Set estimated BFC offset to the next child's constraint space. | |
736 curr_bfc_offset_ = builder_->BfcOffset() ? builder_->BfcOffset().value() | |
737 : ConstraintSpace().BfcOffset(); | |
738 curr_bfc_offset_.block_offset += content_size_; | |
739 curr_bfc_offset_.inline_offset += border_and_padding_.inline_start; | |
740 if (ConstraintSpace().IsNewFormattingContext()) { | |
741 curr_bfc_offset_.inline_offset += curr_child_margins_.inline_start; | |
742 } | |
743 space_builder_->SetBfcOffset(curr_bfc_offset_); | |
744 | |
745 return space_builder_->ToConstraintSpace(); | |
682 } | 746 } |
683 | 747 |
684 DEFINE_TRACE(NGBlockLayoutAlgorithm) { | 748 DEFINE_TRACE(NGBlockLayoutAlgorithm) { |
685 NGLayoutAlgorithm::trace(visitor); | 749 NGLayoutAlgorithm::trace(visitor); |
686 visitor->trace(first_child_); | 750 visitor->trace(first_child_); |
687 visitor->trace(constraint_space_); | 751 visitor->trace(constraint_space_); |
688 visitor->trace(break_token_); | 752 visitor->trace(break_token_); |
689 visitor->trace(builder_); | 753 visitor->trace(builder_); |
690 visitor->trace(space_builder_); | 754 visitor->trace(space_builder_); |
691 visitor->trace(space_for_current_child_); | 755 visitor->trace(space_for_current_child_); |
692 visitor->trace(current_child_); | 756 visitor->trace(current_child_); |
693 visitor->trace(fragmentainer_mapper_); | 757 visitor->trace(fragmentainer_mapper_); |
694 } | 758 } |
695 | 759 |
696 } // namespace blink | 760 } // namespace blink |
OLD | NEW |