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

Unified Diff: ui/gfx/render_text_linux.cc

Issue 8747001: Reintroduce password support to NativeTextfieldViews (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: new implementation, linux only Created 8 years, 10 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
Index: ui/gfx/render_text_linux.cc
diff --git a/ui/gfx/render_text_linux.cc b/ui/gfx/render_text_linux.cc
index 133bd4eb63d435ff7daf451b8f08f9fb4a889b0d..c10548ebb8972ac74fce35998375a15a32a8798c 100644
--- a/ui/gfx/render_text_linux.cc
+++ b/ui/gfx/render_text_linux.cc
@@ -11,12 +11,11 @@
#include "base/i18n/break_iterator.h"
#include "base/logging.h"
+#include "base/utf_offset_string_conversions.h"
#include "third_party/skia/include/core/SkTypeface.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 {
@@ -58,7 +57,9 @@ RenderTextLinux::RenderTextLinux()
log_attrs_(NULL),
num_log_attrs_(0),
layout_text_(NULL),
- layout_text_len_(0) {
+ layout_text_len_(0),
+ last_text_index_(0),
+ last_layout_pointer_(NULL) {
}
RenderTextLinux::~RenderTextLinux() {
@@ -99,22 +100,15 @@ SelectionModel RenderTextLinux::FindCursorPosition(const Point& point) {
else if (p.x() > GetStringWidth())
return EdgeSelectionModel(CURSOR_RIGHT);
- int caret_pos, trailing;
+ int caret_pos_in_layout, trailing;
msw 2012/02/22 00:33:26 Init these locals to 0, please.
benrg 2012/02/24 19:07:44 I backed out all changes to this code; should I st
pango_layout_xy_to_index(layout_, p.x() * PANGO_SCALE, p.y() * PANGO_SCALE,
- &caret_pos, &trailing);
-
- size_t selection_end = caret_pos;
- if (trailing > 0) {
- const char* ch = g_utf8_offset_to_pointer(layout_text_ + caret_pos,
- trailing);
- DCHECK_GE(ch, layout_text_);
- DCHECK_LE(ch, layout_text_ + layout_text_len_);
- selection_end = ch - layout_text_;
- }
-
+ &caret_pos_in_layout, &trailing);
+ size_t caret_pos = LayoutIndexToTextIndex(caret_pos_in_layout);
+ size_t selection_end = Utf16OffsetToIndex(text(), caret_pos, trailing);
+ DCHECK_LE(caret_pos, selection_end);
+ DCHECK_LE(selection_end, text().length());
return SelectionModel(
- Utf8IndexToUtf16Index(selection_end),
- Utf8IndexToUtf16Index(caret_pos),
+ selection_end, caret_pos,
msw 2012/02/22 00:33:26 |caret_pos| belongs on its own line.
trailing > 0 ? SelectionModel::TRAILING : SelectionModel::LEADING);
}
@@ -125,7 +119,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,8 +166,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)
@@ -209,6 +203,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 +240,12 @@ 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 = IndexOfAdjacentGrapheme(
+ LayoutIndexToTextIndex(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);
}
}
@@ -281,12 +278,12 @@ std::vector<Rect> RenderTextLinux::GetSubstringBounds(size_t from, size_t to) {
}
bool RenderTextLinux::IsCursorablePosition(size_t position) {
- if (position == 0 && text().empty())
+ if (position == 0)
return true;
-
+ if (position > text().length())
+ return false;
EnsureLayout();
- return (position < static_cast<size_t>(num_log_attrs_) &&
- log_attrs_[position].is_cursor_position);
+ return log_attrs_[Utf16IndexToOffset(text(), 0, position)].is_cursor_position;
}
void RenderTextLinux::UpdateLayout() {
@@ -302,7 +299,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,7 +312,6 @@ 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);
- SetupPangoAttributes(layout_);
current_line_ = pango_layout_get_line_readonly(layout_, 0);
pango_layout_line_ref(current_line_);
@@ -324,6 +320,11 @@ void RenderTextLinux::EnsureLayout() {
layout_text_ = pango_layout_get_text(layout_);
layout_text_len_ = strlen(layout_text_);
+
+ last_text_index_ = 0;
+ last_layout_pointer_ = layout_text_;
+
+ SetupPangoAttributes(layout_);
}
}
@@ -345,8 +346,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);
}
@@ -369,17 +370,6 @@ void RenderTextLinux::DrawVisualText(Canvas* canvas) {
StyleRanges styles(style_ranges());
ApplyCompositionAndSelectionStyles(&styles);
- // Pre-calculate UTF8 indices from UTF16 indices.
- // TODO(asvitkine): Can we cache these?
- std::vector<ui::Range> style_ranges_utf8;
- 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());
- style_ranges_utf8.push_back(ui::Range(start_index, end_index));
- start_index = end_index;
- }
xji 2012/02/18 01:28:47 will removing this cause performance hit if we do
-
internal::SkiaTextRenderer renderer(canvas);
ApplyFadeEffects(&renderer);
@@ -390,14 +380,15 @@ void RenderTextLinux::DrawVisualText(Canvas* canvas) {
continue;
size_t run_start = run->item->offset;
- size_t first_glyph_byte_index = run_start + run->glyphs->log_clusters[0];
+ size_t first_glyph_index =
+ LayoutIndexToTextIndex(run_start + run->glyphs->log_clusters[0]);
size_t style_increment = IsForwardMotion(CURSOR_RIGHT, run->item) ? 1 : -1;
// Find the initial style for this run.
// TODO(asvitkine): Can we avoid looping here, e.g. by caching this per run?
int style = -1;
- for (size_t i = 0; i < style_ranges_utf8.size(); ++i) {
- if (IndexInRange(style_ranges_utf8[i], first_glyph_byte_index)) {
+ for (size_t i = 0; i < styles.size(); ++i) {
+ if (IndexInRange(styles[i].range, first_glyph_index)) {
style = i;
break;
}
@@ -431,10 +422,11 @@ void RenderTextLinux::DrawVisualText(Canvas* canvas) {
// If this glyph is beyond the current style, draw the glyphs so far and
// advance to the next style.
- size_t glyph_byte_index = run_start + run->glyphs->log_clusters[i];
+ size_t glyph_index =
+ LayoutIndexToTextIndex(run_start + run->glyphs->log_clusters[i]);
DCHECK_GE(style, 0);
DCHECK_LT(style, static_cast<int>(styles.size()));
- if (!IndexInRange(style_ranges_utf8[style], glyph_byte_index)) {
+ if (!IndexInRange(styles[style].range, glyph_index)) {
// TODO(asvitkine): For cases like "fi", where "fi" is a single glyph
// but can span multiple styles, Pango splits the
// styles evenly over the glyph. We can do this too by
@@ -450,7 +442,7 @@ void RenderTextLinux::DrawVisualText(Canvas* canvas) {
do {
style += style_increment;
} while (style >= 0 && style < static_cast<int>(styles.size()) &&
- !IndexInRange(style_ranges_utf8[style], glyph_byte_index));
+ !IndexInRange(styles[style].range, glyph_index));
}
}
@@ -469,31 +461,8 @@ size_t RenderTextLinux::IndexOfAdjacentGrapheme(
if (index > text().length())
return text().length();
EnsureLayout();
- return Utf8IndexToUtf16Index(
- Utf8IndexOfAdjacentGrapheme(Utf16IndexToUtf8Index(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);
- if (position >= run_start && position < run_end)
- return run;
- run = run->next;
- }
- return NULL;
-}
-
-size_t RenderTextLinux::Utf8IndexOfAdjacentGrapheme(
- size_t utf8_index_of_current_grapheme,
- LogicalCursorDirection direction) const {
- const char* ch = layout_text_ + utf8_index_of_current_grapheme;
- int char_offset = static_cast<int>(g_utf8_pointer_to_offset(layout_text_,
- ch));
- int start_char_offset = char_offset;
+ ptrdiff_t char_offset = Utf16IndexToOffset(text(), 0, index);
if (direction == CURSOR_BACKWARD) {
if (char_offset > 0) {
do {
@@ -508,23 +477,31 @@ size_t RenderTextLinux::Utf8IndexOfAdjacentGrapheme(
!log_attrs_[char_offset].is_cursor_position);
}
}
+ return Utf16OffsetToIndex(text(), 0, char_offset);
+}
- ch = g_utf8_offset_to_pointer(ch, char_offset - start_char_offset);
- return static_cast<size_t>(ch - layout_text_);
+GSList* RenderTextLinux::GetRunContainingPosition(size_t position) const {
+ position = TextIndexToLayoutIndex(position);
+ for (GSList* run = current_line_->runs; run; run = run->next) {
+ PangoItem* item = reinterpret_cast<PangoLayoutRun*>(run->data)->item;
+ if (position >= static_cast<size_t>(item->offset) &&
+ position < static_cast<size_t>(item->offset + item->length))
+ return run;
+ }
+ return NULL;
xji 2012/02/18 01:28:47 Ah, nice!
}
SelectionModel RenderTextLinux::FirstSelectionModelInsideRun(
- const PangoItem* item) const {
- size_t caret = Utf8IndexToUtf16Index(item->offset);
- size_t cursor = Utf8IndexToUtf16Index(
- Utf8IndexOfAdjacentGrapheme(item->offset, CURSOR_FORWARD));
+ const PangoItem* item) {
+ size_t caret = LayoutIndexToTextIndex(item->offset);
+ size_t cursor = IndexOfAdjacentGrapheme(caret, CURSOR_FORWARD);
return SelectionModel(cursor, caret, SelectionModel::TRAILING);
}
SelectionModel RenderTextLinux::LastSelectionModelInsideRun(
- const PangoItem* item) const {
- size_t caret = Utf8IndexToUtf16Index(Utf8IndexOfAdjacentGrapheme(
- item->offset + item->length, CURSOR_BACKWARD));
+ const PangoItem* item) {
+ size_t caret = IndexOfAdjacentGrapheme(
+ LayoutIndexToTextIndex(item->offset + item->length), CURSOR_BACKWARD);
return SelectionModel(caret, caret, SelectionModel::LEADING);
}
@@ -548,39 +525,40 @@ void RenderTextLinux::ResetLayout() {
selection_visual_bounds_.clear();
layout_text_ = NULL;
layout_text_len_ = 0;
+ last_text_index_ = 0;
+ last_layout_pointer_ = NULL;
}
-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 = Utf16IndexToOffset(text(), last_text_index_, text_index);
+ const char* layout_pointer = g_utf8_offset_to_pointer(last_layout_pointer_,
+ offset);
+ last_text_index_ = text_index;
+ last_layout_pointer_ = layout_pointer;
+ 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;
+ glong offset = g_utf8_pointer_to_offset(last_layout_pointer_, layout_pointer);
+ size_t text_index = Utf16OffsetToIndex(text(), last_text_index_, offset);
+ last_text_index_ = text_index;
+ last_layout_pointer_ = layout_pointer;
+ return text_index;
}
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),

Powered by Google App Engine
This is Rietveld 408576698