Android has this nifty feature where you can distribute a TTF with your app. Since games use OpenGL to render everything (including text), I was using a TTF-to-PNG converter that I wrote for my XNA book back in 2007.
Fancier fonts use something called kerning to make the text look more natural. For example, “Hijack” in certain fonts has a noticeable overlap between the “i” and “j”. That’s great for print and web, but it makes converting the glyphs to sprites a pain.
The way my utility “disabled” kerning was to draw each character to a separate surface and scan for the bounds of the rendered pixels. Remember, the utility was a part of the content production workflow. It sounds like a lot of work, but it was an offline, build-time tool — the place you want to do repetitive, laborious stuff.
Well, having the ability to use custom TTFs at runtime appeals to me. But, my old build-time logic wasn’t going to cut it. It turns out that Android provides a way for you to know exactly how much a glyph is influenced by kerning.
There are two basic ways to get the width of a character — Paint.measureText and Paint.getTextBounds. Paint.measureText will give you the exact number of pixels that the rendered character will occupy, but you don’t know how much the glyph will be shifted when drawn.
Paint.getTextBounds also reports the width (via getWidth), but the “left” property tells you where the character will start. For example, the font I’m using reports the “left” bounds of the “j” character to be “-9″ (Gochi Hand @20pt).
The code to calculate the width looks something like this:
Rect bounds = new Rect();
paint.getTextBounds(allChars, i, i+1, bounds);
float leading = -bounds.left;
float width = bounds.width();
When you actually draw the character to your texture, you just need to offset the x location with the value in “leading”.
c.drawText(chr, x+leading, y, paint);
Now, you have a sprite font that’s kerning-aware. While I’m currently ignoring the leading space once the glyph is rendered, I could just as easily incorporate that data into the sprite font rendering logic, adding kerning to my in-game text.
