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 <algorithm> | 7 #include <algorithm> |
8 | 8 |
9 #include "base/i18n/break_iterator.h" | 9 #include "base/i18n/break_iterator.h" |
10 #include "base/logging.h" | 10 #include "base/logging.h" |
(...skipping 283 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
294 range = range.Intersect(styles_[i].GetRange(style_[i])); | 294 range = range.Intersect(styles_[i].GetRange(style_[i])); |
295 return range; | 295 return range; |
296 } | 296 } |
297 | 297 |
298 void StyleIterator::UpdatePosition(size_t position) { | 298 void StyleIterator::UpdatePosition(size_t position) { |
299 color_ = colors_.GetBreak(position); | 299 color_ = colors_.GetBreak(position); |
300 for (size_t i = 0; i < NUM_TEXT_STYLES; ++i) | 300 for (size_t i = 0; i < NUM_TEXT_STYLES; ++i) |
301 style_[i] = styles_[i].GetBreak(position); | 301 style_[i] = styles_[i].GetBreak(position); |
302 } | 302 } |
303 | 303 |
| 304 LineSegment::LineSegment() : run(0) {} |
| 305 |
| 306 Line::Line() : preceding_heights(0), baseline(0) {} |
| 307 |
304 } // namespace internal | 308 } // namespace internal |
305 | 309 |
306 RenderText::~RenderText() { | 310 RenderText::~RenderText() { |
307 } | 311 } |
308 | 312 |
309 void RenderText::SetText(const base::string16& text) { | 313 void RenderText::SetText(const base::string16& text) { |
310 DCHECK(!composition_range_.IsValid()); | 314 DCHECK(!composition_range_.IsValid()); |
| 315 if (text_ == text) |
| 316 return; |
311 text_ = text; | 317 text_ = text; |
312 | 318 |
313 // Adjust ranged styles and colors to accommodate a new text length. | 319 // Adjust ranged styles and colors to accommodate a new text length. |
314 const size_t text_length = text_.length(); | 320 const size_t text_length = text_.length(); |
315 colors_.SetMax(text_length); | 321 colors_.SetMax(text_length); |
316 for (size_t style = 0; style < NUM_TEXT_STYLES; ++style) | 322 for (size_t style = 0; style < NUM_TEXT_STYLES; ++style) |
317 styles_[style].SetMax(text_length); | 323 styles_[style].SetMax(text_length); |
318 cached_bounds_and_offset_valid_ = false; | 324 cached_bounds_and_offset_valid_ = false; |
319 | 325 |
320 // Reset selection model. SetText should always followed by SetSelectionModel | 326 // Reset selection model. SetText should always followed by SetSelectionModel |
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
387 void RenderText::SetObscuredRevealIndex(int index) { | 393 void RenderText::SetObscuredRevealIndex(int index) { |
388 if (obscured_reveal_index_ == index) | 394 if (obscured_reveal_index_ == index) |
389 return; | 395 return; |
390 | 396 |
391 obscured_reveal_index_ = index; | 397 obscured_reveal_index_ = index; |
392 cached_bounds_and_offset_valid_ = false; | 398 cached_bounds_and_offset_valid_ = false; |
393 UpdateLayoutText(); | 399 UpdateLayoutText(); |
394 ResetLayout(); | 400 ResetLayout(); |
395 } | 401 } |
396 | 402 |
| 403 void RenderText::SetMultiline(bool multiline) { |
| 404 if (multiline != multiline_) { |
| 405 multiline_ = multiline; |
| 406 cached_bounds_and_offset_valid_ = false; |
| 407 lines_.clear(); |
| 408 } |
| 409 } |
| 410 |
397 void RenderText::SetDisplayRect(const Rect& r) { | 411 void RenderText::SetDisplayRect(const Rect& r) { |
398 display_rect_ = r; | 412 display_rect_ = r; |
399 cached_bounds_and_offset_valid_ = false; | 413 cached_bounds_and_offset_valid_ = false; |
| 414 lines_.clear(); |
400 } | 415 } |
401 | 416 |
402 void RenderText::SetCursorPosition(size_t position) { | 417 void RenderText::SetCursorPosition(size_t position) { |
403 MoveCursorTo(position, false); | 418 MoveCursorTo(position, false); |
404 } | 419 } |
405 | 420 |
406 void RenderText::MoveCursor(BreakType break_type, | 421 void RenderText::MoveCursor(BreakType break_type, |
407 VisualCursorDirection direction, | 422 VisualCursorDirection direction, |
408 bool select) { | 423 bool select) { |
409 SelectionModel position(cursor_position(), selection_model_.caret_affinity()); | 424 SelectionModel position(cursor_position(), selection_model_.caret_affinity()); |
(...skipping 269 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
679 canvas->Restore(); | 694 canvas->Restore(); |
680 } | 695 } |
681 | 696 |
682 // Restore saved transparency and selection color. | 697 // Restore saved transparency and selection color. |
683 set_selection_color(saved_selection_color); | 698 set_selection_color(saved_selection_color); |
684 set_background_is_transparent(saved_background_is_transparent); | 699 set_background_is_transparent(saved_background_is_transparent); |
685 } | 700 } |
686 | 701 |
687 Rect RenderText::GetCursorBounds(const SelectionModel& caret, | 702 Rect RenderText::GetCursorBounds(const SelectionModel& caret, |
688 bool insert_mode) { | 703 bool insert_mode) { |
| 704 // TODO(ckocagil): Support multiline. This function should return the height |
| 705 // of the line the cursor is on. |GetStringSize()| now returns |
| 706 // the multiline size, eliminate its use here. |
| 707 |
689 EnsureLayout(); | 708 EnsureLayout(); |
690 | 709 |
691 size_t caret_pos = caret.caret_pos(); | 710 size_t caret_pos = caret.caret_pos(); |
692 DCHECK(IsCursorablePosition(caret_pos)); | 711 DCHECK(IsCursorablePosition(caret_pos)); |
693 // In overtype mode, ignore the affinity and always indicate that we will | 712 // In overtype mode, ignore the affinity and always indicate that we will |
694 // overtype the next character. | 713 // overtype the next character. |
695 LogicalCursorDirection caret_affinity = | 714 LogicalCursorDirection caret_affinity = |
696 insert_mode ? caret.caret_affinity() : CURSOR_FORWARD; | 715 insert_mode ? caret.caret_affinity() : CURSOR_FORWARD; |
697 int x = 0, width = 1; | 716 int x = 0, width = 1; |
698 Size size = GetStringSize(); | 717 Size size = GetStringSize(); |
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
768 selection_color_(kDefaultColor), | 787 selection_color_(kDefaultColor), |
769 selection_background_focused_color_(kDefaultSelectionBackgroundColor), | 788 selection_background_focused_color_(kDefaultSelectionBackgroundColor), |
770 focused_(false), | 789 focused_(false), |
771 composition_range_(ui::Range::InvalidRange()), | 790 composition_range_(ui::Range::InvalidRange()), |
772 colors_(kDefaultColor), | 791 colors_(kDefaultColor), |
773 styles_(NUM_TEXT_STYLES), | 792 styles_(NUM_TEXT_STYLES), |
774 composition_and_selection_styles_applied_(false), | 793 composition_and_selection_styles_applied_(false), |
775 obscured_(false), | 794 obscured_(false), |
776 obscured_reveal_index_(-1), | 795 obscured_reveal_index_(-1), |
777 truncate_length_(0), | 796 truncate_length_(0), |
| 797 multiline_(false), |
778 fade_head_(false), | 798 fade_head_(false), |
779 fade_tail_(false), | 799 fade_tail_(false), |
780 background_is_transparent_(false), | 800 background_is_transparent_(false), |
781 clip_to_display_rect_(true), | 801 clip_to_display_rect_(true), |
782 cached_bounds_and_offset_valid_(false) { | 802 cached_bounds_and_offset_valid_(false) { |
783 } | 803 } |
784 | 804 |
785 const Vector2d& RenderText::GetUpdatedDisplayOffset() { | 805 const Vector2d& RenderText::GetUpdatedDisplayOffset() { |
786 UpdateCachedBoundsAndOffset(); | 806 UpdateCachedBoundsAndOffset(); |
787 return display_offset_; | 807 return display_offset_; |
(...skipping 23 matching lines...) Expand all Loading... |
811 void RenderText::SetSelectionModel(const SelectionModel& model) { | 831 void RenderText::SetSelectionModel(const SelectionModel& model) { |
812 DCHECK_LE(model.selection().GetMax(), text().length()); | 832 DCHECK_LE(model.selection().GetMax(), text().length()); |
813 selection_model_ = model; | 833 selection_model_ = model; |
814 cached_bounds_and_offset_valid_ = false; | 834 cached_bounds_and_offset_valid_ = false; |
815 } | 835 } |
816 | 836 |
817 const base::string16& RenderText::GetLayoutText() const { | 837 const base::string16& RenderText::GetLayoutText() const { |
818 return layout_text_.empty() ? text_ : layout_text_; | 838 return layout_text_.empty() ? text_ : layout_text_; |
819 } | 839 } |
820 | 840 |
| 841 const BreakList<size_t>& RenderText::GetLineBreaks() { |
| 842 if (line_breaks_.max() != 0) |
| 843 return line_breaks_; |
| 844 |
| 845 const string16& layout_text = GetLayoutText(); |
| 846 const size_t text_length = layout_text.length(); |
| 847 line_breaks_.SetValue(0); |
| 848 line_breaks_.SetMax(text_length); |
| 849 base::i18n::BreakIterator iter(layout_text, |
| 850 base::i18n::BreakIterator::BREAK_LINE); |
| 851 const bool success = iter.Init(); |
| 852 DCHECK(success); |
| 853 if (success) { |
| 854 do { |
| 855 line_breaks_.ApplyValue(iter.pos(), ui::Range(iter.pos(), text_length)); |
| 856 } while (iter.Advance()); |
| 857 } |
| 858 return line_breaks_; |
| 859 } |
| 860 |
821 void RenderText::ApplyCompositionAndSelectionStyles() { | 861 void RenderText::ApplyCompositionAndSelectionStyles() { |
822 // Save the underline and color breaks to undo the temporary styles later. | 862 // Save the underline and color breaks to undo the temporary styles later. |
823 DCHECK(!composition_and_selection_styles_applied_); | 863 DCHECK(!composition_and_selection_styles_applied_); |
824 saved_colors_ = colors_; | 864 saved_colors_ = colors_; |
825 saved_underlines_ = styles_[UNDERLINE]; | 865 saved_underlines_ = styles_[UNDERLINE]; |
826 | 866 |
827 // Apply an underline to the composition range in |underlines|. | 867 // Apply an underline to the composition range in |underlines|. |
828 if (composition_range_.IsValid() && !composition_range_.is_empty()) | 868 if (composition_range_.IsValid() && !composition_range_.is_empty()) |
829 styles_[UNDERLINE].ApplyValue(true, composition_range_); | 869 styles_[UNDERLINE].ApplyValue(true, composition_range_); |
830 | 870 |
831 // Apply the selected text color to the [un-reversed] selection range. | 871 // Apply the selected text color to the [un-reversed] selection range. |
832 if (!selection().is_empty()) { | 872 if (!selection().is_empty()) { |
833 const ui::Range range(selection().GetMin(), selection().GetMax()); | 873 const ui::Range range(selection().GetMin(), selection().GetMax()); |
834 colors_.ApplyValue(selection_color_, range); | 874 colors_.ApplyValue(selection_color_, range); |
835 } | 875 } |
836 composition_and_selection_styles_applied_ = true; | 876 composition_and_selection_styles_applied_ = true; |
837 } | 877 } |
838 | 878 |
839 void RenderText::UndoCompositionAndSelectionStyles() { | 879 void RenderText::UndoCompositionAndSelectionStyles() { |
840 // Restore the underline and color breaks to undo the temporary styles. | 880 // Restore the underline and color breaks to undo the temporary styles. |
841 DCHECK(composition_and_selection_styles_applied_); | 881 DCHECK(composition_and_selection_styles_applied_); |
842 colors_ = saved_colors_; | 882 colors_ = saved_colors_; |
843 styles_[UNDERLINE] = saved_underlines_; | 883 styles_[UNDERLINE] = saved_underlines_; |
844 composition_and_selection_styles_applied_ = false; | 884 composition_and_selection_styles_applied_ = false; |
845 } | 885 } |
846 | 886 |
847 Vector2d RenderText::GetTextOffset() { | 887 Vector2d RenderText::GetLineOffset(size_t line_number) { |
848 Vector2d offset = display_rect().OffsetFromOrigin(); | 888 Vector2d offset = display_rect().OffsetFromOrigin(); |
849 offset.Add(GetUpdatedDisplayOffset()); | 889 if (!multiline()) |
850 offset.Add(GetAlignmentOffset()); | 890 offset.Add(GetUpdatedDisplayOffset()); |
| 891 else |
| 892 offset.Add(Vector2d(0, lines_[line_number].preceding_heights)); |
| 893 offset.Add(GetAlignmentOffset(line_number)); |
851 return offset; | 894 return offset; |
852 } | 895 } |
853 | 896 |
854 Point RenderText::ToTextPoint(const Point& point) { | 897 Point RenderText::ToTextPoint(const Point& point) { |
855 return point - GetTextOffset(); | 898 return point - GetLineOffset(0); |
| 899 // TODO(ckocagil): Convert multiline view space points to text space. |
856 } | 900 } |
857 | 901 |
858 Point RenderText::ToViewPoint(const Point& point) { | 902 Point RenderText::ToViewPoint(const Point& point) { |
859 return point + GetTextOffset(); | 903 if (!multiline()) |
| 904 return point + GetLineOffset(0); |
| 905 |
| 906 // TODO(ckocagil): Traverse individual line segments for RTL support. |
| 907 DCHECK(!lines_.empty()); |
| 908 int x = point.x(); |
| 909 size_t line = 0; |
| 910 for (; line < lines_.size() && x > lines_[line].size.width(); ++line) |
| 911 x -= lines_[line].size.width(); |
| 912 return Point(x, point.y()) + GetLineOffset(line); |
860 } | 913 } |
861 | 914 |
862 Vector2d RenderText::GetAlignmentOffset() { | 915 std::vector<Rect> RenderText::TextBoundsToViewBounds(const ui::Range& x) { |
| 916 std::vector<Rect> rects; |
| 917 |
| 918 if (!multiline()) { |
| 919 rects.push_back(Rect(ToViewPoint(Point(x.GetMin(), 0)), |
| 920 Size(x.length(), GetStringSize().height()))); |
| 921 return rects; |
| 922 } |
| 923 |
| 924 EnsureLayout(); |
| 925 |
| 926 // Each line segment keeps its position in text coordinates. Traverse all line |
| 927 // segments and if the segment intersects with the given range, add the view |
| 928 // rect corresponding to the intersection to |rects|. |
| 929 for (size_t line = 0; line < lines_.size(); ++line) { |
| 930 int line_x = 0; |
| 931 const Vector2d offset = GetLineOffset(line); |
| 932 for (size_t i = 0; i < lines_[line].segments.size(); ++i) { |
| 933 const internal::LineSegment* segment = &lines_[line].segments[i]; |
| 934 const ui::Range intersection = segment->x_range.Intersect(x); |
| 935 if (!intersection.is_empty()) { |
| 936 Rect rect(line_x + intersection.start() - segment->x_range.start(), |
| 937 0, intersection.length(), lines_[line].size.height()); |
| 938 rects.push_back(rect + offset); |
| 939 } |
| 940 line_x += segment->x_range.length(); |
| 941 } |
| 942 } |
| 943 |
| 944 return rects; |
| 945 } |
| 946 |
| 947 Vector2d RenderText::GetAlignmentOffset(size_t line_number) { |
| 948 DCHECK_LT(line_number, lines_.size()); |
863 Vector2d offset; | 949 Vector2d offset; |
864 if (horizontal_alignment_ != ALIGN_LEFT) { | 950 if (horizontal_alignment_ != ALIGN_LEFT) { |
865 offset.set_x(display_rect().width() - GetContentWidth()); | 951 const int width = lines_[line_number].size.width() + |
| 952 (cursor_enabled_ ? 1 : 0); |
| 953 offset.set_x(display_rect().width() - width); |
866 if (horizontal_alignment_ == ALIGN_CENTER) | 954 if (horizontal_alignment_ == ALIGN_CENTER) |
867 offset.set_x(offset.x() / 2); | 955 offset.set_x(offset.x() / 2); |
868 } | 956 } |
869 if (vertical_alignment_ != ALIGN_TOP) { | 957 if (vertical_alignment_ != ALIGN_TOP) { |
870 offset.set_y(display_rect().height() - GetStringSize().height()); | 958 offset.set_y(display_rect().height() - GetStringSize().height()); |
871 if (vertical_alignment_ == ALIGN_VCENTER) | 959 if (vertical_alignment_ == ALIGN_VCENTER) |
872 offset.set_y(offset.y() / 2); | 960 offset.set_y(offset.y() / 2); |
873 } | 961 } |
874 return offset; | 962 return offset; |
875 } | 963 } |
876 | 964 |
877 void RenderText::ApplyFadeEffects(internal::SkiaTextRenderer* renderer) { | 965 void RenderText::ApplyFadeEffects(internal::SkiaTextRenderer* renderer) { |
878 if (!fade_head() && !fade_tail()) | 966 if (multiline() || !fade_head() && !fade_tail()) |
879 return; | 967 return; |
880 | 968 |
881 const int text_width = GetStringSize().width(); | |
882 const int display_width = display_rect().width(); | 969 const int display_width = display_rect().width(); |
883 | 970 |
884 // If the text fits as-is, no need to fade. | 971 // If the text fits as-is, no need to fade. |
885 if (text_width <= display_width) | 972 if (GetStringSize().width() <= display_width) |
886 return; | 973 return; |
887 | 974 |
888 int gradient_width = CalculateFadeGradientWidth(GetPrimaryFont(), | 975 int gradient_width = CalculateFadeGradientWidth(GetPrimaryFont(), |
889 display_width); | 976 display_width); |
890 if (gradient_width == 0) | 977 if (gradient_width == 0) |
891 return; | 978 return; |
892 | 979 |
893 bool fade_left = fade_head(); | 980 bool fade_left = fade_head(); |
894 bool fade_right = fade_tail(); | 981 bool fade_right = fade_tail(); |
895 // Under RTL, |fade_right| == |fade_head|. | 982 // Under RTL, |fade_right| == |fade_head|. |
(...skipping 11 matching lines...) Expand all Loading... |
907 left_part.Inset(0, 0, solid_part.width() - gradient_width, 0); | 994 left_part.Inset(0, 0, solid_part.width() - gradient_width, 0); |
908 solid_part.Inset(gradient_width, 0, 0, 0); | 995 solid_part.Inset(gradient_width, 0, 0, 0); |
909 } | 996 } |
910 if (fade_right) { | 997 if (fade_right) { |
911 right_part = solid_part; | 998 right_part = solid_part; |
912 right_part.Inset(solid_part.width() - gradient_width, 0, 0, 0); | 999 right_part.Inset(solid_part.width() - gradient_width, 0, 0, 0); |
913 solid_part.Inset(0, 0, gradient_width, 0); | 1000 solid_part.Inset(0, 0, gradient_width, 0); |
914 } | 1001 } |
915 | 1002 |
916 Rect text_rect = display_rect(); | 1003 Rect text_rect = display_rect(); |
917 text_rect.Inset(GetAlignmentOffset().x(), 0, 0, 0); | 1004 text_rect.Inset(GetAlignmentOffset(0).x(), 0, 0, 0); |
918 | 1005 |
919 // TODO(msw): Use the actual text colors corresponding to each faded part. | 1006 // TODO(msw): Use the actual text colors corresponding to each faded part. |
920 skia::RefPtr<SkShader> shader = CreateFadeShader( | 1007 skia::RefPtr<SkShader> shader = CreateFadeShader( |
921 text_rect, left_part, right_part, colors_.breaks().front().second); | 1008 text_rect, left_part, right_part, colors_.breaks().front().second); |
922 if (shader) | 1009 if (shader) |
923 renderer->SetShader(shader.get(), display_rect()); | 1010 renderer->SetShader(shader.get(), display_rect()); |
924 } | 1011 } |
925 | 1012 |
926 void RenderText::ApplyTextShadows(internal::SkiaTextRenderer* renderer) { | 1013 void RenderText::ApplyTextShadows(internal::SkiaTextRenderer* renderer) { |
927 skia::RefPtr<SkDrawLooper> looper = CreateShadowDrawLooper(text_shadows_); | 1014 skia::RefPtr<SkDrawLooper> looper = CreateShadowDrawLooper(text_shadows_); |
(...skipping 13 matching lines...) Expand all Loading... |
941 void RenderText::MoveCursorTo(size_t position, bool select) { | 1028 void RenderText::MoveCursorTo(size_t position, bool select) { |
942 size_t cursor = std::min(position, text().length()); | 1029 size_t cursor = std::min(position, text().length()); |
943 if (IsCursorablePosition(cursor)) | 1030 if (IsCursorablePosition(cursor)) |
944 SetSelectionModel(SelectionModel( | 1031 SetSelectionModel(SelectionModel( |
945 ui::Range(select ? selection().start() : cursor, cursor), | 1032 ui::Range(select ? selection().start() : cursor, cursor), |
946 (cursor == 0) ? CURSOR_FORWARD : CURSOR_BACKWARD)); | 1033 (cursor == 0) ? CURSOR_FORWARD : CURSOR_BACKWARD)); |
947 } | 1034 } |
948 | 1035 |
949 void RenderText::UpdateLayoutText() { | 1036 void RenderText::UpdateLayoutText() { |
950 layout_text_.clear(); | 1037 layout_text_.clear(); |
| 1038 line_breaks_.SetMax(0); |
951 | 1039 |
952 if (obscured_) { | 1040 if (obscured_) { |
953 size_t obscured_text_length = | 1041 size_t obscured_text_length = |
954 static_cast<size_t>(ui::UTF16IndexToOffset(text_, 0, text_.length())); | 1042 static_cast<size_t>(ui::UTF16IndexToOffset(text_, 0, text_.length())); |
955 layout_text_.assign(obscured_text_length, kPasswordReplacementChar); | 1043 layout_text_.assign(obscured_text_length, kPasswordReplacementChar); |
956 | 1044 |
957 if (obscured_reveal_index_ >= 0 && | 1045 if (obscured_reveal_index_ >= 0 && |
958 obscured_reveal_index_ < static_cast<int>(text_.length())) { | 1046 obscured_reveal_index_ < static_cast<int>(text_.length())) { |
959 // Gets the index range in |text_| to be revealed. | 1047 // Gets the index range in |text_| to be revealed. |
960 size_t start = obscured_reveal_index_; | 1048 size_t start = obscured_reveal_index_; |
(...skipping 16 matching lines...) Expand all Loading... |
977 icu::StringCharacterIterator iter(text.c_str()); | 1065 icu::StringCharacterIterator iter(text.c_str()); |
978 iter.setIndex32(truncate_length_ - 1); | 1066 iter.setIndex32(truncate_length_ - 1); |
979 layout_text_.assign(text.substr(0, iter.getIndex()) + ui::kEllipsisUTF16); | 1067 layout_text_.assign(text.substr(0, iter.getIndex()) + ui::kEllipsisUTF16); |
980 } | 1068 } |
981 } | 1069 } |
982 | 1070 |
983 void RenderText::UpdateCachedBoundsAndOffset() { | 1071 void RenderText::UpdateCachedBoundsAndOffset() { |
984 if (cached_bounds_and_offset_valid_) | 1072 if (cached_bounds_and_offset_valid_) |
985 return; | 1073 return; |
986 | 1074 |
| 1075 // TODO(ckocagil): Add support for scrolling multiline text. |
| 1076 |
987 // First, set the valid flag true to calculate the current cursor bounds using | 1077 // First, set the valid flag true to calculate the current cursor bounds using |
988 // the stale |display_offset_|. Applying |delta_offset| at the end of this | 1078 // the stale |display_offset_|. Applying |delta_offset| at the end of this |
989 // function will set |cursor_bounds_| and |display_offset_| to correct values. | 1079 // function will set |cursor_bounds_| and |display_offset_| to correct values. |
990 cached_bounds_and_offset_valid_ = true; | 1080 cached_bounds_and_offset_valid_ = true; |
991 cursor_bounds_ = GetCursorBounds(selection_model_, insert_mode_); | 1081 cursor_bounds_ = GetCursorBounds(selection_model_, insert_mode_); |
992 | 1082 |
993 // Update |display_offset_| to ensure the current cursor is visible. | 1083 // Update |display_offset_| to ensure the current cursor is visible. |
994 const int display_width = display_rect_.width(); | 1084 const int display_width = display_rect_.width(); |
995 const int content_width = GetContentWidth(); | 1085 const int content_width = GetContentWidth(); |
996 | 1086 |
(...skipping 30 matching lines...) Expand all Loading... |
1027 cursor_bounds_ += delta_offset; | 1117 cursor_bounds_ += delta_offset; |
1028 } | 1118 } |
1029 | 1119 |
1030 void RenderText::DrawSelection(Canvas* canvas) { | 1120 void RenderText::DrawSelection(Canvas* canvas) { |
1031 const std::vector<Rect> sel = GetSubstringBounds(selection()); | 1121 const std::vector<Rect> sel = GetSubstringBounds(selection()); |
1032 for (std::vector<Rect>::const_iterator i = sel.begin(); i < sel.end(); ++i) | 1122 for (std::vector<Rect>::const_iterator i = sel.begin(); i < sel.end(); ++i) |
1033 canvas->FillRect(*i, selection_background_focused_color_); | 1123 canvas->FillRect(*i, selection_background_focused_color_); |
1034 } | 1124 } |
1035 | 1125 |
1036 } // namespace gfx | 1126 } // namespace gfx |
OLD | NEW |