Implement direct write fallback proxy
This change implements an IDWriteFontFallback that uses IPC to talk to the browser process and obtain font fallback data. This is part 2 of a three part change. 1: https://codereview.chromium.org/1878843002/ Adds support for specifying a font fallback in skia 2: https://codereview.chromium.org/1846433005/ Implements the fallback proxy in Chromium 3: https://codereview.chromium.org/1883483002/ Adds code to blink to call skia's fallback API BUG=459056 Review URL: https://codereview.chromium.org/1846433005 Cr-Commit-Position: refs/heads/master@{#388262}
This commit is contained in:
content
browser
renderer_host
child
dwrite_font_proxy
common
content_child.gypicontent_common.gypicontent_tests.gypitest
@ -20,6 +20,7 @@
|
||||
#include "base/strings/string_util.h"
|
||||
#include "base/strings/utf_string_conversions.h"
|
||||
#include "content/common/dwrite_font_proxy_messages.h"
|
||||
#include "content/common/dwrite_text_analysis_source_win.h"
|
||||
#include "ipc/ipc_message_macros.h"
|
||||
#include "ui/gfx/win/direct_write.h"
|
||||
|
||||
@ -90,6 +91,7 @@ bool DWriteFontProxyMessageFilter::OnMessageReceived(
|
||||
IPC_MESSAGE_HANDLER(DWriteFontProxyMsg_GetFamilyCount, OnGetFamilyCount)
|
||||
IPC_MESSAGE_HANDLER(DWriteFontProxyMsg_GetFamilyNames, OnGetFamilyNames)
|
||||
IPC_MESSAGE_HANDLER(DWriteFontProxyMsg_GetFontFiles, OnGetFontFiles)
|
||||
IPC_MESSAGE_HANDLER(DWriteFontProxyMsg_MapCharacters, OnMapCharacters)
|
||||
IPC_MESSAGE_UNHANDLED(handled = false)
|
||||
IPC_END_MESSAGE_MAP()
|
||||
return handled;
|
||||
@ -142,13 +144,13 @@ void DWriteFontProxyMessageFilter::OnGetFamilyNames(
|
||||
|
||||
mswr::ComPtr<IDWriteFontFamily> family;
|
||||
HRESULT hr = collection_->GetFontFamily(family_index, &family);
|
||||
if (!SUCCEEDED(hr)) {
|
||||
if (FAILED(hr)) {
|
||||
return;
|
||||
}
|
||||
|
||||
mswr::ComPtr<IDWriteLocalizedStrings> localized_names;
|
||||
hr = family->GetFamilyNames(&localized_names);
|
||||
if (!SUCCEEDED(hr)) {
|
||||
if (FAILED(hr)) {
|
||||
return;
|
||||
}
|
||||
|
||||
@ -159,26 +161,26 @@ void DWriteFontProxyMessageFilter::OnGetFamilyNames(
|
||||
for (size_t index = 0; index < string_count; ++index) {
|
||||
UINT32 length = 0;
|
||||
hr = localized_names->GetLocaleNameLength(index, &length);
|
||||
if (!SUCCEEDED(hr)) {
|
||||
if (FAILED(hr)) {
|
||||
return;
|
||||
}
|
||||
++length; // Reserve space for the null terminator.
|
||||
locale.resize(length);
|
||||
hr = localized_names->GetLocaleName(index, locale.data(), length);
|
||||
if (!SUCCEEDED(hr)) {
|
||||
if (FAILED(hr)) {
|
||||
return;
|
||||
}
|
||||
CHECK_EQ(L'\0', locale[length - 1]);
|
||||
|
||||
length = 0;
|
||||
hr = localized_names->GetStringLength(index, &length);
|
||||
if (!SUCCEEDED(hr)) {
|
||||
if (FAILED(hr)) {
|
||||
return;
|
||||
}
|
||||
++length; // Reserve space for the null terminator.
|
||||
name.resize(length);
|
||||
hr = localized_names->GetString(index, name.data(), length);
|
||||
if (!SUCCEEDED(hr)) {
|
||||
if (FAILED(hr)) {
|
||||
return;
|
||||
}
|
||||
CHECK_EQ(L'\0', name[length - 1]);
|
||||
@ -200,7 +202,7 @@ void DWriteFontProxyMessageFilter::OnGetFontFiles(
|
||||
|
||||
mswr::ComPtr<IDWriteFontFamily> family;
|
||||
HRESULT hr = collection_->GetFontFamily(family_index, &family);
|
||||
if (!SUCCEEDED(hr)) {
|
||||
if (FAILED(hr)) {
|
||||
return;
|
||||
}
|
||||
|
||||
@ -213,7 +215,7 @@ void DWriteFontProxyMessageFilter::OnGetFontFiles(
|
||||
for (UINT32 font_index = 0; font_index < font_count; ++font_index) {
|
||||
mswr::ComPtr<IDWriteFont> font;
|
||||
hr = family->GetFont(font_index, &font);
|
||||
if (!SUCCEEDED(hr)) {
|
||||
if (FAILED(hr)) {
|
||||
return;
|
||||
}
|
||||
|
||||
@ -223,6 +225,105 @@ void DWriteFontProxyMessageFilter::OnGetFontFiles(
|
||||
file_paths->assign(path_set.begin(), path_set.end());
|
||||
}
|
||||
|
||||
void DWriteFontProxyMessageFilter::OnMapCharacters(
|
||||
const base::string16& text,
|
||||
const DWriteFontStyle& font_style,
|
||||
const base::string16& locale_name,
|
||||
uint32_t reading_direction,
|
||||
const base::string16& base_family_name,
|
||||
MapCharactersResult* result) {
|
||||
InitializeDirectWrite();
|
||||
result->family_index = UINT32_MAX;
|
||||
result->mapped_length = text.length();
|
||||
result->family_name.clear();
|
||||
result->scale = 0.0;
|
||||
result->font_style.font_slant = DWRITE_FONT_STYLE_NORMAL;
|
||||
result->font_style.font_stretch = DWRITE_FONT_STRETCH_NORMAL;
|
||||
result->font_style.font_weight = DWRITE_FONT_WEIGHT_NORMAL;
|
||||
if (factory2_ == nullptr || collection_ == nullptr)
|
||||
return;
|
||||
if (font_fallback_ == nullptr) {
|
||||
if (FAILED(factory2_->GetSystemFontFallback(&font_fallback_)))
|
||||
return;
|
||||
}
|
||||
|
||||
UINT32 length;
|
||||
mswr::ComPtr<IDWriteFont> mapped_font;
|
||||
|
||||
mswr::ComPtr<IDWriteNumberSubstitution> number_substitution;
|
||||
if (FAILED(factory2_->CreateNumberSubstitution(
|
||||
DWRITE_NUMBER_SUBSTITUTION_METHOD_NONE, locale_name.c_str(),
|
||||
TRUE /* ignoreUserOverride */, &number_substitution))) {
|
||||
DCHECK(false);
|
||||
return;
|
||||
}
|
||||
mswr::ComPtr<IDWriteTextAnalysisSource> analysis_source;
|
||||
if (FAILED(mswr::MakeAndInitialize<TextAnalysisSource>(
|
||||
&analysis_source, text, locale_name, number_substitution.Get(),
|
||||
static_cast<DWRITE_READING_DIRECTION>(reading_direction)))) {
|
||||
DCHECK(false);
|
||||
return;
|
||||
}
|
||||
|
||||
if (FAILED(font_fallback_->MapCharacters(
|
||||
analysis_source.Get(), 0, text.length(), collection_.Get(),
|
||||
base_family_name.c_str(),
|
||||
static_cast<DWRITE_FONT_WEIGHT>(font_style.font_weight),
|
||||
static_cast<DWRITE_FONT_STYLE>(font_style.font_slant),
|
||||
static_cast<DWRITE_FONT_STRETCH>(font_style.font_stretch), &length,
|
||||
&mapped_font, &result->scale))) {
|
||||
DCHECK(false);
|
||||
return;
|
||||
}
|
||||
|
||||
result->mapped_length = length;
|
||||
if (mapped_font == nullptr)
|
||||
return;
|
||||
|
||||
mswr::ComPtr<IDWriteFontFamily> mapped_family;
|
||||
if (FAILED(mapped_font->GetFontFamily(&mapped_family))) {
|
||||
DCHECK(false);
|
||||
return;
|
||||
}
|
||||
mswr::ComPtr<IDWriteLocalizedStrings> family_names;
|
||||
if (FAILED(mapped_family->GetFamilyNames(&family_names))) {
|
||||
DCHECK(false);
|
||||
return;
|
||||
}
|
||||
|
||||
result->font_style.font_slant = mapped_font->GetStyle();
|
||||
result->font_style.font_stretch = mapped_font->GetStretch();
|
||||
result->font_style.font_weight = mapped_font->GetWeight();
|
||||
|
||||
std::vector<base::char16> name;
|
||||
size_t name_count = family_names->GetCount();
|
||||
for (size_t name_index = 0; name_index < name_count; name_index++) {
|
||||
UINT32 name_length = 0;
|
||||
if (FAILED(family_names->GetStringLength(name_index, &name_length)))
|
||||
continue; // Keep trying other names
|
||||
|
||||
++name_length; // Reserve space for the null terminator.
|
||||
name.resize(name_length);
|
||||
if (FAILED(family_names->GetString(name_index, name.data(), name_length)))
|
||||
continue;
|
||||
UINT32 index = UINT32_MAX;
|
||||
BOOL exists = false;
|
||||
if (FAILED(collection_->FindFamilyName(name.data(), &index, &exists)) ||
|
||||
!exists)
|
||||
continue;
|
||||
|
||||
// Found a matching family!
|
||||
result->family_index = index;
|
||||
result->family_name = name.data();
|
||||
return;
|
||||
}
|
||||
// Could not find a matching family
|
||||
// TODO(kulshin): log UMA that we matched a font, but could not locate the
|
||||
// family
|
||||
DCHECK_EQ(result->family_index, UINT32_MAX);
|
||||
DCHECK_GT(result->mapped_length, 0u);
|
||||
}
|
||||
|
||||
void DWriteFontProxyMessageFilter::InitializeDirectWrite() {
|
||||
DCHECK_CURRENTLY_ON(BrowserThread::FILE);
|
||||
if (direct_write_initialized_)
|
||||
@ -237,6 +338,10 @@ void DWriteFontProxyMessageFilter::InitializeDirectWrite() {
|
||||
return;
|
||||
}
|
||||
|
||||
// QueryInterface for IDWriteFactory2. It's ok for this to fail if we are
|
||||
// running an older version of DirectWrite (earlier than Win8.1).
|
||||
factory.As<IDWriteFactory2>(&factory2_);
|
||||
|
||||
HRESULT hr = factory->GetSystemFontCollection(&collection_);
|
||||
DCHECK(SUCCEEDED(hr));
|
||||
}
|
||||
@ -247,13 +352,13 @@ bool DWriteFontProxyMessageFilter::AddFilesForFont(
|
||||
mswr::ComPtr<IDWriteFontFace> font_face;
|
||||
HRESULT hr;
|
||||
hr = font->CreateFontFace(&font_face);
|
||||
if (!SUCCEEDED(hr)) {
|
||||
if (FAILED(hr)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
UINT32 file_count;
|
||||
hr = font_face->GetFiles(&file_count, nullptr);
|
||||
if (!SUCCEEDED(hr)) {
|
||||
if (FAILED(hr)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -261,14 +366,14 @@ bool DWriteFontProxyMessageFilter::AddFilesForFont(
|
||||
font_files.resize(file_count);
|
||||
hr = font_face->GetFiles(
|
||||
&file_count, reinterpret_cast<IDWriteFontFile**>(font_files.data()));
|
||||
if (!SUCCEEDED(hr)) {
|
||||
if (FAILED(hr)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
for (unsigned int file_index = 0; file_index < file_count; ++file_index) {
|
||||
mswr::ComPtr<IDWriteFontFileLoader> loader;
|
||||
hr = font_files[file_index]->GetLoader(&loader);
|
||||
if (!SUCCEEDED(hr)) {
|
||||
if (FAILED(hr)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -289,7 +394,7 @@ bool DWriteFontProxyMessageFilter::AddFilesForFont(
|
||||
DCHECK(false);
|
||||
|
||||
return false;
|
||||
} else if (!SUCCEEDED(hr)) {
|
||||
} else if (FAILED(hr)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -309,13 +414,13 @@ bool DWriteFontProxyMessageFilter::AddLocalFile(
|
||||
const void* key;
|
||||
UINT32 key_size;
|
||||
hr = font_file->GetReferenceKey(&key, &key_size);
|
||||
if (!SUCCEEDED(hr)) {
|
||||
if (FAILED(hr)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
UINT32 path_length = 0;
|
||||
hr = local_loader->GetFilePathLengthFromKey(key, key_size, &path_length);
|
||||
if (!SUCCEEDED(hr)) {
|
||||
if (FAILED(hr)) {
|
||||
return false;
|
||||
}
|
||||
++path_length; // Reserve space for the null terminator.
|
||||
@ -323,7 +428,7 @@ bool DWriteFontProxyMessageFilter::AddLocalFile(
|
||||
file_path_chars.resize(path_length);
|
||||
hr = local_loader->GetFilePathFromKey(key, key_size, file_path_chars.data(),
|
||||
path_length);
|
||||
if (!SUCCEEDED(hr)) {
|
||||
if (FAILED(hr)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -6,6 +6,7 @@
|
||||
#define CONTENT_BROWSER_RENDERER_HOST_DWRITE_FONT_PROXY_MESSAGE_FILTER_WIN_H_
|
||||
|
||||
#include <dwrite.h>
|
||||
#include <dwrite_2.h>
|
||||
#include <wrl.h>
|
||||
#include <set>
|
||||
#include <utility>
|
||||
@ -18,6 +19,9 @@
|
||||
#include "content/public/browser/browser_message_filter.h"
|
||||
#include "content/public/browser/browser_thread.h"
|
||||
|
||||
struct DWriteFontStyle;
|
||||
struct MapCharactersResult;
|
||||
|
||||
namespace content {
|
||||
|
||||
// Implements a message filter that handles the dwrite font proxy messages.
|
||||
@ -43,6 +47,12 @@ class CONTENT_EXPORT DWriteFontProxyMessageFilter
|
||||
std::vector<std::pair<base::string16, base::string16>>* family_names);
|
||||
void OnGetFontFiles(UINT32 family_index,
|
||||
std::vector<base::string16>* file_paths);
|
||||
void OnMapCharacters(const base::string16& text,
|
||||
const DWriteFontStyle& font_style,
|
||||
const base::string16& locale_name,
|
||||
uint32_t reading_direction,
|
||||
const base::string16& base_family_name,
|
||||
MapCharactersResult* result);
|
||||
|
||||
void InitializeDirectWrite();
|
||||
|
||||
@ -55,6 +65,8 @@ class CONTENT_EXPORT DWriteFontProxyMessageFilter
|
||||
private:
|
||||
bool direct_write_initialized_ = false;
|
||||
Microsoft::WRL::ComPtr<IDWriteFontCollection> collection_;
|
||||
Microsoft::WRL::ComPtr<IDWriteFactory2> factory2_;
|
||||
Microsoft::WRL::ComPtr<IDWriteFontFallback> font_fallback_;
|
||||
base::string16 windows_fonts_path_;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(DWriteFontProxyMessageFilter);
|
||||
|
@ -5,11 +5,13 @@
|
||||
#include "content/browser/renderer_host/dwrite_font_proxy_message_filter_win.h"
|
||||
|
||||
#include <dwrite.h>
|
||||
#include <dwrite_2.h>
|
||||
|
||||
#include "base/memory/ref_counted.h"
|
||||
#include "base/run_loop.h"
|
||||
#include "base/test/test_simple_task_runner.h"
|
||||
#include "base/thread_task_runner_handle.h"
|
||||
#include "base/win/windows_version.h"
|
||||
#include "content/common/dwrite_font_proxy_messages.h"
|
||||
#include "content/public/test/test_browser_thread_bundle.h"
|
||||
#include "ipc/ipc_message_macros.h"
|
||||
@ -56,6 +58,19 @@ class DWriteFontProxyMessageFilterUnitTest : public testing::Test {
|
||||
serializer->SerializeOutputParameters(*(filter_->GetReply()));
|
||||
}
|
||||
|
||||
bool IsDWrite2Available() {
|
||||
mswr::ComPtr<IDWriteFactory> factory;
|
||||
gfx::win::CreateDWriteFactory(&factory);
|
||||
mswr::ComPtr<IDWriteFactory2> factory2;
|
||||
factory.As<IDWriteFactory2>(&factory2);
|
||||
|
||||
if (!factory2.Get()) {
|
||||
// IDWriteFactory2 is expected to not be available before Win8.1
|
||||
EXPECT_LT(base::win::GetVersion(), base::win::VERSION_WIN8_1);
|
||||
}
|
||||
return factory2.Get();
|
||||
}
|
||||
|
||||
scoped_refptr<FilterWithFakeSender> filter_;
|
||||
content::TestBrowserThreadBundle thread_bundle_;
|
||||
};
|
||||
@ -140,6 +155,71 @@ TEST_F(DWriteFontProxyMessageFilterUnitTest, GetFontFilesIndexOutOfBounds) {
|
||||
EXPECT_EQ(0u, files.size());
|
||||
}
|
||||
|
||||
TEST_F(DWriteFontProxyMessageFilterUnitTest, MapCharacter) {
|
||||
if (!gfx::win::ShouldUseDirectWrite() || !IsDWrite2Available())
|
||||
return;
|
||||
|
||||
DWriteFontStyle font_style;
|
||||
font_style.font_weight = DWRITE_FONT_WEIGHT_NORMAL;
|
||||
font_style.font_slant = DWRITE_FONT_STYLE_NORMAL;
|
||||
font_style.font_stretch = DWRITE_FONT_STRETCH_NORMAL;
|
||||
|
||||
MapCharactersResult result;
|
||||
Send(new DWriteFontProxyMsg_MapCharacters(
|
||||
L"abc", font_style, L"", DWRITE_READING_DIRECTION_LEFT_TO_RIGHT, L"",
|
||||
&result));
|
||||
|
||||
EXPECT_NE(UINT32_MAX, result.family_index);
|
||||
EXPECT_STRNE(L"", result.family_name.c_str());
|
||||
EXPECT_EQ(3u, result.mapped_length);
|
||||
EXPECT_NE(0.0, result.scale);
|
||||
EXPECT_NE(0, result.font_style.font_weight);
|
||||
EXPECT_EQ(DWRITE_FONT_STYLE_NORMAL, result.font_style.font_slant);
|
||||
EXPECT_NE(0, result.font_style.font_stretch);
|
||||
}
|
||||
|
||||
TEST_F(DWriteFontProxyMessageFilterUnitTest, MapCharacterInvalidCharacter) {
|
||||
if (!gfx::win::ShouldUseDirectWrite() || !IsDWrite2Available())
|
||||
return;
|
||||
|
||||
DWriteFontStyle font_style;
|
||||
font_style.font_weight = DWRITE_FONT_WEIGHT_NORMAL;
|
||||
font_style.font_slant = DWRITE_FONT_STYLE_NORMAL;
|
||||
font_style.font_stretch = DWRITE_FONT_STRETCH_NORMAL;
|
||||
|
||||
MapCharactersResult result;
|
||||
Send(new DWriteFontProxyMsg_MapCharacters(
|
||||
L"\ufffe\uffffabc", font_style, L"en-us",
|
||||
DWRITE_READING_DIRECTION_LEFT_TO_RIGHT, L"", &result));
|
||||
|
||||
EXPECT_EQ(UINT32_MAX, result.family_index);
|
||||
EXPECT_STREQ(L"", result.family_name.c_str());
|
||||
EXPECT_EQ(2u, result.mapped_length);
|
||||
}
|
||||
|
||||
TEST_F(DWriteFontProxyMessageFilterUnitTest, MapCharacterInvalidAfterValid) {
|
||||
if (!gfx::win::ShouldUseDirectWrite() || !IsDWrite2Available())
|
||||
return;
|
||||
|
||||
DWriteFontStyle font_style;
|
||||
font_style.font_weight = DWRITE_FONT_WEIGHT_NORMAL;
|
||||
font_style.font_slant = DWRITE_FONT_STYLE_NORMAL;
|
||||
font_style.font_stretch = DWRITE_FONT_STRETCH_NORMAL;
|
||||
|
||||
MapCharactersResult result;
|
||||
Send(new DWriteFontProxyMsg_MapCharacters(
|
||||
L"abc\ufffe\uffff", font_style, L"en-us",
|
||||
DWRITE_READING_DIRECTION_LEFT_TO_RIGHT, L"", &result));
|
||||
|
||||
EXPECT_NE(UINT32_MAX, result.family_index);
|
||||
EXPECT_STRNE(L"", result.family_name.c_str());
|
||||
EXPECT_EQ(3u, result.mapped_length);
|
||||
EXPECT_NE(0.0, result.scale);
|
||||
EXPECT_NE(0, result.font_style.font_weight);
|
||||
EXPECT_EQ(DWRITE_FONT_STYLE_NORMAL, result.font_style.font_slant);
|
||||
EXPECT_NE(0, result.font_style.font_stretch);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
} // namespace content
|
||||
|
@ -12,6 +12,7 @@
|
||||
#include "base/win/iat_patch_function.h"
|
||||
#include "base/win/windows_version.h"
|
||||
#include "content/child/dwrite_font_proxy/dwrite_font_proxy_win.h"
|
||||
#include "content/child/dwrite_font_proxy/font_fallback_win.h"
|
||||
#include "content/child/font_warmup_win.h"
|
||||
#include "skia/ext/fontmgr_default_win.h"
|
||||
#include "third_party/WebKit/public/web/win/WebFontRendering.h"
|
||||
@ -71,8 +72,15 @@ void InitializeDWriteFontProxy() {
|
||||
&g_font_collection, factory.Get(), g_sender_override);
|
||||
}
|
||||
|
||||
sk_sp<SkFontMgr> skia_font_manager(
|
||||
SkFontMgr_New_DirectWrite(factory.Get(), g_font_collection.Get()));
|
||||
mswr::ComPtr<IDWriteFontFallback> font_fallback;
|
||||
mswr::ComPtr<IDWriteFactory2> factory2;
|
||||
if (SUCCEEDED(factory.As(&factory2)) && factory2.Get()) {
|
||||
mswr::MakeAndInitialize<FontFallback>(
|
||||
&font_fallback, g_font_collection.Get(), g_sender_override);
|
||||
}
|
||||
|
||||
sk_sp<SkFontMgr> skia_font_manager(SkFontMgr_New_DirectWrite(
|
||||
factory.Get(), g_font_collection.Get(), font_fallback.Get()));
|
||||
blink::WebFontRendering::setSkiaFontManager(skia_font_manager.get());
|
||||
|
||||
// Add an extra ref for SetDefaultSkiaFactory, which keeps a ref but doesn't
|
||||
|
@ -245,6 +245,22 @@ bool DWriteFontCollectionProxy::LoadFamily(
|
||||
return SUCCEEDED(hr);
|
||||
}
|
||||
|
||||
bool DWriteFontCollectionProxy::GetFontFamily(UINT32 family_index,
|
||||
const base::string16& family_name,
|
||||
IDWriteFontFamily** font_family) {
|
||||
DCHECK(font_family);
|
||||
DCHECK(!family_name.empty());
|
||||
if (!CreateFamily(family_index))
|
||||
return false;
|
||||
|
||||
mswr::ComPtr<DWriteFontFamilyProxy>& family = families_[family_index];
|
||||
if (!family->IsLoaded() || family->GetName().empty())
|
||||
family->SetName(family_name);
|
||||
|
||||
family.CopyTo(font_family);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool DWriteFontCollectionProxy::LoadFamilyNames(
|
||||
UINT32 family_index,
|
||||
IDWriteLocalizedStrings** localized_strings) {
|
||||
@ -404,6 +420,10 @@ void DWriteFontFamilyProxy::SetName(const base::string16& family_name) {
|
||||
family_name_.assign(family_name);
|
||||
}
|
||||
|
||||
const base::string16& DWriteFontFamilyProxy::GetName() {
|
||||
return family_name_;
|
||||
}
|
||||
|
||||
bool DWriteFontFamilyProxy::IsLoaded() {
|
||||
return family_ != nullptr;
|
||||
}
|
||||
|
@ -71,6 +71,12 @@ class CONTENT_EXPORT DWriteFontCollectionProxy
|
||||
bool LoadFamily(UINT32 family_index,
|
||||
IDWriteFontCollection** containing_collection);
|
||||
|
||||
// Gets the family at the specified index with the expected name. This can be
|
||||
// used to avoid an IPC call when both the index and family name are known.
|
||||
bool GetFontFamily(UINT32 family_index,
|
||||
const base::string16& family_name,
|
||||
IDWriteFontFamily** font_family);
|
||||
|
||||
bool LoadFamilyNames(UINT32 family_index, IDWriteLocalizedStrings** strings);
|
||||
|
||||
bool CreateFamily(UINT32 family_index);
|
||||
@ -124,6 +130,8 @@ class CONTENT_EXPORT DWriteFontFamilyProxy
|
||||
|
||||
void SetName(const base::string16& family_name);
|
||||
|
||||
const base::string16& GetName();
|
||||
|
||||
bool IsLoaded();
|
||||
|
||||
protected:
|
||||
|
108
content/child/dwrite_font_proxy/font_fallback_win.cc
Normal file
108
content/child/dwrite_font_proxy/font_fallback_win.cc
Normal file
@ -0,0 +1,108 @@
|
||||
// Copyright 2016 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 "content/child/dwrite_font_proxy/font_fallback_win.h"
|
||||
|
||||
#include "base/strings/string16.h"
|
||||
|
||||
#include "content/child/dwrite_font_proxy/dwrite_font_proxy_win.h"
|
||||
#include "content/common/dwrite_font_proxy_messages.h"
|
||||
#include "content/public/child/child_thread.h"
|
||||
#include "ipc/ipc_sender.h"
|
||||
|
||||
namespace mswr = Microsoft::WRL;
|
||||
|
||||
namespace content {
|
||||
|
||||
FontFallback::FontFallback() = default;
|
||||
FontFallback::~FontFallback() = default;
|
||||
|
||||
HRESULT FontFallback::MapCharacters(IDWriteTextAnalysisSource* source,
|
||||
UINT32 text_position,
|
||||
UINT32 text_length,
|
||||
IDWriteFontCollection* base_font_collection,
|
||||
const wchar_t* base_family_name,
|
||||
DWRITE_FONT_WEIGHT base_weight,
|
||||
DWRITE_FONT_STYLE base_style,
|
||||
DWRITE_FONT_STRETCH base_stretch,
|
||||
UINT32* mapped_length,
|
||||
IDWriteFont** mapped_font,
|
||||
FLOAT* scale) {
|
||||
*mapped_font = nullptr;
|
||||
*mapped_length = 1;
|
||||
*scale = 1.0;
|
||||
|
||||
const WCHAR* text = nullptr;
|
||||
UINT32 chunk_length = 0;
|
||||
if (FAILED(source->GetTextAtPosition(text_position, &text, &chunk_length))) {
|
||||
DCHECK(false);
|
||||
return E_FAIL;
|
||||
}
|
||||
base::string16 text_chunk(text, chunk_length);
|
||||
|
||||
const WCHAR* locale = nullptr;
|
||||
// |locale_text_length| is actually the length of text with the locale, not
|
||||
// the length of the locale string itself.
|
||||
UINT32 locale_text_length = 0;
|
||||
source->GetLocaleName(text_position /*textPosition*/, &locale_text_length,
|
||||
&locale);
|
||||
|
||||
if (locale == nullptr)
|
||||
locale = L"";
|
||||
|
||||
DWriteFontStyle style;
|
||||
style.font_weight = base_weight;
|
||||
style.font_slant = base_style;
|
||||
style.font_stretch = base_stretch;
|
||||
|
||||
MapCharactersResult result;
|
||||
|
||||
IPC::Sender* sender =
|
||||
sender_override_ ? sender_override_ : ChildThread::Get();
|
||||
if (!sender->Send(new DWriteFontProxyMsg_MapCharacters(
|
||||
text_chunk, style, locale, source->GetParagraphReadingDirection(),
|
||||
base_family_name ? base_family_name : L"", &result)))
|
||||
return E_FAIL;
|
||||
|
||||
*mapped_length = result.mapped_length;
|
||||
*scale = result.scale;
|
||||
|
||||
if (result.family_index == UINT32_MAX)
|
||||
return S_OK;
|
||||
|
||||
mswr::ComPtr<IDWriteFontFamily> family;
|
||||
// It would be nice to find a way to determine at runtime if |collection_| is
|
||||
// a proxy collection, or just a generic IDWriteFontCollection. Unfortunately
|
||||
// I can't find a way to get QueryInterface to return the actual class when
|
||||
// using mswr::RuntimeClass. If we could use QI, we can fallback on
|
||||
// FindFontFamily if the proxy is not available.
|
||||
if (!collection_->GetFontFamily(result.family_index, result.family_name,
|
||||
&family)) {
|
||||
DCHECK(false);
|
||||
return E_FAIL;
|
||||
}
|
||||
|
||||
if (FAILED(family->GetFirstMatchingFont(
|
||||
static_cast<DWRITE_FONT_WEIGHT>(result.font_style.font_weight),
|
||||
static_cast<DWRITE_FONT_STRETCH>(result.font_style.font_stretch),
|
||||
static_cast<DWRITE_FONT_STYLE>(result.font_style.font_slant),
|
||||
mapped_font))) {
|
||||
DCHECK(false);
|
||||
return E_FAIL;
|
||||
}
|
||||
|
||||
DCHECK(*mapped_font);
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT STDMETHODCALLTYPE
|
||||
FontFallback::RuntimeClassInitialize(DWriteFontCollectionProxy* collection,
|
||||
IPC::Sender* sender_override) {
|
||||
sender_override_ = sender_override;
|
||||
collection_ = collection;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
} // namespace content
|
56
content/child/dwrite_font_proxy/font_fallback_win.h
Normal file
56
content/child/dwrite_font_proxy/font_fallback_win.h
Normal file
@ -0,0 +1,56 @@
|
||||
// Copyright 2016 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 CONTENT_CHILD_DWRITE_FONT_PROXY_FONT_FALLBACK_WIN_H_
|
||||
#define CONTENT_CHILD_DWRITE_FONT_PROXY_FONT_FALLBACK_WIN_H_
|
||||
|
||||
#include <dwrite.h>
|
||||
#include <dwrite_2.h>
|
||||
#include <wrl.h>
|
||||
|
||||
#include "content/child/dwrite_font_proxy/dwrite_font_proxy_win.h"
|
||||
#include "content/common/content_export.h"
|
||||
#include "ipc/ipc_sender.h"
|
||||
|
||||
namespace content {
|
||||
|
||||
// Implements an IDWriteFontFallback that uses IPC to proxy the fallback calls
|
||||
// to the system fallback in the browser process.
|
||||
class CONTENT_EXPORT FontFallback
|
||||
: public Microsoft::WRL::RuntimeClass<
|
||||
Microsoft::WRL::RuntimeClassFlags<Microsoft::WRL::ClassicCom>,
|
||||
IDWriteFontFallback> {
|
||||
public:
|
||||
FontFallback();
|
||||
|
||||
HRESULT STDMETHODCALLTYPE
|
||||
MapCharacters(IDWriteTextAnalysisSource* source,
|
||||
UINT32 text_position,
|
||||
UINT32 text_length,
|
||||
IDWriteFontCollection* base_font_collection,
|
||||
const wchar_t* base_family_name,
|
||||
DWRITE_FONT_WEIGHT base_weight,
|
||||
DWRITE_FONT_STYLE base_style,
|
||||
DWRITE_FONT_STRETCH base_stretch,
|
||||
UINT32* mapped_length,
|
||||
IDWriteFont** mapped_font,
|
||||
FLOAT* scale) override;
|
||||
|
||||
HRESULT STDMETHODCALLTYPE
|
||||
RuntimeClassInitialize(DWriteFontCollectionProxy* collection,
|
||||
IPC::Sender* sender_override);
|
||||
|
||||
protected:
|
||||
~FontFallback() override;
|
||||
|
||||
private:
|
||||
IPC::Sender* sender_override_;
|
||||
Microsoft::WRL::ComPtr<DWriteFontCollectionProxy> collection_;
|
||||
|
||||
DISALLOW_ASSIGN(FontFallback);
|
||||
};
|
||||
|
||||
} // namespace content
|
||||
|
||||
#endif // CONTENT_CHILD_DWRITE_FONT_PROXY_FONT_FALLBACK_WIN_H_
|
@ -0,0 +1,95 @@
|
||||
// Copyright 2016 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 "content/child/dwrite_font_proxy/font_fallback_win.h"
|
||||
|
||||
#include <dwrite.h>
|
||||
#include <shlobj.h>
|
||||
#include <wrl.h>
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include "base/memory/ref_counted.h"
|
||||
#include "content/child/dwrite_font_proxy/dwrite_font_proxy_win.h"
|
||||
#include "content/common/dwrite_text_analysis_source_win.h"
|
||||
#include "content/test/dwrite_font_fake_sender_win.h"
|
||||
#include "testing/gtest/include/gtest/gtest.h"
|
||||
|
||||
namespace mswr = Microsoft::WRL;
|
||||
|
||||
namespace content {
|
||||
|
||||
namespace {
|
||||
|
||||
class FontFallbackUnitTest : public testing::Test {
|
||||
public:
|
||||
FontFallbackUnitTest() {
|
||||
CreateDWriteFactory(&factory_);
|
||||
|
||||
factory_->CreateNumberSubstitution(DWRITE_NUMBER_SUBSTITUTION_METHOD_NONE,
|
||||
L"en-us", true /* ignoreUserOverride */,
|
||||
&number_substitution_);
|
||||
|
||||
std::vector<base::char16> font_path;
|
||||
font_path.resize(MAX_PATH);
|
||||
SHGetSpecialFolderPath(nullptr /* hwndOwner - reserved */, font_path.data(),
|
||||
CSIDL_FONTS, FALSE /* fCreate*/);
|
||||
base::string16 arial_path;
|
||||
arial_path.append(font_path.data()).append(L"\\arial.ttf");
|
||||
|
||||
fake_collection_ = new FakeFontCollection();
|
||||
fake_collection_->AddFont(L"Arial")
|
||||
.AddFamilyName(L"en-us", L"Arial")
|
||||
.AddFilePath(arial_path);
|
||||
|
||||
mswr::MakeAndInitialize<DWriteFontCollectionProxy>(
|
||||
&collection_, factory_.Get(), fake_collection_->GetSender());
|
||||
}
|
||||
|
||||
void CreateDWriteFactory(IUnknown** factory) {
|
||||
using DWriteCreateFactoryProc = decltype(DWriteCreateFactory)*;
|
||||
HMODULE dwrite_dll = LoadLibraryW(L"dwrite.dll");
|
||||
if (!dwrite_dll)
|
||||
return;
|
||||
|
||||
DWriteCreateFactoryProc dwrite_create_factory_proc =
|
||||
reinterpret_cast<DWriteCreateFactoryProc>(
|
||||
GetProcAddress(dwrite_dll, "DWriteCreateFactory"));
|
||||
if (!dwrite_create_factory_proc)
|
||||
return;
|
||||
|
||||
dwrite_create_factory_proc(DWRITE_FACTORY_TYPE_SHARED,
|
||||
__uuidof(IDWriteFactory), factory);
|
||||
}
|
||||
|
||||
scoped_refptr<FakeFontCollection> fake_collection_;
|
||||
mswr::ComPtr<IDWriteFactory> factory_;
|
||||
mswr::ComPtr<DWriteFontCollectionProxy> collection_;
|
||||
mswr::ComPtr<IDWriteNumberSubstitution> number_substitution_;
|
||||
};
|
||||
|
||||
TEST_F(FontFallbackUnitTest, MapCharacters) {
|
||||
mswr::ComPtr<FontFallback> fallback;
|
||||
mswr::MakeAndInitialize<FontFallback>(&fallback, collection_.Get(),
|
||||
fake_collection_->GetTrackingSender());
|
||||
|
||||
mswr::ComPtr<IDWriteFont> font;
|
||||
UINT32 mapped_length = 0;
|
||||
float scale = 0.0;
|
||||
|
||||
mswr::ComPtr<TextAnalysisSource> text;
|
||||
mswr::MakeAndInitialize<TextAnalysisSource>(
|
||||
&text, L"hello", L"en-us", number_substitution_.Get(),
|
||||
DWRITE_READING_DIRECTION_LEFT_TO_RIGHT);
|
||||
fallback->MapCharacters(text.Get(), 0, 1, nullptr, nullptr,
|
||||
DWRITE_FONT_WEIGHT_NORMAL, DWRITE_FONT_STYLE_NORMAL,
|
||||
DWRITE_FONT_STRETCH_NORMAL, &mapped_length, &font,
|
||||
&scale);
|
||||
|
||||
EXPECT_EQ(1u, mapped_length); // The fake sender only maps one character
|
||||
EXPECT_NE(nullptr, font.Get());
|
||||
}
|
||||
|
||||
} // namespace
|
||||
} // namespace content
|
@ -23,6 +23,20 @@ typedef std::pair<base::string16, base::string16> DWriteStringPair;
|
||||
|
||||
#endif // CONTENT_COMMON_DWRITE_FONT_PROXY_MESSAGES_H_
|
||||
|
||||
IPC_STRUCT_BEGIN(DWriteFontStyle)
|
||||
IPC_STRUCT_MEMBER(uint16_t, font_weight)
|
||||
IPC_STRUCT_MEMBER(uint8_t, font_slant)
|
||||
IPC_STRUCT_MEMBER(uint8_t, font_stretch)
|
||||
IPC_STRUCT_END()
|
||||
|
||||
IPC_STRUCT_BEGIN(MapCharactersResult)
|
||||
IPC_STRUCT_MEMBER(uint32_t, family_index)
|
||||
IPC_STRUCT_MEMBER(base::string16, family_name)
|
||||
IPC_STRUCT_MEMBER(uint32_t, mapped_length)
|
||||
IPC_STRUCT_MEMBER(float, scale)
|
||||
IPC_STRUCT_MEMBER(DWriteFontStyle, font_style)
|
||||
IPC_STRUCT_END()
|
||||
|
||||
// Locates the index of the specified font family within the system collection.
|
||||
IPC_SYNC_MESSAGE_CONTROL1_1(DWriteFontProxyMsg_FindFamily,
|
||||
base::string16 /* family_name */,
|
||||
@ -44,3 +58,18 @@ IPC_SYNC_MESSAGE_CONTROL1_1(
|
||||
IPC_SYNC_MESSAGE_CONTROL1_1(DWriteFontProxyMsg_GetFontFiles,
|
||||
uint32_t /* family_index */,
|
||||
std::vector<base::string16> /* out file_paths */)
|
||||
|
||||
// Locates a font family that is able to render the specified text using the
|
||||
// specified style. If successful, the family_index and family_name will
|
||||
// indicate which family in the system font collection can render the requested
|
||||
// text and the mapped_length will indicate how many characters can be
|
||||
// rendered. If no font exists that can render the text, family_index will be
|
||||
// UINT32_MAX and mapped_length will indicate how many characters cannot be
|
||||
// rendered by any installed font.
|
||||
IPC_SYNC_MESSAGE_CONTROL5_1(DWriteFontProxyMsg_MapCharacters,
|
||||
base::string16 /* text */,
|
||||
DWriteFontStyle /* font_style */,
|
||||
base::string16 /* locale_name */,
|
||||
uint32_t /* reading_direction */,
|
||||
base::string16 /* base_family_name - optional */,
|
||||
MapCharactersResult /* out */)
|
||||
|
82
content/common/dwrite_text_analysis_source_win.cc
Normal file
82
content/common/dwrite_text_analysis_source_win.cc
Normal file
@ -0,0 +1,82 @@
|
||||
// Copyright 2016 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 "content/common/dwrite_text_analysis_source_win.h"
|
||||
|
||||
#include "base/logging.h"
|
||||
|
||||
namespace content {
|
||||
|
||||
TextAnalysisSource::TextAnalysisSource() = default;
|
||||
TextAnalysisSource::~TextAnalysisSource() = default;
|
||||
|
||||
HRESULT TextAnalysisSource::GetLocaleName(UINT32 text_position,
|
||||
UINT32* text_length,
|
||||
const WCHAR** locale_name) {
|
||||
if (text_position >= text_.length() || !text_length || !locale_name)
|
||||
return E_INVALIDARG;
|
||||
*text_length = text_.length() - text_position;
|
||||
*locale_name = locale_name_.c_str();
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT TextAnalysisSource::GetNumberSubstitution(
|
||||
UINT32 text_position,
|
||||
UINT32* text_length,
|
||||
IDWriteNumberSubstitution** number_substitution) {
|
||||
if (text_position >= text_.length() || !text_length || !number_substitution)
|
||||
return E_INVALIDARG;
|
||||
*text_length = text_.length() - text_position;
|
||||
number_substitution_.CopyTo(number_substitution);
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
DWRITE_READING_DIRECTION TextAnalysisSource::GetParagraphReadingDirection() {
|
||||
return reading_direction_;
|
||||
}
|
||||
|
||||
HRESULT TextAnalysisSource::GetTextAtPosition(UINT32 text_position,
|
||||
const WCHAR** text_string,
|
||||
UINT32* text_length) {
|
||||
if (!text_length || !text_string)
|
||||
return E_INVALIDARG;
|
||||
if (text_position >= text_.length()) {
|
||||
*text_string = nullptr;
|
||||
*text_length = 0;
|
||||
return S_OK;
|
||||
}
|
||||
*text_string = text_.c_str() + text_position;
|
||||
*text_length = text_.length() - text_position;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT TextAnalysisSource::GetTextBeforePosition(UINT32 text_position,
|
||||
const WCHAR** text_string,
|
||||
UINT32* text_length) {
|
||||
if (!text_length || !text_string)
|
||||
return E_INVALIDARG;
|
||||
if (text_position < 1 || text_position > text_.length()) {
|
||||
*text_string = nullptr;
|
||||
*text_length = 0;
|
||||
return S_OK;
|
||||
}
|
||||
*text_string = text_.c_str();
|
||||
*text_length = text_position;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT TextAnalysisSource::RuntimeClassInitialize(
|
||||
const base::string16& text,
|
||||
const base::string16& locale_name,
|
||||
IDWriteNumberSubstitution* number_substitution,
|
||||
DWRITE_READING_DIRECTION reading_direction) {
|
||||
DCHECK(number_substitution);
|
||||
text_ = text;
|
||||
locale_name_ = locale_name;
|
||||
number_substitution_ = number_substitution;
|
||||
reading_direction_ = reading_direction;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
} // namespace content
|
64
content/common/dwrite_text_analysis_source_win.h
Normal file
64
content/common/dwrite_text_analysis_source_win.h
Normal file
@ -0,0 +1,64 @@
|
||||
// Copyright 2016 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 CONTENT_COMMON_DWRITE_TEXT_ANALYSIS_SOURCE_WIN_H_
|
||||
#define CONTENT_COMMON_DWRITE_TEXT_ANALYSIS_SOURCE_WIN_H_
|
||||
|
||||
#include <dwrite.h>
|
||||
#include <wrl.h>
|
||||
|
||||
#include "base/macros.h"
|
||||
#include "base/strings/string16.h"
|
||||
#include "content/common/content_export.h"
|
||||
|
||||
namespace content {
|
||||
|
||||
// Implements an IDWriteTextAnalysisSource, describing a single pre-defined
|
||||
// chunk of text with a uniform locale, reading direction, and number
|
||||
// substitution.
|
||||
class CONTENT_EXPORT TextAnalysisSource
|
||||
: public Microsoft::WRL::RuntimeClass<
|
||||
Microsoft::WRL::RuntimeClassFlags<Microsoft::WRL::ClassicCom>,
|
||||
IDWriteTextAnalysisSource> {
|
||||
public:
|
||||
TextAnalysisSource();
|
||||
|
||||
// IDWriteTextAnalysisSource:
|
||||
HRESULT STDMETHODCALLTYPE GetLocaleName(UINT32 text_position,
|
||||
UINT32* text_length,
|
||||
const WCHAR** locale_name) override;
|
||||
HRESULT STDMETHODCALLTYPE GetNumberSubstitution(
|
||||
UINT32 text_position,
|
||||
UINT32* text_length,
|
||||
IDWriteNumberSubstitution** number_substitution) override;
|
||||
DWRITE_READING_DIRECTION STDMETHODCALLTYPE
|
||||
GetParagraphReadingDirection() override;
|
||||
HRESULT STDMETHODCALLTYPE GetTextAtPosition(UINT32 text_position,
|
||||
const WCHAR** text_string,
|
||||
UINT32* text_length) override;
|
||||
HRESULT STDMETHODCALLTYPE GetTextBeforePosition(UINT32 text_position,
|
||||
const WCHAR** text_string,
|
||||
UINT32* text_length) override;
|
||||
|
||||
HRESULT STDMETHODCALLTYPE
|
||||
RuntimeClassInitialize(const base::string16& text,
|
||||
const base::string16& locale_name,
|
||||
IDWriteNumberSubstitution* number_substitution,
|
||||
DWRITE_READING_DIRECTION reading_direction);
|
||||
|
||||
protected:
|
||||
~TextAnalysisSource() override;
|
||||
|
||||
private:
|
||||
base::string16 text_;
|
||||
base::string16 locale_name_;
|
||||
Microsoft::WRL::ComPtr<IDWriteNumberSubstitution> number_substitution_;
|
||||
DWRITE_READING_DIRECTION reading_direction_;
|
||||
|
||||
DISALLOW_ASSIGN(TextAnalysisSource);
|
||||
};
|
||||
|
||||
} // namespace content
|
||||
|
||||
#endif // CONTENT_COMMON_DWRITE_TEXT_ANALYSIS_SOURCE_WIN_H_
|
@ -96,6 +96,8 @@
|
||||
'child/dwrite_font_proxy/dwrite_font_proxy_win.h',
|
||||
'child/dwrite_font_proxy/dwrite_localized_strings_win.cc',
|
||||
'child/dwrite_font_proxy/dwrite_localized_strings_win.h',
|
||||
'child/dwrite_font_proxy/font_fallback_win.cc',
|
||||
'child/dwrite_font_proxy/font_fallback_win.h',
|
||||
'child/file_info_util.cc',
|
||||
'child/file_info_util.h',
|
||||
'child/fileapi/file_system_dispatcher.cc',
|
||||
|
@ -314,6 +314,8 @@
|
||||
'common/drag_messages.h',
|
||||
'common/drag_traits.h',
|
||||
'common/dwrite_font_proxy_messages.h',
|
||||
'common/dwrite_text_analysis_source_win.cc',
|
||||
'common/dwrite_text_analysis_source_win.h',
|
||||
'common/edit_command.h',
|
||||
'common/establish_channel_params.cc',
|
||||
'common/establish_channel_params.h',
|
||||
|
@ -642,6 +642,7 @@
|
||||
'child/blob_storage/blob_consolidation_unittest.cc',
|
||||
'child/blob_storage/blob_transport_controller_unittest.cc',
|
||||
'child/dwrite_font_proxy/dwrite_font_proxy_win_unittest.cc',
|
||||
'child/dwrite_font_proxy/font_fallback_win_unittest.cc',
|
||||
'child/fileapi/webfilewriter_base_unittest.cc',
|
||||
'child/font_warmup_win_unittest.cc',
|
||||
'child/indexed_db/indexed_db_dispatcher_unittest.cc',
|
||||
|
@ -4,6 +4,7 @@
|
||||
|
||||
#include "content/test/dwrite_font_fake_sender_win.h"
|
||||
|
||||
#include <dwrite.h>
|
||||
#include <shlobj.h>
|
||||
|
||||
#include "content/common/dwrite_font_proxy_messages.h"
|
||||
@ -79,6 +80,7 @@ FakeFontCollection::ReplySender::OnMessageReceived(const IPC::Message& msg) {
|
||||
IPC_MESSAGE_HANDLER(DWriteFontProxyMsg_GetFamilyCount, OnGetFamilyCount)
|
||||
IPC_MESSAGE_HANDLER(DWriteFontProxyMsg_GetFamilyNames, OnGetFamilyNames)
|
||||
IPC_MESSAGE_HANDLER(DWriteFontProxyMsg_GetFontFiles, OnGetFontFiles)
|
||||
IPC_MESSAGE_HANDLER(DWriteFontProxyMsg_MapCharacters, OnMapCharacters)
|
||||
IPC_MESSAGE_UNHANDLED(handled = false)
|
||||
IPC_END_MESSAGE_MAP()
|
||||
return reply_;
|
||||
@ -111,6 +113,17 @@ void FakeFontCollection::ReplySender::OnGetFontFiles(
|
||||
collection_->OnGetFontFiles(family_index, file_paths);
|
||||
}
|
||||
|
||||
void FakeFontCollection::ReplySender::OnMapCharacters(
|
||||
const base::string16& text,
|
||||
const DWriteFontStyle& font_style,
|
||||
const base::string16& locale_name,
|
||||
uint32_t reading_direction,
|
||||
const base::string16& base_family_name,
|
||||
MapCharactersResult* result) {
|
||||
collection_->OnMapCharacters(text, font_style, locale_name, reading_direction,
|
||||
base_family_name, result);
|
||||
}
|
||||
|
||||
FakeFontCollection::FakeSender::FakeSender(FakeFontCollection* collection,
|
||||
bool track_messages)
|
||||
: track_messages_(track_messages), collection_(collection) {}
|
||||
@ -165,6 +178,21 @@ void FakeFontCollection::OnGetFontFiles(
|
||||
*file_paths = fonts_[family_index].file_paths_;
|
||||
}
|
||||
|
||||
void FakeFontCollection::OnMapCharacters(const base::string16& text,
|
||||
const DWriteFontStyle& font_style,
|
||||
const base::string16& locale_name,
|
||||
uint32_t reading_direction,
|
||||
const base::string16& base_family_name,
|
||||
MapCharactersResult* result) {
|
||||
result->family_index = 0;
|
||||
result->family_name = fonts_[0].font_name();
|
||||
result->mapped_length = 1;
|
||||
result->scale = 1.0;
|
||||
result->font_style.font_weight = DWRITE_FONT_WEIGHT_NORMAL;
|
||||
result->font_style.font_slant = DWRITE_FONT_STYLE_NORMAL;
|
||||
result->font_style.font_stretch = DWRITE_FONT_STRETCH_NORMAL;
|
||||
}
|
||||
|
||||
std::unique_ptr<FakeFontCollection::ReplySender>
|
||||
FakeFontCollection::GetReplySender() {
|
||||
return std::unique_ptr<FakeFontCollection::ReplySender>(
|
||||
|
@ -19,6 +19,9 @@
|
||||
#include "ipc/ipc_message.h"
|
||||
#include "ipc/ipc_sender.h"
|
||||
|
||||
struct DWriteFontStyle;
|
||||
struct MapCharactersResult;
|
||||
|
||||
namespace content {
|
||||
|
||||
class FakeFontCollection;
|
||||
@ -47,6 +50,8 @@ class FakeFont {
|
||||
return *this;
|
||||
}
|
||||
|
||||
const base::string16& font_name() { return font_name_; }
|
||||
|
||||
private:
|
||||
friend FakeFontCollection;
|
||||
base::string16 font_name_;
|
||||
@ -114,6 +119,13 @@ class FakeFontCollection : public base::RefCounted<FakeFontCollection> {
|
||||
void OnGetFontFiles(uint32_t family_index,
|
||||
std::vector<base::string16>* file_paths_);
|
||||
|
||||
void OnMapCharacters(const base::string16& text,
|
||||
const DWriteFontStyle& font_style,
|
||||
const base::string16& locale_name,
|
||||
uint32_t reading_direction,
|
||||
const base::string16& base_family_name,
|
||||
MapCharactersResult* result);
|
||||
|
||||
private:
|
||||
scoped_refptr<FakeFontCollection> collection_;
|
||||
std::unique_ptr<IPC::Message> reply_;
|
||||
@ -148,6 +160,13 @@ class FakeFontCollection : public base::RefCounted<FakeFontCollection> {
|
||||
void OnGetFontFiles(uint32_t family_index,
|
||||
std::vector<base::string16>* file_paths);
|
||||
|
||||
void OnMapCharacters(const base::string16& text,
|
||||
const DWriteFontStyle& font_style,
|
||||
const base::string16& locale_name,
|
||||
uint32_t reading_direction,
|
||||
const base::string16& base_family_name,
|
||||
MapCharactersResult* result);
|
||||
|
||||
std::unique_ptr<ReplySender> GetReplySender();
|
||||
|
||||
private:
|
||||
|
Reference in New Issue
Block a user