Tutorial #7

Conditional Features

OpenType and Apple fonts both provide contextual features. These are features which only take place in a given context and are essential for typesetting Indic and Arabic scripts. In OpenType a context is specified by a set of patterns that are tested against the glyph stream of a document. If a pattern matches then any substitutions it defines will be applied. In an Apple font, the context is specified by a state machine -- a mini program which parses and transforms the glyph stream.

Conditional features may involve substitutions, ligatures or kerning (and some more obscure behaviors). I am going to provide an example here of a contextual substitution.

Instead of an Indic or Arabic example, let us take something I'm more familiar with, the problem of typesetting a latin script font where the letters ``b,'' ``o,'' ``v'' and ``w'' join their following letter near the x-height, while all other letters join near the baseline. Thus we need two variants for each glyph, one that joins (on the left) at the baseline (the default variant) and one which joins at the x-height. Let us call this second set of letters the ``high'' letters and name them ``a.high,'' ``b.high'' and so forth.

OpenType Example

Warning
The following example does not work! The font tables produced by it are all correct, but the designers of OpenType decided that the latin script does not need complex conditional features and implementations of OpenType do not support them for latin. This is not even mentioned in the standard, but is hidden away in supplemental information on microsoft's site.

Why do I provide an example which doesn't work? It's the best I can do. If I knew enough about Indic or Arabic typesetting I would provide an example for those scripts. But I don't. The procedures are the same. If you follow them for some other scripts they will work.

On some systems and in some applications this example can be made to work by replacing the 'calt' feature tag (conditional alternatives) with a Required tag.

We divide the set of possible glyphs into three classes: the letters ``bovw'', all other letters, and all other glyphs. We need to create two patterns, the first will match a glyph in the ``bovw'' class followed by a glyph in the ``bovw'' class, while the second will match a glyph in the ``bovw'' class followed by any other letter. If either of these matches the second glyph should be transformed into its high variant.

The first thing we must do is create a simple substitution mapping each low letter to its high variant. Let us call this substitution by the four character OpenType tag ``high.'' To define the substitution we use Element -> Glyph Info as before except that here we use the special ``script / language'' called ``--- Nested ---'' (an option in the pulldown menu).

The tricky part is defining the context. This is done with the Contextual tab in the Element -> Font Info dialog, revealing five different types of contextual behavior, we are interested in contextual chaining substitutions.

You can add a new entry by pressing the [New] button. This brings up a series of dialogs, the first requests a four character OpenType tag and a script / language (much as we saw earlier).

In this example we are using 'calt'. That seems an apropriate tag, until you discover that it is not implemented for the Latin script. Indeed there seems to be no appropriate feature that is implemented for Latin. The example will produce a font, which while syntactically correct, will never do anything. It is frustrating that OpenType provides the capabilities needed to do wonderous things, and then to find that MicroSoft doesn't let that happen in Latin.

The next dialog allows you to specify the overall format of the substitution. We want a class based system -- we've already mentioned what the glyph classes will be above.

The next dialog finally shows something interesting. At the top are a series of patterns to match and substitutions that will be applied if the string matches. Underneath that are the glyph classes that this substitution uses. A contextual chaining dialog divides the glyph stream into three categories: those glyphs before the current glyph (these are called backtracking glyphs), the current glyph itself (you may specify more than one), and this (these) glyphs may have simple substitutions applied to them, and finally glyphs after the current glyph (these are called lookahead glyphs).

Each category of glyphs may divide glyphs into a different set of classes, but in this example we use the same classes for all categories (this makes it easier to convert the substitution to Apple's format). The first line (in the ``List of lists'' field) should be read thus: If a backtracking glyph (the glyph before the current one) in class 1 is followed by the current glyph in class 2, then location 0 --the only location -- in the match string (that is the current glyph) should have simple substitution `high' applied to it.

If you look at the glyph class definitions you will see that class 1 includes those glyphs which must be followed by a high variant, so this seems reasonable.

The second line is similar except that it matches glyphs in class 1. Looking at the class definitions we see that classes 1 & 2 include all the letters, so these two lines mean that if any letter follows one of ``bovw'' then that letter should be converted to its `high' variant.

To edit a glyph class simply double click on it. To create a new one press the [New] button (under the class list). This produces another dialog showing all the names of all the glyphs in the current class. Pressing the [Select] button will set the selection in the font window to match the glyphs in the class, while the [Set] button will do the reverse and set the class to the selection in the font window. These provide a short cut to typing in a lot of glyph names.

Pressing the [Next] button defines the class and returns to the overview dialog.

To edit a pattern double click on it, or to create a new one press the [New] button (under the List of lists). Again the pattern string is divided into three categories, those glyphs before the current one, the current one itself, and any glyphs after the current one. You choose which category of the pattern you are editing with the tabs at the top of the dialog.

Underneath these is the subset of the pattern that falls within the current category, the classes defined for this category, and finally the substitutions for the current glyph(s). Clicking on one of the classes will add the class number to the pattern.

To edit a substitution double click on it, or to create a new one press the [New] button (under ``An ordered list...''). The sequence number specifies which glyph among the current glyphs should be modified, and the tag specifies a four character substitution name

A warning about contextual behavior: Not all software supports them. And even more confusing software may support them for some scripts and not for others.

Apple advanced typography

Apple specifies a context with a finite state machine, which is essentially a tiny program that looks at the glyph stream and decides what substitutions to apply. Each state machine has a set of glyph class definitions (just as in the OpenType example), and a set of states. The process begins in state 0 at the start of the glyph stream. The computer determines what class the current glyph is in and then looks at the current state to see how it will behave when given input from that class. The behavior includes the ability to change to a different state, advancing the input to the next glyph, applying a substitution to either the current glyph or a previous one (the ``marked'' glyph).

Using the same example of a latin script font... We again need a simple substitution to convert each letter into its high alternate. The process is the same as it was for OpenType, and indeed we can use the same substitution. Again we divide the glyphs into three classes (Apple gives us some extra classes whether we want them or no, but conceptually we use the same three classes as in the OpenType example). We want a state machine with two states (again Apple gives us an extra state for free, but we shall ignore that), one is the start state (the base state -- where nothing changes), and the other is the state where we've just read a glyph from the ``bovw'' class.

Again we use the Element -> Font Info dialog and the Mac SM tag to look at the contextual substitutions available. Again there are several types of contextual behavior, and we are interested in contextual substitutions. Double clicking on a state machine, or pressing the [New] button provides an overview of the given state machine.

At the top of the dialog we see a field specifying the feature / setting of the machine, this is Apple's equivalent of the OpenType 4 character feature tag. Under this is a set of class definitions, and at the bottom is a representation of the state machine itself.

Double clicking on a class brings up a dialog similar to that used in OpenType

Clicking on a transition in the state machine (there is a transition for each state / class combination) produces a transition dialog. This controls how the state machine behaves when it is in a given state and receives a glyph in a given class. In this example it is in state 2 (which means it has already read a ``bovw'' glyph), and it has received a glyph in class 4 (which is another ``bovw'' glyph). In this case the next state will be state 2 again (we will have just read a new ``bovw'' glyph), read another glyph and apply the ``high'' substitution to the current glyph.

At the bottom of the dialog are a series of buttons that allow you to navigate through the transitions of the state machine.

Pressing [OK] many times will extract you from this chain of dialogs and add a new state machine to your font.

-- Prev -- TOC -- Next --