diff options
author | estade@chromium.org <estade@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-04-07 01:03:57 +0000 |
---|---|---|
committer | estade@chromium.org <estade@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-04-07 01:03:57 +0000 |
commit | 7a69c1461163ab03dac93b8459ac6f71c6df4a44 (patch) | |
tree | c574c310729bf1bc5933ebeda4e0aee498488733 /chrome/common | |
parent | cdb0835bb3df4a9d1c7b8614af3e348bbba0107d (diff) | |
download | chromium_src-7a69c1461163ab03dac93b8459ac6f71c6df4a44.zip chromium_src-7a69c1461163ab03dac93b8459ac6f71c6df4a44.tar.gz chromium_src-7a69c1461163ab03dac93b8459ac6f71c6df4a44.tar.bz2 |
Fix crash if skia failed to find default font.
If system has various fonts, fontconfig will find several font family for
default font, but it might not be the best match in SkFontHost_fontconfig.cpp,
so SkTypeface::Create returns NULL.
Find font family in the same way as FontMatch in SkFontHost_fontconfig.cpp, so
that make sure the font available.
BUG=9654
patch by ukai@google.com: <http://codereview.chromium.org/56147>
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@13217 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome/common')
-rw-r--r-- | chrome/common/gfx/chrome_font.h | 6 | ||||
-rw-r--r-- | chrome/common/gfx/chrome_font_gtk.cc | 44 | ||||
-rw-r--r-- | chrome/common/gfx/chrome_font_skia.cc | 21 |
3 files changed, 57 insertions, 14 deletions
diff --git a/chrome/common/gfx/chrome_font.h b/chrome/common/gfx/chrome_font.h index af68aa1..0358afc 100644 --- a/chrome/common/gfx/chrome_font.h +++ b/chrome/common/gfx/chrome_font.h @@ -50,6 +50,7 @@ class ChromeFont { }; // Creates a ChromeFont given font name (e.g. arial), font size (e.g. 12). + // Skia actually expects a family name and not a font name. static ChromeFont CreateFont(const std::wstring& font_name, int font_size); ~ChromeFont() { } @@ -91,6 +92,8 @@ class ChromeFont { int style() const; // Font Name. + // It is actually a font family name, because Skia expects a family name + // and not a font name. std::wstring FontName(); // Font Size. @@ -204,7 +207,8 @@ class ChromeFont { SkTypeface *typeface_; // Additional information about the face - std::wstring font_name_; + // Skia actually expects a family name and not a font name. + std::wstring font_family_; int font_size_; int style_; diff --git a/chrome/common/gfx/chrome_font_gtk.cc b/chrome/common/gfx/chrome_font_gtk.cc index bdb0324..f0d2120 100644 --- a/chrome/common/gfx/chrome_font_gtk.cc +++ b/chrome/common/gfx/chrome_font_gtk.cc @@ -4,12 +4,46 @@ #include "chrome/common/gfx/chrome_font.h" +#include <fontconfig/fontconfig.h> #include <gtk/gtk.h> #include "base/string_util.h" ChromeFont* ChromeFont::default_font_ = NULL; +// Find the best match font for |family_name| in the same way as Skia +// to make sure CreateFont() successfully creates default font. +// In Skia, it only checks the best match font. If it failed to find, +// SkTypeface will be NULL for that font family. It eventually causes 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 system has 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; +} + // Get the default gtk system font (name and size). ChromeFont::ChromeFont() { if (default_font_ == NULL) { @@ -31,10 +65,14 @@ ChromeFont::ChromeFont() { PangoFontDescription* desc = pango_font_description_from_string(font_ptr); gint size = pango_font_description_get_size(desc); - const char* name = pango_font_description_get_family(desc); + const char* family_name = pango_font_description_get_family(desc); + + // Find best match font for |family_name| to make sure we can get + // SkTypeface for default font. + // TODO(agl): remove this. + std::wstring font_family = FindBestMatchFontFamilyName(family_name); - default_font_ = new ChromeFont(CreateFont(UTF8ToWide(name), - size / PANGO_SCALE)); + default_font_ = new ChromeFont(CreateFont(font_family, size / PANGO_SCALE)); pango_font_description_free(desc); g_free(font_name); diff --git a/chrome/common/gfx/chrome_font_skia.cc b/chrome/common/gfx/chrome_font_skia.cc index 096513a..6c80c8d 100644 --- a/chrome/common/gfx/chrome_font_skia.cc +++ b/chrome/common/gfx/chrome_font_skia.cc @@ -19,11 +19,11 @@ ChromeFont& ChromeFont::operator=(const ChromeFont& other) { return *this; } -ChromeFont::ChromeFont(SkTypeface* tf, const std::wstring& font_name, +ChromeFont::ChromeFont(SkTypeface* tf, const std::wstring& font_family, int font_size, int style) : typeface_helper_(new SkAutoUnref(tf)), typeface_(tf), - font_name_(font_name), + font_family_(font_family), font_size_(font_size), style_(style) { tf->ref(); @@ -60,7 +60,7 @@ void ChromeFont::CopyChromeFont(const ChromeFont& other) { typeface_helper_.reset(new SkAutoUnref(other.typeface_)); typeface_ = other.typeface_; typeface_->ref(); - font_name_ = other.font_name_; + font_family_ = other.font_family_; font_size_ = other.font_size_; style_ = other.style_; height_ = other.height_; @@ -80,15 +80,16 @@ int ChromeFont::ave_char_width() const { return avg_width_; } -ChromeFont ChromeFont::CreateFont(const std::wstring& font_name, +ChromeFont ChromeFont::CreateFont(const std::wstring& font_family, int font_size) { DCHECK_GT(font_size, 0); - SkTypeface* tf = SkTypeface::Create(base::SysWideToUTF8(font_name).c_str(), + SkTypeface* tf = SkTypeface::Create(base::SysWideToUTF8(font_family).c_str(), SkTypeface::kNormal); + DCHECK(tf) << "Could not find font: " << base::SysWideToUTF8(font_family); SkAutoUnref tf_helper(tf); - return ChromeFont(tf, font_name, font_size, NORMAL); + return ChromeFont(tf, font_family, font_size, NORMAL); } ChromeFont ChromeFont::DeriveFont(int size_delta, int style) const { @@ -99,7 +100,7 @@ ChromeFont ChromeFont::DeriveFont(int size_delta, int style) const { if (style == style_) { // Fast path, we just use the same typeface at a different size - return ChromeFont(typeface_, font_name_, font_size_ + size_delta, style_); + return ChromeFont(typeface_, font_family_, font_size_ + size_delta, style_); } // If the style has changed we may need to load a new face @@ -109,11 +110,11 @@ ChromeFont ChromeFont::DeriveFont(int size_delta, int style) const { if (ITALIC & style) skstyle |= SkTypeface::kItalic; - SkTypeface* tf = SkTypeface::Create(base::SysWideToUTF8(font_name_).c_str(), + SkTypeface* tf = SkTypeface::Create(base::SysWideToUTF8(font_family_).c_str(), static_cast<SkTypeface::Style>(skstyle)); SkAutoUnref tf_helper(tf); - return ChromeFont(tf, font_name_, font_size_ + size_delta, skstyle); + return ChromeFont(tf, font_family_, font_size_ + size_delta, skstyle); } void ChromeFont::PaintSetup(SkPaint* paint) const { @@ -154,7 +155,7 @@ int ChromeFont::style() const { } std::wstring ChromeFont::FontName() { - return font_name_; + return font_family_; } int ChromeFont::FontSize() { |