Scripted font generation using fontforge

This is my first attempt at making fonts using scripts... Well, apart from a digits only font, it is my first attempt to make any font! It seemed like a good use of a Sunday afternoon :-)

The plan was to make some fonts based on classic 5x9 dot matrix characters. Not a huge challenge you may think - but I did not want to spend ages positioning dots in a graphical user interface. So I ended up making some C code, that produces SVG for each character and then Python script to use fontforge to make a font from the SVG.

My 5x9 characters are defined in the C code using hex.

   {"A", {{0x20, 0x50, 0x88, 0x88, 0xF8, 0x88, 0x88}}},

That defines the capital A to look like :-
My C code makes an SVG that looks like :-

<?xml version="1.0" encoding="UTF-8">
<svg xmlns="http://www.w3.org/2000/svg" version="1.1" width="816" height="1024">
      <circle cx="255" cy="51" r="40"/>
      <circle cx="153" cy="153" r="40"/>
      <circle cx="357" cy="153" r="40"/>
      <circle cx="51" cy="255" r="40"/>
      <circle cx="459" cy="255" r="40"/>
      <circle cx="51" cy="357" r="40"/>
      <circle cx="459" cy="357" r="40"/>
      <circle cx="51" cy="459" r="40"/>
      <circle cx="153" cy="459" r="40"/>
      <circle cx="255" cy="459" r="40"/>
      <circle cx="357" cy="459" r="40"/>
      <circle cx="459" cy="459" r="40"/>
      <circle cx="51" cy="561" r="40"/>
      <circle cx="459" cy="561" r="40"/>
      <circle cx="51" cy="663" r="40"/>
      <circle cx="459" cy="663" r="40"/>

Which, as you can see was simple enough.

I also make a Python script (from the C code) along the lines of :-

import psMat
import fontforge
f.copyright="Adrian Kennard"
f.fullname="FiveByNineLED Regular"

Which has for that letters :-


And finally saves :-


Simple enough :-)

As you might guess, I was not going to just make a font as simple as that. For a start it was sensible to make some different weights and an italic variant.

For different weights, I just changed the size of the dots :-

For italic I simply adjusted the position of the dots, and told the font it was italic. I picked 10 degrees.

But that was not all. A simple dotty font looked nice but I felt I could do me. You will note I called this "LED" on the basis that it looks like a simple array of round LEDs as seen on railway stations and many such signs.

But what of LCD. For this I made squares.

For bold I actually made the squares touch, and the overlap removal in fontforge creates an outline of the joined up squares.

However, to make an italic version I could not simply move the positions as I did for the LED version as that creates a staggered row of squares. Instead I had to skew the whole glyph.

My first thought was to simply put an transform="skew(-10)" in the SVG. That worked, but there are limits to what the SVG import will do on fontforge it seems. Combinations of translations on individual components and a group object with a skew did not quite work as expected. I had to make the SVG very simple. Later, with some overlapping rectangles I actually managed to not just make errors from fontforge but segfault it! So I ended up doing the skew in the python!


That seemed to work well for this...

But I could do more... What about the way these fonts looked on an old fashioned CRT? So I made a CRT version which joined the dots horizontally with rectangles.

But there's more. This is something I did in something like 1981 when making a printer driver for a spark jet printer that could screen print BBC Micro MODE7 but not look like crap. Back then I created 45 degree lines joining octagonal dots. This works well for most letters.

But some needed help, notably where a diagonal joins a horizontal or vertical line, I would create a right angle not a diagonal. The fix was making a second "layer" of the bit map. For LED and LCD and CRT this did not matter, a dot was a dot, but for this JTD (Join The Dots) mode, it was needed to allow for things like the diagonal of an R to work...

This was another case which was a challenge. I originally planned on using an SVG path to join the dots, but that did not work. The import messed up the translations somehow, and then the overlap removal in fontforge just did not work. By simply creating a rectangle to join each circle, that worked, even the 45 degree ones, until I tried to apply a skew at the SVG level and that got very upset. A skew applied at the phython stage worked. Oddly the 45 degree ones are still making warnings but creating clean glyphs, so close enough.

Creating a simple ASCII character set was not hard. But these days we need a bit more, and so I went through the extended latin and did a lot of them (that I could sensibly work in a 5x9 matrix). I am sure there are more I can add. Thanks to Ray for pointing me to the SAA5050 data sheet with additional characters. So far over 400 characters, and more may be added over time.

The accents all look a lot better in the join-the-dots version as I could make the joins allow for the accents and not stick the accent to the letter in an odd way...

P.S. In honour of a previous blog post...

P.P.S. the "TXT" version is an attempt to mimic the Mullard SAA5050 character rounding logic.

So this is the result (may be updated from time to time if I add more characters) :-



  1. Nice! It's a shame there's not full coverage in Unicode for all the teletext characters as your code would be ideal for creating the full set.

    1. Indeed, easy to add if we could find a suitable place for them in unicode.

    2. There's been a proposal to include teletext characters in a future Unicode update. :-)


  2. Ooh, it looks like you've independently invented something very like my SAA5050-derived font, Bedstead. I haven't yet release Bedstead Plotter (which is very like your FiveByNineJTD family) but I did embroider it.

    I took the other approach to joins like the one in 'R': mine look like the ones generated by a real SAA5050 even though that's a bit odd.

    If you want to add the teletext mosaic graphics characters, please choose the same encoding in the Private Use Area that someone has already used! I think I know of three or four different encodings for them now, and it would be nice to avoid even more.

    Bedstead's glyphs are essentially in the public domain one way or another, so if you want Cyrillic, Greek, Hebrew, or IPA, you could steal Bedstead's bitmaps.

    1. That is very much more like what I coded in 1981 on a BBC micro, and yes I had the same issue with the R back then and left it like that. To make accented characters I had to do something slightly better though, hence the two pass approach now.

    2. Ah, and you went further to do proportional spacing, which I also did back in 1981, but have yet to do on this font.

    3. Yeah, the accents in Bedstead Plotter are pretty ugly when they touch the base letter. I decided that was an acceptable price for the principle of generating everything from the bitmap.

    4. You guys were writing your own proportional spacing fonts in 1981?? I couldn't even spell my name back then. Heck, the first computer I used was a Spectrum and I didn't even know proportional spacing fonts were a thing back then! You guys take "leet" to the next level.

  3. 𓂺 (Cockburn - pronounced "Coburn")Tuesday 4 December 2018 at 19:13:00 GMT

    These fonts look excellent! People seem to forget that the key function of a font is readability, and these great fonts have it in spades.

    I saw a TV show about the lady who designed the font used in UK road signs and apparently she made a fortune from it. A good font makes a better world.

    1. LOL, those were the days of the BBC game Elite, which was good, and employed deliberate duff sectors on the 5¼" disc to avoid copying. One would have to re-create the duff sector on the copy for it to work, or decode and reverse engineer its scrambling code at start up "DOES YOUR MOTHER KNOW YOU DO THIS?"... Apparently. :-)

    2. 𓂺 (Cockburn - pronounced "Coburn")Wednesday 5 December 2018 at 18:51:00 GMT

      Yes, Elite was a very good game. I remember that, once you made a certain amount of money, thereafter it was very easy to keep on raking it in. I think I used to use the mining lasers on the way to Mars to bounty hunt, which made me my first small fortune in the game.

      Do you also remember the hidden messages in the startup sequence batch files of Commodore Amiga games? I remember one game, Turbo Outrun I think it was, which had a 1000 word essay to wannabe pirates, telling them all about their "copulation" habits and insulting them in other ways. I remember having to look that word up at the time (please note, I never pirated any software, mine was an original copy and I just opened the file out of curiousity). Weren't those different times hey. Back then you could get a whole game in just a few hundred kilobytes. In fact, some of the best demo software was written in assembler and was literally less than a kilobyte (compressed) and they had all sorts of lovely 'chip tune' music and graphics. Nowadays even things like HP inkjet drivers can be a couple of Gig.

  4. Great job--thank you! I love to script and program, so I appreciate your approach. Besides that, I'm making an ugly Christmas shirt for my wife, and one of your fonts is exactly what I need. Thanks again!


Comments are moderated purely to filter out obvious spam, but it means they may not show immediately.

TOTSCO changing the rules again

One of the big issues I had in initial coding was the use of correlationID on messages. The test cases showed it being used the same on a se...