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

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

Issue 17745005: Clamp RenderTextWin layout length to 10,000 code points. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Resolve string formatting; you just can't please some compilers. 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 | Annotate | Revision Log
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"
11 #include "base/stl_util.h" 11 #include "base/stl_util.h"
12 #include "third_party/icu/public/common/unicode/rbbi.h"
12 #include "third_party/icu/public/common/unicode/utf16.h" 13 #include "third_party/icu/public/common/unicode/utf16.h"
13 #include "third_party/skia/include/core/SkTypeface.h" 14 #include "third_party/skia/include/core/SkTypeface.h"
14 #include "third_party/skia/include/effects/SkGradientShader.h" 15 #include "third_party/skia/include/effects/SkGradientShader.h"
16 #include "ui/base/text/text_elider.h"
15 #include "ui/base/text/utf16_indexing.h" 17 #include "ui/base/text/utf16_indexing.h"
16 #include "ui/gfx/canvas.h" 18 #include "ui/gfx/canvas.h"
17 #include "ui/gfx/insets.h" 19 #include "ui/gfx/insets.h"
18 #include "ui/gfx/skia_util.h" 20 #include "ui/gfx/skia_util.h"
19 #include "ui/gfx/text_constants.h" 21 #include "ui/gfx/text_constants.h"
20 22
21 namespace gfx { 23 namespace gfx {
22 24
23 namespace { 25 namespace {
24 26
(...skipping 292 matching lines...) Expand 10 before | Expand all | Expand 10 after
317 319
318 // Reset selection model. SetText should always followed by SetSelectionModel 320 // Reset selection model. SetText should always followed by SetSelectionModel
319 // or SetCursorPosition in upper layer. 321 // or SetCursorPosition in upper layer.
320 SetSelectionModel(SelectionModel()); 322 SetSelectionModel(SelectionModel());
321 323
322 // Invalidate the cached text direction if it depends on the text contents. 324 // Invalidate the cached text direction if it depends on the text contents.
323 if (directionality_mode_ == DIRECTIONALITY_FROM_TEXT) 325 if (directionality_mode_ == DIRECTIONALITY_FROM_TEXT)
324 text_direction_ = base::i18n::UNKNOWN_DIRECTION; 326 text_direction_ = base::i18n::UNKNOWN_DIRECTION;
325 327
326 obscured_reveal_index_ = -1; 328 obscured_reveal_index_ = -1;
327 UpdateObscuredText(); 329 UpdateLayoutText();
328 ResetLayout(); 330 ResetLayout();
329 } 331 }
330 332
331 void RenderText::SetHorizontalAlignment(HorizontalAlignment alignment) { 333 void RenderText::SetHorizontalAlignment(HorizontalAlignment alignment) {
332 if (horizontal_alignment_ != alignment) { 334 if (horizontal_alignment_ != alignment) {
333 horizontal_alignment_ = alignment; 335 horizontal_alignment_ = alignment;
334 display_offset_ = Vector2d(); 336 display_offset_ = Vector2d();
335 cached_bounds_and_offset_valid_ = false; 337 cached_bounds_and_offset_valid_ = false;
336 } 338 }
337 } 339 }
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
372 void RenderText::ToggleInsertMode() { 374 void RenderText::ToggleInsertMode() {
373 insert_mode_ = !insert_mode_; 375 insert_mode_ = !insert_mode_;
374 cached_bounds_and_offset_valid_ = false; 376 cached_bounds_and_offset_valid_ = false;
375 } 377 }
376 378
377 void RenderText::SetObscured(bool obscured) { 379 void RenderText::SetObscured(bool obscured) {
378 if (obscured != obscured_) { 380 if (obscured != obscured_) {
379 obscured_ = obscured; 381 obscured_ = obscured;
380 obscured_reveal_index_ = -1; 382 obscured_reveal_index_ = -1;
381 cached_bounds_and_offset_valid_ = false; 383 cached_bounds_and_offset_valid_ = false;
382 UpdateObscuredText(); 384 UpdateLayoutText();
383 ResetLayout(); 385 ResetLayout();
384 } 386 }
385 } 387 }
386 388
387 void RenderText::SetObscuredRevealIndex(int index) { 389 void RenderText::SetObscuredRevealIndex(int index) {
388 if (obscured_reveal_index_ == index) 390 if (obscured_reveal_index_ == index)
389 return; 391 return;
390 392
391 obscured_reveal_index_ = index; 393 obscured_reveal_index_ = index;
392 cached_bounds_and_offset_valid_ = false; 394 cached_bounds_and_offset_valid_ = false;
393 UpdateObscuredText(); 395 UpdateLayoutText();
394 ResetLayout(); 396 ResetLayout();
395 } 397 }
396 398
397 void RenderText::SetDisplayRect(const Rect& r) { 399 void RenderText::SetDisplayRect(const Rect& r) {
398 display_rect_ = r; 400 display_rect_ = r;
399 cached_bounds_and_offset_valid_ = false; 401 cached_bounds_and_offset_valid_ = false;
400 } 402 }
401 403
402 void RenderText::SetCursorPosition(size_t position) { 404 void RenderText::SetCursorPosition(size_t position) {
403 MoveCursorTo(position, false); 405 MoveCursorTo(position, false);
(...skipping 298 matching lines...) Expand 10 before | Expand all | Expand 10 after
702 } 704 }
703 return Rect(ToViewPoint(Point(x, 0)), Size(width, size.height())); 705 return Rect(ToViewPoint(Point(x, 0)), Size(width, size.height()));
704 } 706 }
705 707
706 const Rect& RenderText::GetUpdatedCursorBounds() { 708 const Rect& RenderText::GetUpdatedCursorBounds() {
707 UpdateCachedBoundsAndOffset(); 709 UpdateCachedBoundsAndOffset();
708 return cursor_bounds_; 710 return cursor_bounds_;
709 } 711 }
710 712
711 size_t RenderText::IndexOfAdjacentGrapheme(size_t index, 713 size_t RenderText::IndexOfAdjacentGrapheme(size_t index,
712 LogicalCursorDirection direction) { 714 LogicalCursorDirection direction) {
713 if (index > text().length()) 715 if (index > text().length())
714 return text().length(); 716 return text().length();
715 717
716 EnsureLayout(); 718 EnsureLayout();
717 719
718 if (direction == CURSOR_FORWARD) { 720 if (direction == CURSOR_FORWARD) {
719 while (index < text().length()) { 721 while (index < text().length()) {
720 index++; 722 index++;
721 if (IsCursorablePosition(index)) 723 if (IsCursorablePosition(index))
722 return index; 724 return index;
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
756 selection_color_(kDefaultColor), 758 selection_color_(kDefaultColor),
757 selection_background_focused_color_(kDefaultSelectionBackgroundColor), 759 selection_background_focused_color_(kDefaultSelectionBackgroundColor),
758 selection_background_unfocused_color_(kDefaultSelectionBackgroundColor), 760 selection_background_unfocused_color_(kDefaultSelectionBackgroundColor),
759 focused_(false), 761 focused_(false),
760 composition_range_(ui::Range::InvalidRange()), 762 composition_range_(ui::Range::InvalidRange()),
761 colors_(kDefaultColor), 763 colors_(kDefaultColor),
762 styles_(NUM_TEXT_STYLES), 764 styles_(NUM_TEXT_STYLES),
763 composition_and_selection_styles_applied_(false), 765 composition_and_selection_styles_applied_(false),
764 obscured_(false), 766 obscured_(false),
765 obscured_reveal_index_(-1), 767 obscured_reveal_index_(-1),
768 truncate_length_(0),
766 fade_head_(false), 769 fade_head_(false),
767 fade_tail_(false), 770 fade_tail_(false),
768 background_is_transparent_(false), 771 background_is_transparent_(false),
769 clip_to_display_rect_(true), 772 clip_to_display_rect_(true),
770 cached_bounds_and_offset_valid_(false) { 773 cached_bounds_and_offset_valid_(false) {
771 } 774 }
772 775
773 const Vector2d& RenderText::GetUpdatedDisplayOffset() { 776 const Vector2d& RenderText::GetUpdatedDisplayOffset() {
774 UpdateCachedBoundsAndOffset(); 777 UpdateCachedBoundsAndOffset();
775 return display_offset_; 778 return display_offset_;
(...skipping 20 matching lines...) Expand all
796 return SelectionModel(0, CURSOR_BACKWARD); 799 return SelectionModel(0, CURSOR_BACKWARD);
797 } 800 }
798 801
799 void RenderText::SetSelectionModel(const SelectionModel& model) { 802 void RenderText::SetSelectionModel(const SelectionModel& model) {
800 DCHECK_LE(model.selection().GetMax(), text().length()); 803 DCHECK_LE(model.selection().GetMax(), text().length());
801 selection_model_ = model; 804 selection_model_ = model;
802 cached_bounds_and_offset_valid_ = false; 805 cached_bounds_and_offset_valid_ = false;
803 } 806 }
804 807
805 const base::string16& RenderText::GetLayoutText() const { 808 const base::string16& RenderText::GetLayoutText() const {
806 return obscured() ? obscured_text_ : text(); 809 return layout_text_.empty() ? text_ : layout_text_;
807 } 810 }
808 811
809 void RenderText::ApplyCompositionAndSelectionStyles() { 812 void RenderText::ApplyCompositionAndSelectionStyles() {
810 // Save the underline and color breaks to undo the temporary styles later. 813 // Save the underline and color breaks to undo the temporary styles later.
811 DCHECK(!composition_and_selection_styles_applied_); 814 DCHECK(!composition_and_selection_styles_applied_);
812 saved_colors_ = colors_; 815 saved_colors_ = colors_;
813 saved_underlines_ = styles_[UNDERLINE]; 816 saved_underlines_ = styles_[UNDERLINE];
814 817
815 // Apply an underline to the composition range in |underlines|. 818 // Apply an underline to the composition range in |underlines|.
816 if (composition_range_.IsValid() && !composition_range_.is_empty()) 819 if (composition_range_.IsValid() && !composition_range_.is_empty())
(...skipping 109 matching lines...) Expand 10 before | Expand all | Expand 10 after
926 } 929 }
927 930
928 void RenderText::MoveCursorTo(size_t position, bool select) { 931 void RenderText::MoveCursorTo(size_t position, bool select) {
929 size_t cursor = std::min(position, text().length()); 932 size_t cursor = std::min(position, text().length());
930 if (IsCursorablePosition(cursor)) 933 if (IsCursorablePosition(cursor))
931 SetSelectionModel(SelectionModel( 934 SetSelectionModel(SelectionModel(
932 ui::Range(select ? selection().start() : cursor, cursor), 935 ui::Range(select ? selection().start() : cursor, cursor),
933 (cursor == 0) ? CURSOR_FORWARD : CURSOR_BACKWARD)); 936 (cursor == 0) ? CURSOR_FORWARD : CURSOR_BACKWARD));
934 } 937 }
935 938
936 void RenderText::UpdateObscuredText() { 939 void RenderText::UpdateLayoutText() {
937 if (!obscured_) 940 layout_text_.clear();
938 return;
939 941
940 const size_t obscured_text_length = 942 if (obscured_) {
941 static_cast<size_t>(ui::UTF16IndexToOffset(text_, 0, text_.length())); 943 size_t obscured_text_length =
942 obscured_text_.assign(obscured_text_length, kPasswordReplacementChar); 944 static_cast<size_t>(ui::UTF16IndexToOffset(text_, 0, text_.length()));
945 layout_text_.assign(obscured_text_length, kPasswordReplacementChar);
943 946
944 if (obscured_reveal_index_ >= 0 && 947 if (obscured_reveal_index_ >= 0 &&
945 obscured_reveal_index_ < static_cast<int>(text_.length())) { 948 obscured_reveal_index_ < static_cast<int>(text_.length())) {
946 // Gets the index range in |text_| to be revealed. 949 // Gets the index range in |text_| to be revealed.
947 size_t start = obscured_reveal_index_; 950 size_t start = obscured_reveal_index_;
948 U16_SET_CP_START(text_.data(), 0, start); 951 U16_SET_CP_START(text_.data(), 0, start);
949 size_t end = start; 952 size_t end = start;
950 UChar32 unused_char; 953 UChar32 unused_char;
951 U16_NEXT(text_.data(), end, text_.length(), unused_char); 954 U16_NEXT(text_.data(), end, text_.length(), unused_char);
952 955
953 // Gets the index in |obscured_text_| to be replaced. 956 // Gets the index in |layout_text_| to be replaced.
954 const size_t cp_start = 957 const size_t cp_start =
955 static_cast<size_t>(ui::UTF16IndexToOffset(text_, 0, start)); 958 static_cast<size_t>(ui::UTF16IndexToOffset(text_, 0, start));
956 obscured_text_.replace(cp_start, 1, text_.substr(start, end - start)); 959 if (layout_text_.length() > cp_start)
960 layout_text_.replace(cp_start, 1, text_.substr(start, end - start));
961 }
962 }
963
964 const base::string16& text = obscured_ ? layout_text_ : text_;
965 if (truncate_length_ > 0 && truncate_length_ < text.length()) {
966 // Truncate the text at a valid character break and append an ellipsis.
967 icu::StringCharacterIterator iter(text.c_str());
968 iter.setIndex32(truncate_length_ - 1);
969 layout_text_.assign(text.substr(0, iter.getIndex()) + ui::kEllipsisUTF16);
957 } 970 }
958 } 971 }
959 972
960 void RenderText::UpdateCachedBoundsAndOffset() { 973 void RenderText::UpdateCachedBoundsAndOffset() {
961 if (cached_bounds_and_offset_valid_) 974 if (cached_bounds_and_offset_valid_)
962 return; 975 return;
963 976
964 // First, set the valid flag true to calculate the current cursor bounds using 977 // First, set the valid flag true to calculate the current cursor bounds using
965 // the stale |display_offset_|. Applying |delta_offset| at the end of this 978 // the stale |display_offset_|. Applying |delta_offset| at the end of this
966 // function will set |cursor_bounds_| and |display_offset_| to correct values. 979 // function will set |cursor_bounds_| and |display_offset_| to correct values.
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after
1007 void RenderText::DrawSelection(Canvas* canvas) { 1020 void RenderText::DrawSelection(Canvas* canvas) {
1008 const SkColor color = focused() ? 1021 const SkColor color = focused() ?
1009 selection_background_focused_color_ : 1022 selection_background_focused_color_ :
1010 selection_background_unfocused_color_; 1023 selection_background_unfocused_color_;
1011 const std::vector<Rect> sel = GetSubstringBounds(selection()); 1024 const std::vector<Rect> sel = GetSubstringBounds(selection());
1012 for (std::vector<Rect>::const_iterator i = sel.begin(); i < sel.end(); ++i) 1025 for (std::vector<Rect>::const_iterator i = sel.begin(); i < sel.end(); ++i)
1013 canvas->FillRect(*i, color); 1026 canvas->FillRect(*i, color);
1014 } 1027 }
1015 1028
1016 } // namespace gfx 1029 } // namespace gfx
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698