| 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 |