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"
14 #include "SkDWriteFontFileStream.h"
15 #include "SkDWriteGeometrySink.h"
16 #include "SkDescriptor.h"
18 #include "SkFontDescriptor.h"
19 #include "SkFontHost.h"
20 #include "SkFontMgr.h"
21 #include "SkFontStream.h"
23 #include "SkHRESULT.h"
24 #include "SkMaskGamma.h"
25 #include "SkMatrix22.h"
27 #include "SkOTTable_EBLC.h"
28 #include "SkOTTable_EBSC.h"
29 #include "SkOTTable_head.h"
30 #include "SkOTTable_hhea.h"
31 #include "SkOTTable_OS_2.h"
32 #include "SkOTTable_post.h"
36 #include "SkTScopedComPtr.h"
38 #include "SkTypeface_win.h"
39 #include "SkTypefaceCache.h"
44 static bool isLCD(const SkScalerContext::Rec& rec) {
45 return SkMask::kLCD16_Format == rec.fMaskFormat ||
46 SkMask::kLCD32_Format == rec.fMaskFormat;
49 ///////////////////////////////////////////////////////////////////////////////
51 class StreamFontFileLoader;
53 class SkFontMgr_DirectWrite : public SkFontMgr {
55 /** localeNameLength must include the null terminator. */
56 SkFontMgr_DirectWrite(IDWriteFactory* factory, IDWriteFontCollection* fontCollection,
57 WCHAR* localeName, int localeNameLength)
58 : fFactory(SkRefComPtr(factory))
59 , fFontCollection(SkRefComPtr(fontCollection))
60 , fLocaleName(localeNameLength)
62 memcpy(fLocaleName.get(), localeName, localeNameLength * sizeof(WCHAR));
65 /** Creates a typeface using a typeface cache. */
66 SkTypeface* createTypefaceFromDWriteFont(IDWriteFontFace* fontFace,
68 IDWriteFontFamily* fontFamily) const;
71 virtual int onCountFamilies() const SK_OVERRIDE;
72 virtual void onGetFamilyName(int index, SkString* familyName) const SK_OVERRIDE;
73 virtual SkFontStyleSet* onCreateStyleSet(int index) const SK_OVERRIDE;
74 virtual SkFontStyleSet* onMatchFamily(const char familyName[]) const SK_OVERRIDE;
75 virtual SkTypeface* onMatchFamilyStyle(const char familyName[],
76 const SkFontStyle& fontstyle) const SK_OVERRIDE;
77 virtual SkTypeface* onMatchFaceStyle(const SkTypeface* familyMember,
78 const SkFontStyle& fontstyle) const SK_OVERRIDE;
79 virtual SkTypeface* onCreateFromStream(SkStream* stream, int ttcIndex) const SK_OVERRIDE;
80 virtual SkTypeface* onCreateFromData(SkData* data, int ttcIndex) const SK_OVERRIDE;
81 virtual SkTypeface* onCreateFromFile(const char path[], int ttcIndex) const SK_OVERRIDE;
82 virtual SkTypeface* onLegacyCreateTypeface(const char familyName[],
83 unsigned styleBits) const SK_OVERRIDE;
86 HRESULT getByFamilyName(const WCHAR familyName[], IDWriteFontFamily** fontFamily) const;
87 HRESULT getDefaultFontFamily(IDWriteFontFamily** fontFamily) const;
89 void Add(SkTypeface* face, SkTypeface::Style requestedStyle, bool strong) const {
90 SkAutoMutexAcquire ama(fTFCacheMutex);
91 fTFCache.add(face, requestedStyle, strong);
94 SkTypeface* FindByProcAndRef(SkTypefaceCache::FindProc proc, void* ctx) const {
95 SkAutoMutexAcquire ama(fTFCacheMutex);
96 SkTypeface* typeface = fTFCache.findByProcAndRef(proc, ctx);
100 SkTScopedComPtr<IDWriteFactory> fFactory;
101 SkTScopedComPtr<IDWriteFontCollection> fFontCollection;
102 SkSMallocWCHAR fLocaleName;
103 mutable SkMutex fTFCacheMutex;
104 mutable SkTypefaceCache fTFCache;
106 friend class SkFontStyleSet_DirectWrite;
109 class SkFontStyleSet_DirectWrite : public SkFontStyleSet {
111 SkFontStyleSet_DirectWrite(const SkFontMgr_DirectWrite* fontMgr,
112 IDWriteFontFamily* fontFamily)
113 : fFontMgr(SkRef(fontMgr))
114 , fFontFamily(SkRefComPtr(fontFamily))
117 virtual int count() SK_OVERRIDE;
118 virtual void getStyle(int index, SkFontStyle* fs, SkString* styleName) SK_OVERRIDE;
119 virtual SkTypeface* createTypeface(int index) SK_OVERRIDE;
120 virtual SkTypeface* matchStyle(const SkFontStyle& pattern) SK_OVERRIDE;
123 SkAutoTUnref<const SkFontMgr_DirectWrite> fFontMgr;
124 SkTScopedComPtr<IDWriteFontFamily> fFontFamily;
127 ///////////////////////////////////////////////////////////////////////////////
129 class StreamFontFileLoader : public IDWriteFontFileLoader {
132 virtual HRESULT STDMETHODCALLTYPE QueryInterface(REFIID iid, void** ppvObject);
133 virtual ULONG STDMETHODCALLTYPE AddRef();
134 virtual ULONG STDMETHODCALLTYPE Release();
136 // IDWriteFontFileLoader methods
137 virtual HRESULT STDMETHODCALLTYPE CreateStreamFromKey(
138 void const* fontFileReferenceKey,
139 UINT32 fontFileReferenceKeySize,
140 IDWriteFontFileStream** fontFileStream);
142 static HRESULT Create(SkStream* stream, StreamFontFileLoader** streamFontFileLoader) {
143 *streamFontFileLoader = new StreamFontFileLoader(stream);
144 if (NULL == streamFontFileLoader) {
145 return E_OUTOFMEMORY;
150 SkAutoTUnref<SkStream> fStream;
153 StreamFontFileLoader(SkStream* stream) : fRefCount(1), fStream(SkRef(stream)) { }
158 HRESULT StreamFontFileLoader::QueryInterface(REFIID iid, void** ppvObject) {
159 if (iid == IID_IUnknown || iid == __uuidof(IDWriteFontFileLoader)) {
165 return E_NOINTERFACE;
169 ULONG StreamFontFileLoader::AddRef() {
170 return InterlockedIncrement(&fRefCount);
173 ULONG StreamFontFileLoader::Release() {
174 ULONG newCount = InterlockedDecrement(&fRefCount);
181 HRESULT StreamFontFileLoader::CreateStreamFromKey(
182 void const* fontFileReferenceKey,
183 UINT32 fontFileReferenceKeySize,
184 IDWriteFontFileStream** fontFileStream)
186 SkTScopedComPtr<SkDWriteFontFileStreamWrapper> stream;
187 HR(SkDWriteFontFileStreamWrapper::Create(fStream, &stream));
188 *fontFileStream = stream.release();
192 class StreamFontFileEnumerator : public IDWriteFontFileEnumerator {
195 virtual HRESULT STDMETHODCALLTYPE QueryInterface(REFIID iid, void** ppvObject);
196 virtual ULONG STDMETHODCALLTYPE AddRef();
197 virtual ULONG STDMETHODCALLTYPE Release();
199 // IDWriteFontFileEnumerator methods
200 virtual HRESULT STDMETHODCALLTYPE MoveNext(BOOL* hasCurrentFile);
201 virtual HRESULT STDMETHODCALLTYPE GetCurrentFontFile(IDWriteFontFile** fontFile);
203 static HRESULT Create(IDWriteFactory* factory, IDWriteFontFileLoader* fontFileLoader,
204 StreamFontFileEnumerator** streamFontFileEnumerator) {
205 *streamFontFileEnumerator = new StreamFontFileEnumerator(factory, fontFileLoader);
206 if (NULL == streamFontFileEnumerator) {
207 return E_OUTOFMEMORY;
212 StreamFontFileEnumerator(IDWriteFactory* factory, IDWriteFontFileLoader* fontFileLoader);
215 SkTScopedComPtr<IDWriteFactory> fFactory;
216 SkTScopedComPtr<IDWriteFontFile> fCurrentFile;
217 SkTScopedComPtr<IDWriteFontFileLoader> fFontFileLoader;
221 StreamFontFileEnumerator::StreamFontFileEnumerator(IDWriteFactory* factory,
222 IDWriteFontFileLoader* fontFileLoader)
224 , fFactory(SkRefComPtr(factory))
226 , fFontFileLoader(SkRefComPtr(fontFileLoader))
230 HRESULT StreamFontFileEnumerator::QueryInterface(REFIID iid, void** ppvObject) {
231 if (iid == IID_IUnknown || iid == __uuidof(IDWriteFontFileEnumerator)) {
237 return E_NOINTERFACE;
241 ULONG StreamFontFileEnumerator::AddRef() {
242 return InterlockedIncrement(&fRefCount);
245 ULONG StreamFontFileEnumerator::Release() {
246 ULONG newCount = InterlockedDecrement(&fRefCount);
253 HRESULT StreamFontFileEnumerator::MoveNext(BOOL* hasCurrentFile) {
254 *hasCurrentFile = FALSE;
262 HR(fFactory->CreateCustomFontFileReference(
263 &dummy, //cannot be NULL
264 sizeof(dummy), //even if this is 0
265 fFontFileLoader.get(),
268 *hasCurrentFile = TRUE;
272 HRESULT StreamFontFileEnumerator::GetCurrentFontFile(IDWriteFontFile** fontFile) {
273 if (fCurrentFile.get() == NULL) {
278 *fontFile = SkRefComPtr(fCurrentFile.get());
282 class StreamFontCollectionLoader : public IDWriteFontCollectionLoader {
285 virtual HRESULT STDMETHODCALLTYPE QueryInterface(REFIID iid, void** ppvObject);
286 virtual ULONG STDMETHODCALLTYPE AddRef();
287 virtual ULONG STDMETHODCALLTYPE Release();
289 // IDWriteFontCollectionLoader methods
290 virtual HRESULT STDMETHODCALLTYPE CreateEnumeratorFromKey(
291 IDWriteFactory* factory,
292 void const* collectionKey,
293 UINT32 collectionKeySize,
294 IDWriteFontFileEnumerator** fontFileEnumerator);
296 static HRESULT Create(IDWriteFontFileLoader* fontFileLoader,
297 StreamFontCollectionLoader** streamFontCollectionLoader) {
298 *streamFontCollectionLoader = new StreamFontCollectionLoader(fontFileLoader);
299 if (NULL == streamFontCollectionLoader) {
300 return E_OUTOFMEMORY;
305 StreamFontCollectionLoader(IDWriteFontFileLoader* fontFileLoader)
307 , fFontFileLoader(SkRefComPtr(fontFileLoader))
311 SkTScopedComPtr<IDWriteFontFileLoader> fFontFileLoader;
314 HRESULT StreamFontCollectionLoader::QueryInterface(REFIID iid, void** ppvObject) {
315 if (iid == IID_IUnknown || iid == __uuidof(IDWriteFontCollectionLoader)) {
321 return E_NOINTERFACE;
325 ULONG StreamFontCollectionLoader::AddRef() {
326 return InterlockedIncrement(&fRefCount);
329 ULONG StreamFontCollectionLoader::Release() {
330 ULONG newCount = InterlockedDecrement(&fRefCount);
337 HRESULT StreamFontCollectionLoader::CreateEnumeratorFromKey(
338 IDWriteFactory* factory,
339 void const* collectionKey,
340 UINT32 collectionKeySize,
341 IDWriteFontFileEnumerator** fontFileEnumerator)
343 SkTScopedComPtr<StreamFontFileEnumerator> enumerator;
344 HR(StreamFontFileEnumerator::Create(factory, fFontFileLoader.get(), &enumerator));
345 *fontFileEnumerator = enumerator.release();
349 ///////////////////////////////////////////////////////////////////////////////
351 static SkTypeface::Style get_style(IDWriteFont* font) {
352 int style = SkTypeface::kNormal;
353 DWRITE_FONT_WEIGHT weight = font->GetWeight();
354 if (DWRITE_FONT_WEIGHT_DEMI_BOLD <= weight) {
355 style |= SkTypeface::kBold;
357 DWRITE_FONT_STYLE angle = font->GetStyle();
358 if (DWRITE_FONT_STYLE_OBLIQUE == angle || DWRITE_FONT_STYLE_ITALIC == angle) {
359 style |= SkTypeface::kItalic;
361 return static_cast<SkTypeface::Style>(style);
364 class DWriteFontTypeface : public SkTypeface {
366 DWriteFontTypeface(SkTypeface::Style style, SkFontID fontID,
367 IDWriteFactory* factory,
368 IDWriteFontFace* fontFace,
370 IDWriteFontFamily* fontFamily,
371 StreamFontFileLoader* fontFileLoader = NULL,
372 IDWriteFontCollectionLoader* fontCollectionLoader = NULL)
373 : SkTypeface(style, fontID, false)
374 , fFactory(SkRefComPtr(factory))
375 , fDWriteFontCollectionLoader(SkSafeRefComPtr(fontCollectionLoader))
376 , fDWriteFontFileLoader(SkSafeRefComPtr(fontFileLoader))
377 , fDWriteFontFamily(SkRefComPtr(fontFamily))
378 , fDWriteFont(SkRefComPtr(font))
379 , fDWriteFontFace(SkRefComPtr(fontFace))
383 SkTScopedComPtr<IDWriteFactory> fFactory;
384 SkTScopedComPtr<IDWriteFontCollectionLoader> fDWriteFontCollectionLoader;
385 SkTScopedComPtr<StreamFontFileLoader> fDWriteFontFileLoader;
386 SkTScopedComPtr<IDWriteFontFamily> fDWriteFontFamily;
387 SkTScopedComPtr<IDWriteFont> fDWriteFont;
388 SkTScopedComPtr<IDWriteFontFace> fDWriteFontFace;
390 static DWriteFontTypeface* Create(IDWriteFactory* factory,
391 IDWriteFontFace* fontFace,
393 IDWriteFontFamily* fontFamily,
394 StreamFontFileLoader* fontFileLoader = NULL,
395 IDWriteFontCollectionLoader* fontCollectionLoader = NULL) {
396 SkTypeface::Style style = get_style(font);
397 SkFontID fontID = SkTypefaceCache::NewFontID();
398 return SkNEW_ARGS(DWriteFontTypeface, (style, fontID,
399 factory, fontFace, font, fontFamily,
400 fontFileLoader, fontCollectionLoader));
404 virtual void weak_dispose() const SK_OVERRIDE {
405 if (fDWriteFontCollectionLoader.get()) {
406 HRV(fFactory->UnregisterFontCollectionLoader(fDWriteFontCollectionLoader.get()));
408 if (fDWriteFontFileLoader.get()) {
409 HRV(fFactory->UnregisterFontFileLoader(fDWriteFontFileLoader.get()));
412 //SkTypefaceCache::Remove(this);
413 INHERITED::weak_dispose();
416 virtual SkStream* onOpenStream(int* ttcIndex) const SK_OVERRIDE;
417 virtual SkScalerContext* onCreateScalerContext(const SkDescriptor*) const SK_OVERRIDE;
418 virtual void onFilterRec(SkScalerContextRec*) const SK_OVERRIDE;
419 virtual SkAdvancedTypefaceMetrics* onGetAdvancedTypefaceMetrics(
420 SkAdvancedTypefaceMetrics::PerGlyphInfo,
421 const uint32_t*, uint32_t) const SK_OVERRIDE;
422 virtual void onGetFontDescriptor(SkFontDescriptor*, bool*) const SK_OVERRIDE;
423 virtual int onCharsToGlyphs(const void* chars, Encoding encoding,
424 uint16_t glyphs[], int glyphCount) const SK_OVERRIDE;
425 virtual int onCountGlyphs() const SK_OVERRIDE;
426 virtual int onGetUPEM() const SK_OVERRIDE;
427 virtual SkTypeface::LocalizedStrings* onCreateFamilyNameIterator() const SK_OVERRIDE;
428 virtual int onGetTableTags(SkFontTableTag tags[]) const SK_OVERRIDE;
429 virtual size_t onGetTableData(SkFontTableTag, size_t offset,
430 size_t length, void* data) const SK_OVERRIDE;
433 typedef SkTypeface INHERITED;
436 class SkScalerContext_DW : public SkScalerContext {
438 SkScalerContext_DW(DWriteFontTypeface*, const SkDescriptor* desc);
439 virtual ~SkScalerContext_DW();
442 virtual unsigned generateGlyphCount() SK_OVERRIDE;
443 virtual uint16_t generateCharToGlyph(SkUnichar uni) SK_OVERRIDE;
444 virtual void generateAdvance(SkGlyph* glyph) SK_OVERRIDE;
445 virtual void generateMetrics(SkGlyph* glyph) SK_OVERRIDE;
446 virtual void generateImage(const SkGlyph& glyph) SK_OVERRIDE;
447 virtual void generatePath(const SkGlyph& glyph, SkPath* path) SK_OVERRIDE;
448 virtual void generateFontMetrics(SkPaint::FontMetrics* mX,
449 SkPaint::FontMetrics* mY) SK_OVERRIDE;
452 const void* drawDWMask(const SkGlyph& glyph);
454 SkTDArray<uint8_t> fBits;
455 /** The total matrix without the text height scale. */
457 /** The total matrix without the text height scale. */
458 DWRITE_MATRIX fXform;
459 /** The non-rotational part of total matrix without the text height scale.
460 * This is used to find the magnitude of gdi compatible advances.
463 /** The inverse of the rotational part of the total matrix.
464 * This is used to find the direction of gdi compatible advances.
467 /** The text size to render with. */
468 SkScalar fTextSizeRender;
469 /** The text size to measure with. */
470 SkScalar fTextSizeMeasure;
471 SkAutoTUnref<DWriteFontTypeface> fTypeface;
473 DWRITE_RENDERING_MODE fRenderingMode;
474 DWRITE_TEXTURE_TYPE fTextureType;
475 DWRITE_MEASURING_MODE fMeasuringMode;
478 static bool are_same(IUnknown* a, IUnknown* b) {
479 SkTScopedComPtr<IUnknown> iunkA;
480 if (FAILED(a->QueryInterface(&iunkA))) {
484 SkTScopedComPtr<IUnknown> iunkB;
485 if (FAILED(b->QueryInterface(&iunkB))) {
489 return iunkA.get() == iunkB.get();
491 static bool FindByDWriteFont(SkTypeface* face, SkTypeface::Style requestedStyle, void* ctx) {
492 //Check to see if the two fonts are identical.
493 DWriteFontTypeface* dwFace = reinterpret_cast<DWriteFontTypeface*>(face);
494 IDWriteFont* dwFont = reinterpret_cast<IDWriteFont*>(ctx);
495 if (are_same(dwFace->fDWriteFont.get(), dwFont)) {
499 //Check if the two fonts share the same loader and have the same key.
500 SkTScopedComPtr<IDWriteFontFace> dwFaceFontFace;
501 SkTScopedComPtr<IDWriteFontFace> dwFontFace;
502 HRB(dwFace->fDWriteFont->CreateFontFace(&dwFaceFontFace));
503 HRB(dwFont->CreateFontFace(&dwFontFace));
504 if (are_same(dwFaceFontFace.get(), dwFontFace.get())) {
508 UINT32 dwFaceNumFiles;
510 HRB(dwFaceFontFace->GetFiles(&dwFaceNumFiles, NULL));
511 HRB(dwFontFace->GetFiles(&dwNumFiles, NULL));
512 if (dwFaceNumFiles != dwNumFiles) {
516 SkTScopedComPtr<IDWriteFontFile> dwFaceFontFile;
517 SkTScopedComPtr<IDWriteFontFile> dwFontFile;
518 HRB(dwFaceFontFace->GetFiles(&dwFaceNumFiles, &dwFaceFontFile));
519 HRB(dwFontFace->GetFiles(&dwNumFiles, &dwFontFile));
521 //for (each file) { //we currently only admit fonts from one file.
522 SkTScopedComPtr<IDWriteFontFileLoader> dwFaceFontFileLoader;
523 SkTScopedComPtr<IDWriteFontFileLoader> dwFontFileLoader;
524 HRB(dwFaceFontFile->GetLoader(&dwFaceFontFileLoader));
525 HRB(dwFontFile->GetLoader(&dwFontFileLoader));
526 if (!are_same(dwFaceFontFileLoader.get(), dwFontFileLoader.get())) {
531 const void* dwFaceFontRefKey;
532 UINT32 dwFaceFontRefKeySize;
533 const void* dwFontRefKey;
534 UINT32 dwFontRefKeySize;
535 HRB(dwFaceFontFile->GetReferenceKey(&dwFaceFontRefKey, &dwFaceFontRefKeySize));
536 HRB(dwFontFile->GetReferenceKey(&dwFontRefKey, &dwFontRefKeySize));
537 if (dwFaceFontRefKeySize != dwFontRefKeySize) {
540 if (0 != memcmp(dwFaceFontRefKey, dwFontRefKey, dwFontRefKeySize)) {
544 //TODO: better means than comparing name strings?
545 //NOTE: .tfc and fake bold/italic will end up here.
546 SkTScopedComPtr<IDWriteFontFamily> dwFaceFontFamily;
547 SkTScopedComPtr<IDWriteFontFamily> dwFontFamily;
548 HRB(dwFace->fDWriteFont->GetFontFamily(&dwFaceFontFamily));
549 HRB(dwFont->GetFontFamily(&dwFontFamily));
551 SkTScopedComPtr<IDWriteLocalizedStrings> dwFaceFontFamilyNames;
552 SkTScopedComPtr<IDWriteLocalizedStrings> dwFaceFontNames;
553 HRB(dwFaceFontFamily->GetFamilyNames(&dwFaceFontFamilyNames));
554 HRB(dwFace->fDWriteFont->GetFaceNames(&dwFaceFontNames));
556 SkTScopedComPtr<IDWriteLocalizedStrings> dwFontFamilyNames;
557 SkTScopedComPtr<IDWriteLocalizedStrings> dwFontNames;
558 HRB(dwFontFamily->GetFamilyNames(&dwFontFamilyNames));
559 HRB(dwFont->GetFaceNames(&dwFontNames));
561 UINT32 dwFaceFontFamilyNameLength;
562 UINT32 dwFaceFontNameLength;
563 HRB(dwFaceFontFamilyNames->GetStringLength(0, &dwFaceFontFamilyNameLength));
564 HRB(dwFaceFontNames->GetStringLength(0, &dwFaceFontNameLength));
566 UINT32 dwFontFamilyNameLength;
567 UINT32 dwFontNameLength;
568 HRB(dwFontFamilyNames->GetStringLength(0, &dwFontFamilyNameLength));
569 HRB(dwFontNames->GetStringLength(0, &dwFontNameLength));
571 if (dwFaceFontFamilyNameLength != dwFontFamilyNameLength ||
572 dwFaceFontNameLength != dwFontNameLength)
577 SkSMallocWCHAR dwFaceFontFamilyNameChar(dwFaceFontFamilyNameLength+1);
578 SkSMallocWCHAR dwFaceFontNameChar(dwFaceFontNameLength+1);
579 HRB(dwFaceFontFamilyNames->GetString(0, dwFaceFontFamilyNameChar.get(), dwFaceFontFamilyNameLength+1));
580 HRB(dwFaceFontNames->GetString(0, dwFaceFontNameChar.get(), dwFaceFontNameLength+1));
582 SkSMallocWCHAR dwFontFamilyNameChar(dwFontFamilyNameLength+1);
583 SkSMallocWCHAR dwFontNameChar(dwFontNameLength+1);
584 HRB(dwFontFamilyNames->GetString(0, dwFontFamilyNameChar.get(), dwFontFamilyNameLength+1));
585 HRB(dwFontNames->GetString(0, dwFontNameChar.get(), dwFontNameLength+1));
587 return wcscmp(dwFaceFontFamilyNameChar.get(), dwFontFamilyNameChar.get()) == 0 &&
588 wcscmp(dwFaceFontNameChar.get(), dwFontNameChar.get()) == 0;
591 class AutoDWriteTable {
593 AutoDWriteTable(IDWriteFontFace* fontFace, UINT32 beTag) : fFontFace(fontFace), fExists(FALSE) {
594 // Any errors are ignored, user must check fExists anyway.
595 fontFace->TryGetFontTable(beTag,
596 reinterpret_cast<const void **>(&fData), &fSize, &fLock, &fExists);
600 fFontFace->ReleaseFontTable(fLock);
604 const uint8_t* fData;
608 // Borrowed reference, the user must ensure the fontFace stays alive.
609 IDWriteFontFace* fFontFace;
612 template<typename T> class AutoTDWriteTable : public AutoDWriteTable {
614 static const UINT32 tag = DWRITE_MAKE_OPENTYPE_TAG(T::TAG0, T::TAG1, T::TAG2, T::TAG3);
615 AutoTDWriteTable(IDWriteFontFace* fontFace) : AutoDWriteTable(fontFace, tag) { }
617 const T* get() const { return reinterpret_cast<const T*>(fData); }
618 const T* operator->() const { return reinterpret_cast<const T*>(fData); }
621 static bool hasBitmapStrike(DWriteFontTypeface* typeface, int size) {
623 AutoTDWriteTable<SkOTTableEmbeddedBitmapLocation> eblc(typeface->fDWriteFontFace.get());
627 if (eblc.fSize < sizeof(SkOTTableEmbeddedBitmapLocation)) {
630 if (eblc->version != SkOTTableEmbeddedBitmapLocation::version_initial) {
634 uint32_t numSizes = SkEndianSwap32(eblc->numSizes);
635 if (eblc.fSize < sizeof(SkOTTableEmbeddedBitmapLocation) +
636 sizeof(SkOTTableEmbeddedBitmapLocation::BitmapSizeTable) * numSizes)
641 const SkOTTableEmbeddedBitmapLocation::BitmapSizeTable* sizeTable =
642 SkTAfter<const SkOTTableEmbeddedBitmapLocation::BitmapSizeTable>(eblc.get());
643 for (uint32_t i = 0; i < numSizes; ++i, ++sizeTable) {
644 if (sizeTable->ppemX == size && sizeTable->ppemY == size) {
645 // TODO: determine if we should dig through IndexSubTableArray/IndexSubTable
646 // to determine the actual number of glyphs with bitmaps.
648 // TODO: Ensure that the bitmaps actually cover a significant portion of the strike.
650 //TODO: Endure that the bitmaps are bi-level.
651 if (sizeTable->endGlyphIndex >= sizeTable->startGlyphIndex + 3) {
659 AutoTDWriteTable<SkOTTableEmbeddedBitmapScaling> ebsc(typeface->fDWriteFontFace.get());
663 if (ebsc.fSize < sizeof(SkOTTableEmbeddedBitmapScaling)) {
666 if (ebsc->version != SkOTTableEmbeddedBitmapScaling::version_initial) {
670 uint32_t numSizes = SkEndianSwap32(ebsc->numSizes);
671 if (ebsc.fSize < sizeof(SkOTTableEmbeddedBitmapScaling) +
672 sizeof(SkOTTableEmbeddedBitmapScaling::BitmapScaleTable) * numSizes)
677 const SkOTTableEmbeddedBitmapScaling::BitmapScaleTable* scaleTable =
678 SkTAfter<const SkOTTableEmbeddedBitmapScaling::BitmapScaleTable>(ebsc.get());
679 for (uint32_t i = 0; i < numSizes; ++i, ++scaleTable) {
680 if (scaleTable->ppemX == size && scaleTable->ppemY == size) {
681 // EBSC tables are normally only found in bitmap only fonts.
690 static bool bothZero(SkScalar a, SkScalar b) {
691 return 0 == a && 0 == b;
694 // returns false if there is any non-90-rotation or skew
695 static bool isAxisAligned(const SkScalerContext::Rec& rec) {
696 return 0 == rec.fPreSkewX &&
697 (bothZero(rec.fPost2x2[0][1], rec.fPost2x2[1][0]) ||
698 bothZero(rec.fPost2x2[0][0], rec.fPost2x2[1][1]));
701 SkScalerContext_DW::SkScalerContext_DW(DWriteFontTypeface* typeface,
702 const SkDescriptor* desc)
703 : SkScalerContext(typeface, desc)
704 , fTypeface(SkRef(typeface))
707 // In general, all glyphs should use CLEARTYPE_NATURAL_SYMMETRIC
708 // except when bi-level rendering is requested or there are embedded
709 // bi-level bitmaps (and the embedded bitmap flag is set and no rotation).
711 // DirectWrite's IDWriteFontFace::GetRecommendedRenderingMode does not do
712 // this. As a result, determine the actual size of the text and then see if
713 // there are any embedded bi-level bitmaps of that size. If there are, then
714 // force bitmaps by requesting bi-level rendering.
716 // FreeType allows for separate ppemX and ppemY, but DirectWrite assumes
717 // square pixels and only uses ppemY. Therefore the transform must track any
718 // non-uniform x-scale.
720 // Also, rotated glyphs should have the same absolute advance widths as
721 // horizontal glyphs and the subpixel flag should not affect glyph shapes.
723 // A is the total matrix.
725 fRec.getSingleMatrix(&A);
727 // h is where A maps the horizontal baseline.
728 SkPoint h = SkPoint::Make(SK_Scalar1, 0);
731 // G is the Givens Matrix for A (rotational matrix where GA[0][1] == 0).
733 SkComputeGivensRotation(h, &G);
735 // GA is the matrix A with rotation removed.
739 // realTextSize is the actual device size we want (as opposed to the size the user requested).
740 // gdiTextSize is the size we request when GDI compatible.
741 // If the scale is negative, this means the matrix will do the flip anyway.
742 SkScalar realTextSize = SkScalarAbs(GA.get(SkMatrix::kMScaleY));
743 // Due to floating point math, the lower bits are suspect. Round carefully.
744 SkScalar roundedTextSize = SkScalarRoundToScalar(realTextSize * 64.0f) / 64.0f;
745 SkScalar gdiTextSize = SkScalarFloorToScalar(roundedTextSize);
746 if (gdiTextSize == 0) {
747 gdiTextSize = SK_Scalar1;
750 bool hasBitmap = fRec.fFlags & SkScalerContext::kEmbeddedBitmapText_Flag &&
751 hasBitmapStrike(typeface, SkScalarTruncToInt(gdiTextSize));
752 bool axisAligned = isAxisAligned(fRec);
753 bool isBiLevel = SkMask::kBW_Format == fRec.fMaskFormat || (hasBitmap && axisAligned);
756 fTextSizeRender = gdiTextSize;
757 fRenderingMode = DWRITE_RENDERING_MODE_ALIASED;
758 fTextureType = DWRITE_TEXTURE_ALIASED_1x1;
759 fTextSizeMeasure = gdiTextSize;
760 fMeasuringMode = DWRITE_MEASURING_MODE_GDI_CLASSIC;
761 } else if (hasBitmap) {
762 // If rotated but the horizontal text would have used a bitmap,
763 // render high quality rotated glyphs using the bitmap metrics.
764 fTextSizeRender = gdiTextSize;
765 fRenderingMode = DWRITE_RENDERING_MODE_CLEARTYPE_NATURAL_SYMMETRIC;
766 fTextureType = DWRITE_TEXTURE_CLEARTYPE_3x1;
767 fTextSizeMeasure = gdiTextSize;
768 fMeasuringMode = DWRITE_MEASURING_MODE_GDI_CLASSIC;
770 fTextSizeRender = realTextSize;
771 fRenderingMode = DWRITE_RENDERING_MODE_CLEARTYPE_NATURAL_SYMMETRIC;
772 fTextureType = DWRITE_TEXTURE_CLEARTYPE_3x1;
773 fTextSizeMeasure = realTextSize;
774 fMeasuringMode = DWRITE_MEASURING_MODE_NATURAL;
777 if (this->isSubpixel()) {
778 fTextSizeMeasure = realTextSize;
779 fMeasuringMode = DWRITE_MEASURING_MODE_NATURAL;
782 // Remove the realTextSize, as that is the text height scale currently in A.
783 SkScalar scale = SkScalarInvert(realTextSize);
785 // fSkXform is the total matrix A without the text height scale.
787 fSkXform.preScale(scale, scale); //remove the text height scale.
789 fXform.m11 = SkScalarToFloat(fSkXform.getScaleX());
790 fXform.m12 = SkScalarToFloat(fSkXform.getSkewY());
791 fXform.m21 = SkScalarToFloat(fSkXform.getSkewX());
792 fXform.m22 = SkScalarToFloat(fSkXform.getScaleY());
796 // GsA is the non-rotational part of A without the text height scale.
798 GsA.preScale(scale, scale); //remove text height scale, G is rotational so reorders with scale.
800 fGsA.m11 = SkScalarToFloat(GsA.get(SkMatrix::kMScaleX));
801 fGsA.m12 = SkScalarToFloat(GsA.get(SkMatrix::kMSkewY)); // This should be ~0.
802 fGsA.m21 = SkScalarToFloat(GsA.get(SkMatrix::kMSkewX));
803 fGsA.m22 = SkScalarToFloat(GsA.get(SkMatrix::kMScaleY));
805 // fG_inv is G inverse, which is fairly simple since G is 2x2 rotational.
806 fG_inv.setAll(G.get(SkMatrix::kMScaleX), -G.get(SkMatrix::kMSkewX), G.get(SkMatrix::kMTransX),
807 -G.get(SkMatrix::kMSkewY), G.get(SkMatrix::kMScaleY), G.get(SkMatrix::kMTransY),
808 G.get(SkMatrix::kMPersp0), G.get(SkMatrix::kMPersp1), G.get(SkMatrix::kMPersp2));
811 SkScalerContext_DW::~SkScalerContext_DW() {
814 unsigned SkScalerContext_DW::generateGlyphCount() {
815 if (fGlyphCount < 0) {
816 fGlyphCount = fTypeface->fDWriteFontFace->GetGlyphCount();
821 uint16_t SkScalerContext_DW::generateCharToGlyph(SkUnichar uni) {
823 fTypeface->fDWriteFontFace->GetGlyphIndices(reinterpret_cast<UINT32*>(&uni), 1, &index);
827 void SkScalerContext_DW::generateAdvance(SkGlyph* glyph) {
828 //Delta is the difference between the right/left side bearing metric
829 //and where the right/left side bearing ends up after hinting.
830 //DirectWrite does not provide this information.
831 glyph->fRsbDelta = 0;
832 glyph->fLsbDelta = 0;
834 glyph->fAdvanceX = 0;
835 glyph->fAdvanceY = 0;
837 uint16_t glyphId = glyph->getGlyphID();
838 DWRITE_GLYPH_METRICS gm;
840 if (DWRITE_MEASURING_MODE_GDI_CLASSIC == fMeasuringMode ||
841 DWRITE_MEASURING_MODE_GDI_NATURAL == fMeasuringMode)
843 HRVM(fTypeface->fDWriteFontFace->GetGdiCompatibleGlyphMetrics(
845 1.0f, // pixelsPerDip
847 DWRITE_MEASURING_MODE_GDI_NATURAL == fMeasuringMode,
850 "Could not get gdi compatible glyph metrics.");
852 HRVM(fTypeface->fDWriteFontFace->GetDesignGlyphMetrics(&glyphId, 1, &gm),
853 "Could not get design metrics.");
856 DWRITE_FONT_METRICS dwfm;
857 fTypeface->fDWriteFontFace->GetMetrics(&dwfm);
858 SkScalar advanceX = SkScalarMulDiv(fTextSizeMeasure,
859 SkIntToScalar(gm.advanceWidth),
860 SkIntToScalar(dwfm.designUnitsPerEm));
862 if (!this->isSubpixel()) {
863 advanceX = SkScalarRoundToScalar(advanceX);
866 SkVector vecs[1] = { { advanceX, 0 } };
867 if (DWRITE_MEASURING_MODE_GDI_CLASSIC == fMeasuringMode ||
868 DWRITE_MEASURING_MODE_GDI_NATURAL == fMeasuringMode)
870 fG_inv.mapVectors(vecs, SK_ARRAY_COUNT(vecs));
872 fSkXform.mapVectors(vecs, SK_ARRAY_COUNT(vecs));
875 glyph->fAdvanceX = SkScalarToFixed(vecs[0].fX);
876 glyph->fAdvanceY = SkScalarToFixed(vecs[0].fY);
879 void SkScalerContext_DW::generateMetrics(SkGlyph* glyph) {
882 this->generateAdvance(glyph);
884 //Measure raster size.
885 fXform.dx = SkFixedToFloat(glyph->getSubXFixed());
886 fXform.dy = SkFixedToFloat(glyph->getSubYFixed());
890 UINT16 glyphId = glyph->getGlyphID();
892 DWRITE_GLYPH_OFFSET offset;
893 offset.advanceOffset = 0.0f;
894 offset.ascenderOffset = 0.0f;
896 DWRITE_GLYPH_RUN run;
898 run.glyphAdvances = &advance;
899 run.fontFace = fTypeface->fDWriteFontFace.get();
900 run.fontEmSize = SkScalarToFloat(fTextSizeRender);
902 run.glyphIndices = &glyphId;
903 run.isSideways = FALSE;
904 run.glyphOffsets = &offset;
906 SkTScopedComPtr<IDWriteGlyphRunAnalysis> glyphRunAnalysis;
907 HRVM(fTypeface->fFactory->CreateGlyphRunAnalysis(
909 1.0f, // pixelsPerDip,
913 0.0f, // baselineOriginX,
914 0.0f, // baselineOriginY,
916 "Could not create glyph run analysis.");
919 HRVM(glyphRunAnalysis->GetAlphaTextureBounds(fTextureType, &bbox),
920 "Could not get texture bounds.");
922 glyph->fWidth = SkToU16(bbox.right - bbox.left);
923 glyph->fHeight = SkToU16(bbox.bottom - bbox.top);
924 glyph->fLeft = SkToS16(bbox.left);
925 glyph->fTop = SkToS16(bbox.top);
928 void SkScalerContext_DW::generateFontMetrics(SkPaint::FontMetrics* mx,
929 SkPaint::FontMetrics* my) {
934 sk_bzero(mx, sizeof(*mx));
937 sk_bzero(my, sizeof(*my));
940 DWRITE_FONT_METRICS dwfm;
941 if (DWRITE_MEASURING_MODE_GDI_CLASSIC == fMeasuringMode ||
942 DWRITE_MEASURING_MODE_GDI_NATURAL == fMeasuringMode)
944 fTypeface->fDWriteFontFace->GetGdiCompatibleMetrics(
946 1.0f, // pixelsPerDip
950 fTypeface->fDWriteFontFace->GetMetrics(&dwfm);
953 SkScalar upem = SkIntToScalar(dwfm.designUnitsPerEm);
955 mx->fTop = -fTextSizeRender * SkIntToScalar(dwfm.ascent) / upem;
956 mx->fAscent = mx->fTop;
957 mx->fDescent = fTextSizeRender * SkIntToScalar(dwfm.descent) / upem;
958 mx->fBottom = mx->fDescent;
959 mx->fLeading = fTextSizeRender * SkIntToScalar(dwfm.lineGap) / upem;
960 mx->fXHeight = fTextSizeRender * SkIntToScalar(dwfm.xHeight) / upem;
961 mx->fUnderlineThickness = fTextSizeRender * SkIntToScalar(dwfm.underlinePosition) / upem;
962 mx->fUnderlinePosition = -(fTextSizeRender * SkIntToScalar(dwfm.underlineThickness) / upem);
964 mx->fFlags |= SkPaint::FontMetrics::kUnderlineThinknessIsValid_Flag;
965 mx->fFlags |= SkPaint::FontMetrics::kUnderlinePositionIsValid_Flag;
969 my->fTop = -fTextSizeRender * SkIntToScalar(dwfm.ascent) / upem;
970 my->fAscent = my->fTop;
971 my->fDescent = fTextSizeRender * SkIntToScalar(dwfm.descent) / upem;
972 my->fBottom = my->fDescent;
973 my->fLeading = fTextSizeRender * SkIntToScalar(dwfm.lineGap) / upem;
974 my->fXHeight = fTextSizeRender * SkIntToScalar(dwfm.xHeight) / upem;
975 my->fUnderlineThickness = fTextSizeRender * SkIntToScalar(dwfm.underlinePosition) / upem;
976 my->fUnderlinePosition = -(fTextSizeRender * SkIntToScalar(dwfm.underlineThickness) / upem);
978 my->fFlags |= SkPaint::FontMetrics::kUnderlineThinknessIsValid_Flag;
979 my->fFlags |= SkPaint::FontMetrics::kUnderlinePositionIsValid_Flag;
983 ///////////////////////////////////////////////////////////////////////////////
985 #include "SkColorPriv.h"
987 static void bilevel_to_bw(const uint8_t* SK_RESTRICT src, const SkGlyph& glyph) {
988 const int width = glyph.fWidth;
989 const size_t dstRB = (width + 7) >> 3;
990 uint8_t* SK_RESTRICT dst = static_cast<uint8_t*>(glyph.fImage);
992 int byteCount = width >> 3;
993 int bitCount = width & 7;
995 for (int y = 0; y < glyph.fHeight; ++y) {
997 for (int i = 0; i < byteCount; ++i) {
999 byte |= src[0] & (1 << 7);
1000 byte |= src[1] & (1 << 6);
1001 byte |= src[2] & (1 << 5);
1002 byte |= src[3] & (1 << 4);
1003 byte |= src[4] & (1 << 3);
1004 byte |= src[5] & (1 << 2);
1005 byte |= src[6] & (1 << 1);
1006 byte |= src[7] & (1 << 0);
1013 unsigned mask = 0x80;
1014 for (int i = 0; i < bitCount; i++) {
1015 byte |= (src[i]) & mask;
1018 dst[byteCount] = byte;
1025 template<bool APPLY_PREBLEND>
1026 static void rgb_to_a8(const uint8_t* SK_RESTRICT src, const SkGlyph& glyph, const uint8_t* table8) {
1027 const size_t dstRB = glyph.rowBytes();
1028 const U16CPU width = glyph.fWidth;
1029 uint8_t* SK_RESTRICT dst = static_cast<uint8_t*>(glyph.fImage);
1031 for (U16CPU y = 0; y < glyph.fHeight; y++) {
1032 for (U16CPU i = 0; i < width; i++) {
1036 dst[i] = sk_apply_lut_if<APPLY_PREBLEND>((r + g + b) / 3, table8);
1038 dst = (uint8_t*)((char*)dst + dstRB);
1042 template<bool APPLY_PREBLEND>
1043 static void rgb_to_lcd16(const uint8_t* SK_RESTRICT src, const SkGlyph& glyph,
1044 const uint8_t* tableR, const uint8_t* tableG, const uint8_t* tableB) {
1045 const size_t dstRB = glyph.rowBytes();
1046 const U16CPU width = glyph.fWidth;
1047 uint16_t* SK_RESTRICT dst = static_cast<uint16_t*>(glyph.fImage);
1049 for (U16CPU y = 0; y < glyph.fHeight; y++) {
1050 for (U16CPU i = 0; i < width; i++) {
1051 U8CPU r = sk_apply_lut_if<APPLY_PREBLEND>(*(src++), tableR);
1052 U8CPU g = sk_apply_lut_if<APPLY_PREBLEND>(*(src++), tableG);
1053 U8CPU b = sk_apply_lut_if<APPLY_PREBLEND>(*(src++), tableB);
1054 dst[i] = SkPack888ToRGB16(r, g, b);
1056 dst = (uint16_t*)((char*)dst + dstRB);
1060 template<bool APPLY_PREBLEND>
1061 static void rgb_to_lcd32(const uint8_t* SK_RESTRICT src, const SkGlyph& glyph,
1062 const uint8_t* tableR, const uint8_t* tableG, const uint8_t* tableB) {
1063 const size_t dstRB = glyph.rowBytes();
1064 const U16CPU width = glyph.fWidth;
1065 SkPMColor* SK_RESTRICT dst = static_cast<SkPMColor*>(glyph.fImage);
1067 for (U16CPU y = 0; y < glyph.fHeight; y++) {
1068 for (U16CPU i = 0; i < width; i++) {
1069 U8CPU r = sk_apply_lut_if<APPLY_PREBLEND>(*(src++), tableR);
1070 U8CPU g = sk_apply_lut_if<APPLY_PREBLEND>(*(src++), tableG);
1071 U8CPU b = sk_apply_lut_if<APPLY_PREBLEND>(*(src++), tableB);
1072 dst[i] = SkPackARGB32(0xFF, r, g, b);
1074 dst = (SkPMColor*)((char*)dst + dstRB);
1078 const void* SkScalerContext_DW::drawDWMask(const SkGlyph& glyph) {
1079 int sizeNeeded = glyph.fWidth * glyph.fHeight;
1080 if (DWRITE_RENDERING_MODE_ALIASED != fRenderingMode) {
1083 if (sizeNeeded > fBits.count()) {
1084 fBits.setCount(sizeNeeded);
1088 memset(fBits.begin(), 0, sizeNeeded);
1090 fXform.dx = SkFixedToFloat(glyph.getSubXFixed());
1091 fXform.dy = SkFixedToFloat(glyph.getSubYFixed());
1093 FLOAT advance = 0.0f;
1095 UINT16 index = glyph.getGlyphID();
1097 DWRITE_GLYPH_OFFSET offset;
1098 offset.advanceOffset = 0.0f;
1099 offset.ascenderOffset = 0.0f;
1101 DWRITE_GLYPH_RUN run;
1103 run.glyphAdvances = &advance;
1104 run.fontFace = fTypeface->fDWriteFontFace.get();
1105 run.fontEmSize = SkScalarToFloat(fTextSizeRender);
1107 run.glyphIndices = &index;
1108 run.isSideways = FALSE;
1109 run.glyphOffsets = &offset;
1111 SkTScopedComPtr<IDWriteGlyphRunAnalysis> glyphRunAnalysis;
1112 HRNM(fTypeface->fFactory->CreateGlyphRunAnalysis(&run,
1113 1.0f, // pixelsPerDip,
1117 0.0f, // baselineOriginX,
1118 0.0f, // baselineOriginY,
1120 "Could not create glyph run analysis.");
1122 //NOTE: this assumes that the glyph has already been measured
1123 //with an exact same glyph run analysis.
1125 bbox.left = glyph.fLeft;
1126 bbox.top = glyph.fTop;
1127 bbox.right = glyph.fLeft + glyph.fWidth;
1128 bbox.bottom = glyph.fTop + glyph.fHeight;
1129 HRNM(glyphRunAnalysis->CreateAlphaTexture(fTextureType,
1133 "Could not draw mask.");
1134 return fBits.begin();
1137 void SkScalerContext_DW::generateImage(const SkGlyph& glyph) {
1139 const void* bits = this->drawDWMask(glyph);
1141 sk_bzero(glyph.fImage, glyph.computeImageSize());
1145 //Copy the mask into the glyph.
1146 const uint8_t* src = (const uint8_t*)bits;
1147 if (DWRITE_RENDERING_MODE_ALIASED == fRenderingMode) {
1148 bilevel_to_bw(src, glyph);
1149 const_cast<SkGlyph&>(glyph).fMaskFormat = SkMask::kBW_Format;
1150 } else if (!isLCD(fRec)) {
1151 if (fPreBlend.isApplicable()) {
1152 rgb_to_a8<true>(src, glyph, fPreBlend.fG);
1154 rgb_to_a8<false>(src, glyph, fPreBlend.fG);
1156 } else if (SkMask::kLCD16_Format == glyph.fMaskFormat) {
1157 if (fPreBlend.isApplicable()) {
1158 rgb_to_lcd16<true>(src, glyph, fPreBlend.fR, fPreBlend.fG, fPreBlend.fB);
1160 rgb_to_lcd16<false>(src, glyph, fPreBlend.fR, fPreBlend.fG, fPreBlend.fB);
1163 SkASSERT(SkMask::kLCD32_Format == glyph.fMaskFormat);
1164 if (fPreBlend.isApplicable()) {
1165 rgb_to_lcd32<true>(src, glyph, fPreBlend.fR, fPreBlend.fG, fPreBlend.fB);
1167 rgb_to_lcd32<false>(src, glyph, fPreBlend.fR, fPreBlend.fG, fPreBlend.fB);
1172 void SkScalerContext_DW::generatePath(const SkGlyph& glyph, SkPath* path) {
1173 SkASSERT(&glyph && path);
1177 SkTScopedComPtr<IDWriteGeometrySink> geometryToPath;
1178 HRVM(SkDWriteGeometrySink::Create(path, &geometryToPath),
1179 "Could not create geometry to path converter.");
1180 uint16_t glyphId = glyph.getGlyphID();
1181 //TODO: convert to<->from DIUs? This would make a difference if hinting.
1182 //It may not be needed, it appears that DirectWrite only hints at em size.
1183 HRVM(fTypeface->fDWriteFontFace->GetGlyphRunOutline(SkScalarToFloat(fTextSizeRender),
1190 geometryToPath.get()),
1191 "Could not create glyph outline.");
1193 path->transform(fSkXform);
1196 void DWriteFontTypeface::onGetFontDescriptor(SkFontDescriptor* desc,
1197 bool* isLocalStream) const {
1198 // Get the family name.
1199 SkTScopedComPtr<IDWriteLocalizedStrings> dwFamilyNames;
1200 HRV(fDWriteFontFamily->GetFamilyNames(&dwFamilyNames));
1202 UINT32 dwFamilyNamesLength;
1203 HRV(dwFamilyNames->GetStringLength(0, &dwFamilyNamesLength));
1205 SkSMallocWCHAR dwFamilyNameChar(dwFamilyNamesLength+1);
1206 HRV(dwFamilyNames->GetString(0, dwFamilyNameChar.get(), dwFamilyNamesLength+1));
1208 SkString utf8FamilyName;
1209 HRV(sk_wchar_to_skstring(dwFamilyNameChar.get(), &utf8FamilyName));
1211 desc->setFamilyName(utf8FamilyName.c_str());
1212 *isLocalStream = SkToBool(fDWriteFontFileLoader.get());
1215 static SkUnichar next_utf8(const void** chars) {
1216 return SkUTF8_NextUnichar((const char**)chars);
1219 static SkUnichar next_utf16(const void** chars) {
1220 return SkUTF16_NextUnichar((const uint16_t**)chars);
1223 static SkUnichar next_utf32(const void** chars) {
1224 const SkUnichar** uniChars = (const SkUnichar**)chars;
1225 SkUnichar uni = **uniChars;
1230 typedef SkUnichar (*EncodingProc)(const void**);
1232 static EncodingProc find_encoding_proc(SkTypeface::Encoding enc) {
1233 static const EncodingProc gProcs[] = {
1234 next_utf8, next_utf16, next_utf32
1236 SkASSERT((size_t)enc < SK_ARRAY_COUNT(gProcs));
1240 int DWriteFontTypeface::onCharsToGlyphs(const void* chars, Encoding encoding,
1241 uint16_t glyphs[], int glyphCount) const
1243 if (NULL == glyphs) {
1244 EncodingProc next_ucs4_proc = find_encoding_proc(encoding);
1245 for (int i = 0; i < glyphCount; ++i) {
1246 const SkUnichar c = next_ucs4_proc(&chars);
1248 fDWriteFont->HasCharacter(c, &exists);
1257 case SkTypeface::kUTF8_Encoding:
1258 case SkTypeface::kUTF16_Encoding: {
1259 static const int scratchCount = 256;
1260 UINT32 scratch[scratchCount];
1261 EncodingProc next_ucs4_proc = find_encoding_proc(encoding);
1262 for (int baseGlyph = 0; baseGlyph < glyphCount; baseGlyph += scratchCount) {
1263 int glyphsLeft = glyphCount - baseGlyph;
1264 int limit = SkTMin(glyphsLeft, scratchCount);
1265 for (int i = 0; i < limit; ++i) {
1266 scratch[i] = next_ucs4_proc(&chars);
1268 fDWriteFontFace->GetGlyphIndices(scratch, limit, &glyphs[baseGlyph]);
1272 case SkTypeface::kUTF32_Encoding: {
1273 const UINT32* utf32 = reinterpret_cast<const UINT32*>(chars);
1274 fDWriteFontFace->GetGlyphIndices(utf32, glyphCount, glyphs);
1281 for (int i = 0; i < glyphCount; ++i) {
1282 if (0 == glyphs[i]) {
1289 int DWriteFontTypeface::onCountGlyphs() const {
1290 return fDWriteFontFace->GetGlyphCount();
1293 int DWriteFontTypeface::onGetUPEM() const {
1294 DWRITE_FONT_METRICS metrics;
1295 fDWriteFontFace->GetMetrics(&metrics);
1296 return metrics.designUnitsPerEm;
1299 class LocalizedStrings_IDWriteLocalizedStrings : public SkTypeface::LocalizedStrings {
1301 /** Takes ownership of the IDWriteLocalizedStrings. */
1302 explicit LocalizedStrings_IDWriteLocalizedStrings(IDWriteLocalizedStrings* strings)
1303 : fIndex(0), fStrings(strings)
1306 virtual bool next(SkTypeface::LocalizedString* localizedString) SK_OVERRIDE {
1307 if (fIndex >= fStrings->GetCount()) {
1312 UINT32 stringLength;
1313 HRBM(fStrings->GetStringLength(fIndex, &stringLength), "Could not get string length.");
1316 SkSMallocWCHAR wString(stringLength);
1317 HRBM(fStrings->GetString(fIndex, wString.get(), stringLength), "Could not get string.");
1319 HRB(sk_wchar_to_skstring(wString.get(), &localizedString->fString));
1322 UINT32 localeLength;
1323 HRBM(fStrings->GetLocaleNameLength(fIndex, &localeLength), "Could not get locale length.");
1326 SkSMallocWCHAR wLocale(localeLength);
1327 HRBM(fStrings->GetLocaleName(fIndex, wLocale.get(), localeLength), "Could not get locale.");
1329 HRB(sk_wchar_to_skstring(wLocale.get(), &localizedString->fLanguage));
1337 SkTScopedComPtr<IDWriteLocalizedStrings> fStrings;
1340 SkTypeface::LocalizedStrings* DWriteFontTypeface::onCreateFamilyNameIterator() const {
1341 SkTScopedComPtr<IDWriteLocalizedStrings> familyNames;
1342 HRNM(fDWriteFontFamily->GetFamilyNames(&familyNames), "Could not obtain family names.");
1344 return new LocalizedStrings_IDWriteLocalizedStrings(familyNames.release());
1347 int DWriteFontTypeface::onGetTableTags(SkFontTableTag tags[]) const {
1348 DWRITE_FONT_FACE_TYPE type = fDWriteFontFace->GetType();
1349 if (type != DWRITE_FONT_FACE_TYPE_CFF &&
1350 type != DWRITE_FONT_FACE_TYPE_TRUETYPE &&
1351 type != DWRITE_FONT_FACE_TYPE_TRUETYPE_COLLECTION)
1357 SkAutoTUnref<SkStream> stream(this->openStream(&ttcIndex));
1358 return stream.get() ? SkFontStream::GetTableTags(stream, ttcIndex, tags) : 0;
1361 size_t DWriteFontTypeface::onGetTableData(SkFontTableTag tag, size_t offset,
1362 size_t length, void* data) const
1364 AutoDWriteTable table(fDWriteFontFace.get(), SkEndian_SwapBE32(tag));
1365 if (!table.fExists) {
1369 if (offset > table.fSize) {
1372 size_t size = SkTMin(length, table.fSize - offset);
1374 memcpy(data, table.fData + offset, size);
1380 template <typename T> class SkAutoIDWriteUnregister {
1382 SkAutoIDWriteUnregister(IDWriteFactory* factory, T* unregister)
1383 : fFactory(factory), fUnregister(unregister)
1386 ~SkAutoIDWriteUnregister() {
1388 unregister(fFactory, fUnregister);
1393 T* old = fUnregister;
1399 HRESULT unregister(IDWriteFactory* factory, IDWriteFontFileLoader* unregister) {
1400 return factory->UnregisterFontFileLoader(unregister);
1403 HRESULT unregister(IDWriteFactory* factory, IDWriteFontCollectionLoader* unregister) {
1404 return factory->UnregisterFontCollectionLoader(unregister);
1407 IDWriteFactory* fFactory;
1411 SkStream* DWriteFontTypeface::onOpenStream(int* ttcIndex) const {
1412 *ttcIndex = fDWriteFontFace->GetIndex();
1415 HRNM(fDWriteFontFace->GetFiles(&numFiles, NULL),
1416 "Could not get number of font files.");
1417 if (numFiles != 1) {
1421 SkTScopedComPtr<IDWriteFontFile> fontFile;
1422 HRNM(fDWriteFontFace->GetFiles(&numFiles, &fontFile), "Could not get font files.");
1424 const void* fontFileKey;
1425 UINT32 fontFileKeySize;
1426 HRNM(fontFile->GetReferenceKey(&fontFileKey, &fontFileKeySize),
1427 "Could not get font file reference key.");
1429 SkTScopedComPtr<IDWriteFontFileLoader> fontFileLoader;
1430 HRNM(fontFile->GetLoader(&fontFileLoader), "Could not get font file loader.");
1432 SkTScopedComPtr<IDWriteFontFileStream> fontFileStream;
1433 HRNM(fontFileLoader->CreateStreamFromKey(fontFileKey, fontFileKeySize,
1435 "Could not create font file stream.");
1437 return SkNEW_ARGS(SkDWriteFontFileStream, (fontFileStream.get()));
1440 SkScalerContext* DWriteFontTypeface::onCreateScalerContext(const SkDescriptor* desc) const {
1441 return SkNEW_ARGS(SkScalerContext_DW, (const_cast<DWriteFontTypeface*>(this), desc));
1444 void DWriteFontTypeface::onFilterRec(SkScalerContext::Rec* rec) const {
1445 if (rec->fFlags & SkScalerContext::kLCD_BGROrder_Flag ||
1446 rec->fFlags & SkScalerContext::kLCD_Vertical_Flag)
1448 rec->fMaskFormat = SkMask::kA8_Format;
1451 unsigned flagsWeDontSupport = SkScalerContext::kDevKernText_Flag |
1452 SkScalerContext::kForceAutohinting_Flag |
1453 SkScalerContext::kEmbolden_Flag |
1454 SkScalerContext::kLCD_BGROrder_Flag |
1455 SkScalerContext::kLCD_Vertical_Flag;
1456 rec->fFlags &= ~flagsWeDontSupport;
1458 SkPaint::Hinting h = rec->getHinting();
1459 // DirectWrite does not provide for hinting hints.
1460 h = SkPaint::kSlight_Hinting;
1463 #if SK_FONT_HOST_USE_SYSTEM_SETTINGS
1464 IDWriteFactory* factory = get_dwrite_factory();
1465 if (factory != NULL) {
1466 SkTScopedComPtr<IDWriteRenderingParams> defaultRenderingParams;
1467 if (SUCCEEDED(factory->CreateRenderingParams(&defaultRenderingParams))) {
1468 float gamma = defaultRenderingParams->GetGamma();
1469 rec->setDeviceGamma(gamma);
1470 rec->setPaintGamma(gamma);
1472 rec->setContrast(defaultRenderingParams->GetEnhancedContrast());
1478 ///////////////////////////////////////////////////////////////////////////////
1481 using namespace skia_advanced_typeface_metrics_utils;
1483 // Construct Glyph to Unicode table.
1484 // Unicode code points that require conjugate pairs in utf16 are not
1486 // TODO(arthurhsu): Add support for conjugate pairs. It looks like that may
1487 // require parsing the TTF cmap table (platform 4, encoding 12) directly instead
1488 // of calling GetFontUnicodeRange().
1489 // TODO(bungeman): This never does what anyone wants.
1490 // What is really wanted is the text to glyphs mapping
1491 static void populate_glyph_to_unicode(IDWriteFontFace* fontFace,
1492 const unsigned glyphCount,
1493 SkTDArray<SkUnichar>* glyphToUnicode) {
1496 //Do this like free type instead
1498 for (UINT32 c = 0; c < 0x10FFFF; ++c) {
1500 hr = fontFace->GetGlyphIndices(&c, 1, &glyph);
1506 SkAutoTArray<UINT32> chars(count);
1508 for (UINT32 c = 0; c < 0x10FFFF; ++c) {
1510 hr = fontFace->GetGlyphIndices(&c, 1, &glyph);
1517 SkAutoTArray<UINT16> glyph(count);
1518 fontFace->GetGlyphIndices(chars.get(), count, glyph.get());
1520 USHORT maxGlyph = 0;
1521 for (USHORT j = 0; j < count; ++j) {
1522 if (glyph[j] > maxGlyph) maxGlyph = glyph[j];
1525 glyphToUnicode->setCount(maxGlyph+1);
1526 for (USHORT j = 0; j < maxGlyph+1u; ++j) {
1527 (*glyphToUnicode)[j] = 0;
1531 for (USHORT j = 0; j < count; ++j) {
1532 if (glyph[j] < glyphCount && (*glyphToUnicode)[glyph[j]] == 0) {
1533 (*glyphToUnicode)[glyph[j]] = chars[j];
1538 static bool getWidthAdvance(IDWriteFontFace* fontFace, int gId, int16_t* advance) {
1541 UINT16 glyphId = gId;
1542 DWRITE_GLYPH_METRICS gm;
1543 HRESULT hr = fontFace->GetDesignGlyphMetrics(&glyphId, 1, &gm);
1550 *advance = gm.advanceWidth;
1554 SkAdvancedTypefaceMetrics* DWriteFontTypeface::onGetAdvancedTypefaceMetrics(
1555 SkAdvancedTypefaceMetrics::PerGlyphInfo perGlyphInfo,
1556 const uint32_t* glyphIDs,
1557 uint32_t glyphIDsCount) const {
1559 SkAdvancedTypefaceMetrics* info = NULL;
1563 const unsigned glyphCount = fDWriteFontFace->GetGlyphCount();
1565 DWRITE_FONT_METRICS dwfm;
1566 fDWriteFontFace->GetMetrics(&dwfm);
1568 info = new SkAdvancedTypefaceMetrics;
1569 info->fEmSize = dwfm.designUnitsPerEm;
1570 info->fMultiMaster = false;
1571 info->fLastGlyphID = SkToU16(glyphCount - 1);
1575 SkTScopedComPtr<IDWriteLocalizedStrings> familyNames;
1576 SkTScopedComPtr<IDWriteLocalizedStrings> faceNames;
1577 hr = fDWriteFontFamily->GetFamilyNames(&familyNames);
1578 hr = fDWriteFont->GetFaceNames(&faceNames);
1580 UINT32 familyNameLength;
1581 hr = familyNames->GetStringLength(0, &familyNameLength);
1583 UINT32 faceNameLength;
1584 hr = faceNames->GetStringLength(0, &faceNameLength);
1586 UINT32 size = familyNameLength+1+faceNameLength+1;
1587 SkSMallocWCHAR wFamilyName(size);
1588 hr = familyNames->GetString(0, wFamilyName.get(), size);
1589 wFamilyName[familyNameLength] = L' ';
1590 hr = faceNames->GetString(0, &wFamilyName[familyNameLength+1], size - faceNameLength + 1);
1592 hr = sk_wchar_to_skstring(wFamilyName.get(), &info->fFontName);
1594 if (perGlyphInfo & SkAdvancedTypefaceMetrics::kToUnicode_PerGlyphInfo) {
1595 populate_glyph_to_unicode(fDWriteFontFace.get(), glyphCount, &(info->fGlyphToUnicode));
1598 DWRITE_FONT_FACE_TYPE fontType = fDWriteFontFace->GetType();
1599 if (fontType == DWRITE_FONT_FACE_TYPE_TRUETYPE ||
1600 fontType == DWRITE_FONT_FACE_TYPE_TRUETYPE_COLLECTION) {
1601 info->fType = SkAdvancedTypefaceMetrics::kTrueType_Font;
1603 info->fType = SkAdvancedTypefaceMetrics::kOther_Font;
1604 info->fItalicAngle = 0;
1605 info->fAscent = dwfm.ascent;;
1606 info->fDescent = dwfm.descent;
1608 info->fCapHeight = dwfm.capHeight;
1609 info->fBBox = SkIRect::MakeEmpty();
1613 AutoTDWriteTable<SkOTTableHead> headTable(fDWriteFontFace.get());
1614 AutoTDWriteTable<SkOTTablePostScript> postTable(fDWriteFontFace.get());
1615 AutoTDWriteTable<SkOTTableHorizontalHeader> hheaTable(fDWriteFontFace.get());
1616 AutoTDWriteTable<SkOTTableOS2> os2Table(fDWriteFontFace.get());
1617 if (!headTable.fExists || !postTable.fExists || !hheaTable.fExists || !os2Table.fExists) {
1618 info->fItalicAngle = 0;
1619 info->fAscent = dwfm.ascent;;
1620 info->fDescent = dwfm.descent;
1622 info->fCapHeight = dwfm.capHeight;
1623 info->fBBox = SkIRect::MakeEmpty();
1627 //There exist CJK fonts which set the IsFixedPitch and Monospace bits,
1628 //but have full width, latin half-width, and half-width kana.
1629 bool fixedWidth = (postTable->isFixedPitch &&
1630 (1 == SkEndian_SwapBE16(hheaTable->numberOfHMetrics)));
1633 info->fStyle |= SkAdvancedTypefaceMetrics::kFixedPitch_Style;
1636 if (os2Table->version.v0.fsSelection.field.Italic) {
1637 info->fStyle |= SkAdvancedTypefaceMetrics::kItalic_Style;
1640 if (SkPanose::FamilyType::Script == os2Table->version.v0.panose.bFamilyType.value) {
1641 info->fStyle |= SkAdvancedTypefaceMetrics::kScript_Style;
1643 } else if (SkPanose::FamilyType::TextAndDisplay == os2Table->version.v0.panose.bFamilyType.value &&
1644 SkPanose::Data::TextAndDisplay::SerifStyle::Triangle <= os2Table->version.v0.panose.data.textAndDisplay.bSerifStyle.value &&
1645 SkPanose::Data::TextAndDisplay::SerifStyle::NoFit != os2Table->version.v0.panose.data.textAndDisplay.bSerifStyle.value) {
1646 info->fStyle |= SkAdvancedTypefaceMetrics::kSerif_Style;
1649 info->fItalicAngle = SkEndian_SwapBE32(postTable->italicAngle) >> 16;
1651 info->fAscent = SkToS16(dwfm.ascent);
1652 info->fDescent = SkToS16(dwfm.descent);
1653 info->fCapHeight = SkToS16(dwfm.capHeight);
1655 info->fBBox = SkIRect::MakeLTRB((int32_t)SkEndian_SwapBE16((uint16_t)headTable->xMin),
1656 (int32_t)SkEndian_SwapBE16((uint16_t)headTable->yMax),
1657 (int32_t)SkEndian_SwapBE16((uint16_t)headTable->xMax),
1658 (int32_t)SkEndian_SwapBE16((uint16_t)headTable->yMin));
1660 //TODO: is this even desired? It seems PDF only wants this value for Type1
1661 //fonts, and we only get here for TrueType fonts.
1664 // Figure out a good guess for StemV - Min width of i, I, !, 1.
1665 // This probably isn't very good with an italic font.
1666 int16_t min_width = SHRT_MAX;
1668 char stem_chars[] = {'i', 'I', '!', '1'};
1669 for (size_t i = 0; i < SK_ARRAY_COUNT(stem_chars); i++) {
1671 if (GetCharABCWidths(hdc, stem_chars[i], stem_chars[i], &abcWidths)) {
1672 int16_t width = abcWidths.abcB;
1673 if (width > 0 && width < min_width) {
1675 info->fStemV = min_width;
1681 // If Restricted, the font may not be embedded in a document.
1682 // If not Restricted, the font can be embedded.
1683 // If PreviewPrint, the embedding is read-only.
1684 if (os2Table->version.v0.fsType.field.Restricted) {
1685 info->fType = SkAdvancedTypefaceMetrics::kNotEmbeddable_Font;
1686 } else if (perGlyphInfo & SkAdvancedTypefaceMetrics::kHAdvance_PerGlyphInfo) {
1688 appendRange(&info->fGlyphWidths, 0);
1690 getWidthAdvance(fDWriteFontFace.get(), 1, &advance);
1691 info->fGlyphWidths->fAdvance.append(1, &advance);
1692 finishRange(info->fGlyphWidths.get(), 0,
1693 SkAdvancedTypefaceMetrics::WidthRange::kDefault);
1695 info->fGlyphWidths.reset(
1696 getAdvanceData(fDWriteFontFace.get(),
1707 ///////////////////////////////////////////////////////////////////////////////
1709 SkTypeface* SkFontMgr_DirectWrite::createTypefaceFromDWriteFont(
1710 IDWriteFontFace* fontFace,
1712 IDWriteFontFamily* fontFamily) const {
1713 SkTypeface* face = FindByProcAndRef(FindByDWriteFont, font);
1715 face = DWriteFontTypeface::Create(fFactory.get(), fontFace, font, fontFamily);
1717 Add(face, get_style(font), true);
1723 int SkFontMgr_DirectWrite::onCountFamilies() const {
1724 return fFontCollection->GetFontFamilyCount();
1727 void SkFontMgr_DirectWrite::onGetFamilyName(int index, SkString* familyName) const {
1728 SkTScopedComPtr<IDWriteFontFamily> fontFamily;
1729 HRVM(fFontCollection->GetFontFamily(index, &fontFamily), "Could not get requested family.");
1731 SkTScopedComPtr<IDWriteLocalizedStrings> familyNames;
1732 HRVM(fontFamily->GetFamilyNames(&familyNames), "Could not get family names.");
1734 sk_get_locale_string(familyNames.get(), fLocaleName.get(), familyName);
1737 SkFontStyleSet* SkFontMgr_DirectWrite::onCreateStyleSet(int index) const {
1738 SkTScopedComPtr<IDWriteFontFamily> fontFamily;
1739 HRNM(fFontCollection->GetFontFamily(index, &fontFamily), "Could not get requested family.");
1741 return SkNEW_ARGS(SkFontStyleSet_DirectWrite, (this, fontFamily.get()));
1744 SkFontStyleSet* SkFontMgr_DirectWrite::onMatchFamily(const char familyName[]) const {
1745 SkSMallocWCHAR dwFamilyName;
1746 HRN(sk_cstring_to_wchar(familyName, &dwFamilyName));
1750 HRNM(fFontCollection->FindFamilyName(dwFamilyName.get(), &index, &exists),
1751 "Failed while finding family by name.");
1756 return this->onCreateStyleSet(index);
1759 SkTypeface* SkFontMgr_DirectWrite::onMatchFamilyStyle(const char familyName[],
1760 const SkFontStyle& fontstyle) const {
1761 SkAutoTUnref<SkFontStyleSet> sset(this->matchFamily(familyName));
1762 return sset->matchStyle(fontstyle);
1765 SkTypeface* SkFontMgr_DirectWrite::onMatchFaceStyle(const SkTypeface* familyMember,
1766 const SkFontStyle& fontstyle) const {
1767 SkString familyName;
1768 SkFontStyleSet_DirectWrite sset(
1769 this, ((DWriteFontTypeface*)familyMember)->fDWriteFontFamily.get()
1771 return sset.matchStyle(fontstyle);
1774 SkTypeface* SkFontMgr_DirectWrite::onCreateFromStream(SkStream* stream, int ttcIndex) const {
1775 SkTScopedComPtr<StreamFontFileLoader> fontFileLoader;
1776 HRN(StreamFontFileLoader::Create(stream, &fontFileLoader));
1777 HRN(fFactory->RegisterFontFileLoader(fontFileLoader.get()));
1778 SkAutoIDWriteUnregister<StreamFontFileLoader> autoUnregisterFontFileLoader(
1779 fFactory.get(), fontFileLoader.get());
1781 SkTScopedComPtr<StreamFontCollectionLoader> fontCollectionLoader;
1782 HRN(StreamFontCollectionLoader::Create(fontFileLoader.get(), &fontCollectionLoader));
1783 HRN(fFactory->RegisterFontCollectionLoader(fontCollectionLoader.get()));
1784 SkAutoIDWriteUnregister<StreamFontCollectionLoader> autoUnregisterFontCollectionLoader(
1785 fFactory.get(), fontCollectionLoader.get());
1787 SkTScopedComPtr<IDWriteFontCollection> fontCollection;
1788 HRN(fFactory->CreateCustomFontCollection(fontCollectionLoader.get(), NULL, 0, &fontCollection));
1790 // Find the first non-simulated font which has the given ttc index.
1791 UINT32 familyCount = fontCollection->GetFontFamilyCount();
1792 for (UINT32 familyIndex = 0; familyIndex < familyCount; ++familyIndex) {
1793 SkTScopedComPtr<IDWriteFontFamily> fontFamily;
1794 HRN(fontCollection->GetFontFamily(familyIndex, &fontFamily));
1796 UINT32 fontCount = fontFamily->GetFontCount();
1797 for (UINT32 fontIndex = 0; fontIndex < fontCount; ++fontIndex) {
1798 SkTScopedComPtr<IDWriteFont> font;
1799 HRN(fontFamily->GetFont(fontIndex, &font));
1800 if (font->GetSimulations() != DWRITE_FONT_SIMULATIONS_NONE) {
1804 SkTScopedComPtr<IDWriteFontFace> fontFace;
1805 HRN(font->CreateFontFace(&fontFace));
1807 UINT32 faceIndex = fontFace->GetIndex();
1808 if (faceIndex == ttcIndex) {
1809 return DWriteFontTypeface::Create(fFactory.get(),
1810 fontFace.get(), font.get(), fontFamily.get(),
1811 autoUnregisterFontFileLoader.detatch(),
1812 autoUnregisterFontCollectionLoader.detatch());
1820 SkTypeface* SkFontMgr_DirectWrite::onCreateFromData(SkData* data, int ttcIndex) const {
1821 SkAutoTUnref<SkStream> stream(SkNEW_ARGS(SkMemoryStream, (data)));
1822 return this->createFromStream(stream, ttcIndex);
1825 SkTypeface* SkFontMgr_DirectWrite::onCreateFromFile(const char path[], int ttcIndex) const {
1826 SkAutoTUnref<SkStream> stream(SkStream::NewFromFile(path));
1827 return this->createFromStream(stream, ttcIndex);
1830 HRESULT SkFontMgr_DirectWrite::getByFamilyName(const WCHAR wideFamilyName[],
1831 IDWriteFontFamily** fontFamily) const {
1834 HR(fFontCollection->FindFamilyName(wideFamilyName, &index, &exists));
1837 HR(fFontCollection->GetFontFamily(index, fontFamily));
1842 HRESULT SkFontMgr_DirectWrite::getDefaultFontFamily(IDWriteFontFamily** fontFamily) const {
1843 NONCLIENTMETRICSW metrics;
1844 metrics.cbSize = sizeof(metrics);
1845 if (0 == SystemParametersInfoW(SPI_GETNONCLIENTMETRICS,
1849 return E_UNEXPECTED;
1851 HRM(this->getByFamilyName(metrics.lfMessageFont.lfFaceName, fontFamily),
1852 "Could not create DWrite font family from LOGFONT.");
1856 SkTypeface* SkFontMgr_DirectWrite::onLegacyCreateTypeface(const char familyName[],
1857 unsigned styleBits) const {
1858 SkTScopedComPtr<IDWriteFontFamily> fontFamily;
1860 SkSMallocWCHAR wideFamilyName;
1861 if (SUCCEEDED(sk_cstring_to_wchar(familyName, &wideFamilyName))) {
1862 this->getByFamilyName(wideFamilyName, &fontFamily);
1866 if (NULL == fontFamily.get()) {
1867 // No family with given name, try default.
1868 HRNM(this->getDefaultFontFamily(&fontFamily), "Could not get default font family.");
1871 if (NULL == fontFamily.get()) {
1872 // Could not obtain the default font.
1873 HRNM(fFontCollection->GetFontFamily(0, &fontFamily),
1874 "Could not get default-default font family.");
1877 SkTScopedComPtr<IDWriteFont> font;
1878 DWRITE_FONT_WEIGHT weight = (styleBits & SkTypeface::kBold)
1879 ? DWRITE_FONT_WEIGHT_BOLD
1880 : DWRITE_FONT_WEIGHT_NORMAL;
1881 DWRITE_FONT_STRETCH stretch = DWRITE_FONT_STRETCH_NORMAL;
1882 DWRITE_FONT_STYLE italic = (styleBits & SkTypeface::kItalic)
1883 ? DWRITE_FONT_STYLE_ITALIC
1884 : DWRITE_FONT_STYLE_NORMAL;
1885 HRNM(fontFamily->GetFirstMatchingFont(weight, stretch, italic, &font),
1886 "Could not get matching font.");
1888 SkTScopedComPtr<IDWriteFontFace> fontFace;
1889 HRNM(font->CreateFontFace(&fontFace), "Could not create font face.");
1891 return this->createTypefaceFromDWriteFont(fontFace.get(), font.get(), fontFamily.get());
1894 ///////////////////////////////////////////////////////////////////////////////
1896 int SkFontStyleSet_DirectWrite::count() {
1897 return fFontFamily->GetFontCount();
1900 SkTypeface* SkFontStyleSet_DirectWrite::createTypeface(int index) {
1901 SkTScopedComPtr<IDWriteFont> font;
1902 HRNM(fFontFamily->GetFont(index, &font), "Could not get font.");
1904 SkTScopedComPtr<IDWriteFontFace> fontFace;
1905 HRNM(font->CreateFontFace(&fontFace), "Could not create font face.");
1907 return fFontMgr->createTypefaceFromDWriteFont(fontFace.get(), font.get(), fFontFamily.get());
1910 void SkFontStyleSet_DirectWrite::getStyle(int index, SkFontStyle* fs, SkString* styleName) {
1911 SkTScopedComPtr<IDWriteFont> font;
1912 HRVM(fFontFamily->GetFont(index, &font), "Could not get font.");
1915 SkFontStyle::Slant slant;
1916 switch (font->GetStyle()) {
1917 case DWRITE_FONT_STYLE_NORMAL:
1918 slant = SkFontStyle::kUpright_Slant;
1920 case DWRITE_FONT_STYLE_OBLIQUE:
1921 case DWRITE_FONT_STYLE_ITALIC:
1922 slant = SkFontStyle::kItalic_Slant;
1928 int weight = font->GetWeight();
1929 int width = font->GetStretch();
1931 *fs = SkFontStyle(weight, width, slant);
1935 SkTScopedComPtr<IDWriteLocalizedStrings> faceNames;
1936 if (SUCCEEDED(font->GetFaceNames(&faceNames))) {
1937 sk_get_locale_string(faceNames.get(), fFontMgr->fLocaleName.get(), styleName);
1942 SkTypeface* SkFontStyleSet_DirectWrite::matchStyle(const SkFontStyle& pattern) {
1943 DWRITE_FONT_STYLE slant;
1944 switch (pattern.slant()) {
1945 case SkFontStyle::kUpright_Slant:
1946 slant = DWRITE_FONT_STYLE_NORMAL;
1948 case SkFontStyle::kItalic_Slant:
1949 slant = DWRITE_FONT_STYLE_ITALIC;
1955 DWRITE_FONT_WEIGHT weight = (DWRITE_FONT_WEIGHT)pattern.weight();
1956 DWRITE_FONT_STRETCH width = (DWRITE_FONT_STRETCH)pattern.width();
1958 SkTScopedComPtr<IDWriteFont> font;
1959 // TODO: perhaps use GetMatchingFonts and get the least simulated?
1960 HRNM(fFontFamily->GetFirstMatchingFont(weight, width, slant, &font),
1961 "Could not match font in family.");
1963 SkTScopedComPtr<IDWriteFontFace> fontFace;
1964 HRNM(font->CreateFontFace(&fontFace), "Could not create font face.");
1966 return fFontMgr->createTypefaceFromDWriteFont(fontFace.get(), font.get(),
1970 ///////////////////////////////////////////////////////////////////////////////
1972 SkFontMgr* SkFontMgr_New_DirectWrite(IDWriteFactory* factory) {
1973 if (NULL == factory) {
1974 factory = sk_get_dwrite_factory();
1975 if (NULL == factory) {
1980 SkTScopedComPtr<IDWriteFontCollection> sysFontCollection;
1981 HRNM(factory->GetSystemFontCollection(&sysFontCollection, FALSE),
1982 "Could not get system font collection.");
1984 WCHAR localeNameStorage[LOCALE_NAME_MAX_LENGTH];
1985 WCHAR* localeName = NULL;
1986 int localeNameLen = 0;
1988 // Dynamically load GetUserDefaultLocaleName function, as it is not available on XP.
1989 SkGetUserDefaultLocaleNameProc getUserDefaultLocaleNameProc = NULL;
1990 HRESULT hr = SkGetGetUserDefaultLocaleNameProc(&getUserDefaultLocaleNameProc);
1991 if (NULL == getUserDefaultLocaleNameProc) {
1992 SK_TRACEHR(hr, "Could not get GetUserDefaultLocaleName.");
1994 localeNameLen = getUserDefaultLocaleNameProc(localeNameStorage, LOCALE_NAME_MAX_LENGTH);
1995 if (localeNameLen) {
1996 localeName = localeNameStorage;
2000 return SkNEW_ARGS(SkFontMgr_DirectWrite, (factory, sysFontCollection.get(),
2001 localeName, localeNameLen));
2004 #include "SkFontMgr_indirect.h"
2005 SkFontMgr* SkFontMgr_New_DirectWriteRenderer(SkRemotableFontMgr* proxy) {
2006 SkAutoTUnref<SkFontMgr> impl(SkFontMgr_New_DirectWrite());
2007 if (impl.get() == NULL) {
2010 return SkNEW_ARGS(SkFontMgr_Indirect, (impl.get(), proxy));