Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 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 "ui/gfx/platform_font_linux.h" | 5 #include "ui/gfx/platform_font_linux.h" |
| 6 | 6 |
| 7 #include <algorithm> | 7 #include <algorithm> |
| 8 #include <string> | 8 #include <string> |
| 9 | 9 |
| 10 #include "base/lazy_instance.h" | 10 #include "base/lazy_instance.h" |
| 11 #include "base/logging.h" | 11 #include "base/logging.h" |
| 12 #include "base/strings/string_piece.h" | 12 #include "base/strings/string_piece.h" |
| 13 #include "base/strings/string_split.h" | 13 #include "base/strings/string_split.h" |
| 14 #include "base/strings/utf_string_conversions.h" | 14 #include "base/strings/utf_string_conversions.h" |
| 15 #include "build/build_config.h" | 15 #include "build/build_config.h" |
| 16 #include "third_party/skia/include/core/SkFontStyle.h" | |
| 16 #include "third_party/skia/include/core/SkPaint.h" | 17 #include "third_party/skia/include/core/SkPaint.h" |
| 17 #include "third_party/skia/include/core/SkString.h" | 18 #include "third_party/skia/include/core/SkString.h" |
| 18 #include "third_party/skia/include/core/SkTypeface.h" | 19 #include "third_party/skia/include/core/SkTypeface.h" |
| 19 #include "ui/gfx/canvas.h" | 20 #include "ui/gfx/canvas.h" |
| 20 #include "ui/gfx/font.h" | 21 #include "ui/gfx/font.h" |
| 21 #include "ui/gfx/font_list.h" | 22 #include "ui/gfx/font_list.h" |
| 22 #include "ui/gfx/linux_font_delegate.h" | 23 #include "ui/gfx/linux_font_delegate.h" |
| 23 #include "ui/gfx/text_utils.h" | 24 #include "ui/gfx/text_utils.h" |
| 24 | 25 |
| 25 namespace gfx { | 26 namespace gfx { |
| 26 namespace { | 27 namespace { |
| 27 | 28 |
| 28 // The font family name which is used when a user's application font for | 29 // The font family name which is used when a user's application font for |
| 29 // GNOME/KDE is a non-scalable one. The name should be listed in the | 30 // GNOME/KDE is a non-scalable one. The name should be listed in the |
| 30 // IsFallbackFontAllowed function in skia/ext/SkFontHost_fontconfig_direct.cpp. | 31 // IsFallbackFontAllowed function in skia/ext/SkFontHost_fontconfig_direct.cpp. |
| 31 #if defined(OS_ANDROID) | 32 #if defined(OS_ANDROID) |
| 32 const char* kFallbackFontFamilyName = "serif"; | 33 const char* kFallbackFontFamilyName = "serif"; |
| 33 #else | 34 #else |
| 34 const char* kFallbackFontFamilyName = "sans"; | 35 const char* kFallbackFontFamilyName = "sans"; |
| 35 #endif | 36 #endif |
| 36 | 37 |
| 37 // The default font, used for the default constructor. | 38 // The default font, used for the default constructor. |
| 38 base::LazyInstance<scoped_refptr<PlatformFontLinux>>::Leaky g_default_font = | 39 base::LazyInstance<scoped_refptr<PlatformFontLinux>>::Leaky g_default_font = |
| 39 LAZY_INSTANCE_INITIALIZER; | 40 LAZY_INSTANCE_INITIALIZER; |
| 40 | 41 |
| 41 // Creates a SkTypeface for the passed-in Font::FontStyle and family. If a | 42 // Creates a SkTypeface for the passed-in Font::FontStyle and family. If a |
| 42 // fallback typeface is used instead of the requested family, |family| will be | 43 // fallback typeface is used instead of the requested family, |family| will be |
| 43 // updated to contain the fallback's family name. | 44 // updated to contain the fallback's family name. |
| 44 skia::RefPtr<SkTypeface> CreateSkTypeface(int style, std::string* family) { | 45 skia::RefPtr<SkTypeface> CreateSkTypeface(int style, |
| 46 int weight, | |
| 47 std::string* family) { | |
| 45 DCHECK(family); | 48 DCHECK(family); |
| 46 | 49 |
| 47 int skia_style = SkTypeface::kNormal; | 50 SkFontStyle sk_style(weight, SkFontStyle::kNormal_Width, |
| 48 if (Font::BOLD & style) | 51 Font::ITALIC & style ? SkFontStyle::kItalic_Slant |
| 49 skia_style |= SkTypeface::kBold; | 52 : SkFontStyle::kUpright_Slant); |
| 50 if (Font::ITALIC & style) | 53 skia::RefPtr<SkTypeface> typeface = skia::AdoptRef( |
| 51 skia_style |= SkTypeface::kItalic; | 54 SkTypeface::CreateFromNameAndStyle(family->c_str(), sk_style)); |
| 52 | |
| 53 skia::RefPtr<SkTypeface> typeface = skia::AdoptRef(SkTypeface::CreateFromName( | |
| 54 family->c_str(), static_cast<SkTypeface::Style>(skia_style))); | |
| 55 if (!typeface) { | 55 if (!typeface) { |
| 56 // A non-scalable font such as .pcf is specified. Fall back to a default | 56 // A non-scalable font such as .pcf is specified. Fall back to a default |
| 57 // scalable font. | 57 // scalable font. |
| 58 typeface = skia::AdoptRef(SkTypeface::CreateFromName( | 58 typeface = skia::AdoptRef( |
| 59 kFallbackFontFamilyName, static_cast<SkTypeface::Style>(skia_style))); | 59 SkTypeface::CreateFromNameAndStyle(kFallbackFontFamilyName, sk_style)); |
| 60 CHECK(typeface) << "Could not find any font: " << family << ", " | 60 CHECK(typeface) << "Could not find any font: " << family << ", " |
| 61 << kFallbackFontFamilyName; | 61 << kFallbackFontFamilyName; |
| 62 *family = kFallbackFontFamilyName; | 62 *family = kFallbackFontFamilyName; |
| 63 } | 63 } |
| 64 return typeface; | 64 return typeface; |
| 65 } | 65 } |
| 66 | 66 |
| 67 } // namespace | 67 } // namespace |
| 68 | 68 |
| 69 #if defined(OS_CHROMEOS) | 69 #if defined(OS_CHROMEOS) |
| 70 std::string* PlatformFontLinux::default_font_description_ = NULL; | 70 std::string* PlatformFontLinux::default_font_description_ = NULL; |
| 71 #endif | 71 #endif |
| 72 | 72 |
| 73 //////////////////////////////////////////////////////////////////////////////// | 73 //////////////////////////////////////////////////////////////////////////////// |
| 74 // PlatformFontLinux, public: | 74 // PlatformFontLinux, public: |
| 75 | 75 |
| 76 PlatformFontLinux::PlatformFontLinux() { | 76 PlatformFontLinux::PlatformFontLinux() { |
| 77 if (!g_default_font.Get()) { | 77 if (!g_default_font.Get()) { |
| 78 std::string family = kFallbackFontFamilyName; | 78 std::string family = kFallbackFontFamilyName; |
| 79 int size_pixels = 12; | 79 int size_pixels = 12; |
| 80 int style = Font::NORMAL; | 80 int style = Font::NORMAL; |
| 81 Font::FontWeight weight = Font::WEIGHT_NORMAL; | |
| 81 FontRenderParams params; | 82 FontRenderParams params; |
| 82 | 83 |
| 83 #if defined(OS_CHROMEOS) | 84 #if defined(OS_CHROMEOS) |
| 84 // On Chrome OS, a FontList font description string is stored as a | 85 // On Chrome OS, a FontList font description string is stored as a |
| 85 // translatable resource and passed in via SetDefaultFontDescription(). | 86 // translatable resource and passed in via SetDefaultFontDescription(). |
| 86 if (default_font_description_) { | 87 if (default_font_description_) { |
| 87 FontRenderParamsQuery query; | 88 FontRenderParamsQuery query; |
| 88 CHECK(FontList::ParseDescription(*default_font_description_, | 89 CHECK(FontList::ParseDescription(*default_font_description_, |
| 89 &query.families, &query.style, | 90 &query.families, &query.style, |
| 90 &query.pixel_size)) | 91 &query.pixel_size)) |
| 91 << "Failed to parse font description " << *default_font_description_; | 92 << "Failed to parse font description " << *default_font_description_; |
| 92 params = gfx::GetFontRenderParams(query, &family); | 93 params = gfx::GetFontRenderParams(query, &family); |
| 93 size_pixels = query.pixel_size; | 94 size_pixels = query.pixel_size; |
| 94 style = query.style; | 95 style = query.style; |
| 96 weight = query.weight; | |
| 95 } | 97 } |
| 96 #else | 98 #else |
| 97 // On Linux, LinuxFontDelegate is used to query the native toolkit (e.g. | 99 // On Linux, LinuxFontDelegate is used to query the native toolkit (e.g. |
| 98 // GTK+) for the default UI font. | 100 // GTK+) for the default UI font. |
| 99 const LinuxFontDelegate* delegate = LinuxFontDelegate::instance(); | 101 const LinuxFontDelegate* delegate = LinuxFontDelegate::instance(); |
| 100 if (delegate) { | 102 if (delegate) { |
| 101 delegate->GetDefaultFontDescription( | 103 delegate->GetDefaultFontDescription(&family, &size_pixels, &style, |
|
msw
2016/03/22 01:53:44
Should this also get the weight from the system UI
msw
2016/03/22 18:24:10
Ping! Please address this comment.
Mikus
2016/03/23 17:53:21
Done.
| |
| 102 &family, &size_pixels, &style, ¶ms); | 104 ¶ms); |
| 103 } | 105 } |
| 104 #endif | 106 #endif |
| 105 | 107 |
| 106 g_default_font.Get() = new PlatformFontLinux( | 108 g_default_font.Get() = |
| 107 CreateSkTypeface(style, &family), family, size_pixels, style, params); | 109 new PlatformFontLinux(CreateSkTypeface(style, weight, &family), family, |
| 110 size_pixels, style, weight, params); | |
| 108 } | 111 } |
| 109 | 112 |
| 110 InitFromPlatformFont(g_default_font.Get().get()); | 113 InitFromPlatformFont(g_default_font.Get().get()); |
| 111 } | 114 } |
| 112 | 115 |
| 113 PlatformFontLinux::PlatformFontLinux(const std::string& font_name, | 116 PlatformFontLinux::PlatformFontLinux(const std::string& font_name, |
| 114 int font_size_pixels) { | 117 int font_size_pixels) { |
| 115 FontRenderParamsQuery query; | 118 FontRenderParamsQuery query; |
| 116 query.families.push_back(font_name); | 119 query.families.push_back(font_name); |
| 117 query.pixel_size = font_size_pixels; | 120 query.pixel_size = font_size_pixels; |
| 118 query.style = Font::NORMAL; | 121 query.style = Font::NORMAL; |
| 119 InitFromDetails(skia::RefPtr<SkTypeface>(), font_name, font_size_pixels, | 122 InitFromDetails(skia::RefPtr<SkTypeface>(), font_name, font_size_pixels, |
| 120 query.style, gfx::GetFontRenderParams(query, NULL)); | 123 query.style, query.weight, |
| 124 gfx::GetFontRenderParams(query, NULL)); | |
| 121 } | 125 } |
| 122 | 126 |
| 123 //////////////////////////////////////////////////////////////////////////////// | 127 //////////////////////////////////////////////////////////////////////////////// |
| 124 // PlatformFontLinux, PlatformFont implementation: | 128 // PlatformFontLinux, PlatformFont implementation: |
| 125 | 129 |
| 126 // static | 130 // static |
| 127 void PlatformFontLinux::ReloadDefaultFont() { | 131 void PlatformFontLinux::ReloadDefaultFont() { |
| 128 // Reset the scoped_refptr. | 132 // Reset the scoped_refptr. |
| 129 g_default_font.Get() = nullptr; | 133 g_default_font.Get() = nullptr; |
| 130 } | 134 } |
| 131 | 135 |
| 132 #if defined(OS_CHROMEOS) | 136 #if defined(OS_CHROMEOS) |
| 133 // static | 137 // static |
| 134 void PlatformFontLinux::SetDefaultFontDescription( | 138 void PlatformFontLinux::SetDefaultFontDescription( |
| 135 const std::string& font_description) { | 139 const std::string& font_description) { |
| 136 delete default_font_description_; | 140 delete default_font_description_; |
| 137 default_font_description_ = new std::string(font_description); | 141 default_font_description_ = new std::string(font_description); |
| 138 } | 142 } |
| 139 | 143 |
| 140 #endif | 144 #endif |
| 141 | 145 |
| 142 Font PlatformFontLinux::DeriveFont(int size_delta, int style) const { | 146 Font PlatformFontLinux::DeriveFont(int size_delta, |
| 147 int style, | |
| 148 gfx::Font::FontWeight weight) const { | |
| 143 const int new_size = font_size_pixels_ + size_delta; | 149 const int new_size = font_size_pixels_ + size_delta; |
| 144 DCHECK_GT(new_size, 0); | 150 DCHECK_GT(new_size, 0); |
| 145 | 151 |
| 146 // If the style changed, we may need to load a new face. | 152 // If the style changed, we may need to load a new face. |
| 147 std::string new_family = font_family_; | 153 std::string new_family = font_family_; |
| 148 skia::RefPtr<SkTypeface> typeface = | 154 skia::RefPtr<SkTypeface> typeface = |
| 149 (style == style_) ? typeface_ : CreateSkTypeface(style, &new_family); | 155 (style == style_) ? typeface_ |
| 156 : CreateSkTypeface(style, weight, &new_family); | |
| 150 | 157 |
| 151 FontRenderParamsQuery query; | 158 FontRenderParamsQuery query; |
| 152 query.families.push_back(new_family); | 159 query.families.push_back(new_family); |
| 153 query.pixel_size = new_size; | 160 query.pixel_size = new_size; |
| 154 query.style = style; | 161 query.style = style; |
| 155 | 162 |
| 156 return Font(new PlatformFontLinux(typeface, new_family, new_size, style, | 163 return Font(new PlatformFontLinux(typeface, new_family, new_size, style, |
| 164 weight, | |
| 157 gfx::GetFontRenderParams(query, NULL))); | 165 gfx::GetFontRenderParams(query, NULL))); |
| 158 } | 166 } |
| 159 | 167 |
| 160 int PlatformFontLinux::GetHeight() { | 168 int PlatformFontLinux::GetHeight() { |
| 161 ComputeMetricsIfNecessary(); | 169 ComputeMetricsIfNecessary(); |
| 162 return height_pixels_; | 170 return height_pixels_; |
| 163 } | 171 } |
| 164 | 172 |
| 173 gfx::Font::FontWeight PlatformFontLinux::GetWeight() { | |
| 174 return weight_; | |
| 175 } | |
| 176 | |
| 165 int PlatformFontLinux::GetBaseline() { | 177 int PlatformFontLinux::GetBaseline() { |
| 166 ComputeMetricsIfNecessary(); | 178 ComputeMetricsIfNecessary(); |
| 167 return ascent_pixels_; | 179 return ascent_pixels_; |
| 168 } | 180 } |
| 169 | 181 |
| 170 int PlatformFontLinux::GetCapHeight() { | 182 int PlatformFontLinux::GetCapHeight() { |
| 171 ComputeMetricsIfNecessary(); | 183 ComputeMetricsIfNecessary(); |
| 172 return cap_height_pixels_; | 184 return cap_height_pixels_; |
| 173 } | 185 } |
| 174 | 186 |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 211 return font_render_params_; | 223 return font_render_params_; |
| 212 } | 224 } |
| 213 | 225 |
| 214 //////////////////////////////////////////////////////////////////////////////// | 226 //////////////////////////////////////////////////////////////////////////////// |
| 215 // PlatformFontLinux, private: | 227 // PlatformFontLinux, private: |
| 216 | 228 |
| 217 PlatformFontLinux::PlatformFontLinux(const skia::RefPtr<SkTypeface>& typeface, | 229 PlatformFontLinux::PlatformFontLinux(const skia::RefPtr<SkTypeface>& typeface, |
| 218 const std::string& family, | 230 const std::string& family, |
| 219 int size_pixels, | 231 int size_pixels, |
| 220 int style, | 232 int style, |
| 233 gfx::Font::FontWeight weight, | |
| 221 const FontRenderParams& render_params) { | 234 const FontRenderParams& render_params) { |
| 222 InitFromDetails(typeface, family, size_pixels, style, render_params); | 235 InitFromDetails(typeface, family, size_pixels, style, weight, render_params); |
| 223 } | 236 } |
| 224 | 237 |
| 225 PlatformFontLinux::~PlatformFontLinux() {} | 238 PlatformFontLinux::~PlatformFontLinux() {} |
| 226 | 239 |
| 227 void PlatformFontLinux::InitFromDetails( | 240 void PlatformFontLinux::InitFromDetails( |
| 228 const skia::RefPtr<SkTypeface>& typeface, | 241 const skia::RefPtr<SkTypeface>& typeface, |
| 229 const std::string& font_family, | 242 const std::string& font_family, |
| 230 int font_size_pixels, | 243 int font_size_pixels, |
| 231 int style, | 244 int style, |
| 245 gfx::Font::FontWeight weight, | |
| 232 const FontRenderParams& render_params) { | 246 const FontRenderParams& render_params) { |
| 233 DCHECK_GT(font_size_pixels, 0); | 247 DCHECK_GT(font_size_pixels, 0); |
| 234 | 248 |
| 235 font_family_ = font_family; | 249 font_family_ = font_family; |
| 236 typeface_ = typeface ? typeface : CreateSkTypeface(style, &font_family_); | 250 typeface_ = |
| 251 typeface ? typeface : CreateSkTypeface(style, weight, &font_family_); | |
| 237 | 252 |
| 238 font_size_pixels_ = font_size_pixels; | 253 font_size_pixels_ = font_size_pixels; |
| 239 style_ = style; | 254 style_ = style; |
| 255 weight_ = weight; | |
| 240 #if defined(OS_CHROMEOS) | 256 #if defined(OS_CHROMEOS) |
| 241 device_scale_factor_ = GetFontRenderParamsDeviceScaleFactor(); | 257 device_scale_factor_ = GetFontRenderParamsDeviceScaleFactor(); |
| 242 #endif | 258 #endif |
| 243 font_render_params_ = render_params; | 259 font_render_params_ = render_params; |
| 244 | |
| 245 } | 260 } |
| 246 | 261 |
| 247 void PlatformFontLinux::InitFromPlatformFont(const PlatformFontLinux* other) { | 262 void PlatformFontLinux::InitFromPlatformFont(const PlatformFontLinux* other) { |
| 248 typeface_ = other->typeface_; | 263 typeface_ = other->typeface_; |
| 249 font_family_ = other->font_family_; | 264 font_family_ = other->font_family_; |
| 250 font_size_pixels_ = other->font_size_pixels_; | 265 font_size_pixels_ = other->font_size_pixels_; |
| 251 style_ = other->style_; | 266 style_ = other->style_; |
| 267 weight_ = other->weight_; | |
| 252 #if defined(OS_CHROMEOS) | 268 #if defined(OS_CHROMEOS) |
| 253 device_scale_factor_ = other->device_scale_factor_; | 269 device_scale_factor_ = other->device_scale_factor_; |
| 254 #endif | 270 #endif |
| 255 font_render_params_ = other->font_render_params_; | 271 font_render_params_ = other->font_render_params_; |
| 256 | 272 |
| 257 if (!other->metrics_need_computation_) { | 273 if (!other->metrics_need_computation_) { |
| 258 metrics_need_computation_ = false; | 274 metrics_need_computation_ = false; |
| 259 ascent_pixels_ = other->ascent_pixels_; | 275 ascent_pixels_ = other->ascent_pixels_; |
| 260 height_pixels_ = other->height_pixels_; | 276 height_pixels_ = other->height_pixels_; |
| 261 cap_height_pixels_ = other->cap_height_pixels_; | 277 cap_height_pixels_ = other->cap_height_pixels_; |
| 262 average_width_pixels_ = other->average_width_pixels_; | 278 average_width_pixels_ = other->average_width_pixels_; |
| 263 } | 279 } |
| 264 } | 280 } |
| 265 | 281 |
| 266 void PlatformFontLinux::ComputeMetricsIfNecessary() { | 282 void PlatformFontLinux::ComputeMetricsIfNecessary() { |
| 267 if (metrics_need_computation_) { | 283 if (metrics_need_computation_) { |
| 268 metrics_need_computation_ = false; | 284 metrics_need_computation_ = false; |
| 269 | 285 |
| 270 SkPaint paint; | 286 SkPaint paint; |
| 271 paint.setAntiAlias(false); | 287 paint.setAntiAlias(false); |
| 272 paint.setSubpixelText(false); | 288 paint.setSubpixelText(false); |
| 273 paint.setTextSize(font_size_pixels_); | 289 paint.setTextSize(font_size_pixels_); |
| 274 paint.setTypeface(typeface_.get()); | 290 paint.setTypeface(typeface_.get()); |
| 275 paint.setFakeBoldText((Font::BOLD & style_) && !typeface_->isBold()); | 291 paint.setFakeBoldText(weight_ >= gfx::Font::WEIGHT_BOLD && |
| 292 !typeface_->isBold()); | |
| 276 paint.setTextSkewX((Font::ITALIC & style_) && !typeface_->isItalic() ? | 293 paint.setTextSkewX((Font::ITALIC & style_) && !typeface_->isItalic() ? |
| 277 -SK_Scalar1/4 : 0); | 294 -SK_Scalar1/4 : 0); |
| 278 SkPaint::FontMetrics metrics; | 295 SkPaint::FontMetrics metrics; |
| 279 paint.getFontMetrics(&metrics); | 296 paint.getFontMetrics(&metrics); |
| 280 ascent_pixels_ = SkScalarCeilToInt(-metrics.fAscent); | 297 ascent_pixels_ = SkScalarCeilToInt(-metrics.fAscent); |
| 281 height_pixels_ = ascent_pixels_ + SkScalarCeilToInt(metrics.fDescent); | 298 height_pixels_ = ascent_pixels_ + SkScalarCeilToInt(metrics.fDescent); |
| 282 cap_height_pixels_ = SkScalarCeilToInt(metrics.fCapHeight); | 299 cap_height_pixels_ = SkScalarCeilToInt(metrics.fCapHeight); |
| 283 average_width_pixels_ = SkScalarToDouble(metrics.fAvgCharWidth); | 300 average_width_pixels_ = SkScalarToDouble(metrics.fAvgCharWidth); |
| 284 } | 301 } |
| 285 } | 302 } |
| 286 | 303 |
| 287 //////////////////////////////////////////////////////////////////////////////// | 304 //////////////////////////////////////////////////////////////////////////////// |
| 288 // PlatformFont, public: | 305 // PlatformFont, public: |
| 289 | 306 |
| 290 // static | 307 // static |
| 291 PlatformFont* PlatformFont::CreateDefault() { | 308 PlatformFont* PlatformFont::CreateDefault() { |
| 292 return new PlatformFontLinux; | 309 return new PlatformFontLinux; |
| 293 } | 310 } |
| 294 | 311 |
| 295 // static | 312 // static |
| 296 PlatformFont* PlatformFont::CreateFromNameAndSize(const std::string& font_name, | 313 PlatformFont* PlatformFont::CreateFromNameAndSize(const std::string& font_name, |
| 297 int font_size) { | 314 int font_size) { |
| 298 return new PlatformFontLinux(font_name, font_size); | 315 return new PlatformFontLinux(font_name, font_size); |
| 299 } | 316 } |
| 300 | 317 |
| 301 } // namespace gfx | 318 } // namespace gfx |
| OLD | NEW |