Chromium Code Reviews| Index: ui/gfx/render_text.cc |
| diff --git a/ui/gfx/render_text.cc b/ui/gfx/render_text.cc |
| index edee554cc3496494a798386443f5a824c4924235..14d6449d129525b43e183f89bb98091460ef8287 100644 |
| --- a/ui/gfx/render_text.cc |
| +++ b/ui/gfx/render_text.cc |
| @@ -15,6 +15,21 @@ |
| namespace { |
| +// All chars are replaced by this char when the password style is set. |
| +// TODO(benrg): GTK uses the first of U+25CF, U+2022, U+2731, U+273A, '*' |
| +// that's available in the font (find_invisible_char() in gtkentry.c). |
| +const char16 kPasswordReplacementChar = '*'; |
| + |
| +// Color settings for text, backgrounds and cursor. |
| +// These are tentative, and should be derived from theme, system |
| +// settings and current settings. |
| +// TODO(oshima): Change this to match the standard chrome |
| +// before dogfooding textfield views. |
| +const SkColor kSelectedTextColor = SK_ColorWHITE; |
| +const SkColor kFocusedSelectionColor = SkColorSetRGB(30, 144, 255); |
| +const SkColor kUnfocusedSelectionColor = SK_ColorLTGRAY; |
| +const SkColor kCursorColor = SK_ColorBLACK; |
| + |
| #ifndef NDEBUG |
| // Check StyleRanges invariant conditions: sorted and non-overlapping ranges. |
| void CheckStyleRanges(const gfx::StyleRanges& style_ranges, size_t length) { |
| @@ -127,11 +142,29 @@ void RenderText::SetText(const string16& text) { |
| UpdateLayout(); |
| } |
| +string16 RenderText::GetObscuredText() const { |
| + string16 txt = text(); |
| + if (obscured_) { |
| + // TODO(benrg): There should probably be one bullet/asterisk per |
| + // cursorable character, not one per UTF-16 word. However, I'm not sure |
| + // it's worth the effort. GTK appears to use one per code point. Do people |
| + // use non-BMP code points and combining diacritics in their passwords? |
|
xji
2011/12/22 01:11:20
Ben and I just talked about how to map obscured te
benrg
2011/12/22 02:14:21
xji wrote:
|
| + std::fill(txt.begin(), txt.end(), kPasswordReplacementChar); |
| + } |
| + return txt; |
| +} |
| + |
| void RenderText::ToggleInsertMode() { |
| insert_mode_ = !insert_mode_; |
| cached_bounds_and_offset_valid_ = false; |
| } |
| +void RenderText::SetObscured(bool obscured) { |
| + obscured_ = obscured; |
| + cached_bounds_and_offset_valid_ = false; |
| + UpdateLayout(); |
| +} |
| + |
| void RenderText::SetDisplayRect(const Rect& r) { |
| display_rect_ = r; |
| cached_bounds_and_offset_valid_ = false; |
| @@ -273,7 +306,8 @@ void RenderText::SelectAll() { |
| void RenderText::SelectWord() { |
| size_t cursor_position = GetCursorPosition(); |
| - base::i18n::BreakIterator iter(text(), base::i18n::BreakIterator::BREAK_WORD); |
| + string16 txt = GetObscuredText(); |
| + base::i18n::BreakIterator iter(txt, base::i18n::BreakIterator::BREAK_WORD); |
| bool success = iter.Init(); |
| DCHECK(success); |
| if (!success) |
| @@ -289,7 +323,7 @@ void RenderText::SelectWord() { |
| if (selection_start == cursor_position) |
| ++cursor_position; |
| - for (; cursor_position < text().length(); ++cursor_position) { |
| + for (; cursor_position < txt.length(); ++cursor_position) { |
| if (iter.IsEndOfWord(cursor_position) || |
| iter.IsStartOfWord(cursor_position)) |
| break; |
| @@ -341,10 +375,6 @@ base::i18n::TextDirection RenderText::GetTextDirection() { |
| return base::i18n::LEFT_TO_RIGHT; |
| } |
| -int RenderText::GetStringWidth() { |
| - return default_style_.font.GetStringWidth(text()); |
| -} |
| - |
| void RenderText::Draw(Canvas* canvas) { |
| EnsureLayout(); |
| @@ -355,35 +385,6 @@ void RenderText::Draw(Canvas* canvas) { |
| DrawCursor(canvas); |
| } |
| -SelectionModel RenderText::FindCursorPosition(const Point& point) { |
| - const Font& font = default_style_.font; |
| - int left = 0; |
| - int left_pos = 0; |
| - int right = font.GetStringWidth(text()); |
| - int right_pos = text().length(); |
| - |
| - int x = point.x() - (display_rect_.x() + GetUpdatedDisplayOffset().x()); |
| - if (x <= left) return SelectionModel(left_pos); |
| - if (x >= right) return SelectionModel(right_pos); |
| - // binary searching the cursor position. |
| - // TODO(oshima): use the center of character instead of edge. |
| - // Binary search may not work for language like Arabic. |
| - while (std::abs(static_cast<long>(right_pos - left_pos)) > 1) { |
| - int pivot_pos = left_pos + (right_pos - left_pos) / 2; |
| - int pivot = font.GetStringWidth(text().substr(0, pivot_pos)); |
| - if (pivot < x) { |
| - left = pivot; |
| - left_pos = pivot_pos; |
| - } else if (pivot == x) { |
| - return SelectionModel(pivot_pos); |
| - } else { |
| - right = pivot; |
| - right_pos = pivot_pos; |
| - } |
| - } |
| - return SelectionModel(left_pos); |
| -} |
| - |
| const Rect& RenderText::GetUpdatedCursorBounds() { |
| UpdateCachedBoundsAndOffset(); |
| return cursor_bounds_; |
| @@ -416,6 +417,7 @@ RenderText::RenderText() |
| composition_range_(ui::Range::InvalidRange()), |
| style_ranges_(), |
| default_style_(), |
| + obscured_(false), |
| display_rect_(), |
| display_offset_(), |
| cached_bounds_and_offset_valid_(false) { |
| @@ -426,80 +428,6 @@ const Point& RenderText::GetUpdatedDisplayOffset() { |
| return display_offset_; |
| } |
| -SelectionModel RenderText::GetLeftSelectionModel(const SelectionModel& current, |
| - BreakType break_type) { |
| - if (break_type == LINE_BREAK) |
| - return LeftEndSelectionModel(); |
| - size_t pos = std::max(static_cast<long>(current.selection_end() - 1), |
| - static_cast<long>(0)); |
| - if (break_type == CHARACTER_BREAK) |
| - return SelectionModel(pos, pos, SelectionModel::LEADING); |
| - |
| - // Notes: We always iterate words from the beginning. |
| - // This is probably fast enough for our usage, but we may |
| - // want to modify WordIterator so that it can start from the |
| - // middle of string and advance backwards. |
| - base::i18n::BreakIterator iter(text(), base::i18n::BreakIterator::BREAK_WORD); |
| - bool success = iter.Init(); |
| - DCHECK(success); |
| - if (!success) |
| - return current; |
| - while (iter.Advance()) { |
| - if (iter.IsWord()) { |
| - size_t begin = iter.pos() - iter.GetString().length(); |
| - if (begin == current.selection_end()) { |
| - // The cursor is at the beginning of a word. |
| - // Move to previous word. |
| - break; |
| - } else if (iter.pos() >= current.selection_end()) { |
| - // The cursor is in the middle or at the end of a word. |
| - // Move to the top of current word. |
| - pos = begin; |
| - break; |
| - } else { |
| - pos = iter.pos() - iter.GetString().length(); |
| - } |
| - } |
| - } |
| - |
| - return SelectionModel(pos, pos, SelectionModel::LEADING); |
| -} |
| - |
| -SelectionModel RenderText::GetRightSelectionModel(const SelectionModel& current, |
| - BreakType break_type) { |
| - if (text_.empty()) |
| - return SelectionModel(0, 0, SelectionModel::LEADING); |
| - if (break_type == LINE_BREAK) |
| - return RightEndSelectionModel(); |
| - size_t pos = std::min(current.selection_end() + 1, text().length()); |
| - if (break_type == CHARACTER_BREAK) |
| - return SelectionModel(pos, pos, SelectionModel::LEADING); |
| - |
| - base::i18n::BreakIterator iter(text(), base::i18n::BreakIterator::BREAK_WORD); |
| - bool success = iter.Init(); |
| - DCHECK(success); |
| - if (!success) |
| - return current; |
| - while (iter.Advance()) { |
| - pos = iter.pos(); |
| - if (iter.IsWord() && pos > current.selection_end()) |
| - break; |
| - } |
| - return SelectionModel(pos, pos, SelectionModel::LEADING); |
| -} |
| - |
| -SelectionModel RenderText::LeftEndSelectionModel() { |
| - return SelectionModel(0, 0, SelectionModel::LEADING); |
| -} |
| - |
| -SelectionModel RenderText::RightEndSelectionModel() { |
| - size_t cursor = text().length(); |
| - size_t caret_pos = GetIndexOfPreviousGrapheme(cursor); |
| - SelectionModel::CaretPlacement placement = (caret_pos == cursor) ? |
| - SelectionModel::LEADING : SelectionModel::TRAILING; |
| - return SelectionModel(cursor, caret_pos, placement); |
| -} |
| - |
| void RenderText::SetSelectionModel(const SelectionModel& model) { |
| DCHECK_LE(model.selection_start(), text().length()); |
| selection_model_.set_selection_start(model.selection_start()); |