summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorjianli@chromium.org <jianli@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-10-10 09:57:19 +0000
committerjianli@chromium.org <jianli@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-10-10 09:57:19 +0000
commit8ad3c5a758ba0d46bee600f559a7af88d3038ea6 (patch)
treefd317d0b10b4740b3c0965c14dedd0f945eaf675
parent51cc0bd3ab9e3e8d905d4fce624cd352e2d97915 (diff)
downloadchromium_src-8ad3c5a758ba0d46bee600f559a7af88d3038ea6.zip
chromium_src-8ad3c5a758ba0d46bee600f559a7af88d3038ea6.tar.gz
chromium_src-8ad3c5a758ba0d46bee600f559a7af88d3038ea6.tar.bz2
Uses and returns the fractional width in text eliding
On Mac, the width is repsented as CGFloat due to possible sub-pixel rendering and extra kerning. We need to return the fractional widt, instead of the integral width. Some tests have been updated with the hack removed. BUG=288987 TEST=new tests plus updating existing tests Review URL: https://codereview.chromium.org/24883002 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@227905 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r--ui/gfx/canvas.cc24
-rw-r--r--ui/gfx/canvas.h17
-rw-r--r--ui/gfx/canvas_android.cc12
-rw-r--r--ui/gfx/canvas_skia.cc18
-rw-r--r--ui/gfx/canvas_unittest_mac.mm50
-rw-r--r--ui/gfx/render_text.cc5
-rw-r--r--ui/gfx/render_text.h8
-rw-r--r--ui/gfx/render_text_mac.cc7
-rw-r--r--ui/gfx/render_text_mac.h3
-rw-r--r--ui/gfx/text_elider.cc139
-rw-r--r--ui/gfx/text_elider.h20
-rw-r--r--ui/gfx/text_elider_unittest.cc193
-rw-r--r--ui/gfx/text_utils.h4
-rw-r--r--ui/gfx/text_utils_android.cc5
-rw-r--r--ui/gfx/text_utils_ios.mm6
-rw-r--r--ui/gfx/text_utils_skia.cc4
16 files changed, 286 insertions, 229 deletions
diff --git a/ui/gfx/canvas.cc b/ui/gfx/canvas.cc
index eb0834b..69f10cf 100644
--- a/ui/gfx/canvas.cc
+++ b/ui/gfx/canvas.cc
@@ -4,6 +4,7 @@
#include "ui/gfx/canvas.h"
+#include <cmath>
#include <limits>
#include "base/i18n/rtl.h"
@@ -84,6 +85,21 @@ void Canvas::RecreateBackingCanvas(const Size& size,
// static
void Canvas::SizeStringInt(const base::string16& text,
+ const FontList& font_list,
+ int* width,
+ int* height,
+ int line_height,
+ int flags) {
+ float fractional_width = *width;
+ float factional_height = *height;
+ SizeStringFloat(text, font_list, &fractional_width,
+ &factional_height, line_height, flags);
+ *width = std::ceil(fractional_width);
+ *height = std::ceil(factional_height);
+}
+
+// static
+void Canvas::SizeStringInt(const base::string16& text,
const Font& font,
int* width,
int* height,
@@ -101,6 +117,14 @@ int Canvas::GetStringWidth(const base::string16& text,
}
// static
+float Canvas::GetStringWidthF(const base::string16& text,
+ const FontList& font_list) {
+ float width = 0, height = 0;
+ SizeStringFloat(text, font_list, &width, &height, 0, NO_ELLIPSIS);
+ return width;
+}
+
+// static
int Canvas::GetStringWidth(const base::string16& text, const Font& font) {
int width = 0, height = 0;
SizeStringInt(text, FontList(font), &width, &height, 0, NO_ELLIPSIS);
diff --git a/ui/gfx/canvas.h b/ui/gfx/canvas.h
index 9aa7a0a..4470023 100644
--- a/ui/gfx/canvas.h
+++ b/ui/gfx/canvas.h
@@ -139,6 +139,15 @@ class GFX_EXPORT Canvas {
int line_height,
int flags);
+ // This is same as SizeStringInt except that fractional size is returned.
+ // See comment in GetStringWidthF for its usage.
+ static void SizeStringFloat(const base::string16& text,
+ const FontList& font_list,
+ float* width,
+ float* height,
+ int line_height,
+ int flags);
+
// Returns the number of horizontal pixels needed to display the specified
// |text| with |font_list|.
static int GetStringWidth(const base::string16& text,
@@ -146,6 +155,14 @@ class GFX_EXPORT Canvas {
// Obsolete version. Use the above version which takes FontList.
static int GetStringWidth(const base::string16& text, const Font& font);
+ // This is same as GetStringWidth except that fractional width is returned.
+ // Use this method for the scenario that multiple string widths need to be
+ // summed up. This is because GetStringWidth returns the ceiled width and
+ // adding multiple ceiled widths could cause more precision loss for certain
+ // platform like Mac where the fractioal width is used.
+ static float GetStringWidthF(const base::string16& text,
+ const FontList& font_list);
+
// Returns the default text alignment to be used when drawing text on a
// Canvas based on the directionality of the system locale language.
// This function is used by Canvas::DrawStringInt when the text alignment
diff --git a/ui/gfx/canvas_android.cc b/ui/gfx/canvas_android.cc
index 54e45f7..61e3a3a 100644
--- a/ui/gfx/canvas_android.cc
+++ b/ui/gfx/canvas_android.cc
@@ -9,12 +9,12 @@
namespace gfx {
// static
-void Canvas::SizeStringInt(const base::string16& text,
- const FontList& font_list,
- int* width,
- int* height,
- int line_height,
- int flags) {
+void Canvas::SizeStringFloat(const base::string16& text,
+ const FontList& font_list,
+ float* width,
+ float* height,
+ int line_height,
+ int flags) {
NOTIMPLEMENTED();
}
diff --git a/ui/gfx/canvas_skia.cc b/ui/gfx/canvas_skia.cc
index ad15edd..c259232 100644
--- a/ui/gfx/canvas_skia.cc
+++ b/ui/gfx/canvas_skia.cc
@@ -155,11 +155,11 @@ void UpdateRenderText(const Rect& rect,
} // namespace
// static
-void Canvas::SizeStringInt(const base::string16& text,
- const FontList& font_list,
- int* width, int* height,
- int line_height,
- int flags) {
+void Canvas::SizeStringFloat(const base::string16& text,
+ const FontList& font_list,
+ float* width, float* height,
+ int line_height,
+ int flags) {
DCHECK_GE(*width, 0);
DCHECK_GE(*height, 0);
@@ -184,12 +184,12 @@ void Canvas::SizeStringInt(const base::string16& text,
UpdateRenderText(rect, base::string16(), font_list, flags, 0,
render_text.get());
- int h = 0;
- int w = 0;
+ float h = 0;
+ float w = 0;
for (size_t i = 0; i < strings.size(); ++i) {
StripAcceleratorChars(flags, &strings[i]);
render_text->SetText(strings[i]);
- const Size& string_size = render_text->GetStringSize();
+ const SizeF& string_size = render_text->GetStringSizeF();
w = std::max(w, string_size.width());
h += (i > 0 && line_height > 0) ? line_height : string_size.height();
}
@@ -208,7 +208,7 @@ void Canvas::SizeStringInt(const base::string16& text,
StripAcceleratorChars(flags, &adjusted_text);
UpdateRenderText(rect, adjusted_text, font_list, flags, 0,
render_text.get());
- const Size& string_size = render_text->GetStringSize();
+ const SizeF& string_size = render_text->GetStringSizeF();
*width = string_size.width();
*height = string_size.height();
}
diff --git a/ui/gfx/canvas_unittest_mac.mm b/ui/gfx/canvas_unittest_mac.mm
index d607218..7aff64b 100644
--- a/ui/gfx/canvas_unittest_mac.mm
+++ b/ui/gfx/canvas_unittest_mac.mm
@@ -18,25 +18,16 @@ namespace gfx {
namespace {
-// Mac-specific code for string size computations. This is a verbatim copy
-// of the old implementation that used to be in canvas_mac.mm.
-void CanvasMac_SizeStringInt(const base::string16& text,
- const FontList& font_list,
- int* width,
- int* height,
- int line_height,
- int flags) {
- DLOG_IF(WARNING, line_height != 0) << "Line heights not implemented.";
- DLOG_IF(WARNING, flags & Canvas::MULTI_LINE) << "Multi-line not implemented.";
-
+// Returns the pixel width of the string via calling the native method
+// -sizeWithAttributes.
+float GetStringNativeWidth(const base::string16& text,
+ const FontList& font_list) {
NSFont* native_font = font_list.GetPrimaryFont().GetNativeFont();
NSString* ns_string = base::SysUTF16ToNSString(text);
NSDictionary* attributes =
[NSDictionary dictionaryWithObject:native_font
forKey:NSFontAttributeName];
- NSSize string_size = [ns_string sizeWithAttributes:attributes];
- *width = std::ceil(string_size.width);
- *height = font_list.GetHeight();
+ return [ns_string sizeWithAttributes:attributes].width;
}
} // namespace
@@ -49,30 +40,31 @@ class CanvasTestMac : public testing::Test {
// without specified line height, since that is all the platform
// implementation supports.
void CompareSizes(const char* text) {
- const int kReallyLargeNumber = 12345678;
+ const float kReallyLargeNumber = 12345678;
FontList font_list(font_);
base::string16 text16 = base::UTF8ToUTF16(text);
- int mac_width = kReallyLargeNumber;
- int mac_height = kReallyLargeNumber;
- CanvasMac_SizeStringInt(text16, font_list, &mac_width, &mac_height, 0, 0);
+ float mac_width = GetStringNativeWidth(text16, font_list);
+ int mac_height = font_list.GetHeight();
- int canvas_width = kReallyLargeNumber;
- int canvas_height = kReallyLargeNumber;
- Canvas::SizeStringInt(
+ float canvas_width = kReallyLargeNumber;
+ float canvas_height = kReallyLargeNumber;
+ Canvas::SizeStringFloat(
text16, font_list, &canvas_width, &canvas_height, 0, 0);
EXPECT_NE(kReallyLargeNumber, mac_width) << "no width for " << text;
EXPECT_NE(kReallyLargeNumber, mac_height) << "no height for " << text;
EXPECT_EQ(mac_width, canvas_width) << " width for " << text;
- EXPECT_EQ(mac_height, canvas_height) << " height for " << text;
+ // FontList::GetHeight returns a truncated height.
+ EXPECT_EQ(mac_height,
+ static_cast<int>(canvas_height)) << " height for " << text;
}
private:
Font font_;
};
- // Tests that Canvas' SizeStringInt yields result consistent with a native
+ // Tests that Canvas' SizeStringFloat yields result consistent with a native
// implementation.
TEST_F(CanvasTestMac, StringSizeIdenticalForSkia) {
CompareSizes("");
@@ -81,4 +73,16 @@ class CanvasTestMac : public testing::Test {
CompareSizes("This is a complete sentence.");
}
+TEST_F(CanvasTestMac, FractionalWidth) {
+ const float kReallyLargeNumber = 12345678;
+ float width = kReallyLargeNumber;
+ float height = kReallyLargeNumber;
+
+ FontList font_list;
+ Canvas::SizeStringFloat(
+ base::UTF8ToUTF16("Test"), font_list, &width, &height, 0, 0);
+
+ EXPECT_GT(width, static_cast<int>(width));
+}
+
} // namespace gfx
diff --git a/ui/gfx/render_text.cc b/ui/gfx/render_text.cc
index 6e7fbda..fc8bad1 100644
--- a/ui/gfx/render_text.cc
+++ b/ui/gfx/render_text.cc
@@ -644,6 +644,11 @@ VisualCursorDirection RenderText::GetVisualDirectionOfLogicalEnd() {
CURSOR_RIGHT : CURSOR_LEFT;
}
+SizeF RenderText::GetStringSizeF() {
+ const Size size = GetStringSize();
+ return SizeF(size.width(), size.height());
+}
+
int RenderText::GetContentWidth() {
return GetStringSize().width() + (cursor_enabled_ ? 1 : 0);
}
diff --git a/ui/gfx/render_text.h b/ui/gfx/render_text.h
index df23ff3..ce0a027 100644
--- a/ui/gfx/render_text.h
+++ b/ui/gfx/render_text.h
@@ -25,6 +25,7 @@
#include "ui/gfx/rect.h"
#include "ui/gfx/selection_model.h"
#include "ui/gfx/shadow_value.h"
+#include "ui/gfx/size_f.h"
#include "ui/gfx/text_constants.h"
#include "ui/gfx/vector2d.h"
@@ -326,6 +327,13 @@ class GFX_EXPORT RenderText {
// shadows.
virtual Size GetStringSize() = 0;
+ // This is same as GetStringSize except that fractional size is returned.
+ // The default implementation is same as GetStringSize. Certain platforms that
+ // compute the text size as floating-point values, like Mac, will override
+ // this method.
+ // See comment in Canvas::GetStringWidthF for its usage.
+ virtual SizeF GetStringSizeF();
+
// Returns the width of the content (which is the wrapped width in multiline
// mode). Reserves room for the cursor if |cursor_enabled_| is true.
int GetContentWidth();
diff --git a/ui/gfx/render_text_mac.cc b/ui/gfx/render_text_mac.cc
index 2fcea01..d86975d 100644
--- a/ui/gfx/render_text_mac.cc
+++ b/ui/gfx/render_text_mac.cc
@@ -25,6 +25,11 @@ RenderTextMac::~RenderTextMac() {
Size RenderTextMac::GetStringSize() {
EnsureLayout();
+ return Size(std::ceil(string_size_.width()), string_size_.height());
+}
+
+SizeF RenderTextMac::GetStringSizeF() {
+ EnsureLayout();
return string_size_;
}
@@ -149,7 +154,7 @@ void RenderTextMac::EnsureLayout() {
CGFloat font_list_baseline = font_list().GetBaseline();
ascent = std::max(ascent, font_list_baseline);
descent = std::max(descent, font_list_height - font_list_baseline);
- string_size_ = Size(std::ceil(width), ascent + descent + leading);
+ string_size_ = SizeF(width, ascent + descent + leading);
common_baseline_ = ascent;
}
diff --git a/ui/gfx/render_text_mac.h b/ui/gfx/render_text_mac.h
index be5f128..3d25430 100644
--- a/ui/gfx/render_text_mac.h
+++ b/ui/gfx/render_text_mac.h
@@ -27,6 +27,7 @@ class RenderTextMac : public RenderText {
// Overridden from RenderText:
virtual Size GetStringSize() OVERRIDE;
+ virtual SizeF GetStringSizeF() OVERRIDE;
virtual int GetBaseline() OVERRIDE;
virtual SelectionModel FindCursorPosition(const Point& point) OVERRIDE;
virtual std::vector<FontSpan> GetFontSpansForTesting() OVERRIDE;
@@ -81,7 +82,7 @@ class RenderTextMac : public RenderText {
base::ScopedCFTypeRef<CFMutableArrayRef> attributes_;
// Visual dimensions of the text. Computed by |EnsureLayout()|.
- Size string_size_;
+ SizeF string_size_;
// Common baseline for this line of text. Computed by |EnsureLayout()|.
SkScalar common_baseline_;
diff --git a/ui/gfx/text_elider.cc b/ui/gfx/text_elider.cc
index bc4eb3b..9fec05f 100644
--- a/ui/gfx/text_elider.cc
+++ b/ui/gfx/text_elider.cc
@@ -129,15 +129,15 @@ string16 ElideComponentizedPath(const string16& url_path_prefix,
const std::vector<string16>& url_path_elements,
const string16& url_filename,
const string16& url_query,
- const gfx::FontList& font_list,
- int available_pixel_width) {
+ const FontList& font_list,
+ float available_pixel_width) {
const size_t url_path_number_of_elements = url_path_elements.size();
CHECK(url_path_number_of_elements);
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 >= gfx::GetStringWidth(elided_path, font_list))
+ if (available_pixel_width >= GetStringWidthF(elided_path, font_list))
return ElideText(elided_path + url_query, font_list,
available_pixel_width, ELIDE_AT_END);
}
@@ -148,9 +148,9 @@ string16 ElideComponentizedPath(const string16& url_path_prefix,
} // namespace
string16 ElideEmail(const string16& email,
- const gfx::FontList& font_list,
- int available_pixel_width) {
- if (gfx::GetStringWidth(email, font_list) <= available_pixel_width)
+ 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
@@ -167,24 +167,24 @@ string16 ElideEmail(const string16& email,
// Subtract the @ symbol from the available width as it is mandatory.
const string16 kAtSignUTF16 = ASCIIToUTF16("@");
- available_pixel_width -= gfx::GetStringWidth(kAtSignUTF16, font_list);
+ 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 int full_username_width = gfx::GetStringWidth(username, font_list);
- const int available_domain_width =
+ const float full_username_width = GetStringWidthF(username, font_list);
+ const float available_domain_width =
available_pixel_width -
std::min(full_username_width,
- gfx::GetStringWidth(username.substr(0, 1) + kEllipsisUTF16,
- font_list));
- if (gfx::GetStringWidth(domain, font_list) > available_domain_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 int desired_domain_width =
+ const float desired_domain_width =
std::min(available_domain_width,
std::max(available_pixel_width - full_username_width,
available_pixel_width / 2));
@@ -199,7 +199,7 @@ string16 ElideEmail(const string16& email,
// 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 -= gfx::GetStringWidth(domain, font_list);
+ available_pixel_width -= GetStringWidthF(domain, font_list);
username = ElideText(username, font_list, available_pixel_width,
ELIDE_AT_END);
@@ -207,9 +207,9 @@ string16 ElideEmail(const string16& email,
}
string16 ElideEmail(const string16& email,
- const gfx::Font& font,
- int available_pixel_width) {
- return ElideEmail(email, gfx::FontList(font), available_pixel_width);
+ const Font& font,
+ float available_pixel_width) {
+ return ElideEmail(email, FontList(font), available_pixel_width);
}
// TODO(pkasting): http://crbug.com/77883 This whole function gets
@@ -217,8 +217,8 @@ string16 ElideEmail(const string16& email,
// a rendered string is always the sum of the widths of its substrings. Also I
// suspect it could be made simpler.
string16 ElideUrl(const GURL& url,
- const gfx::FontList& font_list,
- int available_pixel_width,
+ const FontList& font_list,
+ float available_pixel_width,
const std::string& languages) {
// Get a formatted string and corresponding parsing of the url.
url_parse::Parsed parsed;
@@ -235,7 +235,7 @@ string16 ElideUrl(const GURL& url,
// Now start eliding url_string to fit within available pixel width.
// Fist pass - check to see whether entire url_string fits.
- const int pixel_width_url_string = gfx::GetStringWidth(url_string, font_list);
+ const float pixel_width_url_string = GetStringWidthF(url_string, font_list);
if (available_pixel_width >= pixel_width_url_string)
return url_string;
@@ -248,7 +248,7 @@ string16 ElideUrl(const GURL& url,
// Return general elided text if url minus the query fits.
const string16 url_minus_query =
url_string.substr(0, path_start_index + path_len);
- if (available_pixel_width >= gfx::GetStringWidth(url_minus_query, font_list))
+ if (available_pixel_width >= GetStringWidthF(url_minus_query, font_list))
return ElideText(url_string, font_list, available_pixel_width,
ELIDE_AT_END);
@@ -298,17 +298,17 @@ string16 ElideUrl(const GURL& url,
}
// Second Pass - remove scheme - the rest fits.
- const int pixel_width_url_host = gfx::GetStringWidth(url_host, font_list);
- const int pixel_width_url_path = gfx::GetStringWidth(url_path_query_etc,
- font_list);
+ const float pixel_width_url_host = GetStringWidthF(url_host, font_list);
+ const float pixel_width_url_path = GetStringWidthF(url_path_query_etc,
+ font_list);
if (available_pixel_width >=
pixel_width_url_host + pixel_width_url_path)
return url_host + url_path_query_etc;
// Third Pass: Subdomain, domain and entire path fits.
- const int pixel_width_url_domain = gfx::GetStringWidth(url_domain, font_list);
- const int pixel_width_url_subdomain = gfx::GetStringWidth(url_subdomain,
- font_list);
+ const float pixel_width_url_domain = GetStringWidthF(url_domain, font_list);
+ const float pixel_width_url_subdomain =
+ GetStringWidthF(url_subdomain, font_list);
if (available_pixel_width >=
pixel_width_url_subdomain + pixel_width_url_domain +
pixel_width_url_path)
@@ -316,13 +316,13 @@ string16 ElideUrl(const GURL& url,
// Query element.
string16 url_query;
- const int kPixelWidthDotsTrailer = gfx::GetStringWidth(
+ const float kPixelWidthDotsTrailer = GetStringWidthF(
string16(kEllipsisUTF16), font_list);
if (parsed.query.is_nonempty()) {
url_query = UTF8ToUTF16("?") + url_string.substr(parsed.query.begin);
if (available_pixel_width >=
(pixel_width_url_subdomain + pixel_width_url_domain +
- pixel_width_url_path - gfx::GetStringWidth(url_query, font_list))) {
+ pixel_width_url_path - GetStringWidthF(url_query, font_list))) {
return ElideText(url_subdomain + url_domain + url_path_query_etc,
font_list, available_pixel_width, ELIDE_AT_END);
}
@@ -357,8 +357,8 @@ string16 ElideUrl(const GURL& url,
// Start eliding the path and replacing elements by ".../".
const string16 kEllipsisAndSlash = string16(kEllipsisUTF16) + kForwardSlash;
- const int pixel_width_ellipsis_slash = gfx::GetStringWidth(kEllipsisAndSlash,
- font_list);
+ const float pixel_width_ellipsis_slash =
+ GetStringWidthF(kEllipsisAndSlash, font_list);
// Check with both subdomain and domain.
string16 elided_path =
@@ -390,13 +390,13 @@ string16 ElideUrl(const GURL& url,
// Return elided domain/.../filename anyway.
string16 final_elided_url_string(url_elided_domain);
- const int url_elided_domain_width = gfx::GetStringWidth(url_elided_domain,
- font_list);
+ const float url_elided_domain_width = GetStringWidthF(url_elided_domain,
+ font_list);
// A hack to prevent trailing ".../...".
if ((available_pixel_width - url_elided_domain_width) >
pixel_width_ellipsis_slash + kPixelWidthDotsTrailer +
- gfx::GetStringWidth(ASCIIToUTF16("UV"), font_list)) {
+ GetStringWidthF(ASCIIToUTF16("UV"), font_list)) {
final_elided_url_string += BuildPathFromComponents(string16(),
url_path_elements, url_filename, 1);
} else {
@@ -408,15 +408,15 @@ string16 ElideUrl(const GURL& url,
}
string16 ElideUrl(const GURL& url,
- const gfx::Font& font,
- int available_pixel_width,
+ const Font& font,
+ float available_pixel_width,
const std::string& languages) {
- return ElideUrl(url, gfx::FontList(font), available_pixel_width, languages);
+ return ElideUrl(url, FontList(font), available_pixel_width, languages);
}
string16 ElideFilename(const base::FilePath& filename,
- const gfx::FontList& font_list,
- int available_pixel_width) {
+ const FontList& font_list,
+ float available_pixel_width) {
#if defined(OS_WIN)
string16 filename_utf16 = filename.value();
string16 extension = filename.Extension();
@@ -430,7 +430,7 @@ string16 ElideFilename(const base::FilePath& filename,
filename.BaseName().RemoveExtension().value()));
#endif
- const int full_width = gfx::GetStringWidth(filename_utf16, font_list);
+ const float full_width = GetStringWidthF(filename_utf16, font_list);
if (full_width <= available_pixel_width)
return base::i18n::GetDisplayStringInLTRDirectionality(filename_utf16);
@@ -440,8 +440,8 @@ string16 ElideFilename(const base::FilePath& filename,
return base::i18n::GetDisplayStringInLTRDirectionality(elided_name);
}
- const int ext_width = gfx::GetStringWidth(extension, font_list);
- const int root_width = gfx::GetStringWidth(rootname, font_list);
+ const float ext_width = GetStringWidthF(extension, font_list);
+ const float root_width = GetStringWidthF(rootname, font_list);
// We may have trimmed the path.
if (root_width + ext_width <= available_pixel_width) {
@@ -456,7 +456,7 @@ string16 ElideFilename(const base::FilePath& filename,
return base::i18n::GetDisplayStringInLTRDirectionality(elided_name);
}
- int available_root_width = available_pixel_width - ext_width;
+ float available_root_width = available_pixel_width - ext_width;
string16 elided_name =
ElideText(rootname, font_list, available_root_width, ELIDE_AT_END);
elided_name += extension;
@@ -464,19 +464,19 @@ string16 ElideFilename(const base::FilePath& filename,
}
string16 ElideFilename(const base::FilePath& filename,
- const gfx::Font& font,
- int available_pixel_width) {
- return ElideFilename(filename, gfx::FontList(font), available_pixel_width);
+ const Font& font,
+ float available_pixel_width) {
+ return ElideFilename(filename, FontList(font), available_pixel_width);
}
string16 ElideText(const string16& text,
- const gfx::FontList& font_list,
- int available_pixel_width,
+ const FontList& font_list,
+ float available_pixel_width,
ElideBehavior elide_behavior) {
if (text.empty())
return text;
- const int current_text_pixel_width = gfx::GetStringWidth(text, font_list);
+ const float current_text_pixel_width = GetStringWidthF(text, font_list);
const bool elide_in_middle = (elide_behavior == ELIDE_IN_MIDDLE);
const bool insert_ellipsis = (elide_behavior != TRUNCATE_AT_END);
@@ -500,7 +500,7 @@ string16 ElideText(const string16& text,
return text;
if (insert_ellipsis &&
- gfx::GetStringWidth(ellipsis, font_list) > available_pixel_width)
+ GetStringWidthF(ellipsis, font_list) > available_pixel_width)
return string16();
// Use binary search to compute the elided text.
@@ -511,7 +511,7 @@ string16 ElideText(const string16& text,
// We check the length of the whole desired string at once to ensure we
// handle kerning/ligatures/etc. correctly.
const string16 cut = slicer.CutString(guess, insert_ellipsis);
- const int guess_length = gfx::GetStringWidth(cut, font_list);
+ const float guess_length = GetStringWidthF(cut, font_list);
// 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) {
@@ -528,11 +528,10 @@ string16 ElideText(const string16& text,
}
string16 ElideText(const string16& text,
- const gfx::Font& font,
- int available_pixel_width,
+ const Font& font,
+ float available_pixel_width,
ElideBehavior elide_behavior) {
- return ElideText(text, gfx::FontList(font), available_pixel_width,
- elide_behavior);
+ return ElideText(text, FontList(font), available_pixel_width, elide_behavior);
}
SortedDisplayURL::SortedDisplayURL(const GURL& url,
@@ -809,8 +808,8 @@ void RectangleString::NewLine(bool output) {
// can be broken into smaller methods sharing this state.
class RectangleText {
public:
- RectangleText(const gfx::FontList& font_list,
- int available_pixel_width,
+ RectangleText(const FontList& font_list,
+ float available_pixel_width,
int available_pixel_height,
WordWrapBehavior wrap_behavior,
std::vector<string16>* lines)
@@ -859,7 +858,7 @@ class RectangleText {
// Append the specified |text| to the current output line, incrementing the
// running width by the specified amount. This is an optimization over
// |AddToCurrentLine()| when |text_width| is already known.
- void AddToCurrentLineWithWidth(const string16& text, int text_width);
+ void AddToCurrentLineWithWidth(const string16& text, float text_width);
// Append the specified |text| to the current output line.
void AddToCurrentLine(const string16& text);
@@ -868,13 +867,13 @@ class RectangleText {
bool NewLine();
// The font list used for measuring text width.
- const gfx::FontList& font_list_;
+ const FontList& font_list_;
// The height of each line of text.
const int line_height_;
// The number of pixels of available width in the rectangle.
- const int available_pixel_width_;
+ const float available_pixel_width_;
// The number of pixels of available height in the rectangle.
const int available_pixel_height_;
@@ -883,7 +882,7 @@ class RectangleText {
const WordWrapBehavior wrap_behavior_;
// The current running width.
- int current_width_;
+ float current_width_;
// The current running height.
int current_height_;
@@ -941,7 +940,7 @@ int RectangleText::Finalize() {
}
void RectangleText::AddLine(const string16& line) {
- const int line_width = gfx::GetStringWidth(line, font_list_);
+ const float line_width = GetStringWidthF(line, font_list_);
if (line_width <= available_pixel_width_) {
AddToCurrentLineWithWidth(line, line_width);
} else {
@@ -1028,7 +1027,7 @@ int RectangleText::AddWord(const string16& word) {
int lines_added = 0;
string16 trimmed;
TrimWhitespace(word, TRIM_TRAILING, &trimmed);
- const int trimmed_width = gfx::GetStringWidth(trimmed, font_list_);
+ const float trimmed_width = GetStringWidthF(trimmed, font_list_);
if (trimmed_width <= available_pixel_width_) {
// Word can be made to fit, no need to fragment it.
if ((current_width_ + trimmed_width > available_pixel_width_) && NewLine())
@@ -1043,11 +1042,11 @@ int RectangleText::AddWord(const string16& word) {
}
void RectangleText::AddToCurrentLine(const string16& text) {
- AddToCurrentLineWithWidth(text, gfx::GetStringWidth(text, font_list_));
+ AddToCurrentLineWithWidth(text, GetStringWidthF(text, font_list_));
}
void RectangleText::AddToCurrentLineWithWidth(const string16& text,
- int text_width) {
+ float text_width) {
if (current_height_ >= available_pixel_height_) {
insufficient_height_ = true;
return;
@@ -1081,8 +1080,8 @@ bool ElideRectangleString(const string16& input, size_t max_rows,
}
int ElideRectangleText(const string16& input,
- const gfx::FontList& font_list,
- int available_pixel_width,
+ const FontList& font_list,
+ float available_pixel_width,
int available_pixel_height,
WordWrapBehavior wrap_behavior,
std::vector<string16>* lines) {
@@ -1097,12 +1096,12 @@ int ElideRectangleText(const string16& input,
}
int ElideRectangleText(const string16& input,
- const gfx::Font& font,
- int available_pixel_width,
+ const Font& font,
+ float available_pixel_width,
int available_pixel_height,
WordWrapBehavior wrap_behavior,
std::vector<string16>* lines) {
- return ElideRectangleText(input, gfx::FontList(font),
+ return ElideRectangleText(input, FontList(font),
available_pixel_width, available_pixel_height,
wrap_behavior, lines);
}
diff --git a/ui/gfx/text_elider.h b/ui/gfx/text_elider.h
index ff0cef0..8ea1921 100644
--- a/ui/gfx/text_elider.h
+++ b/ui/gfx/text_elider.h
@@ -41,11 +41,11 @@ GFX_EXPORT extern const char16 kEllipsisUTF16[];
// extra width).
GFX_EXPORT string16 ElideEmail(const string16& email,
const gfx::FontList& font_list,
- int available_pixel_width);
+ float available_pixel_width);
// Obsolete version. Use the above version which takes gfx::FontList.
GFX_EXPORT string16 ElideEmail(const string16& email,
const gfx::Font& font,
- int available_pixel_width);
+ float available_pixel_width);
// This function takes a GURL object and elides it. It returns a string
// which composed of parts from subdomain, domain, path, filename and query.
@@ -63,12 +63,12 @@ GFX_EXPORT string16 ElideEmail(const string16& email,
// http://crbug.com/6487 for more information.
GFX_EXPORT string16 ElideUrl(const GURL& url,
const gfx::FontList& font_list,
- int available_pixel_width,
+ float available_pixel_width,
const std::string& languages);
// Obsolete version. Use the above version which takes gfx::FontList.
GFX_EXPORT string16 ElideUrl(const GURL& url,
const gfx::Font& font,
- int available_pixel_width,
+ float available_pixel_width,
const std::string& languages);
enum ElideBehavior {
@@ -84,12 +84,12 @@ enum ElideBehavior {
// |elide_behavior|.
GFX_EXPORT string16 ElideText(const string16& text,
const gfx::FontList& font_list,
- int available_pixel_width,
+ float available_pixel_width,
ElideBehavior elide_behavior);
// Obsolete version. Use the above version which takes gfx::FontList.
GFX_EXPORT string16 ElideText(const string16& text,
const gfx::Font& font,
- int available_pixel_width,
+ float available_pixel_width,
ElideBehavior elide_behavior);
// Elide a filename to fit a given pixel width, with an emphasis on not hiding
@@ -100,11 +100,11 @@ GFX_EXPORT string16 ElideText(const string16& text,
// PDF (Pop Directional Formatting) mark.
GFX_EXPORT string16 ElideFilename(const base::FilePath& filename,
const gfx::FontList& font_list,
- int available_pixel_width);
+ float available_pixel_width);
// Obsolete version. Use the above version which takes gfx::FontList.
GFX_EXPORT string16 ElideFilename(const base::FilePath& filename,
const gfx::Font& font,
- int available_pixel_width);
+ float available_pixel_width);
// SortedDisplayURL maintains a string from a URL suitable for display to the
// use. SortedDisplayURL also provides a function used for comparing two
@@ -208,14 +208,14 @@ enum ReformattingResultFlags {
// leading to elision or truncation (and not just reformatting).
GFX_EXPORT int ElideRectangleText(const string16& text,
const gfx::FontList& font_list,
- int available_pixel_width,
+ float available_pixel_width,
int available_pixel_height,
WordWrapBehavior wrap_behavior,
std::vector<string16>* lines);
// Obsolete version. Use the above version which takes gfx::FontList.
GFX_EXPORT int ElideRectangleText(const string16& text,
const gfx::Font& font,
- int available_pixel_width,
+ float available_pixel_width,
int available_pixel_height,
WordWrapBehavior wrap_behavior,
std::vector<string16>* lines);
diff --git a/ui/gfx/text_elider_unittest.cc b/ui/gfx/text_elider_unittest.cc
index 2a90e5d..6b1a4e3 100644
--- a/ui/gfx/text_elider_unittest.cc
+++ b/ui/gfx/text_elider_unittest.cc
@@ -13,6 +13,8 @@
#include "base/strings/utf_string_conversions.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "ui/gfx/font.h"
+#include "ui/gfx/font_list.h"
+#include "ui/gfx/text_utils.h"
#include "url/gurl.h"
namespace gfx {
@@ -41,36 +43,22 @@ struct TestData {
};
void RunUrlTest(Testcase* testcases, size_t num_testcases) {
- static const gfx::Font font;
+ static const FontList font_list;
for (size_t i = 0; i < num_testcases; ++i) {
const GURL url(testcases[i].input);
// Should we test with non-empty language list?
// That's kinda redundant with net_util_unittests.
+ const float available_width =
+ GetStringWidthF(UTF8ToUTF16(testcases[i].output), font_list);
EXPECT_EQ(UTF8ToUTF16(testcases[i].output),
- ElideUrl(url, font,
- font.GetStringWidth(UTF8ToUTF16(testcases[i].output)),
- std::string()));
+ ElideUrl(url, font_list, available_width, std::string()));
}
}
-gfx::Font GetTestingFont() {
- gfx::Font font;
-#if defined(OS_MACOSX)
- // Use a specific font for certain tests on Mac.
- // 1) Different Mac machines might be configured with different default font.
- // The number of extra pixels needed to make ElideEmail/TestFilenameEliding
- // tests work might vary per the default font.
- // 2) This specific font helps expose the line width exceeding problem as in
- // ElideRectangleTextCheckLineWidth.
- font = gfx::Font("LucidaGrande", 12);
-#endif
- return font;
-}
-
} // namespace
-// TODO(ios): Complex eliding is off by one for some of those tests on iOS.
-// See crbug.com/154019
+// TODO(ios): This test fails on iOS because iOS version of GetStringWidthF
+// that calls [NSString sizeWithFont] returns the rounded string width.
#if defined(OS_IOS)
#define MAYBE_ElideEmail DISABLED_ElideEmail
#else
@@ -121,22 +109,14 @@ TEST(TextEliderTest, MAYBE_ElideEmail) {
{"mmmmm@llllllllll", "m" + kEllipsisStr + "@l" + kEllipsisStr},
};
- const gfx::Font font = GetTestingFont();
+ const FontList font_list;
for (size_t i = 0; i < arraysize(testcases); ++i) {
const string16 expected_output = UTF8ToUTF16(testcases[i].output);
- int available_width = font.GetStringWidth(expected_output);
-#if defined(OS_MACOSX)
- // Give two extra pixels to offset the ceiling width returned by
- // GetStringWidth on Mac. This workaround will no longer be needed once
- // the floating point width is adopted (http://crbug.com/288987).
- // Note that we need one more pixel than TestFilenameEliding because
- // multiple strings are elided and we need to offset more.
- available_width += 2;
-#endif
EXPECT_EQ(expected_output,
- ElideEmail(UTF8ToUTF16(testcases[i].input),
- font,
- available_width));
+ ElideEmail(
+ UTF8ToUTF16(testcases[i].input),
+ font_list,
+ GetStringWidthF(expected_output, font_list)));
}
}
@@ -153,7 +133,7 @@ TEST(TextEliderTest, ElideEmailMoreSpace) {
"supermegalongusername@withasuperlonnnggggdomain.gouv.qc.ca",
};
- const gfx::Font font;
+ const Font font;
for (size_t i = 0; i < arraysize(test_width_factors); ++i) {
const int test_width = test_width_factors[i] *
font.GetAverageCharacterWidth();
@@ -199,23 +179,26 @@ TEST(TextEliderTest, TestTrailingEllipsisSlashEllipsisHack) {
const std::string kEllipsisStr(kEllipsis);
// Very little space, would cause double ellipsis.
- gfx::Font font;
+ FontList font_list;
GURL url("http://battersbox.com/directory/foo/peter_paul_and_mary.html");
- int available_width = font.GetStringWidth(
- UTF8ToUTF16("battersbox.com/" + kEllipsisStr + "/" + kEllipsisStr));
+ float available_width = GetStringWidthF(
+ UTF8ToUTF16("battersbox.com/" + kEllipsisStr + "/" + kEllipsisStr),
+ font_list);
// Create the expected string, after elision. Depending on font size, the
// directory might become /dir... or /di... or/d... - it never should be
// shorter than that. (If it is, the font considers d... to be longer
// than .../... - that should never happen).
- ASSERT_GT(font.GetStringWidth(UTF8ToUTF16(kEllipsisStr + "/" + kEllipsisStr)),
- font.GetStringWidth(UTF8ToUTF16("d" + kEllipsisStr)));
+ ASSERT_GT(GetStringWidthF(UTF8ToUTF16(kEllipsisStr + "/" + kEllipsisStr),
+ font_list),
+ GetStringWidthF(UTF8ToUTF16("d" + kEllipsisStr), font_list));
GURL long_url("http://battersbox.com/directorynameisreallylongtoforcetrunc");
- string16 expected = ElideUrl(long_url, font, available_width, std::string());
+ string16 expected =
+ ElideUrl(long_url, font_list, available_width, std::string());
// Ensure that the expected result still contains part of the directory name.
ASSERT_GT(expected.length(), std::string("battersbox.com/d").length());
EXPECT_EQ(expected,
- ElideUrl(url, font, available_width, std::string()));
+ ElideUrl(url, font_list, available_width, std::string()));
// More space available - elide directories, partially elide filename.
Testcase testcases[] = {
@@ -288,8 +271,8 @@ TEST(TextEliderTest, TestFileURLEliding) {
RunUrlTest(testcases, arraysize(testcases));
}
-// TODO(ios): Complex eliding is off by one for some of those tests on iOS.
-// See crbug.com/154019
+// TODO(ios): This test fails on iOS because iOS version of GetStringWidthF
+// that calls [NSString sizeWithFont] returns the rounded string width.
#if defined(OS_IOS)
#define MAYBE_TestFilenameEliding DISABLED_TestFilenameEliding
#else
@@ -334,28 +317,22 @@ TEST(TextEliderTest, MAYBE_TestFilenameEliding) {
"file.name.re" + kEllipsisStr + "emelylongext"}
};
- static const gfx::Font font = GetTestingFont();
+ static const FontList font_list;
for (size_t i = 0; i < arraysize(testcases); ++i) {
base::FilePath filepath(testcases[i].input);
string16 expected = UTF8ToUTF16(testcases[i].output);
expected = base::i18n::GetDisplayStringInLTRDirectionality(expected);
- int available_width = font.GetStringWidth(UTF8ToUTF16(testcases[i].output));
-#if defined(OS_MACOSX)
- // Give one extra pixel to offset the ceiling width returned by
- // GetStringWidth on Mac. This workaround will no longer be needed once
- // the floating point width is adopted (http://crbug.com/288987).
- available_width += 1;
-#endif
- EXPECT_EQ(expected, ElideFilename(filepath, font, available_width));
+ EXPECT_EQ(expected, ElideFilename(filepath, font_list,
+ GetStringWidthF(UTF8ToUTF16(testcases[i].output), font_list)));
}
}
TEST(TextEliderTest, ElideTextTruncate) {
- const gfx::Font font;
- const int kTestWidth = font.GetStringWidth(ASCIIToUTF16("Test"));
+ const FontList font_list;
+ const float kTestWidth = GetStringWidthF(ASCIIToUTF16("Test"), font_list);
struct TestData {
const char* input;
- int width;
+ float width;
const char* output;
} cases[] = {
{ "", 0, "" },
@@ -367,20 +344,21 @@ TEST(TextEliderTest, ElideTextTruncate) {
};
for (size_t i = 0; i < ARRAYSIZE_UNSAFE(cases); ++i) {
- string16 result = ElideText(UTF8ToUTF16(cases[i].input), font,
+ string16 result = ElideText(UTF8ToUTF16(cases[i].input), font_list,
cases[i].width, TRUNCATE_AT_END);
EXPECT_EQ(cases[i].output, UTF16ToUTF8(result));
}
}
TEST(TextEliderTest, ElideTextEllipsis) {
- const gfx::Font font;
- const int kTestWidth = font.GetStringWidth(ASCIIToUTF16("Test"));
+ const FontList font_list;
+ const float kTestWidth = GetStringWidthF(ASCIIToUTF16("Test"), font_list);
const char* kEllipsis = "\xE2\x80\xA6";
- const int kEllipsisWidth = font.GetStringWidth(UTF8ToUTF16(kEllipsis));
+ const float kEllipsisWidth =
+ GetStringWidthF(UTF8ToUTF16(kEllipsis), font_list);
struct TestData {
const char* input;
- int width;
+ float width;
const char* output;
} cases[] = {
{ "", 0, "" },
@@ -392,7 +370,7 @@ TEST(TextEliderTest, ElideTextEllipsis) {
};
for (size_t i = 0; i < ARRAYSIZE_UNSAFE(cases); ++i) {
- string16 result = ElideText(UTF8ToUTF16(cases[i].input), font,
+ string16 result = ElideText(UTF8ToUTF16(cases[i].input), font_list,
cases[i].width, ELIDE_AT_END);
EXPECT_EQ(cases[i].output, UTF16ToUTF8(result));
}
@@ -418,27 +396,27 @@ static void CheckSurrogatePairs(const string16& text,
}
TEST(TextEliderTest, ElideTextSurrogatePairs) {
- const gfx::Font font;
+ const FontList font_list;
// The below is 'MUSICAL SYMBOL G CLEF', which is represented in UTF-16 as
// two characters forming a surrogate pair 0x0001D11E.
const std::string kSurrogate = "\xF0\x9D\x84\x9E";
const string16 kTestString =
UTF8ToUTF16(kSurrogate + "ab" + kSurrogate + kSurrogate + "cd");
- const int kTestStringWidth = font.GetStringWidth(kTestString);
+ const float kTestStringWidth = GetStringWidthF(kTestString, font_list);
const char16 kSurrogateFirstChar = kTestString[0];
const char16 kSurrogateSecondChar = kTestString[1];
string16 result;
// Elide |kTextString| to all possible widths and check that no instance of
// |kSurrogate| was split in two.
- for (int width = 0; width <= kTestStringWidth; width++) {
- result = ElideText(kTestString, font, width, TRUNCATE_AT_END);
+ for (float width = 0; width <= kTestStringWidth; width++) {
+ result = ElideText(kTestString, font_list, width, TRUNCATE_AT_END);
CheckSurrogatePairs(result, kSurrogateFirstChar, kSurrogateSecondChar);
- result = ElideText(kTestString, font, width, ELIDE_AT_END);
+ result = ElideText(kTestString, font_list, width, ELIDE_AT_END);
CheckSurrogatePairs(result, kSurrogateFirstChar, kSurrogateSecondChar);
- result = ElideText(kTestString, font, width, ELIDE_IN_MIDDLE);
+ result = ElideText(kTestString, font_list, width, ELIDE_IN_MIDDLE);
CheckSurrogatePairs(result, kSurrogateFirstChar, kSurrogateSecondChar);
}
}
@@ -467,17 +445,19 @@ TEST(TextEliderTest, ElideTextLongStrings) {
{data_scheme + million_a, long_string_end},
};
- const gfx::Font font;
- int ellipsis_width = font.GetStringWidth(kEllipsisStr);
+ const FontList font_list;
+ float ellipsis_width = GetStringWidthF(kEllipsisStr, font_list);
for (size_t i = 0; i < arraysize(testcases_end); ++i) {
// Compare sizes rather than actual contents because if the test fails,
// output is rather long.
EXPECT_EQ(testcases_end[i].output.size(),
- ElideText(testcases_end[i].input, font,
- font.GetStringWidth(testcases_end[i].output),
- ELIDE_AT_END).size());
+ ElideText(
+ testcases_end[i].input,
+ font_list,
+ GetStringWidthF(testcases_end[i].output, font_list),
+ ELIDE_AT_END).size());
EXPECT_EQ(kEllipsisStr,
- ElideText(testcases_end[i].input, font, ellipsis_width,
+ ElideText(testcases_end[i].input, font_list, ellipsis_width,
ELIDE_AT_END));
}
@@ -498,11 +478,13 @@ TEST(TextEliderTest, ElideTextLongStrings) {
// Compare sizes rather than actual contents because if the test fails,
// output is rather long.
EXPECT_EQ(testcases_middle[i].output.size(),
- ElideText(testcases_middle[i].input, font,
- font.GetStringWidth(testcases_middle[i].output),
- ELIDE_AT_END).size());
+ ElideText(
+ testcases_middle[i].input,
+ font_list,
+ GetStringWidthF(testcases_middle[i].output, font_list),
+ ELIDE_AT_END).size());
EXPECT_EQ(kEllipsisStr,
- ElideText(testcases_middle[i].input, font, ellipsis_width,
+ ElideText(testcases_middle[i].input, font_list, ellipsis_width,
ELIDE_AT_END));
}
}
@@ -580,13 +562,13 @@ TEST(TextEliderTest, ElideString) {
}
TEST(TextEliderTest, ElideRectangleText) {
- const gfx::Font font;
- const int line_height = font.GetHeight();
- const int test_width = font.GetStringWidth(ASCIIToUTF16("Test"));
+ const FontList font_list;
+ const int line_height = font_list.GetHeight();
+ const float test_width = GetStringWidthF(ASCIIToUTF16("Test"), font_list);
struct TestData {
const char* input;
- int available_pixel_width;
+ float available_pixel_width;
int available_pixel_height;
bool truncated_y;
const char* output;
@@ -622,7 +604,7 @@ TEST(TextEliderTest, ElideRectangleText) {
std::vector<string16> lines;
EXPECT_EQ(cases[i].truncated_y ? INSUFFICIENT_SPACE_VERTICAL : 0,
ElideRectangleText(UTF8ToUTF16(cases[i].input),
- font,
+ font_list,
cases[i].available_pixel_width,
cases[i].available_pixel_height,
TRUNCATE_LONG_WORDS,
@@ -637,14 +619,14 @@ TEST(TextEliderTest, ElideRectangleText) {
}
TEST(TextEliderTest, ElideRectangleTextPunctuation) {
- const gfx::Font font;
- const int line_height = font.GetHeight();
- const int test_width = font.GetStringWidth(ASCIIToUTF16("Test"));
- const int test_t_width = font.GetStringWidth(ASCIIToUTF16("Test T"));
+ const FontList font_list;
+ const int line_height = font_list.GetHeight();
+ const float test_width = GetStringWidthF(ASCIIToUTF16("Test"), font_list);
+ const float test_t_width = GetStringWidthF(ASCIIToUTF16("Test T"), font_list);
struct TestData {
const char* input;
- int available_pixel_width;
+ float available_pixel_width;
int available_pixel_height;
bool wrap_words;
bool truncated_x;
@@ -662,7 +644,7 @@ TEST(TextEliderTest, ElideRectangleTextPunctuation) {
(cases[i].wrap_words ? WRAP_LONG_WORDS : TRUNCATE_LONG_WORDS);
EXPECT_EQ(cases[i].truncated_x ? INSUFFICIENT_SPACE_HORIZONTAL : 0,
ElideRectangleText(UTF8ToUTF16(cases[i].input),
- font,
+ font_list,
cases[i].available_pixel_width,
cases[i].available_pixel_height,
wrap_behavior,
@@ -677,15 +659,15 @@ TEST(TextEliderTest, ElideRectangleTextPunctuation) {
}
TEST(TextEliderTest, ElideRectangleTextLongWords) {
- const gfx::Font font;
+ const FontList font_list;
const int kAvailableHeight = 1000;
const string16 kElidedTesting = UTF8ToUTF16(std::string("Tes") + kEllipsis);
- const int elided_width = font.GetStringWidth(kElidedTesting);
- const int test_width = font.GetStringWidth(ASCIIToUTF16("Test"));
+ const float elided_width = GetStringWidthF(kElidedTesting, font_list);
+ const float test_width = GetStringWidthF(ASCIIToUTF16("Test"), font_list);
struct TestData {
const char* input;
- int available_pixel_width;
+ float available_pixel_width;
WordWrapBehavior wrap_behavior;
bool truncated_x;
const char* output;
@@ -723,7 +705,7 @@ TEST(TextEliderTest, ElideRectangleTextLongWords) {
std::vector<string16> lines;
EXPECT_EQ(cases[i].truncated_x ? INSUFFICIENT_SPACE_HORIZONTAL : 0,
ElideRectangleText(UTF8ToUTF16(cases[i].input),
- font,
+ font_list,
cases[i].available_pixel_width,
kAvailableHeight,
cases[i].wrap_behavior,
@@ -735,35 +717,30 @@ TEST(TextEliderTest, ElideRectangleTextLongWords) {
}
}
-// TODO(ios): Complex eliding is off by one for some of those tests on iOS.
-// See crbug.com/154019
-#if defined(OS_IOS)
-#define MAYBE_ElideRectangleTextCheckLineWidth \
- DISABLED_ElideRectangleTextCheckLineWidth
-#else
-#define MAYBE_ElideRectangleTextCheckLineWidth ElideRectangleTextCheckLineWidth
-#endif
-
// This test is to make sure that the width of each wrapped line does not
// exceed the available width. On some platform like Mac, this test used to
// fail because the truncated integer width is returned for the string
// and the accumulation of the truncated values causes the elide function
// to wrap incorrectly.
-TEST(TextEliderTest, MAYBE_ElideRectangleTextCheckLineWidth) {
- gfx::Font font = GetTestingFont();
- const int kAvailableWidth = 235;
+TEST(TextEliderTest, ElideRectangleTextCheckLineWidth) {
+ FontList font_list;
+#if defined(OS_MACOSX) && !defined(OS_IOS)
+ // Use a specific font to expose the line width exceeding problem.
+ font_list = FontList(Font("LucidaGrande", 12));
+#endif
+ const float kAvailableWidth = 235;
const int kAvailableHeight = 1000;
const char text[] = "that Russian place we used to go to after fencing";
std::vector<string16> lines;
EXPECT_EQ(0, ElideRectangleText(UTF8ToUTF16(text),
- font,
+ font_list,
kAvailableWidth,
kAvailableHeight,
WRAP_LONG_WORDS,
&lines));
ASSERT_EQ(2u, lines.size());
- EXPECT_LE(font.GetStringWidth(lines[0]), kAvailableWidth);
- EXPECT_LE(font.GetStringWidth(lines[1]), kAvailableWidth);
+ EXPECT_LE(GetStringWidthF(lines[0], font_list), kAvailableWidth);
+ EXPECT_LE(GetStringWidthF(lines[1], font_list), kAvailableWidth);
}
TEST(TextEliderTest, ElideRectangleString) {
diff --git a/ui/gfx/text_utils.h b/ui/gfx/text_utils.h
index fa5caef..088f97c 100644
--- a/ui/gfx/text_utils.h
+++ b/ui/gfx/text_utils.h
@@ -27,6 +27,10 @@ GFX_EXPORT base::string16 RemoveAcceleratorChar(const base::string16& s,
GFX_EXPORT int GetStringWidth(const base::string16& text,
const FontList& font_list);
+// This is same as GetStringWidth except that fractional width is returned.
+GFX_EXPORT float GetStringWidthF(const base::string16& text,
+ const FontList& font_list);
+
} // namespace gfx
#endif // UI_GFX_TEXT_UTILS_H_
diff --git a/ui/gfx/text_utils_android.cc b/ui/gfx/text_utils_android.cc
index c564b9b..93938d5 100644
--- a/ui/gfx/text_utils_android.cc
+++ b/ui/gfx/text_utils_android.cc
@@ -13,4 +13,9 @@ int GetStringWidth(const base::string16& text, const FontList& font_list) {
return 0;
}
+float GetStringWidthF(const base::string16& text, const FontList& font_list) {
+ NOTIMPLEMENTED();
+ return 0;
+}
+
} // namespace gfx
diff --git a/ui/gfx/text_utils_ios.mm b/ui/gfx/text_utils_ios.mm
index 1841864..56c01df7 100644
--- a/ui/gfx/text_utils_ios.mm
+++ b/ui/gfx/text_utils_ios.mm
@@ -14,9 +14,13 @@
namespace gfx {
int GetStringWidth(const base::string16& text, const FontList& font_list) {
+ return std::ceil(GetStringWidthF(text, font_list));
+}
+
+float GetStringWidthF(const base::string16& text, const FontList& font_list) {
NSString* ns_text = base::SysUTF16ToNSString(text);
NativeFont native_font = font_list.GetPrimaryFont().GetNativeFont();
- return std::ceil([ns_text sizeWithFont:native_font].width);
+ return [ns_text sizeWithFont:native_font].width;
}
} // namespace gfx
diff --git a/ui/gfx/text_utils_skia.cc b/ui/gfx/text_utils_skia.cc
index 0de1156..4ef0c23 100644
--- a/ui/gfx/text_utils_skia.cc
+++ b/ui/gfx/text_utils_skia.cc
@@ -12,4 +12,8 @@ int GetStringWidth(const base::string16& text, const FontList& font_list) {
return Canvas::GetStringWidth(text, font_list);
}
+float GetStringWidthF(const base::string16& text, const FontList& font_list) {
+ return Canvas::GetStringWidthF(text, font_list);
+}
+
} // namespace gfx