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

Side by Side Diff: third_party/WebKit/Source/core/layout/LayoutBlockFlow.cpp

Issue 2359733002: Need to consider the need for a soft break even when inserting a forced break. (Closed)
Patch Set: Created 4 years, 3 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
« no previous file with comments | « third_party/WebKit/Source/core/layout/LayoutBlockFlow.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 /* 1 /*
2 * Copyright (C) 2013 Google Inc. All rights reserved. 2 * Copyright (C) 2013 Google Inc. All rights reserved.
3 * 3 *
4 * Redistribution and use in source and binary forms, with or without 4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are 5 * modification, are permitted provided that the following conditions are
6 * met: 6 * met:
7 * 7 *
8 * * Redistributions of source code must retain the above copyright 8 * * Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer. 9 * notice, this list of conditions and the following disclaimer.
10 * * Redistributions in binary form must reproduce the above 10 * * Redistributions in binary form must reproduce the above
(...skipping 659 matching lines...) Expand 10 before | Expand all | Expand 10 after
670 child.markForPaginationRelayoutIfNeeded(layoutScope); 670 child.markForPaginationRelayoutIfNeeded(layoutScope);
671 } 671 }
672 } 672 }
673 673
674 if (!child.needsLayout()) 674 if (!child.needsLayout())
675 return false; 675 return false;
676 child.layout(); 676 child.layout();
677 return true; 677 return true;
678 } 678 }
679 679
680 bool LayoutBlockFlow::insertForcedBreakBeforeChildIfNeeded(LayoutBox& child, Blo ckChildrenLayoutInfo& layoutInfo) 680 void LayoutBlockFlow::insertForcedBreakBeforeChildIfNeeded(LayoutBox& child, Blo ckChildrenLayoutInfo& layoutInfo)
681 { 681 {
682 if (layoutInfo.isAtFirstInFlowChild()) { 682 if (layoutInfo.isAtFirstInFlowChild()) {
683 // There's no class A break point before the first child (only *between* siblings), so 683 // There's no class A break point before the first child (only *between* siblings), so
684 // steal its break value and join it with what we already have here. 684 // steal its break value and join it with what we already have here.
685 setBreakBefore(joinFragmentainerBreakValues(breakBefore(), child.breakBe fore())); 685 setBreakBefore(joinFragmentainerBreakValues(breakBefore(), child.breakBe fore()));
686 return false; 686 return;
687 } 687 }
688 688
689 // Figure out if a forced break should be inserted in front of the child. If we insert a forced 689 // Figure out if a forced break should be inserted in front of the child. If we insert a forced
690 // break, the margins on this child may not collapse with those preceding th e break. 690 // break, the margins on this child may not collapse with those preceding th e break.
691 EBreak classABreakPointValue = child.classABreakPointValue(layoutInfo.previo usBreakAfterValue()); 691 EBreak classABreakPointValue = child.classABreakPointValue(layoutInfo.previo usBreakAfterValue());
692 if (isForcedFragmentainerBreakValue(classABreakPointValue)) { 692 if (isForcedFragmentainerBreakValue(classABreakPointValue)) {
693 layoutInfo.marginInfo().clearMargin(); 693 layoutInfo.marginInfo().clearMargin();
694 LayoutUnit oldLogicalTop = logicalHeight(); 694 LayoutUnit oldLogicalTop = logicalHeight();
695 LayoutUnit newLogicalTop = applyForcedBreak(oldLogicalTop, classABreakPo intValue); 695 LayoutUnit newLogicalTop = applyForcedBreak(oldLogicalTop, classABreakPo intValue);
696 setLogicalHeight(newLogicalTop); 696 setLogicalHeight(newLogicalTop);
697 LayoutUnit paginationStrut = newLogicalTop - oldLogicalTop; 697 LayoutUnit paginationStrut = newLogicalTop - oldLogicalTop;
698 child.setPaginationStrut(paginationStrut); 698 child.setPaginationStrut(paginationStrut);
699 return true;
700 } 699 }
701 return false;
702 } 700 }
703 701
704 void LayoutBlockFlow::layoutBlockChild(LayoutBox& child, BlockChildrenLayoutInfo & layoutInfo) 702 void LayoutBlockFlow::layoutBlockChild(LayoutBox& child, BlockChildrenLayoutInfo & layoutInfo)
705 { 703 {
706 MarginInfo& marginInfo = layoutInfo.marginInfo(); 704 MarginInfo& marginInfo = layoutInfo.marginInfo();
707 LayoutBlockFlow* childLayoutBlockFlow = child.isLayoutBlockFlow() ? toLayout BlockFlow(&child) : nullptr; 705 LayoutBlockFlow* childLayoutBlockFlow = child.isLayoutBlockFlow() ? toLayout BlockFlow(&child) : nullptr;
708 LayoutUnit oldPosMarginBefore = maxPositiveMarginBefore(); 706 LayoutUnit oldPosMarginBefore = maxPositiveMarginBefore();
709 LayoutUnit oldNegMarginBefore = maxNegativeMarginBefore(); 707 LayoutUnit oldNegMarginBefore = maxNegativeMarginBefore();
710 708
711 // The child is a normal flow object. Compute the margins we will use for co llapsing now. 709 // The child is a normal flow object. Compute the margins we will use for co llapsing now.
(...skipping 18 matching lines...) Expand all
730 728
731 // Cache if we are at the top of the block right now. 729 // Cache if we are at the top of the block right now.
732 bool atBeforeSideOfBlock = marginInfo.atBeforeSideOfBlock(); 730 bool atBeforeSideOfBlock = marginInfo.atBeforeSideOfBlock();
733 bool childIsSelfCollapsing = child.isSelfCollapsingBlock(); 731 bool childIsSelfCollapsing = child.isSelfCollapsingBlock();
734 bool childDiscardMarginBefore = mustDiscardMarginBeforeForChild(child); 732 bool childDiscardMarginBefore = mustDiscardMarginBeforeForChild(child);
735 bool childDiscardMarginAfter = mustDiscardMarginAfterForChild(child); 733 bool childDiscardMarginAfter = mustDiscardMarginAfterForChild(child);
736 bool paginated = view()->layoutState()->isPaginated(); 734 bool paginated = view()->layoutState()->isPaginated();
737 735
738 // If there should be a forced break before the child, we need to insert it before attempting 736 // If there should be a forced break before the child, we need to insert it before attempting
739 // to collapse margins or apply clearance. 737 // to collapse margins or apply clearance.
740 bool forcedBreakWasInserted = paginated && insertForcedBreakBeforeChildIfNee ded(child, layoutInfo); 738 if (paginated) {
739 // We will now insert the strut needed by any forced break. After this o peration, we will
740 // have calculated the offset where we can apply margin collapsing and c learance. After
741 // having applied those things, we'll be at the position where we can ho nor requirements of
742 // unbreakable content, which may extend the strut further.
743 child.resetPaginationStrut();
744 insertForcedBreakBeforeChildIfNeeded(child, layoutInfo);
745 }
741 746
742 // Now determine the correct ypos based off examination of collapsing margin 747 // Now determine the correct ypos based off examination of collapsing margin
743 // values. 748 // values.
744 LayoutUnit logicalTopBeforeClear = collapseMargins(child, marginInfo, childI sSelfCollapsing, childDiscardMarginBefore, childDiscardMarginAfter); 749 LayoutUnit logicalTopBeforeClear = collapseMargins(child, marginInfo, childI sSelfCollapsing, childDiscardMarginBefore, childDiscardMarginAfter);
745 750
746 // Now check for clear. 751 // Now check for clear.
747 bool childDiscardMargin = childDiscardMarginBefore || childDiscardMarginAfte r; 752 bool childDiscardMargin = childDiscardMarginBefore || childDiscardMarginAfte r;
748 LayoutUnit newLogicalTop = clearFloatsIfNeeded(child, marginInfo, oldPosMarg inBefore, oldNegMarginBefore, logicalTopBeforeClear, childIsSelfCollapsing, chil dDiscardMargin); 753 LayoutUnit newLogicalTop = clearFloatsIfNeeded(child, marginInfo, oldPosMarg inBefore, oldNegMarginBefore, logicalTopBeforeClear, childIsSelfCollapsing, chil dDiscardMargin);
749 754
750 // If there's a forced break in front of this child, its final position has already been 755 // If there's a forced break in front of this child, its final position has already been
751 // determined. Otherwise, see if there are other reasons for breaking before it 756 // determined. Otherwise, see if there are other reasons for breaking before it
752 // (break-inside:avoid, or not enough space for the first piece of child con tent to fit in the 757 // (break-inside:avoid, or not enough space for the first piece of child con tent to fit in the
753 // current fragmentainer), and adjust the position accordingly. 758 // current fragmentainer), and adjust the position accordingly.
754 if (paginated && !forcedBreakWasInserted) { 759 if (paginated) {
755 if (estimateWithoutPagination != newLogicalTop) { 760 if (estimateWithoutPagination != newLogicalTop) {
756 // We got a new position due to clearance or margin collapsing. Befo re we attempt to 761 // We got a new position due to clearance or margin collapsing. Befo re we attempt to
757 // paginate (which may result in the position changing again), let's try again at the 762 // paginate (which may result in the position changing again), let's try again at the
758 // new position (since a new position may result in a new logical he ight). 763 // new position (since a new position may result in a new logical he ight).
759 positionAndLayoutOnceIfNeeded(child, newLogicalTop, layoutInfo); 764 positionAndLayoutOnceIfNeeded(child, newLogicalTop, layoutInfo);
760 } 765 }
761 766
767 // We have now applied forced breaks, margin collapsing and clearance, a nd we're at the
768 // position where we can honor requirements of unbreakable content.
762 newLogicalTop = adjustBlockChildForPagination(newLogicalTop, child, layo utInfo, atBeforeSideOfBlock && logicalTopBeforeClear == newLogicalTop); 769 newLogicalTop = adjustBlockChildForPagination(newLogicalTop, child, layo utInfo, atBeforeSideOfBlock && logicalTopBeforeClear == newLogicalTop);
763 } 770 }
764 771
765 // Clearance, margin collapsing or pagination may have given us a new logica l top, in which 772 // Clearance, margin collapsing or pagination may have given us a new logica l top, in which
766 // case we may have to reposition and possibly relayout as well. If we deter mined during child 773 // case we may have to reposition and possibly relayout as well. If we deter mined during child
767 // layout that we need to insert a break to honor widows, we also need to re layout. 774 // layout that we need to insert a break to honor widows, we also need to re layout.
768 if (newLogicalTop != logicalTopEstimate 775 if (newLogicalTop != logicalTopEstimate
769 || child.needsLayout() 776 || child.needsLayout()
770 || (paginated && childLayoutBlockFlow && childLayoutBlockFlow->shouldBre akAtLineToAvoidWidow())) { 777 || (paginated && childLayoutBlockFlow && childLayoutBlockFlow->shouldBre akAtLineToAvoidWidow())) {
771 positionAndLayoutOnceIfNeeded(child, newLogicalTop, layoutInfo); 778 positionAndLayoutOnceIfNeeded(child, newLogicalTop, layoutInfo);
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after
814 } 821 }
815 822
816 if (child.isLayoutMultiColumnSpannerPlaceholder()) { 823 if (child.isLayoutMultiColumnSpannerPlaceholder()) {
817 // The actual column-span:all element is positioned by this placeholder child. 824 // The actual column-span:all element is positioned by this placeholder child.
818 positionSpannerDescendant(toLayoutMultiColumnSpannerPlaceholder(child)); 825 positionSpannerDescendant(toLayoutMultiColumnSpannerPlaceholder(child));
819 } 826 }
820 } 827 }
821 828
822 LayoutUnit LayoutBlockFlow::adjustBlockChildForPagination(LayoutUnit logicalTop, LayoutBox& child, BlockChildrenLayoutInfo& layoutInfo, bool atBeforeSideOfBlock ) 829 LayoutUnit LayoutBlockFlow::adjustBlockChildForPagination(LayoutUnit logicalTop, LayoutBox& child, BlockChildrenLayoutInfo& layoutInfo, bool atBeforeSideOfBlock )
823 { 830 {
824 // Forced breaks trumps unforced ones, and if we have a forced break, we sho uldn't even be here.
825 ASSERT(layoutInfo.isAtFirstInFlowChild() || !isForcedFragmentainerBreakValue (child.classABreakPointValue(layoutInfo.previousBreakAfterValue())));
826
827 LayoutBlockFlow* childBlockFlow = child.isLayoutBlockFlow() ? toLayoutBlockF low(&child) : 0; 831 LayoutBlockFlow* childBlockFlow = child.isLayoutBlockFlow() ? toLayoutBlockF low(&child) : 0;
828 832
829 // See if we need a soft (unforced) break in front of this child, and set th e pagination strut 833 // See if we need a soft (unforced) break in front of this child, and set th e pagination strut
830 // in that case. An unforced break may come from two sources: 834 // in that case. An unforced break may come from two sources:
831 // 1. The first piece of content inside the child doesn't fit in the current page or column 835 // 1. The first piece of content inside the child doesn't fit in the current page or column
832 // 2. The child itself has breaking restrictions (break-inside:avoid, replac ed content, etc.) 836 // 2. The child itself has breaking restrictions (break-inside:avoid, replac ed content, etc.)
833 // and doesn't fully fit in the current page or column. 837 // and doesn't fully fit in the current page or column.
834 // 838 //
835 // No matter which source, if we need to insert a strut, it should always ta ke us to the exact 839 // No matter which source, if we need to insert a strut, it should always ta ke us to the exact
836 // top of a page or column further ahead, or be zero. 840 // top of a page or column further ahead, or be zero.
837 841
838 // We're now going to calculate the child's final pagination strut. We may e nd up propagating
839 // it to its containing block (|this|), so reset it first.
840 child.resetPaginationStrut();
841
842 // The first piece of content inside the child may have set a strut during l ayout. Currently, 842 // The first piece of content inside the child may have set a strut during l ayout. Currently,
843 // only block flows support strut propagation, but this may (and should) cha nge in the future. 843 // only block flows support strut propagation, but this may (and should) cha nge in the future.
844 // See crbug.com/539873 844 // See crbug.com/539873
845 LayoutUnit strutFromContent = childBlockFlow ? childBlockFlow->paginationStr utPropagatedFromChild() : LayoutUnit(); 845 LayoutUnit strutFromContent = childBlockFlow ? childBlockFlow->paginationStr utPropagatedFromChild() : LayoutUnit();
846 LayoutUnit logicalTopWithContentStrut = logicalTop + strutFromContent; 846 LayoutUnit logicalTopWithContentStrut = logicalTop + strutFromContent;
847 847
848 // For replaced elements and scrolled elements, we want to shift them to the next page if they don't fit on the current one. 848 // For replaced elements and scrolled elements, we want to shift them to the next page if they don't fit on the current one.
849 LayoutUnit logicalTopAfterUnsplittable = adjustForUnsplittableChild(child, l ogicalTop); 849 LayoutUnit logicalTopAfterUnsplittable = adjustForUnsplittableChild(child, l ogicalTop);
850 850
851 // Pick the largest offset. Tall unsplittable content may take us to a page or column further 851 // Pick the largest offset. Tall unsplittable content may take us to a page or column further
852 // ahead than the next one. 852 // ahead than the next one.
853 LayoutUnit logicalTopAfterPagination = std::max(logicalTopWithContentStrut, logicalTopAfterUnsplittable); 853 LayoutUnit logicalTopAfterPagination = std::max(logicalTopWithContentStrut, logicalTopAfterUnsplittable);
854 LayoutUnit newLogicalTop = logicalTop; 854 LayoutUnit newLogicalTop = logicalTop;
855 if (LayoutUnit paginationStrut = logicalTopAfterPagination - logicalTop) { 855
856 // Forced breaks may already have caused a strut, and this needs to be added together with
857 // any strut detected here in this method.
858 LayoutUnit previousStrut = child.paginationStrut();
859
860 if (LayoutUnit paginationStrut = logicalTopAfterPagination - logicalTop + pr eviousStrut) {
856 ASSERT(paginationStrut > 0); 861 ASSERT(paginationStrut > 0);
857 // If we're not at the first in-flow child, there's a class A break poin t before the child. If we *are* at the 862 // If we're not at the first in-flow child, there's a class A break poin t before the child. If we *are* at the
858 // first in-flow child, but the child isn't flush with the content edge of its container, due to e.g. clearance, 863 // first in-flow child, but the child isn't flush with the content edge of its container, due to e.g. clearance,
859 // there's a class C break point before the child. Otherwise we should p ropagate the strut to our parent block, 864 // there's a class C break point before the child. Otherwise we should p ropagate the strut to our parent block,
860 // and attempt to break there instead. See https://drafts.csswg.org/css- break/#possible-breaks 865 // and attempt to break there instead. See https://drafts.csswg.org/css- break/#possible-breaks
861 if (layoutInfo.isAtFirstInFlowChild() && atBeforeSideOfBlock && allowsPa ginationStrut()) { 866 if (layoutInfo.isAtFirstInFlowChild() && atBeforeSideOfBlock && allowsPa ginationStrut()) {
862 // FIXME: Should really check if we're exceeding the page height bef ore propagating the strut, but we don't 867 // FIXME: Should really check if we're exceeding the page height bef ore propagating the strut, but we don't
863 // have all the information to do so (the strut only has the remaini ng amount to push). Gecko gets this wrong too 868 // have all the information to do so (the strut only has the remaini ng amount to push). Gecko gets this wrong too
864 // and pushes to the next page anyway, so not too concerned about it . 869 // and pushes to the next page anyway, so not too concerned about it .
865 paginationStrut += logicalTop + marginBeforeIfFloating(); 870 paginationStrut += logicalTop + marginBeforeIfFloating();
866 setPaginationStrutPropagatedFromChild(paginationStrut); 871 setPaginationStrutPropagatedFromChild(paginationStrut);
872 child.resetPaginationStrut();
867 if (childBlockFlow) 873 if (childBlockFlow)
868 childBlockFlow->setPaginationStrutPropagatedFromChild(LayoutUnit ()); 874 childBlockFlow->setPaginationStrutPropagatedFromChild(LayoutUnit ());
869 } else { 875 } else {
870 child.setPaginationStrut(paginationStrut); 876 child.setPaginationStrut(paginationStrut);
871 newLogicalTop += paginationStrut; 877 // |previousStrut| was already baked into the logical top, so don't add it again.
878 newLogicalTop += paginationStrut - previousStrut;
872 } 879 }
873 } 880 }
874 881
875 // Similar to how we apply clearance. Go ahead and boost height() to be the place where we're going to position the child. 882 // Similar to how we apply clearance. Go ahead and boost height() to be the place where we're going to position the child.
876 setLogicalHeight(logicalHeight() + (newLogicalTop - logicalTop)); 883 setLogicalHeight(logicalHeight() + (newLogicalTop - logicalTop));
877 884
878 // Return the final adjusted logical top. 885 // Return the final adjusted logical top.
879 return newLogicalTop; 886 return newLogicalTop;
880 } 887 }
881 888
(...skipping 2878 matching lines...) Expand 10 before | Expand all | Expand 10 after
3760 3767
3761 return LayoutBlock::invalidatePaintIfNeeded(paintInvalidationState); 3768 return LayoutBlock::invalidatePaintIfNeeded(paintInvalidationState);
3762 } 3769 }
3763 3770
3764 void LayoutBlockFlow::invalidateDisplayItemClients(PaintInvalidationReason inval idationReason) const 3771 void LayoutBlockFlow::invalidateDisplayItemClients(PaintInvalidationReason inval idationReason) const
3765 { 3772 {
3766 BlockFlowPaintInvalidator(*this).invalidateDisplayItemClients(invalidationRe ason); 3773 BlockFlowPaintInvalidator(*this).invalidateDisplayItemClients(invalidationRe ason);
3767 } 3774 }
3768 3775
3769 } // namespace blink 3776 } // namespace blink
OLDNEW
« no previous file with comments | « third_party/WebKit/Source/core/layout/LayoutBlockFlow.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698