Index: ui/gfx/render_text.cc |
diff --git a/ui/gfx/render_text.cc b/ui/gfx/render_text.cc |
index c9404fc0b14bc5411008da5f5af69919786d31b4..eb569f847b29674ab5a1f42d0b77bc7c44b60c35 100644 |
--- a/ui/gfx/render_text.cc |
+++ b/ui/gfx/render_text.cc |
@@ -721,39 +721,7 @@ void RenderText::SelectAll(bool reversed) { |
} |
void RenderText::SelectWord() { |
- if (obscured_) { |
- SelectAll(false); |
- return; |
- } |
- |
- size_t selection_max = selection().GetMax(); |
- |
- base::i18n::BreakIterator iter(text(), base::i18n::BreakIterator::BREAK_WORD); |
- bool success = iter.Init(); |
- DCHECK(success); |
- if (!success) |
- return; |
- |
- size_t selection_min = selection().GetMin(); |
- if (selection_min == text().length() && selection_min != 0) |
- --selection_min; |
- |
- for (; selection_min != 0; --selection_min) { |
- if (iter.IsStartOfWord(selection_min) || |
- iter.IsEndOfWord(selection_min)) |
- break; |
- } |
- |
- if (selection_min == selection_max && selection_max != text().length()) |
- ++selection_max; |
- |
- for (; selection_max < text().length(); ++selection_max) |
- if (iter.IsEndOfWord(selection_max) || iter.IsStartOfWord(selection_max)) |
- break; |
- |
- const bool reversed = selection().is_reversed(); |
- MoveCursorTo(reversed ? selection_max : selection_min, false); |
- MoveCursorTo(reversed ? selection_min : selection_max, true); |
+ SelectRange(ExpandRangeToWordBoundary(selection())); |
} |
void RenderText::SetCompositionRange(const Range& composition_range) { |
@@ -1042,6 +1010,45 @@ Vector2d RenderText::GetLineOffset(size_t line_number) { |
return offset; |
} |
+bool RenderText::GetDecoratedWordAtPoint(const Point& point, |
+ DecoratedText* decorated_word, |
+ Point* baseline_point) { |
+ // FindCursorPosition doesn't currently support multiline. |
+ if (multiline() || obscured()) |
+ return false; |
+ |
+ const SelectionModel model_at_point = FindCursorPosition(point); |
+ const size_t word_index = |
+ GetNearestWordStartBoundary(model_at_point.caret_pos()); |
+ if (word_index >= text().length()) |
+ return false; |
+ |
+ const Range word_range = ExpandRangeToWordBoundary(Range(word_index)); |
+ DCHECK(!word_range.is_reversed()); |
+ DCHECK(!word_range.is_empty()); |
+ |
+ if (!GetDecoratedTextForRange(word_range, decorated_word)) |
+ return false; |
+ |
+ const std::vector<Rect> word_bounds = GetSubstringBounds(word_range); |
karandeepb
2016/09/22 08:17:39
Had to change the approach here and use GetSubstri
|
+ if (word_bounds.empty()) |
+ return false; |
+ |
+ const Rect* left_rect = &word_bounds[0]; |
+ for (const Rect& rect : word_bounds) |
+ if (rect.x() < left_rect->x()) |
+ left_rect = ▭ |
+ |
+ *baseline_point = left_rect->origin() + Vector2d(0, GetDisplayTextBaseline()); |
+ return true; |
+} |
+ |
+base::string16 RenderText::GetTextFromRange(const Range& range) const { |
+ if (range.IsValid() && range.GetMin() < text().length()) |
+ return text().substr(range.GetMin(), range.length()); |
+ return base::string16(); |
+} |
+ |
RenderText::RenderText() |
: horizontal_alignment_(base::i18n::IsRTL() ? ALIGN_RIGHT : ALIGN_LEFT), |
directionality_mode_(DIRECTIONALITY_FROM_TEXT), |
@@ -1627,4 +1634,61 @@ void RenderText::DrawSelection(Canvas* canvas) { |
canvas->FillRect(s, selection_background_focused_color_); |
} |
+size_t RenderText::GetNearestWordStartBoundary(size_t index) const { |
+ const size_t length = text().length(); |
+ if (obscured()) |
+ return length; |
+ |
+ base::i18n::BreakIterator iter(text(), base::i18n::BreakIterator::BREAK_WORD); |
+ const bool success = iter.Init(); |
+ DCHECK(success); |
+ if (!success) |
+ return length; |
+ |
+ // First search for the word start boundary in the CURSOR_BACKWARD direction, |
+ // then in the CURSOR_FORWARD direction. |
+ for (int i = std::min<int>(index, (int)length - 1); i >= 0; i--) |
+ if (iter.IsStartOfWord(i)) |
+ return i; |
+ |
+ for (size_t i = index + 1; i < length; i++) |
+ if (iter.IsStartOfWord(i)) |
+ return i; |
+ |
+ return length; |
+} |
+ |
+Range RenderText::ExpandRangeToWordBoundary(const Range& range) const { |
+ const size_t length = text().length(); |
+ DCHECK(range.GetMax() <= length); |
+ if (obscured()) |
+ return range.is_reversed() ? Range(length, 0) : Range(0, length); |
+ |
+ base::i18n::BreakIterator iter(text(), base::i18n::BreakIterator::BREAK_WORD); |
+ const bool success = iter.Init(); |
+ DCHECK(success); |
+ if (!success) |
+ return range; |
+ |
+ size_t range_min = range.GetMin(); |
+ if (range_min == length && range_min != 0) |
+ --range_min; |
+ |
+ for (; range_min != 0; --range_min) { |
+ if (iter.IsStartOfWord(range_min) || iter.IsEndOfWord(range_min)) |
+ break; |
+ } |
+ |
+ size_t range_max = range.GetMax(); |
+ if (range_min == range_max && range_max != length) |
+ ++range_max; |
+ |
+ for (; range_max < length; ++range_max) |
+ if (iter.IsEndOfWord(range_max) || iter.IsStartOfWord(range_max)) |
+ break; |
+ |
+ return range.is_reversed() ? Range(range_max, range_min) |
+ : Range(range_min, range_max); |
+} |
+ |
} // namespace gfx |