Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(2)

Side by Side Diff: third_party/WebKit/Source/core/layout/ng/ng_block_layout_algorithm.cc

Issue 2954953002: [LayoutNG] Abort a layout once the BFC offset is resolved. (Closed)
Patch Set: rebase. Created 3 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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_constraint_space.h" 10 #include "core/layout/ng/ng_constraint_space.h"
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after
54 return false; 54 return false;
55 } 55 }
56 56
57 // Whether we've run out of space in this flow. If so, there will be no work 57 // Whether we've run out of space in this flow. If so, there will be no work
58 // left to do for this block in this fragmentainer. 58 // left to do for this block in this fragmentainer.
59 bool IsOutOfSpace(const NGConstraintSpace& space, LayoutUnit content_size) { 59 bool IsOutOfSpace(const NGConstraintSpace& space, LayoutUnit content_size) {
60 return space.HasBlockFragmentation() && 60 return space.HasBlockFragmentation() &&
61 content_size >= space.FragmentainerSpaceAvailable(); 61 content_size >= space.FragmentainerSpaceAvailable();
62 } 62 }
63 63
64 bool IsEmptyFragment(NGWritingMode writing_mode,
65 const NGLayoutResult& layout_result) {
66 if (!layout_result.PhysicalFragment())
67 return true;
68
69 NGFragment fragment(writing_mode, layout_result.PhysicalFragment().Get());
70 if (!fragment.BlockSize())
71 return true;
72
73 return false;
74 }
75
64 } // namespace 76 } // namespace
65 77
66 // This struct is used for communicating to a child the position of the 78 bool MaybeUpdateFragmentBfcOffset(const NGConstraintSpace& space,
67 // previous inflow child.
68 struct NGPreviousInflowPosition {
69 LayoutUnit bfc_block_offset;
70 LayoutUnit logical_block_offset;
71 NGMarginStrut margin_strut;
72 };
73
74 // This strut holds information for the current inflow child. The data is not
75 // useful outside of handling this single inflow child.
76 struct NGInflowChildData {
77 NGLogicalOffset bfc_offset_estimate;
78 NGMarginStrut margin_strut;
79 NGBoxStrut margins;
80 };
81
82 void MaybeUpdateFragmentBfcOffset(const NGConstraintSpace& space,
83 LayoutUnit bfc_block_offset, 79 LayoutUnit bfc_block_offset,
84 NGFragmentBuilder* builder) { 80 NGFragmentBuilder* builder) {
85 DCHECK(builder); 81 DCHECK(builder);
86 if (!builder->BfcOffset()) { 82 if (!builder->BfcOffset()) {
87 NGLogicalOffset bfc_offset = {space.BfcOffset().inline_offset, 83 NGLogicalOffset bfc_offset = {space.BfcOffset().inline_offset,
88 bfc_block_offset}; 84 bfc_block_offset};
89 AdjustToClearance(space.ClearanceOffset(), &bfc_offset); 85 AdjustToClearance(space.ClearanceOffset(), &bfc_offset);
90 builder->SetBfcOffset(bfc_offset); 86 builder->SetBfcOffset(bfc_offset);
87 return true;
91 } 88 }
89
90 return false;
92 } 91 }
93 92
94 void PositionPendingFloats(LayoutUnit origin_block_offset, 93 void PositionPendingFloats(
95 NGFragmentBuilder* container_builder, 94 LayoutUnit origin_block_offset,
96 NGConstraintSpace* space) { 95 NGFragmentBuilder* container_builder,
97 DCHECK(container_builder->BfcOffset()) 96 Vector<RefPtr<NGUnpositionedFloat>>* unpositioned_floats,
97 NGConstraintSpace* space) {
98 DCHECK(container_builder->BfcOffset() || space->FloatsBfcOffset())
98 << "Parent BFC offset should be known here"; 99 << "Parent BFC offset should be known here";
100 LayoutUnit from_block_offset =
101 container_builder->BfcOffset()
102 ? container_builder->BfcOffset().value().block_offset
103 : space->FloatsBfcOffset().value().block_offset;
99 104
100 const auto& unpositioned_floats = container_builder->UnpositionedFloats();
101 const auto positioned_floats = PositionFloats( 105 const auto positioned_floats = PositionFloats(
102 origin_block_offset, container_builder->BfcOffset().value().block_offset, 106 origin_block_offset, from_block_offset, *unpositioned_floats, space);
103 unpositioned_floats, space);
104 107
105 for (const auto& positioned_float : positioned_floats) 108 for (const auto& positioned_float : positioned_floats)
106 container_builder->AddPositionedFloat(positioned_float); 109 container_builder->AddPositionedFloat(positioned_float);
107 110
108 container_builder->MutableUnpositionedFloats().clear(); 111 unpositioned_floats->clear();
109 } 112 }
110 113
111 NGBlockLayoutAlgorithm::NGBlockLayoutAlgorithm(NGBlockNode node, 114 NGBlockLayoutAlgorithm::NGBlockLayoutAlgorithm(NGBlockNode node,
112 NGConstraintSpace* space, 115 NGConstraintSpace* space,
113 NGBlockBreakToken* break_token) 116 NGBlockBreakToken* break_token)
114 : NGLayoutAlgorithm(node, space, break_token) {} 117 : NGLayoutAlgorithm(node, space, break_token) {}
115 118
116 Optional<MinMaxContentSize> NGBlockLayoutAlgorithm::ComputeMinMaxContentSize() 119 Optional<MinMaxContentSize> NGBlockLayoutAlgorithm::ComputeMinMaxContentSize()
117 const { 120 const {
118 MinMaxContentSize sizes; 121 MinMaxContentSize sizes;
(...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after
192 adjusted_size.block_size = std::max(adjusted_size.block_size, LayoutUnit()); 195 adjusted_size.block_size = std::max(adjusted_size.block_size, LayoutUnit());
193 } 196 }
194 adjusted_size.inline_size = std::max(adjusted_size.inline_size, LayoutUnit()); 197 adjusted_size.inline_size = std::max(adjusted_size.inline_size, LayoutUnit());
195 198
196 child_available_size_ = adjusted_size; 199 child_available_size_ = adjusted_size;
197 child_percentage_size_ = adjusted_size; 200 child_percentage_size_ = adjusted_size;
198 201
199 container_builder_.SetDirection(constraint_space_->Direction()); 202 container_builder_.SetDirection(constraint_space_->Direction());
200 container_builder_.SetWritingMode(constraint_space_->WritingMode()); 203 container_builder_.SetWritingMode(constraint_space_->WritingMode());
201 container_builder_.SetSize(size); 204 container_builder_.SetSize(size);
202 container_builder_.MutableUnpositionedFloats() = 205
203 constraint_space_->UnpositionedFloats(); 206 // If we have a list of unpositioned floats as input to this layout, we'll
207 // need to abort once our BFC offset is resolved. Additionally the
208 // FloatsBfcOffset() must not be present in this case.
209 unpositioned_floats_ = constraint_space_->UnpositionedFloats();
210 abort_when_bfc_resolved_ = !unpositioned_floats_.IsEmpty();
211 if (abort_when_bfc_resolved_)
212 DCHECK(!constraint_space_->FloatsBfcOffset());
204 213
205 NGBlockChildIterator child_iterator(Node().FirstChild(), BreakToken()); 214 NGBlockChildIterator child_iterator(Node().FirstChild(), BreakToken());
206 NGBlockChildIterator::Entry entry = child_iterator.NextChild(); 215 NGBlockChildIterator::Entry entry = child_iterator.NextChild();
207 NGLayoutInputNode child = entry.node; 216 NGLayoutInputNode child = entry.node;
208 NGBreakToken* child_break_token = entry.token; 217 NGBreakToken* child_break_token = entry.token;
209 218
210 // If we are resuming from a break token our start border and padding is 219 // If we are resuming from a break token our start border and padding is
211 // within a previous fragment. 220 // within a previous fragment.
212 content_size_ = 221 content_size_ =
213 BreakToken() ? LayoutUnit() : border_scrollbar_padding_.block_start; 222 BreakToken() ? LayoutUnit() : border_scrollbar_padding_.block_start;
214 223
215 NGMarginStrut input_margin_strut = ConstraintSpace().MarginStrut(); 224 NGMarginStrut input_margin_strut = ConstraintSpace().MarginStrut();
216 LayoutUnit input_bfc_block_offset = 225 LayoutUnit input_bfc_block_offset =
217 ConstraintSpace().BfcOffset().block_offset; 226 ConstraintSpace().BfcOffset().block_offset;
218 227
219 // Margins collapsing: 228 // Margins collapsing:
220 // Do not collapse margins between parent and its child if there is 229 // Do not collapse margins between parent and its child if there is
221 // border/padding between them. 230 // border/padding between them.
222 if (border_scrollbar_padding_.block_start) { 231 if (border_scrollbar_padding_.block_start) {
223 input_bfc_block_offset += input_margin_strut.Sum(); 232 input_bfc_block_offset += input_margin_strut.Sum();
224 MaybeUpdateFragmentBfcOffset(ConstraintSpace(), input_bfc_block_offset, 233 bool updated = MaybeUpdateFragmentBfcOffset(
225 &container_builder_); 234 ConstraintSpace(), input_bfc_block_offset, &container_builder_);
235
236 if (updated && abort_when_bfc_resolved_) {
237 container_builder_.SwapUnpositionedFloats(&unpositioned_floats_);
238 return container_builder_.Abort(NGLayoutResult::kBfcOffsetResolved);
239 }
240
226 // We reset the block offset here as it may have been effected by clearance. 241 // We reset the block offset here as it may have been effected by clearance.
227 input_bfc_block_offset = ContainerBfcOffset().block_offset; 242 input_bfc_block_offset = ContainerBfcOffset().block_offset;
228 input_margin_strut = NGMarginStrut(); 243 input_margin_strut = NGMarginStrut();
229 } 244 }
230 245
231 // If a new formatting context hits the margin collapsing if-branch above 246 // If a new formatting context hits the margin collapsing if-branch above
232 // then the BFC offset is still {} as the margin strut from the constraint 247 // then the BFC offset is still {} as the margin strut from the constraint
233 // space must also be empty. 248 // space must also be empty.
234 // If we are resuming layout from a break token the same rule applies. Margin 249 // If we are resuming layout from a break token the same rule applies. Margin
235 // struts cannot pass through break tokens. 250 // struts cannot pass through break tokens.
236 if (ConstraintSpace().IsNewFormattingContext() || BreakToken()) { 251 if (ConstraintSpace().IsNewFormattingContext() || BreakToken()) {
237 MaybeUpdateFragmentBfcOffset(ConstraintSpace(), input_bfc_block_offset, 252 MaybeUpdateFragmentBfcOffset(ConstraintSpace(), input_bfc_block_offset,
238 &container_builder_); 253 &container_builder_);
239 DCHECK_EQ(input_margin_strut, NGMarginStrut()); 254 DCHECK_EQ(input_margin_strut, NGMarginStrut());
240 DCHECK_EQ(container_builder_.BfcOffset().value(), NGLogicalOffset()); 255 DCHECK_EQ(container_builder_.BfcOffset().value(), NGLogicalOffset());
241 } 256 }
242 257
243 input_bfc_block_offset += content_size_; 258 input_bfc_block_offset += content_size_;
244 259
245 NGPreviousInflowPosition previous_inflow_position = { 260 WTF::Optional<NGPreviousInflowPosition> previous_inflow_position =
246 input_bfc_block_offset, content_size_, input_margin_strut}; 261 NGPreviousInflowPosition{input_bfc_block_offset, content_size_,
262 input_margin_strut};
247 263
248 while (child) { 264 while (child) {
249 if (child.IsOutOfFlowPositioned()) { 265 if (child.IsOutOfFlowPositioned()) {
250 DCHECK(!child_break_token); 266 DCHECK(!child_break_token);
251 HandleOutOfFlowPositioned(previous_inflow_position, ToNGBlockNode(child)); 267 HandleOutOfFlowPositioned(previous_inflow_position.value(),
268 ToNGBlockNode(child));
252 } else if (child.IsFloating()) { 269 } else if (child.IsFloating()) {
253 HandleFloating(previous_inflow_position, ToNGBlockNode(child), 270 HandleFloating(previous_inflow_position.value(), ToNGBlockNode(child),
254 ToNGBlockBreakToken(child_break_token)); 271 ToNGBlockBreakToken(child_break_token));
255 } else { 272 } else {
256 NGInflowChildData child_data = 273 // TODO(ikilpatrick): Refactor this else branch.
257 PrepareChildLayout(previous_inflow_position, child); 274 WTF::Optional<NGInflowChildData> child_data =
275 PrepareChildLayout(previous_inflow_position.value(), child);
276
277 // If PrepareChildLayout resolved our BFC offset, abort the layout.
278 if (!child_data) {
279 DCHECK(container_builder_.BfcOffset());
280 container_builder_.SwapUnpositionedFloats(&unpositioned_floats_);
281 return container_builder_.Abort(NGLayoutResult::kBfcOffsetResolved);
282 }
283
258 RefPtr<NGConstraintSpace> child_space = 284 RefPtr<NGConstraintSpace> child_space =
259 CreateConstraintSpaceForChild(child, child_data); 285 CreateConstraintSpaceForChild(child, child_data.value());
260 RefPtr<NGLayoutResult> layout_result = 286 RefPtr<NGLayoutResult> layout_result =
261 child.Layout(child_space.Get(), child_break_token); 287 child.Layout(child_space.Get(), child_break_token);
262 previous_inflow_position = 288
263 FinishChildLayout(*child_space, previous_inflow_position, child_data, 289 // A child may have aborted its layout if it resolved its BFC offset. If
264 child, layout_result.Get()); 290 // we don't have a BFC offset yet, we need to propagate the abortion up
291 // to our parent.
292 if (layout_result->Status() == NGLayoutResult::kBfcOffsetResolved &&
293 !container_builder_.BfcOffset()) {
294 MaybeUpdateFragmentBfcOffset(
295 ConstraintSpace(), layout_result->BfcOffset().value().block_offset,
296 &container_builder_);
297 container_builder_.SwapUnpositionedFloats(&unpositioned_floats_);
298 return container_builder_.Abort(NGLayoutResult::kBfcOffsetResolved);
299 }
300
301 previous_inflow_position = FinishChildLayout(
302 *child_space, previous_inflow_position.value(), child_data.value(),
303 child, child_break_token, std::move(layout_result));
304
305 // If FinishChildLayout resolved our BFC offset, abort the layout.
306 if (!previous_inflow_position) {
307 container_builder_.SwapUnpositionedFloats(&unpositioned_floats_);
308 return container_builder_.Abort(NGLayoutResult::kBfcOffsetResolved);
309 }
265 } 310 }
266 311
267 entry = child_iterator.NextChild(); 312 entry = child_iterator.NextChild();
268 child = entry.node; 313 child = entry.node;
269 child_break_token = entry.token; 314 child_break_token = entry.token;
270 315
271 if (IsOutOfSpace(ConstraintSpace(), content_size_)) 316 if (IsOutOfSpace(ConstraintSpace(), content_size_))
272 break; 317 break;
273 } 318 }
274 319
275 NGMarginStrut end_margin_strut = previous_inflow_position.margin_strut; 320 NGMarginStrut end_margin_strut = previous_inflow_position->margin_strut;
276 LayoutUnit end_bfc_block_offset = previous_inflow_position.bfc_block_offset; 321 LayoutUnit end_bfc_block_offset = previous_inflow_position->bfc_block_offset;
277 322
278 // Margins collapsing: 323 // Margins collapsing:
279 // Bottom margins of an in-flow block box doesn't collapse with its last 324 // Bottom margins of an in-flow block box doesn't collapse with its last
280 // in-flow block-level child's bottom margin if the box has bottom 325 // in-flow block-level child's bottom margin if the box has bottom
281 // border/padding. 326 // border/padding.
282 if (border_scrollbar_padding_.block_end || 327 if (border_scrollbar_padding_.block_end ||
283 ConstraintSpace().IsNewFormattingContext()) { 328 ConstraintSpace().IsNewFormattingContext()) {
284 content_size_ = 329 content_size_ =
285 std::max(content_size_, previous_inflow_position.logical_block_offset + 330 std::max(content_size_, previous_inflow_position->logical_block_offset +
286 end_margin_strut.Sum()); 331 end_margin_strut.Sum());
287 end_margin_strut = NGMarginStrut(); 332 end_margin_strut = NGMarginStrut();
288 } 333 }
289 334
290 // If the current layout is a new formatting context, we need to encapsulate 335 // If the current layout is a new formatting context, we need to encapsulate
291 // all of our floats. 336 // all of our floats.
292 if (ConstraintSpace().IsNewFormattingContext()) { 337 if (ConstraintSpace().IsNewFormattingContext()) {
293 // We can use the BFC coordinates, as we are a new formatting context. 338 // We can use the BFC coordinates, as we are a new formatting context.
294 DCHECK_EQ(container_builder_.BfcOffset().value(), NGLogicalOffset()); 339 DCHECK_EQ(container_builder_.BfcOffset().value(), NGLogicalOffset());
295 340
296 WTF::Optional<LayoutUnit> float_end_offset = 341 WTF::Optional<LayoutUnit> float_end_offset =
297 GetClearanceOffset(ConstraintSpace().Exclusions(), EClear::kBoth); 342 GetClearanceOffset(ConstraintSpace().Exclusions(), EClear::kBoth);
298 if (float_end_offset) 343 if (float_end_offset)
299 content_size_ = std::max(content_size_, float_end_offset.value()); 344 content_size_ = std::max(content_size_, float_end_offset.value());
300 } 345 }
301 346
302 content_size_ += border_scrollbar_padding_.block_end; 347 content_size_ += border_scrollbar_padding_.block_end;
303 348
304 // Recompute the block-axis size now that we know our content size. 349 // Recompute the block-axis size now that we know our content size.
305 size.block_size = 350 size.block_size =
306 ComputeBlockSizeForFragment(ConstraintSpace(), Style(), content_size_); 351 ComputeBlockSizeForFragment(ConstraintSpace(), Style(), content_size_);
307 container_builder_.SetBlockSize(size.block_size); 352 container_builder_.SetBlockSize(size.block_size);
308 353
309 // Layout our absolute and fixed positioned children.
310 NGOutOfFlowLayoutPart(ConstraintSpace(), Style(), &container_builder_).Run();
311
312 // Non-empty blocks always know their position in space. 354 // Non-empty blocks always know their position in space.
313 // TODO(ikilpatrick): This check for a break token seems error prone. 355 // TODO(ikilpatrick): This check for a break token seems error prone.
314 if (size.block_size || BreakToken()) { 356 if (size.block_size || BreakToken()) {
315 end_bfc_block_offset += end_margin_strut.Sum(); 357 end_bfc_block_offset += end_margin_strut.Sum();
316 MaybeUpdateFragmentBfcOffset(ConstraintSpace(), end_bfc_block_offset, 358 bool updated = MaybeUpdateFragmentBfcOffset(
317 &container_builder_); 359 ConstraintSpace(), end_bfc_block_offset, &container_builder_);
360
361 if (updated && abort_when_bfc_resolved_) {
362 container_builder_.SwapUnpositionedFloats(&unpositioned_floats_);
363 return container_builder_.Abort(NGLayoutResult::kBfcOffsetResolved);
364 }
365
318 PositionPendingFloats(end_bfc_block_offset, &container_builder_, 366 PositionPendingFloats(end_bfc_block_offset, &container_builder_,
319 MutableConstraintSpace()); 367 &unpositioned_floats_, MutableConstraintSpace());
320 } 368 }
321 369
322 // Margins collapsing: 370 // Margins collapsing:
323 // Do not collapse margins between the last in-flow child and bottom margin 371 // Do not collapse margins between the last in-flow child and bottom margin
324 // of its parent if the parent has height != auto() 372 // of its parent if the parent has height != auto()
325 if (!Style().LogicalHeight().IsAuto()) { 373 if (!Style().LogicalHeight().IsAuto()) {
326 // TODO(glebl): handle minLogicalHeight, maxLogicalHeight. 374 // TODO(glebl): handle minLogicalHeight, maxLogicalHeight.
327 end_margin_strut = NGMarginStrut(); 375 end_margin_strut = NGMarginStrut();
328 } 376 }
329 container_builder_.SetEndMarginStrut(end_margin_strut); 377 container_builder_.SetEndMarginStrut(end_margin_strut);
330 container_builder_.SetOverflowSize( 378 container_builder_.SetOverflowSize(
331 NGLogicalSize(max_inline_size_, content_size_)); 379 NGLogicalSize(max_inline_size_, content_size_));
332 380
333 // We only finalize for fragmentation if the fragment has a BFC offset. This 381 // We only finalize for fragmentation if the fragment has a BFC offset. This
334 // may occur with a zero block size fragment. We need to know the BFC offset 382 // may occur with a zero block size fragment. We need to know the BFC offset
335 // to determine where the fragmentation line is relative to us. 383 // to determine where the fragmentation line is relative to us.
336 if (container_builder_.BfcOffset() && 384 if (container_builder_.BfcOffset() &&
337 ConstraintSpace().HasBlockFragmentation()) 385 ConstraintSpace().HasBlockFragmentation())
338 FinalizeForFragmentation(); 386 FinalizeForFragmentation();
339 387
388 // Only layout absolute and fixed children if we aren't going to revisit this
389 // layout.
390 if (unpositioned_floats_.IsEmpty()) {
391 NGOutOfFlowLayoutPart(ConstraintSpace(), Style(), &container_builder_)
392 .Run();
393 }
394
395 // If we have any unpositioned floats at this stage, need to tell our parent
396 // about this, so that we get relayout with a forced BFC offset.
397 if (!unpositioned_floats_.IsEmpty()) {
398 DCHECK(!container_builder_.BfcOffset());
399 container_builder_.SwapUnpositionedFloats(&unpositioned_floats_);
400 }
401
340 PropagateBaselinesFromChildren(); 402 PropagateBaselinesFromChildren();
341 403
342 return container_builder_.ToBoxFragment(); 404 return container_builder_.ToBoxFragment();
343 } 405 }
344 406
345 void NGBlockLayoutAlgorithm::HandleOutOfFlowPositioned( 407 void NGBlockLayoutAlgorithm::HandleOutOfFlowPositioned(
346 const NGPreviousInflowPosition& previous_inflow_position, 408 const NGPreviousInflowPosition& previous_inflow_position,
347 NGBlockNode child) { 409 NGBlockNode child) {
348 // TODO(ikilpatrick): Determine which of the child's margins need to be 410 // TODO(ikilpatrick): Determine which of the child's margins need to be
349 // included for the static position. 411 // included for the static position.
(...skipping 15 matching lines...) Expand all
365 // Calculate margins in the BFC's writing mode. 427 // Calculate margins in the BFC's writing mode.
366 NGBoxStrut margins = CalculateMargins(child); 428 NGBoxStrut margins = CalculateMargins(child);
367 429
368 LayoutUnit origin_inline_offset = 430 LayoutUnit origin_inline_offset =
369 constraint_space_->BfcOffset().inline_offset + 431 constraint_space_->BfcOffset().inline_offset +
370 border_scrollbar_padding_.inline_start; 432 border_scrollbar_padding_.inline_start;
371 433
372 RefPtr<NGUnpositionedFloat> unpositioned_float = NGUnpositionedFloat::Create( 434 RefPtr<NGUnpositionedFloat> unpositioned_float = NGUnpositionedFloat::Create(
373 child_available_size_, child_percentage_size_, origin_inline_offset, 435 child_available_size_, child_percentage_size_, origin_inline_offset,
374 constraint_space_->BfcOffset().inline_offset, margins, child, token); 436 constraint_space_->BfcOffset().inline_offset, margins, child, token);
375 container_builder_.AddUnpositionedFloat(unpositioned_float); 437 unpositioned_floats_.push_back(std::move(unpositioned_float));
376 438
377 // If there is a break token for a float we must be resuming layout, we must 439 // If there is a break token for a float we must be resuming layout, we must
378 // always know our position in the BFC. 440 // always know our position in the BFC.
379 DCHECK(!token || container_builder_.BfcOffset()); 441 DCHECK(!token || container_builder_.BfcOffset());
380 442
381 // No need to postpone the positioning if we know the correct offset. 443 // No need to postpone the positioning if we know the correct offset.
382 if (container_builder_.BfcOffset()) { 444 if (container_builder_.BfcOffset() || ConstraintSpace().FloatsBfcOffset()) {
383 // Adjust origin point to the margins of the last child. 445 // Adjust origin point to the margins of the last child.
384 // Example: <div style="margin-bottom: 20px"><float></div> 446 // Example: <div style="margin-bottom: 20px"><float></div>
385 // <div style="margin-bottom: 30px"></div> 447 // <div style="margin-bottom: 30px"></div>
386 LayoutUnit origin_block_offset = 448 LayoutUnit origin_block_offset =
387 previous_inflow_position.bfc_block_offset + 449 container_builder_.BfcOffset()
388 previous_inflow_position.margin_strut.Sum(); 450 ? previous_inflow_position.bfc_block_offset +
451 previous_inflow_position.margin_strut.Sum()
452 : ConstraintSpace().FloatsBfcOffset().value().block_offset;
389 PositionPendingFloats(origin_block_offset, &container_builder_, 453 PositionPendingFloats(origin_block_offset, &container_builder_,
390 MutableConstraintSpace()); 454 &unpositioned_floats_, MutableConstraintSpace());
391 } 455 }
392 } 456 }
393 457
394 NGInflowChildData NGBlockLayoutAlgorithm::PrepareChildLayout( 458 WTF::Optional<NGInflowChildData> NGBlockLayoutAlgorithm::PrepareChildLayout(
395 const NGPreviousInflowPosition& previous_inflow_position, 459 const NGPreviousInflowPosition& previous_inflow_position,
396 NGLayoutInputNode child) { 460 NGLayoutInputNode child) {
397 DCHECK(child); 461 DCHECK(child);
398 DCHECK(!child.IsFloating()); 462 DCHECK(!child.IsFloating());
399 463
400 LayoutUnit bfc_block_offset = previous_inflow_position.bfc_block_offset; 464 LayoutUnit bfc_block_offset = previous_inflow_position.bfc_block_offset;
401 465
402 // Calculate margins in parent's writing mode. 466 // Calculate margins in parent's writing mode.
403 NGBoxStrut margins = CalculateMargins(child); 467 NGBoxStrut margins = CalculateMargins(child);
404 NGMarginStrut margin_strut = previous_inflow_position.margin_strut; 468 NGMarginStrut margin_strut = previous_inflow_position.margin_strut;
405 469
406 bool should_position_pending_floats = 470 bool should_position_pending_floats =
407 !child.CreatesNewFormattingContext() && 471 !child.CreatesNewFormattingContext() &&
408 ClearanceMayAffectLayout(ConstraintSpace(), 472 ClearanceMayAffectLayout(ConstraintSpace(), unpositioned_floats_,
409 container_builder_.UnpositionedFloats(),
410 child.Style()); 473 child.Style());
411 474
412 // Children which may clear a float need to force all the pending floats to 475 // Children which may clear a float need to force all the pending floats to
413 // be positioned before layout. This also resolves the fragment's bfc offset. 476 // be positioned before layout. This also resolves the fragment's bfc offset.
414 if (should_position_pending_floats) { 477 if (should_position_pending_floats) {
415 LayoutUnit origin_point_block_offset = 478 LayoutUnit origin_point_block_offset =
416 bfc_block_offset + margin_strut.Sum(); 479 bfc_block_offset + margin_strut.Sum();
417 MaybeUpdateFragmentBfcOffset(ConstraintSpace(), origin_point_block_offset, 480 bool updated = MaybeUpdateFragmentBfcOffset(
418 &container_builder_); 481 ConstraintSpace(), origin_point_block_offset, &container_builder_);
482
483 if (updated && abort_when_bfc_resolved_)
484 return WTF::nullopt;
485
419 // TODO(ikilpatrick): Check if origin_point_block_offset is correct - 486 // TODO(ikilpatrick): Check if origin_point_block_offset is correct -
420 // MaybeUpdateFragmentBfcOffset might have changed it due to clearance. 487 // MaybeUpdateFragmentBfcOffset might have changed it due to clearance.
421 PositionPendingFloats(origin_point_block_offset, &container_builder_, 488 PositionPendingFloats(origin_point_block_offset, &container_builder_,
422 MutableConstraintSpace()); 489 &unpositioned_floats_, MutableConstraintSpace());
423 } 490 }
424 491
425 NGLogicalOffset child_bfc_offset = { 492 NGLogicalOffset child_bfc_offset = {
426 ConstraintSpace().BfcOffset().inline_offset + 493 ConstraintSpace().BfcOffset().inline_offset +
427 border_scrollbar_padding_.inline_start + margins.inline_start, 494 border_scrollbar_padding_.inline_start + margins.inline_start,
428 bfc_block_offset}; 495 bfc_block_offset};
429 496
430 // Append the current margin strut with child's block start margin. 497 // Append the current margin strut with child's block start margin.
431 // Non empty border/padding, and new FC use cases are handled inside of the 498 // Non empty border/padding, and new FC use cases are handled inside of the
432 // child's layout. 499 // child's layout
433 margin_strut.Append(margins.block_start); 500 margin_strut.Append(margins.block_start);
434 501
435 return {child_bfc_offset, margin_strut, margins}; 502 return NGInflowChildData{child_bfc_offset, margin_strut, margins};
436 } 503 }
437 504
438 NGPreviousInflowPosition NGBlockLayoutAlgorithm::FinishChildLayout( 505 WTF::Optional<NGPreviousInflowPosition>
506 NGBlockLayoutAlgorithm::FinishChildLayout(
439 const NGConstraintSpace& child_space, 507 const NGConstraintSpace& child_space,
440 const NGPreviousInflowPosition& previous_inflow_position, 508 const NGPreviousInflowPosition& previous_inflow_position,
441 const NGInflowChildData& child_data, 509 const NGInflowChildData& child_data,
442 const NGLayoutInputNode child, 510 NGLayoutInputNode child,
443 NGLayoutResult* layout_result) { 511 NGBreakToken* child_break_token,
444 // Pull out unpositioned floats to the current fragment. This may needed if 512 RefPtr<NGLayoutResult> layout_result) {
445 // for example the child fragment could not position its floats because it's 513 // TODO(ikilpatrick): Split this function into two - one for positioning, and
446 // empty and therefore couldn't determine its position in space. 514 // the other for producing NGPreviousInflowPosition.
447 container_builder_.MutableUnpositionedFloats().AppendVector( 515
448 layout_result->UnpositionedFloats()); 516 // If we don't know our BFC offset yet, we need to copy the list of
517 // unpositioned floats from the child's layout result.
518 //
519 // If the child had any unpositioned floats, we need to abort our layout if
520 // we resolve our BFC offset.
521 //
522 // If we are a new formatting context, the child will get re-laid out once it
523 // has been positioned.
524 //
525 // TODO(ikilpatrick): a more optimal version of this is to set
526 // abort_when_bfc_resolved_, if the child tree _added_ any floats.
527 if (!container_builder_.BfcOffset() &&
528 !child_space.IsNewFormattingContext()) {
529 unpositioned_floats_ = layout_result->UnpositionedFloats();
530 abort_when_bfc_resolved_ |= !layout_result->UnpositionedFloats().IsEmpty();
531 if (child_space.FloatsBfcOffset())
532 DCHECK(layout_result->UnpositionedFloats().IsEmpty());
533 }
534
535 // Determine the fragment's position in the parent space.
536 WTF::Optional<NGLogicalOffset> child_bfc_offset;
537 if (child.CreatesNewFormattingContext()) {
538 if (!PositionNewFc(child, previous_inflow_position, *layout_result,
539 child_data, child_space, &child_bfc_offset))
540 return WTF::nullopt;
541 } else if (layout_result->BfcOffset()) {
542 if (!PositionWithBfcOffset(layout_result->BfcOffset().value(),
543 &child_bfc_offset))
544 return WTF::nullopt;
545 } else if (container_builder_.BfcOffset()) {
546 child_bfc_offset =
547 PositionWithParentBfc(child_space, child_data, *layout_result);
548 } else
549 DCHECK(IsEmptyFragment(ConstraintSpace().WritingMode(), *layout_result));
550
551 if ((layout_result->Status() == NGLayoutResult::kBfcOffsetResolved ||
552 !layout_result->UnpositionedFloats().IsEmpty()) &&
553 child_bfc_offset) {
554 RefPtr<NGConstraintSpace> new_child_space =
555 CreateConstraintSpaceForChild(child, child_data, child_bfc_offset);
556 layout_result = child.Layout(new_child_space.Get(), child_break_token);
557 }
449 558
450 NGBoxFragment fragment( 559 NGBoxFragment fragment(
451 ConstraintSpace().WritingMode(), 560 ConstraintSpace().WritingMode(),
452 ToNGPhysicalBoxFragment(layout_result->PhysicalFragment().Get())); 561 ToNGPhysicalBoxFragment(layout_result->PhysicalFragment().Get()));
453 562
454 // Determine the fragment's position in the parent space.
455 WTF::Optional<NGLogicalOffset> child_bfc_offset;
456 if (child.CreatesNewFormattingContext())
457 child_bfc_offset = PositionNewFc(child, previous_inflow_position, fragment,
458 child_data, child_space);
459 else if (layout_result->BfcOffset())
460 child_bfc_offset =
461 PositionWithBfcOffset(layout_result->BfcOffset().value());
462 else if (container_builder_.BfcOffset())
463 child_bfc_offset =
464 PositionWithParentBfc(child_space, child_data, *layout_result);
465 else
466 DCHECK(!fragment.BlockSize());
467
468 NGLogicalOffset logical_offset = 563 NGLogicalOffset logical_offset =
469 CalculateLogicalOffset(child_data.margins, child_bfc_offset); 564 CalculateLogicalOffset(child_data.margins, child_bfc_offset);
470 565
471 NGMarginStrut margin_strut = layout_result->EndMarginStrut(); 566 NGMarginStrut margin_strut = layout_result->EndMarginStrut();
472 margin_strut.Append(child_data.margins.block_end); 567 margin_strut.Append(child_data.margins.block_end);
473 568
569 // TODO(ikilpatrick): Refactor below such that we don't have to rely on the
570 // if (fragment) ... checks.
571
474 // Only modify content_size_ if the fragment's BlockSize is not empty. This is 572 // Only modify content_size_ if the fragment's BlockSize is not empty. This is
475 // needed to prevent the situation when logical_offset is included in 573 // needed to prevent the situation when logical_offset is included in
476 // content_size_ for empty blocks. Example: 574 // content_size_ for empty blocks. Example:
477 // <div style="overflow:hidden"> 575 // <div style="overflow:hidden">
478 // <div style="margin-top: 8px"></div> 576 // <div style="margin-top: 8px"></div>
479 // <div style="margin-top: 10px"></div> 577 // <div style="margin-top: 10px"></div>
480 // </div> 578 // </div>
481 if (fragment.BlockSize()) 579 if (fragment) {
482 content_size_ = std::max( 580 if (fragment.BlockSize()) {
483 content_size_, logical_offset.block_offset + fragment.BlockSize()); 581 content_size_ = std::max(
484 max_inline_size_ = std::max( 582 content_size_, logical_offset.block_offset + fragment.BlockSize());
485 max_inline_size_, fragment.InlineSize() + child_data.margins.InlineSum() + 583 }
486 border_scrollbar_padding_.InlineSum()); 584 max_inline_size_ =
585 std::max(max_inline_size_, fragment.InlineSize() +
586 child_data.margins.InlineSum() +
587 border_scrollbar_padding_.InlineSum());
588 }
487 589
488 container_builder_.AddChild(layout_result, logical_offset); 590 if (fragment)
591 container_builder_.AddChild(layout_result, logical_offset);
489 592
490 // Determine the child's end BFC block offset and logical offset, for the 593 // Determine the child's end BFC block offset and logical offset, for the
491 // next child to use. 594 // next child to use.
492 LayoutUnit child_end_bfc_block_offset; 595 LayoutUnit child_end_bfc_block_offset;
493 LayoutUnit logical_block_offset; 596 LayoutUnit logical_block_offset;
494 597
495 if (child_bfc_offset) { 598 if (child_bfc_offset) {
496 // TODO(crbug.com/716930): I think the layout_result->BfcOffset() condition 599 // TODO(crbug.com/716930): I think the layout_result->BfcOffset() condition
497 // here can be removed once we've removed inline splitting. 600 // here can be removed once we've removed inline splitting.
498 if (fragment.BlockSize() || layout_result->BfcOffset()) { 601 if (fragment && (fragment.BlockSize() || layout_result->BfcOffset())) {
499 child_end_bfc_block_offset = 602 child_end_bfc_block_offset =
500 child_bfc_offset.value().block_offset + fragment.BlockSize(); 603 child_bfc_offset.value().block_offset + fragment.BlockSize();
501 logical_block_offset = logical_offset.block_offset + fragment.BlockSize(); 604 logical_block_offset = logical_offset.block_offset + fragment.BlockSize();
502 } else { 605 } else {
503 DCHECK_EQ(LayoutUnit(), fragment.BlockSize()); 606 DCHECK(IsEmptyFragment(ConstraintSpace().WritingMode(), *layout_result));
607
504 child_end_bfc_block_offset = previous_inflow_position.bfc_block_offset; 608 child_end_bfc_block_offset = previous_inflow_position.bfc_block_offset;
505 logical_block_offset = previous_inflow_position.logical_block_offset; 609 logical_block_offset = previous_inflow_position.logical_block_offset;
506 } 610 }
507 } else { 611 } else {
508 child_end_bfc_block_offset = ConstraintSpace().BfcOffset().block_offset; 612 child_end_bfc_block_offset = ConstraintSpace().BfcOffset().block_offset;
509 logical_block_offset = LayoutUnit(); 613 logical_block_offset = LayoutUnit();
510 } 614 }
511 615
512 return {child_end_bfc_block_offset, logical_block_offset, margin_strut}; 616 return NGPreviousInflowPosition{child_end_bfc_block_offset,
617 logical_block_offset, margin_strut};
513 } 618 }
514 619
515 NGLogicalOffset NGBlockLayoutAlgorithm::PositionNewFc( 620 bool NGBlockLayoutAlgorithm::PositionNewFc(
516 const NGLayoutInputNode& child, 621 const NGLayoutInputNode& child,
517 const NGPreviousInflowPosition& previous_inflow_position, 622 const NGPreviousInflowPosition& previous_inflow_position,
518 const NGBoxFragment& fragment, 623 const NGLayoutResult& layout_result,
519 const NGInflowChildData& child_data, 624 const NGInflowChildData& child_data,
520 const NGConstraintSpace& child_space) { 625 const NGConstraintSpace& child_space,
626 WTF::Optional<NGLogicalOffset>* child_bfc_offset) {
521 const ComputedStyle& child_style = child.Style(); 627 const ComputedStyle& child_style = child.Style();
522 628
629 NGBoxFragment fragment(
630 ConstraintSpace().WritingMode(),
631 ToNGPhysicalBoxFragment(layout_result.PhysicalFragment().Get()));
632
523 LayoutUnit child_bfc_offset_estimate = 633 LayoutUnit child_bfc_offset_estimate =
524 child_data.bfc_offset_estimate.block_offset; 634 child_data.bfc_offset_estimate.block_offset;
525 635
526 // 1. Position all pending floats to a temporary space. 636 // 1. Position all pending floats to a temporary space.
527 RefPtr<NGConstraintSpace> tmp_space = 637 RefPtr<NGConstraintSpace> tmp_space =
528 NGConstraintSpaceBuilder(&child_space) 638 NGConstraintSpaceBuilder(&child_space)
529 .SetIsNewFormattingContext(false) 639 .SetIsNewFormattingContext(false)
530 .ToConstraintSpace(child_space.WritingMode()); 640 .ToConstraintSpace(child_space.WritingMode());
531 PositionFloats(child_bfc_offset_estimate, child_bfc_offset_estimate, 641 PositionFloats(child_bfc_offset_estimate, child_bfc_offset_estimate,
532 container_builder_.UnpositionedFloats(), tmp_space.Get()); 642 unpositioned_floats_, tmp_space.Get());
533 643
534 NGLogicalOffset origin_offset = {ConstraintSpace().BfcOffset().inline_offset + 644 NGLogicalOffset origin_offset = {ConstraintSpace().BfcOffset().inline_offset +
535 border_scrollbar_padding_.inline_start, 645 border_scrollbar_padding_.inline_start,
536 child_bfc_offset_estimate}; 646 child_bfc_offset_estimate};
537 AdjustToClearance( 647 AdjustToClearance(
538 GetClearanceOffset(ConstraintSpace().Exclusions(), child_style.Clear()), 648 GetClearanceOffset(ConstraintSpace().Exclusions(), child_style.Clear()),
539 &origin_offset); 649 &origin_offset);
540 650
541 // 2. Find an estimated layout opportunity for our fragment. 651 // 2. Find an estimated layout opportunity for our fragment.
542 NGLayoutOpportunity opportunity = FindLayoutOpportunityForFragment( 652 NGLayoutOpportunity opportunity = FindLayoutOpportunityForFragment(
543 tmp_space->Exclusions().get(), child_space.AvailableSize(), origin_offset, 653 tmp_space->Exclusions().get(), child_space.AvailableSize(), origin_offset,
544 child_data.margins, fragment.Size()); 654 child_data.margins, fragment.Size());
545 655
546 NGMarginStrut margin_strut = previous_inflow_position.margin_strut; 656 NGMarginStrut margin_strut = previous_inflow_position.margin_strut;
547 657
548 // 3. If the found opportunity lies on the same line with our estimated 658 // 3. If the found opportunity lies on the same line with our estimated
549 // child's BFC offset then merge fragment's margins with the current 659 // child's BFC offset then merge fragment's margins with the current
550 // MarginStrut. 660 // MarginStrut.
551 if (opportunity.offset.block_offset == child_bfc_offset_estimate) 661 if (opportunity.offset.block_offset == child_bfc_offset_estimate)
552 margin_strut.Append(child_data.margins.block_start); 662 margin_strut.Append(child_data.margins.block_start);
553 child_bfc_offset_estimate += margin_strut.Sum(); 663 child_bfc_offset_estimate += margin_strut.Sum();
554 664
555 // 4. The child's BFC block offset is known here. 665 // 4. The child's BFC block offset is known here.
556 MaybeUpdateFragmentBfcOffset(ConstraintSpace(), child_bfc_offset_estimate, 666 bool updated = MaybeUpdateFragmentBfcOffset(
557 &container_builder_); 667 ConstraintSpace(), child_bfc_offset_estimate, &container_builder_);
668
669 if (updated && abort_when_bfc_resolved_)
670 return false;
671
558 PositionPendingFloats(child_bfc_offset_estimate, &container_builder_, 672 PositionPendingFloats(child_bfc_offset_estimate, &container_builder_,
559 MutableConstraintSpace()); 673 &unpositioned_floats_, MutableConstraintSpace());
560 674
561 origin_offset = {ConstraintSpace().BfcOffset().inline_offset + 675 origin_offset = {ConstraintSpace().BfcOffset().inline_offset +
562 border_scrollbar_padding_.inline_start, 676 border_scrollbar_padding_.inline_start,
563 child_bfc_offset_estimate}; 677 child_bfc_offset_estimate};
564 AdjustToClearance( 678 AdjustToClearance(
565 GetClearanceOffset(ConstraintSpace().Exclusions(), child_style.Clear()), 679 GetClearanceOffset(ConstraintSpace().Exclusions(), child_style.Clear()),
566 &origin_offset); 680 &origin_offset);
567 681
568 // 5. Find the final layout opportunity for the fragment after all pending 682 // 5. Find the final layout opportunity for the fragment after all pending
569 // floats are positioned at the correct BFC block's offset. 683 // floats are positioned at the correct BFC block's offset.
570 opportunity = FindLayoutOpportunityForFragment( 684 opportunity = FindLayoutOpportunityForFragment(
571 MutableConstraintSpace()->Exclusions().get(), child_space.AvailableSize(), 685 MutableConstraintSpace()->Exclusions().get(), child_space.AvailableSize(),
572 origin_offset, child_data.margins, fragment.Size()); 686 origin_offset, child_data.margins, fragment.Size());
573 687
574 return opportunity.offset; 688 *child_bfc_offset = opportunity.offset;
689 return true;
575 } 690 }
576 691
577 NGLogicalOffset NGBlockLayoutAlgorithm::PositionWithBfcOffset( 692 bool NGBlockLayoutAlgorithm::PositionWithBfcOffset(
578 const NGLogicalOffset& bfc_offset) { 693 const NGLogicalOffset& bfc_offset,
694 WTF::Optional<NGLogicalOffset>* child_bfc_offset) {
579 LayoutUnit bfc_block_offset = bfc_offset.block_offset; 695 LayoutUnit bfc_block_offset = bfc_offset.block_offset;
580 MaybeUpdateFragmentBfcOffset(ConstraintSpace(), bfc_block_offset, 696 bool updated = MaybeUpdateFragmentBfcOffset(
581 &container_builder_); 697 ConstraintSpace(), bfc_block_offset, &container_builder_);
698
699 if (updated && abort_when_bfc_resolved_)
700 return false;
701
582 PositionPendingFloats(bfc_block_offset, &container_builder_, 702 PositionPendingFloats(bfc_block_offset, &container_builder_,
583 MutableConstraintSpace()); 703 &unpositioned_floats_, MutableConstraintSpace());
584 return bfc_offset; 704
705 *child_bfc_offset = bfc_offset;
706 return true;
585 } 707 }
586 708
587 NGLogicalOffset NGBlockLayoutAlgorithm::PositionWithParentBfc( 709 NGLogicalOffset NGBlockLayoutAlgorithm::PositionWithParentBfc(
588 const NGConstraintSpace& space, 710 const NGConstraintSpace& space,
589 const NGInflowChildData& child_data, 711 const NGInflowChildData& child_data,
590 const NGLayoutResult& layout_result) { 712 const NGLayoutResult& layout_result) {
591 // The child must be an in-flow zero-block-size fragment, use its end margin 713 // The child must be an in-flow zero-block-size fragment, use its end margin
592 // strut for positioning. 714 // strut for positioning.
593 NGFragment fragment(ConstraintSpace().WritingMode(), 715 DCHECK(IsEmptyFragment(ConstraintSpace().WritingMode(), layout_result));
594 layout_result.PhysicalFragment().Get());
595 DCHECK_EQ(fragment.BlockSize(), LayoutUnit());
596 716
597 NGLogicalOffset child_bfc_offset = { 717 NGLogicalOffset child_bfc_offset = {
598 ConstraintSpace().BfcOffset().inline_offset + 718 ConstraintSpace().BfcOffset().inline_offset +
599 border_scrollbar_padding_.inline_start + 719 border_scrollbar_padding_.inline_start +
600 child_data.margins.inline_start, 720 child_data.margins.inline_start,
601 child_data.bfc_offset_estimate.block_offset + 721 child_data.bfc_offset_estimate.block_offset +
602 layout_result.EndMarginStrut().Sum()}; 722 layout_result.EndMarginStrut().Sum()};
603 723
604 AdjustToClearance(space.ClearanceOffset(), &child_bfc_offset); 724 AdjustToClearance(space.ClearanceOffset(), &child_bfc_offset);
605 PositionPendingFloats(child_bfc_offset.block_offset, &container_builder_,
606 MutableConstraintSpace());
607 return child_bfc_offset; 725 return child_bfc_offset;
608 } 726 }
609 727
610 void NGBlockLayoutAlgorithm::FinalizeForFragmentation() { 728 void NGBlockLayoutAlgorithm::FinalizeForFragmentation() {
611 LayoutUnit used_block_size = 729 LayoutUnit used_block_size =
612 BreakToken() ? BreakToken()->UsedBlockSize() : LayoutUnit(); 730 BreakToken() ? BreakToken()->UsedBlockSize() : LayoutUnit();
613 LayoutUnit block_size = ComputeBlockSizeForFragment( 731 LayoutUnit block_size = ComputeBlockSizeForFragment(
614 ConstraintSpace(), Style(), used_block_size + content_size_); 732 ConstraintSpace(), Style(), used_block_size + content_size_);
615 733
616 block_size -= used_block_size; 734 block_size -= used_block_size;
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after
669 787
670 LayoutUnit child_inline_size = 788 LayoutUnit child_inline_size =
671 ComputeInlineSizeForFragment(*space, child_style, sizes); 789 ComputeInlineSizeForFragment(*space, child_style, sizes);
672 ApplyAutoMargins(*space, child_style, child_inline_size, &margins); 790 ApplyAutoMargins(*space, child_style, child_inline_size, &margins);
673 } 791 }
674 return margins; 792 return margins;
675 } 793 }
676 794
677 RefPtr<NGConstraintSpace> NGBlockLayoutAlgorithm::CreateConstraintSpaceForChild( 795 RefPtr<NGConstraintSpace> NGBlockLayoutAlgorithm::CreateConstraintSpaceForChild(
678 const NGLayoutInputNode child, 796 const NGLayoutInputNode child,
679 const NGInflowChildData& child_data) { 797 const NGInflowChildData& child_data,
798 const WTF::Optional<NGLogicalOffset> floats_bfc_offset) {
680 NGConstraintSpaceBuilder space_builder(MutableConstraintSpace()); 799 NGConstraintSpaceBuilder space_builder(MutableConstraintSpace());
681 space_builder.SetAvailableSize(child_available_size_) 800 space_builder.SetAvailableSize(child_available_size_)
682 .SetPercentageResolutionSize(child_percentage_size_); 801 .SetPercentageResolutionSize(child_percentage_size_);
683 802
684 if (NGBaseline::ShouldPropagateBaselines(child)) 803 if (NGBaseline::ShouldPropagateBaselines(child))
685 space_builder.AddBaselineRequests(ConstraintSpace().BaselineRequests()); 804 space_builder.AddBaselineRequests(ConstraintSpace().BaselineRequests());
686 805
687 bool is_new_fc = child.CreatesNewFormattingContext(); 806 bool is_new_fc = child.CreatesNewFormattingContext();
688 space_builder.SetIsNewFormattingContext(is_new_fc) 807 space_builder.SetIsNewFormattingContext(is_new_fc)
689 .SetBfcOffset(child_data.bfc_offset_estimate) 808 .SetBfcOffset(child_data.bfc_offset_estimate)
690 .SetMarginStrut(child_data.margin_strut); 809 .SetMarginStrut(child_data.margin_strut);
691 810
692 if (!is_new_fc) { 811 if (!container_builder_.BfcOffset() && ConstraintSpace().FloatsBfcOffset()) {
693 // This clears the current layout's unpositioned floats as they may be 812 space_builder.SetFloatsBfcOffset(
694 // positioned by the child. 813 NGLogicalOffset{child_data.bfc_offset_estimate.inline_offset,
695 space_builder.SetUnpositionedFloats( 814 ConstraintSpace().FloatsBfcOffset()->block_offset});
696 container_builder_.MutableUnpositionedFloats()); 815 }
816
817 if (floats_bfc_offset)
818 space_builder.SetFloatsBfcOffset(floats_bfc_offset);
819
820 if (!is_new_fc && !floats_bfc_offset) {
821 space_builder.SetUnpositionedFloats(unpositioned_floats_);
697 } 822 }
698 823
699 if (child.IsInline()) { 824 if (child.IsInline()) {
700 // TODO(kojii): Setup space_builder appropriately for inline child. 825 // TODO(kojii): Setup space_builder appropriately for inline child.
701 space_builder.SetClearanceOffset(ConstraintSpace().ClearanceOffset()); 826 space_builder.SetClearanceOffset(ConstraintSpace().ClearanceOffset());
702 return space_builder.ToConstraintSpace( 827 return space_builder.ToConstraintSpace(
703 FromPlatformWritingMode(Style().GetWritingMode())); 828 FromPlatformWritingMode(Style().GetWritingMode()));
704 } 829 }
705 830
706 const ComputedStyle& child_style = child.Style(); 831 const ComputedStyle& child_style = child.Style();
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after
766 break; 891 break;
767 case NGBaselineAlgorithmType::kFirstLine: 892 case NGBaselineAlgorithmType::kFirstLine:
768 for (unsigned i = 0; i < container_builder_.Children().size(); i++) { 893 for (unsigned i = 0; i < container_builder_.Children().size(); i++) {
769 if (AddBaseline(request, i)) 894 if (AddBaseline(request, i))
770 break; 895 break;
771 } 896 }
772 break; 897 break;
773 } 898 }
774 } 899 }
775 } 900 }
901
776 } // namespace blink 902 } // namespace blink
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698