Commit 70586989 authored by Morten Stenshorne's avatar Morten Stenshorne Committed by Commit Bot

[LayoutNG] Refactor and fix code for breaking before a child.

This was just meant to be a preparatory CL for adding support for
avoiding breaks using the break-before and break-after properties, but
ended up fixing bugs as well. :)

This makes 3 web tests pass, because we now have more control over break
avoidance, so that we can keep last resort breaks inside a child if
breaking before would be just as bad. When two breakpoints are equally
bad, prefer the one that takes us the furthest in the content.

Rename BreakBeforeChild() to BreakBeforeChildIfNeeded(), and introduce
BreakBeforeChild(), which actually always breaks before a child.
BreakTypeBeforeChild() only partially contained the logic to determine
whether and how to break, and has now been swallowed by
BreakBeforeChildIfNeeded().

Bug: 829028
Change-Id: Ia620c19e1dfd31e88cf76eb7cea150a9e1152865
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1829101Reviewed-by: default avatarIan Kilpatrick <ikilpatrick@chromium.org>
Reviewed-by: default avatarEmil A Eklund <eae@chromium.org>
Commit-Queue: Morten Stenshorne <mstensho@chromium.org>
Cr-Commit-Position: refs/heads/master@{#701456}
parent c4fe46ca
...@@ -224,6 +224,14 @@ class CORE_EXPORT NGBlockLayoutAlgorithm ...@@ -224,6 +224,14 @@ class CORE_EXPORT NGBlockLayoutAlgorithm
// whether fits within the fragmentainer or not. // whether fits within the fragmentainer or not.
bool IsFragmentainerOutOfSpace(LayoutUnit block_offset) const; bool IsFragmentainerOutOfSpace(LayoutUnit block_offset) const;
// Final adjustments before fragment creation. We need to prevent the fragment
// from crossing fragmentainer boundaries, and rather create a break token if
// we're out of space. As part of finalizing we may also discover that we need
// to abort layout, because we've run out of space at a less-than-ideal
// location. In this case, false will be returned. Otherwise, true will be
// returned.
bool FinalizeForFragmentation();
// Insert a fragmentainer break before the child if necessary. // Insert a fragmentainer break before the child if necessary.
// Update previous in-flow position and return true if a break was inserted. // Update previous in-flow position and return true if a break was inserted.
// Otherwise return false. // Otherwise return false.
...@@ -237,28 +245,24 @@ class CORE_EXPORT NGBlockLayoutAlgorithm ...@@ -237,28 +245,24 @@ class CORE_EXPORT NGBlockLayoutAlgorithm
// block-start content edge of the container and the block-start margin edge // block-start content edge of the container and the block-start margin edge
// of the first in-flow child. This can happen when in-flow content is pushed // of the first in-flow child. This can happen when in-flow content is pushed
// down by floats. https://www.w3.org/TR/css-break-3/#possible-breaks // down by floats. https://www.w3.org/TR/css-break-3/#possible-breaks
bool BreakBeforeChild(NGLayoutInputNode child, bool BreakBeforeChildIfNeeded(NGLayoutInputNode child,
const NGLayoutResult&,
NGPreviousInflowPosition*,
LayoutUnit block_offset,
bool has_container_separation);
// Insert either a soft or forced break before the child.
void BreakBeforeChild(NGLayoutInputNode child,
const NGLayoutResult&, const NGLayoutResult&,
NGPreviousInflowPosition*,
LayoutUnit block_offset, LayoutUnit block_offset,
bool has_container_separation); bool is_forced_break,
NGPreviousInflowPosition*);
enum BreakType { NoBreak, SoftBreak, ForcedBreak }; void BreakBeforeChild(NGLayoutInputNode child,
bool is_forced_break,
// Given a child fragment and the corresponding node's style, determine the NGPreviousInflowPosition*);
// type of break we should insert in front of it, if any.
BreakType BreakTypeBeforeChild(NGLayoutInputNode child, // Propagate the minimal space shortage from a child.
const NGLayoutResult&, void PropagateSpaceShortage(const NGLayoutResult&, LayoutUnit block_offset);
LayoutUnit block_offset,
bool has_container_separation) const;
// Final adjustments before fragment creation. We need to prevent the fragment
// from crossing fragmentainer boundaries, and rather create a break token if
// we're out of space. As part of finalizing we may also discover that we need
// to abort layout, because we've run out of space at a less-than-ideal
// location. In this case, false will be returned. Otherwise, true will be
// returned.
bool FinalizeForFragmentation();
void PropagateBaselinesFromChildren(); void PropagateBaselinesFromChildren();
bool AddBaseline(const NGBaselineRequest&, bool AddBaseline(const NGBaselineRequest&,
......
...@@ -81,6 +81,9 @@ void GatherInlineContainerFragmentsFromLinebox( ...@@ -81,6 +81,9 @@ void GatherInlineContainerFragmentsFromLinebox(
void NGBoxFragmentBuilder::AddBreakBeforeChild(NGLayoutInputNode child, void NGBoxFragmentBuilder::AddBreakBeforeChild(NGLayoutInputNode child,
bool is_forced_break) { bool is_forced_break) {
if (is_forced_break)
SetHasForcedBreak();
DCHECK(has_block_fragmentation_); DCHECK(has_block_fragmentation_);
SetDidBreak(); SetDidBreak();
if (auto* child_inline_node = DynamicTo<NGInlineNode>(child)) { if (auto* child_inline_node = DynamicTo<NGInlineNode>(child)) {
......
...@@ -117,11 +117,6 @@ class CORE_EXPORT NGBoxFragmentBuilder final ...@@ -117,11 +117,6 @@ class CORE_EXPORT NGBoxFragmentBuilder final
// This will result in a fragment which has an unfinished break token. // This will result in a fragment which has an unfinished break token.
void SetDidBreak() { did_break_ = true; } void SetDidBreak() { did_break_ = true; }
void SetHasForcedBreak() {
has_forced_break_ = true;
minimal_space_shortage_ = LayoutUnit();
}
// Report space shortage, i.e. how much more space would have been sufficient // Report space shortage, i.e. how much more space would have been sufficient
// to prevent some piece of content from breaking. This information may be // to prevent some piece of content from breaking. This information may be
// used by the column balancer to stretch columns. // used by the column balancer to stretch columns.
...@@ -252,6 +247,11 @@ class CORE_EXPORT NGBoxFragmentBuilder final ...@@ -252,6 +247,11 @@ class CORE_EXPORT NGBoxFragmentBuilder final
// Update whether we have fragmented in this flow. // Update whether we have fragmented in this flow.
void PropagateBreak(const NGLayoutResult&); void PropagateBreak(const NGLayoutResult&);
void SetHasForcedBreak() {
has_forced_break_ = true;
minimal_space_shortage_ = LayoutUnit();
}
scoped_refptr<const NGLayoutResult> ToBoxFragment(WritingMode); scoped_refptr<const NGLayoutResult> ToBoxFragment(WritingMode);
const NGFragmentGeometry* initial_fragment_geometry_ = nullptr; const NGFragmentGeometry* initial_fragment_geometry_ = nullptr;
......
...@@ -90,6 +90,16 @@ bool IsAvoidBreakValue(const NGConstraintSpace& constraint_space, ...@@ -90,6 +90,16 @@ bool IsAvoidBreakValue(const NGConstraintSpace& constraint_space,
return false; return false;
} }
EBreakBetween CalculateBreakBetweenValue(NGLayoutInputNode child,
const NGLayoutResult& layout_result,
const NGBoxFragmentBuilder& builder) {
if (child.IsInline())
return EBreakBetween::kAuto;
EBreakBetween break_before = JoinFragmentainerBreakValues(
child.Style().BreakBefore(), layout_result.InitialBreakBefore());
return builder.JoinedBreakBetweenValue(break_before);
}
void SetupFragmentation(const NGConstraintSpace& parent_space, void SetupFragmentation(const NGConstraintSpace& parent_space,
LayoutUnit new_bfc_block_offset, LayoutUnit new_bfc_block_offset,
NGConstraintSpaceBuilder* builder, NGConstraintSpaceBuilder* builder,
......
...@@ -13,7 +13,9 @@ ...@@ -13,7 +13,9 @@
namespace blink { namespace blink {
class NGBoxFragmentBuilder;
class NGConstraintSpace; class NGConstraintSpace;
class NGLayoutResult;
// Join two adjacent break values specified on break-before and/or break- // Join two adjacent break values specified on break-before and/or break-
// after. avoid* values win over auto values, and forced break values win over // after. avoid* values win over auto values, and forced break values win over
...@@ -41,6 +43,13 @@ inline bool IsResumingLayout(const NGBlockBreakToken* token) { ...@@ -41,6 +43,13 @@ inline bool IsResumingLayout(const NGBlockBreakToken* token) {
return token && !token->IsBreakBefore(); return token && !token->IsBreakBefore();
} }
// Calculate the final "break-between" value at a class A or C breakpoint. This
// is the combination of all break-before and break-after values that met at the
// breakpoint.
EBreakBetween CalculateBreakBetweenValue(NGLayoutInputNode child,
const NGLayoutResult&,
const NGBoxFragmentBuilder&);
// Set up a child's constraint space builder for block fragmentation. The child // Set up a child's constraint space builder for block fragmentation. The child
// participates in the same fragmentation context as parent_space. If the child // participates in the same fragmentation context as parent_space. If the child
// establishes a new formatting context, new_bfc_block_offset must be set to the // establishes a new formatting context, new_bfc_block_offset must be set to the
......
...@@ -1560,7 +1560,6 @@ crbug.com/591099 virtual/layout_ng_experimental/fast/multicol/dynamic/insert-spa ...@@ -1560,7 +1560,6 @@ crbug.com/591099 virtual/layout_ng_experimental/fast/multicol/dynamic/insert-spa
crbug.com/591099 virtual/layout_ng_experimental/fast/multicol/dynamic/insert-spanner-pseudo-before-following-content.html [ Failure ] crbug.com/591099 virtual/layout_ng_experimental/fast/multicol/dynamic/insert-spanner-pseudo-before-following-content.html [ Failure ]
crbug.com/591099 virtual/layout_ng_experimental/fast/multicol/dynamic/insert-spanner-pseudo-before.html [ Failure ] crbug.com/591099 virtual/layout_ng_experimental/fast/multicol/dynamic/insert-spanner-pseudo-before.html [ Failure ]
crbug.com/591099 virtual/layout_ng_experimental/fast/multicol/dynamic/relpos-becomes-static-has-abspos.html [ Failure ] crbug.com/591099 virtual/layout_ng_experimental/fast/multicol/dynamic/relpos-becomes-static-has-abspos.html [ Failure ]
crbug.com/591099 virtual/layout_ng_experimental/fast/multicol/dynamic/remove-abspos-next-to-spanner.html [ Crash Failure ]
crbug.com/591099 virtual/layout_ng_experimental/fast/multicol/dynamic/remove-and-insert-block-after-spanner.html [ Failure ] crbug.com/591099 virtual/layout_ng_experimental/fast/multicol/dynamic/remove-and-insert-block-after-spanner.html [ Failure ]
crbug.com/591099 virtual/layout_ng_experimental/fast/multicol/dynamic/remove-and-insert-block-before-spanner.html [ Failure ] crbug.com/591099 virtual/layout_ng_experimental/fast/multicol/dynamic/remove-and-insert-block-before-spanner.html [ Failure ]
crbug.com/591099 virtual/layout_ng_experimental/fast/multicol/dynamic/remove-and-insert-block-between-spanners.html [ Failure ] crbug.com/591099 virtual/layout_ng_experimental/fast/multicol/dynamic/remove-and-insert-block-between-spanners.html [ Failure ]
...@@ -1803,8 +1802,6 @@ crbug.com/591099 virtual/layout_ng_experimental/fast/multicol/widows-and-orphans ...@@ -1803,8 +1802,6 @@ crbug.com/591099 virtual/layout_ng_experimental/fast/multicol/widows-and-orphans
crbug.com/591099 virtual/layout_ng_experimental/fast/multicol/widows.html [ Failure ] crbug.com/591099 virtual/layout_ng_experimental/fast/multicol/widows.html [ Failure ]
crbug.com/591099 virtual/layout_ng_experimental/fragmentation/abspos-after-forced-break.html [ Failure ] crbug.com/591099 virtual/layout_ng_experimental/fragmentation/abspos-after-forced-break.html [ Failure ]
crbug.com/591099 virtual/layout_ng_experimental/fragmentation/auto-scrollbar-shrink-to-fit.html [ Failure ] crbug.com/591099 virtual/layout_ng_experimental/fragmentation/auto-scrollbar-shrink-to-fit.html [ Failure ]
crbug.com/591099 virtual/layout_ng_experimental/fragmentation/avoid-break-inside-first-child.html [ Failure ]
crbug.com/591099 virtual/layout_ng_experimental/fragmentation/avoid-break-inside-first-child-nested.html [ Failure ]
crbug.com/591099 virtual/layout_ng_experimental/fragmentation/become-unfragmented-with-lines.html [ Crash Pass ] crbug.com/591099 virtual/layout_ng_experimental/fragmentation/become-unfragmented-with-lines.html [ Crash Pass ]
crbug.com/591099 virtual/layout_ng_experimental/fragmentation/become-unfragmented-with-unbreakable-blocks.html [ Crash Pass ] crbug.com/591099 virtual/layout_ng_experimental/fragmentation/become-unfragmented-with-unbreakable-blocks.html [ Crash Pass ]
crbug.com/591099 virtual/layout_ng_experimental/fragmentation/block-after-float-first-child.html [ Failure ] crbug.com/591099 virtual/layout_ng_experimental/fragmentation/block-after-float-first-child.html [ Failure ]
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment