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