diff options
-rw-r--r-- | app/app.gyp | 1 | ||||
-rw-r--r-- | app/gfx/canvas_linux.cc | 4 | ||||
-rw-r--r-- | app/gfx/font.h | 81 | ||||
-rw-r--r-- | app/gfx/font_gtk.cc | 188 | ||||
-rw-r--r-- | app/gfx/font_skia.cc | 160 | ||||
-rw-r--r-- | app/gfx/font_unittest.cc | 7 | ||||
-rw-r--r-- | chrome/browser/autocomplete/autocomplete_popup_view_gtk.cc | 31 | ||||
-rw-r--r-- | views/controls/button/native_button_gtk.cc | 5 | ||||
-rw-r--r-- | views/controls/textfield/native_textfield_gtk.cc | 3 |
9 files changed, 173 insertions, 307 deletions
diff --git a/app/app.gyp b/app/app.gyp index f01073c..41b7ee6 100644 --- a/app/app.gyp +++ b/app/app.gyp @@ -75,7 +75,6 @@ 'gfx/font.h', 'gfx/font_gtk.cc', 'gfx/font_mac.mm', - 'gfx/font_skia.cc', 'gfx/font_win.cc', 'gfx/color_utils.cc', 'gfx/color_utils.h', 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) { diff --git a/chrome/browser/autocomplete/autocomplete_popup_view_gtk.cc b/chrome/browser/autocomplete/autocomplete_popup_view_gtk.cc index 394077c..d459775 100644 --- a/chrome/browser/autocomplete/autocomplete_popup_view_gtk.cc +++ b/chrome/browser/autocomplete/autocomplete_popup_view_gtk.cc @@ -69,33 +69,6 @@ const int kCornerSize = 3; // UTF-8 Left-to-right embedding. const char* kLRE = "\xe2\x80\xaa"; -// TODO(deanm): We should put this on gfx::Font so it can be shared. -// Returns a new pango font, free with pango_font_description_free(). -PangoFontDescription* PangoFontFromGfxFont(const gfx::Font& chrome_font) { - gfx::Font font = chrome_font; // Copy so we can call non-const methods. - 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; - } - - return pfd; -} - // Return a Rect covering the whole area of |window|. gfx::Rect GetWindowRect(GdkWindow* window) { gint width, height; @@ -273,9 +246,7 @@ AutocompletePopupViewGtk::AutocompletePopupViewGtk( // For now, force the font size. gfx::Font font = gfx::Font::CreateFont( gfx::Font().FontName(), browser_defaults::kAutocompletePopupFontSize); - PangoFontDescription* pfd = PangoFontFromGfxFont(font); - pango_layout_set_font_description(layout_, pfd); - pango_font_description_free(pfd); + pango_layout_set_font_description(layout_, font.nativeFont()); gtk_widget_add_events(window_, GDK_BUTTON_MOTION_MASK | GDK_POINTER_MOTION_MASK | diff --git a/views/controls/button/native_button_gtk.cc b/views/controls/button/native_button_gtk.cc index c5f0f1a..fd89da2 100644 --- a/views/controls/button/native_button_gtk.cc +++ b/views/controls/button/native_button_gtk.cc @@ -41,11 +41,8 @@ void NativeButtonGtk::UpdateFont() { if (!native_view()) return; - NOTIMPLEMENTED(); preferred_size_ = gfx::Size(); - // SendMessage(GetHWND(), WM_SETFONT, - // reinterpret_cast<WPARAM>(native_button_->font().hfont()), - // FALSE); + gtk_widget_modify_font(native_view(), native_button_->font().nativeFont()); } void NativeButtonGtk::UpdateEnabled() { diff --git a/views/controls/textfield/native_textfield_gtk.cc b/views/controls/textfield/native_textfield_gtk.cc index ef7a67d..34c4a1f 100644 --- a/views/controls/textfield/native_textfield_gtk.cc +++ b/views/controls/textfield/native_textfield_gtk.cc @@ -105,8 +105,7 @@ void NativeTextfieldGtk::UpdateReadOnly() { void NativeTextfieldGtk::UpdateFont() { if (!native_view()) return; - gtk_widget_modify_font(native_view(), - gfx::Font::PangoFontFromGfxFont(textfield_->font())); + gtk_widget_modify_font(native_view(), textfield_->font().nativeFont()); } void NativeTextfieldGtk::UpdateEnabled() { |