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