| OLD | NEW |
| 1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "ui/gfx/render_text_harfbuzz.h" | 5 #include "ui/gfx/render_text_harfbuzz.h" |
| 6 | 6 |
| 7 #include <limits> | 7 #include <limits> |
| 8 #include <set> | 8 #include <set> |
| 9 | 9 |
| 10 #include "base/i18n/bidi_line_iterator.h" | 10 #include "base/i18n/bidi_line_iterator.h" |
| (...skipping 824 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 835 VisualCursorDirection direction) { | 835 VisualCursorDirection direction) { |
| 836 if (obscured()) | 836 if (obscured()) |
| 837 return EdgeSelectionModel(direction); | 837 return EdgeSelectionModel(direction); |
| 838 | 838 |
| 839 base::i18n::BreakIterator iter(text(), base::i18n::BreakIterator::BREAK_WORD); | 839 base::i18n::BreakIterator iter(text(), base::i18n::BreakIterator::BREAK_WORD); |
| 840 bool success = iter.Init(); | 840 bool success = iter.Init(); |
| 841 DCHECK(success); | 841 DCHECK(success); |
| 842 if (!success) | 842 if (!success) |
| 843 return selection; | 843 return selection; |
| 844 | 844 |
| 845 // Match OS specific word break behavior. | |
| 846 #if defined(OS_WIN) | |
| 847 size_t pos; | |
| 848 if (direction == CURSOR_RIGHT) { | |
| 849 pos = std::min(selection.caret_pos() + 1, text().length()); | |
| 850 while (iter.Advance()) { | |
| 851 pos = iter.pos(); | |
| 852 if (iter.IsWord() && pos > selection.caret_pos()) | |
| 853 break; | |
| 854 } | |
| 855 } else { // direction == CURSOR_LEFT | |
| 856 // Notes: We always iterate words from the beginning. | |
| 857 // This is probably fast enough for our usage, but we may | |
| 858 // want to modify WordIterator so that it can start from the | |
| 859 // middle of string and advance backwards. | |
| 860 pos = std::max<int>(selection.caret_pos() - 1, 0); | |
| 861 while (iter.Advance()) { | |
| 862 if (iter.IsWord()) { | |
| 863 size_t begin = iter.pos() - iter.GetString().length(); | |
| 864 if (begin == selection.caret_pos()) { | |
| 865 // The cursor is at the beginning of a word. | |
| 866 // Move to previous word. | |
| 867 break; | |
| 868 } else if (iter.pos() >= selection.caret_pos()) { | |
| 869 // The cursor is in the middle or at the end of a word. | |
| 870 // Move to the top of current word. | |
| 871 pos = begin; | |
| 872 break; | |
| 873 } | |
| 874 pos = iter.pos() - iter.GetString().length(); | |
| 875 } | |
| 876 } | |
| 877 } | |
| 878 return SelectionModel(pos, CURSOR_FORWARD); | |
| 879 #else | |
| 880 internal::TextRunList* run_list = GetRunList(); | 845 internal::TextRunList* run_list = GetRunList(); |
| 881 SelectionModel cur(selection); | 846 SelectionModel cur(selection); |
| 882 for (;;) { | 847 for (;;) { |
| 883 cur = AdjacentCharSelectionModel(cur, direction); | 848 cur = AdjacentCharSelectionModel(cur, direction); |
| 884 size_t run = GetRunContainingCaret(cur); | 849 size_t run = GetRunContainingCaret(cur); |
| 885 if (run == run_list->size()) | 850 if (run == run_list->size()) |
| 886 break; | 851 break; |
| 887 const bool is_forward = | 852 const bool is_forward = |
| 888 run_list->runs()[run]->is_rtl == (direction == CURSOR_LEFT); | 853 run_list->runs()[run]->is_rtl == (direction == CURSOR_LEFT); |
| 889 size_t cursor = cur.caret_pos(); | 854 size_t cursor = cur.caret_pos(); |
| 890 if (is_forward ? iter.IsEndOfWord(cursor) : iter.IsStartOfWord(cursor)) | 855 if (is_forward ? iter.IsEndOfWord(cursor) : iter.IsStartOfWord(cursor)) |
| 891 break; | 856 break; |
| 892 } | 857 } |
| 893 return cur; | 858 return cur; |
| 894 #endif | |
| 895 } | 859 } |
| 896 | 860 |
| 897 std::vector<Rect> RenderTextHarfBuzz::GetSubstringBounds(const Range& range) { | 861 std::vector<Rect> RenderTextHarfBuzz::GetSubstringBounds(const Range& range) { |
| 898 DCHECK(!update_display_run_list_); | 862 DCHECK(!update_display_run_list_); |
| 899 DCHECK(Range(0, text().length()).Contains(range)); | 863 DCHECK(Range(0, text().length()).Contains(range)); |
| 900 Range layout_range(TextIndexToDisplayIndex(range.start()), | 864 Range layout_range(TextIndexToDisplayIndex(range.start()), |
| 901 TextIndexToDisplayIndex(range.end())); | 865 TextIndexToDisplayIndex(range.end())); |
| 902 DCHECK(Range(0, GetDisplayText().length()).Contains(layout_range)); | 866 DCHECK(Range(0, GetDisplayText().length()).Contains(layout_range)); |
| 903 | 867 |
| 904 std::vector<Rect> rects; | 868 std::vector<Rect> rects; |
| (...skipping 574 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1479 DCHECK(!update_layout_run_list_); | 1443 DCHECK(!update_layout_run_list_); |
| 1480 DCHECK(!update_display_run_list_); | 1444 DCHECK(!update_display_run_list_); |
| 1481 return text_elided() ? display_run_list_.get() : &layout_run_list_; | 1445 return text_elided() ? display_run_list_.get() : &layout_run_list_; |
| 1482 } | 1446 } |
| 1483 | 1447 |
| 1484 const internal::TextRunList* RenderTextHarfBuzz::GetRunList() const { | 1448 const internal::TextRunList* RenderTextHarfBuzz::GetRunList() const { |
| 1485 return const_cast<RenderTextHarfBuzz*>(this)->GetRunList(); | 1449 return const_cast<RenderTextHarfBuzz*>(this)->GetRunList(); |
| 1486 } | 1450 } |
| 1487 | 1451 |
| 1488 } // namespace gfx | 1452 } // namespace gfx |
| OLD | NEW |