Index: ui/base/text/text_elider.cc |
diff --git a/ui/base/text/text_elider.cc b/ui/base/text/text_elider.cc |
index 1a4b79d5e2e9ebbcbeeffdc6e35e79bff4b2b9cb..842322df528aff72c1eaf91f51f41425302d028c 100644 |
--- a/ui/base/text/text_elider.cc |
+++ b/ui/base/text/text_elider.cc |
@@ -73,6 +73,89 @@ string16 BuildPathFromComponents(const string16& path_prefix, |
return path; |
} |
vandebo (ex-Chrome)
2011/07/19 21:31:20
I think this is the wrong way to go about things.
Aayush Kumar
2011/07/21 21:58:53
Restored changes :) I now have mapping between th
|
+// Measures the width of the |text| string passed depending on the |object_type| |
+// passed. |
+// If the object is a Skia_Paint object, then the width of the text is returned |
+// in points. |
+// If the object is a gfx::Font object, then the width of the text is returned |
+// in pixels. |
+SkScalar measureStringWidth(const string16& text, |
dpapad
2011/07/19 20:34:01
Nit: Function names should start with capital lett
Aayush Kumar
2011/07/21 21:58:53
Done.
|
+ void* font_or_paint, |
+ ObjectType object_type) { |
+ // TODO(aayushkumar): Make sure that |font_or_paint| is actually of type |
+ // |object_type| otherwise we will segfault! |
+ if (object_type == Skia_Paint) { |
+ return ((SkPaint *)font_or_paint)->measureText(text.c_str(), |
+ text.length()*sizeof(char16)); |
+ } else { |
+ return ((gfx::Font *)font_or_paint)->GetStringWidth(text); |
+ } |
+} |
+ |
+// Overloaded function. |
+// This function adds an ellipsis at the end of the text if the text |
+// does not fit the given pixel width. |
+// The |font_or_paint| argument is a pointer to either a Font or Paint object |
+// and that is specified in the |object_type| parameter. |
+// Depending on what type of object is passed, the appropriate function is |
+// called to measure the width of the text. |
+string16 ElideText(const string16& text, |
+ void* font_or_paint, |
+ SkScalar available_width, |
+ bool elide_in_middle, |
+ ObjectType object_type) { |
+ |
+ if (text.empty()) |
+ return text; |
+ |
+ int current_text_pixel_width = measureStringWidth(text, font_or_paint, |
+ object_type); |
+ |
+ // 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 && !text.empty()) { |
+ return ElideText(CutString(text, text.length() / 2, elide_in_middle, false), |
+ font_or_paint, available_width, false, object_type); |
+ } |
+ |
+ if (current_text_pixel_width <= available_width) |
+ return text; |
+ |
+ if (measureStringWidth(UTF8ToUTF16(kEllipsis), font_or_paint, object_type) > |
+ available_width) |
+ return string16(); |
+ |
+ // Use binary search to compute the elided text. |
+ size_t lo = 0; |
+ size_t hi = text.length() - 1; |
+ for (size_t guess = (lo + hi) / 2; guess != lo; guess = (lo + hi) / 2) { |
+ // We check the length of the whole desired string at once to ensure we |
+ // handle kerning/ligatures/etc. correctly. |
+ int guess_length = measureStringWidth(//font.GetStringWidth( |
+ CutString(text, guess, elide_in_middle, true), font_or_paint, |
+ object_type); |
+ // Check again that we didn't hit a Pango width overflow. If so, cut the |
+ // current string in half and start over. |
+ if (guess_length <= 0) { |
+ return ElideText(CutString(text, guess / 2, elide_in_middle, false), |
+ font_or_paint, available_width, elide_in_middle, |
+ object_type); |
+ } |
+ if (guess_length > available_width) |
+ hi = guess; |
+ else |
+ lo = guess; |
+ } |
+ |
+ return CutString(text, lo, elide_in_middle, true); |
+} |
+ |
// Takes a prefix (Domain, or Domain+subdomain) and a collection of path |
// components and elides if possible. Returns a string containing the longest |
// possible elided path, or an empty string if elision is not possible. |
@@ -80,8 +163,9 @@ string16 ElideComponentizedPath(const string16& url_path_prefix, |
const std::vector<string16>& url_path_elements, |
const string16& url_filename, |
const string16& url_query, |
- const gfx::Font& font, |
- int available_pixel_width) { |
+ void* font_or_paint, |
+ int available_width, |
+ ObjectType object_type) { |
size_t url_path_number_of_elements = url_path_elements.size(); |
static const string16 kEllipsisAndSlash = UTF8ToUTF16(kEllipsis) + |
@@ -90,16 +174,17 @@ string16 ElideComponentizedPath(const string16& url_path_prefix, |
for (size_t i = url_path_number_of_elements - 1; i > 0; --i) { |
string16 elided_path = BuildPathFromComponents(url_path_prefix, |
url_path_elements, url_filename, i); |
- if (available_pixel_width >= font.GetStringWidth(elided_path)) |
+ if (available_width >= measureStringWidth(elided_path, font_or_paint, |
+ object_type)) { |
return ElideText(elided_path + url_query, |
- font, available_pixel_width, false); |
+ font_or_paint, available_width, false, object_type); |
+ } |
} |
return string16(); |
} |
-} // namespace |
- |
+// Overloaded Function. |
// This function takes a GURL object and elides it. It returns a string |
// which composed of parts from subdomain, domain, path, filename and query. |
// A "..." is added automatically at the end if the elided string is bigger |
@@ -110,25 +195,32 @@ string16 ElideComponentizedPath(const string16& url_path_prefix, |
// kerning/ligatures/etc. issues potentially wrong by assuming that the width of |
// a rendered string is always the sum of the widths of its substrings. Also I |
// suspect it could be made simpler. |
+// The |font_or_paint| argument is a pointer to either a Font or Paint object |
+// and that is specified in the |object_type| parameter. |
+// Depending on what type of object is passed, the appropriate function is |
+// called to measure the width of the text. |
string16 ElideUrl(const GURL& url, |
- const gfx::Font& font, |
- int available_pixel_width, |
- const std::string& languages) { |
+ void* font_or_paint, |
+ int available_width, |
+ const std::string& languages, |
+ ObjectType object_type) { |
// Get a formatted string and corresponding parsing of the url. |
url_parse::Parsed parsed; |
string16 url_string = net::FormatUrl(url, languages, net::kFormatUrlOmitAll, |
UnescapeRule::SPACES, &parsed, NULL, NULL); |
- if (available_pixel_width <= 0) |
+ if (available_width <= 0) |
return url_string; |
// If non-standard or not file type, return plain eliding. |
if (!(url.SchemeIsFile() || url.IsStandard())) |
- return ElideText(url_string, font, available_pixel_width, false); |
+ return ElideText(url_string, font_or_paint, available_width, false, |
+ object_type); |
// Now start eliding url_string to fit within available pixel width. |
// Fist pass - check to see whether entire url_string fits. |
- int pixel_width_url_string = font.GetStringWidth(url_string); |
- if (available_pixel_width >= pixel_width_url_string) |
+ int pixel_width_url_string = measureStringWidth(url_string, font_or_paint, |
+ object_type); |
+ if (available_width >= pixel_width_url_string) |
return url_string; |
// Get the path substring, including query and reference. |
@@ -139,8 +231,11 @@ string16 ElideUrl(const GURL& url, |
// Return general elided text if url minus the query fits. |
string16 url_minus_query = url_string.substr(0, path_start_index + path_len); |
- if (available_pixel_width >= font.GetStringWidth(url_minus_query)) |
- return ElideText(url_string, font, available_pixel_width, false); |
+ if (available_width >= measureStringWidth(url_minus_query, font_or_paint, |
+ object_type)) { |
+ return ElideText(url_string, font_or_paint, available_width, false, |
+ object_type); |
+ } |
// Get Host. |
string16 url_host = UTF8ToUTF16(url.host()); |
@@ -187,16 +282,21 @@ string16 ElideUrl(const GURL& url, |
} |
// Second Pass - remove scheme - the rest fits. |
- int pixel_width_url_host = font.GetStringWidth(url_host); |
- int pixel_width_url_path = font.GetStringWidth(url_path_query_etc); |
- if (available_pixel_width >= |
+ int pixel_width_url_host = measureStringWidth(url_host, font_or_paint, |
+ object_type); |
+ int pixel_width_url_path = measureStringWidth(url_path_query_etc, |
+ font_or_paint, object_type); |
+ if (available_width >= |
pixel_width_url_host + pixel_width_url_path) |
dpapad
2011/07/19 20:34:01
Use braces when an if statement spans multiple lin
Aayush Kumar
2011/07/21 21:58:53
Done.
|
return url_host + url_path_query_etc; |
// Third Pass: Subdomain, domain and entire path fits. |
- int pixel_width_url_domain = font.GetStringWidth(url_domain); |
- int pixel_width_url_subdomain = font.GetStringWidth(url_subdomain); |
- if (available_pixel_width >= |
+ int pixel_width_url_domain = measureStringWidth(url_domain, font_or_paint, |
+ object_type); |
+ int pixel_width_url_subdomain = measureStringWidth(url_subdomain, |
+ font_or_paint, |
+ object_type); |
+ if (available_width >= |
pixel_width_url_subdomain + pixel_width_url_domain + |
pixel_width_url_path) |
return url_subdomain + url_domain + url_path_query_etc; |
@@ -204,14 +304,14 @@ string16 ElideUrl(const GURL& url, |
// Query element. |
string16 url_query; |
const int kPixelWidthDotsTrailer = |
- font.GetStringWidth(UTF8ToUTF16(kEllipsis)); |
+ measureStringWidth(UTF8ToUTF16(kEllipsis), font_or_paint, object_type); |
if (parsed.query.is_nonempty()) { |
url_query = UTF8ToUTF16("?") + url_string.substr(parsed.query.begin); |
- if (available_pixel_width >= (pixel_width_url_subdomain + |
+ if (available_width >= (pixel_width_url_subdomain + |
pixel_width_url_domain + pixel_width_url_path - |
- font.GetStringWidth(url_query))) { |
+ measureStringWidth(url_query, font_or_paint, object_type))) { |
return ElideText(url_subdomain + url_domain + url_path_query_etc, |
- font, available_pixel_width, false); |
+ font_or_paint, available_width, false, object_type); |
} |
} |
@@ -238,17 +338,20 @@ string16 ElideUrl(const GURL& url, |
url_path_number_of_elements > kMaxNumberOfUrlPathElementsAllowed) { |
// No path to elide, or too long of a path (could overflow in loop below) |
// Just elide this as a text string. |
- return ElideText(url_subdomain + url_domain + url_path_query_etc, font, |
- available_pixel_width, false); |
+ return ElideText(url_subdomain + url_domain + url_path_query_etc, |
+ font_or_paint, available_width, false, object_type); |
} |
// Start eliding the path and replacing elements by ".../". |
const string16 kEllipsisAndSlash = UTF8ToUTF16(kEllipsis) + kForwardSlash; |
- int pixel_width_ellipsis_slash = font.GetStringWidth(kEllipsisAndSlash); |
+ int pixel_width_ellipsis_slash = measureStringWidth(kEllipsisAndSlash, |
+ font_or_paint, |
+ object_type); |
// Check with both subdomain and domain. |
string16 elided_path = ElideComponentizedPath(url_subdomain + url_domain, |
- url_path_elements, url_filename, url_query, font, available_pixel_width); |
+ url_path_elements, url_filename, url_query, font_or_paint, |
+ available_width, object_type); |
if (!elided_path.empty()) |
return elided_path; |
@@ -268,7 +371,7 @@ string16 ElideUrl(const GURL& url, |
} |
elided_path = ElideComponentizedPath(url_elided_domain, url_path_elements, |
- url_filename, url_query, font, available_pixel_width); |
+ url_filename, url_query, font_or_paint, available_width, object_type); |
if (!elided_path.empty()) |
return elided_path; |
@@ -276,24 +379,48 @@ string16 ElideUrl(const GURL& url, |
// Return elided domain/.../filename anyway. |
string16 final_elided_url_string(url_elided_domain); |
- int url_elided_domain_width = font.GetStringWidth(url_elided_domain); |
+ int url_elided_domain_width = measureStringWidth(url_elided_domain, |
+ font_or_paint, object_type); |
// A hack to prevent trailing ".../...". |
- if ((available_pixel_width - url_elided_domain_width) > |
+ if ((available_width - url_elided_domain_width) > |
pixel_width_ellipsis_slash + kPixelWidthDotsTrailer + |
- font.GetStringWidth(ASCIIToUTF16("UV"))) { |
+ measureStringWidth(ASCIIToUTF16("UV"), font_or_paint, object_type)) { |
final_elided_url_string += BuildPathFromComponents(string16(), |
url_path_elements, url_filename, 1); |
} else { |
final_elided_url_string += url_path; |
} |
- return ElideText(final_elided_url_string, font, available_pixel_width, false); |
+ return ElideText(final_elided_url_string, font_or_paint, available_width, |
+ false, object_type); |
+} |
+ |
+} // namespace |
+ |
+// Overloaded Function. |
+// Takes a Font object to measure the string width. |
+string16 ElideUrl(const GURL& url, |
+ const gfx::Font& font, |
+ int available_pixel_width, |
+ const std::string& languages) { |
+ return ElideUrl(url, (void* )&font, available_pixel_width, languages, |
+ GFX_Font); |
+} |
+ |
+// Overloaded Function. |
+// Takes a SkPaint object to measure the string width. |
+string16 ElideUrl(const GURL& url, |
+ const SkPaint paint, |
+ SkScalar available_point_width, |
+ const std::string& languages) { |
+ return ElideUrl(url, (void* )&paint, available_point_width, languages, |
+ Skia_Paint); |
} |
string16 ElideFilename(const FilePath& filename, |
const gfx::Font& font, |
- int available_pixel_width) { |
+ int available_width) { |
#if defined(OS_WIN) |
string16 filename_utf16 = filename.value(); |
string16 extension = filename.Extension(); |
@@ -308,12 +435,12 @@ string16 ElideFilename(const FilePath& filename, |
#endif |
int full_width = font.GetStringWidth(filename_utf16); |
- if (full_width <= available_pixel_width) |
+ if (full_width <= available_width) |
return base::i18n::GetDisplayStringInLTRDirectionality(filename_utf16); |
if (rootname.empty() || extension.empty()) { |
string16 elided_name = ElideText(filename_utf16, font, |
- available_pixel_width, false); |
+ available_width, false); |
return base::i18n::GetDisplayStringInLTRDirectionality(elided_name); |
} |
@@ -321,75 +448,42 @@ string16 ElideFilename(const FilePath& filename, |
int root_width = font.GetStringWidth(rootname); |
// We may have trimmed the path. |
- if (root_width + ext_width <= available_pixel_width) { |
+ if (root_width + ext_width <= available_width) { |
string16 elided_name = rootname + extension; |
return base::i18n::GetDisplayStringInLTRDirectionality(elided_name); |
} |
- if (ext_width >= available_pixel_width) { |
+ if (ext_width >= available_width) { |
string16 elided_name = ElideText(rootname + extension, font, |
- available_pixel_width, true); |
+ available_width, true); |
return base::i18n::GetDisplayStringInLTRDirectionality(elided_name); |
} |
- int available_root_width = available_pixel_width - ext_width; |
+ int available_root_width = available_width - ext_width; |
string16 elided_name = |
ElideText(rootname, font, available_root_width, false); |
elided_name += extension; |
return base::i18n::GetDisplayStringInLTRDirectionality(elided_name); |
} |
-// This function adds an ellipsis at the end of the text if the text |
-// does not fit the given pixel width. |
+// Overloaded function. |
+// Uses Font object to determine text width. |
string16 ElideText(const string16& text, |
const gfx::Font& font, |
int available_pixel_width, |
bool elide_in_middle) { |
- if (text.empty()) |
- return text; |
- |
- int current_text_pixel_width = font.GetStringWidth(text); |
- |
- // 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 && !text.empty()) { |
- return ElideText(CutString(text, text.length() / 2, elide_in_middle, false), |
- font, available_pixel_width, false); |
- } |
- |
- if (current_text_pixel_width <= available_pixel_width) |
- return text; |
- |
- if (font.GetStringWidth(UTF8ToUTF16(kEllipsis)) > available_pixel_width) |
- return string16(); |
- |
- // Use binary search to compute the elided text. |
- size_t lo = 0; |
- size_t hi = text.length() - 1; |
- for (size_t guess = (lo + hi) / 2; guess != lo; guess = (lo + hi) / 2) { |
- // We check the length of the whole desired string at once to ensure we |
- // handle kerning/ligatures/etc. correctly. |
- int guess_length = font.GetStringWidth( |
- CutString(text, guess, elide_in_middle, true)); |
- // Check again that we didn't hit a Pango width overflow. If so, cut the |
- // current string in half and start over. |
- if (guess_length <= 0) { |
- return ElideText(CutString(text, guess / 2, elide_in_middle, false), |
- font, available_pixel_width, elide_in_middle); |
- } |
- if (guess_length > available_pixel_width) |
- hi = guess; |
- else |
- lo = guess; |
- } |
+ return ElideText(text, (void* )&font, (SkScalar)available_pixel_width, |
dpapad
2011/07/19 20:34:01
Nit: No need for space in "(void* )", here and els
Aayush Kumar
2011/07/21 21:58:53
Done.
|
+ elide_in_middle, GFX_Font); |
+} |
- return CutString(text, lo, elide_in_middle, true); |
+// Overloaded function. |
+// Uses SkPaint object to determine text width. |
+string16 ElideText(const string16& text, |
+ const SkPaint paint, |
+ SkScalar available_point_width, |
+ bool elide_in_middle) { |
+ return ElideText(text, (void* )&paint, available_point_width, elide_in_middle, |
+ Skia_Paint); |
} |
SortedDisplayURL::SortedDisplayURL(const GURL& url, |