Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(939)

Unified Diff: ui/gfx/render_text.cc

Issue 2348143003: MacViews: Implement Force Touch/Mac dictionary lookup for Textfields. (Closed)
Patch Set: Address nits. Created 4 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « ui/gfx/render_text.h ('k') | ui/gfx/render_text_harfbuzz.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: ui/gfx/render_text.cc
diff --git a/ui/gfx/render_text.cc b/ui/gfx/render_text.cc
index c9404fc0b14bc5411008da5f5af69919786d31b4..7ccaaa6131a5ece76f65603b9c3cc7f5450b4248 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. See
+ // http://crbug.com/650120.
+ if (multiline() || obscured())
+ return false;
+
+ // Note: FindCursorPosition will trigger a layout via EnsureLayout.
+ 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());
+
+ const std::vector<Rect> word_bounds = GetSubstringBounds(word_range);
+ if (word_bounds.empty() ||
+ !GetDecoratedTextForRange(word_range, decorated_word)) {
+ return false;
+ }
+
+ // Retrieve the baseline origin of the left-most glyph.
+ const auto left_rect = std::min_element(
+ word_bounds.begin(), word_bounds.end(),
+ [](const Rect& lhs, const Rect& rhs) { return lhs.x() < rhs.x(); });
+ *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,60 @@ 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() || length == 0)
+ 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(index, 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_LE(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
« no previous file with comments | « ui/gfx/render_text.h ('k') | ui/gfx/render_text_harfbuzz.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698