Custom Font Collections
DirectWrite provides access to the system font collection by using the IDWriteFactory::GetSystemFontCollection method. This is the font collection that is most frequently used. However some applications have to use fonts that are not installed on the system, such as from included font files or font files embedded in the application.
If the fonts that you want are not in the system font collection, you can create a custom font collection derived from IDWriteFontCollection.
This overview consists of the following parts:
- Registering and unregistering a Font Collection Loader
- Example Code
You register a font collection loader by using the IDWriteFactory::RegisterFontCollectionLoader method and passing it an IDWriteFontCollectionLoader interface implemented by the application as a singleton object. This object will load the fonts when the custom collection is requested. Both the system font collection and custom font collections are cached, so the fonts are only loaded one time.
The font collection loader must be unloaded eventually by using the IDWriteFactory::UnregisterFontCollectionLoader.
You create an IDWriteFontFileEnumerator object by using the IDWriteFactory::CreateCustomFontCollection and passing it an application-defined key. The key is a void pointer and the data type, format, and meaning are defined by the application and are opaque to the font system.
Whereas the key can be anything, DirectWrite requires that each key is both:
- Unique to a single font collection within the scope of the loader.
- Valid until the loader is unregistered using the factory.
When the CreateCustomFontCollection method is called, DirectWrite calls back to an IDWriteFontCollectionLoader interface implemented as a singleton object by the application. The IDWriteFontCollection::CreateEnumeratorFromKey callback method is used by DirectWrite to retrieve an IDWriteFontFileEnumerator object implemented by the application. The IDWriteFactory object that is being used to create the collection is passed to this method and should be used by the font file enumerator to create the IDWriteFontFile objects to be included in the collection.
The key passed to this method identifies the font collection and is the same key passed to CreateCustomFontCollection.
The application-defined IDWriteFontFileEnumerator object that was created by the CreateEnumeratorFromKey method is used to enumerate the font files in a collection, creating an IDWriteFontFile object for each file. The IDWriteFontFileEnumerator::MoveNext method changes the position to the next font file. If there is a file at the position, it will set the hasCurrentFile to TRUE. Otherwise it will be set to FALSE and the method will return S_OK.
An IDWriteFontFile object is output by the IDWriteFontFileEnumerator::GetCurrentFontFile method. If there is no font file at the current position, because MoveNext has not yet been called or hasCurrentFile was set to FALSE, then GetCurrentFontFile will return E_FAIL.
The IDWriteFontFile object output byGetCurrentFontFile can be created by calling IDWriteFactory::CreateCustomFontFileReference. The font file reference key identifies a specific font file reference and must be unique within the font file loader that will load the file.
The CreateCustomFontFileReference method takes an IDWriteFontFileLoader object implemented by the application that is used to load the font. The IDWriteFontFileLoader::CreateStreamFromKey callback method is passed the key and outputs an IDWriteFontFileStream object.
The application-implemented IDWriteFontFileStream object provides the font file data for a font file reference from a custom font file loader. Together with the file size and last write time, it provides a method (ReadFileFragment) for retrieving file fragments that are to be compiled into an IDWriteFontFile object.
An IDWriteFontFileStream can get the font file contents from anywhere, such as the local hard disk drive, or embedded resources.
Example code is available in the Custom Font Sample, which uses a custom font collection of fonts that are embedded as resources in the executable.