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

Side by Side Diff: ui/base/text/text_elider.cc

Issue 13846005: Fix infinite loop caused by ElideText() (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: fix android failure Created 7 years, 7 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 // This file implements utility functions for eliding and formatting UI text. 5 // This file implements utility functions for eliding and formatting UI text.
6 // 6 //
7 // Note that several of the functions declared in text_elider.h are implemented 7 // Note that several of the functions declared in text_elider.h are implemented
8 // in this file using helper classes in an unnamed namespace. 8 // in this file using helper classes in an unnamed namespace.
9 9
10 #include "ui/base/text/text_elider.h" 10 #include "ui/base/text/text_elider.h"
(...skipping 30 matching lines...) Expand all
41 class StringSlicer { 41 class StringSlicer {
42 public: 42 public:
43 StringSlicer(const string16& text, 43 StringSlicer(const string16& text,
44 const string16& ellipsis, 44 const string16& ellipsis,
45 bool elide_in_middle) 45 bool elide_in_middle)
46 : text_(text), 46 : text_(text),
47 ellipsis_(ellipsis), 47 ellipsis_(ellipsis),
48 elide_in_middle_(elide_in_middle) { 48 elide_in_middle_(elide_in_middle) {
49 } 49 }
50 50
51 // Cuts |text_| to be |length| characters long. If |cut_in_middle_| is true, 51 // Cuts |text_| to be |length| characters long. If |elide_in_middle_| is true,
52 // the middle of the string is removed to leave equal-length pieces from the 52 // the middle of the string is removed to leave equal-length pieces from the
53 // beginning and end of the string; otherwise, the end of the string is 53 // beginning and end of the string; otherwise, the end of the string is
54 // removed and only the beginning remains. If |insert_ellipsis| is true, 54 // removed and only the beginning remains. If |insert_ellipsis| is true,
55 // then an ellipsis character will by inserted at the cut point. 55 // then an ellipsis character will be inserted at the cut point.
56 string16 CutString(size_t length, bool insert_ellipsis) { 56 string16 CutString(size_t length, bool insert_ellipsis) {
57 const string16 ellipsis_text = insert_ellipsis ? ellipsis_ : string16(); 57 const string16 ellipsis_text = insert_ellipsis ? ellipsis_ : string16();
58 58
59 if (!elide_in_middle_) 59 if (!elide_in_middle_)
60 return text_.substr(0, FindValidBoundaryBefore(length)) + ellipsis_text; 60 return text_.substr(0, FindValidBoundaryBefore(length)) + ellipsis_text;
61 61
62 // We put the extra character, if any, before the cut. 62 // We put the extra character, if any, before the cut.
63 const size_t half_length = length / 2; 63 const size_t half_length = length / 2;
64 const size_t prefix_length = FindValidBoundaryBefore(length - half_length); 64 const size_t prefix_length = FindValidBoundaryBefore(length - half_length);
65 const size_t suffix_start_guess = text_.length() - half_length; 65 const size_t suffix_start_guess = text_.length() - half_length;
(...skipping 405 matching lines...) Expand 10 before | Expand all | Expand 10 after
471 // (eliding way too much from a ridiculous string is probably still 471 // (eliding way too much from a ridiculous string is probably still
472 // ridiculous), but we should check other widths for bogus values as well. 472 // ridiculous), but we should check other widths for bogus values as well.
473 if (current_text_pixel_width <= 0 && !text.empty()) { 473 if (current_text_pixel_width <= 0 && !text.empty()) {
474 const string16 cut = slicer.CutString(text.length() / 2, false); 474 const string16 cut = slicer.CutString(text.length() / 2, false);
475 return ElideText(cut, font, available_pixel_width, elide_behavior); 475 return ElideText(cut, font, available_pixel_width, elide_behavior);
476 } 476 }
477 477
478 if (current_text_pixel_width <= available_pixel_width) 478 if (current_text_pixel_width <= available_pixel_width)
479 return text; 479 return text;
480 480
481 if (font.GetStringWidth(kEllipsisUTF16) > available_pixel_width) 481 if (insert_ellipsis &&
482 font.GetStringWidth(kEllipsisUTF16) > available_pixel_width)
482 return string16(); 483 return string16();
483 484
484 // Use binary search to compute the elided text. 485 // Use binary search to compute the elided text.
485 size_t lo = 0; 486 size_t lo = 0;
486 size_t hi = text.length() - 1; 487 size_t hi = text.length() - 1;
487 size_t guess; 488 size_t guess;
488 for (guess = (lo + hi) / 2; lo <= hi; guess = (lo + hi) / 2) { 489 for (guess = (lo + hi) / 2; lo <= hi; guess = (lo + hi) / 2) {
489 // We check the length of the whole desired string at once to ensure we 490 // We check the length of the whole desired string at once to ensure we
490 // handle kerning/ligatures/etc. correctly. 491 // handle kerning/ligatures/etc. correctly.
491 const string16 cut = slicer.CutString(guess, insert_ellipsis); 492 const string16 cut = slicer.CutString(guess, insert_ellipsis);
(...skipping 454 matching lines...) Expand 10 before | Expand all | Expand 10 after
946 // Account for naturally-occuring newlines. 947 // Account for naturally-occuring newlines.
947 NewLine(); 948 NewLine();
948 } 949 }
949 950
950 int RectangleText::WrapWord(const string16& word) { 951 int RectangleText::WrapWord(const string16& word) {
951 // Word is so wide that it must be fragmented. 952 // Word is so wide that it must be fragmented.
952 string16 text = word; 953 string16 text = word;
953 int lines_added = 0; 954 int lines_added = 0;
954 bool first_fragment = true; 955 bool first_fragment = true;
955 while (!insufficient_height_ && !text.empty()) { 956 while (!insufficient_height_ && !text.empty()) {
956 const string16 fragment = 957 string16 fragment =
957 ui::ElideText(text, font_, available_pixel_width_, ui::TRUNCATE_AT_END); 958 ui::ElideText(text, font_, available_pixel_width_, ui::TRUNCATE_AT_END);
959 // At least one character has to be added at every line, even if the
960 // available space is too small.
961 if(fragment.empty())
962 fragment = text.substr(0, 1);
958 if (!first_fragment && NewLine()) 963 if (!first_fragment && NewLine())
959 lines_added++; 964 lines_added++;
960 AddToCurrentLine(fragment); 965 AddToCurrentLine(fragment);
961 text = text.substr(fragment.length()); 966 text = text.substr(fragment.length());
962 first_fragment = false; 967 first_fragment = false;
963 } 968 }
964 return lines_added; 969 return lines_added;
965 } 970 }
966 971
967 int RectangleText::AddWordOverflow(const string16& word) { 972 int RectangleText::AddWordOverflow(const string16& word) {
(...skipping 154 matching lines...) Expand 10 before | Expand all | Expand 10 after
1122 index = char_iterator.getIndex(); 1127 index = char_iterator.getIndex();
1123 } else { 1128 } else {
1124 // String has leading whitespace, return the elide string. 1129 // String has leading whitespace, return the elide string.
1125 return kElideString; 1130 return kElideString;
1126 } 1131 }
1127 } 1132 }
1128 return string.substr(0, index) + kElideString; 1133 return string.substr(0, index) + kElideString;
1129 } 1134 }
1130 1135
1131 } // namespace ui 1136 } // namespace ui
OLDNEW
« no previous file with comments | « build/android/pylib/gtest/filter/ui_unittests_disabled ('k') | ui/base/text/text_elider_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698