summaryrefslogtreecommitdiffstats
path: root/gfx
diff options
context:
space:
mode:
authorben@chromium.org <ben@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-08-13 16:43:03 +0000
committerben@chromium.org <ben@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-08-13 16:43:03 +0000
commitc6ac841f51c0b884b38e917ac30b1dfde0dc43a7 (patch)
tree2b490ffa6795f72e7232d658b766785f0de64e38 /gfx
parent6b32b95cff99ee72fd7824237ae5070263e5c496 (diff)
downloadchromium_src-c6ac841f51c0b884b38e917ac30b1dfde0dc43a7.zip
chromium_src-c6ac841f51c0b884b38e917ac30b1dfde0dc43a7.tar.gz
chromium_src-c6ac841f51c0b884b38e917ac30b1dfde0dc43a7.tar.bz2
Rework gfx::Font by moving platform-specific code into inner classes.
gfx::Font is a platform-neutral API shim that exists as a wrapper object to allow for the creation and lifetime of gfx::Font objects to remain consistent with past usage. gfx::PlatformFont is an interface implemented by the platform-specific inner classes (gfx::PlatformFontWin,Mac,Gtk). BUG=none TEST=existing unittests Review URL: http://codereview.chromium.org/3083022 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@56040 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'gfx')
-rw-r--r--gfx/canvas_skia_linux.cc11
-rw-r--r--gfx/canvas_skia_mac.mm6
-rw-r--r--gfx/canvas_skia_win.cc4
-rw-r--r--gfx/font.cc85
-rw-r--r--gfx/font.h268
-rw-r--r--gfx/font_gtk.cc152
-rw-r--r--gfx/font_mac.mm92
-rw-r--r--gfx/font_skia.cc255
-rw-r--r--gfx/font_unittest.cc42
-rw-r--r--gfx/font_win.cc216
-rw-r--r--gfx/gfx.gyp12
-rw-r--r--gfx/native_widget_types.h7
-rw-r--r--gfx/platform_font.h78
-rw-r--r--gfx/platform_font_gtk.cc434
-rw-r--r--gfx/platform_font_gtk.h111
-rw-r--r--gfx/platform_font_mac.h57
-rw-r--r--gfx/platform_font_mac.mm142
-rw-r--r--gfx/platform_font_win.cc268
-rw-r--r--gfx/platform_font_win.h131
19 files changed, 1401 insertions, 970 deletions
diff --git a/gfx/canvas_skia_linux.cc b/gfx/canvas_skia_linux.cc
index d63f9b4..1a22af5 100644
--- a/gfx/canvas_skia_linux.cc
+++ b/gfx/canvas_skia_linux.cc
@@ -14,6 +14,7 @@
#include "base/utf_string_conversions.h"
#include "gfx/font.h"
#include "gfx/gtk_util.h"
+#include "gfx/platform_font_gtk.h"
#include "gfx/rect.h"
namespace {
@@ -149,7 +150,7 @@ static void SetupPangoLayout(PangoLayout* layout,
resolution);
}
- PangoFontDescription* desc = gfx::Font::PangoFontFromGfxFont(font);
+ PangoFontDescription* desc = font.GetNativeFont();
pango_layout_set_font_description(layout, desc);
pango_font_description_free(desc);
@@ -246,10 +247,12 @@ void CanvasSkia::DrawStringInt(const std::wstring& text,
cairo_move_to(cr, x, y);
pango_cairo_show_layout(cr, layout);
- if (font.style() & gfx::Font::UNDERLINED) {
+ if (font.GetStyle() & gfx::Font::UNDERLINED) {
+ gfx::PlatformFontGtk* platform_font =
+ static_cast<gfx::PlatformFontGtk*>(font.platform_font());
double underline_y =
- static_cast<double>(y) + height + font.underline_position();
- cairo_set_line_width(cr, font.underline_thickness());
+ static_cast<double>(y) + height + platform_font->underline_position();
+ cairo_set_line_width(cr, platform_font->underline_thickness());
cairo_move_to(cr, x, underline_y);
cairo_line_to(cr, x + width, underline_y);
cairo_stroke(cr);
diff --git a/gfx/canvas_skia_mac.mm b/gfx/canvas_skia_mac.mm
index 7836869..e2cb553 100644
--- a/gfx/canvas_skia_mac.mm
+++ b/gfx/canvas_skia_mac.mm
@@ -28,14 +28,14 @@ CanvasSkia::~CanvasSkia() {
void CanvasSkia::SizeStringInt(const std::wstring& text,
const gfx::Font& font,
int *width, int *height, int flags) {
- NSFont* native_font = font.nativeFont();
+ NSFont* native_font = font.GetNativeFont();
NSString* ns_string = base::SysWideToNSString(text);
NSDictionary* attributes =
[NSDictionary dictionaryWithObject:native_font
forKey:NSFontAttributeName];
NSSize string_size = [ns_string sizeWithAttributes:attributes];
*width = string_size.width;
- *height = font.height();
+ *height = font.GetHeight();
}
void CanvasSkia::DrawStringInt(const std::wstring& text, const gfx::Font& font,
@@ -59,7 +59,7 @@ void CanvasSkia::DrawStringInt(const std::wstring& text, const gfx::Font& font,
NSDictionary* attributes =
[NSDictionary dictionaryWithObjectsAndKeys:
- font.nativeFont(), NSFontAttributeName,
+ font.GetNativeFont(), NSFontAttributeName,
ns_color, NSForegroundColorAttributeName,
ns_style, NSParagraphStyleAttributeName,
nil];
diff --git a/gfx/canvas_skia_win.cc b/gfx/canvas_skia_win.cc
index f3c5f8f..cc8a7eb 100644
--- a/gfx/canvas_skia_win.cc
+++ b/gfx/canvas_skia_win.cc
@@ -163,7 +163,7 @@ void CanvasSkia::SizeStringInt(const std::wstring& text,
RECT r = { 0, 0, *width, *height };
HDC dc = GetDC(NULL);
- HFONT old_font = static_cast<HFONT>(SelectObject(dc, font.hfont()));
+ HFONT old_font = static_cast<HFONT>(SelectObject(dc, font.GetNativeFont()));
DoDrawText(dc, clamped_string, &r,
ComputeFormatFlags(flags, clamped_string) | DT_CALCRECT);
SelectObject(dc, old_font);
@@ -212,7 +212,7 @@ void CanvasSkia::DrawStringInt(const std::wstring& text,
const gfx::Font& font,
const SkColor& color,
int x, int y, int w, int h, int flags) {
- DrawStringInt(text, font.hfont(), color, x, y, w, h, flags);
+ DrawStringInt(text, font.GetNativeFont(), color, x, y, w, h, flags);
}
// Checks each pixel immediately adjacent to the given pixel in the bitmap. If
diff --git a/gfx/font.cc b/gfx/font.cc
new file mode 100644
index 0000000..625968a
--- /dev/null
+++ b/gfx/font.cc
@@ -0,0 +1,85 @@
+// 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 "gfx/font.h"
+
+#include "gfx/platform_font.h"
+
+namespace gfx {
+
+////////////////////////////////////////////////////////////////////////////////
+// Font, public:
+
+Font::Font() : platform_font_(PlatformFont::CreateDefault()) {
+}
+
+Font::Font(const Font& other) : platform_font_(other.platform_font_) {
+}
+
+gfx::Font& Font::operator=(const Font& other) {
+ platform_font_ = other.platform_font_;
+ return *this;
+}
+
+Font::Font(NativeFont native_font)
+ : platform_font_(PlatformFont::CreateFromNativeFont(native_font)) {
+}
+
+Font::Font(PlatformFont* platform_font) : platform_font_(platform_font) {
+}
+
+Font::Font(const std::wstring& font_name, int font_size)
+ : platform_font_(PlatformFont::CreateFromNameAndSize(font_name,
+ font_size)) {
+}
+
+Font::~Font() {
+}
+
+Font Font::DeriveFont(int size_delta) const {
+ return DeriveFont(size_delta, GetStyle());
+}
+
+Font Font::DeriveFont(int size_delta, int style) const {
+ return platform_font_->DeriveFont(size_delta, style);
+}
+
+int Font::GetHeight() const {
+ return platform_font_->GetHeight();
+}
+
+int Font::GetBaseline() const {
+ return platform_font_->GetBaseline();
+}
+
+int Font::GetAverageCharacterWidth() const {
+ return platform_font_->GetAverageCharacterWidth();
+}
+
+int Font::GetStringWidth(const std::wstring& text) const {
+ return platform_font_->GetStringWidth(text);
+}
+
+int Font::GetExpectedTextWidth(int length) const {
+ return platform_font_->GetExpectedTextWidth(length);
+}
+
+int Font::GetStyle() const {
+ return platform_font_->GetStyle();
+}
+
+const std::wstring& Font::GetFontName() const {
+ return platform_font_->GetFontName();
+}
+
+int Font::GetFontSize() const {
+ return platform_font_->GetFontSize();
+}
+
+NativeFont Font::GetNativeFont() const {
+ return platform_font_->GetNativeFont();
+}
+
+} // namespace gfx
+
diff --git a/gfx/font.h b/gfx/font.h
index 9ee40b6..9d9276b 100644
--- a/gfx/font.h
+++ b/gfx/font.h
@@ -6,63 +6,50 @@
#define GFX_FONT_H_
#pragma once
-#include "build/build_config.h"
-
#include <string>
-#if defined(OS_WIN)
-typedef struct HFONT__* HFONT;
-#elif !defined(OS_MACOSX)
-#include "third_party/skia/include/core/SkRefCnt.h"
-class SkPaint;
-class SkTypeface;
-#endif
-
-#if defined(OS_WIN)
-typedef struct HFONT__* NativeFont;
-#elif defined(OS_MACOSX)
-#ifdef __OBJC__
-@class NSFont;
-#else
-class NSFont;
-#endif
-typedef NSFont* NativeFont;
-#else
-typedef struct _PangoFontDescription PangoFontDescription;
-class SkTypeface;
-typedef SkTypeface* NativeFont;
-#endif
-
-#include "base/basictypes.h"
#include "base/ref_counted.h"
-#include "base/scoped_ptr.h"
+#include "gfx/native_widget_types.h"
namespace gfx {
+class PlatformFont;
+
// Font provides a wrapper around an underlying font. Copy and assignment
// operators are explicitly allowed, and cheap.
class Font {
public:
// The following constants indicate the font style.
- enum {
+ enum FontStyle {
NORMAL = 0,
BOLD = 1,
ITALIC = 2,
UNDERLINED = 4,
};
- // Creates a Font given font name (e.g. arial), font size (e.g. 12).
- // Skia actually expects a family name and not a font name.
- static Font CreateFont(const std::wstring& font_name, int font_size);
+ // Creates a font with the default name and style.
+ Font();
+
+ // Creates a font that is a clone of another font object.
+ Font(const Font& other);
+ gfx::Font& operator=(const Font& other);
+
+ // Creates a font from the specified native font.
+ explicit Font(NativeFont native_font);
- ~Font() { }
+ // Construct a Font object with the specified PlatformFont object. The Font
+ // object takes ownership of the PlatformFont object.
+ explicit Font(PlatformFont* platform_font);
+
+ // Creates a font with the specified name and size.
+ Font(const std::wstring& font_name, int font_size);
+
+ ~Font();
// Returns a new Font derived from the existing font.
// size_deta is the size to add to the current font. For example, a value
// of 5 results in a font 5 units bigger than this font.
- Font DeriveFont(int size_delta) const {
- return DeriveFont(size_delta, style());
- }
+ Font DeriveFont(int size_delta) const;
// Returns a new Font derived from the existing font.
// size_delta is the size to add to the current font. See the single
@@ -76,212 +63,51 @@ class Font {
// greater than just ascent + descent. Specifically, the Windows and Mac
// implementations include leading and the Linux one does not. This may
// need to be revisited in the future.
- int height() const;
+ int GetHeight() const;
// Returns the baseline, or ascent, of the font.
- int baseline() const;
+ int GetBaseline() const;
// Returns the average character width for the font.
- int ave_char_width() const;
+ int GetAverageCharacterWidth() const;
// Returns the number of horizontal pixels needed to display the specified
// string.
int GetStringWidth(const std::wstring& text) const;
- // Returns the expected number of horizontal pixels needed to display
- // the specified length of characters.
- // Call GetStringWidth() to retrieve the actual number.
+ // Returns the expected number of horizontal pixels needed to display the
+ // specified length of characters. Call GetStringWidth() to retrieve the
+ // actual number.
int GetExpectedTextWidth(int length) const;
// Returns the style of the font.
- int style() const;
-
- // Font Name.
- // It is actually a font family name, because Skia expects a family name
- // and not a font name.
- const std::wstring& FontName() const;
+ int GetStyle() const;
- // Font Size.
- int FontSize();
+ // Returns the font name.
+ const std::wstring& GetFontName() const;
- NativeFont nativeFont() const;
+ // Returns the font size in pixels.
+ int GetFontSize() const;
- // Creates a font with the default name and style.
- Font();
-
-#if defined(OS_WIN)
- // Creates a Font from the specified HFONT. The supplied HFONT is effectively
- // copied.
- static Font CreateFont(HFONT hfont);
-
- // Returns the handle to the underlying HFONT. This is used by gfx::Canvas to
- // draw text.
- HFONT hfont() const { return font_ref_->hfont(); }
-
- // Dialog units to pixels conversion.
- // See http://support.microsoft.com/kb/145994 for details.
- int horizontal_dlus_to_pixels(int dlus) {
- return dlus * font_ref_->dlu_base_x() / 4;
- }
- int vertical_dlus_to_pixels(int dlus) {
- return dlus * font_ref_->height() / 8;
- }
-
- // Callback that returns the minimum height that should be used for
- // gfx::Fonts. Optional. If not specified, the minimum font size is 0.
- typedef int (*GetMinimumFontSizeCallback)();
- static GetMinimumFontSizeCallback get_minimum_font_size_callback;
+ // Returns the native font handle.
+ // Lifetime lore:
+ // Windows: This handle is owned by the Font object, and should not be
+ // destroyed by the caller.
+ // Mac: Caller must release this object.
+ // Gtk: This handle is created on demand, and must be freed by calling
+ // pango_font_description_free() when the caller is done using it.
+ NativeFont GetNativeFont() const;
- // Callback that adjusts a LOGFONT to meet suitability requirements of the
- // embedding application. Optional. If not specified, no adjustments are
- // performed other than clamping to a minimum font height if
- // |get_minimum_font_size_callback| is specified.
- typedef void (*AdjustFontCallback)(LOGFONT* lf);
- static AdjustFontCallback adjust_font_callback;
-
-#elif !defined(OS_MACOSX)
- 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);
-
- // Position as an offset from the height of the drawn text, used to draw
- // an underline. This is a negative number, so the underline would be
- // drawn at y + height + underline_position;
- double underline_position() const;
- // The thickness to draw the underline.
- double underline_thickness() const;
-#endif
+ // Raw access to the underlying platform font implementation. Can be
+ // static_cast to a known implementation type if needed.
+ PlatformFont* platform_font() const { return platform_font_.get(); }
private:
-
-#if defined(OS_WIN)
- // Chrome text drawing bottoms out in the Windows GDI functions that take an
- // HFONT (an opaque handle into Windows). To avoid lots of GDI object
- // allocation and destruction, Font indirectly refers to the HFONT by way of
- // an HFontRef. That is, every Font has an HFontRef, which has an HFONT.
- //
- // HFontRef is reference counted. Upon deletion, it deletes the HFONT.
- // By making HFontRef maintain the reference to the HFONT, multiple
- // HFontRefs can share the same HFONT, and Font can provide value semantics.
- class HFontRef : public base::RefCounted<HFontRef> {
- public:
- // This constructor takes control of the HFONT, and will delete it when
- // the HFontRef is deleted.
- HFontRef(HFONT hfont,
- int height,
- int baseline,
- int ave_char_width,
- int style,
- int dlu_base_x);
-
- // Accessors
- HFONT hfont() const { return hfont_; }
- int height() const { return height_; }
- int baseline() const { return baseline_; }
- int ave_char_width() const { return ave_char_width_; }
- int style() const { return style_; }
- int dlu_base_x() const { return dlu_base_x_; }
- const std::wstring& font_name() const { return font_name_; }
-
- private:
- friend class base::RefCounted<HFontRef>;
-
- ~HFontRef();
-
- const HFONT hfont_;
- const int height_;
- const int baseline_;
- const int ave_char_width_;
- const int style_;
- // Constants used in converting dialog units to pixels.
- const int dlu_base_x_;
- std::wstring font_name_;
-
- DISALLOW_COPY_AND_ASSIGN(HFontRef);
- };
-
- // Returns the base font ref. This should ONLY be invoked on the
- // UI thread.
- static HFontRef* GetBaseFontRef();
-
- // Creates and returns a new HFONTRef from the specified HFONT.
- static HFontRef* CreateHFontRef(HFONT font);
-
- explicit Font(HFontRef* font_ref) : font_ref_(font_ref) { }
-
- // Reference to the base font all fonts are derived from.
- static HFontRef* base_font_ref_;
-
- // Indirect reference to the HFontRef, which references the underlying HFONT.
- scoped_refptr<HFontRef> font_ref_;
-#elif !defined(OS_MACOSX)
- 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);
-
- // The default font, used for the default constructor.
- static Font* default_font_;
-
- // Return the scale factor for fonts that account for DPI.
- static float GetPangoScaleFactor();
-
- // The average width of a character, initialized and cached if needed.
- double avg_width() const;
-
- // Potentially slow call to get pango metrics (avg width, underline info).
- void InitPangoMetrics();
-
- // 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_;
-
- // 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_;
-
- // Cached metrics, generated at construction
- int height_;
- int ascent_;
-
- // The pango metrics are much more expensive so we wait until we need them
- // to compute them.
- bool pango_metrics_inited_;
- double avg_width_;
- double underline_position_;
- double underline_thickness_;
-#else // OS_MACOSX
- explicit Font(const std::wstring& font_name, int font_size, int style);
-
- // Calculate and cache the font metrics.
- void calculateMetrics();
-
- std::wstring font_name_;
- int font_size_;
- int style_;
-
- // Cached metrics, generated at construction
- int height_;
- int ascent_;
- int avg_width_;
-#endif
-
+ // Wrapped platform font implementation.
+ scoped_refptr<PlatformFont> platform_font_;
};
} // namespace gfx
#endif // GFX_FONT_H_
+
diff --git a/gfx/font_gtk.cc b/gfx/font_gtk.cc
index 644a7ff..e69de29 100644
--- a/gfx/font_gtk.cc
+++ b/gfx/font_gtk.cc
@@ -1,152 +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 "gfx/font.h"
-
-#include <algorithm>
-#include <fontconfig/fontconfig.h>
-#include <gtk/gtk.h>
-
-#include "base/logging.h"
-#include "base/string_piece.h"
-#include "base/utf_string_conversions.h"
-#include "gfx/gtk_util.h"
-
-namespace gfx {
-
-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;
-}
-
-// Pango scales font sizes. This returns the scale factor. See
-// pango_cairo_context_set_resolution for details.
-// NOTE: this isn't entirely accurate, in that Pango also consults the
-// FC_PIXEL_SIZE first (see get_font_size in pangocairo-fcfont), but this
-// seems to give us the same sizes as used by Pango for all our fonts in both
-// English and Thai.
-float Font::GetPangoScaleFactor() {
- static float scale_factor = gfx::GetPangoResolution();
- static bool determined_scale = false;
- if (!determined_scale) {
- if (scale_factor <= 0)
- scale_factor = 1;
- else
- scale_factor /= 72.0;
- determined_scale = true;
- }
- return scale_factor;
-}
-
-// static
-Font Font::CreateFont(PangoFontDescription* desc) {
- gint size = pango_font_description_get_size(desc);
- const char* family_name = pango_font_description_get_family(desc);
-
- // 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);
-
- Font font = CreateFont(font_family, size / PANGO_SCALE);
- int style = 0;
- if (pango_font_description_get_weight(desc) == PANGO_WEIGHT_BOLD) {
- // TODO(davemoore) What should we do about other weights? We currently
- // only support BOLD.
- style |= BOLD;
- }
- if (pango_font_description_get_style(desc) == PANGO_STYLE_ITALIC) {
- // TODO(davemoore) What about PANGO_STYLE_OBLIQUE?
- style |= ITALIC;
- }
- if (style != 0) {
- font = font.DeriveFont(0, style);
- }
- return Font(font);
-}
-
-// Get the default gtk system font (name and size).
-Font::Font() {
- if (default_font_ == NULL) {
- GtkSettings* settings = gtk_settings_get_default();
-
- gchar* font_name = NULL;
- g_object_get(settings, "gtk-font-name", &font_name, NULL);
-
- // Temporary CHECK for helping track down
- // http://code.google.com/p/chromium/issues/detail?id=12530
- CHECK(font_name) << " Unable to get gtk-font-name for default font.";
-
- PangoFontDescription* desc =
- pango_font_description_from_string(font_name);
- default_font_ = new Font(CreateFont(desc));
- pango_font_description_free(desc);
- g_free(font_name);
-
- DCHECK(default_font_);
- }
-
- CopyFont(*default_font_);
-}
-
-// static
-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.FontName()).c_str());
- // Set the absolute size to avoid overflowing UI elements.
- pango_font_description_set_absolute_size(pfd,
- font.FontSize() * PANGO_SCALE * Font::GetPangoScaleFactor());
-
- 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;
-}
-
-} // namespace gfx
diff --git a/gfx/font_mac.mm b/gfx/font_mac.mm
deleted file mode 100644
index e569a35..0000000
--- a/gfx/font_mac.mm
+++ /dev/null
@@ -1,92 +0,0 @@
-// Copyright (c) 2010 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 "gfx/font.h"
-
-#include <Cocoa/Cocoa.h>
-
-#include "base/logging.h"
-#include "base/scoped_nsobject.h"
-#include "base/sys_string_conversions.h"
-#include "gfx/canvas_skia.h"
-
-namespace gfx {
-
-// static
-Font Font::CreateFont(const std::wstring& font_name, int font_size) {
- return Font(font_name, font_size, NORMAL);
-}
-
-Font::Font(const std::wstring& font_name, int font_size, int style)
- : font_name_(font_name),
- font_size_(font_size),
- style_(style) {
- calculateMetrics();
-}
-
-Font::Font()
- : font_size_([NSFont systemFontSize]),
- style_(NORMAL) {
- NSFont* system_font = [NSFont systemFontOfSize:font_size_];
- font_name_ = base::SysNSStringToWide([system_font fontName]);
- calculateMetrics();
-}
-
-void Font::calculateMetrics() {
- NSFont* font = nativeFont();
- scoped_nsobject<NSLayoutManager> layout_manager(
- [[NSLayoutManager alloc] init]);
- height_ = [layout_manager defaultLineHeightForFont:font];
- ascent_ = [font ascender];
- avg_width_ = [font boundingRectForGlyph:[font glyphWithName:@"x"]].size.width;
-}
-
-Font Font::DeriveFont(int size_delta, int style) const {
- return Font(font_name_, font_size_ + size_delta, style);
-}
-
-int Font::height() const {
- return height_;
-}
-
-int Font::baseline() const {
- return ascent_;
-}
-
-int Font::ave_char_width() const {
- return avg_width_;
-}
-
-int Font::GetStringWidth(const std::wstring& text) const {
- int width = 0, height = 0;
- CanvasSkia::SizeStringInt(text, *this, &width, &height,
- gfx::Canvas::NO_ELLIPSIS);
- return width;
-}
-
-int Font::GetExpectedTextWidth(int length) const {
- return length * avg_width_;
-}
-
-int Font::style() const {
- return style_;
-}
-
-const std::wstring& Font::FontName() const {
- return font_name_;
-}
-
-int Font::FontSize() {
- return font_size_;
-}
-
-NativeFont Font::nativeFont() const {
- // TODO(pinkerton): apply |style_| to font. http://crbug.com/34667
- // We could cache this, but then we'd have to conditionally change the
- // dtor just for MacOS. Not sure if we want to/need to do that.
- return [NSFont fontWithName:base::SysWideToNSString(font_name_)
- size:font_size_];
-}
-
-} // namespace gfx
diff --git a/gfx/font_skia.cc b/gfx/font_skia.cc
deleted file mode 100644
index 0289cdb..0000000
--- a/gfx/font_skia.cc
+++ /dev/null
@@ -1,255 +0,0 @@
-// Copyright (c) 2010 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 "gfx/font.h"
-
-#include <gdk/gdk.h>
-#include <map>
-#include <pango/pango.h>
-
-#include "base/logging.h"
-#include "base/string_piece.h"
-#include "base/sys_string_conversions.h"
-#include "gfx/canvas_skia.h"
-#include "third_party/skia/include/core/SkTypeface.h"
-#include "third_party/skia/include/core/SkPaint.h"
-
-namespace {
-
-// The font family name which is used when a user's application font for
-// GNOME/KDE is a non-scalable one. The name should be listed in the
-// IsFallbackFontAllowed function in skia/ext/SkFontHost_fontconfig_direct.cpp.
-const char* kFallbackFontFamilyName = "sans";
-
-// Retrieves the pango metrics for a pango font description. Caches the metrics
-// and never frees them. The metrics objects are relatively small and
-// very expensive to look up.
-static PangoFontMetrics* GetPangoFontMetrics(PangoFontDescription* desc) {
- static std::map<int, PangoFontMetrics*>* desc_to_metrics = NULL;
- static PangoContext* context = NULL;
-
- if (!context) {
- context = gdk_pango_context_get_for_screen(gdk_screen_get_default());
- pango_context_set_language(context, pango_language_get_default());
- }
-
- if (!desc_to_metrics) {
- desc_to_metrics = new std::map<int, PangoFontMetrics*>();
- }
-
- int desc_hash = pango_font_description_hash(desc);
- std::map<int, PangoFontMetrics*>::iterator i =
- desc_to_metrics->find(desc_hash);
-
- if (i == desc_to_metrics->end()) {
- PangoFontMetrics* metrics = pango_context_get_metrics(context, desc, NULL);
- (*desc_to_metrics)[desc_hash] = metrics;
- return metrics;
- } else {
- return i->second;
- }
-}
-
-} // namespace
-
-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),
- pango_metrics_inited_(false),
- avg_width_(0.0),
- underline_position_(0.0),
- underline_thickness_(0.0) {
- tf->ref();
- calculateMetrics();
-}
-
-void Font::calculateMetrics() {
- SkPaint paint;
- SkPaint::FontMetrics metrics;
- PaintSetup(&paint);
- paint.getFontMetrics(&metrics);
-
- ascent_ = SkScalarCeil(-metrics.fAscent);
- height_ = ascent_ + SkScalarCeil(metrics.fDescent);
-
-}
-
-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_;
- pango_metrics_inited_ = other.pango_metrics_inited_;
- avg_width_ = other.avg_width_;
- underline_position_ = other.underline_position_;
- underline_thickness_ = other.underline_thickness_;
-}
-
-int Font::height() const {
- return height_;
-}
-
-int Font::baseline() const {
- return ascent_;
-}
-
-int Font::ave_char_width() const {
- return SkScalarRound(avg_width());
-}
-
-Font Font::CreateFont(const std::wstring& font_family, int font_size) {
- DCHECK_GT(font_size, 0);
- std::wstring fallback;
-
- SkTypeface* tf = SkTypeface::CreateFromName(
- base::SysWideToUTF8(font_family).c_str(), SkTypeface::kNormal);
- if (!tf) {
- // A non-scalable font such as .pcf is specified. Falls back to a default
- // scalable font.
- tf = SkTypeface::CreateFromName(
- kFallbackFontFamilyName, SkTypeface::kNormal);
- CHECK(tf) << "Could not find any font: "
- << base::SysWideToUTF8(font_family)
- << ", " << kFallbackFontFamilyName;
- fallback = base::SysUTF8ToWide(kFallbackFontFamilyName);
- }
- SkAutoUnref tf_helper(tf);
-
- return Font(
- tf, fallback.empty() ? font_family : fallback, 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, style);
-}
-
-void Font::PaintSetup(SkPaint* paint) const {
- paint->setAntiAlias(false);
- paint->setSubpixelText(false);
- paint->setTextSize(SkFloatToScalar(font_size_ * Font::GetPangoScaleFactor()));
- 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;
- CanvasSkia::SizeStringInt(text, *this, &width, &height,
- gfx::Canvas::NO_ELLIPSIS);
- return width;
-}
-
-void Font::InitPangoMetrics() {
- if (!pango_metrics_inited_) {
- pango_metrics_inited_ = true;
- PangoFontDescription* pango_desc = PangoFontFromGfxFont(*this);
- PangoFontMetrics* pango_metrics = GetPangoFontMetrics(pango_desc);
-
- underline_position_ =
- pango_font_metrics_get_underline_position(pango_metrics);
- underline_position_ /= PANGO_SCALE;
-
- // todo(davemoore) Come up with a better solution.
- // This is a hack, but without doing this the underlines
- // we get end up fuzzy. So we align to the midpoint of a pixel.
- underline_position_ /= 2;
-
- underline_thickness_ =
- pango_font_metrics_get_underline_thickness(pango_metrics);
- underline_thickness_ /= PANGO_SCALE;
-
- // First get the pango based width
- 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);
- pango_font_description_free(pango_desc);
- }
-}
-
-double Font::avg_width() const {
- const_cast<Font*>(this)->InitPangoMetrics();
- return avg_width_;
-}
-
-double Font::underline_position() const {
- const_cast<Font*>(this)->InitPangoMetrics();
- return underline_position_;
-}
-
-double Font::underline_thickness() const {
- const_cast<Font*>(this)->InitPangoMetrics();
- return underline_thickness_;
-}
-
-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_;
-}
-
-const std::wstring& Font::FontName() const {
- return font_family_;
-}
-
-int Font::FontSize() {
- return font_size_;
-}
-
-NativeFont Font::nativeFont() const {
- return typeface_;
-}
-
-} // namespace gfx
diff --git a/gfx/font_unittest.cc b/gfx/font_unittest.cc
index 6e63951..d2eda1c 100644
--- a/gfx/font_unittest.cc
+++ b/gfx/font_unittest.cc
@@ -14,35 +14,35 @@ class FontTest : public testing::Test {
};
TEST_F(FontTest, LoadArial) {
- Font cf(Font::CreateFont(L"Arial", 16));
- ASSERT_TRUE(cf.nativeFont());
- ASSERT_EQ(cf.style(), Font::NORMAL);
- ASSERT_EQ(cf.FontSize(), 16);
- ASSERT_EQ(cf.FontName(), L"Arial");
+ Font cf(L"Arial", 16);
+ ASSERT_TRUE(cf.GetNativeFont());
+ ASSERT_EQ(cf.GetStyle(), Font::NORMAL);
+ ASSERT_EQ(cf.GetFontSize(), 16);
+ ASSERT_EQ(cf.GetFontName(), L"Arial");
}
TEST_F(FontTest, LoadArialBold) {
- Font cf(Font::CreateFont(L"Arial", 16));
+ Font cf(L"Arial", 16);
Font bold(cf.DeriveFont(0, Font::BOLD));
- ASSERT_TRUE(bold.nativeFont());
- ASSERT_EQ(bold.style(), Font::BOLD);
+ ASSERT_TRUE(bold.GetNativeFont());
+ ASSERT_EQ(bold.GetStyle(), Font::BOLD);
}
TEST_F(FontTest, Ascent) {
- Font cf(Font::CreateFont(L"Arial", 16));
- ASSERT_GT(cf.baseline(), 2);
- ASSERT_LE(cf.baseline(), 22);
+ Font cf(L"Arial", 16);
+ ASSERT_GT(cf.GetBaseline(), 2);
+ ASSERT_LE(cf.GetBaseline(), 22);
}
TEST_F(FontTest, Height) {
- Font cf(Font::CreateFont(L"Arial", 16));
- ASSERT_GE(cf.height(), 16);
+ Font cf(L"Arial", 16);
+ ASSERT_GE(cf.GetHeight(), 16);
// TODO(akalin): Figure out why height is so large on Linux.
- ASSERT_LE(cf.height(), 26);
+ ASSERT_LE(cf.GetHeight(), 26);
}
TEST_F(FontTest, AvgWidths) {
- Font cf(Font::CreateFont(L"Arial", 16));
+ Font cf(L"Arial", 16);
ASSERT_EQ(cf.GetExpectedTextWidth(0), 0);
ASSERT_GT(cf.GetExpectedTextWidth(1), cf.GetExpectedTextWidth(0));
ASSERT_GT(cf.GetExpectedTextWidth(2), cf.GetExpectedTextWidth(1));
@@ -50,7 +50,7 @@ TEST_F(FontTest, AvgWidths) {
}
TEST_F(FontTest, Widths) {
- Font cf(Font::CreateFont(L"Arial", 16));
+ Font cf(L"Arial", 16);
ASSERT_EQ(cf.GetStringWidth(L""), 0);
ASSERT_GT(cf.GetStringWidth(L"a"), cf.GetStringWidth(L""));
ASSERT_GT(cf.GetStringWidth(L"ab"), cf.GetStringWidth(L"a"));
@@ -61,20 +61,20 @@ TEST_F(FontTest, Widths) {
// http://crbug.com/46733
TEST_F(FontTest, FAILS_DeriveFontResizesIfSizeTooSmall) {
// This creates font of height -8.
- Font cf(Font::CreateFont(L"Arial", 6));
+ Font cf(L"Arial", 6);
Font derived_font = cf.DeriveFont(-4);
LOGFONT font_info;
- GetObject(derived_font.hfont(), sizeof(LOGFONT), &font_info);
+ GetObject(derived_font.GetNativeFont(), sizeof(LOGFONT), &font_info);
EXPECT_EQ(-5, font_info.lfHeight);
}
TEST_F(FontTest, DeriveFontKeepsOriginalSizeIfHeightOk) {
// This creates font of height -8.
- Font cf(Font::CreateFont(L"Arial", 6));
+ Font cf(L"Arial", 6);
Font derived_font = cf.DeriveFont(-2);
LOGFONT font_info;
- GetObject(derived_font.hfont(), sizeof(LOGFONT), &font_info);
+ GetObject(derived_font.GetNativeFont(), sizeof(LOGFONT), &font_info);
EXPECT_EQ(-6, font_info.lfHeight);
}
#endif
-} // anonymous namespace
+} // namespace
diff --git a/gfx/font_win.cc b/gfx/font_win.cc
deleted file mode 100644
index f9b7243..0000000
--- a/gfx/font_win.cc
+++ /dev/null
@@ -1,216 +0,0 @@
-// Copyright (c) 2010 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 "gfx/font.h"
-
-#include <windows.h>
-#include <math.h>
-
-#include <algorithm>
-
-#include "base/logging.h"
-#include "base/string_util.h"
-#include "base/win_util.h"
-#include "gfx/canvas_skia.h"
-
-namespace gfx {
-
-// static
-Font::HFontRef* Font::base_font_ref_;
-
-// static
-Font::AdjustFontCallback Font::adjust_font_callback = NULL;
-Font::GetMinimumFontSizeCallback Font::get_minimum_font_size_callback = NULL;
-
-// If the tmWeight field of a TEXTMETRIC structure has a value >= this, the
-// font is bold.
-static const int kTextMetricWeightBold = 700;
-
-// Returns either minimum font allowed for a current locale or
-// lf_height + size_delta value.
-static int AdjustFontSize(int lf_height, int size_delta) {
- if (lf_height < 0) {
- lf_height -= size_delta;
- } else {
- lf_height += size_delta;
- }
- int min_font_size = 0;
- if (Font::get_minimum_font_size_callback)
- min_font_size = Font::get_minimum_font_size_callback();
- // Make sure lf_height is not smaller than allowed min font size for current
- // locale.
- if (abs(lf_height) < min_font_size) {
- return lf_height < 0 ? -min_font_size : min_font_size;
- } else {
- return lf_height;
- }
-}
-
-//
-// Font
-//
-
-Font::Font()
- : font_ref_(GetBaseFontRef()) {
-}
-
-int Font::height() const {
- return font_ref_->height();
-}
-
-int Font::baseline() const {
- return font_ref_->baseline();
-}
-
-int Font::ave_char_width() const {
- return font_ref_->ave_char_width();
-}
-
-int Font::GetExpectedTextWidth(int length) const {
- return length * std::min(font_ref_->dlu_base_x(), ave_char_width());
-}
-
-int Font::style() const {
- return font_ref_->style();
-}
-
-NativeFont Font::nativeFont() const {
- return hfont();
-}
-
-// static
-Font Font::CreateFont(HFONT font) {
- DCHECK(font);
- LOGFONT font_info;
- GetObject(font, sizeof(LOGFONT), &font_info);
- return Font(CreateHFontRef(CreateFontIndirect(&font_info)));
-}
-
-Font Font::CreateFont(const std::wstring& font_name, int font_size) {
- HDC hdc = GetDC(NULL);
- long lf_height = -MulDiv(font_size, GetDeviceCaps(hdc, LOGPIXELSY), 72);
- ReleaseDC(NULL, hdc);
- HFONT hf = ::CreateFont(lf_height, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- font_name.c_str());
- return Font::CreateFont(hf);
-}
-
-// static
-Font::HFontRef* Font::GetBaseFontRef() {
- if (base_font_ref_ == NULL) {
- NONCLIENTMETRICS metrics;
- win_util::GetNonClientMetrics(&metrics);
-
- if (adjust_font_callback)
- adjust_font_callback(&metrics.lfMessageFont);
- metrics.lfMessageFont.lfHeight =
- AdjustFontSize(metrics.lfMessageFont.lfHeight, 0);
- HFONT font = CreateFontIndirect(&metrics.lfMessageFont);
- DLOG_ASSERT(font);
- base_font_ref_ = Font::CreateHFontRef(font);
- // base_font_ref_ is global, up the ref count so it's never deleted.
- base_font_ref_->AddRef();
- }
- return base_font_ref_;
-}
-
-const std::wstring& Font::FontName() const {
- return font_ref_->font_name();
-}
-
-int Font::FontSize() {
- LOGFONT font_info;
- GetObject(hfont(), sizeof(LOGFONT), &font_info);
- long lf_height = font_info.lfHeight;
- HDC hdc = GetDC(NULL);
- int device_caps = GetDeviceCaps(hdc, LOGPIXELSY);
- int font_size = 0;
- if (device_caps != 0) {
- float font_size_float = -static_cast<float>(lf_height)*72/device_caps;
- font_size = static_cast<int>(::ceil(font_size_float - 0.5));
- }
- ReleaseDC(NULL, hdc);
- return font_size;
-}
-
-Font::HFontRef::HFontRef(HFONT hfont,
- int height,
- int baseline,
- int ave_char_width,
- int style,
- int dlu_base_x)
- : hfont_(hfont),
- height_(height),
- baseline_(baseline),
- ave_char_width_(ave_char_width),
- style_(style),
- dlu_base_x_(dlu_base_x) {
- DLOG_ASSERT(hfont);
-
- LOGFONT font_info;
- GetObject(hfont_, sizeof(LOGFONT), &font_info);
- font_name_ = std::wstring(font_info.lfFaceName);
-}
-
-Font::HFontRef::~HFontRef() {
- DeleteObject(hfont_);
-}
-
-Font Font::DeriveFont(int size_delta, int style) const {
- LOGFONT font_info;
- GetObject(hfont(), sizeof(LOGFONT), &font_info);
- font_info.lfHeight = AdjustFontSize(font_info.lfHeight, size_delta);
- font_info.lfUnderline = ((style & UNDERLINED) == UNDERLINED);
- font_info.lfItalic = ((style & ITALIC) == ITALIC);
- font_info.lfWeight = (style & BOLD) ? FW_BOLD : FW_NORMAL;
-
- HFONT hfont = CreateFontIndirect(&font_info);
- return Font(CreateHFontRef(hfont));
-}
-
-int Font::GetStringWidth(const std::wstring& text) const {
- int width = 0, height = 0;
- CanvasSkia::SizeStringInt(text, *this, &width, &height,
- gfx::Canvas::NO_ELLIPSIS);
- return width;
-}
-
-Font::HFontRef* Font::CreateHFontRef(HFONT font) {
- TEXTMETRIC font_metrics;
- HDC screen_dc = GetDC(NULL);
- HFONT previous_font = static_cast<HFONT>(SelectObject(screen_dc, font));
- int last_map_mode = SetMapMode(screen_dc, MM_TEXT);
- GetTextMetrics(screen_dc, &font_metrics);
- // Yes, this is how Microsoft recommends calculating the dialog unit
- // conversions.
- SIZE ave_text_size;
- GetTextExtentPoint32(screen_dc,
- L"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz",
- 52, &ave_text_size);
- const int dlu_base_x = (ave_text_size.cx / 26 + 1) / 2;
- // To avoid the DC referencing font_handle_, select the previous font.
- SelectObject(screen_dc, previous_font);
- SetMapMode(screen_dc, last_map_mode);
- ReleaseDC(NULL, screen_dc);
-
- const int height = std::max(1, static_cast<int>(font_metrics.tmHeight));
- const int baseline = std::max(1, static_cast<int>(font_metrics.tmAscent));
- const int ave_char_width =
- std::max(1, static_cast<int>(font_metrics.tmAveCharWidth));
- int style = 0;
- if (font_metrics.tmItalic) {
- style |= Font::ITALIC;
- }
- if (font_metrics.tmUnderlined) {
- style |= Font::UNDERLINED;
- }
- if (font_metrics.tmWeight >= kTextMetricWeightBold) {
- style |= Font::BOLD;
- }
-
- return new HFontRef(font, height, baseline, ave_char_width, style,
- dlu_base_x);
-}
-
-} // namespace gfx
diff --git a/gfx/gfx.gyp b/gfx/gfx.gyp
index 5947c4a..9b7e4aa 100644
--- a/gfx/gfx.gyp
+++ b/gfx/gfx.gyp
@@ -97,9 +97,7 @@
'color_utils.h',
'favicon_size.h',
'font.h',
- 'font_gtk.cc',
- 'font_mac.mm',
- 'font_win.cc',
+ 'font.cc',
'gfx_paths.cc',
'gfx_paths.h',
'insets.cc',
@@ -109,6 +107,13 @@
'path.h',
'path_gtk.cc',
'path_win.cc',
+ 'platform_font.h',
+ 'platform_font_gtk.h',
+ 'platform_font_gtk.cc',
+ 'platform_font_mac.h',
+ 'platform_font_mac.mm',
+ 'platform_font_win.h',
+ 'platform_font_win.cc',
'point.cc',
'point.h',
'rect.cc',
@@ -151,7 +156,6 @@
'../build/linux/system.gyp:gtk',
],
'sources': [
- 'font_skia.cc',
'gtk_native_view_id_manager.cc',
'gtk_native_view_id_manager.h',
'gtk_util.cc',
diff --git a/gfx/native_widget_types.h b/gfx/native_widget_types.h
index 5cc032a..51b0885 100644
--- a/gfx/native_widget_types.h
+++ b/gfx/native_widget_types.h
@@ -35,18 +35,22 @@
#if defined(OS_WIN)
#include <windows.h>
+typedef struct HFONT__* HFONT;
#elif defined(OS_MACOSX)
struct CGContext;
#ifdef __OBJC__
+@class NSFont;
@class NSView;
@class NSWindow;
@class NSTextField;
#else
+class NSFont;
class NSView;
class NSWindow;
class NSTextField;
#endif // __OBJC__
#elif defined(TOOLKIT_USES_GTK)
+typedef struct _PangoFontDescription PangoFontDescription;
typedef struct _GdkCursor GdkCursor;
typedef struct _GdkRegion GdkRegion;
typedef struct _GtkWidget GtkWidget;
@@ -57,6 +61,7 @@ typedef struct _cairo cairo_t;
namespace gfx {
#if defined(OS_WIN)
+typedef HFONT NativeFont;
typedef HWND NativeView;
typedef HWND NativeWindow;
typedef HWND NativeEditView;
@@ -65,6 +70,7 @@ typedef HCURSOR NativeCursor;
typedef HMENU NativeMenu;
typedef HRGN NativeRegion;
#elif defined(OS_MACOSX)
+typedef NSFont* NativeFont;
typedef NSView* NativeView;
typedef NSWindow* NativeWindow;
typedef NSTextField* NativeEditView;
@@ -72,6 +78,7 @@ typedef CGContext* NativeDrawingContext;
typedef void* NativeCursor;
typedef void* NativeMenu;
#elif defined(USE_X11)
+typedef PangoFontDescription* NativeFont;
typedef GtkWidget* NativeView;
typedef GtkWindow* NativeWindow;
typedef GtkWidget* NativeEditView;
diff --git a/gfx/platform_font.h b/gfx/platform_font.h
new file mode 100644
index 0000000..df3c7f2
--- /dev/null
+++ b/gfx/platform_font.h
@@ -0,0 +1,78 @@
+// Copyright (c) 2010 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.
+
+#ifndef GFX_PLATFORM_FONT_
+#define GFX_PLATFORM_FONT_
+#pragma once
+
+#include <string>
+
+#include "base/ref_counted.h"
+#include "gfx/native_widget_types.h"
+
+namespace gfx {
+
+class Font;
+
+class PlatformFont : public base::RefCounted<PlatformFont> {
+ public:
+ // Create an appropriate PlatformFont implementation.
+ static PlatformFont* CreateDefault();
+ static PlatformFont* CreateFromFont(const Font& other);
+ static PlatformFont* CreateFromNativeFont(NativeFont native_font);
+ static PlatformFont* CreateFromNameAndSize(const std::wstring& font_name,
+ int font_size);
+
+ // Returns a new Font derived from the existing font.
+ // size_delta is the size to add to the current font. See the single
+ // argument version of this method for an example.
+ // The style parameter specifies the new style for the font, and is a
+ // bitmask of the values: BOLD, ITALIC and UNDERLINED.
+ virtual Font DeriveFont(int size_delta, int style) const = 0;
+
+ // Returns the number of vertical pixels needed to display characters from
+ // the specified font. This may include some leading, i.e. height may be
+ // greater than just ascent + descent. Specifically, the Windows and Mac
+ // implementations include leading and the Linux one does not. This may
+ // need to be revisited in the future.
+ virtual int GetHeight() const = 0;
+
+ // Returns the baseline, or ascent, of the font.
+ virtual int GetBaseline() const = 0;
+
+ // Returns the average character width for the font.
+ virtual int GetAverageCharacterWidth() const = 0;
+
+ // Returns the number of horizontal pixels needed to display the specified
+ // string.
+ virtual int GetStringWidth(const std::wstring& text) const = 0;
+
+ // Returns the expected number of horizontal pixels needed to display the
+ // specified length of characters. Call GetStringWidth() to retrieve the
+ // actual number.
+ virtual int GetExpectedTextWidth(int length) const = 0;
+
+ // Returns the style of the font.
+ virtual int GetStyle() const = 0;
+
+ // Returns the font name.
+ virtual const std::wstring& GetFontName() const = 0;
+
+ // Returns the font size in pixels.
+ virtual int GetFontSize() const = 0;
+
+ // Returns the native font handle.
+ virtual NativeFont GetNativeFont() const = 0;
+
+ protected:
+ virtual ~PlatformFont() {}
+
+ private:
+ friend class base::RefCounted<PlatformFont>;
+};
+
+} // namespace gfx
+
+#endif // GFX_PLATFORM_FONT_
+
diff --git a/gfx/platform_font_gtk.cc b/gfx/platform_font_gtk.cc
new file mode 100644
index 0000000..db2e0c0
--- /dev/null
+++ b/gfx/platform_font_gtk.cc
@@ -0,0 +1,434 @@
+// Copyright (c) 2010 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 "gfx/platform_font_gtk.h"
+
+#include <algorithm>
+#include <fontconfig/fontconfig.h>
+#include <gdk/gdk.h>
+#include <gtk/gtk.h>
+#include <map>
+#include <pango/pango.h>
+
+#include "base/logging.h"
+#include "base/string_piece.h"
+#include "base/sys_string_conversions.h"
+#include "base/utf_string_conversions.h"
+#include "gfx/canvas_skia.h"
+#include "gfx/font.h"
+#include "gfx/gtk_util.h"
+#include "third_party/skia/include/core/SkTypeface.h"
+#include "third_party/skia/include/core/SkPaint.h"
+
+namespace {
+
+// The font family name which is used when a user's application font for
+// GNOME/KDE is a non-scalable one. The name should be listed in the
+// IsFallbackFontAllowed function in skia/ext/SkFontHost_fontconfig_direct.cpp.
+const char* kFallbackFontFamilyName = "sans";
+
+// Retrieves the pango metrics for a pango font description. Caches the metrics
+// and never frees them. The metrics objects are relatively small and
+// very expensive to look up.
+PangoFontMetrics* GetPangoFontMetrics(PangoFontDescription* desc) {
+ static std::map<int, PangoFontMetrics*>* desc_to_metrics = NULL;
+ static PangoContext* context = NULL;
+
+ if (!context) {
+ context = gdk_pango_context_get_for_screen(gdk_screen_get_default());
+ pango_context_set_language(context, pango_language_get_default());
+ }
+
+ if (!desc_to_metrics) {
+ desc_to_metrics = new std::map<int, PangoFontMetrics*>();
+ }
+
+ int desc_hash = pango_font_description_hash(desc);
+ std::map<int, PangoFontMetrics*>::iterator i =
+ desc_to_metrics->find(desc_hash);
+
+ if (i == desc_to_metrics->end()) {
+ PangoFontMetrics* metrics = pango_context_get_metrics(context, desc, NULL);
+ (*desc_to_metrics)[desc_hash] = metrics;
+ return metrics;
+ } else {
+ return i->second;
+ }
+}
+
+// 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.
+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;
+}
+
+} // namespace
+
+namespace gfx {
+
+Font* PlatformFontGtk::default_font_ = NULL;
+
+////////////////////////////////////////////////////////////////////////////////
+// PlatformFontGtk, public:
+
+PlatformFontGtk::PlatformFontGtk() {
+ if (default_font_ == NULL) {
+ GtkSettings* settings = gtk_settings_get_default();
+
+ gchar* font_name = NULL;
+ g_object_get(settings, "gtk-font-name", &font_name, NULL);
+
+ // Temporary CHECK for helping track down
+ // http://code.google.com/p/chromium/issues/detail?id=12530
+ CHECK(font_name) << " Unable to get gtk-font-name for default font.";
+
+ PangoFontDescription* desc =
+ pango_font_description_from_string(font_name);
+ default_font_ = new Font(desc);
+ pango_font_description_free(desc);
+ g_free(font_name);
+
+ DCHECK(default_font_);
+ }
+
+ InitFromPlatformFont(
+ static_cast<PlatformFontGtk*>(default_font_->platform_font()));
+}
+
+PlatformFontGtk::PlatformFontGtk(const Font& other) {
+ InitFromPlatformFont(
+ static_cast<PlatformFontGtk*>(other.platform_font()));
+}
+
+PlatformFontGtk::PlatformFontGtk(NativeFont native_font) {
+ gint size = pango_font_description_get_size(native_font);
+ const char* family_name = pango_font_description_get_family(native_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);
+
+ InitWithNameAndSize(font_family, size / PANGO_SCALE);
+ int style = 0;
+ if (pango_font_description_get_weight(native_font) == PANGO_WEIGHT_BOLD) {
+ // TODO(davemoore) What should we do about other weights? We currently
+ // only support BOLD.
+ style |= gfx::Font::BOLD;
+ }
+ if (pango_font_description_get_style(native_font) == PANGO_STYLE_ITALIC) {
+ // TODO(davemoore) What about PANGO_STYLE_OBLIQUE?
+ style |= gfx::Font::ITALIC;
+ }
+ if (style != 0)
+ style_ = style;
+}
+
+PlatformFontGtk::PlatformFontGtk(const std::wstring& font_name,
+ int font_size) {
+ InitWithNameAndSize(font_name, font_size);
+}
+
+double PlatformFontGtk::underline_position() const {
+ const_cast<PlatformFontGtk*>(this)->InitPangoMetrics();
+ return underline_position_;
+}
+
+double PlatformFontGtk::underline_thickness() const {
+ const_cast<PlatformFontGtk*>(this)->InitPangoMetrics();
+ return underline_thickness_;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// PlatformFontGtk, PlatformFont implementation:
+
+Font PlatformFontGtk::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(new PlatformFontGtk(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 (gfx::Font::BOLD & style)
+ skstyle |= SkTypeface::kBold;
+ if (gfx::Font::ITALIC & style)
+ skstyle |= SkTypeface::kItalic;
+
+ SkTypeface* typeface = SkTypeface::CreateFromName(
+ base::SysWideToUTF8(font_family_).c_str(),
+ static_cast<SkTypeface::Style>(skstyle));
+ SkAutoUnref tf_helper(typeface);
+
+ return Font(new PlatformFontGtk(typeface,
+ font_family_,
+ font_size_ + size_delta,
+ style));
+}
+
+int PlatformFontGtk::GetHeight() const {
+ return height_;
+}
+
+int PlatformFontGtk::GetBaseline() const {
+ return ascent_;
+}
+
+int PlatformFontGtk::GetAverageCharacterWidth() const {
+ return SkScalarRound(average_width_);
+}
+
+int PlatformFontGtk::GetStringWidth(const std::wstring& text) const {
+ int width = 0, height = 0;
+ CanvasSkia::SizeStringInt(text, Font(const_cast<PlatformFontGtk*>(this)),
+ &width, &height, gfx::Canvas::NO_ELLIPSIS);
+ return width;
+}
+
+int PlatformFontGtk::GetExpectedTextWidth(int length) const {
+ double char_width = const_cast<PlatformFontGtk*>(this)->GetAverageWidth();
+ return round(static_cast<float>(length) * char_width);
+}
+
+int PlatformFontGtk::GetStyle() const {
+ return style_;
+}
+
+const std::wstring& PlatformFontGtk::GetFontName() const {
+ return font_family_;
+}
+
+int PlatformFontGtk::GetFontSize() const {
+ return font_size_;
+}
+
+NativeFont PlatformFontGtk::GetNativeFont() const {
+ PangoFontDescription* pfd = pango_font_description_new();
+ pango_font_description_set_family(pfd, WideToUTF8(GetFontName()).c_str());
+ // Set the absolute size to avoid overflowing UI elements.
+ pango_font_description_set_absolute_size(pfd,
+ GetFontSize() * PANGO_SCALE * GetPangoScaleFactor());
+
+ switch (GetStyle()) {
+ 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;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// PlatformFontGtk, private:
+
+PlatformFontGtk::PlatformFontGtk(SkTypeface* typeface,
+ const std::wstring& name,
+ int size,
+ int style) {
+ InitWithTypefaceNameSizeAndStyle(typeface, name, size, style);
+}
+
+void PlatformFontGtk::InitWithNameAndSize(const std::wstring& font_name,
+ int font_size) {
+ DCHECK_GT(font_size, 0);
+ std::wstring fallback;
+
+ SkTypeface* typeface = SkTypeface::CreateFromName(
+ base::SysWideToUTF8(font_name).c_str(), SkTypeface::kNormal);
+ if (!typeface) {
+ // A non-scalable font such as .pcf is specified. Falls back to a default
+ // scalable font.
+ typeface = SkTypeface::CreateFromName(
+ kFallbackFontFamilyName, SkTypeface::kNormal);
+ CHECK(typeface) << "Could not find any font: "
+ << base::SysWideToUTF8(font_name)
+ << ", " << kFallbackFontFamilyName;
+ fallback = base::SysUTF8ToWide(kFallbackFontFamilyName);
+ }
+ SkAutoUnref typeface_helper(typeface);
+
+ InitWithTypefaceNameSizeAndStyle(typeface,
+ fallback.empty() ? font_name : fallback,
+ font_size,
+ gfx::Font::NORMAL);
+}
+
+void PlatformFontGtk::InitWithTypefaceNameSizeAndStyle(
+ SkTypeface* typeface,
+ const std::wstring& font_family,
+ int font_size,
+ int style) {
+ typeface_helper_.reset(new SkAutoUnref(typeface));
+ typeface_ = typeface;
+ typeface_->ref();
+ font_family_ = font_family;
+ font_size_ = font_size;
+ style_ = style;
+ pango_metrics_inited_ = false;
+ average_width_ = 0.0f;
+ underline_position_ = 0.0f;
+ underline_thickness_ = 0.0f;
+
+ SkPaint paint;
+ SkPaint::FontMetrics metrics;
+ PaintSetup(&paint);
+ paint.getFontMetrics(&metrics);
+
+ ascent_ = SkScalarCeil(-metrics.fAscent);
+ height_ = ascent_ + SkScalarCeil(metrics.fDescent);
+}
+
+void PlatformFontGtk::InitFromPlatformFont(const PlatformFontGtk* 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_;
+ pango_metrics_inited_ = other->pango_metrics_inited_;
+ average_width_ = other->average_width_;
+ underline_position_ = other->underline_position_;
+ underline_thickness_ = other->underline_thickness_;
+}
+
+void PlatformFontGtk::PaintSetup(SkPaint* paint) const {
+ paint->setAntiAlias(false);
+ paint->setSubpixelText(false);
+ paint->setTextSize(
+ SkFloatToScalar(font_size_ * PlatformFontGtk::GetPangoScaleFactor()));
+ paint->setTypeface(typeface_);
+ paint->setFakeBoldText((gfx::Font::BOLD & style_) && !typeface_->isBold());
+ paint->setTextSkewX((gfx::Font::ITALIC & style_) && !typeface_->isItalic() ?
+ -SK_Scalar1/4 : 0);
+}
+
+void PlatformFontGtk::InitPangoMetrics() {
+ if (!pango_metrics_inited_) {
+ pango_metrics_inited_ = true;
+ PangoFontDescription* pango_desc = GetNativeFont();
+ PangoFontMetrics* pango_metrics = GetPangoFontMetrics(pango_desc);
+
+ underline_position_ =
+ pango_font_metrics_get_underline_position(pango_metrics);
+ underline_position_ /= PANGO_SCALE;
+
+ // todo(davemoore) Come up with a better solution.
+ // This is a hack, but without doing this the underlines
+ // we get end up fuzzy. So we align to the midpoint of a pixel.
+ underline_position_ /= 2;
+
+ underline_thickness_ =
+ pango_font_metrics_get_underline_thickness(pango_metrics);
+ underline_thickness_ /= PANGO_SCALE;
+
+ // First get the pango based width
+ 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;
+ average_width_ = std::min(pango_width, dialog_units);
+ pango_font_description_free(pango_desc);
+ }
+}
+
+
+float PlatformFontGtk::GetPangoScaleFactor() {
+ // Pango scales font sizes. This returns the scale factor. See
+ // pango_cairo_context_set_resolution for details.
+ // NOTE: this isn't entirely accurate, in that Pango also consults the
+ // FC_PIXEL_SIZE first (see get_font_size in pangocairo-fcfont), but this
+ // seems to give us the same sizes as used by Pango for all our fonts in both
+ // English and Thai.
+ static float scale_factor = gfx::GetPangoResolution();
+ static bool determined_scale = false;
+ if (!determined_scale) {
+ if (scale_factor <= 0)
+ scale_factor = 1;
+ else
+ scale_factor /= 72.0;
+ determined_scale = true;
+ }
+ return scale_factor;
+}
+
+double PlatformFontGtk::GetAverageWidth() const {
+ const_cast<PlatformFontGtk*>(this)->InitPangoMetrics();
+ return average_width_;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// PlatformFont, public:
+
+// static
+PlatformFont* PlatformFont::CreateDefault() {
+ return new PlatformFontGtk;
+}
+
+// static
+PlatformFont* PlatformFont::CreateFromFont(const Font& other) {
+ return new PlatformFontGtk(other);
+}
+
+// static
+PlatformFont* PlatformFont::CreateFromNativeFont(NativeFont native_font) {
+ return new PlatformFontGtk(native_font);
+}
+
+// static
+PlatformFont* PlatformFont::CreateFromNameAndSize(const std::wstring& font_name,
+ int font_size) {
+ return new PlatformFontGtk(font_name, font_size);
+}
+
+} // namespace gfx
diff --git a/gfx/platform_font_gtk.h b/gfx/platform_font_gtk.h
new file mode 100644
index 0000000..3c507fb
--- /dev/null
+++ b/gfx/platform_font_gtk.h
@@ -0,0 +1,111 @@
+// Copyright (c) 2010 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.
+
+#ifndef GFX_PLATFORM_FONT_GTK_
+#define GFX_PLATFORM_FONT_GTK_
+#pragma once
+
+#include "base/scoped_ptr.h"
+#include "gfx/platform_font.h"
+#include "third_party/skia/include/core/SkRefCnt.h"
+
+class SkTypeface;
+class SkPaint;
+
+namespace gfx {
+
+class PlatformFontGtk : public PlatformFont {
+ public:
+ PlatformFontGtk();
+ explicit PlatformFontGtk(const Font& other);
+ explicit PlatformFontGtk(NativeFont native_font);
+ PlatformFontGtk(const std::wstring& font_name,
+ int font_size);
+
+ // 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);
+
+ // Position as an offset from the height of the drawn text, used to draw
+ // an underline. This is a negative number, so the underline would be
+ // drawn at y + height + underline_position;
+ double underline_position() const;
+ // The thickness to draw the underline.
+ double underline_thickness() const;
+
+ // Overridden from PlatformFont:
+ virtual Font DeriveFont(int size_delta, int style) const;
+ virtual int GetHeight() const;
+ virtual int GetBaseline() const;
+ virtual int GetAverageCharacterWidth() const;
+ virtual int GetStringWidth(const std::wstring& text) const;
+ virtual int GetExpectedTextWidth(int length) const;
+ virtual int GetStyle() const;
+ virtual const std::wstring& GetFontName() const;
+ virtual int GetFontSize() const;
+ virtual NativeFont GetNativeFont() const;
+
+ private:
+ // Create a new instance of this object with the specified properties. Called
+ // from DeriveFont.
+ PlatformFontGtk(SkTypeface* typeface,
+ const std::wstring& name,
+ int size,
+ int style);
+ virtual ~PlatformFontGtk() {}
+
+ // Initialize this object.
+ void InitWithNameAndSize(const std::wstring& font_name, int font_size);
+ void InitWithTypefaceNameSizeAndStyle(SkTypeface* typeface,
+ const std::wstring& name,
+ int size,
+ int style);
+ void InitFromPlatformFont(const PlatformFontGtk* other);
+
+ // Potentially slow call to get pango metrics (average width, underline info).
+ void InitPangoMetrics();
+
+ // Setup a Skia context to use the current typeface
+ void PaintSetup(SkPaint* paint) const;
+
+ // Make |this| a copy of |other|.
+ void CopyFont(const Font& other);
+
+ // Return the scale factor for fonts that account for DPI.
+ static float GetPangoScaleFactor();
+
+ // The average width of a character, initialized and cached if needed.
+ double GetAverageWidth() const;
+
+ // 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_;
+
+ // 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_;
+
+ // Cached metrics, generated at construction
+ int height_;
+ int ascent_;
+
+ // The pango metrics are much more expensive so we wait until we need them
+ // to compute them.
+ bool pango_metrics_inited_;
+ double average_width_;
+ double underline_position_;
+ double underline_thickness_;
+
+ // The default font, used for the default constructor.
+ static Font* default_font_;
+};
+
+} // namespace gfx
+
+#endif // GFX_PLATFORM_FONT_GTK_
+
diff --git a/gfx/platform_font_mac.h b/gfx/platform_font_mac.h
new file mode 100644
index 0000000..71a8262
--- /dev/null
+++ b/gfx/platform_font_mac.h
@@ -0,0 +1,57 @@
+// Copyright (c) 2010 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.
+
+#ifndef GFX_PLATFORM_FONT_MAC_
+#define GFX_PLATFORM_FONT_MAC_
+#pragma once
+
+#include "gfx/platform_font.h"
+
+namespace gfx {
+
+class PlatformFontMac : public PlatformFont {
+ public:
+ PlatformFontMac();
+ explicit PlatformFontMac(const Font& other);
+ explicit PlatformFontMac(NativeFont native_font);
+ PlatformFontMac(const std::wstring& font_name,
+ int font_size);
+
+ // Overridden from PlatformFont:
+ virtual Font DeriveFont(int size_delta, int style) const;
+ virtual int GetHeight() const;
+ virtual int GetBaseline() const;
+ virtual int GetAverageCharacterWidth() const;
+ virtual int GetStringWidth(const std::wstring& text) const;
+ virtual int GetExpectedTextWidth(int length) const;
+ virtual int GetStyle() const;
+ virtual const std::wstring& GetFontName() const;
+ virtual int GetFontSize() const;
+ virtual NativeFont GetNativeFont() const;
+
+ private:
+ PlatformFontMac(const std::wstring& font_name, int font_size, int style);
+ virtual ~PlatformFontMac() {}
+
+ // Initialize the object with the specified parameters.
+ void InitWithNameSizeAndStyle(const std::wstring& font_name,
+ int font_size,
+ int style);
+
+ // Calculate and cache the font metrics.
+ void CalculateMetrics();
+
+ std::wstring font_name_;
+ int font_size_;
+ int style_;
+
+ // Cached metrics, generated at construction
+ int height_;
+ int ascent_;
+ int average_width_;
+};
+
+} // namespace gfx
+
+#endif // GFX_PLATFORM_FONT_MAC_
diff --git a/gfx/platform_font_mac.mm b/gfx/platform_font_mac.mm
new file mode 100644
index 0000000..89616c5
--- /dev/null
+++ b/gfx/platform_font_mac.mm
@@ -0,0 +1,142 @@
+// Copyright (c) 2010 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 "gfx/platform_font_mac.h"
+
+#include <Cocoa/Cocoa.h>
+
+#include "base/logging.h"
+#include "base/scoped_nsobject.h"
+#include "base/sys_string_conversions.h"
+#include "gfx/canvas_skia.h"
+#include "gfx/font.h"
+
+namespace gfx {
+
+////////////////////////////////////////////////////////////////////////////////
+// PlatformFontMac, public:
+
+PlatformFontMac::PlatformFontMac() {
+ font_size_ = [NSFont systemFontSize];
+ style_ = gfx::Font::NORMAL;
+ NSFont* system_font = [NSFont systemFontOfSize:font_size_];
+ font_name_ = base::SysNSStringToWide([system_font fontName]);
+ CalculateMetrics();
+}
+
+PlatformFontMac::PlatformFontMac(const Font& other) {
+}
+
+PlatformFontMac::PlatformFontMac(NativeFont native_font) {
+}
+
+PlatformFontMac::PlatformFontMac(const std::wstring& font_name,
+ int font_size) {
+ InitWithNameSizeAndStyle(font_name, font_size, gfx::Font::NORMAL);
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// PlatformFontMac, PlatformFont implementation:
+
+Font PlatformFontMac::DeriveFont(int size_delta, int style) const {
+ return Font(new PlatformFontMac(font_name_, font_size_ + size_delta, style));
+}
+
+int PlatformFontMac::GetHeight() const {
+ return height_;
+}
+
+int PlatformFontMac::GetBaseline() const {
+ return ascent_;
+}
+
+int PlatformFontMac::GetAverageCharacterWidth() const {
+ return average_width_;
+}
+
+int PlatformFontMac::GetStringWidth(const std::wstring& text) const {
+ int width = 0, height = 0;
+ CanvasSkia::SizeStringInt(text, Font(const_cast<PlatformFontMac*>(this)),
+ &width, &height, gfx::Canvas::NO_ELLIPSIS);
+ return width;
+}
+
+int PlatformFontMac::GetExpectedTextWidth(int length) const {
+ return length * average_width_;
+}
+
+int PlatformFontMac::GetStyle() const {
+ return style_;
+}
+
+const std::wstring& PlatformFontMac::GetFontName() const {
+ return font_name_;
+}
+
+int PlatformFontMac::GetFontSize() const {
+ return font_size_;
+}
+
+NativeFont PlatformFontMac::GetNativeFont() const {
+ // TODO(pinkerton): apply |style_| to font. http://crbug.com/34667
+ // We could cache this, but then we'd have to conditionally change the
+ // dtor just for MacOS. Not sure if we want to/need to do that.
+ return [NSFont fontWithName:base::SysWideToNSString(font_name_)
+ size:font_size_];
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// PlatformFontMac, private:
+
+PlatformFontMac::PlatformFontMac(const std::wstring& font_name,
+ int font_size,
+ int style) {
+ InitWithNameSizeAndStyle(font_name, font_size, style);
+}
+
+void PlatformFontMac::InitWithNameSizeAndStyle(const std::wstring& font_name,
+ int font_size,
+ int style) {
+ font_name_ = font_name;
+ font_size_ = font_size;
+ style_ = style;
+ CalculateMetrics();
+}
+
+void PlatformFontMac::CalculateMetrics() {
+ NSFont* font = GetNativeFont();
+ scoped_nsobject<NSLayoutManager> layout_manager(
+ [[NSLayoutManager alloc] init]);
+ height_ = [layout_manager defaultLineHeightForFont:font];
+ ascent_ = [font ascender];
+ average_width_ =
+ [font boundingRectForGlyph:[font glyphWithName:@"x"]].size.width;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// PlatformFont, public:
+
+// static
+PlatformFont* PlatformFont::CreateDefault() {
+ return new PlatformFontMac;
+}
+
+// static
+PlatformFont* PlatformFont::CreateFromFont(const Font& other) {
+ return new PlatformFontMac(other);
+}
+
+// static
+PlatformFont* PlatformFont::CreateFromNativeFont(NativeFont native_font) {
+ return new PlatformFontMac(native_font);
+}
+
+// static
+PlatformFont* PlatformFont::CreateFromNameAndSize(const std::wstring& font_name,
+ int font_size) {
+ return new PlatformFontMac(font_name, font_size);
+}
+
+} // namespace gfx
+
diff --git a/gfx/platform_font_win.cc b/gfx/platform_font_win.cc
new file mode 100644
index 0000000..41cadde
--- /dev/null
+++ b/gfx/platform_font_win.cc
@@ -0,0 +1,268 @@
+// Copyright (c) 2010 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 "gfx/platform_font_win.h"
+
+#include <windows.h>
+#include <math.h>
+
+#include <algorithm>
+
+#include "base/logging.h"
+#include "base/string_util.h"
+#include "base/win_util.h"
+#include "gfx/canvas_skia.h"
+#include "gfx/font.h"
+
+namespace {
+
+// If the tmWeight field of a TEXTMETRIC structure has a value >= this, the
+// font is bold.
+const int kTextMetricWeightBold = 700;
+
+// Returns either minimum font allowed for a current locale or
+// lf_height + size_delta value.
+int AdjustFontSize(int lf_height, int size_delta) {
+ if (lf_height < 0) {
+ lf_height -= size_delta;
+ } else {
+ lf_height += size_delta;
+ }
+ int min_font_size = 0;
+ if (gfx::PlatformFontWin::get_minimum_font_size_callback)
+ min_font_size = gfx::PlatformFontWin::get_minimum_font_size_callback();
+ // Make sure lf_height is not smaller than allowed min font size for current
+ // locale.
+ if (abs(lf_height) < min_font_size) {
+ return lf_height < 0 ? -min_font_size : min_font_size;
+ } else {
+ return lf_height;
+ }
+}
+
+} // namespace
+
+namespace gfx {
+
+// static
+PlatformFontWin::HFontRef* PlatformFontWin::base_font_ref_;
+
+// static
+PlatformFontWin::AdjustFontCallback
+ PlatformFontWin::adjust_font_callback = NULL;
+PlatformFontWin::GetMinimumFontSizeCallback
+ PlatformFontWin::get_minimum_font_size_callback = NULL;
+
+////////////////////////////////////////////////////////////////////////////////
+// PlatformFontWin, public
+
+PlatformFontWin::PlatformFontWin() : font_ref_(GetBaseFontRef()) {
+}
+
+PlatformFontWin::PlatformFontWin(const Font& other) {
+ InitWithCopyOfHFONT(other.GetNativeFont());
+}
+
+PlatformFontWin::PlatformFontWin(NativeFont native_font) {
+ InitWithCopyOfHFONT(native_font);
+}
+
+PlatformFontWin::PlatformFontWin(const std::wstring& font_name,
+ int font_size) {
+ InitWithFontNameAndSize(font_name, font_size);
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// PlatformFontWin, PlatformFont implementation:
+
+Font PlatformFontWin::DeriveFont(int size_delta, int style) const {
+ LOGFONT font_info;
+ GetObject(GetNativeFont(), sizeof(LOGFONT), &font_info);
+ font_info.lfHeight = AdjustFontSize(font_info.lfHeight, size_delta);
+ font_info.lfUnderline =
+ ((style & gfx::Font::UNDERLINED) == gfx::Font::UNDERLINED);
+ font_info.lfItalic = ((style & gfx::Font::ITALIC) == gfx::Font::ITALIC);
+ font_info.lfWeight = (style & gfx::Font::BOLD) ? FW_BOLD : FW_NORMAL;
+
+ HFONT hfont = CreateFontIndirect(&font_info);
+ return Font(new PlatformFontWin(CreateHFontRef(hfont)));
+}
+
+int PlatformFontWin::GetHeight() const {
+ return font_ref_->height();
+}
+
+int PlatformFontWin::GetBaseline() const {
+ return font_ref_->baseline();
+}
+
+int PlatformFontWin::GetAverageCharacterWidth() const {
+ return font_ref_->ave_char_width();
+}
+
+int PlatformFontWin::GetStringWidth(const std::wstring& text) const {
+ int width = 0, height = 0;
+ CanvasSkia::SizeStringInt(text, Font(const_cast<PlatformFontWin*>(this)),
+ &width, &height, gfx::Canvas::NO_ELLIPSIS);
+ return width;
+}
+
+int PlatformFontWin::GetExpectedTextWidth(int length) const {
+ return length * std::min(font_ref_->dlu_base_x(), GetAverageCharacterWidth());
+}
+
+int PlatformFontWin::GetStyle() const {
+ return font_ref_->style();
+}
+
+const std::wstring& PlatformFontWin::GetFontName() const {
+ return font_ref_->font_name();
+}
+
+int PlatformFontWin::GetFontSize() const {
+ LOGFONT font_info;
+ GetObject(font_ref_->hfont(), sizeof(LOGFONT), &font_info);
+ long lf_height = font_info.lfHeight;
+ HDC hdc = GetDC(NULL);
+ int device_caps = GetDeviceCaps(hdc, LOGPIXELSY);
+ int font_size = 0;
+ if (device_caps != 0) {
+ float font_size_float = -static_cast<float>(lf_height)*72/device_caps;
+ font_size = static_cast<int>(::ceil(font_size_float - 0.5));
+ }
+ ReleaseDC(NULL, hdc);
+ return font_size;
+}
+
+NativeFont PlatformFontWin::GetNativeFont() const {
+ return font_ref_->hfont();
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// Font, private:
+
+void PlatformFontWin::InitWithCopyOfHFONT(HFONT hfont) {
+ DCHECK(hfont);
+ LOGFONT font_info;
+ GetObject(hfont, sizeof(LOGFONT), &font_info);
+ font_ref_ = CreateHFontRef(CreateFontIndirect(&font_info));
+}
+
+void PlatformFontWin::InitWithFontNameAndSize(const std::wstring& font_name,
+ int font_size) {
+ HDC hdc = GetDC(NULL);
+ long lf_height = -MulDiv(font_size, GetDeviceCaps(hdc, LOGPIXELSY), 72);
+ ReleaseDC(NULL, hdc);
+ HFONT hf = ::CreateFont(lf_height, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ font_name.c_str());
+ font_ref_ = CreateHFontRef(hf);
+}
+
+// static
+PlatformFontWin::HFontRef* PlatformFontWin::GetBaseFontRef() {
+ if (base_font_ref_ == NULL) {
+ NONCLIENTMETRICS metrics;
+ win_util::GetNonClientMetrics(&metrics);
+
+ if (adjust_font_callback)
+ adjust_font_callback(&metrics.lfMessageFont);
+ metrics.lfMessageFont.lfHeight =
+ AdjustFontSize(metrics.lfMessageFont.lfHeight, 0);
+ HFONT font = CreateFontIndirect(&metrics.lfMessageFont);
+ DLOG_ASSERT(font);
+ base_font_ref_ = PlatformFontWin::CreateHFontRef(font);
+ // base_font_ref_ is global, up the ref count so it's never deleted.
+ base_font_ref_->AddRef();
+ }
+ return base_font_ref_;
+}
+
+PlatformFontWin::HFontRef* PlatformFontWin::CreateHFontRef(HFONT font) {
+ TEXTMETRIC font_metrics;
+ HDC screen_dc = GetDC(NULL);
+ HFONT previous_font = static_cast<HFONT>(SelectObject(screen_dc, font));
+ int last_map_mode = SetMapMode(screen_dc, MM_TEXT);
+ GetTextMetrics(screen_dc, &font_metrics);
+ // Yes, this is how Microsoft recommends calculating the dialog unit
+ // conversions.
+ SIZE ave_text_size;
+ GetTextExtentPoint32(screen_dc,
+ L"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz",
+ 52, &ave_text_size);
+ const int dlu_base_x = (ave_text_size.cx / 26 + 1) / 2;
+ // To avoid the DC referencing font_handle_, select the previous font.
+ SelectObject(screen_dc, previous_font);
+ SetMapMode(screen_dc, last_map_mode);
+ ReleaseDC(NULL, screen_dc);
+
+ const int height = std::max(1, static_cast<int>(font_metrics.tmHeight));
+ const int baseline = std::max(1, static_cast<int>(font_metrics.tmAscent));
+ const int ave_char_width =
+ std::max(1, static_cast<int>(font_metrics.tmAveCharWidth));
+ int style = 0;
+ if (font_metrics.tmItalic)
+ style |= Font::ITALIC;
+ if (font_metrics.tmUnderlined)
+ style |= Font::UNDERLINED;
+ if (font_metrics.tmWeight >= kTextMetricWeightBold)
+ style |= Font::BOLD;
+
+ return new HFontRef(font, height, baseline, ave_char_width, style,
+ dlu_base_x);
+}
+
+PlatformFontWin::PlatformFontWin(HFontRef* hfont_ref) : font_ref_(hfont_ref) {
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// PlatformFontWin::HFontRef:
+
+PlatformFontWin::HFontRef::HFontRef(HFONT hfont,
+ int height,
+ int baseline,
+ int ave_char_width,
+ int style,
+ int dlu_base_x)
+ : hfont_(hfont),
+ height_(height),
+ baseline_(baseline),
+ ave_char_width_(ave_char_width),
+ style_(style),
+ dlu_base_x_(dlu_base_x) {
+ DLOG_ASSERT(hfont);
+
+ LOGFONT font_info;
+ GetObject(hfont_, sizeof(LOGFONT), &font_info);
+ font_name_ = std::wstring(font_info.lfFaceName);
+}
+
+PlatformFontWin::HFontRef::~HFontRef() {
+ DeleteObject(hfont_);
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// PlatformFont, public:
+
+// static
+PlatformFont* PlatformFont::CreateDefault() {
+ return new PlatformFontWin;
+}
+
+// static
+PlatformFont* PlatformFont::CreateFromFont(const Font& other) {
+ return new PlatformFontWin(other);
+}
+
+// static
+PlatformFont* PlatformFont::CreateFromNativeFont(NativeFont native_font) {
+ return new PlatformFontWin(native_font);
+}
+
+// static
+PlatformFont* PlatformFont::CreateFromNameAndSize(const std::wstring& font_name,
+ int font_size) {
+ return new PlatformFontWin(font_name, font_size);
+}
+
+} // namespace gfx
diff --git a/gfx/platform_font_win.h b/gfx/platform_font_win.h
new file mode 100644
index 0000000..1fd89166
--- /dev/null
+++ b/gfx/platform_font_win.h
@@ -0,0 +1,131 @@
+// Copyright (c) 2010 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.
+
+#ifndef GFX_PLATFORM_FONT_WIN_
+#define GFX_PLATFORM_FONT_WIN_
+#pragma once
+
+#include "base/ref_counted.h"
+#include "gfx/platform_font.h"
+
+namespace gfx {
+
+class PlatformFontWin : public PlatformFont {
+ public:
+ PlatformFontWin();
+ explicit PlatformFontWin(const Font& other);
+ explicit PlatformFontWin(NativeFont native_font);
+ PlatformFontWin(const std::wstring& font_name,
+ int font_size);
+
+ // Dialog units to pixels conversion.
+ // See http://support.microsoft.com/kb/145994 for details.
+ int horizontal_dlus_to_pixels(int dlus) const {
+ return dlus * font_ref_->dlu_base_x() / 4;
+ }
+ int vertical_dlus_to_pixels(int dlus) const {
+ return dlus * font_ref_->height() / 8;
+ }
+
+ // Callback that returns the minimum height that should be used for
+ // gfx::Fonts. Optional. If not specified, the minimum font size is 0.
+ typedef int (*GetMinimumFontSizeCallback)();
+ static GetMinimumFontSizeCallback get_minimum_font_size_callback;
+
+ // Callback that adjusts a LOGFONT to meet suitability requirements of the
+ // embedding application. Optional. If not specified, no adjustments are
+ // performed other than clamping to a minimum font height if
+ // |get_minimum_font_size_callback| is specified.
+ typedef void (*AdjustFontCallback)(LOGFONT* lf);
+ static AdjustFontCallback adjust_font_callback;
+
+ // Overridden from PlatformFont:
+ virtual Font DeriveFont(int size_delta, int style) const;
+ virtual int GetHeight() const;
+ virtual int GetBaseline() const;
+ virtual int GetAverageCharacterWidth() const;
+ virtual int GetStringWidth(const std::wstring& text) const;
+ virtual int GetExpectedTextWidth(int length) const;
+ virtual int GetStyle() const;
+ virtual const std::wstring& GetFontName() const;
+ virtual int GetFontSize() const;
+ virtual NativeFont GetNativeFont() const;
+
+ private:
+ virtual ~PlatformFontWin() {}
+
+ // Chrome text drawing bottoms out in the Windows GDI functions that take an
+ // HFONT (an opaque handle into Windows). To avoid lots of GDI object
+ // allocation and destruction, Font indirectly refers to the HFONT by way of
+ // an HFontRef. That is, every Font has an HFontRef, which has an HFONT.
+ //
+ // HFontRef is reference counted. Upon deletion, it deletes the HFONT.
+ // By making HFontRef maintain the reference to the HFONT, multiple
+ // HFontRefs can share the same HFONT, and Font can provide value semantics.
+ class HFontRef : public base::RefCounted<HFontRef> {
+ public:
+ // This constructor takes control of the HFONT, and will delete it when
+ // the HFontRef is deleted.
+ HFontRef(HFONT hfont,
+ int height,
+ int baseline,
+ int ave_char_width,
+ int style,
+ int dlu_base_x);
+
+ // Accessors
+ HFONT hfont() const { return hfont_; }
+ int height() const { return height_; }
+ int baseline() const { return baseline_; }
+ int ave_char_width() const { return ave_char_width_; }
+ int style() const { return style_; }
+ int dlu_base_x() const { return dlu_base_x_; }
+ const std::wstring& font_name() const { return font_name_; }
+
+ private:
+ friend class base::RefCounted<HFontRef>;
+
+ ~HFontRef();
+
+ const HFONT hfont_;
+ const int height_;
+ const int baseline_;
+ const int ave_char_width_;
+ const int style_;
+ // Constants used in converting dialog units to pixels.
+ const int dlu_base_x_;
+ std::wstring font_name_;
+
+ DISALLOW_COPY_AND_ASSIGN(HFontRef);
+ };
+
+ // Initializes this object with a copy of the specified HFONT.
+ void InitWithCopyOfHFONT(HFONT hfont);
+
+ // Initializes this object with the specified font name and size.
+ void InitWithFontNameAndSize(const std::wstring& font_name,
+ int font_size);
+
+ // Returns the base font ref. This should ONLY be invoked on the
+ // UI thread.
+ static HFontRef* GetBaseFontRef();
+
+ // Creates and returns a new HFONTRef from the specified HFONT.
+ static HFontRef* CreateHFontRef(HFONT font);
+
+ // Creates a new PlatformFontWin with the specified HFontRef. Used when
+ // constructing a Font from a HFONT we don't want to copy.
+ explicit PlatformFontWin(HFontRef* hfont_ref);
+
+ // Reference to the base font all fonts are derived from.
+ static HFontRef* base_font_ref_;
+
+ // Indirect reference to the HFontRef, which references the underlying HFONT.
+ scoped_refptr<HFontRef> font_ref_;
+};
+
+} // namespace gfx
+
+#endif // GFX_PLATFORM_FONT_WIN_
+