blob: 9c8250b5bbf5175e7e339e7b72fbae5cfd550ecd [file] [log] [blame]
// Copyright 2014 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/win/direct_write.h"
#include "base/basictypes.h"
#include "base/command_line.h"
#include "base/metrics/field_trial.h"
#include "base/win/registry.h"
#include "base/win/scoped_comptr.h"
#include "base/win/windows_version.h"
#include "skia/ext/fontmgr_default_win.h"
#include "third_party/skia/include/ports/SkTypeface_win.h"
#include "ui/gfx/platform_font_win.h"
#include "ui/gfx/switches.h"
#include "ui/gfx/win/dpi.h"
namespace gfx {
namespace win {
namespace {
static bool dwrite_enabled = false;
}
bool ShouldUseDirectWrite() {
// If the flag is currently on, and we're on Win7 or above, we enable
// DirectWrite. Skia does not require the additions to DirectWrite in QFE
// 2670838, but a simple 'better than XP' check is not enough.
if (base::win::GetVersion() < base::win::VERSION_WIN7)
return false;
base::win::OSInfo::VersionNumber os_version =
base::win::OSInfo::GetInstance()->version_number();
if ((os_version.major == 6) && (os_version.minor == 1)) {
// We can't use DirectWrite for pre-release versions of Windows 7.
if (os_version.build < 7600)
return false;
}
// If forced off, don't use it.
const base::CommandLine& command_line =
*base::CommandLine::ForCurrentProcess();
if (command_line.HasSwitch(switches::kDisableDirectWrite))
return false;
// Can't use GDI on HiDPI.
if (gfx::GetDPIScale() > 1.0f)
return true;
// Otherwise, check the field trial.
const std::string group_name =
base::FieldTrialList::FindFullName("DirectWrite");
return group_name != "Disabled";
}
void CreateDWriteFactory(IDWriteFactory** factory) {
if (!ShouldUseDirectWrite() ||
base::CommandLine::ForCurrentProcess()->HasSwitch(
switches::kDisableDirectWriteForUI)) {
return;
}
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"));
// Not finding the DWriteCreateFactory function indicates a corrupt dll.
if (!dwrite_create_factory_proc)
return;
// Failure to create the DirectWrite factory indicates a corrupt dll.
base::win::ScopedComPtr<IUnknown> factory_unknown;
if (FAILED(dwrite_create_factory_proc(DWRITE_FACTORY_TYPE_SHARED,
__uuidof(IDWriteFactory),
factory_unknown.Receive()))) {
return;
}
factory_unknown.QueryInterface<IDWriteFactory>(factory);
}
void MaybeInitializeDirectWrite() {
static bool tried_dwrite_initialize = false;
if (tried_dwrite_initialize)
return;
tried_dwrite_initialize = true;
base::win::ScopedComPtr<IDWriteFactory> factory;
CreateDWriteFactory(factory.Receive());
if (factory == nullptr)
return;
// 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.*). We should just use GDI in these cases.
SkFontMgr* direct_write_font_mgr = SkFontMgr_New_DirectWrite(factory.get());
if (!direct_write_font_mgr)
return;
dwrite_enabled = true;
SetDefaultSkiaFactory(direct_write_font_mgr);
gfx::PlatformFontWin::SetDirectWriteFactory(factory.get());
}
bool IsDirectWriteEnabled() {
return dwrite_enabled;
}
} // namespace win
} // namespace gfx