Commit 25a6baa6 authored by Koji Ishii's avatar Koji Ishii Committed by Commit Bot

[LayoutNG] Run CreateLine() even for empty lines

When a line box is [certain zero-height line boxes], most of
line layout algorithm is not necessary and that we have a
fast code-path for that case.

However, there are some edge cases where we still need to
create box fragments such as when the line has a containing
block for out-of-flow objects.

This patch runs the normal line layout algorithm even when
the line box is "empty".

We could detect when the algorithm is really needed, and/or
run only necessary part of the algoirithm for the performance
in future.

[certain zero-height line boxes]: https://drafts.csswg.org/css2/visuren.html#phantom-line-box

Bug: 636993
Cq-Include-Trybots: luci.chromium.try:linux_layout_tests_layout_ng
Change-Id: I4d7c6a6b2a3155f1eb5c5ae2f17b78b89bfb833a
Reviewed-on: https://chromium-review.googlesource.com/1121656
Commit-Queue: Koji Ishii <kojii@chromium.org>
Reviewed-by: default avatarAleks Totic <atotic@chromium.org>
Cr-Commit-Position: refs/heads/master@{#571807}
parent db5145c7
......@@ -345,6 +345,8 @@ crbug.com/591099 fast/block/float/overlapping-floats-paint-hittest-order-1.html
crbug.com/591099 fast/block/line-layout/floats-do-not-fit-on-line.html [ Failure ]
crbug.com/591099 fast/block/over-constrained-auto-margin.html [ Failure ]
crbug.com/591099 fast/block/positioning/positioned-child-inside-relative-positioned-anonymous-block.html [ Failure ]
crbug.com/591099 fast/block/positioning/rtl-static-positioning.html [ Failure ]
crbug.com/591099 fast/block/positioning/table-cell-static-position.html [ Failure ]
crbug.com/591099 fast/borders/bidi-002.html [ Failure ]
crbug.com/591099 fast/borders/bidi-012.html [ Failure ]
crbug.com/591099 fast/borders/border-image-border-radius.html [ Failure ]
......@@ -614,7 +616,6 @@ crbug.com/591099 paint/invalidation/clip/caret-ancestor-clip-change.html [ Failu
crbug.com/591099 paint/invalidation/clip/clipped-relative.html [ Failure ]
crbug.com/591099 paint/invalidation/clip/control-clip.html [ Failure ]
crbug.com/591099 paint/invalidation/clip/outline-clip-change.html [ Failure ]
crbug.com/591099 paint/invalidation/clip/repaint-tile-clipped.html [ Crash ]
crbug.com/591099 paint/invalidation/clip/replaced-clipped-positioned-not-wrong-incremental-repainting.html [ Failure ]
crbug.com/591099 paint/invalidation/compositing/iframe-inside-squashed-layer.html [ Failure ]
crbug.com/591099 paint/invalidation/compositing/remove-squashed-layer-plus-move.html [ Failure ]
......
......@@ -606,12 +606,21 @@ scoped_refptr<NGLayoutResult> NGInlineLayoutAlgorithm::Layout() {
bool is_empty_inline = Node().IsEmptyInline();
if (is_empty_inline) {
// Margins should collapse across "certain zero-height line boxes".
// https://drafts.csswg.org/css2/box.html#collapsing-margins
container_builder_.SetEndMarginStrut(ConstraintSpace().MarginStrut());
// We're just going to collapse through this one, so whatever went in on one
// side will go out on the other side. The position of the adjoining floats
// will be affected by any subsequent block, until the BFC offset is
// resolved.
container_builder_.AddAdjoiningFloatTypes(
ConstraintSpace().AdjoiningFloatTypes());
// For the empty lines, most of the logic here are not necessary, but in
// some edge cases we still need to create box fragments, such as when it
// has a containing block for out of flow objects. For now, use the code
// path than to create a fast code path for the stability.
} else {
DCHECK(ConstraintSpace().MarginStrut().IsEmpty());
container_builder_.SetBfcOffset(ConstraintSpace().BfcOffset());
......@@ -626,21 +635,6 @@ scoped_refptr<NGLayoutResult> NGInlineLayoutAlgorithm::Layout() {
unsigned handled_item_index =
PositionLeadingItems(initial_exclusion_space.get());
// If we are an empty inline, we don't have to run the full algorithm, we can
// return now as we should have positioned all of our floats.
if (is_empty_inline) {
DCHECK_EQ(handled_item_index, Node().ItemsData(false).items.size());
container_builder_.SwapPositionedFloats(&positioned_floats_);
container_builder_.SetEndMarginStrut(ConstraintSpace().MarginStrut());
container_builder_.SetExclusionSpace(std::move(initial_exclusion_space));
container_builder_.MoveOutOfFlowDescendantCandidatesToDescendants();
return container_builder_.ToLineBoxFragment();
}
DCHECK(container_builder_.BfcOffset());
// We query all the layout opportunities on the initial exclusion space up
// front, as if the line breaker may add floats and change the opportunities.
const Vector<NGLayoutOpportunity> opportunities =
......@@ -649,7 +643,8 @@ scoped_refptr<NGLayoutResult> NGInlineLayoutAlgorithm::Layout() {
ConstraintSpace().AvailableSize().inline_size);
Vector<NGPositionedFloat> positioned_floats;
DCHECK(unpositioned_floats_.IsEmpty());
// We shouldn't have any unpositioned floats if we aren't empty.
DCHECK(unpositioned_floats_.IsEmpty() || is_empty_inline);
std::unique_ptr<NGExclusionSpace> exclusion_space;
NGInlineBreakToken* break_token = BreakToken();
......@@ -767,20 +762,23 @@ scoped_refptr<NGLayoutResult> NGInlineLayoutAlgorithm::Layout() {
container_builder_.SetBreakToken(
line_breaker.CreateBreakToken(line_info, std::move(box_states_)));
// Place any remaining floats which couldn't fit on the line.
PositionPendingFloats(line_height, exclusion_space.get());
// A <br clear=both> will strech the line-box height, such that the
// block-end edge will clear any floats.
// TODO(ikilpatrick): Move this into ng_block_layout_algorithm.
container_builder_.SetBlockSize(
ComputeContentSize(line_info, *exclusion_space, line_height));
if (is_empty_inline) {
DCHECK_EQ(container_builder_.BlockSize(), 0);
} else {
// Place any remaining floats which couldn't fit on the line.
PositionPendingFloats(line_height, exclusion_space.get());
// A <br clear=both> will strech the line-box height, such that the
// block-end edge will clear any floats.
// TODO(ikilpatrick): Move this into ng_block_layout_algorithm.
container_builder_.SetBlockSize(
ComputeContentSize(line_info, *exclusion_space, line_height));
}
break;
}
// We shouldn't have any unpositioned floats if we aren't empty.
DCHECK(unpositioned_floats_.IsEmpty());
DCHECK(unpositioned_floats_.IsEmpty() || is_empty_inline);
container_builder_.SwapPositionedFloats(&positioned_floats_);
container_builder_.SetExclusionSpace(
exclusion_space ? std::move(exclusion_space)
......
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