pjg1.site / minfonts

Minified versions of fonts

While looking for custom fonts for this website, I came across Minlo, a minified version of the Apple system font Menlo.

I first thought it was made smaller by some cool compression technique. While that is true (converting to WOFF2 leads to smaller file sizes), I found that it even contains lesser characters (glyphs) than in a regular font file.

As I'd been considering using custom fonts in my website, I wanted to make something like Minlo, but for other fonts.

Manual approach

The first idea I had was to manually remove glyphs I don't need using Font Forge, a font editor.

I found a post that describes the exact same steps I tried - Create a custom font with only the glyphs you need. To summarize:

The process is straight-forward but time-consuming. Font files can have lots of glyphs, specifically any combination of characters from this List of unicode characters. There are also separate files for different weights, so the process became repetitive really quickly.

There had to be a way to do this programmatically, right?

Meet pyftsubset

I found an answer to this in the most unexpected of places - the FAQ section of Inter, a sans-serif font family.

The tool is called pyftsubset, and since I'm looking for to create a file that contains a subset of the original set of glyphs, this sounds like the right one to go with!

Looking at the documentation, the tool is part of the fonttools Python package, which I installed using pip.

$ python3 -m pip install fonttools
$ pyftsubset -h
usage: pyftsubset font-file [glyph...] [--option=value]...
Try pyftsubset --help for more information.

Looking back at the docs, there are a couple of ways to provide which glyphs I want to keep. The easiest option seems to be using --unicodes1, that takes a list of the Unicode code points (U+ followed by hexadecimal digits) representing each character.

If you're familiar with ASCII, Unicode (more specifically UTF-8) is another encoding standard that contains more characters than ASCII, like symbols and characters from other languages.

Demo time!

I created a subset file of the font Inter Regular, containing only uppercase and lowercase letters, digits and punctuation.

$ pyftsubset Inter-Regular.otf --unicodes=U+0020-007E \ 
  --layout-features='' \ 
  --passthrough-tables

The unicode range is from the Basic Latin unicode block, the --layout-features flag is set to an empty string to remove all glyphs associated with OpenType features, while --passthrough-tables skips over any sections of the file that the tool doesn't know what to do with.

With this, the file size has reduced from 591KB to 12KB, a 97% decrease!

$ du -Ahs Inter-Regular.otf Inter-Regular.subset.otf
591K    Inter-Regular.otf
 12K    Inter-Regular.subset.otf

Converting the file to the WOFF2 format reduces the size further to 7.5KB!

$ pyftsubset Inter-Regular.otf --unicodes=U+0020-007E \ 
  --layout-features='' \ 
  --passthrough-tables \ 
  --flavor=woff2

$ du -Ahs Inter-Regular.otf Inter-Regular.subset.woff2
591K    Inter-Regular.otf
7.5K    Inter-Regular.subset.woff2

This was pretty fun to experiment with, and after quite a lot of trial and error, I settled on a combination of Verdana for the text (same as before) and a custom subset of Menlo for code blocks.

Font trivia

While re-designing my blog, I found out more about the origins of Verdana and Menlo, and apparently they share common links to other fonts!

Verdana was the basis for the design of Bitstream Vera Sans. Bitstream Vera also has a monospaced font, which is what Menlo is based on.

Another common link is the DejaVu font family, an extension to the Bitstream Vera font family that adds support for more glyphs, which Menlo includes.

This explains why the two work well together!

Footnotes

  1. I got confused for a bit on why the unicodes flag was displayed with one dash instead of two. This a bug in the docs, which has been discussed in fonttools#2900