What’s about fixed-width-fonts and non-fixed-width-fonts? If I assume a
Bitmap Font might use fixed-width glyphs everything is quite easy. But
when using True Type Fonts with different font widths I need to handle
this in another way:
Either make them fixed-width and work with as described. Or I need to
calculate each glyph’s size and need to lookup it while rendering. Sure:
when using e.g. ASCII as template for the prerendering I can use a
continuous array of length 256 to store each glyphs size, so I get
constant seek/access time. This might be the better solution, isn’t it?
Here’s what we did for Dungeons of Dredmor.
Originally (as a software-rendered SDL 1.2 game), Dredmor used SDL_ttf
and rendered strings to a Surface and blitted that Surface appropriately.
This worked because the game isn’t CPU-intensive in general, and
everything was in a memory buffer waiting to be blitted to the screen,
so a little more memory bandwidth and overdraw wasn’t a big deal for
this title.
When we moved to SDL 2.0, and to its Render API, I wanted to get
everything onto the GPU, so this system would have been pushing lots of
new texture data to the GPU every frame, so I moved it to a font atlas.
I hacked up the utility here to fit my specific needs:
https://code.google.com/p/freetype-gl/
So I gave it a font and it spit out a .png and a bunch of C code like this:
static const texture_font_t font8 =
{
//height, linegap, ascender, descender
10.750000f, 0.720000f, 7.770000f, -2.260000f,
{ // individual glyph details…
// tex_x, tex_y, width, height, offset_x, offset_y, advance_x
// […snip…]
{ 6, 2, 4, 4, 0, 4, 4.125000f },
{ 11, 2, 5, 4, 0, 4, 4.187500f },
{ 17, 2, 6, 4, 0, 4, 5.906250f },
{ 24, 2, 5, 4, 0, 4, 4.203125f },
{ 30, 2, 6, 6, -1, 4, 4.296875f },
{ 96, 3, 4, 4, 0, 4, 3.562500f },
// […snip…]
};
This system wasn’t made robust for Unicode (at this moment), but it did
let us render an ‘A’ in 8-point font by doing:
const texture_font_t *myGlyph = &font8.glyphs['A'];
And then drawing from the right part of the texture and taking all the
other metrics into account.
Here’s the .png it spit out, with the background flattened to black so
you can see it in a web browser (normally the background is transparent)…
https://icculus.org/~icculus/dotplan/Austin.png
As you can see, it’s not fixed width, and we stored multiple font sizes
in one texture. We could have stored multiple unrelated fonts in the
same way, too. If we were really fancy, we could have saved some pixels
by reusing pieces (the letter and the letter with an accent, for
example), but the software didn’t do that by default and we weren’t
desperate to save space here.
If we moved to proper Unicode and translated to, say, Japanese, we would
need bigger (and multiple) textures, and probably a hashtable of glyphs
instead of a flat array…and maybe generation of the font atlas at
runtime. As it stands now, the game doesn’t use SDL_ttf at all anymore,
as that utility that generated the font atlas did all that work offline.
–ryan.