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