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_absolute_utils.h" | 7 #include "core/layout/ng/ng_absolute_utils.h" |
8 #include "core/layout/ng/ng_block_break_token.h" | 8 #include "core/layout/ng/ng_block_break_token.h" |
9 #include "core/layout/ng/ng_block_child_iterator.h" | 9 #include "core/layout/ng/ng_block_child_iterator.h" |
10 #include "core/layout/ng/ng_box_fragment.h" | 10 #include "core/layout/ng/ng_box_fragment.h" |
(...skipping 292 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
303 | 303 |
304 } // namespace | 304 } // namespace |
305 | 305 |
306 NGBlockLayoutAlgorithm::NGBlockLayoutAlgorithm( | 306 NGBlockLayoutAlgorithm::NGBlockLayoutAlgorithm( |
307 NGBlockNode* node, | 307 NGBlockNode* node, |
308 NGConstraintSpace* constraint_space, | 308 NGConstraintSpace* constraint_space, |
309 NGBlockBreakToken* break_token) | 309 NGBlockBreakToken* break_token) |
310 : node_(node), | 310 : node_(node), |
311 constraint_space_(constraint_space), | 311 constraint_space_(constraint_space), |
312 break_token_(break_token), | 312 break_token_(break_token), |
313 builder_(WTF::wrapUnique( | 313 builder_(NGPhysicalFragment::kFragmentBox, node), |
314 new NGFragmentBuilder(NGPhysicalFragment::kFragmentBox, node))) {} | 314 space_builder_(constraint_space_) {} |
315 | 315 |
316 Optional<MinAndMaxContentSizes> | 316 Optional<MinAndMaxContentSizes> |
317 NGBlockLayoutAlgorithm::ComputeMinAndMaxContentSizes() const { | 317 NGBlockLayoutAlgorithm::ComputeMinAndMaxContentSizes() const { |
318 MinAndMaxContentSizes sizes; | 318 MinAndMaxContentSizes sizes; |
319 | 319 |
320 // Size-contained elements don't consider their contents for intrinsic sizing. | 320 // Size-contained elements don't consider their contents for intrinsic sizing. |
321 if (Style().containsSize()) | 321 if (Style().containsSize()) |
322 return sizes; | 322 return sizes; |
323 | 323 |
324 // TODO: handle floats & orthogonal children. | 324 // TODO: handle floats & orthogonal children. |
(...skipping 28 matching lines...) Expand all Loading... |
353 return sizes; | 353 return sizes; |
354 } | 354 } |
355 | 355 |
356 NGLogicalOffset NGBlockLayoutAlgorithm::CalculateLogicalOffset( | 356 NGLogicalOffset NGBlockLayoutAlgorithm::CalculateLogicalOffset( |
357 const WTF::Optional<NGLogicalOffset>& known_fragment_offset) { | 357 const WTF::Optional<NGLogicalOffset>& known_fragment_offset) { |
358 LayoutUnit inline_offset = | 358 LayoutUnit inline_offset = |
359 border_and_padding_.inline_start + curr_child_margins_.inline_start; | 359 border_and_padding_.inline_start + curr_child_margins_.inline_start; |
360 LayoutUnit block_offset = content_size_; | 360 LayoutUnit block_offset = content_size_; |
361 if (known_fragment_offset) { | 361 if (known_fragment_offset) { |
362 block_offset = known_fragment_offset.value().block_offset - | 362 block_offset = known_fragment_offset.value().block_offset - |
363 builder_->BfcOffset().value().block_offset; | 363 builder_.BfcOffset().value().block_offset; |
364 } | 364 } |
365 return {inline_offset, block_offset}; | 365 return {inline_offset, block_offset}; |
366 } | 366 } |
367 | 367 |
368 void NGBlockLayoutAlgorithm::UpdateFragmentBfcOffset( | 368 void NGBlockLayoutAlgorithm::UpdateFragmentBfcOffset( |
369 const NGLogicalOffset& offset) { | 369 const NGLogicalOffset& offset) { |
370 if (!builder_->BfcOffset()) { | 370 if (!builder_.BfcOffset()) { |
371 NGLogicalOffset bfc_offset = offset; | 371 NGLogicalOffset bfc_offset = offset; |
372 if (ConstraintSpace().ClearanceOffset()) { | 372 if (ConstraintSpace().ClearanceOffset()) { |
373 bfc_offset.block_offset = std::max( | 373 bfc_offset.block_offset = std::max( |
374 ConstraintSpace().ClearanceOffset().value(), offset.block_offset); | 374 ConstraintSpace().ClearanceOffset().value(), offset.block_offset); |
375 } | 375 } |
376 builder_->SetBfcOffset(bfc_offset); | 376 builder_.SetBfcOffset(bfc_offset); |
377 } | 377 } |
378 } | 378 } |
379 | 379 |
380 RefPtr<NGLayoutResult> NGBlockLayoutAlgorithm::Layout() { | 380 RefPtr<NGLayoutResult> NGBlockLayoutAlgorithm::Layout() { |
381 WTF::Optional<MinAndMaxContentSizes> sizes; | 381 WTF::Optional<MinAndMaxContentSizes> sizes; |
382 if (NeedMinAndMaxContentSizes(ConstraintSpace(), Style())) | 382 if (NeedMinAndMaxContentSizes(ConstraintSpace(), Style())) |
383 sizes = ComputeMinAndMaxContentSizes(); | 383 sizes = ComputeMinAndMaxContentSizes(); |
384 | 384 |
385 border_and_padding_ = ComputeBorders(ConstraintSpace(), Style()) + | 385 border_and_padding_ = ComputeBorders(ConstraintSpace(), Style()) + |
386 ComputePadding(ConstraintSpace(), Style()); | 386 ComputePadding(ConstraintSpace(), Style()); |
387 | 387 |
388 LayoutUnit inline_size = | 388 LayoutUnit inline_size = |
389 ComputeInlineSizeForFragment(ConstraintSpace(), Style(), sizes); | 389 ComputeInlineSizeForFragment(ConstraintSpace(), Style(), sizes); |
390 LayoutUnit adjusted_inline_size = | 390 LayoutUnit adjusted_inline_size = |
391 inline_size - border_and_padding_.InlineSum(); | 391 inline_size - border_and_padding_.InlineSum(); |
392 // TODO(layout-ng): For quirks mode, should we pass blockSize instead of | 392 // TODO(layout-ng): For quirks mode, should we pass blockSize instead of |
393 // -1? | 393 // -1? |
394 LayoutUnit block_size = | 394 LayoutUnit block_size = |
395 ComputeBlockSizeForFragment(ConstraintSpace(), Style(), NGSizeIndefinite); | 395 ComputeBlockSizeForFragment(ConstraintSpace(), Style(), NGSizeIndefinite); |
396 LayoutUnit adjusted_block_size(block_size); | 396 LayoutUnit adjusted_block_size(block_size); |
397 // Our calculated block-axis size may be indefinite at this point. | 397 // Our calculated block-axis size may be indefinite at this point. |
398 // If so, just leave the size as NGSizeIndefinite instead of subtracting | 398 // If so, just leave the size as NGSizeIndefinite instead of subtracting |
399 // borders and padding. | 399 // borders and padding. |
400 if (adjusted_block_size != NGSizeIndefinite) | 400 if (adjusted_block_size != NGSizeIndefinite) |
401 adjusted_block_size -= border_and_padding_.BlockSum(); | 401 adjusted_block_size -= border_and_padding_.BlockSum(); |
402 | 402 |
403 space_builder_ = new NGConstraintSpaceBuilder(constraint_space_); | |
404 space_builder_ | 403 space_builder_ |
405 ->SetAvailableSize( | 404 .SetAvailableSize( |
406 NGLogicalSize(adjusted_inline_size, adjusted_block_size)) | 405 NGLogicalSize(adjusted_inline_size, adjusted_block_size)) |
407 .SetPercentageResolutionSize( | 406 .SetPercentageResolutionSize( |
408 NGLogicalSize(adjusted_inline_size, adjusted_block_size)); | 407 NGLogicalSize(adjusted_inline_size, adjusted_block_size)); |
409 | 408 |
410 builder_->SetDirection(constraint_space_->Direction()); | 409 builder_.SetDirection(constraint_space_->Direction()); |
411 builder_->SetWritingMode(constraint_space_->WritingMode()); | 410 builder_.SetWritingMode(constraint_space_->WritingMode()); |
412 builder_->SetInlineSize(inline_size).SetBlockSize(block_size); | 411 builder_.SetInlineSize(inline_size).SetBlockSize(block_size); |
413 | 412 |
414 NGBlockChildIterator child_iterator(node_->FirstChild(), break_token_); | 413 NGBlockChildIterator child_iterator(node_->FirstChild(), break_token_); |
415 NGBlockChildIterator::Entry entry = child_iterator.NextChild(); | 414 NGBlockChildIterator::Entry entry = child_iterator.NextChild(); |
416 NGLayoutInputNode* child = entry.node; | 415 NGLayoutInputNode* child = entry.node; |
417 NGBreakToken* child_break_token = entry.token; | 416 NGBreakToken* child_break_token = entry.token; |
418 | 417 |
419 // If we are resuming from a break token our start border and padding is | 418 // If we are resuming from a break token our start border and padding is |
420 // within a previous fragment. | 419 // within a previous fragment. |
421 content_size_ = break_token_ ? LayoutUnit() : border_and_padding_.block_start; | 420 content_size_ = break_token_ ? LayoutUnit() : border_and_padding_.block_start; |
422 | 421 |
423 curr_margin_strut_ = ConstraintSpace().MarginStrut(); | 422 curr_margin_strut_ = ConstraintSpace().MarginStrut(); |
424 curr_bfc_offset_ = ConstraintSpace().BfcOffset(); | 423 curr_bfc_offset_ = ConstraintSpace().BfcOffset(); |
425 | 424 |
426 // Margins collapsing: | 425 // Margins collapsing: |
427 // Do not collapse margins between parent and its child if there is | 426 // Do not collapse margins between parent and its child if there is |
428 // border/padding between them. | 427 // border/padding between them. |
429 if (border_and_padding_.block_start) { | 428 if (border_and_padding_.block_start) { |
430 curr_bfc_offset_.block_offset += curr_margin_strut_.Sum(); | 429 curr_bfc_offset_.block_offset += curr_margin_strut_.Sum(); |
431 UpdateFragmentBfcOffset(curr_bfc_offset_); | 430 UpdateFragmentBfcOffset(curr_bfc_offset_); |
432 curr_margin_strut_ = NGMarginStrut(); | 431 curr_margin_strut_ = NGMarginStrut(); |
433 } | 432 } |
434 | 433 |
435 // Block that establishes a new BFC knows its BFC offset == {} | 434 // Block that establishes a new BFC knows its BFC offset == {} |
436 // If a new formatting context hits the if branch above then the BFC offset is | 435 // If a new formatting context hits the if branch above then the BFC offset is |
437 // still {} as the margin strut from the constraint space must also be empty. | 436 // still {} as the margin strut from the constraint space must also be empty. |
438 if (ConstraintSpace().IsNewFormattingContext()) { | 437 if (ConstraintSpace().IsNewFormattingContext()) { |
439 UpdateFragmentBfcOffset(curr_bfc_offset_); | 438 UpdateFragmentBfcOffset(curr_bfc_offset_); |
440 DCHECK_EQ(builder_->BfcOffset().value(), NGLogicalOffset()); | 439 DCHECK_EQ(builder_.BfcOffset().value(), NGLogicalOffset()); |
441 DCHECK_EQ(curr_margin_strut_, NGMarginStrut()); | 440 DCHECK_EQ(curr_margin_strut_, NGMarginStrut()); |
442 } | 441 } |
443 | 442 |
444 curr_bfc_offset_.block_offset += content_size_; | 443 curr_bfc_offset_.block_offset += content_size_; |
445 | 444 |
446 while (child) { | 445 while (child) { |
447 if (child->Type() == NGLayoutInputNode::kLegacyBlock) { | 446 if (child->Type() == NGLayoutInputNode::kLegacyBlock) { |
448 NGBlockNode* current_block_child = toNGBlockNode(child); | 447 NGBlockNode* current_block_child = toNGBlockNode(child); |
449 EPosition position = current_block_child->Style().position(); | 448 EPosition position = current_block_child->Style().position(); |
450 if (position == EPosition::kAbsolute || position == EPosition::kFixed) { | 449 if (position == EPosition::kAbsolute || position == EPosition::kFixed) { |
451 builder_->AddOutOfFlowChildCandidate(current_block_child, | 450 builder_.AddOutOfFlowChildCandidate(current_block_child, |
452 GetChildSpaceOffset()); | 451 GetChildSpaceOffset()); |
453 NGBlockChildIterator::Entry entry = child_iterator.NextChild(); | 452 NGBlockChildIterator::Entry entry = child_iterator.NextChild(); |
454 child = entry.node; | 453 child = entry.node; |
455 child_break_token = entry.token; | 454 child_break_token = entry.token; |
456 continue; | 455 continue; |
457 } | 456 } |
458 } | 457 } |
459 | 458 |
460 NGConstraintSpace* child_space = CreateConstraintSpaceForChild(child); | 459 NGConstraintSpace* child_space = CreateConstraintSpaceForChild(child); |
461 | 460 |
462 if (child->Type() == NGLayoutInputNode::kLegacyInline) { | 461 if (child->Type() == NGLayoutInputNode::kLegacyInline) { |
(...skipping 21 matching lines...) Expand all Loading... |
484 content_size_ += border_and_padding_.block_end; | 483 content_size_ += border_and_padding_.block_end; |
485 if (border_and_padding_.block_end || | 484 if (border_and_padding_.block_end || |
486 ConstraintSpace().IsNewFormattingContext()) { | 485 ConstraintSpace().IsNewFormattingContext()) { |
487 content_size_ += curr_margin_strut_.Sum(); | 486 content_size_ += curr_margin_strut_.Sum(); |
488 curr_margin_strut_ = NGMarginStrut(); | 487 curr_margin_strut_ = NGMarginStrut(); |
489 } | 488 } |
490 | 489 |
491 // Recompute the block-axis size now that we know our content size. | 490 // Recompute the block-axis size now that we know our content size. |
492 block_size = | 491 block_size = |
493 ComputeBlockSizeForFragment(ConstraintSpace(), Style(), content_size_); | 492 ComputeBlockSizeForFragment(ConstraintSpace(), Style(), content_size_); |
494 builder_->SetBlockSize(block_size); | 493 builder_.SetBlockSize(block_size); |
495 | 494 |
496 // Layout our absolute and fixed positioned children. | 495 // Layout our absolute and fixed positioned children. |
497 NGOutOfFlowLayoutPart(ConstraintSpace(), Style(), builder_.get()).Run(); | 496 NGOutOfFlowLayoutPart(ConstraintSpace(), Style(), &builder_).Run(); |
498 | 497 |
499 // Non-empty blocks always know their position in space: | 498 // Non-empty blocks always know their position in space: |
500 if (block_size) { | 499 if (block_size) { |
501 curr_bfc_offset_.block_offset += curr_margin_strut_.Sum(); | 500 curr_bfc_offset_.block_offset += curr_margin_strut_.Sum(); |
502 UpdateFragmentBfcOffset(curr_bfc_offset_); | 501 UpdateFragmentBfcOffset(curr_bfc_offset_); |
503 PositionPendingFloats(curr_bfc_offset_.block_offset, ConstraintSpace(), | 502 PositionPendingFloats(curr_bfc_offset_.block_offset, ConstraintSpace(), |
504 builder_.get()); | 503 &builder_); |
505 } | 504 } |
506 | 505 |
507 // Margins collapsing: | 506 // Margins collapsing: |
508 // Do not collapse margins between the last in-flow child and bottom margin | 507 // Do not collapse margins between the last in-flow child and bottom margin |
509 // of its parent if the parent has height != auto() | 508 // of its parent if the parent has height != auto() |
510 if (!Style().logicalHeight().isAuto()) { | 509 if (!Style().logicalHeight().isAuto()) { |
511 // TODO(glebl): handle minLogicalHeight, maxLogicalHeight. | 510 // TODO(glebl): handle minLogicalHeight, maxLogicalHeight. |
512 curr_margin_strut_ = NGMarginStrut(); | 511 curr_margin_strut_ = NGMarginStrut(); |
513 } | 512 } |
514 builder_->SetEndMarginStrut(curr_margin_strut_); | 513 builder_.SetEndMarginStrut(curr_margin_strut_); |
515 | 514 |
516 builder_->SetInlineOverflow(max_inline_size_).SetBlockOverflow(content_size_); | 515 builder_.SetInlineOverflow(max_inline_size_).SetBlockOverflow(content_size_); |
517 | 516 |
518 if (ConstraintSpace().HasBlockFragmentation()) | 517 if (ConstraintSpace().HasBlockFragmentation()) |
519 FinalizeForFragmentation(); | 518 FinalizeForFragmentation(); |
520 | 519 |
521 return builder_->ToBoxFragment(); | 520 return builder_.ToBoxFragment(); |
522 } | 521 } |
523 | 522 |
524 void NGBlockLayoutAlgorithm::LayoutInlineChildren( | 523 void NGBlockLayoutAlgorithm::LayoutInlineChildren( |
525 NGInlineNode* inline_child, | 524 NGInlineNode* inline_child, |
526 NGConstraintSpace* child_space) { | 525 NGConstraintSpace* child_space) { |
527 // TODO(kojii): This logic does not handle when children are mix of | 526 // TODO(kojii): This logic does not handle when children are mix of |
528 // inline/block. We need to detect the case and setup appropriately; e.g., | 527 // inline/block. We need to detect the case and setup appropriately; e.g., |
529 // constraint space, margin collapsing, next siblings, etc. | 528 // constraint space, margin collapsing, next siblings, etc. |
530 NGLineBuilder line_builder(inline_child, child_space); | 529 NGLineBuilder line_builder(inline_child, child_space); |
531 // TODO(kojii): Need to determine when to invalidate PrepareLayout() more | 530 // TODO(kojii): Need to determine when to invalidate PrepareLayout() more |
(...skipping 14 matching lines...) Expand all Loading... |
546 NGLayoutInputNode* child, | 545 NGLayoutInputNode* child, |
547 NGConstraintSpace* child_space, | 546 NGConstraintSpace* child_space, |
548 RefPtr<NGLayoutResult> layout_result) { | 547 RefPtr<NGLayoutResult> layout_result) { |
549 NGBoxFragment fragment( | 548 NGBoxFragment fragment( |
550 ConstraintSpace().WritingMode(), | 549 ConstraintSpace().WritingMode(), |
551 toNGPhysicalBoxFragment(layout_result->PhysicalFragment().get())); | 550 toNGPhysicalBoxFragment(layout_result->PhysicalFragment().get())); |
552 | 551 |
553 // Pull out unpositioned floats to the current fragment. This may needed if | 552 // Pull out unpositioned floats to the current fragment. This may needed if |
554 // for example the child fragment could not position its floats because it's | 553 // for example the child fragment could not position its floats because it's |
555 // empty and therefore couldn't determine its position in space. | 554 // empty and therefore couldn't determine its position in space. |
556 builder_->MutableUnpositionedFloats().appendVector( | 555 builder_.MutableUnpositionedFloats().appendVector( |
557 layout_result->UnpositionedFloats()); | 556 layout_result->UnpositionedFloats()); |
558 | 557 |
559 if (child->Type() == NGLayoutInputNode::kLegacyBlock && | 558 if (child->Type() == NGLayoutInputNode::kLegacyBlock && |
560 toNGBlockNode(child)->Style().isFloating()) { | 559 toNGBlockNode(child)->Style().isFloating()) { |
561 NGFloatingObject* floating_object = new NGFloatingObject( | 560 NGFloatingObject* floating_object = new NGFloatingObject( |
562 layout_result->PhysicalFragment().get(), child_space, constraint_space_, | 561 layout_result->PhysicalFragment().get(), child_space, constraint_space_, |
563 toNGBlockNode(child), toNGBlockNode(child)->Style(), | 562 toNGBlockNode(child), toNGBlockNode(child)->Style(), |
564 curr_child_margins_); | 563 curr_child_margins_); |
565 builder_->AddUnpositionedFloat(floating_object); | 564 builder_.AddUnpositionedFloat(floating_object); |
566 // No need to postpone the positioning if we know the correct offset. | 565 // No need to postpone the positioning if we know the correct offset. |
567 if (builder_->BfcOffset()) { | 566 if (builder_.BfcOffset()) { |
568 NGLogicalOffset origin_point = curr_bfc_offset_; | 567 NGLogicalOffset origin_point = curr_bfc_offset_; |
569 // Adjust origin point to the margins of the last child. | 568 // Adjust origin point to the margins of the last child. |
570 // Example: <div style="margin-bottom: 20px"><float></div> | 569 // Example: <div style="margin-bottom: 20px"><float></div> |
571 // <div style="margin-bottom: 30px"></div> | 570 // <div style="margin-bottom: 30px"></div> |
572 origin_point.block_offset += curr_margin_strut_.Sum(); | 571 origin_point.block_offset += curr_margin_strut_.Sum(); |
573 PositionPendingFloats(origin_point.block_offset, ConstraintSpace(), | 572 PositionPendingFloats(origin_point.block_offset, ConstraintSpace(), |
574 builder_.get()); | 573 &builder_); |
575 } | 574 } |
576 return; | 575 return; |
577 } | 576 } |
578 | 577 |
579 // Determine the fragment's position in the parent space either by using | 578 // Determine the fragment's position in the parent space either by using |
580 // content_size_ or known fragment's BFC offset. | 579 // content_size_ or known fragment's BFC offset. |
581 WTF::Optional<NGLogicalOffset> bfc_offset; | 580 WTF::Optional<NGLogicalOffset> bfc_offset; |
582 if (child_space->IsNewFormattingContext()) { | 581 if (child_space->IsNewFormattingContext()) { |
583 // TODO(ikilpatrick): We may need to place ourself within the BFC | 582 // TODO(ikilpatrick): We may need to place ourself within the BFC |
584 // before a new formatting context child is laid out. (Not after layout as | 583 // before a new formatting context child is laid out. (Not after layout as |
585 // is done here). | 584 // is done here). |
586 curr_bfc_offset_.block_offset += curr_margin_strut_.Sum(); | 585 curr_bfc_offset_.block_offset += curr_margin_strut_.Sum(); |
587 bfc_offset = curr_bfc_offset_; | 586 bfc_offset = curr_bfc_offset_; |
588 } else if (fragment.BfcOffset()) { | 587 } else if (fragment.BfcOffset()) { |
589 // Fragment that knows its offset can be used to set parent's BFC position. | 588 // Fragment that knows its offset can be used to set parent's BFC position. |
590 curr_bfc_offset_.block_offset = fragment.BfcOffset().value().block_offset; | 589 curr_bfc_offset_.block_offset = fragment.BfcOffset().value().block_offset; |
591 bfc_offset = curr_bfc_offset_; | 590 bfc_offset = curr_bfc_offset_; |
592 } else if (builder_->BfcOffset()) { | 591 } else if (builder_.BfcOffset()) { |
593 // Fragment doesn't know its offset but we can still calculate its BFC | 592 // Fragment doesn't know its offset but we can still calculate its BFC |
594 // position because the parent fragment's BFC is known. | 593 // position because the parent fragment's BFC is known. |
595 // Example: | 594 // Example: |
596 // BFC Offset is known here because of the padding. | 595 // BFC Offset is known here because of the padding. |
597 // <div style="padding: 1px"> | 596 // <div style="padding: 1px"> |
598 // <div id="empty-div" style="margins: 1px"></div> | 597 // <div id="empty-div" style="margins: 1px"></div> |
599 bfc_offset = curr_bfc_offset_; | 598 bfc_offset = curr_bfc_offset_; |
600 bfc_offset.value().block_offset += curr_margin_strut_.Sum(); | 599 bfc_offset.value().block_offset += curr_margin_strut_.Sum(); |
601 } | 600 } |
602 if (bfc_offset) { | 601 if (bfc_offset) { |
603 UpdateFragmentBfcOffset(curr_bfc_offset_); | 602 UpdateFragmentBfcOffset(curr_bfc_offset_); |
604 PositionPendingFloats(curr_bfc_offset_.block_offset, ConstraintSpace(), | 603 PositionPendingFloats(curr_bfc_offset_.block_offset, ConstraintSpace(), |
605 builder_.get()); | 604 &builder_); |
606 } | 605 } |
607 NGLogicalOffset logical_offset = CalculateLogicalOffset(bfc_offset); | 606 NGLogicalOffset logical_offset = CalculateLogicalOffset(bfc_offset); |
608 | 607 |
609 // Update margin strut. | 608 // Update margin strut. |
610 curr_margin_strut_ = fragment.EndMarginStrut(); | 609 curr_margin_strut_ = fragment.EndMarginStrut(); |
611 curr_margin_strut_.Append(curr_child_margins_.block_end); | 610 curr_margin_strut_.Append(curr_child_margins_.block_end); |
612 | 611 |
613 // Only modify content_size if BlockSize is not empty. It's needed to prevent | 612 // Only modify content_size if BlockSize is not empty. It's needed to prevent |
614 // the situation when logical_offset is included in content_size for empty | 613 // the situation when logical_offset is included in content_size for empty |
615 // blocks. Example: | 614 // blocks. Example: |
616 // <div style="overflow:hidden"> | 615 // <div style="overflow:hidden"> |
617 // <div style="margin-top: 8px"></div> | 616 // <div style="margin-top: 8px"></div> |
618 // <div style="margin-top: 10px"></div> | 617 // <div style="margin-top: 10px"></div> |
619 // </div> | 618 // </div> |
620 if (fragment.BlockSize()) | 619 if (fragment.BlockSize()) |
621 content_size_ = fragment.BlockSize() + logical_offset.block_offset; | 620 content_size_ = fragment.BlockSize() + logical_offset.block_offset; |
622 max_inline_size_ = | 621 max_inline_size_ = |
623 std::max(max_inline_size_, fragment.InlineSize() + | 622 std::max(max_inline_size_, fragment.InlineSize() + |
624 curr_child_margins_.InlineSum() + | 623 curr_child_margins_.InlineSum() + |
625 border_and_padding_.InlineSum()); | 624 border_and_padding_.InlineSum()); |
626 | 625 |
627 builder_->AddChild(layout_result, logical_offset); | 626 builder_.AddChild(layout_result, logical_offset); |
628 } | 627 } |
629 | 628 |
630 void NGBlockLayoutAlgorithm::FinalizeForFragmentation() { | 629 void NGBlockLayoutAlgorithm::FinalizeForFragmentation() { |
631 LayoutUnit used_block_size = | 630 LayoutUnit used_block_size = |
632 break_token_ ? break_token_->UsedBlockSize() : LayoutUnit(); | 631 break_token_ ? break_token_->UsedBlockSize() : LayoutUnit(); |
633 LayoutUnit block_size = ComputeBlockSizeForFragment( | 632 LayoutUnit block_size = ComputeBlockSizeForFragment( |
634 ConstraintSpace(), Style(), used_block_size + content_size_); | 633 ConstraintSpace(), Style(), used_block_size + content_size_); |
635 | 634 |
636 block_size -= used_block_size; | 635 block_size -= used_block_size; |
637 DCHECK_GE(block_size, LayoutUnit()) | 636 DCHECK_GE(block_size, LayoutUnit()) |
638 << "Adding and subtracting the used_block_size shouldn't leave the " | 637 << "Adding and subtracting the used_block_size shouldn't leave the " |
639 "block_size for this fragment smaller than zero."; | 638 "block_size for this fragment smaller than zero."; |
640 | 639 |
641 DCHECK(builder_->BfcOffset()) << "We must have our BfcOffset by this point " | 640 DCHECK(builder_.BfcOffset()) << "We must have our BfcOffset by this point " |
642 "to determine the space left in the flow."; | 641 "to determine the space left in the flow."; |
643 LayoutUnit space_left = ConstraintSpace().FragmentainerSpaceAvailable() - | 642 LayoutUnit space_left = ConstraintSpace().FragmentainerSpaceAvailable() - |
644 builder_->BfcOffset().value().block_offset; | 643 builder_.BfcOffset().value().block_offset; |
645 DCHECK_GE(space_left, LayoutUnit()); | 644 DCHECK_GE(space_left, LayoutUnit()); |
646 | 645 |
647 if (builder_->DidBreak()) { | 646 if (builder_.DidBreak()) { |
648 // One of our children broke. Even if we fit within the remaining space we | 647 // One of our children broke. Even if we fit within the remaining space we |
649 // need to prepare a break token. | 648 // need to prepare a break token. |
650 builder_->SetUsedBlockSize(std::min(space_left, block_size) + | 649 builder_.SetUsedBlockSize(std::min(space_left, block_size) + |
651 used_block_size); | 650 used_block_size); |
652 builder_->SetBlockSize(std::min(space_left, block_size)); | 651 builder_.SetBlockSize(std::min(space_left, block_size)); |
653 builder_->SetBlockOverflow(space_left); | 652 builder_.SetBlockOverflow(space_left); |
654 return; | 653 return; |
655 } | 654 } |
656 | 655 |
657 if (block_size > space_left) { | 656 if (block_size > space_left) { |
658 // Need a break inside this block. | 657 // Need a break inside this block. |
659 builder_->SetUsedBlockSize(space_left + used_block_size); | 658 builder_.SetUsedBlockSize(space_left + used_block_size); |
660 builder_->SetBlockSize(space_left); | 659 builder_.SetBlockSize(space_left); |
661 builder_->SetBlockOverflow(space_left); | 660 builder_.SetBlockOverflow(space_left); |
662 return; | 661 return; |
663 } | 662 } |
664 | 663 |
665 // The end of the block fits in the current fragmentainer. | 664 // The end of the block fits in the current fragmentainer. |
666 builder_->SetBlockSize(block_size); | 665 builder_.SetBlockSize(block_size); |
667 builder_->SetBlockOverflow(content_size_); | 666 builder_.SetBlockOverflow(content_size_); |
668 } | 667 } |
669 | 668 |
670 NGBoxStrut NGBlockLayoutAlgorithm::CalculateMargins( | 669 NGBoxStrut NGBlockLayoutAlgorithm::CalculateMargins( |
671 NGBlockNode* child, | 670 NGBlockNode* child, |
672 const NGConstraintSpace& space) { | 671 const NGConstraintSpace& space) { |
673 DCHECK(child); | 672 DCHECK(child); |
674 const ComputedStyle& child_style = child->Style(); | 673 const ComputedStyle& child_style = child->Style(); |
675 | 674 |
676 WTF::Optional<MinAndMaxContentSizes> sizes; | 675 WTF::Optional<MinAndMaxContentSizes> sizes; |
677 if (NeedMinAndMaxContentSizes(space, child_style)) | 676 if (NeedMinAndMaxContentSizes(space, child_style)) |
(...skipping 13 matching lines...) Expand all Loading... |
691 NGLayoutInputNode* child) { | 690 NGLayoutInputNode* child) { |
692 DCHECK(child); | 691 DCHECK(child); |
693 | 692 |
694 if (child->Type() == NGLayoutInputNode::kLegacyInline) { | 693 if (child->Type() == NGLayoutInputNode::kLegacyInline) { |
695 // TODO(kojii): Setup space_builder_ appropriately for inline child. | 694 // TODO(kojii): Setup space_builder_ appropriately for inline child. |
696 | 695 |
697 // Margins collapsing: Inline block. | 696 // Margins collapsing: Inline block. |
698 curr_bfc_offset_.block_offset += curr_margin_strut_.Sum(); | 697 curr_bfc_offset_.block_offset += curr_margin_strut_.Sum(); |
699 UpdateFragmentBfcOffset(curr_bfc_offset_); | 698 UpdateFragmentBfcOffset(curr_bfc_offset_); |
700 PositionPendingFloats(curr_bfc_offset_.block_offset, ConstraintSpace(), | 699 PositionPendingFloats(curr_bfc_offset_.block_offset, ConstraintSpace(), |
701 builder_.get()); | 700 &builder_); |
702 curr_margin_strut_ = {}; | 701 curr_margin_strut_ = {}; |
703 | 702 |
704 return space_builder_->ToConstraintSpace( | 703 return space_builder_.ToConstraintSpace( |
705 FromPlatformWritingMode(Style().getWritingMode())); | 704 FromPlatformWritingMode(Style().getWritingMode())); |
706 } | 705 } |
707 | 706 |
708 NGBlockNode* block_child = toNGBlockNode(child); | 707 NGBlockNode* block_child = toNGBlockNode(child); |
709 const ComputedStyle& child_style = block_child->Style(); | 708 const ComputedStyle& child_style = block_child->Style(); |
710 | 709 |
711 // Calculate margins in parent's writing mode. | 710 // Calculate margins in parent's writing mode. |
712 curr_child_margins_ = CalculateMargins( | 711 curr_child_margins_ = CalculateMargins( |
713 block_child, *space_builder_->ToConstraintSpace( | 712 block_child, *space_builder_.ToConstraintSpace( |
714 FromPlatformWritingMode(Style().getWritingMode()))); | 713 FromPlatformWritingMode(Style().getWritingMode()))); |
715 | 714 |
716 bool is_new_bfc = IsNewFormattingContextForInFlowBlockLevelChild( | 715 bool is_new_bfc = IsNewFormattingContextForInFlowBlockLevelChild( |
717 ConstraintSpace(), child_style); | 716 ConstraintSpace(), child_style); |
718 space_builder_->SetIsNewFormattingContext(is_new_bfc) | 717 space_builder_.SetIsNewFormattingContext(is_new_bfc) |
719 .SetIsShrinkToFit(ShouldShrinkToFit(ConstraintSpace(), child_style)) | 718 .SetIsShrinkToFit(ShouldShrinkToFit(ConstraintSpace(), child_style)) |
720 .SetTextDirection(child_style.direction()); | 719 .SetTextDirection(child_style.direction()); |
721 | 720 |
722 // Clearance : | 721 // Clearance : |
723 // - *Always* collapse margins and update *container*'s BFC offset. | 722 // - *Always* collapse margins and update *container*'s BFC offset. |
724 // - Position all pending floats since the fragment's BFC offset is known. | 723 // - Position all pending floats since the fragment's BFC offset is known. |
725 // - Set the clearance offset on the constraint space's builder. | 724 // - Set the clearance offset on the constraint space's builder. |
726 if (child_style.clear() != EClear::kNone) { | 725 if (child_style.clear() != EClear::kNone) { |
727 curr_bfc_offset_.block_offset += curr_margin_strut_.Sum(); | 726 curr_bfc_offset_.block_offset += curr_margin_strut_.Sum(); |
728 UpdateFragmentBfcOffset(curr_bfc_offset_); | 727 UpdateFragmentBfcOffset(curr_bfc_offset_); |
729 // Only collapse margins if it's an adjoining block with clearance. | 728 // Only collapse margins if it's an adjoining block with clearance. |
730 if (!content_size_) { | 729 if (!content_size_) { |
731 curr_margin_strut_ = NGMarginStrut(); | 730 curr_margin_strut_ = NGMarginStrut(); |
732 curr_child_margins_.block_start = LayoutUnit(); | 731 curr_child_margins_.block_start = LayoutUnit(); |
733 } | 732 } |
734 PositionPendingFloats(curr_bfc_offset_.block_offset, ConstraintSpace(), | 733 PositionPendingFloats(curr_bfc_offset_.block_offset, ConstraintSpace(), |
735 builder_.get()); | 734 &builder_); |
736 WTF::Optional<LayoutUnit> clearance_offset = | 735 WTF::Optional<LayoutUnit> clearance_offset = |
737 GetClearanceOffset(constraint_space_->Exclusions(), child_style); | 736 GetClearanceOffset(constraint_space_->Exclusions(), child_style); |
738 space_builder_->SetClearanceOffset(clearance_offset); | 737 space_builder_.SetClearanceOffset(clearance_offset); |
739 } | 738 } |
740 | 739 |
741 // Set estimated BFC offset to the next child's constraint space. | 740 // Set estimated BFC offset to the next child's constraint space. |
742 curr_bfc_offset_ = builder_->BfcOffset() ? builder_->BfcOffset().value() | 741 curr_bfc_offset_ = builder_.BfcOffset() ? builder_.BfcOffset().value() |
743 : ConstraintSpace().BfcOffset(); | 742 : ConstraintSpace().BfcOffset(); |
744 curr_bfc_offset_.block_offset += content_size_; | 743 curr_bfc_offset_.block_offset += content_size_; |
745 curr_bfc_offset_.inline_offset += border_and_padding_.inline_start; | 744 curr_bfc_offset_.inline_offset += border_and_padding_.inline_start; |
746 | 745 |
747 // Floats margins are not included in child's CS because | 746 // Floats margins are not included in child's CS because |
748 // 1) Floats do not participate in margins collapsing | 747 // 1) Floats do not participate in margins collapsing |
749 // 2) Floats margins are used separately to calculate floating exclusions. | 748 // 2) Floats margins are used separately to calculate floating exclusions. |
750 if (!child_style.isFloating()) { | 749 if (!child_style.isFloating()) { |
751 curr_bfc_offset_.inline_offset += curr_child_margins_.inline_start; | 750 curr_bfc_offset_.inline_offset += curr_child_margins_.inline_start; |
752 // Append the current margin strut with child's block start margin. | 751 // Append the current margin strut with child's block start margin. |
753 // Non empty border/padding use cases are handled inside of the child's | 752 // Non empty border/padding use cases are handled inside of the child's |
754 // layout. | 753 // layout. |
755 curr_margin_strut_.Append(curr_child_margins_.block_start); | 754 curr_margin_strut_.Append(curr_child_margins_.block_start); |
756 space_builder_->SetMarginStrut(curr_margin_strut_); | 755 space_builder_.SetMarginStrut(curr_margin_strut_); |
757 } | 756 } |
758 | 757 |
759 space_builder_->SetBfcOffset(curr_bfc_offset_); | 758 space_builder_.SetBfcOffset(curr_bfc_offset_); |
760 | 759 |
761 LayoutUnit space_available; | 760 LayoutUnit space_available; |
762 if (constraint_space_->HasBlockFragmentation()) { | 761 if (constraint_space_->HasBlockFragmentation()) { |
763 space_available = ConstraintSpace().FragmentainerSpaceAvailable(); | 762 space_available = ConstraintSpace().FragmentainerSpaceAvailable(); |
764 // If a block establishes a new formatting context we must know our | 763 // If a block establishes a new formatting context we must know our |
765 // position in the formatting context, and are able to adjust the | 764 // position in the formatting context, and are able to adjust the |
766 // fragmentation line. | 765 // fragmentation line. |
767 if (is_new_bfc) { | 766 if (is_new_bfc) { |
768 DCHECK(builder_->BfcOffset()); | 767 DCHECK(builder_.BfcOffset()); |
769 space_available -= curr_bfc_offset_.block_offset; | 768 space_available -= curr_bfc_offset_.block_offset; |
770 } | 769 } |
771 } | 770 } |
772 space_builder_->SetFragmentainerSpaceAvailable(space_available); | 771 space_builder_.SetFragmentainerSpaceAvailable(space_available); |
773 | 772 |
774 return space_builder_->ToConstraintSpace( | 773 return space_builder_.ToConstraintSpace( |
775 FromPlatformWritingMode(child_style.getWritingMode())); | 774 FromPlatformWritingMode(child_style.getWritingMode())); |
776 } | 775 } |
777 } // namespace blink | 776 } // namespace blink |
OLD | NEW |