Fonts
Author: Jeroen van der Zijp

Fonts in FOX

Fonts.

Type faces in FOX are manipulated using FXFont objects. To provide a consistent look and feel for all applications, most FOX widgets normally share one common font object, which is automatically adopted when the widget is constructed. However, a widget's font is readily changed using the setFont() member function. Changing fonts on widgets will automatically cause an adjustment in layout so that the new size of the widget is accomodated.

As with most other resources such as FXIcon and FXCursor etc., building FXFont objects also takes two steps:- construction of the client-side part of the font object, followed by creation of the corresponding server-side part. During construction, all necessary information is supplied to the FXFont object so that the desired font may be located and loaded into memory during the creation.

In most cases, the font objects are automatically created when the widget that uses it is being created. If you have constructed a new FXFont object later on, however, you may have to make a call to the font object's `create()` member function to make sure the font object is fully initialized.

As different computer systems may have different fonts, it is possible that the specific font your application needs may not be available. Since you probably still would like this application to run anyway, alternative fonts must be found.

FOX supports mechanisms to localize fonts which are ``close'' [in some easthetic sense] to the desired font, so that applications will typically not fail simply because of missing fonts. Keep in mind, however, that the information you supplied to the FXFont contructor may not accurately reflect the font that is actually being used in your application.

Also note that information about a font will not be available until after the font has been created using `create()`.

Using Font Objects.

Using fonts is really very easy. For example, to build a Button Control with a different Font for the caption, you would use the following C++ code:

`FXButton *button = new FXButton(parent,"&Caption");` `FXFont* captionfont = new FXFont(app,"times",24);` `button->setFont(captionfont);`

This statements will create a Button with caption ``Caption'' and use a font of 24 points Times. Note that in this case we assume that the captionfont will be created in the process of creating the Button; if you were to change fonts after the application has already started running, you would want to call `captionfont->create()` to make sure the font resources are created.

Also note that font objects may be shared between several controls; thus, you don't have to create a different font object for each control [unless of course you want to use a different font!].

In the above example, we have taken default values for many parameters influencing the choice of font. The above call is actually equivalent to:

`FXFont* captionfont = new FXFont(app,` `"times",` `24,` `FONTWEIGHT_NORMAL,` `FONTSLANT_REGULAR,` `FONTENCODING_DEFAULT,` `0);`

That is to say, construct a font with face name ``times,'' 24 points, normal weight [not bold], no italics, and use whatever character encoding is available for this font; finally, the zero (0) indicates there are no hints.

Besides the above platform-independent font constructor, FXFont also has an alternative constructor which is only applicable to the X11 Window System; this method bypasses the font matching algorithm.

Assuming that our display was 75 dots per inch (dpi), the alternative method of contructing fonts using the X11 font string would have been:

`FXFont* captionfont = new FXFont(app,"-adobe-times-medium-r-normal--24-240-75-75-p-124-iso8859-1");`

Besides being harder to remember, this method would not port over very well to other systems, or systems where this particular font is not available. However, there are a few reasons why sometimes you may need this method:

1. You want to make sure you obtain a specific font, and do not want the matching algorithm to get in the way;
2. You need to obtain certain raster-based system fonts, for example "9x15bold."

Font Matching and Substitution.

In order to be able to write applications which may be ported to a large variety of computer systems and software environments, it is necessary to make sure that the absence of certain fonts is handled gracefully.
The FXFont implementation offers a number of benefits that allow you to get your application running under a wide variety of environments, even on systems where very few fonts have been installed:

1. Font Substitution. Font substitution is used to map type face names which may be hard-coded in your application to another type face name, so an alternative font may be used without having to make changes to programs or recompiling them. FOX uses the standard Registry mechanism to map one type face name to another.
2. Font Matching. Font matching algorithms are used to determine the closest available font to the desired font. Different weighting factors are applied to different font attributes to get the best visual approximation.
3. Font Match Hints. Hints may be passed to the matching algorithms so you are able to emphasize certain types of font attributes more strongly than others.
4. X11 Font String. Platform-dependent fonts may be directly specified also. This method is not recommended unless you need to select a specific font, and are not interested in portability.

Before trying to acquire a list of available fonts for a certain type face, the FXFont implementation first tries a substitution for the type face name. The standard FOX registry is used to make this association. The substitute font is found in the section FONTSUBSTITUTIONS of the registry.
For example, the following fragment decribes the registry settings which would replace ``swiss'' by ``helvetica'' and ``new century schoolbook'' by ``courier'':

[FONTSUBSTITUTIONS] swiss = helvetica new century schoolbook = courier

Thus, you can easily give a FOX application another font even if you might not have the source code around!

After having substituted the type face name, the FXFont implementation tries to find the font from the given type face that best matches the parameters and hints. Parameters or hints which are given a ``don't care'' value are considered matched. For example, if you specify FONTWEIGHT_DONTCARE for the font weight, all font weights would match and the resulting font will be based on other parameters.

Not all parameters have the same priority as far as matching goes; the importance of the parameters is as follows:

1. Character Set Encoding. If you needed East European character sets and you got Greek instead, even all other things being equal, you'd be disappointed.
2. Fixed or Variable Pitch hints. For programming editors, for example, fixed pitch fonts are a must so that indentation is properly maintained; therefore, font pitch is quite important for legibility purposes.
3. Screen Resolution. Bitmapped fonts are much more readable when the resolution matches that of your screen; so resolution is quite important. The FXFont implementation tries to determine the screen's resolution (in terms of dots per inch) and then match fonts designed for this resolution.
4. Scalable Font Hint. Certain operations such as scaling and shearing [obliqueing] are only possible with scalable fonts; thus, if you have specified this hint, all other things being equal, you'd prefer scalable fonts over other ones.
5. Polymorphic Font Hint. Polymorphic fonts allow continuous variations in various attributes of a font, such as set width, weight, slant, and others. If your application needs such fonts for certain effects, this much be made to match.
6. Point Size. When all the above are satisfied, you certainly want the size of the font to be roughly equal to the one specified. For scalable fonts, you can of course virtually always match the requested size exactly. For non-scalable fonts, the FXFont implementation matches the largest font which is less than or equal to the desired size. Even though a larger font may be closer, the larger one may be too large for proper layout on a finite screen; therefore, the implementation yields only smaller fonts. As the resolution has influence over the observed point size, the implementation corrects for this [see ``Screen Resolution'' below].
7. Weight. The weight or ``boldness'' of the font.
8. Slant. Oblique and italic may both be matched for a slanted font.
9. Set Width. Wide or narrow (condensed) printing.

After having tried all the members of the specified type face, if no match is found at all, the FXFont implementation tries a number of other common fonts, based on additional hints:

- If no hints are given, or if the hint FONTHINT_SWISS is given, the face ``helvetica'' or its substitution will be tried;
- Next, if no hint is given or if the hint given is FONTHINT_ROMAN, the face ``times'' or its substitution will be tried;
- Next, if no hint given or if the given hint was equal to FONTHINT_MODERN, the face ``courier'' or its substitution will be tried;
- After that, if no hint is given or if the hint was FONTHINT_DECORATIVE, the face ``gothic'' or its substitution will be tried;
- Finally, if all else fails, the implementation will try a number of ``fallback fonts'' which have been determined to be commonly available.

If all the above failed, yet there is at least one font on your system, then you should report this problem on the FOX mailing list...

Screen Resolution.

Since current-day analog monitors can stretch and shrink the visible field of the display, the actual resolution is typically not exactly 75dpi or 100dpi. To get a font's point size as close to the desired pointsize as possible, FOX adjusts for the actual screen dpi relative to the font's dpi.
For example, suppose we have a font such as:

> `-adobe-helvetica-bold-r-normal--12-120-75-75-p-70-iso8859-1`

This font is a 12-point font designed for a 75 dpi device. If your monitor however is set to display 90 dpi, the font would be too small. The implementation can correct for this by multiplying the font's point size by (75/90) which means visually this font would actually be more like 10-points on your monitor. Thus, to get a font designed for 100 dpi to display as 12 points on your monitor, we should search for a font which is slightly larger than 12-point; to be exact, we should be looking for a font (90/75)*12 = 14.4-point font.

On many systems such as work stations, the machine is shipped with accurate information about the particular monitor supplied with the system; on such systems, the font implementation of FOX will correctly determine the right resolution to use. On PC's however, hardware is mixed and matched from different sources, and the reported screen sizes may be incorrect, causing fonts to bigger or smaller than requested.

When the system reports the wrong resolution, you can easily correct that by setting the resolution yourself using the registry database. On my system, for example, the XFree86 X Server reports 75 dpi, while I really have 100dpi. So I change my registry database as follows:

[SETTINGS] screenxres = 100 screenyres = 100

These entries need to go into the ``Desktop'' file so that all FOX programs will be aware of this, regardless of vendor or application name. For more about the registry, see the section on FXRegistry.

Copyright © 1997,2001 Jeroen van der Zijp, All Rights Reserved.