Chromium Code Reviews| Index: content/browser/renderer_host/dwrite_font_proxy_message_filter_win.cc |
| diff --git a/content/browser/renderer_host/dwrite_font_proxy_message_filter_win.cc b/content/browser/renderer_host/dwrite_font_proxy_message_filter_win.cc |
| index eccace7f0d93d58ab1ba688f6f02d0eff6909b67..53d423008ae6cb447e81f84d68e2c98c8bb72018 100644 |
| --- a/content/browser/renderer_host/dwrite_font_proxy_message_filter_win.cc |
| +++ b/content/browser/renderer_host/dwrite_font_proxy_message_filter_win.cc |
| @@ -41,6 +41,7 @@ enum DirectWriteFontLoaderType { |
| FILE_SYSTEM_FONT_DIR = 0, |
| FILE_OUTSIDE_SANDBOX = 1, |
| OTHER_LOADER = 2, |
| + FONT_WITH_MISSING_REQUIRED_STYLES = 3, |
| FONT_LOADER_TYPE_MAX_VALUE |
| }; |
| @@ -131,6 +132,61 @@ const base::Feature kForceCustomFonts { |
| "ForceDirectWriteCustomFonts", base::FEATURE_DISABLED_BY_DEFAULT |
| }; |
| +struct RequiredFontStyle { |
| + const wchar_t* family_name; |
| + DWRITE_FONT_WEIGHT required_weight; |
| + DWRITE_FONT_STRETCH required_stretch; |
| + DWRITE_FONT_STYLE required_style; |
| +}; |
| + |
| +const RequiredFontStyle kRequiredStyles[] = { |
| + {L"open sans", DWRITE_FONT_WEIGHT_NORMAL, DWRITE_FONT_STRETCH_NORMAL, |
| + DWRITE_FONT_STYLE_NORMAL}, |
| + {L"helvetica", DWRITE_FONT_WEIGHT_NORMAL, DWRITE_FONT_STRETCH_NORMAL, |
| + DWRITE_FONT_STYLE_NORMAL}, |
|
ananta
2016/08/19 21:19:49
Is this list likely to grow?. Do IE and Firefox do
Ilya Kulshin
2016/08/19 21:29:42
I think we will want to add 'Gill Sans' to the lis
|
| +}; |
| + |
| +// As a workaround for crbug.com/635932, refuse to load some common fonts that |
| +// do not contain certain styles. We found that sometimes these fonts are |
| +// installed only in specialized styles ('Open Sans' might only be available in |
| +// the condensed light variant, or Helvetica might only be available in bold). |
| +// That results in a poor user experience because websites that use those fonts |
| +// usually expect them to be rendered in the regular variant. |
| +bool CheckRequiredStylesPresent(IDWriteFontCollection* collection, |
| + const base::string16& family_name, |
| + uint32_t family_index) { |
| + for (const auto& font_style : kRequiredStyles) { |
| + if (base::EqualsCaseInsensitiveASCII(family_name, font_style.family_name)) { |
| + mswr::ComPtr<IDWriteFontFamily> family; |
| + if (FAILED(collection->GetFontFamily(family_index, &family))) { |
| + DCHECK(false); |
| + return true; |
| + } |
| + mswr::ComPtr<IDWriteFont> font; |
| + if (FAILED(family->GetFirstMatchingFont( |
| + font_style.required_weight, font_style.required_stretch, |
| + font_style.required_style, &font))) { |
| + DCHECK(false); |
| + return true; |
| + } |
| + |
| + // GetFirstMatchingFont doesn't require strict style matching, so check |
| + // the actual font that we got. |
| + if (font->GetWeight() != font_style.required_weight || |
| + font->GetStretch() != font_style.required_stretch || |
| + font->GetStyle() != font_style.required_style) { |
| + // Not really a loader type, but good to have telemetry on how often |
| + // fonts like these are encountered, and the data can be compared with |
| + // the other loader types. |
| + LogLoaderType(FONT_WITH_MISSING_REQUIRED_STYLES); |
| + return false; |
| + } |
| + break; |
| + } |
| + } |
| + return true; |
| +} |
| + |
| } // namespace |
| DWriteFontProxyMessageFilter::DWriteFontProxyMessageFilter() |
| @@ -178,8 +234,10 @@ void DWriteFontProxyMessageFilter::OnFindFamily( |
| UINT32 index = UINT32_MAX; |
| HRESULT hr = |
| collection_->FindFamilyName(family_name.data(), &index, &exists); |
| - if (SUCCEEDED(hr) && exists) |
| + if (SUCCEEDED(hr) && exists && |
| + CheckRequiredStylesPresent(collection_.Get(), family_name, index)) { |
| *family_index = index; |
| + } |
| } |
| } |