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_box_fragment.h" | 9 #include "core/layout/ng/ng_box_fragment.h" |
10 #include "core/layout/ng/ng_column_mapper.h" | 10 #include "core/layout/ng/ng_column_mapper.h" |
(...skipping 282 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
293 | 293 |
294 if (space.WritingMode() != FromPlatformWritingMode(style.getWritingMode())) | 294 if (space.WritingMode() != FromPlatformWritingMode(style.getWritingMode())) |
295 return true; | 295 return true; |
296 | 296 |
297 return false; | 297 return false; |
298 } | 298 } |
299 | 299 |
300 } // namespace | 300 } // namespace |
301 | 301 |
302 NGBlockLayoutAlgorithm::NGBlockLayoutAlgorithm( | 302 NGBlockLayoutAlgorithm::NGBlockLayoutAlgorithm( |
303 LayoutObject* layout_object, | 303 NGBlockNode* node, |
304 PassRefPtr<const ComputedStyle> style, | |
305 NGLayoutInputNode* first_child, | |
306 NGConstraintSpace* constraint_space, | 304 NGConstraintSpace* constraint_space, |
307 NGBreakToken* break_token) | 305 NGBlockBreakToken* break_token) |
308 : style_(style), | 306 : style_(node->Style()), |
309 first_child_(first_child), | 307 first_child_(node->FirstChild()), |
310 constraint_space_(constraint_space), | 308 constraint_space_(constraint_space), |
311 break_token_(break_token), | 309 break_token_(break_token), |
312 builder_(WTF::wrapUnique( | 310 builder_(WTF::wrapUnique( |
313 new NGFragmentBuilder(NGPhysicalFragment::kFragmentBox, | 311 new NGFragmentBuilder(NGPhysicalFragment::kFragmentBox, node))), |
314 layout_object))) { | 312 child_iterator_(WTF::wrapUnique( |
313 new NGBlockLayoutChildIterator(first_child_, break_token))) { | |
315 DCHECK(style_); | 314 DCHECK(style_); |
316 } | 315 } |
317 | 316 |
318 Optional<MinAndMaxContentSizes> | 317 Optional<MinAndMaxContentSizes> |
319 NGBlockLayoutAlgorithm::ComputeMinAndMaxContentSizes() const { | 318 NGBlockLayoutAlgorithm::ComputeMinAndMaxContentSizes() const { |
320 MinAndMaxContentSizes sizes; | 319 MinAndMaxContentSizes sizes; |
321 | 320 |
322 // Size-contained elements don't consider their contents for intrinsic sizing. | 321 // Size-contained elements don't consider their contents for intrinsic sizing. |
323 if (Style().containsSize()) | 322 if (Style().containsSize()) |
324 return sizes; | 323 return sizes; |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
357 builder_->BfcOffset().value().block_offset; | 356 builder_->BfcOffset().value().block_offset; |
358 } | 357 } |
359 return {inline_offset, block_offset}; | 358 return {inline_offset, block_offset}; |
360 } | 359 } |
361 | 360 |
362 RefPtr<NGPhysicalFragment> NGBlockLayoutAlgorithm::Layout() { | 361 RefPtr<NGPhysicalFragment> NGBlockLayoutAlgorithm::Layout() { |
363 WTF::Optional<MinAndMaxContentSizes> sizes; | 362 WTF::Optional<MinAndMaxContentSizes> sizes; |
364 if (NeedMinAndMaxContentSizes(ConstraintSpace(), Style())) | 363 if (NeedMinAndMaxContentSizes(ConstraintSpace(), Style())) |
365 sizes = ComputeMinAndMaxContentSizes(); | 364 sizes = ComputeMinAndMaxContentSizes(); |
366 | 365 |
366 // TODO(ikilpatrick): should be no borders or padding if anon. | |
367 border_and_padding_ = | 367 border_and_padding_ = |
368 ComputeBorders(Style()) + ComputePadding(ConstraintSpace(), Style()); | 368 ComputeBorders(Style()) + ComputePadding(ConstraintSpace(), Style()); |
369 | 369 |
370 LayoutUnit inline_size = | 370 LayoutUnit inline_size = |
371 ComputeInlineSizeForFragment(ConstraintSpace(), Style(), sizes); | 371 ComputeInlineSizeForFragment(ConstraintSpace(), Style(), sizes); |
372 LayoutUnit adjusted_inline_size = | 372 LayoutUnit adjusted_inline_size = |
373 inline_size - border_and_padding_.InlineSum(); | 373 inline_size - border_and_padding_.InlineSum(); |
374 // TODO(layout-ng): For quirks mode, should we pass blockSize instead of | 374 // TODO(layout-ng): For quirks mode, should we pass blockSize instead of |
375 // -1? | 375 // -1? |
376 LayoutUnit block_size = | 376 LayoutUnit block_size = |
377 ComputeBlockSizeForFragment(ConstraintSpace(), Style(), NGSizeIndefinite); | 377 ComputeBlockSizeForFragment(ConstraintSpace(), Style(), NGSizeIndefinite); |
378 LayoutUnit adjusted_block_size(block_size); | 378 LayoutUnit adjusted_block_size(block_size); |
379 // Our calculated block-axis size may be indefinite at this point. | 379 // Our calculated block-axis size may be indefinite at this point. |
380 // If so, just leave the size as NGSizeIndefinite instead of subtracting | 380 // If so, just leave the size as NGSizeIndefinite instead of subtracting |
381 // borders and padding. | 381 // borders and padding. |
382 if (adjusted_block_size != NGSizeIndefinite) | 382 if (adjusted_block_size != NGSizeIndefinite) |
383 adjusted_block_size -= border_and_padding_.BlockSum(); | 383 adjusted_block_size -= border_and_padding_.BlockSum(); |
384 | 384 |
385 space_builder_ = new NGConstraintSpaceBuilder(constraint_space_); | 385 space_builder_ = new NGConstraintSpaceBuilder(constraint_space_); |
386 if (Style().specifiesColumns()) { | 386 space_builder_ |
387 space_builder_->SetFragmentationType(kFragmentColumn); | 387 ->SetAvailableSize( |
388 adjusted_inline_size = | 388 NGLogicalSize(adjusted_inline_size, adjusted_block_size)) |
389 ResolveUsedColumnInlineSize(adjusted_inline_size, Style()); | 389 .SetPercentageResolutionSize( |
390 LayoutUnit inline_progression = | 390 NGLogicalSize(adjusted_inline_size, adjusted_block_size)); |
391 adjusted_inline_size + ResolveUsedColumnGap(Style()); | |
392 fragmentainer_mapper_ = | |
393 new NGColumnMapper(inline_progression, adjusted_block_size); | |
394 } | |
395 space_builder_->SetAvailableSize( | |
396 NGLogicalSize(adjusted_inline_size, adjusted_block_size)); | |
397 space_builder_->SetPercentageResolutionSize( | |
398 NGLogicalSize(adjusted_inline_size, adjusted_block_size)); | |
399 | 391 |
400 builder_->SetDirection(constraint_space_->Direction()); | 392 builder_->SetDirection(constraint_space_->Direction()); |
401 builder_->SetWritingMode(constraint_space_->WritingMode()); | 393 builder_->SetWritingMode(constraint_space_->WritingMode()); |
402 builder_->SetInlineSize(inline_size).SetBlockSize(block_size); | 394 builder_->SetInlineSize(inline_size).SetBlockSize(block_size); |
403 | 395 |
404 // TODO(glebl): fix multicol after the new margin collapsing/floats algorithm | 396 std::tie(current_child_, current_child_break_token_) = |
405 // based on BFCOffset is checked in. | 397 child_iterator_->NextChild(); |
406 if (NGBlockBreakToken* token = CurrentBlockBreakToken()) { | 398 |
407 // Resume after a previous break. | 399 content_size_ = |
408 content_size_ = token->BreakOffset(); | 400 break_token_ ? LayoutUnit(0) : border_and_padding_.block_start; |
mstensho (USE GERRIT)
2017/02/15 21:12:22
Should use LayoutUnit() instead of LayoutUnit(0),
| |
409 current_child_ = token->InputNode(); | |
410 } else { | |
411 content_size_ = border_and_padding_.block_start; | |
412 current_child_ = first_child_; | |
413 } | |
414 | 401 |
415 curr_margin_strut_ = ConstraintSpace().MarginStrut(); | 402 curr_margin_strut_ = ConstraintSpace().MarginStrut(); |
416 curr_bfc_offset_ = ConstraintSpace().BfcOffset(); | 403 curr_bfc_offset_ = ConstraintSpace().BfcOffset(); |
417 | 404 |
418 // Margins collapsing: | 405 // Margins collapsing: |
419 // Do not collapse margins between parent and its child if there is | 406 // Do not collapse margins between parent and its child if there is |
420 // border/padding between them. | 407 // border/padding between them. |
421 if (border_and_padding_.block_start || | 408 if (border_and_padding_.block_start || |
422 ConstraintSpace().IsNewFormattingContext()) { | 409 ConstraintSpace().IsNewFormattingContext()) { |
423 curr_bfc_offset_.block_offset += curr_margin_strut_.Sum(); | 410 curr_bfc_offset_.block_offset += curr_margin_strut_.Sum(); |
424 builder_->SetBfcOffset(curr_bfc_offset_); | 411 builder_->SetBfcOffset(curr_bfc_offset_); |
425 curr_margin_strut_ = NGMarginStrut(); | 412 curr_margin_strut_ = NGMarginStrut(); |
426 } | 413 } |
427 curr_bfc_offset_.block_offset += content_size_; | 414 curr_bfc_offset_.block_offset += content_size_; |
428 | 415 |
429 while (current_child_) { | 416 while (current_child_) { |
430 if (current_child_->Type() == NGLayoutInputNode::kLegacyBlock) { | 417 if (current_child_->Type() == NGLayoutInputNode::kLegacyBlock) { |
431 NGBlockNode* current_block_child = toNGBlockNode(current_child_); | 418 NGBlockNode* current_block_child = toNGBlockNode(current_child_); |
432 EPosition position = current_block_child->Style().position(); | 419 EPosition position = current_block_child->Style().position(); |
433 if (position == AbsolutePosition || position == FixedPosition) { | 420 if (position == AbsolutePosition || position == FixedPosition) { |
434 builder_->AddOutOfFlowChildCandidate(current_block_child, | 421 builder_->AddOutOfFlowChildCandidate(current_block_child, |
435 GetChildSpaceOffset()); | 422 GetChildSpaceOffset()); |
436 current_child_ = current_block_child->NextSibling(); | 423 current_child_ = current_block_child->NextSibling(); |
437 continue; | 424 continue; |
438 } | 425 } |
439 } | 426 } |
440 | 427 |
441 DCHECK(!ConstraintSpace().HasBlockFragmentation() || | |
442 SpaceAvailableForCurrentChild() > LayoutUnit()); | |
443 space_for_current_child_ = CreateConstraintSpaceForCurrentChild(); | 428 space_for_current_child_ = CreateConstraintSpaceForCurrentChild(); |
444 | 429 |
445 if (current_child_->Type() == NGLayoutInputNode::kLegacyInline) { | 430 if (current_child_->Type() == NGLayoutInputNode::kLegacyInline) { |
446 LayoutInlineChildren(toNGInlineNode(current_child_)); | 431 LayoutInlineChildren(toNGInlineNode(current_child_)); |
447 continue; | 432 continue; |
448 } | 433 } |
449 | 434 |
450 RefPtr<NGPhysicalFragment> physical_fragment = | 435 RefPtr<NGPhysicalFragment> physical_fragment = |
451 current_child_->Layout(space_for_current_child_); | 436 current_child_->Layout(space_for_current_child_); |
452 | 437 |
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
501 } | 486 } |
502 | 487 |
503 void NGBlockLayoutAlgorithm::LayoutInlineChildren(NGInlineNode* current_child) { | 488 void NGBlockLayoutAlgorithm::LayoutInlineChildren(NGInlineNode* current_child) { |
504 // TODO(kojii): This logic does not handle when children are mix of | 489 // TODO(kojii): This logic does not handle when children are mix of |
505 // inline/block. We need to detect the case and setup appropriately; e.g., | 490 // inline/block. We need to detect the case and setup appropriately; e.g., |
506 // constraint space, margin collapsing, next siblings, etc. | 491 // constraint space, margin collapsing, next siblings, etc. |
507 NGLineBuilder line_builder(current_child, space_for_current_child_); | 492 NGLineBuilder line_builder(current_child, space_for_current_child_); |
508 current_child->LayoutInline(space_for_current_child_, &line_builder); | 493 current_child->LayoutInline(space_for_current_child_, &line_builder); |
509 // TODO(kojii): The wrapper fragment should not be needed. | 494 // TODO(kojii): The wrapper fragment should not be needed. |
510 NGFragmentBuilder wrapper_fragment_builder(NGPhysicalFragment::kFragmentBox, | 495 NGFragmentBuilder wrapper_fragment_builder(NGPhysicalFragment::kFragmentBox, |
511 current_child->GetLayoutObject()); | 496 current_child); |
512 line_builder.CreateFragments(&wrapper_fragment_builder); | 497 line_builder.CreateFragments(&wrapper_fragment_builder); |
513 RefPtr<NGPhysicalBoxFragment> child_fragment = | 498 RefPtr<NGPhysicalBoxFragment> child_fragment = |
514 wrapper_fragment_builder.ToBoxFragment(); | 499 wrapper_fragment_builder.ToBoxFragment(); |
515 line_builder.CopyFragmentDataToLayoutBlockFlow(); | 500 line_builder.CopyFragmentDataToLayoutBlockFlow(); |
516 FinishCurrentChildLayout(child_fragment.get()); | 501 FinishCurrentChildLayout(child_fragment.get()); |
517 current_child_ = nullptr; | 502 current_child_ = nullptr; |
518 } | 503 } |
519 | 504 |
520 void NGBlockLayoutAlgorithm::FinishCurrentChildLayout( | 505 void NGBlockLayoutAlgorithm::FinishCurrentChildLayout( |
521 RefPtr<NGPhysicalBoxFragment> physical_fragment) { | 506 RefPtr<NGPhysicalBoxFragment> physical_fragment) { |
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
561 curr_bfc_offset_.block_offset = fragment.BfcOffset().value().block_offset; | 546 curr_bfc_offset_.block_offset = fragment.BfcOffset().value().block_offset; |
562 bfc_offset = curr_bfc_offset_; | 547 bfc_offset = curr_bfc_offset_; |
563 } | 548 } |
564 if (bfc_offset) { | 549 if (bfc_offset) { |
565 UpdateFragmentBfcOffset(curr_bfc_offset_, builder_.get()); | 550 UpdateFragmentBfcOffset(curr_bfc_offset_, builder_.get()); |
566 PositionPendingFloats(curr_bfc_offset_.block_offset, ConstraintSpace(), | 551 PositionPendingFloats(curr_bfc_offset_.block_offset, ConstraintSpace(), |
567 builder_.get()); | 552 builder_.get()); |
568 } | 553 } |
569 NGLogicalOffset logical_offset = CalculateLogicalOffset(bfc_offset); | 554 NGLogicalOffset logical_offset = CalculateLogicalOffset(bfc_offset); |
570 | 555 |
571 if (fragmentainer_mapper_) | |
572 fragmentainer_mapper_->ToVisualOffset(logical_offset); | |
mstensho (USE GERRIT)
2017/02/15 21:12:22
Is the plan to replace the fragmentainer mapper wi
ikilpatrick
2017/02/16 16:48:31
Yeah i think most of the logic inside the fragment
| |
573 else | |
574 logical_offset.block_offset -= PreviousBreakOffset(); | |
575 | |
576 // Update margin strut. | 556 // Update margin strut. |
577 curr_margin_strut_ = fragment.EndMarginStrut(); | 557 curr_margin_strut_ = fragment.EndMarginStrut(); |
578 curr_margin_strut_.Append(curr_child_margins_.block_end); | 558 curr_margin_strut_.Append(curr_child_margins_.block_end); |
579 | 559 |
580 content_size_ = fragment.BlockSize() + logical_offset.block_offset; | 560 content_size_ = fragment.BlockSize() + logical_offset.block_offset; |
581 max_inline_size_ = | 561 max_inline_size_ = |
582 std::max(max_inline_size_, fragment.InlineSize() + | 562 std::max(max_inline_size_, fragment.InlineSize() + |
583 curr_child_margins_.InlineSum() + | 563 curr_child_margins_.InlineSum() + |
584 border_and_padding_.InlineSum()); | 564 border_and_padding_.InlineSum()); |
585 | 565 |
586 builder_->AddChild(std::move(physical_fragment), logical_offset); | 566 builder_->AddChild(std::move(physical_fragment), logical_offset); |
587 } | 567 } |
588 | 568 |
589 bool NGBlockLayoutAlgorithm::ProceedToNextUnfinishedSibling( | 569 bool NGBlockLayoutAlgorithm::ProceedToNextUnfinishedSibling( |
590 NGPhysicalFragment* child_fragment) { | 570 NGPhysicalFragment* child_fragment) { |
591 DCHECK(current_child_); | 571 DCHECK(current_child_); |
592 NGBlockNode* finished_child = toNGBlockNode(current_child_); | 572 std::tie(current_child_, current_child_break_token_) = |
593 current_child_ = current_child_->NextSibling(); | 573 child_iterator_->NextChild(); |
594 if (!ConstraintSpace().HasBlockFragmentation() && !fragmentainer_mapper_) | |
595 return true; | |
596 // If we're resuming layout after a fragmentainer break, we need to skip | |
597 // siblings that we're done with. We may have been able to fully lay out some | |
598 // node(s) preceding a node that we had to break inside (and therefore were | |
599 // not able to fully lay out). This happens when we have parallel flows [1], | |
600 // which are caused by floats, overflow, etc. | |
601 // | |
602 // [1] https://drafts.csswg.org/css-break/#parallel-flows | |
603 if (CurrentBlockBreakToken()) { | |
604 // TODO(layout-ng): Figure out if we need a better way to determine if the | |
605 // node is finished. Maybe something to encode in a break token? | |
606 // TODO(kojii): Handle inline children. | |
607 while (current_child_ && | |
608 current_child_->Type() == NGLayoutInputNode::kLegacyBlock && | |
609 toNGBlockNode(current_child_)->IsLayoutFinished()) { | |
610 current_child_ = current_child_->NextSibling(); | |
611 } | |
612 } | |
613 LayoutUnit break_offset = NextBreakOffset(); | |
614 bool is_out_of_space = content_size_ - PreviousBreakOffset() >= break_offset; | |
615 if (!HasPendingBreakToken()) { | |
616 bool child_broke = child_fragment->BreakToken(); | |
617 // This block needs to break if the child broke, or if we're out of space | |
618 // and there's more content waiting to be laid out. Otherwise, just bail | |
619 // now. | |
620 if (!child_broke && (!is_out_of_space || !current_child_)) | |
621 return true; | |
622 // Prepare a break token for this block, so that we know where to resume | |
623 // when the time comes for that. We may not be able to abort layout of this | |
624 // block right away, due to the posibility of parallel flows. We can only | |
625 // abort when we're out of space, or when there are no siblings left to | |
626 // process. | |
627 NGBlockBreakToken* token; | |
628 if (child_broke) { | |
629 // The child we just laid out was the first one to break. So that is | |
630 // where we need to resume. | |
631 token = new NGBlockBreakToken(finished_child, break_offset); | |
632 } else { | |
633 // Resume layout at the next sibling that needs layout. | |
634 DCHECK(current_child_); | |
635 token = | |
636 new NGBlockBreakToken(toNGBlockNode(current_child_), break_offset); | |
637 } | |
638 SetPendingBreakToken(token); | |
639 } | |
640 | 574 |
641 if (!fragmentainer_mapper_) { | 575 bool is_out_of_space = |
642 if (!is_out_of_space) | 576 constraint_space_->HasBlockFragmentation() |
643 return true; | 577 ? content_size_ >= constraint_space_->FragmentainerSpaceAvailable() |
mstensho (USE GERRIT)
2017/02/15 21:12:22
All you need is: constraint_space_->HasBlockFragme
| |
644 // We have run out of space in this flow, so there's no work left to do for | 578 : false; |
645 // this block in this fragmentainer. We should finalize the fragment and get | 579 |
646 // back to the remaining content when laying out the next fragmentainer(s). | 580 // We have run out of space in this flow, so there's no work left to do for |
581 // this block in this fragmentainer. We should finalize the fragment and get | |
582 // back to the remaining content when laying out the next fragmentainer(s). | |
583 if (is_out_of_space) | |
647 return false; | 584 return false; |
648 } | |
649 | 585 |
650 if (is_out_of_space || !current_child_) { | 586 return current_child_; |
651 NGBlockBreakToken* token = fragmentainer_mapper_->Advance(); | |
652 DCHECK(token || !is_out_of_space); | |
653 if (token) { | |
654 break_token_ = token; | |
655 content_size_ = token->BreakOffset(); | |
656 current_child_ = token->InputNode(); | |
657 } | |
658 } | |
659 return true; | |
660 } | |
661 | |
662 void NGBlockLayoutAlgorithm::SetPendingBreakToken(NGBlockBreakToken* token) { | |
663 if (fragmentainer_mapper_) | |
664 fragmentainer_mapper_->SetBreakToken(token); | |
665 else | |
666 builder_->SetBreakToken(token); | |
667 } | |
668 | |
669 bool NGBlockLayoutAlgorithm::HasPendingBreakToken() const { | |
670 if (fragmentainer_mapper_) | |
671 return fragmentainer_mapper_->HasBreakToken(); | |
672 return builder_->HasBreakToken(); | |
673 } | 587 } |
674 | 588 |
675 void NGBlockLayoutAlgorithm::FinalizeForFragmentation() { | 589 void NGBlockLayoutAlgorithm::FinalizeForFragmentation() { |
676 LayoutUnit block_size = | 590 LayoutUnit used_block_size = |
677 ComputeBlockSizeForFragment(ConstraintSpace(), Style(), content_size_); | 591 break_token_ ? break_token_->UsedBlockSize() : LayoutUnit(); |
678 LayoutUnit previous_break_offset = PreviousBreakOffset(); | 592 LayoutUnit block_size = ComputeBlockSizeForFragment( |
679 block_size -= previous_break_offset; | 593 ConstraintSpace(), Style(), used_block_size + content_size_); |
680 block_size = std::max(LayoutUnit(), block_size); | 594 |
681 LayoutUnit space_left = ConstraintSpace().FragmentainerSpaceAvailable(); | 595 if (!block_size) |
596 return; | |
597 | |
598 block_size -= used_block_size; | |
599 DCHECK_GE(block_size, LayoutUnit()); | |
600 | |
601 // This is relative to the bfc offset, we should have this if non-zero block | |
602 // size. | |
603 DCHECK(builder_->BfcOffset()); | |
604 LayoutUnit space_left = ConstraintSpace().FragmentainerSpaceAvailable() - | |
605 builder_->BfcOffset().value().block_offset; | |
682 DCHECK_GE(space_left, LayoutUnit()); | 606 DCHECK_GE(space_left, LayoutUnit()); |
683 if (builder_->HasBreakToken()) { | 607 |
608 if (builder_->DidBreak()) { | |
684 // A break token is ready, which means that we're going to break | 609 // A break token is ready, which means that we're going to break |
685 // before or inside a block-level child. | 610 // before or inside a block-level child. |
611 builder_->SetUsedBlockSize(std::min(space_left, block_size) + | |
612 used_block_size); | |
686 builder_->SetBlockSize(std::min(space_left, block_size)); | 613 builder_->SetBlockSize(std::min(space_left, block_size)); |
687 builder_->SetBlockOverflow(space_left); | 614 builder_->SetBlockOverflow(space_left); |
688 return; | 615 return; |
689 } | 616 } |
617 | |
690 if (block_size > space_left) { | 618 if (block_size > space_left) { |
691 // Need a break inside this block. | 619 // Need a break inside this block. |
692 builder_->SetBreakToken(new NGBlockBreakToken(nullptr, NextBreakOffset())); | 620 builder_->SetUsedBlockSize(space_left + used_block_size); |
693 builder_->SetBlockSize(space_left); | 621 builder_->SetBlockSize(space_left); |
694 builder_->SetBlockOverflow(space_left); | 622 builder_->SetBlockOverflow(space_left); |
695 return; | 623 return; |
696 } | 624 } |
625 | |
697 // The end of the block fits in the current fragmentainer. | 626 // The end of the block fits in the current fragmentainer. |
698 builder_->SetBlockSize(block_size); | 627 builder_->SetBlockSize(block_size); |
699 builder_->SetBlockOverflow(content_size_ - previous_break_offset); | 628 builder_->SetBlockOverflow(content_size_); |
700 } | |
701 | |
702 NGBlockBreakToken* NGBlockLayoutAlgorithm::CurrentBlockBreakToken() const { | |
703 NGBreakToken* token = break_token_; | |
704 if (!token || token->Type() != NGBreakToken::kBlockBreakToken) | |
705 return nullptr; | |
706 return toNGBlockBreakToken(token); | |
707 } | |
708 | |
709 LayoutUnit NGBlockLayoutAlgorithm::PreviousBreakOffset() const { | |
710 const NGBlockBreakToken* token = CurrentBlockBreakToken(); | |
711 return token ? token->BreakOffset() : LayoutUnit(); | |
712 } | |
713 | |
714 LayoutUnit NGBlockLayoutAlgorithm::NextBreakOffset() const { | |
715 if (fragmentainer_mapper_) | |
716 return fragmentainer_mapper_->NextBreakOffset(); | |
717 DCHECK(ConstraintSpace().HasBlockFragmentation()); | |
718 return PreviousBreakOffset() + | |
719 ConstraintSpace().FragmentainerSpaceAvailable(); | |
720 } | |
721 | |
722 LayoutUnit NGBlockLayoutAlgorithm::SpaceAvailableForCurrentChild() const { | |
723 LayoutUnit space_left; | |
724 if (fragmentainer_mapper_) | |
725 space_left = fragmentainer_mapper_->BlockSize(); | |
726 else if (ConstraintSpace().HasBlockFragmentation()) | |
727 space_left = ConstraintSpace().FragmentainerSpaceAvailable(); | |
728 else | |
729 return NGSizeIndefinite; | |
730 space_left -= BorderEdgeForCurrentChild() - PreviousBreakOffset(); | |
731 return space_left; | |
732 } | 629 } |
733 | 630 |
734 NGBoxStrut NGBlockLayoutAlgorithm::CalculateMargins( | 631 NGBoxStrut NGBlockLayoutAlgorithm::CalculateMargins( |
735 const NGConstraintSpace& space, | 632 const NGConstraintSpace& space, |
736 const ComputedStyle& style) { | 633 const ComputedStyle& style) { |
737 WTF::Optional<MinAndMaxContentSizes> sizes; | 634 WTF::Optional<MinAndMaxContentSizes> sizes; |
738 if (NeedMinAndMaxContentSizes(space, style)) { | 635 if (NeedMinAndMaxContentSizes(space, style)) { |
739 // TODO(ikilpatrick): Change ComputeMinAndMaxContentSizes to return | 636 // TODO(ikilpatrick): Change ComputeMinAndMaxContentSizes to return |
740 // MinAndMaxContentSizes. | 637 // MinAndMaxContentSizes. |
741 sizes = toNGBlockNode(current_child_)->ComputeMinAndMaxContentSizes(); | 638 sizes = toNGBlockNode(current_child_)->ComputeMinAndMaxContentSizes(); |
(...skipping 21 matching lines...) Expand all Loading... | |
763 | 660 |
764 const ComputedStyle& current_child_style = CurrentChildStyle(); | 661 const ComputedStyle& current_child_style = CurrentChildStyle(); |
765 bool is_new_bfc = IsNewFormattingContextForInFlowBlockLevelChild( | 662 bool is_new_bfc = IsNewFormattingContextForInFlowBlockLevelChild( |
766 ConstraintSpace(), current_child_style); | 663 ConstraintSpace(), current_child_style); |
767 space_builder_->SetIsNewFormattingContext(is_new_bfc) | 664 space_builder_->SetIsNewFormattingContext(is_new_bfc) |
768 .SetIsShrinkToFit( | 665 .SetIsShrinkToFit( |
769 ShouldShrinkToFit(ConstraintSpace(), CurrentChildStyle())) | 666 ShouldShrinkToFit(ConstraintSpace(), CurrentChildStyle())) |
770 .SetWritingMode( | 667 .SetWritingMode( |
771 FromPlatformWritingMode(current_child_style.getWritingMode())) | 668 FromPlatformWritingMode(current_child_style.getWritingMode())) |
772 .SetTextDirection(current_child_style.direction()); | 669 .SetTextDirection(current_child_style.direction()); |
773 LayoutUnit space_available = SpaceAvailableForCurrentChild(); | |
774 space_builder_->SetFragmentainerSpaceAvailable(space_available); | |
775 | 670 |
776 // Clearance : | 671 // Clearance : |
777 // - Collapse margins | 672 // - Collapse margins |
778 // - Update curr_bfc_offset and parent BFC offset if needed. | 673 // - Update curr_bfc_offset and parent BFC offset if needed. |
779 // - Position all pending floats as position is known now. | 674 // - Position all pending floats as position is known now. |
780 // TODO(glebl): Fix the use case with clear: left and an intruding right. | 675 // TODO(glebl): Fix the use case with clear: left and an intruding right. |
781 // https://software.hixie.ch/utilities/js/live-dom-viewer/saved/4847 | 676 // https://software.hixie.ch/utilities/js/live-dom-viewer/saved/4847 |
782 if (current_child_style.clear() != EClear::kNone) { | 677 if (current_child_style.clear() != EClear::kNone) { |
783 curr_bfc_offset_.block_offset += curr_margin_strut_.Sum(); | 678 curr_bfc_offset_.block_offset += curr_margin_strut_.Sum(); |
784 UpdateFragmentBfcOffset(curr_bfc_offset_, builder_.get()); | 679 UpdateFragmentBfcOffset(curr_bfc_offset_, builder_.get()); |
(...skipping 21 matching lines...) Expand all Loading... | |
806 curr_bfc_offset_.inline_offset += border_and_padding_.inline_start; | 701 curr_bfc_offset_.inline_offset += border_and_padding_.inline_start; |
807 | 702 |
808 // Floats margins are not included in child's CS because they are used to | 703 // Floats margins are not included in child's CS because they are used to |
809 // calculate floating exclusions. | 704 // calculate floating exclusions. |
810 if (!CurrentChildStyle().isFloating()) { | 705 if (!CurrentChildStyle().isFloating()) { |
811 curr_bfc_offset_.inline_offset += curr_child_margins_.inline_start; | 706 curr_bfc_offset_.inline_offset += curr_child_margins_.inline_start; |
812 } | 707 } |
813 | 708 |
814 space_builder_->SetBfcOffset(curr_bfc_offset_); | 709 space_builder_->SetBfcOffset(curr_bfc_offset_); |
815 | 710 |
711 if (constraint_space_->HasBlockFragmentation()) { | |
712 LayoutUnit space_available = | |
713 ConstraintSpace().FragmentainerSpaceAvailable(); | |
714 if (builder_->BfcOffset()) { | |
715 // TODO(ikilpatrick): this should be true for new FC's. | |
716 space_available -= builder_->BfcOffset().value().block_offset; | |
mstensho (USE GERRIT)
2017/02/15 21:12:22
I don't understand how this is supposed to work. W
ikilpatrick
2017/02/16 16:48:31
Ah yeah this is wrong, we need a IsNewFormattingCo
mstensho (USE GERRIT)
2017/02/16 21:14:47
Not sure if I misunderstand what you mean here, bu
| |
717 } | |
718 space_builder_->SetFragmentainerSpaceAvailable(space_available); | |
719 } else { | |
720 space_builder_->SetFragmentainerSpaceAvailable(LayoutUnit(0)); | |
mstensho (USE GERRIT)
2017/02/15 21:12:22
Just LayoutUnit().
| |
721 } | |
722 | |
816 return space_builder_->ToConstraintSpace(); | 723 return space_builder_->ToConstraintSpace(); |
817 } | 724 } |
818 | 725 |
819 } // namespace blink | 726 } // namespace blink |
OLD | NEW |