Commit 6ea2a2e7 authored by Javier Fernandez's avatar Javier Fernandez Committed by Commit Bot

[css-text] A leading white-space should break before handling overflow

Leading white-spaces are indeed breaking opportunities that should
prevent, if there are no other css properties forcing it, breaking text
in the middle of a word when honoring the word-wrap/overflow-wrap CSS
property.

We are doing so if the leading white-space sequence is longer than 1
character, but when we have a single leading white-space, we are missing
that breaking opportunity and we may lead to cases, like the one
described in the bug.

However, this breaking opportunity should be considered together
with other provided by the word-break CSS property (eg, break-word or
break-all).

There is a discussion [1] in the CSS WG github about this issue, which
provides an interoperability analysis of a few cases where a single
leading white-space character may produce different results, depending
on the browser and the combination of line-breaking properties.

[1] https://github.com/w3c/csswg-drafts/issues/2907

Bug: 854624
Change-Id: I49ec8282e899a32990662c104b48cab04057b909
Reviewed-on: https://chromium-review.googlesource.com/1130515
Commit-Queue: Javier Fernandez <jfernandez@igalia.com>
Reviewed-by: default avatarKoji Ishii <kojii@chromium.org>
Cr-Commit-Position: refs/heads/master@{#575596}
parent fe5239c6
<!DOCTYPE html>
<meta charset="utf-8">
<title>CSS Text Test: overflow-wrap: break-word</title>
<link rel="author" title="Javier Fernandez Garcia-Boente" href="mailto:jfernandez@igalia.com">
<link rel="help" href="https://drafts.csswg.org/css-text-3/#valdef-overflow-wrap-break-word">
<meta name="flags" content="ahem">
<link rel="match" href="reference/overflow-wrap-break-word-001-ref.html">
<meta name="assert" content="A Single leading white-space constitutes a soft breaking opportunity, honoring the 'white-space: pre-wrap' property, that must prevent the word to be broken.">
<style>
div {
position: relative;
font-size: 20px;
font-family: Ahem;
}
.red {
position: absolute;
background: green;
color: red;
width: 100px;
height: 100px;
z-index: -1;
}
.test {
color: green;
line-height: 1em;
width: 5ch;
white-space: pre-wrap;
overflow-wrap: break-word;
}
</style>
<body>
<p>Test passes if there is a <strong>filled green square</strong> and <strong>no red</strong>.</p>
<div class="red"><br>XXXXX</div>
<div class="test"> XXXXX </div>
</body>
<!DOCTYPE html>
<meta charset="utf-8">
<title>CSS Text Reference File</title>
<link rel="author" title="Florian Rivoal" href="http://florian.rivoal.net/">
<style>
div {
position: relative;
width: 100px;
height: 100px;
background: green;
}
</style>
<body>
<p>Test passes if there is a <strong>filled green square</strong> and <strong>no red</strong>.</p>
<div></div>
</body>
<!DOCTYPE html>
<meta charset="utf-8">
<title>CSS Text Test: overflow-wrap: break-word</title>
<link rel="author" title="Javier Fernandez Garcia-Boente" href="mailto:jfernandez@igalia.com">
<link rel="help" href="https://drafts.csswg.org/css-text-3/#valdef-word-break-break-all">
<meta name="flags" content="ahem">
<link rel="match" href="reference/word-break-break-all-010-ref.html">
<meta name="assert" content="The word is broken even if pre-wrap provides a former breaking opportunity in leading white-space.">
<style>
div {
position: relative;
font-size: 20px;
font-family: Ahem;
}
.red {
position: absolute;
white-space: pre;
background: green;
color: red;
width: 100px;
height: 100px;
z-index: -1;
}
.test {
color: green;
line-height: 1em;
width: 5ch;
white-space: pre-wrap;
word-break: break-all;
}
</style>
<body>
<p>Test passes if there is a <strong>filled green square</strong> and <strong>no red</strong>.</p>
<div class="red"> XXXX<br>X</div>
<div class="test"> XXXXX</div>
</body>
<!DOCTYPE html>
<meta charset="utf-8">
<title>CSS Text Test: overflow-wrap: break-word</title>
<link rel="author" title="Javier Fernandez Garcia-Boente" href="mailto:jfernandez@igalia.com">
<link rel="help" href="https://drafts.csswg.org/css-text-3/#valdef-word-break-break-all">
<meta name="flags" content="ahem">
<link rel="match" href="reference/word-break-break-all-010-ref.html">
<meta name="assert" content="A single leading white-space should account as soft breaking opportunity, honoring the 'white-space: pre-wrap', on top to the ones provided by 'word-break: break-all'.">
<style>
div {
position: relative;
font-size: 20px;
font-family: Ahem;
}
.red {
position: absolute;
background: green;
color: red;
width: 100px;
height: 100px;
z-index: -1;
}
.test {
color: green;
background: green;
line-height: 1em;
width: 1ch;
white-space: pre-wrap;
word-break: break-all;
}
</style>
<body>
<p>Test passes if there is a <strong>filled green square</strong> and <strong>no red</strong>.</p>
<div class="red">X<br>X<br>X</div>
<div class="test"> XX</div>
</body>
......@@ -824,7 +824,7 @@ ALWAYS_INLINE bool BreakingContext::RewindToFirstMidWordBreak(
int start = word_measurement.start_offset;
int end = CanMidWordBreakBefore(text)
? start
: break_iterator.NextBreakOpportunity(start + 1);
: break_iterator.NextBreakOpportunity(start);
if (end >= word_measurement.end_offset)
return false;
......@@ -1061,11 +1061,13 @@ inline bool BreakingContext::HandleText(WordMeasurements& word_measurements,
break_all, next_breakable_position_for_break_all);
}
// Determine if we are in the whitespace between words.
// Determine if we are in the whitespace between words or in a leading
// whitespace.
int next_breakable_position = current_.NextBreakablePosition();
bool between_words =
c == kNewlineCharacter ||
(curr_ws_ != EWhiteSpace::kPre && !at_start_ &&
(curr_ws_ != EWhiteSpace::kPre &&
(!at_start_ || current_character_is_space_) &&
layout_text_info_.line_break_iterator_.IsBreakable(
current_.Offset(), next_breakable_position, line_break_type) &&
(!disable_soft_hyphen ||
......@@ -1209,7 +1211,8 @@ inline bool BreakingContext::HandleText(WordMeasurements& word_measurements,
}
// Auto-wrapping text should not wrap in the middle of a word once it has
// had an opportunity to break after a word.
// had an opportunity to break after a word or before, at a leading
// white-space.
if (auto_wrap_ && between_words) {
width_.Commit();
width_from_last_breaking_opportunity = 0;
......
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