This is what I changed in Juce to get it working
Allow derived classes to announce that they are hinted typefaces.
virtual bool Typeface::isHinted () { return false; } // new function
Shift hinted typefaces by whole pixels only. Thanks to Jules’ great design skills most of the code goes through this one routine, but there might be one or two other places I don’t know about that would need a similar adjustment. I found that it covered the case of Label, and most of the text routines in the Graphics class. Not sure about the TextEditor.
void GlyphArrangement::moveRangeOfGlyphs()
{
//...
if (num > 0 && glyphs.getUnchecked (0)->font.getTypeface()->isHinted())
dx = floor (dx + .5f);
//...
}
As Jules pointed out, “A Typeface represents a typeface in its most general form, and the Font represents a typeface at a particular size and style. Trying to bend those meanings would end in tears.”
Changing that would be a nightmare. Fortunately, we don’t have to do that All we need to do is modify the Typeface cache so that even though a CustomTypeface exists with the same name, its considered
a different font if its hinted. Another virtual function in Typeface:
virtual bool Typeface::useTypefaceFor (const Font& font) { return true; }
Now we change the cache to call this routine
const Typeface::Ptr TypefaceCache::findTypefaceFor (const Font& font)
{
//....
if (face->flags == flags
&& face->typefaceName == faceName
&& face->typeFace->useTypefaceFor (font)) // additional test
At this point, we have the minimum amount of Juce code that needs to be changed to support these hinted faces, excluding any places like moveRangeOfGlyphs that I might have missed.
[size=150]ONLY FIVE LINES OF CODE!!![/size]
With only these changes to Juce, I was able to write my own CustomTypeface using hinted FreeType-loaded fonts. The result looks like this:
[attachment=2]hinting_demo.gif[/attachment]
[attachment=1]juce.png[/attachment]
[attachment=0]freetype.png[/attachment]
My FreeType CustomTypeFace class requires the following:
- Add FreeType to your project includes and libraries
- Turn your .ttf file into a static variable with BinaryBuilder and embed it in your application
- Override getTypefaceForFont() in your subclass of LookAndFeel:
const Typeface::Ptr YourLookAndFeel::getTypefaceForFont (const Font &font)
{
// this is a cheap fix for DocumentWindow and MenuBarComponent oddities
float fontHeight = font.getHeight();
if (font.getHeight()<1)
return LookAndFeel::getTypefaceForFont (font);
return new FreeTypeHintedFace (fontHeight,
pointerToFileData,
numberOfBytesInFileData);
}
Now don’t be thinking that I’m going to be making this work with system fonts, i.e. dig into the Windows/Mac/Linux operating system specific place where the fonts are kept and parse those files myself. Although on Linux I would imagine its easy since Juce already does that. All I needed was to make the embedded font I bought appear hinted on screen.