GLKernedFont - Building a Kerning Table
Rather than wasting time trying to measure every possible conflict, we can just use the three measurement points of the baseline, meanline and capsline as starting points to divide a letter into three blocks - then we just check for the possibility of overlapping in those areas. We could just use those three points as measurements, but given that characters can have slanted elements you need to 'widen' the comparison area slightly.
What I like to do is take the average width of the main lines on a glype (like the arm at the top of a T or the spine down the middle of the T), add it to our meanline and divide by two to give us the 'middle' area between them as our dividing line for the top comparison. Then for the bottom area's height I just subtract 150% the arm height from the baseline. To the right is an image of the fond divided into our three comparison areas. On that 36x60 cell font, our meanline is 8px down, and our baseline is 34px down. With the arm height being 6px our capsline comparison area is 7px tall, while the top of the baseline comparison area ends up 25px from the top.
So now that we know what areas to get our six numbers from, on to making useful kerning data. In each area, we just count in to whatever pixel is closest to the edge in each area... For example:
Left Side 9 // capsline / red area 3 // meanline / green area 0 // baseline / blue area Right Side 24 // capsline / red area 30 // meanline / green area 33 // baseline / blue area
To use these numbers is pretty simple. We just take the right side of the previous character in each 'area' and subtract the left side of the current area. I actually use addition for this, choosing to store the left side numbers as negative numbers.
For example, if we had two letter A's next to each-other, the first one would have no previous character, so we don't adjust it's position. To place the next one, we'd test the capsline: 24-9==15, then the meanline: 30-3==27, and the baseline: 33-0==33 - since 33 is the largest of our values, that (plus any extra desired letter-spacing) is where we can place our next letter, 33px from the left edge of the first one. The letter T from the same character set would have 0,10,10 as it's left side values, so the "AT" pairing would end up being 24-0==24, 30-10==20, 33-10==23 - so 24 as the largest value is how far from the left edge of the A the left edge of T should go - giving us our desired overlap.
So, we need to store this information. In the glkfont file I simply store these values as a packed shortInt array - but for creating the data I've made a .kerning file that is just lines of eight comma delimited fields:
- character code
- left capsline
- left meanline
- left baseline
- right capsline
- right meanline
- right baseline
- Ignored/Comments - usually the actual character
Thus the line for our letter's A and T would look like this:
65, -9 , -3 , 0 , 24, 30, 33, A 84, 0 , -6 , -6 , 27, 21, 21, T
So, from there it's just a matter of doing that for ugh... every character in your font. Ok, I admit it, that's a lot of work and probably SHOULD be automated, I've just not gotten around to it yet (if feel like running with this, knock yourself out!). Still, it's not as much work as it sounds like and goes pretty quickly... and the result of our formula isn't 'perfect' and it helps to do some manual tweaks increasing/decreasing values to fit...
Of course, the scary part is I developed this quick kerning technique back in the early 80's on a Trash-80 Color computer. When you only had a 256x192 and a native text mode that was only 32x16, using overlapping sprites to stuff more characters on every line almost turned it into a real display. With a 8x8 tile set and a average capswidth of four pixels, I was able to fit an average of around 60 characters per line on that ancient hardware.