Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(205)

Unified Diff: ui/gfx/render_text_harfbuzz.cc

Issue 1070223004: Stop combining text runs which are connected by 'COMMON' blocks. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Address Mukai's comments. Created 5 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « ui/gfx/render_text_harfbuzz.h ('k') | ui/gfx/render_text_unittest.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: ui/gfx/render_text_harfbuzz.cc
diff --git a/ui/gfx/render_text_harfbuzz.cc b/ui/gfx/render_text_harfbuzz.cc
index 32a9e554f60b47127cef9d426aef71a9f410adfa..0db4394cd66ea3c7b3beb883e5a16d499d9254e7 100644
--- a/ui/gfx/render_text_harfbuzz.cc
+++ b/ui/gfx/render_text_harfbuzz.cc
@@ -90,15 +90,12 @@ size_t FindRunBreakingCharacter(const base::string16& text,
return run_break;
}
-// If the given scripts match, returns the one that isn't USCRIPT_COMMON or
-// USCRIPT_INHERITED, i.e. the more specific one. Otherwise returns
-// USCRIPT_INVALID_CODE.
+// If the given scripts match, returns the one that isn't USCRIPT_INHERITED,
+// i.e. the more specific one. Otherwise returns USCRIPT_INVALID_CODE.
UScriptCode ScriptIntersect(UScriptCode first, UScriptCode second) {
- if (first == second ||
- (second > USCRIPT_INVALID_CODE && second <= USCRIPT_INHERITED)) {
+ if (first == second || second == USCRIPT_INHERITED)
return first;
- }
- if (first > USCRIPT_INVALID_CODE && first <= USCRIPT_INHERITED)
+ if (first == USCRIPT_INHERITED)
return second;
return USCRIPT_INVALID_CODE;
}
@@ -167,6 +164,11 @@ int ScriptInterval(const base::string16& text,
while (char_iterator.Advance()) {
Jun Mukai 2015/04/29 21:09:07 Hm, why not just doing if (u_isUWhiteSpace(char_it
xdai1 2015/05/05 18:27:49 As I said in the previous comment to msw@, this is
ScriptSetIntersect(char_iterator.get(), scripts, &scripts_size);
+ // Special handling to merge white space into the previous run.
+ if (u_isUWhiteSpace(char_iterator.get())) {
+ scripts[0] = *script;
+ scripts_size = 1U;
+ }
if (scripts_size == 0U)
return char_iterator.array_pos();
*script = scripts[0];
@@ -239,7 +241,9 @@ class HarfBuzzLineBreaker {
text_x_(0),
line_x_(0),
max_descent_(0),
- max_ascent_(0) {
+ max_ascent_(0),
+ next_word_start_pos_(0),
+ word_width_(0) {
DCHECK_EQ(multiline_, (words_ != nullptr));
AdvanceLine();
}
@@ -248,6 +252,15 @@ class HarfBuzzLineBreaker {
void AddRun(int run_index) {
const internal::TextRunHarfBuzz* run = run_list_.runs()[run_index];
base::char16 first_char = text_[run->range.start()];
+
+ if (word_wrap_behavior_ == TRUNCATE_LONG_WORDS && words_) {
+ // If the run has been processed, skip it.
+ size_t current_word_start_pos =
+ words_->GetBreak(run->range.start())->first;
+ if (current_word_start_pos < next_word_start_pos_)
+ return;
+ }
+
if (multiline_ && first_char == '\n') {
AdvanceLine();
} else if (multiline_ && (line_x_ + SkFloatToScalar(run->width)) >
@@ -317,8 +330,8 @@ class HarfBuzzLineBreaker {
SkScalar available_width = max_width_ - line_x_;
BreakList<size_t>::const_iterator word = words_->GetBreak(start_char);
BreakList<size_t>::const_iterator next_word = word + 1;
- // Width from |std::max(word->first, start_char)| to the current character.
- SkScalar word_width = 0;
+ next_word_start_pos_ =
Jun Mukai 2015/04/29 21:09:07 Probably word_end_pos_ would be a better name?
xdai1 2015/05/05 18:27:49 Done.
+ (next_word == words_->breaks().end()) ? text_.size() : next_word->first;
*width = 0;
Range char_range;
@@ -328,17 +341,11 @@ class HarfBuzzLineBreaker {
// 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) {
Jun Mukai 2015/04/29 21:09:07 I am not sure if removing this block works correct
xdai1 2015/05/05 18:27:49 In third run it won't come inside this inner if be
Jun Mukai 2015/05/06 17:38:52 For line 387, the behavior has to be TRUNCATE_LONG
xdai1 2015/05/06 20:23:44 In this case when it comes to "b", it will return
Jun Mukai 2015/05/06 20:47:55 No, "b " and "ccc" must be in a single run, they a
- 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;
+ next_word_start_pos_ = (next_word == words_->breaks().end())
+ ? text_.size()
+ : next_word->first;
+ word_width_ = 0;
}
Range glyph_range;
@@ -351,15 +358,17 @@ class HarfBuzzLineBreaker {
run.positions[glyph_range.start()].x();
*width += char_width;
- word_width += char_width;
+ word_width_ += char_width;
// TODO(mukai): implement ELIDE_LONG_WORDS.
if (*width > available_width) {
- if (line_x_ != 0 || word_width < *width) {
+ if ((line_x_ != 0 && word_width_ <= *width) ||
+ (line_x_ == 0 && word_width_ < *width)) {
// Roll back one word.
- *width -= word_width;
+ *width -= word_width_;
*next_char = std::max(word->first, start_char);
*end_char = *next_char;
+ word_width_ = 0;
return true;
} else if (word_wrap_behavior_ == WRAP_LONG_WORDS) {
if (char_width < *width) {
@@ -372,6 +381,10 @@ class HarfBuzzLineBreaker {
}
*end_char = *next_char;
return true;
+ } else if (word_wrap_behavior_ == TRUNCATE_LONG_WORDS) {
+ *width = truncated_width;
+ *next_char = next_word_start_pos_;
+ return true;
}
} else {
*end_char = char_range.end();
@@ -423,6 +436,7 @@ class HarfBuzzLineBreaker {
max_descent_ = 0;
max_ascent_ = 0;
line_x_ = 0;
+ word_width_ = 0;
lines_.push_back(internal::Line());
}
@@ -468,6 +482,31 @@ class HarfBuzzLineBreaker {
}
text_x_ += SkFloatToScalar(width);
line_x_ += SkFloatToScalar(width);
+
+ // Calculate |word_width_|.
+ if (words_) {
+ BreakList<size_t>::const_iterator current_word =
+ (char_range.start() == 0) ? words_->breaks().begin()
+ : words_->GetBreak(char_range.end() - 1);
+ BreakList<size_t>::const_iterator next_word =
+ (char_range.end() == text_.size())
+ ? words_->breaks().end()
+ : words_->GetBreak(char_range.end());
+ if (word_width_ == 0 && current_word == next_word) {
+ Range tmp_range;
+ Range glyph_range;
+ for (size_t pos = current_word->first; pos < char_range.end(); ++pos) {
+ run.GetClusterAt(pos, &tmp_range, &glyph_range);
+ SkScalar char_width = ((glyph_range.end() >= run.glyph_count)
+ ? SkFloatToScalar(run.width)
+ : run.positions[glyph_range.end()].x()) -
+ run.positions[glyph_range.start()].x();
+ word_width_ += char_width;
+ }
+ } else if (current_word != next_word) {
+ word_width_ = 0;
+ }
+ }
}
const SkScalar max_width_;
@@ -489,6 +528,13 @@ class HarfBuzzLineBreaker {
float max_descent_;
float max_ascent_;
+ // Stores the start position of next word that need to be processed.
+ size_t next_word_start_pos_;
+ // Stores the glyph width between the current position and the start position
+ // of the current word. If the current position is pointing to the first
+ // character of the current word, |word_width_| is set to 0.
+ SkScalar word_width_;
+
// Size of the multiline text, not including the currently processed line.
SizeF total_size_;
« no previous file with comments | « ui/gfx/render_text_harfbuzz.h ('k') | ui/gfx/render_text_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698