| Index: ui/gfx/render_text.cc
|
| diff --git a/ui/gfx/render_text.cc b/ui/gfx/render_text.cc
|
| index 498bb3b42a3ad552208fee366dc42ec7de434b44..26518d1be332ee1c52dd36fc14c66e0f9c860050 100644
|
| --- a/ui/gfx/render_text.cc
|
| +++ b/ui/gfx/render_text.cc
|
| @@ -164,14 +164,8 @@ void RenderText::SetText(const string16& text) {
|
| cached_bounds_and_offset_valid_ = false;
|
| }
|
|
|
| -void RenderText::SetSelectionModel(const SelectionModel& sel) {
|
| - size_t start = sel.selection_start();
|
| - size_t end = sel.selection_end();
|
| - selection_model_.set_selection_start(std::min(start, text().length()));
|
| - selection_model_.set_selection_end(std::min(end, text().length()));
|
| - selection_model_.set_caret_pos(std::min(sel.caret_pos(), text().length()));
|
| - selection_model_.set_caret_placement(sel.caret_placement());
|
| -
|
| +void RenderText::ToggleInsertMode() {
|
| + insert_mode_ = !insert_mode_;
|
| cached_bounds_and_offset_valid_ = false;
|
| }
|
|
|
| @@ -184,13 +178,8 @@ size_t RenderText::GetCursorPosition() const {
|
| return selection_model_.selection_end();
|
| }
|
|
|
| -void RenderText::SetCursorPosition(const size_t position) {
|
| - SelectionModel sel(selection_model());
|
| - sel.set_selection_start(position);
|
| - sel.set_selection_end(position);
|
| - sel.set_caret_pos(GetIndexOfPreviousGrapheme(position));
|
| - sel.set_caret_placement(SelectionModel::TRAILING);
|
| - SetSelectionModel(sel);
|
| +void RenderText::SetCursorPosition(size_t position) {
|
| + MoveCursorTo(position, false);
|
| }
|
|
|
| void RenderText::MoveCursorLeft(BreakType break_type, bool select) {
|
| @@ -237,9 +226,26 @@ void RenderText::MoveCursorRight(BreakType break_type, bool select) {
|
| MoveCursorTo(position);
|
| }
|
|
|
| -bool RenderText::MoveCursorTo(const SelectionModel& selection) {
|
| - bool changed = !selection.Equals(selection_model_);
|
| - SetSelectionModel(selection);
|
| +bool RenderText::MoveCursorTo(const SelectionModel& selection_model) {
|
| + SelectionModel sel(selection_model);
|
| + size_t text_length = text().length();
|
| + // Enforce valid selection model components.
|
| + if (sel.selection_start() > text_length)
|
| + sel.set_selection_start(text_length);
|
| + if (sel.selection_end() > text_length)
|
| + sel.set_selection_end(text_length);
|
| + // The current model only supports caret positions at valid character indices.
|
| + if (text_length == 0) {
|
| + sel.set_caret_pos(0);
|
| + sel.set_caret_placement(SelectionModel::LEADING);
|
| + } else if (sel.caret_pos() >= text_length) {
|
| + SelectionModel end = GetTextDirection() == base::i18n::RIGHT_TO_LEFT ?
|
| + LeftEndSelectionModel() : RightEndSelectionModel();
|
| + sel.set_caret_pos(end.caret_pos());
|
| + sel.set_caret_placement(end.caret_placement());
|
| + }
|
| + bool changed = !sel.Equals(selection_model_);
|
| + SetSelectionModel(sel);
|
| return changed;
|
| }
|
|
|
| @@ -251,6 +257,8 @@ bool RenderText::MoveCursorTo(const Point& point, bool select) {
|
| }
|
|
|
| bool RenderText::IsPointInSelection(const Point& point) {
|
| + if (EmptySelection())
|
| + return false;
|
| // TODO(xji): should this check whether the point is inside the visual
|
| // selection bounds? In case of "abcFED", if "ED" is selected, |point| points
|
| // to the right half of 'c', is the point in selection?
|
| @@ -265,8 +273,8 @@ void RenderText::ClearSelection() {
|
| }
|
|
|
| void RenderText::SelectAll() {
|
| - SelectionModel sel(0, text().length(),
|
| - text().length(), SelectionModel::LEADING);
|
| + SelectionModel sel(RightEndSelectionModel());
|
| + sel.set_selection_start(LeftEndSelectionModel().selection_start());
|
| SetSelectionModel(sel);
|
| }
|
|
|
| @@ -308,12 +316,8 @@ void RenderText::SelectWord() {
|
| break;
|
| }
|
|
|
| - SelectionModel sel(selection_model());
|
| - sel.set_selection_start(selection_start);
|
| - sel.set_selection_end(cursor_position);
|
| - sel.set_caret_pos(GetIndexOfPreviousGrapheme(cursor_position));
|
| - sel.set_caret_placement(SelectionModel::TRAILING);
|
| - SetSelectionModel(sel);
|
| + MoveCursorTo(selection_start, false);
|
| + MoveCursorTo(cursor_position, true);
|
| }
|
|
|
| const ui::Range& RenderText::GetCompositionRange() const {
|
| @@ -350,8 +354,8 @@ void RenderText::ApplyDefaultStyle() {
|
| }
|
|
|
| base::i18n::TextDirection RenderText::GetTextDirection() const {
|
| - // TODO(msw): Bidi implementation, intended to replace the functionality added
|
| - // in crrev.com/91881 (discussed in codereview.chromium.org/7324011).
|
| + if (base::i18n::IsRTL())
|
| + return base::i18n::RIGHT_TO_LEFT;
|
| return base::i18n::LEFT_TO_RIGHT;
|
| }
|
|
|
| @@ -443,20 +447,6 @@ SelectionModel RenderText::FindCursorPosition(const Point& point) {
|
| return SelectionModel(left_pos);
|
| }
|
|
|
| -std::vector<Rect> RenderText::GetSubstringBounds(size_t from, size_t to) {
|
| - size_t start = std::min(from, to);
|
| - size_t end = std::max(from, to);
|
| - const Font& font = default_style_.font;
|
| - int start_x = font.GetStringWidth(text().substr(0, start));
|
| - int end_x = font.GetStringWidth(text().substr(0, end));
|
| - Rect rect(start_x, 0, end_x - start_x, font.GetHeight());
|
| - rect.Offset(display_rect_.origin());
|
| - rect.Offset(GetUpdatedDisplayOffset());
|
| - // Center the rect vertically in |display_rect_|.
|
| - rect.Offset(Point(0, (display_rect_.height() - rect.height()) / 2));
|
| - return std::vector<Rect>(1, rect);
|
| -}
|
| -
|
| Rect RenderText::GetCursorBounds(const SelectionModel& selection,
|
| bool insert_mode) {
|
| size_t from = selection.selection_end();
|
| @@ -549,9 +539,35 @@ SelectionModel RenderText::GetRightSelectionModel(const SelectionModel& current,
|
| 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);
|
| +}
|
| +
|
| size_t RenderText::GetIndexOfPreviousGrapheme(size_t position) {
|
| // TODO(msw): Handle complex script.
|
| - return std::max(static_cast<int>(position - 1), static_cast<int>(0));
|
| + return std::max(static_cast<long>(position - 1), static_cast<long>(0));
|
| +}
|
| +
|
| +std::vector<Rect> RenderText::GetSubstringBounds(size_t from, size_t to) {
|
| + size_t start = std::min(from, to);
|
| + size_t end = std::max(from, to);
|
| + const Font& font = default_style_.font;
|
| + int start_x = font.GetStringWidth(text().substr(0, start));
|
| + int end_x = font.GetStringWidth(text().substr(0, end));
|
| + Rect rect(start_x, 0, end_x - start_x, font.GetHeight());
|
| + rect.Offset(display_rect_.origin());
|
| + rect.Offset(GetUpdatedDisplayOffset());
|
| + // Center the rect vertically in |display_rect_|.
|
| + rect.Offset(Point(0, (display_rect_.height() - rect.height()) / 2));
|
| + return std::vector<Rect>(1, rect);
|
| }
|
|
|
| void RenderText::ApplyCompositionAndSelectionStyles(
|
| @@ -576,6 +592,45 @@ void RenderText::ApplyCompositionAndSelectionStyles(
|
| }
|
| }
|
|
|
| +Point RenderText::ToTextPoint(const Point& point) {
|
| + Point p(point.Subtract(display_rect().origin()));
|
| + p = p.Subtract(GetUpdatedDisplayOffset());
|
| + if (base::i18n::IsRTL())
|
| + p.Offset(GetStringWidth() - display_rect().width() + 1, 0);
|
| + return p;
|
| +}
|
| +
|
| +Point RenderText::ToViewPoint(const Point& point) {
|
| + Point p(point.Add(display_rect().origin()));
|
| + p = p.Add(GetUpdatedDisplayOffset());
|
| + if (base::i18n::IsRTL())
|
| + p.Offset(display_rect().width() - GetStringWidth() - 1, 0);
|
| + return p;
|
| +}
|
| +
|
| +void RenderText::SetSelectionModel(const SelectionModel& selection_model) {
|
| + DCHECK_LE(selection_model.selection_start(), text().length());
|
| + selection_model_.set_selection_start(selection_model.selection_start());
|
| + DCHECK_LE(selection_model.selection_end(), text().length());
|
| + selection_model_.set_selection_end(selection_model.selection_end());
|
| + DCHECK_LT(selection_model.caret_pos(),
|
| + std::max(text().length(), static_cast<size_t>(1)));
|
| + selection_model_.set_caret_pos(selection_model.caret_pos());
|
| + selection_model_.set_caret_placement(selection_model.caret_placement());
|
| +
|
| + cached_bounds_and_offset_valid_ = false;
|
| +}
|
| +
|
| +void RenderText::MoveCursorTo(size_t position, bool select) {
|
| + size_t cursor = std::min(position, text().length());
|
| + size_t caret_pos = GetIndexOfPreviousGrapheme(cursor);
|
| + SelectionModel::CaretPlacement placement = (caret_pos == cursor) ?
|
| + SelectionModel::LEADING : SelectionModel::TRAILING;
|
| + size_t selection_start = select ? GetSelectionStart() : cursor;
|
| + SelectionModel sel(selection_start, cursor, caret_pos, placement);
|
| + SetSelectionModel(sel);
|
| +}
|
| +
|
| bool RenderText::IsPositionAtWordSelectionBoundary(size_t pos) {
|
| return pos == 0 || (u_isalnum(text()[pos - 1]) && !u_isalnum(text()[pos])) ||
|
| (!u_isalnum(text()[pos - 1]) && u_isalnum(text()[pos]));
|
| @@ -589,7 +644,6 @@ void RenderText::UpdateCachedBoundsAndOffset() {
|
| // function will set |cursor_bounds_| and |display_offset_| to correct values.
|
| cached_bounds_and_offset_valid_ = true;
|
| cursor_bounds_ = GetCursorBounds(selection_model_, insert_mode_);
|
| - cursor_bounds_.set_width(std::max(cursor_bounds_.width(), 1));
|
| // Update |display_offset_| to ensure the current cursor is visible.
|
| int display_width = display_rect_.width();
|
| int string_width = GetStringWidth();
|
|
|