From 336ecceed40888771467fe77d17ffa847a7dd8be Mon Sep 17 00:00:00 2001 From: Adam Date: Mon, 4 Oct 2021 02:41:28 +0300 Subject: [PATCH] Implement GDI Font Rendering on 87.0.4247.0 --- .../Implement GDI Font Rendering.patch | 1132 +++++++++++++++++ 1 file changed, 1132 insertions(+) create mode 100644 patches/87.0.4247.0/Implement GDI Font Rendering.patch diff --git a/patches/87.0.4247.0/Implement GDI Font Rendering.patch b/patches/87.0.4247.0/Implement GDI Font Rendering.patch new file mode 100644 index 0000000..a2ee0ad --- /dev/null +++ b/patches/87.0.4247.0/Implement GDI Font Rendering.patch @@ -0,0 +1,1132 @@ +diff --git a/chrome/browser/chrome_content_browser_client.cc b/chrome/browser/chrome_content_browser_client.cc +index c481dd9ad3086..5d9ec4e59ed45 100644 +--- a/chrome/browser/chrome_content_browser_client.cc ++++ b/chrome/browser/chrome_content_browser_client.cc +@@ -671,7 +671,7 @@ namespace { + // running on Windows 10 1511 and above. See + // https://blogs.windows.com/blog/tag/code-integrity-guard/. + const base::Feature kRendererCodeIntegrity{"RendererCodeIntegrity", +- base::FEATURE_ENABLED_BY_DEFAULT}; ++ base::FEATURE_DISABLED_BY_DEFAULT}; + #endif // defined(OS_WIN) && !defined(COMPONENT_BUILD) && + // !defined(ADDRESS_SANITIZER) + +diff --git a/content/browser/renderer_host/dwrite_font_lookup_table_builder_win.cc b/content/browser/renderer_host/dwrite_font_lookup_table_builder_win.cc +index 9d4a00a80fa6d..91501704f1a59 100644 +--- a/content/browser/renderer_host/dwrite_font_lookup_table_builder_win.cc ++++ b/content/browser/renderer_host/dwrite_font_lookup_table_builder_win.cc +@@ -330,6 +330,7 @@ bool DWriteFontLookupTableBuilder::FontUniqueNameTableReady() { + + void DWriteFontLookupTableBuilder:: + SchedulePrepareFontUniqueNameTableIfNeeded() { ++ return; // Important + DCHECK(base::FeatureList::IsEnabled(features::kFontSrcLocalMatching)); + + { +diff --git a/content/public/common/content_features.cc b/content/public/common/content_features.cc +index a8306e524b996..4f69c57cbb88c 100644 +--- a/content/public/common/content_features.cc ++++ b/content/public/common/content_features.cc +@@ -244,7 +244,7 @@ const base::Feature kFirstScrollLatencyMeasurement{ + // font name or postscript name. Rolling out behind a flag, as enabling this + // enables a font indexer on Android which we need to test in the field first. + const base::Feature kFontSrcLocalMatching{"FontSrcLocalMatching", +- base::FEATURE_ENABLED_BY_DEFAULT}; ++ base::FEATURE_DISABLED_BY_DEFAULT}; + + #if !defined(OS_ANDROID) + // Feature controlling whether or not memory pressure signals will be forwarded +diff --git a/content/renderer/renderer_main.cc b/content/renderer/renderer_main.cc +index 9e0f9a37b4348..db2226398007e 100644 +--- a/content/renderer/renderer_main.cc ++++ b/content/renderer/renderer_main.cc +@@ -193,8 +193,8 @@ int RendererMain(const MainFunctionParams& parameters) { + + { + bool should_run_loop = true; +- bool need_sandbox = +- !command_line.HasSwitch(sandbox::policy::switches::kNoSandbox); ++ bool need_sandbox = false; ++ // !command_line.HasSwitch(sandbox::policy::switches::kNoSandbox); + + #if !defined(OS_WIN) && !defined(OS_MAC) + // Sandbox is enabled before RenderProcess initialization on all platforms, +diff --git a/content/renderer/renderer_main_platform_delegate_win.cc b/content/renderer/renderer_main_platform_delegate_win.cc +index 4fb80f41e7f8f..c39ade84e035e 100644 +--- a/content/renderer/renderer_main_platform_delegate_win.cc ++++ b/content/renderer/renderer_main_platform_delegate_win.cc +@@ -27,6 +27,12 @@ + #include "ui/gfx/win/direct_write.h" + + namespace content { ++namespace { ++ void SkiaPreCacheFont(const LOGFONT& logfont) { ++ RenderThread* render_thread = RenderThread::Get(); ++ if (render_thread) render_thread->PreCacheFont(logfont); ++ } ++} + + RendererMainPlatformDelegate::RendererMainPlatformDelegate( + const MainFunctionParams& parameters) +@@ -51,13 +57,13 @@ void RendererMainPlatformDelegate::PlatformInitialize() { + // cached and there's no more need to access the registry. If the sandbox + // is disabled, we don't have to make this dummy call. + std::unique_ptr zone(icu::TimeZone::createDefault()); ++ SkTypeface_SetEnsureLOGFONTAccessibleProc(SkiaPreCacheFont); + } + +- InitializeDWriteFontProxy(); + } + + void RendererMainPlatformDelegate::PlatformUninitialize() { +- UninitializeDWriteFontProxy(); ++ UninitializeDWriteFontProxy(); + } + + bool RendererMainPlatformDelegate::EnableSandbox() { +diff --git a/sandbox/policy/win/sandbox_win.cc b/sandbox/policy/win/sandbox_win.cc +index d63d942c7e3e8..900b828bdee35 100644 +--- a/sandbox/policy/win/sandbox_win.cc ++++ b/sandbox/policy/win/sandbox_win.cc +@@ -575,10 +575,10 @@ BOOL WINAPI DuplicateHandlePatch(HANDLE source_process_handle, + + bool IsAppContainerEnabled() { + if (base::win::GetVersion() < base::win::Version::WIN8) +- return false; ++ return false; + + return base::FeatureList::IsEnabled( +- {"RendererAppContainer", base::FEATURE_DISABLED_BY_DEFAULT}); ++ {"RendererAppContainer", base::FEATURE_DISABLED_BY_DEFAULT}); + } + + ResultCode SetJobMemoryLimit(const base::CommandLine& cmd_line, +@@ -918,26 +918,26 @@ ResultCode SandboxWin::StartSandboxedProcess( + + // Pre-startup mitigations. + MitigationFlags mitigations = +- MITIGATION_HEAP_TERMINATE | ++ //MITIGATION_HEAP_TERMINATE | + MITIGATION_BOTTOM_UP_ASLR | + MITIGATION_DEP | + MITIGATION_DEP_NO_ATL_THUNK | + MITIGATION_EXTENSION_POINT_DISABLE | + MITIGATION_SEHOP | +- MITIGATION_NONSYSTEM_FONT_DISABLE | ++ //MITIGATION_NONSYSTEM_FONT_DISABLE | + MITIGATION_IMAGE_LOAD_NO_REMOTE | + MITIGATION_IMAGE_LOAD_NO_LOW_LABEL | + MITIGATION_RESTRICT_INDIRECT_BRANCH_PREDICTION; + + ResultCode result = policy->SetProcessMitigations(mitigations); + if (result != SBOX_ALL_OK) + return result; + +- if (process_type == switches::kRendererProcess) { +- result = SandboxWin::AddWin32kLockdownPolicy(policy.get(), false); +- if (result != SBOX_ALL_OK) +- return result; +- } ++ // if (process_type == switches::kRendererProcess) { ++ // result = SandboxWin::AddWin32kLockdownPolicy(policy.get(), false); ++ // if (result != SBOX_ALL_OK) ++ // return result; ++ // } + + // Post-startup mitigations. + mitigations = MITIGATION_DLL_SEARCH_ORDER; +diff --git a/third_party/blink/renderer/platform/fonts/font_cache.cc b/third_party/blink/renderer/platform/fonts/font_cache.cc +index 1cceea6f774aa..66a9310e1457d 100644 +--- a/third_party/blink/renderer/platform/fonts/font_cache.cc ++++ b/third_party/blink/renderer/platform/fonts/font_cache.cc +@@ -107,7 +107,7 @@ FontCache::FontCache() + // This code path is only for unit tests. This SkFontMgr does not work in + // sandboxed environments, but injecting this initialization code to all + // unit tests isn't easy. +- font_manager_ = SkFontMgr_New_DirectWrite(); ++ font_manager_ = SkFontMgr_New_GDI(); + // Set |is_test_font_mgr_| to capture if this is not happening in the + // production code. crbug.com/561873 + is_test_font_mgr_ = true; +diff --git a/third_party/blink/renderer/platform/fonts/font_custom_platform_data.cc b/third_party/blink/renderer/platform/fonts/font_custom_platform_data.cc +index 212ae08ce3cb7..367049b645326 100644 +--- a/third_party/blink/renderer/platform/fonts/font_custom_platform_data.cc ++++ b/third_party/blink/renderer/platform/fonts/font_custom_platform_data.cc +@@ -63,7 +63,21 @@ FontPlatformData FontCustomPlatformData::GetFontPlatformData( + DCHECK(base_typeface_); + + sk_sp return_typeface = base_typeface_; +- ++ bool syntheticBold = bold && !base_typeface_->isBold(); ++ bool syntheticItalic = italic && !base_typeface_->isItalic(); ++ if (syntheticBold || syntheticItalic) { ++ SkString name; ++ base_typeface_->getFamilyName(&name); ++ SkFontStyle realStyle = base_typeface_->fontStyle(); ++ SkFontStyle syntheticStyle = SkFontStyle( ++ realStyle.weight() + (syntheticBold ? 200 : 0), realStyle.width(), ++ syntheticItalic ? SkFontStyle::kItalic_Slant : realStyle.slant()); ++ sk_sp typeface; ++ typeface = (FontCache::GetFontCache()->FontManager()->legacyMakeTypeface(name.c_str(), syntheticStyle)); ++ syntheticBold = false; ++ syntheticItalic = false; ++ return FontPlatformData((const sk_sp) typeface.release(), "", size, syntheticBold, syntheticItalic, orientation); ++ } + // Maximum axis count is maximum value for the OpenType USHORT, + // which is a 16bit unsigned. + // https://www.microsoft.com/typography/otspec/fvar.htm Variation +diff --git a/third_party/blink/renderer/platform/fonts/skia/font_cache_skia.cc b/third_party/blink/renderer/platform/fonts/skia/font_cache_skia.cc +index f8d43f6c4144f..c91ba06d05f7e 100644 +--- a/third_party/blink/renderer/platform/fonts/skia/font_cache_skia.cc ++++ b/third_party/blink/renderer/platform/fonts/skia/font_cache_skia.cc +@@ -234,8 +234,8 @@ sk_sp FontCache::CreateTypeface( + // the embedder provided font Manager rather than calling + // SkTypeface::CreateFromName which may redirect the call to the default font + // Manager. On Windows the font manager is always present. +- if (font_manager_) { +- auto tf = sk_sp(font_manager_->matchFamilyStyle( ++ if (font_manager_) { ++ auto tf = sk_sp(font_manager_->legacyMakeTypeface( + name.c_str(), font_description.SkiaFontStyle())); + return tf; + } +diff --git a/third_party/blink/renderer/platform/fonts/win/font_fallback_win.cc b/third_party/blink/renderer/platform/fonts/win/font_fallback_win.cc +index 6f90e69c6f2e1..c1bf6d566f5d3 100644 +--- a/third_party/blink/renderer/platform/fonts/win/font_fallback_win.cc ++++ b/third_party/blink/renderer/platform/fonts/win/font_fallback_win.cc +@@ -56,7 +56,7 @@ static inline bool IsFontPresent(const UChar* font_name, + SkFontMgr* font_manager) { + String family = font_name; + sk_sp tf( +- font_manager->matchFamilyStyle(family.Utf8().c_str(), SkFontStyle())); ++ font_manager->legacyMakeTypeface(family.Utf8().c_str(), SkFontStyle())); + if (!tf) + return false; + +diff --git a/ui/gfx/BUILD.gn b/ui/gfx/BUILD.gn +index e688b1c5cd61b..c313f96412728 100644 +--- a/ui/gfx/BUILD.gn ++++ b/ui/gfx/BUILD.gn +@@ -192,6 +192,8 @@ component("gfx") { + "font_render_params_win.cc", + "path_win.cc", + "path_win.h", ++ "platform_font_win.cc", ++ "platform_font_win.h", + "system_fonts_win.cc", + "system_fonts_win.h", + "win/crash_id_helper.cc", +diff --git a/ui/gfx/font_render_params_win.cc b/ui/gfx/font_render_params_win.cc +index f953ab91818a4..8b0f4a2df350a 100644 +--- a/ui/gfx/font_render_params_win.cc ++++ b/ui/gfx/font_render_params_win.cc +@@ -61,13 +61,13 @@ class CachedFontRenderParams { + params_->subpixel_positioning = false; + params_->autohinter = false; + params_->use_bitmaps = false; +- params_->hinting = FontRenderParams::HINTING_MEDIUM; ++ params_->hinting = FontRenderParams::HINTING_FULL; + params_->subpixel_rendering = FontRenderParams::SUBPIXEL_RENDERING_NONE; + + BOOL enabled = false; + if (SystemParametersInfo(SPI_GETFONTSMOOTHING, 0, &enabled, 0) && enabled) { +- params_->antialiasing = true; +- params_->subpixel_positioning = true; ++ params_->antialiasing = true; // Required! ++ params_->subpixel_positioning = false; + + UINT type = 0; + if (SystemParametersInfo(SPI_GETFONTSMOOTHINGTYPE, 0, &type, 0) && +diff --git a/ui/gfx/platform_font_win.cc b/ui/gfx/platform_font_win.cc +new file mode 100644 +index 0000000000000..6d96f09bedd39 +--- /dev/null ++++ b/ui/gfx/platform_font_win.cc +@@ -0,0 +1,586 @@ ++// Copyright (c) 2012 The Chromium Authors. All rights reserved. ++// Use of this source code is governed by a BSD-style license that can be ++// found in the LICENSE file. ++#include "ui/gfx/platform_font_win.h" ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include "base/containers/flat_map.h" ++#include "base/debug/alias.h" ++#include "base/feature_list.h" ++#include "base/logging.h" ++#include "base/no_destructor.h" ++#include "base/stl_util.h" ++#include "base/strings/string16.h" ++#include "base/strings/string_util.h" ++#include "base/strings/sys_string_conversions.h" ++#include "base/strings/utf_string_conversions.h" ++#include "base/trace_event/trace_event.h" ++#include "base/win/scoped_gdi_object.h" ++#include "base/win/scoped_hdc.h" ++#include "base/win/scoped_select_object.h" ++#include "third_party/skia/include/core/SkFontLCDConfig.h" ++#include "third_party/skia/include/core/SkFontMetrics.h" ++#include "third_party/skia/include/core/SkRefCnt.h" ++#include "third_party/skia/include/core/SkTypeface.h" ++#include "ui/gfx/canvas.h" ++#include "ui/gfx/font.h" ++#include "ui/gfx/font_render_params.h" ++#include "ui/gfx/platform_font_skia.h" ++#include "ui/gfx/system_fonts_win.h" ++#include "ui/gfx/win/direct_write.h" ++#include "ui/gfx/win/scoped_set_map_mode.h" ++namespace { ++// Sets style properties on |font_info| based on |font_style|. ++void SetLogFontStyle(int font_style, LOGFONT* font_info) { ++ font_info->lfUnderline = (font_style & gfx::Font::UNDERLINE) != 0; ++ font_info->lfItalic = (font_style & gfx::Font::ITALIC) != 0; ++} ++gfx::Font::Weight ToGfxFontWeight(int weight) { ++ return static_cast(weight); ++} ++// Uses the GDI interop functionality exposed by DirectWrite to find a ++// matching DirectWrite font for the LOGFONT passed in. If we fail to ++// find a direct match then we try the DirectWrite font substitution ++// route to find a match. ++// The contents of the LOGFONT pointer |font_info| may be modified on ++// return. ++/* ++HRESULT FindDirectWriteFontForLOGFONT(IDWriteFactory* factory, ++ LOGFONT* font_info, ++ IDWriteFont** dwrite_font) { ++ TRACE_EVENT0("fonts", "gfx::FindDirectWriteFontForLOGFONT"); ++ Microsoft::WRL::ComPtr gdi_interop; ++ HRESULT hr = factory->GetGdiInterop(gdi_interop.GetAddressOf()); ++ if (FAILED(hr)) { ++ CHECK(false); ++ return hr; ++ } ++ hr = gdi_interop->CreateFontFromLOGFONT(font_info, dwrite_font); ++ if (SUCCEEDED(hr)) ++ return hr; ++ Microsoft::WRL::ComPtr font_collection; ++ hr = factory->GetSystemFontCollection(font_collection.GetAddressOf()); ++ if (FAILED(hr)) ++ return hr; ++ // We try to find a matching font by triggering DirectWrite to substitute the ++ // font passed in with a matching font (FontSubstitutes registry key) ++ // If this succeeds we return the matched font. ++ base::win::ScopedGDIObject font(::CreateFontIndirect(font_info)); ++ base::win::ScopedGetDC screen_dc(NULL); ++ base::win::ScopedSelectObject scoped_font(screen_dc, font.get()); ++ Microsoft::WRL::ComPtr font_face; ++ hr = gdi_interop->CreateFontFaceFromHdc(screen_dc, font_face.GetAddressOf()); ++ if (FAILED(hr)) ++ return hr; ++ LOGFONT converted_font = {0}; ++ hr = gdi_interop->ConvertFontFaceToLOGFONT(font_face.Get(), &converted_font); ++ if (SUCCEEDED(hr)) { ++ hr = font_collection->GetFontFromFontFace(font_face.Get(), dwrite_font); ++ if (SUCCEEDED(hr)) { ++ wcscpy_s(font_info->lfFaceName, base::size(font_info->lfFaceName), ++ converted_font.lfFaceName); ++ } ++ } ++ return hr; ++} ++*/ ++// Returns a matching IDWriteFont for the |font_info| passed in. If we fail ++// to find a matching font, then we return the IDWriteFont corresponding to ++// the default font on the system. ++// Returns S_OK on success. ++// The contents of the LOGFONT pointer |font_info| may be modified on ++// return. ++/* ++HRESULT GetMatchingDirectWriteFont(LOGFONT* font_info, ++ bool italic, ++ IDWriteFactory* factory, ++ IDWriteFont** dwrite_font) { ++ TRACE_EVENT0("fonts", "gfx::GetMatchingDirectWriteFont"); ++ // First try the GDI compat route to get a matching DirectWrite font. ++ // If that succeeds then we are good. If that fails then try and find a ++ // match from the DirectWrite font collection. ++ HRESULT hr = FindDirectWriteFontForLOGFONT(factory, font_info, dwrite_font); ++ if (SUCCEEDED(hr)) ++ return hr; ++ // Get a matching font from the system font collection exposed by ++ // DirectWrite. ++ Microsoft::WRL::ComPtr font_collection; ++ hr = factory->GetSystemFontCollection(font_collection.GetAddressOf()); ++ if (FAILED(hr)) { ++ // On some old windows, the call to GetSystemFontCollection may fail. ++ return hr; ++ } ++ // Steps as below:- ++ // This mirrors skia. ++ // 1. Attempt to find a DirectWrite font family based on the face name in the ++ // font. That may not work at all times, as the face name could be random ++ // GDI has its own font system where in it creates a font matching the ++ // characteristics in the LOGFONT structure passed into ++ // CreateFontIndirect. DirectWrite does not do that. If this succeeds then ++ // return the matching IDWriteFont from the family. ++ // 2. If step 1 fails then repeat with the default system font. This has the ++ // same limitations with the face name as mentioned above. ++ // 3. If step 2 fails then return the first family from the collection and ++ // use that. ++ Microsoft::WRL::ComPtr font_family; ++ BOOL exists = FALSE; ++ uint32_t index = 0; ++ hr = font_collection->FindFamilyName(font_info->lfFaceName, &index, &exists); ++ // If we fail to find a match then try fallback to the default font on the ++ // system. This is what skia does as well. ++ if (FAILED(hr) || (index == UINT_MAX) || !exists) { ++ NONCLIENTMETRICS metrics = {0}; ++ metrics.cbSize = sizeof(metrics); ++ if (!SystemParametersInfoW(SPI_GETNONCLIENTMETRICS, ++ sizeof(metrics), ++ &metrics, ++ 0)) { ++ CHECK(false); ++ return E_FAIL; ++ } ++ if (wcsncmp(font_info->lfFaceName, metrics.lfMessageFont.lfFaceName, ++ base::size(font_info->lfFaceName))) { ++ // First try the GDI compat route to get a matching DirectWrite font. If ++ // that succeeds we are good. If not find a matching font from the font ++ // collection. ++ wcscpy_s(font_info->lfFaceName, base::size(font_info->lfFaceName), ++ metrics.lfMessageFont.lfFaceName); ++ hr = FindDirectWriteFontForLOGFONT(factory, font_info, dwrite_font); ++ if (SUCCEEDED(hr)) ++ return hr; ++ // Best effort to find a matching font from the system font collection. ++ hr = font_collection->FindFamilyName(metrics.lfMessageFont.lfFaceName, ++ &index, ++ &exists); ++ } ++ } ++ if (index != UINT_MAX && exists) { ++ hr = font_collection->GetFontFamily(index, font_family.GetAddressOf()); ++ } else { ++ // If we fail to find a matching font, then fallback to the first font in ++ // the list. This is what skia does as well. ++ hr = font_collection->GetFontFamily(0, font_family.GetAddressOf()); ++ } ++ if (FAILED(hr)) { ++ CHECK(false); ++ return hr; ++ } ++ DWRITE_FONT_WEIGHT weight = ++ static_cast(font_info->lfWeight); ++ DWRITE_FONT_STRETCH stretch = DWRITE_FONT_STRETCH_NORMAL; ++ DWRITE_FONT_STYLE style = ++ (italic) ? DWRITE_FONT_STYLE_ITALIC : DWRITE_FONT_STYLE_NORMAL; ++ // The IDWriteFontFamily::GetFirstMatchingFont call fails on certain machines ++ // for fonts like MS UI Gothic, Segoe UI, etc. It is not clear why these ++ // fonts could be accessible to GDI and not to DirectWrite. ++ // The code below adds some debug fields to help track down these failures. ++ // 1. We get the matching font list for the font attributes passed in. ++ // 2. We get the font count in the family with a debug alias variable. ++ // 3. If GetFirstMatchingFont fails then we CHECK as before. ++ // Next step would be to remove the CHECKs in this function and fallback to ++ // GDI. ++ // http://crbug.com/434425 ++ // TODO(ananta) ++ // Remove the GetMatchingFonts and related code here once we get to a stable ++ // state in canary. ++ Microsoft::WRL::ComPtr matching_font_list; ++ hr = font_family->GetMatchingFonts(weight, stretch, style, ++ matching_font_list.GetAddressOf()); ++ uint32_t matching_font_count = 0; ++ if (SUCCEEDED(hr)) ++ matching_font_count = matching_font_list->GetFontCount(); ++ hr = font_family->GetFirstMatchingFont(weight, stretch, style, dwrite_font); ++ if (FAILED(hr)) { ++ base::debug::Alias(&matching_font_count); ++ CHECK(false); ++ } ++ base::string16 font_name; ++ gfx::GetFamilyNameFromDirectWriteFont(*dwrite_font, &font_name); ++ wcscpy_s(font_info->lfFaceName, base::size(font_info->lfFaceName), ++ font_name.c_str()); ++ return hr; ++} ++*/ ++} // namespace ++namespace gfx { ++// Enable the use of PlatformFontSkia instead of PlatformFontWin. ++const base::Feature kPlatformFontSkiaOnWindows{ ++ "PlatformFontSkiaOnWindows", base::FEATURE_ENABLED_BY_DEFAULT}; ++// static ++PlatformFontWin::HFontRef* PlatformFontWin::base_font_ref_; ++// TODO(ananta) ++// Remove the CHECKs in this function once this stabilizes on the field. ++HRESULT GetFamilyNameFromDirectWriteFont(IDWriteFont* dwrite_font, ++ base::string16* family_name) { ++ Microsoft::WRL::ComPtr font_family; ++ HRESULT hr = dwrite_font->GetFontFamily(font_family.GetAddressOf()); ++ if (FAILED(hr)) ++ CHECK(false); ++ Microsoft::WRL::ComPtr family_names; ++ hr = font_family->GetFamilyNames(family_names.GetAddressOf()); ++ if (FAILED(hr)) ++ CHECK(false); ++ // TODO(ananta) ++ // Add support for retrieving the family for the current locale. ++ wchar_t family_name_for_locale[MAX_PATH] = {0}; ++ hr = family_names->GetString(0, family_name_for_locale, ++ base::size(family_name_for_locale)); ++ if (FAILED(hr)) ++ CHECK(false); ++ *family_name = family_name_for_locale; ++ return hr; ++} ++//////////////////////////////////////////////////////////////////////////////// ++// PlatformFontWin, public ++PlatformFontWin::PlatformFontWin() : font_ref_(GetBaseFontRef()) { ++} ++PlatformFontWin::PlatformFontWin(const std::string& font_name, int font_size) { ++ InitWithFontNameAndSize(font_name, font_size); ++} ++PlatformFontWin::PlatformFontWin(sk_sp typeface, ++ int font_size_pixels, ++ const base::Optional& params) ++ : typeface_(std::move(typeface)) { ++ DCHECK(typeface_); ++ // TODO(http://crbug.com/944227): This is a transitional code path until we ++ // complete migrating to PlatformFontSkia on Windows. Being unable to wrap the ++ // SkTypeface into a PlatformFontSkia and performing a rematching by font ++ // family name instead loses platform font handles encapsulated in SkTypeface, ++ // and in turn leads to instantiating a different font than what was returned ++ // by font fallback, compare https://crbug.com/1003829. ++ SkString family_name; ++ typeface_->getFamilyName(&family_name); ++ InitWithFontNameAndSize(family_name.c_str(), font_size_pixels); ++} ++//////////////////////////////////////////////////////////////////////////////// ++// PlatformFontWin, PlatformFont implementation: ++Font PlatformFontWin::DeriveFont(int size_delta, ++ int style, ++ Font::Weight weight) const { ++ LOGFONT font_info; ++ GetObject(GetNativeFont(), sizeof(LOGFONT), &font_info); ++ const int requested_font_size = font_ref_->requested_font_size(); ++ font_info.lfHeight = win::AdjustFontSize(-requested_font_size, size_delta); ++ font_info.lfWeight = static_cast(weight); ++ SetLogFontStyle(style, &font_info); ++ HFONT hfont = CreateFontIndirect(&font_info); ++ return Font(new PlatformFontWin(CreateHFontRef(hfont))); ++} ++int PlatformFontWin::GetHeight() { ++ return font_ref_->height(); ++} ++Font::Weight PlatformFontWin::GetWeight() const { ++ return font_ref_->weight(); ++} ++int PlatformFontWin::GetBaseline() { ++ return font_ref_->baseline(); ++} ++int PlatformFontWin::GetCapHeight() { ++ return font_ref_->cap_height(); ++} ++int PlatformFontWin::GetExpectedTextWidth(int length) { ++ return length * std::min(font_ref_->GetDluBaseX(), ++ font_ref_->ave_char_width()); ++} ++int PlatformFontWin::GetStyle() const { ++ return font_ref_->style(); ++} ++const std::string& PlatformFontWin::GetFontName() const { ++ return font_ref_->font_name(); ++} ++std::string PlatformFontWin::GetActualFontName() const { ++ // With the current implementation on Windows, HFontRef::font_name() returns ++ // the font name taken from the HFONT handle, but it's not the name that comes ++ // from the font's metadata. See http://crbug.com/327287 ++ return font_ref_->font_name(); ++} ++std::string PlatformFontWin::GetLocalizedFontName() const { ++ base::win::ScopedCreateDC memory_dc(CreateCompatibleDC(NULL)); ++ if (!memory_dc.Get()) ++ return GetFontName(); ++ // When a font has a localized name for a language matching the system ++ // locale, GetTextFace() returns the localized name. ++ base::win::ScopedSelectObject font(memory_dc.Get(), font_ref_->hfont()); ++ wchar_t localized_font_name[LF_FACESIZE]; ++ int length = GetTextFace(memory_dc.Get(), base::size(localized_font_name), ++ &localized_font_name[0]); ++ if (length <= 0) ++ return GetFontName(); ++ return base::SysWideToUTF8(localized_font_name); ++} ++int PlatformFontWin::GetFontSize() const { ++ return font_ref_->font_size(); ++} ++const FontRenderParams& PlatformFontWin::GetFontRenderParams() { ++ static const base::NoDestructor params( ++ gfx::GetFontRenderParams(FontRenderParamsQuery(), nullptr)); ++ return *params; ++} ++sk_sp PlatformFontWin::GetNativeSkTypeface() const { // was GetNativeSkTypefaceIfAvailable() ++ return sk_sp(typeface_); ++} ++NativeFont PlatformFontWin::GetNativeFont() const { ++ return font_ref_->hfont(); ++} ++//////////////////////////////////////////////////////////////////////////////// ++// Font, private: ++void PlatformFontWin::InitWithCopyOfHFONT(HFONT hfont) { ++ DCHECK(hfont); ++ LOGFONT font_info; ++ GetObject(hfont, sizeof(LOGFONT), &font_info); ++ font_ref_ = CreateHFontRef(CreateFontIndirect(&font_info)); ++} ++void PlatformFontWin::InitWithFontNameAndSize(const std::string& font_name, ++ int font_size) { ++ HFONT hf = ::CreateFont(-font_size, 0, 0, 0, FW_DONTCARE, FALSE, FALSE, FALSE, ++ DEFAULT_CHARSET, ++ OUT_DEFAULT_PRECIS, ++ CLIP_DEFAULT_PRECIS, ++ DEFAULT_QUALITY, ++ DEFAULT_PITCH | FF_DONTCARE, ++ base::UTF8ToUTF16(font_name).c_str()); ++ font_ref_ = CreateHFontRef(hf); ++} ++// static ++void PlatformFontWin::GetTextMetricsForFont(HDC hdc, ++ HFONT font, ++ TEXTMETRIC* text_metrics) { ++ base::win::ScopedSelectObject scoped_font(hdc, font); ++ GetTextMetrics(hdc, text_metrics); ++} ++// static ++PlatformFontWin::HFontRef* PlatformFontWin::GetBaseFontRef() { ++ if (base_font_ref_ == nullptr) { ++ // We'll delegate to our SystemFonts instance to give us the default ++ // message font. ++ PlatformFontWin* message_font = static_cast( ++ win::GetSystemFont(win::SystemFont::kMessage).platform_font()); ++ base_font_ref_ = message_font->font_ref_.get(); ++ } ++ return base_font_ref_; ++} ++PlatformFontWin::HFontRef* PlatformFontWin::CreateHFontRef(HFONT font) { ++ TRACE_EVENT0("fonts", "PlatformFont::CreateHFontRef"); ++ TEXTMETRIC font_metrics; ++ { ++ base::win::ScopedGetDC screen_dc(NULL); ++ ScopedSetMapMode mode(screen_dc, MM_TEXT); ++ GetTextMetricsForFont(screen_dc, font, &font_metrics); ++ } ++ return CreateHFontRefFromSkia(font, font_metrics); ++} ++PlatformFontWin::HFontRef* PlatformFontWin::CreateHFontRefFromGDI( ++ HFONT font, ++ const TEXTMETRIC& font_metrics) { ++ TRACE_EVENT0("fonts", "PlatformFontWin::CreateHFontRefFromGDI"); ++ const int height = std::max(1, font_metrics.tmHeight); ++ const int baseline = std::max(1, font_metrics.tmAscent); ++ const int cap_height = ++ std::max(1, font_metrics.tmAscent - font_metrics.tmInternalLeading); ++ const int ave_char_width = std::max(1, font_metrics.tmAveCharWidth); ++ const int font_size = ++ std::max(1, font_metrics.tmHeight - font_metrics.tmInternalLeading); ++ int style = 0; ++ if (font_metrics.tmItalic) ++ style |= Font::ITALIC; ++ if (font_metrics.tmUnderlined) ++ style |= Font::UNDERLINE; ++ return new HFontRef(font, font_size, height, baseline, cap_height, ++ ave_char_width, ToGfxFontWeight(font_metrics.tmWeight), ++ style); ++} ++// static ++PlatformFontWin::HFontRef* PlatformFontWin::CreateHFontRefFromSkia( ++ HFONT gdi_font, ++ const TEXTMETRIC& font_metrics) { ++ TRACE_EVENT0("fonts", "PlatformFontWin::CreateHFontRefFromSkia"); ++ LOGFONT font_info = {0}; ++ GetObject(gdi_font, sizeof(LOGFONT), &font_info); ++ // If the font height is passed in as 0, assume the height to be -1 to ensure ++ // that we return the metrics for a 1 point font. ++ // If the font height is positive it represents the rasterized font's cell ++ // height. Calculate the actual height accordingly. ++ if (font_info.lfHeight > 0) { ++ font_info.lfHeight = ++ font_metrics.tmInternalLeading - font_metrics.tmHeight; ++ } else if (font_info.lfHeight == 0) { ++ font_info.lfHeight = -1; ++ } ++ if (font_info.lfWeight == 0) { ++ font_info.lfWeight = static_cast(Font::Weight::NORMAL); ++ } ++ // const bool italic = font_info.lfItalic != 0; ++ // Skia does not return all values we need for font metrics. For e.g. ++ // the cap height which indicates the height of capital letters is not ++ // returned even though it is returned by DirectWrite. ++ // TODO(ananta) ++ // Fix SkScalerContext_win_dw.cpp to return all metrics we need from ++ // DirectWrite and remove the code here which retrieves metrics from ++ // DirectWrite to calculate the cap height. ++ return CreateHFontRefFromGDI(gdi_font, font_metrics); ++/* ++ Microsoft::WRL::ComPtr dwrite_font; ++ HRESULT hr = GetMatchingDirectWriteFont( ++ &font_info, italic, win::GetDirectWriteFactory(), &dwrite_font); ++ if (FAILED(hr)) { ++ // If we are not able to find a font using Direct Write, fallback to ++ // the old GDI font. ++ return CreateHFontRefFromGDI(gdi_font, font_metrics); ++ } ++ DWRITE_FONT_METRICS dwrite_font_metrics = {0}; ++ dwrite_font->GetMetrics(&dwrite_font_metrics); ++ SkFontStyle skia_font_style(font_info.lfWeight, SkFontStyle::kNormal_Width, ++ font_info.lfItalic ? SkFontStyle::kItalic_Slant ++ : SkFontStyle::kUpright_Slant); ++ sk_sp skia_face( ++ SkTypeface::MakeFromName( ++ base::SysWideToUTF8(font_info.lfFaceName).c_str(), ++ skia_font_style)); ++ FontRenderParams font_params = ++ gfx::GetFontRenderParams(FontRenderParamsQuery(), nullptr); ++ SkFontLCDConfig::SetSubpixelOrder( ++ FontRenderParams::SubpixelRenderingToSkiaLCDOrder( ++ font_params.subpixel_rendering)); ++ SkFontLCDConfig::SetSubpixelOrientation( ++ FontRenderParams::SubpixelRenderingToSkiaLCDOrientation( ++ font_params.subpixel_rendering)); ++ SkFont font(std::move(skia_face), -font_info.lfHeight); ++ font.setEdging(font_params.antialiasing ? SkFont::Edging::kAntiAlias ++ : SkFont::Edging::kAlias); ++ SkFontMetrics skia_metrics; ++ font.getMetrics(&skia_metrics); ++ // The calculations below are similar to those in the CreateHFontRef ++ // function. The height, baseline and cap height are rounded up to ensure ++ // that they match up closely with GDI. ++ const int height = std::ceil(skia_metrics.fDescent - skia_metrics.fAscent); ++ const int baseline = std::max(1, std::ceil(-skia_metrics.fAscent)); ++ const int cap_height = std::ceil( ++ font.getSize() * static_cast(dwrite_font_metrics.capHeight) / ++ dwrite_font_metrics.designUnitsPerEm); ++ // The metrics retrieved from skia don't have the average character width. In ++ // any case if we get the average character width from skia then use that or ++ // the average character width in the TEXTMETRIC structure. ++ // TODO(ananta): Investigate whether it is possible to retrieve this value ++ // from DirectWrite. ++ const int ave_char_width = ++ skia_metrics.fAvgCharWidth == 0 ? font_metrics.tmAveCharWidth ++ : skia_metrics.fAvgCharWidth; ++ int style = 0; ++ if (italic) ++ style |= Font::ITALIC; ++ if (font_info.lfUnderline) ++ style |= Font::UNDERLINE; ++ // DirectWrite may have substituted the GDI font name with a fallback ++ // font. Ensure that it is updated here. ++ DeleteObject(gdi_font); ++ gdi_font = ::CreateFontIndirect(&font_info); ++ return new HFontRef(gdi_font, -font_info.lfHeight, height, baseline, ++ cap_height, ave_char_width, ++ ToGfxFontWeight(font_info.lfWeight), style); ++ */ ++} ++// static ++Font PlatformFontWin::HFontToFont(HFONT hfont) { ++ return Font(new PlatformFontWin(CreateHFontRef(hfont))); ++} ++PlatformFontWin::PlatformFontWin(HFontRef* hfont_ref) : font_ref_(hfont_ref) { ++} ++PlatformFontWin::PlatformFontWin(NativeFont native_font) { ++ InitWithCopyOfHFONT(native_font); ++} ++PlatformFontWin::~PlatformFontWin() { ++} ++//////////////////////////////////////////////////////////////////////////////// ++// PlatformFontWin::HFontRef: ++PlatformFontWin::HFontRef::HFontRef(HFONT hfont, ++ int font_size, ++ int height, ++ int baseline, ++ int cap_height, ++ int ave_char_width, ++ Font::Weight weight, ++ int style) ++ : hfont_(hfont), ++ font_size_(font_size), ++ height_(height), ++ baseline_(baseline), ++ cap_height_(cap_height), ++ ave_char_width_(ave_char_width), ++ weight_(weight), ++ style_(style), ++ dlu_base_x_(-1), ++ requested_font_size_(font_size) { ++ DLOG_ASSERT(hfont); ++ LOGFONT font_info; ++ GetObject(hfont_, sizeof(LOGFONT), &font_info); ++ font_name_ = base::UTF16ToUTF8(base::string16(font_info.lfFaceName)); ++ // Retrieve the font size from the GetTextMetrics API instead of referencing ++ // it from the LOGFONT structure. This is because the height as reported by ++ // the LOGFONT structure is not always correct. For small fonts with size 1 ++ // the LOGFONT structure reports the height as -1, while the actual font size ++ // is different. (2 on my XP machine). ++ base::win::ScopedGetDC screen_dc(NULL); ++ TEXTMETRIC font_metrics = {0}; ++ PlatformFontWin::GetTextMetricsForFont(screen_dc, hfont_, &font_metrics); ++ requested_font_size_ = font_metrics.tmHeight - font_metrics.tmInternalLeading; ++} ++int PlatformFontWin::HFontRef::GetDluBaseX() { ++ if (dlu_base_x_ != -1) ++ return dlu_base_x_; ++ dlu_base_x_ = GetAverageCharWidthInDialogUnits(hfont_); ++ return dlu_base_x_; ++} ++// static ++int PlatformFontWin::HFontRef::GetAverageCharWidthInDialogUnits( ++ HFONT gdi_font) { ++ base::win::ScopedGetDC screen_dc(NULL); ++ base::win::ScopedSelectObject font(screen_dc, gdi_font); ++ ScopedSetMapMode mode(screen_dc, MM_TEXT); ++ // Yes, this is how Microsoft recommends calculating the dialog unit ++ // conversions. See: http://support.microsoft.com/kb/125681 ++ SIZE ave_text_size; ++ GetTextExtentPoint32(screen_dc, ++ L"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz", ++ 52, &ave_text_size); ++ int dlu_base_x = (ave_text_size.cx / 26 + 1) / 2; ++ DCHECK_NE(dlu_base_x, -1); ++ return dlu_base_x; ++} ++PlatformFontWin::HFontRef::~HFontRef() { ++ DeleteObject(hfont_); ++} ++//////////////////////////////////////////////////////////////////////////////// ++// PlatformFont, public: ++// static ++PlatformFont* PlatformFont::CreateDefault() { ++// if (base::FeatureList::IsEnabled(kPlatformFontSkiaOnWindows)) // turned off ++ // return new PlatformFontSkia; ++ return new PlatformFontWin; ++} ++// static ++PlatformFont* PlatformFont::CreateFromNameAndSize(const std::string& font_name, ++ int font_size) { ++ TRACE_EVENT0("fonts", "PlatformFont::CreateFromNameAndSize"); ++ // if (base::FeatureList::IsEnabled(kPlatformFontSkiaOnWindows)) // turned off ++ // return new PlatformFontSkia(font_name, font_size); ++ return new PlatformFontWin(font_name, font_size); ++} ++// static ++PlatformFont* PlatformFont::CreateFromSkTypeface( ++ sk_sp typeface, ++ int font_size, ++ const base::Optional& params) { ++ TRACE_EVENT0("fonts", "PlatformFont::CreateFromSkTypeface"); ++ // if (base::FeatureList::IsEnabled(kPlatformFontSkiaOnWindows)) // turned off ++ // return new PlatformFontSkia(typeface, font_size, params); ++ return new PlatformFontWin(typeface, font_size, params); ++} ++ ++} // namespace gfx +\ No newline at end of file +diff --git a/ui/gfx/platform_font_win.h b/ui/gfx/platform_font_win.h +new file mode 100644 +index 0000000000000..279828e1e0edf +--- /dev/null ++++ b/ui/gfx/platform_font_win.h +@@ -0,0 +1,177 @@ ++// Copyright (c) 2012 The Chromium Authors. All rights reserved. ++// Use of this source code is governed by a BSD-style license that can be ++// found in the LICENSE file. ++#ifndef UI_GFX_PLATFORM_FONT_WIN_H_ ++#define UI_GFX_PLATFORM_FONT_WIN_H_ ++#include ++#include ++#include "base/compiler_specific.h" ++#include "base/feature_list.h" ++#include "base/gtest_prod_util.h" ++#include "base/macros.h" ++#include "base/memory/ref_counted.h" ++#include "third_party/skia/include/core/SkTypeface.h" ++#include "ui/gfx/gfx_export.h" ++#include "ui/gfx/platform_font.h" ++struct IDWriteFactory; ++struct IDWriteFont; ++namespace gfx { ++// Deprecation of PlatformFontWin (See http://crbug.com/944227). ++extern GFX_EXPORT const base::Feature kPlatformFontSkiaOnWindows; ++class GFX_EXPORT PlatformFontWin : public PlatformFont { ++ public: ++ PlatformFontWin(); ++ PlatformFontWin(const std::string& font_name, int font_size); ++ // Wraps the provided SkTypeface without triggering a font rematch. ++ PlatformFontWin(sk_sp typeface, ++ int font_size_pixels, ++ const base::Optional& params); ++ // Dialog units to pixels conversion. ++ // See http://support.microsoft.com/kb/145994 for details. ++ int horizontal_dlus_to_pixels(int dlus) const { ++ return dlus * font_ref_->GetDluBaseX() / 4; ++ } ++ int vertical_dlus_to_pixels(int dlus) const { ++ return dlus * font_ref_->height() / 8; ++ } ++ // Returns the font name for the system locale. Some fonts, particularly ++ // East Asian fonts, have different names per locale. If the localized font ++ // name could not be retrieved, returns GetFontName(). ++ std::string GetLocalizedFontName() const; ++ // Overridden from PlatformFont: ++ Font DeriveFont(int size_delta, ++ int style, ++ Font::Weight weight) const override; ++ int GetHeight() override; ++ Font::Weight GetWeight() const override; ++ int GetBaseline() override; ++ int GetCapHeight() override; ++ int GetExpectedTextWidth(int length) override; ++ int GetStyle() const override; ++ const std::string& GetFontName() const override; ++ std::string GetActualFontName() const override; ++ int GetFontSize() const override; ++ const FontRenderParams& GetFontRenderParams() override; ++ sk_sp GetNativeSkTypeface() const override; // was GetNativeSkTypefaceIfAvailable() ++ NativeFont GetNativeFont() const; ++ // Called once during initialization if we should be retrieving font metrics ++ // from skia and DirectWrite. ++ static void SetDirectWriteFactory(IDWriteFactory* factory); ++ private: ++ FRIEND_TEST_ALL_PREFIXES(PlatformFontWinTest, Metrics_SkiaVersusGDI); ++ FRIEND_TEST_ALL_PREFIXES(PlatformFontWinTest, DirectWriteFontSubstitution); ++ explicit PlatformFontWin(NativeFont native_font); ++ ~PlatformFontWin() override; ++ // Chrome text drawing bottoms out in the Windows GDI functions that take an ++ // HFONT (an opaque handle into Windows). To avoid lots of GDI object ++ // allocation and destruction, Font indirectly refers to the HFONT by way of ++ // an HFontRef. That is, every Font has an HFontRef, which has an HFONT. ++ // ++ // HFontRef is reference counted. Upon deletion, it deletes the HFONT. ++ // By making HFontRef maintain the reference to the HFONT, multiple ++ // HFontRefs can share the same HFONT, and Font can provide value semantics. ++ class GFX_EXPORT HFontRef : public base::RefCounted { ++ public: ++ // This constructor takes control of the HFONT, and will delete it when ++ // the HFontRef is deleted. ++ HFontRef(HFONT hfont, ++ int font_size, ++ int height, ++ int baseline, ++ int cap_height, ++ int ave_char_width, ++ Font::Weight weight, ++ int style); ++ // Accessors ++ HFONT hfont() const { return hfont_; } ++ int height() const { return height_; } ++ int baseline() const { return baseline_; } ++ int cap_height() const { return cap_height_; } ++ int ave_char_width() const { return ave_char_width_; } ++ Font::Weight weight() const { return weight_; } ++ int style() const { return style_; } ++ const std::string& font_name() const { return font_name_; } ++ int font_size() const { return font_size_; } ++ int requested_font_size() const { return requested_font_size_; } ++ // Returns the average character width in dialog units. ++ int GetDluBaseX(); ++ // Helper to return the average character width using the text extent ++ // technique mentioned here. http://support.microsoft.com/kb/125681. ++ static int GetAverageCharWidthInDialogUnits(HFONT gdi_font); ++ private: ++ friend class base::RefCounted; ++ FRIEND_TEST_ALL_PREFIXES(PlatformFontWinTest, Metrics_SkiaVersusGDI); ++ FRIEND_TEST_ALL_PREFIXES(PlatformFontWinTest, DirectWriteFontSubstitution); ++ ~HFontRef(); ++ const HFONT hfont_; ++ const int font_size_; ++ const int height_; ++ const int baseline_; ++ const int cap_height_; ++ const int ave_char_width_; ++ const Font::Weight weight_; ++ const int style_; ++ // Average character width in dialog units. This is queried lazily from the ++ // system, with an initial value of -1 meaning it hasn't yet been queried. ++ int dlu_base_x_; ++ std::string font_name_; ++ // If the requested font size is not possible for the font, |font_size_| ++ // will be different than |requested_font_size_|. This is stored separately ++ // so that code that increases the font size in a loop will not cause the ++ // loop to get stuck on the same size. ++ int requested_font_size_; ++ DISALLOW_COPY_AND_ASSIGN(HFontRef); ++ }; ++ // Initializes this object with a copy of the specified HFONT. ++ void InitWithCopyOfHFONT(HFONT hfont); ++ // Initializes this object with the specified font name and size. ++ void InitWithFontNameAndSize(const std::string& font_name, ++ int font_size); ++ // Returns the GDI metrics for the font passed in. ++ static void GetTextMetricsForFont(HDC hdc, ++ HFONT font, ++ TEXTMETRIC* text_metrics); ++ // Returns the base font ref. This should ONLY be invoked on the ++ // UI thread. ++ static HFontRef* GetBaseFontRef(); ++ // Creates and returns a new HFontRef from the specified HFONT. ++ static HFontRef* CreateHFontRef(HFONT font); ++ // Creates and returns a new HFontRef from the specified HFONT. Uses provided ++ // |font_metrics| instead of calculating new one. ++ static HFontRef* CreateHFontRefFromGDI(HFONT font, ++ const TEXTMETRIC& font_metrics); ++ // Creates and returns a new HFontRef from the specified HFONT using metrics ++ // from skia. Currently this is only used if we use DirectWrite for font ++ // metrics. ++ // |gdi_font| : Handle to the GDI font created via CreateFontIndirect. ++ // |font_metrics| : The GDI font metrics retrieved via the GetTextMetrics ++ // API. This is currently used to calculate the correct height of the font ++ // in case we get a font created with a positive height. ++ // A positive height represents the cell height (ascent + descent). ++ // A negative height represents the character Em height which is cell ++ // height minus the internal leading value. ++ static PlatformFontWin::HFontRef* CreateHFontRefFromSkia( ++ HFONT gdi_font, ++ const TEXTMETRIC& font_metrics); ++ // Takes control of a native font (e.g. from CreateFontIndirect()) and wraps ++ // it in a Font object to manage its lifespan. Note that |hfont| may not be ++ // valid after the call; use the returned Font object instead. ++ static Font HFontToFont(HFONT hfont); ++ // Creates a new PlatformFontWin with the specified HFontRef. Used when ++ // constructing a Font from a HFONT we don't want to copy. ++ explicit PlatformFontWin(HFontRef* hfont_ref); ++ // Reference to the base font all fonts are derived from. ++ static HFontRef* base_font_ref_; ++ // Indirect reference to the HFontRef, which references the underlying HFONT. ++ scoped_refptr font_ref_; ++ // An optional typeface when the font is constructed from a typeface. ++ sk_sp typeface_; ++ DISALLOW_COPY_AND_ASSIGN(PlatformFontWin); ++}; ++// Returns the family name for the |IDWriteFont| interface passed in. ++// The family name is returned in the |family_name| parameter. ++// Returns S_OK on success. ++HRESULT GetFamilyNameFromDirectWriteFont(IDWriteFont* dwrite_font, ++ base::string16* family_name); ++} // namespace gfx ++#endif // UI_GFX_PLATFORM_FONT_WIN_H_ +\ No newline at end of file +diff --git a/ui/gfx/render_text_harfbuzz.cc b/ui/gfx/render_text_harfbuzz.cc +index 16b6f85909c72..1f421960a466e 100644 +--- a/ui/gfx/render_text_harfbuzz.cc ++++ b/ui/gfx/render_text_harfbuzz.cc +@@ -2096,7 +2096,9 @@ void RenderTextHarfBuzz::ShapeRuns( + // could be a raster font like System, which would not give us a reasonable + // fallback font list. + Font segoe("Segoe UI", 13); +- if (!FontWasAlreadyTried(segoe.platform_font()->GetNativeSkTypeface(), ++ if (//fallback_fonts_already_tried.size() > 0 && ++ segoe.platform_font()->GetNativeSkTypeface() != NULL && ++ !FontWasAlreadyTried(segoe.platform_font()->GetNativeSkTypeface(), + &fallback_fonts_already_tried)) { + std::vector default_fallback_families = GetFallbackFonts(segoe); + fallback_font_list.insert(fallback_font_list.end(), +diff --git a/ui/gfx/win/direct_write.cc b/ui/gfx/win/direct_write.cc +index 4f531c9f3627a..02aa14f8d052c 100644 +--- a/ui/gfx/win/direct_write.cc ++++ b/ui/gfx/win/direct_write.cc +@@ -18,93 +18,19 @@ + + namespace gfx { + namespace win { +- +-namespace { +- +-// Pointer to the global IDWriteFactory interface. +-IDWriteFactory* g_direct_write_factory = nullptr; +- +-void SetDirectWriteFactory(IDWriteFactory* factory) { +- DCHECK(!g_direct_write_factory); +- // We grab a reference on the DirectWrite factory. This reference is +- // leaked, which is ok because skia leaks it as well. +- factory->AddRef(); +- g_direct_write_factory = factory; +-} +- +-} // anonymous namespace +- +-void CreateDWriteFactory(IDWriteFactory** factory) { +- Microsoft::WRL::ComPtr factory_unknown; +- HRESULT hr = +- DWriteCreateFactory(DWRITE_FACTORY_TYPE_SHARED, __uuidof(IDWriteFactory), +- &factory_unknown); +- if (FAILED(hr)) { +- base::debug::Alias(&hr); +- CHECK(false); +- return; +- } +- factory_unknown.CopyTo(factory); ++void CreateDWriteFactory(IDWriteFactory** factory) { + } + + void InitializeDirectWrite() { +- static bool tried_dwrite_initialize = false; +- DCHECK(!tried_dwrite_initialize); +- tried_dwrite_initialize = true; +- +- TRACE_EVENT0("fonts", "gfx::InitializeDirectWrite"); +- +- Microsoft::WRL::ComPtr factory; +- CreateDWriteFactory(&factory); +- CHECK(!!factory); +- SetDirectWriteFactory(factory.Get()); +- +- // The skia call to create a new DirectWrite font manager instance can fail +- // if we are unable to get the system font collection from the DirectWrite +- // factory. The GetSystemFontCollection method in the IDWriteFactory +- // interface fails with E_INVALIDARG on certain Windows 7 gold versions +- // (6.1.7600.*). +- sk_sp direct_write_font_mgr = +- SkFontMgr_New_DirectWrite(factory.Get()); +- int iteration = 0; +- if (!direct_write_font_mgr && +- base::win::GetVersion() == base::win::Version::WIN7) { +- // Windows (win7_rtm) may fail to map the service sections +- // (crbug.com/956064). +- constexpr int kMaxRetries = 5; +- constexpr base::TimeDelta kRetrySleepTime = +- base::TimeDelta::FromMicroseconds(500); +- while (iteration < kMaxRetries) { +- base::PlatformThread::Sleep(kRetrySleepTime); +- direct_write_font_mgr = SkFontMgr_New_DirectWrite(factory.Get()); +- if (direct_write_font_mgr) +- break; +- ++iteration; +- } +- } +- if (!direct_write_font_mgr) +- iteration = -1; +- base::UmaHistogramSparse("DirectWrite.Fonts.Gfx.InitializeLoopCount", +- iteration); +- // TODO(crbug.com/956064): Move to a CHECK when the cause of the crash is +- // fixed and remove the if statement that fallback to GDI font manager. +- DCHECK(!!direct_write_font_mgr); +- if (!direct_write_font_mgr) +- direct_write_font_mgr = SkFontMgr_New_GDI(); +- + // Override the default skia font manager. This must be called before any + // use of the skia font manager is done (e.g. before any call to + // SkFontMgr::RefDefault()). ++ sk_sp direct_write_font_mgr = SkFontMgr_New_GDI(); + skia::OverrideDefaultSkFontMgr(std::move(direct_write_font_mgr)); + } + + IDWriteFactory* GetDirectWriteFactory() { +- // Some unittests may access this accessor without any previous call to +- // |InitializeDirectWrite|. A call to |InitializeDirectWrite| after this +- // function being called is still invalid. +- if (!g_direct_write_factory) +- InitializeDirectWrite(); +- return g_direct_write_factory; ++ return 0; + } + + base::Optional RetrieveLocalizedString(