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_win.h" | 5 #include "ui/gfx/platform_font_win.h" |
6 | 6 |
7 #include <windows.h> | 7 #include <windows.h> |
8 #include <math.h> | 8 #include <math.h> |
9 | 9 |
10 #include <algorithm> | 10 #include <algorithm> |
11 #include <string> | 11 #include <string> |
12 | 12 |
13 #include "base/logging.h" | 13 #include "base/logging.h" |
14 #include "base/macros.h" | 14 #include "base/macros.h" |
15 #include "base/strings/string_util.h" | 15 #include "base/strings/string_util.h" |
16 #include "base/strings/sys_string_conversions.h" | 16 #include "base/strings/sys_string_conversions.h" |
17 #include "base/strings/utf_string_conversions.h" | 17 #include "base/strings/utf_string_conversions.h" |
18 #include "base/win/scoped_comptr.h" | 18 #include "base/win/scoped_comptr.h" |
19 #include "base/win/scoped_gdi_object.h" | 19 #include "base/win/scoped_gdi_object.h" |
20 #include "base/win/scoped_hdc.h" | 20 #include "base/win/scoped_hdc.h" |
21 #include "base/win/scoped_select_object.h" | 21 #include "base/win/scoped_select_object.h" |
22 #include "base/win/win_util.h" | 22 #include "base/win/win_util.h" |
| 23 #include "third_party/skia/include/core/SkTypeface.h" |
23 #include "ui/gfx/canvas.h" | 24 #include "ui/gfx/canvas.h" |
24 #include "ui/gfx/font.h" | 25 #include "ui/gfx/font.h" |
25 #include "ui/gfx/font_render_params.h" | 26 #include "ui/gfx/font_render_params.h" |
26 #include "ui/gfx/win/scoped_set_map_mode.h" | 27 #include "ui/gfx/win/scoped_set_map_mode.h" |
27 | 28 |
28 namespace { | 29 namespace { |
29 | 30 |
30 // If the tmWeight field of a TEXTMETRIC structure has a value >= this, the | 31 // If the tmWeight field of a TEXTMETRIC structure has a value >= this, the |
31 // font is bold. | 32 // font is bold. |
32 const int kTextMetricWeightBold = 700; | 33 const int kTextMetricWeightBold = 700; |
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
75 | 76 |
76 // static | 77 // static |
77 PlatformFontWin::HFontRef* PlatformFontWin::base_font_ref_; | 78 PlatformFontWin::HFontRef* PlatformFontWin::base_font_ref_; |
78 | 79 |
79 // static | 80 // static |
80 PlatformFontWin::AdjustFontCallback | 81 PlatformFontWin::AdjustFontCallback |
81 PlatformFontWin::adjust_font_callback = NULL; | 82 PlatformFontWin::adjust_font_callback = NULL; |
82 PlatformFontWin::GetMinimumFontSizeCallback | 83 PlatformFontWin::GetMinimumFontSizeCallback |
83 PlatformFontWin::get_minimum_font_size_callback = NULL; | 84 PlatformFontWin::get_minimum_font_size_callback = NULL; |
84 | 85 |
85 IDWriteFactory* PlatformFontWin::direct_write_factory_ = NULL; | 86 bool PlatformFontWin::use_skia_for_font_metrics_ = false; |
86 | 87 |
87 //////////////////////////////////////////////////////////////////////////////// | 88 //////////////////////////////////////////////////////////////////////////////// |
88 // PlatformFontWin, public | 89 // PlatformFontWin, public |
89 | 90 |
90 PlatformFontWin::PlatformFontWin() : font_ref_(GetBaseFontRef()) { | 91 PlatformFontWin::PlatformFontWin() : font_ref_(GetBaseFontRef()) { |
91 } | 92 } |
92 | 93 |
93 PlatformFontWin::PlatformFontWin(NativeFont native_font) { | 94 PlatformFontWin::PlatformFontWin(NativeFont native_font) { |
94 InitWithCopyOfHFONT(native_font); | 95 InitWithCopyOfHFONT(native_font); |
95 } | 96 } |
(...skipping 147 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
243 base_font_ref_ = PlatformFontWin::CreateHFontRef(font); | 244 base_font_ref_ = PlatformFontWin::CreateHFontRef(font); |
244 // base_font_ref_ is global, up the ref count so it's never deleted. | 245 // base_font_ref_ is global, up the ref count so it's never deleted. |
245 base_font_ref_->AddRef(); | 246 base_font_ref_->AddRef(); |
246 } | 247 } |
247 return base_font_ref_; | 248 return base_font_ref_; |
248 } | 249 } |
249 | 250 |
250 PlatformFontWin::HFontRef* PlatformFontWin::CreateHFontRef(HFONT font) { | 251 PlatformFontWin::HFontRef* PlatformFontWin::CreateHFontRef(HFONT font) { |
251 TEXTMETRIC font_metrics; | 252 TEXTMETRIC font_metrics; |
252 | 253 |
253 if (direct_write_factory_) { | 254 if (use_skia_for_font_metrics_) |
254 base::win::ScopedGDIObject<HFONT> gdi_font(font); | 255 return CreateHFontRefFromSkia(font); |
255 font = ConvertGDIFontToDirectWriteFont(gdi_font); | |
256 } | |
257 | 256 |
258 { | 257 { |
259 base::win::ScopedGetDC screen_dc(NULL); | 258 base::win::ScopedGetDC screen_dc(NULL); |
260 gfx::ScopedSetMapMode mode(screen_dc, MM_TEXT); | 259 gfx::ScopedSetMapMode mode(screen_dc, MM_TEXT); |
261 GetTextMetricsForFont(screen_dc, font, &font_metrics); | 260 GetTextMetricsForFont(screen_dc, font, &font_metrics); |
262 } | 261 } |
263 | 262 |
264 return CreateHFontRef(font, font_metrics); | 263 return CreateHFontRef(font, font_metrics); |
265 } | 264 } |
266 | 265 |
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
311 if (font_metrics.tmHeight > best_font_metrics.tmHeight) | 310 if (font_metrics.tmHeight > best_font_metrics.tmHeight) |
312 break; | 311 break; |
313 best_font.Set(font.release()); | 312 best_font.Set(font.release()); |
314 best_font_metrics = font_metrics; | 313 best_font_metrics = font_metrics; |
315 } while (true); | 314 } while (true); |
316 | 315 |
317 return Font(new PlatformFontWin(CreateHFontRef(best_font.release()))); | 316 return Font(new PlatformFontWin(CreateHFontRef(best_font.release()))); |
318 } | 317 } |
319 | 318 |
320 // static | 319 // static |
321 HFONT PlatformFontWin::ConvertGDIFontToDirectWriteFont(HFONT gdi_font) { | 320 PlatformFontWin::HFontRef* PlatformFontWin::CreateHFontRefFromSkia( |
322 // This function uses the DirectWrite Gdi interop interfaces to convert the | 321 HFONT gdi_font) { |
323 // gdi font passed in to a HFONT which is compatible with DirectWrite font | 322 LOGFONT font_info = {0}; |
324 // metrics which could be different from GDI font metrics. This ensures that | 323 GetObject(gdi_font, sizeof(LOGFONT), &font_info); |
325 // widgets like labels which use font metrics to calculate bounds have the | 324 |
326 // same calculations as skia which uses DirectWrite. | 325 int skia_style = SkTypeface::kNormal; |
327 DCHECK(direct_write_factory_); | 326 if (font_info.lfWeight >= FW_SEMIBOLD && |
328 base::win::ScopedComPtr<IDWriteGdiInterop> gdi_interop; | 327 font_info.lfWeight <= FW_ULTRABOLD) { |
329 HRESULT hr = direct_write_factory_->GetGdiInterop(gdi_interop.Receive()); | 328 skia_style |= SkTypeface::kBold; |
330 if (FAILED(hr)) { | |
331 CHECK(false); | |
332 return NULL; | |
333 } | 329 } |
| 330 if (font_info.lfItalic) |
| 331 skia_style |= SkTypeface::kItalic; |
334 | 332 |
335 base::win::ScopedGetDC screen_dc(NULL); | 333 skia::RefPtr<SkTypeface> skia_face = skia::AdoptRef( |
336 gfx::ScopedSetMapMode mode(screen_dc, MM_TEXT); | 334 SkTypeface::CreateFromName( |
| 335 base::SysWideToUTF8(font_info.lfFaceName).c_str(), |
| 336 static_cast<SkTypeface::Style>(skia_style))); |
| 337 BOOL antialiasing = TRUE; |
| 338 SystemParametersInfo(SPI_GETFONTSMOOTHING, 0, &antialiasing, 0); |
337 | 339 |
338 base::win::ScopedSelectObject scoped_font(screen_dc, gdi_font); | 340 SkPaint paint; |
| 341 paint.setAntiAlias(!!antialiasing); |
| 342 paint.setTypeface(skia_face.get()); |
| 343 SkPaint::FontMetrics skia_metrics; |
| 344 paint.getFontMetrics(&skia_metrics); |
339 | 345 |
340 base::win::ScopedComPtr<IDWriteFontFace> font_face_gdi; | 346 // The calculations below are similar to those in the CreateHFontRef |
341 hr = gdi_interop->CreateFontFaceFromHdc(screen_dc, font_face_gdi.Receive()); | 347 // function. |
342 if (FAILED(hr)) { | 348 const int height = |
343 CHECK(false); | 349 std::max<int>(1, std::ceil(fabs(skia_metrics.fAscent)) + |
344 return NULL; | 350 std::ceil(skia_metrics.fDescent)); |
345 } | 351 const int baseline = std::max<int>(1, std::ceil(fabs(skia_metrics.fAscent))); |
| 352 const int cap_height = std::max<int>(1, |
| 353 std::ceil(fabs(skia_metrics.fAscent)) - skia_metrics.fLeading); |
| 354 const int ave_char_width = std::max<int>(1, skia_metrics.fAvgCharWidth); |
| 355 const int font_size = std::max<int>(1, height - skia_metrics.fLeading); |
346 | 356 |
347 LOGFONT dwrite_to_gdi_log_font = {0}; | 357 int style = 0; |
348 hr = gdi_interop->ConvertFontFaceToLOGFONT(font_face_gdi, | 358 if (skia_style & SkTypeface::kItalic) |
349 &dwrite_to_gdi_log_font); | 359 style |= Font::ITALIC; |
350 if (FAILED(hr)) { | 360 if (font_info.lfUnderline) |
351 CHECK(false); | 361 style |= Font::UNDERLINE; |
352 return NULL; | 362 if (font_info.lfWeight >= kTextMetricWeightBold) |
353 } | 363 style |= Font::BOLD; |
354 return CreateFontIndirect(&dwrite_to_gdi_log_font); | 364 return new HFontRef(gdi_font, font_size, height, baseline, cap_height, |
| 365 ave_char_width, style); |
355 } | 366 } |
356 | 367 |
357 PlatformFontWin::PlatformFontWin(HFontRef* hfont_ref) : font_ref_(hfont_ref) { | 368 PlatformFontWin::PlatformFontWin(HFontRef* hfont_ref) : font_ref_(hfont_ref) { |
358 } | 369 } |
359 | 370 |
360 //////////////////////////////////////////////////////////////////////////////// | 371 //////////////////////////////////////////////////////////////////////////////// |
361 // PlatformFontWin::HFontRef: | 372 // PlatformFontWin::HFontRef: |
362 | 373 |
363 PlatformFontWin::HFontRef::HFontRef(HFONT hfont, | 374 PlatformFontWin::HFontRef::HFontRef(HFONT hfont, |
364 int font_size, | 375 int font_size, |
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
422 return new PlatformFontWin(native_font); | 433 return new PlatformFontWin(native_font); |
423 } | 434 } |
424 | 435 |
425 // static | 436 // static |
426 PlatformFont* PlatformFont::CreateFromNameAndSize(const std::string& font_name, | 437 PlatformFont* PlatformFont::CreateFromNameAndSize(const std::string& font_name, |
427 int font_size) { | 438 int font_size) { |
428 return new PlatformFontWin(font_name, font_size); | 439 return new PlatformFontWin(font_name, font_size); |
429 } | 440 } |
430 | 441 |
431 } // namespace gfx | 442 } // namespace gfx |
OLD | NEW |