Index: ui/gfx/render_text_harfbuzz.cc |
diff --git a/ui/gfx/render_text_harfbuzz.cc b/ui/gfx/render_text_harfbuzz.cc |
index 6e2be3a1b03871a134adb40ef6a2f6c8f4f57237..138cd548c00e1653f8d85407b4b2c32cfdf719a5 100644 |
--- a/ui/gfx/render_text_harfbuzz.cc |
+++ b/ui/gfx/render_text_harfbuzz.cc |
@@ -863,17 +863,12 @@ |
const bool is_text_rtl = GetTextDirection() == base::i18n::RIGHT_TO_LEFT; |
DCHECK_NE(0U, text.length()); |
- // If ICU fails to itemize the text, we create a run that spans the entire |
- // text. This is needed because leaving the runs set empty causes some clients |
- // to misbehave since they expect non-zero text metrics from a non-empty text. |
+ // If ICU fails to itemize the text, we set |fake_runs| and create a run that |
+ // spans the entire text. This is needed because early returning and leaving |
+ // the runs set empty causes some clients to crash/misbehave since they expect |
+ // non-zero text metrics from a non-empty text. |
base::i18n::BiDiLineIterator bidi_iterator; |
- if (!bidi_iterator.Open(text, is_text_rtl, false)) { |
- internal::TextRunHarfBuzz* run = new internal::TextRunHarfBuzz; |
- run->range = Range(0, text.length()); |
- runs_.push_back(run); |
- visual_to_logical_ = logical_to_visual_ = std::vector<int32_t>(1, 0); |
- return; |
- } |
+ bool fake_runs = !bidi_iterator.Open(text, is_text_rtl, false); |
// Temporarily apply composition underlines and selection colors. |
ApplyCompositionAndSelectionStyles(); |
@@ -893,34 +888,36 @@ |
run->diagonal_strike = style.style(DIAGONAL_STRIKE); |
run->underline = style.style(UNDERLINE); |
- int32 script_item_break = 0; |
- bidi_iterator.GetLogicalRun(run_break, &script_item_break, &run->level); |
- // Odd BiDi embedding levels correspond to RTL runs. |
- run->is_rtl = (run->level % 2) == 1; |
- // Find the length and script of this script run. |
- script_item_break = ScriptInterval(text, run_break, |
- script_item_break - run_break, &run->script) + run_break; |
- |
- // Find the next break and advance the iterators as needed. |
- run_break = std::min(static_cast<size_t>(script_item_break), |
- TextIndexToLayoutIndex(style.GetRange().end())); |
- |
- // Break runs adjacent to character substrings in certain code blocks. |
- // This avoids using their fallback fonts for more characters than needed, |
- // in cases like "\x25B6 Media Title", etc. http://crbug.com/278913 |
- if (run_break > run->range.start()) { |
- const size_t run_start = run->range.start(); |
- const int32 run_length = static_cast<int32>(run_break - run_start); |
- base::i18n::UTF16CharIterator iter(text.c_str() + run_start, |
- run_length); |
- const UBlockCode first_block_code = ublock_getCode(iter.get()); |
- const bool first_block_unusual = IsUnusualBlockCode(first_block_code); |
- while (iter.Advance() && iter.array_pos() < run_length) { |
- const UBlockCode current_block_code = ublock_getCode(iter.get()); |
- if (current_block_code != first_block_code && |
- (first_block_unusual || IsUnusualBlockCode(current_block_code))) { |
- run_break = run_start + iter.array_pos(); |
- break; |
+ if (fake_runs) { |
+ run_break = text.length(); |
+ } else { |
+ int32 script_item_break = 0; |
+ bidi_iterator.GetLogicalRun(run_break, &script_item_break, &run->level); |
+ // Find the length and script of this script run. |
+ script_item_break = ScriptInterval(text, run_break, |
+ script_item_break - run_break, &run->script) + run_break; |
+ |
+ // Find the next break and advance the iterators as needed. |
+ run_break = std::min(static_cast<size_t>(script_item_break), |
+ TextIndexToLayoutIndex(style.GetRange().end())); |
+ |
+ // Break runs adjacent to character substrings in certain code blocks. |
+ // This avoids using their fallback fonts for more characters than needed, |
+ // in cases like "\x25B6 Media Title", etc. http://crbug.com/278913 |
+ if (run_break > run->range.start()) { |
+ const size_t run_start = run->range.start(); |
+ const int32 run_length = static_cast<int32>(run_break - run_start); |
+ base::i18n::UTF16CharIterator iter(text.c_str() + run_start, |
+ run_length); |
+ const UBlockCode first_block_code = ublock_getCode(iter.get()); |
+ const bool first_block_unusual = IsUnusualBlockCode(first_block_code); |
+ while (iter.Advance() && iter.array_pos() < run_length) { |
+ const UBlockCode current_block_code = ublock_getCode(iter.get()); |
+ if (current_block_code != first_block_code && |
+ (first_block_unusual || IsUnusualBlockCode(current_block_code))) { |
+ run_break = run_start + iter.array_pos(); |
+ break; |
+ } |
} |
} |
} |
@@ -928,7 +925,12 @@ |
DCHECK(IsValidCodePointIndex(text, run_break)); |
style.UpdatePosition(LayoutIndexToTextIndex(run_break)); |
run->range.set_end(run_break); |
- |
+ UBiDiDirection direction = ubidi_getBaseDirection( |
+ text.c_str() + run->range.start(), run->range.length()); |
+ if (direction == UBIDI_NEUTRAL) |
+ run->is_rtl = is_text_rtl; |
+ else |
+ run->is_rtl = direction == UBIDI_RTL; |
runs_.push_back(run); |
} |