OLD | NEW |
---|---|
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 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.h" | 5 #include "ui/gfx/render_text.h" |
6 | 6 |
7 #include <limits.h> | 7 #include <limits.h> |
8 | 8 |
9 #include <algorithm> | 9 #include <algorithm> |
10 #include <climits> | 10 #include <climits> |
(...skipping 189 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
200 range = break_list->GetRange(current_break); | 200 range = break_list->GetRange(current_break); |
201 if (range.end() < break_list->max() && | 201 if (range.end() < break_list->max() && |
202 !render_text->IsValidCursorIndex(range.end())) { | 202 !render_text->IsValidCursorIndex(range.end())) { |
203 range.set_end( | 203 range.set_end( |
204 render_text->IndexOfAdjacentGrapheme(range.end(), CURSOR_FORWARD)); | 204 render_text->IndexOfAdjacentGrapheme(range.end(), CURSOR_FORWARD)); |
205 break_list->ApplyValue(current_break->second, range); | 205 break_list->ApplyValue(current_break->second, range); |
206 } | 206 } |
207 } | 207 } |
208 } | 208 } |
209 | 209 |
210 // Merges |range1| and |range2|, with the directionality of the result same as | |
211 // |range2|. |range1| and |range2| must at least share a point. | |
212 gfx::Range MergeRangesWithDirection(const Range& range1, const Range& range2) { | |
213 DCHECK(!(range1.GetMax() < range2.GetMin() || | |
tapted
2016/08/11 03:44:07
DCHECK(range1.Intersects(range2))?
karandeepb
2016/08/16 10:24:51
Removed this function. Also Range::Intersects is w
| |
214 range2.GetMax() < range1.GetMin())); | |
215 const uint32_t min = std::min(range1.GetMin(), range2.GetMin()); | |
216 const uint32_t max = std::max(range1.GetMax(), range2.GetMax()); | |
217 | |
218 // If |range2| is empty, use the direction opposition to the one of |range1|. | |
219 bool reversed = | |
220 range2.is_empty() ? !range1.is_reversed() : range2.is_reversed(); | |
221 return reversed ? Range(max, min) : Range(min, max); | |
222 } | |
tapted
2016/08/11 03:44:07
ui/gfx OWNERS might be interested in a Range::Unio
| |
223 | |
210 } // namespace | 224 } // namespace |
211 | 225 |
212 namespace internal { | 226 namespace internal { |
213 | 227 |
214 // Value of |underline_thickness_| that indicates that underline metrics have | 228 // Value of |underline_thickness_| that indicates that underline metrics have |
215 // not been set explicitly. | 229 // not been set explicitly. |
216 const SkScalar kUnderlineMetricsNotSet = -1.0f; | 230 const SkScalar kUnderlineMetricsNotSet = -1.0f; |
217 | 231 |
218 SkiaTextRenderer::SkiaTextRenderer(Canvas* canvas) | 232 SkiaTextRenderer::SkiaTextRenderer(Canvas* canvas) |
219 : canvas_(canvas), | 233 : canvas_(canvas), |
(...skipping 386 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
606 } | 620 } |
607 } | 621 } |
608 } | 622 } |
609 | 623 |
610 void RenderText::SetCursorPosition(size_t position) { | 624 void RenderText::SetCursorPosition(size_t position) { |
611 MoveCursorTo(position, false); | 625 MoveCursorTo(position, false); |
612 } | 626 } |
613 | 627 |
614 void RenderText::MoveCursor(BreakType break_type, | 628 void RenderText::MoveCursor(BreakType break_type, |
615 VisualCursorDirection direction, | 629 VisualCursorDirection direction, |
616 bool select) { | 630 bool select, |
631 SelectionReversedBehavior select_behavior) { | |
617 SelectionModel cursor(cursor_position(), selection_model_.caret_affinity()); | 632 SelectionModel cursor(cursor_position(), selection_model_.caret_affinity()); |
618 // Cancelling a selection moves to the edge of the selection. | 633 // Cancelling a selection moves to the edge of the selection. |
619 if (break_type != LINE_BREAK && !selection().is_empty() && !select) { | 634 if (break_type != LINE_BREAK && !selection().is_empty() && !select) { |
620 SelectionModel selection_start = GetSelectionModelForSelectionStart(); | 635 SelectionModel selection_start = GetSelectionModelForSelectionStart(); |
621 int start_x = GetCursorBounds(selection_start, true).x(); | 636 int start_x = GetCursorBounds(selection_start, true).x(); |
622 int cursor_x = GetCursorBounds(cursor, true).x(); | 637 int cursor_x = GetCursorBounds(cursor, true).x(); |
623 // Use the selection start if it is left (when |direction| is CURSOR_LEFT) | 638 // Use the selection start if it is left (when |direction| is CURSOR_LEFT) |
624 // or right (when |direction| is CURSOR_RIGHT) of the selection end. | 639 // or right (when |direction| is CURSOR_RIGHT) of the selection end. |
625 if (direction == CURSOR_RIGHT ? start_x > cursor_x : start_x < cursor_x) | 640 if (direction == CURSOR_RIGHT ? start_x > cursor_x : start_x < cursor_x) |
626 cursor = selection_start; | 641 cursor = selection_start; |
627 // Use the nearest word boundary in the proper |direction| for word breaks. | 642 // Use the nearest word boundary in the proper |direction| for word breaks. |
628 if (break_type == WORD_BREAK) | 643 if (break_type == WORD_BREAK) |
629 cursor = GetAdjacentSelectionModel(cursor, break_type, direction); | 644 cursor = GetAdjacentSelectionModel(cursor, break_type, direction); |
630 // Use an adjacent selection model if the cursor is not at a valid position. | 645 // Use an adjacent selection model if the cursor is not at a valid position. |
631 if (!IsValidCursorIndex(cursor.caret_pos())) | 646 if (!IsValidCursorIndex(cursor.caret_pos())) |
632 cursor = GetAdjacentSelectionModel(cursor, CHARACTER_BREAK, direction); | 647 cursor = GetAdjacentSelectionModel(cursor, CHARACTER_BREAK, direction); |
633 } else { | 648 } else { |
634 cursor = GetAdjacentSelectionModel(cursor, break_type, direction); | 649 cursor = GetAdjacentSelectionModel(cursor, break_type, direction); |
635 } | 650 } |
636 if (select) | 651 if (select) { |
652 // |select_behavior| is not relevant for CHARACTER_BREAK. Verify | |
653 // |select_behavior| has the default value for this case. | |
654 DCHECK(break_type != CHARACTER_BREAK || | |
655 select_behavior == SELECTION_DEFAULT); | |
656 | |
657 // SELECTION_EXTEND is only relevant for LINE_BREAK. | |
658 DCHECK(select_behavior != SELECTION_EXTEND || break_type == LINE_BREAK); | |
tapted
2016/08/11 03:44:07
What's the behaviour if these DCHECKs fail? (is it
karandeepb
2016/08/16 10:24:51
Removed the DCHECK. The behavior is now correct an
| |
659 | |
637 cursor.set_selection_start(selection().start()); | 660 cursor.set_selection_start(selection().start()); |
661 | |
662 // cursor now corresponds to the new selection. Take |select_behavior| into | |
tapted
2016/08/11 03:44:07
cursor -> Cursor, or "The cursor"
karandeepb
2016/08/16 10:24:51
Changed to |cursor| since I want to refer to the l
| |
663 // account. | |
664 bool selection_direction_changed = | |
665 !selection().is_empty() && !cursor.selection().is_empty() && | |
666 selection().is_reversed() != cursor.selection().is_reversed(); | |
667 | |
668 if (select_behavior == SELECTION_EXTEND) { | |
669 cursor = SelectionModel( | |
670 MergeRangesWithDirection(selection(), cursor.selection()), | |
671 selection_model_.caret_affinity()); | |
672 } else if (selection_direction_changed && | |
673 select_behavior == SELECTION_CARET) { | |
674 cursor = SelectionModel(selection().start(), | |
675 selection_model_.caret_affinity()); | |
676 } | |
677 } | |
678 | |
638 MoveCursorTo(cursor); | 679 MoveCursorTo(cursor); |
639 } | 680 } |
640 | 681 |
641 bool RenderText::MoveCursorTo(const SelectionModel& model) { | 682 bool RenderText::MoveCursorTo(const SelectionModel& model) { |
642 // Enforce valid selection model components. | 683 // Enforce valid selection model components. |
643 size_t text_length = text().length(); | 684 size_t text_length = text().length(); |
644 Range range(std::min(model.selection().start(), | 685 Range range(std::min(model.selection().start(), |
645 static_cast<uint32_t>(text_length)), | 686 static_cast<uint32_t>(text_length)), |
646 std::min(model.caret_pos(), text_length)); | 687 std::min(model.caret_pos(), text_length)); |
647 // The current model only supports caret positions at valid cursor indices. | 688 // The current model only supports caret positions at valid cursor indices. |
(...skipping 939 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1587 | 1628 |
1588 SetDisplayOffset(display_offset_.x() + delta_x); | 1629 SetDisplayOffset(display_offset_.x() + delta_x); |
1589 } | 1630 } |
1590 | 1631 |
1591 void RenderText::DrawSelection(Canvas* canvas) { | 1632 void RenderText::DrawSelection(Canvas* canvas) { |
1592 for (const Rect& s : GetSubstringBounds(selection())) | 1633 for (const Rect& s : GetSubstringBounds(selection())) |
1593 canvas->FillRect(s, selection_background_focused_color_); | 1634 canvas->FillRect(s, selection_background_focused_color_); |
1594 } | 1635 } |
1595 | 1636 |
1596 } // namespace gfx | 1637 } // namespace gfx |
OLD | NEW |