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

Unified Diff: ui/base/text/text_elider.cc

Issue 7348010: Added Header and Footer support using Skia (Closed) Base URL: http://git.chromium.org/git/chromium.git@trunk
Patch Set: Custom length strings being printed Created 9 years, 5 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 side-by-side diff with in-line comments
Download patch
« ui/base/text/text_elider.h ('K') | « ui/base/text/text_elider.h ('k') | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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,
« ui/base/text/text_elider.h ('K') | « ui/base/text/text_elider.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698