summaryrefslogtreecommitdiffstats
path: root/ui/base/text
diff options
context:
space:
mode:
authorasvitkine@chromium.org <asvitkine@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-12-12 19:58:18 +0000
committerasvitkine@chromium.org <asvitkine@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-12-12 19:58:18 +0000
commit9b6e452c3cefd6ae2c3cb199add3c43b20bae214 (patch)
tree7f382adc8d156068e45b9b9898bf3ae55c9cae2e /ui/base/text
parent8d1558d71bf32daa6d2f4639eea9eda0778a9705 (diff)
downloadchromium_src-9b6e452c3cefd6ae2c3cb199add3c43b20bae214.zip
chromium_src-9b6e452c3cefd6ae2c3cb199add3c43b20bae214.tar.gz
chromium_src-9b6e452c3cefd6ae2c3cb199add3c43b20bae214.tar.bz2
Change signature of |ui::ElideText()|. Add a truncate mode.
The new truncate mode is needed by my upcoming changes to rewrite CanvasSkia::DrawText(). Part of the change is changing the binary search code to a more traditional form that also makes the truncate mode work correctly. This is covered by the new unit tests. BUG=105550 TEST=New and existing tests in text_elider_unittest.cc. Review URL: http://codereview.chromium.org/8917011 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@114063 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'ui/base/text')
-rw-r--r--ui/base/text/text_elider.cc43
-rw-r--r--ui/base/text/text_elider.h16
-rw-r--r--ui/base/text/text_elider_unittest.cc35
3 files changed, 66 insertions, 28 deletions
diff --git a/ui/base/text/text_elider.cc b/ui/base/text/text_elider.cc
index 17f41c4..13ee279 100644
--- a/ui/base/text/text_elider.cc
+++ b/ui/base/text/text_elider.cc
@@ -94,7 +94,7 @@ string16 ElideComponentizedPath(const string16& url_path_prefix,
url_path_elements, url_filename, i);
if (available_pixel_width >= font.GetStringWidth(elided_path))
return ElideText(elided_path + url_query,
- font, available_pixel_width, false);
+ font, available_pixel_width, ui::ELIDE_AT_END);
}
return string16();
@@ -125,7 +125,7 @@ string16 ElideUrl(const GURL& url,
// 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, available_pixel_width, ui::ELIDE_AT_END);
// Now start eliding url_string to fit within available pixel width.
// Fist pass - check to see whether entire url_string fits.
@@ -142,7 +142,7 @@ 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);
+ return ElideText(url_string, font, available_pixel_width, ui::ELIDE_AT_END);
// Get Host.
string16 url_host = UTF8ToUTF16(url.host());
@@ -213,7 +213,7 @@ string16 ElideUrl(const GURL& url,
pixel_width_url_domain + pixel_width_url_path -
font.GetStringWidth(url_query))) {
return ElideText(url_subdomain + url_domain + url_path_query_etc,
- font, available_pixel_width, false);
+ font, available_pixel_width, ui::ELIDE_AT_END);
}
}
@@ -241,7 +241,7 @@ string16 ElideUrl(const GURL& url,
// 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);
+ available_pixel_width, ui::ELIDE_AT_END);
}
// Start eliding the path and replacing elements by ".../".
@@ -288,7 +288,8 @@ string16 ElideUrl(const GURL& url,
final_elided_url_string += url_path;
}
- return ElideText(final_elided_url_string, font, available_pixel_width, false);
+ return ElideText(final_elided_url_string, font, available_pixel_width,
+ ui::ELIDE_AT_END);
}
string16 ElideFilename(const FilePath& filename,
@@ -313,7 +314,7 @@ string16 ElideFilename(const FilePath& filename,
if (rootname.empty() || extension.empty()) {
string16 elided_name = ElideText(filename_utf16, font,
- available_pixel_width, false);
+ available_pixel_width, ui::ELIDE_AT_END);
return base::i18n::GetDisplayStringInLTRDirectionality(elided_name);
}
@@ -328,13 +329,14 @@ string16 ElideFilename(const FilePath& filename,
if (ext_width >= available_pixel_width) {
string16 elided_name = ElideText(rootname + extension, font,
- available_pixel_width, true);
+ available_pixel_width,
+ ui::ELIDE_IN_MIDDLE);
return base::i18n::GetDisplayStringInLTRDirectionality(elided_name);
}
int available_root_width = available_pixel_width - ext_width;
string16 elided_name =
- ElideText(rootname, font, available_root_width, false);
+ ElideText(rootname, font, available_root_width, ui::ELIDE_AT_END);
elided_name += extension;
return base::i18n::GetDisplayStringInLTRDirectionality(elided_name);
}
@@ -344,11 +346,13 @@ string16 ElideFilename(const FilePath& filename,
string16 ElideText(const string16& text,
const gfx::Font& font,
int available_pixel_width,
- bool elide_in_middle) {
+ ElideBehavior elide_behavior) {
if (text.empty())
return text;
int current_text_pixel_width = font.GetStringWidth(text);
+ bool elide_in_middle = (elide_behavior == ui::ELIDE_IN_MIDDLE);
+ bool insert_ellipsis = (elide_behavior != ui::TRUNCATE_AT_END);
// Pango will return 0 width for absurdly long strings. Cut the string in
// half and try again.
@@ -360,7 +364,7 @@ string16 ElideText(const string16& text,
// 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);
+ font, available_pixel_width, elide_behavior);
}
if (current_text_pixel_width <= available_pixel_width)
@@ -372,24 +376,25 @@ string16 ElideText(const string16& text,
// 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) {
+ size_t guess;
+ for (guess = (lo + hi) / 2; lo <= hi; 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));
+ string16 cut = CutString(text, guess, elide_in_middle, insert_ellipsis);
+ int guess_length = font.GetStringWidth(cut);
// 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);
+ font, available_pixel_width, elide_behavior);
}
if (guess_length > available_pixel_width)
- hi = guess;
+ hi = guess - 1;
else
- lo = guess;
+ lo = guess + 1;
}
- return CutString(text, lo, elide_in_middle, true);
+ return CutString(text, guess, elide_in_middle, insert_ellipsis);
}
SortedDisplayURL::SortedDisplayURL(const GURL& url,
@@ -576,6 +581,8 @@ class RectangleString {
// String onto which the output is accumulated.
string16* output_;
+
+ DISALLOW_COPY_AND_ASSIGN(RectangleString);
};
void RectangleString::AddString(const string16& input) {
diff --git a/ui/base/text/text_elider.h b/ui/base/text/text_elider.h
index 7b298ee..a1dd86a 100644
--- a/ui/base/text/text_elider.h
+++ b/ui/base/text/text_elider.h
@@ -40,13 +40,21 @@ UI_EXPORT string16 ElideUrl(const GURL& url,
int available_pixel_width,
const std::string& languages);
-// Elides |text| to fit in |available_pixel_width|. If |elide_in_middle| is
-// set the ellipsis is placed in the middle of the string; otherwise it is
-// placed at the end.
+enum ElideBehavior {
+ // Add ellipsis at the end of the string.
+ ELIDE_AT_END,
+ // Add ellipsis in the middle of the string.
+ ELIDE_IN_MIDDLE,
+ // Truncate the end of the string.
+ TRUNCATE_AT_END
+};
+
+// Elides |text| to fit in |available_pixel_width| according to the specified
+// |elide_behavior|.
UI_EXPORT string16 ElideText(const string16& text,
const gfx::Font& font,
int available_pixel_width,
- bool elide_in_middle);
+ ElideBehavior elide_behavior);
// Elide a filename to fit a given pixel width, with an emphasis on not hiding
// the extension unless we have to. If filename contains a path, the path will
diff --git a/ui/base/text/text_elider_unittest.cc b/ui/base/text/text_elider_unittest.cc
index 60ab1f7..b716a00 100644
--- a/ui/base/text/text_elider_unittest.cc
+++ b/ui/base/text/text_elider_unittest.cc
@@ -82,8 +82,7 @@ TEST(TextEliderTest, TestGeneralEliding) {
// both path AND file name to an ellipsis - ".../...". To avoid this result,
// there is a hack in place that simply treats them as one string in this
// case.
-TEST(TextEliderTest, TestTrailingEllipsisSlashEllipsisHack)
-{
+TEST(TextEliderTest, TestTrailingEllipsisSlashEllipsisHack) {
const std::string kEllipsisStr(kEllipsis);
// Very little space, would cause double ellipsis.
@@ -215,6 +214,29 @@ TEST(TextEliderTest, TestFilenameEliding) {
}
}
+TEST(TextEliderTest, ElideTextTruncate) {
+ const gfx::Font font;
+ const int kTestWidth = font.GetStringWidth(ASCIIToUTF16("Test"));
+ struct TestData {
+ const char* input;
+ int width;
+ const char* output;
+ } cases[] = {
+ { "", 0, "" },
+ { "Test", 0, "" },
+ { "", kTestWidth, "" },
+ { "Tes", kTestWidth, "Tes" },
+ { "Test", kTestWidth, "Test" },
+ { "Tests", kTestWidth, "Test" },
+ };
+
+ for (size_t i = 0; i < ARRAYSIZE_UNSAFE(cases); ++i) {
+ string16 result = ui::ElideText(UTF8ToUTF16(cases[i].input), font,
+ cases[i].width, ui::TRUNCATE_AT_END);
+ EXPECT_EQ(cases[i].output, UTF16ToUTF8(result));
+ }
+}
+
TEST(TextEliderTest, ElideTextLongStrings) {
const string16 kEllipsisStr = UTF8ToUTF16(kEllipsis);
string16 data_scheme(UTF8ToUTF16("data:text/plain,"));
@@ -247,9 +269,10 @@ TEST(TextEliderTest, ElideTextLongStrings) {
EXPECT_EQ(testcases_end[i].output.size(),
ElideText(testcases_end[i].input, font,
font.GetStringWidth(testcases_end[i].output),
- false).size());
+ ui::ELIDE_AT_END).size());
EXPECT_EQ(kEllipsisStr,
- ElideText(testcases_end[i].input, font, ellipsis_width, false));
+ ElideText(testcases_end[i].input, font, ellipsis_width,
+ ui::ELIDE_AT_END));
}
size_t number_of_trailing_as = (data_scheme_length + number_of_as) / 2;
@@ -271,10 +294,10 @@ TEST(TextEliderTest, ElideTextLongStrings) {
EXPECT_EQ(testcases_middle[i].output.size(),
ElideText(testcases_middle[i].input, font,
font.GetStringWidth(testcases_middle[i].output),
- false).size());
+ ui::ELIDE_AT_END).size());
EXPECT_EQ(kEllipsisStr,
ElideText(testcases_middle[i].input, font, ellipsis_width,
- false));
+ ui::ELIDE_AT_END));
}
}