summaryrefslogtreecommitdiffstats
path: root/gfx/font_skia.cc
diff options
context:
space:
mode:
authorben@chromium.org <ben@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-03-23 04:05:01 +0000
committerben@chromium.org <ben@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-03-23 04:05:01 +0000
commitd07b6b5b992faad3506ac004503c11d25930cdca (patch)
treea5a795b8980d90e4a10208ad4f8eabe140ee3e5e /gfx/font_skia.cc
parentf2a13d89ca22cdbe3808bcb14e02d5baee8d33b3 (diff)
downloadchromium_src-d07b6b5b992faad3506ac004503c11d25930cdca.zip
chromium_src-d07b6b5b992faad3506ac004503c11d25930cdca.tar.gz
chromium_src-d07b6b5b992faad3506ac004503c11d25930cdca.tar.bz2
Move app/gfx/canvas and app/gfx/font to gfx/.
TBR=darin BUG=none TEST=none Review URL: http://codereview.chromium.org/1132006 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@42312 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'gfx/font_skia.cc')
-rw-r--r--gfx/font_skia.cc255
1 files changed, 255 insertions, 0 deletions
diff --git a/gfx/font_skia.cc b/gfx/font_skia.cc
new file mode 100644
index 0000000..fffc53e
--- /dev/null
+++ b/gfx/font_skia.cc
@@ -0,0 +1,255 @@
+// 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 <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.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;
+
+ Canvas::SizeStringInt(text, *this, &width, &height, 0);
+ 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