diff --git a/Common/Gfx/CanvasD2D.cpp b/Common/Gfx/CanvasD2D.cpp index 2df1ed2f..1d458707 100644 --- a/Common/Gfx/CanvasD2D.cpp +++ b/Common/Gfx/CanvasD2D.cpp @@ -18,6 +18,7 @@ #include "CanvasD2D.h" #include "TextFormatD2D.h" +#include "Util/DWriteFontCollectionLoader.h" #include "WICBitmapLockGDIP.h" #include "../../Library/Litestep.h" @@ -106,6 +107,9 @@ bool CanvasD2D::Initialize() hr = c_DWFactory->GetGdiInterop(&c_DWGDIInterop); if (FAILED(hr)) return false; + + hr = c_DWFactory->RegisterFontCollectionLoader(Util::DWriteFontCollectionLoader::GetInstance()); + if (FAILED(hr)) return false; } return true; @@ -119,6 +123,8 @@ void CanvasD2D::Finalize() SafeRelease(&c_D2DFactory); SafeRelease(&c_WICFactory); SafeRelease(&c_DWGDIInterop); + + c_DWFactory->UnregisterFontCollectionLoader(Util::DWriteFontCollectionLoader::GetInstance()); SafeRelease(&c_DWFactory); } } diff --git a/Common/Gfx/CanvasD2D.h b/Common/Gfx/CanvasD2D.h index a1f7cea9..76d444d9 100644 --- a/Common/Gfx/CanvasD2D.h +++ b/Common/Gfx/CanvasD2D.h @@ -73,6 +73,7 @@ public: virtual void FillRectangle(Gdiplus::Rect& rect, const Gdiplus::SolidBrush& brush) override; private: + friend class FontCollectionD2D; friend class TextFormatD2D; CanvasD2D(const CanvasD2D& other) {} diff --git a/Common/Gfx/FontCollectionD2D.cpp b/Common/Gfx/FontCollectionD2D.cpp index ff784e30..1692513a 100644 --- a/Common/Gfx/FontCollectionD2D.cpp +++ b/Common/Gfx/FontCollectionD2D.cpp @@ -17,22 +17,63 @@ */ #include "FontCollectionD2D.h" +#include "CanvasD2D.h" +#include "Util/DWriteFontCollectionLoader.h" #include namespace Gfx { -FontCollectionD2D::FontCollectionD2D() : FontCollection() +FontCollectionD2D::FontCollectionD2D() : FontCollection(), + m_Collection() { } FontCollectionD2D::~FontCollectionD2D() { + Dispose(); +} + +void FontCollectionD2D::Dispose() +{ + for (IDWriteFontFile* fileReference : m_FileReferences) + { + fileReference->Release(); + } + m_FileReferences.clear(); +} + +bool FontCollectionD2D::InitializeCollection() +{ + if (!m_Collection) + { + auto loader = Util::DWriteFontCollectionLoader::GetInstance(); + CanvasD2D::c_DWFactory->CreateCustomFontCollection( + loader, &m_FileReferences, sizeof(m_FileReferences), &m_Collection); + } + + return m_Collection; } bool FontCollectionD2D::AddFile(const WCHAR* file) { - // FIXME. - return true; + // If DirecWrite font collection already exists, we need to destroy it as fonts cannot be added to + // an existing collection. The collection will be recreated on the next call to + // InitializeCollection(). + if (m_Collection) + { + m_Collection->Release(); + m_Collection = nullptr; + } + + IDWriteFontFile* fileReference; + HRESULT hr = CanvasD2D::c_DWFactory->CreateFontFileReference(file, nullptr, &fileReference); + if (SUCCEEDED(hr)) + { + m_FileReferences.push_back(fileReference); + return true; + } + + return false; } } // namespace Gfx diff --git a/Common/Gfx/FontCollectionD2D.h b/Common/Gfx/FontCollectionD2D.h index 2658fa39..c434fa10 100644 --- a/Common/Gfx/FontCollectionD2D.h +++ b/Common/Gfx/FontCollectionD2D.h @@ -20,6 +20,8 @@ #define RM_GFX_FONTCOLLECTIOND2D_H_ #include "FontCollection.h" +#include +#include namespace Gfx { @@ -41,6 +43,11 @@ private: FontCollectionD2D(const FontCollectionD2D& other) {} void Dispose(); + + bool InitializeCollection(); + + std::vector m_FileReferences; + IDWriteFontCollection* m_Collection; }; } // namespace Gfx diff --git a/Common/Gfx/Util/DWriteFontCollectionLoader.cpp b/Common/Gfx/Util/DWriteFontCollectionLoader.cpp new file mode 100644 index 00000000..97bcb735 --- /dev/null +++ b/Common/Gfx/Util/DWriteFontCollectionLoader.cpp @@ -0,0 +1,67 @@ +/* + Copyright (C) 2013 Birunthan Mohanathas + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +#include "DWriteFontCollectionLoader.h" +#include "DWriteFontFileEnumerator.h" +#include + +namespace Gfx { +namespace Util { + +DWriteFontCollectionLoader* DWriteFontCollectionLoader::GetInstance() +{ + static DWriteFontCollectionLoader s_Instance; + return &s_Instance; +} + +ULONG STDMETHODCALLTYPE DWriteFontCollectionLoader::AddRef() +{ + // This is a singleton class so return a dummy value. + return 1; +} + +ULONG STDMETHODCALLTYPE DWriteFontCollectionLoader::Release() +{ + // This is a singleton class so return a dummy value. + return 1; +} + +HRESULT STDMETHODCALLTYPE DWriteFontCollectionLoader::QueryInterface(IID const& riid, void** ppvObject) +{ + if (riid == IID_IUnknown || + riid == __uuidof(IDWriteFontCollectionLoader)) + { + *ppvObject = this; + return S_OK; + } + + *ppvObject = NULL; + return E_NOINTERFACE; +} + +HRESULT STDMETHODCALLTYPE DWriteFontCollectionLoader::CreateEnumeratorFromKey( + IDWriteFactory* factory, void const* collectionKey, UINT32 collectionKeySize, + IDWriteFontFileEnumerator** fontFileEnumerator) +{ + *fontFileEnumerator = new DWriteFontFileEnumerator( + *(const std::vector*)collectionKey); + return S_OK; +} + +} // namespace Util +} // namespace Gfx diff --git a/Common/Gfx/Util/DWriteFontCollectionLoader.h b/Common/Gfx/Util/DWriteFontCollectionLoader.h new file mode 100644 index 00000000..0889a85f --- /dev/null +++ b/Common/Gfx/Util/DWriteFontCollectionLoader.h @@ -0,0 +1,53 @@ +/* + Copyright (C) 2013 Birunthan Mohanathas + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +#ifndef RM_GFX_UTIL_DWRITEFONTCOLLECTIONLOADER_H_ +#define RM_GFX_UTIL_DWRITEFONTCOLLECTIONLOADER_H_ + +#include + +namespace Gfx { +namespace Util { + +// Implements the IDWriteFontCollectionLoader interface as a singleton object. When +// CreateEnumeratorFromKey is called, a new DWriteFontFileEnumerator object is created using +// |fontCollectionKey| (which is assumed to be a pointer to std::vector). +class DWriteFontCollectionLoader : public IDWriteFontCollectionLoader +{ +public: + static DWriteFontCollectionLoader* GetInstance(); + + // IUnknown + virtual HRESULT STDMETHODCALLTYPE QueryInterface(REFIID uuid, void** object) override; + virtual ULONG STDMETHODCALLTYPE AddRef() override; + virtual ULONG STDMETHODCALLTYPE Release() override; + + // IFontCollectionLoader + virtual HRESULT STDMETHODCALLTYPE CreateEnumeratorFromKey( + IDWriteFactory* factory, void const* fontCollectionKey, UINT32 fontCollectionKeySize, + IDWriteFontFileEnumerator** fontFileEnumerator) override; + +private: + DWriteFontCollectionLoader() {} + DWriteFontCollectionLoader(const DWriteFontCollectionLoader& other) {} +}; + +} // namespace Util +} // namespace Gfx + +#endif \ No newline at end of file diff --git a/Common/Gfx/Util/DWriteFontFileEnumerator.cpp b/Common/Gfx/Util/DWriteFontFileEnumerator.cpp new file mode 100644 index 00000000..ea8e0cb3 --- /dev/null +++ b/Common/Gfx/Util/DWriteFontFileEnumerator.cpp @@ -0,0 +1,77 @@ +/* + Copyright (C) 2013 Birunthan Mohanathas + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +#include "DWriteFontFileEnumerator.h" + +namespace Gfx { +namespace Util { + +DWriteFontFileEnumerator::DWriteFontFileEnumerator(const std::vector& fontFiles) : + m_RefCount(1), + m_FontFiles(fontFiles), + m_CurrentFontFileIndex(-1) +{ +} + +ULONG STDMETHODCALLTYPE DWriteFontFileEnumerator::AddRef() +{ + ++m_RefCount; + return m_RefCount; +} + +ULONG STDMETHODCALLTYPE DWriteFontFileEnumerator::Release() +{ + --m_RefCount; + if (m_RefCount == 0) + { + delete this; + return 0; + } + return m_RefCount; +} + +HRESULT STDMETHODCALLTYPE DWriteFontFileEnumerator::QueryInterface(IID const& riid, void** ppvObject) +{ + if (riid == IID_IUnknown || + riid == __uuidof(IDWriteFontFileEnumerator)) + { + *ppvObject = this; + AddRef(); + return S_OK; + } + + *ppvObject = NULL; + return E_NOINTERFACE; +} + +HRESULT STDMETHODCALLTYPE DWriteFontFileEnumerator::MoveNext(BOOL* hasCurrentFile) +{ + *hasCurrentFile = (++m_CurrentFontFileIndex < m_FontFiles.size()); + return S_OK; +} + +HRESULT STDMETHODCALLTYPE DWriteFontFileEnumerator::GetCurrentFontFile(IDWriteFontFile** fontFile) +{ + IDWriteFontFile* currentFontFile = m_FontFiles[m_CurrentFontFileIndex]; + currentFontFile->AddRef(); + *fontFile = currentFontFile; + return S_OK; +} + +} // namespace Util +} // namespace Gfx diff --git a/Common/Gfx/Util/DWriteFontFileEnumerator.h b/Common/Gfx/Util/DWriteFontFileEnumerator.h new file mode 100644 index 00000000..77d2d494 --- /dev/null +++ b/Common/Gfx/Util/DWriteFontFileEnumerator.h @@ -0,0 +1,56 @@ +/* + Copyright (C) 2013 Birunthan Mohanathas + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +#ifndef RM_GFX_UTIL_DWRITEFONTFILEENUMERATOR_H_ +#define RM_GFX_UTIL_DWRITEFONTFILEENUMERATOR_H_ + +#include +#include + +namespace Gfx { +namespace Util { + +// Implements IDWriteFontFileEnumerator by enumerating over std::vector. +class DWriteFontFileEnumerator : public IDWriteFontFileEnumerator +{ +public: + DWriteFontFileEnumerator(const std::vector& fontFiles); + + // IUnknown + virtual HRESULT STDMETHODCALLTYPE QueryInterface(REFIID uuid, void** object) override; + virtual ULONG STDMETHODCALLTYPE AddRef() override; + virtual ULONG STDMETHODCALLTYPE Release() override; + + // IDWriteFontFileEnumerator + virtual HRESULT STDMETHODCALLTYPE MoveNext(BOOL* hasCurrentFile) override; + virtual HRESULT STDMETHODCALLTYPE GetCurrentFontFile(IDWriteFontFile** currentFontFile) override; + +private: + ULONG m_RefCount; + + const std::vector& m_FontFiles; + + // Current index of |m_FontFiles|. The type is int instead of size_t as it starts from -1 as + // required by IDWriteFontFileEnumerator. + int m_CurrentFontFileIndex; +}; + +} // namespace Util +} // namespace Gfx + +#endif \ No newline at end of file diff --git a/Library/Library.vcxproj b/Library/Library.vcxproj index 8dacc5b6..e99ec640 100644 --- a/Library/Library.vcxproj +++ b/Library/Library.vcxproj @@ -74,6 +74,8 @@ + + @@ -296,6 +298,8 @@ + + diff --git a/Library/Library.vcxproj.filters b/Library/Library.vcxproj.filters index ef35c777..d4ee2a13 100644 --- a/Library/Library.vcxproj.filters +++ b/Library/Library.vcxproj.filters @@ -31,6 +31,9 @@ {26d9c191-5857-45c2-9e73-b0b88964728f} + + {acfbb3c5-84fd-471f-845c-f7d178d35c55} + @@ -369,6 +372,12 @@ Common\Gfx + + Common\Gfx\Util + + + Common\Gfx\Util + Common\Gfx @@ -650,6 +659,12 @@ Common\Gfx + + Common\Gfx\Util + + + Common\Gfx\Util + Common\Gfx