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