• 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 "SkDWrite.h"
9 #include "SkDWriteFontFileStream.h"
10 #include "SkFontMgr.h"
11 #include "SkHRESULT.h"
12 #include "SkStream.h"
13 #include "SkTScopedComPtr.h"
14 #include "SkThread.h"
15 #include "SkTypeface.h"
16 #include "SkTypefaceCache.h"
17 #include "SkTypeface_win_dw.h"
18 #include "SkTypes.h"
19 #include "SkUtils.h"
20 
21 #include <dwrite.h>
22 
23 #if SK_HAS_DWRITE_2_H
24 #include <dwrite_2.h>
25 #endif
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 (NULL == streamFontFileLoader) {
46             return E_OUTOFMEMORY;
47         }
48         return S_OK;
49     }
50 
51     SkAutoTDelete<SkStreamAsset> fStream;
52 
53 private:
StreamFontFileLoader(SkStreamAsset * stream)54     StreamFontFileLoader(SkStreamAsset* stream) : fRefCount(1), fStream(stream) { }
~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 = NULL;
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 (NULL == 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 = NULL;
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 NULL
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() == NULL) {
180         *fontFile = NULL;
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 (NULL == 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 = NULL;
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,WCHAR * localeName,int localeNameLength)263     SkFontMgr_DirectWrite(IDWriteFactory* factory, IDWriteFontCollection* fontCollection,
264                           WCHAR* localeName, int localeNameLength)
265         : fFactory(SkRefComPtr(factory))
266         , fFontCollection(SkRefComPtr(fontCollection))
267         , fLocaleName(localeNameLength)
268     {
269 #if SK_HAS_DWRITE_2_H
270         if (!SUCCEEDED(fFactory->QueryInterface(&fFactory2))) {
271             // IUnknown::QueryInterface states that if it fails, punk will be set to NULL.
272             // http://blogs.msdn.com/b/oldnewthing/archive/2004/03/26/96777.aspx
273             SK_ALWAYSBREAK(NULL == fFactory2.get());
274         }
275 #endif
276         memcpy(fLocaleName.get(), localeName, localeNameLength * sizeof(WCHAR));
277     }
278 
279 protected:
280     int onCountFamilies() const override;
281     void onGetFamilyName(int index, SkString* familyName) const override;
282     SkFontStyleSet* onCreateStyleSet(int index) const override;
283     SkFontStyleSet* onMatchFamily(const char familyName[]) const override;
284     virtual SkTypeface* onMatchFamilyStyle(const char familyName[],
285                                            const SkFontStyle& fontstyle) const override;
286     virtual SkTypeface* onMatchFamilyStyleCharacter(const char familyName[], const SkFontStyle&,
287                                                     const char* bcp47[], int bcp47Count,
288                                                     SkUnichar character) const override;
289     virtual SkTypeface* onMatchFaceStyle(const SkTypeface* familyMember,
290                                          const SkFontStyle& fontstyle) const override;
291     SkTypeface* onCreateFromStream(SkStreamAsset* stream, int ttcIndex) const override;
292     SkTypeface* onCreateFromData(SkData* data, int ttcIndex) const override;
293     SkTypeface* onCreateFromFile(const char path[], int ttcIndex) const override;
294     virtual SkTypeface* onLegacyCreateTypeface(const char familyName[],
295                                                unsigned styleBits) const override;
296 
297 private:
298     HRESULT getByFamilyName(const WCHAR familyName[], IDWriteFontFamily** fontFamily) const;
299     HRESULT getDefaultFontFamily(IDWriteFontFamily** fontFamily) const;
300 
301     /** Creates a typeface using a typeface cache. */
302     SkTypeface* createTypefaceFromDWriteFont(IDWriteFontFace* fontFace,
303                                              IDWriteFont* font,
304                                              IDWriteFontFamily* fontFamily) const;
305 
306     SkTScopedComPtr<IDWriteFactory> fFactory;
307 #if SK_HAS_DWRITE_2_H
308     SkTScopedComPtr<IDWriteFactory2> fFactory2;
309 #endif
310     SkTScopedComPtr<IDWriteFontCollection> fFontCollection;
311     SkSMallocWCHAR fLocaleName;
312     mutable SkMutex fTFCacheMutex;
313     mutable SkTypefaceCache fTFCache;
314 
315     friend class SkFontStyleSet_DirectWrite;
316     friend class FontFallbackRenderer;
317 };
318 
319 class SkFontStyleSet_DirectWrite : public SkFontStyleSet {
320 public:
SkFontStyleSet_DirectWrite(const SkFontMgr_DirectWrite * fontMgr,IDWriteFontFamily * fontFamily)321     SkFontStyleSet_DirectWrite(const SkFontMgr_DirectWrite* fontMgr,
322                                IDWriteFontFamily* fontFamily)
323         : fFontMgr(SkRef(fontMgr))
324         , fFontFamily(SkRefComPtr(fontFamily))
325     { }
326 
327     int count() override;
328     void getStyle(int index, SkFontStyle* fs, SkString* styleName) override;
329     SkTypeface* createTypeface(int index) override;
330     SkTypeface* matchStyle(const SkFontStyle& pattern) override;
331 
332 private:
333     SkAutoTUnref<const SkFontMgr_DirectWrite> fFontMgr;
334     SkTScopedComPtr<IDWriteFontFamily> fFontFamily;
335 };
336 
are_same(IUnknown * a,IUnknown * b,bool & same)337 static HRESULT are_same(IUnknown* a, IUnknown* b, bool& same) {
338     SkTScopedComPtr<IUnknown> iunkA;
339     HRM(a->QueryInterface(&iunkA), "Failed to QI<IUnknown> for a.");
340 
341     SkTScopedComPtr<IUnknown> iunkB;
342     HRM(b->QueryInterface(&iunkB), "Failed to QI<IUnknown> for b.");
343 
344     same = (iunkA.get() == iunkB.get());
345     return S_OK;
346 }
347 
348 struct ProtoDWriteTypeface {
349     IDWriteFontFace* fDWriteFontFace;
350     IDWriteFont* fDWriteFont;
351     IDWriteFontFamily* fDWriteFontFamily;
352 };
353 
FindByDWriteFont(SkTypeface * cached,const SkFontStyle &,void * ctx)354 static bool FindByDWriteFont(SkTypeface* cached, const SkFontStyle&, void* ctx) {
355     DWriteFontTypeface* cshFace = reinterpret_cast<DWriteFontTypeface*>(cached);
356     ProtoDWriteTypeface* ctxFace = reinterpret_cast<ProtoDWriteTypeface*>(ctx);
357     bool same;
358 
359     //Check to see if the two fonts are identical.
360     HRB(are_same(cshFace->fDWriteFont.get(), ctxFace->fDWriteFont, same));
361     if (same) {
362         return true;
363     }
364 
365     HRB(are_same(cshFace->fDWriteFontFace.get(), ctxFace->fDWriteFontFace, same));
366     if (same) {
367         return true;
368     }
369 
370     //Check if the two fonts share the same loader and have the same key.
371     UINT32 cshNumFiles;
372     UINT32 ctxNumFiles;
373     HRB(cshFace->fDWriteFontFace->GetFiles(&cshNumFiles, NULL));
374     HRB(ctxFace->fDWriteFontFace->GetFiles(&ctxNumFiles, NULL));
375     if (cshNumFiles != ctxNumFiles) {
376         return false;
377     }
378 
379     SkTScopedComPtr<IDWriteFontFile> cshFontFile;
380     SkTScopedComPtr<IDWriteFontFile> ctxFontFile;
381     HRB(cshFace->fDWriteFontFace->GetFiles(&cshNumFiles, &cshFontFile));
382     HRB(ctxFace->fDWriteFontFace->GetFiles(&ctxNumFiles, &ctxFontFile));
383 
384     //for (each file) { //we currently only admit fonts from one file.
385     SkTScopedComPtr<IDWriteFontFileLoader> cshFontFileLoader;
386     SkTScopedComPtr<IDWriteFontFileLoader> ctxFontFileLoader;
387     HRB(cshFontFile->GetLoader(&cshFontFileLoader));
388     HRB(ctxFontFile->GetLoader(&ctxFontFileLoader));
389     HRB(are_same(cshFontFileLoader.get(), ctxFontFileLoader.get(), same));
390     if (!same) {
391         return false;
392     }
393     //}
394 
395     const void* cshRefKey;
396     UINT32 cshRefKeySize;
397     const void* ctxRefKey;
398     UINT32 ctxRefKeySize;
399     HRB(cshFontFile->GetReferenceKey(&cshRefKey, &cshRefKeySize));
400     HRB(ctxFontFile->GetReferenceKey(&ctxRefKey, &ctxRefKeySize));
401     if (cshRefKeySize != ctxRefKeySize) {
402         return false;
403     }
404     if (0 != memcmp(cshRefKey, ctxRefKey, ctxRefKeySize)) {
405         return false;
406     }
407 
408     //TODO: better means than comparing name strings?
409     //NOTE: .ttc and fake bold/italic will end up here.
410     SkTScopedComPtr<IDWriteLocalizedStrings> cshFamilyNames;
411     SkTScopedComPtr<IDWriteLocalizedStrings> cshFaceNames;
412     HRB(cshFace->fDWriteFontFamily->GetFamilyNames(&cshFamilyNames));
413     HRB(cshFace->fDWriteFont->GetFaceNames(&cshFaceNames));
414     UINT32 cshFamilyNameLength;
415     UINT32 cshFaceNameLength;
416     HRB(cshFamilyNames->GetStringLength(0, &cshFamilyNameLength));
417     HRB(cshFaceNames->GetStringLength(0, &cshFaceNameLength));
418 
419     SkTScopedComPtr<IDWriteLocalizedStrings> ctxFamilyNames;
420     SkTScopedComPtr<IDWriteLocalizedStrings> ctxFaceNames;
421     HRB(ctxFace->fDWriteFontFamily->GetFamilyNames(&ctxFamilyNames));
422     HRB(ctxFace->fDWriteFont->GetFaceNames(&ctxFaceNames));
423     UINT32 ctxFamilyNameLength;
424     UINT32 ctxFaceNameLength;
425     HRB(ctxFamilyNames->GetStringLength(0, &ctxFamilyNameLength));
426     HRB(ctxFaceNames->GetStringLength(0, &ctxFaceNameLength));
427 
428     if (cshFamilyNameLength != ctxFamilyNameLength ||
429         cshFaceNameLength != ctxFaceNameLength)
430     {
431         return false;
432     }
433 
434     SkSMallocWCHAR cshFamilyName(cshFamilyNameLength+1);
435     SkSMallocWCHAR cshFaceName(cshFaceNameLength+1);
436     HRB(cshFamilyNames->GetString(0, cshFamilyName.get(), cshFamilyNameLength+1));
437     HRB(cshFaceNames->GetString(0, cshFaceName.get(), cshFaceNameLength+1));
438 
439     SkSMallocWCHAR ctxFamilyName(ctxFamilyNameLength+1);
440     SkSMallocWCHAR ctxFaceName(ctxFaceNameLength+1);
441     HRB(ctxFamilyNames->GetString(0, ctxFamilyName.get(), ctxFamilyNameLength+1));
442     HRB(ctxFaceNames->GetString(0, ctxFaceName.get(), ctxFaceNameLength+1));
443 
444     return wcscmp(cshFamilyName.get(), ctxFamilyName.get()) == 0 &&
445            wcscmp(cshFaceName.get(), ctxFaceName.get()) == 0;
446 }
447 
createTypefaceFromDWriteFont(IDWriteFontFace * fontFace,IDWriteFont * font,IDWriteFontFamily * fontFamily) const448 SkTypeface* SkFontMgr_DirectWrite::createTypefaceFromDWriteFont(
449         IDWriteFontFace* fontFace,
450         IDWriteFont* font,
451         IDWriteFontFamily* fontFamily) const {
452     SkAutoMutexAcquire ama(fTFCacheMutex);
453     ProtoDWriteTypeface spec = { fontFace, font, fontFamily };
454     SkTypeface* face = fTFCache.findByProcAndRef(FindByDWriteFont, &spec);
455     if (NULL == face) {
456         face = DWriteFontTypeface::Create(fFactory.get(), fontFace, font, fontFamily);
457         if (face) {
458             fTFCache.add(face, get_style(font));
459         }
460     }
461     return face;
462 }
463 
onCountFamilies() const464 int SkFontMgr_DirectWrite::onCountFamilies() const {
465     return fFontCollection->GetFontFamilyCount();
466 }
467 
onGetFamilyName(int index,SkString * familyName) const468 void SkFontMgr_DirectWrite::onGetFamilyName(int index, SkString* familyName) const {
469     SkTScopedComPtr<IDWriteFontFamily> fontFamily;
470     HRVM(fFontCollection->GetFontFamily(index, &fontFamily), "Could not get requested family.");
471 
472     SkTScopedComPtr<IDWriteLocalizedStrings> familyNames;
473     HRVM(fontFamily->GetFamilyNames(&familyNames), "Could not get family names.");
474 
475     sk_get_locale_string(familyNames.get(), fLocaleName.get(), familyName);
476 }
477 
onCreateStyleSet(int index) const478 SkFontStyleSet* SkFontMgr_DirectWrite::onCreateStyleSet(int index) const {
479     SkTScopedComPtr<IDWriteFontFamily> fontFamily;
480     HRNM(fFontCollection->GetFontFamily(index, &fontFamily), "Could not get requested family.");
481 
482     return SkNEW_ARGS(SkFontStyleSet_DirectWrite, (this, fontFamily.get()));
483 }
484 
onMatchFamily(const char familyName[]) const485 SkFontStyleSet* SkFontMgr_DirectWrite::onMatchFamily(const char familyName[]) const {
486     SkSMallocWCHAR dwFamilyName;
487     HRN(sk_cstring_to_wchar(familyName, &dwFamilyName));
488 
489     UINT32 index;
490     BOOL exists;
491     HRNM(fFontCollection->FindFamilyName(dwFamilyName.get(), &index, &exists),
492             "Failed while finding family by name.");
493     if (!exists) {
494         return NULL;
495     }
496 
497     return this->onCreateStyleSet(index);
498 }
499 
onMatchFamilyStyle(const char familyName[],const SkFontStyle & fontstyle) const500 SkTypeface* SkFontMgr_DirectWrite::onMatchFamilyStyle(const char familyName[],
501                                                       const SkFontStyle& fontstyle) const {
502     SkAutoTUnref<SkFontStyleSet> sset(this->matchFamily(familyName));
503     return sset->matchStyle(fontstyle);
504 }
505 
506 class FontFallbackRenderer : public IDWriteTextRenderer {
507 public:
FontFallbackRenderer(const SkFontMgr_DirectWrite * outer,UINT32 character)508     FontFallbackRenderer(const SkFontMgr_DirectWrite* outer, UINT32 character)
509         : fRefCount(1), fOuter(SkSafeRef(outer)), fCharacter(character), fResolvedTypeface(NULL) {
510     }
511 
~FontFallbackRenderer()512     virtual ~FontFallbackRenderer() { }
513 
514     // 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)515     virtual HRESULT STDMETHODCALLTYPE DrawGlyphRun(
516         void* clientDrawingContext,
517         FLOAT baselineOriginX,
518         FLOAT baselineOriginY,
519         DWRITE_MEASURING_MODE measuringMode,
520         DWRITE_GLYPH_RUN const* glyphRun,
521         DWRITE_GLYPH_RUN_DESCRIPTION const* glyphRunDescription,
522         IUnknown* clientDrawingEffect) override
523     {
524         SkTScopedComPtr<IDWriteFont> font;
525         HRM(fOuter->fFontCollection->GetFontFromFontFace(glyphRun->fontFace, &font),
526             "Could not get font from font face.");
527 
528         // It is possible that the font passed does not actually have the requested character,
529         // due to no font being found and getting the fallback font.
530         // Check that the font actually contains the requested character.
531         BOOL exists;
532         HRM(font->HasCharacter(fCharacter, &exists), "Could not find character.");
533 
534         if (exists) {
535             SkTScopedComPtr<IDWriteFontFamily> fontFamily;
536             HRM(font->GetFontFamily(&fontFamily), "Could not get family.");
537             fResolvedTypeface = fOuter->createTypefaceFromDWriteFont(glyphRun->fontFace,
538                                                                      font.get(),
539                                                                      fontFamily.get());
540         }
541 
542         return S_OK;
543     }
544 
DrawUnderline(void * clientDrawingContext,FLOAT baselineOriginX,FLOAT baselineOriginY,DWRITE_UNDERLINE const * underline,IUnknown * clientDrawingEffect)545     virtual HRESULT STDMETHODCALLTYPE DrawUnderline(
546         void* clientDrawingContext,
547         FLOAT baselineOriginX,
548         FLOAT baselineOriginY,
549         DWRITE_UNDERLINE const* underline,
550         IUnknown* clientDrawingEffect) override
551     { return E_NOTIMPL; }
552 
DrawStrikethrough(void * clientDrawingContext,FLOAT baselineOriginX,FLOAT baselineOriginY,DWRITE_STRIKETHROUGH const * strikethrough,IUnknown * clientDrawingEffect)553     virtual HRESULT STDMETHODCALLTYPE DrawStrikethrough(
554         void* clientDrawingContext,
555         FLOAT baselineOriginX,
556         FLOAT baselineOriginY,
557         DWRITE_STRIKETHROUGH const* strikethrough,
558         IUnknown* clientDrawingEffect) override
559     { return E_NOTIMPL; }
560 
DrawInlineObject(void * clientDrawingContext,FLOAT originX,FLOAT originY,IDWriteInlineObject * inlineObject,BOOL isSideways,BOOL isRightToLeft,IUnknown * clientDrawingEffect)561     virtual HRESULT STDMETHODCALLTYPE DrawInlineObject(
562         void* clientDrawingContext,
563         FLOAT originX,
564         FLOAT originY,
565         IDWriteInlineObject* inlineObject,
566         BOOL isSideways,
567         BOOL isRightToLeft,
568         IUnknown* clientDrawingEffect) override
569     { return E_NOTIMPL; }
570 
571     // IDWritePixelSnapping methods
IsPixelSnappingDisabled(void * clientDrawingContext,BOOL * isDisabled)572     virtual HRESULT STDMETHODCALLTYPE IsPixelSnappingDisabled(
573         void* clientDrawingContext,
574         BOOL* isDisabled) override
575     {
576         *isDisabled = FALSE;
577         return S_OK;
578     }
579 
GetCurrentTransform(void * clientDrawingContext,DWRITE_MATRIX * transform)580     virtual HRESULT STDMETHODCALLTYPE GetCurrentTransform(
581         void* clientDrawingContext,
582         DWRITE_MATRIX* transform) override
583     {
584         const DWRITE_MATRIX ident = { 1.0, 0.0, 0.0, 1.0, 0.0, 0.0 };
585         *transform = ident;
586         return S_OK;
587     }
588 
GetPixelsPerDip(void * clientDrawingContext,FLOAT * pixelsPerDip)589     virtual HRESULT STDMETHODCALLTYPE GetPixelsPerDip(
590         void* clientDrawingContext,
591         FLOAT* pixelsPerDip) override
592     {
593         *pixelsPerDip = 1.0f;
594         return S_OK;
595     }
596 
597     // IUnknown methods
AddRef()598     ULONG STDMETHODCALLTYPE AddRef() override {
599         return InterlockedIncrement(&fRefCount);
600     }
601 
Release()602     ULONG STDMETHODCALLTYPE Release() override {
603         ULONG newCount = InterlockedDecrement(&fRefCount);
604         if (0 == newCount) {
605             delete this;
606         }
607         return newCount;
608     }
609 
QueryInterface(IID const & riid,void ** ppvObject)610     virtual HRESULT STDMETHODCALLTYPE QueryInterface(IID const& riid, void** ppvObject) override{
611         if (__uuidof(IUnknown) == riid ||
612             __uuidof(IDWritePixelSnapping) == riid ||
613             __uuidof(IDWriteTextRenderer) == riid)
614         {
615             *ppvObject = this;
616             this->AddRef();
617             return S_OK;
618         }
619         *ppvObject = NULL;
620         return E_FAIL;
621     }
622 
FallbackTypeface()623     SkTypeface* FallbackTypeface() { return fResolvedTypeface; }
624 
625 protected:
626     ULONG fRefCount;
627     SkAutoTUnref<const SkFontMgr_DirectWrite> fOuter;
628     UINT32 fCharacter;
629     SkTypeface* fResolvedTypeface;
630 };
631 
632 class FontFallbackSource : public IDWriteTextAnalysisSource {
633 public:
FontFallbackSource(const WCHAR * string,UINT32 length,const WCHAR * locale,IDWriteNumberSubstitution * numberSubstitution)634     FontFallbackSource(const WCHAR* string, UINT32 length, const WCHAR* locale,
635                        IDWriteNumberSubstitution* numberSubstitution)
636         : fString(string)
637         , fLength(length)
638         , fLocale(locale)
639         , fNumberSubstitution(numberSubstitution)
640     { }
641 
~FontFallbackSource()642     virtual ~FontFallbackSource() { }
643 
644     // IDWriteTextAnalysisSource methods
GetTextAtPosition(UINT32 textPosition,WCHAR const ** textString,UINT32 * textLength)645     virtual HRESULT STDMETHODCALLTYPE GetTextAtPosition(
646         UINT32 textPosition,
647         WCHAR const** textString,
648         UINT32* textLength) override
649     {
650         if (fLength <= textPosition) {
651             *textString = NULL;
652             *textLength = 0;
653             return S_OK;
654         }
655         *textString = fString + textPosition;
656         *textLength = fLength - textPosition;
657         return S_OK;
658     }
659 
GetTextBeforePosition(UINT32 textPosition,WCHAR const ** textString,UINT32 * textLength)660     virtual HRESULT STDMETHODCALLTYPE GetTextBeforePosition(
661         UINT32 textPosition,
662         WCHAR const** textString,
663         UINT32* textLength) override
664     {
665         if (textPosition < 1 || fLength <= textPosition) {
666             *textString = NULL;
667             *textLength = 0;
668             return S_OK;
669         }
670         *textString = fString;
671         *textLength = textPosition;
672         return S_OK;
673     }
674 
GetParagraphReadingDirection()675     virtual DWRITE_READING_DIRECTION STDMETHODCALLTYPE GetParagraphReadingDirection() override {
676         // TODO: this is also interesting.
677         return DWRITE_READING_DIRECTION_LEFT_TO_RIGHT;
678     }
679 
GetLocaleName(UINT32 textPosition,UINT32 * textLength,WCHAR const ** localeName)680     virtual HRESULT STDMETHODCALLTYPE GetLocaleName(
681         UINT32 textPosition,
682         UINT32* textLength,
683         WCHAR const** localeName) override
684     {
685         *localeName = fLocale;
686         return S_OK;
687     }
688 
GetNumberSubstitution(UINT32 textPosition,UINT32 * textLength,IDWriteNumberSubstitution ** numberSubstitution)689     virtual HRESULT STDMETHODCALLTYPE GetNumberSubstitution(
690         UINT32 textPosition,
691         UINT32* textLength,
692         IDWriteNumberSubstitution** numberSubstitution) override
693     {
694         *numberSubstitution = fNumberSubstitution;
695         return S_OK;
696     }
697 
698     // IUnknown methods
AddRef()699     ULONG STDMETHODCALLTYPE AddRef() override {
700         return InterlockedIncrement(&fRefCount);
701     }
702 
Release()703     ULONG STDMETHODCALLTYPE Release() override {
704         ULONG newCount = InterlockedDecrement(&fRefCount);
705         if (0 == newCount) {
706             delete this;
707         }
708         return newCount;
709     }
710 
QueryInterface(IID const & riid,void ** ppvObject)711     virtual HRESULT STDMETHODCALLTYPE QueryInterface(IID const& riid, void** ppvObject) override{
712         if (__uuidof(IUnknown) == riid ||
713             __uuidof(IDWriteTextAnalysisSource) == riid)
714         {
715             *ppvObject = this;
716             this->AddRef();
717             return S_OK;
718         }
719         *ppvObject = NULL;
720         return E_FAIL;
721     }
722 
723 protected:
724     ULONG fRefCount;
725     const WCHAR* fString;
726     UINT32 fLength;
727     const WCHAR* fLocale;
728     IDWriteNumberSubstitution* fNumberSubstitution;
729 };
730 
onMatchFamilyStyleCharacter(const char familyName[],const SkFontStyle & style,const char * bcp47[],int bcp47Count,SkUnichar character) const731 SkTypeface* SkFontMgr_DirectWrite::onMatchFamilyStyleCharacter(const char familyName[],
732                                                                const SkFontStyle& style,
733                                                                const char* bcp47[], int bcp47Count,
734                                                                SkUnichar character) const
735 {
736     const DWriteStyle dwStyle(style);
737 
738     const WCHAR* dwFamilyName = NULL;
739     SkSMallocWCHAR dwFamilyNameLocal;
740     if (familyName) {
741         HRN(sk_cstring_to_wchar(familyName, &dwFamilyNameLocal));
742         dwFamilyName = dwFamilyNameLocal;
743     }
744 
745     WCHAR str[16];
746     UINT32 strLen = static_cast<UINT32>(
747         SkUTF16_FromUnichar(character, reinterpret_cast<uint16_t*>(str)));
748 
749     const SkSMallocWCHAR* dwBcp47;
750     SkSMallocWCHAR dwBcp47Local;
751     if (bcp47Count < 1) {
752         dwBcp47 = &fLocaleName;
753     } else {
754         // TODO: support fallback stack.
755         // TODO: DirectWrite supports 'zh-CN' or 'zh-Hans', but 'zh' misses completely
756         // and may produce a Japanese font.
757         HRN(sk_cstring_to_wchar(bcp47[bcp47Count - 1], &dwBcp47Local));
758         dwBcp47 = &dwBcp47Local;
759     }
760 
761 #if SK_HAS_DWRITE_2_H
762     if (fFactory2.get()) {
763         SkTScopedComPtr<IDWriteFontFallback> fontFallback;
764         HRNM(fFactory2->GetSystemFontFallback(&fontFallback), "Could not get system fallback.");
765 
766         SkTScopedComPtr<IDWriteNumberSubstitution> numberSubstitution;
767         HRNM(fFactory2->CreateNumberSubstitution(DWRITE_NUMBER_SUBSTITUTION_METHOD_NONE, NULL, TRUE,
768                                                  &numberSubstitution),
769              "Could not create number substitution.");
770         SkTScopedComPtr<FontFallbackSource> fontFallbackSource(
771             new FontFallbackSource(str, strLen, *dwBcp47, numberSubstitution.get()));
772 
773         UINT32 mappedLength;
774         SkTScopedComPtr<IDWriteFont> font;
775         FLOAT scale;
776         HRNM(fontFallback->MapCharacters(fontFallbackSource.get(),
777                                          0, // textPosition,
778                                          strLen,
779                                          fFontCollection.get(),
780                                          dwFamilyName,
781                                          dwStyle.fWeight,
782                                          dwStyle.fSlant,
783                                          dwStyle.fWidth,
784                                          &mappedLength,
785                                          &font,
786                                          &scale),
787              "Could not map characters");
788         if (!font.get()) {
789             return NULL;
790         }
791 
792         SkTScopedComPtr<IDWriteFontFace> fontFace;
793         HRNM(font->CreateFontFace(&fontFace), "Could not get font face from font.");
794 
795         SkTScopedComPtr<IDWriteFontFamily> fontFamily;
796         HRNM(font->GetFontFamily(&fontFamily), "Could not get family from font.");
797         return this->createTypefaceFromDWriteFont(fontFace.get(), font.get(), fontFamily.get());
798     }
799 #else
800 #  pragma message("No dwrite_2.h is available, font fallback may be affected.")
801 #endif
802 
803     SkTScopedComPtr<IDWriteTextFormat> fallbackFormat;
804     HRNM(fFactory->CreateTextFormat(dwFamilyName ? dwFamilyName : L"",
805                                     fFontCollection.get(),
806                                     dwStyle.fWeight,
807                                     dwStyle.fSlant,
808                                     dwStyle.fWidth,
809                                     72.0f,
810                                     *dwBcp47,
811                                     &fallbackFormat),
812          "Could not create text format.");
813 
814     SkTScopedComPtr<IDWriteTextLayout> fallbackLayout;
815     HRNM(fFactory->CreateTextLayout(str, strLen, fallbackFormat.get(),
816                                     200.0f, 200.0f,
817                                     &fallbackLayout),
818          "Could not create text layout.");
819 
820     SkTScopedComPtr<FontFallbackRenderer> fontFallbackRenderer(
821         new FontFallbackRenderer(this, character));
822 
823     HRNM(fallbackLayout->Draw(NULL, fontFallbackRenderer.get(), 50.0f, 50.0f),
824          "Could not draw layout with renderer.");
825 
826     return fontFallbackRenderer->FallbackTypeface();
827 }
828 
onMatchFaceStyle(const SkTypeface * familyMember,const SkFontStyle & fontstyle) const829 SkTypeface* SkFontMgr_DirectWrite::onMatchFaceStyle(const SkTypeface* familyMember,
830                                                     const SkFontStyle& fontstyle) const {
831     SkString familyName;
832     SkFontStyleSet_DirectWrite sset(
833         this, ((DWriteFontTypeface*)familyMember)->fDWriteFontFamily.get()
834     );
835     return sset.matchStyle(fontstyle);
836 }
837 
838 template <typename T> class SkAutoIDWriteUnregister {
839 public:
SkAutoIDWriteUnregister(IDWriteFactory * factory,T * unregister)840     SkAutoIDWriteUnregister(IDWriteFactory* factory, T* unregister)
841         : fFactory(factory), fUnregister(unregister)
842     { }
843 
~SkAutoIDWriteUnregister()844     ~SkAutoIDWriteUnregister() {
845         if (fUnregister) {
846             unregister(fFactory, fUnregister);
847         }
848     }
849 
detatch()850     T* detatch() {
851         T* old = fUnregister;
852         fUnregister = NULL;
853         return old;
854     }
855 
856 private:
unregister(IDWriteFactory * factory,IDWriteFontFileLoader * unregister)857     HRESULT unregister(IDWriteFactory* factory, IDWriteFontFileLoader* unregister) {
858         return factory->UnregisterFontFileLoader(unregister);
859     }
860 
unregister(IDWriteFactory * factory,IDWriteFontCollectionLoader * unregister)861     HRESULT unregister(IDWriteFactory* factory, IDWriteFontCollectionLoader* unregister) {
862         return factory->UnregisterFontCollectionLoader(unregister);
863     }
864 
865     IDWriteFactory* fFactory;
866     T* fUnregister;
867 };
868 
onCreateFromStream(SkStreamAsset * stream,int ttcIndex) const869 SkTypeface* SkFontMgr_DirectWrite::onCreateFromStream(SkStreamAsset* stream, int ttcIndex) const {
870     SkTScopedComPtr<StreamFontFileLoader> fontFileLoader;
871     // This transfers ownership of stream to the new object.
872     HRN(StreamFontFileLoader::Create(stream, &fontFileLoader));
873     HRN(fFactory->RegisterFontFileLoader(fontFileLoader.get()));
874     SkAutoIDWriteUnregister<StreamFontFileLoader> autoUnregisterFontFileLoader(
875         fFactory.get(), fontFileLoader.get());
876 
877     SkTScopedComPtr<StreamFontCollectionLoader> fontCollectionLoader;
878     HRN(StreamFontCollectionLoader::Create(fontFileLoader.get(), &fontCollectionLoader));
879     HRN(fFactory->RegisterFontCollectionLoader(fontCollectionLoader.get()));
880     SkAutoIDWriteUnregister<StreamFontCollectionLoader> autoUnregisterFontCollectionLoader(
881         fFactory.get(), fontCollectionLoader.get());
882 
883     SkTScopedComPtr<IDWriteFontCollection> fontCollection;
884     HRN(fFactory->CreateCustomFontCollection(fontCollectionLoader.get(), NULL, 0, &fontCollection));
885 
886     // Find the first non-simulated font which has the given ttc index.
887     UINT32 familyCount = fontCollection->GetFontFamilyCount();
888     for (UINT32 familyIndex = 0; familyIndex < familyCount; ++familyIndex) {
889         SkTScopedComPtr<IDWriteFontFamily> fontFamily;
890         HRN(fontCollection->GetFontFamily(familyIndex, &fontFamily));
891 
892         UINT32 fontCount = fontFamily->GetFontCount();
893         for (UINT32 fontIndex = 0; fontIndex < fontCount; ++fontIndex) {
894             SkTScopedComPtr<IDWriteFont> font;
895             HRN(fontFamily->GetFont(fontIndex, &font));
896             if (font->GetSimulations() != DWRITE_FONT_SIMULATIONS_NONE) {
897                 continue;
898             }
899 
900             SkTScopedComPtr<IDWriteFontFace> fontFace;
901             HRN(font->CreateFontFace(&fontFace));
902 
903             UINT32 faceIndex = fontFace->GetIndex();
904             if (faceIndex == ttcIndex) {
905                 return DWriteFontTypeface::Create(fFactory.get(),
906                                                   fontFace.get(), font.get(), fontFamily.get(),
907                                                   autoUnregisterFontFileLoader.detatch(),
908                                                   autoUnregisterFontCollectionLoader.detatch());
909             }
910         }
911     }
912 
913     return NULL;
914 }
915 
onCreateFromData(SkData * data,int ttcIndex) const916 SkTypeface* SkFontMgr_DirectWrite::onCreateFromData(SkData* data, int ttcIndex) const {
917     return this->createFromStream(SkNEW_ARGS(SkMemoryStream, (data)), ttcIndex);
918 }
919 
onCreateFromFile(const char path[],int ttcIndex) const920 SkTypeface* SkFontMgr_DirectWrite::onCreateFromFile(const char path[], int ttcIndex) const {
921     return this->createFromStream(SkStream::NewFromFile(path), ttcIndex);
922 }
923 
getByFamilyName(const WCHAR wideFamilyName[],IDWriteFontFamily ** fontFamily) const924 HRESULT SkFontMgr_DirectWrite::getByFamilyName(const WCHAR wideFamilyName[],
925                                                IDWriteFontFamily** fontFamily) const {
926     UINT32 index;
927     BOOL exists;
928     HR(fFontCollection->FindFamilyName(wideFamilyName, &index, &exists));
929 
930     if (exists) {
931         HR(fFontCollection->GetFontFamily(index, fontFamily));
932     }
933     return S_OK;
934 }
935 
getDefaultFontFamily(IDWriteFontFamily ** fontFamily) const936 HRESULT SkFontMgr_DirectWrite::getDefaultFontFamily(IDWriteFontFamily** fontFamily) const {
937     NONCLIENTMETRICSW metrics;
938     metrics.cbSize = sizeof(metrics);
939     if (0 == SystemParametersInfoW(SPI_GETNONCLIENTMETRICS,
940                                    sizeof(metrics),
941                                    &metrics,
942                                    0)) {
943         return E_UNEXPECTED;
944     }
945     HRM(this->getByFamilyName(metrics.lfMessageFont.lfFaceName, fontFamily),
946         "Could not create DWrite font family from LOGFONT.");
947     return S_OK;
948 }
949 
onLegacyCreateTypeface(const char familyName[],unsigned styleBits) const950 SkTypeface* SkFontMgr_DirectWrite::onLegacyCreateTypeface(const char familyName[],
951                                                           unsigned styleBits) const {
952     SkTScopedComPtr<IDWriteFontFamily> fontFamily;
953     if (familyName) {
954         SkSMallocWCHAR wideFamilyName;
955         if (SUCCEEDED(sk_cstring_to_wchar(familyName, &wideFamilyName))) {
956             this->getByFamilyName(wideFamilyName, &fontFamily);
957         }
958     }
959 
960     if (NULL == fontFamily.get()) {
961         // No family with given name, try default.
962         HRNM(this->getDefaultFontFamily(&fontFamily), "Could not get default font family.");
963     }
964 
965     if (NULL == fontFamily.get()) {
966         // Could not obtain the default font.
967         HRNM(fFontCollection->GetFontFamily(0, &fontFamily),
968              "Could not get default-default font family.");
969     }
970 
971     SkTScopedComPtr<IDWriteFont> font;
972     DWRITE_FONT_WEIGHT weight = (styleBits & SkTypeface::kBold)
973                               ? DWRITE_FONT_WEIGHT_BOLD
974                               : DWRITE_FONT_WEIGHT_NORMAL;
975     DWRITE_FONT_STRETCH stretch = DWRITE_FONT_STRETCH_NORMAL;
976     DWRITE_FONT_STYLE italic = (styleBits & SkTypeface::kItalic)
977                              ? DWRITE_FONT_STYLE_ITALIC
978                              : DWRITE_FONT_STYLE_NORMAL;
979     HRNM(fontFamily->GetFirstMatchingFont(weight, stretch, italic, &font),
980          "Could not get matching font.");
981 
982     SkTScopedComPtr<IDWriteFontFace> fontFace;
983     HRNM(font->CreateFontFace(&fontFace), "Could not create font face.");
984 
985     return this->createTypefaceFromDWriteFont(fontFace.get(), font.get(), fontFamily.get());
986 }
987 
988 ///////////////////////////////////////////////////////////////////////////////
989 
count()990 int SkFontStyleSet_DirectWrite::count() {
991     return fFontFamily->GetFontCount();
992 }
993 
createTypeface(int index)994 SkTypeface* SkFontStyleSet_DirectWrite::createTypeface(int index) {
995     SkTScopedComPtr<IDWriteFont> font;
996     HRNM(fFontFamily->GetFont(index, &font), "Could not get font.");
997 
998     SkTScopedComPtr<IDWriteFontFace> fontFace;
999     HRNM(font->CreateFontFace(&fontFace), "Could not create font face.");
1000 
1001     return fFontMgr->createTypefaceFromDWriteFont(fontFace.get(), font.get(), fFontFamily.get());
1002 }
1003 
getStyle(int index,SkFontStyle * fs,SkString * styleName)1004 void SkFontStyleSet_DirectWrite::getStyle(int index, SkFontStyle* fs, SkString* styleName) {
1005     SkTScopedComPtr<IDWriteFont> font;
1006     HRVM(fFontFamily->GetFont(index, &font), "Could not get font.");
1007 
1008     if (fs) {
1009         SkFontStyle::Slant slant;
1010         switch (font->GetStyle()) {
1011         case DWRITE_FONT_STYLE_NORMAL:
1012             slant = SkFontStyle::kUpright_Slant;
1013             break;
1014         case DWRITE_FONT_STYLE_OBLIQUE:
1015         case DWRITE_FONT_STYLE_ITALIC:
1016             slant = SkFontStyle::kItalic_Slant;
1017             break;
1018         default:
1019             SkASSERT(false);
1020         }
1021 
1022         int weight = font->GetWeight();
1023         int width = font->GetStretch();
1024 
1025         *fs = SkFontStyle(weight, width, slant);
1026     }
1027 
1028     if (styleName) {
1029         SkTScopedComPtr<IDWriteLocalizedStrings> faceNames;
1030         if (SUCCEEDED(font->GetFaceNames(&faceNames))) {
1031             sk_get_locale_string(faceNames.get(), fFontMgr->fLocaleName.get(), styleName);
1032         }
1033     }
1034 }
1035 
matchStyle(const SkFontStyle & pattern)1036 SkTypeface* SkFontStyleSet_DirectWrite::matchStyle(const SkFontStyle& pattern) {
1037     DWRITE_FONT_STYLE slant;
1038     switch (pattern.slant()) {
1039     case SkFontStyle::kUpright_Slant:
1040         slant = DWRITE_FONT_STYLE_NORMAL;
1041         break;
1042     case SkFontStyle::kItalic_Slant:
1043         slant = DWRITE_FONT_STYLE_ITALIC;
1044         break;
1045     default:
1046         SkASSERT(false);
1047     }
1048 
1049     DWRITE_FONT_WEIGHT weight = (DWRITE_FONT_WEIGHT)pattern.weight();
1050     DWRITE_FONT_STRETCH width = (DWRITE_FONT_STRETCH)pattern.width();
1051 
1052     SkTScopedComPtr<IDWriteFont> font;
1053     // TODO: perhaps use GetMatchingFonts and get the least simulated?
1054     HRNM(fFontFamily->GetFirstMatchingFont(weight, width, slant, &font),
1055          "Could not match font in family.");
1056 
1057     SkTScopedComPtr<IDWriteFontFace> fontFace;
1058     HRNM(font->CreateFontFace(&fontFace), "Could not create font face.");
1059 
1060     return fFontMgr->createTypefaceFromDWriteFont(fontFace.get(), font.get(),
1061                                                   fFontFamily.get());
1062 }
1063 
1064 ////////////////////////////////////////////////////////////////////////////////
1065 #include "SkTypeface_win.h"
1066 
SkFontMgr_New_DirectWrite(IDWriteFactory * factory)1067 SK_API SkFontMgr* SkFontMgr_New_DirectWrite(IDWriteFactory* factory) {
1068     if (NULL == factory) {
1069         factory = sk_get_dwrite_factory();
1070         if (NULL == factory) {
1071             return NULL;
1072         }
1073     }
1074 
1075     SkTScopedComPtr<IDWriteFontCollection> sysFontCollection;
1076     HRNM(factory->GetSystemFontCollection(&sysFontCollection, FALSE),
1077          "Could not get system font collection.");
1078 
1079     WCHAR localeNameStorage[LOCALE_NAME_MAX_LENGTH];
1080     WCHAR* localeName = NULL;
1081     int localeNameLen = 0;
1082 
1083     // Dynamically load GetUserDefaultLocaleName function, as it is not available on XP.
1084     SkGetUserDefaultLocaleNameProc getUserDefaultLocaleNameProc = NULL;
1085     HRESULT hr = SkGetGetUserDefaultLocaleNameProc(&getUserDefaultLocaleNameProc);
1086     if (NULL == getUserDefaultLocaleNameProc) {
1087         SK_TRACEHR(hr, "Could not get GetUserDefaultLocaleName.");
1088     } else {
1089         localeNameLen = getUserDefaultLocaleNameProc(localeNameStorage, LOCALE_NAME_MAX_LENGTH);
1090         if (localeNameLen) {
1091             localeName = localeNameStorage;
1092         };
1093     }
1094 
1095     return SkNEW_ARGS(SkFontMgr_DirectWrite, (factory, sysFontCollection.get(),
1096                                               localeName, localeNameLen));
1097 }
1098 
1099 #include "SkFontMgr_indirect.h"
SkFontMgr_New_DirectWriteRenderer(SkRemotableFontMgr * proxy)1100 SK_API SkFontMgr* SkFontMgr_New_DirectWriteRenderer(SkRemotableFontMgr* proxy) {
1101     SkAutoTUnref<SkFontMgr> impl(SkFontMgr_New_DirectWrite());
1102     if (impl.get() == NULL) {
1103         return NULL;
1104     }
1105     return SkNEW_ARGS(SkFontMgr_Indirect, (impl.get(), proxy));
1106 }
1107