Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1273)

Unified Diff: src/ports/SkFontMgr_win_dw.cpp

Issue 314193002: Split SkFontHost_win_dw. (Closed) Base URL: https://skia.googlesource.com/skia.git@master
Patch Set: Remove unneeded includes. Created 6 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « src/ports/SkFontHost_win_dw.cpp ('k') | src/ports/SkScalerContext_win_dw.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/ports/SkFontMgr_win_dw.cpp
diff --git a/src/ports/SkFontMgr_win_dw.cpp b/src/ports/SkFontMgr_win_dw.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..fe82258c6803e9aaaeb54fad4f9e346fa4a6895e
--- /dev/null
+++ b/src/ports/SkFontMgr_win_dw.cpp
@@ -0,0 +1,774 @@
+/*
+ * Copyright 2014 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include "SkDWrite.h"
+#include "SkDWriteFontFileStream.h"
+#include "SkFontMgr.h"
+#include "SkHRESULT.h"
+#include "SkStream.h"
+#include "SkTScopedComPtr.h"
+#include "SkThread.h"
+#include "SkTypeface.h"
+#include "SkTypefaceCache.h"
+#include "SkTypeface_win_dw.h"
+#include "SkTypes.h"
+
+#include <dwrite.h>
+
+////////////////////////////////////////////////////////////////////////////////
+
+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;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+
+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;
+};
+
+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, 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;
+}
+
+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);
+}
+
+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;
+};
+
+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"
+#include "SkTypeface_win.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));
+}
« no previous file with comments | « src/ports/SkFontHost_win_dw.cpp ('k') | src/ports/SkScalerContext_win_dw.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698