| 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 // 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/gfx/text_elider.h" | 10 #include "ui/gfx/text_elider.h" |
| (...skipping 14 matching lines...) Expand all Loading... |
| 25 #include "third_party/icu/source/common/unicode/uloc.h" | 25 #include "third_party/icu/source/common/unicode/uloc.h" |
| 26 #include "ui/gfx/font_list.h" | 26 #include "ui/gfx/font_list.h" |
| 27 #include "ui/gfx/text_utils.h" | 27 #include "ui/gfx/text_utils.h" |
| 28 | 28 |
| 29 using base::ASCIIToUTF16; | 29 using base::ASCIIToUTF16; |
| 30 using base::UTF8ToUTF16; | 30 using base::UTF8ToUTF16; |
| 31 using base::WideToUTF16; | 31 using base::WideToUTF16; |
| 32 | 32 |
| 33 namespace gfx { | 33 namespace gfx { |
| 34 | 34 |
| 35 // U+2026 in utf8 | 35 namespace { |
| 36 const char kEllipsis[] = "\xE2\x80\xA6"; | |
| 37 const base::char16 kEllipsisUTF16[] = { 0x2026, 0 }; | |
| 38 const base::char16 kForwardSlash = '/'; | |
| 39 | 36 |
| 40 StringSlicer::StringSlicer(const base::string16& text, | 37 // Elides a well-formed email address (e.g. username@domain.com) to fit into |
| 41 const base::string16& ellipsis, | 38 // |available_pixel_width| using the specified |font_list|. |
| 42 bool elide_in_middle, | 39 // This function guarantees that the string returned will contain at least one |
| 43 bool elide_at_beginning) | 40 // character, other than the ellipses, on either side of the '@'. If it is |
| 44 : text_(text), | 41 // impossible to achieve these requirements: only an ellipsis will be returned. |
| 45 ellipsis_(ellipsis), | 42 // If possible: this elides only the username portion of the |email|. Otherwise, |
| 46 elide_in_middle_(elide_in_middle), | 43 // the domain is elided in the middle so that it splits the available width |
| 47 elide_at_beginning_(elide_at_beginning) { | 44 // equally with the elided username (should the username be short enough that it |
| 48 } | 45 // doesn't need half the available width: the elided domain will occupy that |
| 49 | 46 // extra width). |
| 50 base::string16 StringSlicer::CutString(size_t length, bool insert_ellipsis) { | |
| 51 const base::string16 ellipsis_text = insert_ellipsis ? ellipsis_ | |
| 52 : base::string16(); | |
| 53 | |
| 54 if (elide_at_beginning_) | |
| 55 return ellipsis_text + | |
| 56 text_.substr(FindValidBoundaryBefore(text_.length() - length)); | |
| 57 | |
| 58 if (!elide_in_middle_) | |
| 59 return text_.substr(0, FindValidBoundaryBefore(length)) + ellipsis_text; | |
| 60 | |
| 61 // We put the extra character, if any, before the cut. | |
| 62 const size_t half_length = length / 2; | |
| 63 const size_t prefix_length = FindValidBoundaryBefore(length - half_length); | |
| 64 const size_t suffix_start_guess = text_.length() - half_length; | |
| 65 const size_t suffix_start = FindValidBoundaryAfter(suffix_start_guess); | |
| 66 const size_t suffix_length = | |
| 67 half_length - (suffix_start_guess - suffix_start); | |
| 68 return text_.substr(0, prefix_length) + ellipsis_text + | |
| 69 text_.substr(suffix_start, suffix_length); | |
| 70 } | |
| 71 | |
| 72 size_t StringSlicer::FindValidBoundaryBefore(size_t index) const { | |
| 73 DCHECK_LE(index, text_.length()); | |
| 74 if (index != text_.length()) | |
| 75 U16_SET_CP_START(text_.data(), 0, index); | |
| 76 return index; | |
| 77 } | |
| 78 | |
| 79 size_t StringSlicer::FindValidBoundaryAfter(size_t index) const { | |
| 80 DCHECK_LE(index, text_.length()); | |
| 81 if (index != text_.length()) | |
| 82 U16_SET_CP_LIMIT(text_.data(), 0, index, text_.length()); | |
| 83 return index; | |
| 84 } | |
| 85 | |
| 86 base::string16 ElideEmail(const base::string16& email, | 47 base::string16 ElideEmail(const base::string16& email, |
| 87 const FontList& font_list, | 48 const FontList& font_list, |
| 88 float available_pixel_width) { | 49 float available_pixel_width) { |
| 89 if (GetStringWidthF(email, font_list) <= available_pixel_width) | 50 if (GetStringWidthF(email, font_list) <= available_pixel_width) |
| 90 return email; | 51 return email; |
| 91 | 52 |
| 92 // Split the email into its local-part (username) and domain-part. The email | 53 // Split the email into its local-part (username) and domain-part. The email |
| 93 // spec technically allows for @ symbols in the local-part (username) of the | 54 // spec technically allows for @ symbols in the local-part (username) of the |
| 94 // email under some special requirements. It is guaranteed that there is no @ | 55 // email under some special requirements. It is guaranteed that there is no @ |
| 95 // symbol in the domain part of the email however so splitting at the last @ | 56 // symbol in the domain part of the email however so splitting at the last @ |
| (...skipping 21 matching lines...) Expand all Loading... |
| 117 // Elide the domain so that it only takes half of the available width. | 78 // Elide the domain so that it only takes half of the available width. |
| 118 // Should the username not need all the width available in its half, the | 79 // Should the username not need all the width available in its half, the |
| 119 // domain will occupy the leftover width. | 80 // domain will occupy the leftover width. |
| 120 // If |desired_domain_width| is greater than |available_domain_width|: the | 81 // If |desired_domain_width| is greater than |available_domain_width|: the |
| 121 // minimal username elision allowed by the specifications will not fit; thus | 82 // minimal username elision allowed by the specifications will not fit; thus |
| 122 // |desired_domain_width| must be <= |available_domain_width| at all cost. | 83 // |desired_domain_width| must be <= |available_domain_width| at all cost. |
| 123 const float desired_domain_width = | 84 const float desired_domain_width = |
| 124 std::min(available_domain_width, | 85 std::min(available_domain_width, |
| 125 std::max(available_pixel_width - full_username_width, | 86 std::max(available_pixel_width - full_username_width, |
| 126 available_pixel_width / 2)); | 87 available_pixel_width / 2)); |
| 127 domain = ElideText(domain, font_list, desired_domain_width, | 88 domain = ElideText(domain, font_list, desired_domain_width, ELIDE_MIDDLE); |
| 128 ELIDE_IN_MIDDLE); | |
| 129 // Failing to elide the domain such that at least one character remains | 89 // Failing to elide the domain such that at least one character remains |
| 130 // (other than the ellipsis itself) remains: return a single ellipsis. | 90 // (other than the ellipsis itself) remains: return a single ellipsis. |
| 131 if (domain.length() <= 1U) | 91 if (domain.length() <= 1U) |
| 132 return base::string16(kEllipsisUTF16); | 92 return base::string16(kEllipsisUTF16); |
| 133 } | 93 } |
| 134 | 94 |
| 135 // Fit the username in the remaining width (at this point the elided username | 95 // Fit the username in the remaining width (at this point the elided username |
| 136 // is guaranteed to fit with at least one character remaining given all the | 96 // is guaranteed to fit with at least one character remaining given all the |
| 137 // precautions taken earlier). | 97 // precautions taken earlier). |
| 138 available_pixel_width -= GetStringWidthF(domain, font_list); | 98 available_pixel_width -= GetStringWidthF(domain, font_list); |
| 139 username = ElideText(username, font_list, available_pixel_width, | 99 username = ElideText(username, font_list, available_pixel_width, ELIDE_TAIL); |
| 140 ELIDE_AT_END); | 100 return username + kAtSignUTF16 + domain; |
| 101 } |
| 141 | 102 |
| 142 return username + kAtSignUTF16 + domain; | 103 } // namespace |
| 104 |
| 105 // U+2026 in utf8 |
| 106 const char kEllipsis[] = "\xE2\x80\xA6"; |
| 107 const base::char16 kEllipsisUTF16[] = { 0x2026, 0 }; |
| 108 const base::char16 kForwardSlash = '/'; |
| 109 |
| 110 StringSlicer::StringSlicer(const base::string16& text, |
| 111 const base::string16& ellipsis, |
| 112 bool elide_in_middle, |
| 113 bool elide_at_beginning) |
| 114 : text_(text), |
| 115 ellipsis_(ellipsis), |
| 116 elide_in_middle_(elide_in_middle), |
| 117 elide_at_beginning_(elide_at_beginning) { |
| 118 } |
| 119 |
| 120 base::string16 StringSlicer::CutString(size_t length, bool insert_ellipsis) { |
| 121 const base::string16 ellipsis_text = insert_ellipsis ? ellipsis_ |
| 122 : base::string16(); |
| 123 |
| 124 if (elide_at_beginning_) |
| 125 return ellipsis_text + |
| 126 text_.substr(FindValidBoundaryBefore(text_.length() - length)); |
| 127 |
| 128 if (!elide_in_middle_) |
| 129 return text_.substr(0, FindValidBoundaryBefore(length)) + ellipsis_text; |
| 130 |
| 131 // We put the extra character, if any, before the cut. |
| 132 const size_t half_length = length / 2; |
| 133 const size_t prefix_length = FindValidBoundaryBefore(length - half_length); |
| 134 const size_t suffix_start_guess = text_.length() - half_length; |
| 135 const size_t suffix_start = FindValidBoundaryAfter(suffix_start_guess); |
| 136 const size_t suffix_length = |
| 137 half_length - (suffix_start_guess - suffix_start); |
| 138 return text_.substr(0, prefix_length) + ellipsis_text + |
| 139 text_.substr(suffix_start, suffix_length); |
| 140 } |
| 141 |
| 142 size_t StringSlicer::FindValidBoundaryBefore(size_t index) const { |
| 143 DCHECK_LE(index, text_.length()); |
| 144 if (index != text_.length()) |
| 145 U16_SET_CP_START(text_.data(), 0, index); |
| 146 return index; |
| 147 } |
| 148 |
| 149 size_t StringSlicer::FindValidBoundaryAfter(size_t index) const { |
| 150 DCHECK_LE(index, text_.length()); |
| 151 if (index != text_.length()) |
| 152 U16_SET_CP_LIMIT(text_.data(), 0, index, text_.length()); |
| 153 return index; |
| 143 } | 154 } |
| 144 | 155 |
| 145 base::string16 ElideFilename(const base::FilePath& filename, | 156 base::string16 ElideFilename(const base::FilePath& filename, |
| 146 const FontList& font_list, | 157 const FontList& font_list, |
| 147 float available_pixel_width) { | 158 float available_pixel_width) { |
| 148 #if defined(OS_WIN) | 159 #if defined(OS_WIN) |
| 149 base::string16 filename_utf16 = filename.value(); | 160 base::string16 filename_utf16 = filename.value(); |
| 150 base::string16 extension = filename.Extension(); | 161 base::string16 extension = filename.Extension(); |
| 151 base::string16 rootname = filename.BaseName().RemoveExtension().value(); | 162 base::string16 rootname = filename.BaseName().RemoveExtension().value(); |
| 152 #elif defined(OS_POSIX) | 163 #elif defined(OS_POSIX) |
| 153 base::string16 filename_utf16 = WideToUTF16(base::SysNativeMBToWide( | 164 base::string16 filename_utf16 = WideToUTF16(base::SysNativeMBToWide( |
| 154 filename.value())); | 165 filename.value())); |
| 155 base::string16 extension = WideToUTF16(base::SysNativeMBToWide( | 166 base::string16 extension = WideToUTF16(base::SysNativeMBToWide( |
| 156 filename.Extension())); | 167 filename.Extension())); |
| 157 base::string16 rootname = WideToUTF16(base::SysNativeMBToWide( | 168 base::string16 rootname = WideToUTF16(base::SysNativeMBToWide( |
| 158 filename.BaseName().RemoveExtension().value())); | 169 filename.BaseName().RemoveExtension().value())); |
| 159 #endif | 170 #endif |
| 160 | 171 |
| 161 const float full_width = GetStringWidthF(filename_utf16, font_list); | 172 const float full_width = GetStringWidthF(filename_utf16, font_list); |
| 162 if (full_width <= available_pixel_width) | 173 if (full_width <= available_pixel_width) |
| 163 return base::i18n::GetDisplayStringInLTRDirectionality(filename_utf16); | 174 return base::i18n::GetDisplayStringInLTRDirectionality(filename_utf16); |
| 164 | 175 |
| 165 if (rootname.empty() || extension.empty()) { | 176 if (rootname.empty() || extension.empty()) { |
| 166 const base::string16 elided_name = ElideText(filename_utf16, font_list, | 177 const base::string16 elided_name = |
| 167 available_pixel_width, ELIDE_AT_END); | 178 ElideText(filename_utf16, font_list, available_pixel_width, ELIDE_TAIL); |
| 168 return base::i18n::GetDisplayStringInLTRDirectionality(elided_name); | 179 return base::i18n::GetDisplayStringInLTRDirectionality(elided_name); |
| 169 } | 180 } |
| 170 | 181 |
| 171 const float ext_width = GetStringWidthF(extension, font_list); | 182 const float ext_width = GetStringWidthF(extension, font_list); |
| 172 const float root_width = GetStringWidthF(rootname, font_list); | 183 const float root_width = GetStringWidthF(rootname, font_list); |
| 173 | 184 |
| 174 // We may have trimmed the path. | 185 // We may have trimmed the path. |
| 175 if (root_width + ext_width <= available_pixel_width) { | 186 if (root_width + ext_width <= available_pixel_width) { |
| 176 const base::string16 elided_name = rootname + extension; | 187 const base::string16 elided_name = rootname + extension; |
| 177 return base::i18n::GetDisplayStringInLTRDirectionality(elided_name); | 188 return base::i18n::GetDisplayStringInLTRDirectionality(elided_name); |
| 178 } | 189 } |
| 179 | 190 |
| 180 if (ext_width >= available_pixel_width) { | 191 if (ext_width >= available_pixel_width) { |
| 181 const base::string16 elided_name = ElideText( | 192 const base::string16 elided_name = ElideText( |
| 182 rootname + extension, font_list, available_pixel_width, | 193 rootname + extension, font_list, available_pixel_width, ELIDE_MIDDLE); |
| 183 ELIDE_IN_MIDDLE); | |
| 184 return base::i18n::GetDisplayStringInLTRDirectionality(elided_name); | 194 return base::i18n::GetDisplayStringInLTRDirectionality(elided_name); |
| 185 } | 195 } |
| 186 | 196 |
| 187 float available_root_width = available_pixel_width - ext_width; | 197 float available_root_width = available_pixel_width - ext_width; |
| 188 base::string16 elided_name = | 198 base::string16 elided_name = |
| 189 ElideText(rootname, font_list, available_root_width, ELIDE_AT_END); | 199 ElideText(rootname, font_list, available_root_width, ELIDE_TAIL); |
| 190 elided_name += extension; | 200 elided_name += extension; |
| 191 return base::i18n::GetDisplayStringInLTRDirectionality(elided_name); | 201 return base::i18n::GetDisplayStringInLTRDirectionality(elided_name); |
| 192 } | 202 } |
| 193 | 203 |
| 194 base::string16 ElideText(const base::string16& text, | 204 base::string16 ElideText(const base::string16& text, |
| 195 const FontList& font_list, | 205 const FontList& font_list, |
| 196 float available_pixel_width, | 206 float available_pixel_width, |
| 197 ElideBehavior elide_behavior) { | 207 ElideBehavior behavior) { |
| 198 if (text.empty()) | 208 DCHECK_NE(behavior, FADE_TAIL); |
| 209 if (text.empty() || behavior == FADE_TAIL) |
| 199 return text; | 210 return text; |
| 211 if (behavior == ELIDE_EMAIL) |
| 212 return ElideEmail(text, font_list, available_pixel_width); |
| 200 | 213 |
| 201 const float current_text_pixel_width = GetStringWidthF(text, font_list); | 214 const float current_text_pixel_width = GetStringWidthF(text, font_list); |
| 202 const bool elide_in_middle = (elide_behavior == ELIDE_IN_MIDDLE); | 215 const bool elide_in_middle = (behavior == ELIDE_MIDDLE); |
| 203 const bool elide_at_beginning = (elide_behavior == ELIDE_AT_BEGINNING); | 216 const bool elide_at_beginning = (behavior == ELIDE_HEAD); |
| 204 const bool insert_ellipsis = (elide_behavior != TRUNCATE_AT_END); | 217 const bool insert_ellipsis = (behavior != TRUNCATE); |
| 205 | |
| 206 const base::string16 ellipsis = base::string16(kEllipsisUTF16); | 218 const base::string16 ellipsis = base::string16(kEllipsisUTF16); |
| 207 StringSlicer slicer(text, ellipsis, elide_in_middle, elide_at_beginning); | 219 StringSlicer slicer(text, ellipsis, elide_in_middle, elide_at_beginning); |
| 208 | 220 |
| 209 // Pango will return 0 width for absurdly long strings. Cut the string in | 221 // Pango will return 0 width for absurdly long strings. Cut the string in |
| 210 // half and try again. | 222 // half and try again. |
| 211 // This is caused by an int overflow in Pango (specifically, in | 223 // This is caused by an int overflow in Pango (specifically, in |
| 212 // pango_glyph_string_extents_range). It's actually more subtle than just | 224 // pango_glyph_string_extents_range). It's actually more subtle than just |
| 213 // returning 0, since on super absurdly long strings, the int can wrap and | 225 // returning 0, since on super absurdly long strings, the int can wrap and |
| 214 // return positive numbers again. Detecting that is probably not worth it | 226 // return positive numbers again. Detecting that is probably not worth it |
| 215 // (eliding way too much from a ridiculous string is probably still | 227 // (eliding way too much from a ridiculous string is probably still |
| 216 // ridiculous), but we should check other widths for bogus values as well. | 228 // ridiculous), but we should check other widths for bogus values as well. |
| 217 if (current_text_pixel_width <= 0 && !text.empty()) { | 229 if (current_text_pixel_width <= 0) { |
| 218 const base::string16 cut = | 230 const base::string16 cut = |
| 219 slicer.CutString(text.length() / 2, insert_ellipsis); | 231 slicer.CutString(text.length() / 2, insert_ellipsis); |
| 220 return ElideText(cut, font_list, available_pixel_width, elide_behavior); | 232 return ElideText(cut, font_list, available_pixel_width, behavior); |
| 221 } | 233 } |
| 222 | 234 |
| 223 if (current_text_pixel_width <= available_pixel_width) | 235 if (current_text_pixel_width <= available_pixel_width) |
| 224 return text; | 236 return text; |
| 225 | 237 |
| 226 if (insert_ellipsis && | 238 if (insert_ellipsis && |
| 227 GetStringWidthF(ellipsis, font_list) > available_pixel_width) | 239 GetStringWidthF(ellipsis, font_list) > available_pixel_width) |
| 228 return base::string16(); | 240 return base::string16(); |
| 229 | 241 |
| 230 // Use binary search to compute the elided text. | 242 // Use binary search to compute the elided text. |
| (...skipping 16 matching lines...) Expand all Loading... |
| 247 if (hi < lo) | 259 if (hi < lo) |
| 248 lo = hi; | 260 lo = hi; |
| 249 } else { | 261 } else { |
| 250 lo = guess + 1; | 262 lo = guess + 1; |
| 251 } | 263 } |
| 252 } | 264 } |
| 253 | 265 |
| 254 return slicer.CutString(guess, insert_ellipsis); | 266 return slicer.CutString(guess, insert_ellipsis); |
| 255 } | 267 } |
| 256 | 268 |
| 257 bool ElideString(const base::string16& input, int max_len, | 269 bool ElideString(const base::string16& input, |
| 270 int max_len, |
| 258 base::string16* output) { | 271 base::string16* output) { |
| 259 DCHECK_GE(max_len, 0); | 272 DCHECK_GE(max_len, 0); |
| 260 if (static_cast<int>(input.length()) <= max_len) { | 273 if (static_cast<int>(input.length()) <= max_len) { |
| 261 output->assign(input); | 274 output->assign(input); |
| 262 return false; | 275 return false; |
| 263 } | 276 } |
| 264 | 277 |
| 265 switch (max_len) { | 278 switch (max_len) { |
| 266 case 0: | 279 case 0: |
| 267 output->clear(); | 280 output->clear(); |
| (...skipping 358 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 626 NewLine(); | 639 NewLine(); |
| 627 } | 640 } |
| 628 | 641 |
| 629 int RectangleText::WrapWord(const base::string16& word) { | 642 int RectangleText::WrapWord(const base::string16& word) { |
| 630 // Word is so wide that it must be fragmented. | 643 // Word is so wide that it must be fragmented. |
| 631 base::string16 text = word; | 644 base::string16 text = word; |
| 632 int lines_added = 0; | 645 int lines_added = 0; |
| 633 bool first_fragment = true; | 646 bool first_fragment = true; |
| 634 while (!insufficient_height_ && !text.empty()) { | 647 while (!insufficient_height_ && !text.empty()) { |
| 635 base::string16 fragment = | 648 base::string16 fragment = |
| 636 ElideText(text, font_list_, available_pixel_width_, | 649 ElideText(text, font_list_, available_pixel_width_, TRUNCATE); |
| 637 TRUNCATE_AT_END); | |
| 638 // At least one character has to be added at every line, even if the | 650 // At least one character has to be added at every line, even if the |
| 639 // available space is too small. | 651 // available space is too small. |
| 640 if(fragment.empty()) | 652 if (fragment.empty()) |
| 641 fragment = text.substr(0, 1); | 653 fragment = text.substr(0, 1); |
| 642 if (!first_fragment && NewLine()) | 654 if (!first_fragment && NewLine()) |
| 643 lines_added++; | 655 lines_added++; |
| 644 AddToCurrentLine(fragment); | 656 AddToCurrentLine(fragment); |
| 645 text = text.substr(fragment.length()); | 657 text = text.substr(fragment.length()); |
| 646 first_fragment = false; | 658 first_fragment = false; |
| 647 } | 659 } |
| 648 return lines_added; | 660 return lines_added; |
| 649 } | 661 } |
| 650 | 662 |
| 651 int RectangleText::AddWordOverflow(const base::string16& word) { | 663 int RectangleText::AddWordOverflow(const base::string16& word) { |
| 652 int lines_added = 0; | 664 int lines_added = 0; |
| 653 | 665 |
| 654 // Unless this is the very first word, put it on a new line. | 666 // Unless this is the very first word, put it on a new line. |
| 655 if (!current_line_.empty()) { | 667 if (!current_line_.empty()) { |
| 656 if (!NewLine()) | 668 if (!NewLine()) |
| 657 return 0; | 669 return 0; |
| 658 lines_added++; | 670 lines_added++; |
| 659 } | 671 } |
| 660 | 672 |
| 661 if (wrap_behavior_ == IGNORE_LONG_WORDS) { | 673 if (wrap_behavior_ == IGNORE_LONG_WORDS) { |
| 662 current_line_ = word; | 674 current_line_ = word; |
| 663 current_width_ = available_pixel_width_; | 675 current_width_ = available_pixel_width_; |
| 664 } else if (wrap_behavior_ == WRAP_LONG_WORDS) { | 676 } else if (wrap_behavior_ == WRAP_LONG_WORDS) { |
| 665 lines_added += WrapWord(word); | 677 lines_added += WrapWord(word); |
| 666 } else { | 678 } else { |
| 667 const ElideBehavior elide_behavior = | 679 const ElideBehavior elide_behavior = |
| 668 (wrap_behavior_ == ELIDE_LONG_WORDS ? ELIDE_AT_END : TRUNCATE_AT_END); | 680 (wrap_behavior_ == ELIDE_LONG_WORDS ? ELIDE_TAIL : TRUNCATE); |
| 669 const base::string16 elided_word = | 681 const base::string16 elided_word = |
| 670 ElideText(word, font_list_, available_pixel_width_, elide_behavior); | 682 ElideText(word, font_list_, available_pixel_width_, elide_behavior); |
| 671 AddToCurrentLine(elided_word); | 683 AddToCurrentLine(elided_word); |
| 672 insufficient_width_ = true; | 684 insufficient_width_ = true; |
| 673 } | 685 } |
| 674 | 686 |
| 675 return lines_added; | 687 return lines_added; |
| 676 } | 688 } |
| 677 | 689 |
| 678 int RectangleText::AddWord(const base::string16& word) { | 690 int RectangleText::AddWord(const base::string16& word) { |
| (...skipping 125 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 804 index = char_iterator.getIndex(); | 816 index = char_iterator.getIndex(); |
| 805 } else { | 817 } else { |
| 806 // String has leading whitespace, return the elide string. | 818 // String has leading whitespace, return the elide string. |
| 807 return kElideString; | 819 return kElideString; |
| 808 } | 820 } |
| 809 } | 821 } |
| 810 return string.substr(0, index) + kElideString; | 822 return string.substr(0, index) + kElideString; |
| 811 } | 823 } |
| 812 | 824 |
| 813 } // namespace gfx | 825 } // namespace gfx |
| OLD | NEW |