Programmatically manipulating typefaces
#!/usr/bin/env python
# usage: $ python rotate-font-fontforge.py "League Gothic.ufo" League-Gothic-tranformed.ufo
import fontforge
import psMat
import math
import sys
matrix = psMat.rotate(math.radians(45))
font = fontforge.open(sys.argv[1])
for glyph in font.glyphs():
glyph.transform(matrix)
font.generate(sys.argv[2])
If you like programming, chances are you like typefaces. My favourite tumblelog, by developer Christian Neukirchen, often links to type design projects. As does Hacker News. And programming demigod Donald Knuth took time off from his epos The Art of Computer Programming to develop his own parametric typeface. And the language that describes it. And an accompanying lay out engine.
Typefaces are wonderful hybrids between design and tool. More so than any other type of design they are made to be reused. And more so than any other type of design they have a predictable structure (a font made out of glyphs made out of contours made out of points), that makes them especially suitable to be manipulated through computer programs of your own devising.
Yet if you haven’t worked within the confines of the type design world, chances are you have not yet experienced exactly how straightforward it is to work with typefaces programmatically, nowadays.
Yes, your typical binary font file is quite messy to open up and to play around with. That is why it is nice if you can use a programming library to access them. But in addition we now have the UFO file format, which is meant as an open, hackable file format for fonts. And there exist two libraries that really make it really easy to deal with font objects in a high level fashion: Robofab and FontForge-python.
Both libraries are written in the Python language. There is a historical reason for this. The typographers Just van Rossum and Erik van Blokland are pioneers in scripting for type design. They chose to go with Python, and since it has grown that Python is the go to scripting language in the type design world.
I can imagine that reasons for choosing Python include that it is straightforward and high level—and in being white space sensitive it is arguably one of the few languages which is opiniated typographically! Then again, it probably also helped that Just van Rossum is the brother of Guido van Rossum, who wrote the Python language.
If you already know Python, you are in luck. If you know programming, but do not know Python, it is pretty easy to pick up. And if you do not know programming, Python is a great language to get started as it is quite straightforward and consistent.
RoboFab is made by the aforementioned Dutch duo, joined by Tal Leming. It started its life as a scripting language for Fontlab, one of the more popular commercial font editors (and for quite some time the only one). But since the inception of the UFO file format, you can use the RoboFab library in your stand alone python scripts.
A downside to RoboFab is that it will only work with UFO fonts. In this sense the Python extension to FontForge is more flexible. It makes a lot of the functionality of FontForge available to Python: FontForge is the main open source font editor. With python-fontforge you can open and save in a slew of different font formats. It is also easy to export individual glyphs to images, or to import vector shapes into your font.
A downside to python-fontforge is that it might be tricky to install. On Linux it is usually quite easy (Debian/ubuntu: sudo apt-get install fontforge python-fontforge). On the Mac it used to be more hard: installing the Python extension through Homebrew is not working out yet. Luckily, developer Jeff Escelante recently reached out to me over this issue. He is now providing a Fontforge installer for Mac OSX that provides the python extension. But on Windows, I am not sure how feasible it is to get python-fontforge working? If someone could re-package the whole thing is an easy_installable package that would be wonderful.
In implementation the two libraries are quite similar. Imagine we have downloaded the open source League Gothic in UFO format (link! The ufo is in the source folder) and you put the UFO in the same folder as your python script.
Here is how you load in a font and print the names of the glyphs:
Fontforge
#!/usr/bin/env python
# usage: $ python print-glyphs-fontforge.py "League-Gothic.ufo"
import fontforge
import sys
font = fontforge.open(sys.argv[1])
for glyph in font.glyphs():
print glyph
Robofab
#!/usr/bin/env python
# usage: $ python print-glyphs-robofab.py "League Gothic.ufo"
from robofab.world import RFont
import sys
font = RFont(sys.argv[1])
for glyph in font:
print glyph.name
And this is to rotate each glyph 45 degrees and save to a new font.
Fontforge:
#!/usr/bin/env python
# usage: $ python rotate-font-fontforge.py "League Gothic.ufo" League-Gothic-tranformed.ufo
import fontforge
import psMat
import math
import sys
matrix = psMat.rotate(math.radians(45))
font = fontforge.open(sys.argv[1])
for glyph in font.glyphs():
glyph.transform(matrix)
font.generate(sys.argv[2])
Robofab:
#!/usr/bin/env python
# usage: $ python rotate-font.py "League Gothic.ufo" League-Gothic-tranformed.ufo
from robofab.world import RFont
from fontTools.misc.transform import Identity
import math
import sys
matrix = Identity
matrix = matrix.rotate(math.radians(45))
font = RFont(sys.argv[1])
for glyph in font:
glyph.transform(matrix)
font.save(sys.argv[2])
There's also cool stuff you can do if you save the font as an SVG font. You can then just manipulate all of the nodes
by Antonio Roberts - May 3, 2012 4:07 PM
Reply