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.
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, and 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 not in any available code page.
For example, in this code from the
python-escpos library, the
? subsitution character still has to be printed for some characters:
encoding = self.encoder.find_suitable_encoding(text) if not encoding: self._handle_character_failed(text)
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 8×16 with a thin line and a lot of whitespace, while I need to print in 12×24, 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 12×24, we have our glyph.
This glyph is now the correct size and weight for use on most thermal receipt printers.
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.
I’ve made my initial work work on “Thermal Sans Mono” available as a bitmap font PCF and BDF format on GitHub. You can find these in the “Releases” section of the GitHub project.
As always, bugs, comments and suggestions are appreciated.