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