Hi all,
If I understand correctly, the following method lets you use a custom font file that is embedded as a JUCE binary resource:
Typeface::createSystemTypefaceFor (const void* data, size_t dataSize);
For example:
myCustomTypeface = Typeface::createSystemTypefaceFor (BinaryData::CustomFont_ttf, BinaryData::CustomFont_ttfSize);
if (myCustomTypeface != nullptr)
myLookAndFeel.setDefaultSansSerifTypeface (myCustomTypeface);
It works, but unless I’m missing something, it always uses software rendering instead of Direct2D/DirectWrite! Some digging reveals the cause.
Firstly, JUCE uses the Win32 AddFontMemResourceEx() API to load/create the font behind the scenes.
Secondly, when rendering, TextLayout::createLayout() checks to see if it can use a native (DirectWrite) layout or if it must fall back to using a software layout:
juce::canAllTypefacesBeUsedInLayout(const juce::AttributedString & text)
juce::TextLayout::createNativeLayout(const juce::AttributedString & text)
juce::TextLayout::createLayout(const juce::AttributedString & text, float maxWidth, float maxHeight)
juce::TextLayout::createLayout(const juce::AttributedString & text, float maxWidth)
juce::AttributedString::draw(juce::Graphics & g, const juce::Rectangle<float> & area)
It does this by checking that the AttributedString font/s are of type WindowsDirectWriteTypeface, but this fails (canAllTypefacesBeUsedInLayout() returns false) because the custom font is of type WindowsTypeface. Consequently, it calls createStandardLayout() instead.
Further digging shows that IDWriteFontCollection can’t find the custom font in the WindowsDirectWriteTypeface constructor. After much Googling, it seems this is because the font was added using the Win32 AddFontMemResourceEx() API. There’s barely any info about it online - so much so that I can’t even find the stuff I originally Googled, but it’s definitely out there (somewhere), and stepping through the code shows it to be the case:
juce::WindowsDirectWriteTypeface::WindowsDirectWriteTypeface(const juce::Font & font, IDWriteFontCollection * fontCollection)
juce::Typeface::createSystemTypefaceFor(const juce::Font & font)
juce::LookAndFeel::getTypefaceForFont(const juce::Font & font)
juce::getTypefaceForFontFromLookAndFeel(const juce::Font & font)
juce::TypefaceCache::findTypefaceFor(const juce::Font & font)
juce::Font::getTypeface()
Note #1: I’m using a custom font that is not installed in C:\Windows\Fonts. That may be crucial. I suspect if the custom font also happens to be installed (ie. it shows up in C:\Windows\Fonts), then DirectWrite will find it, but that kind of defeats the object of using a custom, private font.
Note #2: It works if I add the font using the Win32 AddFontResourceEx() API to load the font file from disk. Again, this is consistent with what I’ve read online, if only I’d bookmarked the damn pages!
I’d be grateful if someone would look into it to confirm that it’s a JUCE issue.
Many thanks,
Ben Staton
Edit: This is best I can find so far, but it’s a bit vague. Will keep looking.
c++ - How to load font from resource using dwrite API? - Stack Overflow