dev.nlited.com

>>

Loading DWrite Fonts

2017-05-28 20:26:13 chip Page 1985 📢 PUBLIC

Loading Fonts

May 28 2017

I want to be able to load a font from a file so I can use downloaded fonts and include custom fonts as resources in programs.

IDWriteFactory::CreateTextFormat() takes an IDWriteFontCollection as the source for the font, which is set to 0 to use the default system collection. To load a font, I need to create my own font collection using IDWriteFactory::CreateCustomFontCollection(). This is a fairly involved process that includes registering a custom font collection interface and a font file loader interface.

I found a StackOverflow topic with some sample code. I also tried to install the Windows SDK.

Online MSDN article.

  1. Install .NET Framework 4.7
    .NET Framework 4.7 offline installer
    (Required by the Windows SDK)
  2. Download the Windows SDK
    Windows 10 SDK
    (644MB, ~40 minutes)
    The first download stalled after 225MB. Finally finished after about 90 minutes. However, there are a lot of warnings that installing the Win10 SDK on a Win81 system could be a lot a trouble. I think I will defer this until I build my VS17 system.

Creating a custom font collection:

  1. Create a font collection loader
    Implement a class based on IDWriteFontCollectionLoader.
    class nFontLoader: public IDWriteFontCollectionLoader { }
  2. Implement the IUnknown interface
    HRESULT STDMETHODCALLTYPE nFontLoader::QueryInterface(REFIID RefIID, void **ppObj) { if(!(RefIID==IID_Unknown || RefIID==__uuidof(IDWriteFontCollectionLoader))) { *ppObj= 0; return(E_NOINTERFACE); } *ppObj= this; AddRef(); return(S_OK); } ULONG STDMETHODCALLTYPE nFontLoader::AddRef(void) { return(InterlockedIncrement(&RefCt)); } ULONG STDMETHODCALLTYPE nFontLoader::Release(void) { ULONG NewCt= InterlockedDecrement(&RefCt); if(NewCt==0) { //Destroy object? } return(NewCt); } };
  3. Create a font file enumerator class.
    Implement the IUnknown interface.
    class nFontFileEnumerator: public IDWriteFontFileEnumerator { public: HRESULT STDMETHODCALLTYPE nFontFileEnumerator::QueryInterface(REFIID RefIID, void **ppObj) { if(!(RefIID==IID_Unknown || RefIID==__uuidof(IDWriteFontFileEnumerator))) { *ppObj= 0; return(E_NOINTERFACE); } *ppObj= this; AddRef(); return(S_OK); } ULONG STDMETHODCALLTYPE nFontLoader::AddRef(void) { return(InterlockedIncrement(&RefCt)); } ULONG STDMETHODCALLTYPE nFontLoader::Release(void) { ULONG NewCt= InterlockedDecrement(&RefCt); if(NewCt==0) { //Destroy object? } return(NewCt); } };
  4. Add the Initialize() method
    HRESULT Initialize(UINT const *pKey, UINT32 KeySz) { HRESULT WinErr= S_OK; try { UINT Pos= *pKey; MFCollection::iterator it= MFFontGlobals::collections()[Pos].begin(); while(it!=MFFontGlobals::collections()[Pos].end()) { filePaths_.push_back(it->c_str()); it++; } } catch(...) { WinErr= ExceptionToHResult(); } return(WinErr); }
  5. Add the GetCurrentFontFile() method
    HRESULT GetCurrentFontFile(IDWriteFontFile **ppFile) { *ppFile= SafeAcquire(currentFile_); return(currentFile_!=0 ? S_OK:E_FAIL); }
  6. Add the MoveNext() method
    HRESULT nFontFileEnumerator::MoveNext(BOOL *pIsFound) { HRESULT WinErr= S_OK; *pIsFound= FALSE; SafeRelease(&currentFile_); if(nextIndex_ < filePaths_.size()) { const WCHAR *FName= filePaths_[nextIndex_].c_str(); if(SUCCEEDED(WinErr= pFactory->CreateFontFileReference(FName,0,&currentFile_))) { *pIsFound= TRUE; ++nextIndex_; } } return(WinErr); }
  7. Implement the CreateEnumeratorFromKey() interface
    HRESULT STDMETHODCALLTYPE nFontLoader::CreateEnumeratorFromKey( IDWriteFactory *pFactory ,void const *pKey ,UINT32 KeySz ,IDWriteFontFileEnumerator **ppEnum ) { HRESULT WinErr= S_OK; *ppEnumerator= 0; nFontFileEnumerator *pEnum= new nFontFileEnumerator(pFactory); if(!pEnum) return(E_OUTOFMEMORY); if(!SUCCEEDED(WinErr= pEnum->Initialize(pKey,KeySz))) { delete pEnum; return(WinErr); } *ppEnum= pEnum; return(WinErr); }
  8. Register the font collection loader:
    IDWriteFactory::RegisterFontCollectionLoader(pCollectionLoader);


WebV7 (C)2018 nlited | Rendered by tikope in 33.636ms | 18.226.226.158