summaryrefslogtreecommitdiffstats
path: root/app/gfx
diff options
context:
space:
mode:
authorsky@chromium.org <sky@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2009-09-11 21:11:12 +0000
committersky@chromium.org <sky@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2009-09-11 21:11:12 +0000
commitb7e273f8fc7448ecd476ecdb563a3566eb9bce1e (patch)
tree66d4973b47b89d04af3a84e7f54d53f0cc8b9c6a /app/gfx
parent67cb4c8380be25c52627944e52a23eeb006484f6 (diff)
downloadchromium_src-b7e273f8fc7448ecd476ecdb563a3566eb9bce1e.zip
chromium_src-b7e273f8fc7448ecd476ecdb563a3566eb9bce1e.tar.gz
chromium_src-b7e273f8fc7448ecd476ecdb563a3566eb9bce1e.tar.bz2
Nukes font_skia and converts font_gtk to use pango. This was
necessitated by Pango and Skia differing on how the fonts are sized, resulting in lots of clipping in views. The only iffy part of this is I've made Font::nativeFont() win/mac only (it isn't used on Linux). I did this to avoid folks accidentally modifying the underlying font out from under Font. That said, I could certainly nuke GetPangoFontDescription in favor of nativeFont() and make it return the PangoFontDescription (not a copy). Let me know if you feel strongly about converting this. Assuming your ok with this, I'll watch the perf tests to make sure this doesn't impact startup. BUG=20823 TEST=none Review URL: http://codereview.chromium.org/195058 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@26015 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'app/gfx')
-rw-r--r--app/gfx/canvas_linux.cc4
-rw-r--r--app/gfx/font.h81
-rw-r--r--app/gfx/font_gtk.cc188
-rw-r--r--app/gfx/font_skia.cc160
-rw-r--r--app/gfx/font_unittest.cc7
5 files changed, 170 insertions, 270 deletions
diff --git a/app/gfx/canvas_linux.cc b/app/gfx/canvas_linux.cc
index 7ed1904..1614f44 100644
--- a/app/gfx/canvas_linux.cc
+++ b/app/gfx/canvas_linux.cc
@@ -130,9 +130,7 @@ static void SetupPangoLayout(PangoLayout* layout,
PANGO_WRAP_WORD_CHAR : PANGO_WRAP_WORD);
}
- PangoFontDescription* desc = gfx::Font::PangoFontFromGfxFont(font);
- pango_layout_set_font_description(layout, desc);
- pango_font_description_free(desc);
+ pango_layout_set_font_description(layout, font.nativeFont());
}
// static
diff --git a/app/gfx/font.h b/app/gfx/font.h
index e53bd79..3cd7a1f 100644
--- a/app/gfx/font.h
+++ b/app/gfx/font.h
@@ -11,10 +11,6 @@
#if defined(OS_WIN)
typedef struct HFONT__* HFONT;
-#elif defined(OS_LINUX)
-#include "third_party/skia/include/core/SkRefCnt.h"
-class SkPaint;
-class SkTypeface;
#endif
#if defined(OS_WIN)
@@ -28,8 +24,7 @@ class NSFont;
typedef NSFont* NativeFont;
#elif defined(OS_LINUX)
typedef struct _PangoFontDescription PangoFontDescription;
-class SkTypeface;
-typedef SkTypeface* NativeFont;
+typedef PangoFontDescription* NativeFont;
#else // null port.
#error No known OS defined
#endif
@@ -102,6 +97,10 @@ class Font {
// Font Size.
int FontSize();
+ // Returns a handle to the native font.
+ // NOTE: on linux this returns the PangoFontDescription* being held by this
+ // object. You should not modify or free it. If you need to use it, make a
+ // copy of it by way of pango_font_description_copy(nativeFont()).
NativeFont nativeFont() const;
// Creates a font with the default name and style.
@@ -126,16 +125,6 @@ class Font {
}
#elif defined(OS_LINUX)
static Font CreateFont(PangoFontDescription* desc);
- // We need a copy constructor and assignment operator to deal with
- // the Skia reference counting.
- Font(const Font& other);
- Font& operator=(const Font& other);
- // Setup a Skia context to use the current typeface
- void PaintSetup(SkPaint* paint) const;
-
- // Converts |gfx_font| to a new pango font. Free the returned font with
- // pango_font_description_free().
- static PangoFontDescription* PangoFontFromGfxFont(const gfx::Font& gfx_font);
#endif
private:
@@ -196,32 +185,48 @@ class Font {
// Indirect reference to the HFontRef, which references the underlying HFONT.
scoped_refptr<HFontRef> font_ref_;
#elif defined(OS_LINUX)
- explicit Font(SkTypeface* typeface, const std::wstring& name,
- int size, int style);
- // Calculate and cache the font metrics.
- void calculateMetrics();
- // Make |this| a copy of |other|.
- void CopyFont(const Font& other);
+ // Used internally on Linux to cache information about the font. This is used
+ // similarly to HFontRef above, see it for a description of lifetime and
+ // usage by Font. Additionally PangoFontRef copies the PangoFontDescription
+ // passed into the constructor, and deletes it when the PangoFontRef is
+ // deleted.
+ class PangoFontRef : public base::RefCounted<PangoFontRef> {
+ public:
+ PangoFontRef(PangoFontDescription* pfd,
+ const std::wstring& family,
+ int size,
+ int style,
+ int height,
+ int ascent,
+ int ave_char_width);
+ ~PangoFontRef();
+
+ PangoFontDescription* pfd() const { return pfd_; }
+ const std::wstring& family() const { return family_; }
+ int size() const { return size_; }
+ int style() const { return style_; }
+ int height() const { return height_; }
+ int ascent() const { return ascent_; }
+ int ave_char_width() const { return ave_char_width_; }
- // The default font, used for the default constructor.
- static Font* default_font_;
+ private:
+ PangoFontDescription* pfd_;
+ const std::wstring family_;
+ const int size_;
+ const int style_;
+ const int height_;
+ const int ascent_;
+ const int ave_char_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.
- scoped_ptr<SkAutoUnref> typeface_helper_;
- SkTypeface *typeface_;
+ DISALLOW_COPY_AND_ASSIGN(PangoFontRef);
+ };
- // Additional information about the face
- // Skia actually expects a family name and not a font name.
- std::wstring font_family_;
- int font_size_;
- int style_;
+ explicit Font(PangoFontDescription* pfd);
- // Cached metrics, generated at construction
- int height_;
- int ascent_;
- int avg_width_;
+ // The default font, used for the default constructor.
+ static Font* default_font_;
+
+ scoped_refptr<PangoFontRef> font_ref_;
#elif defined(OS_MACOSX)
explicit Font(const std::wstring& font_name, int font_size, int style);
diff --git a/app/gfx/font_gtk.cc b/app/gfx/font_gtk.cc
index 244810a..5e16fc2 100644
--- a/app/gfx/font_gtk.cc
+++ b/app/gfx/font_gtk.cc
@@ -7,56 +7,87 @@
#include <fontconfig/fontconfig.h>
#include <gtk/gtk.h>
+#include "app/gfx/canvas.h"
#include "base/string_util.h"
namespace gfx {
-Font* Font::default_font_ = NULL;
+namespace {
-// Find the best match font for |family_name| in the same way as Skia
-// to make sure CreateFont() successfully creates a default font. In
-// Skia, it only checks the best match font. If it failed to find
-// one, SkTypeface will be NULL for that font family. It eventually
-// causes a segfault. For example, family_name = "Sans" and system
-// may have various fonts. The first font family in FcPattern will be
-// "DejaVu Sans" but a font family returned by FcFontMatch will be "VL
-// PGothic". In this case, SkTypeface for "Sans" returns NULL even if
-// the system has a font for "Sans" font family. See FontMatch() in
-// skia/ports/SkFontHost_fontconfig.cpp for more detail.
-static std::wstring FindBestMatchFontFamilyName(const char* family_name) {
- FcPattern* pattern = FcPatternCreate();
- FcValue fcvalue;
- fcvalue.type = FcTypeString;
- char* family_name_copy = strdup(family_name);
- fcvalue.u.s = reinterpret_cast<FcChar8*>(family_name_copy);
- FcPatternAdd(pattern, FC_FAMILY, fcvalue, 0);
- FcConfigSubstitute(0, pattern, FcMatchPattern);
- FcDefaultSubstitute(pattern);
- FcResult result;
- FcPattern* match = FcFontMatch(0, pattern, &result);
- DCHECK(match) << "Could not find font: " << family_name;
- FcChar8* match_family;
- FcPatternGetString(match, FC_FAMILY, 0, &match_family);
-
- std::wstring font_family = UTF8ToWide(
- reinterpret_cast<char*>(match_family));
- FcPatternDestroy(match);
- FcPatternDestroy(pattern);
- free(family_name_copy);
- return font_family;
+// Returns a PangoContext that is used to get metrics. The returned context
+// should never be freed.
+PangoContext* get_context() {
+ static PangoContext* context = NULL;
+ if (!context) {
+ context = gdk_pango_context_get_for_screen(gdk_screen_get_default());
+ pango_context_set_language(context, gtk_get_default_language());
+ }
+ return context;
}
+}
+
+Font* Font::default_font_ = NULL;
+
// static
Font Font::CreateFont(PangoFontDescription* desc) {
- gint size = pango_font_description_get_size(desc);
- const char* family_name = pango_font_description_get_family(desc);
+ return Font(desc);
+}
+
+Font Font::DeriveFont(int size_delta, int style) const {
+ // If the delta is negative, if must not push the size below 1
+ if (size_delta < 0)
+ DCHECK_LT(-size_delta, font_ref_->size());
+
+ PangoFontDescription* pfd = pango_font_description_copy(nativeFont());
+ pango_font_description_set_size(
+ pfd, (font_ref_->size() + size_delta) * PANGO_SCALE);
+ pango_font_description_set_style(
+ pfd, style & ITALIC ? PANGO_STYLE_ITALIC : PANGO_STYLE_NORMAL);
+ pango_font_description_set_weight(
+ pfd, style & BOLD ? PANGO_WEIGHT_BOLD : PANGO_WEIGHT_NORMAL);
+ Font font(pfd);
+ pango_font_description_free(pfd);
+ return font;
+}
- // Find best match font for |family_name| to make sure we can get
- // a SkTypeface for the default font.
- // TODO(agl): remove this.
- std::wstring font_family = FindBestMatchFontFamilyName(family_name);
+int Font::height() const {
+ return font_ref_->height();
+}
+
+int Font::baseline() const {
+ return font_ref_->ascent();
+}
+
+int Font::ave_char_width() const {
+ return font_ref_->ave_char_width();
+}
+
+int Font::GetStringWidth(const std::wstring& text) const {
+ int width = 0, height = 0;
+
+ Canvas::SizeStringInt(text, *this, &width, &height, 0);
+ return width;
+}
- return Font(CreateFont(font_family, size / PANGO_SCALE));
+int Font::GetExpectedTextWidth(int length) const {
+ return length * font_ref_->ave_char_width();
+}
+
+int Font::style() const {
+ return font_ref_->style();
+}
+
+std::wstring Font::FontName() {
+ return font_ref_->family();
+}
+
+int Font::FontSize() {
+ return font_ref_->size();
+}
+
+PangoFontDescription* Font::nativeFont() const {
+ return font_ref_->pfd();
}
// Get the default gtk system font (name and size).
@@ -75,41 +106,68 @@ Font::Font() {
PangoFontDescription* desc =
pango_font_description_from_string(font_name);
- default_font_ = new Font(CreateFont(desc));
+ default_font_ = new Font(desc);
pango_font_description_free(desc);
g_free(font_name);
-
- DCHECK(default_font_);
}
- CopyFont(*default_font_);
+ *this = *default_font_;
}
// static
-PangoFontDescription* Font::PangoFontFromGfxFont(
- const gfx::Font& gfx_font) {
- gfx::Font font = gfx_font; // Copy so we can call non-const methods.
+Font Font::CreateFont(const std::wstring& font_family, int font_size) {
+ DCHECK_GT(font_size, 0);
+
PangoFontDescription* pfd = pango_font_description_new();
- pango_font_description_set_family(pfd, WideToUTF8(font.FontName()).c_str());
- pango_font_description_set_size(pfd, font.FontSize() * PANGO_SCALE);
-
- switch (font.style()) {
- case gfx::Font::NORMAL:
- // Nothing to do, should already be PANGO_STYLE_NORMAL.
- break;
- case gfx::Font::BOLD:
- pango_font_description_set_weight(pfd, PANGO_WEIGHT_BOLD);
- break;
- case gfx::Font::ITALIC:
- pango_font_description_set_style(pfd, PANGO_STYLE_ITALIC);
- break;
- case gfx::Font::UNDERLINED:
- // TODO(deanm): How to do underlined? Where do we use it? Probably have
- // to paint it ourselves, see pango_font_metrics_get_underline_position.
- break;
- }
+ pango_font_description_set_family(pfd, WideToUTF8(font_family).c_str());
+ pango_font_description_set_size(pfd, font_size * PANGO_SCALE);
+ pango_font_description_set_style(pfd, PANGO_STYLE_NORMAL);
+ pango_font_description_set_weight(pfd, PANGO_WEIGHT_NORMAL);
+ Font font(pfd);
+ pango_font_description_free(pfd);
+ return font;
+}
+
+Font::Font(PangoFontDescription* desc) {
+ PangoContext* context = get_context();
+ pango_context_set_font_description(context, desc);
+ PangoFontMetrics* metrics = pango_context_get_metrics(context, desc, NULL);
+ int ascent = pango_font_metrics_get_ascent(metrics) / PANGO_SCALE;
+ int height = ascent + pango_font_metrics_get_descent(metrics) / PANGO_SCALE;
+ int size = pango_font_description_get_size(desc) / PANGO_SCALE;
+ int style = 0;
+ if (pango_font_description_get_weight(desc) >= PANGO_WEIGHT_BOLD)
+ style |= BOLD;
+ if (pango_font_description_get_style(desc) == PANGO_STYLE_ITALIC)
+ style |= ITALIC;
+ // TODO(deanm): How to do underlined? Where do we use it? Probably have
+ // to paint it ourselves, see pango_font_metrics_get_underline_position.
+ int avg_width = pango_font_metrics_get_approximate_char_width(metrics) /
+ PANGO_SCALE;
+ std::wstring name(UTF8ToWide(pango_font_description_get_family(desc)));
+ font_ref_ = new PangoFontRef(desc, name, size, style, height, ascent,
+ avg_width);
+ pango_font_metrics_unref(metrics);
+}
+
+Font::PangoFontRef::PangoFontRef(PangoFontDescription* pfd,
+ const std::wstring& family,
+ int size,
+ int style,
+ int height,
+ int ascent,
+ int ave_char_width)
+ : pfd_(pango_font_description_copy(pfd)),
+ family_(family),
+ size_(size),
+ style_(style),
+ height_(height),
+ ascent_(ascent),
+ ave_char_width_(ave_char_width) {
+}
- return pfd;
+Font::PangoFontRef::~PangoFontRef() {
+ pango_font_description_free(pfd_);
}
} // namespace gfx
diff --git a/app/gfx/font_skia.cc b/app/gfx/font_skia.cc
deleted file mode 100644
index 4308bf6..0000000
--- a/app/gfx/font_skia.cc
+++ /dev/null
@@ -1,160 +0,0 @@
-// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "app/gfx/font.h"
-
-#include "app/gfx/canvas.h"
-
-#include "base/logging.h"
-#include "base/sys_string_conversions.h"
-
-#include "third_party/skia/include/core/SkTypeface.h"
-#include "third_party/skia/include/core/SkPaint.h"
-
-namespace gfx {
-
-Font::Font(const Font& other) {
- CopyFont(other);
-}
-
-Font& Font::operator=(const Font& other) {
- CopyFont(other);
- return *this;
-}
-
-Font::Font(SkTypeface* tf, const std::wstring& font_family, int font_size,
- int style)
- : typeface_helper_(new SkAutoUnref(tf)),
- typeface_(tf),
- font_family_(font_family),
- font_size_(font_size),
- style_(style) {
- tf->ref();
- calculateMetrics();
-}
-
-void Font::calculateMetrics() {
- SkPaint paint;
- SkPaint::FontMetrics metrics;
-
- PaintSetup(&paint);
- paint.getFontMetrics(&metrics);
-
- ascent_ = SkScalarRound(-metrics.fAscent);
- height_ = SkScalarRound(-metrics.fAscent + metrics.fDescent +
- metrics.fLeading);
-
- 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) {
- typeface_helper_.reset(new SkAutoUnref(other.typeface_));
- typeface_ = other.typeface_;
- typeface_->ref();
- font_family_ = other.font_family_;
- font_size_ = other.font_size_;
- style_ = other.style_;
- height_ = other.height_;
- ascent_ = other.ascent_;
- avg_width_ = other.avg_width_;
-}
-
-int Font::height() const {
- return height_;
-}
-
-int Font::baseline() const {
- return ascent_;
-}
-
-int Font::ave_char_width() const {
- return avg_width_;
-}
-
-Font Font::CreateFont(const std::wstring& font_family, int font_size) {
- DCHECK_GT(font_size, 0);
-
- SkTypeface* tf = SkTypeface::CreateFromName(
- base::SysWideToUTF8(font_family).c_str(), SkTypeface::kNormal);
- // Temporary CHECK for tracking down
- // http://code.google.com/p/chromium/issues/detail?id=12530
- CHECK(tf) << "Could not find font: " << base::SysWideToUTF8(font_family);
- SkAutoUnref tf_helper(tf);
-
- return Font(tf, font_family, font_size, NORMAL);
-}
-
-Font Font::DeriveFont(int size_delta, int style) const {
- // If the delta is negative, if must not push the size below 1
- if (size_delta < 0) {
- DCHECK_LT(-size_delta, font_size_);
- }
-
- if (style == style_) {
- // Fast path, we just use the same typeface at a different size
- return Font(typeface_, font_family_, font_size_ + size_delta, style_);
- }
-
- // If the style has changed we may need to load a new face
- int skstyle = SkTypeface::kNormal;
- if (BOLD & style)
- skstyle |= SkTypeface::kBold;
- if (ITALIC & style)
- skstyle |= SkTypeface::kItalic;
-
- SkTypeface* tf = SkTypeface::CreateFromName(
- base::SysWideToUTF8(font_family_).c_str(),
- static_cast<SkTypeface::Style>(skstyle));
- SkAutoUnref tf_helper(tf);
-
- return Font(tf, font_family_, font_size_ + size_delta, skstyle);
-}
-
-void Font::PaintSetup(SkPaint* paint) const {
- paint->setAntiAlias(false);
- paint->setSubpixelText(false);
- paint->setTextSize(SkFloatToScalar(font_size_));
- paint->setTypeface(typeface_);
- paint->setFakeBoldText((BOLD & style_) && !typeface_->isBold());
- paint->setTextSkewX((ITALIC & style_) && !typeface_->isItalic() ?
- -SK_Scalar1/4 : 0);
-}
-
-int Font::GetStringWidth(const std::wstring& text) const {
- int width = 0, height = 0;
-
- Canvas::SizeStringInt(text, *this, &width, &height, 0);
- return width;
-}
-
-int Font::GetExpectedTextWidth(int length) const {
- return length * avg_width_;
-}
-
-
-int Font::style() const {
- return style_;
-}
-
-std::wstring Font::FontName() {
- return font_family_;
-}
-
-int Font::FontSize() {
- return font_size_;
-}
-
-NativeFont Font::nativeFont() const {
- return typeface_;
-}
-
-} // namespace gfx
diff --git a/app/gfx/font_unittest.cc b/app/gfx/font_unittest.cc
index dc81ca8..d0f4fff 100644
--- a/app/gfx/font_unittest.cc
+++ b/app/gfx/font_unittest.cc
@@ -10,8 +10,7 @@ namespace {
using gfx::Font;
-class FontTest : public testing::Test {
-};
+typedef testing::Test FontTest;
TEST_F(FontTest, LoadArial) {
Font cf(Font::CreateFont(L"Arial", 16));
@@ -31,13 +30,13 @@ TEST_F(FontTest, LoadArialBold) {
TEST_F(FontTest, Ascent) {
Font cf(Font::CreateFont(L"Arial", 16));
ASSERT_GT(cf.baseline(), 2);
- ASSERT_LT(cf.baseline(), 20);
+ ASSERT_LT(cf.baseline(), 22);
}
TEST_F(FontTest, Height) {
Font cf(Font::CreateFont(L"Arial", 16));
ASSERT_GT(cf.baseline(), 2);
- ASSERT_LT(cf.baseline(), 20);
+ ASSERT_LT(cf.baseline(), 22);
}
TEST_F(FontTest, AvgWidths) {