Index: ui/gfx/render_text_harfbuzz.cc |
diff --git a/ui/gfx/render_text_harfbuzz.cc b/ui/gfx/render_text_harfbuzz.cc |
index 10e7a1a5276931a44ad6e8ff6643d5a03bba9ed9..7fc5ef65abf31e6d71e693acb8910b24d663fa2e 100644 |
--- a/ui/gfx/render_text_harfbuzz.cc |
+++ b/ui/gfx/render_text_harfbuzz.cc |
@@ -6,6 +6,7 @@ |
#include <map> |
+#include "base/i18n/bidi_line_iterator.h" |
#include "base/i18n/break_iterator.h" |
#include "base/i18n/char_iterator.h" |
#include "third_party/harfbuzz-ng/src/hb.h" |
@@ -328,7 +329,7 @@ namespace internal { |
TextRunHarfBuzz::TextRunHarfBuzz() |
: width(0), |
preceding_run_widths(0), |
- direction(UBIDI_LTR), |
+ is_rtl(false), |
level(0), |
script(USCRIPT_INVALID_CODE), |
glyph_count(-1), |
@@ -343,7 +344,7 @@ TextRunHarfBuzz::~TextRunHarfBuzz() {} |
size_t TextRunHarfBuzz::CharToGlyph(size_t pos) const { |
DCHECK(range.start() <= pos && pos < range.end()); |
- if (direction == UBIDI_LTR) { |
+ if (!is_rtl) { |
for (size_t i = 0; i < glyph_count - 1; ++i) { |
if (pos < glyph_to_char[i + 1]) |
return i; |
@@ -386,14 +387,13 @@ int TextRunHarfBuzz::GetGlyphXBoundary(size_t text_index, bool trailing) const { |
Range glyph_range; |
if (text_index == range.end()) { |
trailing = true; |
- glyph_range = direction == UBIDI_LTR ? |
- Range(glyph_count - 1, glyph_count) : Range(0, 1); |
+ glyph_range = is_rtl ? Range(0, 1) : Range(glyph_count - 1, glyph_count); |
} else { |
glyph_range = CharRangeToGlyphRange(Range(text_index, text_index + 1)); |
} |
const int trailing_step = trailing ? 1 : 0; |
- const size_t glyph_pos = glyph_range.start() + |
- (direction == UBIDI_LTR ? trailing_step : (1 - trailing_step)); |
+ const size_t glyph_pos = |
+ glyph_range.start() + (is_rtl ? (1 - trailing_step) : trailing_step); |
x += glyph_pos < glyph_count ? |
SkScalarRoundToInt(positions[glyph_pos].x()) : width; |
return x; |
@@ -426,16 +426,16 @@ SelectionModel RenderTextHarfBuzz::FindCursorPosition(const Point& point) { |
const SkScalar end = |
i + 1 == run.glyph_count ? run.width : run.positions[i + 1].x(); |
const SkScalar middle = (end + run.positions[i].x()) / 2; |
- const bool is_rtl = run.direction == UBIDI_RTL; |
+ |
if (offset < middle) { |
return SelectionModel(LayoutIndexToTextIndex( |
- run.glyph_to_char[i] + (is_rtl ? 1 : 0)), |
- (is_rtl ? CURSOR_BACKWARD : CURSOR_FORWARD)); |
+ run.glyph_to_char[i] + (run.is_rtl ? 1 : 0)), |
+ (run.is_rtl ? CURSOR_BACKWARD : CURSOR_FORWARD)); |
} |
if (offset < end) { |
return SelectionModel(LayoutIndexToTextIndex( |
- run.glyph_to_char[i] + (is_rtl ? 0 : 1)), |
- (is_rtl ? CURSOR_FORWARD : CURSOR_BACKWARD)); |
+ run.glyph_to_char[i] + (run.is_rtl ? 0 : 1)), |
+ (run.is_rtl ? CURSOR_FORWARD : CURSOR_BACKWARD)); |
} |
} |
return EdgeSelectionModel(CURSOR_RIGHT); |
@@ -469,8 +469,7 @@ SelectionModel RenderTextHarfBuzz::AdjacentCharSelectionModel( |
// grapheme in the appropriate direction. |
run = runs_[run_index]; |
size_t caret = selection.caret_pos(); |
- bool forward_motion = |
- (run->direction == UBIDI_RTL) == (direction == CURSOR_LEFT); |
+ bool forward_motion = run->is_rtl == (direction == CURSOR_LEFT); |
if (forward_motion) { |
if (caret < LayoutIndexToTextIndex(run->range.end())) { |
caret = IndexOfAdjacentGrapheme(caret, CURSOR_FORWARD); |
@@ -489,8 +488,7 @@ SelectionModel RenderTextHarfBuzz::AdjacentCharSelectionModel( |
return EdgeSelectionModel(direction); |
run = runs_[visual_to_logical_[visual_index]]; |
} |
- bool forward_motion = |
- (run->direction == UBIDI_RTL) == (direction == CURSOR_LEFT); |
+ bool forward_motion = run->is_rtl == (direction == CURSOR_LEFT); |
return forward_motion ? FirstSelectionModelInsideRun(run) : |
LastSelectionModelInsideRun(run); |
} |
@@ -794,29 +792,15 @@ SelectionModel RenderTextHarfBuzz::LastSelectionModelInsideRun( |
void RenderTextHarfBuzz::ItemizeText() { |
const base::string16& text = GetLayoutText(); |
- const bool is_rtl = GetTextDirection() == base::i18n::RIGHT_TO_LEFT; |
+ const bool is_text_rtl = GetTextDirection() == base::i18n::RIGHT_TO_LEFT; |
DCHECK_NE(0U, text.length()); |
// 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. |
- bool fake_runs = false; |
- UErrorCode result = U_ZERO_ERROR; |
- |
- UBiDi* line = ubidi_openSized(text.length(), 0, &result); |
- if (U_FAILURE(result)) { |
- NOTREACHED(); |
- fake_runs = true; |
- } else { |
- ubidi_setPara(line, text.c_str(), text.length(), |
- is_rtl ? UBIDI_DEFAULT_RTL : UBIDI_DEFAULT_LTR, NULL, |
- &result); |
- if (U_FAILURE(result)) { |
- NOTREACHED(); |
- fake_runs = true; |
- } |
- } |
+ base::i18n::BiDiLineIterator bidi_iterator; |
+ bool fake_runs = !bidi_iterator.Open(text, is_text_rtl, false); |
// Temporarily apply composition underlines and selection colors. |
ApplyCompositionAndSelectionStyles(); |
@@ -840,7 +824,7 @@ void RenderTextHarfBuzz::ItemizeText() { |
run_break = text.length(); |
} else { |
int32 script_item_break = 0; |
- ubidi_getLogicalRun(line, run_break, &script_item_break, &run->level); |
+ 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; |
@@ -873,18 +857,15 @@ void RenderTextHarfBuzz::ItemizeText() { |
DCHECK(IsValidCodePointIndex(text, run_break)); |
style.UpdatePosition(LayoutIndexToTextIndex(run_break)); |
run->range.set_end(run_break); |
- const UChar* uchar_start = ubidi_getText(line); |
- // TODO(ckocagil): Add |ubidi_getBaseDirection| to i18n::BiDiLineIterator |
- // and remove the bare ICU use here. |
- run->direction = ubidi_getBaseDirection(uchar_start + run->range.start(), |
- run->range.length()); |
- if (run->direction == UBIDI_NEUTRAL) |
- run->direction = is_rtl ? UBIDI_RTL : UBIDI_LTR; |
+ 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); |
} |
- ubidi_close(line); |
- |
// Undo the temporarily applied composition underlines and selection colors. |
UndoCompositionAndSelectionStyles(); |
@@ -917,7 +898,7 @@ void RenderTextHarfBuzz::ShapeRun(internal::TextRunHarfBuzz* run) { |
text.length(), run->range.start(), run->range.length()); |
hb_buffer_set_script(buffer, ICUScriptToHBScript(run->script)); |
hb_buffer_set_direction(buffer, |
- run->direction == UBIDI_LTR ? HB_DIRECTION_LTR : HB_DIRECTION_RTL); |
+ run->is_rtl ? HB_DIRECTION_RTL : HB_DIRECTION_LTR); |
// TODO(ckocagil): Should we determine the actual language? |
hb_buffer_set_language(buffer, hb_language_get_default()); |