TTF Fonts not rendering correctly
Overview
I'm having a problem with the rendering of a TTF font in Solarus where it looks awful because the letters look misaligned vertically. The font also does not look as bold as it should.
The font I am using is Andika New Basic (the bold variant) with anti-aliasing enabled. However, the problem is most pronounced with antialiasing turned off:
Rendered in Solarus with rendering mode: solid
For example, the "Z" appears to be higher than "A".
Steps to Reproduce
Sample Code to reproduce the problem:
local text_surface = sol.text_surface.create{
font = "AndikaNewBasic/AndikaNewBasic-Bold",
font_size = 16,
color = {255, 255, 255},
rendering_mode = "antialiasing",
horizontal_alignment = "left",
vertical_alignment = "top",
}
Project Files
This project simply draws a menu displaying a single text surface.
Potential Solution: Hinting
@hhromic on discord was able to determine that adjusting the hinting options could fix the vertical alignment issue. The following image shows how the font renders in GIMP on the top line, then shows how it renders in Solarus with each of the possible hinting options (where Solarus is currently hard-coded to use normal hinting):
(latest -dev version of Solarus running on Ubuntu was used to generate the above image)
Here is a zoomed in view showing the most noticeable problem: the uppercase "i" appears shorter than the adjacent letters on line 2 (current Solarus behavior).
Using the hinting value of "None" or "Light" fixes the problem where "i" appears to be shorter.
It's also strange that using a hinting value of "None" seems to adjust the kerning to make only that line longer, whereas the top line from GIMP is also using hinting of "None" while remaining the same width as the other lines.
Modifying the Solarus Source Code
The following Solarus code was modified to generate the image above.
File location: solarus/src/core/FontResource.cpp
); //original line 221
TTF_SetFontHinting(outline_font.get(), TTF_HINTING_NONE); //new code
OutlineFontReader reader = { std::move(rw), std::move(outline_font) }; //original line 222
Where values of TTF_HINTING_NORMAL
(default), TTF_HINTING_MONO
, TTF_HINTING_LIGHT
and TTF_HINTING_NONE
were tested.
from the SDL_TTF documentation:
Set the hinting of the loaded font. You should experiment with this setting if you know which font you are using beforehand, especially when using smaller sized fonts. If the user is selecting a font, you may wish to let them select the hinting mode for that font as well.
Final Mystery: Lack of Bold
There remains the other question as to why the font doesn't get rendered bold in Solarus like it does in GIMP.
One thing I noticed is that GIMP has a bold attribute that can be enabled/disabled, but for the AndikaNewBasic-Bold font, pressing the button to toggle this attribute has no effect in GIMP. I wonder if this means that GIMP is forcing the bold attribute to be enabled for the font. So does that mean that the bold attribute has to be active for it to appear bold like it does in GIMP?