Font engineering, Part 1: Git repository structure
As I’m fond of mentioning at every opportunity, my twin passions are web development and typeface design. It was curious though that until recently, I never considered combining the two disciplines. Fonts are essentially pieces of software; can we therefore apply techniques commonly found in the world of software engineering to font projects?
Software engineers are typically familiar with the following concepts:
- Source control. A source control system such as Git can be used to track and manage a complete history of changes to your project.
- Writing tests. A developer may write a suite of tests to ensure that a piece of software behaves as intended. This is especially useful to ensure that, when new functionality is added to a project, it does not break existing behaviour.
- Continuous Integration/Continuous Deployment (or CI/CD). A mechanism for deploying changes immediately to a production environment.
In this post we’ll adopt a source control system before (hopefully) discussing other concepts in future posts.
Source control
The benefits of using Git as a source control system have been discussed numerous times elsewhere. So, instead of repeating all of that, I suggest you have a read of Git for Type Designers, which is a few years old now but still broadly relevant. I’ll be referring to this page at various points throughout this post.
I won’t go through the whole step-by-step process of creating a repository from scratch. Instead, I’ve already created an example repository for one of my old and cringeworthy open-source fonts from 2005 and will take you through some of the decisions I’ve made when setting up the structure of the repository. Your use cases may differ, in which case hopefully I’ve given you enough information for you to make your own decisions.
Firstly I’ve chosen GitHub to host a remote copy of this repository. Since Git for Type Designers was written, GitHub was acquired by Microsoft and now allows unlimited private repositories with up to three collaborators for free. So, GitHub it is.
The second thing to note is that using Git on the command line can be a little daunting and - developer confession! - I tend to use a GUI instead. My tool of choice is SourceTree from Atlassian, which is available on Windows and macOS. Other tools are available though.
File structure
Next: how should we structure our project - which folders do we need? Fortunately that decision has already (pretty much) been made for you. Unified Font Repository is a sample font project structure which lets you organise your files into areas for sources, fonts and associated documentation. It’s nice to have a convention for this sort of thing as it saves having to relearn different folder structures for different projects.
Others have extended the Unified Font Repository and it’s worth checking them out. If you’re thinking of releasing your font through Google Fonts then the Google Fonts public template is the way to go. Not only has the folder structure been set up for you, but you can also build, test and create HTML proof files too. Fantastic!
I’m not going to take that route as I want to go through the learning experience of setting all this up, and if you’ve got this far, hopefully you will too. So instead I’ve plumped for this extended version from David Jonathan Ross. The README describes the folders nicely, so I recommend you go over there and have a look.
File format
The next decision: what source file format(s) should we be storing? Let’s once again turn to the Git for Type Designers page for advice. Here it recommends using the UFO file format, which is a pretty fair recommendation - it’s the native font format for Robofont and other font editors are also able to save to that format. However using this as your sole font format means you may lose font editor-specific data.
Why is this? I’m going to discuss FontLab here as that’s the editor I predominantly use, but this may be true of other editors. In the FontLab documentation on file formats:
FontLab offers two native file formats for saving: VFC (binary) and VFJ (JSON based). Both can keep all elements used in the font design process. Saving in any other format is actually an export and is likely to lose some elements such as glyph notes, pins, element references, etc. VFC is faster, but VFJ is human-readable.
An aside here: these two new font formats have been introduced since Git for Type Designers was written. FontLab’s .vfj
font format is human-readable and is indeed capable of being ‘diffed’ (i.e. Git is capable of displaying what changes have been made to your file)
Making a decision
We could solely use FontLab’s .vfj
file format as the single source of truth. However I’m not going to. The .vfj
file is large and it can be quite slow for source control tools to display the diffed results in a GUI.
So, my recommendation is to store fonts in both .ufo
AND a native file format (.vfc
, .glyphs
). You get the twin benefits of:
- easily navigating the changes to your font in the source control GUI of your choice by looking through the
.ufo
folder - not losing any font editor-specific data
The only downside is that, when saving your .vfc
file in FontLab, you have to remember to export your source files as a UFO at the same time. It’s a pain, but a trade-off I’m willing to make at the moment. Maybe it’s possible to do this as a Python script - I haven’t really worked that bit out yet. Hey ho.
Output fonts
Our repository now nicely stores all our source files and we can easily see updates. But what about our final exported fonts? We need .otf
s, .ttf
s and web fonts too. We could just export all the file formats we need in our font editor and commit them along with our source files. But that’s a very laborious thing to do manually. Moreover, we’re just bulking up our repository with redundant information. We have all the info we need to generate our output fonts in our source files - so why bother committing them too? Here comes a potentially controversial decision - I’m not going to store output fonts directly in the repository. Instead we’re going to use Python scripts to build our fonts, and we’ll do that in Part 2, coming soon.