Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(67)

Side by Side Diff: gfx/font_skia.cc

Issue 3083022: Rework gfx::Font by moving platform-specific code into inner classes.... (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src/
Patch Set: '' Created 10 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « gfx/font_mac.mm ('k') | gfx/font_unittest.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 // Copyright (c) 2010 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "gfx/font.h"
6
7 #include <gdk/gdk.h>
8 #include <map>
9 #include <pango/pango.h>
10
11 #include "base/logging.h"
12 #include "base/string_piece.h"
13 #include "base/sys_string_conversions.h"
14 #include "gfx/canvas_skia.h"
15 #include "third_party/skia/include/core/SkTypeface.h"
16 #include "third_party/skia/include/core/SkPaint.h"
17
18 namespace {
19
20 // The font family name which is used when a user's application font for
21 // GNOME/KDE is a non-scalable one. The name should be listed in the
22 // IsFallbackFontAllowed function in skia/ext/SkFontHost_fontconfig_direct.cpp.
23 const char* kFallbackFontFamilyName = "sans";
24
25 // Retrieves the pango metrics for a pango font description. Caches the metrics
26 // and never frees them. The metrics objects are relatively small and
27 // very expensive to look up.
28 static PangoFontMetrics* GetPangoFontMetrics(PangoFontDescription* desc) {
29 static std::map<int, PangoFontMetrics*>* desc_to_metrics = NULL;
30 static PangoContext* context = NULL;
31
32 if (!context) {
33 context = gdk_pango_context_get_for_screen(gdk_screen_get_default());
34 pango_context_set_language(context, pango_language_get_default());
35 }
36
37 if (!desc_to_metrics) {
38 desc_to_metrics = new std::map<int, PangoFontMetrics*>();
39 }
40
41 int desc_hash = pango_font_description_hash(desc);
42 std::map<int, PangoFontMetrics*>::iterator i =
43 desc_to_metrics->find(desc_hash);
44
45 if (i == desc_to_metrics->end()) {
46 PangoFontMetrics* metrics = pango_context_get_metrics(context, desc, NULL);
47 (*desc_to_metrics)[desc_hash] = metrics;
48 return metrics;
49 } else {
50 return i->second;
51 }
52 }
53
54 } // namespace
55
56 namespace gfx {
57
58 Font::Font(const Font& other) {
59 CopyFont(other);
60 }
61
62 Font& Font::operator=(const Font& other) {
63 CopyFont(other);
64 return *this;
65 }
66
67 Font::Font(SkTypeface* tf, const std::wstring& font_family, int font_size,
68 int style)
69 : typeface_helper_(new SkAutoUnref(tf)),
70 typeface_(tf),
71 font_family_(font_family),
72 font_size_(font_size),
73 style_(style),
74 pango_metrics_inited_(false),
75 avg_width_(0.0),
76 underline_position_(0.0),
77 underline_thickness_(0.0) {
78 tf->ref();
79 calculateMetrics();
80 }
81
82 void Font::calculateMetrics() {
83 SkPaint paint;
84 SkPaint::FontMetrics metrics;
85 PaintSetup(&paint);
86 paint.getFontMetrics(&metrics);
87
88 ascent_ = SkScalarCeil(-metrics.fAscent);
89 height_ = ascent_ + SkScalarCeil(metrics.fDescent);
90
91 }
92
93 void Font::CopyFont(const Font& other) {
94 typeface_helper_.reset(new SkAutoUnref(other.typeface_));
95 typeface_ = other.typeface_;
96 typeface_->ref();
97 font_family_ = other.font_family_;
98 font_size_ = other.font_size_;
99 style_ = other.style_;
100 height_ = other.height_;
101 ascent_ = other.ascent_;
102 pango_metrics_inited_ = other.pango_metrics_inited_;
103 avg_width_ = other.avg_width_;
104 underline_position_ = other.underline_position_;
105 underline_thickness_ = other.underline_thickness_;
106 }
107
108 int Font::height() const {
109 return height_;
110 }
111
112 int Font::baseline() const {
113 return ascent_;
114 }
115
116 int Font::ave_char_width() const {
117 return SkScalarRound(avg_width());
118 }
119
120 Font Font::CreateFont(const std::wstring& font_family, int font_size) {
121 DCHECK_GT(font_size, 0);
122 std::wstring fallback;
123
124 SkTypeface* tf = SkTypeface::CreateFromName(
125 base::SysWideToUTF8(font_family).c_str(), SkTypeface::kNormal);
126 if (!tf) {
127 // A non-scalable font such as .pcf is specified. Falls back to a default
128 // scalable font.
129 tf = SkTypeface::CreateFromName(
130 kFallbackFontFamilyName, SkTypeface::kNormal);
131 CHECK(tf) << "Could not find any font: "
132 << base::SysWideToUTF8(font_family)
133 << ", " << kFallbackFontFamilyName;
134 fallback = base::SysUTF8ToWide(kFallbackFontFamilyName);
135 }
136 SkAutoUnref tf_helper(tf);
137
138 return Font(
139 tf, fallback.empty() ? font_family : fallback, font_size, NORMAL);
140 }
141
142 Font Font::DeriveFont(int size_delta, int style) const {
143 // If the delta is negative, if must not push the size below 1
144 if (size_delta < 0) {
145 DCHECK_LT(-size_delta, font_size_);
146 }
147
148 if (style == style_) {
149 // Fast path, we just use the same typeface at a different size
150 return Font(typeface_, font_family_, font_size_ + size_delta, style_);
151 }
152
153 // If the style has changed we may need to load a new face
154 int skstyle = SkTypeface::kNormal;
155 if (BOLD & style)
156 skstyle |= SkTypeface::kBold;
157 if (ITALIC & style)
158 skstyle |= SkTypeface::kItalic;
159
160 SkTypeface* tf = SkTypeface::CreateFromName(
161 base::SysWideToUTF8(font_family_).c_str(),
162 static_cast<SkTypeface::Style>(skstyle));
163 SkAutoUnref tf_helper(tf);
164
165 return Font(tf, font_family_, font_size_ + size_delta, style);
166 }
167
168 void Font::PaintSetup(SkPaint* paint) const {
169 paint->setAntiAlias(false);
170 paint->setSubpixelText(false);
171 paint->setTextSize(SkFloatToScalar(font_size_ * Font::GetPangoScaleFactor()));
172 paint->setTypeface(typeface_);
173 paint->setFakeBoldText((BOLD & style_) && !typeface_->isBold());
174 paint->setTextSkewX((ITALIC & style_) && !typeface_->isItalic() ?
175 -SK_Scalar1/4 : 0);
176 }
177
178 int Font::GetStringWidth(const std::wstring& text) const {
179 int width = 0, height = 0;
180 CanvasSkia::SizeStringInt(text, *this, &width, &height,
181 gfx::Canvas::NO_ELLIPSIS);
182 return width;
183 }
184
185 void Font::InitPangoMetrics() {
186 if (!pango_metrics_inited_) {
187 pango_metrics_inited_ = true;
188 PangoFontDescription* pango_desc = PangoFontFromGfxFont(*this);
189 PangoFontMetrics* pango_metrics = GetPangoFontMetrics(pango_desc);
190
191 underline_position_ =
192 pango_font_metrics_get_underline_position(pango_metrics);
193 underline_position_ /= PANGO_SCALE;
194
195 // todo(davemoore) Come up with a better solution.
196 // This is a hack, but without doing this the underlines
197 // we get end up fuzzy. So we align to the midpoint of a pixel.
198 underline_position_ /= 2;
199
200 underline_thickness_ =
201 pango_font_metrics_get_underline_thickness(pango_metrics);
202 underline_thickness_ /= PANGO_SCALE;
203
204 // First get the pango based width
205 double pango_width =
206 pango_font_metrics_get_approximate_char_width(pango_metrics);
207 pango_width /= PANGO_SCALE;
208
209 // Yes, this is how Microsoft recommends calculating the dialog unit
210 // conversions.
211 int text_width = GetStringWidth(
212 L"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz");
213 double dialog_units = (text_width / 26 + 1) / 2;
214 avg_width_ = std::min(pango_width, dialog_units);
215 pango_font_description_free(pango_desc);
216 }
217 }
218
219 double Font::avg_width() const {
220 const_cast<Font*>(this)->InitPangoMetrics();
221 return avg_width_;
222 }
223
224 double Font::underline_position() const {
225 const_cast<Font*>(this)->InitPangoMetrics();
226 return underline_position_;
227 }
228
229 double Font::underline_thickness() const {
230 const_cast<Font*>(this)->InitPangoMetrics();
231 return underline_thickness_;
232 }
233
234 int Font::GetExpectedTextWidth(int length) const {
235 double char_width = const_cast<Font*>(this)->avg_width();
236 return round(static_cast<float>(length) * char_width);
237 }
238
239 int Font::style() const {
240 return style_;
241 }
242
243 const std::wstring& Font::FontName() const {
244 return font_family_;
245 }
246
247 int Font::FontSize() {
248 return font_size_;
249 }
250
251 NativeFont Font::nativeFont() const {
252 return typeface_;
253 }
254
255 } // namespace gfx
OLDNEW
« no previous file with comments | « gfx/font_mac.mm ('k') | gfx/font_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698