Index: ui/gfx/render_text_linux.cc |
diff --git a/ui/gfx/render_text_linux.cc b/ui/gfx/render_text_linux.cc |
index 9ceeb9e2ea6aa4f80cd877d861d286345e17fbfa..19334d1df01545d21116170083f98b16e941c09f 100644 |
--- a/ui/gfx/render_text_linux.cc |
+++ b/ui/gfx/render_text_linux.cc |
@@ -12,11 +12,10 @@ |
#include "base/i18n/break_iterator.h" |
#include "base/logging.h" |
#include "third_party/skia/include/core/SkTypeface.h" |
+#include "ui/base/text/utf16_indexing.h" |
#include "ui/gfx/canvas_skia.h" |
#include "ui/gfx/font.h" |
#include "ui/gfx/pango_util.h" |
-#include "unicode/uchar.h" |
-#include "unicode/ustring.h" |
namespace gfx { |
@@ -113,8 +112,8 @@ SelectionModel RenderTextLinux::FindCursorPosition(const Point& point) { |
} |
return SelectionModel( |
- Utf8IndexToUtf16Index(selection_end), |
- Utf8IndexToUtf16Index(caret_pos), |
+ LayoutIndexToTextIndex(selection_end), |
+ LayoutIndexToTextIndex(caret_pos), |
trailing > 0 ? SelectionModel::TRAILING : SelectionModel::LEADING); |
} |
@@ -125,7 +124,7 @@ Rect RenderTextLinux::GetCursorBounds(const SelectionModel& selection, |
size_t caret_pos = insert_mode ? selection.caret_pos() : |
selection.selection_end(); |
PangoRectangle pos; |
- pango_layout_index_to_pos(layout_, Utf16IndexToUtf8Index(caret_pos), &pos); |
+ pango_layout_index_to_pos(layout_, TextIndexToLayoutIndex(caret_pos), &pos); |
SelectionModel::CaretPlacement caret_placement = selection.caret_placement(); |
int x = pos.x; |
@@ -172,9 +171,8 @@ SelectionModel RenderTextLinux::AdjacentCharSelectionModel( |
PangoLayoutRun* layout_run = reinterpret_cast<PangoLayoutRun*>(run->data); |
PangoItem* item = layout_run->item; |
- size_t run_start = Utf8IndexToUtf16Index(item->offset); |
- size_t run_end = Utf8IndexToUtf16Index(item->offset + item->length); |
- |
+ size_t run_start = LayoutIndexToTextIndex(item->offset); |
+ size_t run_end = LayoutIndexToTextIndex(item->offset + item->length); |
if (!IsForwardMotion(direction, item)) { |
if (caret_placement == SelectionModel::TRAILING) |
return SelectionModel(caret, caret, SelectionModel::LEADING); |
@@ -209,6 +207,9 @@ SelectionModel RenderTextLinux::AdjacentCharSelectionModel( |
SelectionModel RenderTextLinux::AdjacentWordSelectionModel( |
const SelectionModel& selection, |
VisualCursorDirection direction) { |
+ if (is_obscured()) |
+ return EdgeSelectionModel(direction); |
+ |
base::i18n::BreakIterator iter(text(), base::i18n::BreakIterator::BREAK_WORD); |
bool success = iter.Init(); |
DCHECK(success); |
@@ -243,12 +244,11 @@ SelectionModel RenderTextLinux::EdgeSelectionModel( |
PangoLayoutRun* end_run = reinterpret_cast<PangoLayoutRun*>(run->data); |
PangoItem* item = end_run->item; |
if (IsForwardMotion(direction, item)) { |
- size_t caret = Utf8IndexToUtf16Index( |
- Utf8IndexOfAdjacentGrapheme(item->offset + item->length, |
- CURSOR_BACKWARD)); |
+ size_t caret = LayoutIndexToTextIndex(LayoutIndexOfAdjacentGrapheme( |
+ item->offset + item->length, CURSOR_BACKWARD)); |
return SelectionModel(text().length(), caret, SelectionModel::TRAILING); |
} else { |
- size_t caret = Utf8IndexToUtf16Index(item->offset); |
+ size_t caret = LayoutIndexToTextIndex(item->offset); |
return SelectionModel(text().length(), caret, SelectionModel::LEADING); |
} |
} |
@@ -285,8 +285,8 @@ bool RenderTextLinux::IsCursorablePosition(size_t position) { |
return true; |
EnsureLayout(); |
- return (position < static_cast<size_t>(num_log_attrs_) && |
- log_attrs_[position].is_cursor_position); |
+ ptrdiff_t offset = ui::UTF16IndexToOffset(text(), 0, position); |
+ return (offset < num_log_attrs_ && log_attrs_[offset].is_cursor_position); |
} |
void RenderTextLinux::UpdateLayout() { |
@@ -302,7 +302,7 @@ void RenderTextLinux::EnsureLayout() { |
layout_ = pango_cairo_create_layout(cr); |
SetupPangoLayoutWithFontDescription( |
layout_, |
- text(), |
+ GetDisplayText(), |
font_list().GetFontDescriptionString(), |
display_rect().width(), |
base::i18n::GetFirstStrongCharacterDirection(text()), |
@@ -315,15 +315,17 @@ void RenderTextLinux::EnsureLayout() { |
// TODO(xji): If RenderText will be used for displaying purpose, such as |
// label, we will need to remove the single-line-mode setting. |
pango_layout_set_single_paragraph_mode(layout_, true); |
+ |
+ // These are used by SetupPangoAttributes. |
+ layout_text_ = pango_layout_get_text(layout_); |
+ layout_text_len_ = strlen(layout_text_); |
+ |
SetupPangoAttributes(layout_); |
current_line_ = pango_layout_get_line_readonly(layout_, 0); |
pango_layout_line_ref(current_line_); |
pango_layout_get_log_attrs(layout_, &log_attrs_, &num_log_attrs_); |
- |
- layout_text_ = pango_layout_get_text(layout_); |
- layout_text_len_ = strlen(layout_text_); |
} |
} |
@@ -345,8 +347,8 @@ void RenderTextLinux::SetupPangoAttributes(PangoLayout* layout) { |
derived_font_list.GetFontDescriptionString().c_str()); |
PangoAttribute* pango_attr = pango_attr_font_desc_new(desc); |
- pango_attr->start_index = Utf16IndexToUtf8Index(i->range.start()); |
- pango_attr->end_index = Utf16IndexToUtf8Index(i->range.end()); |
+ pango_attr->start_index = TextIndexToLayoutIndex(i->range.start()); |
+ pango_attr->end_index = TextIndexToLayoutIndex(i->range.end()); |
pango_attr_list_insert(attrs, pango_attr); |
pango_font_description_free(desc); |
} |
@@ -375,7 +377,7 @@ void RenderTextLinux::DrawVisualText(Canvas* canvas) { |
style_ranges_utf8.reserve(styles.size()); |
size_t start_index = 0; |
for (size_t i = 0; i < styles.size(); ++i) { |
- size_t end_index = Utf16IndexToUtf8Index(styles[i].range.end()); |
+ size_t end_index = TextIndexToLayoutIndex(styles[i].range.end()); |
style_ranges_utf8.push_back(ui::Range(start_index, end_index)); |
start_index = end_index; |
} |
@@ -470,16 +472,16 @@ size_t RenderTextLinux::IndexOfAdjacentGrapheme( |
if (index > text().length()) |
return text().length(); |
EnsureLayout(); |
- return Utf8IndexToUtf16Index( |
- Utf8IndexOfAdjacentGrapheme(Utf16IndexToUtf8Index(index), direction)); |
+ return LayoutIndexToTextIndex( |
+ LayoutIndexOfAdjacentGrapheme(TextIndexToLayoutIndex(index), direction)); |
} |
GSList* RenderTextLinux::GetRunContainingPosition(size_t position) const { |
GSList* run = current_line_->runs; |
while (run) { |
PangoItem* item = reinterpret_cast<PangoLayoutRun*>(run->data)->item; |
- size_t run_start = Utf8IndexToUtf16Index(item->offset); |
- size_t run_end = Utf8IndexToUtf16Index(item->offset + item->length); |
+ size_t run_start = LayoutIndexToTextIndex(item->offset); |
+ size_t run_end = LayoutIndexToTextIndex(item->offset + item->length); |
if (position >= run_start && position < run_end) |
return run; |
@@ -488,10 +490,10 @@ GSList* RenderTextLinux::GetRunContainingPosition(size_t position) const { |
return NULL; |
} |
-size_t RenderTextLinux::Utf8IndexOfAdjacentGrapheme( |
- size_t utf8_index_of_current_grapheme, |
+size_t RenderTextLinux::LayoutIndexOfAdjacentGrapheme( |
+ size_t layout_index_of_current_grapheme, |
LogicalCursorDirection direction) const { |
- const char* ch = layout_text_ + utf8_index_of_current_grapheme; |
+ const char* ch = layout_text_ + layout_index_of_current_grapheme; |
int char_offset = static_cast<int>(g_utf8_pointer_to_offset(layout_text_, |
ch)); |
int start_char_offset = char_offset; |
@@ -516,15 +518,15 @@ size_t RenderTextLinux::Utf8IndexOfAdjacentGrapheme( |
SelectionModel RenderTextLinux::FirstSelectionModelInsideRun( |
const PangoItem* item) const { |
- size_t caret = Utf8IndexToUtf16Index(item->offset); |
- size_t cursor = Utf8IndexToUtf16Index( |
- Utf8IndexOfAdjacentGrapheme(item->offset, CURSOR_FORWARD)); |
+ size_t caret = LayoutIndexToTextIndex(item->offset); |
+ size_t cursor = LayoutIndexToTextIndex( |
+ LayoutIndexOfAdjacentGrapheme(item->offset, CURSOR_FORWARD)); |
return SelectionModel(cursor, caret, SelectionModel::TRAILING); |
} |
SelectionModel RenderTextLinux::LastSelectionModelInsideRun( |
const PangoItem* item) const { |
- size_t caret = Utf8IndexToUtf16Index(Utf8IndexOfAdjacentGrapheme( |
+ size_t caret = LayoutIndexToTextIndex(LayoutIndexOfAdjacentGrapheme( |
item->offset + item->length, CURSOR_BACKWARD)); |
return SelectionModel(caret, caret, SelectionModel::LEADING); |
} |
@@ -551,37 +553,30 @@ void RenderTextLinux::ResetLayout() { |
layout_text_len_ = 0; |
} |
-size_t RenderTextLinux::Utf16IndexToUtf8Index(size_t index) const { |
- int32_t utf8_index = 0; |
- UErrorCode ec = U_ZERO_ERROR; |
- u_strToUTF8(NULL, 0, &utf8_index, text().data(), index, &ec); |
- // Even given a destination buffer as NULL and destination capacity as 0, |
- // if the output length is equal to or greater than the capacity, then the |
- // UErrorCode is set to U_STRING_NOT_TERMINATED_WARNING or |
- // U_BUFFER_OVERFLOW_ERROR respectively. |
- // Please refer to |
- // http://userguide.icu-project.org/strings#TOC-Using-C-Strings:-NUL-Terminated-vs |
- // for detail (search for "Note that" below "Preflighting"). |
- DCHECK(ec == U_BUFFER_OVERFLOW_ERROR || |
- ec == U_STRING_NOT_TERMINATED_WARNING); |
- return utf8_index; |
+size_t RenderTextLinux::TextIndexToLayoutIndex(size_t text_index) const { |
+ // If the text is obscured then |layout_text_| is not the same as |text()|, |
+ // but whether or not the text is obscured, the character (code point) offset |
+ // in |layout_text_| is the same as that in |text()|. |
+ DCHECK(layout_); |
+ ptrdiff_t offset = ui::UTF16IndexToOffset(text(), 0, text_index); |
+ const char* layout_pointer = g_utf8_offset_to_pointer(layout_text_, offset); |
+ return (layout_pointer - layout_text_); |
} |
-size_t RenderTextLinux::Utf8IndexToUtf16Index(size_t index) const { |
- int32_t utf16_index = 0; |
- UErrorCode ec = U_ZERO_ERROR; |
- u_strFromUTF8(NULL, 0, &utf16_index, layout_text_, index, &ec); |
- DCHECK(ec == U_BUFFER_OVERFLOW_ERROR || |
- ec == U_STRING_NOT_TERMINATED_WARNING); |
- return utf16_index; |
+size_t RenderTextLinux::LayoutIndexToTextIndex(size_t layout_index) const { |
+ // See |TextIndexToLayoutIndex()|. |
+ DCHECK(layout_); |
+ const char* layout_pointer = layout_text_ + layout_index; |
+ long offset = g_utf8_pointer_to_offset(layout_text_, layout_pointer); |
+ return ui::UTF16OffsetToIndex(text(), 0, offset); |
} |
std::vector<Rect> RenderTextLinux::CalculateSubstringBounds(size_t from, |
size_t to) { |
int* ranges; |
int n_ranges; |
- size_t from_in_utf8 = Utf16IndexToUtf8Index(from); |
- size_t to_in_utf8 = Utf16IndexToUtf8Index(to); |
+ size_t from_in_utf8 = TextIndexToLayoutIndex(from); |
+ size_t to_in_utf8 = TextIndexToLayoutIndex(to); |
pango_layout_line_get_x_ranges( |
current_line_, |
std::min(from_in_utf8, to_in_utf8), |