| Index: ui/gfx/render_text_harfbuzz.cc
|
| diff --git a/ui/gfx/render_text_harfbuzz.cc b/ui/gfx/render_text_harfbuzz.cc
|
| index f34dce7e3fb4d8182d76b59b6244dc06c7a036c8..c7b070f292cbb869e5c84c89a85c62d1ce574246 100644
|
| --- a/ui/gfx/render_text_harfbuzz.cc
|
| +++ b/ui/gfx/render_text_harfbuzz.cc
|
| @@ -224,6 +224,7 @@ class HarfBuzzLineBreaker {
|
| int min_baseline,
|
| float min_height,
|
| bool multiline,
|
| + WordWrapBehavior word_wrap_behavior,
|
| const base::string16& text,
|
| const BreakList<size_t>* words,
|
| const internal::TextRunList& run_list)
|
| @@ -231,6 +232,7 @@ class HarfBuzzLineBreaker {
|
| min_baseline_(min_baseline),
|
| min_height_(min_height),
|
| multiline_(multiline),
|
| + word_wrap_behavior_(word_wrap_behavior),
|
| text_(text),
|
| words_(words),
|
| run_list_(run_list),
|
| @@ -285,9 +287,10 @@ class HarfBuzzLineBreaker {
|
| // Break the run until it fits the current line.
|
| while (next_char < run.range.end()) {
|
| const size_t current_char = next_char;
|
| + size_t end_char = next_char;
|
| const bool skip_line =
|
| - BreakRunAtWidth(run, current_char, &width, &next_char);
|
| - AddSegment(run_index, Range(current_char, next_char),
|
| + BreakRunAtWidth(run, current_char, &width, &end_char, &next_char);
|
| + AddSegment(run_index, Range(current_char, end_char),
|
| SkScalarToFloat(width));
|
| if (skip_line)
|
| AdvanceLine();
|
| @@ -298,7 +301,8 @@ class HarfBuzzLineBreaker {
|
| // before available width using word break. If the current position is at the
|
| // beginning of a line, this function will not roll back to |start_char| and
|
| // |*next_char| will be greater than |start_char| (to avoid constructing empty
|
| - // lines).
|
| + // lines). It stores the end of the segment range to |end_char|, which can be
|
| + // smaller than |*next_char| for certain word wrapping behavior.
|
| // Returns whether to skip the line before |*next_char|.
|
| // TODO(ckocagil): We might have to reshape after breaking at ligatures.
|
| // See whether resolving the TODO above resolves this too.
|
| @@ -306,6 +310,7 @@ class HarfBuzzLineBreaker {
|
| bool BreakRunAtWidth(const internal::TextRunHarfBuzz& run,
|
| size_t start_char,
|
| SkScalar* width,
|
| + size_t* end_char,
|
| size_t* next_char) {
|
| DCHECK(words_);
|
| DCHECK(run.range.Contains(Range(start_char, start_char + 1)));
|
| @@ -317,11 +322,21 @@ class HarfBuzzLineBreaker {
|
| *width = 0;
|
|
|
| Range char_range;
|
| + SkScalar truncated_width = 0;
|
| for (size_t i = start_char; i < run.range.end(); i += char_range.length()) {
|
| // |word| holds the word boundary at or before |i|, and |next_word| holds
|
| // the word boundary right after |i|. Advance both |word| and |next_word|
|
| // when |i| reaches |next_word|.
|
| if (next_word != words_->breaks().end() && i >= next_word->first) {
|
| + if (*width > available_width) {
|
| + DCHECK_NE(WRAP_LONG_WORDS, word_wrap_behavior_);
|
| + *next_char = i;
|
| + if (word_wrap_behavior_ != TRUNCATE_LONG_WORDS)
|
| + *end_char = *next_char;
|
| + else
|
| + *width = truncated_width;
|
| + return true;
|
| + }
|
| word = next_word++;
|
| word_width = 0;
|
| }
|
| @@ -338,24 +353,35 @@ class HarfBuzzLineBreaker {
|
| *width += char_width;
|
| word_width += char_width;
|
|
|
| + // TODO(mukai): implement ELIDE_LONG_WORDS.
|
| if (*width > available_width) {
|
| if (line_x_ != 0 || word_width < *width) {
|
| // Roll back one word.
|
| *width -= word_width;
|
| *next_char = std::max(word->first, start_char);
|
| - } else if (char_width < *width) {
|
| - // Roll back one character.
|
| - *width -= char_width;
|
| - *next_char = i;
|
| - } else {
|
| - // Continue from the next character.
|
| - *next_char = i + char_range.length();
|
| + *end_char = *next_char;
|
| + return true;
|
| + } else if (word_wrap_behavior_ == WRAP_LONG_WORDS) {
|
| + if (char_width < *width) {
|
| + // Roll back one character.
|
| + *width -= char_width;
|
| + *next_char = i;
|
| + } else {
|
| + // Continue from the next character.
|
| + *next_char = i + char_range.length();
|
| + }
|
| + *end_char = *next_char;
|
| + return true;
|
| }
|
| - return true;
|
| + } else {
|
| + *end_char = char_range.end();
|
| + truncated_width = *width;
|
| }
|
| }
|
|
|
| - *next_char = run.range.end();
|
| + if (word_wrap_behavior_ == TRUNCATE_LONG_WORDS)
|
| + *width = truncated_width;
|
| + *end_char = *next_char = run.range.end();
|
| return false;
|
| }
|
|
|
| @@ -448,6 +474,7 @@ class HarfBuzzLineBreaker {
|
| const int min_baseline_;
|
| const float min_height_;
|
| const bool multiline_;
|
| + const WordWrapBehavior word_wrap_behavior_;
|
| const base::string16& text_;
|
| const BreakList<size_t>* const words_;
|
| const internal::TextRunList& run_list_;
|
| @@ -997,7 +1024,8 @@ void RenderTextHarfBuzz::EnsureLayout() {
|
| HarfBuzzLineBreaker line_breaker(
|
| display_rect().width(), font_list().GetBaseline(),
|
| std::max(font_list().GetHeight(), min_line_height()), multiline(),
|
| - GetDisplayText(), multiline() ? &GetLineBreaks() : nullptr, *run_list);
|
| + word_wrap_behavior(), GetDisplayText(),
|
| + multiline() ? &GetLineBreaks() : nullptr, *run_list);
|
|
|
| // TODO(vadimt): Remove ScopedTracker below once crbug.com/431326 is fixed.
|
| tracked_objects::ScopedTracker tracking_profile3(
|
|
|