| 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 <map> | 7 #include <map> |
| 8 | 8 |
| 9 #include "base/debug/leak_annotations.h" | 9 #include "base/debug/leak_annotations.h" |
| 10 #include "base/i18n/bidi_line_iterator.h" | 10 #include "base/i18n/bidi_line_iterator.h" |
| (...skipping 633 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 644 run = runs_[visual_to_logical_[visual_index]]; | 644 run = runs_[visual_to_logical_[visual_index]]; |
| 645 } | 645 } |
| 646 bool forward_motion = run->is_rtl == (direction == CURSOR_LEFT); | 646 bool forward_motion = run->is_rtl == (direction == CURSOR_LEFT); |
| 647 return forward_motion ? FirstSelectionModelInsideRun(run) : | 647 return forward_motion ? FirstSelectionModelInsideRun(run) : |
| 648 LastSelectionModelInsideRun(run); | 648 LastSelectionModelInsideRun(run); |
| 649 } | 649 } |
| 650 | 650 |
| 651 SelectionModel RenderTextHarfBuzz::AdjacentWordSelectionModel( | 651 SelectionModel RenderTextHarfBuzz::AdjacentWordSelectionModel( |
| 652 const SelectionModel& selection, | 652 const SelectionModel& selection, |
| 653 VisualCursorDirection direction) { | 653 VisualCursorDirection direction) { |
| 654 // TODO(ckocagil): This implementation currently matches RenderTextWin, but it | |
| 655 // should match the native behavior on other platforms. | |
| 656 if (obscured()) | 654 if (obscured()) |
| 657 return EdgeSelectionModel(direction); | 655 return EdgeSelectionModel(direction); |
| 658 | 656 |
| 659 base::i18n::BreakIterator iter(text(), base::i18n::BreakIterator::BREAK_WORD); | 657 base::i18n::BreakIterator iter(text(), base::i18n::BreakIterator::BREAK_WORD); |
| 660 bool success = iter.Init(); | 658 bool success = iter.Init(); |
| 661 DCHECK(success); | 659 DCHECK(success); |
| 662 if (!success) | 660 if (!success) |
| 663 return selection; | 661 return selection; |
| 664 | 662 |
| 663 // Match OS specific word break behavior. |
| 664 #if defined(OS_WIN) |
| 665 size_t pos; | 665 size_t pos; |
| 666 if (direction == CURSOR_RIGHT) { | 666 if (direction == CURSOR_RIGHT) { |
| 667 pos = std::min(selection.caret_pos() + 1, text().length()); | 667 pos = std::min(selection.caret_pos() + 1, text().length()); |
| 668 while (iter.Advance()) { | 668 while (iter.Advance()) { |
| 669 pos = iter.pos(); | 669 pos = iter.pos(); |
| 670 if (iter.IsWord() && pos > selection.caret_pos()) | 670 if (iter.IsWord() && pos > selection.caret_pos()) |
| 671 break; | 671 break; |
| 672 } | 672 } |
| 673 } else { // direction == CURSOR_LEFT | 673 } else { // direction == CURSOR_LEFT |
| 674 // Notes: We always iterate words from the beginning. | 674 // Notes: We always iterate words from the beginning. |
| (...skipping 12 matching lines...) Expand all Loading... |
| 687 // The cursor is in the middle or at the end of a word. | 687 // The cursor is in the middle or at the end of a word. |
| 688 // Move to the top of current word. | 688 // Move to the top of current word. |
| 689 pos = begin; | 689 pos = begin; |
| 690 break; | 690 break; |
| 691 } | 691 } |
| 692 pos = iter.pos() - iter.GetString().length(); | 692 pos = iter.pos() - iter.GetString().length(); |
| 693 } | 693 } |
| 694 } | 694 } |
| 695 } | 695 } |
| 696 return SelectionModel(pos, CURSOR_FORWARD); | 696 return SelectionModel(pos, CURSOR_FORWARD); |
| 697 #else |
| 698 SelectionModel cur(selection); |
| 699 for (;;) { |
| 700 cur = AdjacentCharSelectionModel(cur, direction); |
| 701 size_t run = GetRunContainingCaret(cur); |
| 702 if (run == runs_.size()) |
| 703 break; |
| 704 const bool is_forward = runs_[run]->is_rtl == (direction == CURSOR_LEFT); |
| 705 size_t cursor = cur.caret_pos(); |
| 706 if (is_forward ? iter.IsEndOfWord(cursor) : iter.IsStartOfWord(cursor)) |
| 707 break; |
| 708 } |
| 709 return cur; |
| 710 #endif |
| 697 } | 711 } |
| 698 | 712 |
| 699 std::vector<Rect> RenderTextHarfBuzz::GetSubstringBounds(const Range& range) { | 713 std::vector<Rect> RenderTextHarfBuzz::GetSubstringBounds(const Range& range) { |
| 700 DCHECK(!needs_layout_); | 714 DCHECK(!needs_layout_); |
| 701 DCHECK(Range(0, text().length()).Contains(range)); | 715 DCHECK(Range(0, text().length()).Contains(range)); |
| 702 Range layout_range(TextIndexToLayoutIndex(range.start()), | 716 Range layout_range(TextIndexToLayoutIndex(range.start()), |
| 703 TextIndexToLayoutIndex(range.end())); | 717 TextIndexToLayoutIndex(range.end())); |
| 704 DCHECK(Range(0, GetLayoutText().length()).Contains(layout_range)); | 718 DCHECK(Range(0, GetLayoutText().length()).Contains(layout_range)); |
| 705 | 719 |
| 706 std::vector<Rect> rects; | 720 std::vector<Rect> rects; |
| (...skipping 414 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1121 run->width += | 1135 run->width += |
| 1122 SkScalarRoundToInt(SkFixedToScalar(hb_positions[i].x_advance)); | 1136 SkScalarRoundToInt(SkFixedToScalar(hb_positions[i].x_advance)); |
| 1123 } | 1137 } |
| 1124 | 1138 |
| 1125 hb_buffer_destroy(buffer); | 1139 hb_buffer_destroy(buffer); |
| 1126 hb_font_destroy(harfbuzz_font); | 1140 hb_font_destroy(harfbuzz_font); |
| 1127 return true; | 1141 return true; |
| 1128 } | 1142 } |
| 1129 | 1143 |
| 1130 } // namespace gfx | 1144 } // namespace gfx |
| OLD | NEW |