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