Inside the GTK font chooser

I’ve written about the handling of fonts in GTK before. This post is going to focus on how to use the more advanced font (and font chooser) features in your application.

Finding fonts

The most prominent end-user feature of the file chooser is of course that you can search for fonts by name, using the search entry:

A more hidden feature is that you can filter the list by various criteria. One criterium is to show only monospace fonts, another is to only show fonts covering a certain language:

A little detail to notice here is that GTK automatically changes the preview text to match the language you are filtering by.

Less is more

The font chooser returns a PangoFontDescription which contains the full details of the selected font: family, style, size, etc. If your application only needs the family, then it is confusing to let the user select a style and size only to have them be ignored.

If this is the case for your application, you can instruct GTK about the font details you need, using gtk_font_chooser_set_level(), and the GtkFontChooserLevel flags:

typedef enum {
  GTK_FONT_CHOOSER_LEVEL_FAMILY     = 0,
  GTK_FONT_CHOOSER_LEVEL_STYLE      = 1 << 0, 
  GTK_FONT_CHOOSER_LEVEL_SIZE       = 1 << 1,
  GTK_FONT_CHOOSER_LEVEL_VARIATIONS = 1 << 2,
  GTK_FONT_CHOOSER_LEVEL_FEATURES   = 1 << 3
} GtkFontChooserLevel;

For example, after

gtk_font_chooser_set_level (chooser, 
                            GTK_FONT_CHOOSER_LEVEL_FAMILY);

the font chooser looks like this:

Much simpler!

Into the abyss

Modern fonts are complicated beasts, and there’s much that’s lurking under the surface. The GTK font chooser can make many of these font features available if you tell it to.

First, there are font variations. These let you continuously vary the characteristics of a font (as long as those characteristics are exposed as variation axes).

 

Typical variation axes are weight, width and slant of a font, but there can others (such as Optical Size in this example).

The selected variations are part of the PangoFontDescription that the font chooser returns, applications don’t have to do any extra work to apply them. Just use the font description as usual.

To enable the font variation support in the GTK file chooser, use GTK_FONT_CHOOSER_LEVEL_VARIATIONS flag:

level = level | GTK_FONT_CHOOSER_LEVEL_VARIATIONS;
gtk_font_chooser_set_level (chooser, level);

More features

Fonts contain not just the glyph contours, but lots of other data that can be applied in various ways when rendering those glyphs. This includes traditional data like kerning and ligatures, but also things like optional glyph shape or positioning variants or even color palettes. Many of these can be enabled by the user with the help of OpenType features.

Here is an example of an OpenType feature for glyph shape variations:


The feature that is toggled on here when going from left to right is called ss12. Thankfully, the font provides the more meaningful name “Single-story g” as well.

This example shows the effect of the frac feature on the display of fractions.

In the GTK font chooser, OpenType features are presented on the same page as variations. As you see, there can be quite a few of them:

Note that Pango treats OpenType features as separate from the font itself. They are not part of the font description, but have to be applied to text either with PangoAttributes or via Pango markup.

To apply the selected font features from a GTK font chooser, call gtk_font_chooser_get_font_features () and pass the returned string to pango_attr_font_features_new().

To enable the OpenType features support in the GTK file chooser, use GTK_FONT_CHOOSER_LEVEL_FEATURES flag:

level = level | GTK_FONT_CHOOSER_LEVEL_FEATURES;
gtk_font_chooser_set_level (chooser, level);

Summary

In summary, you can use the level property of GtkFontChooser to influence the granularity of font selection you offer to users of your application. If you include font features in it, don’t forget to apply the selected features, using PangoAttributes or markup.

All of this is enabled by harfbuzz providing us with a cross-platform API to fonts and all their features. It would not be possible otherwise. It is worth pointing out that this is done by accessing harfbuzz objects directly, rather than wrapping all the harfbuzz APIs in Pango.