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

[LayoutNG] Carry over incoming inline break token when no new lines.

If we want to break before the first line in a fragment, we need to
check if there's an incoming inline break token, and add that one to the
builder, rather than assuming that we should always resume at the
beginning of the inline formatting context.

The new test would either freeze or trigger a DCHECK failure without
this fix.

Bug: 1122901
Change-Id: Ib698d477aef18d11dbe1436eaf12d5d52bdc023d
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2537834
Commit-Queue: Morten Stenshorne <mstensho@chromium.org>
Reviewed-by: default avatarIan Kilpatrick <ikilpatrick@chromium.org>
Reviewed-by: default avatarKoji Ishii <kojii@chromium.org>
Cr-Commit-Position: refs/heads/master@{#827752}
parent 2ab5789c
...@@ -168,11 +168,31 @@ void NGBoxFragmentBuilder::AddBreakBeforeChild( ...@@ -168,11 +168,31 @@ void NGBoxFragmentBuilder::AddBreakBeforeChild(
if (auto* child_inline_node = DynamicTo<NGInlineNode>(child)) { if (auto* child_inline_node = DynamicTo<NGInlineNode>(child)) {
if (!last_inline_break_token_) { if (!last_inline_break_token_) {
// In some cases we may want to break before the first line, as a last // In some cases we may want to break before the first line in the
// resort. We need a break token for that as well, so that the machinery // fragment. This happens if there's a tall float before the line, or, as
// will understand that we should resume at the beginning of the inline // a last resort, when there are no better breakpoints to choose from, and
// formatting context, rather than concluding that we're done with the // we're out of space. When laying out, we store the inline break token
// whole thing. // from the last line added to the builder, but if we haven't added any
// lines at all, we are still going to need a break token, so that the we
// can tell where to resume in the inline formatting context in the next
// fragmentainer.
if (previous_break_token_) {
// If there's an incoming break token, see if it has a child inline
// break token, and use that one. We may be past floats or lines that
// were laid out in earlier fragments.
const auto& child_tokens = previous_break_token_->ChildBreakTokens();
if (child_tokens.size()) {
// If there is an inline break token, it will always be the last
// child.
last_inline_break_token_ =
DynamicTo<NGInlineBreakToken>(child_tokens.back());
if (last_inline_break_token_)
return;
}
}
// We're at the beginning of the inline formatting context.
last_inline_break_token_ = NGInlineBreakToken::Create( last_inline_break_token_ = NGInlineBreakToken::Create(
*child_inline_node, /* style */ nullptr, /* item_index */ 0, *child_inline_node, /* style */ nullptr, /* item_index */ 0,
/* text_offset */ 0, NGInlineBreakToken::kDefault); /* text_offset */ 0, NGInlineBreakToken::kDefault);
......
<!DOCTYPE html>
<link rel="author" title="Morten Stenshorne" href="mailto:mstensho@chromium.org">
<link rel="help" href="https://www.w3.org/TR/css-break-3/#breaking-rules">
<link rel="help" href="https://bugs.chromium.org/p/chromium/issues/detail?id=1122901">
<link rel="match" href="../reference/ref-filled-green-100px-square.xht">
<p>Test passes if there is a filled green square and <strong>no red</strong>.</p>
<div style="columns:4; column-fill:auto; column-gap:0; width:100px; height:100px; background:red;">
<div style="float:left; width:100%; height:350px; background:green;"></div>
<div style="display:inline-block; vertical-align:top; width:100%; height:50px; background:green;"></div>
</div>
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