Converting Obscure Font Format into TTF


Right away, the ask is:  Is there a way to convert this to a TrueType font?  Not asking for free, but asking.

Mark Simonson thought I should try to ask my question here--not sure if this is the correct category as I am absolutely NOT a type designer, but am very interested in my font.

In the beginning of CAD (computer aided drafting) there existed a drafting font called 'blockfont.'  I find it so interesting and want to convert it to ttf so it doesn't get lost.  It is a single stroke font, so going to ttf isn't precisely straight-forward.  It is currently in a .fnt file format--but not the one you're probably thinking, not the windows one.  This one can be read in a text editor and are (x,y) coordinate pairs.  Here is a lowercase 'f'.  Part of the charm for me are the straight lines.  The file has 135 characters plotted out just like this.

CHAR     'f'   
 LM    22    31
 LD    22    94
 LD    25    108
 LD    34    119
 LD    46    125
 LD    61    125
 LD    74    119
 LD    83    108
 LD    86    94
 LM    34    73
 LD    10    73

If you plotted the (x,y) coordinates in Excel using 'Scatter with Straight Lines and Markers' you will see the letter drawn.  You will also see an extra line from the end of the curve of the 'f' to the horizontal line of the 'f'.  This would not be drawn--and I suspect the LM 34 73 may read something like 'lift your pen from (86,94) to (34,73).

At the top of the font file are only three other lines:

127, 95, 31, 94,
1, 0, 0, 0,
0.500000, 0.100000, 0.002100,

The first row is the size of the font box grid that all the letters fit in.  If you look at the 'f' above, you'll see the bottom of the 'f' is at y=31.

The second row indicates which width type was defined for the character font:  1 is fixed width

The third row are the overlap shifts and will be used only when the overlap width type is selected.  I am not sure that applies here...

If you've made it this far, MUCH APPRECIATED.  I feel like this is a tractable problem, but I am not clever enough to sort it out.


  • John HudsonJohn Hudson Posts: 2,815
    I’m guessing that the numbers could be plotted with Drawbot, and that could give you bezier lines in UFO format that could either be opened in a font editor or further manipulated in Drawbot. Obviously, to output as a visible TTF, at least minimal weight will need to be added to the lines to creat outlines. An issue you will have is that grid rounding will affect the relative thickness of the strokes at different angles, so either work with a high UPM value or perhaps go for CFF with fractional coordinate values rather than TTF.
  • PabloImpallariPabloImpallari Posts: 773
    edited March 12
    Another less complicated solution will be to generate a very very very high resolution image of your alphabet and autotrace it.
    I can do it for you in 10 minutes if you provide me with the image.
    If the result are not good enough, then John's method is the way to go.
  • Simon CozensSimon Cozens Posts: 698
    edited March 13
    Try this:

    from defcon import Font, Glyph
    import re
    import argparse
    parser = argparse.ArgumentParser(description='Convert a FNT file to UFO.')
    parser.add_argument('input', metavar='FNT', help='FNT file')
    parser.add_argument('-o', '--output')
    args = parser.parse_args()
    # Parse the file
    glyphs = {}
    thischar = None
    metrics = None
    for line in open(args.input):
    	line = line.rstrip()
    	if metrics is None:
    		metrics = [int(x) for x in line.split(",") if x]
    	newchar ="CHAR\s+'(\w+)'", line)
    	if newchar:
    		thischar = newchar[1]
    		glyphs[thischar] = []
    	instruction ="^\s+(\w+)\s+(\d+)\s+(\d+)", line)
    	if instruction:
    		glyphs[thischar].append((instruction[1], int(instruction[2]), int(instruction[3])))
    scale = 1000 / metrics[0]
    # Create the UFO
    font = Font() = 1000 = metrics[2] * scale
    layer = font.layers.defaultLayer
    for glyphname, instructions in glyphs.items():
    	glyph = layer.newGlyph(glyphname)
    	pen = glyph.getPen()
    	for ix, (instruction, x, y) in enumerate(instructions):
    		if instruction == "LM":
    			if ix != 0:
    		elif instruction == "LD":
    			print(f"Unknown instruction {instruction} in glyph {glyph}")
    	glyph.width = metrics[1] * scale
    if not args.output:
    	args.output = args.input[:-4] + ".ufo"
    print(f"Writing on {args.output}")

    As John says, you will then need to edit it in a font editor to add weight before converting to TTF, as TTF does not allow "open" outlines.

  • Amazing script!  I dropped in:

    args = parser.parse_args(['blockfont.fnt'])

    Spyder is showing me this:

    I edited the top of the font file so the top of it looks like this, and it's the same all the way down.  The script seems to have noticed the '!'

  • thecogdesignsthecogdesigns Posts: 6
    edited March 14
    This did it: for line in open(args.input, encoding='utf-8-sig'):
    So I see a folder called blockfont.ufo
    Inside that folder is a folder called glyphs and three files--fontinfo.plist, layercontents.plist, and metainfo.plist
    Inside the glyphs folder is a file called contents.plist
    All files are 1 KB.  I can open them, but it looks a bit more like a header.
    This is very close, but I don't quite see a larger file
  • John SavardJohn Savard Posts: 1,064
    Of course, there wouldn't be tools to convert such a font to TrueType directly, as it is based on different principles. But perhaps it could be converted to Metafont, since those fonts are single-stroke, and there are tools for converting from Metafont to TrueType, I believe.
  • thecogdesignsthecogdesigns Posts: 6
    edited March 14
    Just for clarity, this is the top of the file--wanted you to see the commas and whatnot just in case it is throwing the script

    127, 95, 31, 94,
    1, 0, 0, 0,
    0.500000, 0.100000, 0.002100,
    CHAR, ' ',
     LM, 0, 0,
    CHAR, ' ',
     LM, 0, 0,
    CHAR, '!',
     LM, 48, 59,
     LD, 38, 117,
     LD, 48, 126,
     LD, 57, 117,
     LD, 48, 59,
     LM, 47, 50,
     LD, 38, 40,
     LD, 47, 31,
     LD, 57, 40,
     LD, 48, 50,

  • Simon CozensSimon Cozens Posts: 698
    Sounds like it didn't correctly parse the start-of-glyph line. Put a comma after CHAR in this line:

    	newchar ="CHAR\s+'(\w+)'", line)
    and try again.

    The resulting UFO file should have more files in the glyphs/ directory, and you should be able to open it in something like Robofont or Glyphs.
  • Mark SimonsonMark Simonson Posts: 1,593
    edited March 14
    @thecogdesigns : FYI, A UFO "file" is actually a directory containing other files. On macOS, it appears to be a single file, but on your Windows system (and maybe Linux?) it will just look like a directory. Most modern font editors can open UFOs.
  • closer!

    line 317, in endPath
        raise PenError("Contour missing required initial moveTo")

    happy to take this offline if it's helpful--thank you again so much.

  • Simon CozensSimon Cozens Posts: 698
    Yeah, if you DM me the actual font file, I can see what's going on, and I can also help you with stroking/offsetting the path as well. 
  • Thomas PhinneyThomas Phinney Posts: 2,583
    Some mod needs to post it to “best of”!
  • Simon is the MAN!!  Thanks soo much.  That was awesome, thank you everyone!  Good times.
Sign In or Register to comment.