1 /*
2 * Copyright 2014 Google Inc.
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
7 #include "src/utils/win/SkDWriteNTDDI_VERSION.h"
8
9 #include "include/core/SkTypes.h"
10 #if defined(SK_BUILD_FOR_WIN)
11
12 #include "include/core/SkFontMgr.h"
13 #include "include/core/SkStream.h"
14 #include "include/core/SkTypeface.h"
15 #include "include/core/SkTypes.h"
16 #include "include/private/SkMutex.h"
17 #include "src/core/SkEndian.h"
18 #include "src/core/SkMakeUnique.h"
19 #include "src/core/SkTypefaceCache.h"
20 #include "src/ports/SkTypeface_win_dw.h"
21 #include "src/utils/SkUTF.h"
22 #include "src/utils/win/SkDWrite.h"
23 #include "src/utils/win/SkDWriteFontFileStream.h"
24 #include "src/utils/win/SkHRESULT.h"
25 #include "src/utils/win/SkObjBase.h"
26 #include "src/utils/win/SkTScopedComPtr.h"
27
28 #include <dwrite.h>
29 #include <dwrite_2.h>
30 #include <dwrite_3.h>
31
32 ////////////////////////////////////////////////////////////////////////////////
33
34 class StreamFontFileLoader : public IDWriteFontFileLoader {
35 public:
36 // IUnknown methods
37 SK_STDMETHODIMP QueryInterface(REFIID iid, void** ppvObject) override;
38 SK_STDMETHODIMP_(ULONG) AddRef() override;
39 SK_STDMETHODIMP_(ULONG) Release() override;
40
41 // IDWriteFontFileLoader methods
42 SK_STDMETHODIMP CreateStreamFromKey(
43 void const* fontFileReferenceKey,
44 UINT32 fontFileReferenceKeySize,
45 IDWriteFontFileStream** fontFileStream) override;
46
47 // Takes ownership of stream.
Create(std::unique_ptr<SkStreamAsset> stream,StreamFontFileLoader ** streamFontFileLoader)48 static HRESULT Create(std::unique_ptr<SkStreamAsset> stream,
49 StreamFontFileLoader** streamFontFileLoader) {
50 *streamFontFileLoader = new StreamFontFileLoader(std::move(stream));
51 if (nullptr == *streamFontFileLoader) {
52 return E_OUTOFMEMORY;
53 }
54 return S_OK;
55 }
56
57 private:
StreamFontFileLoader(std::unique_ptr<SkStreamAsset> stream)58 StreamFontFileLoader(std::unique_ptr<SkStreamAsset> stream)
59 : fStream(std::move(stream)), fRefCount(1)
60 {}
~StreamFontFileLoader()61 virtual ~StreamFontFileLoader() { }
62
63 std::unique_ptr<SkStreamAsset> fStream;
64 ULONG fRefCount;
65 };
66
QueryInterface(REFIID iid,void ** ppvObject)67 SK_STDMETHODIMP StreamFontFileLoader::QueryInterface(REFIID iid, void** ppvObject) {
68 if (iid == IID_IUnknown || iid == __uuidof(IDWriteFontFileLoader)) {
69 *ppvObject = this;
70 AddRef();
71 return S_OK;
72 } else {
73 *ppvObject = nullptr;
74 return E_NOINTERFACE;
75 }
76 }
77
SK_STDMETHODIMP_(ULONG)78 SK_STDMETHODIMP_(ULONG) StreamFontFileLoader::AddRef() {
79 return InterlockedIncrement(&fRefCount);
80 }
81
SK_STDMETHODIMP_(ULONG)82 SK_STDMETHODIMP_(ULONG) StreamFontFileLoader::Release() {
83 ULONG newCount = InterlockedDecrement(&fRefCount);
84 if (0 == newCount) {
85 delete this;
86 }
87 return newCount;
88 }
89
CreateStreamFromKey(void const * fontFileReferenceKey,UINT32 fontFileReferenceKeySize,IDWriteFontFileStream ** fontFileStream)90 SK_STDMETHODIMP StreamFontFileLoader::CreateStreamFromKey(
91 void const* fontFileReferenceKey,
92 UINT32 fontFileReferenceKeySize,
93 IDWriteFontFileStream** fontFileStream)
94 {
95 SkTScopedComPtr<SkDWriteFontFileStreamWrapper> stream;
96 HR(SkDWriteFontFileStreamWrapper::Create(fStream->duplicate().release(), &stream));
97 *fontFileStream = stream.release();
98 return S_OK;
99 }
100
101 ////////////////////////////////////////////////////////////////////////////////
102
103 class StreamFontFileEnumerator : public IDWriteFontFileEnumerator {
104 public:
105 // IUnknown methods
106 SK_STDMETHODIMP QueryInterface(REFIID iid, void** ppvObject) override;
107 SK_STDMETHODIMP_(ULONG) AddRef() override;
108 SK_STDMETHODIMP_(ULONG) Release() override;
109
110 // IDWriteFontFileEnumerator methods
111 SK_STDMETHODIMP MoveNext(BOOL* hasCurrentFile) override;
112 SK_STDMETHODIMP GetCurrentFontFile(IDWriteFontFile** fontFile) override;
113
Create(IDWriteFactory * factory,IDWriteFontFileLoader * fontFileLoader,StreamFontFileEnumerator ** streamFontFileEnumerator)114 static HRESULT Create(IDWriteFactory* factory, IDWriteFontFileLoader* fontFileLoader,
115 StreamFontFileEnumerator** streamFontFileEnumerator) {
116 *streamFontFileEnumerator = new StreamFontFileEnumerator(factory, fontFileLoader);
117 if (nullptr == *streamFontFileEnumerator) {
118 return E_OUTOFMEMORY;
119 }
120 return S_OK;
121 }
122 private:
123 StreamFontFileEnumerator(IDWriteFactory* factory, IDWriteFontFileLoader* fontFileLoader);
~StreamFontFileEnumerator()124 virtual ~StreamFontFileEnumerator() { }
125
126 ULONG fRefCount;
127
128 SkTScopedComPtr<IDWriteFactory> fFactory;
129 SkTScopedComPtr<IDWriteFontFile> fCurrentFile;
130 SkTScopedComPtr<IDWriteFontFileLoader> fFontFileLoader;
131 bool fHasNext;
132 };
133
StreamFontFileEnumerator(IDWriteFactory * factory,IDWriteFontFileLoader * fontFileLoader)134 StreamFontFileEnumerator::StreamFontFileEnumerator(IDWriteFactory* factory,
135 IDWriteFontFileLoader* fontFileLoader)
136 : fRefCount(1)
137 , fFactory(SkRefComPtr(factory))
138 , fCurrentFile()
139 , fFontFileLoader(SkRefComPtr(fontFileLoader))
140 , fHasNext(true)
141 { }
142
QueryInterface(REFIID iid,void ** ppvObject)143 SK_STDMETHODIMP StreamFontFileEnumerator::QueryInterface(REFIID iid, void** ppvObject) {
144 if (iid == IID_IUnknown || iid == __uuidof(IDWriteFontFileEnumerator)) {
145 *ppvObject = this;
146 AddRef();
147 return S_OK;
148 } else {
149 *ppvObject = nullptr;
150 return E_NOINTERFACE;
151 }
152 }
153
SK_STDMETHODIMP_(ULONG)154 SK_STDMETHODIMP_(ULONG) StreamFontFileEnumerator::AddRef() {
155 return InterlockedIncrement(&fRefCount);
156 }
157
SK_STDMETHODIMP_(ULONG)158 SK_STDMETHODIMP_(ULONG) StreamFontFileEnumerator::Release() {
159 ULONG newCount = InterlockedDecrement(&fRefCount);
160 if (0 == newCount) {
161 delete this;
162 }
163 return newCount;
164 }
165
MoveNext(BOOL * hasCurrentFile)166 SK_STDMETHODIMP StreamFontFileEnumerator::MoveNext(BOOL* hasCurrentFile) {
167 *hasCurrentFile = FALSE;
168
169 if (!fHasNext) {
170 return S_OK;
171 }
172 fHasNext = false;
173
174 UINT32 dummy = 0;
175 HR(fFactory->CreateCustomFontFileReference(
176 &dummy, //cannot be nullptr
177 sizeof(dummy), //even if this is 0
178 fFontFileLoader.get(),
179 &fCurrentFile));
180
181 *hasCurrentFile = TRUE;
182 return S_OK;
183 }
184
GetCurrentFontFile(IDWriteFontFile ** fontFile)185 SK_STDMETHODIMP StreamFontFileEnumerator::GetCurrentFontFile(IDWriteFontFile** fontFile) {
186 if (fCurrentFile.get() == nullptr) {
187 *fontFile = nullptr;
188 return E_FAIL;
189 }
190
191 *fontFile = SkRefComPtr(fCurrentFile.get());
192 return S_OK;
193 }
194
195 ////////////////////////////////////////////////////////////////////////////////
196
197 class StreamFontCollectionLoader : public IDWriteFontCollectionLoader {
198 public:
199 // IUnknown methods
200 SK_STDMETHODIMP QueryInterface(REFIID iid, void** ppvObject) override;
201 SK_STDMETHODIMP_(ULONG) AddRef() override;
202 SK_STDMETHODIMP_(ULONG) Release() override;
203
204 // IDWriteFontCollectionLoader methods
205 SK_STDMETHODIMP CreateEnumeratorFromKey(
206 IDWriteFactory* factory,
207 void const* collectionKey,
208 UINT32 collectionKeySize,
209 IDWriteFontFileEnumerator** fontFileEnumerator) override;
210
Create(IDWriteFontFileLoader * fontFileLoader,StreamFontCollectionLoader ** streamFontCollectionLoader)211 static HRESULT Create(IDWriteFontFileLoader* fontFileLoader,
212 StreamFontCollectionLoader** streamFontCollectionLoader) {
213 *streamFontCollectionLoader = new StreamFontCollectionLoader(fontFileLoader);
214 if (nullptr == *streamFontCollectionLoader) {
215 return E_OUTOFMEMORY;
216 }
217 return S_OK;
218 }
219 private:
StreamFontCollectionLoader(IDWriteFontFileLoader * fontFileLoader)220 StreamFontCollectionLoader(IDWriteFontFileLoader* fontFileLoader)
221 : fRefCount(1)
222 , fFontFileLoader(SkRefComPtr(fontFileLoader))
223 { }
~StreamFontCollectionLoader()224 virtual ~StreamFontCollectionLoader() { }
225
226 ULONG fRefCount;
227 SkTScopedComPtr<IDWriteFontFileLoader> fFontFileLoader;
228 };
229
QueryInterface(REFIID iid,void ** ppvObject)230 SK_STDMETHODIMP StreamFontCollectionLoader::QueryInterface(REFIID iid, void** ppvObject) {
231 if (iid == IID_IUnknown || iid == __uuidof(IDWriteFontCollectionLoader)) {
232 *ppvObject = this;
233 AddRef();
234 return S_OK;
235 } else {
236 *ppvObject = nullptr;
237 return E_NOINTERFACE;
238 }
239 }
240
SK_STDMETHODIMP_(ULONG)241 SK_STDMETHODIMP_(ULONG) StreamFontCollectionLoader::AddRef() {
242 return InterlockedIncrement(&fRefCount);
243 }
244
SK_STDMETHODIMP_(ULONG)245 SK_STDMETHODIMP_(ULONG) StreamFontCollectionLoader::Release() {
246 ULONG newCount = InterlockedDecrement(&fRefCount);
247 if (0 == newCount) {
248 delete this;
249 }
250 return newCount;
251 }
252
CreateEnumeratorFromKey(IDWriteFactory * factory,void const * collectionKey,UINT32 collectionKeySize,IDWriteFontFileEnumerator ** fontFileEnumerator)253 SK_STDMETHODIMP StreamFontCollectionLoader::CreateEnumeratorFromKey(
254 IDWriteFactory* factory,
255 void const* collectionKey,
256 UINT32 collectionKeySize,
257 IDWriteFontFileEnumerator** fontFileEnumerator)
258 {
259 SkTScopedComPtr<StreamFontFileEnumerator> enumerator;
260 HR(StreamFontFileEnumerator::Create(factory, fFontFileLoader.get(), &enumerator));
261 *fontFileEnumerator = enumerator.release();
262 return S_OK;
263 }
264
265 ////////////////////////////////////////////////////////////////////////////////
266
267 class SkFontMgr_DirectWrite : public SkFontMgr {
268 public:
269 /** localeNameLength and defaultFamilyNameLength must include the null terminator. */
SkFontMgr_DirectWrite(IDWriteFactory * factory,IDWriteFontCollection * fontCollection,IDWriteFontFallback * fallback,const WCHAR * localeName,int localeNameLength,const WCHAR * defaultFamilyName,int defaultFamilyNameLength)270 SkFontMgr_DirectWrite(IDWriteFactory* factory, IDWriteFontCollection* fontCollection,
271 IDWriteFontFallback* fallback,
272 const WCHAR* localeName, int localeNameLength,
273 const WCHAR* defaultFamilyName, int defaultFamilyNameLength)
274 : fFactory(SkRefComPtr(factory))
275 , fFontFallback(SkSafeRefComPtr(fallback))
276 , fFontCollection(SkRefComPtr(fontCollection))
277 , fLocaleName(localeNameLength)
278 , fDefaultFamilyName(defaultFamilyNameLength)
279 {
280 memcpy(fLocaleName.get(), localeName, localeNameLength * sizeof(WCHAR));
281 memcpy(fDefaultFamilyName.get(), defaultFamilyName, defaultFamilyNameLength*sizeof(WCHAR));
282 }
283
284 protected:
285 int onCountFamilies() const override;
286 void onGetFamilyName(int index, SkString* familyName) const override;
287 SkFontStyleSet* onCreateStyleSet(int index) const override;
288 SkFontStyleSet* onMatchFamily(const char familyName[]) const override;
289 SkTypeface* onMatchFamilyStyle(const char familyName[],
290 const SkFontStyle& fontstyle) const override;
291 SkTypeface* onMatchFamilyStyleCharacter(const char familyName[], const SkFontStyle&,
292 const char* bcp47[], int bcp47Count,
293 SkUnichar character) const override;
294 SkTypeface* onMatchFaceStyle(const SkTypeface* familyMember,
295 const SkFontStyle& fontstyle) const override;
296 sk_sp<SkTypeface> onMakeFromStreamIndex(std::unique_ptr<SkStreamAsset>, int ttcIndex) const override;
297 sk_sp<SkTypeface> onMakeFromStreamArgs(std::unique_ptr<SkStreamAsset>, const SkFontArguments&) const override;
298 sk_sp<SkTypeface> onMakeFromData(sk_sp<SkData>, int ttcIndex) const override;
299 sk_sp<SkTypeface> onMakeFromFile(const char path[], int ttcIndex) const override;
300 sk_sp<SkTypeface> onLegacyMakeTypeface(const char familyName[], SkFontStyle) const override;
301
302 private:
303 HRESULT getByFamilyName(const WCHAR familyName[], IDWriteFontFamily** fontFamily) const;
304 sk_sp<SkTypeface> fallback(const WCHAR* dwFamilyName, DWriteStyle,
305 const WCHAR* dwBcp47, UINT32 character) const;
306 sk_sp<SkTypeface> layoutFallback(const WCHAR* dwFamilyName, DWriteStyle,
307 const WCHAR* dwBcp47, UINT32 character) const;
308
309 /** Creates a typeface using a typeface cache. */
310 sk_sp<SkTypeface> makeTypefaceFromDWriteFont(IDWriteFontFace* fontFace,
311 IDWriteFont* font,
312 IDWriteFontFamily* fontFamily) const;
313
314 SkTScopedComPtr<IDWriteFactory> fFactory;
315 SkTScopedComPtr<IDWriteFontFallback> fFontFallback;
316 SkTScopedComPtr<IDWriteFontCollection> fFontCollection;
317 SkSMallocWCHAR fLocaleName;
318 SkSMallocWCHAR fDefaultFamilyName;
319 mutable SkMutex fTFCacheMutex;
320 mutable SkTypefaceCache fTFCache;
321
322 friend class SkFontStyleSet_DirectWrite;
323 friend class FontFallbackRenderer;
324 };
325
326 class SkFontStyleSet_DirectWrite : public SkFontStyleSet {
327 public:
SkFontStyleSet_DirectWrite(const SkFontMgr_DirectWrite * fontMgr,IDWriteFontFamily * fontFamily)328 SkFontStyleSet_DirectWrite(const SkFontMgr_DirectWrite* fontMgr,
329 IDWriteFontFamily* fontFamily)
330 : fFontMgr(SkRef(fontMgr))
331 , fFontFamily(SkRefComPtr(fontFamily))
332 { }
333
334 int count() override;
335 void getStyle(int index, SkFontStyle* fs, SkString* styleName) override;
336 SkTypeface* createTypeface(int index) override;
337 SkTypeface* matchStyle(const SkFontStyle& pattern) override;
338
339 private:
340 sk_sp<const SkFontMgr_DirectWrite> fFontMgr;
341 SkTScopedComPtr<IDWriteFontFamily> fFontFamily;
342 };
343
are_same(IUnknown * a,IUnknown * b,bool & same)344 static HRESULT are_same(IUnknown* a, IUnknown* b, bool& same) {
345 SkTScopedComPtr<IUnknown> iunkA;
346 HRM(a->QueryInterface(&iunkA), "Failed to QI<IUnknown> for a.");
347
348 SkTScopedComPtr<IUnknown> iunkB;
349 HRM(b->QueryInterface(&iunkB), "Failed to QI<IUnknown> for b.");
350
351 same = (iunkA.get() == iunkB.get());
352 return S_OK;
353 }
354
355 struct ProtoDWriteTypeface {
356 IDWriteFontFace* fDWriteFontFace;
357 IDWriteFont* fDWriteFont;
358 IDWriteFontFamily* fDWriteFontFamily;
359 };
360
FindByDWriteFont(SkTypeface * cached,void * ctx)361 static bool FindByDWriteFont(SkTypeface* cached, void* ctx) {
362 DWriteFontTypeface* cshFace = reinterpret_cast<DWriteFontTypeface*>(cached);
363 ProtoDWriteTypeface* ctxFace = reinterpret_cast<ProtoDWriteTypeface*>(ctx);
364 bool same;
365
366 //Check to see if the two fonts are identical.
367 HRB(are_same(cshFace->fDWriteFont.get(), ctxFace->fDWriteFont, same));
368 if (same) {
369 return true;
370 }
371
372 HRB(are_same(cshFace->fDWriteFontFace.get(), ctxFace->fDWriteFontFace, same));
373 if (same) {
374 return true;
375 }
376
377 //Check if the two fonts share the same loader and have the same key.
378 UINT32 cshNumFiles;
379 UINT32 ctxNumFiles;
380 HRB(cshFace->fDWriteFontFace->GetFiles(&cshNumFiles, nullptr));
381 HRB(ctxFace->fDWriteFontFace->GetFiles(&ctxNumFiles, nullptr));
382 if (cshNumFiles != ctxNumFiles) {
383 return false;
384 }
385
386 SkTScopedComPtr<IDWriteFontFile> cshFontFile;
387 SkTScopedComPtr<IDWriteFontFile> ctxFontFile;
388 HRB(cshFace->fDWriteFontFace->GetFiles(&cshNumFiles, &cshFontFile));
389 HRB(ctxFace->fDWriteFontFace->GetFiles(&ctxNumFiles, &ctxFontFile));
390
391 //for (each file) { //we currently only admit fonts from one file.
392 SkTScopedComPtr<IDWriteFontFileLoader> cshFontFileLoader;
393 SkTScopedComPtr<IDWriteFontFileLoader> ctxFontFileLoader;
394 HRB(cshFontFile->GetLoader(&cshFontFileLoader));
395 HRB(ctxFontFile->GetLoader(&ctxFontFileLoader));
396 HRB(are_same(cshFontFileLoader.get(), ctxFontFileLoader.get(), same));
397 if (!same) {
398 return false;
399 }
400 //}
401
402 const void* cshRefKey;
403 UINT32 cshRefKeySize;
404 const void* ctxRefKey;
405 UINT32 ctxRefKeySize;
406 HRB(cshFontFile->GetReferenceKey(&cshRefKey, &cshRefKeySize));
407 HRB(ctxFontFile->GetReferenceKey(&ctxRefKey, &ctxRefKeySize));
408 if (cshRefKeySize != ctxRefKeySize) {
409 return false;
410 }
411 if (0 != memcmp(cshRefKey, ctxRefKey, ctxRefKeySize)) {
412 return false;
413 }
414
415 //TODO: better means than comparing name strings?
416 //NOTE: .ttc and fake bold/italic will end up here.
417 SkTScopedComPtr<IDWriteLocalizedStrings> cshFamilyNames;
418 SkTScopedComPtr<IDWriteLocalizedStrings> cshFaceNames;
419 HRB(cshFace->fDWriteFontFamily->GetFamilyNames(&cshFamilyNames));
420 HRB(cshFace->fDWriteFont->GetFaceNames(&cshFaceNames));
421 UINT32 cshFamilyNameLength;
422 UINT32 cshFaceNameLength;
423 HRB(cshFamilyNames->GetStringLength(0, &cshFamilyNameLength));
424 HRB(cshFaceNames->GetStringLength(0, &cshFaceNameLength));
425
426 SkTScopedComPtr<IDWriteLocalizedStrings> ctxFamilyNames;
427 SkTScopedComPtr<IDWriteLocalizedStrings> ctxFaceNames;
428 HRB(ctxFace->fDWriteFontFamily->GetFamilyNames(&ctxFamilyNames));
429 HRB(ctxFace->fDWriteFont->GetFaceNames(&ctxFaceNames));
430 UINT32 ctxFamilyNameLength;
431 UINT32 ctxFaceNameLength;
432 HRB(ctxFamilyNames->GetStringLength(0, &ctxFamilyNameLength));
433 HRB(ctxFaceNames->GetStringLength(0, &ctxFaceNameLength));
434
435 if (cshFamilyNameLength != ctxFamilyNameLength ||
436 cshFaceNameLength != ctxFaceNameLength)
437 {
438 return false;
439 }
440
441 SkSMallocWCHAR cshFamilyName(cshFamilyNameLength+1);
442 SkSMallocWCHAR cshFaceName(cshFaceNameLength+1);
443 HRB(cshFamilyNames->GetString(0, cshFamilyName.get(), cshFamilyNameLength+1));
444 HRB(cshFaceNames->GetString(0, cshFaceName.get(), cshFaceNameLength+1));
445
446 SkSMallocWCHAR ctxFamilyName(ctxFamilyNameLength+1);
447 SkSMallocWCHAR ctxFaceName(ctxFaceNameLength+1);
448 HRB(ctxFamilyNames->GetString(0, ctxFamilyName.get(), ctxFamilyNameLength+1));
449 HRB(ctxFaceNames->GetString(0, ctxFaceName.get(), ctxFaceNameLength+1));
450
451 return wcscmp(cshFamilyName.get(), ctxFamilyName.get()) == 0 &&
452 wcscmp(cshFaceName.get(), ctxFaceName.get()) == 0;
453 }
454
makeTypefaceFromDWriteFont(IDWriteFontFace * fontFace,IDWriteFont * font,IDWriteFontFamily * fontFamily) const455 sk_sp<SkTypeface> SkFontMgr_DirectWrite::makeTypefaceFromDWriteFont(
456 IDWriteFontFace* fontFace,
457 IDWriteFont* font,
458 IDWriteFontFamily* fontFamily) const {
459 SkAutoMutexExclusive ama(fTFCacheMutex);
460 ProtoDWriteTypeface spec = { fontFace, font, fontFamily };
461 sk_sp<SkTypeface> face = fTFCache.findByProcAndRef(FindByDWriteFont, &spec);
462 if (nullptr == face) {
463 face = DWriteFontTypeface::Make(fFactory.get(), fontFace, font, fontFamily);
464 if (face) {
465 fTFCache.add(face);
466 }
467 }
468 return face;
469 }
470
onCountFamilies() const471 int SkFontMgr_DirectWrite::onCountFamilies() const {
472 return fFontCollection->GetFontFamilyCount();
473 }
474
onGetFamilyName(int index,SkString * familyName) const475 void SkFontMgr_DirectWrite::onGetFamilyName(int index, SkString* familyName) const {
476 SkTScopedComPtr<IDWriteFontFamily> fontFamily;
477 HRVM(fFontCollection->GetFontFamily(index, &fontFamily), "Could not get requested family.");
478
479 SkTScopedComPtr<IDWriteLocalizedStrings> familyNames;
480 HRVM(fontFamily->GetFamilyNames(&familyNames), "Could not get family names.");
481
482 sk_get_locale_string(familyNames.get(), fLocaleName.get(), familyName);
483 }
484
onCreateStyleSet(int index) const485 SkFontStyleSet* SkFontMgr_DirectWrite::onCreateStyleSet(int index) const {
486 SkTScopedComPtr<IDWriteFontFamily> fontFamily;
487 HRNM(fFontCollection->GetFontFamily(index, &fontFamily), "Could not get requested family.");
488
489 return new SkFontStyleSet_DirectWrite(this, fontFamily.get());
490 }
491
onMatchFamily(const char familyName[]) const492 SkFontStyleSet* SkFontMgr_DirectWrite::onMatchFamily(const char familyName[]) const {
493 if (!familyName) {
494 return nullptr;
495 }
496
497 SkSMallocWCHAR dwFamilyName;
498 HRN(sk_cstring_to_wchar(familyName, &dwFamilyName));
499
500 UINT32 index;
501 BOOL exists;
502 HRNM(fFontCollection->FindFamilyName(dwFamilyName.get(), &index, &exists),
503 "Failed while finding family by name.");
504 if (!exists) {
505 return nullptr;
506 }
507
508 return this->onCreateStyleSet(index);
509 }
510
onMatchFamilyStyle(const char familyName[],const SkFontStyle & fontstyle) const511 SkTypeface* SkFontMgr_DirectWrite::onMatchFamilyStyle(const char familyName[],
512 const SkFontStyle& fontstyle) const {
513 sk_sp<SkFontStyleSet> sset(this->matchFamily(familyName));
514 return sset->matchStyle(fontstyle);
515 }
516
517 class FontFallbackRenderer : public IDWriteTextRenderer {
518 public:
FontFallbackRenderer(const SkFontMgr_DirectWrite * outer,UINT32 character)519 FontFallbackRenderer(const SkFontMgr_DirectWrite* outer, UINT32 character)
520 : fRefCount(1), fOuter(SkSafeRef(outer)), fCharacter(character), fResolvedTypeface(nullptr) {
521 }
522
523 // IUnknown methods
QueryInterface(IID const & riid,void ** ppvObject)524 SK_STDMETHODIMP QueryInterface(IID const& riid, void** ppvObject) override {
525 if (__uuidof(IUnknown) == riid ||
526 __uuidof(IDWritePixelSnapping) == riid ||
527 __uuidof(IDWriteTextRenderer) == riid)
528 {
529 *ppvObject = this;
530 this->AddRef();
531 return S_OK;
532 }
533 *ppvObject = nullptr;
534 return E_FAIL;
535 }
536
AddRef()537 SK_STDMETHODIMP_(ULONG) AddRef() override {
538 return InterlockedIncrement(&fRefCount);
539 }
540
Release()541 SK_STDMETHODIMP_(ULONG) Release() override {
542 ULONG newCount = InterlockedDecrement(&fRefCount);
543 if (0 == newCount) {
544 delete this;
545 }
546 return newCount;
547 }
548
549 // IDWriteTextRenderer methods
DrawGlyphRun(void * clientDrawingContext,FLOAT baselineOriginX,FLOAT baselineOriginY,DWRITE_MEASURING_MODE measuringMode,DWRITE_GLYPH_RUN const * glyphRun,DWRITE_GLYPH_RUN_DESCRIPTION const * glyphRunDescription,IUnknown * clientDrawingEffect)550 SK_STDMETHODIMP DrawGlyphRun(
551 void* clientDrawingContext,
552 FLOAT baselineOriginX,
553 FLOAT baselineOriginY,
554 DWRITE_MEASURING_MODE measuringMode,
555 DWRITE_GLYPH_RUN const* glyphRun,
556 DWRITE_GLYPH_RUN_DESCRIPTION const* glyphRunDescription,
557 IUnknown* clientDrawingEffect) override
558 {
559 if (!glyphRun->fontFace) {
560 HRM(E_INVALIDARG, "Glyph run without font face.");
561 }
562
563 SkTScopedComPtr<IDWriteFont> font;
564 HRM(fOuter->fFontCollection->GetFontFromFontFace(glyphRun->fontFace, &font),
565 "Could not get font from font face.");
566
567 // It is possible that the font passed does not actually have the requested character,
568 // due to no font being found and getting the fallback font.
569 // Check that the font actually contains the requested character.
570 BOOL exists;
571 HRM(font->HasCharacter(fCharacter, &exists), "Could not find character.");
572
573 if (exists) {
574 SkTScopedComPtr<IDWriteFontFamily> fontFamily;
575 HRM(font->GetFontFamily(&fontFamily), "Could not get family.");
576 fResolvedTypeface = fOuter->makeTypefaceFromDWriteFont(glyphRun->fontFace,
577 font.get(),
578 fontFamily.get());
579 }
580
581 return S_OK;
582 }
583
DrawUnderline(void * clientDrawingContext,FLOAT baselineOriginX,FLOAT baselineOriginY,DWRITE_UNDERLINE const * underline,IUnknown * clientDrawingEffect)584 SK_STDMETHODIMP DrawUnderline(
585 void* clientDrawingContext,
586 FLOAT baselineOriginX,
587 FLOAT baselineOriginY,
588 DWRITE_UNDERLINE const* underline,
589 IUnknown* clientDrawingEffect) override
590 { return E_NOTIMPL; }
591
DrawStrikethrough(void * clientDrawingContext,FLOAT baselineOriginX,FLOAT baselineOriginY,DWRITE_STRIKETHROUGH const * strikethrough,IUnknown * clientDrawingEffect)592 SK_STDMETHODIMP DrawStrikethrough(
593 void* clientDrawingContext,
594 FLOAT baselineOriginX,
595 FLOAT baselineOriginY,
596 DWRITE_STRIKETHROUGH const* strikethrough,
597 IUnknown* clientDrawingEffect) override
598 { return E_NOTIMPL; }
599
DrawInlineObject(void * clientDrawingContext,FLOAT originX,FLOAT originY,IDWriteInlineObject * inlineObject,BOOL isSideways,BOOL isRightToLeft,IUnknown * clientDrawingEffect)600 SK_STDMETHODIMP DrawInlineObject(
601 void* clientDrawingContext,
602 FLOAT originX,
603 FLOAT originY,
604 IDWriteInlineObject* inlineObject,
605 BOOL isSideways,
606 BOOL isRightToLeft,
607 IUnknown* clientDrawingEffect) override
608 { return E_NOTIMPL; }
609
610 // IDWritePixelSnapping methods
IsPixelSnappingDisabled(void * clientDrawingContext,BOOL * isDisabled)611 SK_STDMETHODIMP IsPixelSnappingDisabled(
612 void* clientDrawingContext,
613 BOOL* isDisabled) override
614 {
615 *isDisabled = FALSE;
616 return S_OK;
617 }
618
GetCurrentTransform(void * clientDrawingContext,DWRITE_MATRIX * transform)619 SK_STDMETHODIMP GetCurrentTransform(
620 void* clientDrawingContext,
621 DWRITE_MATRIX* transform) override
622 {
623 const DWRITE_MATRIX ident = { 1.0, 0.0, 0.0, 1.0, 0.0, 0.0 };
624 *transform = ident;
625 return S_OK;
626 }
627
GetPixelsPerDip(void * clientDrawingContext,FLOAT * pixelsPerDip)628 SK_STDMETHODIMP GetPixelsPerDip(
629 void* clientDrawingContext,
630 FLOAT* pixelsPerDip) override
631 {
632 *pixelsPerDip = 1.0f;
633 return S_OK;
634 }
635
ConsumeFallbackTypeface()636 sk_sp<SkTypeface> ConsumeFallbackTypeface() { return std::move(fResolvedTypeface); }
637
638 private:
~FontFallbackRenderer()639 virtual ~FontFallbackRenderer() { }
640
641 ULONG fRefCount;
642 sk_sp<const SkFontMgr_DirectWrite> fOuter;
643 UINT32 fCharacter;
644 sk_sp<SkTypeface> fResolvedTypeface;
645 };
646
647 class FontFallbackSource : public IDWriteTextAnalysisSource {
648 public:
FontFallbackSource(const WCHAR * string,UINT32 length,const WCHAR * locale,IDWriteNumberSubstitution * numberSubstitution)649 FontFallbackSource(const WCHAR* string, UINT32 length, const WCHAR* locale,
650 IDWriteNumberSubstitution* numberSubstitution)
651 : fRefCount(1)
652 , fString(string)
653 , fLength(length)
654 , fLocale(locale)
655 , fNumberSubstitution(numberSubstitution)
656 { }
657
658 // IUnknown methods
QueryInterface(IID const & riid,void ** ppvObject)659 SK_STDMETHODIMP QueryInterface(IID const& riid, void** ppvObject) override {
660 if (__uuidof(IUnknown) == riid ||
661 __uuidof(IDWriteTextAnalysisSource) == riid)
662 {
663 *ppvObject = this;
664 this->AddRef();
665 return S_OK;
666 }
667 *ppvObject = nullptr;
668 return E_FAIL;
669 }
670
AddRef()671 SK_STDMETHODIMP_(ULONG) AddRef() override {
672 return InterlockedIncrement(&fRefCount);
673 }
674
Release()675 SK_STDMETHODIMP_(ULONG) Release() override {
676 ULONG newCount = InterlockedDecrement(&fRefCount);
677 if (0 == newCount) {
678 delete this;
679 }
680 return newCount;
681 }
682
683 // IDWriteTextAnalysisSource methods
GetTextAtPosition(UINT32 textPosition,WCHAR const ** textString,UINT32 * textLength)684 SK_STDMETHODIMP GetTextAtPosition(
685 UINT32 textPosition,
686 WCHAR const** textString,
687 UINT32* textLength) override
688 {
689 if (fLength <= textPosition) {
690 *textString = nullptr;
691 *textLength = 0;
692 return S_OK;
693 }
694 *textString = fString + textPosition;
695 *textLength = fLength - textPosition;
696 return S_OK;
697 }
698
GetTextBeforePosition(UINT32 textPosition,WCHAR const ** textString,UINT32 * textLength)699 SK_STDMETHODIMP GetTextBeforePosition(
700 UINT32 textPosition,
701 WCHAR const** textString,
702 UINT32* textLength) override
703 {
704 if (textPosition < 1 || fLength <= textPosition) {
705 *textString = nullptr;
706 *textLength = 0;
707 return S_OK;
708 }
709 *textString = fString;
710 *textLength = textPosition;
711 return S_OK;
712 }
713
GetParagraphReadingDirection()714 SK_STDMETHODIMP_(DWRITE_READING_DIRECTION) GetParagraphReadingDirection() override {
715 // TODO: this is also interesting.
716 return DWRITE_READING_DIRECTION_LEFT_TO_RIGHT;
717 }
718
GetLocaleName(UINT32 textPosition,UINT32 * textLength,WCHAR const ** localeName)719 SK_STDMETHODIMP GetLocaleName(
720 UINT32 textPosition,
721 UINT32* textLength,
722 WCHAR const** localeName) override
723 {
724 *localeName = fLocale;
725 return S_OK;
726 }
727
GetNumberSubstitution(UINT32 textPosition,UINT32 * textLength,IDWriteNumberSubstitution ** numberSubstitution)728 SK_STDMETHODIMP GetNumberSubstitution(
729 UINT32 textPosition,
730 UINT32* textLength,
731 IDWriteNumberSubstitution** numberSubstitution) override
732 {
733 *numberSubstitution = fNumberSubstitution;
734 return S_OK;
735 }
736
737 private:
~FontFallbackSource()738 virtual ~FontFallbackSource() { }
739
740 ULONG fRefCount;
741 const WCHAR* fString;
742 UINT32 fLength;
743 const WCHAR* fLocale;
744 IDWriteNumberSubstitution* fNumberSubstitution;
745 };
746
onMatchFamilyStyleCharacter(const char familyName[],const SkFontStyle & style,const char * bcp47[],int bcp47Count,SkUnichar character) const747 SkTypeface* SkFontMgr_DirectWrite::onMatchFamilyStyleCharacter(const char familyName[],
748 const SkFontStyle& style,
749 const char* bcp47[], int bcp47Count,
750 SkUnichar character) const
751 {
752 const DWriteStyle dwStyle(style);
753
754 const WCHAR* dwFamilyName = nullptr;
755 SkSMallocWCHAR dwFamilyNameLocal;
756 if (familyName) {
757 HRN(sk_cstring_to_wchar(familyName, &dwFamilyNameLocal));
758 dwFamilyName = dwFamilyNameLocal;
759 }
760
761 const SkSMallocWCHAR* dwBcp47;
762 SkSMallocWCHAR dwBcp47Local;
763 if (bcp47Count < 1) {
764 dwBcp47 = &fLocaleName;
765 } else {
766 // TODO: support fallback stack.
767 // TODO: DirectWrite supports 'zh-CN' or 'zh-Hans', but 'zh' misses completely
768 // and may produce a Japanese font.
769 HRN(sk_cstring_to_wchar(bcp47[bcp47Count - 1], &dwBcp47Local));
770 dwBcp47 = &dwBcp47Local;
771 }
772
773 if (fFontFallback) {
774 return this->fallback(dwFamilyName, dwStyle, dwBcp47->get(), character).release();
775 }
776
777 // LayoutFallback may use the system font collection for fallback.
778 return this->layoutFallback(dwFamilyName, dwStyle, dwBcp47->get(), character).release();
779 }
780
fallback(const WCHAR * dwFamilyName,DWriteStyle dwStyle,const WCHAR * dwBcp47,UINT32 character) const781 sk_sp<SkTypeface> SkFontMgr_DirectWrite::fallback(const WCHAR* dwFamilyName,
782 DWriteStyle dwStyle,
783 const WCHAR* dwBcp47,
784 UINT32 character) const
785 {
786 WCHAR str[16];
787 UINT32 strLen = SkTo<UINT32>(SkUTF::ToUTF16(character, reinterpret_cast<uint16_t*>(str)));
788
789 if (!fFontFallback) {
790 return nullptr;
791 }
792
793 SkTScopedComPtr<IDWriteNumberSubstitution> numberSubstitution;
794 HRNM(fFactory->CreateNumberSubstitution(DWRITE_NUMBER_SUBSTITUTION_METHOD_NONE, dwBcp47,
795 TRUE, &numberSubstitution),
796 "Could not create number substitution.");
797 SkTScopedComPtr<FontFallbackSource> fontFallbackSource(
798 new FontFallbackSource(str, strLen, dwBcp47, numberSubstitution.get()));
799
800 UINT32 mappedLength;
801 SkTScopedComPtr<IDWriteFont> font;
802 FLOAT scale;
803 HRNM(fFontFallback->MapCharacters(fontFallbackSource.get(),
804 0, // textPosition,
805 strLen,
806 fFontCollection.get(),
807 dwFamilyName,
808 dwStyle.fWeight,
809 dwStyle.fSlant,
810 dwStyle.fWidth,
811 &mappedLength,
812 &font,
813 &scale),
814 "Could not map characters");
815 if (!font.get()) {
816 return nullptr;
817 }
818
819 SkTScopedComPtr<IDWriteFontFace> fontFace;
820 HRNM(font->CreateFontFace(&fontFace), "Could not get font face from font.");
821
822 SkTScopedComPtr<IDWriteFontFamily> fontFamily;
823 HRNM(font->GetFontFamily(&fontFamily), "Could not get family from font.");
824 return this->makeTypefaceFromDWriteFont(fontFace.get(), font.get(), fontFamily.get());
825 }
826
layoutFallback(const WCHAR * dwFamilyName,DWriteStyle dwStyle,const WCHAR * dwBcp47,UINT32 character) const827 sk_sp<SkTypeface> SkFontMgr_DirectWrite::layoutFallback(const WCHAR* dwFamilyName,
828 DWriteStyle dwStyle,
829 const WCHAR* dwBcp47,
830 UINT32 character) const
831 {
832 WCHAR str[16];
833 UINT32 strLen = SkTo<UINT32>(SkUTF::ToUTF16(character, reinterpret_cast<uint16_t*>(str)));
834
835 SkTScopedComPtr<IDWriteTextFormat> fallbackFormat;
836 HRNM(fFactory->CreateTextFormat(dwFamilyName ? dwFamilyName : L"",
837 fFontCollection.get(),
838 dwStyle.fWeight,
839 dwStyle.fSlant,
840 dwStyle.fWidth,
841 72.0f,
842 dwBcp47,
843 &fallbackFormat),
844 "Could not create text format.");
845
846 // No matter how the font collection is set on this IDWriteTextLayout, it is not possible to
847 // disable use of the system font collection in fallback.
848 SkTScopedComPtr<IDWriteTextLayout> fallbackLayout;
849 HRNM(fFactory->CreateTextLayout(str, strLen, fallbackFormat.get(),
850 200.0f, 200.0f,
851 &fallbackLayout),
852 "Could not create text layout.");
853
854 SkTScopedComPtr<FontFallbackRenderer> fontFallbackRenderer(
855 new FontFallbackRenderer(this, character));
856
857 HRNM(fallbackLayout->SetFontCollection(fFontCollection.get(), { 0, strLen }),
858 "Could not set layout font collection.");
859 HRNM(fallbackLayout->Draw(nullptr, fontFallbackRenderer.get(), 50.0f, 50.0f),
860 "Could not draw layout with renderer.");
861
862 return fontFallbackRenderer->ConsumeFallbackTypeface();
863 }
864
onMatchFaceStyle(const SkTypeface * familyMember,const SkFontStyle & fontstyle) const865 SkTypeface* SkFontMgr_DirectWrite::onMatchFaceStyle(const SkTypeface* familyMember,
866 const SkFontStyle& fontstyle) const {
867 SkString familyName;
868 SkFontStyleSet_DirectWrite sset(
869 this, ((DWriteFontTypeface*)familyMember)->fDWriteFontFamily.get()
870 );
871 return sset.matchStyle(fontstyle);
872 }
873
874 template <typename T> class SkAutoIDWriteUnregister {
875 public:
SkAutoIDWriteUnregister(IDWriteFactory * factory,T * unregister)876 SkAutoIDWriteUnregister(IDWriteFactory* factory, T* unregister)
877 : fFactory(factory), fUnregister(unregister)
878 { }
879
~SkAutoIDWriteUnregister()880 ~SkAutoIDWriteUnregister() {
881 if (fUnregister) {
882 unregister(fFactory, fUnregister);
883 }
884 }
885
detatch()886 T* detatch() {
887 T* old = fUnregister;
888 fUnregister = nullptr;
889 return old;
890 }
891
892 private:
unregister(IDWriteFactory * factory,IDWriteFontFileLoader * unregister)893 HRESULT unregister(IDWriteFactory* factory, IDWriteFontFileLoader* unregister) {
894 return factory->UnregisterFontFileLoader(unregister);
895 }
896
unregister(IDWriteFactory * factory,IDWriteFontCollectionLoader * unregister)897 HRESULT unregister(IDWriteFactory* factory, IDWriteFontCollectionLoader* unregister) {
898 return factory->UnregisterFontCollectionLoader(unregister);
899 }
900
901 IDWriteFactory* fFactory;
902 T* fUnregister;
903 };
904
onMakeFromStreamIndex(std::unique_ptr<SkStreamAsset> stream,int ttcIndex) const905 sk_sp<SkTypeface> SkFontMgr_DirectWrite::onMakeFromStreamIndex(std::unique_ptr<SkStreamAsset> stream,
906 int ttcIndex) const {
907 SkTScopedComPtr<StreamFontFileLoader> fontFileLoader;
908 // This transfers ownership of stream to the new object.
909 HRN(StreamFontFileLoader::Create(std::move(stream), &fontFileLoader));
910 HRN(fFactory->RegisterFontFileLoader(fontFileLoader.get()));
911 SkAutoIDWriteUnregister<StreamFontFileLoader> autoUnregisterFontFileLoader(
912 fFactory.get(), fontFileLoader.get());
913
914 SkTScopedComPtr<StreamFontCollectionLoader> fontCollectionLoader;
915 HRN(StreamFontCollectionLoader::Create(fontFileLoader.get(), &fontCollectionLoader));
916 HRN(fFactory->RegisterFontCollectionLoader(fontCollectionLoader.get()));
917 SkAutoIDWriteUnregister<StreamFontCollectionLoader> autoUnregisterFontCollectionLoader(
918 fFactory.get(), fontCollectionLoader.get());
919
920 SkTScopedComPtr<IDWriteFontCollection> fontCollection;
921 HRN(fFactory->CreateCustomFontCollection(fontCollectionLoader.get(), nullptr, 0, &fontCollection));
922
923 // Find the first non-simulated font which has the given ttc index.
924 UINT32 familyCount = fontCollection->GetFontFamilyCount();
925 for (UINT32 familyIndex = 0; familyIndex < familyCount; ++familyIndex) {
926 SkTScopedComPtr<IDWriteFontFamily> fontFamily;
927 HRN(fontCollection->GetFontFamily(familyIndex, &fontFamily));
928
929 UINT32 fontCount = fontFamily->GetFontCount();
930 for (UINT32 fontIndex = 0; fontIndex < fontCount; ++fontIndex) {
931 SkTScopedComPtr<IDWriteFont> font;
932 HRN(fontFamily->GetFont(fontIndex, &font));
933 if (font->GetSimulations() != DWRITE_FONT_SIMULATIONS_NONE) {
934 continue;
935 }
936
937 SkTScopedComPtr<IDWriteFontFace> fontFace;
938 HRN(font->CreateFontFace(&fontFace));
939
940 int faceIndex = fontFace->GetIndex();
941 if (faceIndex == ttcIndex) {
942 return DWriteFontTypeface::Make(fFactory.get(),
943 fontFace.get(), font.get(), fontFamily.get(),
944 autoUnregisterFontFileLoader.detatch(),
945 autoUnregisterFontCollectionLoader.detatch());
946 }
947 }
948 }
949
950 return nullptr;
951 }
952
onMakeFromStreamArgs(std::unique_ptr<SkStreamAsset> stream,const SkFontArguments & args) const953 sk_sp<SkTypeface> SkFontMgr_DirectWrite::onMakeFromStreamArgs(std::unique_ptr<SkStreamAsset> stream,
954 const SkFontArguments& args) const {
955 SkTScopedComPtr<StreamFontFileLoader> fontFileLoader;
956 // This transfers ownership of stream to the new object.
957 HRN(StreamFontFileLoader::Create(std::move(stream), &fontFileLoader));
958 HRN(fFactory->RegisterFontFileLoader(fontFileLoader.get()));
959 SkAutoIDWriteUnregister<StreamFontFileLoader> autoUnregisterFontFileLoader(
960 fFactory.get(), fontFileLoader.get());
961
962 SkTScopedComPtr<StreamFontCollectionLoader> fontCollectionLoader;
963 HRN(StreamFontCollectionLoader::Create(fontFileLoader.get(), &fontCollectionLoader));
964 HRN(fFactory->RegisterFontCollectionLoader(fontCollectionLoader.get()));
965 SkAutoIDWriteUnregister<StreamFontCollectionLoader> autoUnregisterFontCollectionLoader(
966 fFactory.get(), fontCollectionLoader.get());
967
968 SkTScopedComPtr<IDWriteFontCollection> fontCollection;
969 HRN(fFactory->CreateCustomFontCollection(fontCollectionLoader.get(), nullptr, 0,
970 &fontCollection));
971
972 // Find the first non-simulated font which has the given ttc index.
973 UINT32 familyCount = fontCollection->GetFontFamilyCount();
974 for (UINT32 familyIndex = 0; familyIndex < familyCount; ++familyIndex) {
975 SkTScopedComPtr<IDWriteFontFamily> fontFamily;
976 HRN(fontCollection->GetFontFamily(familyIndex, &fontFamily));
977
978 UINT32 fontCount = fontFamily->GetFontCount();
979 for (UINT32 fontIndex = 0; fontIndex < fontCount; ++fontIndex) {
980 SkTScopedComPtr<IDWriteFont> font;
981 HRN(fontFamily->GetFont(fontIndex, &font));
982
983 // Skip if the current font is simulated
984 if (font->GetSimulations() != DWRITE_FONT_SIMULATIONS_NONE) {
985 continue;
986 }
987 SkTScopedComPtr<IDWriteFontFace> fontFace;
988 HRN(font->CreateFontFace(&fontFace));
989 int faceIndex = fontFace->GetIndex();
990 int ttcIndex = args.getCollectionIndex();
991
992 // Skip if the current face index does not match the ttcIndex
993 if (faceIndex != ttcIndex) {
994 continue;
995 }
996
997 #if defined(NTDDI_WIN10_RS3) && NTDDI_VERSION >= NTDDI_WIN10_RS3
998
999 SkTScopedComPtr<IDWriteFontFace5> fontFace5;
1000 if (SUCCEEDED(fontFace->QueryInterface(&fontFace5)) && fontFace5->HasVariations()) {
1001 UINT32 fontAxisCount = fontFace5->GetFontAxisValueCount();
1002 UINT32 argsCoordCount = args.getVariationDesignPosition().coordinateCount;
1003 SkAutoSTMalloc<8, DWRITE_FONT_AXIS_VALUE> fontAxisValues(fontAxisCount);
1004 SkTScopedComPtr<IDWriteFontResource> fontResource;
1005 HRN(fontFace5->GetFontResource(&fontResource));
1006 // Set all axes by default values
1007 HRN(fontResource->GetDefaultFontAxisValues(fontAxisValues, fontAxisCount));
1008
1009 for (UINT32 fontIndex = 0; fontIndex < fontAxisCount; ++fontIndex) {
1010 for (UINT32 argsIndex = 0; argsIndex < argsCoordCount; ++argsIndex) {
1011 if (SkEndian_SwapBE32(fontAxisValues[fontIndex].axisTag) ==
1012 args.getVariationDesignPosition().coordinates[argsIndex].axis) {
1013 fontAxisValues[fontIndex].value =
1014 args.getVariationDesignPosition().coordinates[argsIndex].value;
1015 }
1016 }
1017 }
1018
1019 SkTScopedComPtr<IDWriteFontFace5> fontFace5_Out;
1020 HRN(fontResource->CreateFontFace(DWRITE_FONT_SIMULATIONS_NONE,
1021 fontAxisValues.get(),
1022 fontAxisCount,
1023 &fontFace5_Out));
1024 fontFace.reset();
1025 HRN(fontFace5_Out->QueryInterface(&fontFace));
1026 }
1027
1028 #endif
1029
1030 return DWriteFontTypeface::Make(
1031 fFactory.get(), fontFace.get(), font.get(), fontFamily.get(),
1032 autoUnregisterFontFileLoader.detatch(),
1033 autoUnregisterFontCollectionLoader.detatch());
1034 }
1035 }
1036
1037 return nullptr;
1038 }
1039
onMakeFromData(sk_sp<SkData> data,int ttcIndex) const1040 sk_sp<SkTypeface> SkFontMgr_DirectWrite::onMakeFromData(sk_sp<SkData> data, int ttcIndex) const {
1041 return this->makeFromStream(skstd::make_unique<SkMemoryStream>(std::move(data)), ttcIndex);
1042 }
1043
onMakeFromFile(const char path[],int ttcIndex) const1044 sk_sp<SkTypeface> SkFontMgr_DirectWrite::onMakeFromFile(const char path[], int ttcIndex) const {
1045 return this->makeFromStream(SkStream::MakeFromFile(path), ttcIndex);
1046 }
1047
getByFamilyName(const WCHAR wideFamilyName[],IDWriteFontFamily ** fontFamily) const1048 HRESULT SkFontMgr_DirectWrite::getByFamilyName(const WCHAR wideFamilyName[],
1049 IDWriteFontFamily** fontFamily) const {
1050 UINT32 index;
1051 BOOL exists;
1052 HR(fFontCollection->FindFamilyName(wideFamilyName, &index, &exists));
1053
1054 if (exists) {
1055 HR(fFontCollection->GetFontFamily(index, fontFamily));
1056 }
1057 return S_OK;
1058 }
1059
onLegacyMakeTypeface(const char familyName[],SkFontStyle style) const1060 sk_sp<SkTypeface> SkFontMgr_DirectWrite::onLegacyMakeTypeface(const char familyName[],
1061 SkFontStyle style) const {
1062 SkTScopedComPtr<IDWriteFontFamily> fontFamily;
1063 const DWriteStyle dwStyle(style);
1064 if (familyName) {
1065 SkSMallocWCHAR dwFamilyName;
1066 if (SUCCEEDED(sk_cstring_to_wchar(familyName, &dwFamilyName))) {
1067 this->getByFamilyName(dwFamilyName, &fontFamily);
1068 if (!fontFamily && fFontFallback) {
1069 return this->fallback(dwFamilyName, dwStyle, fLocaleName.get(), 32);
1070 }
1071 }
1072 }
1073
1074 if (!fontFamily) {
1075 if (fFontFallback) {
1076 return this->fallback(nullptr, dwStyle, fLocaleName.get(), 32);
1077 }
1078 // SPI_GETNONCLIENTMETRICS lfMessageFont can fail in Win8. (DisallowWin32kSystemCalls)
1079 // layoutFallback causes DCHECK in Chromium. (Uses system font collection.)
1080 HRNM(this->getByFamilyName(fDefaultFamilyName, &fontFamily),
1081 "Could not create DWrite font family from LOGFONT.");
1082 }
1083
1084 if (!fontFamily) {
1085 // Could not obtain the default font.
1086 HRNM(fFontCollection->GetFontFamily(0, &fontFamily),
1087 "Could not get default-default font family.");
1088 }
1089
1090 SkTScopedComPtr<IDWriteFont> font;
1091 HRNM(fontFamily->GetFirstMatchingFont(dwStyle.fWeight, dwStyle.fWidth, dwStyle.fSlant, &font),
1092 "Could not get matching font.");
1093
1094 SkTScopedComPtr<IDWriteFontFace> fontFace;
1095 HRNM(font->CreateFontFace(&fontFace), "Could not create font face.");
1096
1097 return this->makeTypefaceFromDWriteFont(fontFace.get(), font.get(), fontFamily.get());
1098 }
1099
1100 ///////////////////////////////////////////////////////////////////////////////
1101
count()1102 int SkFontStyleSet_DirectWrite::count() {
1103 return fFontFamily->GetFontCount();
1104 }
1105
createTypeface(int index)1106 SkTypeface* SkFontStyleSet_DirectWrite::createTypeface(int index) {
1107 SkTScopedComPtr<IDWriteFont> font;
1108 HRNM(fFontFamily->GetFont(index, &font), "Could not get font.");
1109
1110 SkTScopedComPtr<IDWriteFontFace> fontFace;
1111 HRNM(font->CreateFontFace(&fontFace), "Could not create font face.");
1112
1113 return fFontMgr->makeTypefaceFromDWriteFont(fontFace.get(), font.get(), fFontFamily.get()).release();
1114 }
1115
getStyle(int index,SkFontStyle * fs,SkString * styleName)1116 void SkFontStyleSet_DirectWrite::getStyle(int index, SkFontStyle* fs, SkString* styleName) {
1117 SkTScopedComPtr<IDWriteFont> font;
1118 HRVM(fFontFamily->GetFont(index, &font), "Could not get font.");
1119
1120 if (fs) {
1121 *fs = get_style(font.get());
1122 }
1123
1124 if (styleName) {
1125 SkTScopedComPtr<IDWriteLocalizedStrings> faceNames;
1126 if (SUCCEEDED(font->GetFaceNames(&faceNames))) {
1127 sk_get_locale_string(faceNames.get(), fFontMgr->fLocaleName.get(), styleName);
1128 }
1129 }
1130 }
1131
matchStyle(const SkFontStyle & pattern)1132 SkTypeface* SkFontStyleSet_DirectWrite::matchStyle(const SkFontStyle& pattern) {
1133 SkTScopedComPtr<IDWriteFont> font;
1134 DWriteStyle dwStyle(pattern);
1135 // TODO: perhaps use GetMatchingFonts and get the least simulated?
1136 HRNM(fFontFamily->GetFirstMatchingFont(dwStyle.fWeight, dwStyle.fWidth, dwStyle.fSlant, &font),
1137 "Could not match font in family.");
1138
1139 SkTScopedComPtr<IDWriteFontFace> fontFace;
1140 HRNM(font->CreateFontFace(&fontFace), "Could not create font face.");
1141
1142 return fFontMgr->makeTypefaceFromDWriteFont(fontFace.get(), font.get(),
1143 fFontFamily.get()).release();
1144 }
1145
1146 ////////////////////////////////////////////////////////////////////////////////
1147 #include "include/ports/SkTypeface_win.h"
1148
SkFontMgr_New_DirectWrite(IDWriteFactory * factory,IDWriteFontCollection * collection)1149 SK_API sk_sp<SkFontMgr> SkFontMgr_New_DirectWrite(IDWriteFactory* factory,
1150 IDWriteFontCollection* collection) {
1151 return SkFontMgr_New_DirectWrite(factory, collection, nullptr);
1152 }
1153
SkFontMgr_New_DirectWrite(IDWriteFactory * factory,IDWriteFontCollection * collection,IDWriteFontFallback * fallback)1154 SK_API sk_sp<SkFontMgr> SkFontMgr_New_DirectWrite(IDWriteFactory* factory,
1155 IDWriteFontCollection* collection,
1156 IDWriteFontFallback* fallback) {
1157 if (nullptr == factory) {
1158 factory = sk_get_dwrite_factory();
1159 if (nullptr == factory) {
1160 return nullptr;
1161 }
1162 }
1163
1164 SkTScopedComPtr<IDWriteFontCollection> systemFontCollection;
1165 if (nullptr == collection) {
1166 HRNM(factory->GetSystemFontCollection(&systemFontCollection, FALSE),
1167 "Could not get system font collection.");
1168 collection = systemFontCollection.get();
1169 }
1170
1171 // It is possible to have been provided a font fallback when factory2 is not available.
1172 SkTScopedComPtr<IDWriteFontFallback> systemFontFallback;
1173 if (nullptr == fallback) {
1174 SkTScopedComPtr<IDWriteFactory2> factory2;
1175 if (!SUCCEEDED(factory->QueryInterface(&factory2))) {
1176 // IUnknown::QueryInterface states that if it fails, punk will be set to nullptr.
1177 // http://blogs.msdn.com/b/oldnewthing/archive/2004/03/26/96777.aspx
1178 SkASSERT_RELEASE(nullptr == factory2.get());
1179 } else {
1180 HRNM(factory2->GetSystemFontFallback(&systemFontFallback),
1181 "Could not get system fallback.");
1182 fallback = systemFontFallback.get();
1183 }
1184 }
1185
1186 const WCHAR* defaultFamilyName = L"";
1187 int defaultFamilyNameLen = 1;
1188 NONCLIENTMETRICSW metrics;
1189 metrics.cbSize = sizeof(metrics);
1190 if (nullptr == fallback) {
1191 if (SystemParametersInfoW(SPI_GETNONCLIENTMETRICS, sizeof(metrics), &metrics, 0)) {
1192 defaultFamilyName = metrics.lfMessageFont.lfFaceName;
1193 defaultFamilyNameLen = LF_FACESIZE;
1194 }
1195 }
1196
1197 WCHAR localeNameStorage[LOCALE_NAME_MAX_LENGTH];
1198 const WCHAR* localeName = L"";
1199 int localeNameLen = 1;
1200
1201 // Dynamically load GetUserDefaultLocaleName function, as it is not available on XP.
1202 SkGetUserDefaultLocaleNameProc getUserDefaultLocaleNameProc = nullptr;
1203 HRESULT hr = SkGetGetUserDefaultLocaleNameProc(&getUserDefaultLocaleNameProc);
1204 if (nullptr == getUserDefaultLocaleNameProc) {
1205 SK_TRACEHR(hr, "Could not get GetUserDefaultLocaleName.");
1206 } else {
1207 int size = getUserDefaultLocaleNameProc(localeNameStorage, LOCALE_NAME_MAX_LENGTH);
1208 if (size) {
1209 localeName = localeNameStorage;
1210 localeNameLen = size;
1211 }
1212 }
1213
1214 return sk_make_sp<SkFontMgr_DirectWrite>(factory, collection, fallback,
1215 localeName, localeNameLen,
1216 defaultFamilyName, defaultFamilyNameLen);
1217 }
1218
1219 #include "include/ports/SkFontMgr_indirect.h"
SkFontMgr_New_DirectWriteRenderer(sk_sp<SkRemotableFontMgr> proxy)1220 SK_API sk_sp<SkFontMgr> SkFontMgr_New_DirectWriteRenderer(sk_sp<SkRemotableFontMgr> proxy) {
1221 sk_sp<SkFontMgr> impl(SkFontMgr_New_DirectWrite());
1222 if (!impl) {
1223 return nullptr;
1224 }
1225 return sk_make_sp<SkFontMgr_Indirect>(std::move(impl), std::move(proxy));
1226 }
1227 #endif//defined(SK_BUILD_FOR_WIN)
1228