Commit 8a1b3565 authored by Koji Ishii's avatar Koji Ishii Committed by Commit Bot

Merge the forked code in LazyLineBreakIterator and some cleanup

The word-break:keep-all code was forked in [1]. This patch merges it
back to single template function, in preparation of supporting
after-white-space in LayoutNG.

Includes some cleanup to make IsBreakable() inline function smaller
without increasing non-inline function calls.

[1] https://codereview.chromium.org/1094863007

BUG=636993

Change-Id: I6471b83437e29f5ee2fcb30473c8eb8d526abf35
Reviewed-on: https://chromium-review.googlesource.com/575799
Commit-Queue: Koji Ishii <kojii@chromium.org>
Reviewed-by: default avatarEmil A Eklund <eae@chromium.org>
Cr-Commit-Position: refs/heads/master@{#488146}
parent ee8ec000
......@@ -244,30 +244,48 @@ static inline bool ShouldBreakAfterBreakAll(ULineBreak last_line_break,
return false;
}
// Computes if 'word-break:keep-all' should prevent line break.
// https://drafts.csswg.org/css-text-3/#valdef-word-break-keep-all
// The spec is not very verbose on how this should work. This logic prevents L/M
// general categories and complex line breaking since the spec says "except some
// south east aisans".
// https://github.com/w3c/csswg-drafts/issues/1619
static inline bool ShouldKeepAfterKeepAll(UChar last_ch,
UChar ch,
UChar next_ch) {
UChar pre_ch = U_MASK(u_charType(ch)) & U_GC_M_MASK ? last_ch : ch;
return U_MASK(u_charType(pre_ch)) & (U_GC_L_MASK | U_GC_N_MASK) &&
!WTF::Unicode::HasLineBreakingPropertyComplexContext(pre_ch) &&
U_MASK(u_charType(next_ch)) & (U_GC_L_MASK | U_GC_N_MASK) &&
!WTF::Unicode::HasLineBreakingPropertyComplexContext(next_ch);
}
inline bool NeedsLineBreakIterator(UChar ch) {
return ch > kAsciiLineBreakTableLastChar && ch != kNoBreakSpaceCharacter;
}
template <typename CharacterType, LineBreakType lineBreakType>
static inline int NextBreakablePosition(
const LazyLineBreakIterator& lazy_break_iterator,
const CharacterType* str,
unsigned length,
int pos) {
int len = static_cast<int>(length);
inline int LazyLineBreakIterator::NextBreakablePosition(
int pos,
const CharacterType* str) const {
int len = static_cast<int>(string_.length());
int next_break = -1;
UChar last_last_ch =
pos > 1 ? str[pos - 2] : lazy_break_iterator.SecondToLastCharacter();
UChar last_ch = pos > 0 ? str[pos - 1] : lazy_break_iterator.LastCharacter();
UChar last_last_ch = pos > 1 ? str[pos - 2] : SecondToLastCharacter();
UChar last_ch = pos > 0 ? str[pos - 1] : LastCharacter();
bool is_last_space = IsBreakableSpace(last_ch);
ULineBreak last_line_break;
if (lineBreakType == LineBreakType::kBreakAll)
last_line_break = LineBreakPropertyValue(last_last_ch, last_ch);
unsigned prior_context_length = lazy_break_iterator.PriorContextLength();
for (int i = pos; i < len; i++) {
CharacterType ch = str[i];
if (IsBreakableSpace(ch) || ShouldBreakAfter(last_last_ch, last_ch, ch))
unsigned prior_context_length = PriorContextLength();
CharacterType ch;
bool is_space;
for (int i = pos; i < len;
i++, last_last_ch = last_ch, last_ch = ch, is_last_space = is_space) {
ch = str[i];
is_space = IsBreakableSpace(ch);
if (is_space || ShouldBreakAfter(last_last_ch, last_ch, ch))
return i;
if (lineBreakType == LineBreakType::kBreakAll && !U16_IS_LEAD(ch)) {
......@@ -278,70 +296,18 @@ static inline int NextBreakablePosition(
last_line_break = line_break;
}
if (NeedsLineBreakIterator(ch) || NeedsLineBreakIterator(last_ch)) {
if (next_break < i) {
// Don't break if positioned at start of primary context and there is no
// prior context.
if (i || prior_context_length) {
TextBreakIterator* break_iterator =
lazy_break_iterator.Get(prior_context_length);
if (break_iterator) {
next_break =
break_iterator->following(i - 1 + prior_context_length);
if (next_break >= 0) {
next_break -= prior_context_length;
}
}
}
}
if (i == next_break && !IsBreakableSpace(last_ch))
return i;
if (lineBreakType == LineBreakType::kKeepAll &&
ShouldKeepAfterKeepAll(last_last_ch, last_ch, ch)) {
// word-break:keep-all prevents breaks between East Asian ideographic.
continue;
}
last_last_ch = last_ch;
last_ch = ch;
}
return len;
}
static inline bool ShouldKeepAfter(UChar last_ch, UChar ch, UChar next_ch) {
UChar pre_ch = U_MASK(u_charType(ch)) & U_GC_M_MASK ? last_ch : ch;
return U_MASK(u_charType(pre_ch)) & (U_GC_L_MASK | U_GC_N_MASK) &&
!WTF::Unicode::HasLineBreakingPropertyComplexContext(pre_ch) &&
U_MASK(u_charType(next_ch)) & (U_GC_L_MASK | U_GC_N_MASK) &&
!WTF::Unicode::HasLineBreakingPropertyComplexContext(next_ch);
}
static inline int NextBreakablePositionKeepAllInternal(
const LazyLineBreakIterator& lazy_break_iterator,
const UChar* str,
unsigned length,
int pos) {
int len = static_cast<int>(length);
int next_break = -1;
UChar last_last_ch =
pos > 1 ? str[pos - 2]
: static_cast<UChar>(lazy_break_iterator.SecondToLastCharacter());
UChar last_ch = pos > 0
? str[pos - 1]
: static_cast<UChar>(lazy_break_iterator.LastCharacter());
unsigned prior_context_length = lazy_break_iterator.PriorContextLength();
for (int i = pos; i < len; i++) {
UChar ch = str[i];
if (IsBreakableSpace(ch) || ShouldBreakAfter(last_last_ch, last_ch, ch))
return i;
if (!ShouldKeepAfter(last_last_ch, last_ch, ch) &&
(NeedsLineBreakIterator(ch) || NeedsLineBreakIterator(last_ch))) {
if (NeedsLineBreakIterator(ch) || NeedsLineBreakIterator(last_ch)) {
if (next_break < i) {
// Don't break if positioned at start of primary context and there is no
// prior context.
if (i || prior_context_length) {
TextBreakIterator* break_iterator =
lazy_break_iterator.Get(prior_context_length);
TextBreakIterator* break_iterator = Get(prior_context_length);
if (break_iterator) {
next_break =
break_iterator->following(i - 1 + prior_context_length);
......@@ -351,43 +317,22 @@ static inline int NextBreakablePositionKeepAllInternal(
}
}
}
if (i == next_break && !IsBreakableSpace(last_ch))
if (i == next_break && !is_last_space)
return i;
}
last_last_ch = last_ch;
last_ch = ch;
}
return len;
}
template <LineBreakType lineBreakType>
static inline int NextBreakablePosition(
const LazyLineBreakIterator& lazy_break_iterator,
const String& string,
int pos) {
if (string.Is8Bit())
return NextBreakablePosition<LChar, lineBreakType>(
lazy_break_iterator, string.Characters8(), string.length(), pos);
return NextBreakablePosition<UChar, lineBreakType>(
lazy_break_iterator, string.Characters16(), string.length(), pos);
}
int LazyLineBreakIterator::NextBreakablePositionIgnoringNBSP(int pos) const {
return NextBreakablePosition<LineBreakType::kNormal>(*this, string_, pos);
}
int LazyLineBreakIterator::NextBreakablePositionBreakAll(int pos) const {
return NextBreakablePosition<LineBreakType::kBreakAll>(*this, string_, pos);
}
int LazyLineBreakIterator::NextBreakablePositionKeepAll(int pos) const {
if (string_.Is8Bit())
return NextBreakablePosition<LChar, LineBreakType::kNormal>(
*this, string_.Characters8(), string_.length(), pos);
return NextBreakablePositionKeepAllInternal(*this, string_.Characters16(),
string_.length(), pos);
inline int LazyLineBreakIterator::NextBreakablePosition(int pos) const {
if (string_.Is8Bit()) {
return NextBreakablePosition<LChar, lineBreakType>(pos,
string_.Characters8());
}
return NextBreakablePosition<UChar, lineBreakType>(pos,
string_.Characters16());
}
int LazyLineBreakIterator::NextBreakablePositionBreakCharacter(int pos) const {
......@@ -396,6 +341,23 @@ int LazyLineBreakIterator::NextBreakablePositionBreakCharacter(int pos) const {
return next != kTextBreakDone ? next : string_.length();
}
int LazyLineBreakIterator::NextBreakablePosition(
int pos,
LineBreakType line_break_type) const {
switch (line_break_type) {
case LineBreakType::kNormal:
return NextBreakablePosition<LineBreakType::kNormal>(pos);
case LineBreakType::kBreakAll:
return NextBreakablePosition<LineBreakType::kBreakAll>(pos);
case LineBreakType::kKeepAll:
return NextBreakablePosition<LineBreakType::kKeepAll>(pos);
case LineBreakType::kBreakCharacter:
return NextBreakablePositionBreakCharacter(pos);
}
NOTREACHED();
return NextBreakablePosition(pos, LineBreakType::kNormal);
}
unsigned LazyLineBreakIterator::NextBreakOpportunity(unsigned offset) const {
int next_break = -1;
IsBreakable(offset, next_break);
......
......@@ -214,20 +214,7 @@ class PLATFORM_EXPORT LazyLineBreakIterator final {
int& next_breakable,
LineBreakType line_break_type) const {
if (pos > next_breakable) {
switch (line_break_type) {
case LineBreakType::kBreakAll:
next_breakable = NextBreakablePositionBreakAll(pos);
break;
case LineBreakType::kKeepAll:
next_breakable = NextBreakablePositionKeepAll(pos);
break;
case LineBreakType::kNormal:
next_breakable = NextBreakablePositionIgnoringNBSP(pos);
break;
case LineBreakType::kBreakCharacter:
next_breakable = NextBreakablePositionBreakCharacter(pos);
break;
}
next_breakable = NextBreakablePosition(pos, line_break_type);
}
return pos == next_breakable;
}
......@@ -256,10 +243,12 @@ class PLATFORM_EXPORT LazyLineBreakIterator final {
cached_prior_context_length_ = 0;
}
int NextBreakablePositionIgnoringNBSP(int pos) const;
int NextBreakablePositionBreakAll(int pos) const;
int NextBreakablePositionKeepAll(int pos) const;
template <typename CharacterType, LineBreakType>
int NextBreakablePosition(int pos, const CharacterType* str) const;
template <LineBreakType>
int NextBreakablePosition(int pos) const;
int NextBreakablePositionBreakCharacter(int pos) const;
int NextBreakablePosition(int pos, LineBreakType) const;
static const unsigned kPriorContextCapacity = 2;
String string_;
......
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