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/inline/ng_inline_node.h" | 7 #include "core/layout/ng/inline/ng_inline_node.h" |
8 #include "core/layout/ng/ng_absolute_utils.h" | 8 #include "core/layout/ng/ng_absolute_utils.h" |
9 #include "core/layout/ng/ng_block_child_iterator.h" | 9 #include "core/layout/ng/ng_block_child_iterator.h" |
10 #include "core/layout/ng/ng_box_fragment.h" | 10 #include "core/layout/ng/ng_box_fragment.h" |
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
81 NGLogicalOffset mutable_offset(offset); | 81 NGLogicalOffset mutable_offset(offset); |
82 AdjustToClearance(space.ClearanceOffset(), &mutable_offset); | 82 AdjustToClearance(space.ClearanceOffset(), &mutable_offset); |
83 builder->SetBfcOffset(mutable_offset); | 83 builder->SetBfcOffset(mutable_offset); |
84 } | 84 } |
85 } | 85 } |
86 | 86 |
87 NGBlockLayoutAlgorithm::NGBlockLayoutAlgorithm(NGBlockNode* node, | 87 NGBlockLayoutAlgorithm::NGBlockLayoutAlgorithm(NGBlockNode* node, |
88 NGConstraintSpace* space, | 88 NGConstraintSpace* space, |
89 NGBlockBreakToken* break_token) | 89 NGBlockBreakToken* break_token) |
90 : NGLayoutAlgorithm(node, space, break_token), | 90 : NGLayoutAlgorithm(node, space, break_token), |
91 builder_(NGPhysicalFragment::kFragmentBox, node), | |
92 space_builder_(constraint_space_) {} | 91 space_builder_(constraint_space_) {} |
93 | 92 |
94 Optional<MinMaxContentSize> NGBlockLayoutAlgorithm::ComputeMinMaxContentSize() | 93 Optional<MinMaxContentSize> NGBlockLayoutAlgorithm::ComputeMinMaxContentSize() |
95 const { | 94 const { |
96 MinMaxContentSize sizes; | 95 MinMaxContentSize sizes; |
97 | 96 |
98 // Size-contained elements don't consider their contents for intrinsic sizing. | 97 // Size-contained elements don't consider their contents for intrinsic sizing. |
99 if (Style().ContainsSize()) | 98 if (Style().ContainsSize()) |
100 return sizes; | 99 return sizes; |
101 | 100 |
(...skipping 27 matching lines...) Expand all Loading... |
129 return sizes; | 128 return sizes; |
130 } | 129 } |
131 | 130 |
132 NGLogicalOffset NGBlockLayoutAlgorithm::CalculateLogicalOffset( | 131 NGLogicalOffset NGBlockLayoutAlgorithm::CalculateLogicalOffset( |
133 const WTF::Optional<NGLogicalOffset>& known_fragment_offset) { | 132 const WTF::Optional<NGLogicalOffset>& known_fragment_offset) { |
134 LayoutUnit inline_offset = | 133 LayoutUnit inline_offset = |
135 border_and_padding_.inline_start + curr_child_margins_.inline_start; | 134 border_and_padding_.inline_start + curr_child_margins_.inline_start; |
136 LayoutUnit block_offset = content_size_; | 135 LayoutUnit block_offset = content_size_; |
137 if (known_fragment_offset) { | 136 if (known_fragment_offset) { |
138 block_offset = known_fragment_offset.value().block_offset - | 137 block_offset = known_fragment_offset.value().block_offset - |
139 builder_.BfcOffset().value().block_offset; | 138 ContainerBfcOffset().block_offset; |
140 } | 139 } |
141 return {inline_offset, block_offset}; | 140 return {inline_offset, block_offset}; |
142 } | 141 } |
143 | 142 |
144 RefPtr<NGLayoutResult> NGBlockLayoutAlgorithm::Layout() { | 143 RefPtr<NGLayoutResult> NGBlockLayoutAlgorithm::Layout() { |
145 WTF::Optional<MinMaxContentSize> min_max_size; | 144 WTF::Optional<MinMaxContentSize> min_max_size; |
146 if (NeedMinMaxContentSize(ConstraintSpace(), Style())) | 145 if (NeedMinMaxContentSize(ConstraintSpace(), Style())) |
147 min_max_size = ComputeMinMaxContentSize(); | 146 min_max_size = ComputeMinMaxContentSize(); |
148 | 147 |
149 border_and_padding_ = ComputeBorders(ConstraintSpace(), Style()) + | 148 border_and_padding_ = ComputeBorders(ConstraintSpace(), Style()) + |
(...skipping 10 matching lines...) Expand all Loading... |
160 // borders and padding. | 159 // borders and padding. |
161 NGLogicalSize adjusted_size(size); | 160 NGLogicalSize adjusted_size(size); |
162 if (size.block_size == NGSizeIndefinite) | 161 if (size.block_size == NGSizeIndefinite) |
163 adjusted_size.inline_size -= border_and_padding_.InlineSum(); | 162 adjusted_size.inline_size -= border_and_padding_.InlineSum(); |
164 else | 163 else |
165 adjusted_size -= border_and_padding_; | 164 adjusted_size -= border_and_padding_; |
166 | 165 |
167 space_builder_.SetAvailableSize(adjusted_size) | 166 space_builder_.SetAvailableSize(adjusted_size) |
168 .SetPercentageResolutionSize(adjusted_size); | 167 .SetPercentageResolutionSize(adjusted_size); |
169 | 168 |
170 builder_.SetDirection(constraint_space_->Direction()); | 169 container_builder_.SetDirection(constraint_space_->Direction()); |
171 builder_.SetWritingMode(constraint_space_->WritingMode()); | 170 container_builder_.SetWritingMode(constraint_space_->WritingMode()); |
172 builder_.SetSize(size); | 171 container_builder_.SetSize(size); |
173 | 172 |
174 NGBlockChildIterator child_iterator(Node()->FirstChild(), BreakToken()); | 173 NGBlockChildIterator child_iterator(Node()->FirstChild(), BreakToken()); |
175 NGBlockChildIterator::Entry entry = child_iterator.NextChild(); | 174 NGBlockChildIterator::Entry entry = child_iterator.NextChild(); |
176 NGLayoutInputNode* child = entry.node; | 175 NGLayoutInputNode* child = entry.node; |
177 NGBreakToken* child_break_token = entry.token; | 176 NGBreakToken* child_break_token = entry.token; |
178 | 177 |
179 // If we are resuming from a break token our start border and padding is | 178 // If we are resuming from a break token our start border and padding is |
180 // within a previous fragment. | 179 // within a previous fragment. |
181 content_size_ = BreakToken() ? LayoutUnit() : border_and_padding_.block_start; | 180 content_size_ = BreakToken() ? LayoutUnit() : border_and_padding_.block_start; |
182 | 181 |
183 curr_margin_strut_ = ConstraintSpace().MarginStrut(); | 182 curr_margin_strut_ = ConstraintSpace().MarginStrut(); |
184 curr_bfc_offset_ = ConstraintSpace().BfcOffset(); | 183 curr_bfc_offset_ = ConstraintSpace().BfcOffset(); |
185 | 184 |
186 // Margins collapsing: | 185 // Margins collapsing: |
187 // Do not collapse margins between parent and its child if there is | 186 // Do not collapse margins between parent and its child if there is |
188 // border/padding between them. | 187 // border/padding between them. |
189 if (border_and_padding_.block_start) { | 188 if (border_and_padding_.block_start) { |
190 curr_bfc_offset_.block_offset += curr_margin_strut_.Sum(); | 189 curr_bfc_offset_.block_offset += curr_margin_strut_.Sum(); |
191 MaybeUpdateFragmentBfcOffset(ConstraintSpace(), curr_bfc_offset_, | 190 MaybeUpdateFragmentBfcOffset(ConstraintSpace(), curr_bfc_offset_, |
192 &builder_); | 191 &container_builder_); |
193 curr_margin_strut_ = NGMarginStrut(); | 192 curr_margin_strut_ = NGMarginStrut(); |
194 } | 193 } |
195 | 194 |
196 // If a new formatting context hits the if branch above then the BFC offset is | 195 // If a new formatting context hits the if branch above then the BFC offset is |
197 // still {} as the margin strut from the constraint space must also be empty. | 196 // still {} as the margin strut from the constraint space must also be empty. |
198 if (ConstraintSpace().IsNewFormattingContext()) { | 197 if (ConstraintSpace().IsNewFormattingContext()) { |
199 MaybeUpdateFragmentBfcOffset(ConstraintSpace(), curr_bfc_offset_, | 198 MaybeUpdateFragmentBfcOffset(ConstraintSpace(), curr_bfc_offset_, |
200 &builder_); | 199 &container_builder_); |
201 DCHECK_EQ(curr_margin_strut_, NGMarginStrut()); | 200 DCHECK_EQ(curr_margin_strut_, NGMarginStrut()); |
202 DCHECK_EQ(builder_.BfcOffset().value(), NGLogicalOffset()); | 201 DCHECK_EQ(container_builder_.BfcOffset().value(), NGLogicalOffset()); |
203 curr_bfc_offset_ = {}; | 202 curr_bfc_offset_ = {}; |
204 } | 203 } |
205 | 204 |
206 curr_bfc_offset_.block_offset += content_size_; | 205 curr_bfc_offset_.block_offset += content_size_; |
207 | 206 |
208 while (child) { | 207 while (child) { |
209 if (child->IsBlock()) { | 208 if (child->IsBlock()) { |
210 EPosition position = child->Style().GetPosition(); | 209 EPosition position = child->Style().GetPosition(); |
211 if (position == EPosition::kAbsolute || position == EPosition::kFixed) { | 210 if (position == EPosition::kAbsolute || position == EPosition::kFixed) { |
212 // TODO(ikilpatrick): curr_margin_strut_ shouldn't be included if there | 211 // TODO(ikilpatrick): curr_margin_strut_ shouldn't be included if there |
213 // is no content size yet? See floats-wrap-inside-inline-006. | 212 // is no content size yet? See floats-wrap-inside-inline-006. |
214 NGLogicalOffset offset = {border_and_padding_.inline_start, | 213 NGLogicalOffset offset = {border_and_padding_.inline_start, |
215 content_size_ + curr_margin_strut_.Sum()}; | 214 content_size_ + curr_margin_strut_.Sum()}; |
216 builder_.AddOutOfFlowChildCandidate(ToNGBlockNode(child), offset); | 215 container_builder_.AddOutOfFlowChildCandidate(ToNGBlockNode(child), |
| 216 offset); |
217 NGBlockChildIterator::Entry entry = child_iterator.NextChild(); | 217 NGBlockChildIterator::Entry entry = child_iterator.NextChild(); |
218 child = entry.node; | 218 child = entry.node; |
219 child_break_token = entry.token; | 219 child_break_token = entry.token; |
220 continue; | 220 continue; |
221 } | 221 } |
222 } | 222 } |
223 | 223 |
224 PrepareChildLayout(child); | 224 PrepareChildLayout(child); |
225 RefPtr<NGConstraintSpace> child_space = | 225 RefPtr<NGConstraintSpace> child_space = |
226 CreateConstraintSpaceForChild(child); | 226 CreateConstraintSpaceForChild(child); |
(...skipping 17 matching lines...) Expand all Loading... |
244 content_size_ += border_and_padding_.block_end; | 244 content_size_ += border_and_padding_.block_end; |
245 if (border_and_padding_.block_end || | 245 if (border_and_padding_.block_end || |
246 ConstraintSpace().IsNewFormattingContext()) { | 246 ConstraintSpace().IsNewFormattingContext()) { |
247 content_size_ += curr_margin_strut_.Sum(); | 247 content_size_ += curr_margin_strut_.Sum(); |
248 curr_margin_strut_ = NGMarginStrut(); | 248 curr_margin_strut_ = NGMarginStrut(); |
249 } | 249 } |
250 | 250 |
251 // Recompute the block-axis size now that we know our content size. | 251 // Recompute the block-axis size now that we know our content size. |
252 size.block_size = | 252 size.block_size = |
253 ComputeBlockSizeForFragment(ConstraintSpace(), Style(), content_size_); | 253 ComputeBlockSizeForFragment(ConstraintSpace(), Style(), content_size_); |
254 builder_.SetBlockSize(size.block_size); | 254 container_builder_.SetBlockSize(size.block_size); |
255 | 255 |
256 // Layout our absolute and fixed positioned children. | 256 // Layout our absolute and fixed positioned children. |
257 NGOutOfFlowLayoutPart(ConstraintSpace(), Style(), &builder_).Run(); | 257 NGOutOfFlowLayoutPart(ConstraintSpace(), Style(), &container_builder_).Run(); |
258 | 258 |
259 // Non-empty blocks always know their position in space: | 259 // Non-empty blocks always know their position in space: |
260 if (size.block_size) { | 260 if (size.block_size) { |
261 curr_bfc_offset_.block_offset += curr_margin_strut_.Sum(); | 261 curr_bfc_offset_.block_offset += curr_margin_strut_.Sum(); |
262 MaybeUpdateFragmentBfcOffset(ConstraintSpace(), curr_bfc_offset_, | 262 MaybeUpdateFragmentBfcOffset(ConstraintSpace(), curr_bfc_offset_, |
263 &builder_); | 263 &container_builder_); |
264 PositionPendingFloats(curr_bfc_offset_.block_offset, | 264 PositionPendingFloats(curr_bfc_offset_.block_offset, |
265 MutableConstraintSpace(), &builder_); | 265 MutableConstraintSpace(), &container_builder_); |
266 } | 266 } |
267 | 267 |
268 // Margins collapsing: | 268 // Margins collapsing: |
269 // Do not collapse margins between the last in-flow child and bottom margin | 269 // Do not collapse margins between the last in-flow child and bottom margin |
270 // of its parent if the parent has height != auto() | 270 // of its parent if the parent has height != auto() |
271 if (!Style().LogicalHeight().IsAuto()) { | 271 if (!Style().LogicalHeight().IsAuto()) { |
272 // TODO(glebl): handle minLogicalHeight, maxLogicalHeight. | 272 // TODO(glebl): handle minLogicalHeight, maxLogicalHeight. |
273 curr_margin_strut_ = NGMarginStrut(); | 273 curr_margin_strut_ = NGMarginStrut(); |
274 } | 274 } |
275 builder_.SetEndMarginStrut(curr_margin_strut_); | 275 container_builder_.SetEndMarginStrut(curr_margin_strut_); |
276 | 276 |
277 builder_.SetOverflowSize(NGLogicalSize(max_inline_size_, content_size_)); | 277 container_builder_.SetOverflowSize( |
| 278 NGLogicalSize(max_inline_size_, content_size_)); |
278 | 279 |
279 if (ConstraintSpace().HasBlockFragmentation()) | 280 if (ConstraintSpace().HasBlockFragmentation()) |
280 FinalizeForFragmentation(); | 281 FinalizeForFragmentation(); |
281 | 282 |
282 return builder_.ToBoxFragment(); | 283 return container_builder_.ToBoxFragment(); |
283 } | 284 } |
284 | 285 |
285 void NGBlockLayoutAlgorithm::PrepareChildLayout(NGLayoutInputNode* child) { | 286 void NGBlockLayoutAlgorithm::PrepareChildLayout(NGLayoutInputNode* child) { |
286 DCHECK(child); | 287 DCHECK(child); |
287 | 288 |
288 // Calculate margins in parent's writing mode. | 289 // Calculate margins in parent's writing mode. |
289 curr_child_margins_ = CalculateMargins( | 290 curr_child_margins_ = CalculateMargins( |
290 child, *space_builder_.ToConstraintSpace( | 291 child, *space_builder_.ToConstraintSpace( |
291 FromPlatformWritingMode(Style().GetWritingMode()))); | 292 FromPlatformWritingMode(Style().GetWritingMode()))); |
292 | 293 |
293 // Set estimated BFC offset to the next child's constraint space. | 294 // Set estimated BFC offset to the next child's constraint space. |
294 curr_bfc_offset_ = builder_.BfcOffset() ? builder_.BfcOffset().value() | 295 curr_bfc_offset_ = container_builder_.BfcOffset() |
295 : ConstraintSpace().BfcOffset(); | 296 ? container_builder_.BfcOffset().value() |
| 297 : ConstraintSpace().BfcOffset(); |
296 curr_bfc_offset_.block_offset += content_size_; | 298 curr_bfc_offset_.block_offset += content_size_; |
297 curr_bfc_offset_.inline_offset += border_and_padding_.inline_start; | 299 curr_bfc_offset_.inline_offset += border_and_padding_.inline_start; |
298 | 300 |
299 bool is_floating = child->IsBlock() && child->Style().IsFloating(); | 301 bool is_floating = child->IsBlock() && child->Style().IsFloating(); |
300 | 302 |
301 bool should_position_pending_floats = | 303 bool should_position_pending_floats = |
302 child->IsBlock() && !is_floating && | 304 child->IsBlock() && !is_floating && |
303 !IsNewFormattingContextForBlockLevelChild(Style(), *child) && | 305 !IsNewFormattingContextForBlockLevelChild(Style(), *child) && |
304 ClearanceMayAffectLayout(ConstraintSpace(), builder_.UnpositionedFloats(), | 306 ClearanceMayAffectLayout(ConstraintSpace(), |
| 307 container_builder_.UnpositionedFloats(), |
305 child->Style()); | 308 child->Style()); |
306 | 309 |
307 // Children which may clear a float need to force all the pending floats to | 310 // Children which may clear a float need to force all the pending floats to |
308 // be positioned before layout. This also resolves the fragment's bfc offset. | 311 // be positioned before layout. This also resolves the fragment's bfc offset. |
309 if (should_position_pending_floats) { | 312 if (should_position_pending_floats) { |
310 LayoutUnit origin_point_block_offset = | 313 LayoutUnit origin_point_block_offset = |
311 curr_bfc_offset_.block_offset + curr_margin_strut_.Sum(); | 314 curr_bfc_offset_.block_offset + curr_margin_strut_.Sum(); |
312 MaybeUpdateFragmentBfcOffset( | 315 MaybeUpdateFragmentBfcOffset( |
313 ConstraintSpace(), | 316 ConstraintSpace(), |
314 {curr_bfc_offset_.inline_offset, origin_point_block_offset}, &builder_); | 317 {curr_bfc_offset_.inline_offset, origin_point_block_offset}, |
| 318 &container_builder_); |
315 PositionPendingFloats(origin_point_block_offset, MutableConstraintSpace(), | 319 PositionPendingFloats(origin_point_block_offset, MutableConstraintSpace(), |
316 &builder_); | 320 &container_builder_); |
317 } | 321 } |
318 | 322 |
319 bool is_inflow = child->IsInline() || !is_floating; | 323 bool is_inflow = child->IsInline() || !is_floating; |
320 | 324 |
321 // Only inflow children (e.g. not floats) are included in the child's margin | 325 // Only inflow children (e.g. not floats) are included in the child's margin |
322 // strut as they do not participate in margin collapsing. | 326 // strut as they do not participate in margin collapsing. |
323 if (is_inflow) { | 327 if (is_inflow) { |
324 curr_bfc_offset_.inline_offset += curr_child_margins_.inline_start; | 328 curr_bfc_offset_.inline_offset += curr_child_margins_.inline_start; |
325 // Append the current margin strut with child's block start margin. | 329 // Append the current margin strut with child's block start margin. |
326 // Non empty border/padding use cases are handled inside of the child's | 330 // Non empty border/padding use cases are handled inside of the child's |
(...skipping 11 matching lines...) Expand all Loading... |
338 child->IsInline() || | 342 child->IsInline() || |
339 (!is_floating && | 343 (!is_floating && |
340 IsNewFormattingContextForBlockLevelChild(Style(), *child)); | 344 IsNewFormattingContextForBlockLevelChild(Style(), *child)); |
341 | 345 |
342 // Inline children or children which establish a block formatting context | 346 // Inline children or children which establish a block formatting context |
343 // collapse margins and position themselves immediately as they need to know | 347 // collapse margins and position themselves immediately as they need to know |
344 // their BFC offset for fragmentation purposes. | 348 // their BFC offset for fragmentation purposes. |
345 if (should_collapse_margins) { | 349 if (should_collapse_margins) { |
346 curr_bfc_offset_.block_offset += curr_margin_strut_.Sum(); | 350 curr_bfc_offset_.block_offset += curr_margin_strut_.Sum(); |
347 MaybeUpdateFragmentBfcOffset(ConstraintSpace(), curr_bfc_offset_, | 351 MaybeUpdateFragmentBfcOffset(ConstraintSpace(), curr_bfc_offset_, |
348 &builder_); | 352 &container_builder_); |
349 PositionPendingFloats(curr_bfc_offset_.block_offset, | 353 PositionPendingFloats(curr_bfc_offset_.block_offset, |
350 MutableConstraintSpace(), &builder_); | 354 MutableConstraintSpace(), &container_builder_); |
351 curr_margin_strut_ = {}; | 355 curr_margin_strut_ = {}; |
352 } | 356 } |
353 } | 357 } |
354 | 358 |
355 void NGBlockLayoutAlgorithm::FinishChildLayout( | 359 void NGBlockLayoutAlgorithm::FinishChildLayout( |
356 NGLayoutInputNode* child, | 360 NGLayoutInputNode* child, |
357 NGConstraintSpace* child_space, | 361 NGConstraintSpace* child_space, |
358 RefPtr<NGLayoutResult> layout_result) { | 362 RefPtr<NGLayoutResult> layout_result) { |
359 NGBoxFragment fragment( | 363 NGBoxFragment fragment( |
360 ConstraintSpace().WritingMode(), | 364 ConstraintSpace().WritingMode(), |
361 ToNGPhysicalBoxFragment(layout_result->PhysicalFragment().Get())); | 365 ToNGPhysicalBoxFragment(layout_result->PhysicalFragment().Get())); |
362 | 366 |
363 // Pull out unpositioned floats to the current fragment. This may needed if | 367 // Pull out unpositioned floats to the current fragment. This may needed if |
364 // for example the child fragment could not position its floats because it's | 368 // for example the child fragment could not position its floats because it's |
365 // empty and therefore couldn't determine its position in space. | 369 // empty and therefore couldn't determine its position in space. |
366 builder_.MutableUnpositionedFloats().AppendVector( | 370 container_builder_.MutableUnpositionedFloats().AppendVector( |
367 layout_result->UnpositionedFloats()); | 371 layout_result->UnpositionedFloats()); |
368 | 372 |
369 if (child->IsBlock() && child->Style().IsFloating()) { | 373 if (child->IsBlock() && child->Style().IsFloating()) { |
370 NGLogicalOffset origin_offset = constraint_space_->BfcOffset(); | 374 NGLogicalOffset origin_offset = constraint_space_->BfcOffset(); |
371 origin_offset.inline_offset += border_and_padding_.inline_start; | 375 origin_offset.inline_offset += border_and_padding_.inline_start; |
372 RefPtr<NGFloatingObject> floating_object = NGFloatingObject::Create( | 376 RefPtr<NGFloatingObject> floating_object = NGFloatingObject::Create( |
373 child->Style(), child_space->WritingMode(), | 377 child->Style(), child_space->WritingMode(), |
374 child_space->AvailableSize(), origin_offset, | 378 child_space->AvailableSize(), origin_offset, |
375 constraint_space_->BfcOffset(), curr_child_margins_, | 379 constraint_space_->BfcOffset(), curr_child_margins_, |
376 layout_result->PhysicalFragment().Get()); | 380 layout_result->PhysicalFragment().Get()); |
377 builder_.AddUnpositionedFloat(floating_object); | 381 container_builder_.AddUnpositionedFloat(floating_object); |
378 // No need to postpone the positioning if we know the correct offset. | 382 // No need to postpone the positioning if we know the correct offset. |
379 if (builder_.BfcOffset()) { | 383 if (container_builder_.BfcOffset()) { |
380 NGLogicalOffset origin_point = curr_bfc_offset_; | 384 NGLogicalOffset origin_point = curr_bfc_offset_; |
381 // Adjust origin point to the margins of the last child. | 385 // Adjust origin point to the margins of the last child. |
382 // Example: <div style="margin-bottom: 20px"><float></div> | 386 // Example: <div style="margin-bottom: 20px"><float></div> |
383 // <div style="margin-bottom: 30px"></div> | 387 // <div style="margin-bottom: 30px"></div> |
384 origin_point.block_offset += curr_margin_strut_.Sum(); | 388 origin_point.block_offset += curr_margin_strut_.Sum(); |
385 PositionPendingFloats(origin_point.block_offset, MutableConstraintSpace(), | 389 PositionPendingFloats(origin_point.block_offset, MutableConstraintSpace(), |
386 &builder_); | 390 &container_builder_); |
387 } | 391 } |
388 return; | 392 return; |
389 } | 393 } |
390 | 394 |
391 // Determine the fragment's position in the parent space either by using | 395 // Determine the fragment's position in the parent space either by using |
392 // content_size_ or known fragment's BFC offset. | 396 // content_size_ or known fragment's BFC offset. |
393 WTF::Optional<NGLogicalOffset> bfc_offset; | 397 WTF::Optional<NGLogicalOffset> bfc_offset; |
394 if (child_space->IsNewFormattingContext()) { | 398 if (child_space->IsNewFormattingContext()) { |
395 DCHECK(builder_.BfcOffset()); | |
396 bfc_offset = curr_bfc_offset_; | 399 bfc_offset = curr_bfc_offset_; |
397 } else if (fragment.BfcOffset()) { | 400 } else if (fragment.BfcOffset()) { |
398 // Fragment that knows its offset can be used to set parent's BFC position. | 401 // Fragment that knows its offset can be used to set parent's BFC position. |
399 curr_bfc_offset_.block_offset = fragment.BfcOffset().value().block_offset; | 402 curr_bfc_offset_.block_offset = fragment.BfcOffset().value().block_offset; |
400 MaybeUpdateFragmentBfcOffset(ConstraintSpace(), curr_bfc_offset_, | 403 MaybeUpdateFragmentBfcOffset(ConstraintSpace(), curr_bfc_offset_, |
401 &builder_); | 404 &container_builder_); |
402 PositionPendingFloats(curr_bfc_offset_.block_offset, | 405 PositionPendingFloats(curr_bfc_offset_.block_offset, |
403 MutableConstraintSpace(), &builder_); | 406 MutableConstraintSpace(), &container_builder_); |
404 bfc_offset = curr_bfc_offset_; | 407 bfc_offset = curr_bfc_offset_; |
405 } else if (builder_.BfcOffset()) { | 408 } else if (container_builder_.BfcOffset()) { |
406 // Fragment doesn't know its offset but we can still calculate its BFC | 409 // Fragment doesn't know its offset but we can still calculate its BFC |
407 // position because the parent fragment's BFC is known. | 410 // position because the parent fragment's BFC is known. |
408 // Example: | 411 // Example: |
409 // BFC Offset is known here because of the padding. | 412 // BFC Offset is known here because of the padding. |
410 // <div style="padding: 1px"> | 413 // <div style="padding: 1px"> |
411 // <div id="empty-div" style="margins: 1px"></div> | 414 // <div id="empty-div" style="margins: 1px"></div> |
412 bfc_offset = curr_bfc_offset_; | 415 bfc_offset = curr_bfc_offset_; |
413 bfc_offset.value().block_offset += curr_margin_strut_.Sum(); | 416 bfc_offset.value().block_offset += curr_margin_strut_.Sum(); |
414 } | 417 } |
415 NGLogicalOffset logical_offset = CalculateLogicalOffset(bfc_offset); | 418 NGLogicalOffset logical_offset = CalculateLogicalOffset(bfc_offset); |
416 | 419 |
417 // Update margin strut. | 420 // Update margin strut. |
418 curr_margin_strut_ = fragment.EndMarginStrut(); | 421 curr_margin_strut_ = fragment.EndMarginStrut(); |
419 curr_margin_strut_.Append(curr_child_margins_.block_end); | 422 curr_margin_strut_.Append(curr_child_margins_.block_end); |
420 | 423 |
421 // Only modify content_size if BlockSize is not empty. It's needed to prevent | 424 // Only modify content_size if BlockSize is not empty. It's needed to prevent |
422 // the situation when logical_offset is included in content_size for empty | 425 // the situation when logical_offset is included in content_size for empty |
423 // blocks. Example: | 426 // blocks. Example: |
424 // <div style="overflow:hidden"> | 427 // <div style="overflow:hidden"> |
425 // <div style="margin-top: 8px"></div> | 428 // <div style="margin-top: 8px"></div> |
426 // <div style="margin-top: 10px"></div> | 429 // <div style="margin-top: 10px"></div> |
427 // </div> | 430 // </div> |
428 if (fragment.BlockSize()) | 431 if (fragment.BlockSize()) |
429 content_size_ = fragment.BlockSize() + logical_offset.block_offset; | 432 content_size_ = fragment.BlockSize() + logical_offset.block_offset; |
430 max_inline_size_ = | 433 max_inline_size_ = |
431 std::max(max_inline_size_, fragment.InlineSize() + | 434 std::max(max_inline_size_, fragment.InlineSize() + |
432 curr_child_margins_.InlineSum() + | 435 curr_child_margins_.InlineSum() + |
433 border_and_padding_.InlineSum()); | 436 border_and_padding_.InlineSum()); |
434 | 437 |
435 builder_.AddChild(layout_result, logical_offset); | 438 container_builder_.AddChild(layout_result, logical_offset); |
436 } | 439 } |
437 | 440 |
438 void NGBlockLayoutAlgorithm::FinalizeForFragmentation() { | 441 void NGBlockLayoutAlgorithm::FinalizeForFragmentation() { |
439 LayoutUnit used_block_size = | 442 LayoutUnit used_block_size = |
440 BreakToken() ? BreakToken()->UsedBlockSize() : LayoutUnit(); | 443 BreakToken() ? BreakToken()->UsedBlockSize() : LayoutUnit(); |
441 LayoutUnit block_size = ComputeBlockSizeForFragment( | 444 LayoutUnit block_size = ComputeBlockSizeForFragment( |
442 ConstraintSpace(), Style(), used_block_size + content_size_); | 445 ConstraintSpace(), Style(), used_block_size + content_size_); |
443 | 446 |
444 block_size -= used_block_size; | 447 block_size -= used_block_size; |
445 DCHECK_GE(block_size, LayoutUnit()) | 448 DCHECK_GE(block_size, LayoutUnit()) |
446 << "Adding and subtracting the used_block_size shouldn't leave the " | 449 << "Adding and subtracting the used_block_size shouldn't leave the " |
447 "block_size for this fragment smaller than zero."; | 450 "block_size for this fragment smaller than zero."; |
448 | 451 |
449 DCHECK(builder_.BfcOffset()) << "We must have our BfcOffset by this point " | |
450 "to determine the space left in the flow."; | |
451 LayoutUnit space_left = ConstraintSpace().FragmentainerSpaceAvailable() - | 452 LayoutUnit space_left = ConstraintSpace().FragmentainerSpaceAvailable() - |
452 builder_.BfcOffset().value().block_offset; | 453 ContainerBfcOffset().block_offset; |
453 DCHECK_GE(space_left, LayoutUnit()); | 454 DCHECK_GE(space_left, LayoutUnit()); |
454 | 455 |
455 if (builder_.DidBreak()) { | 456 if (container_builder_.DidBreak()) { |
456 // One of our children broke. Even if we fit within the remaining space we | 457 // One of our children broke. Even if we fit within the remaining space we |
457 // need to prepare a break token. | 458 // need to prepare a break token. |
458 builder_.SetUsedBlockSize(std::min(space_left, block_size) + | 459 container_builder_.SetUsedBlockSize(std::min(space_left, block_size) + |
459 used_block_size); | 460 used_block_size); |
460 builder_.SetBlockSize(std::min(space_left, block_size)); | 461 container_builder_.SetBlockSize(std::min(space_left, block_size)); |
461 builder_.SetBlockOverflow(space_left); | 462 container_builder_.SetBlockOverflow(space_left); |
462 return; | 463 return; |
463 } | 464 } |
464 | 465 |
465 if (block_size > space_left) { | 466 if (block_size > space_left) { |
466 // Need a break inside this block. | 467 // Need a break inside this block. |
467 builder_.SetUsedBlockSize(space_left + used_block_size); | 468 container_builder_.SetUsedBlockSize(space_left + used_block_size); |
468 builder_.SetBlockSize(space_left); | 469 container_builder_.SetBlockSize(space_left); |
469 builder_.SetBlockOverflow(space_left); | 470 container_builder_.SetBlockOverflow(space_left); |
470 return; | 471 return; |
471 } | 472 } |
472 | 473 |
473 // The end of the block fits in the current fragmentainer. | 474 // The end of the block fits in the current fragmentainer. |
474 builder_.SetBlockSize(block_size); | 475 container_builder_.SetBlockSize(block_size); |
475 builder_.SetBlockOverflow(content_size_); | 476 container_builder_.SetBlockOverflow(content_size_); |
476 } | 477 } |
477 | 478 |
478 NGBoxStrut NGBlockLayoutAlgorithm::CalculateMargins( | 479 NGBoxStrut NGBlockLayoutAlgorithm::CalculateMargins( |
479 NGLayoutInputNode* child, | 480 NGLayoutInputNode* child, |
480 const NGConstraintSpace& space) { | 481 const NGConstraintSpace& space) { |
481 DCHECK(child); | 482 DCHECK(child); |
482 const ComputedStyle& child_style = child->Style(); | 483 const ComputedStyle& child_style = child->Style(); |
483 | 484 |
484 WTF::Optional<MinMaxContentSize> sizes; | 485 WTF::Optional<MinMaxContentSize> sizes; |
485 if (NeedMinMaxContentSize(space, child_style)) | 486 if (NeedMinMaxContentSize(space, child_style)) |
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
524 space_builder_.SetMarginStrut(child_style.IsFloating() ? NGMarginStrut() | 525 space_builder_.SetMarginStrut(child_style.IsFloating() ? NGMarginStrut() |
525 : curr_margin_strut_); | 526 : curr_margin_strut_); |
526 | 527 |
527 LayoutUnit space_available; | 528 LayoutUnit space_available; |
528 if (constraint_space_->HasBlockFragmentation()) { | 529 if (constraint_space_->HasBlockFragmentation()) { |
529 space_available = ConstraintSpace().FragmentainerSpaceAvailable(); | 530 space_available = ConstraintSpace().FragmentainerSpaceAvailable(); |
530 // If a block establishes a new formatting context we must know our | 531 // If a block establishes a new formatting context we must know our |
531 // position in the formatting context, and are able to adjust the | 532 // position in the formatting context, and are able to adjust the |
532 // fragmentation line. | 533 // fragmentation line. |
533 if (is_new_bfc) { | 534 if (is_new_bfc) { |
534 DCHECK(builder_.BfcOffset()); | |
535 space_available -= curr_bfc_offset_.block_offset; | 535 space_available -= curr_bfc_offset_.block_offset; |
536 } | 536 } |
537 } | 537 } |
538 space_builder_.SetFragmentainerSpaceAvailable(space_available); | 538 space_builder_.SetFragmentainerSpaceAvailable(space_available); |
539 | 539 |
540 return space_builder_.ToConstraintSpace( | 540 return space_builder_.ToConstraintSpace( |
541 FromPlatformWritingMode(child_style.GetWritingMode())); | 541 FromPlatformWritingMode(child_style.GetWritingMode())); |
542 } | 542 } |
543 } // namespace blink | 543 } // namespace blink |
OLD | NEW |