• 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 
20 #include <dwrite.h>
21 
22 ////////////////////////////////////////////////////////////////////////////////
23 
24 class StreamFontFileLoader : public IDWriteFontFileLoader {
25 public:
26     // IUnknown methods
27     virtual HRESULT STDMETHODCALLTYPE QueryInterface(REFIID iid, void** ppvObject);
28     virtual ULONG STDMETHODCALLTYPE AddRef();
29     virtual ULONG STDMETHODCALLTYPE Release();
30 
31     // IDWriteFontFileLoader methods
32     virtual HRESULT STDMETHODCALLTYPE CreateStreamFromKey(
33         void const* fontFileReferenceKey,
34         UINT32 fontFileReferenceKeySize,
35         IDWriteFontFileStream** fontFileStream);
36 
Create(SkStream * stream,StreamFontFileLoader ** streamFontFileLoader)37     static HRESULT Create(SkStream* stream, StreamFontFileLoader** streamFontFileLoader) {
38         *streamFontFileLoader = new StreamFontFileLoader(stream);
39         if (NULL == streamFontFileLoader) {
40             return E_OUTOFMEMORY;
41         }
42         return S_OK;
43     }
44 
45     SkAutoTUnref<SkStream> fStream;
46 
47 private:
StreamFontFileLoader(SkStream * stream)48     StreamFontFileLoader(SkStream* stream) : fRefCount(1), fStream(SkRef(stream)) { }
~StreamFontFileLoader()49     virtual ~StreamFontFileLoader() { }
50 
51     ULONG fRefCount;
52 };
53 
QueryInterface(REFIID iid,void ** ppvObject)54 HRESULT StreamFontFileLoader::QueryInterface(REFIID iid, void** ppvObject) {
55     if (iid == IID_IUnknown || iid == __uuidof(IDWriteFontFileLoader)) {
56         *ppvObject = this;
57         AddRef();
58         return S_OK;
59     } else {
60         *ppvObject = NULL;
61         return E_NOINTERFACE;
62     }
63 }
64 
AddRef()65 ULONG StreamFontFileLoader::AddRef() {
66     return InterlockedIncrement(&fRefCount);
67 }
68 
Release()69 ULONG StreamFontFileLoader::Release() {
70     ULONG newCount = InterlockedDecrement(&fRefCount);
71     if (0 == newCount) {
72         delete this;
73     }
74     return newCount;
75 }
76 
CreateStreamFromKey(void const * fontFileReferenceKey,UINT32 fontFileReferenceKeySize,IDWriteFontFileStream ** fontFileStream)77 HRESULT StreamFontFileLoader::CreateStreamFromKey(
78     void const* fontFileReferenceKey,
79     UINT32 fontFileReferenceKeySize,
80     IDWriteFontFileStream** fontFileStream)
81 {
82     SkTScopedComPtr<SkDWriteFontFileStreamWrapper> stream;
83     HR(SkDWriteFontFileStreamWrapper::Create(fStream, &stream));
84     *fontFileStream = stream.release();
85     return S_OK;
86 }
87 
88 ////////////////////////////////////////////////////////////////////////////////
89 
90 class StreamFontFileEnumerator : public IDWriteFontFileEnumerator {
91 public:
92     // IUnknown methods
93     virtual HRESULT STDMETHODCALLTYPE QueryInterface(REFIID iid, void** ppvObject);
94     virtual ULONG STDMETHODCALLTYPE AddRef();
95     virtual ULONG STDMETHODCALLTYPE Release();
96 
97     // IDWriteFontFileEnumerator methods
98     virtual HRESULT STDMETHODCALLTYPE MoveNext(BOOL* hasCurrentFile);
99     virtual HRESULT STDMETHODCALLTYPE GetCurrentFontFile(IDWriteFontFile** fontFile);
100 
Create(IDWriteFactory * factory,IDWriteFontFileLoader * fontFileLoader,StreamFontFileEnumerator ** streamFontFileEnumerator)101     static HRESULT Create(IDWriteFactory* factory, IDWriteFontFileLoader* fontFileLoader,
102                           StreamFontFileEnumerator** streamFontFileEnumerator) {
103         *streamFontFileEnumerator = new StreamFontFileEnumerator(factory, fontFileLoader);
104         if (NULL == streamFontFileEnumerator) {
105             return E_OUTOFMEMORY;
106         }
107         return S_OK;
108     }
109 private:
110     StreamFontFileEnumerator(IDWriteFactory* factory, IDWriteFontFileLoader* fontFileLoader);
~StreamFontFileEnumerator()111     virtual ~StreamFontFileEnumerator() { }
112 
113     ULONG fRefCount;
114 
115     SkTScopedComPtr<IDWriteFactory> fFactory;
116     SkTScopedComPtr<IDWriteFontFile> fCurrentFile;
117     SkTScopedComPtr<IDWriteFontFileLoader> fFontFileLoader;
118     bool fHasNext;
119 };
120 
StreamFontFileEnumerator(IDWriteFactory * factory,IDWriteFontFileLoader * fontFileLoader)121 StreamFontFileEnumerator::StreamFontFileEnumerator(IDWriteFactory* factory,
122                                                    IDWriteFontFileLoader* fontFileLoader)
123     : fRefCount(1)
124     , fFactory(SkRefComPtr(factory))
125     , fCurrentFile()
126     , fFontFileLoader(SkRefComPtr(fontFileLoader))
127     , fHasNext(true)
128 { }
129 
QueryInterface(REFIID iid,void ** ppvObject)130 HRESULT StreamFontFileEnumerator::QueryInterface(REFIID iid, void** ppvObject) {
131     if (iid == IID_IUnknown || iid == __uuidof(IDWriteFontFileEnumerator)) {
132         *ppvObject = this;
133         AddRef();
134         return S_OK;
135     } else {
136         *ppvObject = NULL;
137         return E_NOINTERFACE;
138     }
139 }
140 
AddRef()141 ULONG StreamFontFileEnumerator::AddRef() {
142     return InterlockedIncrement(&fRefCount);
143 }
144 
Release()145 ULONG StreamFontFileEnumerator::Release() {
146     ULONG newCount = InterlockedDecrement(&fRefCount);
147     if (0 == newCount) {
148         delete this;
149     }
150     return newCount;
151 }
152 
MoveNext(BOOL * hasCurrentFile)153 HRESULT StreamFontFileEnumerator::MoveNext(BOOL* hasCurrentFile) {
154     *hasCurrentFile = FALSE;
155 
156     if (!fHasNext) {
157         return S_OK;
158     }
159     fHasNext = false;
160 
161     UINT32 dummy = 0;
162     HR(fFactory->CreateCustomFontFileReference(
163             &dummy, //cannot be NULL
164             sizeof(dummy), //even if this is 0
165             fFontFileLoader.get(),
166             &fCurrentFile));
167 
168     *hasCurrentFile = TRUE;
169     return S_OK;
170 }
171 
GetCurrentFontFile(IDWriteFontFile ** fontFile)172 HRESULT StreamFontFileEnumerator::GetCurrentFontFile(IDWriteFontFile** fontFile) {
173     if (fCurrentFile.get() == NULL) {
174         *fontFile = NULL;
175         return E_FAIL;
176     }
177 
178     *fontFile = SkRefComPtr(fCurrentFile.get());
179     return  S_OK;
180 }
181 
182 ////////////////////////////////////////////////////////////////////////////////
183 
184 class StreamFontCollectionLoader : public IDWriteFontCollectionLoader {
185 public:
186     // IUnknown methods
187     virtual HRESULT STDMETHODCALLTYPE QueryInterface(REFIID iid, void** ppvObject);
188     virtual ULONG STDMETHODCALLTYPE AddRef();
189     virtual ULONG STDMETHODCALLTYPE Release();
190 
191     // IDWriteFontCollectionLoader methods
192     virtual HRESULT STDMETHODCALLTYPE CreateEnumeratorFromKey(
193         IDWriteFactory* factory,
194         void const* collectionKey,
195         UINT32 collectionKeySize,
196         IDWriteFontFileEnumerator** fontFileEnumerator);
197 
Create(IDWriteFontFileLoader * fontFileLoader,StreamFontCollectionLoader ** streamFontCollectionLoader)198     static HRESULT Create(IDWriteFontFileLoader* fontFileLoader,
199                           StreamFontCollectionLoader** streamFontCollectionLoader) {
200         *streamFontCollectionLoader = new StreamFontCollectionLoader(fontFileLoader);
201         if (NULL == streamFontCollectionLoader) {
202             return E_OUTOFMEMORY;
203         }
204         return S_OK;
205     }
206 private:
StreamFontCollectionLoader(IDWriteFontFileLoader * fontFileLoader)207     StreamFontCollectionLoader(IDWriteFontFileLoader* fontFileLoader)
208         : fRefCount(1)
209         , fFontFileLoader(SkRefComPtr(fontFileLoader))
210     { }
~StreamFontCollectionLoader()211     virtual ~StreamFontCollectionLoader() { }
212 
213     ULONG fRefCount;
214     SkTScopedComPtr<IDWriteFontFileLoader> fFontFileLoader;
215 };
216 
QueryInterface(REFIID iid,void ** ppvObject)217 HRESULT StreamFontCollectionLoader::QueryInterface(REFIID iid, void** ppvObject) {
218     if (iid == IID_IUnknown || iid == __uuidof(IDWriteFontCollectionLoader)) {
219         *ppvObject = this;
220         AddRef();
221         return S_OK;
222     } else {
223         *ppvObject = NULL;
224         return E_NOINTERFACE;
225     }
226 }
227 
AddRef()228 ULONG StreamFontCollectionLoader::AddRef() {
229     return InterlockedIncrement(&fRefCount);
230 }
231 
Release()232 ULONG StreamFontCollectionLoader::Release() {
233     ULONG newCount = InterlockedDecrement(&fRefCount);
234     if (0 == newCount) {
235         delete this;
236     }
237     return newCount;
238 }
239 
CreateEnumeratorFromKey(IDWriteFactory * factory,void const * collectionKey,UINT32 collectionKeySize,IDWriteFontFileEnumerator ** fontFileEnumerator)240 HRESULT StreamFontCollectionLoader::CreateEnumeratorFromKey(
241     IDWriteFactory* factory,
242     void const* collectionKey,
243     UINT32 collectionKeySize,
244     IDWriteFontFileEnumerator** fontFileEnumerator)
245 {
246     SkTScopedComPtr<StreamFontFileEnumerator> enumerator;
247     HR(StreamFontFileEnumerator::Create(factory, fFontFileLoader.get(), &enumerator));
248     *fontFileEnumerator = enumerator.release();
249     return S_OK;
250 }
251 
252 ////////////////////////////////////////////////////////////////////////////////
253 
254 class SkFontMgr_DirectWrite : public SkFontMgr {
255 public:
256     /** localeNameLength must include the null terminator. */
SkFontMgr_DirectWrite(IDWriteFactory * factory,IDWriteFontCollection * fontCollection,WCHAR * localeName,int localeNameLength)257     SkFontMgr_DirectWrite(IDWriteFactory* factory, IDWriteFontCollection* fontCollection,
258                           WCHAR* localeName, int localeNameLength)
259         : fFactory(SkRefComPtr(factory))
260         , fFontCollection(SkRefComPtr(fontCollection))
261         , fLocaleName(localeNameLength)
262     {
263         memcpy(fLocaleName.get(), localeName, localeNameLength * sizeof(WCHAR));
264     }
265 
266 protected:
267     virtual int onCountFamilies() const SK_OVERRIDE;
268     virtual void onGetFamilyName(int index, SkString* familyName) const SK_OVERRIDE;
269     virtual SkFontStyleSet* onCreateStyleSet(int index) const SK_OVERRIDE;
270     virtual SkFontStyleSet* onMatchFamily(const char familyName[]) const SK_OVERRIDE;
271     virtual SkTypeface* onMatchFamilyStyle(const char familyName[],
272                                            const SkFontStyle& fontstyle) const SK_OVERRIDE;
273     virtual SkTypeface* onMatchFaceStyle(const SkTypeface* familyMember,
274                                          const SkFontStyle& fontstyle) const SK_OVERRIDE;
275     virtual SkTypeface* onCreateFromStream(SkStream* stream, int ttcIndex) const SK_OVERRIDE;
276     virtual SkTypeface* onCreateFromData(SkData* data, int ttcIndex) const SK_OVERRIDE;
277     virtual SkTypeface* onCreateFromFile(const char path[], int ttcIndex) const SK_OVERRIDE;
278     virtual SkTypeface* onLegacyCreateTypeface(const char familyName[],
279                                                unsigned styleBits) const SK_OVERRIDE;
280 
281 private:
282     HRESULT getByFamilyName(const WCHAR familyName[], IDWriteFontFamily** fontFamily) const;
283     HRESULT getDefaultFontFamily(IDWriteFontFamily** fontFamily) const;
284 
285     /** Creates a typeface using a typeface cache. */
286     SkTypeface* createTypefaceFromDWriteFont(IDWriteFontFace* fontFace,
287                                              IDWriteFont* font,
288                                              IDWriteFontFamily* fontFamily) const;
289 
290     SkTScopedComPtr<IDWriteFactory> fFactory;
291     SkTScopedComPtr<IDWriteFontCollection> fFontCollection;
292     SkSMallocWCHAR fLocaleName;
293     mutable SkMutex fTFCacheMutex;
294     mutable SkTypefaceCache fTFCache;
295 
296     friend class SkFontStyleSet_DirectWrite;
297 };
298 
299 class SkFontStyleSet_DirectWrite : public SkFontStyleSet {
300 public:
SkFontStyleSet_DirectWrite(const SkFontMgr_DirectWrite * fontMgr,IDWriteFontFamily * fontFamily)301     SkFontStyleSet_DirectWrite(const SkFontMgr_DirectWrite* fontMgr,
302                                IDWriteFontFamily* fontFamily)
303         : fFontMgr(SkRef(fontMgr))
304         , fFontFamily(SkRefComPtr(fontFamily))
305     { }
306 
307     virtual int count() SK_OVERRIDE;
308     virtual void getStyle(int index, SkFontStyle* fs, SkString* styleName) SK_OVERRIDE;
309     virtual SkTypeface* createTypeface(int index) SK_OVERRIDE;
310     virtual SkTypeface* matchStyle(const SkFontStyle& pattern) SK_OVERRIDE;
311 
312 private:
313     SkAutoTUnref<const SkFontMgr_DirectWrite> fFontMgr;
314     SkTScopedComPtr<IDWriteFontFamily> fFontFamily;
315 };
316 
are_same(IUnknown * a,IUnknown * b,bool & same)317 static HRESULT are_same(IUnknown* a, IUnknown* b, bool& same) {
318     SkTScopedComPtr<IUnknown> iunkA;
319     HRM(a->QueryInterface(&iunkA), "Failed to QI<IUnknown> for a.");
320 
321     SkTScopedComPtr<IUnknown> iunkB;
322     HRM(b->QueryInterface(&iunkB), "Failed to QI<IUnknown> for b.");
323 
324     same = (iunkA.get() == iunkB.get());
325     return S_OK;
326 }
327 
328 struct ProtoDWriteTypeface {
329     IDWriteFontFace* fDWriteFontFace;
330     IDWriteFont* fDWriteFont;
331     IDWriteFontFamily* fDWriteFontFamily;
332 };
333 
FindByDWriteFont(SkTypeface * cached,SkTypeface::Style,void * ctx)334 static bool FindByDWriteFont(SkTypeface* cached, SkTypeface::Style, void* ctx) {
335     DWriteFontTypeface* cshFace = reinterpret_cast<DWriteFontTypeface*>(cached);
336     ProtoDWriteTypeface* ctxFace = reinterpret_cast<ProtoDWriteTypeface*>(ctx);
337     bool same;
338 
339     //Check to see if the two fonts are identical.
340     HRB(are_same(cshFace->fDWriteFont.get(), ctxFace->fDWriteFont, same));
341     if (same) {
342         return true;
343     }
344 
345     HRB(are_same(cshFace->fDWriteFontFace.get(), ctxFace->fDWriteFontFace, same));
346     if (same) {
347         return true;
348     }
349 
350     //Check if the two fonts share the same loader and have the same key.
351     UINT32 cshNumFiles;
352     UINT32 ctxNumFiles;
353     HRB(cshFace->fDWriteFontFace->GetFiles(&cshNumFiles, NULL));
354     HRB(ctxFace->fDWriteFontFace->GetFiles(&ctxNumFiles, NULL));
355     if (cshNumFiles != ctxNumFiles) {
356         return false;
357     }
358 
359     SkTScopedComPtr<IDWriteFontFile> cshFontFile;
360     SkTScopedComPtr<IDWriteFontFile> ctxFontFile;
361     HRB(cshFace->fDWriteFontFace->GetFiles(&cshNumFiles, &cshFontFile));
362     HRB(ctxFace->fDWriteFontFace->GetFiles(&ctxNumFiles, &ctxFontFile));
363 
364     //for (each file) { //we currently only admit fonts from one file.
365     SkTScopedComPtr<IDWriteFontFileLoader> cshFontFileLoader;
366     SkTScopedComPtr<IDWriteFontFileLoader> ctxFontFileLoader;
367     HRB(cshFontFile->GetLoader(&cshFontFileLoader));
368     HRB(ctxFontFile->GetLoader(&ctxFontFileLoader));
369     HRB(are_same(cshFontFileLoader.get(), ctxFontFileLoader.get(), same));
370     if (!same) {
371         return false;
372     }
373     //}
374 
375     const void* cshRefKey;
376     UINT32 cshRefKeySize;
377     const void* ctxRefKey;
378     UINT32 ctxRefKeySize;
379     HRB(cshFontFile->GetReferenceKey(&cshRefKey, &cshRefKeySize));
380     HRB(ctxFontFile->GetReferenceKey(&ctxRefKey, &ctxRefKeySize));
381     if (cshRefKeySize != ctxRefKeySize) {
382         return false;
383     }
384     if (0 != memcmp(cshRefKey, ctxRefKey, ctxRefKeySize)) {
385         return false;
386     }
387 
388     //TODO: better means than comparing name strings?
389     //NOTE: .ttc and fake bold/italic will end up here.
390     SkTScopedComPtr<IDWriteLocalizedStrings> cshFamilyNames;
391     SkTScopedComPtr<IDWriteLocalizedStrings> cshFaceNames;
392     HRB(cshFace->fDWriteFontFamily->GetFamilyNames(&cshFamilyNames));
393     HRB(cshFace->fDWriteFont->GetFaceNames(&cshFaceNames));
394     UINT32 cshFamilyNameLength;
395     UINT32 cshFaceNameLength;
396     HRB(cshFamilyNames->GetStringLength(0, &cshFamilyNameLength));
397     HRB(cshFaceNames->GetStringLength(0, &cshFaceNameLength));
398 
399     SkTScopedComPtr<IDWriteLocalizedStrings> ctxFamilyNames;
400     SkTScopedComPtr<IDWriteLocalizedStrings> ctxFaceNames;
401     HRB(ctxFace->fDWriteFontFamily->GetFamilyNames(&ctxFamilyNames));
402     HRB(ctxFace->fDWriteFont->GetFaceNames(&ctxFaceNames));
403     UINT32 ctxFamilyNameLength;
404     UINT32 ctxFaceNameLength;
405     HRB(ctxFamilyNames->GetStringLength(0, &ctxFamilyNameLength));
406     HRB(ctxFaceNames->GetStringLength(0, &ctxFaceNameLength));
407 
408     if (cshFamilyNameLength != ctxFamilyNameLength ||
409         cshFaceNameLength != ctxFaceNameLength)
410     {
411         return false;
412     }
413 
414     SkSMallocWCHAR cshFamilyName(cshFamilyNameLength+1);
415     SkSMallocWCHAR cshFaceName(cshFaceNameLength+1);
416     HRB(cshFamilyNames->GetString(0, cshFamilyName.get(), cshFamilyNameLength+1));
417     HRB(cshFaceNames->GetString(0, cshFaceName.get(), cshFaceNameLength+1));
418 
419     SkSMallocWCHAR ctxFamilyName(ctxFamilyNameLength+1);
420     SkSMallocWCHAR ctxFaceName(ctxFaceNameLength+1);
421     HRB(ctxFamilyNames->GetString(0, ctxFamilyName.get(), ctxFamilyNameLength+1));
422     HRB(ctxFaceNames->GetString(0, ctxFaceName.get(), ctxFaceNameLength+1));
423 
424     return wcscmp(cshFamilyName.get(), ctxFamilyName.get()) == 0 &&
425            wcscmp(cshFaceName.get(), ctxFaceName.get()) == 0;
426 }
427 
createTypefaceFromDWriteFont(IDWriteFontFace * fontFace,IDWriteFont * font,IDWriteFontFamily * fontFamily) const428 SkTypeface* SkFontMgr_DirectWrite::createTypefaceFromDWriteFont(
429         IDWriteFontFace* fontFace,
430         IDWriteFont* font,
431         IDWriteFontFamily* fontFamily) const {
432     SkAutoMutexAcquire ama(fTFCacheMutex);
433     ProtoDWriteTypeface spec = { fontFace, font, fontFamily };
434     SkTypeface* face = fTFCache.findByProcAndRef(FindByDWriteFont, &spec);
435     if (NULL == face) {
436         face = DWriteFontTypeface::Create(fFactory.get(), fontFace, font, fontFamily);
437         if (face) {
438             fTFCache.add(face, get_style(font), true);
439         }
440     }
441     return face;
442 }
443 
onCountFamilies() const444 int SkFontMgr_DirectWrite::onCountFamilies() const {
445     return fFontCollection->GetFontFamilyCount();
446 }
447 
onGetFamilyName(int index,SkString * familyName) const448 void SkFontMgr_DirectWrite::onGetFamilyName(int index, SkString* familyName) const {
449     SkTScopedComPtr<IDWriteFontFamily> fontFamily;
450     HRVM(fFontCollection->GetFontFamily(index, &fontFamily), "Could not get requested family.");
451 
452     SkTScopedComPtr<IDWriteLocalizedStrings> familyNames;
453     HRVM(fontFamily->GetFamilyNames(&familyNames), "Could not get family names.");
454 
455     sk_get_locale_string(familyNames.get(), fLocaleName.get(), familyName);
456 }
457 
onCreateStyleSet(int index) const458 SkFontStyleSet* SkFontMgr_DirectWrite::onCreateStyleSet(int index) const {
459     SkTScopedComPtr<IDWriteFontFamily> fontFamily;
460     HRNM(fFontCollection->GetFontFamily(index, &fontFamily), "Could not get requested family.");
461 
462     return SkNEW_ARGS(SkFontStyleSet_DirectWrite, (this, fontFamily.get()));
463 }
464 
onMatchFamily(const char familyName[]) const465 SkFontStyleSet* SkFontMgr_DirectWrite::onMatchFamily(const char familyName[]) const {
466     SkSMallocWCHAR dwFamilyName;
467     HRN(sk_cstring_to_wchar(familyName, &dwFamilyName));
468 
469     UINT32 index;
470     BOOL exists;
471     HRNM(fFontCollection->FindFamilyName(dwFamilyName.get(), &index, &exists),
472             "Failed while finding family by name.");
473     if (!exists) {
474         return NULL;
475     }
476 
477     return this->onCreateStyleSet(index);
478 }
479 
onMatchFamilyStyle(const char familyName[],const SkFontStyle & fontstyle) const480 SkTypeface* SkFontMgr_DirectWrite::onMatchFamilyStyle(const char familyName[],
481                                                       const SkFontStyle& fontstyle) const {
482     SkAutoTUnref<SkFontStyleSet> sset(this->matchFamily(familyName));
483     return sset->matchStyle(fontstyle);
484 }
485 
onMatchFaceStyle(const SkTypeface * familyMember,const SkFontStyle & fontstyle) const486 SkTypeface* SkFontMgr_DirectWrite::onMatchFaceStyle(const SkTypeface* familyMember,
487                                                     const SkFontStyle& fontstyle) const {
488     SkString familyName;
489     SkFontStyleSet_DirectWrite sset(
490         this, ((DWriteFontTypeface*)familyMember)->fDWriteFontFamily.get()
491     );
492     return sset.matchStyle(fontstyle);
493 }
494 
495 template <typename T> class SkAutoIDWriteUnregister {
496 public:
SkAutoIDWriteUnregister(IDWriteFactory * factory,T * unregister)497     SkAutoIDWriteUnregister(IDWriteFactory* factory, T* unregister)
498         : fFactory(factory), fUnregister(unregister)
499     { }
500 
~SkAutoIDWriteUnregister()501     ~SkAutoIDWriteUnregister() {
502         if (fUnregister) {
503             unregister(fFactory, fUnregister);
504         }
505     }
506 
detatch()507     T* detatch() {
508         T* old = fUnregister;
509         fUnregister = NULL;
510         return old;
511     }
512 
513 private:
unregister(IDWriteFactory * factory,IDWriteFontFileLoader * unregister)514     HRESULT unregister(IDWriteFactory* factory, IDWriteFontFileLoader* unregister) {
515         return factory->UnregisterFontFileLoader(unregister);
516     }
517 
unregister(IDWriteFactory * factory,IDWriteFontCollectionLoader * unregister)518     HRESULT unregister(IDWriteFactory* factory, IDWriteFontCollectionLoader* unregister) {
519         return factory->UnregisterFontCollectionLoader(unregister);
520     }
521 
522     IDWriteFactory* fFactory;
523     T* fUnregister;
524 };
525 
onCreateFromStream(SkStream * stream,int ttcIndex) const526 SkTypeface* SkFontMgr_DirectWrite::onCreateFromStream(SkStream* stream, int ttcIndex) const {
527     SkTScopedComPtr<StreamFontFileLoader> fontFileLoader;
528     HRN(StreamFontFileLoader::Create(stream, &fontFileLoader));
529     HRN(fFactory->RegisterFontFileLoader(fontFileLoader.get()));
530     SkAutoIDWriteUnregister<StreamFontFileLoader> autoUnregisterFontFileLoader(
531         fFactory.get(), fontFileLoader.get());
532 
533     SkTScopedComPtr<StreamFontCollectionLoader> fontCollectionLoader;
534     HRN(StreamFontCollectionLoader::Create(fontFileLoader.get(), &fontCollectionLoader));
535     HRN(fFactory->RegisterFontCollectionLoader(fontCollectionLoader.get()));
536     SkAutoIDWriteUnregister<StreamFontCollectionLoader> autoUnregisterFontCollectionLoader(
537         fFactory.get(), fontCollectionLoader.get());
538 
539     SkTScopedComPtr<IDWriteFontCollection> fontCollection;
540     HRN(fFactory->CreateCustomFontCollection(fontCollectionLoader.get(), NULL, 0, &fontCollection));
541 
542     // Find the first non-simulated font which has the given ttc index.
543     UINT32 familyCount = fontCollection->GetFontFamilyCount();
544     for (UINT32 familyIndex = 0; familyIndex < familyCount; ++familyIndex) {
545         SkTScopedComPtr<IDWriteFontFamily> fontFamily;
546         HRN(fontCollection->GetFontFamily(familyIndex, &fontFamily));
547 
548         UINT32 fontCount = fontFamily->GetFontCount();
549         for (UINT32 fontIndex = 0; fontIndex < fontCount; ++fontIndex) {
550             SkTScopedComPtr<IDWriteFont> font;
551             HRN(fontFamily->GetFont(fontIndex, &font));
552             if (font->GetSimulations() != DWRITE_FONT_SIMULATIONS_NONE) {
553                 continue;
554             }
555 
556             SkTScopedComPtr<IDWriteFontFace> fontFace;
557             HRN(font->CreateFontFace(&fontFace));
558 
559             UINT32 faceIndex = fontFace->GetIndex();
560             if (faceIndex == ttcIndex) {
561                 return DWriteFontTypeface::Create(fFactory.get(),
562                                                   fontFace.get(), font.get(), fontFamily.get(),
563                                                   autoUnregisterFontFileLoader.detatch(),
564                                                   autoUnregisterFontCollectionLoader.detatch());
565             }
566         }
567     }
568 
569     return NULL;
570 }
571 
onCreateFromData(SkData * data,int ttcIndex) const572 SkTypeface* SkFontMgr_DirectWrite::onCreateFromData(SkData* data, int ttcIndex) const {
573     SkAutoTUnref<SkStream> stream(SkNEW_ARGS(SkMemoryStream, (data)));
574     return this->createFromStream(stream, ttcIndex);
575 }
576 
onCreateFromFile(const char path[],int ttcIndex) const577 SkTypeface* SkFontMgr_DirectWrite::onCreateFromFile(const char path[], int ttcIndex) const {
578     SkAutoTUnref<SkStream> stream(SkStream::NewFromFile(path));
579     return this->createFromStream(stream, ttcIndex);
580 }
581 
getByFamilyName(const WCHAR wideFamilyName[],IDWriteFontFamily ** fontFamily) const582 HRESULT SkFontMgr_DirectWrite::getByFamilyName(const WCHAR wideFamilyName[],
583                                                IDWriteFontFamily** fontFamily) const {
584     UINT32 index;
585     BOOL exists;
586     HR(fFontCollection->FindFamilyName(wideFamilyName, &index, &exists));
587 
588     if (exists) {
589         HR(fFontCollection->GetFontFamily(index, fontFamily));
590     }
591     return S_OK;
592 }
593 
getDefaultFontFamily(IDWriteFontFamily ** fontFamily) const594 HRESULT SkFontMgr_DirectWrite::getDefaultFontFamily(IDWriteFontFamily** fontFamily) const {
595     NONCLIENTMETRICSW metrics;
596     metrics.cbSize = sizeof(metrics);
597     if (0 == SystemParametersInfoW(SPI_GETNONCLIENTMETRICS,
598                                    sizeof(metrics),
599                                    &metrics,
600                                    0)) {
601         return E_UNEXPECTED;
602     }
603     HRM(this->getByFamilyName(metrics.lfMessageFont.lfFaceName, fontFamily),
604         "Could not create DWrite font family from LOGFONT.");
605     return S_OK;
606 }
607 
onLegacyCreateTypeface(const char familyName[],unsigned styleBits) const608 SkTypeface* SkFontMgr_DirectWrite::onLegacyCreateTypeface(const char familyName[],
609                                                           unsigned styleBits) const {
610     SkTScopedComPtr<IDWriteFontFamily> fontFamily;
611     if (familyName) {
612         SkSMallocWCHAR wideFamilyName;
613         if (SUCCEEDED(sk_cstring_to_wchar(familyName, &wideFamilyName))) {
614             this->getByFamilyName(wideFamilyName, &fontFamily);
615         }
616     }
617 
618     if (NULL == fontFamily.get()) {
619         // No family with given name, try default.
620         HRNM(this->getDefaultFontFamily(&fontFamily), "Could not get default font family.");
621     }
622 
623     if (NULL == fontFamily.get()) {
624         // Could not obtain the default font.
625         HRNM(fFontCollection->GetFontFamily(0, &fontFamily),
626              "Could not get default-default font family.");
627     }
628 
629     SkTScopedComPtr<IDWriteFont> font;
630     DWRITE_FONT_WEIGHT weight = (styleBits & SkTypeface::kBold)
631                               ? DWRITE_FONT_WEIGHT_BOLD
632                               : DWRITE_FONT_WEIGHT_NORMAL;
633     DWRITE_FONT_STRETCH stretch = DWRITE_FONT_STRETCH_NORMAL;
634     DWRITE_FONT_STYLE italic = (styleBits & SkTypeface::kItalic)
635                              ? DWRITE_FONT_STYLE_ITALIC
636                              : DWRITE_FONT_STYLE_NORMAL;
637     HRNM(fontFamily->GetFirstMatchingFont(weight, stretch, italic, &font),
638          "Could not get matching font.");
639 
640     SkTScopedComPtr<IDWriteFontFace> fontFace;
641     HRNM(font->CreateFontFace(&fontFace), "Could not create font face.");
642 
643     return this->createTypefaceFromDWriteFont(fontFace.get(), font.get(), fontFamily.get());
644 }
645 
646 ///////////////////////////////////////////////////////////////////////////////
647 
count()648 int SkFontStyleSet_DirectWrite::count() {
649     return fFontFamily->GetFontCount();
650 }
651 
createTypeface(int index)652 SkTypeface* SkFontStyleSet_DirectWrite::createTypeface(int index) {
653     SkTScopedComPtr<IDWriteFont> font;
654     HRNM(fFontFamily->GetFont(index, &font), "Could not get font.");
655 
656     SkTScopedComPtr<IDWriteFontFace> fontFace;
657     HRNM(font->CreateFontFace(&fontFace), "Could not create font face.");
658 
659     return fFontMgr->createTypefaceFromDWriteFont(fontFace.get(), font.get(), fFontFamily.get());
660 }
661 
getStyle(int index,SkFontStyle * fs,SkString * styleName)662 void SkFontStyleSet_DirectWrite::getStyle(int index, SkFontStyle* fs, SkString* styleName) {
663     SkTScopedComPtr<IDWriteFont> font;
664     HRVM(fFontFamily->GetFont(index, &font), "Could not get font.");
665 
666     if (fs) {
667         SkFontStyle::Slant slant;
668         switch (font->GetStyle()) {
669         case DWRITE_FONT_STYLE_NORMAL:
670             slant = SkFontStyle::kUpright_Slant;
671             break;
672         case DWRITE_FONT_STYLE_OBLIQUE:
673         case DWRITE_FONT_STYLE_ITALIC:
674             slant = SkFontStyle::kItalic_Slant;
675             break;
676         default:
677             SkASSERT(false);
678         }
679 
680         int weight = font->GetWeight();
681         int width = font->GetStretch();
682 
683         *fs = SkFontStyle(weight, width, slant);
684     }
685 
686     if (styleName) {
687         SkTScopedComPtr<IDWriteLocalizedStrings> faceNames;
688         if (SUCCEEDED(font->GetFaceNames(&faceNames))) {
689             sk_get_locale_string(faceNames.get(), fFontMgr->fLocaleName.get(), styleName);
690         }
691     }
692 }
693 
matchStyle(const SkFontStyle & pattern)694 SkTypeface* SkFontStyleSet_DirectWrite::matchStyle(const SkFontStyle& pattern) {
695     DWRITE_FONT_STYLE slant;
696     switch (pattern.slant()) {
697     case SkFontStyle::kUpright_Slant:
698         slant = DWRITE_FONT_STYLE_NORMAL;
699         break;
700     case SkFontStyle::kItalic_Slant:
701         slant = DWRITE_FONT_STYLE_ITALIC;
702         break;
703     default:
704         SkASSERT(false);
705     }
706 
707     DWRITE_FONT_WEIGHT weight = (DWRITE_FONT_WEIGHT)pattern.weight();
708     DWRITE_FONT_STRETCH width = (DWRITE_FONT_STRETCH)pattern.width();
709 
710     SkTScopedComPtr<IDWriteFont> font;
711     // TODO: perhaps use GetMatchingFonts and get the least simulated?
712     HRNM(fFontFamily->GetFirstMatchingFont(weight, width, slant, &font),
713          "Could not match font in family.");
714 
715     SkTScopedComPtr<IDWriteFontFace> fontFace;
716     HRNM(font->CreateFontFace(&fontFace), "Could not create font face.");
717 
718     return fFontMgr->createTypefaceFromDWriteFont(fontFace.get(), font.get(),
719                                                   fFontFamily.get());
720 }
721 
722 ////////////////////////////////////////////////////////////////////////////////
723 #include "SkTypeface_win.h"
724 
SkFontMgr_New_DirectWrite(IDWriteFactory * factory)725 SK_API SkFontMgr* SkFontMgr_New_DirectWrite(IDWriteFactory* factory) {
726     if (NULL == factory) {
727         factory = sk_get_dwrite_factory();
728         if (NULL == factory) {
729             return NULL;
730         }
731     }
732 
733     SkTScopedComPtr<IDWriteFontCollection> sysFontCollection;
734     HRNM(factory->GetSystemFontCollection(&sysFontCollection, FALSE),
735          "Could not get system font collection.");
736 
737     WCHAR localeNameStorage[LOCALE_NAME_MAX_LENGTH];
738     WCHAR* localeName = NULL;
739     int localeNameLen = 0;
740 
741     // Dynamically load GetUserDefaultLocaleName function, as it is not available on XP.
742     SkGetUserDefaultLocaleNameProc getUserDefaultLocaleNameProc = NULL;
743     HRESULT hr = SkGetGetUserDefaultLocaleNameProc(&getUserDefaultLocaleNameProc);
744     if (NULL == getUserDefaultLocaleNameProc) {
745         SK_TRACEHR(hr, "Could not get GetUserDefaultLocaleName.");
746     } else {
747         localeNameLen = getUserDefaultLocaleNameProc(localeNameStorage, LOCALE_NAME_MAX_LENGTH);
748         if (localeNameLen) {
749             localeName = localeNameStorage;
750         };
751     }
752 
753     return SkNEW_ARGS(SkFontMgr_DirectWrite, (factory, sysFontCollection.get(),
754                                               localeName, localeNameLen));
755 }
756 
757 #include "SkFontMgr_indirect.h"
SkFontMgr_New_DirectWriteRenderer(SkRemotableFontMgr * proxy)758 SK_API SkFontMgr* SkFontMgr_New_DirectWriteRenderer(SkRemotableFontMgr* proxy) {
759     SkAutoTUnref<SkFontMgr> impl(SkFontMgr_New_DirectWrite());
760     if (impl.get() == NULL) {
761         return NULL;
762     }
763     return SkNEW_ARGS(SkFontMgr_Indirect, (impl.get(), proxy));
764 }
765