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 <dwrite.h> | 8 #include <dwrite.h> |
9 #include <limits.h> | 9 #include <limits.h> |
10 #include <math.h> | 10 #include <math.h> |
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
74 // Uses the GDI interop functionality exposed by DirectWrite to find a | 74 // Uses the GDI interop functionality exposed by DirectWrite to find a |
75 // matching DirectWrite font for the LOGFONT passed in. If we fail to | 75 // matching DirectWrite font for the LOGFONT passed in. If we fail to |
76 // find a direct match then we try the DirectWrite font substitution | 76 // find a direct match then we try the DirectWrite font substitution |
77 // route to find a match. | 77 // route to find a match. |
78 // The contents of the LOGFONT pointer |font_info| may be modified on | 78 // The contents of the LOGFONT pointer |font_info| may be modified on |
79 // return. | 79 // return. |
80 HRESULT FindDirectWriteFontForLOGFONT(IDWriteFactory* factory, | 80 HRESULT FindDirectWriteFontForLOGFONT(IDWriteFactory* factory, |
81 LOGFONT* font_info, | 81 LOGFONT* font_info, |
82 IDWriteFont** dwrite_font) { | 82 IDWriteFont** dwrite_font) { |
83 base::win::ScopedComPtr<IDWriteGdiInterop> gdi_interop; | 83 base::win::ScopedComPtr<IDWriteGdiInterop> gdi_interop; |
84 HRESULT hr = factory->GetGdiInterop(gdi_interop.Receive()); | 84 HRESULT hr = factory->GetGdiInterop(gdi_interop.GetAddressOf()); |
85 if (FAILED(hr)) { | 85 if (FAILED(hr)) { |
86 CHECK(false); | 86 CHECK(false); |
87 return hr; | 87 return hr; |
88 } | 88 } |
89 | 89 |
90 hr = gdi_interop->CreateFontFromLOGFONT(font_info, dwrite_font); | 90 hr = gdi_interop->CreateFontFromLOGFONT(font_info, dwrite_font); |
91 if (SUCCEEDED(hr)) | 91 if (SUCCEEDED(hr)) |
92 return hr; | 92 return hr; |
93 | 93 |
94 base::win::ScopedComPtr<IDWriteFontCollection> font_collection; | 94 base::win::ScopedComPtr<IDWriteFontCollection> font_collection; |
95 hr = factory->GetSystemFontCollection(font_collection.Receive()); | 95 hr = factory->GetSystemFontCollection(font_collection.GetAddressOf()); |
96 if (FAILED(hr)) { | 96 if (FAILED(hr)) { |
97 CHECK(false); | 97 CHECK(false); |
98 return hr; | 98 return hr; |
99 } | 99 } |
100 | 100 |
101 // We try to find a matching font by triggering DirectWrite to substitute the | 101 // We try to find a matching font by triggering DirectWrite to substitute the |
102 // font passed in with a matching font (FontSubstitutes registry key) | 102 // font passed in with a matching font (FontSubstitutes registry key) |
103 // If this succeeds we return the matched font. | 103 // If this succeeds we return the matched font. |
104 base::win::ScopedGDIObject<HFONT> font(::CreateFontIndirect(font_info)); | 104 base::win::ScopedGDIObject<HFONT> font(::CreateFontIndirect(font_info)); |
105 base::win::ScopedGetDC screen_dc(NULL); | 105 base::win::ScopedGetDC screen_dc(NULL); |
106 base::win::ScopedSelectObject scoped_font(screen_dc, font.get()); | 106 base::win::ScopedSelectObject scoped_font(screen_dc, font.get()); |
107 | 107 |
108 base::win::ScopedComPtr<IDWriteFontFace> font_face; | 108 base::win::ScopedComPtr<IDWriteFontFace> font_face; |
109 hr = gdi_interop->CreateFontFaceFromHdc(screen_dc, font_face.Receive()); | 109 hr = gdi_interop->CreateFontFaceFromHdc(screen_dc, font_face.GetAddressOf()); |
110 if (FAILED(hr)) | 110 if (FAILED(hr)) |
111 return hr; | 111 return hr; |
112 | 112 |
113 LOGFONT converted_font = {0}; | 113 LOGFONT converted_font = {0}; |
114 hr = gdi_interop->ConvertFontFaceToLOGFONT(font_face.Get(), &converted_font); | 114 hr = gdi_interop->ConvertFontFaceToLOGFONT(font_face.Get(), &converted_font); |
115 if (SUCCEEDED(hr)) { | 115 if (SUCCEEDED(hr)) { |
116 hr = font_collection->GetFontFromFontFace(font_face.Get(), dwrite_font); | 116 hr = font_collection->GetFontFromFontFace(font_face.Get(), dwrite_font); |
117 if (SUCCEEDED(hr)) { | 117 if (SUCCEEDED(hr)) { |
118 wcscpy_s(font_info->lfFaceName, arraysize(font_info->lfFaceName), | 118 wcscpy_s(font_info->lfFaceName, arraysize(font_info->lfFaceName), |
119 converted_font.lfFaceName); | 119 converted_font.lfFaceName); |
(...skipping 15 matching lines...) Expand all Loading... |
135 // First try the GDI compat route to get a matching DirectWrite font. | 135 // First try the GDI compat route to get a matching DirectWrite font. |
136 // If that succeeds then we are good. If that fails then try and find a | 136 // If that succeeds then we are good. If that fails then try and find a |
137 // match from the DirectWrite font collection. | 137 // match from the DirectWrite font collection. |
138 HRESULT hr = FindDirectWriteFontForLOGFONT(factory, font_info, dwrite_font); | 138 HRESULT hr = FindDirectWriteFontForLOGFONT(factory, font_info, dwrite_font); |
139 if (SUCCEEDED(hr)) | 139 if (SUCCEEDED(hr)) |
140 return hr; | 140 return hr; |
141 | 141 |
142 // Get a matching font from the system font collection exposed by | 142 // Get a matching font from the system font collection exposed by |
143 // DirectWrite. | 143 // DirectWrite. |
144 base::win::ScopedComPtr<IDWriteFontCollection> font_collection; | 144 base::win::ScopedComPtr<IDWriteFontCollection> font_collection; |
145 hr = factory->GetSystemFontCollection(font_collection.Receive()); | 145 hr = factory->GetSystemFontCollection(font_collection.GetAddressOf()); |
146 if (FAILED(hr)) { | 146 if (FAILED(hr)) { |
147 CHECK(false); | 147 CHECK(false); |
148 return hr; | 148 return hr; |
149 } | 149 } |
150 | 150 |
151 // Steps as below:- | 151 // Steps as below:- |
152 // This mirrors skia. | 152 // This mirrors skia. |
153 // 1. Attempt to find a DirectWrite font family based on the face name in the | 153 // 1. Attempt to find a DirectWrite font family based on the face name in the |
154 // font. That may not work at all times, as the face name could be random | 154 // font. That may not work at all times, as the face name could be random |
155 // GDI has its own font system where in it creates a font matching the | 155 // GDI has its own font system where in it creates a font matching the |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
189 return hr; | 189 return hr; |
190 | 190 |
191 // Best effort to find a matching font from the system font collection. | 191 // Best effort to find a matching font from the system font collection. |
192 hr = font_collection->FindFamilyName(metrics.lfMessageFont.lfFaceName, | 192 hr = font_collection->FindFamilyName(metrics.lfMessageFont.lfFaceName, |
193 &index, | 193 &index, |
194 &exists); | 194 &exists); |
195 } | 195 } |
196 } | 196 } |
197 | 197 |
198 if (index != UINT_MAX && exists) { | 198 if (index != UINT_MAX && exists) { |
199 hr = font_collection->GetFontFamily(index, font_family.Receive()); | 199 hr = font_collection->GetFontFamily(index, font_family.GetAddressOf()); |
200 } else { | 200 } else { |
201 // If we fail to find a matching font, then fallback to the first font in | 201 // If we fail to find a matching font, then fallback to the first font in |
202 // the list. This is what skia does as well. | 202 // the list. This is what skia does as well. |
203 hr = font_collection->GetFontFamily(0, font_family.Receive()); | 203 hr = font_collection->GetFontFamily(0, font_family.GetAddressOf()); |
204 } | 204 } |
205 | 205 |
206 if (FAILED(hr)) { | 206 if (FAILED(hr)) { |
207 CHECK(false); | 207 CHECK(false); |
208 return hr; | 208 return hr; |
209 } | 209 } |
210 | 210 |
211 DWRITE_FONT_WEIGHT weight = | 211 DWRITE_FONT_WEIGHT weight = |
212 static_cast<DWRITE_FONT_WEIGHT>(font_info->lfWeight); | 212 static_cast<DWRITE_FONT_WEIGHT>(font_info->lfWeight); |
213 DWRITE_FONT_STRETCH stretch = DWRITE_FONT_STRETCH_NORMAL; | 213 DWRITE_FONT_STRETCH stretch = DWRITE_FONT_STRETCH_NORMAL; |
214 DWRITE_FONT_STYLE style = | 214 DWRITE_FONT_STYLE style = |
215 (italic) ? DWRITE_FONT_STYLE_ITALIC : DWRITE_FONT_STYLE_NORMAL; | 215 (italic) ? DWRITE_FONT_STYLE_ITALIC : DWRITE_FONT_STYLE_NORMAL; |
216 | 216 |
217 // The IDWriteFontFamily::GetFirstMatchingFont call fails on certain machines | 217 // The IDWriteFontFamily::GetFirstMatchingFont call fails on certain machines |
218 // for fonts like MS UI Gothic, Segoe UI, etc. It is not clear why these | 218 // for fonts like MS UI Gothic, Segoe UI, etc. It is not clear why these |
219 // fonts could be accessible to GDI and not to DirectWrite. | 219 // fonts could be accessible to GDI and not to DirectWrite. |
220 // The code below adds some debug fields to help track down these failures. | 220 // The code below adds some debug fields to help track down these failures. |
221 // 1. We get the matching font list for the font attributes passed in. | 221 // 1. We get the matching font list for the font attributes passed in. |
222 // 2. We get the font count in the family with a debug alias variable. | 222 // 2. We get the font count in the family with a debug alias variable. |
223 // 3. If GetFirstMatchingFont fails then we CHECK as before. | 223 // 3. If GetFirstMatchingFont fails then we CHECK as before. |
224 // Next step would be to remove the CHECKs in this function and fallback to | 224 // Next step would be to remove the CHECKs in this function and fallback to |
225 // GDI. | 225 // GDI. |
226 // http://crbug.com/434425 | 226 // http://crbug.com/434425 |
227 // TODO(ananta) | 227 // TODO(ananta) |
228 // Remove the GetMatchingFonts and related code here once we get to a stable | 228 // Remove the GetMatchingFonts and related code here once we get to a stable |
229 // state in canary. | 229 // state in canary. |
230 base::win::ScopedComPtr<IDWriteFontList> matching_font_list; | 230 base::win::ScopedComPtr<IDWriteFontList> matching_font_list; |
231 hr = font_family->GetMatchingFonts(weight, stretch, style, | 231 hr = font_family->GetMatchingFonts(weight, stretch, style, |
232 matching_font_list.Receive()); | 232 matching_font_list.GetAddressOf()); |
233 uint32_t matching_font_count = 0; | 233 uint32_t matching_font_count = 0; |
234 if (SUCCEEDED(hr)) | 234 if (SUCCEEDED(hr)) |
235 matching_font_count = matching_font_list->GetFontCount(); | 235 matching_font_count = matching_font_list->GetFontCount(); |
236 | 236 |
237 hr = font_family->GetFirstMatchingFont(weight, stretch, style, dwrite_font); | 237 hr = font_family->GetFirstMatchingFont(weight, stretch, style, dwrite_font); |
238 if (FAILED(hr)) { | 238 if (FAILED(hr)) { |
239 base::debug::Alias(&matching_font_count); | 239 base::debug::Alias(&matching_font_count); |
240 CHECK(false); | 240 CHECK(false); |
241 } | 241 } |
242 | 242 |
(...skipping 17 matching lines...) Expand all Loading... |
260 PlatformFontWin::GetMinimumFontSizeCallback | 260 PlatformFontWin::GetMinimumFontSizeCallback |
261 PlatformFontWin::get_minimum_font_size_callback = NULL; | 261 PlatformFontWin::get_minimum_font_size_callback = NULL; |
262 | 262 |
263 IDWriteFactory* PlatformFontWin::direct_write_factory_ = nullptr; | 263 IDWriteFactory* PlatformFontWin::direct_write_factory_ = nullptr; |
264 | 264 |
265 // TODO(ananta) | 265 // TODO(ananta) |
266 // Remove the CHECKs in this function once this stabilizes on the field. | 266 // Remove the CHECKs in this function once this stabilizes on the field. |
267 HRESULT GetFamilyNameFromDirectWriteFont(IDWriteFont* dwrite_font, | 267 HRESULT GetFamilyNameFromDirectWriteFont(IDWriteFont* dwrite_font, |
268 base::string16* family_name) { | 268 base::string16* family_name) { |
269 base::win::ScopedComPtr<IDWriteFontFamily> font_family; | 269 base::win::ScopedComPtr<IDWriteFontFamily> font_family; |
270 HRESULT hr = dwrite_font->GetFontFamily(font_family.Receive()); | 270 HRESULT hr = dwrite_font->GetFontFamily(font_family.GetAddressOf()); |
271 if (FAILED(hr)) | 271 if (FAILED(hr)) |
272 CHECK(false); | 272 CHECK(false); |
273 | 273 |
274 base::win::ScopedComPtr<IDWriteLocalizedStrings> family_names; | 274 base::win::ScopedComPtr<IDWriteLocalizedStrings> family_names; |
275 hr = font_family->GetFamilyNames(family_names.Receive()); | 275 hr = font_family->GetFamilyNames(family_names.GetAddressOf()); |
276 if (FAILED(hr)) | 276 if (FAILED(hr)) |
277 CHECK(false); | 277 CHECK(false); |
278 | 278 |
279 // TODO(ananta) | 279 // TODO(ananta) |
280 // Add support for retrieving the family for the current locale. | 280 // Add support for retrieving the family for the current locale. |
281 wchar_t family_name_for_locale[MAX_PATH] = {0}; | 281 wchar_t family_name_for_locale[MAX_PATH] = {0}; |
282 hr = family_names->GetString(0, family_name_for_locale, | 282 hr = family_names->GetString(0, family_name_for_locale, |
283 arraysize(family_name_for_locale)); | 283 arraysize(family_name_for_locale)); |
284 if (FAILED(hr)) | 284 if (FAILED(hr)) |
285 CHECK(false); | 285 CHECK(false); |
(...skipping 232 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
518 | 518 |
519 // Skia does not return all values we need for font metrics. For e.g. | 519 // Skia does not return all values we need for font metrics. For e.g. |
520 // the cap height which indicates the height of capital letters is not | 520 // the cap height which indicates the height of capital letters is not |
521 // returned even though it is returned by DirectWrite. | 521 // returned even though it is returned by DirectWrite. |
522 // TODO(ananta) | 522 // TODO(ananta) |
523 // Fix SkScalerContext_win_dw.cpp to return all metrics we need from | 523 // Fix SkScalerContext_win_dw.cpp to return all metrics we need from |
524 // DirectWrite and remove the code here which retrieves metrics from | 524 // DirectWrite and remove the code here which retrieves metrics from |
525 // DirectWrite to calculate the cap height. | 525 // DirectWrite to calculate the cap height. |
526 base::win::ScopedComPtr<IDWriteFont> dwrite_font; | 526 base::win::ScopedComPtr<IDWriteFont> dwrite_font; |
527 HRESULT hr = GetMatchingDirectWriteFont( | 527 HRESULT hr = GetMatchingDirectWriteFont( |
528 &font_info, italic, direct_write_factory_, dwrite_font.Receive()); | 528 &font_info, italic, direct_write_factory_, dwrite_font.GetAddressOf()); |
529 if (FAILED(hr)) { | 529 if (FAILED(hr)) { |
530 CHECK(false); | 530 CHECK(false); |
531 return nullptr; | 531 return nullptr; |
532 } | 532 } |
533 | 533 |
534 DWRITE_FONT_METRICS dwrite_font_metrics = {0}; | 534 DWRITE_FONT_METRICS dwrite_font_metrics = {0}; |
535 dwrite_font->GetMetrics(&dwrite_font_metrics); | 535 dwrite_font->GetMetrics(&dwrite_font_metrics); |
536 | 536 |
537 SkFontStyle skia_font_style(font_info.lfWeight, SkFontStyle::kNormal_Width, | 537 SkFontStyle skia_font_style(font_info.lfWeight, SkFontStyle::kNormal_Width, |
538 font_info.lfItalic ? SkFontStyle::kItalic_Slant | 538 font_info.lfItalic ? SkFontStyle::kItalic_Slant |
(...skipping 140 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
679 return new PlatformFontWin(native_font); | 679 return new PlatformFontWin(native_font); |
680 } | 680 } |
681 | 681 |
682 // static | 682 // static |
683 PlatformFont* PlatformFont::CreateFromNameAndSize(const std::string& font_name, | 683 PlatformFont* PlatformFont::CreateFromNameAndSize(const std::string& font_name, |
684 int font_size) { | 684 int font_size) { |
685 return new PlatformFontWin(font_name, font_size); | 685 return new PlatformFontWin(font_name, font_size); |
686 } | 686 } |
687 | 687 |
688 } // namespace gfx | 688 } // namespace gfx |
OLD | NEW |