| 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 |