Computing stuff tied to the physical world

Font tables – proportional

In Software on Jun 7, 2011 at 00:01

Unlike monospaced font tables, proportional fonts have character glyphs which all differ in size and relative positioning. This not only requires more storage, it also complicates the way these glyphs are stored in the bitmap image in flash memory.

In the GLCD library, I implemented this by storing two bytes for each character:

  • P: the horizontal start position of the glyph in the image (1 byte)
  • A: same as for monospaced fonts, but per-character pre-gap (4 bits)
  • B: same as for monospaced fonts, but per-character post-gap (4 bits)

The width of a glyph can be found by looking at the position of the next character glyph in the bitmap, which is placed right next to it.

Here is an example of a small proportional font:

Screen Shot 2011 06 01 at 17.24.37

I removed some parts for brevity.

So the “!” exclamation point for example, has width 2 in the bitmap (i.e. 3-1), with pre- and post-gaps of both 1 (i.e. 5-4). And the “#” numbersign charcter uses kerning, with a -1 pre-gap.

There is a problem, however. Most characters are fine, but after the “S”, the bit map position increments to a value greater than 255, which can’t be represented in a single byte!

Instead of doubling the position to use 2 bytes each, I implemented an “overflow” mechanism. This saves some memory, since most positions are just fine, if we ignore the top byte. We merely need to keep track of those few character positions where overflow actually happens.

This is what the “overflow position table” at the end does: for each character which straddles a 256-pixel boundary, it stores the offset of that character in the table. The result is that there is now sufficient info to locate each glyph, and this process only requires a few flash memory reads for any character code.

Note that for consistency, there are also two sentinels: one at the end of the per-character info, so that the width of that last character can be computed, and another one at the very end, to simplify the overflow calculation logic.

So there you have it: full font support, which easily fits in an ATmega!