| Index: ui/gfx/text_elider.cc
|
| diff --git a/ui/gfx/text_elider.cc b/ui/gfx/text_elider.cc
|
| index 8c07bdecd5f581d2e88b3bf20f1947bd94fe1c6b..c8a823d31c89dad9755d2ba5823ee0341cb27b4b 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;
|
| @@ -32,76 +33,6 @@ using base::WideToUTF16;
|
|
|
| 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).
|
| -base::string16 ElideEmail(const base::string16& email,
|
| - const FontList& font_list,
|
| - float available_pixel_width) {
|
| - if (GetStringWidthF(email, font_list) <= available_pixel_width)
|
| - 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.
|
| - const size_t split_index = email.find_last_of('@');
|
| - DCHECK_NE(split_index, base::string16::npos);
|
| - base::string16 username = email.substr(0, split_index);
|
| - base::string16 domain = email.substr(split_index + 1);
|
| - DCHECK(!username.empty());
|
| - DCHECK(!domain.empty());
|
| -
|
| - // Subtract the @ symbol from the available width as it is mandatory.
|
| - const base::string16 kAtSignUTF16 = ASCIIToUTF16("@");
|
| - available_pixel_width -= GetStringWidthF(kAtSignUTF16, font_list);
|
| -
|
| - // Check whether eliding the domain is necessary: if eliding the username
|
| - // is sufficient, the domain will not be elided.
|
| - const float full_username_width = GetStringWidthF(username, font_list);
|
| - const float available_domain_width =
|
| - available_pixel_width -
|
| - std::min(full_username_width,
|
| - GetStringWidthF(username.substr(0, 1) + kEllipsisUTF16,
|
| - font_list));
|
| - if (GetStringWidthF(domain, font_list) > available_domain_width) {
|
| - // Elide the domain so that it only takes half of the available width.
|
| - // Should the username not need all the width available in its half, the
|
| - // domain will occupy the leftover width.
|
| - // If |desired_domain_width| is greater than |available_domain_width|: the
|
| - // minimal username elision allowed by the specifications will not fit; thus
|
| - // |desired_domain_width| must be <= |available_domain_width| at all cost.
|
| - const float desired_domain_width =
|
| - std::min(available_domain_width,
|
| - std::max(available_pixel_width - full_username_width,
|
| - available_pixel_width / 2));
|
| - domain = ElideText(domain, font_list, desired_domain_width, ELIDE_MIDDLE);
|
| - // Failing to elide the domain such that at least one character remains
|
| - // (other than the ellipsis itself) remains: return a single ellipsis.
|
| - if (domain.length() <= 1U)
|
| - return base::string16(kEllipsisUTF16);
|
| - }
|
| -
|
| - // Fit the username in the remaining width (at this point the elided username
|
| - // is guaranteed to fit with at least one character remaining given all the
|
| - // precautions taken earlier).
|
| - available_pixel_width -= GetStringWidthF(domain, font_list);
|
| - username = ElideText(username, font_list, available_pixel_width, ELIDE_TAIL);
|
| - return username + kAtSignUTF16 + domain;
|
| -}
|
| -
|
| -} // namespace
|
| -
|
| // U+2026 in utf8
|
| const char kEllipsis[] = "\xE2\x80\xA6";
|
| const base::char16 kEllipsisUTF16[] = { 0x2026, 0 };
|
| @@ -206,64 +137,10 @@ base::string16 ElideText(const base::string16& text,
|
| float available_pixel_width,
|
| ElideBehavior behavior) {
|
| DCHECK_NE(behavior, FADE_TAIL);
|
| - if (text.empty() || behavior == FADE_TAIL)
|
| - 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();
|
| -
|
| - // Use binary search to compute the elided text.
|
| - size_t lo = 0;
|
| - size_t hi = text.length() - 1;
|
| - size_t guess;
|
| - for (guess = (lo + hi) / 2; lo <= hi; guess = (lo + hi) / 2) {
|
| - // We check the width of the whole desired string at once to ensure we
|
| - // handle kerning/ligatures/etc. correctly.
|
| - // TODO(skanuj) : Handle directionality of ellipsis based on adjacent
|
| - // characters. See crbug.com/327963.
|
| - const base::string16 cut = slicer.CutString(guess, insert_ellipsis);
|
| - const float guess_width = GetStringWidthF(cut, font_list);
|
| - if (guess_width == available_pixel_width)
|
| - 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.
|
| - if (hi < lo)
|
| - lo = hi;
|
| - } else {
|
| - lo = guess + 1;
|
| - }
|
| - }
|
| -
|
| - return slicer.CutString(guess, insert_ellipsis);
|
| + scoped_ptr<RenderText> render_text(RenderText::CreateInstance());
|
| + render_text->SetCursorEnabled(false);
|
| + render_text->SetFontList(font_list);
|
| + return render_text->Elide(text, available_pixel_width, behavior);
|
| }
|
|
|
| bool ElideString(const base::string16& input,
|
|
|