summaryrefslogtreecommitdiffstats
path: root/app/gfx/font_gtk.cc
diff options
context:
space:
mode:
Diffstat (limited to 'app/gfx/font_gtk.cc')
-rw-r--r--app/gfx/font_gtk.cc188
1 files changed, 65 insertions, 123 deletions
diff --git a/app/gfx/font_gtk.cc b/app/gfx/font_gtk.cc
index 5e16fc2..244810a 100644
--- a/app/gfx/font_gtk.cc
+++ b/app/gfx/font_gtk.cc
@@ -7,87 +7,56 @@
#include <fontconfig/fontconfig.h>
#include <gtk/gtk.h>
-#include "app/gfx/canvas.h"
#include "base/string_util.h"
namespace gfx {
-namespace {
-
-// 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;
+// 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;
}
-Font* Font::default_font_ = NULL;
-
// static
Font Font::CreateFont(PangoFontDescription* 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;
-}
+ gint size = pango_font_description_get_size(desc);
+ const char* family_name = pango_font_description_get_family(desc);
-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;
-}
+ // 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::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();
+ return Font(CreateFont(font_family, size / PANGO_SCALE));
}
// Get the default gtk system font (name and size).
@@ -106,68 +75,41 @@ Font::Font() {
PangoFontDescription* desc =
pango_font_description_from_string(font_name);
- default_font_ = new Font(desc);
+ default_font_ = new Font(CreateFont(desc));
pango_font_description_free(desc);
g_free(font_name);
+
+ DCHECK(default_font_);
}
- *this = *default_font_;
+ CopyFont(*default_font_);
}
// static
-Font Font::CreateFont(const std::wstring& font_family, int font_size) {
- DCHECK_GT(font_size, 0);
-
+PangoFontDescription* Font::PangoFontFromGfxFont(
+ const gfx::Font& gfx_font) {
+ gfx::Font font = gfx_font; // Copy so we can call non-const methods.
PangoFontDescription* pfd = pango_font_description_new();
- 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) {
-}
+ 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;
+ }
-Font::PangoFontRef::~PangoFontRef() {
- pango_font_description_free(pfd_);
+ return pfd;
}
} // namespace gfx