summaryrefslogtreecommitdiffstats
path: root/app
diff options
context:
space:
mode:
Diffstat (limited to 'app')
-rw-r--r--app/gfx/canvas_linux.cc30
-rw-r--r--app/gfx/font.h5
-rw-r--r--app/gfx/font_skia.cc43
3 files changed, 54 insertions, 24 deletions
diff --git a/app/gfx/canvas_linux.cc b/app/gfx/canvas_linux.cc
index 7ed1904..fc4e10e3 100644
--- a/app/gfx/canvas_linux.cc
+++ b/app/gfx/canvas_linux.cc
@@ -98,8 +98,10 @@ Canvas::Canvas() : skia::PlatformCanvas() {
Canvas::~Canvas() {
}
+// Pass a width > 0 to force wrapping and elliding.
static void SetupPangoLayout(PangoLayout* layout,
const gfx::Font& font,
+ int width,
int flags) {
if (!cairo_font_options)
UpdateCairoFontOptions();
@@ -112,6 +114,9 @@ static void SetupPangoLayout(PangoLayout* layout,
// scope out RTL characters.
pango_layout_set_auto_dir(layout, FALSE);
+ if (width > 0)
+ pango_layout_set_width(layout, width * PANGO_SCALE);
+
if (flags & Canvas::NO_ELLIPSIS) {
pango_layout_set_ellipsize(layout, PANGO_ELLIPSIZE_NONE);
} else {
@@ -144,14 +149,16 @@ void Canvas::SizeStringInt(const std::wstring& text,
cairo_t* cr = cairo_create(surface);
PangoLayout* layout = pango_cairo_create_layout(cr);
- SetupPangoLayout(layout, font, flags);
+ SetupPangoLayout(layout, font, *width, flags);
std::string utf8 = WideToUTF8(text);
pango_layout_set_text(layout, utf8.data(), utf8.size());
- pango_layout_get_size(layout, width, height);
+ int chars_height;
+ pango_layout_get_size(layout, width, &chars_height);
*width /= PANGO_SCALE;
- *height /= PANGO_SCALE;
+ // Pango returns the height of the characters, not the height of the font.
+ *height = font.height();
g_object_unref(layout);
cairo_destroy(cr);
@@ -160,14 +167,14 @@ void Canvas::SizeStringInt(const std::wstring& text,
void Canvas::DrawStringInt(const std::wstring& text,
const gfx::Font& font,
- const SkColor& color, int x, int y, int w, int h,
+ const SkColor& color,
+ int x, int y, int w, int h,
int flags) {
cairo_t* cr = beginPlatformPaint();
PangoLayout* layout = pango_cairo_create_layout(cr);
- SetupPangoLayout(layout, font, flags);
+ SetupPangoLayout(layout, font, w, flags);
- pango_layout_set_width(layout, w * PANGO_SCALE);
pango_layout_set_height(layout, h * PANGO_SCALE);
cairo_save(cr);
@@ -179,16 +186,19 @@ void Canvas::DrawStringInt(const std::wstring& text,
std::string utf8 = WideToUTF8(text);
pango_layout_set_text(layout, utf8.data(), utf8.size());
- int width, height;
- pango_layout_get_size(layout, &width, &height);
+ int width, height, chars_height;
+ pango_layout_get_size(layout, &width, &chars_height);
+ width /= PANGO_SCALE;
+ // Pango returns the height of the characters, not the height of the font.
+ height = font.height();
if (flags & Canvas::TEXT_VALIGN_TOP) {
// Cairo should draw from the top left corner already.
} else if (flags & Canvas::TEXT_VALIGN_BOTTOM) {
- y = y + (h - (height / PANGO_SCALE));
+ y += (h - height);
} else {
// Vertically centered.
- y = y + ((h - (height / PANGO_SCALE)) / 2);
+ y += ((h - height) / 2);
}
cairo_rectangle(cr, x, y, w, h);
diff --git a/app/gfx/font.h b/app/gfx/font.h
index e53bd79..bc8ee92 100644
--- a/app/gfx/font.h
+++ b/app/gfx/font.h
@@ -206,6 +206,9 @@ class Font {
// The default font, used for the default constructor.
static Font* default_font_;
+ // The average width of a character, initialized and cached if needed.
+ double avg_width();
+
// These two both point to the same SkTypeface. We use the SkAutoUnref to
// handle the reference counting, but without @typeface_ we would have to
// cast the SkRefCnt from @typeface_helper_ every time.
@@ -221,7 +224,7 @@ class Font {
// Cached metrics, generated at construction
int height_;
int ascent_;
- int avg_width_;
+ double avg_width_;
#elif defined(OS_MACOSX)
explicit Font(const std::wstring& font_name, int font_size, int style);
diff --git a/app/gfx/font_skia.cc b/app/gfx/font_skia.cc
index 41c29c6..70d6cf2 100644
--- a/app/gfx/font_skia.cc
+++ b/app/gfx/font_skia.cc
@@ -69,22 +69,14 @@ Font::Font(SkTypeface* tf, const std::wstring& font_family, int font_size,
void Font::calculateMetrics() {
SkPaint paint;
SkPaint::FontMetrics metrics;
-
PaintSetup(&paint);
paint.getFontMetrics(&metrics);
ascent_ = SkScalarCeil(-metrics.fAscent);
height_ = ascent_ + SkScalarCeil(metrics.fDescent);
+ // avg_width_ is calculated lazily, as it's expensive and not used often.
+ avg_width_ = -1.0;
- if (metrics.fAvgCharWidth) {
- avg_width_ = SkScalarRound(metrics.fAvgCharWidth);
- } else {
- static const char x_char = 'x';
- paint.setTextEncoding(SkPaint::kUTF8_TextEncoding);
- SkScalar width = paint.measureText(&x_char, 1);
-
- avg_width_ = static_cast<int>(ceilf(SkScalarToFloat(width)));
- }
}
void Font::CopyFont(const Font& other) {
@@ -108,7 +100,7 @@ int Font::baseline() const {
}
int Font::ave_char_width() const {
- return avg_width_;
+ return SkScalarRound(const_cast<Font*>(this)->avg_width());
}
Font Font::CreateFont(const std::wstring& font_family, int font_size) {
@@ -176,10 +168,35 @@ int Font::GetStringWidth(const std::wstring& text) const {
return width;
}
-int Font::GetExpectedTextWidth(int length) const {
- return length * avg_width_;
+double Font::avg_width() {
+ if (avg_width_ < 0) {
+ // First get the pango based width
+ PangoFontDescription* pango_desc = gfx::Font::PangoFontFromGfxFont(*this);
+ PangoContext* context =
+ gdk_pango_context_get_for_screen(gdk_screen_get_default());
+ PangoFontMetrics* pango_metrics =
+ pango_context_get_metrics(context,
+ pango_desc,
+ pango_language_get_default());
+ double pango_width =
+ pango_font_metrics_get_approximate_char_width(pango_metrics);
+ pango_width /= PANGO_SCALE;
+
+ // Yes, this is how Microsoft recommends calculating the dialog unit
+ // conversions.
+ int text_width = GetStringWidth(
+ L"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz");
+ double dialog_units = (text_width / 26 + 1) / 2;
+
+ avg_width_ = std::min(pango_width, dialog_units);
+ }
+ return avg_width_;
}
+int Font::GetExpectedTextWidth(int length) const {
+ double char_width = const_cast<Font*>(this)->avg_width();
+ return round(static_cast<float>(length) * char_width);
+}
int Font::style() const {
return style_;