Chromium Code Reviews| Index: ui/gfx/text_elider.cc |
| diff --git a/ui/gfx/text_elider.cc b/ui/gfx/text_elider.cc |
| index 8c07bdecd5f581d2e88b3bf20f1947bd94fe1c6b..947027887b02c92791a3296fcfb23ddb0f949b12 100644 |
| --- a/ui/gfx/text_elider.cc |
| +++ b/ui/gfx/text_elider.cc |
| @@ -24,6 +24,7 @@ |
| #include "third_party/icu/source/common/unicode/rbbi.h" |
| #include "third_party/icu/source/common/unicode/uloc.h" |
| #include "ui/gfx/font_list.h" |
| +#include "ui/gfx/render_text.h" |
| #include "ui/gfx/text_utils.h" |
| using base::ASCIIToUTF16; |
| @@ -34,16 +35,13 @@ namespace gfx { |
| namespace { |
| -// Elides a well-formed email address (e.g. username@domain.com) to fit into |
| -// |available_pixel_width| using the specified |font_list|. |
| -// This function guarantees that the string returned will contain at least one |
| -// character, other than the ellipses, on either side of the '@'. If it is |
| -// impossible to achieve these requirements: only an ellipsis will be returned. |
| -// If possible: this elides only the username portion of the |email|. Otherwise, |
| -// the domain is elided in the middle so that it splits the available width |
| -// equally with the elided username (should the username be short enough that it |
| -// doesn't need half the available width: the elided domain will occupy that |
| -// extra width). |
| +#if !defined(OS_WIN) && !defined(OS_LINUX) |
| +// The returned string will have at least one character besides the ellipsis |
| +// on either side of '@'; if that's impossible, a single ellipsis is returned. |
| +// If possible, only the username is elided. Otherwise, the domain is elided |
| +// in the middle, splitting available width equally with the elided username. |
| +// If the username is short enough that it doesn't need half the available |
| +// width, the elided domain will occupy that extra width. |
| base::string16 ElideEmail(const base::string16& email, |
| const FontList& font_list, |
| float available_pixel_width) { |
| @@ -51,10 +49,8 @@ base::string16 ElideEmail(const base::string16& email, |
| return email; |
| // Split the email into its local-part (username) and domain-part. The email |
| - // spec technically allows for @ symbols in the local-part (username) of the |
| - // email under some special requirements. It is guaranteed that there is no @ |
| - // symbol in the domain part of the email however so splitting at the last @ |
| - // symbol is safe. |
| + // spec allows for @ symbols in the username under some special requirements, |
| + // but not in the domain part, so splitting at the last @ symbol is safe. |
| const size_t split_index = email.find_last_of('@'); |
| DCHECK_NE(split_index, base::string16::npos); |
| base::string16 username = email.substr(0, split_index); |
| @@ -99,6 +95,7 @@ base::string16 ElideEmail(const base::string16& email, |
| username = ElideText(username, font_list, available_pixel_width, ELIDE_TAIL); |
| return username + kAtSignUTF16 + domain; |
| } |
| +#endif |
| } // namespace |
| @@ -205,36 +202,32 @@ base::string16 ElideText(const base::string16& text, |
| const FontList& font_list, |
| float available_pixel_width, |
| ElideBehavior behavior) { |
| +#if defined(OS_WIN) || defined(OS_LINUX) |
|
Alexei Svitkine (slow)
2014/07/03 20:12:34
I understand why it wouldn't work on platforms tha
msw
2014/07/08 19:07:36
RenderText doesn't support RectF values for the di
|
| + DCHECK_NE(behavior, FADE_TAIL); |
| + scoped_ptr<RenderText> render_text(RenderText::CreateInstance()); |
| + render_text->SetCursorEnabled(false); |
| + // Do not bother accurately sizing strings over 5000 characters here, for |
| + // performance purposes. This matches the behavior of Canvas::SizeStringFloat. |
| + render_text->set_truncate_length(5000); |
| + render_text->SetFontList(font_list); |
| + render_text->SetDisplayRect(gfx::Rect(gfx::Size(available_pixel_width, 1))); |
| + render_text->SetElideBehavior(behavior); |
| + render_text->SetText(text); |
| + return render_text->layout_text(); |
| +#else |
| DCHECK_NE(behavior, FADE_TAIL); |
| - if (text.empty() || behavior == FADE_TAIL) |
| + if (text.empty() || behavior == FADE_TAIL || behavior == NO_ELIDE || |
| + GetStringWidthF(text, font_list) <= available_pixel_width) |
|
Alexei Svitkine (slow)
2014/07/03 20:12:34
Nit: {}'s
msw
2014/07/08 19:07:36
Done.
|
| return text; |
| if (behavior == ELIDE_EMAIL) |
| return ElideEmail(text, font_list, available_pixel_width); |
| - const float current_text_pixel_width = GetStringWidthF(text, font_list); |
| const bool elide_in_middle = (behavior == ELIDE_MIDDLE); |
| const bool elide_at_beginning = (behavior == ELIDE_HEAD); |
| const bool insert_ellipsis = (behavior != TRUNCATE); |
| const base::string16 ellipsis = base::string16(kEllipsisUTF16); |
| StringSlicer slicer(text, ellipsis, elide_in_middle, elide_at_beginning); |
| - // Pango will return 0 width for absurdly long strings. Cut the string in |
| - // half and try again. |
| - // This is caused by an int overflow in Pango (specifically, in |
| - // pango_glyph_string_extents_range). It's actually more subtle than just |
| - // returning 0, since on super absurdly long strings, the int can wrap and |
| - // return positive numbers again. Detecting that is probably not worth it |
| - // (eliding way too much from a ridiculous string is probably still |
| - // ridiculous), but we should check other widths for bogus values as well. |
| - if (current_text_pixel_width <= 0) { |
| - const base::string16 cut = |
| - slicer.CutString(text.length() / 2, insert_ellipsis); |
| - return ElideText(cut, font_list, available_pixel_width, behavior); |
| - } |
| - |
| - if (current_text_pixel_width <= available_pixel_width) |
| - return text; |
| - |
| if (insert_ellipsis && |
| GetStringWidthF(ellipsis, font_list) > available_pixel_width) |
| return base::string16(); |
| @@ -254,8 +247,7 @@ base::string16 ElideText(const base::string16& text, |
| break; |
| if (guess_width > available_pixel_width) { |
| hi = guess - 1; |
| - // Move back if we are on loop terminating condition, and guess is wider |
| - // than available. |
| + // Move back on the loop terminating condition when the guess is too wide. |
| if (hi < lo) |
| lo = hi; |
| } else { |
| @@ -264,6 +256,7 @@ base::string16 ElideText(const base::string16& text, |
| } |
| return slicer.CutString(guess, insert_ellipsis); |
| +#endif |
| } |
| bool ElideString(const base::string16& input, |