Today I’m writing about a new project that I’ve started to create a font, called “Thermal Sans Mono”. I’m hoping to make this into a set of specialized free bitmap fonts for use on thermal receipt printers and printer emulators.
Here is what it looks like so far:
In this blog post I’ll talk a bit about why I needed a new font, how it’s derived from GNU Unifont, and what I’m planning to do with it.
Background
Firstly, I am solving a technical problem, not a design problem.
Printing non-ASCII characters on receipts can get a bit complex, especially if you have a lot of different printers to support. Each thermal receipt printer has a different set of available “code pages” of glyphs, which makes localisation a real adventure.
Using the escpos-printer-db project, we can currently create software which accepts UTF-8 text, then switches between the available code pages to render text for a specific printer. I’m now looking at how we can encode characters that are not in any available code page.
For example, in this code from the python-escpos
library, the ?
substitution character still has to be printed for some characters:
encoding = self.encoder.find_suitable_encoding(text[0])
if not encoding:
self._handle_character_failed(text[0])
Rather than send a ?
character, I think we could retrieve a glyph from a suitable font and send it as a bitmap instead. I previously wrote about a technique to cache glyphs from GNU Unifont in printer memory, but these glyphs don’t have the correct size or weight to be displayed alongside the glyphs that the printer has rendered itself.
Of course we can’t do this yet, because there is no suitable bitmap font.
How it’s made
The closest font to what we need is GNU Unifont, which is thankfully freely licensed. A Unifont glyph is typically 8x16 with a thin line and a lot of whitespace. I need to print in 12x24, with thick lines and no whitespace.
To control as many variables as possible, I decided to pre-render a transformed version of GNU Unifont. This involved tracing the original glyph and re-drawing it with new parameters.
The first step is to use a purpose-built algorithm to trace the lines from the glyph:
The points are then re-drawn onto a new canvas with a thicker outline, and a lot less whitespace.
When this canvas is scaled back to 12x24, we have our glyph.
This glyph is now the correct size and weight for use on most thermal receipt printers.
Roadmap
Currently, I have only processed the ASCII characters. As a GNU Unifont derivative, we should (with some effort) be able to include many more glyphs in the future.
As a starting goal, I am aiming to make the font complete enough to include as a fallback font in the escpos-php
printing library.
Download
I’ve made my initial work on “Thermal Sans Mono” available on GitHub at mike42/thermal-sans-mono. You can find it as a bitmap font in PCF and BDF format under the “Releases” section of the GitHub project.
As always, bugs, comments and suggestions are appreciated.