Commit 3e138a8e authored by Koji Ishii's avatar Koji Ishii Committed by Commit Bot

[LayoutNG] Fix line breaking when `font-size: 0`

This patch fixes line breaking when break opportunities have
`font-size: 0`.

`font-size: 0` makes all characters at position 0. This
confuses when |NGLineBreaker| needs to rewind, and tries to
find the break opportunity before the current one.

This patch fixes it by using |PreviousBreakOpportunity| in
such case.

Bug: 1006127
Change-Id: I449d6f8aaba4deccd458c5e077920b1a8bf79305
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1843991Reviewed-by: default avatarYoshifumi Inoue <yosin@chromium.org>
Reviewed-by: default avatarEmil A Eklund <eae@chromium.org>
Commit-Queue: Koji Ishii <kojii@chromium.org>
Cr-Commit-Position: refs/heads/master@{#703753}
parent 95cd3c10
......@@ -748,6 +748,31 @@ NGLineBreaker::BreakResult NGLineBreaker::BreakText(
return inline_size <= available_width ? kSuccess : kOverflow;
}
// Breaks the text item at the previous break opportunity from
// |item_result->end_offset|. Returns false if there were no previous break
// opportunities.
bool NGLineBreaker::BreakTextAtPreviousBreakOpportunity(
NGInlineItemResult* item_result) {
DCHECK(item_result->item);
DCHECK(item_result->may_break_inside);
const NGInlineItem& item = *item_result->item;
DCHECK_EQ(item.Type(), NGInlineItem::kText);
DCHECK(item.Style() && item.Style()->AutoWrap());
unsigned break_opportunity = break_iterator_.PreviousBreakOpportunity(
item_result->end_offset - 1, item_result->start_offset);
if (break_opportunity <= item_result->start_offset)
return false;
item_result->end_offset = break_opportunity;
item_result->shape_result =
ShapeResultView::Create(item.TextShapeResult(), item_result->start_offset,
item_result->end_offset);
item_result->inline_size =
item_result->shape_result->SnappedWidth().ClampNegativeToZero();
item_result->can_break_after = true;
return true;
}
// This function handles text item for min-content. The specialized logic is
// because min-content is very expensive by breaking at every break opportunity
// and producing as many lines as the number of break opportunities.
......@@ -1596,10 +1621,24 @@ void NGLineBreaker::HandleOverflow(NGLineInfo* line_info) {
// If space is available, and if this text is breakable, part of the text
// may fit. Try to break this item.
if (width_to_rewind < 0 && item_result->may_break_inside) {
// When the text fits but its right margin does not, the break point
// must not be at the end.
LayoutUnit item_available_width =
std::min(-width_to_rewind, item_result->inline_size - 1);
LayoutUnit item_available_width = -width_to_rewind;
// Make sure the available width is smaller than the current width. The
// break point must not be at the end when e.g., the text fits but its
// right margin does not or following items do not.
const LayoutUnit min_available_width = item_result->inline_size - 1;
if (item_available_width > min_available_width) {
item_available_width = min_available_width;
// If |inline_size| is zero (e.g., `font-size: 0`), |BreakText| cannot
// make it shorter. Take the previous break opportunity.
if (UNLIKELY(item_available_width <= 0)) {
if (BreakTextAtPreviousBreakOpportunity(item_result)) {
state_ = LineBreakState::kTrailing;
Rewind(i + 1, line_info);
return;
}
continue;
}
}
auto was_current_style = current_style_;
SetCurrentStyle(*item.Style());
BreakResult break_result =
......
......@@ -138,6 +138,7 @@ class CORE_EXPORT NGLineBreaker {
const ShapeResult&,
LayoutUnit available_width,
NGLineInfo*);
bool BreakTextAtPreviousBreakOpportunity(NGInlineItemResult* item_result);
bool ShouldHangTraillingSpaces(const NGInlineItem&);
bool HandleTextForFastMinContent(NGInlineItemResult*,
const NGInlineItem&,
......
<!DOCTYPE html>
<style>
div {
width: 100px;
background: blue;
}
inline-block {
display: inline-block;
width: 80px;
height: 1em;
background: orange;
}
</style>
</head>
<body>
<div>
<inline-block></inline-block><br>
<inline-block></inline-block><br>
<inline-block></inline-block><br>
<inline-block></inline-block><br>
<inline-block></inline-block>
</div>
</body>
<!DOCTYPE html>
<title>CSS Test: Check line breaks when break opportunities have font-size: 0</title>
<link rel="match" href="line-breaking-font-size-zero-001-ref.html">
<link rel="help" href="https://drafts.csswg.org/css2/text.html#propdef-white-space" />
<link rel="author" href="mailto:kojii@chromium.org">
<style>
div {
width: 100px;
background: blue;
}
inline-block {
display: inline-block;
width: 80px;
height: 1em;
background: orange;
}
sep {
font-size: 0;
}
</style>
</head>
<body>
<div>
<inline-block></inline-block><sep> </sep>
<inline-block></inline-block><sep>, </sep>
<inline-block></inline-block><sep>) (</sep>
<inline-block></inline-block><sep>a</sep>
<inline-block></inline-block>
</div>
</body>
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