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(bool italic, |
| 46 Font::Weight weight, |
| 47 std::string* family) { |
45 DCHECK(family); | 48 DCHECK(family); |
46 | 49 |
47 int skia_style = SkTypeface::kNormal; | 50 const int font_weight = (weight == Font::Weight::INVALID) |
48 if (Font::BOLD & style) | 51 ? static_cast<int>(Font::Weight::NORMAL) |
49 skia_style |= SkTypeface::kBold; | 52 : static_cast<int>(weight); |
50 if (Font::ITALIC & style) | 53 SkFontStyle sk_style( |
51 skia_style |= SkTypeface::kItalic; | 54 font_weight, SkFontStyle::kNormal_Width, |
52 | 55 italic ? SkFontStyle::kItalic_Slant : SkFontStyle::kUpright_Slant); |
53 skia::RefPtr<SkTypeface> typeface = skia::AdoptRef(SkTypeface::CreateFromName( | 56 skia::RefPtr<SkTypeface> typeface = |
54 family->c_str(), static_cast<SkTypeface::Style>(skia_style))); | 57 skia::AdoptRef(SkTypeface::CreateFromName(family->c_str(), sk_style)); |
55 if (!typeface) { | 58 if (!typeface) { |
56 // A non-scalable font such as .pcf is specified. Fall back to a default | 59 // A non-scalable font such as .pcf is specified. Fall back to a default |
57 // scalable font. | 60 // scalable font. |
58 typeface = skia::AdoptRef(SkTypeface::CreateFromName( | 61 typeface = skia::AdoptRef( |
59 kFallbackFontFamilyName, static_cast<SkTypeface::Style>(skia_style))); | 62 SkTypeface::CreateFromName(kFallbackFontFamilyName, sk_style)); |
60 CHECK(typeface) << "Could not find any font: " << family << ", " | 63 CHECK(typeface) << "Could not find any font: " << family << ", " |
61 << kFallbackFontFamilyName; | 64 << kFallbackFontFamilyName; |
62 *family = kFallbackFontFamilyName; | 65 *family = kFallbackFontFamilyName; |
63 } | 66 } |
64 return typeface; | 67 return typeface; |
65 } | 68 } |
66 | 69 |
67 } // namespace | 70 } // namespace |
68 | 71 |
69 #if defined(OS_CHROMEOS) | 72 #if defined(OS_CHROMEOS) |
70 std::string* PlatformFontLinux::default_font_description_ = NULL; | 73 std::string* PlatformFontLinux::default_font_description_ = NULL; |
71 #endif | 74 #endif |
72 | 75 |
73 //////////////////////////////////////////////////////////////////////////////// | 76 //////////////////////////////////////////////////////////////////////////////// |
74 // PlatformFontLinux, public: | 77 // PlatformFontLinux, public: |
75 | 78 |
76 PlatformFontLinux::PlatformFontLinux() { | 79 PlatformFontLinux::PlatformFontLinux() { |
77 if (!g_default_font.Get()) { | 80 if (!g_default_font.Get()) { |
78 std::string family = kFallbackFontFamilyName; | 81 std::string family = kFallbackFontFamilyName; |
79 int size_pixels = 12; | 82 int size_pixels = 12; |
80 int style = Font::NORMAL; | 83 bool italic = false; |
| 84 Font::Weight weight = Font::Weight::NORMAL; |
81 FontRenderParams params; | 85 FontRenderParams params; |
82 | 86 |
83 #if defined(OS_CHROMEOS) | 87 #if defined(OS_CHROMEOS) |
84 // On Chrome OS, a FontList font description string is stored as a | 88 // On Chrome OS, a FontList font description string is stored as a |
85 // translatable resource and passed in via SetDefaultFontDescription(). | 89 // translatable resource and passed in via SetDefaultFontDescription(). |
86 if (default_font_description_) { | 90 if (default_font_description_) { |
87 FontRenderParamsQuery query; | 91 FontRenderParamsQuery query; |
88 CHECK(FontList::ParseDescription(*default_font_description_, | 92 CHECK(FontList::ParseDescription(*default_font_description_, |
89 &query.families, &query.style, | 93 &query.families, &query.style, |
90 &query.pixel_size)) | 94 &query.pixel_size)) |
91 << "Failed to parse font description " << *default_font_description_; | 95 << "Failed to parse font description " << *default_font_description_; |
92 params = gfx::GetFontRenderParams(query, &family); | 96 params = gfx::GetFontRenderParams(query, &family); |
93 size_pixels = query.pixel_size; | 97 size_pixels = query.pixel_size; |
94 style = query.style; | 98 style = query.style; |
| 99 weight = query.weight; |
95 } | 100 } |
96 #else | 101 #else |
97 // On Linux, LinuxFontDelegate is used to query the native toolkit (e.g. | 102 // On Linux, LinuxFontDelegate is used to query the native toolkit (e.g. |
98 // GTK+) for the default UI font. | 103 // GTK+) for the default UI font. |
99 const LinuxFontDelegate* delegate = LinuxFontDelegate::instance(); | 104 const LinuxFontDelegate* delegate = LinuxFontDelegate::instance(); |
100 if (delegate) { | 105 if (delegate) { |
101 delegate->GetDefaultFontDescription( | 106 delegate->GetDefaultFontDescription(&family, &size_pixels, &italic, |
102 &family, &size_pixels, &style, ¶ms); | 107 &weight, ¶ms); |
103 } | 108 } |
104 #endif | 109 #endif |
105 | 110 |
106 g_default_font.Get() = new PlatformFontLinux( | 111 g_default_font.Get() = |
107 CreateSkTypeface(style, &family), family, size_pixels, style, params); | 112 new PlatformFontLinux(CreateSkTypeface(italic, weight, &family), family, |
| 113 size_pixels, italic, weight, params); |
108 } | 114 } |
109 | 115 |
110 InitFromPlatformFont(g_default_font.Get().get()); | 116 InitFromPlatformFont(g_default_font.Get().get()); |
111 } | 117 } |
112 | 118 |
113 PlatformFontLinux::PlatformFontLinux(const std::string& font_name, | 119 PlatformFontLinux::PlatformFontLinux(const std::string& font_name, |
114 int font_size_pixels) { | 120 int font_size_pixels) { |
115 FontRenderParamsQuery query; | 121 FontRenderParamsQuery query; |
116 query.families.push_back(font_name); | 122 query.families.push_back(font_name); |
117 query.pixel_size = font_size_pixels; | 123 query.pixel_size = font_size_pixels; |
118 query.style = Font::NORMAL; | |
119 InitFromDetails(skia::RefPtr<SkTypeface>(), font_name, font_size_pixels, | 124 InitFromDetails(skia::RefPtr<SkTypeface>(), font_name, font_size_pixels, |
120 query.style, gfx::GetFontRenderParams(query, NULL)); | 125 false, query.weight, gfx::GetFontRenderParams(query, NULL)); |
121 } | 126 } |
122 | 127 |
123 //////////////////////////////////////////////////////////////////////////////// | 128 //////////////////////////////////////////////////////////////////////////////// |
124 // PlatformFontLinux, PlatformFont implementation: | 129 // PlatformFontLinux, PlatformFont implementation: |
125 | 130 |
126 // static | 131 // static |
127 void PlatformFontLinux::ReloadDefaultFont() { | 132 void PlatformFontLinux::ReloadDefaultFont() { |
128 // Reset the scoped_refptr. | 133 // Reset the scoped_refptr. |
129 g_default_font.Get() = nullptr; | 134 g_default_font.Get() = nullptr; |
130 } | 135 } |
131 | 136 |
132 #if defined(OS_CHROMEOS) | 137 #if defined(OS_CHROMEOS) |
133 // static | 138 // static |
134 void PlatformFontLinux::SetDefaultFontDescription( | 139 void PlatformFontLinux::SetDefaultFontDescription( |
135 const std::string& font_description) { | 140 const std::string& font_description) { |
136 delete default_font_description_; | 141 delete default_font_description_; |
137 default_font_description_ = new std::string(font_description); | 142 default_font_description_ = new std::string(font_description); |
138 } | 143 } |
139 | 144 |
140 #endif | 145 #endif |
141 | 146 |
142 Font PlatformFontLinux::DeriveFont(int size_delta, int style) const { | 147 Font PlatformFontLinux::DeriveFont(int size_delta, |
| 148 int style, |
| 149 gfx::Font::Weight weight) const { |
143 const int new_size = font_size_pixels_ + size_delta; | 150 const int new_size = font_size_pixels_ + size_delta; |
144 DCHECK_GT(new_size, 0); | 151 DCHECK_GT(new_size, 0); |
145 | 152 |
| 153 const int current_style = italic_ ? gfx::Font::ITALIC : gfx::Font::NORMAL; |
| 154 |
146 // If the style changed, we may need to load a new face. | 155 // If the style changed, we may need to load a new face. |
147 std::string new_family = font_family_; | 156 std::string new_family = font_family_; |
148 skia::RefPtr<SkTypeface> typeface = | 157 skia::RefPtr<SkTypeface> typeface = |
149 (style == style_) ? typeface_ : CreateSkTypeface(style, &new_family); | 158 (style == current_style) ? typeface_ |
| 159 : CreateSkTypeface(style, weight, &new_family); |
150 | 160 |
151 FontRenderParamsQuery query; | 161 FontRenderParamsQuery query; |
152 query.families.push_back(new_family); | 162 query.families.push_back(new_family); |
153 query.pixel_size = new_size; | 163 query.pixel_size = new_size; |
154 query.style = style; | 164 query.style = style; |
155 | 165 |
156 return Font(new PlatformFontLinux(typeface, new_family, new_size, style, | 166 return Font(new PlatformFontLinux(typeface, new_family, new_size, style, |
| 167 weight, |
157 gfx::GetFontRenderParams(query, NULL))); | 168 gfx::GetFontRenderParams(query, NULL))); |
158 } | 169 } |
159 | 170 |
160 int PlatformFontLinux::GetHeight() { | 171 int PlatformFontLinux::GetHeight() { |
161 ComputeMetricsIfNecessary(); | 172 ComputeMetricsIfNecessary(); |
162 return height_pixels_; | 173 return height_pixels_; |
163 } | 174 } |
164 | 175 |
| 176 gfx::Font::Weight PlatformFontLinux::GetWeight() const { |
| 177 return weight_; |
| 178 } |
| 179 |
165 int PlatformFontLinux::GetBaseline() { | 180 int PlatformFontLinux::GetBaseline() { |
166 ComputeMetricsIfNecessary(); | 181 ComputeMetricsIfNecessary(); |
167 return ascent_pixels_; | 182 return ascent_pixels_; |
168 } | 183 } |
169 | 184 |
170 int PlatformFontLinux::GetCapHeight() { | 185 int PlatformFontLinux::GetCapHeight() { |
171 ComputeMetricsIfNecessary(); | 186 ComputeMetricsIfNecessary(); |
172 return cap_height_pixels_; | 187 return cap_height_pixels_; |
173 } | 188 } |
174 | 189 |
175 int PlatformFontLinux::GetExpectedTextWidth(int length) { | 190 int PlatformFontLinux::GetExpectedTextWidth(int length) { |
176 ComputeMetricsIfNecessary(); | 191 ComputeMetricsIfNecessary(); |
177 return round(static_cast<float>(length) * average_width_pixels_); | 192 return round(static_cast<float>(length) * average_width_pixels_); |
178 } | 193 } |
179 | 194 |
180 int PlatformFontLinux::GetStyle() const { | 195 int PlatformFontLinux::GetStyle() const { |
181 return style_; | 196 return italic_ ? gfx::Font::ITALIC : gfx::Font::NORMAL; |
182 } | 197 } |
183 | 198 |
184 const std::string& PlatformFontLinux::GetFontName() const { | 199 const std::string& PlatformFontLinux::GetFontName() const { |
185 return font_family_; | 200 return font_family_; |
186 } | 201 } |
187 | 202 |
188 std::string PlatformFontLinux::GetActualFontNameForTesting() const { | 203 std::string PlatformFontLinux::GetActualFontNameForTesting() const { |
189 SkString family_name; | 204 SkString family_name; |
190 typeface_->getFamilyName(&family_name); | 205 typeface_->getFamilyName(&family_name); |
191 return family_name.c_str(); | 206 return family_name.c_str(); |
(...skipping 18 matching lines...) Expand all Loading... |
210 #endif | 225 #endif |
211 return font_render_params_; | 226 return font_render_params_; |
212 } | 227 } |
213 | 228 |
214 //////////////////////////////////////////////////////////////////////////////// | 229 //////////////////////////////////////////////////////////////////////////////// |
215 // PlatformFontLinux, private: | 230 // PlatformFontLinux, private: |
216 | 231 |
217 PlatformFontLinux::PlatformFontLinux(const skia::RefPtr<SkTypeface>& typeface, | 232 PlatformFontLinux::PlatformFontLinux(const skia::RefPtr<SkTypeface>& typeface, |
218 const std::string& family, | 233 const std::string& family, |
219 int size_pixels, | 234 int size_pixels, |
220 int style, | 235 bool italic, |
| 236 gfx::Font::Weight weight, |
221 const FontRenderParams& render_params) { | 237 const FontRenderParams& render_params) { |
222 InitFromDetails(typeface, family, size_pixels, style, render_params); | 238 InitFromDetails(typeface, family, size_pixels, italic, weight, render_params); |
223 } | 239 } |
224 | 240 |
225 PlatformFontLinux::~PlatformFontLinux() {} | 241 PlatformFontLinux::~PlatformFontLinux() {} |
226 | 242 |
227 void PlatformFontLinux::InitFromDetails( | 243 void PlatformFontLinux::InitFromDetails( |
228 const skia::RefPtr<SkTypeface>& typeface, | 244 const skia::RefPtr<SkTypeface>& typeface, |
229 const std::string& font_family, | 245 const std::string& font_family, |
230 int font_size_pixels, | 246 int font_size_pixels, |
231 int style, | 247 bool italic, |
| 248 gfx::Font::Weight weight, |
232 const FontRenderParams& render_params) { | 249 const FontRenderParams& render_params) { |
233 DCHECK_GT(font_size_pixels, 0); | 250 DCHECK_GT(font_size_pixels, 0); |
234 | 251 |
235 font_family_ = font_family; | 252 font_family_ = font_family; |
236 typeface_ = typeface ? typeface : CreateSkTypeface(style, &font_family_); | 253 typeface_ = |
| 254 typeface ? typeface : CreateSkTypeface(italic, weight, &font_family_); |
237 | 255 |
238 font_size_pixels_ = font_size_pixels; | 256 font_size_pixels_ = font_size_pixels; |
239 style_ = style; | 257 italic_ = italic; |
| 258 weight_ = weight; |
240 #if defined(OS_CHROMEOS) | 259 #if defined(OS_CHROMEOS) |
241 device_scale_factor_ = GetFontRenderParamsDeviceScaleFactor(); | 260 device_scale_factor_ = GetFontRenderParamsDeviceScaleFactor(); |
242 #endif | 261 #endif |
243 font_render_params_ = render_params; | 262 font_render_params_ = render_params; |
244 | |
245 } | 263 } |
246 | 264 |
247 void PlatformFontLinux::InitFromPlatformFont(const PlatformFontLinux* other) { | 265 void PlatformFontLinux::InitFromPlatformFont(const PlatformFontLinux* other) { |
248 typeface_ = other->typeface_; | 266 typeface_ = other->typeface_; |
249 font_family_ = other->font_family_; | 267 font_family_ = other->font_family_; |
250 font_size_pixels_ = other->font_size_pixels_; | 268 font_size_pixels_ = other->font_size_pixels_; |
251 style_ = other->style_; | 269 italic_ = other->italic_; |
| 270 weight_ = other->weight_; |
252 #if defined(OS_CHROMEOS) | 271 #if defined(OS_CHROMEOS) |
253 device_scale_factor_ = other->device_scale_factor_; | 272 device_scale_factor_ = other->device_scale_factor_; |
254 #endif | 273 #endif |
255 font_render_params_ = other->font_render_params_; | 274 font_render_params_ = other->font_render_params_; |
256 | 275 |
257 if (!other->metrics_need_computation_) { | 276 if (!other->metrics_need_computation_) { |
258 metrics_need_computation_ = false; | 277 metrics_need_computation_ = false; |
259 ascent_pixels_ = other->ascent_pixels_; | 278 ascent_pixels_ = other->ascent_pixels_; |
260 height_pixels_ = other->height_pixels_; | 279 height_pixels_ = other->height_pixels_; |
261 cap_height_pixels_ = other->cap_height_pixels_; | 280 cap_height_pixels_ = other->cap_height_pixels_; |
262 average_width_pixels_ = other->average_width_pixels_; | 281 average_width_pixels_ = other->average_width_pixels_; |
263 } | 282 } |
264 } | 283 } |
265 | 284 |
266 void PlatformFontLinux::ComputeMetricsIfNecessary() { | 285 void PlatformFontLinux::ComputeMetricsIfNecessary() { |
267 if (metrics_need_computation_) { | 286 if (metrics_need_computation_) { |
268 metrics_need_computation_ = false; | 287 metrics_need_computation_ = false; |
269 | 288 |
270 SkPaint paint; | 289 SkPaint paint; |
271 paint.setAntiAlias(false); | 290 paint.setAntiAlias(false); |
272 paint.setSubpixelText(false); | 291 paint.setSubpixelText(false); |
273 paint.setTextSize(font_size_pixels_); | 292 paint.setTextSize(font_size_pixels_); |
274 paint.setTypeface(typeface_.get()); | 293 paint.setTypeface(typeface_.get()); |
275 paint.setFakeBoldText((Font::BOLD & style_) && !typeface_->isBold()); | 294 paint.setFakeBoldText(weight_ >= gfx::Font::Weight::BOLD && |
276 paint.setTextSkewX((Font::ITALIC & style_) && !typeface_->isItalic() ? | 295 !typeface_->isBold()); |
277 -SK_Scalar1/4 : 0); | 296 paint.setTextSkewX(italic_ && !typeface_->isItalic() ? -SK_Scalar1 / 4 : 0); |
278 SkPaint::FontMetrics metrics; | 297 SkPaint::FontMetrics metrics; |
279 paint.getFontMetrics(&metrics); | 298 paint.getFontMetrics(&metrics); |
280 ascent_pixels_ = SkScalarCeilToInt(-metrics.fAscent); | 299 ascent_pixels_ = SkScalarCeilToInt(-metrics.fAscent); |
281 height_pixels_ = ascent_pixels_ + SkScalarCeilToInt(metrics.fDescent); | 300 height_pixels_ = ascent_pixels_ + SkScalarCeilToInt(metrics.fDescent); |
282 cap_height_pixels_ = SkScalarCeilToInt(metrics.fCapHeight); | 301 cap_height_pixels_ = SkScalarCeilToInt(metrics.fCapHeight); |
283 average_width_pixels_ = SkScalarToDouble(metrics.fAvgCharWidth); | 302 average_width_pixels_ = SkScalarToDouble(metrics.fAvgCharWidth); |
284 } | 303 } |
285 } | 304 } |
286 | 305 |
287 //////////////////////////////////////////////////////////////////////////////// | 306 //////////////////////////////////////////////////////////////////////////////// |
288 // PlatformFont, public: | 307 // PlatformFont, public: |
289 | 308 |
290 // static | 309 // static |
291 PlatformFont* PlatformFont::CreateDefault() { | 310 PlatformFont* PlatformFont::CreateDefault() { |
292 return new PlatformFontLinux; | 311 return new PlatformFontLinux; |
293 } | 312 } |
294 | 313 |
295 // static | 314 // static |
296 PlatformFont* PlatformFont::CreateFromNameAndSize(const std::string& font_name, | 315 PlatformFont* PlatformFont::CreateFromNameAndSize(const std::string& font_name, |
297 int font_size) { | 316 int font_size) { |
298 return new PlatformFontLinux(font_name, font_size); | 317 return new PlatformFontLinux(font_name, font_size); |
299 } | 318 } |
300 | 319 |
301 } // namespace gfx | 320 } // namespace gfx |
OLD | NEW |