A Little Font Hackery

by John Cwikla

Copyright © 1995,1996,1997,1998,1999,2000,2001,2002 John Cwikla, All Rights Reserved.

Every now and then I come across a programming problem in X that I don't know how to solve. The first thing I do is to grab my X reference guides, 'cd' to my X source directory and start probing to see if I can find the root of my problem. I try to spend as much time as it takes to solve the problem or to sufficiently convince myself that there is no viable solution. (Most of these problems stem from having to duplicate functionality that other windowing systems provide, usually inherently, and the gods above don't understand why X is deficient in that area -- anyone doing cross-platform development knows what I am talking about.). It really annoys me if I cannot realize a solution, and I tend to put it in the back of mind hoping that my subconscious will do a better job with the puzzle than my conscious mind can. However, sometimes nothing surfaces, and I will proclaim to one and all, that due to the current state of X, with the various vendors having their own servers and source with which I have to deal, a solution that will work on all our supported platforms is completely impossible. About that time the subconscious kicks in and all the sudden I know the answer and how to fix it.

So, you wonder, what is Cwikla rambling on about now? Well, this week I had come across such a problem, made my proclamation, and then found a solution: a client wishes to request a font and get bitmaps (non-scaled) if they exist, a Type 1 scalable font if it does not, and finally any type scaled font if the there is no appropriate Type 1 font. Think about this one for a moment. When a client requests a font it specifices properties of that font, name, foundry, size, etc., and it is the server that then looks along the font path, and finds the appropriate file, bitmap or Type 1, possibly scaling the font and returning it. Remember how the sample X server works (and fs, the fontserver client). It uses a simple algorithm for finding fonts, if it finds any font that can be scaled to your specification it uses the first one it finds. If you happen to have bitmap fonts in your font path first, your bitmap fonts will be scaled. If you happen to have Type 1 fonts first in your path your Type 1 fonts will be scaled, even if you have a bitmap font of that size,if it comes after the Type 1 font in your font path it will not be used. When specifying a font you cannot ask explicitely for bitmaps or outline fonts, this is left up to the server and your font path. It would seem that you either get your bitmaps scaled, which will look good at the true bitmap sizes but look "blocky" at scaled sizes, or trust your outline fonts to look good at all sizes, which isn't going to happen. (The one point I have sort of glossed over is that the font(s) I am referring to would be the same font, but one that has both bitmaps and an outline font available.) The ideal would be to have the hand-tuned bitmaps used when they exist, but only for their true size, otherwise use the outline fonts. I did not think attaining this ideal is possible.

The subconsciouse says it is. If you read the documentation describing scalable fonts and the XLFD, there is one line that is key. It basically says that a server is not required to return a scalable font unless all fourteen fields (and the surrounding "-"'s) are included in a font specification. I think the reason for this is font aliases. Since it is possible to request a font called "fixed" or "cour24" it would be bad if a server decided to give you a scaled version of this font. "fixed" means "fixed" and the server should not return what would be its default scaled size of a font with "fixed" in its name. It is because of this reason that I believe that the majority of X servers, sample or not, will work in this way. Of course some might not, hence the "hackery" in the title of this column. This is my interpretation of my own reading in between the lines.

You need to specify all fourteen fields to get a scalable font. Or, if you do not specify all fourteen fields you will get a non-scalable font. A non-scalable font is a bitmap font. Now we are getting somewhere. If we want a 12 point Times bitmap font at 75 DPI, we can ask for:

"*-times-*-*-*-*-*-120-75-75-*-*-*-*"

Note that the first "-" is missing. And to get a 76 point Times outline font:

"-*-times-*-*-*-*-*-760-75-75-*-*-*-*"

Does this guarantee that we will get our outline font? Only if our outline fonts are first in our font path. If the bitmaps (like the 12 point bitmap) are first in our font path, the bitmaps will be scaled, and the outlines will not be used. The font path should be setup something like:

% xset fp /usr/lib/X11/fonts/Type1,/usr/lib/X11/fonts/75dpi

The motivation behind this font puzzle is due to the fact that my company needs to ship its own font with our product. We of course want our font to look as good as possible at all times, so we needed exactly what is provided for here, bitmaps if available, outline if not. The other windowing systems have been doing this for years, I'm told. Now X can too.

I wonder what else that subconscious is up to...


References

Flanagan, Programmers's Supplement for Release 5, O'Reilly & Associates, Inc.