summaryrefslogtreecommitdiffstats
path: root/ui/gfx/render_text.cc
diff options
context:
space:
mode:
Diffstat (limited to 'ui/gfx/render_text.cc')
-rw-r--r--ui/gfx/render_text.cc142
1 files changed, 98 insertions, 44 deletions
diff --git a/ui/gfx/render_text.cc b/ui/gfx/render_text.cc
index 498bb3b..26518d1 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();