Fonts

An X font is (yet another) a server-side resource. In essence, a font is a collection of bitmaps representing characters. The bitmaps in a single font will have a similar size and style. GDK allows you to manipulate fonts with a client-side handle called GdkFont.

To obtain a GdkFont, call gdk_font_load() (or use the font from a preexisting GtkStyle; more on this in the section called GtkStyle and Themes). Fonts are loaded by name; font names are a fairly involved topic. Names follow a convention called the "X Logical Font Description," or XLFD. The best way to get a feel for XLFD is to play with the xfontsel program that comes with X. You can also get a list of font names on your X server with the xlsfonts program. The standard X distribution includes a 30-page XLFD manual, but the basics aren't too complicated.

A font name is a string made up of hyphen-separated fields. Each field describes some aspect of the font. For example:


-misc-fixed-medium-r-normal--0-0-75-75-c-0-iso8859-1

or


 -adobe-new century schoolbook-bold-i-normal--11-80-100-100-p-66-iso8859-1

The fourteen fields are:

It is not necessary to specify all 14 fields when requesting a font. "Wild cards" are allowed: * matches any number of characters, and ? matches a single character. For example, a 160 point Bold Roman Helvetica font can be requested like this:


-*-helvetica-bold-r-*-*-*-160-*-*-*-*-*-*

When you pass a font name to gdk_font_load(), you should consider it a default choice only. Users in other countries will certainly want to use a font appropriate to their language; US and European users might want to customize fonts too. Also, there are no fonts guaranteed to exist on all servers. Thus you should provide a way to customize any fonts you use. The easiest way is to use fonts from a widget's GtkStyle (again, see the section called GtkStyle and Themes).

gdk_font_load() returns NULL if it fails to find a font matching the supplied name. When you are done with a font, you should release it by calling gdk_font_unref(). Figure 10 summarizes these functions.

When loading fonts, you will need to specify at least the font name, the weight, the slant, and a size---otherwise the * wildcards would probably load a random bold italic font, which is unlikely to be what you want. The Xlib Programming Manual suggests that you always specify the font size in points, so that users with different monitors will get the right effect; however, X servers do not reliably know the display resolution, so this is more theory than reality. Perhaps it's better to specify pixels, because you do know the pixel size of other elements of your display. Neither is perfect; be sure you make your application's fonts configurable.

#include <gdk/gdk.h>

GdkFont* gdk_font_load(const gchar* font_name);

void gdk_font_unref(GdkFont* font);

Figure 10. GdkFont

Font Metrics

To use a font, you typically need detailed information about its metrics. Font metrics are used to position characters with respect to one another, and to determine the size of strings rendered in the font. The most fundamental metrics are the ascent and descent of the font. Text is placed on a baseline; the baseline is like a rule on a sheet of notebook paper. The bottom of each character touches the baseline. Some characters (such as lowercase "p" and "y") extend below the baseline. A font's descent is the maximum distance below the baseline reached by its characters. Its ascent is the maximum distance above the baseline. The height of a font is the sum of the ascent and the descent. When rendering multiple lines of text, you should leave at least the font's height between each baseline.

Ascent and descent are available as members of the GdkFont struct:


typedef struct _GdkFont GdkFont;

struct _GdkFont
{
  GdkFontType type;
  gint ascent;
  gint descent;
};

The type field distinguishes fonts from fontsets; fontsets are used to display non-European languages.

Individual characters in a font have their own ascent and descent; a character's ascent and descent will always be less than or equal to the font's ascent and descent. GDK can calculate the sum of the maximum ascent and descent for a particular string, rather than an entire font; this height will be less than or equal to the font's height. The relevant functions are gdk_string_height(), gdk_text_height(), and gdk_char_height(). gdk_text_height() is different from gdk_string_height() because it accepts the length of the string as an argument; gdk_string_height() calls strlen() for you. Thus gdk_text_height() is preferred if you already know a string's length.

In addition to its vertical metrics, each character in a font has three metrics describing its horizontal dimensions. The width of a character is the distance from the left origin of the character to the start of the next character. Note: the width is not the distance to the furthest-right pixel in a character; in some fonts, especially italic fonts, characters may lean over past the start of the next character. The left-side-bearing or lbearing is the distance from the left origin to the leftmost pixel in the character; the right-side-bearing or rbearing is the distance from the origin to the rightmost pixel in the character. Thus the rbearing can be larger than the width, in the case of italic fonts that lean over past the start of the next character.

GDK functions that return a character or string width return the width of the character, or the sum of the character widths in the string. If the rbearing of the rightmost character is greater than its width, a string may require more space than gdk_string_width(), gdk_text_width(), or gdk_char_width() will return. Like the height-measurement functions, the _string_ variant computes the length of the string for you, and the _text_ variant accepts a precomputed length as an argument.

The functions ending in _measure are more often what you want. For a string with N characters, these return the sum of the widths of the first N-1 characters, plus the rbearing of the final character. That is, they take into account the fact that rbearing may be greater than width. If you're trying to decide how much space to leave for rendering a string, you probably want the gdk_string_measure(), gdk_text_measure(), or gdk_char_measure() functions. Sometimes you don't want to consider the rbearing, however; for example, if you're centering a string, it may look nicer to use the width (because a small italic flourish extending past the width won't "fill" the space and the string will look slightly left of center).

gdk_text_extents() and gdk_string_extents() return all the metrics for a string, including both bearings, the width, ascent, and descent. The returned left-side-bearing is the leftmost pixel in the string; the right-side-bearing is the rightmost pixel as returned by gdk_text_measure(). The width is the sum of character widths, as returned by gdk_text_width().

Figure 11 depicts the various font metrics. Figure 12 summarizes the API for querying font metrics. All font metrics are computed on the client side, so these functions are not expensive compared to most of the drawing API.

Figure 11. Font Metrics

#include <gdk/gdk.h>

gint gdk_string_width(GdkFont* font, const gchar* string);

gint gdk_text_width(GdkFont* font, const gchar* string, gint string_length);

gint gdk_char_width(GdkFont* font, gchar character);

gint gdk_string_measure(GdkFont* font, const gchar* string);

gint gdk_text_measure(GdkFont* font, const gchar* string, gint string_length);

gint gdk_char_measure(GdkFont* font, gchar character);

gint gdk_string_height(GdkFont* font, const gchar* string);

gint gdk_text_height(GdkFont* font, const gchar* string, gint string_length);

gint gdk_char_height(GdkFont* font, gchar character);

void gdk_string_extents(GdkFont* font, const gchar* string, gint* lbearing, gint* rbearing, gint* width, gint* ascent, gint* descent);

void gdk_text_extents(GdkFont* font, const gchar* string, gint string_length, gint* lbearing, gint* rbearing, gint* width, gint* ascent, gint* descent);

Figure 12. Font Metrics