The joy of build scripts

When writing software, there is a big difference between the human readable code, and the compiled machine readable code. The human readable code is easy to edit, while the machine readable code can only be read by complete psycos, and even there with lots of effort. In order to get from human to computer readable, there is a step called compiling.

I've found this to be a useful paradigm with type design as well. The source files are my FontLab files. There are a lot of things that need to happen between my easy to edit source files and the finished exported fonts. For one thing, I use interpolation for some of the weights. All of the interpolated weights must be created, then renamed with have the proper "Font Info" applied. Also, I often like to use separate contours and sometimes even components for different strokes (see fig. 1). For example, it's much easier to adjust the weight and correct italic distortions in the "A" if the crossbar isn't welded on to the frame. These all need to be decomposed with overlaps removed. When I started making fonts, it would take forever if I needed to make a tweak and re-export final files.

Enter the build script. When compiling complicated software, you will often see a file called Makefile, build.sh or build.xml in the directory with all of the source. These files are often complicated scripts telling the complier (whether it be java, c, or even Actionscript) where all of the pieces are and the steps to compile to final executable software.

I've started doing the same thing with my type design projects. Along with a series of master files in the project directory is a file called build.py. This build file is customized for each project. Here is the build script for Doublewide:

"build script for Doublewide"

from MixFonts import Mix,Master
from SetNames import setNames
from string import split
from ItalicizeGlyph import italicizeGlyph

BASEDIR = "/Volumes/Data/Type/2007/Doublewide"
BUILDDIR = "Build_Doublewide"
DECOMPOSELIST = split("A B D E F G H K L M N P Q R S T U V W X Z Y OE oe onesuperior tm section a b d e f g h i k l m n p q r t u z dollar registered plusminus notequal multiply ampersand Thorn thorn one eight AE ae yen sterling cent Oslash oslash eth Eth lslash Lslash plus numbersign fl fi at asterisk Ccedilla ccedilla Euro")

fl.Open("%s/Doublewide_Bold.vfb"%BASEDIR,False)
BOLD = fl[len(fl)-1]

fl.Open("%s/Doublewide_Light.vfb"%BASEDIR,False)
LIGHT = fl[len(fl)-1]

fl.Open("%s/Doublewide_Medium.vfb"%BASEDIR,False)
MEDIUM = fl[len(fl)-1]

fl.Open("%s/Doublewide_LightItalic.vfb"%BASEDIR,False)
LIGHTITALIC = fl[len(fl)-1]

fl.Open("%s/Doublewide_BoldItalic.vfb"%BASEDIR,False)
BOLDITALIC = fl[len(fl)-1]


def copyFeatures(f1, f2):
	for ft in f1.features:
		t = Feature(ft.tag, ft.value)
		f2.features.append(t)
	f2.ot_classes = f1.ot_classes

def makeFont(mix,names,italic = None):
	n = names.split("/")
	print n[0],n[1]
	f = mix.mixFonts()
	fl.Add(f)
	copyFeatures(BOLD,f)
	#fl.CallCommand(33553)
	for gname in DECOMPOSELIST:
		g = f[f.FindGlyph(gname)]
		if g != None:
			g.Decompose()
			g.RemoveOverlap()
	g.Autohint()
		
	index = len(fl)-1
	fl.UpdateFont(index)
	setNames(f,n[0],n[1],n[2],n[3])
	otfName = "%s/%s/otf/%s.otf"%(BASEDIR,BUILDDIR,f.font_name)
	ttfName = "%s/%s/ttf/%s.ttf"%(BASEDIR,BUILDDIR,f.font_name)
	fl.GenerateFont(index,ftOPENTYPE,otfName)
	fl.GenerateFont(index,ftTRUETYPE,ttfName)
	
	f.modified = 0
	fl.Close(index)

# Masters

lt = Master(LIGHT,0.)
bd = Master(BOLD,1.)

ltit = Master(LIGHTITALIC,0.)
bdit = Master(BOLDITALIC,1.)

#exceptions
med = Master(MEDIUM,.5)

makeFont(Mix([lt,bd],0.),"Doublewide/Light/Regular/Lt")
makeFont(Mix([lt,med,bd],Point(0.3,0.38)),"Doublewide/Regular/Regular/Rg")
makeFont(Mix([lt,med,bd],Point(0.56,0.61)),"Doublewide/Medium/Bold/Lt")
makeFont(Mix([lt,bd],1.),"Doublewide/Bold/Bold/Rg")

makeFont(Mix([ltit,bdit],Point(0.,-0.05)),"Doublewide/Light Italic/Italic/Lt")
makeFont(Mix([ltit,bdit],Point(0.3,0.30)),"Doublewide/Italic/Italic/Rg")
makeFont(Mix([ltit,bdit],Point(0.56,0.61)),"Doublewide/Medium Italic/Bold Italic/Lt")
makeFont(Mix([ltit,bdit],1.),"Doublewide/Bold Italic/Bold Italic/Rg")

Note: Mix and Master are my interpolation classes. More on them later.

Post new comment

The content of this field is kept private and will not be shown publicly.
  • Web page addresses and e-mail addresses turn into links automatically.
  • Allowed HTML tags: <a> <em> <strong> <cite> <code> <ul> <ol> <li> <dl> <dt> <dd>
  • Lines and paragraphs break automatically.

More information about formatting options

Image CAPTCHA
Copy the characters (respecting upper/lower case) from the image.