January 12, 2005

Packaging new fonts for a new year

Author: Nathan Willis

There's nothing like a new set of typefaces for starting off the new year. Like snowflakes, no two are alike -- and also like snowflakes, they have to be handled just right. After you've found the fonts you want to spend the next 12 months with, here's how you can install them correctly and easily on your Linux system by getting your package management program to do it for you.

Chances are that the fonts you've downloaded are of TrueType format. Most free fonts are made with the Macromedia Fontographer application, in which this is the default. With TrueType fonts, the only file that matters is the one with the .ttf extension; this is the actual font data.

It is common for freeware font download sites to compress their offerings in a .zip archive even if it contains only the .ttf file; if you need to, go ahead and extract it. Individual font designers may also provide their fonts in .zip archives, often including extra files like READMEs, changelogs, or shareware licenses. If you are a stickler for detail, you can find somewhere on your system to install this information, but I think it is happiest remaining in its .zip file until called upon.

The current generation of Linux distributions uses Fontconfig for keeping track of the installed fonts on the system. Check for the file /etc/fonts/fonts.conf, the Fontconfig system-wide configuration file. Among other things, this file indicates what directories Fontconfig should search for fonts. By default, most are kept in /usr/share/fonts/, so this is the simplest place to which to copy your new acquisitions.

Make a new subdirectory inside /usr/share/fonts (say, /usr/share/fonts/freeware, to be descriptive) and cp over the .ttf files you want to use. Last but not least, from the command line, issue the command fc-cache /usr/share/fonts to make Fontconfig scan the directory and pick up the presence of your new fonts.

It doesn't take much time to follow the procedure above each time you get a new batch of fonts. Nevertheless, a task like this is a perfect candidate for a little automation. I like to make an RPM binary of the fonts that I'm installing. Making a private fonts package makes it easier to keep track of what I've installed and what came out of the box, and -- because fonts are architecture-independent -- I can install the exact same set of fonts on every machine I use with minimum hassle.

RPM: Not just for breakfast anymore

Red Hat Package Manager is designed with the needs of binary application programs in mind; there are dozens of macros and options important for making, building, and installing software. Luckily, if all you want to do is move around a few non-executable files, you don't have to worry about any of that. As we saw above, the installation process takes only two steps, neither of them hazardous. All we have to do is create a .spec file that outlines these steps; the RPM program can then build a package out of our font files that, when installed, performs those steps automatically.

Listing 1 is a very simple example .spec file I used to make an RPM for a couple of freeware and shareware TrueType fonts, including my favorite Soviet-propaganda face Chyelovek, the Gavin Friday handwriting font Apologia, and the like.

Standing on the shoulders of those before me, I made this .spec file by inspecting the .spec file for an existing fonts package (in this case, the Bitstream Vera package). If you want to learn all the ins and outs of RPM or any other packaging system, there are lots of tutorials online, but it is often much easier to learn by studying real-world .spec files. I was able to excise quite a bit from the tutorial examples once I looked at the working Bitstream Vera .spec.

I'll hit the high points: the first 20 or so lines are self-explanatory things like defining the package name and revision number. Right below the description paragraph comes the first command that the rpmbuild program will actually use: %setup -q -n %{name}-%{version}. This is a built-in macro that creates the necessary directories and unpacks the sources before the RPM-building process itself.

The %install section includes one RPM-building command (/bin/rm -rf $RPM_BUILD_ROOT) followed by two install commands to mimic the steps we took to copy the .ttf files into the right directory and give them the correct permissions. It also creates an empty file called fonts.cache-1 in the fonts directory.

A few lines down, we find the fc-cache command listed under both the %post and %postun sections. This way, Fontconfig will update its cache both after we install the fonts and if we should uninstall them later.

Finally, the %files section denotes which parts of the system are affected by our package (the newly installed font files themselves and the directories where they reside).

Building an RPM from this .spec and a tarball of the .ttf font files we are installing is a simple procedure, but for the sake of space I refer you to Thomas Chung's excellent tutorials on the subject. You can do this with other packaging systems as well; the example I'm providing is for RPM-based systems, but the benefits of packaging the font files rather than installing them directly apply to all distributions.

We're talking about lifestyle choices

As I mentioned above, this is a bare-bones RPM package, but once you build it, you can leverage the RPM system's ability to maintain a clean installation and to migrate the fonts to other machines and other architectures.

Furthermore, if you take a closer look at the .spec file, you will see that it never acts on an explicitly named font file. So if you want to add more fonts to the package, you don't have to alter the .spec -- you just add the .ttf files to the tarball and rebuild the package.

But as long as we're in a package-building mood, it would behoove us to do a bit of head-scratching and decide whether we want all of our new fonts in one package, or in several. Certainly if you pay for professionally designed fonts, they should be packaged separately for licensing reasons. But it is also a good idea to (for example) put your "novelty" fonts together and separate them from your "normal" (or "readable," depending on who you ask) fonts. You do have to make a choice about how detailed you want to be when dividing your fonts into categories, but once you start thinking about them as packages rather than individual files, it soon becomes second nature.

Another thing to consider is whether to put your new fonts into a separate directory. I am an advocate of not touching /usr when there is a viable alternative. You could build your font package to install to /usr/local/share/fonts, just so long as you remember to tell Fontconfig to look there. That means making the appropriate change to the %fontdir variable in the .spec file in this example, and also adding a line to the /etc/fonts/local.conf to add the new directory to Fontconfig's default search. This will protect your font installation from being butchered by a fresh install and by overzealous or broken packages from the outside world.

Oh, and if you've been thinking to yourself, "if I can do this with fonts that I download, then why not with other non-application items like icon-sets and UI themes," congratulate yourself: you're thinking long-term and portable, which puts you ahead of the class. You can indeed make your own packages for other types of data and increase your system's manageability in those areas as well.

Of course, you don't have to go to any of this trouble; Fontconfig will happily find fonts in a user's ~/.fonts directory. But by taking a few extra minutes, you can have a much cleaner, system-wide font installation that will be easier to maintain no matter how many systems you manage or upgrade over the course of 2005.

Click Here!