| 
									
										
										
										
											2019-08-18 10:23:54 +08:00
										 |  |  | // Copyright (c) 2016-2018 Kiwano - Nomango
 | 
					
						
							|  |  |  | // 
 | 
					
						
							|  |  |  | // Permission is hereby granted, free of charge, to any person obtaining a copy
 | 
					
						
							|  |  |  | // of this software and associated documentation files (the "Software"), to deal
 | 
					
						
							|  |  |  | // in the Software without restriction, including without limitation the rights
 | 
					
						
							|  |  |  | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 | 
					
						
							|  |  |  | // copies of the Software, and to permit persons to whom the Software is
 | 
					
						
							|  |  |  | // furnished to do so, subject to the following conditions:
 | 
					
						
							|  |  |  | // 
 | 
					
						
							|  |  |  | // The above copyright notice and this permission notice shall be included in
 | 
					
						
							|  |  |  | // all copies or substantial portions of the Software.
 | 
					
						
							|  |  |  | // 
 | 
					
						
							|  |  |  | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 | 
					
						
							|  |  |  | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 | 
					
						
							|  |  |  | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 | 
					
						
							|  |  |  | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 | 
					
						
							|  |  |  | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 | 
					
						
							|  |  |  | // _Out_ OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 | 
					
						
							|  |  |  | // THE SOFTWARE.
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include "FontCollectionLoader.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | namespace kiwano | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	////////////////////////////////////////////////////////////////////////////////////////
 | 
					
						
							|  |  |  | 	//
 | 
					
						
							|  |  |  | 	// FontCollectionLoader
 | 
					
						
							|  |  |  | 	//
 | 
					
						
							|  |  |  | 	////////////////////////////////////////////////////////////////////////////////////////
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	class FontCollectionLoader | 
					
						
							|  |  |  | 		: public IFontCollectionLoader | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 	public: | 
					
						
							|  |  |  | 		FontCollectionLoader() | 
					
						
							|  |  |  | 			: refCount_(0) | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-08-18 17:49:13 +08:00
										 |  |  | 		STDMETHOD(AddFilePaths)( | 
					
						
							|  |  |  | 			Vector<String> const& filePaths, | 
					
						
							|  |  |  | 			_Out_ LPVOID* pCollectionKey, | 
					
						
							| 
									
										
										
										
											2019-08-18 22:49:44 +08:00
										 |  |  | 			_Out_ UInt32* pCollectionKeySize | 
					
						
							| 
									
										
										
										
											2019-08-18 17:49:13 +08:00
										 |  |  | 		); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-08-18 10:23:54 +08:00
										 |  |  | 		// 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* pFactory, | 
					
						
							|  |  |  | 			void const* collectionKey, | 
					
						
							| 
									
										
										
										
											2019-08-18 22:49:44 +08:00
										 |  |  | 			UInt32 collectionKeySize, | 
					
						
							| 
									
										
										
										
											2019-08-18 10:23:54 +08:00
										 |  |  | 			_Out_ IDWriteFontFileEnumerator** fontFileEnumerator | 
					
						
							|  |  |  | 		); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	private: | 
					
						
							|  |  |  | 		ULONG refCount_; | 
					
						
							| 
									
										
										
										
											2019-08-18 17:49:13 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		typedef Vector<String> FileCollection; | 
					
						
							|  |  |  | 		Vector<FileCollection> filePaths_; | 
					
						
							| 
									
										
										
										
											2019-08-18 22:49:44 +08:00
										 |  |  | 		Vector<UInt32> collectionKeys_; | 
					
						
							| 
									
										
										
										
											2019-08-18 10:23:54 +08:00
										 |  |  | 	}; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	HRESULT IFontCollectionLoader::Create(_Out_ IFontCollectionLoader** ppCollectionLoader) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		HRESULT hr = S_OK; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		if (!ppCollectionLoader) | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			hr = E_POINTER; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		if (SUCCEEDED(hr)) | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			FontCollectionLoader* pCollectionLoader = new (std::nothrow) FontCollectionLoader; | 
					
						
							|  |  |  | 			hr = pCollectionLoader ? S_OK : E_OUTOFMEMORY; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			if (SUCCEEDED(hr)) | 
					
						
							|  |  |  | 			{ | 
					
						
							|  |  |  | 				DX::SafeRelease(*ppCollectionLoader); | 
					
						
							|  |  |  | 				(*ppCollectionLoader) = DX::SafeAcquire(pCollectionLoader); | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		return hr; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-08-18 17:49:13 +08:00
										 |  |  | 	STDMETHODIMP FontCollectionLoader::AddFilePaths( | 
					
						
							|  |  |  | 		Vector<String> const& filePaths, | 
					
						
							|  |  |  | 		_Out_ LPVOID* pCollectionKey, | 
					
						
							| 
									
										
										
										
											2019-08-18 22:49:44 +08:00
										 |  |  | 		_Out_ UInt32* pCollectionKeySize | 
					
						
							| 
									
										
										
										
											2019-08-18 17:49:13 +08:00
										 |  |  | 	) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		if (!pCollectionKey || !pCollectionKeySize) | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			return E_INVALIDARG; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		try | 
					
						
							|  |  |  | 		{ | 
					
						
							| 
									
										
										
										
											2019-08-18 22:49:44 +08:00
										 |  |  | 			UInt32 collectionKey = filePaths_.size(); | 
					
						
							| 
									
										
										
										
											2019-08-18 17:49:13 +08:00
										 |  |  | 			collectionKeys_.push_back(collectionKey); | 
					
						
							|  |  |  | 			filePaths_.push_back(filePaths); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			*pCollectionKey = reinterpret_cast<LPVOID>(&collectionKeys_.back()); | 
					
						
							|  |  |  | 			*pCollectionKeySize = sizeof(collectionKey); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		catch (std::bad_alloc&) | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			return E_OUTOFMEMORY; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		catch (...) | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			return E_FAIL; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		return S_OK; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-08-18 10:23:54 +08:00
										 |  |  | 	HRESULT STDMETHODCALLTYPE FontCollectionLoader::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 STDMETHODCALLTYPE FontCollectionLoader::AddRef() | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		return InterlockedIncrement(&refCount_); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	ULONG STDMETHODCALLTYPE FontCollectionLoader::Release() | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		ULONG newCount = InterlockedDecrement(&refCount_); | 
					
						
							|  |  |  | 		if (newCount == 0) | 
					
						
							|  |  |  | 			delete this; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		return newCount; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	HRESULT STDMETHODCALLTYPE FontCollectionLoader::CreateEnumeratorFromKey( | 
					
						
							|  |  |  | 		IDWriteFactory* pFactory, | 
					
						
							|  |  |  | 		void const* collectionKey, | 
					
						
							| 
									
										
										
										
											2019-08-18 22:49:44 +08:00
										 |  |  | 		UInt32 collectionKeySize, | 
					
						
							| 
									
										
										
										
											2019-08-18 10:23:54 +08:00
										 |  |  | 		_Out_ IDWriteFontFileEnumerator** fontFileEnumerator | 
					
						
							|  |  |  | 	) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		HRESULT hr = S_OK; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-08-18 22:49:44 +08:00
										 |  |  | 		if (collectionKey == NULL || collectionKeySize % sizeof(UInt32) != 0) | 
					
						
							| 
									
										
										
										
											2019-08-18 10:23:54 +08:00
										 |  |  | 			hr = E_INVALIDARG; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		if (SUCCEEDED(hr)) | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			IFontFileEnumerator* pEnumerator = NULL; | 
					
						
							|  |  |  | 			hr = IFontFileEnumerator::Create(&pEnumerator, pFactory); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			if (SUCCEEDED(hr)) | 
					
						
							|  |  |  | 			{ | 
					
						
							| 
									
										
										
										
											2019-08-18 22:49:44 +08:00
										 |  |  | 				const UInt32 fileIndex = *static_cast<UInt32 const*>(collectionKey); | 
					
						
							| 
									
										
										
										
											2019-08-18 17:49:13 +08:00
										 |  |  | 				hr = pEnumerator->SetFilePaths(filePaths_[fileIndex]); | 
					
						
							| 
									
										
										
										
											2019-08-18 10:23:54 +08:00
										 |  |  | 			} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			if (SUCCEEDED(hr)) | 
					
						
							|  |  |  | 			{ | 
					
						
							|  |  |  | 				*fontFileEnumerator = DX::SafeAcquire(pEnumerator); | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		return hr; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	////////////////////////////////////////////////////////////////////////////////////////
 | 
					
						
							|  |  |  | 	//
 | 
					
						
							|  |  |  | 	// FontFileEnumerator
 | 
					
						
							|  |  |  | 	//
 | 
					
						
							|  |  |  | 	////////////////////////////////////////////////////////////////////////////////////////
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	class FontFileEnumerator | 
					
						
							|  |  |  | 		: public IFontFileEnumerator | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 	public: | 
					
						
							|  |  |  | 		FontFileEnumerator(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		STDMETHOD(Initialize)( | 
					
						
							|  |  |  | 			IDWriteFactory* pFactory | 
					
						
							|  |  |  | 		); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		STDMETHOD(SetFilePaths)( | 
					
						
							| 
									
										
										
										
											2019-08-18 17:49:13 +08:00
										 |  |  | 			Vector<String> const& filePaths | 
					
						
							| 
									
										
										
										
											2019-08-18 10:23:54 +08:00
										 |  |  | 		); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		~FontFileEnumerator() | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			DX::SafeRelease(currentFile_); | 
					
						
							|  |  |  | 			DX::SafeRelease(pFactory_); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		// IUnknown methods
 | 
					
						
							|  |  |  | 		virtual HRESULT STDMETHODCALLTYPE QueryInterface(REFIID iid, _Out_ void** ppvObject); | 
					
						
							|  |  |  | 		virtual ULONG STDMETHODCALLTYPE AddRef(); | 
					
						
							|  |  |  | 		virtual ULONG STDMETHODCALLTYPE Release(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		// IDWriteFontFileEnumerator methods
 | 
					
						
							|  |  |  | 		virtual HRESULT STDMETHODCALLTYPE MoveNext(_Out_ BOOL* hasCurrentFile); | 
					
						
							|  |  |  | 		virtual HRESULT STDMETHODCALLTYPE GetCurrentFontFile(_Out_ IDWriteFontFile** fontFile); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	private: | 
					
						
							|  |  |  | 		ULONG refCount_; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		IDWriteFactory* pFactory_; | 
					
						
							|  |  |  | 		IDWriteFontFile* currentFile_; | 
					
						
							|  |  |  | 		Vector<String> filePaths_; | 
					
						
							| 
									
										
										
										
											2019-08-18 22:49:44 +08:00
										 |  |  | 		UInt32 nextIndex_; | 
					
						
							| 
									
										
										
										
											2019-08-18 10:23:54 +08:00
										 |  |  | 	}; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	HRESULT IFontFileEnumerator::Create(_Out_ IFontFileEnumerator** ppEnumerator, IDWriteFactory* pFactory) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		HRESULT hr = S_OK; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		if (!ppEnumerator) | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			hr = E_POINTER; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		if (SUCCEEDED(hr)) | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			FontFileEnumerator* pEnumerator = new (std::nothrow) FontFileEnumerator; | 
					
						
							|  |  |  | 			hr = pEnumerator ? S_OK : E_OUTOFMEMORY; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			if (SUCCEEDED(hr)) | 
					
						
							|  |  |  | 			{ | 
					
						
							|  |  |  | 				hr = pEnumerator->Initialize(pFactory); | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			if (SUCCEEDED(hr)) | 
					
						
							|  |  |  | 			{ | 
					
						
							|  |  |  | 				DX::SafeRelease(*ppEnumerator); | 
					
						
							|  |  |  | 				(*ppEnumerator) = DX::SafeAcquire(pEnumerator); | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		return hr; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	FontFileEnumerator::FontFileEnumerator() | 
					
						
							|  |  |  | 		: refCount_(0) | 
					
						
							|  |  |  | 		, pFactory_(NULL) | 
					
						
							|  |  |  | 		, currentFile_(NULL) | 
					
						
							|  |  |  | 		, nextIndex_(0) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	STDMETHODIMP FontFileEnumerator::Initialize( | 
					
						
							|  |  |  | 		IDWriteFactory* pFactory | 
					
						
							|  |  |  | 	) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		if (pFactory) | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			pFactory_ = DX::SafeAcquire(pFactory); | 
					
						
							|  |  |  | 			return S_OK; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		return E_INVALIDARG; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	STDMETHODIMP FontFileEnumerator::SetFilePaths( | 
					
						
							| 
									
										
										
										
											2019-08-18 17:49:13 +08:00
										 |  |  | 		Vector<String> const& filePaths | 
					
						
							| 
									
										
										
										
											2019-08-18 10:23:54 +08:00
										 |  |  | 	) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		try | 
					
						
							|  |  |  | 		{ | 
					
						
							| 
									
										
										
										
											2019-08-18 17:49:13 +08:00
										 |  |  | 			filePaths_.assign(filePaths); | 
					
						
							| 
									
										
										
										
											2019-08-18 10:23:54 +08:00
										 |  |  | 		} | 
					
						
							|  |  |  | 		catch (std::bad_alloc&) | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			return E_OUTOFMEMORY; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		catch (...) | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			return E_FAIL; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		return S_OK; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	HRESULT STDMETHODCALLTYPE FontFileEnumerator::QueryInterface(REFIID iid, _Out_ void** ppvObject) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		if (iid == IID_IUnknown || iid == __uuidof(IDWriteFontFileEnumerator)) | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			*ppvObject = this; | 
					
						
							|  |  |  | 			AddRef(); | 
					
						
							|  |  |  | 			return S_OK; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		else | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			*ppvObject = NULL; | 
					
						
							|  |  |  | 			return E_NOINTERFACE; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	ULONG STDMETHODCALLTYPE FontFileEnumerator::AddRef() | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		return InterlockedIncrement(&refCount_); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	ULONG STDMETHODCALLTYPE FontFileEnumerator::Release() | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		ULONG newCount = InterlockedDecrement(&refCount_); | 
					
						
							|  |  |  | 		if (newCount == 0) | 
					
						
							|  |  |  | 			delete this; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		return newCount; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	HRESULT STDMETHODCALLTYPE FontFileEnumerator::MoveNext(_Out_ BOOL* hasCurrentFile) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		HRESULT hr = S_OK; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		*hasCurrentFile = FALSE; | 
					
						
							|  |  |  | 		DX::SafeRelease(currentFile_); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		if (nextIndex_ < filePaths_.size()) | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			hr = pFactory_->CreateFontFileReference( | 
					
						
							|  |  |  | 				filePaths_[nextIndex_].c_str(), | 
					
						
							|  |  |  | 				NULL, | 
					
						
							|  |  |  | 				¤tFile_ | 
					
						
							|  |  |  | 			); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			if (SUCCEEDED(hr)) | 
					
						
							|  |  |  | 			{ | 
					
						
							|  |  |  | 				*hasCurrentFile = TRUE; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				++nextIndex_; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		return hr; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	HRESULT STDMETHODCALLTYPE FontFileEnumerator::GetCurrentFontFile(_Out_ IDWriteFontFile** fontFile) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		*fontFile = DX::SafeAcquire(currentFile_); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		return (currentFile_ != NULL) ? S_OK : E_FAIL; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	////////////////////////////////////////////////////////////////////////////////////////
 | 
					
						
							|  |  |  | 	//
 | 
					
						
							|  |  |  | 	// ResourceFontCollectionLoader
 | 
					
						
							|  |  |  | 	//
 | 
					
						
							|  |  |  | 	////////////////////////////////////////////////////////////////////////////////////////
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	class ResourceFontCollectionLoader | 
					
						
							|  |  |  | 		: public IResourceFontCollectionLoader | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 	public: | 
					
						
							|  |  |  | 		ResourceFontCollectionLoader(IDWriteFontFileLoader* pFileLoader) | 
					
						
							|  |  |  | 			: refCount_(0) | 
					
						
							|  |  |  | 			, pFileLoader_(pFileLoader) | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-08-18 17:49:13 +08:00
										 |  |  | 		STDMETHOD(AddResources)( | 
					
						
							|  |  |  | 			Vector<Resource> const& resources, | 
					
						
							|  |  |  | 			_Out_ LPVOID* pCollectionKey, | 
					
						
							| 
									
										
										
										
											2019-08-18 22:49:44 +08:00
										 |  |  | 			_Out_ UInt32* pCollectionKeySize | 
					
						
							| 
									
										
										
										
											2019-08-18 17:49:13 +08:00
										 |  |  | 		); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-08-18 10:23:54 +08:00
										 |  |  | 		// 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* pFactory, | 
					
						
							|  |  |  | 			void const* collectionKey, | 
					
						
							| 
									
										
										
										
											2019-08-18 22:49:44 +08:00
										 |  |  | 			UInt32 collectionKeySize, | 
					
						
							| 
									
										
										
										
											2019-08-18 10:23:54 +08:00
										 |  |  | 			_Out_ IDWriteFontFileEnumerator** fontFileEnumerator | 
					
						
							|  |  |  | 		); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	private: | 
					
						
							|  |  |  | 		ULONG refCount_; | 
					
						
							|  |  |  | 		IDWriteFontFileLoader* pFileLoader_; | 
					
						
							| 
									
										
										
										
											2019-08-18 17:49:13 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		typedef Vector<Resource> ResourceCollection; | 
					
						
							|  |  |  | 		Vector<ResourceCollection> resources_; | 
					
						
							| 
									
										
										
										
											2019-08-18 22:49:44 +08:00
										 |  |  | 		Vector<UInt32> collectionKeys_; | 
					
						
							| 
									
										
										
										
											2019-08-18 10:23:54 +08:00
										 |  |  | 	}; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	HRESULT IResourceFontCollectionLoader::Create(_Out_ IResourceFontCollectionLoader** ppCollectionLoader, IDWriteFontFileLoader* pFileLoader) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		HRESULT hr = S_OK; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		if (!ppCollectionLoader) | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			hr = E_POINTER; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		if (SUCCEEDED(hr)) | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			ResourceFontCollectionLoader* pCollectionLoader = new (std::nothrow) ResourceFontCollectionLoader(pFileLoader); | 
					
						
							|  |  |  | 			hr = pCollectionLoader ? S_OK : E_OUTOFMEMORY; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			if (SUCCEEDED(hr)) | 
					
						
							|  |  |  | 			{ | 
					
						
							|  |  |  | 				DX::SafeRelease(*ppCollectionLoader); | 
					
						
							|  |  |  | 				(*ppCollectionLoader) = DX::SafeAcquire(pCollectionLoader); | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		return hr; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-08-18 17:49:13 +08:00
										 |  |  | 	STDMETHODIMP ResourceFontCollectionLoader::AddResources( | 
					
						
							|  |  |  | 		Vector<Resource> const& resources, | 
					
						
							|  |  |  | 		_Out_ LPVOID* pCollectionKey, | 
					
						
							| 
									
										
										
										
											2019-08-18 22:49:44 +08:00
										 |  |  | 		_Out_ UInt32* pCollectionKeySize | 
					
						
							| 
									
										
										
										
											2019-08-18 17:49:13 +08:00
										 |  |  | 		) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		if (!pCollectionKey || !pCollectionKeySize) | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			return E_INVALIDARG; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		try | 
					
						
							|  |  |  | 		{ | 
					
						
							| 
									
										
										
										
											2019-08-18 22:49:44 +08:00
										 |  |  | 			UInt32 collectionKey = resources_.size(); | 
					
						
							| 
									
										
										
										
											2019-08-18 17:49:13 +08:00
										 |  |  | 			collectionKeys_.push_back(collectionKey); | 
					
						
							|  |  |  | 			resources_.push_back(resources); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			*pCollectionKey = reinterpret_cast<LPVOID>(&collectionKeys_.back()); | 
					
						
							|  |  |  | 			*pCollectionKeySize = sizeof(collectionKey); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		catch (std::bad_alloc&) | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			return E_OUTOFMEMORY; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		catch (...) | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			return E_FAIL; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		return S_OK; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-08-18 10:23:54 +08:00
										 |  |  | 	HRESULT STDMETHODCALLTYPE ResourceFontCollectionLoader::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 STDMETHODCALLTYPE ResourceFontCollectionLoader::AddRef() | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		return InterlockedIncrement(&refCount_); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	ULONG STDMETHODCALLTYPE ResourceFontCollectionLoader::Release() | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		ULONG newCount = InterlockedDecrement(&refCount_); | 
					
						
							|  |  |  | 		if (newCount == 0) | 
					
						
							|  |  |  | 			delete this; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		return newCount; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	HRESULT STDMETHODCALLTYPE ResourceFontCollectionLoader::CreateEnumeratorFromKey( | 
					
						
							|  |  |  | 		IDWriteFactory* pFactory, | 
					
						
							|  |  |  | 		void const* collectionKey, | 
					
						
							| 
									
										
										
										
											2019-08-18 22:49:44 +08:00
										 |  |  | 		UInt32 collectionKeySize, | 
					
						
							| 
									
										
										
										
											2019-08-18 10:23:54 +08:00
										 |  |  | 		_Out_ IDWriteFontFileEnumerator** fontFileEnumerator | 
					
						
							|  |  |  | 	) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		HRESULT hr = S_OK; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-08-18 17:49:13 +08:00
										 |  |  | 		if (collectionKey == NULL || collectionKeySize % sizeof(Resource*) != 0) | 
					
						
							| 
									
										
										
										
											2019-08-18 10:23:54 +08:00
										 |  |  | 			hr = E_INVALIDARG; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		if (SUCCEEDED(hr)) | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			IResourceFontFileEnumerator* pEnumerator = NULL; | 
					
						
							|  |  |  | 			hr = IResourceFontFileEnumerator::Create(&pEnumerator, pFactory, pFileLoader_); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			if (SUCCEEDED(hr)) | 
					
						
							|  |  |  | 			{ | 
					
						
							| 
									
										
										
										
											2019-08-18 22:49:44 +08:00
										 |  |  | 				const UInt32 resourceIndex = *static_cast<const UInt32*>(collectionKey); | 
					
						
							| 
									
										
										
										
											2019-08-18 10:23:54 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-08-18 17:49:13 +08:00
										 |  |  | 				hr = pEnumerator->SetResources(resources_[resourceIndex]); | 
					
						
							| 
									
										
										
										
											2019-08-18 10:23:54 +08:00
										 |  |  | 			} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			if (SUCCEEDED(hr)) | 
					
						
							|  |  |  | 			{ | 
					
						
							|  |  |  | 				*fontFileEnumerator = DX::SafeAcquire(pEnumerator); | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		return hr; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	////////////////////////////////////////////////////////////////////////////////////////
 | 
					
						
							|  |  |  | 	//
 | 
					
						
							|  |  |  | 	// ResourceFontFileLoader
 | 
					
						
							|  |  |  | 	//
 | 
					
						
							|  |  |  | 	////////////////////////////////////////////////////////////////////////////////////////
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	class ResourceFontFileLoader | 
					
						
							|  |  |  | 		: public IResourceFontFileLoader | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 	public: | 
					
						
							|  |  |  | 		ResourceFontFileLoader() | 
					
						
							|  |  |  | 			: refCount_(0) | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		// 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, | 
					
						
							| 
									
										
										
										
											2019-08-18 22:49:44 +08:00
										 |  |  | 			UInt32 fontFileReferenceKeySize, | 
					
						
							| 
									
										
										
										
											2019-08-18 10:23:54 +08:00
										 |  |  | 			_Out_ IDWriteFontFileStream** fontFileStream | 
					
						
							|  |  |  | 		); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	private: | 
					
						
							|  |  |  | 		ULONG refCount_; | 
					
						
							|  |  |  | 	}; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	HRESULT IResourceFontFileLoader::Create(_Out_ IResourceFontFileLoader** ppFileLoader) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		HRESULT hr = S_OK; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		if (!ppFileLoader) | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			hr = E_POINTER; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		if (SUCCEEDED(hr)) | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			ResourceFontFileLoader* pFileLoader = new (std::nothrow) ResourceFontFileLoader; | 
					
						
							|  |  |  | 			hr = pFileLoader ? S_OK : E_OUTOFMEMORY; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			if (SUCCEEDED(hr)) | 
					
						
							|  |  |  | 			{ | 
					
						
							|  |  |  | 				(*ppFileLoader) = DX::SafeAcquire(pFileLoader); | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		return hr; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	HRESULT STDMETHODCALLTYPE ResourceFontFileLoader::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 STDMETHODCALLTYPE ResourceFontFileLoader::AddRef() | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		return InterlockedIncrement(&refCount_); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	ULONG STDMETHODCALLTYPE ResourceFontFileLoader::Release() | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		ULONG newCount = InterlockedDecrement(&refCount_); | 
					
						
							|  |  |  | 		if (newCount == 0) | 
					
						
							|  |  |  | 			delete this; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		return newCount; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	HRESULT STDMETHODCALLTYPE ResourceFontFileLoader::CreateStreamFromKey( | 
					
						
							|  |  |  | 		void const* fontFileReferenceKey, | 
					
						
							| 
									
										
										
										
											2019-08-18 22:49:44 +08:00
										 |  |  | 		UInt32 fontFileReferenceKeySize, | 
					
						
							| 
									
										
										
										
											2019-08-18 10:23:54 +08:00
										 |  |  | 		_Out_ IDWriteFontFileStream** fontFileStream | 
					
						
							|  |  |  | 	) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		HRESULT hr = S_OK; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		// Make sure the key is the right size.
 | 
					
						
							| 
									
										
										
										
											2019-08-18 17:49:13 +08:00
										 |  |  | 		if (fontFileReferenceKeySize != sizeof(Resource)) | 
					
						
							| 
									
										
										
										
											2019-08-18 10:23:54 +08:00
										 |  |  | 			hr = E_INVALIDARG; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		if (SUCCEEDED(hr)) | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			// Create the pFileStream object.
 | 
					
						
							|  |  |  | 			IResourceFontFileStream* pFileStream = NULL; | 
					
						
							| 
									
										
										
										
											2019-08-18 17:49:13 +08:00
										 |  |  | 			Resource resource = *static_cast<Resource const*>(fontFileReferenceKey); | 
					
						
							| 
									
										
										
										
											2019-08-18 10:23:54 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-08-18 17:49:13 +08:00
										 |  |  | 			hr = IResourceFontFileStream::Create(&pFileStream, resource); | 
					
						
							| 
									
										
										
										
											2019-08-18 10:23:54 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 			if (SUCCEEDED(hr)) | 
					
						
							|  |  |  | 			{ | 
					
						
							|  |  |  | 				DX::SafeRelease(*fontFileStream); | 
					
						
							|  |  |  | 				*fontFileStream = DX::SafeAcquire(pFileStream); | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		return hr; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	////////////////////////////////////////////////////////////////////////////////////////
 | 
					
						
							|  |  |  | 	//
 | 
					
						
							|  |  |  | 	// ResourceFontFileEnumerator
 | 
					
						
							|  |  |  | 	//
 | 
					
						
							|  |  |  | 	////////////////////////////////////////////////////////////////////////////////////////
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	class ResourceFontFileEnumerator | 
					
						
							|  |  |  | 		: public IResourceFontFileEnumerator | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 	public: | 
					
						
							|  |  |  | 		ResourceFontFileEnumerator(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		STDMETHOD(Initialize)( | 
					
						
							|  |  |  | 			IDWriteFactory* pFactory, | 
					
						
							|  |  |  | 			IDWriteFontFileLoader* pLoader | 
					
						
							|  |  |  | 		); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		STDMETHOD(SetResources)( | 
					
						
							| 
									
										
										
										
											2019-08-18 17:49:13 +08:00
										 |  |  | 			Vector<Resource> const& resources | 
					
						
							| 
									
										
										
										
											2019-08-18 10:23:54 +08:00
										 |  |  | 		); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		~ResourceFontFileEnumerator() | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			DX::SafeRelease(currentFile_); | 
					
						
							|  |  |  | 			DX::SafeRelease(pFactory_); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		// IUnknown methods
 | 
					
						
							|  |  |  | 		virtual HRESULT STDMETHODCALLTYPE QueryInterface(REFIID iid, _Out_ void** ppvObject); | 
					
						
							|  |  |  | 		virtual ULONG STDMETHODCALLTYPE AddRef(); | 
					
						
							|  |  |  | 		virtual ULONG STDMETHODCALLTYPE Release(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		// IDWriteFontFileEnumerator methods
 | 
					
						
							|  |  |  | 		virtual HRESULT STDMETHODCALLTYPE MoveNext(_Out_ BOOL* hasCurrentFile); | 
					
						
							|  |  |  | 		virtual HRESULT STDMETHODCALLTYPE GetCurrentFontFile(_Out_ IDWriteFontFile** fontFile); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	private: | 
					
						
							|  |  |  | 		ULONG refCount_; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		IDWriteFactory* pFactory_; | 
					
						
							|  |  |  | 		IDWriteFontFile* currentFile_; | 
					
						
							|  |  |  | 		IDWriteFontFileLoader* pLoader_; | 
					
						
							| 
									
										
										
										
											2019-08-18 17:49:13 +08:00
										 |  |  | 		Vector<Resource> resources_; | 
					
						
							| 
									
										
										
										
											2019-08-18 22:49:44 +08:00
										 |  |  | 		UInt32 nextIndex_; | 
					
						
							| 
									
										
										
										
											2019-08-18 10:23:54 +08:00
										 |  |  | 	}; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	HRESULT IResourceFontFileEnumerator::Create(_Out_ IResourceFontFileEnumerator** ppEnumerator, IDWriteFactory* pFactory, IDWriteFontFileLoader* pFileLoader) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		HRESULT hr = S_OK; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		if (!ppEnumerator) | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			hr = E_POINTER; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		if (SUCCEEDED(hr)) | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			ResourceFontFileEnumerator* pEnumerator = new (std::nothrow) ResourceFontFileEnumerator; | 
					
						
							|  |  |  | 			hr = pEnumerator ? S_OK : E_OUTOFMEMORY; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			if (SUCCEEDED(hr)) | 
					
						
							|  |  |  | 			{ | 
					
						
							|  |  |  | 				hr = pEnumerator->Initialize(pFactory, pFileLoader); | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			if (SUCCEEDED(hr)) | 
					
						
							|  |  |  | 			{ | 
					
						
							|  |  |  | 				DX::SafeRelease(*ppEnumerator); | 
					
						
							|  |  |  | 				(*ppEnumerator) = DX::SafeAcquire(pEnumerator); | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		return hr; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	ResourceFontFileEnumerator::ResourceFontFileEnumerator() | 
					
						
							|  |  |  | 		: refCount_(0) | 
					
						
							|  |  |  | 		, pFactory_(NULL) | 
					
						
							|  |  |  | 		, currentFile_(NULL) | 
					
						
							|  |  |  | 		, nextIndex_(0) | 
					
						
							|  |  |  | 		, pLoader_(NULL) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	STDMETHODIMP ResourceFontFileEnumerator::Initialize( | 
					
						
							|  |  |  | 		IDWriteFactory* pFactory, | 
					
						
							|  |  |  | 		IDWriteFontFileLoader* pLoader | 
					
						
							|  |  |  | 	) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		if (pFactory && pLoader) | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			pFactory_ = DX::SafeAcquire(pFactory); | 
					
						
							|  |  |  | 			pLoader_ = DX::SafeAcquire(pLoader); | 
					
						
							|  |  |  | 			return S_OK; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		return E_INVALIDARG; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	STDMETHODIMP ResourceFontFileEnumerator::SetResources( | 
					
						
							| 
									
										
										
										
											2019-08-18 17:49:13 +08:00
										 |  |  | 		Vector<Resource> const& resources | 
					
						
							| 
									
										
										
										
											2019-08-18 10:23:54 +08:00
										 |  |  | 	) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		try | 
					
						
							|  |  |  | 		{ | 
					
						
							| 
									
										
										
										
											2019-08-18 17:49:13 +08:00
										 |  |  | 			resources_.assign(resources); | 
					
						
							| 
									
										
										
										
											2019-08-18 10:23:54 +08:00
										 |  |  | 		} | 
					
						
							|  |  |  | 		catch (std::bad_alloc&) | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			return E_OUTOFMEMORY; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		catch (...) | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			return E_FAIL; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		return S_OK; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	HRESULT STDMETHODCALLTYPE ResourceFontFileEnumerator::QueryInterface(REFIID iid, _Out_ void** ppvObject) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		if (iid == IID_IUnknown || iid == __uuidof(IDWriteFontFileEnumerator)) | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			*ppvObject = this; | 
					
						
							|  |  |  | 			AddRef(); | 
					
						
							|  |  |  | 			return S_OK; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		else | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			*ppvObject = NULL; | 
					
						
							|  |  |  | 			return E_NOINTERFACE; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	ULONG STDMETHODCALLTYPE ResourceFontFileEnumerator::AddRef() | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		return InterlockedIncrement(&refCount_); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	ULONG STDMETHODCALLTYPE ResourceFontFileEnumerator::Release() | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		ULONG newCount = InterlockedDecrement(&refCount_); | 
					
						
							|  |  |  | 		if (newCount == 0) | 
					
						
							|  |  |  | 			delete this; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		return newCount; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	HRESULT STDMETHODCALLTYPE ResourceFontFileEnumerator::MoveNext(_Out_ BOOL* hasCurrentFile) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		HRESULT hr = S_OK; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		*hasCurrentFile = FALSE; | 
					
						
							|  |  |  | 		DX::SafeRelease(currentFile_); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-08-18 17:49:13 +08:00
										 |  |  | 		if (nextIndex_ < resources_.size()) | 
					
						
							| 
									
										
										
										
											2019-08-18 10:23:54 +08:00
										 |  |  | 		{ | 
					
						
							|  |  |  | 			hr = pFactory_->CreateCustomFontFileReference( | 
					
						
							| 
									
										
										
										
											2019-08-18 17:49:13 +08:00
										 |  |  | 				&resources_[nextIndex_], | 
					
						
							|  |  |  | 				sizeof(Resource), | 
					
						
							| 
									
										
										
										
											2019-08-18 10:23:54 +08:00
										 |  |  | 				pLoader_, | 
					
						
							|  |  |  | 				¤tFile_ | 
					
						
							|  |  |  | 			); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			if (SUCCEEDED(hr)) | 
					
						
							|  |  |  | 			{ | 
					
						
							|  |  |  | 				*hasCurrentFile = TRUE; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				++nextIndex_; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		return hr; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	HRESULT STDMETHODCALLTYPE ResourceFontFileEnumerator::GetCurrentFontFile(_Out_ IDWriteFontFile** fontFile) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		*fontFile = DX::SafeAcquire(currentFile_); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		return (currentFile_ != NULL) ? S_OK : E_FAIL; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	////////////////////////////////////////////////////////////////////////////////////////
 | 
					
						
							|  |  |  | 	//
 | 
					
						
							|  |  |  | 	// ResourceFontFileStream
 | 
					
						
							|  |  |  | 	//
 | 
					
						
							|  |  |  | 	////////////////////////////////////////////////////////////////////////////////////////
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	class ResourceFontFileStream | 
					
						
							|  |  |  | 		: public IResourceFontFileStream | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 	public: | 
					
						
							|  |  |  | 		ResourceFontFileStream(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		STDMETHOD(Initialize)( | 
					
						
							| 
									
										
										
										
											2019-08-18 17:49:13 +08:00
										 |  |  | 			Resource const resources | 
					
						
							| 
									
										
										
										
											2019-08-18 10:23:54 +08:00
										 |  |  | 		); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		// IUnknown methods
 | 
					
						
							|  |  |  | 		virtual HRESULT STDMETHODCALLTYPE QueryInterface(REFIID iid, void** ppvObject); | 
					
						
							|  |  |  | 		virtual ULONG STDMETHODCALLTYPE AddRef(); | 
					
						
							|  |  |  | 		virtual ULONG STDMETHODCALLTYPE Release(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		// IDWriteFontFileStream methods
 | 
					
						
							|  |  |  | 		virtual HRESULT STDMETHODCALLTYPE ReadFileFragment( | 
					
						
							|  |  |  | 			void const** fragmentStart, | 
					
						
							|  |  |  | 			UINT64 fileOffset, | 
					
						
							|  |  |  | 			UINT64 fragmentSize, | 
					
						
							|  |  |  | 			_Out_ void** fragmentContext | 
					
						
							|  |  |  | 		); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		virtual void STDMETHODCALLTYPE ReleaseFileFragment( | 
					
						
							|  |  |  | 			void* fragmentContext | 
					
						
							|  |  |  | 		); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		virtual HRESULT STDMETHODCALLTYPE GetFileSize( | 
					
						
							|  |  |  | 			_Out_ UINT64* fileSize | 
					
						
							|  |  |  | 		); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		virtual HRESULT STDMETHODCALLTYPE GetLastWriteTime( | 
					
						
							|  |  |  | 			_Out_ UINT64* lastWriteTime | 
					
						
							|  |  |  | 		); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		bool IsInitialized() | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			return resourcePtr_ != NULL; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	private: | 
					
						
							|  |  |  | 		ULONG refCount_; | 
					
						
							|  |  |  | 		LPVOID resourcePtr_; | 
					
						
							|  |  |  | 		DWORD resourceSize_; | 
					
						
							|  |  |  | 	}; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-08-18 17:49:13 +08:00
										 |  |  | 	HRESULT IResourceFontFileStream::Create(_Out_ IResourceFontFileStream** ppStream, const Resource resource) | 
					
						
							| 
									
										
										
										
											2019-08-18 10:23:54 +08:00
										 |  |  | 	{ | 
					
						
							|  |  |  | 		HRESULT hr = S_OK; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		if (!ppStream) | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			hr = E_POINTER; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		if (SUCCEEDED(hr)) | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			ResourceFontFileStream* pFileStream = new (std::nothrow) ResourceFontFileStream; | 
					
						
							|  |  |  | 			hr = pFileStream ? S_OK : E_OUTOFMEMORY; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			if (SUCCEEDED(hr)) | 
					
						
							|  |  |  | 			{ | 
					
						
							| 
									
										
										
										
											2019-08-18 17:49:13 +08:00
										 |  |  | 				hr = pFileStream->Initialize(resource); | 
					
						
							| 
									
										
										
										
											2019-08-18 10:23:54 +08:00
										 |  |  | 			} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			if (SUCCEEDED(hr)) | 
					
						
							|  |  |  | 			{ | 
					
						
							|  |  |  | 				DX::SafeRelease(*ppStream); | 
					
						
							|  |  |  | 				(*ppStream) = DX::SafeAcquire(pFileStream); | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		return hr; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	ResourceFontFileStream::ResourceFontFileStream() | 
					
						
							|  |  |  | 		: refCount_(0) | 
					
						
							|  |  |  | 		, resourcePtr_(NULL) | 
					
						
							|  |  |  | 		, resourceSize_(0) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	STDMETHODIMP ResourceFontFileStream::Initialize( | 
					
						
							| 
									
										
										
										
											2019-08-18 17:49:13 +08:00
										 |  |  | 		const Resource resource | 
					
						
							| 
									
										
										
										
											2019-08-18 10:23:54 +08:00
										 |  |  | 	) | 
					
						
							|  |  |  | 	{ | 
					
						
							| 
									
										
										
										
											2019-08-18 17:49:13 +08:00
										 |  |  | 		Resource::Data data = resource.GetData(); | 
					
						
							|  |  |  | 		HRESULT hr = data ? S_OK : E_FAIL; | 
					
						
							| 
									
										
										
										
											2019-08-18 10:23:54 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-08-18 17:49:13 +08:00
										 |  |  | 		if (SUCCEEDED(hr)) | 
					
						
							| 
									
										
										
										
											2019-08-18 10:23:54 +08:00
										 |  |  | 		{ | 
					
						
							| 
									
										
										
										
											2019-08-18 17:49:13 +08:00
										 |  |  | 			resourcePtr_ = data.buffer; | 
					
						
							|  |  |  | 			resourceSize_ = data.size; | 
					
						
							| 
									
										
										
										
											2019-08-18 10:23:54 +08:00
										 |  |  | 		} | 
					
						
							|  |  |  | 		return hr; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// IUnknown methods
 | 
					
						
							|  |  |  | 	HRESULT STDMETHODCALLTYPE ResourceFontFileStream::QueryInterface(REFIID iid, void** ppvObject) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		if (iid == IID_IUnknown || iid == __uuidof(IDWriteFontFileStream)) | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			*ppvObject = this; | 
					
						
							|  |  |  | 			AddRef(); | 
					
						
							|  |  |  | 			return S_OK; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		else | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			*ppvObject = NULL; | 
					
						
							|  |  |  | 			return E_NOINTERFACE; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	ULONG STDMETHODCALLTYPE ResourceFontFileStream::AddRef() | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		return InterlockedIncrement(&refCount_); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	ULONG STDMETHODCALLTYPE ResourceFontFileStream::Release() | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		ULONG newCount = InterlockedDecrement(&refCount_); | 
					
						
							|  |  |  | 		if (newCount == 0) | 
					
						
							|  |  |  | 			delete this; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		return newCount; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	HRESULT STDMETHODCALLTYPE ResourceFontFileStream::ReadFileFragment( | 
					
						
							|  |  |  | 		void const** fragmentStart, | 
					
						
							|  |  |  | 		UINT64 fileOffset, | 
					
						
							|  |  |  | 		UINT64 fragmentSize, | 
					
						
							|  |  |  | 		_Out_ void** fragmentContext | 
					
						
							|  |  |  | 	) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		// The pLoader is responsible for doing a bounds check.
 | 
					
						
							|  |  |  | 		if (fileOffset <= resourceSize_ && | 
					
						
							|  |  |  | 			fragmentSize <= resourceSize_ - fileOffset) | 
					
						
							|  |  |  | 		{ | 
					
						
							| 
									
										
										
										
											2019-08-18 22:49:44 +08:00
										 |  |  | 			*fragmentStart = static_cast<BYTE const*>(resourcePtr_) + static_cast<UInt32>(fileOffset); | 
					
						
							| 
									
										
										
										
											2019-08-18 10:23:54 +08:00
										 |  |  | 			*fragmentContext = NULL; | 
					
						
							|  |  |  | 			return S_OK; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		else | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			*fragmentStart = NULL; | 
					
						
							|  |  |  | 			*fragmentContext = NULL; | 
					
						
							|  |  |  | 			return E_FAIL; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	void STDMETHODCALLTYPE ResourceFontFileStream::ReleaseFileFragment( | 
					
						
							|  |  |  | 		void* fragmentContext | 
					
						
							|  |  |  | 	) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	HRESULT STDMETHODCALLTYPE ResourceFontFileStream::GetFileSize( | 
					
						
							|  |  |  | 		_Out_ UINT64* fileSize | 
					
						
							|  |  |  | 	) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		*fileSize = resourceSize_; | 
					
						
							|  |  |  | 		return S_OK; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	HRESULT STDMETHODCALLTYPE ResourceFontFileStream::GetLastWriteTime( | 
					
						
							|  |  |  | 		_Out_ UINT64* lastWriteTime | 
					
						
							|  |  |  | 	) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		*lastWriteTime = 0; | 
					
						
							|  |  |  | 		return E_NOTIMPL; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | } |