diff options
author | mukai <mukai@chromium.org> | 2015-03-27 17:07:05 -0700 |
---|---|---|
committer | Commit bot <commit-bot@chromium.org> | 2015-03-28 00:07:56 +0000 |
commit | a19339399b745657a9d9e7f288cfc797f90403f5 (patch) | |
tree | c4a6ca86b88883a8a75823a91ec0c2bf7966a721 /ui/gfx/render_text_harfbuzz.cc | |
parent | c13a5f6f39e24b8e465250bc6f7ab379bd0f240e (diff) | |
download | chromium_src-a19339399b745657a9d9e7f288cfc797f90403f5.zip chromium_src-a19339399b745657a9d9e7f288cfc797f90403f5.tar.gz chromium_src-a19339399b745657a9d9e7f288cfc797f90403f5.tar.bz2 |
Move allow_character_break property to RenderText.
gfx::ElideRectangleText creates lots of RenderText object which
causes the performance regression. This CL avoids invoking the
method by moving allow_character_break property to RenderText.
BUG=470506
R=msw@chromium.org, sky@chromium.org
TEST=the new test case covers
Review URL: https://codereview.chromium.org/1015533016
Cr-Commit-Position: refs/heads/master@{#322681}
Diffstat (limited to 'ui/gfx/render_text_harfbuzz.cc')
-rw-r--r-- | ui/gfx/render_text_harfbuzz.cc | 54 |
1 files changed, 41 insertions, 13 deletions
diff --git a/ui/gfx/render_text_harfbuzz.cc b/ui/gfx/render_text_harfbuzz.cc index f34dce7..c7b070f 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( |