summaryrefslogtreecommitdiffstats
path: root/ui/gfx/win/direct_write.cc
blob: 38c926a9bd11da661c3e66b614c177427a6bf6ae (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
// 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 <dwrite.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 MaybeInitializeDirectWrite() {
  static bool tried_dwrite_initialize = false;
  if (tried_dwrite_initialize)
    return;
  tried_dwrite_initialize = true;

  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;

  base::win::ScopedComPtr<IDWriteFactory> factory;

  // Failure to create the DirectWrite factory indicates a corrupt dll.
  if (FAILED(dwrite_create_factory_proc(
          DWRITE_FACTORY_TYPE_SHARED,
        __uuidof(IDWriteFactory),
        reinterpret_cast<IUnknown**>(factory.Receive()))))
    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