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 |