2 * Copyright 2011 Google Inc.
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
11 #include "SkAdvancedTypefaceMetrics.h"
12 #include "SkColorFilter.h"
13 #include "SkDWriteFontFileStream.h"
14 #include "SkDWriteGeometrySink.h"
15 #include "SkDescriptor.h"
17 #include "SkFontDescriptor.h"
18 #include "SkFontHost.h"
19 #include "SkFontMgr.h"
20 #include "SkFontStream.h"
22 #include "SkHRESULT.h"
23 #include "SkMaskGamma.h"
25 #include "SkOTTable_head.h"
26 #include "SkOTTable_hhea.h"
27 #include "SkOTTable_OS_2.h"
28 #include "SkOTTable_post.h"
32 #include "SkTScopedComPtr.h"
34 #include "SkTypeface_win.h"
35 #include "SkTypefaceCache.h"
40 static bool isLCD(const SkScalerContext::Rec& rec) {
41 return SkMask::kLCD16_Format == rec.fMaskFormat ||
42 SkMask::kLCD32_Format == rec.fMaskFormat;
45 /** Prefer to use this type to prevent template proliferation. */
46 typedef SkAutoSTMalloc<16, WCHAR> SkSMallocWCHAR;
48 /** Converts a utf8 string to a WCHAR string. */
49 static HRESULT cstring_to_wchar(const char* skname, SkSMallocWCHAR* name) {
50 int wlen = MultiByteToWideChar(CP_UTF8, 0, skname, -1, NULL, 0);
52 HRM(HRESULT_FROM_WIN32(GetLastError()),
53 "Could not get length for wchar to utf-8 conversion.");
56 wlen = MultiByteToWideChar(CP_UTF8, 0, skname, -1, name->get(), wlen);
58 HRM(HRESULT_FROM_WIN32(GetLastError()), "Could not convert wchar to utf-8.");
63 /** Converts a WCHAR string to a utf8 string. */
64 static HRESULT wchar_to_skstring(WCHAR* name, SkString* skname) {
65 int len = WideCharToMultiByte(CP_UTF8, 0, name, -1, NULL, 0, NULL, NULL);
67 HRM(HRESULT_FROM_WIN32(GetLastError()),
68 "Could not get length for utf-8 to wchar conversion.");
70 skname->resize(len - 1);
72 // TODO: remove after https://code.google.com/p/skia/issues/detail?id=1989 is fixed.
73 // If we resize to 0 then the skname points to gEmptyRec (the unique empty SkString::Rec).
74 // gEmptyRec is static const and on Windows this means the value is in a read only page.
75 // Writing to it in the following call to WideCharToMultiByte will cause an access violation.
80 len = WideCharToMultiByte(CP_UTF8, 0, name, -1, skname->writable_str(), len, NULL, NULL);
82 HRM(HRESULT_FROM_WIN32(GetLastError()), "Could not convert utf-8 to wchar.");
87 ///////////////////////////////////////////////////////////////////////////////
89 static void create_dwrite_factory(IDWriteFactory** factory) {
90 typedef decltype(DWriteCreateFactory)* DWriteCreateFactoryProc;
91 DWriteCreateFactoryProc dWriteCreateFactoryProc = reinterpret_cast<DWriteCreateFactoryProc>(
92 GetProcAddress(LoadLibraryW(L"dwrite.dll"), "DWriteCreateFactory"));
94 if (!dWriteCreateFactoryProc) {
95 HRESULT hr = HRESULT_FROM_WIN32(GetLastError());
97 hr = ERROR_PROC_NOT_FOUND;
99 HRVM(hr, "Could not get DWriteCreateFactory proc.");
102 HRVM(dWriteCreateFactoryProc(DWRITE_FACTORY_TYPE_SHARED,
103 __uuidof(IDWriteFactory),
104 reinterpret_cast<IUnknown**>(factory)),
105 "Could not create DirectWrite factory.");
108 static IDWriteFactory* get_dwrite_factory() {
109 static IDWriteFactory* gDWriteFactory = NULL;
110 SK_DECLARE_STATIC_ONCE(once);
111 SkOnce(&once, create_dwrite_factory, &gDWriteFactory);
113 return gDWriteFactory;
116 ///////////////////////////////////////////////////////////////////////////////
118 class StreamFontFileLoader;
120 class SkFontMgr_DirectWrite : public SkFontMgr {
122 /** localeNameLength must include the null terminator. */
123 SkFontMgr_DirectWrite(IDWriteFontCollection* fontCollection,
124 WCHAR* localeName, int localeNameLength)
125 : fFontCollection(SkRefComPtr(fontCollection))
126 , fLocaleName(localeNameLength)
128 memcpy(fLocaleName.get(), localeName, localeNameLength * sizeof(WCHAR));
131 SkTypefaceCache* getTypefaceCache() { return &fTFCache; }
133 SkTypeface* createTypefaceFromDWriteFont(IDWriteFontFace* fontFace,
135 IDWriteFontFamily* fontFamily,
136 StreamFontFileLoader* = NULL,
137 IDWriteFontCollectionLoader* = NULL);
140 virtual int onCountFamilies() SK_OVERRIDE;
141 virtual void onGetFamilyName(int index, SkString* familyName) SK_OVERRIDE;
142 virtual SkFontStyleSet* onCreateStyleSet(int index) SK_OVERRIDE;
143 virtual SkFontStyleSet* onMatchFamily(const char familyName[]) SK_OVERRIDE;
144 virtual SkTypeface* onMatchFamilyStyle(const char familyName[],
145 const SkFontStyle& fontstyle) SK_OVERRIDE;
146 virtual SkTypeface* onMatchFaceStyle(const SkTypeface* familyMember,
147 const SkFontStyle& fontstyle) SK_OVERRIDE;
148 virtual SkTypeface* onCreateFromStream(SkStream* stream, int ttcIndex) SK_OVERRIDE;
149 virtual SkTypeface* onCreateFromData(SkData* data, int ttcIndex) SK_OVERRIDE;
150 virtual SkTypeface* onCreateFromFile(const char path[], int ttcIndex) SK_OVERRIDE;
151 virtual SkTypeface* onLegacyCreateTypeface(const char familyName[],
152 unsigned styleBits) SK_OVERRIDE;
155 HRESULT getByFamilyName(const WCHAR familyName[], IDWriteFontFamily** fontFamily);
156 HRESULT getDefaultFontFamily(IDWriteFontFamily** fontFamily);
158 SkMutex fTFCacheMutex;
159 void Add(SkTypeface* face, SkTypeface::Style requestedStyle, bool strong) {
160 SkAutoMutexAcquire ama(fTFCacheMutex);
161 fTFCache.add(face, requestedStyle, strong);
164 SkTypeface* FindByProcAndRef(SkTypefaceCache::FindProc proc, void* ctx) {
165 SkAutoMutexAcquire ama(fTFCacheMutex);
166 SkTypeface* typeface = fTFCache.findByProcAndRef(proc, ctx);
170 friend class SkFontStyleSet_DirectWrite;
171 SkTScopedComPtr<IDWriteFontCollection> fFontCollection;
172 SkSMallocWCHAR fLocaleName;
173 SkTypefaceCache fTFCache;
176 class SkFontStyleSet_DirectWrite : public SkFontStyleSet {
178 SkFontStyleSet_DirectWrite(SkFontMgr_DirectWrite* fontMgr, IDWriteFontFamily* fontFamily)
179 : fFontMgr(SkRef(fontMgr))
180 , fFontFamily(SkRefComPtr(fontFamily))
183 virtual int count() SK_OVERRIDE;
184 virtual void getStyle(int index, SkFontStyle* fs, SkString* styleName) SK_OVERRIDE;
185 virtual SkTypeface* createTypeface(int index) SK_OVERRIDE;
186 virtual SkTypeface* matchStyle(const SkFontStyle& pattern) SK_OVERRIDE;
189 SkAutoTUnref<SkFontMgr_DirectWrite> fFontMgr;
190 SkTScopedComPtr<IDWriteFontFamily> fFontFamily;
193 ///////////////////////////////////////////////////////////////////////////////
195 class DWriteOffscreen {
197 DWriteOffscreen() : fWidth(0), fHeight(0) {
200 void init(IDWriteFontFace* fontFace, const DWRITE_MATRIX& xform, FLOAT fontSize) {
201 fFontFace = fontFace;
202 fFontSize = fontSize;
206 const void* draw(const SkGlyph&, bool isBW);
211 IDWriteFontFace* fFontFace;
213 DWRITE_MATRIX fXform;
214 SkTDArray<uint8_t> fBits;
217 const void* DWriteOffscreen::draw(const SkGlyph& glyph, bool isBW) {
218 IDWriteFactory* factory = get_dwrite_factory();
219 SkASSERT(factory != NULL);
221 if (fWidth < glyph.fWidth || fHeight < glyph.fHeight) {
222 fWidth = SkMax32(fWidth, glyph.fWidth);
223 fHeight = SkMax32(fHeight, glyph.fHeight);
226 fBits.setCount(fWidth * fHeight);
228 fBits.setCount(fWidth * fHeight * 3);
233 memset(fBits.begin(), 0, fBits.count());
235 fXform.dx = SkFixedToFloat(glyph.getSubXFixed());
236 fXform.dy = SkFixedToFloat(glyph.getSubYFixed());
238 FLOAT advance = 0.0f;
240 UINT16 index = glyph.getGlyphID();
242 DWRITE_GLYPH_OFFSET offset;
243 offset.advanceOffset = 0.0f;
244 offset.ascenderOffset = 0.0f;
246 DWRITE_GLYPH_RUN run;
248 run.glyphAdvances = &advance;
249 run.fontFace = fFontFace;
250 run.fontEmSize = fFontSize;
252 run.glyphIndices = &index;
253 run.isSideways = FALSE;
254 run.glyphOffsets = &offset;
256 DWRITE_RENDERING_MODE renderingMode;
257 DWRITE_TEXTURE_TYPE textureType;
259 renderingMode = DWRITE_RENDERING_MODE_ALIASED;
260 textureType = DWRITE_TEXTURE_ALIASED_1x1;
262 renderingMode = DWRITE_RENDERING_MODE_CLEARTYPE_NATURAL_SYMMETRIC;
263 textureType = DWRITE_TEXTURE_CLEARTYPE_3x1;
265 SkTScopedComPtr<IDWriteGlyphRunAnalysis> glyphRunAnalysis;
266 HRNM(factory->CreateGlyphRunAnalysis(&run,
267 1.0f, // pixelsPerDip,
270 DWRITE_MEASURING_MODE_NATURAL,
271 0.0f, // baselineOriginX,
272 0.0f, // baselineOriginY,
274 "Could not create glyph run analysis.");
276 //NOTE: this assumes that the glyph has already been measured
277 //with an exact same glyph run analysis.
279 bbox.left = glyph.fLeft;
280 bbox.top = glyph.fTop;
281 bbox.right = glyph.fLeft + glyph.fWidth;
282 bbox.bottom = glyph.fTop + glyph.fHeight;
283 HRNM(glyphRunAnalysis->CreateAlphaTexture(textureType,
287 "Could not draw mask.");
288 return fBits.begin();
291 ///////////////////////////////////////////////////////////////////////////////
293 class StreamFontFileLoader : public IDWriteFontFileLoader {
296 virtual HRESULT STDMETHODCALLTYPE QueryInterface(REFIID iid, void** ppvObject);
297 virtual ULONG STDMETHODCALLTYPE AddRef();
298 virtual ULONG STDMETHODCALLTYPE Release();
300 // IDWriteFontFileLoader methods
301 virtual HRESULT STDMETHODCALLTYPE CreateStreamFromKey(
302 void const* fontFileReferenceKey,
303 UINT32 fontFileReferenceKeySize,
304 IDWriteFontFileStream** fontFileStream);
306 static HRESULT Create(SkStream* stream, StreamFontFileLoader** streamFontFileLoader) {
307 *streamFontFileLoader = new StreamFontFileLoader(stream);
308 if (NULL == streamFontFileLoader) {
309 return E_OUTOFMEMORY;
314 SkAutoTUnref<SkStream> fStream;
317 StreamFontFileLoader(SkStream* stream) : fRefCount(1), fStream(SkRef(stream)) { }
322 HRESULT StreamFontFileLoader::QueryInterface(REFIID iid, void** ppvObject) {
323 if (iid == IID_IUnknown || iid == __uuidof(IDWriteFontFileLoader)) {
329 return E_NOINTERFACE;
333 ULONG StreamFontFileLoader::AddRef() {
334 return InterlockedIncrement(&fRefCount);
337 ULONG StreamFontFileLoader::Release() {
338 ULONG newCount = InterlockedDecrement(&fRefCount);
345 HRESULT StreamFontFileLoader::CreateStreamFromKey(
346 void const* fontFileReferenceKey,
347 UINT32 fontFileReferenceKeySize,
348 IDWriteFontFileStream** fontFileStream)
350 SkTScopedComPtr<SkDWriteFontFileStreamWrapper> stream;
351 HR(SkDWriteFontFileStreamWrapper::Create(fStream, &stream));
352 *fontFileStream = stream.release();
356 class StreamFontFileEnumerator : public IDWriteFontFileEnumerator {
359 virtual HRESULT STDMETHODCALLTYPE QueryInterface(REFIID iid, void** ppvObject);
360 virtual ULONG STDMETHODCALLTYPE AddRef();
361 virtual ULONG STDMETHODCALLTYPE Release();
363 // IDWriteFontFileEnumerator methods
364 virtual HRESULT STDMETHODCALLTYPE MoveNext(BOOL* hasCurrentFile);
365 virtual HRESULT STDMETHODCALLTYPE GetCurrentFontFile(IDWriteFontFile** fontFile);
367 static HRESULT Create(IDWriteFactory* factory, IDWriteFontFileLoader* fontFileLoader,
368 StreamFontFileEnumerator** streamFontFileEnumerator) {
369 *streamFontFileEnumerator = new StreamFontFileEnumerator(factory, fontFileLoader);
370 if (NULL == streamFontFileEnumerator) {
371 return E_OUTOFMEMORY;
376 StreamFontFileEnumerator(IDWriteFactory* factory, IDWriteFontFileLoader* fontFileLoader);
379 SkTScopedComPtr<IDWriteFactory> fFactory;
380 SkTScopedComPtr<IDWriteFontFile> fCurrentFile;
381 SkTScopedComPtr<IDWriteFontFileLoader> fFontFileLoader;
385 StreamFontFileEnumerator::StreamFontFileEnumerator(IDWriteFactory* factory,
386 IDWriteFontFileLoader* fontFileLoader)
388 , fFactory(SkRefComPtr(factory))
390 , fFontFileLoader(SkRefComPtr(fontFileLoader))
394 HRESULT StreamFontFileEnumerator::QueryInterface(REFIID iid, void** ppvObject) {
395 if (iid == IID_IUnknown || iid == __uuidof(IDWriteFontFileEnumerator)) {
401 return E_NOINTERFACE;
405 ULONG StreamFontFileEnumerator::AddRef() {
406 return InterlockedIncrement(&fRefCount);
409 ULONG StreamFontFileEnumerator::Release() {
410 ULONG newCount = InterlockedDecrement(&fRefCount);
417 HRESULT StreamFontFileEnumerator::MoveNext(BOOL* hasCurrentFile) {
418 *hasCurrentFile = FALSE;
426 HR(fFactory->CreateCustomFontFileReference(
427 &dummy, //cannot be NULL
428 sizeof(dummy), //even if this is 0
429 fFontFileLoader.get(),
432 *hasCurrentFile = TRUE;
436 HRESULT StreamFontFileEnumerator::GetCurrentFontFile(IDWriteFontFile** fontFile) {
437 if (fCurrentFile.get() == NULL) {
442 *fontFile = SkRefComPtr(fCurrentFile.get());
446 class StreamFontCollectionLoader : public IDWriteFontCollectionLoader {
449 virtual HRESULT STDMETHODCALLTYPE QueryInterface(REFIID iid, void** ppvObject);
450 virtual ULONG STDMETHODCALLTYPE AddRef();
451 virtual ULONG STDMETHODCALLTYPE Release();
453 // IDWriteFontCollectionLoader methods
454 virtual HRESULT STDMETHODCALLTYPE CreateEnumeratorFromKey(
455 IDWriteFactory* factory,
456 void const* collectionKey,
457 UINT32 collectionKeySize,
458 IDWriteFontFileEnumerator** fontFileEnumerator);
460 static HRESULT Create(IDWriteFontFileLoader* fontFileLoader,
461 StreamFontCollectionLoader** streamFontCollectionLoader) {
462 *streamFontCollectionLoader = new StreamFontCollectionLoader(fontFileLoader);
463 if (NULL == streamFontCollectionLoader) {
464 return E_OUTOFMEMORY;
469 StreamFontCollectionLoader(IDWriteFontFileLoader* fontFileLoader)
471 , fFontFileLoader(SkRefComPtr(fontFileLoader))
475 SkTScopedComPtr<IDWriteFontFileLoader> fFontFileLoader;
478 HRESULT StreamFontCollectionLoader::QueryInterface(REFIID iid, void** ppvObject) {
479 if (iid == IID_IUnknown || iid == __uuidof(IDWriteFontCollectionLoader)) {
485 return E_NOINTERFACE;
489 ULONG StreamFontCollectionLoader::AddRef() {
490 return InterlockedIncrement(&fRefCount);
493 ULONG StreamFontCollectionLoader::Release() {
494 ULONG newCount = InterlockedDecrement(&fRefCount);
501 HRESULT StreamFontCollectionLoader::CreateEnumeratorFromKey(
502 IDWriteFactory* factory,
503 void const* collectionKey,
504 UINT32 collectionKeySize,
505 IDWriteFontFileEnumerator** fontFileEnumerator)
507 SkTScopedComPtr<StreamFontFileEnumerator> enumerator;
508 HR(StreamFontFileEnumerator::Create(factory, fFontFileLoader.get(), &enumerator));
509 *fontFileEnumerator = enumerator.release();
513 ///////////////////////////////////////////////////////////////////////////////
515 static SkTypeface::Style get_style(IDWriteFont* font) {
516 int style = SkTypeface::kNormal;
517 DWRITE_FONT_WEIGHT weight = font->GetWeight();
518 if (DWRITE_FONT_WEIGHT_DEMI_BOLD <= weight) {
519 style |= SkTypeface::kBold;
521 DWRITE_FONT_STYLE angle = font->GetStyle();
522 if (DWRITE_FONT_STYLE_OBLIQUE == angle || DWRITE_FONT_STYLE_ITALIC == angle) {
523 style |= SkTypeface::kItalic;
525 return static_cast<SkTypeface::Style>(style);
528 class DWriteFontTypeface : public SkTypeface {
530 DWriteFontTypeface(SkTypeface::Style style, SkFontID fontID,
531 IDWriteFontFace* fontFace,
533 IDWriteFontFamily* fontFamily,
534 StreamFontFileLoader* fontFileLoader = NULL,
535 IDWriteFontCollectionLoader* fontCollectionLoader = NULL)
536 : SkTypeface(style, fontID, false)
537 , fDWriteFontCollectionLoader(SkSafeRefComPtr(fontCollectionLoader))
538 , fDWriteFontFileLoader(SkSafeRefComPtr(fontFileLoader))
539 , fDWriteFontFamily(SkRefComPtr(fontFamily))
540 , fDWriteFont(SkRefComPtr(font))
541 , fDWriteFontFace(SkRefComPtr(fontFace))
545 SkTScopedComPtr<IDWriteFontCollectionLoader> fDWriteFontCollectionLoader;
546 SkTScopedComPtr<StreamFontFileLoader> fDWriteFontFileLoader;
547 SkTScopedComPtr<IDWriteFontFamily> fDWriteFontFamily;
548 SkTScopedComPtr<IDWriteFont> fDWriteFont;
549 SkTScopedComPtr<IDWriteFontFace> fDWriteFontFace;
551 static DWriteFontTypeface* Create(IDWriteFontFace* fontFace,
553 IDWriteFontFamily* fontFamily,
554 StreamFontFileLoader* fontFileLoader = NULL,
555 IDWriteFontCollectionLoader* fontCollectionLoader = NULL) {
556 SkTypeface::Style style = get_style(font);
557 SkFontID fontID = SkTypefaceCache::NewFontID();
558 return SkNEW_ARGS(DWriteFontTypeface, (style, fontID,
559 fontFace, font, fontFamily,
560 fontFileLoader, fontCollectionLoader));
563 ~DWriteFontTypeface() {
564 if (fDWriteFontCollectionLoader.get() == NULL) return;
566 IDWriteFactory* factory = get_dwrite_factory();
567 SkASSERT(factory != NULL);
568 HRV(factory->UnregisterFontCollectionLoader(fDWriteFontCollectionLoader.get()));
569 HRV(factory->UnregisterFontFileLoader(fDWriteFontFileLoader.get()));
573 virtual SkStream* onOpenStream(int* ttcIndex) const SK_OVERRIDE;
574 virtual SkScalerContext* onCreateScalerContext(const SkDescriptor*) const SK_OVERRIDE;
575 virtual void onFilterRec(SkScalerContextRec*) const SK_OVERRIDE;
576 virtual SkAdvancedTypefaceMetrics* onGetAdvancedTypefaceMetrics(
577 SkAdvancedTypefaceMetrics::PerGlyphInfo,
578 const uint32_t*, uint32_t) const SK_OVERRIDE;
579 virtual void onGetFontDescriptor(SkFontDescriptor*, bool*) const SK_OVERRIDE;
580 virtual int onCharsToGlyphs(const void* chars, Encoding encoding,
581 uint16_t glyphs[], int glyphCount) const SK_OVERRIDE;
582 virtual int onCountGlyphs() const SK_OVERRIDE;
583 virtual int onGetUPEM() const SK_OVERRIDE;
584 virtual SkTypeface::LocalizedStrings* onCreateFamilyNameIterator() const SK_OVERRIDE;
585 virtual int onGetTableTags(SkFontTableTag tags[]) const SK_OVERRIDE;
586 virtual size_t onGetTableData(SkFontTableTag, size_t offset,
587 size_t length, void* data) const SK_OVERRIDE;
590 class SkScalerContext_DW : public SkScalerContext {
592 SkScalerContext_DW(DWriteFontTypeface*, const SkDescriptor* desc);
593 virtual ~SkScalerContext_DW();
596 virtual unsigned generateGlyphCount() SK_OVERRIDE;
597 virtual uint16_t generateCharToGlyph(SkUnichar uni) SK_OVERRIDE;
598 virtual void generateAdvance(SkGlyph* glyph) SK_OVERRIDE;
599 virtual void generateMetrics(SkGlyph* glyph) SK_OVERRIDE;
600 virtual void generateImage(const SkGlyph& glyph) SK_OVERRIDE;
601 virtual void generatePath(const SkGlyph& glyph, SkPath* path) SK_OVERRIDE;
602 virtual void generateFontMetrics(SkPaint::FontMetrics* mX,
603 SkPaint::FontMetrics* mY) SK_OVERRIDE;
606 DWriteOffscreen fOffscreen;
607 DWRITE_MATRIX fXform;
608 SkAutoTUnref<DWriteFontTypeface> fTypeface;
612 static bool are_same(IUnknown* a, IUnknown* b) {
613 SkTScopedComPtr<IUnknown> iunkA;
614 if (FAILED(a->QueryInterface(&iunkA))) {
618 SkTScopedComPtr<IUnknown> iunkB;
619 if (FAILED(b->QueryInterface(&iunkB))) {
623 return iunkA.get() == iunkB.get();
625 static bool FindByDWriteFont(SkTypeface* face, SkTypeface::Style requestedStyle, void* ctx) {
626 //Check to see if the two fonts are identical.
627 DWriteFontTypeface* dwFace = reinterpret_cast<DWriteFontTypeface*>(face);
628 IDWriteFont* dwFont = reinterpret_cast<IDWriteFont*>(ctx);
629 if (are_same(dwFace->fDWriteFont.get(), dwFont)) {
633 //Check if the two fonts share the same loader and have the same key.
634 SkTScopedComPtr<IDWriteFontFace> dwFaceFontFace;
635 SkTScopedComPtr<IDWriteFontFace> dwFontFace;
636 HRB(dwFace->fDWriteFont->CreateFontFace(&dwFaceFontFace));
637 HRB(dwFont->CreateFontFace(&dwFontFace));
638 if (are_same(dwFaceFontFace.get(), dwFontFace.get())) {
642 UINT32 dwFaceNumFiles;
644 HRB(dwFaceFontFace->GetFiles(&dwFaceNumFiles, NULL));
645 HRB(dwFontFace->GetFiles(&dwNumFiles, NULL));
646 if (dwFaceNumFiles != dwNumFiles) {
650 SkTScopedComPtr<IDWriteFontFile> dwFaceFontFile;
651 SkTScopedComPtr<IDWriteFontFile> dwFontFile;
652 HRB(dwFaceFontFace->GetFiles(&dwFaceNumFiles, &dwFaceFontFile));
653 HRB(dwFontFace->GetFiles(&dwNumFiles, &dwFontFile));
655 //for (each file) { //we currently only admit fonts from one file.
656 SkTScopedComPtr<IDWriteFontFileLoader> dwFaceFontFileLoader;
657 SkTScopedComPtr<IDWriteFontFileLoader> dwFontFileLoader;
658 HRB(dwFaceFontFile->GetLoader(&dwFaceFontFileLoader));
659 HRB(dwFontFile->GetLoader(&dwFontFileLoader));
660 if (!are_same(dwFaceFontFileLoader.get(), dwFontFileLoader.get())) {
665 const void* dwFaceFontRefKey;
666 UINT32 dwFaceFontRefKeySize;
667 const void* dwFontRefKey;
668 UINT32 dwFontRefKeySize;
669 HRB(dwFaceFontFile->GetReferenceKey(&dwFaceFontRefKey, &dwFaceFontRefKeySize));
670 HRB(dwFontFile->GetReferenceKey(&dwFontRefKey, &dwFontRefKeySize));
671 if (dwFaceFontRefKeySize != dwFontRefKeySize) {
674 if (0 != memcmp(dwFaceFontRefKey, dwFontRefKey, dwFontRefKeySize)) {
678 //TODO: better means than comparing name strings?
679 //NOTE: .tfc and fake bold/italic will end up here.
680 SkTScopedComPtr<IDWriteFontFamily> dwFaceFontFamily;
681 SkTScopedComPtr<IDWriteFontFamily> dwFontFamily;
682 HRB(dwFace->fDWriteFont->GetFontFamily(&dwFaceFontFamily));
683 HRB(dwFont->GetFontFamily(&dwFontFamily));
685 SkTScopedComPtr<IDWriteLocalizedStrings> dwFaceFontFamilyNames;
686 SkTScopedComPtr<IDWriteLocalizedStrings> dwFaceFontNames;
687 HRB(dwFaceFontFamily->GetFamilyNames(&dwFaceFontFamilyNames));
688 HRB(dwFace->fDWriteFont->GetFaceNames(&dwFaceFontNames));
690 SkTScopedComPtr<IDWriteLocalizedStrings> dwFontFamilyNames;
691 SkTScopedComPtr<IDWriteLocalizedStrings> dwFontNames;
692 HRB(dwFontFamily->GetFamilyNames(&dwFontFamilyNames));
693 HRB(dwFont->GetFaceNames(&dwFontNames));
695 UINT32 dwFaceFontFamilyNameLength;
696 UINT32 dwFaceFontNameLength;
697 HRB(dwFaceFontFamilyNames->GetStringLength(0, &dwFaceFontFamilyNameLength));
698 HRB(dwFaceFontNames->GetStringLength(0, &dwFaceFontNameLength));
700 UINT32 dwFontFamilyNameLength;
701 UINT32 dwFontNameLength;
702 HRB(dwFontFamilyNames->GetStringLength(0, &dwFontFamilyNameLength));
703 HRB(dwFontNames->GetStringLength(0, &dwFontNameLength));
705 if (dwFaceFontFamilyNameLength != dwFontFamilyNameLength ||
706 dwFaceFontNameLength != dwFontNameLength)
711 SkSMallocWCHAR dwFaceFontFamilyNameChar(dwFaceFontFamilyNameLength+1);
712 SkSMallocWCHAR dwFaceFontNameChar(dwFaceFontNameLength+1);
713 HRB(dwFaceFontFamilyNames->GetString(0, dwFaceFontFamilyNameChar.get(), dwFaceFontFamilyNameLength+1));
714 HRB(dwFaceFontNames->GetString(0, dwFaceFontNameChar.get(), dwFaceFontNameLength+1));
716 SkSMallocWCHAR dwFontFamilyNameChar(dwFontFamilyNameLength+1);
717 SkSMallocWCHAR dwFontNameChar(dwFontNameLength+1);
718 HRB(dwFontFamilyNames->GetString(0, dwFontFamilyNameChar.get(), dwFontFamilyNameLength+1));
719 HRB(dwFontNames->GetString(0, dwFontNameChar.get(), dwFontNameLength+1));
721 return wcscmp(dwFaceFontFamilyNameChar.get(), dwFontFamilyNameChar.get()) == 0 &&
722 wcscmp(dwFaceFontNameChar.get(), dwFontNameChar.get()) == 0;
725 SkScalerContext_DW::SkScalerContext_DW(DWriteFontTypeface* typeface,
726 const SkDescriptor* desc)
727 : SkScalerContext(typeface, desc)
728 , fTypeface(SkRef(typeface))
731 fXform.m11 = SkScalarToFloat(fRec.fPost2x2[0][0]);
732 fXform.m12 = SkScalarToFloat(fRec.fPost2x2[1][0]);
733 fXform.m21 = SkScalarToFloat(fRec.fPost2x2[0][1]);
734 fXform.m22 = SkScalarToFloat(fRec.fPost2x2[1][1]);
738 fOffscreen.init(fTypeface->fDWriteFontFace.get(), fXform, SkScalarToFloat(fRec.fTextSize));
741 SkScalerContext_DW::~SkScalerContext_DW() {
744 unsigned SkScalerContext_DW::generateGlyphCount() {
745 if (fGlyphCount < 0) {
746 fGlyphCount = fTypeface->fDWriteFontFace->GetGlyphCount();
751 uint16_t SkScalerContext_DW::generateCharToGlyph(SkUnichar uni) {
753 fTypeface->fDWriteFontFace->GetGlyphIndices(reinterpret_cast<UINT32*>(&uni), 1, &index);
757 void SkScalerContext_DW::generateAdvance(SkGlyph* glyph) {
758 //Delta is the difference between the right/left side bearing metric
759 //and where the right/left side bearing ends up after hinting.
760 //DirectWrite does not provide this information.
761 glyph->fRsbDelta = 0;
762 glyph->fLsbDelta = 0;
764 glyph->fAdvanceX = 0;
765 glyph->fAdvanceY = 0;
767 uint16_t glyphId = glyph->getGlyphID();
768 DWRITE_GLYPH_METRICS gm;
769 HRVM(fTypeface->fDWriteFontFace->GetDesignGlyphMetrics(&glyphId, 1, &gm),
770 "Could not get design metrics.");
772 DWRITE_FONT_METRICS dwfm;
773 fTypeface->fDWriteFontFace->GetMetrics(&dwfm);
775 SkScalar advanceX = SkScalarMulDiv(fRec.fTextSize,
776 SkIntToScalar(gm.advanceWidth),
777 SkIntToScalar(dwfm.designUnitsPerEm));
779 if (!(fRec.fFlags & kSubpixelPositioning_Flag)) {
780 advanceX = SkScalarRoundToScalar(advanceX);
783 SkVector vecs[1] = { { advanceX, 0 } };
785 fRec.getMatrixFrom2x2(&mat);
786 mat.mapVectors(vecs, SK_ARRAY_COUNT(vecs));
788 glyph->fAdvanceX = SkScalarToFixed(vecs[0].fX);
789 glyph->fAdvanceY = SkScalarToFixed(vecs[0].fY);
792 void SkScalerContext_DW::generateMetrics(SkGlyph* glyph) {
795 this->generateAdvance(glyph);
797 //Measure raster size.
798 fXform.dx = SkFixedToFloat(glyph->getSubXFixed());
799 fXform.dy = SkFixedToFloat(glyph->getSubYFixed());
803 UINT16 glyphId = glyph->getGlyphID();
805 DWRITE_GLYPH_OFFSET offset;
806 offset.advanceOffset = 0.0f;
807 offset.ascenderOffset = 0.0f;
809 DWRITE_GLYPH_RUN run;
811 run.glyphAdvances = &advance;
812 run.fontFace = fTypeface->fDWriteFontFace.get();
813 run.fontEmSize = SkScalarToFloat(fRec.fTextSize);
815 run.glyphIndices = &glyphId;
816 run.isSideways = FALSE;
817 run.glyphOffsets = &offset;
819 IDWriteFactory* factory = get_dwrite_factory();
820 SkASSERT(factory != NULL);
822 const bool isBW = SkMask::kBW_Format == fRec.fMaskFormat;
823 DWRITE_RENDERING_MODE renderingMode;
824 DWRITE_TEXTURE_TYPE textureType;
826 renderingMode = DWRITE_RENDERING_MODE_ALIASED;
827 textureType = DWRITE_TEXTURE_ALIASED_1x1;
829 renderingMode = DWRITE_RENDERING_MODE_CLEARTYPE_NATURAL_SYMMETRIC;
830 textureType = DWRITE_TEXTURE_CLEARTYPE_3x1;
833 SkTScopedComPtr<IDWriteGlyphRunAnalysis> glyphRunAnalysis;
834 HRVM(factory->CreateGlyphRunAnalysis(&run,
835 1.0f, // pixelsPerDip,
838 DWRITE_MEASURING_MODE_NATURAL,
839 0.0f, // baselineOriginX,
840 0.0f, // baselineOriginY,
842 "Could not create glyph run analysis.");
845 HRVM(glyphRunAnalysis->GetAlphaTextureBounds(textureType, &bbox),
846 "Could not get texture bounds.");
848 glyph->fWidth = SkToU16(bbox.right - bbox.left);
849 glyph->fHeight = SkToU16(bbox.bottom - bbox.top);
850 glyph->fLeft = SkToS16(bbox.left);
851 glyph->fTop = SkToS16(bbox.top);
854 void SkScalerContext_DW::generateFontMetrics(SkPaint::FontMetrics* mx,
855 SkPaint::FontMetrics* my) {
860 sk_bzero(mx, sizeof(*mx));
863 sk_bzero(my, sizeof(*my));
866 DWRITE_FONT_METRICS dwfm;
867 fTypeface->fDWriteFontFace->GetMetrics(&dwfm);
869 SkScalar upem = SkIntToScalar(dwfm.designUnitsPerEm);
871 mx->fTop = -fRec.fTextSize * SkIntToScalar(dwfm.ascent) / upem;
872 mx->fAscent = mx->fTop;
873 mx->fDescent = fRec.fTextSize * SkIntToScalar(dwfm.descent) / upem;
874 mx->fBottom = mx->fDescent;
875 mx->fLeading = fRec.fTextSize * SkIntToScalar(dwfm.lineGap) / upem;
876 mx->fXHeight = fRec.fTextSize * SkIntToScalar(dwfm.xHeight) / upem;
880 my->fTop = -fRec.fTextSize * SkIntToScalar(dwfm.ascent) / upem;
881 my->fAscent = my->fTop;
882 my->fDescent = fRec.fTextSize * SkIntToScalar(dwfm.descent) / upem;
883 my->fBottom = my->fDescent;
884 my->fLeading = fRec.fTextSize * SkIntToScalar(dwfm.lineGap) / upem;
885 my->fXHeight = fRec.fTextSize * SkIntToScalar(dwfm.xHeight) / upem;
889 ///////////////////////////////////////////////////////////////////////////////
891 #include "SkColorPriv.h"
893 static void bilevel_to_bw(const uint8_t* SK_RESTRICT src, const SkGlyph& glyph) {
894 const int width = glyph.fWidth;
895 const size_t dstRB = (width + 7) >> 3;
896 uint8_t* SK_RESTRICT dst = static_cast<uint8_t*>(glyph.fImage);
898 int byteCount = width >> 3;
899 int bitCount = width & 7;
901 for (int y = 0; y < glyph.fHeight; ++y) {
903 for (int i = 0; i < byteCount; ++i) {
905 byte |= src[0] & (1 << 7);
906 byte |= src[1] & (1 << 6);
907 byte |= src[2] & (1 << 5);
908 byte |= src[3] & (1 << 4);
909 byte |= src[4] & (1 << 3);
910 byte |= src[5] & (1 << 2);
911 byte |= src[6] & (1 << 1);
912 byte |= src[7] & (1 << 0);
919 unsigned mask = 0x80;
920 for (int i = 0; i < bitCount; i++) {
921 byte |= (src[i]) & mask;
924 dst[byteCount] = byte;
931 template<bool APPLY_PREBLEND>
932 static void rgb_to_a8(const uint8_t* SK_RESTRICT src, const SkGlyph& glyph, const uint8_t* table8) {
933 const size_t dstRB = glyph.rowBytes();
934 const U16CPU width = glyph.fWidth;
935 uint8_t* SK_RESTRICT dst = static_cast<uint8_t*>(glyph.fImage);
937 for (U16CPU y = 0; y < glyph.fHeight; y++) {
938 for (U16CPU i = 0; i < width; i++) {
942 dst[i] = sk_apply_lut_if<APPLY_PREBLEND>((r + g + b) / 3, table8);
944 dst = (uint8_t*)((char*)dst + dstRB);
948 template<bool APPLY_PREBLEND>
949 static void rgb_to_lcd16(const uint8_t* SK_RESTRICT src, const SkGlyph& glyph,
950 const uint8_t* tableR, const uint8_t* tableG, const uint8_t* tableB) {
951 const size_t dstRB = glyph.rowBytes();
952 const U16CPU width = glyph.fWidth;
953 uint16_t* SK_RESTRICT dst = static_cast<uint16_t*>(glyph.fImage);
955 for (U16CPU y = 0; y < glyph.fHeight; y++) {
956 for (U16CPU i = 0; i < width; i++) {
957 U8CPU r = sk_apply_lut_if<APPLY_PREBLEND>(*(src++), tableR);
958 U8CPU g = sk_apply_lut_if<APPLY_PREBLEND>(*(src++), tableG);
959 U8CPU b = sk_apply_lut_if<APPLY_PREBLEND>(*(src++), tableB);
960 dst[i] = SkPack888ToRGB16(r, g, b);
962 dst = (uint16_t*)((char*)dst + dstRB);
966 template<bool APPLY_PREBLEND>
967 static void rgb_to_lcd32(const uint8_t* SK_RESTRICT src, const SkGlyph& glyph,
968 const uint8_t* tableR, const uint8_t* tableG, const uint8_t* tableB) {
969 const size_t dstRB = glyph.rowBytes();
970 const U16CPU width = glyph.fWidth;
971 SkPMColor* SK_RESTRICT dst = static_cast<SkPMColor*>(glyph.fImage);
973 for (U16CPU y = 0; y < glyph.fHeight; y++) {
974 for (U16CPU i = 0; i < width; i++) {
975 U8CPU r = sk_apply_lut_if<APPLY_PREBLEND>(*(src++), tableR);
976 U8CPU g = sk_apply_lut_if<APPLY_PREBLEND>(*(src++), tableG);
977 U8CPU b = sk_apply_lut_if<APPLY_PREBLEND>(*(src++), tableB);
978 dst[i] = SkPackARGB32(0xFF, r, g, b);
980 dst = (SkPMColor*)((char*)dst + dstRB);
984 void SkScalerContext_DW::generateImage(const SkGlyph& glyph) {
985 const bool isBW = SkMask::kBW_Format == fRec.fMaskFormat;
986 const bool isAA = !isLCD(fRec);
989 const void* bits = fOffscreen.draw(glyph, isBW);
991 sk_bzero(glyph.fImage, glyph.computeImageSize());
995 //Copy the mask into the glyph.
996 const uint8_t* src = (const uint8_t*)bits;
998 bilevel_to_bw(src, glyph);
1000 if (fPreBlend.isApplicable()) {
1001 rgb_to_a8<true>(src, glyph, fPreBlend.fG);
1003 rgb_to_a8<false>(src, glyph, fPreBlend.fG);
1005 } else if (SkMask::kLCD16_Format == glyph.fMaskFormat) {
1006 if (fPreBlend.isApplicable()) {
1007 rgb_to_lcd16<true>(src, glyph, fPreBlend.fR, fPreBlend.fG, fPreBlend.fB);
1009 rgb_to_lcd16<false>(src, glyph, fPreBlend.fR, fPreBlend.fG, fPreBlend.fB);
1012 SkASSERT(SkMask::kLCD32_Format == glyph.fMaskFormat);
1013 if (fPreBlend.isApplicable()) {
1014 rgb_to_lcd32<true>(src, glyph, fPreBlend.fR, fPreBlend.fG, fPreBlend.fB);
1016 rgb_to_lcd32<false>(src, glyph, fPreBlend.fR, fPreBlend.fG, fPreBlend.fB);
1021 void SkScalerContext_DW::generatePath(const SkGlyph& glyph, SkPath* path) {
1022 SkASSERT(&glyph && path);
1026 SkTScopedComPtr<IDWriteGeometrySink> geometryToPath;
1027 HRVM(SkDWriteGeometrySink::Create(path, &geometryToPath),
1028 "Could not create geometry to path converter.");
1029 uint16_t glyphId = glyph.getGlyphID();
1030 //TODO: convert to<->from DIUs? This would make a difference if hinting.
1031 //It may not be needed, it appears that DirectWrite only hints at em size.
1032 HRVM(fTypeface->fDWriteFontFace->GetGlyphRunOutline(SkScalarToFloat(fRec.fTextSize),
1039 geometryToPath.get()),
1040 "Could not create glyph outline.");
1043 fRec.getMatrixFrom2x2(&mat);
1044 path->transform(mat);
1047 void DWriteFontTypeface::onGetFontDescriptor(SkFontDescriptor* desc,
1048 bool* isLocalStream) const {
1049 // Get the family name.
1050 SkTScopedComPtr<IDWriteLocalizedStrings> dwFamilyNames;
1051 HRV(fDWriteFontFamily->GetFamilyNames(&dwFamilyNames));
1053 UINT32 dwFamilyNamesLength;
1054 HRV(dwFamilyNames->GetStringLength(0, &dwFamilyNamesLength));
1056 SkSMallocWCHAR dwFamilyNameChar(dwFamilyNamesLength+1);
1057 HRV(dwFamilyNames->GetString(0, dwFamilyNameChar.get(), dwFamilyNamesLength+1));
1059 SkString utf8FamilyName;
1060 HRV(wchar_to_skstring(dwFamilyNameChar.get(), &utf8FamilyName));
1062 desc->setFamilyName(utf8FamilyName.c_str());
1063 *isLocalStream = SkToBool(fDWriteFontFileLoader.get());
1066 static SkUnichar next_utf8(const void** chars) {
1067 return SkUTF8_NextUnichar((const char**)chars);
1070 static SkUnichar next_utf16(const void** chars) {
1071 return SkUTF16_NextUnichar((const uint16_t**)chars);
1074 static SkUnichar next_utf32(const void** chars) {
1075 const SkUnichar** uniChars = (const SkUnichar**)chars;
1076 SkUnichar uni = **uniChars;
1081 typedef SkUnichar (*EncodingProc)(const void**);
1083 static EncodingProc find_encoding_proc(SkTypeface::Encoding enc) {
1084 static const EncodingProc gProcs[] = {
1085 next_utf8, next_utf16, next_utf32
1087 SkASSERT((size_t)enc < SK_ARRAY_COUNT(gProcs));
1091 int DWriteFontTypeface::onCharsToGlyphs(const void* chars, Encoding encoding,
1092 uint16_t glyphs[], int glyphCount) const
1094 if (NULL == glyphs) {
1095 EncodingProc next_ucs4_proc = find_encoding_proc(encoding);
1096 for (int i = 0; i < glyphCount; ++i) {
1097 const SkUnichar c = next_ucs4_proc(&chars);
1099 fDWriteFont->HasCharacter(c, &exists);
1108 case SkTypeface::kUTF8_Encoding:
1109 case SkTypeface::kUTF16_Encoding: {
1110 static const int scratchCount = 256;
1111 UINT32 scratch[scratchCount];
1112 EncodingProc next_ucs4_proc = find_encoding_proc(encoding);
1113 for (int baseGlyph = 0; baseGlyph < glyphCount; baseGlyph += scratchCount) {
1114 int glyphsLeft = glyphCount - baseGlyph;
1115 int limit = SkTMin(glyphsLeft, scratchCount);
1116 for (int i = 0; i < limit; ++i) {
1117 scratch[i] = next_ucs4_proc(&chars);
1119 fDWriteFontFace->GetGlyphIndices(scratch, limit, &glyphs[baseGlyph]);
1123 case SkTypeface::kUTF32_Encoding: {
1124 const UINT32* utf32 = reinterpret_cast<const UINT32*>(chars);
1125 fDWriteFontFace->GetGlyphIndices(utf32, glyphCount, glyphs);
1132 for (int i = 0; i < glyphCount; ++i) {
1133 if (0 == glyphs[i]) {
1140 int DWriteFontTypeface::onCountGlyphs() const {
1141 return fDWriteFontFace->GetGlyphCount();
1144 int DWriteFontTypeface::onGetUPEM() const {
1145 DWRITE_FONT_METRICS metrics;
1146 fDWriteFontFace->GetMetrics(&metrics);
1147 return metrics.designUnitsPerEm;
1150 class LocalizedStrings_IDWriteLocalizedStrings : public SkTypeface::LocalizedStrings {
1152 /** Takes ownership of the IDWriteLocalizedStrings. */
1153 explicit LocalizedStrings_IDWriteLocalizedStrings(IDWriteLocalizedStrings* strings)
1154 : fIndex(0), fStrings(strings)
1157 virtual bool next(SkTypeface::LocalizedString* localizedString) SK_OVERRIDE {
1158 if (fIndex >= fStrings->GetCount()) {
1163 UINT32 stringLength;
1164 HRBM(fStrings->GetStringLength(fIndex, &stringLength), "Could not get string length.");
1167 SkSMallocWCHAR wString(stringLength);
1168 HRBM(fStrings->GetString(fIndex, wString.get(), stringLength), "Could not get string.");
1170 HRB(wchar_to_skstring(wString.get(), &localizedString->fString));
1173 UINT32 localeLength;
1174 HRBM(fStrings->GetLocaleNameLength(fIndex, &localeLength), "Could not get locale length.");
1177 SkSMallocWCHAR wLocale(localeLength);
1178 HRBM(fStrings->GetLocaleName(fIndex, wLocale.get(), localeLength), "Could not get locale.");
1180 HRB(wchar_to_skstring(wLocale.get(), &localizedString->fLanguage));
1188 SkTScopedComPtr<IDWriteLocalizedStrings> fStrings;
1191 SkTypeface::LocalizedStrings* DWriteFontTypeface::onCreateFamilyNameIterator() const {
1192 SkTScopedComPtr<IDWriteLocalizedStrings> familyNames;
1193 HRNM(fDWriteFontFamily->GetFamilyNames(&familyNames), "Could not obtain family names.");
1195 return new LocalizedStrings_IDWriteLocalizedStrings(familyNames.release());
1198 int DWriteFontTypeface::onGetTableTags(SkFontTableTag tags[]) const {
1199 DWRITE_FONT_FACE_TYPE type = fDWriteFontFace->GetType();
1200 if (type != DWRITE_FONT_FACE_TYPE_CFF &&
1201 type != DWRITE_FONT_FACE_TYPE_TRUETYPE &&
1202 type != DWRITE_FONT_FACE_TYPE_TRUETYPE_COLLECTION)
1208 SkAutoTUnref<SkStream> stream(this->openStream(&ttcIndex));
1209 return stream.get() ? SkFontStream::GetTableTags(stream, ttcIndex, tags) : 0;
1212 class AutoDWriteTable {
1214 AutoDWriteTable(IDWriteFontFace* fontFace, UINT32 beTag) : fFontFace(fontFace), fExists(FALSE) {
1215 // Any errors are ignored, user must check fExists anyway.
1216 fontFace->TryGetFontTable(beTag,
1217 reinterpret_cast<const void **>(&fData), &fSize, &fLock, &fExists);
1219 ~AutoDWriteTable() {
1221 fFontFace->ReleaseFontTable(fLock);
1225 const uint8_t* fData;
1229 // Borrowed reference, the user must ensure the fontFace stays alive.
1230 IDWriteFontFace* fFontFace;
1234 size_t DWriteFontTypeface::onGetTableData(SkFontTableTag tag, size_t offset,
1235 size_t length, void* data) const
1237 AutoDWriteTable table(fDWriteFontFace.get(), SkEndian_SwapBE32(tag));
1238 if (!table.fExists) {
1242 if (offset > table.fSize) {
1245 size_t size = SkTMin(length, table.fSize - offset);
1247 memcpy(data, table.fData + offset, size);
1253 template <typename T> class SkAutoIDWriteUnregister {
1255 SkAutoIDWriteUnregister(IDWriteFactory* factory, T* unregister)
1256 : fFactory(factory), fUnregister(unregister)
1259 ~SkAutoIDWriteUnregister() {
1261 unregister(fFactory, fUnregister);
1266 T* old = fUnregister;
1272 HRESULT unregister(IDWriteFactory* factory, IDWriteFontFileLoader* unregister) {
1273 return factory->UnregisterFontFileLoader(unregister);
1276 HRESULT unregister(IDWriteFactory* factory, IDWriteFontCollectionLoader* unregister) {
1277 return factory->UnregisterFontCollectionLoader(unregister);
1280 IDWriteFactory* fFactory;
1284 static SkTypeface* create_from_stream(SkStream* stream, int ttcIndex) {
1285 IDWriteFactory* factory = get_dwrite_factory();
1286 if (NULL == factory) {
1290 SkTScopedComPtr<StreamFontFileLoader> fontFileLoader;
1291 HRN(StreamFontFileLoader::Create(stream, &fontFileLoader));
1292 HRN(factory->RegisterFontFileLoader(fontFileLoader.get()));
1293 SkAutoIDWriteUnregister<StreamFontFileLoader> autoUnregisterFontFileLoader(
1294 factory, fontFileLoader.get());
1296 SkTScopedComPtr<StreamFontCollectionLoader> fontCollectionLoader;
1297 HRN(StreamFontCollectionLoader::Create(fontFileLoader.get(), &fontCollectionLoader));
1298 HRN(factory->RegisterFontCollectionLoader(fontCollectionLoader.get()));
1299 SkAutoIDWriteUnregister<StreamFontCollectionLoader> autoUnregisterFontCollectionLoader(
1300 factory, fontCollectionLoader.get());
1302 SkTScopedComPtr<IDWriteFontCollection> fontCollection;
1303 HRN(factory->CreateCustomFontCollection(fontCollectionLoader.get(), NULL, 0, &fontCollection));
1305 // Find the first non-simulated font which has the given ttc index.
1306 UINT32 familyCount = fontCollection->GetFontFamilyCount();
1307 for (UINT32 familyIndex = 0; familyIndex < familyCount; ++familyIndex) {
1308 SkTScopedComPtr<IDWriteFontFamily> fontFamily;
1309 HRN(fontCollection->GetFontFamily(familyIndex, &fontFamily));
1311 UINT32 fontCount = fontFamily->GetFontCount();
1312 for (UINT32 fontIndex = 0; fontIndex < fontCount; ++fontIndex) {
1313 SkTScopedComPtr<IDWriteFont> font;
1314 HRN(fontFamily->GetFont(fontIndex, &font));
1315 if (font->GetSimulations() != DWRITE_FONT_SIMULATIONS_NONE) {
1319 SkTScopedComPtr<IDWriteFontFace> fontFace;
1320 HRN(font->CreateFontFace(&fontFace));
1322 UINT32 faceIndex = fontFace->GetIndex();
1323 if (faceIndex == ttcIndex) {
1324 return DWriteFontTypeface::Create(fontFace.get(), font.get(), fontFamily.get(),
1325 autoUnregisterFontFileLoader.detatch(),
1326 autoUnregisterFontCollectionLoader.detatch());
1334 SkStream* DWriteFontTypeface::onOpenStream(int* ttcIndex) const {
1335 *ttcIndex = fDWriteFontFace->GetIndex();
1338 HRNM(fDWriteFontFace->GetFiles(&numFiles, NULL),
1339 "Could not get number of font files.");
1340 if (numFiles != 1) {
1344 SkTScopedComPtr<IDWriteFontFile> fontFile;
1345 HRNM(fDWriteFontFace->GetFiles(&numFiles, &fontFile), "Could not get font files.");
1347 const void* fontFileKey;
1348 UINT32 fontFileKeySize;
1349 HRNM(fontFile->GetReferenceKey(&fontFileKey, &fontFileKeySize),
1350 "Could not get font file reference key.");
1352 SkTScopedComPtr<IDWriteFontFileLoader> fontFileLoader;
1353 HRNM(fontFile->GetLoader(&fontFileLoader), "Could not get font file loader.");
1355 SkTScopedComPtr<IDWriteFontFileStream> fontFileStream;
1356 HRNM(fontFileLoader->CreateStreamFromKey(fontFileKey, fontFileKeySize,
1358 "Could not create font file stream.");
1360 return SkNEW_ARGS(SkDWriteFontFileStream, (fontFileStream.get()));
1363 SkScalerContext* DWriteFontTypeface::onCreateScalerContext(const SkDescriptor* desc) const {
1364 return SkNEW_ARGS(SkScalerContext_DW, (const_cast<DWriteFontTypeface*>(this), desc));
1367 void DWriteFontTypeface::onFilterRec(SkScalerContext::Rec* rec) const {
1368 if (rec->fFlags & SkScalerContext::kLCD_BGROrder_Flag ||
1369 rec->fFlags & SkScalerContext::kLCD_Vertical_Flag)
1371 rec->fMaskFormat = SkMask::kA8_Format;
1374 unsigned flagsWeDontSupport = SkScalerContext::kDevKernText_Flag |
1375 SkScalerContext::kForceAutohinting_Flag |
1376 SkScalerContext::kEmbeddedBitmapText_Flag |
1377 SkScalerContext::kEmbolden_Flag |
1378 SkScalerContext::kLCD_BGROrder_Flag |
1379 SkScalerContext::kLCD_Vertical_Flag;
1380 rec->fFlags &= ~flagsWeDontSupport;
1382 SkPaint::Hinting h = rec->getHinting();
1383 // DirectWrite does not provide for hinting hints.
1384 h = SkPaint::kSlight_Hinting;
1387 #if SK_FONT_HOST_USE_SYSTEM_SETTINGS
1388 IDWriteFactory* factory = get_dwrite_factory();
1389 if (factory != NULL) {
1390 SkTScopedComPtr<IDWriteRenderingParams> defaultRenderingParams;
1391 if (SUCCEEDED(factory->CreateRenderingParams(&defaultRenderingParams))) {
1392 float gamma = defaultRenderingParams->GetGamma();
1393 rec->setDeviceGamma(gamma);
1394 rec->setPaintGamma(gamma);
1396 rec->setContrast(defaultRenderingParams->GetEnhancedContrast());
1402 ///////////////////////////////////////////////////////////////////////////////
1405 using namespace skia_advanced_typeface_metrics_utils;
1407 // Construct Glyph to Unicode table.
1408 // Unicode code points that require conjugate pairs in utf16 are not
1410 // TODO(arthurhsu): Add support for conjugate pairs. It looks like that may
1411 // require parsing the TTF cmap table (platform 4, encoding 12) directly instead
1412 // of calling GetFontUnicodeRange().
1413 // TODO(bungeman): This never does what anyone wants.
1414 // What is really wanted is the text to glyphs mapping
1415 static void populate_glyph_to_unicode(IDWriteFontFace* fontFace,
1416 const unsigned glyphCount,
1417 SkTDArray<SkUnichar>* glyphToUnicode) {
1420 //Do this like free type instead
1422 for (UINT32 c = 0; c < 0x10FFFF; ++c) {
1424 hr = fontFace->GetGlyphIndices(&c, 1, &glyph);
1430 SkAutoTArray<UINT32> chars(count);
1432 for (UINT32 c = 0; c < 0x10FFFF; ++c) {
1434 hr = fontFace->GetGlyphIndices(&c, 1, &glyph);
1441 SkAutoTArray<UINT16> glyph(count);
1442 fontFace->GetGlyphIndices(chars.get(), count, glyph.get());
1444 USHORT maxGlyph = 0;
1445 for (USHORT j = 0; j < count; ++j) {
1446 if (glyph[j] > maxGlyph) maxGlyph = glyph[j];
1449 glyphToUnicode->setCount(maxGlyph+1);
1450 for (USHORT j = 0; j < maxGlyph+1u; ++j) {
1451 (*glyphToUnicode)[j] = 0;
1455 for (USHORT j = 0; j < count; ++j) {
1456 if (glyph[j] < glyphCount && (*glyphToUnicode)[glyph[j]] == 0) {
1457 (*glyphToUnicode)[glyph[j]] = chars[j];
1462 static bool getWidthAdvance(IDWriteFontFace* fontFace, int gId, int16_t* advance) {
1465 UINT16 glyphId = gId;
1466 DWRITE_GLYPH_METRICS gm;
1467 HRESULT hr = fontFace->GetDesignGlyphMetrics(&glyphId, 1, &gm);
1474 *advance = gm.advanceWidth;
1478 template<typename T> class AutoTDWriteTable : public AutoDWriteTable {
1480 static const UINT32 tag = DWRITE_MAKE_OPENTYPE_TAG(T::TAG0, T::TAG1, T::TAG2, T::TAG3);
1481 AutoTDWriteTable(IDWriteFontFace* fontFace) : AutoDWriteTable(fontFace, tag) { }
1483 const T* operator->() const { return reinterpret_cast<const T*>(fData); }
1486 SkAdvancedTypefaceMetrics* DWriteFontTypeface::onGetAdvancedTypefaceMetrics(
1487 SkAdvancedTypefaceMetrics::PerGlyphInfo perGlyphInfo,
1488 const uint32_t* glyphIDs,
1489 uint32_t glyphIDsCount) const {
1491 SkAdvancedTypefaceMetrics* info = NULL;
1495 const unsigned glyphCount = fDWriteFontFace->GetGlyphCount();
1497 DWRITE_FONT_METRICS dwfm;
1498 fDWriteFontFace->GetMetrics(&dwfm);
1500 info = new SkAdvancedTypefaceMetrics;
1501 info->fEmSize = dwfm.designUnitsPerEm;
1502 info->fMultiMaster = false;
1503 info->fLastGlyphID = SkToU16(glyphCount - 1);
1507 SkTScopedComPtr<IDWriteLocalizedStrings> familyNames;
1508 SkTScopedComPtr<IDWriteLocalizedStrings> faceNames;
1509 hr = fDWriteFontFamily->GetFamilyNames(&familyNames);
1510 hr = fDWriteFont->GetFaceNames(&faceNames);
1512 UINT32 familyNameLength;
1513 hr = familyNames->GetStringLength(0, &familyNameLength);
1515 UINT32 faceNameLength;
1516 hr = faceNames->GetStringLength(0, &faceNameLength);
1518 UINT32 size = familyNameLength+1+faceNameLength+1;
1519 SkSMallocWCHAR wFamilyName(size);
1520 hr = familyNames->GetString(0, wFamilyName.get(), size);
1521 wFamilyName[familyNameLength] = L' ';
1522 hr = faceNames->GetString(0, &wFamilyName[familyNameLength+1], size - faceNameLength + 1);
1524 hr = wchar_to_skstring(wFamilyName.get(), &info->fFontName);
1526 if (perGlyphInfo & SkAdvancedTypefaceMetrics::kToUnicode_PerGlyphInfo) {
1527 populate_glyph_to_unicode(fDWriteFontFace.get(), glyphCount, &(info->fGlyphToUnicode));
1530 DWRITE_FONT_FACE_TYPE fontType = fDWriteFontFace->GetType();
1531 if (fontType == DWRITE_FONT_FACE_TYPE_TRUETYPE ||
1532 fontType == DWRITE_FONT_FACE_TYPE_TRUETYPE_COLLECTION) {
1533 info->fType = SkAdvancedTypefaceMetrics::kTrueType_Font;
1535 info->fType = SkAdvancedTypefaceMetrics::kOther_Font;
1536 info->fItalicAngle = 0;
1537 info->fAscent = dwfm.ascent;;
1538 info->fDescent = dwfm.descent;
1540 info->fCapHeight = dwfm.capHeight;
1541 info->fBBox = SkIRect::MakeEmpty();
1545 AutoTDWriteTable<SkOTTableHead> headTable(fDWriteFontFace.get());
1546 AutoTDWriteTable<SkOTTablePostScript> postTable(fDWriteFontFace.get());
1547 AutoTDWriteTable<SkOTTableHorizontalHeader> hheaTable(fDWriteFontFace.get());
1548 AutoTDWriteTable<SkOTTableOS2> os2Table(fDWriteFontFace.get());
1549 if (!headTable.fExists || !postTable.fExists || !hheaTable.fExists || !os2Table.fExists) {
1550 info->fItalicAngle = 0;
1551 info->fAscent = dwfm.ascent;;
1552 info->fDescent = dwfm.descent;
1554 info->fCapHeight = dwfm.capHeight;
1555 info->fBBox = SkIRect::MakeEmpty();
1559 //There exist CJK fonts which set the IsFixedPitch and Monospace bits,
1560 //but have full width, latin half-width, and half-width kana.
1561 bool fixedWidth = (postTable->isFixedPitch &&
1562 (1 == SkEndian_SwapBE16(hheaTable->numberOfHMetrics)));
1565 info->fStyle |= SkAdvancedTypefaceMetrics::kFixedPitch_Style;
1568 if (os2Table->version.v0.fsSelection.field.Italic) {
1569 info->fStyle |= SkAdvancedTypefaceMetrics::kItalic_Style;
1572 if (SkPanose::FamilyType::Script == os2Table->version.v0.panose.bFamilyType.value) {
1573 info->fStyle |= SkAdvancedTypefaceMetrics::kScript_Style;
1575 } else if (SkPanose::FamilyType::TextAndDisplay == os2Table->version.v0.panose.bFamilyType.value &&
1576 SkPanose::Data::TextAndDisplay::SerifStyle::Triangle <= os2Table->version.v0.panose.data.textAndDisplay.bSerifStyle.value &&
1577 SkPanose::Data::TextAndDisplay::SerifStyle::NoFit != os2Table->version.v0.panose.data.textAndDisplay.bSerifStyle.value) {
1578 info->fStyle |= SkAdvancedTypefaceMetrics::kSerif_Style;
1581 info->fItalicAngle = SkEndian_SwapBE32(postTable->italicAngle) >> 16;
1583 info->fAscent = SkToS16(dwfm.ascent);
1584 info->fDescent = SkToS16(dwfm.descent);
1585 info->fCapHeight = SkToS16(dwfm.capHeight);
1587 info->fBBox = SkIRect::MakeLTRB((int32_t)SkEndian_SwapBE16((uint16_t)headTable->xMin),
1588 (int32_t)SkEndian_SwapBE16((uint16_t)headTable->yMax),
1589 (int32_t)SkEndian_SwapBE16((uint16_t)headTable->xMax),
1590 (int32_t)SkEndian_SwapBE16((uint16_t)headTable->yMin));
1592 //TODO: is this even desired? It seems PDF only wants this value for Type1
1593 //fonts, and we only get here for TrueType fonts.
1596 // Figure out a good guess for StemV - Min width of i, I, !, 1.
1597 // This probably isn't very good with an italic font.
1598 int16_t min_width = SHRT_MAX;
1600 char stem_chars[] = {'i', 'I', '!', '1'};
1601 for (size_t i = 0; i < SK_ARRAY_COUNT(stem_chars); i++) {
1603 if (GetCharABCWidths(hdc, stem_chars[i], stem_chars[i], &abcWidths)) {
1604 int16_t width = abcWidths.abcB;
1605 if (width > 0 && width < min_width) {
1607 info->fStemV = min_width;
1613 // If Restricted, the font may not be embedded in a document.
1614 // If not Restricted, the font can be embedded.
1615 // If PreviewPrint, the embedding is read-only.
1616 if (os2Table->version.v0.fsType.field.Restricted) {
1617 info->fType = SkAdvancedTypefaceMetrics::kNotEmbeddable_Font;
1618 } else if (perGlyphInfo & SkAdvancedTypefaceMetrics::kHAdvance_PerGlyphInfo) {
1620 appendRange(&info->fGlyphWidths, 0);
1622 getWidthAdvance(fDWriteFontFace.get(), 1, &advance);
1623 info->fGlyphWidths->fAdvance.append(1, &advance);
1624 finishRange(info->fGlyphWidths.get(), 0,
1625 SkAdvancedTypefaceMetrics::WidthRange::kDefault);
1627 info->fGlyphWidths.reset(
1628 getAdvanceData(fDWriteFontFace.get(),
1639 ///////////////////////////////////////////////////////////////////////////////
1641 static void get_locale_string(IDWriteLocalizedStrings* names, const WCHAR* preferedLocale,
1643 UINT32 nameIndex = 0;
1644 if (preferedLocale) {
1645 // Ignore any errors and continue with index 0 if there is a problem.
1647 names->FindLocaleName(preferedLocale, &nameIndex, &nameExists);
1654 HRVM(names->GetStringLength(nameIndex, &nameLength), "Could not get name length.");
1657 SkSMallocWCHAR name(nameLength);
1658 HRVM(names->GetString(nameIndex, name.get(), nameLength), "Could not get string.");
1660 HRV(wchar_to_skstring(name.get(), skname));
1663 SkTypeface* SkFontMgr_DirectWrite::createTypefaceFromDWriteFont(
1664 IDWriteFontFace* fontFace,
1666 IDWriteFontFamily* fontFamily,
1667 StreamFontFileLoader* fontFileLoader,
1668 IDWriteFontCollectionLoader* fontCollectionLoader) {
1669 SkTypeface* face = FindByProcAndRef(FindByDWriteFont, font);
1671 face = DWriteFontTypeface::Create(fontFace, font, fontFamily,
1672 fontFileLoader, fontCollectionLoader);
1674 Add(face, get_style(font), fontCollectionLoader != NULL);
1680 int SkFontMgr_DirectWrite::onCountFamilies() {
1681 return fFontCollection->GetFontFamilyCount();
1684 void SkFontMgr_DirectWrite::onGetFamilyName(int index, SkString* familyName) {
1685 SkTScopedComPtr<IDWriteFontFamily> fontFamily;
1686 HRVM(fFontCollection->GetFontFamily(index, &fontFamily), "Could not get requested family.");
1688 SkTScopedComPtr<IDWriteLocalizedStrings> familyNames;
1689 HRVM(fontFamily->GetFamilyNames(&familyNames), "Could not get family names.");
1691 get_locale_string(familyNames.get(), fLocaleName.get(), familyName);
1694 SkFontStyleSet* SkFontMgr_DirectWrite::onCreateStyleSet(int index) {
1695 SkTScopedComPtr<IDWriteFontFamily> fontFamily;
1696 HRNM(fFontCollection->GetFontFamily(index, &fontFamily), "Could not get requested family.");
1698 return SkNEW_ARGS(SkFontStyleSet_DirectWrite, (this, fontFamily.get()));
1701 SkFontStyleSet* SkFontMgr_DirectWrite::onMatchFamily(const char familyName[]) {
1702 SkSMallocWCHAR dwFamilyName;
1703 HRN(cstring_to_wchar(familyName, &dwFamilyName));
1707 HRNM(fFontCollection->FindFamilyName(dwFamilyName.get(), &index, &exists),
1708 "Failed while finding family by name.");
1713 return this->onCreateStyleSet(index);
1716 SkTypeface* SkFontMgr_DirectWrite::onMatchFamilyStyle(const char familyName[],
1717 const SkFontStyle& fontstyle) {
1718 SkAutoTUnref<SkFontStyleSet> sset(this->matchFamily(familyName));
1719 return sset->matchStyle(fontstyle);
1722 SkTypeface* SkFontMgr_DirectWrite::onMatchFaceStyle(const SkTypeface* familyMember,
1723 const SkFontStyle& fontstyle) {
1724 SkString familyName;
1725 SkFontStyleSet_DirectWrite sset(
1726 this, ((DWriteFontTypeface*)familyMember)->fDWriteFontFamily.get()
1728 return sset.matchStyle(fontstyle);
1731 SkTypeface* SkFontMgr_DirectWrite::onCreateFromStream(SkStream* stream, int ttcIndex) {
1732 return create_from_stream(stream, ttcIndex);
1735 SkTypeface* SkFontMgr_DirectWrite::onCreateFromData(SkData* data, int ttcIndex) {
1736 SkAutoTUnref<SkStream> stream(SkNEW_ARGS(SkMemoryStream, (data)));
1737 return this->createFromStream(stream, ttcIndex);
1740 SkTypeface* SkFontMgr_DirectWrite::onCreateFromFile(const char path[], int ttcIndex) {
1741 SkAutoTUnref<SkStream> stream(SkStream::NewFromFile(path));
1742 return this->createFromStream(stream, ttcIndex);
1745 HRESULT SkFontMgr_DirectWrite::getByFamilyName(const WCHAR wideFamilyName[],
1746 IDWriteFontFamily** fontFamily) {
1749 HR(fFontCollection->FindFamilyName(wideFamilyName, &index, &exists));
1752 HR(fFontCollection->GetFontFamily(index, fontFamily));
1758 HRESULT SkFontMgr_DirectWrite::getDefaultFontFamily(IDWriteFontFamily** fontFamily) {
1759 NONCLIENTMETRICSW metrics;
1760 metrics.cbSize = sizeof(metrics);
1761 if (0 == SystemParametersInfoW(SPI_GETNONCLIENTMETRICS,
1765 return E_UNEXPECTED;
1767 HRM(this->getByFamilyName(metrics.lfMessageFont.lfFaceName, fontFamily),
1768 "Could not create DWrite font family from LOGFONT.");
1773 SkTypeface* SkFontMgr_DirectWrite::onLegacyCreateTypeface(const char familyName[],
1774 unsigned styleBits) {
1775 SkTScopedComPtr<IDWriteFontFamily> fontFamily;
1777 SkSMallocWCHAR wideFamilyName;
1778 if (SUCCEEDED(cstring_to_wchar(familyName, &wideFamilyName))) {
1779 this->getByFamilyName(wideFamilyName, &fontFamily);
1783 if (NULL == fontFamily.get()) {
1784 // No family with given name, try default.
1785 HRNM(this->getDefaultFontFamily(&fontFamily), "Could not get default font family.");
1788 SkTScopedComPtr<IDWriteFont> font;
1789 DWRITE_FONT_WEIGHT weight = (styleBits & SkTypeface::kBold)
1790 ? DWRITE_FONT_WEIGHT_BOLD
1791 : DWRITE_FONT_WEIGHT_NORMAL;
1792 DWRITE_FONT_STRETCH stretch = DWRITE_FONT_STRETCH_NORMAL;
1793 DWRITE_FONT_STYLE italic = (styleBits & SkTypeface::kItalic)
1794 ? DWRITE_FONT_STYLE_ITALIC
1795 : DWRITE_FONT_STYLE_NORMAL;
1796 HRNM(fontFamily->GetFirstMatchingFont(weight, stretch, italic, &font),
1797 "Could not get matching font.");
1799 SkTScopedComPtr<IDWriteFontFace> fontFace;
1800 HRNM(font->CreateFontFace(&fontFace), "Could not create font face.");
1802 return this->createTypefaceFromDWriteFont(fontFace.get(), font.get(), fontFamily.get());
1805 ///////////////////////////////////////////////////////////////////////////////
1807 int SkFontStyleSet_DirectWrite::count() {
1808 return fFontFamily->GetFontCount();
1811 SkTypeface* SkFontStyleSet_DirectWrite::createTypeface(int index) {
1812 SkTScopedComPtr<IDWriteFont> font;
1813 HRNM(fFontFamily->GetFont(index, &font), "Could not get font.");
1815 SkTScopedComPtr<IDWriteFontFace> fontFace;
1816 HRNM(font->CreateFontFace(&fontFace), "Could not create font face.");
1818 return fFontMgr->createTypefaceFromDWriteFont(fontFace.get(), font.get(), fFontFamily.get());
1821 void SkFontStyleSet_DirectWrite::getStyle(int index, SkFontStyle* fs, SkString* styleName) {
1822 SkTScopedComPtr<IDWriteFont> font;
1823 HRVM(fFontFamily->GetFont(index, &font), "Could not get font.");
1825 SkFontStyle::Slant slant;
1826 switch (font->GetStyle()) {
1827 case DWRITE_FONT_STYLE_NORMAL:
1828 slant = SkFontStyle::kUpright_Slant;
1830 case DWRITE_FONT_STYLE_OBLIQUE:
1831 case DWRITE_FONT_STYLE_ITALIC:
1832 slant = SkFontStyle::kItalic_Slant;
1838 int weight = font->GetWeight();
1839 int width = font->GetStretch();
1841 *fs = SkFontStyle(weight, width, slant);
1843 SkTScopedComPtr<IDWriteLocalizedStrings> faceNames;
1844 if (SUCCEEDED(font->GetFaceNames(&faceNames))) {
1845 get_locale_string(faceNames.get(), fFontMgr->fLocaleName.get(), styleName);
1849 SkTypeface* SkFontStyleSet_DirectWrite::matchStyle(const SkFontStyle& pattern) {
1850 DWRITE_FONT_STYLE slant;
1851 switch (pattern.slant()) {
1852 case SkFontStyle::kUpright_Slant:
1853 slant = DWRITE_FONT_STYLE_NORMAL;
1855 case SkFontStyle::kItalic_Slant:
1856 slant = DWRITE_FONT_STYLE_ITALIC;
1862 DWRITE_FONT_WEIGHT weight = (DWRITE_FONT_WEIGHT)pattern.weight();
1863 DWRITE_FONT_STRETCH width = (DWRITE_FONT_STRETCH)pattern.width();
1865 SkTScopedComPtr<IDWriteFont> font;
1866 // TODO: perhaps use GetMatchingFonts and get the least simulated?
1867 HRNM(fFontFamily->GetFirstMatchingFont(weight, width, slant, &font),
1868 "Could not match font in family.");
1870 SkTScopedComPtr<IDWriteFontFace> fontFace;
1871 HRNM(font->CreateFontFace(&fontFace), "Could not create font face.");
1873 return fFontMgr->createTypefaceFromDWriteFont(fontFace.get(), font.get(),
1877 ///////////////////////////////////////////////////////////////////////////////
1879 typedef decltype(GetUserDefaultLocaleName)* GetUserDefaultLocaleNameProc;
1880 static HRESULT GetGetUserDefaultLocaleNameProc(GetUserDefaultLocaleNameProc* proc) {
1881 *proc = reinterpret_cast<GetUserDefaultLocaleNameProc>(
1882 GetProcAddress(LoadLibraryW(L"Kernel32.dll"), "GetUserDefaultLocaleName")
1885 HRESULT hr = HRESULT_FROM_WIN32(GetLastError());
1886 if (!IS_ERROR(hr)) {
1887 hr = ERROR_PROC_NOT_FOUND;
1894 SkFontMgr* SkFontMgr_New_DirectWrite() {
1895 IDWriteFactory* factory = get_dwrite_factory();
1896 if (NULL == factory) {
1900 SkTScopedComPtr<IDWriteFontCollection> sysFontCollection;
1901 HRNM(factory->GetSystemFontCollection(&sysFontCollection, FALSE),
1902 "Could not get system font collection.");
1904 WCHAR localeNameStorage[LOCALE_NAME_MAX_LENGTH];
1905 WCHAR* localeName = NULL;
1906 int localeNameLen = 0;
1908 // Dynamically load GetUserDefaultLocaleName function, as it is not available on XP.
1909 GetUserDefaultLocaleNameProc getUserDefaultLocaleNameProc = NULL;
1910 HRESULT hr = GetGetUserDefaultLocaleNameProc(&getUserDefaultLocaleNameProc);
1911 if (NULL == getUserDefaultLocaleNameProc) {
1912 SK_TRACEHR(hr, "Could not get GetUserDefaultLocaleName.");
1914 localeNameLen = getUserDefaultLocaleNameProc(localeNameStorage, LOCALE_NAME_MAX_LENGTH);
1915 if (localeNameLen) {
1916 localeName = localeNameStorage;
1920 return SkNEW_ARGS(SkFontMgr_DirectWrite, (sysFontCollection.get(), localeName, localeNameLen));