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