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