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

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: ./ 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);
eae 2017/07/10 23:27:49 This is a good use of Optional, it is logically co
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 return container_builder_.ToBoxFragment(); 402 return container_builder_.ToBoxFragment();
341 } 403 }
342 404
343 void NGBlockLayoutAlgorithm::HandleOutOfFlowPositioned( 405 void NGBlockLayoutAlgorithm::HandleOutOfFlowPositioned(
344 const NGPreviousInflowPosition& previous_inflow_position, 406 const NGPreviousInflowPosition& previous_inflow_position,
345 NGBlockNode child) { 407 NGBlockNode child) {
346 // TODO(ikilpatrick): Determine which of the child's margins need to be 408 // TODO(ikilpatrick): Determine which of the child's margins need to be
347 // included for the static position. 409 // included for the static position.
348 NGLogicalOffset offset = {border_scrollbar_padding_.inline_start, 410 NGLogicalOffset offset = {border_scrollbar_padding_.inline_start,
349 previous_inflow_position.logical_block_offset}; 411 previous_inflow_position.logical_block_offset};
(...skipping 13 matching lines...) Expand all
363 // Calculate margins in the BFC's writing mode. 425 // Calculate margins in the BFC's writing mode.
364 NGBoxStrut margins = CalculateMargins(child); 426 NGBoxStrut margins = CalculateMargins(child);
365 427
366 LayoutUnit origin_inline_offset = 428 LayoutUnit origin_inline_offset =
367 constraint_space_->BfcOffset().inline_offset + 429 constraint_space_->BfcOffset().inline_offset +
368 border_scrollbar_padding_.inline_start; 430 border_scrollbar_padding_.inline_start;
369 431
370 RefPtr<NGUnpositionedFloat> unpositioned_float = NGUnpositionedFloat::Create( 432 RefPtr<NGUnpositionedFloat> unpositioned_float = NGUnpositionedFloat::Create(
371 child_available_size_, child_percentage_size_, origin_inline_offset, 433 child_available_size_, child_percentage_size_, origin_inline_offset,
372 constraint_space_->BfcOffset().inline_offset, margins, child, token); 434 constraint_space_->BfcOffset().inline_offset, margins, child, token);
373 container_builder_.AddUnpositionedFloat(unpositioned_float); 435 unpositioned_floats_.push_back(std::move(unpositioned_float));
374 436
375 // If there is a break token for a float we must be resuming layout, we must 437 // If there is a break token for a float we must be resuming layout, we must
376 // always know our position in the BFC. 438 // always know our position in the BFC.
377 DCHECK(!token || container_builder_.BfcOffset()); 439 DCHECK(!token || container_builder_.BfcOffset());
378 440
379 // No need to postpone the positioning if we know the correct offset. 441 // No need to postpone the positioning if we know the correct offset.
380 if (container_builder_.BfcOffset()) { 442 if (container_builder_.BfcOffset() || ConstraintSpace().FloatsBfcOffset()) {
381 // Adjust origin point to the margins of the last child. 443 // Adjust origin point to the margins of the last child.
382 // Example: <div style="margin-bottom: 20px"><float></div> 444 // Example: <div style="margin-bottom: 20px"><float></div>
383 // <div style="margin-bottom: 30px"></div> 445 // <div style="margin-bottom: 30px"></div>
384 LayoutUnit origin_block_offset = 446 LayoutUnit origin_block_offset =
385 previous_inflow_position.bfc_block_offset + 447 container_builder_.BfcOffset()
386 previous_inflow_position.margin_strut.Sum(); 448 ? previous_inflow_position.bfc_block_offset +
449 previous_inflow_position.margin_strut.Sum()
450 : ConstraintSpace().FloatsBfcOffset().value().block_offset;
387 PositionPendingFloats(origin_block_offset, &container_builder_, 451 PositionPendingFloats(origin_block_offset, &container_builder_,
388 MutableConstraintSpace()); 452 &unpositioned_floats_, MutableConstraintSpace());
389 } 453 }
390 } 454 }
391 455
392 NGInflowChildData NGBlockLayoutAlgorithm::PrepareChildLayout( 456 WTF::Optional<NGInflowChildData> NGBlockLayoutAlgorithm::PrepareChildLayout(
393 const NGPreviousInflowPosition& previous_inflow_position, 457 const NGPreviousInflowPosition& previous_inflow_position,
394 NGLayoutInputNode child) { 458 NGLayoutInputNode child) {
395 DCHECK(child); 459 DCHECK(child);
396 DCHECK(!child.IsFloating()); 460 DCHECK(!child.IsFloating());
397 461
398 LayoutUnit bfc_block_offset = previous_inflow_position.bfc_block_offset; 462 LayoutUnit bfc_block_offset = previous_inflow_position.bfc_block_offset;
399 463
400 // Calculate margins in parent's writing mode. 464 // Calculate margins in parent's writing mode.
401 NGBoxStrut margins = CalculateMargins(child); 465 NGBoxStrut margins = CalculateMargins(child);
402 NGMarginStrut margin_strut = previous_inflow_position.margin_strut; 466 NGMarginStrut margin_strut = previous_inflow_position.margin_strut;
403 467
404 bool should_position_pending_floats = 468 bool should_position_pending_floats =
405 !child.CreatesNewFormattingContext() && 469 !child.CreatesNewFormattingContext() &&
406 ClearanceMayAffectLayout(ConstraintSpace(), 470 ClearanceMayAffectLayout(ConstraintSpace(), unpositioned_floats_,
407 container_builder_.UnpositionedFloats(),
408 child.Style()); 471 child.Style());
409 472
410 // Children which may clear a float need to force all the pending floats to 473 // Children which may clear a float need to force all the pending floats to
411 // be positioned before layout. This also resolves the fragment's bfc offset. 474 // be positioned before layout. This also resolves the fragment's bfc offset.
412 if (should_position_pending_floats) { 475 if (should_position_pending_floats) {
413 LayoutUnit origin_point_block_offset = 476 LayoutUnit origin_point_block_offset =
414 bfc_block_offset + margin_strut.Sum(); 477 bfc_block_offset + margin_strut.Sum();
415 MaybeUpdateFragmentBfcOffset(ConstraintSpace(), origin_point_block_offset, 478 bool updated = MaybeUpdateFragmentBfcOffset(
416 &container_builder_); 479 ConstraintSpace(), origin_point_block_offset, &container_builder_);
480
481 if (updated && abort_when_bfc_resolved_)
482 return WTF::nullopt;
483
417 // TODO(ikilpatrick): Check if origin_point_block_offset is correct - 484 // TODO(ikilpatrick): Check if origin_point_block_offset is correct -
418 // MaybeUpdateFragmentBfcOffset might have changed it due to clearance. 485 // MaybeUpdateFragmentBfcOffset might have changed it due to clearance.
419 PositionPendingFloats(origin_point_block_offset, &container_builder_, 486 PositionPendingFloats(origin_point_block_offset, &container_builder_,
420 MutableConstraintSpace()); 487 &unpositioned_floats_, MutableConstraintSpace());
421 } 488 }
422 489
423 NGLogicalOffset child_bfc_offset = { 490 NGLogicalOffset child_bfc_offset = {
424 ConstraintSpace().BfcOffset().inline_offset + 491 ConstraintSpace().BfcOffset().inline_offset +
425 border_scrollbar_padding_.inline_start + margins.inline_start, 492 border_scrollbar_padding_.inline_start + margins.inline_start,
426 bfc_block_offset}; 493 bfc_block_offset};
427 494
428 // Append the current margin strut with child's block start margin. 495 // Append the current margin strut with child's block start margin.
429 // Non empty border/padding, and new FC use cases are handled inside of the 496 // Non empty border/padding, and new FC use cases are handled inside of the
430 // child's layout. 497 // child's layout
431 margin_strut.Append(margins.block_start); 498 margin_strut.Append(margins.block_start);
432 499
433 return {child_bfc_offset, margin_strut, margins}; 500 return NGInflowChildData{child_bfc_offset, margin_strut, margins};
434 } 501 }
435 502
436 NGPreviousInflowPosition NGBlockLayoutAlgorithm::FinishChildLayout( 503 WTF::Optional<NGPreviousInflowPosition>
504 NGBlockLayoutAlgorithm::FinishChildLayout(
437 const NGConstraintSpace& child_space, 505 const NGConstraintSpace& child_space,
438 const NGPreviousInflowPosition& previous_inflow_position, 506 const NGPreviousInflowPosition& previous_inflow_position,
439 const NGInflowChildData& child_data, 507 const NGInflowChildData& child_data,
440 const NGLayoutInputNode child, 508 NGLayoutInputNode child,
441 NGLayoutResult* layout_result) { 509 NGBreakToken* child_break_token,
442 // Pull out unpositioned floats to the current fragment. This may needed if 510 RefPtr<NGLayoutResult> layout_result) {
443 // for example the child fragment could not position its floats because it's 511 // TODO(ikilpatrick): Split this function into two - one for positioning, and
444 // empty and therefore couldn't determine its position in space. 512 // the other for producing NGPreviousInflowPosition.
445 container_builder_.MutableUnpositionedFloats().AppendVector( 513
446 layout_result->UnpositionedFloats()); 514 // If we don't know our BFC offset yet, we need to copy the list of
515 // unpositioned floats from the child's layout result.
516 //
517 // If the child had any unpositioned floats, we need to abort our layout if
518 // we resolve our BFC offset.
519 //
520 // If we are a new formatting context, the child will get re-laid out once it
521 // has been positioned.
522 //
523 // TODO(ikilpatrick): a more optimal version of this is to set
524 // abort_when_bfc_resolved_, if the child tree _added_ any floats.
525 if (!container_builder_.BfcOffset() &&
526 !child_space.IsNewFormattingContext()) {
527 unpositioned_floats_ = layout_result->UnpositionedFloats();
528 abort_when_bfc_resolved_ |= !layout_result->UnpositionedFloats().IsEmpty();
529 if (child_space.FloatsBfcOffset())
530 DCHECK(layout_result->UnpositionedFloats().IsEmpty());
531 }
532
533 // Determine the fragment's position in the parent space.
534 WTF::Optional<NGLogicalOffset> child_bfc_offset;
535 if (child.CreatesNewFormattingContext()) {
536 child_bfc_offset = PositionNewFc(child, previous_inflow_position,
537 *layout_result, child_data, child_space);
538 if (!child_bfc_offset)
539 return WTF::nullopt;
540 } else if (layout_result->BfcOffset()) {
541 child_bfc_offset =
542 PositionWithBfcOffset(layout_result->BfcOffset().value());
543 if (!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 }
447 558
448 NGBoxFragment fragment( 559 NGBoxFragment fragment(
449 ConstraintSpace().WritingMode(), 560 ConstraintSpace().WritingMode(),
450 ToNGPhysicalBoxFragment(layout_result->PhysicalFragment().Get())); 561 ToNGPhysicalBoxFragment(layout_result->PhysicalFragment().Get()));
451 562
452 // Determine the fragment's position in the parent space.
453 WTF::Optional<NGLogicalOffset> child_bfc_offset;
454 if (child.CreatesNewFormattingContext())
455 child_bfc_offset = PositionNewFc(child, previous_inflow_position, fragment,
456 child_data, child_space);
457 else if (layout_result->BfcOffset())
458 child_bfc_offset =
459 PositionWithBfcOffset(layout_result->BfcOffset().value());
460 else if (container_builder_.BfcOffset())
461 child_bfc_offset =
462 PositionWithParentBfc(child_space, child_data, *layout_result);
463 else
464 DCHECK(!fragment.BlockSize());
465
466 NGLogicalOffset logical_offset = 563 NGLogicalOffset logical_offset =
467 CalculateLogicalOffset(child_data.margins, child_bfc_offset); 564 CalculateLogicalOffset(child_data.margins, child_bfc_offset);
468 565
469 NGMarginStrut margin_strut = layout_result->EndMarginStrut(); 566 NGMarginStrut margin_strut = layout_result->EndMarginStrut();
470 margin_strut.Append(child_data.margins.block_end); 567 margin_strut.Append(child_data.margins.block_end);
471 568
569 // TODO(ikilpatrick): Refactor below such that we don't have to rely on the
570 // if (fragment) ... checks.
571
472 // 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
473 // needed to prevent the situation when logical_offset is included in 573 // needed to prevent the situation when logical_offset is included in
474 // content_size_ for empty blocks. Example: 574 // content_size_ for empty blocks. Example:
475 // <div style="overflow:hidden"> 575 // <div style="overflow:hidden">
476 // <div style="margin-top: 8px"></div> 576 // <div style="margin-top: 8px"></div>
477 // <div style="margin-top: 10px"></div> 577 // <div style="margin-top: 10px"></div>
478 // </div> 578 // </div>
479 if (fragment.BlockSize()) 579 if (fragment) {
480 content_size_ = std::max( 580 if (fragment.BlockSize()) {
eae 2017/07/10 23:27:49 What if the blockSize > 0 but the inlineSize is ze
ikilpatrick 2017/07/11 17:20:41 Only cares about block size, "empty" is only in th
481 content_size_, logical_offset.block_offset + fragment.BlockSize()); 581 content_size_ = std::max(
482 max_inline_size_ = std::max( 582 content_size_, logical_offset.block_offset + fragment.BlockSize());
483 max_inline_size_, fragment.InlineSize() + child_data.margins.InlineSum() + 583 }
484 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 }
485 589
486 container_builder_.AddChild(layout_result, logical_offset); 590 if (fragment)
591 container_builder_.AddChild(layout_result, logical_offset);
487 592
488 // 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
489 // next child to use. 594 // next child to use.
490 LayoutUnit child_end_bfc_block_offset; 595 LayoutUnit child_end_bfc_block_offset;
491 LayoutUnit logical_block_offset; 596 LayoutUnit logical_block_offset;
492 597
493 if (child_bfc_offset) { 598 if (child_bfc_offset) {
494 // TODO(crbug.com/716930): I think the layout_result->BfcOffset() condition 599 // TODO(crbug.com/716930): I think the layout_result->BfcOffset() condition
495 // here can be removed once we've removed inline splitting. 600 // here can be removed once we've removed inline splitting.
496 if (fragment.BlockSize() || layout_result->BfcOffset()) { 601 if (fragment && (fragment.BlockSize() || layout_result->BfcOffset())) {
497 child_end_bfc_block_offset = 602 child_end_bfc_block_offset =
498 child_bfc_offset.value().block_offset + fragment.BlockSize(); 603 child_bfc_offset.value().block_offset + fragment.BlockSize();
499 logical_block_offset = logical_offset.block_offset + fragment.BlockSize(); 604 logical_block_offset = logical_offset.block_offset + fragment.BlockSize();
500 } else { 605 } else {
501 DCHECK_EQ(LayoutUnit(), fragment.BlockSize()); 606 DCHECK(IsEmptyFragment(ConstraintSpace().WritingMode(), *layout_result));
607
502 child_end_bfc_block_offset = previous_inflow_position.bfc_block_offset; 608 child_end_bfc_block_offset = previous_inflow_position.bfc_block_offset;
503 logical_block_offset = previous_inflow_position.logical_block_offset; 609 logical_block_offset = previous_inflow_position.logical_block_offset;
504 } 610 }
505 } else { 611 } else {
506 child_end_bfc_block_offset = ConstraintSpace().BfcOffset().block_offset; 612 child_end_bfc_block_offset = ConstraintSpace().BfcOffset().block_offset;
507 logical_block_offset = LayoutUnit(); 613 logical_block_offset = LayoutUnit();
508 } 614 }
509 615
510 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};
511 } 618 }
512 619
513 NGLogicalOffset NGBlockLayoutAlgorithm::PositionNewFc( 620 WTF::Optional<NGLogicalOffset> NGBlockLayoutAlgorithm::PositionNewFc(
514 const NGLayoutInputNode& child, 621 const NGLayoutInputNode& child,
515 const NGPreviousInflowPosition& previous_inflow_position, 622 const NGPreviousInflowPosition& previous_inflow_position,
516 const NGBoxFragment& fragment, 623 const NGLayoutResult& layout_result,
517 const NGInflowChildData& child_data, 624 const NGInflowChildData& child_data,
518 const NGConstraintSpace& child_space) { 625 const NGConstraintSpace& child_space) {
519 const ComputedStyle& child_style = child.Style(); 626 const ComputedStyle& child_style = child.Style();
520 627
628 NGBoxFragment fragment(
629 ConstraintSpace().WritingMode(),
630 ToNGPhysicalBoxFragment(layout_result.PhysicalFragment().Get()));
631
521 LayoutUnit child_bfc_offset_estimate = 632 LayoutUnit child_bfc_offset_estimate =
522 child_data.bfc_offset_estimate.block_offset; 633 child_data.bfc_offset_estimate.block_offset;
523 634
524 // 1. Position all pending floats to a temporary space. 635 // 1. Position all pending floats to a temporary space.
525 RefPtr<NGConstraintSpace> tmp_space = 636 RefPtr<NGConstraintSpace> tmp_space =
526 NGConstraintSpaceBuilder(&child_space) 637 NGConstraintSpaceBuilder(&child_space)
527 .SetIsNewFormattingContext(false) 638 .SetIsNewFormattingContext(false)
528 .ToConstraintSpace(child_space.WritingMode()); 639 .ToConstraintSpace(child_space.WritingMode());
529 PositionFloats(child_bfc_offset_estimate, child_bfc_offset_estimate, 640 PositionFloats(child_bfc_offset_estimate, child_bfc_offset_estimate,
530 container_builder_.UnpositionedFloats(), tmp_space.Get()); 641 unpositioned_floats_, tmp_space.Get());
531 642
532 NGLogicalOffset origin_offset = {ConstraintSpace().BfcOffset().inline_offset + 643 NGLogicalOffset origin_offset = {ConstraintSpace().BfcOffset().inline_offset +
533 border_scrollbar_padding_.inline_start, 644 border_scrollbar_padding_.inline_start,
534 child_bfc_offset_estimate}; 645 child_bfc_offset_estimate};
535 AdjustToClearance( 646 AdjustToClearance(
536 GetClearanceOffset(ConstraintSpace().Exclusions(), child_style.Clear()), 647 GetClearanceOffset(ConstraintSpace().Exclusions(), child_style.Clear()),
537 &origin_offset); 648 &origin_offset);
538 649
539 // 2. Find an estimated layout opportunity for our fragment. 650 // 2. Find an estimated layout opportunity for our fragment.
540 NGLayoutOpportunity opportunity = FindLayoutOpportunityForFragment( 651 NGLayoutOpportunity opportunity = FindLayoutOpportunityForFragment(
541 tmp_space->Exclusions().get(), child_space.AvailableSize(), origin_offset, 652 tmp_space->Exclusions().get(), child_space.AvailableSize(), origin_offset,
542 child_data.margins, fragment.Size()); 653 child_data.margins, fragment.Size());
543 654
544 NGMarginStrut margin_strut = previous_inflow_position.margin_strut; 655 NGMarginStrut margin_strut = previous_inflow_position.margin_strut;
545 656
546 // 3. If the found opportunity lies on the same line with our estimated 657 // 3. If the found opportunity lies on the same line with our estimated
547 // child's BFC offset then merge fragment's margins with the current 658 // child's BFC offset then merge fragment's margins with the current
548 // MarginStrut. 659 // MarginStrut.
549 if (opportunity.offset.block_offset == child_bfc_offset_estimate) 660 if (opportunity.offset.block_offset == child_bfc_offset_estimate)
550 margin_strut.Append(child_data.margins.block_start); 661 margin_strut.Append(child_data.margins.block_start);
551 child_bfc_offset_estimate += margin_strut.Sum(); 662 child_bfc_offset_estimate += margin_strut.Sum();
552 663
553 // 4. The child's BFC block offset is known here. 664 // 4. The child's BFC block offset is known here.
554 MaybeUpdateFragmentBfcOffset(ConstraintSpace(), child_bfc_offset_estimate, 665 bool updated = MaybeUpdateFragmentBfcOffset(
555 &container_builder_); 666 ConstraintSpace(), child_bfc_offset_estimate, &container_builder_);
667
668 if (updated && abort_when_bfc_resolved_)
669 return WTF::nullopt;
670
556 PositionPendingFloats(child_bfc_offset_estimate, &container_builder_, 671 PositionPendingFloats(child_bfc_offset_estimate, &container_builder_,
557 MutableConstraintSpace()); 672 &unpositioned_floats_, MutableConstraintSpace());
558 673
559 origin_offset = {ConstraintSpace().BfcOffset().inline_offset + 674 origin_offset = {ConstraintSpace().BfcOffset().inline_offset +
560 border_scrollbar_padding_.inline_start, 675 border_scrollbar_padding_.inline_start,
561 child_bfc_offset_estimate}; 676 child_bfc_offset_estimate};
562 AdjustToClearance( 677 AdjustToClearance(
563 GetClearanceOffset(ConstraintSpace().Exclusions(), child_style.Clear()), 678 GetClearanceOffset(ConstraintSpace().Exclusions(), child_style.Clear()),
564 &origin_offset); 679 &origin_offset);
565 680
566 // 5. Find the final layout opportunity for the fragment after all pending 681 // 5. Find the final layout opportunity for the fragment after all pending
567 // floats are positioned at the correct BFC block's offset. 682 // floats are positioned at the correct BFC block's offset.
568 opportunity = FindLayoutOpportunityForFragment( 683 opportunity = FindLayoutOpportunityForFragment(
569 MutableConstraintSpace()->Exclusions().get(), child_space.AvailableSize(), 684 MutableConstraintSpace()->Exclusions().get(), child_space.AvailableSize(),
570 origin_offset, child_data.margins, fragment.Size()); 685 origin_offset, child_data.margins, fragment.Size());
571 686
572 return opportunity.offset; 687 return opportunity.offset;
573 } 688 }
574 689
575 NGLogicalOffset NGBlockLayoutAlgorithm::PositionWithBfcOffset( 690 WTF::Optional<NGLogicalOffset> NGBlockLayoutAlgorithm::PositionWithBfcOffset(
576 const NGLogicalOffset& bfc_offset) { 691 const NGLogicalOffset& bfc_offset) {
577 LayoutUnit bfc_block_offset = bfc_offset.block_offset; 692 LayoutUnit bfc_block_offset = bfc_offset.block_offset;
578 MaybeUpdateFragmentBfcOffset(ConstraintSpace(), bfc_block_offset, 693 bool updated = MaybeUpdateFragmentBfcOffset(
579 &container_builder_); 694 ConstraintSpace(), bfc_block_offset, &container_builder_);
695
696 if (updated && abort_when_bfc_resolved_)
697 return WTF::nullopt;
698
580 PositionPendingFloats(bfc_block_offset, &container_builder_, 699 PositionPendingFloats(bfc_block_offset, &container_builder_,
581 MutableConstraintSpace()); 700 &unpositioned_floats_, MutableConstraintSpace());
582 return bfc_offset; 701 return bfc_offset;
583 } 702 }
584 703
585 NGLogicalOffset NGBlockLayoutAlgorithm::PositionWithParentBfc( 704 NGLogicalOffset NGBlockLayoutAlgorithm::PositionWithParentBfc(
586 const NGConstraintSpace& space, 705 const NGConstraintSpace& space,
587 const NGInflowChildData& child_data, 706 const NGInflowChildData& child_data,
588 const NGLayoutResult& layout_result) { 707 const NGLayoutResult& layout_result) {
589 // The child must be an in-flow zero-block-size fragment, use its end margin 708 // The child must be an in-flow zero-block-size fragment, use its end margin
590 // strut for positioning. 709 // strut for positioning.
591 NGFragment fragment(ConstraintSpace().WritingMode(), 710 DCHECK(IsEmptyFragment(ConstraintSpace().WritingMode(), layout_result));
592 layout_result.PhysicalFragment().Get());
593 DCHECK_EQ(fragment.BlockSize(), LayoutUnit());
594 711
595 NGLogicalOffset child_bfc_offset = { 712 NGLogicalOffset child_bfc_offset = {
596 ConstraintSpace().BfcOffset().inline_offset + 713 ConstraintSpace().BfcOffset().inline_offset +
597 border_scrollbar_padding_.inline_start + 714 border_scrollbar_padding_.inline_start +
598 child_data.margins.inline_start, 715 child_data.margins.inline_start,
599 child_data.bfc_offset_estimate.block_offset + 716 child_data.bfc_offset_estimate.block_offset +
600 layout_result.EndMarginStrut().Sum()}; 717 layout_result.EndMarginStrut().Sum()};
601 718
602 AdjustToClearance(space.ClearanceOffset(), &child_bfc_offset); 719 AdjustToClearance(space.ClearanceOffset(), &child_bfc_offset);
603 PositionPendingFloats(child_bfc_offset.block_offset, &container_builder_,
604 MutableConstraintSpace());
605 return child_bfc_offset; 720 return child_bfc_offset;
606 } 721 }
607 722
608 void NGBlockLayoutAlgorithm::FinalizeForFragmentation() { 723 void NGBlockLayoutAlgorithm::FinalizeForFragmentation() {
609 LayoutUnit used_block_size = 724 LayoutUnit used_block_size =
610 BreakToken() ? BreakToken()->UsedBlockSize() : LayoutUnit(); 725 BreakToken() ? BreakToken()->UsedBlockSize() : LayoutUnit();
611 LayoutUnit block_size = ComputeBlockSizeForFragment( 726 LayoutUnit block_size = ComputeBlockSizeForFragment(
612 ConstraintSpace(), Style(), used_block_size + content_size_); 727 ConstraintSpace(), Style(), used_block_size + content_size_);
613 728
614 block_size -= used_block_size; 729 block_size -= used_block_size;
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after
667 782
668 LayoutUnit child_inline_size = 783 LayoutUnit child_inline_size =
669 ComputeInlineSizeForFragment(*space, child_style, sizes); 784 ComputeInlineSizeForFragment(*space, child_style, sizes);
670 ApplyAutoMargins(*space, child_style, child_inline_size, &margins); 785 ApplyAutoMargins(*space, child_style, child_inline_size, &margins);
671 } 786 }
672 return margins; 787 return margins;
673 } 788 }
674 789
675 RefPtr<NGConstraintSpace> NGBlockLayoutAlgorithm::CreateConstraintSpaceForChild( 790 RefPtr<NGConstraintSpace> NGBlockLayoutAlgorithm::CreateConstraintSpaceForChild(
676 const NGLayoutInputNode child, 791 const NGLayoutInputNode child,
677 const NGInflowChildData& child_data) { 792 const NGInflowChildData& child_data,
793 const WTF::Optional<NGLogicalOffset> floats_bfc_offset) {
678 NGConstraintSpaceBuilder space_builder(MutableConstraintSpace()); 794 NGConstraintSpaceBuilder space_builder(MutableConstraintSpace());
679 space_builder.SetAvailableSize(child_available_size_) 795 space_builder.SetAvailableSize(child_available_size_)
680 .SetPercentageResolutionSize(child_percentage_size_); 796 .SetPercentageResolutionSize(child_percentage_size_);
681 797
682 bool is_new_fc = child.CreatesNewFormattingContext(); 798 bool is_new_fc = child.CreatesNewFormattingContext();
683 space_builder.SetIsNewFormattingContext(is_new_fc) 799 space_builder.SetIsNewFormattingContext(is_new_fc)
684 .SetBfcOffset(child_data.bfc_offset_estimate) 800 .SetBfcOffset(child_data.bfc_offset_estimate)
685 .SetMarginStrut(child_data.margin_strut); 801 .SetMarginStrut(child_data.margin_strut);
686 802
687 if (!is_new_fc) { 803 if (!container_builder_.BfcOffset() && ConstraintSpace().FloatsBfcOffset()) {
688 // This clears the current layout's unpositioned floats as they may be 804 space_builder.SetFloatsBfcOffset(
689 // positioned by the child. 805 NGLogicalOffset{child_data.bfc_offset_estimate.inline_offset,
690 space_builder.SetUnpositionedFloats( 806 ConstraintSpace().FloatsBfcOffset()->block_offset});
691 container_builder_.MutableUnpositionedFloats()); 807 }
808
809 if (floats_bfc_offset)
810 space_builder.SetFloatsBfcOffset(floats_bfc_offset);
811
812 if (!is_new_fc && !floats_bfc_offset) {
813 space_builder.SetUnpositionedFloats(unpositioned_floats_);
692 } 814 }
693 815
694 if (child.IsInline()) { 816 if (child.IsInline()) {
695 // TODO(kojii): Setup space_builder appropriately for inline child. 817 // TODO(kojii): Setup space_builder appropriately for inline child.
696 space_builder.SetClearanceOffset(ConstraintSpace().ClearanceOffset()); 818 space_builder.SetClearanceOffset(ConstraintSpace().ClearanceOffset());
697 return space_builder.ToConstraintSpace( 819 return space_builder.ToConstraintSpace(
698 FromPlatformWritingMode(Style().GetWritingMode())); 820 FromPlatformWritingMode(Style().GetWritingMode()));
699 } 821 }
700 822
701 const ComputedStyle& child_style = child.Style(); 823 const ComputedStyle& child_style = child.Style();
(...skipping 11 matching lines...) Expand all
713 // fragmentation line. 835 // fragmentation line.
714 if (is_new_fc) { 836 if (is_new_fc) {
715 space_available -= child_data.bfc_offset_estimate.block_offset; 837 space_available -= child_data.bfc_offset_estimate.block_offset;
716 } 838 }
717 } 839 }
718 space_builder.SetFragmentainerSpaceAvailable(space_available); 840 space_builder.SetFragmentainerSpaceAvailable(space_available);
719 841
720 return space_builder.ToConstraintSpace( 842 return space_builder.ToConstraintSpace(
721 FromPlatformWritingMode(child_style.GetWritingMode())); 843 FromPlatformWritingMode(child_style.GetWritingMode()));
722 } 844 }
845
723 } // namespace blink 846 } // namespace blink
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698