OLD | NEW |
1 // Copyright 2016 The Chromium Authors. All rights reserved. | 1 // Copyright 2016 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "core/layout/ng/ng_block_layout_algorithm.h" | 5 #include "core/layout/ng/ng_block_layout_algorithm.h" |
6 | 6 |
7 #include "core/layout/ng/ng_break_token.h" | 7 #include "core/layout/ng/ng_break_token.h" |
8 #include "core/layout/ng/ng_constraint_space.h" | 8 #include "core/layout/ng/ng_constraint_space.h" |
9 #include "core/layout/ng/ng_constraint_space_builder.h" | 9 #include "core/layout/ng/ng_constraint_space_builder.h" |
10 #include "core/layout/ng/ng_fragment_base.h" | 10 #include "core/layout/ng/ng_fragment_base.h" |
11 #include "core/layout/ng/ng_fragment_builder.h" | 11 #include "core/layout/ng/ng_fragment_builder.h" |
12 #include "core/layout/ng/ng_fragment.h" | 12 #include "core/layout/ng/ng_fragment.h" |
13 #include "core/layout/ng/ng_layout_opportunity_iterator.h" | 13 #include "core/layout/ng/ng_layout_opportunity_iterator.h" |
14 #include "core/layout/ng/ng_length_utils.h" | 14 #include "core/layout/ng/ng_length_utils.h" |
| 15 #include "core/layout/ng/ng_out_of_flow_layout_part.h" |
15 #include "core/layout/ng/ng_units.h" | 16 #include "core/layout/ng/ng_units.h" |
16 #include "core/style/ComputedStyle.h" | 17 #include "core/style/ComputedStyle.h" |
17 #include "platform/LengthFunctions.h" | 18 #include "platform/LengthFunctions.h" |
18 #include "wtf/Optional.h" | 19 #include "wtf/Optional.h" |
19 | 20 |
20 namespace blink { | 21 namespace blink { |
21 namespace { | 22 namespace { |
22 | 23 |
23 // Adjusts content's offset to CSS "clear" property. | 24 // Adjusts content's offset to CSS "clear" property. |
24 // TODO(glebl): Support margin collapsing edge cases, e.g. margin collapsing | 25 // TODO(glebl): Support margin collapsing edge cases, e.g. margin collapsing |
(...skipping 260 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
285 builder_->SetDirection(constraint_space_->Direction()); | 286 builder_->SetDirection(constraint_space_->Direction()); |
286 builder_->SetWritingMode(constraint_space_->WritingMode()); | 287 builder_->SetWritingMode(constraint_space_->WritingMode()); |
287 builder_->SetInlineSize(inline_size).SetBlockSize(block_size); | 288 builder_->SetInlineSize(inline_size).SetBlockSize(block_size); |
288 | 289 |
289 current_child_ = first_child_; | 290 current_child_ = first_child_; |
290 layout_state_ = kStatePrepareForChildLayout; | 291 layout_state_ = kStatePrepareForChildLayout; |
291 return kNotFinished; | 292 return kNotFinished; |
292 } | 293 } |
293 case kStatePrepareForChildLayout: { | 294 case kStatePrepareForChildLayout: { |
294 if (current_child_) { | 295 if (current_child_) { |
295 // TODO(atotic): uncomment this code when implementing oof layout. | 296 EPosition position = current_child_->Style()->position(); |
296 // This code cannot be turned on because it prevents layout of | 297 if ((position == AbsolutePosition || position == FixedPosition)) { |
297 // oof children, and non-layedout objects trigger a DCHECK. | 298 builder_->AddOutOfFlowChildCandidate(current_child_, |
298 // EPosition position = current_child_->Style()->position(); | 299 GetChildSpaceOffset()); |
299 // if ((position == AbsolutePosition || position == FixedPosition)) { | 300 current_child_ = current_child_->NextSibling(); |
300 // builder_->AddOutOfFlowCandidateChild(current_child_, | 301 return kNotFinished; |
301 // GetChildSpaceOffset()); | 302 } |
302 // } | |
303 // else | |
304 space_for_current_child_ = CreateConstraintSpaceForCurrentChild(); | 303 space_for_current_child_ = CreateConstraintSpaceForCurrentChild(); |
305 *algorithm_out = NGLayoutInputNode::AlgorithmForInputNode( | 304 *algorithm_out = NGLayoutInputNode::AlgorithmForInputNode( |
306 current_child_, space_for_current_child_); | 305 current_child_, space_for_current_child_); |
307 layout_state_ = kStateChildLayout; | 306 layout_state_ = kStateChildLayout; |
308 return kChildAlgorithmRequired; | 307 return kChildAlgorithmRequired; |
309 } | 308 } |
310 | 309 |
311 layout_state_ = kStateFinalize; | 310 // Prepare for kStateOutOfFlowLayout |
| 311 content_size_ += border_and_padding_.block_end; |
| 312 |
| 313 // Recompute the block-axis size now that we know our content size. |
| 314 LayoutUnit block_size = ComputeBlockSizeForFragment( |
| 315 ConstraintSpace(), Style(), content_size_); |
| 316 builder_->SetBlockSize(block_size); |
| 317 |
| 318 // Out of flow setup. |
| 319 out_of_flow_layout_ = new NGOutOfFlowLayoutPart(style_, builder_->Size()); |
| 320 builder_->GetAndClearOutOfFlowDescendantCandidates( |
| 321 &out_of_flow_candidates_, &out_of_flow_candidate_positions_); |
| 322 out_of_flow_candidate_positions_index_ = 0; |
| 323 current_child_ = nullptr; |
| 324 layout_state_ = kStateOutOfFlowLayout; |
312 return kNotFinished; | 325 return kNotFinished; |
313 } | 326 } |
314 case kStateChildLayout: { | 327 case kStateChildLayout: { |
315 DCHECK(current_child_); | 328 DCHECK(current_child_); |
316 DCHECK(child_fragment); | 329 DCHECK(child_fragment); |
317 | 330 |
318 // TODO(layout_ng): Seems like a giant hack to call this here. | 331 // TODO(layout_ng): Seems like a giant hack to call this here. |
319 current_child_->UpdateLayoutBox(toNGPhysicalFragment(child_fragment), | 332 current_child_->UpdateLayoutBox(toNGPhysicalFragment(child_fragment), |
320 space_for_current_child_); | 333 space_for_current_child_); |
321 | 334 |
322 FinishCurrentChildLayout(new NGFragment( | 335 FinishCurrentChildLayout(new NGFragment( |
323 ConstraintSpace().WritingMode(), ConstraintSpace().Direction(), | 336 ConstraintSpace().WritingMode(), ConstraintSpace().Direction(), |
324 toNGPhysicalFragment(child_fragment))); | 337 toNGPhysicalFragment(child_fragment))); |
325 current_child_ = current_child_->NextSibling(); | 338 current_child_ = current_child_->NextSibling(); |
326 layout_state_ = kStatePrepareForChildLayout; | 339 layout_state_ = kStatePrepareForChildLayout; |
327 return kNotFinished; | 340 return kNotFinished; |
328 } | 341 } |
| 342 case kStateOutOfFlowLayout: |
| 343 if (LayoutOutOfFlowChild()) |
| 344 layout_state_ = kStateFinalize; |
| 345 return kNotFinished; |
329 case kStateFinalize: { | 346 case kStateFinalize: { |
330 content_size_ += border_and_padding_.block_end; | 347 builder_->SetInlineOverflow(max_inline_size_) |
331 | |
332 // Recompute the block-axis size now that we know our content size. | |
333 LayoutUnit block_size = ComputeBlockSizeForFragment( | |
334 ConstraintSpace(), Style(), content_size_); | |
335 | |
336 builder_->SetBlockSize(block_size) | |
337 .SetInlineOverflow(max_inline_size_) | |
338 .SetBlockOverflow(content_size_); | 348 .SetBlockOverflow(content_size_); |
339 *fragment_out = builder_->ToFragment(); | 349 *fragment_out = builder_->ToFragment(); |
340 layout_state_ = kStateInit; | 350 layout_state_ = kStateInit; |
341 return kNewFragment; | 351 return kNewFragment; |
342 } | 352 } |
343 }; | 353 }; |
344 NOTREACHED(); | 354 NOTREACHED(); |
345 *fragment_out = nullptr; | 355 *fragment_out = nullptr; |
346 return kNewFragment; | 356 return kNewFragment; |
347 } | 357 } |
348 | 358 |
349 void NGBlockLayoutAlgorithm::FinishCurrentChildLayout( | 359 void NGBlockLayoutAlgorithm::FinishCurrentChildLayout( |
350 NGFragmentBase* fragment) { | 360 NGFragmentBase* fragment) { |
351 NGBoxStrut child_margins = ComputeMargins( | 361 NGBoxStrut child_margins = ComputeMargins( |
352 *space_for_current_child_, CurrentChildStyle(), | 362 *space_for_current_child_, CurrentChildStyle(), |
353 constraint_space_->WritingMode(), constraint_space_->Direction()); | 363 constraint_space_->WritingMode(), constraint_space_->Direction()); |
354 | 364 |
355 NGLogicalOffset fragment_offset; | 365 NGLogicalOffset fragment_offset; |
356 if (CurrentChildStyle().isFloating()) { | 366 if (CurrentChildStyle().isFloating()) { |
357 fragment_offset = PositionFloatFragment(*fragment, child_margins); | 367 fragment_offset = PositionFloatFragment(*fragment, child_margins); |
358 } else { | 368 } else { |
359 ApplyAutoMargins(*space_for_current_child_, CurrentChildStyle(), *fragment, | 369 ApplyAutoMargins(*space_for_current_child_, CurrentChildStyle(), *fragment, |
360 &child_margins); | 370 &child_margins); |
361 fragment_offset = PositionFragment(*fragment, child_margins); | 371 fragment_offset = PositionFragment(*fragment, child_margins); |
362 } | 372 } |
363 builder_->AddChild(fragment, fragment_offset); | 373 builder_->AddChild(fragment, fragment_offset); |
364 } | 374 } |
365 | 375 |
| 376 bool NGBlockLayoutAlgorithm::LayoutOutOfFlowChild() { |
| 377 if (!current_child_) { |
| 378 if (out_of_flow_candidates_.isEmpty()) { |
| 379 out_of_flow_layout_ = nullptr; |
| 380 out_of_flow_candidate_positions_.clear(); |
| 381 return true; |
| 382 } |
| 383 current_child_ = out_of_flow_candidates_.first(); |
| 384 out_of_flow_candidates_.removeFirst(); |
| 385 NGStaticPosition position = out_of_flow_candidate_positions_ |
| 386 [out_of_flow_candidate_positions_index_++]; |
| 387 |
| 388 if (!out_of_flow_layout_->StartLayout(current_child_, position)) { |
| 389 builder_->AddOutOfFlowDescendant(current_child_, position); |
| 390 current_child_ = nullptr; |
| 391 return false; |
| 392 } |
| 393 } |
| 394 NGFragmentBase* fragment; |
| 395 NGLogicalOffset offset; |
| 396 if (out_of_flow_layout_->Layout(&fragment, &offset) == kNewFragment) { |
| 397 // TODO(atotic) Need to adjust size of overflow rect per spec. |
| 398 builder_->AddChild(fragment, offset); |
| 399 current_child_ = nullptr; |
| 400 } |
| 401 return false; |
| 402 } |
| 403 |
366 NGBoxStrut NGBlockLayoutAlgorithm::CollapseMargins( | 404 NGBoxStrut NGBlockLayoutAlgorithm::CollapseMargins( |
367 const NGBoxStrut& margins, | 405 const NGBoxStrut& margins, |
368 const NGFragment& fragment) { | 406 const NGFragment& fragment) { |
369 bool is_zero_height_box = !fragment.BlockSize() && margins.IsEmpty() && | 407 bool is_zero_height_box = !fragment.BlockSize() && margins.IsEmpty() && |
370 fragment.MarginStrut().IsEmpty(); | 408 fragment.MarginStrut().IsEmpty(); |
371 // Create the current child's margin strut from its children's margin strut or | 409 // Create the current child's margin strut from its children's margin strut or |
372 // use margin strut from the the last non-empty child. | 410 // use margin strut from the the last non-empty child. |
373 NGMarginStrut curr_margin_strut = | 411 NGMarginStrut curr_margin_strut = |
374 is_zero_height_box ? prev_child_margin_strut_ : fragment.MarginStrut(); | 412 is_zero_height_box ? prev_child_margin_strut_ : fragment.MarginStrut(); |
375 | 413 |
(...skipping 140 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
516 DEFINE_TRACE(NGBlockLayoutAlgorithm) { | 554 DEFINE_TRACE(NGBlockLayoutAlgorithm) { |
517 NGLayoutAlgorithm::trace(visitor); | 555 NGLayoutAlgorithm::trace(visitor); |
518 visitor->trace(first_child_); | 556 visitor->trace(first_child_); |
519 visitor->trace(constraint_space_); | 557 visitor->trace(constraint_space_); |
520 visitor->trace(break_token_); | 558 visitor->trace(break_token_); |
521 visitor->trace(builder_); | 559 visitor->trace(builder_); |
522 visitor->trace(space_builder_); | 560 visitor->trace(space_builder_); |
523 visitor->trace(space_for_current_child_); | 561 visitor->trace(space_for_current_child_); |
524 visitor->trace(current_child_); | 562 visitor->trace(current_child_); |
525 visitor->trace(current_minmax_child_); | 563 visitor->trace(current_minmax_child_); |
| 564 visitor->trace(out_of_flow_layout_); |
| 565 visitor->trace(out_of_flow_candidates_); |
526 } | 566 } |
527 | 567 |
528 } // namespace blink | 568 } // namespace blink |
OLD | NEW |