Tweaking System Font Registry

You got some really nice TrueType fonts (TTFs), and you install them on your FOSS box. For some reason, they aren't properly grouped so that a particular font is missing its italic or bold version. Instead, the italic or bold version is listed as a separate font. Because of the way the font was read and installed, your system registers the wrong information.

Can it be fixed? Of course! That's what Open Source is all about. No, it does not mean having to rewrite the code for your font installer. However, it may mean something that seems at first almost as arcane as writing code. Since my previous articles make it clear I am quite far from being any sort of coder (okay, I do XHTML by hand), you can rest assured the fix is within the reach of non-geeks. I've done it, and it works fine. It's not because I am any kind of font guru; it's a simple matter of persistence and good fortune that I discoverd this info.

First, a little theory behind the whole thing. TTFs are binary files, unlike some Type1 fonts. There was a time when the X server required special help reading TTFs. Within the file is some header information that is read by your installer. In those other OSs whence we get most of our TrueType fonts, this is all worked out automatically based on some proprietary assumptions. Makers of these TTFs encode their fonts for that system. Our FOSS installers simply read what's there, and it may not follow our much older standards.

Most fonts come in groups of four: normal, italic, bold, and bold-italic. A complete display/printing font will have all four. A notorious exception is Tahoma, but that's another story. Some free TTFs come with only one style because they are largely decorative in the first place. We are focused here on using the standard fonts that fall into rather high use patters for printing and webpage display. When there is trouble, it is usually a matter of the italic versions (meaning slanted forward, also called "oblique") are recognized, but the bold version is read as a separate font. The naming convention between regular and bold faces is not always followed precisely. You end up with two pairs of similar fonts, with similar names, but not properly registered as all one font. Most often, this is reported with some Corel TTFs.

There are two places where this information appears, and it is in plain text, and easy to change. One is in the AFM (Adobe Font Metric) files that are created for each font so that Ghostscript, and other print utilities, can decide how to use them. The other place is the fonts.dir and fonts.scale files in each directory, which are used by the X server in deciding how to display the fonts. In theory, the fonts.dir/fonts.scale files are built from the AFMs.

Let's go to where these things are found. Open Source OSs all tend to keep them in a standard location:

/usr/X11R6/lib/X11/fonts/

with the TTF folder taking any number of various names. On my current system it's called "truetype." Move into your TTF folder and look around. You would likely see at least a few AFM files.

Take at look at any randomly chosen AFM. Each font contains a set of "glyphs" -- a list of characters that have been created using the particular style of the font. Fonts with an extensive set of glyphs are quite large, with a single set of font files together taking up 5MB of space. In the age of 32-bit computing, it has become possible for just about every language in use to have their peculiar alphabet included in the display capabilities of system fonts, and in a few printer fonts. Thus, you hear talk of "UTF-8" and "Unicode" display issues. Very few fonts are truly Unicode, but anything in the range of 3000 glyphs or more comes as close as you are likely to find.

When these fonts are processed for printing, the first step is to create an AFM file that lists whatever glyphs are available. Every glyph is placed within a standard character cell, and it must be located based on where it falls within that cell. You can't simply put your apostrophe on the lower left-hand corner, or no one would consider it an apostrophe, but would think it were a comma or something. The AFM will describe the location of the glyph by citing a standard reference in numbers. When you open an AFM in a text viewer or editor, you'll see those numbers. Fortunately, this particular standard is seldom flouted.

That explains what you see at below the header information. What we are going to fix is in that header. Here's what I see in helvet.afm --

   StartFontMetrics 2.0
   Comment kfontinst iso8859-1
   FontName Helvetica
   FullName Helvetica
   FamilyName Helvetica
   Weight Medium
   Notice Created with kfontinst v0.11

If we are to have trouble, it will be in the lines where the naming appears, lines 3-5. We also add line 6 as an area of concern. In this case, because there is uniformity, there's really no problem. When we compare this with the AFM for the bold version, we see --

   FontName Helvetica-Bold
   FullName Helvetica Bold
   FamilyName Helvetica
   Weight Bold

Notice that everything matches neatly. The line beginning with FontName is simply a record of what's in the font header itself. It may have all sorts of information run together in a single string. That's usually not an issue for us. It's the other three lines where we can run into trouble. When these lines do not follow a consistent pattern for each of the four styles of a single font, they will be improperly read for printing and for display. The pattern for this is:

   Family Bold Italic

In general, the family name can be almost anything, including spaces between several term, but it must be consistent with each of the four AFMs. Bold only if it is so, and Italic comes last if it is so. Obviously, the FamilyName line should be just that, and consistent with the line above, but without the Bold or Italic designation, and the same across all four versions. For most fonts, the Weight will be Medium or Bold as appropriate.

More recent systems often do not create an AFM, because good modern word processors (for example) will present their files for printing to the Ghostscript interpreter as a single, page-filling graphic. However, you will still find the fonts listed in the fonts.dir and fonts.scale. Now here I take issue with a couple of Linux distros that act as if no font is processed directly by the X server, but that all fonts naturally pass through the Xft engine. That's not too bad if you run only KDE 3.x or Gnome 2.x, or every application has an interface drawn by Qt3 or Gtk2. As it happens, there are still a large number of applications built on other interface libraries, chief among them Tkl/Tk, Gtk1, and plain old Xlibs. None of these use the Xft engine, but render directly from the X server itself. Worse, only a handful of Type1 fonts and the TTFs are set up to render through Xft on some systems. That keeps you from seeing other fonts in at all in KDE or Gnome.

It's not as if Xft can't render these other fonts; it can indeed. Feel free to edit your fonts.conf file (usually at /etc/fonts/fonts.conf) and your XftConfig (if you have one, it's usually two directories above, where you find the fonts folder: /usr/X11R6/lib/X11/XftConfig). Just pay attention to the format near the top of each file and make sure all the font paths are listed for the fonts you want to use in your KDE and Gnome apps. Then go to each directory and make sure that fonts.dir is a copy of fonts.scale. You'll probably have to run the command:

   fc-cache

to make them available to Xft.

Take a look at your XF86Config:

   less /etc/X11/XF86Config

and you will see that right near the top is a list of font paths. In order for the X server to process fonts directly for these other interfaces, each of these font directories included in your listing of font paths must have a properly formatted fonts.dir and fonts.scale. These two files have identical formats, by the way. If you make a copy of your fonts.dir and name it fonts.scale, the job is done. It's this fonts.scale that is needed by X to render the fonts.

Since we are already in the TTFs directory, take a look at the fonts.scale file there. Several modern Linux distros make it blank, so go ahead and make a copy of fonts.dir. If you have time, run down where it is in your system that are the instructions to blank that file and turn that feature off. Each OS that does this does it differently, and you'll have to get help from someone who knows that distro.

In this file is a catalog of the fonts, matching the name of the file itself with description of the font in a standard format. Here's the entry for a Helvetica normal font on a system:

helvet.ttf -misc-Helvetica-medium-r-normal--0-0-0-0-p-0-adobe-standard
helvet.ttf -misc-Helvetica-medium-r-normal--0-0-0-0-p-0-iso10646-1
helvet.ttf -misc-Helvetica-medium-r-normal--0-0-0-0-p-0-iso8859-1
helvet.ttf -misc-Helvetica-medium-r-normal--0-0-0-0-p-0-iso8859-10
helvet.ttf -misc-Helvetica-medium-r-normal--0-0-0-0-p-0-iso8859-13
helvet.ttf -misc-Helvetica-medium-r-normal--0-0-0-0-p-0-iso8859-15
helvet.ttf -misc-Helvetica-medium-r-normal--0-0-0-0-p-0-iso8859-2
helvet.ttf -misc-Helvetica-medium-r-normal--0-0-0-0-p-0-iso8859-3
helvet.ttf -misc-Helvetica-medium-r-normal--0-0-0-0-p-0-iso8859-4
helvet.ttf -misc-Helvetica-medium-r-normal--0-0-0-0-p-0-iso8859-5
helvet.ttf -misc-Helvetica-medium-r-normal--0-0-0-0-p-0-iso8859-9
helvet.ttf -misc-Helvetica-medium-r-normal--0-0-0-0-p-0-koi8-e
helvet.ttf -misc-Helvetica-medium-r-normal--0-0-0-0-p-0-koi8-r
helvet.ttf -misc-Helvetica-medium-r-normal--0-0-0-0-p-0-koi8-ru
helvet.ttf -misc-Helvetica-medium-r-normal--0-0-0-0-p-0-koi8-u
helvet.ttf -misc-Helvetica-medium-r-normal--0-0-0-0-p-0-microsoft-cp1252

The font name comes first on each line, and must be exactly the same as the name of the file itself, and capitalized the same, if applicable. Notice that the same file is listed several times, and each line is different only at the end. That's a reference to an encoding scheme. Some applications ask for the font to be displayed according the "adobe-standard" which excludes a large number of glyphs. The next listing is the fancy encoding term for Unicode. That's included for programs that request the font with all the glyphs available. The others you can learn about by reading up on font encodings for foreign languages.

What matters for us here is that this same collection of encodings is listed in this file for each of the four versions of Helvetica. If we compare the lines for the adobe-standard encoding for each of the files, we see:

helvet.ttf -misc-Helvetica-medium-r-normal--0-0-0-0-p-0-adobe-standard
helveti.ttf -misc-Helvetica-medium-o-normal--0-0-0-0-p-0-adobe-standard
helvetb.ttf -misc-Helvetica-bold-r-normal--0-0-0-0-p-0-adobe-standard
helvetz.ttf -misc-Helvetica-bold-o-normal--0-0-0-0-p-0-adobe-standard

Notice that each of them looks the same for the most part. The file name is followed by:

Chances are your problem fonts will have something different for that second item. Whatever you have decided is your standard for the AFMs is what you want to make these match. You must edit each line wherever that font occurs so that every reference to that font file is the same. Also, if you notice that your font files are not properly described by the width and slant, you have to change them to match reality. Most errors are a matter of listing your bold versions as medium.

Naturally you will want to make a backup copy of your fonts.scale and fonts.dir (remember you have to edit both to match) before editing, so that you can recover the original. I usually make a copy in the same directory and change the name a bit:

   cp fonts.dir bak.fonts.dir

Advanced editors will allow you to change multiple lines if you are careful to identify the pattern to find and replace, so that it doesn't change something that is okay as is. Let's pretend for a moment there is some confusion on my system because I included a font called "CharterBld" that is supposed to go with my other "Charter" font files. So my fonts.dir/scale lists the bold font as if it were a separate family. To prevent having to edit each line by hand, I can tell it to search for something that matches only the lines I want to change by including enough of the line to prevent changing other "Charter" listings.

Find: chartbd.ttf -bitflow-CharterBld-medium-

Replace with: chartbd.ttf -bitflow-Charter-bold-

This protects the listings for the font file chartbk.ttf which is "Charter Black" -- a very heavy font for headings. It gives the "Charter Bold" the proper display instructions to be treated as a member of the "Charter" family, but with the bold weight.

Once you've made these corrections, you can test it by restarting the X server -- usually just logging out of the current session and then logging back in.


By Ed Hurst, updated 02 January 2004
This document released into the Public Domain.

Ed Hurst 17 December 2003