Support web test font sideloading for FontDataManager
Web tests depend on Ahem being available as a system font. To achieve this, the DWriteFontProxy sideloads Ahem in its internal collection. This doesn't provide Ahem to the browser process' underlying font manager, which makes it so FontDataManager can't see Ahem in web tests. This CL sideloads the font in the browser's dwrite font manager, which is used by the FontDataManager. This allows web tests that depend on Ahem to pass when using FontDataManager. Bug: None Change-Id: Id56da6ac99070a4ac7f65436b86e68cd5c6de320 Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/6250577 Reviewed-by: Etienne Bergeron <etienneb@chromium.org> Commit-Queue: Anthony Vallée-Dubois <anthonyvd@chromium.org> Reviewed-by: Mike West <mkwst@chromium.org> Cr-Commit-Position: refs/heads/main@{#1418296}
This commit is contained in:

committed by
Chromium LUCI CQ

parent
24940bf77b
commit
6764bd04f4
content/web_test/browser
ui/gfx/win
@ -40,6 +40,7 @@ void SetupFonts() {
|
||||
base_path.Append(FILE_PATH_LITERAL("/test_fonts/Ahem.ttf"));
|
||||
|
||||
DWriteFontProxyImpl::SideLoadFontForTesting(font_path);
|
||||
gfx::win::SideLoadFontForTesting(font_path);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
@ -4,6 +4,10 @@
|
||||
|
||||
#include "ui/gfx/win/direct_write.h"
|
||||
|
||||
#include <dwrite.h>
|
||||
#include <dwrite_2.h>
|
||||
#include <dwrite_3.h>
|
||||
#include <wrl.h>
|
||||
#include <wrl/client.h>
|
||||
|
||||
#include <string>
|
||||
@ -26,6 +30,83 @@ namespace {
|
||||
// Pointer to the global IDWriteFactory interface.
|
||||
IDWriteFactory* g_direct_write_factory = nullptr;
|
||||
|
||||
// Used in tests to allow a known font to masquerade as a locally installed
|
||||
// font. Usually this is the Ahem.ttf font. Leaked at shutdown.
|
||||
std::vector<base::FilePath>* g_sideloaded_fonts = nullptr;
|
||||
|
||||
bool GetFontCollection(Microsoft::WRL::ComPtr<IDWriteFactory>& factory,
|
||||
IDWriteFontCollection** collection) {
|
||||
if (!g_sideloaded_fonts) {
|
||||
// Normal path - The DirectWrite font manager will use the system's font
|
||||
// collection with no sideloading when passed `nullptr` for the collection.
|
||||
return false;
|
||||
}
|
||||
|
||||
// QueryInterface for IDWriteFactory2. This should succeed since we only
|
||||
// support >= Win10.
|
||||
Microsoft::WRL::ComPtr<IDWriteFactory2> factory2;
|
||||
factory.As<IDWriteFactory2>(&factory2);
|
||||
DCHECK(factory2);
|
||||
|
||||
// QueryInterface for IDwriteFactory3, needed for MatchUniqueFont on Windows.
|
||||
// This should succeed since we only support >= Win10.
|
||||
Microsoft::WRL::ComPtr<IDWriteFactory3> factory3;
|
||||
factory2.As<IDWriteFactory3>(&factory3);
|
||||
DCHECK(factory3);
|
||||
|
||||
// If sideloading - build a font set with sideloads then add the system font
|
||||
// collection.
|
||||
Microsoft::WRL::ComPtr<IDWriteFontSetBuilder> font_set_builder;
|
||||
HRESULT hr = factory3->CreateFontSetBuilder(&font_set_builder);
|
||||
DCHECK(SUCCEEDED(hr));
|
||||
|
||||
for (auto& path : *g_sideloaded_fonts) {
|
||||
Microsoft::WRL::ComPtr<IDWriteFontFile> font_file;
|
||||
hr = factory3->CreateFontFileReference(path.value().c_str(), nullptr,
|
||||
&font_file);
|
||||
DCHECK(SUCCEEDED(hr));
|
||||
|
||||
BOOL supported;
|
||||
DWRITE_FONT_FILE_TYPE file_type;
|
||||
UINT32 n_fonts;
|
||||
hr = font_file->Analyze(&supported, &file_type, nullptr, &n_fonts);
|
||||
DCHECK(SUCCEEDED(hr));
|
||||
|
||||
for (UINT32 font_index = 0; font_index < n_fonts; ++font_index) {
|
||||
Microsoft::WRL::ComPtr<IDWriteFontFaceReference> font_face;
|
||||
hr = factory3->CreateFontFaceReference(font_file.Get(), font_index,
|
||||
DWRITE_FONT_SIMULATIONS_NONE,
|
||||
&font_face);
|
||||
DCHECK(SUCCEEDED(hr));
|
||||
|
||||
hr = font_set_builder->AddFontFaceReference(font_face.Get());
|
||||
DCHECK(SUCCEEDED(hr));
|
||||
}
|
||||
}
|
||||
// Now add the system fonts.
|
||||
Microsoft::WRL::ComPtr<IDWriteFontSet> system_font_set;
|
||||
hr = factory3->GetSystemFontSet(&system_font_set);
|
||||
DCHECK(SUCCEEDED(hr));
|
||||
|
||||
hr = font_set_builder->AddFontSet(system_font_set.Get());
|
||||
DCHECK(SUCCEEDED(hr));
|
||||
|
||||
// Make the set.
|
||||
Microsoft::WRL::ComPtr<IDWriteFontSet> font_set;
|
||||
hr = font_set_builder->CreateFontSet(&font_set);
|
||||
DCHECK(SUCCEEDED(hr));
|
||||
|
||||
// Make the collection.
|
||||
Microsoft::WRL::ComPtr<IDWriteFontCollection1> collection1;
|
||||
hr = factory3->CreateFontCollectionFromFontSet(font_set.Get(), &collection1);
|
||||
DCHECK(SUCCEEDED(hr));
|
||||
|
||||
hr = collection1->QueryInterface(collection);
|
||||
DCHECK(SUCCEEDED(hr));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void SetDirectWriteFactory(IDWriteFactory* factory) {
|
||||
DCHECK(!g_direct_write_factory);
|
||||
// We grab a reference on the DirectWrite factory. This reference is
|
||||
@ -36,6 +117,14 @@ void SetDirectWriteFactory(IDWriteFactory* factory) {
|
||||
|
||||
} // anonymous namespace
|
||||
|
||||
void SideLoadFontForTesting(base::FilePath path) {
|
||||
if (!g_sideloaded_fonts) {
|
||||
// Note: this list is leaked.
|
||||
g_sideloaded_fonts = new std::vector<base::FilePath>();
|
||||
}
|
||||
g_sideloaded_fonts->push_back(path);
|
||||
}
|
||||
|
||||
void CreateDWriteFactory(IDWriteFactory** factory) {
|
||||
Microsoft::WRL::ComPtr<IUnknown> factory_unknown;
|
||||
HRESULT hr =
|
||||
@ -60,8 +149,19 @@ void InitializeDirectWrite() {
|
||||
CHECK(!!factory);
|
||||
SetDirectWriteFactory(factory.Get());
|
||||
|
||||
sk_sp<SkFontMgr> direct_write_font_mgr =
|
||||
SkFontMgr_New_DirectWrite(factory.Get());
|
||||
// Get a font collection that contains sideloaded fonts for web tests, or
|
||||
// nullptr to tell the DirectWrite FontMgr to use the system font collection.
|
||||
// SkFontMgr_DirectWrite increments this object's ref count.
|
||||
Microsoft::WRL::ComPtr<IDWriteFontCollection> collection;
|
||||
bool should_use_collection = GetFontCollection(factory, &collection);
|
||||
if (g_sideloaded_fonts) {
|
||||
DCHECK(should_use_collection);
|
||||
} else {
|
||||
DCHECK(!should_use_collection);
|
||||
}
|
||||
|
||||
sk_sp<SkFontMgr> direct_write_font_mgr = SkFontMgr_New_DirectWrite(
|
||||
factory.Get(), should_use_collection ? collection.Get() : nullptr);
|
||||
CHECK(!!direct_write_font_mgr);
|
||||
|
||||
// Override the default skia font manager. This must be called before any
|
||||
|
@ -11,10 +11,13 @@
|
||||
#include <string_view>
|
||||
|
||||
#include "base/component_export.h"
|
||||
#include "base/files/file_path.h"
|
||||
|
||||
namespace gfx {
|
||||
namespace win {
|
||||
|
||||
COMPONENT_EXPORT(GFX) void SideLoadFontForTesting(base::FilePath path);
|
||||
|
||||
COMPONENT_EXPORT(GFX) void InitializeDirectWrite();
|
||||
|
||||
// Creates a DirectWrite factory.
|
||||
|
Reference in New Issue
Block a user