Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(29)

Side by Side Diff: ui/gfx/render_text.cc

Issue 16867016: Windows implementation of multiline RenderText (Closed) Base URL: http://git.chromium.org/chromium/src.git@master
Patch Set: fix ComputeLines and rects Created 7 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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 288 matching lines...) Expand 10 before | Expand all | Expand 10 after
299 style_[i] = styles_[i].GetBreak(position); 299 style_[i] = styles_[i].GetBreak(position);
300 } 300 }
301 301
302 } // namespace internal 302 } // namespace internal
303 303
304 RenderText::~RenderText() { 304 RenderText::~RenderText() {
305 } 305 }
306 306
307 void RenderText::SetText(const base::string16& text) { 307 void RenderText::SetText(const base::string16& text) {
308 DCHECK(!composition_range_.IsValid()); 308 DCHECK(!composition_range_.IsValid());
309 if (text_ == text)
310 return;
309 text_ = text; 311 text_ = text;
310 312
313 // TODO: we might be displaying obscured_text... also move somewhere better.
Alexei Svitkine (slow) 2013/07/09 15:35:13 I think this should be done at the end of UpdateLa
ckocagil 2013/07/13 16:05:10 Done.
314 line_breaks_.clear();
315 base::i18n::BreakIterator iter(text_, base::i18n::BreakIterator::BREAK_LINE);
316 bool success = iter.Init();
317 CHECK(success);
318 do {
319 line_breaks_.push_back(iter.pos());
320 } while (iter.Advance());
321
311 // Adjust ranged styles and colors to accommodate a new text length. 322 // Adjust ranged styles and colors to accommodate a new text length.
312 const size_t text_length = text_.length(); 323 const size_t text_length = text_.length();
313 colors_.SetMax(text_length); 324 colors_.SetMax(text_length);
314 for (size_t style = 0; style < NUM_TEXT_STYLES; ++style) 325 for (size_t style = 0; style < NUM_TEXT_STYLES; ++style)
315 styles_[style].SetMax(text_length); 326 styles_[style].SetMax(text_length);
316 cached_bounds_and_offset_valid_ = false; 327 cached_bounds_and_offset_valid_ = false;
317 328
318 // Reset selection model. SetText should always followed by SetSelectionModel 329 // Reset selection model. SetText should always followed by SetSelectionModel
319 // or SetCursorPosition in upper layer. 330 // or SetCursorPosition in upper layer.
320 SetSelectionModel(SelectionModel()); 331 SetSelectionModel(SelectionModel());
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after
390 401
391 obscured_reveal_index_ = index; 402 obscured_reveal_index_ = index;
392 cached_bounds_and_offset_valid_ = false; 403 cached_bounds_and_offset_valid_ = false;
393 UpdateObscuredText(); 404 UpdateObscuredText();
394 ResetLayout(); 405 ResetLayout();
395 } 406 }
396 407
397 void RenderText::SetDisplayRect(const Rect& r) { 408 void RenderText::SetDisplayRect(const Rect& r) {
398 display_rect_ = r; 409 display_rect_ = r;
399 cached_bounds_and_offset_valid_ = false; 410 cached_bounds_and_offset_valid_ = false;
411 lines_valid_ = false;
400 } 412 }
401 413
402 void RenderText::SetCursorPosition(size_t position) { 414 void RenderText::SetCursorPosition(size_t position) {
403 MoveCursorTo(position, false); 415 MoveCursorTo(position, false);
404 } 416 }
405 417
406 void RenderText::MoveCursor(BreakType break_type, 418 void RenderText::MoveCursor(BreakType break_type,
407 VisualCursorDirection direction, 419 VisualCursorDirection direction,
408 bool select) { 420 bool select) {
409 SelectionModel position(cursor_position(), selection_model_.caret_affinity()); 421 SelectionModel position(cursor_position(), selection_model_.caret_affinity());
(...skipping 286 matching lines...) Expand 10 before | Expand all | Expand 10 after
696 if (insert_mode) { 708 if (insert_mode) {
697 x = (caret_affinity == CURSOR_BACKWARD) ? xspan.end() : xspan.start(); 709 x = (caret_affinity == CURSOR_BACKWARD) ? xspan.end() : xspan.start();
698 } else { // overtype mode 710 } else { // overtype mode
699 x = xspan.GetMin(); 711 x = xspan.GetMin();
700 width = xspan.length(); 712 width = xspan.length();
701 } 713 }
702 } 714 }
703 return Rect(ToViewPoint(Point(x, 0)), Size(width, size.height())); 715 return Rect(ToViewPoint(Point(x, 0)), Size(width, size.height()));
704 } 716 }
705 717
718 std::vector<Rect> RenderText::RangeToViewRects(const ui::Range& x, int y) {
719 std::vector<Rect> rects;
720
721 int height = GetStringSize().height();
msw 2013/07/10 04:01:56 This is fine for the single line case, but each li
ckocagil 2013/07/13 16:05:10 Done.
722
723 if (!multiline()) {
724 Point start(x.GetMin(), y);
725 rects.push_back(Rect(ToViewPoint(start), Size(x.length(), height)));
726 return rects;
727 }
728
729 EnsureLayout();
730 ComputeLines();
msw 2013/07/10 04:01:56 EnsureLayout should ComputeLines as needed, don't
ckocagil 2013/07/13 16:05:10 Done.
731
732 for (size_t line = 0; line < lines().size(); ++line) {
msw 2013/07/10 04:01:56 Add a comment to explain what's happening here, it
ckocagil 2013/07/13 16:05:10 Done.
733 int line_x = 0;
734 for (size_t i = 0; i < lines()[line].size(); ++i) {
735 const internal::LineSegment* segment = lines()[line][i];
736 ui::Range intersection = segment->x_pos.Intersect(x);
737 if (!intersection.is_empty()) {
738 Rect rect(line_x + intersection.start() - segment->x_pos.start(),
739 y + line * height, intersection.length(), height);
msw 2013/07/10 04:01:56 You need to use the proper per-line heights; at le
ckocagil 2013/07/13 16:05:10 Done, it uses per-line heights now.
740 rect += GetTextOffset(LineWidth(line));
msw 2013/07/10 04:01:56 Cache the line's offset in the outer loop.
ckocagil 2013/07/13 16:05:10 Done.
741 rects.push_back(rect);
742 }
743 line_x += segment->x_pos.length();
744 }
745 }
746
747 return rects;
748 }
749
706 const Rect& RenderText::GetUpdatedCursorBounds() { 750 const Rect& RenderText::GetUpdatedCursorBounds() {
707 UpdateCachedBoundsAndOffset(); 751 UpdateCachedBoundsAndOffset();
708 return cursor_bounds_; 752 return cursor_bounds_;
709 } 753 }
710 754
711 size_t RenderText::IndexOfAdjacentGrapheme(size_t index, 755 size_t RenderText::IndexOfAdjacentGrapheme(size_t index,
712 LogicalCursorDirection direction) { 756 LogicalCursorDirection direction) {
713 if (index > text().length()) 757 if (index > text().length())
714 return text().length(); 758 return text().length();
715 759
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after
756 selection_color_(kDefaultColor), 800 selection_color_(kDefaultColor),
757 selection_background_focused_color_(kDefaultSelectionBackgroundColor), 801 selection_background_focused_color_(kDefaultSelectionBackgroundColor),
758 selection_background_unfocused_color_(kDefaultSelectionBackgroundColor), 802 selection_background_unfocused_color_(kDefaultSelectionBackgroundColor),
759 focused_(false), 803 focused_(false),
760 composition_range_(ui::Range::InvalidRange()), 804 composition_range_(ui::Range::InvalidRange()),
761 colors_(kDefaultColor), 805 colors_(kDefaultColor),
762 styles_(NUM_TEXT_STYLES), 806 styles_(NUM_TEXT_STYLES),
763 composition_and_selection_styles_applied_(false), 807 composition_and_selection_styles_applied_(false),
764 obscured_(false), 808 obscured_(false),
765 obscured_reveal_index_(-1), 809 obscured_reveal_index_(-1),
810 multiline_(false),
766 fade_head_(false), 811 fade_head_(false),
767 fade_tail_(false), 812 fade_tail_(false),
768 background_is_transparent_(false), 813 background_is_transparent_(false),
769 clip_to_display_rect_(true), 814 clip_to_display_rect_(true),
770 cached_bounds_and_offset_valid_(false) { 815 cached_bounds_and_offset_valid_(false),
816 lines_valid_(false) {
771 } 817 }
772 818
773 const Vector2d& RenderText::GetUpdatedDisplayOffset() { 819 const Vector2d& RenderText::GetUpdatedDisplayOffset() {
774 UpdateCachedBoundsAndOffset(); 820 UpdateCachedBoundsAndOffset();
775 return display_offset_; 821 return display_offset_;
776 } 822 }
777 823
778 SelectionModel RenderText::GetAdjacentSelectionModel( 824 SelectionModel RenderText::GetAdjacentSelectionModel(
779 const SelectionModel& current, 825 const SelectionModel& current,
780 BreakType break_type, 826 BreakType break_type,
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after
825 } 871 }
826 872
827 void RenderText::UndoCompositionAndSelectionStyles() { 873 void RenderText::UndoCompositionAndSelectionStyles() {
828 // Restore the underline and color breaks to undo the temporary styles. 874 // Restore the underline and color breaks to undo the temporary styles.
829 DCHECK(composition_and_selection_styles_applied_); 875 DCHECK(composition_and_selection_styles_applied_);
830 colors_ = saved_colors_; 876 colors_ = saved_colors_;
831 styles_[UNDERLINE] = saved_underlines_; 877 styles_[UNDERLINE] = saved_underlines_;
832 composition_and_selection_styles_applied_ = false; 878 composition_and_selection_styles_applied_ = false;
833 } 879 }
834 880
835 Vector2d RenderText::GetTextOffset() { 881 Vector2d RenderText::GetTextOffset(int line_width) {
836 Vector2d offset = display_rect().OffsetFromOrigin(); 882 Vector2d offset = display_rect().OffsetFromOrigin();
837 offset.Add(GetUpdatedDisplayOffset()); 883 if (!multiline())
msw 2013/07/10 04:01:56 Why ignore the display offset for multi-line? Even
ckocagil 2013/07/13 16:05:10 I ignored it for now because multi-line vertical s
838 offset.Add(GetAlignmentOffset()); 884 offset.Add(GetUpdatedDisplayOffset());
885 offset.Add(GetAlignmentOffset(line_width));
839 return offset; 886 return offset;
840 } 887 }
841 888
842 Point RenderText::ToTextPoint(const Point& point) { 889 Point RenderText::ToTextPoint(const Point& point) {
843 return point - GetTextOffset(); 890 return point - GetTextOffset(GetContentWidth());
891 // TODO: implement multiline
Alexei Svitkine (slow) 2013/07/09 15:35:13 TODO(ckocagil)
ckocagil 2013/07/13 16:05:10 Done.
844 } 892 }
845 893
846 Point RenderText::ToViewPoint(const Point& point) { 894 Point RenderText::ToViewPoint(const Point& point) {
847 return point + GetTextOffset(); 895 if (!multiline())
896 return point + GetTextOffset(GetContentWidth());
897
898 ComputeLines();
msw 2013/07/10 04:01:56 Don't explicitly call this here, EnsureLayout or [
ckocagil 2013/07/13 16:05:10 Done.
899 int x = point.x();
900 unsigned int line = 0;
901 while (line < lines_.size() && x > LineWidth(line)) {
902 x -= LineWidth(line);
Alexei Svitkine (slow) 2013/07/09 15:35:13 Can you refactor this code to not call LineWidth()
ckocagil 2013/07/13 16:05:10 I will rewrite this method to support RTL soon (be
903 ++line;
904 }
905 return Point(x, point.y() + line * GetStringSize().height()) +
msw 2013/07/10 04:01:56 Again, this needs per-line heights.
ckocagil 2013/07/13 16:05:10 Done.
906 GetTextOffset(LineWidth(line));
848 } 907 }
849 908
850 Vector2d RenderText::GetAlignmentOffset() { 909 Vector2d RenderText::GetAlignmentOffset(int line_width) {
910
msw 2013/07/10 04:01:56 nit: remove blank line.
ckocagil 2013/07/13 16:05:10 Done.
851 Vector2d offset; 911 Vector2d offset;
852 if (horizontal_alignment_ != ALIGN_LEFT) { 912 if (horizontal_alignment_ != ALIGN_LEFT) {
853 offset.set_x(display_rect().width() - GetContentWidth()); 913 offset.set_x(display_rect().width() - (multiline() ? line_width
msw 2013/07/10 04:01:56 Always use |line_width|, you pass in GetContentWid
ckocagil 2013/07/13 16:05:10 I now pass 0 for single-line mode. Single-line mod
914 : GetContentWidth()));
854 if (horizontal_alignment_ == ALIGN_CENTER) 915 if (horizontal_alignment_ == ALIGN_CENTER)
855 offset.set_x(offset.x() / 2); 916 offset.set_x(offset.x() / 2);
856 } 917 }
857 if (vertical_alignment_ != ALIGN_TOP) { 918 if (vertical_alignment_ != ALIGN_TOP) {
858 offset.set_y(display_rect().height() - GetStringSize().height()); 919 offset.set_y(display_rect().height() - GetMultilineTextSize().height());
859 if (vertical_alignment_ == ALIGN_VCENTER) 920 if (vertical_alignment_ == ALIGN_VCENTER)
860 offset.set_y(offset.y() / 2); 921 offset.set_y(offset.y() / 2);
861 } 922 }
862 return offset; 923 return offset;
863 } 924 }
864 925
865 void RenderText::ApplyFadeEffects(internal::SkiaTextRenderer* renderer) { 926 void RenderText::ApplyFadeEffects(internal::SkiaTextRenderer* renderer) {
866 if (!fade_head() && !fade_tail()) 927 if (!fade_head() && !fade_tail())
867 return; 928 return;
868 929
(...skipping 25 matching lines...) Expand all
894 left_part.Inset(0, 0, solid_part.width() - gradient_width, 0); 955 left_part.Inset(0, 0, solid_part.width() - gradient_width, 0);
895 solid_part.Inset(gradient_width, 0, 0, 0); 956 solid_part.Inset(gradient_width, 0, 0, 0);
896 } 957 }
897 if (fade_right) { 958 if (fade_right) {
898 right_part = solid_part; 959 right_part = solid_part;
899 right_part.Inset(solid_part.width() - gradient_width, 0, 0, 0); 960 right_part.Inset(solid_part.width() - gradient_width, 0, 0, 0);
900 solid_part.Inset(0, 0, gradient_width, 0); 961 solid_part.Inset(0, 0, gradient_width, 0);
901 } 962 }
902 963
903 Rect text_rect = display_rect(); 964 Rect text_rect = display_rect();
904 text_rect.Inset(GetAlignmentOffset().x(), 0, 0, 0); 965 text_rect.Inset(GetAlignmentOffset(GetContentWidth()).x(), 0, 0, 0);
905 966
906 // TODO(msw): Use the actual text colors corresponding to each faded part. 967 // TODO(msw): Use the actual text colors corresponding to each faded part.
907 skia::RefPtr<SkShader> shader = CreateFadeShader( 968 skia::RefPtr<SkShader> shader = CreateFadeShader(
908 text_rect, left_part, right_part, colors_.breaks().front().second); 969 text_rect, left_part, right_part, colors_.breaks().front().second);
909 if (shader) 970 if (shader)
910 renderer->SetShader(shader.get(), display_rect()); 971 renderer->SetShader(shader.get(), display_rect());
911 } 972 }
912 973
913 void RenderText::ApplyTextShadows(internal::SkiaTextRenderer* renderer) { 974 void RenderText::ApplyTextShadows(internal::SkiaTextRenderer* renderer) {
914 skia::RefPtr<SkDrawLooper> looper = CreateShadowDrawLooper(text_shadows_); 975 skia::RefPtr<SkDrawLooper> looper = CreateShadowDrawLooper(text_shadows_);
(...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after
1007 void RenderText::DrawSelection(Canvas* canvas) { 1068 void RenderText::DrawSelection(Canvas* canvas) {
1008 const SkColor color = focused() ? 1069 const SkColor color = focused() ?
1009 selection_background_focused_color_ : 1070 selection_background_focused_color_ :
1010 selection_background_unfocused_color_; 1071 selection_background_unfocused_color_;
1011 const std::vector<Rect> sel = GetSubstringBounds(selection()); 1072 const std::vector<Rect> sel = GetSubstringBounds(selection());
1012 for (std::vector<Rect>::const_iterator i = sel.begin(); i < sel.end(); ++i) 1073 for (std::vector<Rect>::const_iterator i = sel.begin(); i < sel.end(); ++i)
1013 canvas->FillRect(*i, color); 1074 canvas->FillRect(*i, color);
1014 } 1075 }
1015 1076
1016 } // namespace gfx 1077 } // namespace gfx
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698