OLD | NEW |
1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "gfx/platform_font_gtk.h" | 5 #include "gfx/platform_font_gtk.h" |
6 | 6 |
7 #include <algorithm> | 7 #include <algorithm> |
8 #include <fontconfig/fontconfig.h> | 8 #include <fontconfig/fontconfig.h> |
9 #include <gdk/gdk.h> | 9 #include <gdk/gdk.h> |
10 #include <gtk/gtk.h> | 10 #include <gtk/gtk.h> |
11 #include <map> | 11 #include <map> |
12 #include <pango/pango.h> | 12 #include <pango/pango.h> |
13 | 13 |
14 #include "base/logging.h" | 14 #include "base/logging.h" |
15 #include "base/string_piece.h" | 15 #include "base/string_piece.h" |
| 16 #include "base/sys_string_conversions.h" |
16 #include "base/utf_string_conversions.h" | 17 #include "base/utf_string_conversions.h" |
17 #include "gfx/canvas_skia.h" | 18 #include "gfx/canvas_skia.h" |
18 #include "gfx/font.h" | 19 #include "gfx/font.h" |
19 #include "gfx/gtk_util.h" | 20 #include "gfx/gtk_util.h" |
20 #include "third_party/skia/include/core/SkTypeface.h" | 21 #include "third_party/skia/include/core/SkTypeface.h" |
21 #include "third_party/skia/include/core/SkPaint.h" | 22 #include "third_party/skia/include/core/SkPaint.h" |
22 | 23 |
23 namespace { | 24 namespace { |
24 | 25 |
25 // The font family name which is used when a user's application font for | 26 // The font family name which is used when a user's application font for |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
59 // Find the best match font for |family_name| in the same way as Skia | 60 // Find the best match font for |family_name| in the same way as Skia |
60 // to make sure CreateFont() successfully creates a default font. In | 61 // to make sure CreateFont() successfully creates a default font. In |
61 // Skia, it only checks the best match font. If it failed to find | 62 // Skia, it only checks the best match font. If it failed to find |
62 // one, SkTypeface will be NULL for that font family. It eventually | 63 // one, SkTypeface will be NULL for that font family. It eventually |
63 // causes a segfault. For example, family_name = "Sans" and system | 64 // causes a segfault. For example, family_name = "Sans" and system |
64 // may have various fonts. The first font family in FcPattern will be | 65 // may have various fonts. The first font family in FcPattern will be |
65 // "DejaVu Sans" but a font family returned by FcFontMatch will be "VL | 66 // "DejaVu Sans" but a font family returned by FcFontMatch will be "VL |
66 // PGothic". In this case, SkTypeface for "Sans" returns NULL even if | 67 // PGothic". In this case, SkTypeface for "Sans" returns NULL even if |
67 // the system has a font for "Sans" font family. See FontMatch() in | 68 // the system has a font for "Sans" font family. See FontMatch() in |
68 // skia/ports/SkFontHost_fontconfig.cpp for more detail. | 69 // skia/ports/SkFontHost_fontconfig.cpp for more detail. |
69 string16 FindBestMatchFontFamilyName(const char* family_name) { | 70 std::wstring FindBestMatchFontFamilyName(const char* family_name) { |
70 FcPattern* pattern = FcPatternCreate(); | 71 FcPattern* pattern = FcPatternCreate(); |
71 FcValue fcvalue; | 72 FcValue fcvalue; |
72 fcvalue.type = FcTypeString; | 73 fcvalue.type = FcTypeString; |
73 char* family_name_copy = strdup(family_name); | 74 char* family_name_copy = strdup(family_name); |
74 fcvalue.u.s = reinterpret_cast<FcChar8*>(family_name_copy); | 75 fcvalue.u.s = reinterpret_cast<FcChar8*>(family_name_copy); |
75 FcPatternAdd(pattern, FC_FAMILY, fcvalue, 0); | 76 FcPatternAdd(pattern, FC_FAMILY, fcvalue, 0); |
76 FcConfigSubstitute(0, pattern, FcMatchPattern); | 77 FcConfigSubstitute(0, pattern, FcMatchPattern); |
77 FcDefaultSubstitute(pattern); | 78 FcDefaultSubstitute(pattern); |
78 FcResult result; | 79 FcResult result; |
79 FcPattern* match = FcFontMatch(0, pattern, &result); | 80 FcPattern* match = FcFontMatch(0, pattern, &result); |
80 DCHECK(match) << "Could not find font: " << family_name; | 81 DCHECK(match) << "Could not find font: " << family_name; |
81 FcChar8* match_family; | 82 FcChar8* match_family; |
82 FcPatternGetString(match, FC_FAMILY, 0, &match_family); | 83 FcPatternGetString(match, FC_FAMILY, 0, &match_family); |
83 | 84 |
84 string16 font_family = UTF8ToUTF16(reinterpret_cast<char*>(match_family)); | 85 std::wstring font_family = UTF8ToWide(reinterpret_cast<char*>(match_family)); |
85 FcPatternDestroy(match); | 86 FcPatternDestroy(match); |
86 FcPatternDestroy(pattern); | 87 FcPatternDestroy(pattern); |
87 free(family_name_copy); | 88 free(family_name_copy); |
88 return font_family; | 89 return font_family; |
89 } | 90 } |
90 | 91 |
91 } // namespace | 92 } // namespace |
92 | 93 |
93 namespace gfx { | 94 namespace gfx { |
94 | 95 |
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
133 if (pango_font_description_get_size_is_absolute(native_font)) { | 134 if (pango_font_description_get_size_is_absolute(native_font)) { |
134 // font_size_ is treated as scaled (see comment in GetPangoScaleFactor). If | 135 // font_size_ is treated as scaled (see comment in GetPangoScaleFactor). If |
135 // we get here the font size is absolute though, and we need to invert the | 136 // we get here the font size is absolute though, and we need to invert the |
136 // scale so that when scaled in the rest of this class everything lines up. | 137 // scale so that when scaled in the rest of this class everything lines up. |
137 size /= GetPangoScaleFactor(); | 138 size /= GetPangoScaleFactor(); |
138 } | 139 } |
139 | 140 |
140 // Find best match font for |family_name| to make sure we can get | 141 // Find best match font for |family_name| to make sure we can get |
141 // a SkTypeface for the default font. | 142 // a SkTypeface for the default font. |
142 // TODO(agl): remove this. | 143 // TODO(agl): remove this. |
143 string16 font_family = FindBestMatchFontFamilyName(family_name); | 144 std::wstring font_family = FindBestMatchFontFamilyName(family_name); |
144 | 145 |
145 InitWithNameAndSize(font_family, size / PANGO_SCALE); | 146 InitWithNameAndSize(font_family, size / PANGO_SCALE); |
146 int style = 0; | 147 int style = 0; |
147 if (pango_font_description_get_weight(native_font) == PANGO_WEIGHT_BOLD) { | 148 if (pango_font_description_get_weight(native_font) == PANGO_WEIGHT_BOLD) { |
148 // TODO(davemoore) What should we do about other weights? We currently | 149 // TODO(davemoore) What should we do about other weights? We currently |
149 // only support BOLD. | 150 // only support BOLD. |
150 style |= gfx::Font::BOLD; | 151 style |= gfx::Font::BOLD; |
151 } | 152 } |
152 if (pango_font_description_get_style(native_font) == PANGO_STYLE_ITALIC) { | 153 if (pango_font_description_get_style(native_font) == PANGO_STYLE_ITALIC) { |
153 // TODO(davemoore) What about PANGO_STYLE_OBLIQUE? | 154 // TODO(davemoore) What about PANGO_STYLE_OBLIQUE? |
154 style |= gfx::Font::ITALIC; | 155 style |= gfx::Font::ITALIC; |
155 } | 156 } |
156 if (style != 0) | 157 if (style != 0) |
157 style_ = style; | 158 style_ = style; |
158 } | 159 } |
159 | 160 |
160 PlatformFontGtk::PlatformFontGtk(const string16& font_name, | 161 PlatformFontGtk::PlatformFontGtk(const std::wstring& font_name, |
161 int font_size) { | 162 int font_size) { |
162 InitWithNameAndSize(font_name, font_size); | 163 InitWithNameAndSize(font_name, font_size); |
163 } | 164 } |
164 | 165 |
165 double PlatformFontGtk::underline_position() const { | 166 double PlatformFontGtk::underline_position() const { |
166 const_cast<PlatformFontGtk*>(this)->InitPangoMetrics(); | 167 const_cast<PlatformFontGtk*>(this)->InitPangoMetrics(); |
167 return underline_position_; | 168 return underline_position_; |
168 } | 169 } |
169 | 170 |
170 double PlatformFontGtk::underline_thickness() const { | 171 double PlatformFontGtk::underline_thickness() const { |
(...skipping 18 matching lines...) Expand all Loading... |
189 } | 190 } |
190 | 191 |
191 // If the style has changed we may need to load a new face | 192 // If the style has changed we may need to load a new face |
192 int skstyle = SkTypeface::kNormal; | 193 int skstyle = SkTypeface::kNormal; |
193 if (gfx::Font::BOLD & style) | 194 if (gfx::Font::BOLD & style) |
194 skstyle |= SkTypeface::kBold; | 195 skstyle |= SkTypeface::kBold; |
195 if (gfx::Font::ITALIC & style) | 196 if (gfx::Font::ITALIC & style) |
196 skstyle |= SkTypeface::kItalic; | 197 skstyle |= SkTypeface::kItalic; |
197 | 198 |
198 SkTypeface* typeface = SkTypeface::CreateFromName( | 199 SkTypeface* typeface = SkTypeface::CreateFromName( |
199 UTF16ToUTF8(font_family_).c_str(), | 200 base::SysWideToUTF8(font_family_).c_str(), |
200 static_cast<SkTypeface::Style>(skstyle)); | 201 static_cast<SkTypeface::Style>(skstyle)); |
201 SkAutoUnref tf_helper(typeface); | 202 SkAutoUnref tf_helper(typeface); |
202 | 203 |
203 return Font(new PlatformFontGtk(typeface, | 204 return Font(new PlatformFontGtk(typeface, |
204 font_family_, | 205 font_family_, |
205 font_size_ + size_delta, | 206 font_size_ + size_delta, |
206 style)); | 207 style)); |
207 } | 208 } |
208 | 209 |
209 int PlatformFontGtk::GetHeight() const { | 210 int PlatformFontGtk::GetHeight() const { |
(...skipping 17 matching lines...) Expand all Loading... |
227 | 228 |
228 int PlatformFontGtk::GetExpectedTextWidth(int length) const { | 229 int PlatformFontGtk::GetExpectedTextWidth(int length) const { |
229 double char_width = const_cast<PlatformFontGtk*>(this)->GetAverageWidth(); | 230 double char_width = const_cast<PlatformFontGtk*>(this)->GetAverageWidth(); |
230 return round(static_cast<float>(length) * char_width); | 231 return round(static_cast<float>(length) * char_width); |
231 } | 232 } |
232 | 233 |
233 int PlatformFontGtk::GetStyle() const { | 234 int PlatformFontGtk::GetStyle() const { |
234 return style_; | 235 return style_; |
235 } | 236 } |
236 | 237 |
237 string16 PlatformFontGtk::GetFontName() const { | 238 const std::wstring& PlatformFontGtk::GetFontName() const { |
238 return font_family_; | 239 return font_family_; |
239 } | 240 } |
240 | 241 |
241 int PlatformFontGtk::GetFontSize() const { | 242 int PlatformFontGtk::GetFontSize() const { |
242 return font_size_; | 243 return font_size_; |
243 } | 244 } |
244 | 245 |
245 NativeFont PlatformFontGtk::GetNativeFont() const { | 246 NativeFont PlatformFontGtk::GetNativeFont() const { |
246 PangoFontDescription* pfd = pango_font_description_new(); | 247 PangoFontDescription* pfd = pango_font_description_new(); |
247 pango_font_description_set_family(pfd, UTF16ToUTF8(GetFontName()).c_str()); | 248 pango_font_description_set_family(pfd, WideToUTF8(GetFontName()).c_str()); |
248 // Set the absolute size to avoid overflowing UI elements. | 249 // Set the absolute size to avoid overflowing UI elements. |
249 pango_font_description_set_absolute_size(pfd, | 250 pango_font_description_set_absolute_size(pfd, |
250 GetFontSize() * PANGO_SCALE * GetPangoScaleFactor()); | 251 GetFontSize() * PANGO_SCALE * GetPangoScaleFactor()); |
251 | 252 |
252 switch (GetStyle()) { | 253 switch (GetStyle()) { |
253 case gfx::Font::NORMAL: | 254 case gfx::Font::NORMAL: |
254 // Nothing to do, should already be PANGO_STYLE_NORMAL. | 255 // Nothing to do, should already be PANGO_STYLE_NORMAL. |
255 break; | 256 break; |
256 case gfx::Font::BOLD: | 257 case gfx::Font::BOLD: |
257 pango_font_description_set_weight(pfd, PANGO_WEIGHT_BOLD); | 258 pango_font_description_set_weight(pfd, PANGO_WEIGHT_BOLD); |
258 break; | 259 break; |
259 case gfx::Font::ITALIC: | 260 case gfx::Font::ITALIC: |
260 pango_font_description_set_style(pfd, PANGO_STYLE_ITALIC); | 261 pango_font_description_set_style(pfd, PANGO_STYLE_ITALIC); |
261 break; | 262 break; |
262 case gfx::Font::UNDERLINED: | 263 case gfx::Font::UNDERLINED: |
263 // TODO(deanm): How to do underlined? Where do we use it? Probably have | 264 // TODO(deanm): How to do underlined? Where do we use it? Probably have |
264 // to paint it ourselves, see pango_font_metrics_get_underline_position. | 265 // to paint it ourselves, see pango_font_metrics_get_underline_position. |
265 break; | 266 break; |
266 } | 267 } |
267 | 268 |
268 return pfd; | 269 return pfd; |
269 } | 270 } |
270 | 271 |
271 //////////////////////////////////////////////////////////////////////////////// | 272 //////////////////////////////////////////////////////////////////////////////// |
272 // PlatformFontGtk, private: | 273 // PlatformFontGtk, private: |
273 | 274 |
274 PlatformFontGtk::PlatformFontGtk(SkTypeface* typeface, | 275 PlatformFontGtk::PlatformFontGtk(SkTypeface* typeface, |
275 const string16& name, | 276 const std::wstring& name, |
276 int size, | 277 int size, |
277 int style) { | 278 int style) { |
278 InitWithTypefaceNameSizeAndStyle(typeface, name, size, style); | 279 InitWithTypefaceNameSizeAndStyle(typeface, name, size, style); |
279 } | 280 } |
280 | 281 |
281 PlatformFontGtk::~PlatformFontGtk() {} | 282 PlatformFontGtk::~PlatformFontGtk() {} |
282 | 283 |
283 void PlatformFontGtk::InitWithNameAndSize(const string16& font_name, | 284 void PlatformFontGtk::InitWithNameAndSize(const std::wstring& font_name, |
284 int font_size) { | 285 int font_size) { |
285 DCHECK_GT(font_size, 0); | 286 DCHECK_GT(font_size, 0); |
286 string16 fallback; | 287 std::wstring fallback; |
287 | 288 |
288 SkTypeface* typeface = SkTypeface::CreateFromName( | 289 SkTypeface* typeface = SkTypeface::CreateFromName( |
289 UTF16ToUTF8(font_name).c_str(), SkTypeface::kNormal); | 290 base::SysWideToUTF8(font_name).c_str(), SkTypeface::kNormal); |
290 if (!typeface) { | 291 if (!typeface) { |
291 // A non-scalable font such as .pcf is specified. Falls back to a default | 292 // A non-scalable font such as .pcf is specified. Falls back to a default |
292 // scalable font. | 293 // scalable font. |
293 typeface = SkTypeface::CreateFromName( | 294 typeface = SkTypeface::CreateFromName( |
294 kFallbackFontFamilyName, SkTypeface::kNormal); | 295 kFallbackFontFamilyName, SkTypeface::kNormal); |
295 CHECK(typeface) << "Could not find any font: " | 296 CHECK(typeface) << "Could not find any font: " |
296 << UTF16ToUTF8(font_name) | 297 << base::SysWideToUTF8(font_name) |
297 << ", " << kFallbackFontFamilyName; | 298 << ", " << kFallbackFontFamilyName; |
298 fallback = UTF8ToUTF16(kFallbackFontFamilyName); | 299 fallback = base::SysUTF8ToWide(kFallbackFontFamilyName); |
299 } | 300 } |
300 SkAutoUnref typeface_helper(typeface); | 301 SkAutoUnref typeface_helper(typeface); |
301 | 302 |
302 InitWithTypefaceNameSizeAndStyle(typeface, | 303 InitWithTypefaceNameSizeAndStyle(typeface, |
303 fallback.empty() ? font_name : fallback, | 304 fallback.empty() ? font_name : fallback, |
304 font_size, | 305 font_size, |
305 gfx::Font::NORMAL); | 306 gfx::Font::NORMAL); |
306 } | 307 } |
307 | 308 |
308 void PlatformFontGtk::InitWithTypefaceNameSizeAndStyle( | 309 void PlatformFontGtk::InitWithTypefaceNameSizeAndStyle( |
309 SkTypeface* typeface, | 310 SkTypeface* typeface, |
310 const string16& font_family, | 311 const std::wstring& font_family, |
311 int font_size, | 312 int font_size, |
312 int style) { | 313 int style) { |
313 typeface_helper_.reset(new SkAutoUnref(typeface)); | 314 typeface_helper_.reset(new SkAutoUnref(typeface)); |
314 typeface_ = typeface; | 315 typeface_ = typeface; |
315 typeface_->ref(); | 316 typeface_->ref(); |
316 font_family_ = font_family; | 317 font_family_ = font_family; |
317 font_size_ = font_size; | 318 font_size_ = font_size; |
318 style_ = style; | 319 style_ = style; |
319 pango_metrics_inited_ = false; | 320 pango_metrics_inited_ = false; |
320 average_width_ = 0.0f; | 321 average_width_ = 0.0f; |
(...skipping 106 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
427 PlatformFont* PlatformFont::CreateFromFont(const Font& other) { | 428 PlatformFont* PlatformFont::CreateFromFont(const Font& other) { |
428 return new PlatformFontGtk(other); | 429 return new PlatformFontGtk(other); |
429 } | 430 } |
430 | 431 |
431 // static | 432 // static |
432 PlatformFont* PlatformFont::CreateFromNativeFont(NativeFont native_font) { | 433 PlatformFont* PlatformFont::CreateFromNativeFont(NativeFont native_font) { |
433 return new PlatformFontGtk(native_font); | 434 return new PlatformFontGtk(native_font); |
434 } | 435 } |
435 | 436 |
436 // static | 437 // static |
437 PlatformFont* PlatformFont::CreateFromNameAndSize(const string16& font_name, | 438 PlatformFont* PlatformFont::CreateFromNameAndSize(const std::wstring& font_name, |
438 int font_size) { | 439 int font_size) { |
439 return new PlatformFontGtk(font_name, font_size); | 440 return new PlatformFontGtk(font_name, font_size); |
440 } | 441 } |
441 | 442 |
442 } // namespace gfx | 443 } // namespace gfx |
OLD | NEW |