| Index: ui/gfx/render_text.cc
|
| diff --git a/ui/gfx/render_text.cc b/ui/gfx/render_text.cc
|
| index edee554cc3496494a798386443f5a824c4924235..1c2653c0a7037eb7543dca8a42a0fc874175dffb 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?
|
| + std::fill(txt.begin(), txt.end(), kPasswordReplacementChar);
|
| + }
|
| + return txt;
|
| +}
|
| +
|
| void RenderText::ToggleInsertMode() {
|
| insert_mode_ = !insert_mode_;
|
| cached_bounds_and_offset_valid_ = false;
|
| }
|
|
|
| +void RenderText::SetIsObscured(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) {
|
| @@ -439,7 +441,8 @@ SelectionModel RenderText::GetLeftSelectionModel(const SelectionModel& current,
|
| // 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);
|
| + string16 txt = GetObscuredText();
|
| + base::i18n::BreakIterator iter(txt, base::i18n::BreakIterator::BREAK_WORD);
|
| bool success = iter.Init();
|
| DCHECK(success);
|
| if (!success)
|
| @@ -475,7 +478,8 @@ SelectionModel RenderText::GetRightSelectionModel(const SelectionModel& current,
|
| if (break_type == CHARACTER_BREAK)
|
| return SelectionModel(pos, pos, SelectionModel::LEADING);
|
|
|
| - 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)
|
|
|