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