Index: src/ports/SkFontHost_win_dw.cpp |
diff --git a/src/ports/SkFontHost_win_dw.cpp b/src/ports/SkFontHost_win_dw.cpp |
index ea41d862096942749cc3afc5f21d334a36cfde6e..fa21df537c3ee6fbc9619bfd3cfe435c92cb1905 100644 |
--- a/src/ports/SkFontHost_win_dw.cpp |
+++ b/src/ports/SkFontHost_win_dw.cpp |
@@ -8,36 +8,20 @@ |
#include "SkTypes.h" |
#undef GetGlyphIndices |
-#include "SkAdvancedTypefaceMetrics.h" |
-#include "SkColorFilter.h" |
#include "SkDWrite.h" |
-#include "SkDWriteFontFileStream.h" |
#include "SkDWriteGeometrySink.h" |
-#include "SkDescriptor.h" |
#include "SkEndian.h" |
-#include "SkFontDescriptor.h" |
-#include "SkFontHost.h" |
-#include "SkFontMgr.h" |
-#include "SkFontStream.h" |
#include "SkGlyph.h" |
#include "SkHRESULT.h" |
#include "SkMaskGamma.h" |
#include "SkMatrix22.h" |
-#include "SkOnce.h" |
#include "SkOTTable_EBLC.h" |
#include "SkOTTable_EBSC.h" |
-#include "SkOTTable_head.h" |
-#include "SkOTTable_hhea.h" |
-#include "SkOTTable_OS_2.h" |
-#include "SkOTTable_post.h" |
#include "SkPath.h" |
-#include "SkStream.h" |
-#include "SkString.h" |
+#include "SkScalerContext.h" |
+#include "SkScalerContext_win_dw.h" |
#include "SkTScopedComPtr.h" |
-#include "SkThread.h" |
-#include "SkTypeface_win.h" |
-#include "SkTypefaceCache.h" |
-#include "SkUtils.h" |
+#include "SkTypeface_win_dw.h" |
#include <dwrite.h> |
@@ -46,578 +30,6 @@ static bool isLCD(const SkScalerContext::Rec& rec) { |
SkMask::kLCD32_Format == rec.fMaskFormat; |
} |
-/////////////////////////////////////////////////////////////////////////////// |
- |
-class StreamFontFileLoader; |
- |
-class SkFontMgr_DirectWrite : public SkFontMgr { |
-public: |
- /** localeNameLength must include the null terminator. */ |
- SkFontMgr_DirectWrite(IDWriteFactory* factory, IDWriteFontCollection* fontCollection, |
- WCHAR* localeName, int localeNameLength) |
- : fFactory(SkRefComPtr(factory)) |
- , fFontCollection(SkRefComPtr(fontCollection)) |
- , fLocaleName(localeNameLength) |
- { |
- memcpy(fLocaleName.get(), localeName, localeNameLength * sizeof(WCHAR)); |
- } |
- |
- /** Creates a typeface using a typeface cache. */ |
- SkTypeface* createTypefaceFromDWriteFont(IDWriteFontFace* fontFace, |
- IDWriteFont* font, |
- IDWriteFontFamily* fontFamily) const; |
- |
-protected: |
- virtual int onCountFamilies() const SK_OVERRIDE; |
- virtual void onGetFamilyName(int index, SkString* familyName) const SK_OVERRIDE; |
- virtual SkFontStyleSet* onCreateStyleSet(int index) const SK_OVERRIDE; |
- virtual SkFontStyleSet* onMatchFamily(const char familyName[]) const SK_OVERRIDE; |
- virtual SkTypeface* onMatchFamilyStyle(const char familyName[], |
- const SkFontStyle& fontstyle) const SK_OVERRIDE; |
- virtual SkTypeface* onMatchFaceStyle(const SkTypeface* familyMember, |
- const SkFontStyle& fontstyle) const SK_OVERRIDE; |
- virtual SkTypeface* onCreateFromStream(SkStream* stream, int ttcIndex) const SK_OVERRIDE; |
- virtual SkTypeface* onCreateFromData(SkData* data, int ttcIndex) const SK_OVERRIDE; |
- virtual SkTypeface* onCreateFromFile(const char path[], int ttcIndex) const SK_OVERRIDE; |
- virtual SkTypeface* onLegacyCreateTypeface(const char familyName[], |
- unsigned styleBits) const SK_OVERRIDE; |
- |
-private: |
- HRESULT getByFamilyName(const WCHAR familyName[], IDWriteFontFamily** fontFamily) const; |
- HRESULT getDefaultFontFamily(IDWriteFontFamily** fontFamily) const; |
- |
- void Add(SkTypeface* face, SkTypeface::Style requestedStyle, bool strong) const { |
- SkAutoMutexAcquire ama(fTFCacheMutex); |
- fTFCache.add(face, requestedStyle, strong); |
- } |
- |
- SkTypeface* FindByProcAndRef(SkTypefaceCache::FindProc proc, void* ctx) const { |
- SkAutoMutexAcquire ama(fTFCacheMutex); |
- SkTypeface* typeface = fTFCache.findByProcAndRef(proc, ctx); |
- return typeface; |
- } |
- |
- SkTScopedComPtr<IDWriteFactory> fFactory; |
- SkTScopedComPtr<IDWriteFontCollection> fFontCollection; |
- SkSMallocWCHAR fLocaleName; |
- mutable SkMutex fTFCacheMutex; |
- mutable SkTypefaceCache fTFCache; |
- |
- friend class SkFontStyleSet_DirectWrite; |
-}; |
- |
-class SkFontStyleSet_DirectWrite : public SkFontStyleSet { |
-public: |
- SkFontStyleSet_DirectWrite(const SkFontMgr_DirectWrite* fontMgr, |
- IDWriteFontFamily* fontFamily) |
- : fFontMgr(SkRef(fontMgr)) |
- , fFontFamily(SkRefComPtr(fontFamily)) |
- { } |
- |
- virtual int count() SK_OVERRIDE; |
- virtual void getStyle(int index, SkFontStyle* fs, SkString* styleName) SK_OVERRIDE; |
- virtual SkTypeface* createTypeface(int index) SK_OVERRIDE; |
- virtual SkTypeface* matchStyle(const SkFontStyle& pattern) SK_OVERRIDE; |
- |
-private: |
- SkAutoTUnref<const SkFontMgr_DirectWrite> fFontMgr; |
- SkTScopedComPtr<IDWriteFontFamily> fFontFamily; |
-}; |
- |
-/////////////////////////////////////////////////////////////////////////////// |
- |
-class StreamFontFileLoader : public IDWriteFontFileLoader { |
-public: |
- // IUnknown methods |
- virtual HRESULT STDMETHODCALLTYPE QueryInterface(REFIID iid, void** ppvObject); |
- virtual ULONG STDMETHODCALLTYPE AddRef(); |
- virtual ULONG STDMETHODCALLTYPE Release(); |
- |
- // IDWriteFontFileLoader methods |
- virtual HRESULT STDMETHODCALLTYPE CreateStreamFromKey( |
- void const* fontFileReferenceKey, |
- UINT32 fontFileReferenceKeySize, |
- IDWriteFontFileStream** fontFileStream); |
- |
- static HRESULT Create(SkStream* stream, StreamFontFileLoader** streamFontFileLoader) { |
- *streamFontFileLoader = new StreamFontFileLoader(stream); |
- if (NULL == streamFontFileLoader) { |
- return E_OUTOFMEMORY; |
- } |
- return S_OK; |
- } |
- |
- SkAutoTUnref<SkStream> fStream; |
- |
-private: |
- StreamFontFileLoader(SkStream* stream) : fRefCount(1), fStream(SkRef(stream)) { } |
- |
- ULONG fRefCount; |
-}; |
- |
-HRESULT StreamFontFileLoader::QueryInterface(REFIID iid, void** ppvObject) { |
- if (iid == IID_IUnknown || iid == __uuidof(IDWriteFontFileLoader)) { |
- *ppvObject = this; |
- AddRef(); |
- return S_OK; |
- } else { |
- *ppvObject = NULL; |
- return E_NOINTERFACE; |
- } |
-} |
- |
-ULONG StreamFontFileLoader::AddRef() { |
- return InterlockedIncrement(&fRefCount); |
-} |
- |
-ULONG StreamFontFileLoader::Release() { |
- ULONG newCount = InterlockedDecrement(&fRefCount); |
- if (0 == newCount) { |
- delete this; |
- } |
- return newCount; |
-} |
- |
-HRESULT StreamFontFileLoader::CreateStreamFromKey( |
- void const* fontFileReferenceKey, |
- UINT32 fontFileReferenceKeySize, |
- IDWriteFontFileStream** fontFileStream) |
-{ |
- SkTScopedComPtr<SkDWriteFontFileStreamWrapper> stream; |
- HR(SkDWriteFontFileStreamWrapper::Create(fStream, &stream)); |
- *fontFileStream = stream.release(); |
- return S_OK; |
-} |
- |
-class StreamFontFileEnumerator : public IDWriteFontFileEnumerator { |
-public: |
- // IUnknown methods |
- virtual HRESULT STDMETHODCALLTYPE QueryInterface(REFIID iid, void** ppvObject); |
- virtual ULONG STDMETHODCALLTYPE AddRef(); |
- virtual ULONG STDMETHODCALLTYPE Release(); |
- |
- // IDWriteFontFileEnumerator methods |
- virtual HRESULT STDMETHODCALLTYPE MoveNext(BOOL* hasCurrentFile); |
- virtual HRESULT STDMETHODCALLTYPE GetCurrentFontFile(IDWriteFontFile** fontFile); |
- |
- static HRESULT Create(IDWriteFactory* factory, IDWriteFontFileLoader* fontFileLoader, |
- StreamFontFileEnumerator** streamFontFileEnumerator) { |
- *streamFontFileEnumerator = new StreamFontFileEnumerator(factory, fontFileLoader); |
- if (NULL == streamFontFileEnumerator) { |
- return E_OUTOFMEMORY; |
- } |
- return S_OK; |
- } |
-private: |
- StreamFontFileEnumerator(IDWriteFactory* factory, IDWriteFontFileLoader* fontFileLoader); |
- ULONG fRefCount; |
- |
- SkTScopedComPtr<IDWriteFactory> fFactory; |
- SkTScopedComPtr<IDWriteFontFile> fCurrentFile; |
- SkTScopedComPtr<IDWriteFontFileLoader> fFontFileLoader; |
- bool fHasNext; |
-}; |
- |
-StreamFontFileEnumerator::StreamFontFileEnumerator(IDWriteFactory* factory, |
- IDWriteFontFileLoader* fontFileLoader) |
- : fRefCount(1) |
- , fFactory(SkRefComPtr(factory)) |
- , fCurrentFile() |
- , fFontFileLoader(SkRefComPtr(fontFileLoader)) |
- , fHasNext(true) |
-{ } |
- |
-HRESULT StreamFontFileEnumerator::QueryInterface(REFIID iid, void** ppvObject) { |
- if (iid == IID_IUnknown || iid == __uuidof(IDWriteFontFileEnumerator)) { |
- *ppvObject = this; |
- AddRef(); |
- return S_OK; |
- } else { |
- *ppvObject = NULL; |
- return E_NOINTERFACE; |
- } |
-} |
- |
-ULONG StreamFontFileEnumerator::AddRef() { |
- return InterlockedIncrement(&fRefCount); |
-} |
- |
-ULONG StreamFontFileEnumerator::Release() { |
- ULONG newCount = InterlockedDecrement(&fRefCount); |
- if (0 == newCount) { |
- delete this; |
- } |
- return newCount; |
-} |
- |
-HRESULT StreamFontFileEnumerator::MoveNext(BOOL* hasCurrentFile) { |
- *hasCurrentFile = FALSE; |
- |
- if (!fHasNext) { |
- return S_OK; |
- } |
- fHasNext = false; |
- |
- UINT32 dummy = 0; |
- HR(fFactory->CreateCustomFontFileReference( |
- &dummy, //cannot be NULL |
- sizeof(dummy), //even if this is 0 |
- fFontFileLoader.get(), |
- &fCurrentFile)); |
- |
- *hasCurrentFile = TRUE; |
- return S_OK; |
-} |
- |
-HRESULT StreamFontFileEnumerator::GetCurrentFontFile(IDWriteFontFile** fontFile) { |
- if (fCurrentFile.get() == NULL) { |
- *fontFile = NULL; |
- return E_FAIL; |
- } |
- |
- *fontFile = SkRefComPtr(fCurrentFile.get()); |
- return S_OK; |
-} |
- |
-class StreamFontCollectionLoader : public IDWriteFontCollectionLoader { |
-public: |
- // IUnknown methods |
- virtual HRESULT STDMETHODCALLTYPE QueryInterface(REFIID iid, void** ppvObject); |
- virtual ULONG STDMETHODCALLTYPE AddRef(); |
- virtual ULONG STDMETHODCALLTYPE Release(); |
- |
- // IDWriteFontCollectionLoader methods |
- virtual HRESULT STDMETHODCALLTYPE CreateEnumeratorFromKey( |
- IDWriteFactory* factory, |
- void const* collectionKey, |
- UINT32 collectionKeySize, |
- IDWriteFontFileEnumerator** fontFileEnumerator); |
- |
- static HRESULT Create(IDWriteFontFileLoader* fontFileLoader, |
- StreamFontCollectionLoader** streamFontCollectionLoader) { |
- *streamFontCollectionLoader = new StreamFontCollectionLoader(fontFileLoader); |
- if (NULL == streamFontCollectionLoader) { |
- return E_OUTOFMEMORY; |
- } |
- return S_OK; |
- } |
-private: |
- StreamFontCollectionLoader(IDWriteFontFileLoader* fontFileLoader) |
- : fRefCount(1) |
- , fFontFileLoader(SkRefComPtr(fontFileLoader)) |
- { } |
- |
- ULONG fRefCount; |
- SkTScopedComPtr<IDWriteFontFileLoader> fFontFileLoader; |
-}; |
- |
-HRESULT StreamFontCollectionLoader::QueryInterface(REFIID iid, void** ppvObject) { |
- if (iid == IID_IUnknown || iid == __uuidof(IDWriteFontCollectionLoader)) { |
- *ppvObject = this; |
- AddRef(); |
- return S_OK; |
- } else { |
- *ppvObject = NULL; |
- return E_NOINTERFACE; |
- } |
-} |
- |
-ULONG StreamFontCollectionLoader::AddRef() { |
- return InterlockedIncrement(&fRefCount); |
-} |
- |
-ULONG StreamFontCollectionLoader::Release() { |
- ULONG newCount = InterlockedDecrement(&fRefCount); |
- if (0 == newCount) { |
- delete this; |
- } |
- return newCount; |
-} |
- |
-HRESULT StreamFontCollectionLoader::CreateEnumeratorFromKey( |
- IDWriteFactory* factory, |
- void const* collectionKey, |
- UINT32 collectionKeySize, |
- IDWriteFontFileEnumerator** fontFileEnumerator) |
-{ |
- SkTScopedComPtr<StreamFontFileEnumerator> enumerator; |
- HR(StreamFontFileEnumerator::Create(factory, fFontFileLoader.get(), &enumerator)); |
- *fontFileEnumerator = enumerator.release(); |
- return S_OK; |
-} |
- |
-/////////////////////////////////////////////////////////////////////////////// |
- |
-static SkTypeface::Style get_style(IDWriteFont* font) { |
- int style = SkTypeface::kNormal; |
- DWRITE_FONT_WEIGHT weight = font->GetWeight(); |
- if (DWRITE_FONT_WEIGHT_DEMI_BOLD <= weight) { |
- style |= SkTypeface::kBold; |
- } |
- DWRITE_FONT_STYLE angle = font->GetStyle(); |
- if (DWRITE_FONT_STYLE_OBLIQUE == angle || DWRITE_FONT_STYLE_ITALIC == angle) { |
- style |= SkTypeface::kItalic; |
- } |
- return static_cast<SkTypeface::Style>(style); |
-} |
- |
-class DWriteFontTypeface : public SkTypeface { |
-private: |
- DWriteFontTypeface(SkTypeface::Style style, SkFontID fontID, |
- IDWriteFactory* factory, |
- IDWriteFontFace* fontFace, |
- IDWriteFont* font, |
- IDWriteFontFamily* fontFamily, |
- StreamFontFileLoader* fontFileLoader = NULL, |
- IDWriteFontCollectionLoader* fontCollectionLoader = NULL) |
- : SkTypeface(style, fontID, false) |
- , fFactory(SkRefComPtr(factory)) |
- , fDWriteFontCollectionLoader(SkSafeRefComPtr(fontCollectionLoader)) |
- , fDWriteFontFileLoader(SkSafeRefComPtr(fontFileLoader)) |
- , fDWriteFontFamily(SkRefComPtr(fontFamily)) |
- , fDWriteFont(SkRefComPtr(font)) |
- , fDWriteFontFace(SkRefComPtr(fontFace)) |
- { } |
- |
-public: |
- SkTScopedComPtr<IDWriteFactory> fFactory; |
- SkTScopedComPtr<IDWriteFontCollectionLoader> fDWriteFontCollectionLoader; |
- SkTScopedComPtr<StreamFontFileLoader> fDWriteFontFileLoader; |
- SkTScopedComPtr<IDWriteFontFamily> fDWriteFontFamily; |
- SkTScopedComPtr<IDWriteFont> fDWriteFont; |
- SkTScopedComPtr<IDWriteFontFace> fDWriteFontFace; |
- |
- static DWriteFontTypeface* Create(IDWriteFactory* factory, |
- IDWriteFontFace* fontFace, |
- IDWriteFont* font, |
- IDWriteFontFamily* fontFamily, |
- StreamFontFileLoader* fontFileLoader = NULL, |
- IDWriteFontCollectionLoader* fontCollectionLoader = NULL) { |
- SkTypeface::Style style = get_style(font); |
- SkFontID fontID = SkTypefaceCache::NewFontID(); |
- return SkNEW_ARGS(DWriteFontTypeface, (style, fontID, |
- factory, fontFace, font, fontFamily, |
- fontFileLoader, fontCollectionLoader)); |
- } |
- |
-protected: |
- virtual void weak_dispose() const SK_OVERRIDE { |
- if (fDWriteFontCollectionLoader.get()) { |
- HRV(fFactory->UnregisterFontCollectionLoader(fDWriteFontCollectionLoader.get())); |
- } |
- if (fDWriteFontFileLoader.get()) { |
- HRV(fFactory->UnregisterFontFileLoader(fDWriteFontFileLoader.get())); |
- } |
- |
- //SkTypefaceCache::Remove(this); |
- INHERITED::weak_dispose(); |
- } |
- |
- virtual SkStream* onOpenStream(int* ttcIndex) const SK_OVERRIDE; |
- virtual SkScalerContext* onCreateScalerContext(const SkDescriptor*) const SK_OVERRIDE; |
- virtual void onFilterRec(SkScalerContextRec*) const SK_OVERRIDE; |
- virtual SkAdvancedTypefaceMetrics* onGetAdvancedTypefaceMetrics( |
- SkAdvancedTypefaceMetrics::PerGlyphInfo, |
- const uint32_t*, uint32_t) const SK_OVERRIDE; |
- virtual void onGetFontDescriptor(SkFontDescriptor*, bool*) const SK_OVERRIDE; |
- virtual int onCharsToGlyphs(const void* chars, Encoding encoding, |
- uint16_t glyphs[], int glyphCount) const SK_OVERRIDE; |
- virtual int onCountGlyphs() const SK_OVERRIDE; |
- virtual int onGetUPEM() const SK_OVERRIDE; |
- virtual SkTypeface::LocalizedStrings* onCreateFamilyNameIterator() const SK_OVERRIDE; |
- virtual int onGetTableTags(SkFontTableTag tags[]) const SK_OVERRIDE; |
- virtual size_t onGetTableData(SkFontTableTag, size_t offset, |
- size_t length, void* data) const SK_OVERRIDE; |
- |
-private: |
- typedef SkTypeface INHERITED; |
-}; |
- |
-class SkScalerContext_DW : public SkScalerContext { |
-public: |
- SkScalerContext_DW(DWriteFontTypeface*, const SkDescriptor* desc); |
- virtual ~SkScalerContext_DW(); |
- |
-protected: |
- virtual unsigned generateGlyphCount() SK_OVERRIDE; |
- virtual uint16_t generateCharToGlyph(SkUnichar uni) SK_OVERRIDE; |
- virtual void generateAdvance(SkGlyph* glyph) SK_OVERRIDE; |
- virtual void generateMetrics(SkGlyph* glyph) SK_OVERRIDE; |
- virtual void generateImage(const SkGlyph& glyph) SK_OVERRIDE; |
- virtual void generatePath(const SkGlyph& glyph, SkPath* path) SK_OVERRIDE; |
- virtual void generateFontMetrics(SkPaint::FontMetrics* mX, |
- SkPaint::FontMetrics* mY) SK_OVERRIDE; |
- |
-private: |
- const void* drawDWMask(const SkGlyph& glyph); |
- |
- SkTDArray<uint8_t> fBits; |
- /** The total matrix without the text height scale. */ |
- SkMatrix fSkXform; |
- /** The total matrix without the text height scale. */ |
- DWRITE_MATRIX fXform; |
- /** The non-rotational part of total matrix without the text height scale. |
- * This is used to find the magnitude of gdi compatible advances. |
- */ |
- DWRITE_MATRIX fGsA; |
- /** The inverse of the rotational part of the total matrix. |
- * This is used to find the direction of gdi compatible advances. |
- */ |
- SkMatrix fG_inv; |
- /** The text size to render with. */ |
- SkScalar fTextSizeRender; |
- /** The text size to measure with. */ |
- SkScalar fTextSizeMeasure; |
- SkAutoTUnref<DWriteFontTypeface> fTypeface; |
- int fGlyphCount; |
- DWRITE_RENDERING_MODE fRenderingMode; |
- DWRITE_TEXTURE_TYPE fTextureType; |
- DWRITE_MEASURING_MODE fMeasuringMode; |
-}; |
- |
-static bool are_same(IUnknown* a, IUnknown* b) { |
- SkTScopedComPtr<IUnknown> iunkA; |
- if (FAILED(a->QueryInterface(&iunkA))) { |
- return false; |
- } |
- |
- SkTScopedComPtr<IUnknown> iunkB; |
- if (FAILED(b->QueryInterface(&iunkB))) { |
- return false; |
- } |
- |
- return iunkA.get() == iunkB.get(); |
-} |
-static bool FindByDWriteFont(SkTypeface* face, SkTypeface::Style requestedStyle, void* ctx) { |
- //Check to see if the two fonts are identical. |
- DWriteFontTypeface* dwFace = reinterpret_cast<DWriteFontTypeface*>(face); |
- IDWriteFont* dwFont = reinterpret_cast<IDWriteFont*>(ctx); |
- if (are_same(dwFace->fDWriteFont.get(), dwFont)) { |
- return true; |
- } |
- |
- //Check if the two fonts share the same loader and have the same key. |
- SkTScopedComPtr<IDWriteFontFace> dwFaceFontFace; |
- SkTScopedComPtr<IDWriteFontFace> dwFontFace; |
- HRB(dwFace->fDWriteFont->CreateFontFace(&dwFaceFontFace)); |
- HRB(dwFont->CreateFontFace(&dwFontFace)); |
- if (are_same(dwFaceFontFace.get(), dwFontFace.get())) { |
- return true; |
- } |
- |
- UINT32 dwFaceNumFiles; |
- UINT32 dwNumFiles; |
- HRB(dwFaceFontFace->GetFiles(&dwFaceNumFiles, NULL)); |
- HRB(dwFontFace->GetFiles(&dwNumFiles, NULL)); |
- if (dwFaceNumFiles != dwNumFiles) { |
- return false; |
- } |
- |
- SkTScopedComPtr<IDWriteFontFile> dwFaceFontFile; |
- SkTScopedComPtr<IDWriteFontFile> dwFontFile; |
- HRB(dwFaceFontFace->GetFiles(&dwFaceNumFiles, &dwFaceFontFile)); |
- HRB(dwFontFace->GetFiles(&dwNumFiles, &dwFontFile)); |
- |
- //for (each file) { //we currently only admit fonts from one file. |
- SkTScopedComPtr<IDWriteFontFileLoader> dwFaceFontFileLoader; |
- SkTScopedComPtr<IDWriteFontFileLoader> dwFontFileLoader; |
- HRB(dwFaceFontFile->GetLoader(&dwFaceFontFileLoader)); |
- HRB(dwFontFile->GetLoader(&dwFontFileLoader)); |
- if (!are_same(dwFaceFontFileLoader.get(), dwFontFileLoader.get())) { |
- return false; |
- } |
- //} |
- |
- const void* dwFaceFontRefKey; |
- UINT32 dwFaceFontRefKeySize; |
- const void* dwFontRefKey; |
- UINT32 dwFontRefKeySize; |
- HRB(dwFaceFontFile->GetReferenceKey(&dwFaceFontRefKey, &dwFaceFontRefKeySize)); |
- HRB(dwFontFile->GetReferenceKey(&dwFontRefKey, &dwFontRefKeySize)); |
- if (dwFaceFontRefKeySize != dwFontRefKeySize) { |
- return false; |
- } |
- if (0 != memcmp(dwFaceFontRefKey, dwFontRefKey, dwFontRefKeySize)) { |
- return false; |
- } |
- |
- //TODO: better means than comparing name strings? |
- //NOTE: .tfc and fake bold/italic will end up here. |
- SkTScopedComPtr<IDWriteFontFamily> dwFaceFontFamily; |
- SkTScopedComPtr<IDWriteFontFamily> dwFontFamily; |
- HRB(dwFace->fDWriteFont->GetFontFamily(&dwFaceFontFamily)); |
- HRB(dwFont->GetFontFamily(&dwFontFamily)); |
- |
- SkTScopedComPtr<IDWriteLocalizedStrings> dwFaceFontFamilyNames; |
- SkTScopedComPtr<IDWriteLocalizedStrings> dwFaceFontNames; |
- HRB(dwFaceFontFamily->GetFamilyNames(&dwFaceFontFamilyNames)); |
- HRB(dwFace->fDWriteFont->GetFaceNames(&dwFaceFontNames)); |
- |
- SkTScopedComPtr<IDWriteLocalizedStrings> dwFontFamilyNames; |
- SkTScopedComPtr<IDWriteLocalizedStrings> dwFontNames; |
- HRB(dwFontFamily->GetFamilyNames(&dwFontFamilyNames)); |
- HRB(dwFont->GetFaceNames(&dwFontNames)); |
- |
- UINT32 dwFaceFontFamilyNameLength; |
- UINT32 dwFaceFontNameLength; |
- HRB(dwFaceFontFamilyNames->GetStringLength(0, &dwFaceFontFamilyNameLength)); |
- HRB(dwFaceFontNames->GetStringLength(0, &dwFaceFontNameLength)); |
- |
- UINT32 dwFontFamilyNameLength; |
- UINT32 dwFontNameLength; |
- HRB(dwFontFamilyNames->GetStringLength(0, &dwFontFamilyNameLength)); |
- HRB(dwFontNames->GetStringLength(0, &dwFontNameLength)); |
- |
- if (dwFaceFontFamilyNameLength != dwFontFamilyNameLength || |
- dwFaceFontNameLength != dwFontNameLength) |
- { |
- return false; |
- } |
- |
- SkSMallocWCHAR dwFaceFontFamilyNameChar(dwFaceFontFamilyNameLength+1); |
- SkSMallocWCHAR dwFaceFontNameChar(dwFaceFontNameLength+1); |
- HRB(dwFaceFontFamilyNames->GetString(0, dwFaceFontFamilyNameChar.get(), dwFaceFontFamilyNameLength+1)); |
- HRB(dwFaceFontNames->GetString(0, dwFaceFontNameChar.get(), dwFaceFontNameLength+1)); |
- |
- SkSMallocWCHAR dwFontFamilyNameChar(dwFontFamilyNameLength+1); |
- SkSMallocWCHAR dwFontNameChar(dwFontNameLength+1); |
- HRB(dwFontFamilyNames->GetString(0, dwFontFamilyNameChar.get(), dwFontFamilyNameLength+1)); |
- HRB(dwFontNames->GetString(0, dwFontNameChar.get(), dwFontNameLength+1)); |
- |
- return wcscmp(dwFaceFontFamilyNameChar.get(), dwFontFamilyNameChar.get()) == 0 && |
- wcscmp(dwFaceFontNameChar.get(), dwFontNameChar.get()) == 0; |
-} |
- |
-class AutoDWriteTable { |
-public: |
- AutoDWriteTable(IDWriteFontFace* fontFace, UINT32 beTag) : fFontFace(fontFace), fExists(FALSE) { |
- // Any errors are ignored, user must check fExists anyway. |
- fontFace->TryGetFontTable(beTag, |
- reinterpret_cast<const void **>(&fData), &fSize, &fLock, &fExists); |
- } |
- ~AutoDWriteTable() { |
- if (fExists) { |
- fFontFace->ReleaseFontTable(fLock); |
- } |
- } |
- |
- const uint8_t* fData; |
- UINT32 fSize; |
- BOOL fExists; |
-private: |
- // Borrowed reference, the user must ensure the fontFace stays alive. |
- IDWriteFontFace* fFontFace; |
- void* fLock; |
-}; |
-template<typename T> class AutoTDWriteTable : public AutoDWriteTable { |
-public: |
- static const UINT32 tag = DWRITE_MAKE_OPENTYPE_TAG(T::TAG0, T::TAG1, T::TAG2, T::TAG3); |
- AutoTDWriteTable(IDWriteFontFace* fontFace) : AutoDWriteTable(fontFace, tag) { } |
- |
- const T* get() const { return reinterpret_cast<const T*>(fData); } |
- const T* operator->() const { return reinterpret_cast<const T*>(fData); } |
-}; |
- |
static bool hasBitmapStrike(DWriteFontTypeface* typeface, int size) { |
{ |
AutoTDWriteTable<SkOTTableEmbeddedBitmapLocation> eblc(typeface->fDWriteFontFace.get()); |
@@ -1209,820 +621,3 @@ void SkScalerContext_DW::generatePath(const SkGlyph& glyph, SkPath* path) { |
path->transform(fSkXform); |
} |
- |
-void DWriteFontTypeface::onGetFontDescriptor(SkFontDescriptor* desc, |
- bool* isLocalStream) const { |
- // Get the family name. |
- SkTScopedComPtr<IDWriteLocalizedStrings> dwFamilyNames; |
- HRV(fDWriteFontFamily->GetFamilyNames(&dwFamilyNames)); |
- |
- UINT32 dwFamilyNamesLength; |
- HRV(dwFamilyNames->GetStringLength(0, &dwFamilyNamesLength)); |
- |
- SkSMallocWCHAR dwFamilyNameChar(dwFamilyNamesLength+1); |
- HRV(dwFamilyNames->GetString(0, dwFamilyNameChar.get(), dwFamilyNamesLength+1)); |
- |
- SkString utf8FamilyName; |
- HRV(sk_wchar_to_skstring(dwFamilyNameChar.get(), &utf8FamilyName)); |
- |
- desc->setFamilyName(utf8FamilyName.c_str()); |
- *isLocalStream = SkToBool(fDWriteFontFileLoader.get()); |
-} |
- |
-static SkUnichar next_utf8(const void** chars) { |
- return SkUTF8_NextUnichar((const char**)chars); |
-} |
- |
-static SkUnichar next_utf16(const void** chars) { |
- return SkUTF16_NextUnichar((const uint16_t**)chars); |
-} |
- |
-static SkUnichar next_utf32(const void** chars) { |
- const SkUnichar** uniChars = (const SkUnichar**)chars; |
- SkUnichar uni = **uniChars; |
- *uniChars += 1; |
- return uni; |
-} |
- |
-typedef SkUnichar (*EncodingProc)(const void**); |
- |
-static EncodingProc find_encoding_proc(SkTypeface::Encoding enc) { |
- static const EncodingProc gProcs[] = { |
- next_utf8, next_utf16, next_utf32 |
- }; |
- SkASSERT((size_t)enc < SK_ARRAY_COUNT(gProcs)); |
- return gProcs[enc]; |
-} |
- |
-int DWriteFontTypeface::onCharsToGlyphs(const void* chars, Encoding encoding, |
- uint16_t glyphs[], int glyphCount) const |
-{ |
- if (NULL == glyphs) { |
- EncodingProc next_ucs4_proc = find_encoding_proc(encoding); |
- for (int i = 0; i < glyphCount; ++i) { |
- const SkUnichar c = next_ucs4_proc(&chars); |
- BOOL exists; |
- fDWriteFont->HasCharacter(c, &exists); |
- if (!exists) { |
- return i; |
- } |
- } |
- return glyphCount; |
- } |
- |
- switch (encoding) { |
- case SkTypeface::kUTF8_Encoding: |
- case SkTypeface::kUTF16_Encoding: { |
- static const int scratchCount = 256; |
- UINT32 scratch[scratchCount]; |
- EncodingProc next_ucs4_proc = find_encoding_proc(encoding); |
- for (int baseGlyph = 0; baseGlyph < glyphCount; baseGlyph += scratchCount) { |
- int glyphsLeft = glyphCount - baseGlyph; |
- int limit = SkTMin(glyphsLeft, scratchCount); |
- for (int i = 0; i < limit; ++i) { |
- scratch[i] = next_ucs4_proc(&chars); |
- } |
- fDWriteFontFace->GetGlyphIndices(scratch, limit, &glyphs[baseGlyph]); |
- } |
- break; |
- } |
- case SkTypeface::kUTF32_Encoding: { |
- const UINT32* utf32 = reinterpret_cast<const UINT32*>(chars); |
- fDWriteFontFace->GetGlyphIndices(utf32, glyphCount, glyphs); |
- break; |
- } |
- default: |
- SK_CRASH(); |
- } |
- |
- for (int i = 0; i < glyphCount; ++i) { |
- if (0 == glyphs[i]) { |
- return i; |
- } |
- } |
- return glyphCount; |
-} |
- |
-int DWriteFontTypeface::onCountGlyphs() const { |
- return fDWriteFontFace->GetGlyphCount(); |
-} |
- |
-int DWriteFontTypeface::onGetUPEM() const { |
- DWRITE_FONT_METRICS metrics; |
- fDWriteFontFace->GetMetrics(&metrics); |
- return metrics.designUnitsPerEm; |
-} |
- |
-class LocalizedStrings_IDWriteLocalizedStrings : public SkTypeface::LocalizedStrings { |
-public: |
- /** Takes ownership of the IDWriteLocalizedStrings. */ |
- explicit LocalizedStrings_IDWriteLocalizedStrings(IDWriteLocalizedStrings* strings) |
- : fIndex(0), fStrings(strings) |
- { } |
- |
- virtual bool next(SkTypeface::LocalizedString* localizedString) SK_OVERRIDE { |
- if (fIndex >= fStrings->GetCount()) { |
- return false; |
- } |
- |
- // String |
- UINT32 stringLength; |
- HRBM(fStrings->GetStringLength(fIndex, &stringLength), "Could not get string length."); |
- stringLength += 1; |
- |
- SkSMallocWCHAR wString(stringLength); |
- HRBM(fStrings->GetString(fIndex, wString.get(), stringLength), "Could not get string."); |
- |
- HRB(sk_wchar_to_skstring(wString.get(), &localizedString->fString)); |
- |
- // Locale |
- UINT32 localeLength; |
- HRBM(fStrings->GetLocaleNameLength(fIndex, &localeLength), "Could not get locale length."); |
- localeLength += 1; |
- |
- SkSMallocWCHAR wLocale(localeLength); |
- HRBM(fStrings->GetLocaleName(fIndex, wLocale.get(), localeLength), "Could not get locale."); |
- |
- HRB(sk_wchar_to_skstring(wLocale.get(), &localizedString->fLanguage)); |
- |
- ++fIndex; |
- return true; |
- } |
- |
-private: |
- UINT32 fIndex; |
- SkTScopedComPtr<IDWriteLocalizedStrings> fStrings; |
-}; |
- |
-SkTypeface::LocalizedStrings* DWriteFontTypeface::onCreateFamilyNameIterator() const { |
- SkTScopedComPtr<IDWriteLocalizedStrings> familyNames; |
- HRNM(fDWriteFontFamily->GetFamilyNames(&familyNames), "Could not obtain family names."); |
- |
- return new LocalizedStrings_IDWriteLocalizedStrings(familyNames.release()); |
-} |
- |
-int DWriteFontTypeface::onGetTableTags(SkFontTableTag tags[]) const { |
- DWRITE_FONT_FACE_TYPE type = fDWriteFontFace->GetType(); |
- if (type != DWRITE_FONT_FACE_TYPE_CFF && |
- type != DWRITE_FONT_FACE_TYPE_TRUETYPE && |
- type != DWRITE_FONT_FACE_TYPE_TRUETYPE_COLLECTION) |
- { |
- return 0; |
- } |
- |
- int ttcIndex; |
- SkAutoTUnref<SkStream> stream(this->openStream(&ttcIndex)); |
- return stream.get() ? SkFontStream::GetTableTags(stream, ttcIndex, tags) : 0; |
-} |
- |
-size_t DWriteFontTypeface::onGetTableData(SkFontTableTag tag, size_t offset, |
- size_t length, void* data) const |
-{ |
- AutoDWriteTable table(fDWriteFontFace.get(), SkEndian_SwapBE32(tag)); |
- if (!table.fExists) { |
- return 0; |
- } |
- |
- if (offset > table.fSize) { |
- return 0; |
- } |
- size_t size = SkTMin(length, table.fSize - offset); |
- if (NULL != data) { |
- memcpy(data, table.fData + offset, size); |
- } |
- |
- return size; |
-} |
- |
-template <typename T> class SkAutoIDWriteUnregister { |
-public: |
- SkAutoIDWriteUnregister(IDWriteFactory* factory, T* unregister) |
- : fFactory(factory), fUnregister(unregister) |
- { } |
- |
- ~SkAutoIDWriteUnregister() { |
- if (fUnregister) { |
- unregister(fFactory, fUnregister); |
- } |
- } |
- |
- T* detatch() { |
- T* old = fUnregister; |
- fUnregister = NULL; |
- return old; |
- } |
- |
-private: |
- HRESULT unregister(IDWriteFactory* factory, IDWriteFontFileLoader* unregister) { |
- return factory->UnregisterFontFileLoader(unregister); |
- } |
- |
- HRESULT unregister(IDWriteFactory* factory, IDWriteFontCollectionLoader* unregister) { |
- return factory->UnregisterFontCollectionLoader(unregister); |
- } |
- |
- IDWriteFactory* fFactory; |
- T* fUnregister; |
-}; |
- |
-SkStream* DWriteFontTypeface::onOpenStream(int* ttcIndex) const { |
- *ttcIndex = fDWriteFontFace->GetIndex(); |
- |
- UINT32 numFiles; |
- HRNM(fDWriteFontFace->GetFiles(&numFiles, NULL), |
- "Could not get number of font files."); |
- if (numFiles != 1) { |
- return NULL; |
- } |
- |
- SkTScopedComPtr<IDWriteFontFile> fontFile; |
- HRNM(fDWriteFontFace->GetFiles(&numFiles, &fontFile), "Could not get font files."); |
- |
- const void* fontFileKey; |
- UINT32 fontFileKeySize; |
- HRNM(fontFile->GetReferenceKey(&fontFileKey, &fontFileKeySize), |
- "Could not get font file reference key."); |
- |
- SkTScopedComPtr<IDWriteFontFileLoader> fontFileLoader; |
- HRNM(fontFile->GetLoader(&fontFileLoader), "Could not get font file loader."); |
- |
- SkTScopedComPtr<IDWriteFontFileStream> fontFileStream; |
- HRNM(fontFileLoader->CreateStreamFromKey(fontFileKey, fontFileKeySize, |
- &fontFileStream), |
- "Could not create font file stream."); |
- |
- return SkNEW_ARGS(SkDWriteFontFileStream, (fontFileStream.get())); |
-} |
- |
-SkScalerContext* DWriteFontTypeface::onCreateScalerContext(const SkDescriptor* desc) const { |
- return SkNEW_ARGS(SkScalerContext_DW, (const_cast<DWriteFontTypeface*>(this), desc)); |
-} |
- |
-void DWriteFontTypeface::onFilterRec(SkScalerContext::Rec* rec) const { |
- if (rec->fFlags & SkScalerContext::kLCD_BGROrder_Flag || |
- rec->fFlags & SkScalerContext::kLCD_Vertical_Flag) |
- { |
- rec->fMaskFormat = SkMask::kA8_Format; |
- } |
- |
- unsigned flagsWeDontSupport = SkScalerContext::kDevKernText_Flag | |
- SkScalerContext::kForceAutohinting_Flag | |
- SkScalerContext::kEmbolden_Flag | |
- SkScalerContext::kLCD_BGROrder_Flag | |
- SkScalerContext::kLCD_Vertical_Flag; |
- rec->fFlags &= ~flagsWeDontSupport; |
- |
- SkPaint::Hinting h = rec->getHinting(); |
- // DirectWrite does not provide for hinting hints. |
- h = SkPaint::kSlight_Hinting; |
- rec->setHinting(h); |
- |
-#if SK_FONT_HOST_USE_SYSTEM_SETTINGS |
- IDWriteFactory* factory = get_dwrite_factory(); |
- if (factory != NULL) { |
- SkTScopedComPtr<IDWriteRenderingParams> defaultRenderingParams; |
- if (SUCCEEDED(factory->CreateRenderingParams(&defaultRenderingParams))) { |
- float gamma = defaultRenderingParams->GetGamma(); |
- rec->setDeviceGamma(gamma); |
- rec->setPaintGamma(gamma); |
- |
- rec->setContrast(defaultRenderingParams->GetEnhancedContrast()); |
- } |
- } |
-#endif |
-} |
- |
-/////////////////////////////////////////////////////////////////////////////// |
-//PDF Support |
- |
-using namespace skia_advanced_typeface_metrics_utils; |
- |
-// Construct Glyph to Unicode table. |
-// Unicode code points that require conjugate pairs in utf16 are not |
-// supported. |
-// TODO(arthurhsu): Add support for conjugate pairs. It looks like that may |
-// require parsing the TTF cmap table (platform 4, encoding 12) directly instead |
-// of calling GetFontUnicodeRange(). |
-// TODO(bungeman): This never does what anyone wants. |
-// What is really wanted is the text to glyphs mapping |
-static void populate_glyph_to_unicode(IDWriteFontFace* fontFace, |
- const unsigned glyphCount, |
- SkTDArray<SkUnichar>* glyphToUnicode) { |
- HRESULT hr = S_OK; |
- |
- //Do this like free type instead |
- UINT32 count = 0; |
- for (UINT32 c = 0; c < 0x10FFFF; ++c) { |
- UINT16 glyph; |
- hr = fontFace->GetGlyphIndices(&c, 1, &glyph); |
- if (glyph > 0) { |
- ++count; |
- } |
- } |
- |
- SkAutoTArray<UINT32> chars(count); |
- count = 0; |
- for (UINT32 c = 0; c < 0x10FFFF; ++c) { |
- UINT16 glyph; |
- hr = fontFace->GetGlyphIndices(&c, 1, &glyph); |
- if (glyph > 0) { |
- chars[count] = c; |
- ++count; |
- } |
- } |
- |
- SkAutoTArray<UINT16> glyph(count); |
- fontFace->GetGlyphIndices(chars.get(), count, glyph.get()); |
- |
- USHORT maxGlyph = 0; |
- for (USHORT j = 0; j < count; ++j) { |
- if (glyph[j] > maxGlyph) maxGlyph = glyph[j]; |
- } |
- |
- glyphToUnicode->setCount(maxGlyph+1); |
- for (USHORT j = 0; j < maxGlyph+1u; ++j) { |
- (*glyphToUnicode)[j] = 0; |
- } |
- |
- //'invert' |
- for (USHORT j = 0; j < count; ++j) { |
- if (glyph[j] < glyphCount && (*glyphToUnicode)[glyph[j]] == 0) { |
- (*glyphToUnicode)[glyph[j]] = chars[j]; |
- } |
- } |
-} |
- |
-static bool getWidthAdvance(IDWriteFontFace* fontFace, int gId, int16_t* advance) { |
- SkASSERT(advance); |
- |
- UINT16 glyphId = gId; |
- DWRITE_GLYPH_METRICS gm; |
- HRESULT hr = fontFace->GetDesignGlyphMetrics(&glyphId, 1, &gm); |
- |
- if (FAILED(hr)) { |
- *advance = 0; |
- return false; |
- } |
- |
- *advance = gm.advanceWidth; |
- return true; |
-} |
- |
-SkAdvancedTypefaceMetrics* DWriteFontTypeface::onGetAdvancedTypefaceMetrics( |
- SkAdvancedTypefaceMetrics::PerGlyphInfo perGlyphInfo, |
- const uint32_t* glyphIDs, |
- uint32_t glyphIDsCount) const { |
- |
- SkAdvancedTypefaceMetrics* info = NULL; |
- |
- HRESULT hr = S_OK; |
- |
- const unsigned glyphCount = fDWriteFontFace->GetGlyphCount(); |
- |
- DWRITE_FONT_METRICS dwfm; |
- fDWriteFontFace->GetMetrics(&dwfm); |
- |
- info = new SkAdvancedTypefaceMetrics; |
- info->fEmSize = dwfm.designUnitsPerEm; |
- info->fMultiMaster = false; |
- info->fLastGlyphID = SkToU16(glyphCount - 1); |
- info->fStyle = 0; |
- |
- |
- SkTScopedComPtr<IDWriteLocalizedStrings> familyNames; |
- SkTScopedComPtr<IDWriteLocalizedStrings> faceNames; |
- hr = fDWriteFontFamily->GetFamilyNames(&familyNames); |
- hr = fDWriteFont->GetFaceNames(&faceNames); |
- |
- UINT32 familyNameLength; |
- hr = familyNames->GetStringLength(0, &familyNameLength); |
- |
- UINT32 faceNameLength; |
- hr = faceNames->GetStringLength(0, &faceNameLength); |
- |
- UINT32 size = familyNameLength+1+faceNameLength+1; |
- SkSMallocWCHAR wFamilyName(size); |
- hr = familyNames->GetString(0, wFamilyName.get(), size); |
- wFamilyName[familyNameLength] = L' '; |
- hr = faceNames->GetString(0, &wFamilyName[familyNameLength+1], size - faceNameLength + 1); |
- |
- hr = sk_wchar_to_skstring(wFamilyName.get(), &info->fFontName); |
- |
- if (perGlyphInfo & SkAdvancedTypefaceMetrics::kToUnicode_PerGlyphInfo) { |
- populate_glyph_to_unicode(fDWriteFontFace.get(), glyphCount, &(info->fGlyphToUnicode)); |
- } |
- |
- DWRITE_FONT_FACE_TYPE fontType = fDWriteFontFace->GetType(); |
- if (fontType == DWRITE_FONT_FACE_TYPE_TRUETYPE || |
- fontType == DWRITE_FONT_FACE_TYPE_TRUETYPE_COLLECTION) { |
- info->fType = SkAdvancedTypefaceMetrics::kTrueType_Font; |
- } else { |
- info->fType = SkAdvancedTypefaceMetrics::kOther_Font; |
- info->fItalicAngle = 0; |
- info->fAscent = dwfm.ascent;; |
- info->fDescent = dwfm.descent; |
- info->fStemV = 0; |
- info->fCapHeight = dwfm.capHeight; |
- info->fBBox = SkIRect::MakeEmpty(); |
- return info; |
- } |
- |
- AutoTDWriteTable<SkOTTableHead> headTable(fDWriteFontFace.get()); |
- AutoTDWriteTable<SkOTTablePostScript> postTable(fDWriteFontFace.get()); |
- AutoTDWriteTable<SkOTTableHorizontalHeader> hheaTable(fDWriteFontFace.get()); |
- AutoTDWriteTable<SkOTTableOS2> os2Table(fDWriteFontFace.get()); |
- if (!headTable.fExists || !postTable.fExists || !hheaTable.fExists || !os2Table.fExists) { |
- info->fItalicAngle = 0; |
- info->fAscent = dwfm.ascent;; |
- info->fDescent = dwfm.descent; |
- info->fStemV = 0; |
- info->fCapHeight = dwfm.capHeight; |
- info->fBBox = SkIRect::MakeEmpty(); |
- return info; |
- } |
- |
- //There exist CJK fonts which set the IsFixedPitch and Monospace bits, |
- //but have full width, latin half-width, and half-width kana. |
- bool fixedWidth = (postTable->isFixedPitch && |
- (1 == SkEndian_SwapBE16(hheaTable->numberOfHMetrics))); |
- //Monospace |
- if (fixedWidth) { |
- info->fStyle |= SkAdvancedTypefaceMetrics::kFixedPitch_Style; |
- } |
- //Italic |
- if (os2Table->version.v0.fsSelection.field.Italic) { |
- info->fStyle |= SkAdvancedTypefaceMetrics::kItalic_Style; |
- } |
- //Script |
- if (SkPanose::FamilyType::Script == os2Table->version.v0.panose.bFamilyType.value) { |
- info->fStyle |= SkAdvancedTypefaceMetrics::kScript_Style; |
- //Serif |
- } else if (SkPanose::FamilyType::TextAndDisplay == os2Table->version.v0.panose.bFamilyType.value && |
- SkPanose::Data::TextAndDisplay::SerifStyle::Triangle <= os2Table->version.v0.panose.data.textAndDisplay.bSerifStyle.value && |
- SkPanose::Data::TextAndDisplay::SerifStyle::NoFit != os2Table->version.v0.panose.data.textAndDisplay.bSerifStyle.value) { |
- info->fStyle |= SkAdvancedTypefaceMetrics::kSerif_Style; |
- } |
- |
- info->fItalicAngle = SkEndian_SwapBE32(postTable->italicAngle) >> 16; |
- |
- info->fAscent = SkToS16(dwfm.ascent); |
- info->fDescent = SkToS16(dwfm.descent); |
- info->fCapHeight = SkToS16(dwfm.capHeight); |
- |
- info->fBBox = SkIRect::MakeLTRB((int32_t)SkEndian_SwapBE16((uint16_t)headTable->xMin), |
- (int32_t)SkEndian_SwapBE16((uint16_t)headTable->yMax), |
- (int32_t)SkEndian_SwapBE16((uint16_t)headTable->xMax), |
- (int32_t)SkEndian_SwapBE16((uint16_t)headTable->yMin)); |
- |
- //TODO: is this even desired? It seems PDF only wants this value for Type1 |
- //fonts, and we only get here for TrueType fonts. |
- info->fStemV = 0; |
- /* |
- // Figure out a good guess for StemV - Min width of i, I, !, 1. |
- // This probably isn't very good with an italic font. |
- int16_t min_width = SHRT_MAX; |
- info->fStemV = 0; |
- char stem_chars[] = {'i', 'I', '!', '1'}; |
- for (size_t i = 0; i < SK_ARRAY_COUNT(stem_chars); i++) { |
- ABC abcWidths; |
- if (GetCharABCWidths(hdc, stem_chars[i], stem_chars[i], &abcWidths)) { |
- int16_t width = abcWidths.abcB; |
- if (width > 0 && width < min_width) { |
- min_width = width; |
- info->fStemV = min_width; |
- } |
- } |
- } |
- */ |
- |
- // If Restricted, the font may not be embedded in a document. |
- // If not Restricted, the font can be embedded. |
- // If PreviewPrint, the embedding is read-only. |
- if (os2Table->version.v0.fsType.field.Restricted) { |
- info->fType = SkAdvancedTypefaceMetrics::kNotEmbeddable_Font; |
- } else if (perGlyphInfo & SkAdvancedTypefaceMetrics::kHAdvance_PerGlyphInfo) { |
- if (fixedWidth) { |
- appendRange(&info->fGlyphWidths, 0); |
- int16_t advance; |
- getWidthAdvance(fDWriteFontFace.get(), 1, &advance); |
- info->fGlyphWidths->fAdvance.append(1, &advance); |
- finishRange(info->fGlyphWidths.get(), 0, |
- SkAdvancedTypefaceMetrics::WidthRange::kDefault); |
- } else { |
- info->fGlyphWidths.reset( |
- getAdvanceData(fDWriteFontFace.get(), |
- glyphCount, |
- glyphIDs, |
- glyphIDsCount, |
- getWidthAdvance)); |
- } |
- } |
- |
- return info; |
-} |
- |
-/////////////////////////////////////////////////////////////////////////////// |
- |
-SkTypeface* SkFontMgr_DirectWrite::createTypefaceFromDWriteFont( |
- IDWriteFontFace* fontFace, |
- IDWriteFont* font, |
- IDWriteFontFamily* fontFamily) const { |
- SkTypeface* face = FindByProcAndRef(FindByDWriteFont, font); |
- if (NULL == face) { |
- face = DWriteFontTypeface::Create(fFactory.get(), fontFace, font, fontFamily); |
- if (face) { |
- Add(face, get_style(font), true); |
- } |
- } |
- return face; |
-} |
- |
-int SkFontMgr_DirectWrite::onCountFamilies() const { |
- return fFontCollection->GetFontFamilyCount(); |
-} |
- |
-void SkFontMgr_DirectWrite::onGetFamilyName(int index, SkString* familyName) const { |
- SkTScopedComPtr<IDWriteFontFamily> fontFamily; |
- HRVM(fFontCollection->GetFontFamily(index, &fontFamily), "Could not get requested family."); |
- |
- SkTScopedComPtr<IDWriteLocalizedStrings> familyNames; |
- HRVM(fontFamily->GetFamilyNames(&familyNames), "Could not get family names."); |
- |
- sk_get_locale_string(familyNames.get(), fLocaleName.get(), familyName); |
-} |
- |
-SkFontStyleSet* SkFontMgr_DirectWrite::onCreateStyleSet(int index) const { |
- SkTScopedComPtr<IDWriteFontFamily> fontFamily; |
- HRNM(fFontCollection->GetFontFamily(index, &fontFamily), "Could not get requested family."); |
- |
- return SkNEW_ARGS(SkFontStyleSet_DirectWrite, (this, fontFamily.get())); |
-} |
- |
-SkFontStyleSet* SkFontMgr_DirectWrite::onMatchFamily(const char familyName[]) const { |
- SkSMallocWCHAR dwFamilyName; |
- HRN(sk_cstring_to_wchar(familyName, &dwFamilyName)); |
- |
- UINT32 index; |
- BOOL exists; |
- HRNM(fFontCollection->FindFamilyName(dwFamilyName.get(), &index, &exists), |
- "Failed while finding family by name."); |
- if (!exists) { |
- return NULL; |
- } |
- |
- return this->onCreateStyleSet(index); |
-} |
- |
-SkTypeface* SkFontMgr_DirectWrite::onMatchFamilyStyle(const char familyName[], |
- const SkFontStyle& fontstyle) const { |
- SkAutoTUnref<SkFontStyleSet> sset(this->matchFamily(familyName)); |
- return sset->matchStyle(fontstyle); |
-} |
- |
-SkTypeface* SkFontMgr_DirectWrite::onMatchFaceStyle(const SkTypeface* familyMember, |
- const SkFontStyle& fontstyle) const { |
- SkString familyName; |
- SkFontStyleSet_DirectWrite sset( |
- this, ((DWriteFontTypeface*)familyMember)->fDWriteFontFamily.get() |
- ); |
- return sset.matchStyle(fontstyle); |
-} |
- |
-SkTypeface* SkFontMgr_DirectWrite::onCreateFromStream(SkStream* stream, int ttcIndex) const { |
- SkTScopedComPtr<StreamFontFileLoader> fontFileLoader; |
- HRN(StreamFontFileLoader::Create(stream, &fontFileLoader)); |
- HRN(fFactory->RegisterFontFileLoader(fontFileLoader.get())); |
- SkAutoIDWriteUnregister<StreamFontFileLoader> autoUnregisterFontFileLoader( |
- fFactory.get(), fontFileLoader.get()); |
- |
- SkTScopedComPtr<StreamFontCollectionLoader> fontCollectionLoader; |
- HRN(StreamFontCollectionLoader::Create(fontFileLoader.get(), &fontCollectionLoader)); |
- HRN(fFactory->RegisterFontCollectionLoader(fontCollectionLoader.get())); |
- SkAutoIDWriteUnregister<StreamFontCollectionLoader> autoUnregisterFontCollectionLoader( |
- fFactory.get(), fontCollectionLoader.get()); |
- |
- SkTScopedComPtr<IDWriteFontCollection> fontCollection; |
- HRN(fFactory->CreateCustomFontCollection(fontCollectionLoader.get(), NULL, 0, &fontCollection)); |
- |
- // Find the first non-simulated font which has the given ttc index. |
- UINT32 familyCount = fontCollection->GetFontFamilyCount(); |
- for (UINT32 familyIndex = 0; familyIndex < familyCount; ++familyIndex) { |
- SkTScopedComPtr<IDWriteFontFamily> fontFamily; |
- HRN(fontCollection->GetFontFamily(familyIndex, &fontFamily)); |
- |
- UINT32 fontCount = fontFamily->GetFontCount(); |
- for (UINT32 fontIndex = 0; fontIndex < fontCount; ++fontIndex) { |
- SkTScopedComPtr<IDWriteFont> font; |
- HRN(fontFamily->GetFont(fontIndex, &font)); |
- if (font->GetSimulations() != DWRITE_FONT_SIMULATIONS_NONE) { |
- continue; |
- } |
- |
- SkTScopedComPtr<IDWriteFontFace> fontFace; |
- HRN(font->CreateFontFace(&fontFace)); |
- |
- UINT32 faceIndex = fontFace->GetIndex(); |
- if (faceIndex == ttcIndex) { |
- return DWriteFontTypeface::Create(fFactory.get(), |
- fontFace.get(), font.get(), fontFamily.get(), |
- autoUnregisterFontFileLoader.detatch(), |
- autoUnregisterFontCollectionLoader.detatch()); |
- } |
- } |
- } |
- |
- return NULL; |
-} |
- |
-SkTypeface* SkFontMgr_DirectWrite::onCreateFromData(SkData* data, int ttcIndex) const { |
- SkAutoTUnref<SkStream> stream(SkNEW_ARGS(SkMemoryStream, (data))); |
- return this->createFromStream(stream, ttcIndex); |
-} |
- |
-SkTypeface* SkFontMgr_DirectWrite::onCreateFromFile(const char path[], int ttcIndex) const { |
- SkAutoTUnref<SkStream> stream(SkStream::NewFromFile(path)); |
- return this->createFromStream(stream, ttcIndex); |
-} |
- |
-HRESULT SkFontMgr_DirectWrite::getByFamilyName(const WCHAR wideFamilyName[], |
- IDWriteFontFamily** fontFamily) const { |
- UINT32 index; |
- BOOL exists; |
- HR(fFontCollection->FindFamilyName(wideFamilyName, &index, &exists)); |
- |
- if (exists) { |
- HR(fFontCollection->GetFontFamily(index, fontFamily)); |
- } |
- return S_OK; |
-} |
- |
-HRESULT SkFontMgr_DirectWrite::getDefaultFontFamily(IDWriteFontFamily** fontFamily) const { |
- NONCLIENTMETRICSW metrics; |
- metrics.cbSize = sizeof(metrics); |
- if (0 == SystemParametersInfoW(SPI_GETNONCLIENTMETRICS, |
- sizeof(metrics), |
- &metrics, |
- 0)) { |
- return E_UNEXPECTED; |
- } |
- HRM(this->getByFamilyName(metrics.lfMessageFont.lfFaceName, fontFamily), |
- "Could not create DWrite font family from LOGFONT."); |
- return S_OK; |
-} |
- |
-SkTypeface* SkFontMgr_DirectWrite::onLegacyCreateTypeface(const char familyName[], |
- unsigned styleBits) const { |
- SkTScopedComPtr<IDWriteFontFamily> fontFamily; |
- if (familyName) { |
- SkSMallocWCHAR wideFamilyName; |
- if (SUCCEEDED(sk_cstring_to_wchar(familyName, &wideFamilyName))) { |
- this->getByFamilyName(wideFamilyName, &fontFamily); |
- } |
- } |
- |
- if (NULL == fontFamily.get()) { |
- // No family with given name, try default. |
- HRNM(this->getDefaultFontFamily(&fontFamily), "Could not get default font family."); |
- } |
- |
- if (NULL == fontFamily.get()) { |
- // Could not obtain the default font. |
- HRNM(fFontCollection->GetFontFamily(0, &fontFamily), |
- "Could not get default-default font family."); |
- } |
- |
- SkTScopedComPtr<IDWriteFont> font; |
- DWRITE_FONT_WEIGHT weight = (styleBits & SkTypeface::kBold) |
- ? DWRITE_FONT_WEIGHT_BOLD |
- : DWRITE_FONT_WEIGHT_NORMAL; |
- DWRITE_FONT_STRETCH stretch = DWRITE_FONT_STRETCH_NORMAL; |
- DWRITE_FONT_STYLE italic = (styleBits & SkTypeface::kItalic) |
- ? DWRITE_FONT_STYLE_ITALIC |
- : DWRITE_FONT_STYLE_NORMAL; |
- HRNM(fontFamily->GetFirstMatchingFont(weight, stretch, italic, &font), |
- "Could not get matching font."); |
- |
- SkTScopedComPtr<IDWriteFontFace> fontFace; |
- HRNM(font->CreateFontFace(&fontFace), "Could not create font face."); |
- |
- return this->createTypefaceFromDWriteFont(fontFace.get(), font.get(), fontFamily.get()); |
-} |
- |
-/////////////////////////////////////////////////////////////////////////////// |
- |
-int SkFontStyleSet_DirectWrite::count() { |
- return fFontFamily->GetFontCount(); |
-} |
- |
-SkTypeface* SkFontStyleSet_DirectWrite::createTypeface(int index) { |
- SkTScopedComPtr<IDWriteFont> font; |
- HRNM(fFontFamily->GetFont(index, &font), "Could not get font."); |
- |
- SkTScopedComPtr<IDWriteFontFace> fontFace; |
- HRNM(font->CreateFontFace(&fontFace), "Could not create font face."); |
- |
- return fFontMgr->createTypefaceFromDWriteFont(fontFace.get(), font.get(), fFontFamily.get()); |
-} |
- |
-void SkFontStyleSet_DirectWrite::getStyle(int index, SkFontStyle* fs, SkString* styleName) { |
- SkTScopedComPtr<IDWriteFont> font; |
- HRVM(fFontFamily->GetFont(index, &font), "Could not get font."); |
- |
- if (fs) { |
- SkFontStyle::Slant slant; |
- switch (font->GetStyle()) { |
- case DWRITE_FONT_STYLE_NORMAL: |
- slant = SkFontStyle::kUpright_Slant; |
- break; |
- case DWRITE_FONT_STYLE_OBLIQUE: |
- case DWRITE_FONT_STYLE_ITALIC: |
- slant = SkFontStyle::kItalic_Slant; |
- break; |
- default: |
- SkASSERT(false); |
- } |
- |
- int weight = font->GetWeight(); |
- int width = font->GetStretch(); |
- |
- *fs = SkFontStyle(weight, width, slant); |
- } |
- |
- if (styleName) { |
- SkTScopedComPtr<IDWriteLocalizedStrings> faceNames; |
- if (SUCCEEDED(font->GetFaceNames(&faceNames))) { |
- sk_get_locale_string(faceNames.get(), fFontMgr->fLocaleName.get(), styleName); |
- } |
- } |
-} |
- |
-SkTypeface* SkFontStyleSet_DirectWrite::matchStyle(const SkFontStyle& pattern) { |
- DWRITE_FONT_STYLE slant; |
- switch (pattern.slant()) { |
- case SkFontStyle::kUpright_Slant: |
- slant = DWRITE_FONT_STYLE_NORMAL; |
- break; |
- case SkFontStyle::kItalic_Slant: |
- slant = DWRITE_FONT_STYLE_ITALIC; |
- break; |
- default: |
- SkASSERT(false); |
- } |
- |
- DWRITE_FONT_WEIGHT weight = (DWRITE_FONT_WEIGHT)pattern.weight(); |
- DWRITE_FONT_STRETCH width = (DWRITE_FONT_STRETCH)pattern.width(); |
- |
- SkTScopedComPtr<IDWriteFont> font; |
- // TODO: perhaps use GetMatchingFonts and get the least simulated? |
- HRNM(fFontFamily->GetFirstMatchingFont(weight, width, slant, &font), |
- "Could not match font in family."); |
- |
- SkTScopedComPtr<IDWriteFontFace> fontFace; |
- HRNM(font->CreateFontFace(&fontFace), "Could not create font face."); |
- |
- return fFontMgr->createTypefaceFromDWriteFont(fontFace.get(), font.get(), |
- fFontFamily.get()); |
-} |
- |
-/////////////////////////////////////////////////////////////////////////////// |
- |
-SkFontMgr* SkFontMgr_New_DirectWrite(IDWriteFactory* factory) { |
- if (NULL == factory) { |
- factory = sk_get_dwrite_factory(); |
- if (NULL == factory) { |
- return NULL; |
- } |
- } |
- |
- SkTScopedComPtr<IDWriteFontCollection> sysFontCollection; |
- HRNM(factory->GetSystemFontCollection(&sysFontCollection, FALSE), |
- "Could not get system font collection."); |
- |
- WCHAR localeNameStorage[LOCALE_NAME_MAX_LENGTH]; |
- WCHAR* localeName = NULL; |
- int localeNameLen = 0; |
- |
- // Dynamically load GetUserDefaultLocaleName function, as it is not available on XP. |
- SkGetUserDefaultLocaleNameProc getUserDefaultLocaleNameProc = NULL; |
- HRESULT hr = SkGetGetUserDefaultLocaleNameProc(&getUserDefaultLocaleNameProc); |
- if (NULL == getUserDefaultLocaleNameProc) { |
- SK_TRACEHR(hr, "Could not get GetUserDefaultLocaleName."); |
- } else { |
- localeNameLen = getUserDefaultLocaleNameProc(localeNameStorage, LOCALE_NAME_MAX_LENGTH); |
- if (localeNameLen) { |
- localeName = localeNameStorage; |
- }; |
- } |
- |
- return SkNEW_ARGS(SkFontMgr_DirectWrite, (factory, sysFontCollection.get(), |
- localeName, localeNameLen)); |
-} |
- |
-#include "SkFontMgr_indirect.h" |
-SkFontMgr* SkFontMgr_New_DirectWriteRenderer(SkRemotableFontMgr* proxy) { |
- SkAutoTUnref<SkFontMgr> impl(SkFontMgr_New_DirectWrite()); |
- if (impl.get() == NULL) { |
- return NULL; |
- } |
- return SkNEW_ARGS(SkFontMgr_Indirect, (impl.get(), proxy)); |
-} |