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"
26 #include "SkOTTable_head.h"
27 #include "SkOTTable_hhea.h"
28 #include "SkOTTable_OS_2.h"
29 #include "SkOTTable_post.h"
33 #include "SkTScopedComPtr.h"
35 #include "SkTypeface_win.h"
36 #include "SkTypefaceCache.h"
41 static bool isLCD(const SkScalerContext::Rec& rec) {
42 return SkMask::kLCD16_Format == rec.fMaskFormat ||
43 SkMask::kLCD32_Format == rec.fMaskFormat;
46 ///////////////////////////////////////////////////////////////////////////////
48 class StreamFontFileLoader;
50 class SkFontMgr_DirectWrite : public SkFontMgr {
52 /** localeNameLength must include the null terminator. */
53 SkFontMgr_DirectWrite(IDWriteFontCollection* fontCollection,
54 WCHAR* localeName, int localeNameLength)
55 : fFontCollection(SkRefComPtr(fontCollection))
56 , fLocaleName(localeNameLength)
58 memcpy(fLocaleName.get(), localeName, localeNameLength * sizeof(WCHAR));
61 SkTypeface* createTypefaceFromDWriteFont(IDWriteFontFace* fontFace,
63 IDWriteFontFamily* fontFamily,
64 StreamFontFileLoader* = NULL,
65 IDWriteFontCollectionLoader* = NULL) const;
68 virtual int onCountFamilies() const SK_OVERRIDE;
69 virtual void onGetFamilyName(int index, SkString* familyName) const SK_OVERRIDE;
70 virtual SkFontStyleSet* onCreateStyleSet(int index) const SK_OVERRIDE;
71 virtual SkFontStyleSet* onMatchFamily(const char familyName[]) const SK_OVERRIDE;
72 virtual SkTypeface* onMatchFamilyStyle(const char familyName[],
73 const SkFontStyle& fontstyle) const SK_OVERRIDE;
74 virtual SkTypeface* onMatchFaceStyle(const SkTypeface* familyMember,
75 const SkFontStyle& fontstyle) const SK_OVERRIDE;
76 virtual SkTypeface* onCreateFromStream(SkStream* stream, int ttcIndex) const SK_OVERRIDE;
77 virtual SkTypeface* onCreateFromData(SkData* data, int ttcIndex) const SK_OVERRIDE;
78 virtual SkTypeface* onCreateFromFile(const char path[], int ttcIndex) const SK_OVERRIDE;
79 virtual SkTypeface* onLegacyCreateTypeface(const char familyName[],
80 unsigned styleBits) const SK_OVERRIDE;
83 HRESULT getByFamilyName(const WCHAR familyName[], IDWriteFontFamily** fontFamily) const;
84 HRESULT getDefaultFontFamily(IDWriteFontFamily** fontFamily) const;
86 void Add(SkTypeface* face, SkTypeface::Style requestedStyle, bool strong) const {
87 SkAutoMutexAcquire ama(fTFCacheMutex);
88 fTFCache.add(face, requestedStyle, strong);
91 SkTypeface* FindByProcAndRef(SkTypefaceCache::FindProc proc, void* ctx) const {
92 SkAutoMutexAcquire ama(fTFCacheMutex);
93 SkTypeface* typeface = fTFCache.findByProcAndRef(proc, ctx);
97 SkTScopedComPtr<IDWriteFontCollection> fFontCollection;
98 SkSMallocWCHAR fLocaleName;
99 mutable SkMutex fTFCacheMutex;
100 mutable SkTypefaceCache fTFCache;
102 friend class SkFontStyleSet_DirectWrite;
105 class SkFontStyleSet_DirectWrite : public SkFontStyleSet {
107 SkFontStyleSet_DirectWrite(const SkFontMgr_DirectWrite* fontMgr,
108 IDWriteFontFamily* fontFamily)
109 : fFontMgr(SkRef(fontMgr))
110 , fFontFamily(SkRefComPtr(fontFamily))
113 virtual int count() SK_OVERRIDE;
114 virtual void getStyle(int index, SkFontStyle* fs, SkString* styleName) SK_OVERRIDE;
115 virtual SkTypeface* createTypeface(int index) SK_OVERRIDE;
116 virtual SkTypeface* matchStyle(const SkFontStyle& pattern) SK_OVERRIDE;
119 SkAutoTUnref<const SkFontMgr_DirectWrite> fFontMgr;
120 SkTScopedComPtr<IDWriteFontFamily> fFontFamily;
123 ///////////////////////////////////////////////////////////////////////////////
125 class DWriteOffscreen {
127 DWriteOffscreen() : fWidth(0), fHeight(0) {
130 void init(IDWriteFontFace* fontFace, const DWRITE_MATRIX& xform, FLOAT fontSize) {
131 fFontFace = fontFace;
132 fFontSize = fontSize;
136 const void* draw(const SkGlyph&, bool isBW);
141 IDWriteFontFace* fFontFace;
143 DWRITE_MATRIX fXform;
144 SkTDArray<uint8_t> fBits;
147 const void* DWriteOffscreen::draw(const SkGlyph& glyph, bool isBW) {
148 IDWriteFactory* factory = sk_get_dwrite_factory();
149 SkASSERT(factory != NULL);
151 if (fWidth < glyph.fWidth || fHeight < glyph.fHeight) {
152 fWidth = SkMax32(fWidth, glyph.fWidth);
153 fHeight = SkMax32(fHeight, glyph.fHeight);
156 fBits.setCount(fWidth * fHeight);
158 fBits.setCount(fWidth * fHeight * 3);
163 memset(fBits.begin(), 0, fBits.count());
165 fXform.dx = SkFixedToFloat(glyph.getSubXFixed());
166 fXform.dy = SkFixedToFloat(glyph.getSubYFixed());
168 FLOAT advance = 0.0f;
170 UINT16 index = glyph.getGlyphID();
172 DWRITE_GLYPH_OFFSET offset;
173 offset.advanceOffset = 0.0f;
174 offset.ascenderOffset = 0.0f;
176 DWRITE_GLYPH_RUN run;
178 run.glyphAdvances = &advance;
179 run.fontFace = fFontFace;
180 run.fontEmSize = fFontSize;
182 run.glyphIndices = &index;
183 run.isSideways = FALSE;
184 run.glyphOffsets = &offset;
186 DWRITE_RENDERING_MODE renderingMode;
187 DWRITE_TEXTURE_TYPE textureType;
189 renderingMode = DWRITE_RENDERING_MODE_ALIASED;
190 textureType = DWRITE_TEXTURE_ALIASED_1x1;
192 renderingMode = DWRITE_RENDERING_MODE_CLEARTYPE_NATURAL_SYMMETRIC;
193 textureType = DWRITE_TEXTURE_CLEARTYPE_3x1;
195 SkTScopedComPtr<IDWriteGlyphRunAnalysis> glyphRunAnalysis;
196 HRNM(factory->CreateGlyphRunAnalysis(&run,
197 1.0f, // pixelsPerDip,
200 DWRITE_MEASURING_MODE_NATURAL,
201 0.0f, // baselineOriginX,
202 0.0f, // baselineOriginY,
204 "Could not create glyph run analysis.");
206 //NOTE: this assumes that the glyph has already been measured
207 //with an exact same glyph run analysis.
209 bbox.left = glyph.fLeft;
210 bbox.top = glyph.fTop;
211 bbox.right = glyph.fLeft + glyph.fWidth;
212 bbox.bottom = glyph.fTop + glyph.fHeight;
213 HRNM(glyphRunAnalysis->CreateAlphaTexture(textureType,
217 "Could not draw mask.");
218 return fBits.begin();
221 ///////////////////////////////////////////////////////////////////////////////
223 class StreamFontFileLoader : public IDWriteFontFileLoader {
226 virtual HRESULT STDMETHODCALLTYPE QueryInterface(REFIID iid, void** ppvObject);
227 virtual ULONG STDMETHODCALLTYPE AddRef();
228 virtual ULONG STDMETHODCALLTYPE Release();
230 // IDWriteFontFileLoader methods
231 virtual HRESULT STDMETHODCALLTYPE CreateStreamFromKey(
232 void const* fontFileReferenceKey,
233 UINT32 fontFileReferenceKeySize,
234 IDWriteFontFileStream** fontFileStream);
236 static HRESULT Create(SkStream* stream, StreamFontFileLoader** streamFontFileLoader) {
237 *streamFontFileLoader = new StreamFontFileLoader(stream);
238 if (NULL == streamFontFileLoader) {
239 return E_OUTOFMEMORY;
244 SkAutoTUnref<SkStream> fStream;
247 StreamFontFileLoader(SkStream* stream) : fRefCount(1), fStream(SkRef(stream)) { }
252 HRESULT StreamFontFileLoader::QueryInterface(REFIID iid, void** ppvObject) {
253 if (iid == IID_IUnknown || iid == __uuidof(IDWriteFontFileLoader)) {
259 return E_NOINTERFACE;
263 ULONG StreamFontFileLoader::AddRef() {
264 return InterlockedIncrement(&fRefCount);
267 ULONG StreamFontFileLoader::Release() {
268 ULONG newCount = InterlockedDecrement(&fRefCount);
275 HRESULT StreamFontFileLoader::CreateStreamFromKey(
276 void const* fontFileReferenceKey,
277 UINT32 fontFileReferenceKeySize,
278 IDWriteFontFileStream** fontFileStream)
280 SkTScopedComPtr<SkDWriteFontFileStreamWrapper> stream;
281 HR(SkDWriteFontFileStreamWrapper::Create(fStream, &stream));
282 *fontFileStream = stream.release();
286 class StreamFontFileEnumerator : public IDWriteFontFileEnumerator {
289 virtual HRESULT STDMETHODCALLTYPE QueryInterface(REFIID iid, void** ppvObject);
290 virtual ULONG STDMETHODCALLTYPE AddRef();
291 virtual ULONG STDMETHODCALLTYPE Release();
293 // IDWriteFontFileEnumerator methods
294 virtual HRESULT STDMETHODCALLTYPE MoveNext(BOOL* hasCurrentFile);
295 virtual HRESULT STDMETHODCALLTYPE GetCurrentFontFile(IDWriteFontFile** fontFile);
297 static HRESULT Create(IDWriteFactory* factory, IDWriteFontFileLoader* fontFileLoader,
298 StreamFontFileEnumerator** streamFontFileEnumerator) {
299 *streamFontFileEnumerator = new StreamFontFileEnumerator(factory, fontFileLoader);
300 if (NULL == streamFontFileEnumerator) {
301 return E_OUTOFMEMORY;
306 StreamFontFileEnumerator(IDWriteFactory* factory, IDWriteFontFileLoader* fontFileLoader);
309 SkTScopedComPtr<IDWriteFactory> fFactory;
310 SkTScopedComPtr<IDWriteFontFile> fCurrentFile;
311 SkTScopedComPtr<IDWriteFontFileLoader> fFontFileLoader;
315 StreamFontFileEnumerator::StreamFontFileEnumerator(IDWriteFactory* factory,
316 IDWriteFontFileLoader* fontFileLoader)
318 , fFactory(SkRefComPtr(factory))
320 , fFontFileLoader(SkRefComPtr(fontFileLoader))
324 HRESULT StreamFontFileEnumerator::QueryInterface(REFIID iid, void** ppvObject) {
325 if (iid == IID_IUnknown || iid == __uuidof(IDWriteFontFileEnumerator)) {
331 return E_NOINTERFACE;
335 ULONG StreamFontFileEnumerator::AddRef() {
336 return InterlockedIncrement(&fRefCount);
339 ULONG StreamFontFileEnumerator::Release() {
340 ULONG newCount = InterlockedDecrement(&fRefCount);
347 HRESULT StreamFontFileEnumerator::MoveNext(BOOL* hasCurrentFile) {
348 *hasCurrentFile = FALSE;
356 HR(fFactory->CreateCustomFontFileReference(
357 &dummy, //cannot be NULL
358 sizeof(dummy), //even if this is 0
359 fFontFileLoader.get(),
362 *hasCurrentFile = TRUE;
366 HRESULT StreamFontFileEnumerator::GetCurrentFontFile(IDWriteFontFile** fontFile) {
367 if (fCurrentFile.get() == NULL) {
372 *fontFile = SkRefComPtr(fCurrentFile.get());
376 class StreamFontCollectionLoader : public IDWriteFontCollectionLoader {
379 virtual HRESULT STDMETHODCALLTYPE QueryInterface(REFIID iid, void** ppvObject);
380 virtual ULONG STDMETHODCALLTYPE AddRef();
381 virtual ULONG STDMETHODCALLTYPE Release();
383 // IDWriteFontCollectionLoader methods
384 virtual HRESULT STDMETHODCALLTYPE CreateEnumeratorFromKey(
385 IDWriteFactory* factory,
386 void const* collectionKey,
387 UINT32 collectionKeySize,
388 IDWriteFontFileEnumerator** fontFileEnumerator);
390 static HRESULT Create(IDWriteFontFileLoader* fontFileLoader,
391 StreamFontCollectionLoader** streamFontCollectionLoader) {
392 *streamFontCollectionLoader = new StreamFontCollectionLoader(fontFileLoader);
393 if (NULL == streamFontCollectionLoader) {
394 return E_OUTOFMEMORY;
399 StreamFontCollectionLoader(IDWriteFontFileLoader* fontFileLoader)
401 , fFontFileLoader(SkRefComPtr(fontFileLoader))
405 SkTScopedComPtr<IDWriteFontFileLoader> fFontFileLoader;
408 HRESULT StreamFontCollectionLoader::QueryInterface(REFIID iid, void** ppvObject) {
409 if (iid == IID_IUnknown || iid == __uuidof(IDWriteFontCollectionLoader)) {
415 return E_NOINTERFACE;
419 ULONG StreamFontCollectionLoader::AddRef() {
420 return InterlockedIncrement(&fRefCount);
423 ULONG StreamFontCollectionLoader::Release() {
424 ULONG newCount = InterlockedDecrement(&fRefCount);
431 HRESULT StreamFontCollectionLoader::CreateEnumeratorFromKey(
432 IDWriteFactory* factory,
433 void const* collectionKey,
434 UINT32 collectionKeySize,
435 IDWriteFontFileEnumerator** fontFileEnumerator)
437 SkTScopedComPtr<StreamFontFileEnumerator> enumerator;
438 HR(StreamFontFileEnumerator::Create(factory, fFontFileLoader.get(), &enumerator));
439 *fontFileEnumerator = enumerator.release();
443 ///////////////////////////////////////////////////////////////////////////////
445 static SkTypeface::Style get_style(IDWriteFont* font) {
446 int style = SkTypeface::kNormal;
447 DWRITE_FONT_WEIGHT weight = font->GetWeight();
448 if (DWRITE_FONT_WEIGHT_DEMI_BOLD <= weight) {
449 style |= SkTypeface::kBold;
451 DWRITE_FONT_STYLE angle = font->GetStyle();
452 if (DWRITE_FONT_STYLE_OBLIQUE == angle || DWRITE_FONT_STYLE_ITALIC == angle) {
453 style |= SkTypeface::kItalic;
455 return static_cast<SkTypeface::Style>(style);
458 class DWriteFontTypeface : public SkTypeface {
460 DWriteFontTypeface(SkTypeface::Style style, SkFontID fontID,
461 IDWriteFontFace* fontFace,
463 IDWriteFontFamily* fontFamily,
464 StreamFontFileLoader* fontFileLoader = NULL,
465 IDWriteFontCollectionLoader* fontCollectionLoader = NULL)
466 : SkTypeface(style, fontID, false)
467 , fDWriteFontCollectionLoader(SkSafeRefComPtr(fontCollectionLoader))
468 , fDWriteFontFileLoader(SkSafeRefComPtr(fontFileLoader))
469 , fDWriteFontFamily(SkRefComPtr(fontFamily))
470 , fDWriteFont(SkRefComPtr(font))
471 , fDWriteFontFace(SkRefComPtr(fontFace))
475 SkTScopedComPtr<IDWriteFontCollectionLoader> fDWriteFontCollectionLoader;
476 SkTScopedComPtr<StreamFontFileLoader> fDWriteFontFileLoader;
477 SkTScopedComPtr<IDWriteFontFamily> fDWriteFontFamily;
478 SkTScopedComPtr<IDWriteFont> fDWriteFont;
479 SkTScopedComPtr<IDWriteFontFace> fDWriteFontFace;
481 static DWriteFontTypeface* Create(IDWriteFontFace* fontFace,
483 IDWriteFontFamily* fontFamily,
484 StreamFontFileLoader* fontFileLoader = NULL,
485 IDWriteFontCollectionLoader* fontCollectionLoader = NULL) {
486 SkTypeface::Style style = get_style(font);
487 SkFontID fontID = SkTypefaceCache::NewFontID();
488 return SkNEW_ARGS(DWriteFontTypeface, (style, fontID,
489 fontFace, font, fontFamily,
490 fontFileLoader, fontCollectionLoader));
494 virtual void weak_dispose() const SK_OVERRIDE {
495 if (fDWriteFontCollectionLoader.get() == NULL) return;
497 IDWriteFactory* factory = sk_get_dwrite_factory();
498 SkASSERT(factory != NULL);
499 HRV(factory->UnregisterFontCollectionLoader(fDWriteFontCollectionLoader.get()));
500 HRV(factory->UnregisterFontFileLoader(fDWriteFontFileLoader.get()));
502 //SkTypefaceCache::Remove(this);
503 INHERITED::weak_dispose();
506 virtual SkStream* onOpenStream(int* ttcIndex) const SK_OVERRIDE;
507 virtual SkScalerContext* onCreateScalerContext(const SkDescriptor*) const SK_OVERRIDE;
508 virtual void onFilterRec(SkScalerContextRec*) const SK_OVERRIDE;
509 virtual SkAdvancedTypefaceMetrics* onGetAdvancedTypefaceMetrics(
510 SkAdvancedTypefaceMetrics::PerGlyphInfo,
511 const uint32_t*, uint32_t) const SK_OVERRIDE;
512 virtual void onGetFontDescriptor(SkFontDescriptor*, bool*) const SK_OVERRIDE;
513 virtual int onCharsToGlyphs(const void* chars, Encoding encoding,
514 uint16_t glyphs[], int glyphCount) const SK_OVERRIDE;
515 virtual int onCountGlyphs() const SK_OVERRIDE;
516 virtual int onGetUPEM() const SK_OVERRIDE;
517 virtual SkTypeface::LocalizedStrings* onCreateFamilyNameIterator() const SK_OVERRIDE;
518 virtual int onGetTableTags(SkFontTableTag tags[]) const SK_OVERRIDE;
519 virtual size_t onGetTableData(SkFontTableTag, size_t offset,
520 size_t length, void* data) const SK_OVERRIDE;
523 typedef SkTypeface INHERITED;
526 class SkScalerContext_DW : public SkScalerContext {
528 SkScalerContext_DW(DWriteFontTypeface*, const SkDescriptor* desc);
529 virtual ~SkScalerContext_DW();
532 virtual unsigned generateGlyphCount() SK_OVERRIDE;
533 virtual uint16_t generateCharToGlyph(SkUnichar uni) SK_OVERRIDE;
534 virtual void generateAdvance(SkGlyph* glyph) SK_OVERRIDE;
535 virtual void generateMetrics(SkGlyph* glyph) SK_OVERRIDE;
536 virtual void generateImage(const SkGlyph& glyph) SK_OVERRIDE;
537 virtual void generatePath(const SkGlyph& glyph, SkPath* path) SK_OVERRIDE;
538 virtual void generateFontMetrics(SkPaint::FontMetrics* mX,
539 SkPaint::FontMetrics* mY) SK_OVERRIDE;
542 DWriteOffscreen fOffscreen;
543 DWRITE_MATRIX fXform;
544 SkAutoTUnref<DWriteFontTypeface> fTypeface;
548 static bool are_same(IUnknown* a, IUnknown* b) {
549 SkTScopedComPtr<IUnknown> iunkA;
550 if (FAILED(a->QueryInterface(&iunkA))) {
554 SkTScopedComPtr<IUnknown> iunkB;
555 if (FAILED(b->QueryInterface(&iunkB))) {
559 return iunkA.get() == iunkB.get();
561 static bool FindByDWriteFont(SkTypeface* face, SkTypeface::Style requestedStyle, void* ctx) {
562 //Check to see if the two fonts are identical.
563 DWriteFontTypeface* dwFace = reinterpret_cast<DWriteFontTypeface*>(face);
564 IDWriteFont* dwFont = reinterpret_cast<IDWriteFont*>(ctx);
565 if (are_same(dwFace->fDWriteFont.get(), dwFont)) {
569 //Check if the two fonts share the same loader and have the same key.
570 SkTScopedComPtr<IDWriteFontFace> dwFaceFontFace;
571 SkTScopedComPtr<IDWriteFontFace> dwFontFace;
572 HRB(dwFace->fDWriteFont->CreateFontFace(&dwFaceFontFace));
573 HRB(dwFont->CreateFontFace(&dwFontFace));
574 if (are_same(dwFaceFontFace.get(), dwFontFace.get())) {
578 UINT32 dwFaceNumFiles;
580 HRB(dwFaceFontFace->GetFiles(&dwFaceNumFiles, NULL));
581 HRB(dwFontFace->GetFiles(&dwNumFiles, NULL));
582 if (dwFaceNumFiles != dwNumFiles) {
586 SkTScopedComPtr<IDWriteFontFile> dwFaceFontFile;
587 SkTScopedComPtr<IDWriteFontFile> dwFontFile;
588 HRB(dwFaceFontFace->GetFiles(&dwFaceNumFiles, &dwFaceFontFile));
589 HRB(dwFontFace->GetFiles(&dwNumFiles, &dwFontFile));
591 //for (each file) { //we currently only admit fonts from one file.
592 SkTScopedComPtr<IDWriteFontFileLoader> dwFaceFontFileLoader;
593 SkTScopedComPtr<IDWriteFontFileLoader> dwFontFileLoader;
594 HRB(dwFaceFontFile->GetLoader(&dwFaceFontFileLoader));
595 HRB(dwFontFile->GetLoader(&dwFontFileLoader));
596 if (!are_same(dwFaceFontFileLoader.get(), dwFontFileLoader.get())) {
601 const void* dwFaceFontRefKey;
602 UINT32 dwFaceFontRefKeySize;
603 const void* dwFontRefKey;
604 UINT32 dwFontRefKeySize;
605 HRB(dwFaceFontFile->GetReferenceKey(&dwFaceFontRefKey, &dwFaceFontRefKeySize));
606 HRB(dwFontFile->GetReferenceKey(&dwFontRefKey, &dwFontRefKeySize));
607 if (dwFaceFontRefKeySize != dwFontRefKeySize) {
610 if (0 != memcmp(dwFaceFontRefKey, dwFontRefKey, dwFontRefKeySize)) {
614 //TODO: better means than comparing name strings?
615 //NOTE: .tfc and fake bold/italic will end up here.
616 SkTScopedComPtr<IDWriteFontFamily> dwFaceFontFamily;
617 SkTScopedComPtr<IDWriteFontFamily> dwFontFamily;
618 HRB(dwFace->fDWriteFont->GetFontFamily(&dwFaceFontFamily));
619 HRB(dwFont->GetFontFamily(&dwFontFamily));
621 SkTScopedComPtr<IDWriteLocalizedStrings> dwFaceFontFamilyNames;
622 SkTScopedComPtr<IDWriteLocalizedStrings> dwFaceFontNames;
623 HRB(dwFaceFontFamily->GetFamilyNames(&dwFaceFontFamilyNames));
624 HRB(dwFace->fDWriteFont->GetFaceNames(&dwFaceFontNames));
626 SkTScopedComPtr<IDWriteLocalizedStrings> dwFontFamilyNames;
627 SkTScopedComPtr<IDWriteLocalizedStrings> dwFontNames;
628 HRB(dwFontFamily->GetFamilyNames(&dwFontFamilyNames));
629 HRB(dwFont->GetFaceNames(&dwFontNames));
631 UINT32 dwFaceFontFamilyNameLength;
632 UINT32 dwFaceFontNameLength;
633 HRB(dwFaceFontFamilyNames->GetStringLength(0, &dwFaceFontFamilyNameLength));
634 HRB(dwFaceFontNames->GetStringLength(0, &dwFaceFontNameLength));
636 UINT32 dwFontFamilyNameLength;
637 UINT32 dwFontNameLength;
638 HRB(dwFontFamilyNames->GetStringLength(0, &dwFontFamilyNameLength));
639 HRB(dwFontNames->GetStringLength(0, &dwFontNameLength));
641 if (dwFaceFontFamilyNameLength != dwFontFamilyNameLength ||
642 dwFaceFontNameLength != dwFontNameLength)
647 SkSMallocWCHAR dwFaceFontFamilyNameChar(dwFaceFontFamilyNameLength+1);
648 SkSMallocWCHAR dwFaceFontNameChar(dwFaceFontNameLength+1);
649 HRB(dwFaceFontFamilyNames->GetString(0, dwFaceFontFamilyNameChar.get(), dwFaceFontFamilyNameLength+1));
650 HRB(dwFaceFontNames->GetString(0, dwFaceFontNameChar.get(), dwFaceFontNameLength+1));
652 SkSMallocWCHAR dwFontFamilyNameChar(dwFontFamilyNameLength+1);
653 SkSMallocWCHAR dwFontNameChar(dwFontNameLength+1);
654 HRB(dwFontFamilyNames->GetString(0, dwFontFamilyNameChar.get(), dwFontFamilyNameLength+1));
655 HRB(dwFontNames->GetString(0, dwFontNameChar.get(), dwFontNameLength+1));
657 return wcscmp(dwFaceFontFamilyNameChar.get(), dwFontFamilyNameChar.get()) == 0 &&
658 wcscmp(dwFaceFontNameChar.get(), dwFontNameChar.get()) == 0;
661 SkScalerContext_DW::SkScalerContext_DW(DWriteFontTypeface* typeface,
662 const SkDescriptor* desc)
663 : SkScalerContext(typeface, desc)
664 , fTypeface(SkRef(typeface))
667 fXform.m11 = SkScalarToFloat(fRec.fPost2x2[0][0]);
668 fXform.m12 = SkScalarToFloat(fRec.fPost2x2[1][0]);
669 fXform.m21 = SkScalarToFloat(fRec.fPost2x2[0][1]);
670 fXform.m22 = SkScalarToFloat(fRec.fPost2x2[1][1]);
674 fOffscreen.init(fTypeface->fDWriteFontFace.get(), fXform, SkScalarToFloat(fRec.fTextSize));
677 SkScalerContext_DW::~SkScalerContext_DW() {
680 unsigned SkScalerContext_DW::generateGlyphCount() {
681 if (fGlyphCount < 0) {
682 fGlyphCount = fTypeface->fDWriteFontFace->GetGlyphCount();
687 uint16_t SkScalerContext_DW::generateCharToGlyph(SkUnichar uni) {
689 fTypeface->fDWriteFontFace->GetGlyphIndices(reinterpret_cast<UINT32*>(&uni), 1, &index);
693 void SkScalerContext_DW::generateAdvance(SkGlyph* glyph) {
694 //Delta is the difference between the right/left side bearing metric
695 //and where the right/left side bearing ends up after hinting.
696 //DirectWrite does not provide this information.
697 glyph->fRsbDelta = 0;
698 glyph->fLsbDelta = 0;
700 glyph->fAdvanceX = 0;
701 glyph->fAdvanceY = 0;
703 uint16_t glyphId = glyph->getGlyphID();
704 DWRITE_GLYPH_METRICS gm;
705 HRVM(fTypeface->fDWriteFontFace->GetDesignGlyphMetrics(&glyphId, 1, &gm),
706 "Could not get design metrics.");
708 DWRITE_FONT_METRICS dwfm;
709 fTypeface->fDWriteFontFace->GetMetrics(&dwfm);
711 SkScalar advanceX = SkScalarMulDiv(fRec.fTextSize,
712 SkIntToScalar(gm.advanceWidth),
713 SkIntToScalar(dwfm.designUnitsPerEm));
715 if (!(fRec.fFlags & kSubpixelPositioning_Flag)) {
716 advanceX = SkScalarRoundToScalar(advanceX);
719 SkVector vecs[1] = { { advanceX, 0 } };
721 fRec.getMatrixFrom2x2(&mat);
722 mat.mapVectors(vecs, SK_ARRAY_COUNT(vecs));
724 glyph->fAdvanceX = SkScalarToFixed(vecs[0].fX);
725 glyph->fAdvanceY = SkScalarToFixed(vecs[0].fY);
728 void SkScalerContext_DW::generateMetrics(SkGlyph* glyph) {
731 this->generateAdvance(glyph);
733 //Measure raster size.
734 fXform.dx = SkFixedToFloat(glyph->getSubXFixed());
735 fXform.dy = SkFixedToFloat(glyph->getSubYFixed());
739 UINT16 glyphId = glyph->getGlyphID();
741 DWRITE_GLYPH_OFFSET offset;
742 offset.advanceOffset = 0.0f;
743 offset.ascenderOffset = 0.0f;
745 DWRITE_GLYPH_RUN run;
747 run.glyphAdvances = &advance;
748 run.fontFace = fTypeface->fDWriteFontFace.get();
749 run.fontEmSize = SkScalarToFloat(fRec.fTextSize);
751 run.glyphIndices = &glyphId;
752 run.isSideways = FALSE;
753 run.glyphOffsets = &offset;
755 IDWriteFactory* factory = sk_get_dwrite_factory();
756 SkASSERT(factory != NULL);
758 const bool isBW = SkMask::kBW_Format == fRec.fMaskFormat;
759 DWRITE_RENDERING_MODE renderingMode;
760 DWRITE_TEXTURE_TYPE textureType;
762 renderingMode = DWRITE_RENDERING_MODE_ALIASED;
763 textureType = DWRITE_TEXTURE_ALIASED_1x1;
765 renderingMode = DWRITE_RENDERING_MODE_CLEARTYPE_NATURAL_SYMMETRIC;
766 textureType = DWRITE_TEXTURE_CLEARTYPE_3x1;
769 SkTScopedComPtr<IDWriteGlyphRunAnalysis> glyphRunAnalysis;
770 HRVM(factory->CreateGlyphRunAnalysis(&run,
771 1.0f, // pixelsPerDip,
774 DWRITE_MEASURING_MODE_NATURAL,
775 0.0f, // baselineOriginX,
776 0.0f, // baselineOriginY,
778 "Could not create glyph run analysis.");
781 HRVM(glyphRunAnalysis->GetAlphaTextureBounds(textureType, &bbox),
782 "Could not get texture bounds.");
784 glyph->fWidth = SkToU16(bbox.right - bbox.left);
785 glyph->fHeight = SkToU16(bbox.bottom - bbox.top);
786 glyph->fLeft = SkToS16(bbox.left);
787 glyph->fTop = SkToS16(bbox.top);
790 void SkScalerContext_DW::generateFontMetrics(SkPaint::FontMetrics* mx,
791 SkPaint::FontMetrics* my) {
796 sk_bzero(mx, sizeof(*mx));
799 sk_bzero(my, sizeof(*my));
802 DWRITE_FONT_METRICS dwfm;
803 fTypeface->fDWriteFontFace->GetMetrics(&dwfm);
805 SkScalar upem = SkIntToScalar(dwfm.designUnitsPerEm);
807 mx->fTop = -fRec.fTextSize * SkIntToScalar(dwfm.ascent) / upem;
808 mx->fAscent = mx->fTop;
809 mx->fDescent = fRec.fTextSize * SkIntToScalar(dwfm.descent) / upem;
810 mx->fBottom = mx->fDescent;
811 mx->fLeading = fRec.fTextSize * SkIntToScalar(dwfm.lineGap) / upem;
812 mx->fXHeight = fRec.fTextSize * SkIntToScalar(dwfm.xHeight) / upem;
813 mx->fUnderlineThickness = fRec.fTextSize * SkIntToScalar(dwfm.underlinePosition) / upem;
814 mx->fUnderlinePosition = -(fRec.fTextSize * SkIntToScalar(dwfm.underlineThickness) / upem);
816 mx->fFlags |= SkPaint::FontMetrics::kUnderlineThinknessIsValid_Flag;
817 mx->fFlags |= SkPaint::FontMetrics::kUnderlinePositionIsValid_Flag;
821 my->fTop = -fRec.fTextSize * SkIntToScalar(dwfm.ascent) / upem;
822 my->fAscent = my->fTop;
823 my->fDescent = fRec.fTextSize * SkIntToScalar(dwfm.descent) / upem;
824 my->fBottom = my->fDescent;
825 my->fLeading = fRec.fTextSize * SkIntToScalar(dwfm.lineGap) / upem;
826 my->fXHeight = fRec.fTextSize * SkIntToScalar(dwfm.xHeight) / upem;
827 my->fUnderlineThickness = fRec.fTextSize * SkIntToScalar(dwfm.underlinePosition) / upem;
828 my->fUnderlinePosition = -(fRec.fTextSize * SkIntToScalar(dwfm.underlineThickness) / upem);
830 my->fFlags |= SkPaint::FontMetrics::kUnderlineThinknessIsValid_Flag;
831 my->fFlags |= SkPaint::FontMetrics::kUnderlinePositionIsValid_Flag;
835 ///////////////////////////////////////////////////////////////////////////////
837 #include "SkColorPriv.h"
839 static void bilevel_to_bw(const uint8_t* SK_RESTRICT src, const SkGlyph& glyph) {
840 const int width = glyph.fWidth;
841 const size_t dstRB = (width + 7) >> 3;
842 uint8_t* SK_RESTRICT dst = static_cast<uint8_t*>(glyph.fImage);
844 int byteCount = width >> 3;
845 int bitCount = width & 7;
847 for (int y = 0; y < glyph.fHeight; ++y) {
849 for (int i = 0; i < byteCount; ++i) {
851 byte |= src[0] & (1 << 7);
852 byte |= src[1] & (1 << 6);
853 byte |= src[2] & (1 << 5);
854 byte |= src[3] & (1 << 4);
855 byte |= src[4] & (1 << 3);
856 byte |= src[5] & (1 << 2);
857 byte |= src[6] & (1 << 1);
858 byte |= src[7] & (1 << 0);
865 unsigned mask = 0x80;
866 for (int i = 0; i < bitCount; i++) {
867 byte |= (src[i]) & mask;
870 dst[byteCount] = byte;
877 template<bool APPLY_PREBLEND>
878 static void rgb_to_a8(const uint8_t* SK_RESTRICT src, const SkGlyph& glyph, const uint8_t* table8) {
879 const size_t dstRB = glyph.rowBytes();
880 const U16CPU width = glyph.fWidth;
881 uint8_t* SK_RESTRICT dst = static_cast<uint8_t*>(glyph.fImage);
883 for (U16CPU y = 0; y < glyph.fHeight; y++) {
884 for (U16CPU i = 0; i < width; i++) {
888 dst[i] = sk_apply_lut_if<APPLY_PREBLEND>((r + g + b) / 3, table8);
890 dst = (uint8_t*)((char*)dst + dstRB);
894 template<bool APPLY_PREBLEND>
895 static void rgb_to_lcd16(const uint8_t* SK_RESTRICT src, const SkGlyph& glyph,
896 const uint8_t* tableR, const uint8_t* tableG, const uint8_t* tableB) {
897 const size_t dstRB = glyph.rowBytes();
898 const U16CPU width = glyph.fWidth;
899 uint16_t* SK_RESTRICT dst = static_cast<uint16_t*>(glyph.fImage);
901 for (U16CPU y = 0; y < glyph.fHeight; y++) {
902 for (U16CPU i = 0; i < width; i++) {
903 U8CPU r = sk_apply_lut_if<APPLY_PREBLEND>(*(src++), tableR);
904 U8CPU g = sk_apply_lut_if<APPLY_PREBLEND>(*(src++), tableG);
905 U8CPU b = sk_apply_lut_if<APPLY_PREBLEND>(*(src++), tableB);
906 dst[i] = SkPack888ToRGB16(r, g, b);
908 dst = (uint16_t*)((char*)dst + dstRB);
912 template<bool APPLY_PREBLEND>
913 static void rgb_to_lcd32(const uint8_t* SK_RESTRICT src, const SkGlyph& glyph,
914 const uint8_t* tableR, const uint8_t* tableG, const uint8_t* tableB) {
915 const size_t dstRB = glyph.rowBytes();
916 const U16CPU width = glyph.fWidth;
917 SkPMColor* SK_RESTRICT dst = static_cast<SkPMColor*>(glyph.fImage);
919 for (U16CPU y = 0; y < glyph.fHeight; y++) {
920 for (U16CPU i = 0; i < width; i++) {
921 U8CPU r = sk_apply_lut_if<APPLY_PREBLEND>(*(src++), tableR);
922 U8CPU g = sk_apply_lut_if<APPLY_PREBLEND>(*(src++), tableG);
923 U8CPU b = sk_apply_lut_if<APPLY_PREBLEND>(*(src++), tableB);
924 dst[i] = SkPackARGB32(0xFF, r, g, b);
926 dst = (SkPMColor*)((char*)dst + dstRB);
930 void SkScalerContext_DW::generateImage(const SkGlyph& glyph) {
931 const bool isBW = SkMask::kBW_Format == fRec.fMaskFormat;
932 const bool isAA = !isLCD(fRec);
935 const void* bits = fOffscreen.draw(glyph, isBW);
937 sk_bzero(glyph.fImage, glyph.computeImageSize());
941 //Copy the mask into the glyph.
942 const uint8_t* src = (const uint8_t*)bits;
944 bilevel_to_bw(src, glyph);
946 if (fPreBlend.isApplicable()) {
947 rgb_to_a8<true>(src, glyph, fPreBlend.fG);
949 rgb_to_a8<false>(src, glyph, fPreBlend.fG);
951 } else if (SkMask::kLCD16_Format == glyph.fMaskFormat) {
952 if (fPreBlend.isApplicable()) {
953 rgb_to_lcd16<true>(src, glyph, fPreBlend.fR, fPreBlend.fG, fPreBlend.fB);
955 rgb_to_lcd16<false>(src, glyph, fPreBlend.fR, fPreBlend.fG, fPreBlend.fB);
958 SkASSERT(SkMask::kLCD32_Format == glyph.fMaskFormat);
959 if (fPreBlend.isApplicable()) {
960 rgb_to_lcd32<true>(src, glyph, fPreBlend.fR, fPreBlend.fG, fPreBlend.fB);
962 rgb_to_lcd32<false>(src, glyph, fPreBlend.fR, fPreBlend.fG, fPreBlend.fB);
967 void SkScalerContext_DW::generatePath(const SkGlyph& glyph, SkPath* path) {
968 SkASSERT(&glyph && path);
972 SkTScopedComPtr<IDWriteGeometrySink> geometryToPath;
973 HRVM(SkDWriteGeometrySink::Create(path, &geometryToPath),
974 "Could not create geometry to path converter.");
975 uint16_t glyphId = glyph.getGlyphID();
976 //TODO: convert to<->from DIUs? This would make a difference if hinting.
977 //It may not be needed, it appears that DirectWrite only hints at em size.
978 HRVM(fTypeface->fDWriteFontFace->GetGlyphRunOutline(SkScalarToFloat(fRec.fTextSize),
985 geometryToPath.get()),
986 "Could not create glyph outline.");
989 fRec.getMatrixFrom2x2(&mat);
990 path->transform(mat);
993 void DWriteFontTypeface::onGetFontDescriptor(SkFontDescriptor* desc,
994 bool* isLocalStream) const {
995 // Get the family name.
996 SkTScopedComPtr<IDWriteLocalizedStrings> dwFamilyNames;
997 HRV(fDWriteFontFamily->GetFamilyNames(&dwFamilyNames));
999 UINT32 dwFamilyNamesLength;
1000 HRV(dwFamilyNames->GetStringLength(0, &dwFamilyNamesLength));
1002 SkSMallocWCHAR dwFamilyNameChar(dwFamilyNamesLength+1);
1003 HRV(dwFamilyNames->GetString(0, dwFamilyNameChar.get(), dwFamilyNamesLength+1));
1005 SkString utf8FamilyName;
1006 HRV(sk_wchar_to_skstring(dwFamilyNameChar.get(), &utf8FamilyName));
1008 desc->setFamilyName(utf8FamilyName.c_str());
1009 *isLocalStream = SkToBool(fDWriteFontFileLoader.get());
1012 static SkUnichar next_utf8(const void** chars) {
1013 return SkUTF8_NextUnichar((const char**)chars);
1016 static SkUnichar next_utf16(const void** chars) {
1017 return SkUTF16_NextUnichar((const uint16_t**)chars);
1020 static SkUnichar next_utf32(const void** chars) {
1021 const SkUnichar** uniChars = (const SkUnichar**)chars;
1022 SkUnichar uni = **uniChars;
1027 typedef SkUnichar (*EncodingProc)(const void**);
1029 static EncodingProc find_encoding_proc(SkTypeface::Encoding enc) {
1030 static const EncodingProc gProcs[] = {
1031 next_utf8, next_utf16, next_utf32
1033 SkASSERT((size_t)enc < SK_ARRAY_COUNT(gProcs));
1037 int DWriteFontTypeface::onCharsToGlyphs(const void* chars, Encoding encoding,
1038 uint16_t glyphs[], int glyphCount) const
1040 if (NULL == glyphs) {
1041 EncodingProc next_ucs4_proc = find_encoding_proc(encoding);
1042 for (int i = 0; i < glyphCount; ++i) {
1043 const SkUnichar c = next_ucs4_proc(&chars);
1045 fDWriteFont->HasCharacter(c, &exists);
1054 case SkTypeface::kUTF8_Encoding:
1055 case SkTypeface::kUTF16_Encoding: {
1056 static const int scratchCount = 256;
1057 UINT32 scratch[scratchCount];
1058 EncodingProc next_ucs4_proc = find_encoding_proc(encoding);
1059 for (int baseGlyph = 0; baseGlyph < glyphCount; baseGlyph += scratchCount) {
1060 int glyphsLeft = glyphCount - baseGlyph;
1061 int limit = SkTMin(glyphsLeft, scratchCount);
1062 for (int i = 0; i < limit; ++i) {
1063 scratch[i] = next_ucs4_proc(&chars);
1065 fDWriteFontFace->GetGlyphIndices(scratch, limit, &glyphs[baseGlyph]);
1069 case SkTypeface::kUTF32_Encoding: {
1070 const UINT32* utf32 = reinterpret_cast<const UINT32*>(chars);
1071 fDWriteFontFace->GetGlyphIndices(utf32, glyphCount, glyphs);
1078 for (int i = 0; i < glyphCount; ++i) {
1079 if (0 == glyphs[i]) {
1086 int DWriteFontTypeface::onCountGlyphs() const {
1087 return fDWriteFontFace->GetGlyphCount();
1090 int DWriteFontTypeface::onGetUPEM() const {
1091 DWRITE_FONT_METRICS metrics;
1092 fDWriteFontFace->GetMetrics(&metrics);
1093 return metrics.designUnitsPerEm;
1096 class LocalizedStrings_IDWriteLocalizedStrings : public SkTypeface::LocalizedStrings {
1098 /** Takes ownership of the IDWriteLocalizedStrings. */
1099 explicit LocalizedStrings_IDWriteLocalizedStrings(IDWriteLocalizedStrings* strings)
1100 : fIndex(0), fStrings(strings)
1103 virtual bool next(SkTypeface::LocalizedString* localizedString) SK_OVERRIDE {
1104 if (fIndex >= fStrings->GetCount()) {
1109 UINT32 stringLength;
1110 HRBM(fStrings->GetStringLength(fIndex, &stringLength), "Could not get string length.");
1113 SkSMallocWCHAR wString(stringLength);
1114 HRBM(fStrings->GetString(fIndex, wString.get(), stringLength), "Could not get string.");
1116 HRB(sk_wchar_to_skstring(wString.get(), &localizedString->fString));
1119 UINT32 localeLength;
1120 HRBM(fStrings->GetLocaleNameLength(fIndex, &localeLength), "Could not get locale length.");
1123 SkSMallocWCHAR wLocale(localeLength);
1124 HRBM(fStrings->GetLocaleName(fIndex, wLocale.get(), localeLength), "Could not get locale.");
1126 HRB(sk_wchar_to_skstring(wLocale.get(), &localizedString->fLanguage));
1134 SkTScopedComPtr<IDWriteLocalizedStrings> fStrings;
1137 SkTypeface::LocalizedStrings* DWriteFontTypeface::onCreateFamilyNameIterator() const {
1138 SkTScopedComPtr<IDWriteLocalizedStrings> familyNames;
1139 HRNM(fDWriteFontFamily->GetFamilyNames(&familyNames), "Could not obtain family names.");
1141 return new LocalizedStrings_IDWriteLocalizedStrings(familyNames.release());
1144 int DWriteFontTypeface::onGetTableTags(SkFontTableTag tags[]) const {
1145 DWRITE_FONT_FACE_TYPE type = fDWriteFontFace->GetType();
1146 if (type != DWRITE_FONT_FACE_TYPE_CFF &&
1147 type != DWRITE_FONT_FACE_TYPE_TRUETYPE &&
1148 type != DWRITE_FONT_FACE_TYPE_TRUETYPE_COLLECTION)
1154 SkAutoTUnref<SkStream> stream(this->openStream(&ttcIndex));
1155 return stream.get() ? SkFontStream::GetTableTags(stream, ttcIndex, tags) : 0;
1158 class AutoDWriteTable {
1160 AutoDWriteTable(IDWriteFontFace* fontFace, UINT32 beTag) : fFontFace(fontFace), fExists(FALSE) {
1161 // Any errors are ignored, user must check fExists anyway.
1162 fontFace->TryGetFontTable(beTag,
1163 reinterpret_cast<const void **>(&fData), &fSize, &fLock, &fExists);
1165 ~AutoDWriteTable() {
1167 fFontFace->ReleaseFontTable(fLock);
1171 const uint8_t* fData;
1175 // Borrowed reference, the user must ensure the fontFace stays alive.
1176 IDWriteFontFace* fFontFace;
1180 size_t DWriteFontTypeface::onGetTableData(SkFontTableTag tag, size_t offset,
1181 size_t length, void* data) const
1183 AutoDWriteTable table(fDWriteFontFace.get(), SkEndian_SwapBE32(tag));
1184 if (!table.fExists) {
1188 if (offset > table.fSize) {
1191 size_t size = SkTMin(length, table.fSize - offset);
1193 memcpy(data, table.fData + offset, size);
1199 template <typename T> class SkAutoIDWriteUnregister {
1201 SkAutoIDWriteUnregister(IDWriteFactory* factory, T* unregister)
1202 : fFactory(factory), fUnregister(unregister)
1205 ~SkAutoIDWriteUnregister() {
1207 unregister(fFactory, fUnregister);
1212 T* old = fUnregister;
1218 HRESULT unregister(IDWriteFactory* factory, IDWriteFontFileLoader* unregister) {
1219 return factory->UnregisterFontFileLoader(unregister);
1222 HRESULT unregister(IDWriteFactory* factory, IDWriteFontCollectionLoader* unregister) {
1223 return factory->UnregisterFontCollectionLoader(unregister);
1226 IDWriteFactory* fFactory;
1230 static SkTypeface* create_from_stream(SkStream* stream, int ttcIndex) {
1231 IDWriteFactory* factory = sk_get_dwrite_factory();
1232 if (NULL == factory) {
1236 SkTScopedComPtr<StreamFontFileLoader> fontFileLoader;
1237 HRN(StreamFontFileLoader::Create(stream, &fontFileLoader));
1238 HRN(factory->RegisterFontFileLoader(fontFileLoader.get()));
1239 SkAutoIDWriteUnregister<StreamFontFileLoader> autoUnregisterFontFileLoader(
1240 factory, fontFileLoader.get());
1242 SkTScopedComPtr<StreamFontCollectionLoader> fontCollectionLoader;
1243 HRN(StreamFontCollectionLoader::Create(fontFileLoader.get(), &fontCollectionLoader));
1244 HRN(factory->RegisterFontCollectionLoader(fontCollectionLoader.get()));
1245 SkAutoIDWriteUnregister<StreamFontCollectionLoader> autoUnregisterFontCollectionLoader(
1246 factory, fontCollectionLoader.get());
1248 SkTScopedComPtr<IDWriteFontCollection> fontCollection;
1249 HRN(factory->CreateCustomFontCollection(fontCollectionLoader.get(), NULL, 0, &fontCollection));
1251 // Find the first non-simulated font which has the given ttc index.
1252 UINT32 familyCount = fontCollection->GetFontFamilyCount();
1253 for (UINT32 familyIndex = 0; familyIndex < familyCount; ++familyIndex) {
1254 SkTScopedComPtr<IDWriteFontFamily> fontFamily;
1255 HRN(fontCollection->GetFontFamily(familyIndex, &fontFamily));
1257 UINT32 fontCount = fontFamily->GetFontCount();
1258 for (UINT32 fontIndex = 0; fontIndex < fontCount; ++fontIndex) {
1259 SkTScopedComPtr<IDWriteFont> font;
1260 HRN(fontFamily->GetFont(fontIndex, &font));
1261 if (font->GetSimulations() != DWRITE_FONT_SIMULATIONS_NONE) {
1265 SkTScopedComPtr<IDWriteFontFace> fontFace;
1266 HRN(font->CreateFontFace(&fontFace));
1268 UINT32 faceIndex = fontFace->GetIndex();
1269 if (faceIndex == ttcIndex) {
1270 return DWriteFontTypeface::Create(fontFace.get(), font.get(), fontFamily.get(),
1271 autoUnregisterFontFileLoader.detatch(),
1272 autoUnregisterFontCollectionLoader.detatch());
1280 SkStream* DWriteFontTypeface::onOpenStream(int* ttcIndex) const {
1281 *ttcIndex = fDWriteFontFace->GetIndex();
1284 HRNM(fDWriteFontFace->GetFiles(&numFiles, NULL),
1285 "Could not get number of font files.");
1286 if (numFiles != 1) {
1290 SkTScopedComPtr<IDWriteFontFile> fontFile;
1291 HRNM(fDWriteFontFace->GetFiles(&numFiles, &fontFile), "Could not get font files.");
1293 const void* fontFileKey;
1294 UINT32 fontFileKeySize;
1295 HRNM(fontFile->GetReferenceKey(&fontFileKey, &fontFileKeySize),
1296 "Could not get font file reference key.");
1298 SkTScopedComPtr<IDWriteFontFileLoader> fontFileLoader;
1299 HRNM(fontFile->GetLoader(&fontFileLoader), "Could not get font file loader.");
1301 SkTScopedComPtr<IDWriteFontFileStream> fontFileStream;
1302 HRNM(fontFileLoader->CreateStreamFromKey(fontFileKey, fontFileKeySize,
1304 "Could not create font file stream.");
1306 return SkNEW_ARGS(SkDWriteFontFileStream, (fontFileStream.get()));
1309 SkScalerContext* DWriteFontTypeface::onCreateScalerContext(const SkDescriptor* desc) const {
1310 return SkNEW_ARGS(SkScalerContext_DW, (const_cast<DWriteFontTypeface*>(this), desc));
1313 void DWriteFontTypeface::onFilterRec(SkScalerContext::Rec* rec) const {
1314 if (rec->fFlags & SkScalerContext::kLCD_BGROrder_Flag ||
1315 rec->fFlags & SkScalerContext::kLCD_Vertical_Flag)
1317 rec->fMaskFormat = SkMask::kA8_Format;
1320 unsigned flagsWeDontSupport = SkScalerContext::kDevKernText_Flag |
1321 SkScalerContext::kForceAutohinting_Flag |
1322 SkScalerContext::kEmbeddedBitmapText_Flag |
1323 SkScalerContext::kEmbolden_Flag |
1324 SkScalerContext::kLCD_BGROrder_Flag |
1325 SkScalerContext::kLCD_Vertical_Flag;
1326 rec->fFlags &= ~flagsWeDontSupport;
1328 SkPaint::Hinting h = rec->getHinting();
1329 // DirectWrite does not provide for hinting hints.
1330 h = SkPaint::kSlight_Hinting;
1333 #if SK_FONT_HOST_USE_SYSTEM_SETTINGS
1334 IDWriteFactory* factory = get_dwrite_factory();
1335 if (factory != NULL) {
1336 SkTScopedComPtr<IDWriteRenderingParams> defaultRenderingParams;
1337 if (SUCCEEDED(factory->CreateRenderingParams(&defaultRenderingParams))) {
1338 float gamma = defaultRenderingParams->GetGamma();
1339 rec->setDeviceGamma(gamma);
1340 rec->setPaintGamma(gamma);
1342 rec->setContrast(defaultRenderingParams->GetEnhancedContrast());
1348 ///////////////////////////////////////////////////////////////////////////////
1351 using namespace skia_advanced_typeface_metrics_utils;
1353 // Construct Glyph to Unicode table.
1354 // Unicode code points that require conjugate pairs in utf16 are not
1356 // TODO(arthurhsu): Add support for conjugate pairs. It looks like that may
1357 // require parsing the TTF cmap table (platform 4, encoding 12) directly instead
1358 // of calling GetFontUnicodeRange().
1359 // TODO(bungeman): This never does what anyone wants.
1360 // What is really wanted is the text to glyphs mapping
1361 static void populate_glyph_to_unicode(IDWriteFontFace* fontFace,
1362 const unsigned glyphCount,
1363 SkTDArray<SkUnichar>* glyphToUnicode) {
1366 //Do this like free type instead
1368 for (UINT32 c = 0; c < 0x10FFFF; ++c) {
1370 hr = fontFace->GetGlyphIndices(&c, 1, &glyph);
1376 SkAutoTArray<UINT32> chars(count);
1378 for (UINT32 c = 0; c < 0x10FFFF; ++c) {
1380 hr = fontFace->GetGlyphIndices(&c, 1, &glyph);
1387 SkAutoTArray<UINT16> glyph(count);
1388 fontFace->GetGlyphIndices(chars.get(), count, glyph.get());
1390 USHORT maxGlyph = 0;
1391 for (USHORT j = 0; j < count; ++j) {
1392 if (glyph[j] > maxGlyph) maxGlyph = glyph[j];
1395 glyphToUnicode->setCount(maxGlyph+1);
1396 for (USHORT j = 0; j < maxGlyph+1u; ++j) {
1397 (*glyphToUnicode)[j] = 0;
1401 for (USHORT j = 0; j < count; ++j) {
1402 if (glyph[j] < glyphCount && (*glyphToUnicode)[glyph[j]] == 0) {
1403 (*glyphToUnicode)[glyph[j]] = chars[j];
1408 static bool getWidthAdvance(IDWriteFontFace* fontFace, int gId, int16_t* advance) {
1411 UINT16 glyphId = gId;
1412 DWRITE_GLYPH_METRICS gm;
1413 HRESULT hr = fontFace->GetDesignGlyphMetrics(&glyphId, 1, &gm);
1420 *advance = gm.advanceWidth;
1424 template<typename T> class AutoTDWriteTable : public AutoDWriteTable {
1426 static const UINT32 tag = DWRITE_MAKE_OPENTYPE_TAG(T::TAG0, T::TAG1, T::TAG2, T::TAG3);
1427 AutoTDWriteTable(IDWriteFontFace* fontFace) : AutoDWriteTable(fontFace, tag) { }
1429 const T* operator->() const { return reinterpret_cast<const T*>(fData); }
1432 SkAdvancedTypefaceMetrics* DWriteFontTypeface::onGetAdvancedTypefaceMetrics(
1433 SkAdvancedTypefaceMetrics::PerGlyphInfo perGlyphInfo,
1434 const uint32_t* glyphIDs,
1435 uint32_t glyphIDsCount) const {
1437 SkAdvancedTypefaceMetrics* info = NULL;
1441 const unsigned glyphCount = fDWriteFontFace->GetGlyphCount();
1443 DWRITE_FONT_METRICS dwfm;
1444 fDWriteFontFace->GetMetrics(&dwfm);
1446 info = new SkAdvancedTypefaceMetrics;
1447 info->fEmSize = dwfm.designUnitsPerEm;
1448 info->fMultiMaster = false;
1449 info->fLastGlyphID = SkToU16(glyphCount - 1);
1453 SkTScopedComPtr<IDWriteLocalizedStrings> familyNames;
1454 SkTScopedComPtr<IDWriteLocalizedStrings> faceNames;
1455 hr = fDWriteFontFamily->GetFamilyNames(&familyNames);
1456 hr = fDWriteFont->GetFaceNames(&faceNames);
1458 UINT32 familyNameLength;
1459 hr = familyNames->GetStringLength(0, &familyNameLength);
1461 UINT32 faceNameLength;
1462 hr = faceNames->GetStringLength(0, &faceNameLength);
1464 UINT32 size = familyNameLength+1+faceNameLength+1;
1465 SkSMallocWCHAR wFamilyName(size);
1466 hr = familyNames->GetString(0, wFamilyName.get(), size);
1467 wFamilyName[familyNameLength] = L' ';
1468 hr = faceNames->GetString(0, &wFamilyName[familyNameLength+1], size - faceNameLength + 1);
1470 hr = sk_wchar_to_skstring(wFamilyName.get(), &info->fFontName);
1472 if (perGlyphInfo & SkAdvancedTypefaceMetrics::kToUnicode_PerGlyphInfo) {
1473 populate_glyph_to_unicode(fDWriteFontFace.get(), glyphCount, &(info->fGlyphToUnicode));
1476 DWRITE_FONT_FACE_TYPE fontType = fDWriteFontFace->GetType();
1477 if (fontType == DWRITE_FONT_FACE_TYPE_TRUETYPE ||
1478 fontType == DWRITE_FONT_FACE_TYPE_TRUETYPE_COLLECTION) {
1479 info->fType = SkAdvancedTypefaceMetrics::kTrueType_Font;
1481 info->fType = SkAdvancedTypefaceMetrics::kOther_Font;
1482 info->fItalicAngle = 0;
1483 info->fAscent = dwfm.ascent;;
1484 info->fDescent = dwfm.descent;
1486 info->fCapHeight = dwfm.capHeight;
1487 info->fBBox = SkIRect::MakeEmpty();
1491 AutoTDWriteTable<SkOTTableHead> headTable(fDWriteFontFace.get());
1492 AutoTDWriteTable<SkOTTablePostScript> postTable(fDWriteFontFace.get());
1493 AutoTDWriteTable<SkOTTableHorizontalHeader> hheaTable(fDWriteFontFace.get());
1494 AutoTDWriteTable<SkOTTableOS2> os2Table(fDWriteFontFace.get());
1495 if (!headTable.fExists || !postTable.fExists || !hheaTable.fExists || !os2Table.fExists) {
1496 info->fItalicAngle = 0;
1497 info->fAscent = dwfm.ascent;;
1498 info->fDescent = dwfm.descent;
1500 info->fCapHeight = dwfm.capHeight;
1501 info->fBBox = SkIRect::MakeEmpty();
1505 //There exist CJK fonts which set the IsFixedPitch and Monospace bits,
1506 //but have full width, latin half-width, and half-width kana.
1507 bool fixedWidth = (postTable->isFixedPitch &&
1508 (1 == SkEndian_SwapBE16(hheaTable->numberOfHMetrics)));
1511 info->fStyle |= SkAdvancedTypefaceMetrics::kFixedPitch_Style;
1514 if (os2Table->version.v0.fsSelection.field.Italic) {
1515 info->fStyle |= SkAdvancedTypefaceMetrics::kItalic_Style;
1518 if (SkPanose::FamilyType::Script == os2Table->version.v0.panose.bFamilyType.value) {
1519 info->fStyle |= SkAdvancedTypefaceMetrics::kScript_Style;
1521 } else if (SkPanose::FamilyType::TextAndDisplay == os2Table->version.v0.panose.bFamilyType.value &&
1522 SkPanose::Data::TextAndDisplay::SerifStyle::Triangle <= os2Table->version.v0.panose.data.textAndDisplay.bSerifStyle.value &&
1523 SkPanose::Data::TextAndDisplay::SerifStyle::NoFit != os2Table->version.v0.panose.data.textAndDisplay.bSerifStyle.value) {
1524 info->fStyle |= SkAdvancedTypefaceMetrics::kSerif_Style;
1527 info->fItalicAngle = SkEndian_SwapBE32(postTable->italicAngle) >> 16;
1529 info->fAscent = SkToS16(dwfm.ascent);
1530 info->fDescent = SkToS16(dwfm.descent);
1531 info->fCapHeight = SkToS16(dwfm.capHeight);
1533 info->fBBox = SkIRect::MakeLTRB((int32_t)SkEndian_SwapBE16((uint16_t)headTable->xMin),
1534 (int32_t)SkEndian_SwapBE16((uint16_t)headTable->yMax),
1535 (int32_t)SkEndian_SwapBE16((uint16_t)headTable->xMax),
1536 (int32_t)SkEndian_SwapBE16((uint16_t)headTable->yMin));
1538 //TODO: is this even desired? It seems PDF only wants this value for Type1
1539 //fonts, and we only get here for TrueType fonts.
1542 // Figure out a good guess for StemV - Min width of i, I, !, 1.
1543 // This probably isn't very good with an italic font.
1544 int16_t min_width = SHRT_MAX;
1546 char stem_chars[] = {'i', 'I', '!', '1'};
1547 for (size_t i = 0; i < SK_ARRAY_COUNT(stem_chars); i++) {
1549 if (GetCharABCWidths(hdc, stem_chars[i], stem_chars[i], &abcWidths)) {
1550 int16_t width = abcWidths.abcB;
1551 if (width > 0 && width < min_width) {
1553 info->fStemV = min_width;
1559 // If Restricted, the font may not be embedded in a document.
1560 // If not Restricted, the font can be embedded.
1561 // If PreviewPrint, the embedding is read-only.
1562 if (os2Table->version.v0.fsType.field.Restricted) {
1563 info->fType = SkAdvancedTypefaceMetrics::kNotEmbeddable_Font;
1564 } else if (perGlyphInfo & SkAdvancedTypefaceMetrics::kHAdvance_PerGlyphInfo) {
1566 appendRange(&info->fGlyphWidths, 0);
1568 getWidthAdvance(fDWriteFontFace.get(), 1, &advance);
1569 info->fGlyphWidths->fAdvance.append(1, &advance);
1570 finishRange(info->fGlyphWidths.get(), 0,
1571 SkAdvancedTypefaceMetrics::WidthRange::kDefault);
1573 info->fGlyphWidths.reset(
1574 getAdvanceData(fDWriteFontFace.get(),
1585 ///////////////////////////////////////////////////////////////////////////////
1587 SkTypeface* SkFontMgr_DirectWrite::createTypefaceFromDWriteFont(
1588 IDWriteFontFace* fontFace,
1590 IDWriteFontFamily* fontFamily,
1591 StreamFontFileLoader* fontFileLoader,
1592 IDWriteFontCollectionLoader* fontCollectionLoader) const {
1593 SkTypeface* face = FindByProcAndRef(FindByDWriteFont, font);
1595 face = DWriteFontTypeface::Create(fontFace, font, fontFamily,
1596 fontFileLoader, fontCollectionLoader);
1598 Add(face, get_style(font), fontCollectionLoader != NULL);
1604 int SkFontMgr_DirectWrite::onCountFamilies() const {
1605 return fFontCollection->GetFontFamilyCount();
1608 void SkFontMgr_DirectWrite::onGetFamilyName(int index, SkString* familyName) const {
1609 SkTScopedComPtr<IDWriteFontFamily> fontFamily;
1610 HRVM(fFontCollection->GetFontFamily(index, &fontFamily), "Could not get requested family.");
1612 SkTScopedComPtr<IDWriteLocalizedStrings> familyNames;
1613 HRVM(fontFamily->GetFamilyNames(&familyNames), "Could not get family names.");
1615 sk_get_locale_string(familyNames.get(), fLocaleName.get(), familyName);
1618 SkFontStyleSet* SkFontMgr_DirectWrite::onCreateStyleSet(int index) const {
1619 SkTScopedComPtr<IDWriteFontFamily> fontFamily;
1620 HRNM(fFontCollection->GetFontFamily(index, &fontFamily), "Could not get requested family.");
1622 return SkNEW_ARGS(SkFontStyleSet_DirectWrite, (this, fontFamily.get()));
1625 SkFontStyleSet* SkFontMgr_DirectWrite::onMatchFamily(const char familyName[]) const {
1626 SkSMallocWCHAR dwFamilyName;
1627 HRN(sk_cstring_to_wchar(familyName, &dwFamilyName));
1631 HRNM(fFontCollection->FindFamilyName(dwFamilyName.get(), &index, &exists),
1632 "Failed while finding family by name.");
1637 return this->onCreateStyleSet(index);
1640 SkTypeface* SkFontMgr_DirectWrite::onMatchFamilyStyle(const char familyName[],
1641 const SkFontStyle& fontstyle) const {
1642 SkAutoTUnref<SkFontStyleSet> sset(this->matchFamily(familyName));
1643 return sset->matchStyle(fontstyle);
1646 SkTypeface* SkFontMgr_DirectWrite::onMatchFaceStyle(const SkTypeface* familyMember,
1647 const SkFontStyle& fontstyle) const {
1648 SkString familyName;
1649 SkFontStyleSet_DirectWrite sset(
1650 this, ((DWriteFontTypeface*)familyMember)->fDWriteFontFamily.get()
1652 return sset.matchStyle(fontstyle);
1655 SkTypeface* SkFontMgr_DirectWrite::onCreateFromStream(SkStream* stream, int ttcIndex) const {
1656 return create_from_stream(stream, ttcIndex);
1659 SkTypeface* SkFontMgr_DirectWrite::onCreateFromData(SkData* data, int ttcIndex) const {
1660 SkAutoTUnref<SkStream> stream(SkNEW_ARGS(SkMemoryStream, (data)));
1661 return this->createFromStream(stream, ttcIndex);
1664 SkTypeface* SkFontMgr_DirectWrite::onCreateFromFile(const char path[], int ttcIndex) const {
1665 SkAutoTUnref<SkStream> stream(SkStream::NewFromFile(path));
1666 return this->createFromStream(stream, ttcIndex);
1669 HRESULT SkFontMgr_DirectWrite::getByFamilyName(const WCHAR wideFamilyName[],
1670 IDWriteFontFamily** fontFamily) const {
1673 HR(fFontCollection->FindFamilyName(wideFamilyName, &index, &exists));
1676 HR(fFontCollection->GetFontFamily(index, fontFamily));
1681 HRESULT SkFontMgr_DirectWrite::getDefaultFontFamily(IDWriteFontFamily** fontFamily) const {
1682 NONCLIENTMETRICSW metrics;
1683 metrics.cbSize = sizeof(metrics);
1684 if (0 == SystemParametersInfoW(SPI_GETNONCLIENTMETRICS,
1688 return E_UNEXPECTED;
1690 HRM(this->getByFamilyName(metrics.lfMessageFont.lfFaceName, fontFamily),
1691 "Could not create DWrite font family from LOGFONT.");
1695 SkTypeface* SkFontMgr_DirectWrite::onLegacyCreateTypeface(const char familyName[],
1696 unsigned styleBits) const {
1697 SkTScopedComPtr<IDWriteFontFamily> fontFamily;
1699 SkSMallocWCHAR wideFamilyName;
1700 if (SUCCEEDED(sk_cstring_to_wchar(familyName, &wideFamilyName))) {
1701 this->getByFamilyName(wideFamilyName, &fontFamily);
1705 if (NULL == fontFamily.get()) {
1706 // No family with given name, try default.
1707 HRNM(this->getDefaultFontFamily(&fontFamily), "Could not get default font family.");
1710 if (NULL == fontFamily.get()) {
1711 // Could not obtain the default font.
1712 HRNM(fFontCollection->GetFontFamily(0, &fontFamily),
1713 "Could not get default-default font family.");
1716 SkTScopedComPtr<IDWriteFont> font;
1717 DWRITE_FONT_WEIGHT weight = (styleBits & SkTypeface::kBold)
1718 ? DWRITE_FONT_WEIGHT_BOLD
1719 : DWRITE_FONT_WEIGHT_NORMAL;
1720 DWRITE_FONT_STRETCH stretch = DWRITE_FONT_STRETCH_NORMAL;
1721 DWRITE_FONT_STYLE italic = (styleBits & SkTypeface::kItalic)
1722 ? DWRITE_FONT_STYLE_ITALIC
1723 : DWRITE_FONT_STYLE_NORMAL;
1724 HRNM(fontFamily->GetFirstMatchingFont(weight, stretch, italic, &font),
1725 "Could not get matching font.");
1727 SkTScopedComPtr<IDWriteFontFace> fontFace;
1728 HRNM(font->CreateFontFace(&fontFace), "Could not create font face.");
1730 return this->createTypefaceFromDWriteFont(fontFace.get(), font.get(), fontFamily.get());
1733 ///////////////////////////////////////////////////////////////////////////////
1735 int SkFontStyleSet_DirectWrite::count() {
1736 return fFontFamily->GetFontCount();
1739 SkTypeface* SkFontStyleSet_DirectWrite::createTypeface(int index) {
1740 SkTScopedComPtr<IDWriteFont> font;
1741 HRNM(fFontFamily->GetFont(index, &font), "Could not get font.");
1743 SkTScopedComPtr<IDWriteFontFace> fontFace;
1744 HRNM(font->CreateFontFace(&fontFace), "Could not create font face.");
1746 return fFontMgr->createTypefaceFromDWriteFont(fontFace.get(), font.get(), fFontFamily.get());
1749 void SkFontStyleSet_DirectWrite::getStyle(int index, SkFontStyle* fs, SkString* styleName) {
1750 SkTScopedComPtr<IDWriteFont> font;
1751 HRVM(fFontFamily->GetFont(index, &font), "Could not get font.");
1754 SkFontStyle::Slant slant;
1755 switch (font->GetStyle()) {
1756 case DWRITE_FONT_STYLE_NORMAL:
1757 slant = SkFontStyle::kUpright_Slant;
1759 case DWRITE_FONT_STYLE_OBLIQUE:
1760 case DWRITE_FONT_STYLE_ITALIC:
1761 slant = SkFontStyle::kItalic_Slant;
1767 int weight = font->GetWeight();
1768 int width = font->GetStretch();
1770 *fs = SkFontStyle(weight, width, slant);
1774 SkTScopedComPtr<IDWriteLocalizedStrings> faceNames;
1775 if (SUCCEEDED(font->GetFaceNames(&faceNames))) {
1776 sk_get_locale_string(faceNames.get(), fFontMgr->fLocaleName.get(), styleName);
1781 SkTypeface* SkFontStyleSet_DirectWrite::matchStyle(const SkFontStyle& pattern) {
1782 DWRITE_FONT_STYLE slant;
1783 switch (pattern.slant()) {
1784 case SkFontStyle::kUpright_Slant:
1785 slant = DWRITE_FONT_STYLE_NORMAL;
1787 case SkFontStyle::kItalic_Slant:
1788 slant = DWRITE_FONT_STYLE_ITALIC;
1794 DWRITE_FONT_WEIGHT weight = (DWRITE_FONT_WEIGHT)pattern.weight();
1795 DWRITE_FONT_STRETCH width = (DWRITE_FONT_STRETCH)pattern.width();
1797 SkTScopedComPtr<IDWriteFont> font;
1798 // TODO: perhaps use GetMatchingFonts and get the least simulated?
1799 HRNM(fFontFamily->GetFirstMatchingFont(weight, width, slant, &font),
1800 "Could not match font in family.");
1802 SkTScopedComPtr<IDWriteFontFace> fontFace;
1803 HRNM(font->CreateFontFace(&fontFace), "Could not create font face.");
1805 return fFontMgr->createTypefaceFromDWriteFont(fontFace.get(), font.get(),
1809 ///////////////////////////////////////////////////////////////////////////////
1811 SkFontMgr* SkFontMgr_New_DirectWrite() {
1812 IDWriteFactory* factory = sk_get_dwrite_factory();
1813 if (NULL == factory) {
1817 SkTScopedComPtr<IDWriteFontCollection> sysFontCollection;
1818 HRNM(factory->GetSystemFontCollection(&sysFontCollection, FALSE),
1819 "Could not get system font collection.");
1821 WCHAR localeNameStorage[LOCALE_NAME_MAX_LENGTH];
1822 WCHAR* localeName = NULL;
1823 int localeNameLen = 0;
1825 // Dynamically load GetUserDefaultLocaleName function, as it is not available on XP.
1826 SkGetUserDefaultLocaleNameProc getUserDefaultLocaleNameProc = NULL;
1827 HRESULT hr = SkGetGetUserDefaultLocaleNameProc(&getUserDefaultLocaleNameProc);
1828 if (NULL == getUserDefaultLocaleNameProc) {
1829 SK_TRACEHR(hr, "Could not get GetUserDefaultLocaleName.");
1831 localeNameLen = getUserDefaultLocaleNameProc(localeNameStorage, LOCALE_NAME_MAX_LENGTH);
1832 if (localeNameLen) {
1833 localeName = localeNameStorage;
1837 return SkNEW_ARGS(SkFontMgr_DirectWrite, (sysFontCollection.get(), localeName, localeNameLen));
1840 #include "SkFontMgr_indirect.h"
1841 SkFontMgr* SkFontMgr_New_DirectWriteRenderer(SkRemotableFontMgr* proxy) {
1842 SkAutoTUnref<SkFontMgr> impl(SkFontMgr_New_DirectWrite());
1843 if (impl.get() == NULL) {
1846 return SkNEW_ARGS(SkFontMgr_Indirect, (impl.get(), proxy));