Appendix B. Specifying Fonts and Colors

This appendix describes the possible values for color, font, and geometry specifications. It also describes the font service and scalable font capabilities added in Release 5.

This appendix describes the possible values for color, font, and geometry specifications. For fonts, it first describes basic font naming, and then the font service and scalable font capabilities added in Release 5.

Color Specification

Many clients have resources and command-line options that allow you to specify the color of the window background, foreground (the color that text or graphic elements will be drawn in), or window border. For example, the following resources might be set for a Label widget:

*background:   orange   set the background color to orange
*foreground:   black    set the foreground color to black
*borderColor:  black    This must be Halloween!

The corresponding command-line options have the form:

-bg color 

sets the background color

-fg color 

sets the foreground color

-bd color 

sets the border color

Some clients allow additional options to specify color for other elements, such as the cursor, highlighting, and so on.

By default, the background is usually white and the foreground black, even on color workstations. You can specify a new color using either the names in the X Window System's color name database or hexadecimal values.

Color Names

The rgb.txt file, usually located in /usr/lib/X11 on UNIX systems, is supplied with X and consists of predefined colors assigned to specific (but not necessarily intuitive) names.[105]

The following are some of the default color names that come with the X Window System. (See Appendix A, System Management, in Volume Three, X Window System User's Guide, Motif Edition, for information on customizing color name definitions.) This file is not part of the X standard, so vendors are free to modify it. However, most will just add to it, or redefine the values associated with each color name for better effects on their display hardware.

aquamarine          mediumaquamarine   black              blue
cadetblue           cornflowerblue     darkslateblue      lightblue
lightsteelblue      mediumblue         mediumslateblue    midnightblue
navyblue            navy               skyblue            slateblue
steelblue           coral              cyan               firebrick
gold                goldenrod          mediumgoldenrod    green
darkgreen           darkolivegreen     forestgreen        limegreen
mediumforestgreen   mediumseagreen     mediumspringgreen  palegreen
seagreen            springgreen        yellowgreen        darkslategray
darkslategray       dimgray            dimgray            lightgray
lightgray           khaki              magenta            maroon
orange              orchid             darkorchid         mediumorchid
pink                plum               red                indianred
mediumvioletred     orangered          violetred          salmon
sienna              tan                thistle            turquoise
darkturquoise       mediumturquoise    violet             blueviolet
wheat               white              yellow             greenyellow

A number zero through three can be appended to each of these names in order to get various intensities of each color. In addition, a complete range of grays are provided by using the name gray or gray followed by a number from zero through 100.

For example, the command line:

% xterm -bg lightblue -fg darkslategray -bd plum &

creates an xterm window with a background of light blue, foreground of dark slate gray, and border of plum. Note that the RGB values in the color database provided by MIT are correct for only one type of display; you may find that the color you get is not exactly what you expect given the name. To combat this, vendors may have corrected the RGB values to give colors closer to what the name implies. Or they may provide a device-independent color database. See Volume One, Xlib Programming Manual or The X Color Management System for more on device-independent color specification.

At the command line, a color name should be typed as a single word (for example, darkslategray). However, you can type the words comprising a color name separately if you enclose them in quotes, as in the following command line:

% xterm -bg "light blue" -fg "dark slate gray" -bd plum &

Hexadecimal Color Specification

You can also specify colors more exactly using a hexadecimal color string. You probably won't use this method unless you require a color not available by using a color name. This method is not recommended in R5 and later: use the device-independent style specification instead. Moreover, you shouldn't use this method unless necessary because it tends to discourage the sharing of colors between applications. In order to understand how this works, you may need a little background on how color is implemented on most workstations.

The RGB Color Model

Most color displays on the market today are based on the RGB color model. Each pixel on the screen is actually made up of three phosphors: one red, one green, and one blue. Each of these three phosphors is excited by a separate electron beam. When all three phosphors are fully illuminated, the pixel appears white to the human eye. When all three are dark, the pixel appears black. When the illumination of each primary color varies, the three phosphors generate a subtractive color. For example, equal portions of red and green, with no admixture of blue, makes yellow.

As you might guess, the intensity of each primary color is controlled by a three-part digital value--and it is the exact makeup of this value that the hexadecimal specification allows you to set.

Depending on the underlying hardware, different servers may use a larger or smaller number of bits (from 4 to 16 bits) to describe the intensity of each primary. To insulate you from this variation, clients are designed to take color values containing anywhere from 4 to 16 bits (1 to 4 hex digits), and the server then scales them to the hardware. As a result, you can specify hexadecimal values in any one of the following formats:

#RGB
#RRGGBB
#RRRGGGBBB
#RRRRGGGGBBBB

where R, G, and B represent single hexadecimal digits and determine the intensity of the red, green, and blue primaries that make up each color.

When fewer than four digits are used, they represent the most significant bits of the value. For example, #3a6 is the same as #3000a0006000.

What this means concretely is perhaps best illustrated by looking at the values that correspond to some colors in the color name database. We'll use 8-bit values (two hexadecimal digits for each primary) because that is the way they are defined in the rgb.txt file:

#000000      black
#FCFCFC      white
#FF0000      red
#00FF00      green
#0000FF      blue
#FFFF00      yellow
#00FFFF      cyan
#FF00FF      magenta
#5F9F9F      cadet blue
#42426F      cornflower blue
#BFD8D8      light blue
#8F8FBC      light steel blue
#3232CC      medium blue
#23238E      navy blue
#3299CC      sky blue
#007FFF      slate blue
#236B8E      steel blue

As you can see from the colors given above, pure red, green, and blue result from the corresponding bits being turned full on. All primaries off yields black, while all nearly full on gives white. Yellow, cyan, and magenta can be created by pairing two of the other primaries at full intensity. The various shades of blue shown above are created by varying the intensity of each primary--sometimes in unexpected ways.

The bottom line here is that if you don't intimately know the physics of color, the best you can do is to look up existing colors from the color name database and experiment with them by varying one or more of the primaries till you find a color you like. Unless you need precise colors, you are probably better off using color names.

If you do specify a color using a hexadecimal value, try to use the same value for several applications so that they will share a color cell.

In R5, the recommended way to specify specific RGB values is:

RGB:<red>/<green>/<blue>

Where red, green, and blue are each between 1 and 4 hexadecimal digits. Different primaries may be specified with different numbers of digits. If fewer than 4 digits are specified, they do not simply represent the most significant bits of the value; instead they represent a fraction of the maximum value. So the single digit 0xA does not mean 0xA000, but 10/15ths of 0xFFFF, or 0xAAAA.

This form is now understood by all the Xlib functions that accept color strings.

How Many Colors are Available?

The number of distinct colors available on the screen at any one time depends on the amount of memory available for color specification.

A color display uses multiple bits per pixel (also referred to as multiple planes or the depth of the display) to select colors. Programs that draw in color use the value of these bits as a pointer to a lookup table called a colormap, in which each entry (or colorcell) contains the RGB values for a particular color.[106] As shown in Figure B-1, any given pixel value is used as an index into this table--for example, a pixel value of 16 will select the sixteenth colorcell.

This implementation explains several issues that you might encounter in working with color displays.

First, the range of colors possible on the display is a function of the number of bits available in the colormap for RGB specification. If 8 bits are available for each primary, then the range of possible colors is 256 3 (somewhere over 16 million colors). This means that you can create incredibly precise differences between colors.

However, the number of different colors that can be displayed on the screen at any one time is a function of the number of planes. A four-plane system can index 2 4 colorcells (16 distinct colors); an eight-plane system can index 2 8 colorcells (256 distinct colors); and a 24-plane system can index 2 24 colorcells (over 16 million distinct colors).

If you are using a four-plane workstation, the fact that you can precisely define hundreds of different shades of blue is far less significant than the fact that you can't use them all at the same time. There isn't space for all of them to be stored in the colormap at one time.

Figure B-1. Multiple planes used to index a colormap

This limitation is made more significant by the fact that X is a multiclient environment. When X starts up, usually no colors are loaded into the colormap. As clients are invoked, certain of these cells are allocated. But when all of the free colorcells are used up, it is no longer possible to request new colors. When this happens, you will usually be given the closest possible color from those that have already been allocated. However, you may instead be given an error message and told that there are no free colorcells.

In order to minimize the chance of running out of colorcells, many programs use “shared” colorcells. Shared colorcells can be used by any number of applications, but they can't be changed by any of them. They can be deallocated only by each application that uses them, and when all applications have deallocated the cell, it is available for setting again. Shared cells are most often used for background, border, and cursor colors.

Alternately, some clients have to be able to change the color of graphics they have already drawn. This requires another kind of cell, called private, which can't be shared. A typical use of a private cell would be for the palette of a color mixing application. Such a program might have three bars of each primary color, and a box which shows the mixed color. The primary bars would use shared cells, while the mixed color box would use a private cell.

In summary, some programs define colorcells to be read-only and shareable, while others define colorcells to be read/write and private.

To top it off, there are even clients that may create a whole private colormap of their own, which will be swapped in by the window manager. Because of the way color is implemented, if this happens, all other applications will be displayed in unexpected colors.

In order to minimize such conflicts, you should request precise colors only when necessary. By preference, use color names or hexadecimal specifications that you specified for other applications.

For more information on color, see Chapter 7, Color, in Volume One, Xlib Programming Manual.

Font Specification

Most widgets that display text allow you to specify the font to be used in displaying text in the widget, via either the XtNfont resource, or the -fn and -font command-line options.

The X Window System supports many different display fonts, with different sizes and type styles. (These are screen fonts and are not to be confused with printer fonts.)

Adobe Systems, Inc., Digital Equipment Corporation, and others have contributed five families of screen fonts (Courier, Helvetica, New Century Schoolbook, Symbol and Times) in a variety of sizes, styles, and weights for 75 dots per inch monitors. Bitstream, Inc. contributed its Charter font family in the same sizes, styles, and weights for both 75 and 100 dots per inch monitors, plus outline versions of the same fonts.

By default, standard fonts are stored in three directories:

Table B-1.

Directory

Contents

/usr/lib/X11/fonts/mis c

Six fixed-width fonts (also available in Release 2), the cursor font.

/usr/lib/X11/fonts/75d pi

Fixed- and variable-width fonts, 75 dots per inch.

/usr/lib/X11/fonts/100 dpi

Fixed- and variable-width fonts, 100 dots per inch.


These three directories (in this order) comprise X's default font path. The font path can be changed with the fp option to the xset client, as described in Volume Three,X Window System User's Guide, Motif Edition. (The font path, together with a great deal of other information about the server defaults, can be listed with xset query.) The font path may include font servers, which supply fonts over the network. All fonts in the font path can be listed with xlsfonts and fslsfonts, and the characters in a font can be displayed on the screen with xfd.

The names of each font file in the font directories has a filename extension of .snf, which stands for server natural format. Fonts are distributed in binary distribution format (bdf) in Release 4, and need to be compiled for a given server. Fonts are distributed in portable compiled format (pcf) in Release 5, and do not need compiling.

Font Naming Conventions

If you do a listing of any of the current font directories, you'll notice that the filenames have .snf or .pdf extensions. However, font names are not determined by the names of the files in which they are stored.

Now, a font's name is determined by the contents of the font property named FONT[107] rather than the name of the file in which the font is stored.

If you run xlsfonts, you'll get an intimidating list of names similar to the one shown in Figure B-2. names are defined by the X Logical Font Description convention, also known as XLFD. The complete XLFD is reprinted in Volume Zero,X Protocol Reference Manual. Upon closer examination and XLFD name contains a great deal of useful information:

Figure B-2. A font name

This rather verbose line is actually the name of the font stored in the file courBO10 (in the 75dpi directory). This font name specifies the foundry (Adobe), the font family (Courier), weight (bold), slant (Oblique), set width (normal), size of the font in pixels (10), size of the font in tenths of a point (100--measured in tenths of a point, thus equals 10 points), horizontal resolution (75dpi), vertical resolution (75dpi), spacing (m, for monospace), average width in tenths of a pixel (60--measured in tenths of a pixel, thus equals 6 pixels) and character set (iso8859-1).

The meaning of many of these statistics is obvious. Some of the less obvious information is explained below.

Foundry 

The type foundry (in this case, Adobe) that digitized and supplied the font.

Set width 

A value describing a font's proportionate width, according to the foundry. Typical set widths include: normal, condensed, narrow, double width. All of the newer fonts have the set width normal.

Pixels and points 

Type is normally measured in points, a printer's unit equal to 1/72 of an inch. The size of a font in pixels depends on the resolution of the display font in pixels. For example, if the display font has 100 dots per inch (dpi) resolution, a 12 point font will have a pixel size of 17, while with 75 dpi resolution, a 12 point font will have a pixel size of 12.

Spacing 

Either m (monospace, i.e., fixed-width) or p (proportional, i.e., variable-width).

Horizontal and vertical resolution 

The resolution in dots per inch that a font is designed for. Horizontal and vertical figures are required because a screen may have different capacities for horizontal and vertical resolution.

Average width 

Mean width of all characters in the font, measured in tenths of a pixel, in this case 6 pixels.

Character set 

ISO, the International Standards Organization, has defined character set standards for various languages. The iso8859-1 in Figure B-2 represents the ISO Latin 1 character set, which is used by all of the fonts in the 75dpi and 100dpi directories. The ISO Latin 1 character set is a superset of the standard ASCII character set, which includes various special characters used in European languages other than English. See Appendix H of Volume Two,Xlib Reference Manual, for a complete listing of the characters in the ISO Latin 1 character set.

This font-naming convention is intended to allow for the unique naming of fonts of any style, resolution and size. It is powerful, but unwieldy.

To create a label widget that displays text in the font stored in the file courBO10, you could use the resource setting:

*label:  -adobe-courier-bold-o-normal--10-100-75-75-m-60-iso8859-1

Developers can specify default fonts using a complete font name. However, requiring users to type a font name of this length is neither desirable nor practical. The X Window System developers have provided two alternatives: wildcarding and aliasing.

Font Name Wildcarding

Any unnecessary part of a font name can be “wildcarded” by specifying a question mark (?) for any single character and an asterisk (*) for any group of characters.

For example, using a wildcarded font name, the resource specification above could be written:

*label:  *courier-bold-o-*-100*

(Note that when using wildcards with the -fn command line option, you must take care to quote the font names, since the UNIX shell has special meanings for the wildcard characters * and ?. This can be done by enclosing the entire font name in quotes, or by escaping each wildcard character by typing a backslash before it.)

If more than one font in a given directory matches a wildcarded font name, the server chooses the font to use. If fonts from more than one directory match the wildcarded name, the server will always choose a font from the directory that is earlier in the font path. Thus, if a wildcarded font name matches a font from both the 75dpi and 100dpi directories, and the 75dpi directory comes first in the font path, the server chooses the font from that directory.

In creating a wildcarded font name, you need to decide which parts of the standard font name must be explicit and which parts can be replaced with wildcards. As the previous example illustrates, you can use a single wildcard character for multiple parts of the font name. For instance, the final asterisk in the example stands for the sequence:

-75-75-m-60-iso8859-1

in the explicit font name. The idea is to specify enough parts of the font name explicitly so that the server gives you the font you have in mind.

It's helpful to familiarize yourself with the available font families, weights, slants, and point sizes. The following list gives these statistics for the fonts in the directories 75dpi and 100dpi in the standard X distribution from MIT.[108](The fonts in the misc directory are holdovers from Release 2 and have short, manageable names that should not require wildcarding.)

Font families 

Charter, Courier, Helvetica, New Century Schoolbook, Symbol, Times

Weights 

Medium, bold

Slants 

Roman (r), an upright design

Italic (i), an italic design slanted clockwise from vertical

Oblique (o), an obliqued upright design, slanted clockwise from vertical

Point sizes 

8, 10, 12, 14, 18, 24

If you're unfamiliar with the general appearance of a particular font family, try displaying one of the fonts with xfd, as described in Volume Three,X Window System User's Guide, Motif Edition.

As a general rule, we suggest you type the following parts of a font name explicitly:

  • Font family

  • Weight

  • Slant

  • Point size

Note that it's better to match the point size field, which is measured in tenths of a point (the 100 in the previous example, equal to 10 points), than the pixel field (the 10). This allows your wildcarded font name to work properly with monitors of different resolutions. For example, say you use the following name to specify a 24 point (size), medium (weight), Italic (slant) Charter (family) font:

*charter-medium-i-*-240-*

This will match either of the following two font names (the first for 75 dpi monitors and the second for 100 dpi monitors):

-bitstream-charter-medium-i-normal--25-240-75-75-p-136-iso8859-1
-bitstream-charter-medium-i-normal--33-240-100-100-p-136-iso8859-1

depending on which directory comes first in your font path. Specifying font size explicitly in pixels (25 for the first or 33 for the second) rather than in points would limit you to matching only one of these fonts.

Given the complexity of font names and the rules of precedence used by the server, you should use wildcards carefully.

Font Name Aliasing

Another way to abbreviate font names is by aliasing--that is, by associating them with alternative names. You can create a file (or files) called fonts.alias, in any directory in the font search path, to set aliases for the fonts in that directory. The X server uses both fonts.dir files (see Section B.2.5, "The fonts.dir Files") and fonts.alias files to locate fonts in the font path.

Be aware that when you create or edit a fonts.alias file, the server does not automatically recognize the aliases in question. You must make the server aware of newly created or edited alias files by resetting the font path with xset.

The fonts.alias file has a two-column format similar to the fonts.dir file (described in a moment): the first column contains aliases, the second contains the actual font names. If you want to specify an alias that contains spaces, enclose the alias in double quotes. If you want to include double quotes or other special characters as part of an alias, precede each special symbol with a backslash.

When you use an alias to specify a font in a command line, the server searches for the font associated with that alias in every directory in the font path. Therefore, a fonts.alias file in one directory can set aliases for fonts in other directories as well. You might choose to create a single alias file in one directory of the font path to set aliases for the most commonly used fonts in all the directories. Example B-1 shows a sample fonts.alias file.

Example B-1. Sample fonts.alias file

xterm12    -adobe-courier-medium-r-normal--12-120-75-75-m-70-iso8859-1
xterm14    -adobe-courier-medium-r-normal--14-140-75-75-m-90-iso8859-1
xterm18    -adobe-courier-medium-r-normal--18-180-75-75-m-110-iso8859-1

As the names of the aliases suggest, this sample file contains aliases for three fonts (of different point sizes) that are easily readable in xterm windows.

You can also use wildcards within the font names in the right hand column of an alias file. For instance, the alias file above might also be written:

xterm12    *courier-medium-r-*-120*
xterm14    *courier-medium-r-*-140*
xterm18    *courier-medium-r-*-180*

Once the server is made aware of aliases, you can specify an alias in resource specifications or on the command line:

xterm.font: xterm12

or:

% xterm -fn xterm12

If you are accustomed to the Release 2 font naming convention (each font name being equivalent to the name of the file in which it is stored, without the .snf extension), there is a way to emulate this convention using alias files. In each directory in the font path, create a fonts.alias file containing only the following line:

FILE_NAMES_ALIASES

Each filename (without the .snf extension) will then serve as an alias for the font the file contains. Note that an alias file containing this line applies only to the directory in which it is found. To make every font name equivalent to the name of the file in which it is stored, you need to create a fonts.alias file such as this in every font directory.

If you've specified FILE_NAMES_ALIASES in an alias file, you can choose the fonts in that directory by means of their filenames, as we did in the resource example at the end of Chapter 2, Introduction to the X Toolkit and Motif.

Making the Server Aware of Aliases

After you create (or update) an alias file, the server does not automatically recognize the aliases in question. You must make the server aware of newly created or edited alias files by “rehashing” the font path with xset. Enter:

% xset fp rehash

on the command line. The xset option fp (font path) with the rehash argument causes the server to reread the fonts.dir and fonts.alias files in the current font path. You need to do this every time you edit an alias file. (You also need to use xset if you add or remove fonts. See Volume Three,X Window System User's Guide, Motif Edition, for details.)

The fonts.dir Files

In addition to font files, each font directory contains a file called fonts.dir. The fonts.dir files serve, in effect, as databases for the X server. When the X server searches the directories in the default font path, it uses the fonts.dir files to locate the font(s) it needs.

Each fonts.dir file contains a list of all the font files in the directory with their associated font names, in two-column form. (The first column lists the font file and the second column lists the actual font name associated with the file.) The first line in fonts.dir lists the number of entries in the file (i.e., the number of fonts in the directory).

Example B-2 shows the fonts.dir file from the directory /usr/lib/X11/fonts/100dpi. As the first line indicates, the directory contains 24 fonts.

Example B-2. a portion of the fonts.dir file in /usr/lib/X11/fonts/100dpi

24
charBI08.snf -bitstream-charter-bold-i-normal--11-80-100-100-p-68-iso8859-1
charBI10.snf -bitstream-charter-bold-i-normal--14-100-100-100-p-86-iso8859-1
charBI12.snf -bitstream-charter-bold-i-normal--17-120-100-100-p-105-iso8859-1
charBI14.snf -bitstream-charter-bold-i-normal--19-140-100-100-p-117-iso8859-1
charR08.snf -bitstream-charter-medium-r-normal--11-80-100-100-p-61-iso8859-1
charR10.snf -bitstream-charter-medium-r-normal--14-100-100-100-p-78-iso8859-1
charR12.snf -bitstream-charter-medium-r-normal--17-120-100-100-p-95-iso8859-1
charR14.snf -bitstream-charter-medium-r-normal--19-140-100-100-p-106-iso8859-1
charR18.snf -bitstream-charter-medium-r-normal--25-180-100-100-p-139-iso8859-1
charR24.snf -bitstream-charter-medium-r-normal--33-240-100-100-p-183-iso8859-1


The fonts.dir files are created by the mkfontdir client when X is installed. mkfontdir reads the font files in directories in the font path, extracts the font names, and creates a fonts.dir file in each directory. If fonts.dir files are present on your system, you probably won't have to deal with them, or with mkfontdir, at all. If the files are not present, or if you have to load new fonts or remove existing ones, you will have to create files with mkfontdir. Refer to Volume Three,X Window System User's Guide, Motif Edition, for details.

Font Service

If you have worked with X at a site with workstations from several vendors, you may have encountered frustrating problems with the use of fonts. If fonts have different names on one host than they do on another, an application that performs normally on one display will abort with a “Can't load font” error on another. Or you may have had to maintain separate defaults files for use on different displays.

Ideally, the site administrator could simply place fonts in a directory of a networked file system that is accessible to all hosts at the site. Unfortunately, no binary format for font data has been standardized, and the X servers supplied by different vendors expect data in mutually incompatible formats. If a vendor wishes to support several font formats, the server must include code to parse each one.

R5 provides an elegant solution to these problems in the form of a networked font service. Under this new model, an X server can obtain font data in a simple bitmap format from a font server process running somewhere on the network. The font server does the work of parsing font files for any supported format and exports font data in a bitmap format standardized by the X Font Service Protocol (reprinted in Volume Zero,X Protocol Reference Manual as of late 1992). X servers that take advantage of font service no longer need to do the work of parsing fonts themselves. In the near future, however, it is likely that workstation-based X servers and X terminals will continue to support file-based fonts along with their support for font servers.

The Font Service Protocol was designed by Jim Fulton of Network Computing Devices. The font server in the MIT distribution was implemented primarily by Dave Lemke, also of NCD. In addition, Apple Computer has donated a font server (which runs only on the Apple Macintosh computer) to export the Apple bitmap fonts, and, if available, the Apple TrueType fonts as well.

Typically, a font server will run on one host per site and will export all the fonts available at the site, but there are a variety of other ways that font service can be configured. A large site may choose to have multiple font servers to prevent overloading of a single server or to protect against service outages caused by network trouble or server crashes. A font server could export fonts parsed from a variety of formats, or a separate server could be used for each format. A vendor of fonts with a custom format might provide a special font server to export those fonts, and might use the special server to implement licensing policies--restricting the maximum number of simultaneous users of a font, for example. Finally, note that in the terminology of X font service, the X server is a font client, and that it is perfectly legal to have other font clients such as printer drivers. Figure B-3 shows a font server providing service to a workstation, an X terminal, and a printer driver.

Figure B-3. A typical font server configuration


R5 font service and scalable font support consists of the following components:

  • The X Font Service Protocol, a standardized, extensible protocol for communication between a font server and font clients, such as an X display server. This protocol also standardizes the format used for the communication of font data between font server and font client.

  • Additions to the X server to allow it to participate in the font service protocol.

  • A convention for the naming and inclusion of font servers in the X server font path.

  • A bitmap and outline font-scaling algorithm in the X server.

  • A set of scalable outline fonts (in Charter and Courier typefaces) from Bitstream, Inc.

  • A font server capable of scaling and exporting the new outline fonts as well as the standard X bitmap fonts.

  • A font server that runs on an Apple Macintosh computer to export the Apple bitmap fonts and, if available, scaled Apple TrueType fonts to any X servers on the network.

  • A respecification of the X server's handling of XListFonts(), XLoadFont(), and XLoadQueryFont() to allow pattern matching for scalable fonts. These functions are used by Xt.

  • An addition to the X Logical Font Description Conventions (XLFD) to handle pattern matching for scalable fonts.

There are no new or changed Xlib or Xt functions for the support of font service or scalable fonts. There are new conventions for naming and listing scalable fonts, however, and applications that want to make explicit use of scalable fonts will have to follow these conventions. Note that R5 defines a new abstraction, the XFontSet, which is used in internationalized applications, but that this has nothing whatsoever to do with font service.

Scalable Fonts

Another new feature in R5 is font scaling. In previous releases, each font was available only in a limited number of standard point sizes and resolutions. In the MIT distribution of R5, both the X server and the font server implement a simple bitmap font-scaling algorithm that allows fonts to be obtained at any desired point size and resolution. Bitmap fonts are easily scalable, but the resulting scaled font is generally jagged and difficult to read. Fortunately, R5 also provides a set of outline fonts. Outline fonts scale nicely, but the scaling process requires significant computation, so an X server might freeze for several seconds while scaling a large Asian font. This is one of the problems that font servers are intended to address. The fonts and the scaling code were donated by Bitstream, Inc.

Until Release 5, X relied exclusively on non-scalable bitmap fonts. If there was no installed font in the point size and resolution you wanted, then you were out of luck--it is obviously not feasible to provide every font in every point size and for every possible resolution. Bitmap fonts do not scale well, because their pixel-by-pixel specification can only be made smaller by omitting pixels or made larger by making pixels bigger, resulting in a jagged, low-resolution font. The fonts shipped by MIT for Release 5 include several “outline fonts” which describe characters by their component curves rather than by individual pixels. This description allows for successful scaling to any desired point size and resolution. The font server shipped by MIT in Release 5 has the capability to read and scale these outline fonts, and therefore the number of fonts available to the user is greatly increased. (Note, however, that a good bitmap font that is “hand-tuned” to a particular point size and screen resolution will generally be better looking than an outline font scaled to that size and resolution. Font design is an art, and the human touch is still important.)

The following two sections apply equally to all scalable and scaled fonts, whether outline or bitmap, from the X server or the font server.

Finding Scalable Fonts

Supporting scalable fonts raises some important questions about the behavior of the Xlib function XListFonts(). First, since there are (theoretically) an infinite number of point sizes and resolutions that a font could be scaled to, it is no longer possible to list all available fonts in all available sizes. So some special syntax is needed to indicate that a font is scalable and is available in any desired size, even if that size is not listed. But backwards compatibility is also an issue--the new point sizes provided by scalable fonts should not be hidden from existing pre-R5 applications.

These seemingly contradictory goals are resolved by changing the semantics of the call to XListFonts() and by extending the X Logical Font Description Conventions slightly.[109] In R5, scalable fonts are returned by XListFonts() with the string “0” in the PIXEL_SIZE, POINT_SIZE, and AVERAGE_WIDTH fields (the seventh, eighth, and twelfth fields of the 14-field XLFD font name). Non-scalable fonts will never have these three fields zero, and therefore these fields are sufficient to distinguish scalable from non-scalable fonts. Most font servers will list a few specific derived instances of each scalable font at standard sizes and resolutions for the benefit of older X applications that expect to find font names in this form.

The X server and font server are only required to match scalable fonts when the font name pattern they are passed is a well-formed one. A well-formed font name is one that contains all 14 hyphens specified in the XLFD convention. Wildcards are permitted for any field, but may not replace multiple fields--all fields must be present in the name. For example,

	*-helvetica-bold-o-*-*-*-120-*

is not a well-formed name, but

	-*-helvetica-bold-o-*-*-*-120-75-75-*-*-iso8859-1

is well-formed. Shortcut names specified as in the first example have come into common use, but with the increasing variety of display resolutions and fonts with non-standard charsets, it is good practice to specify these extra fields, even if you are not interested in using scaled fonts. If XListFonts() is passed a pattern that is not well-formed, it may not include scalable fonts in the search at all.

To list scalable fonts, call XListFonts() with a well-formed pattern with “0” or “*” in its PIXEL_SIZE, POINT_SIZE, and AVERAGE_WIDTH fields. Example B-3 shows some queries that will return scalable fonts. You can quickly try them out by replacing the call to XListFonts() with the client xlsfonts.

Example B-3. Listing scalable fonts

/* List all Latin-1 fonts.  Returned names of scalable fonts will have
 * "0" for pixel size, point size, and average width
 */
fonts = XListFonts(dpy, "-*-*-*-*-*-*-*-*-*-*-*-*-iso8859-1", 1000, &count);
/* List all scalable courier fonts.  Non-scalable fonts will
 * not be listed.
 */
list = XListFonts(dpy,"-*-courier-*-*-*-*-0-0-*-*-*-0-*-*", 200, &count);


Finding Derived Instances of Scalable Fonts

A scalable font name with a point size (and pixel size and average width) of zero is not very useful by itself. If you call XLoadFont() on this font name without a size (or specify such a font name for a font resource), you will get some implementation-defined default size. Instead of listing scalable Helvetica fonts, for example, you will more often want to list all Helvetica fonts at some particular point size. The list you get may contain non-scaled bitmap fonts as well as derived instances of scalable fonts. In order to include derived instances of scalable fonts in a search, it is necessary to specify some of the size fields explicitly. There are five scalable fields in an XLFD font name: PIXEL_SIZE, POINT_SIZE, RESOLUTION_X, RESOLUTION_Y, and AVERAGE_WIDTH (fields 7, 8, 9, 10, and 12.) In order for XListFonts() to list a particular scaled size of a scalable font, enough of these scalable fields must be specified so that the font name pattern matches exactly one derived instance of the font. If too few of the scalable fields are specified, there will be no unique match, and if too many are specified, there may not be any possible scaling that meets all of those specified criteria.

When searching for fonts at a particular size, you will typically wildcard the pixel size and average width by setting those fields to “*” and explicitly specify the point size you want along with the x- and y-resolutions of your screen. (You can calculate screen resolutions with macros like DisplayWidth and DisplayWidthMM, as shown in a later example.) These three fields specify all that is needed to correctly scale the font. You need not (and should not) specify the pixel size, because the point size and y-resolution of the screen determine the desired pixel size. You need not specify the average width because the point size and x-resolution of the screen, together with the height to width ratio implicit to the font, determine the desired width. It is also possible to name a single derived instance of a scalable font by specifying a pixel size plus x- and y-resolutions. There are also other combinations of fields that will work, but none are particularly useful in practice. Example B-4 shows font name patterns that will match derived instances of scalable fonts.

Example B-4. Finding derived instances of scalable fonts

/* Load a 12-point bold helvetica font defined at a 100x100 dpi
 * resolution.  The actual font loaded might be a derived instance of a
 * scalable font, or it might be a bitmap font--there is no way to
 * distinguish them.
 */
font = XLoadFont(dpy, "-*-helvetica-bold-r-*-*-*-120-100-100-*-*-iso8859-1");
/* Load a 20 pixel high helvetica font defined at 100x100 dpi */
font2 = XLoadFont(dpy, "-*-helvetica-medium-r-*-*-20-*-100-100-*-*-iso8859-1");
/* List all 13-point Latin-1 helvetica fonts defined at a 106x97 dpi
 * resolution.  This pattern will match derived instances of scalable
 * fonts, and will probably only match derived instances of scalable
 * fonts, because there are not likely to be bitmap fonts defined at this
 * particular size and resolution.
 */
list = XListFonts(dpy,"-*-helvetica-*-*-*-*-*-130-106-97-*-*-iso8859-1",
                  50, &count);

There are a number of reasons that a font name pattern could fail to match derived instances of scalable fonts. It is difficult to devise an algorithm that will correctly match scalable fonts against any font name pattern. For this reason, the X server or font server is not required to include scalable fonts in its search if the pattern it is given is not well-formed. A well-formed pattern must contain 14 hyphens. Note in particular that the first character in a well-formed name must be a hyphen.

An underspecified font name will not match any derived instances of scalable fonts. This is because your font name could match any number of derived instances, and it is not possible to list them all. When only the point size and pixel size are specified, for example, they are enough together to determine the desired y-resolution for the font, but any x-resolution (and therefore any average width) is still possible. To uniquely match a derived instance, you'd have to specify the x-resolution of your screen or a desired average width for the font. The MIT implementation, however, makes reasonable guesses for unspecified resolution values, so underspecified font names do not occur. If only point size is specified, then default resolutions (75 or 100 dpi) are used. If both point and pixel size are specified as above, then the y-resolution they specify is used for both x- and y-resolution fields.

Similarly, an overspecified font name, one with point size, pixel size, and x- and y-resolutions, for example, may not match any derived instances of scalable fonts: if the specified y-resolution is different from the y-resolution implicitly defined by the combination of point size and pixel size, then there is no way that the font can be scaled to satisfy your request. Example B-5 shows font name patterns that will fail to match any derived instances of scalable fonts.

Example B-5. Font name patterns that don't match scaled fonts.

/* List 15-point bold oblique helvetica fonts.  Derived instances of
 * scalable fonts will probably not be included in the list because the
 * pattern does not have all 14 fields.
 */
helvbold15 = XListFonts(dpy,"*-helvetica-bold-o-*-*-*-150-*", 50, &count);
/* List all 17-point, 17-pixel bold oblique helvetica fonts defined at
 * 100dpi x- and y-resolutions.  This pattern will not match any derived
 * instances of scalable fonts (nor any font) because a 17 point font
 * at 100dpi is not 17 pixels high.
 */
helvbold17 = XListFonts(dpy,"-*-helvetica-bold-o-*-*-17-170-100-100-*-*-
                        iso8859-1",50, &count);


Using Scalable Fonts

Many applications use only a small number of fonts, that are opened at startup and never changed. These applications may leave the choice of fonts to the user. If the user overrides the default with a font that doesn't exist, the application may simply print an error message and exit. Applications such as this need no modification to work with scalable fonts. Users who want to take advantage of scalable fonts, must provide a well-formed and correctly specified font name. Other applications, such as word processors or presentation graphics packages, may allow the user to select fonts from a menu or list at runtime. This kind of application will have to be modified to recognize and make use of scalable fonts. Example B-6 and Example B-7 demonstrate one approach.

Example B-6 shows a procedure that determines whether or not a given font name represents a scalable font. This procedure is intended to be called once for each font returned by XListFonts().

Example B-6. Determining if a font is scalable

/*
 * This routine returns True if the passed name is a well-formed
 * XLFD style font name with a pixel size, point size, and average
 * width (fields 7,8, and 12) of "0".
 */
Bool IsScalableFont(name)
char *name;
{
    int i, field;
    if ((name == NULL) || (name[0] != '-')) return False;
    for(i = field = 0; name[i] != '\0'; i++) {
        if (name[i] == '-') {
            field++;
            if ((field == 7) || (field == 8) || (field == 12))
                if ((name[i+1] != '0') || (name[i+2] != '-'))
                    return False;
        }
    }
    if (field != 14) return False;
    else return True;
}

Example B-7 shows a procedure that takes a scalable font name and a desired point size and loads the derived instance of that font at the requested size and at the precise resolution of the screen. It is intended to be called with a scalable font name as returned by XListFonts().

Example B-7. Loading a derived instance of a scalable font

/*
 * This routine is passed a scalable font name and a point size.  It returns
 * an XFontStruct for the given font scaled to the specified size and the
 * exact resolution of the screen.  The font name is assumed to be a
 * well-formed XLFD name, and to have pixel size, point size, and average
 * width fields of "0" and arbitrary x-resolution and y-resolution fields.
 * Size is specified in tenths of points.  Returns NULL if the name is
 * malformed or no such font exists.
 */
XFontStruct *LoadQueryScalableFont(dpy, screen, name, size)
Display *dpy;
int screen;
char *name;
int size;
{
    int i,j, field;
    char newname[500];    /* big enough for a long font name */
    int res_x, res_y;     /* resolution values for this screen */
    /* catch obvious errors */
    if ((name == NULL) || (name[0] != '-')) return NULL;
    /* calculate our screen resolution in dots per inch. 25.4mm = 1 inch */
    res_x = DisplayWidth(dpy, screen)/(DisplayWidthMM(dpy, screen)/25.4);
    res_y = DisplayHeight(dpy, screen)/(DisplayHeightMM(dpy, screen)/25.4);
    /* copy the font name, changing the scalable fields as we do so */
    for(i = j = field = 0; name[i] != '\0' && field <= 14; i++) {
        newname[j++] = name[i];
        if (name[i] == '-') {
            field++;
            switch(field) {
            case 7:  /* pixel size */
            case 12: /* average width */
                /* change from "-0-" to "-*-" */
                newname[j] = '*';
                j++;
                if (name[i+1] != '\0') i++;
                break;
            case 8:  /* point size */
                /* change from "-0-" to "-<size>-" */
                sprintf(&newname[j], "%d", size);
                while (newname[j] != '\0') j++;
                if (name[i+1] != '\0') i++;
                break;
            case 9:  /* x-resolution */
            case 10: /* y-resolution */
                /* change from an unspecified resolution to res_x or res_y */
                sprintf(&newname[j], "%d", (field == 9) ? res_x : res_y);
                while(newname[j] != '\0') j++;
                while((name[i+1] != '-') && (name[i+1] != '\0')) i++;
                break;
            }
        }
    }
    newname[j] = '\0';
    /* if there aren't 14 hyphens, it isn't a well formed name */
    if (field != 14) return NULL;
    return XLoadQueryFont(dpy, newname);
}


Window Geometry

All clients that display in a window take a geometry option that specifies the size and location of the client window.[110] The syntax of the geometry option is:

-geometry geometry

The -geometry option can be (and often is) abbreviated to -g, unless there is a conflicting option that begins with g.

The corresponding resource is XtNGeometry, which can be set in a resource file as follows:

*mywidget.geometry:  geometry_string

The argument to the geometry option (geometry), referred to as a “standard geometry string,” has the form:

widthxheight±xoff±yoff

The variables width and height, are values in pixels for many clients. However, application developers are encouraged to use units that are meaningful to the application. For example, xterm uses columns and rows of text as width and height values in the xterm window. xoff (x offset), and yoff (y offset) are always in pixels.

You can specify any or all elements of the geometry string. Incomplete geometry specifications are compared to the resource manager defaults and missing elements are supplied by the values specified there. If no default is specified there, and uwm is running, the window manager will require you to place the window interactively.

The values for the x and y offsets have the following effects:

Table B-2. Geometry Specification: x and y Offsets

Offset Variables

Description

+xoff

A positive x offset specifies the distance that the left edge of the window is offset from the left side of the display.

+yoff

A positive y offset specifies the distance that the top edge of the window is offset from the top of the display.

-xoff

A negative x offset specifies the distance that the right edge of the window is offset from the right side of the display.

-yoff

A negative y offset specifies the distance that the bottom edge of the window is offset from the bottom of the display.

For example, the command line:

% xclock -geometry 125x125-10+10 &

places a clock 125×125 pixels in the upper-right corner of the display, 10 pixels from both the top and the right edge of the screen.

For xterm, the size of the window is measured in characters and lines. (80 characters wide by 24 lines long is the default terminal size.) If you wanted to use the vt100 window in 132- column mode, with 40 lines displayed at a time, you could use the following geometry options:

% xterm -geometry 132x40-10+350 &

This will place an xterm window 132 characters wide by 40 lines long in the lower-right corner, 10 pixels from the right edge of the screen and 350 pixels from the top of the screen.

Some clients may allow you to specify geometry strings for the size and position of the icon or an alternate window, usually through resources (in an .Xdefaults or other resource file). See the appropriate client reference pages in Part Three of Volume Three, X Window System User's Guide, Motif Edition, for a complete list of available resources.

You should be aware that, as with all user preferences, you may not always get exactly what you ask for. Clients are designed to work with a window manager, which may have its own rules for window or icon size and placement. However, priority is always given to specific user requests, so you won't often be surprised.



[105] A corresponding compiled file called rgb.pag contains the definitions used by the server; the rgb.txt file is the human-readable equivalent.

[106] There is a type of high-performance display in which pixel values are used directly to control the illumination of the red, green, and blue phosphors, but far more commonly, the bits per pixel are used indirectly, with the actual color values specified independently, as described here.

[107] A property is a piece of information associated with a window or a font. See Volume One,Xlib Programming Manual, for more information about properties.

[108] For fonts other than those shipped by MIT, other families, weights, slants, point sizes, etc., may apply.

[109] The XLFD Conventions are printed as Appendix M of X Protocol Reference Manual, Volume Zero of the O'Reilly & Associates series of X books.

[110] The Release 2 syntax:

=geometry

is no longer supported.