• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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