The Type1 format where 256 characters are assigned to keys on our keyboard, is becoming a thing of the past. We now design and produce OpenType fonts which can consist of thousands of characters — additional ligatures, various figure sets, small caps, stylistic alternates, … — referred to as glyphs. With these many sets of glyphs integrated in a single font, we are faced with the challenge of including definitions instructing the applications we're using when to show which glyph. Simply adding a glyph with a ligature to your font doesn’t mean the program you’re using knows when or how to apply it. Whether you want your typeface to change the sequence of f|f|i into the appropriate ligature or want to use old-style figures instead of tabular, you’ll need to add features to your font — glyph substitution definitions — to make it happen.
In this article we’ll give you a look behind the scenes of OpenType substitution features — a general rather than comprehensive overview as the subject is simply too vast. We’ll start casually and work our way to more complex features and ideas. All examples that we will discuss should be considered starting points, just to pique your interest. Read on and find out that it’s really not difficult!
What does a feature look like?
Let’s take a look at a simple example that, like all OpenType features we’re talking about here, deals with the replacement of glyphs, called glyph substitution (short GSUB). It always comes down to the same thing: substitute a single glyph or a sequence of glyphs by another glyph.
Assuming you have your glyphs in question already drawn (f
, i
and the ligature glyphs called f_i
and f_f_i
), all you need to do is add some code to control the substitution, like this:
feature liga { # I'm just a comment sub f f i by f_f_i; sub f i by f_i; } liga;
feature
followed by liga
, and repeated in the last line is the predefined name of the feature, the identifier that a program like QuarkXPress or InDesign needs in order to know which feature to look at when you choose «Ligatures», (see below for a comprehensive list of feature names and the features they trigger.) The sub
statements — you can also write substitute
— within the curly brackets tell the program that if the sequence of glyphs named f
|f
|i
or f
|i
is found (in the feature statement the glyphs of a sequences are separated by a space), replace it by
the glyphs named f_f_i
resp. f_i
. Lastly, after every statement as well as at the end of the feature, place a semicolon.
To see what happens look at the following comparison of input and output, (to tell the different glyphs in a sequences apart I’ve used a divider: |
)
Input: R|e|f|i|n|i|n|g|space|a|f|f|i|n|i|t|y|question
Output: R|e|f_i|n|i|n|g|space|a|f_f_i|n|i|t|y|question
What Do I Need to Create a Font with Features?
You need a font program that supports feature definitions such as FontLab Studio, DTL’s FontMaster, or FontForge, to name the most common. These allow you to freely define glyphs/glyph names as well as offer integrated feature editors. In FontLab Studio your work space would look something like this:
What are features used for?
In many of the newer fonts, you’ll find various figure sets (old style, lining, super and subscript figures, …) which need to be controlled or small caps as well as alternative character shapes and fractions. A favorite of many are or course, ligatures.
Choose from the following list of features to see some typical applications. Compare the results to the input and take a look at the exemplary feature code which is explained in detail further down:
Input: All featues switched off
Output: Ligatures (liga) switched on
feature liga { # Ligatures sub f i by f_i; } liga;
Output: Stylistic Alternates (salt) switched on
feature salt { # Stylistic Alternates sub [a g] by [a.salt g.salt]; } salt;
Output: Stylistic Set 04 (ss04) switched on
feature ss04 { # Stylistic Set 04 sub parenleft three by three.cameostart; sub period by period.negative; sub two parenright by two.cameoend; } ss04;
Output: Small Caps (smcp) switched on
feature smcp { # Small Caps sub @lowercase by @smallcaps; } smcp;
Output: Superscript (sups) switched on
feature sups { # Superscript sub @figures_standard by @figures_sups; sub @punctuation_regular by @punctuation_sups; } sups;
Output: Fractions (frac) switched on
feature frac { # Fractions sub slash by fraction; sub @figures_standard by @figures_numerator; sub fraction @figures_numerator' by @figures_denominator; sub @figures_denominator @figures_numerator' by @figures_denominator; } frac;
Output: Lining Figures (lnum) switched on
feature lnum { # Lining Figures sub @figures_standard by @figures_lining; } lnum;
What rules do I need to follow?
Naming your glyphs
A must for every well functioning typeface is properly named glyphs. Your letter Ä would use the descriptive glyph name Adieresis
, and its Unicode value 00C4
. If you supply the correct glyph name (for example iacute
) your font program usually knows what the Unicode for a glyph should be (00ED
). If you or your font program are at a loss, try Adobe’s glyph list for new fonts (AGLFN) which lists more than 600 glyph names and their matching Unicode values.
Glyphs that should only have a glyph name (and no Unicode value!) are variants, which are the ones we usually access with the help of features — like a.swsh
or g.salt
. Since they are accessed via their base glyph (a
with its Unicode 0061
is the base glyph of a.swsh
) only a glyph name is needed. The names of the variant glyphs are often assembled like this: source glyph’s name plus the feature’s abbreviation, separated by a dot: a.swsh
as the swash variant of a
.
Naming your features
All features have predefined four letter names. Ligatures for example is called liga
, the Stylistic Alternates feature is named salt
, and Stylistic Set 04 ss04
. Make sure that the application activates the desired features by using the appropriate name. Examples of the the most common feature names you’ll find below in our section Which features is activated by which menu item?
Feature statement schemes
For the definition of features, you work with a flexible but straight-forward syntax. Design programs currently support replacements according to the following schemes:
- Substitute a glyph by another glyph
- Substitute a sequence of glyphs by a certain glyph
- Substitute glyph from a list by certain glyph / glyph in a list
- Substitute glyph from a referenced list called class, by certain glyph / glyph from a referenced class
1st scheme
The following Stylistic Alternates feature named salt
, handles the substitution of the standard versions of a
and g
with the alternative versions of those glyphs. These variants could be named a.salt
and g.salt
, for example.
feature salt { # my Stylistic Alternates sub a by a.salt; sub g by g.salt; } salt;
2nd scheme
Our ligatures feature, same as above.
feature liga { # my Ligatures sub f f i by f_f_i; sub f i by f_i; } liga;
3rd scheme
Like the example of the 1st scheme, the glyph a
is replaced by a.salt
, and g
by g.salt
, but the feature syntax allows us to be more efficient as the following example shows. Here each glyph of the first list is replaced by the corresponding glyph of the second.
Input: D|o|n|quoteright|t|space|e|a|t|space|m|y|B|a|g|e|l|exclam|exclam|exclam
Output: D|o|n|quoteright|t|space|e|a.salt|t|space|m|y|B|a.salt|g.salt|e|l|exclam|exclam|exclam
feature salt { # my Stylistic Alternates, compact using listst sub [a g] by [a.salt g.salt]; } salt;
4th scheme
Up until now we’ve only dealt with four glyphs, but let’s see how you can keep the overview when you need to control a substantially larger number of glyphs, like small caps for example. Here we don’t list our glyphs within the feature itself, but instead refer to lists that contains all the glyphs we need. These lists are called classes and are either created in the Classes panel or directly in the lower right-hand field of the OpenType panel.
The lists in the Classes panel handle each list as a separate item (see the Classes panel in the above image):
lowercase: a b c d e f g h i j k l m n o p q r s t u v x y z
small_caps: a.sc b.sc c.sc d.sc e.sc f.sc g.sc h.sc i.sc j.sc k.sc l.sc m.sc n.sc o.sc p.sc q.sc r.sc s.sc t.sc u.sc v.sc x.sc y.sc z.sc
This is what the lists looks like if you choose to write them in the OpenType features panel (see the OpenType panel in the above image, lower right-hand field):
@lowercase = [a b c d e f g h i j k l m n o p q r s t u v x y z];
@small_caps = [a.sc b.sc c.sc d.sc e.sc f.sc g.sc h.sc i.sc j.sc k.sc l.sc m.sc n.sc o.sc p.sc q.sc r.sc s.sc t.sc u.sc v.sc x.sc y.sc z.sc];
So instead of writing our glyphs directly into the feature we refer to classes, marked by @
. The position of the resp. glyphs in these classes must of course correspond, just like they do in our Stylistic Alternates feature.
feature smcp { # my Small Caps feature sub @lowercase by @small_caps; } smcp;
Input: I|space|L|o|v|e|space|T|y|p|o|g|r|a|p|h|y|exclam
Output: I|space|L|o.sc|v.sc|e.sc|space|T|y.sc|p.sc|o.sc|g.sc|r.sc|a.sc|p.sc|h.sc|y.sc|exclam
Substitute — depending on the context!
In the previous examples, the substitution of a glyph took place when the triggering glyph was used, no matter what. Now let’s look at a feature where the substitution only takes place when additional criteria are met: contextual features.
Contextual features have opened up a whole new spectrum of possibilities, enabling you to define very individual rules on how glyph variants are triggered. They have allowed quite complex typographic ideas to be tunred into working fonts. You’ll find them extensively applied in script typefaces such as Liza (by Underware) or Studio Lettering (by House Industries) where letter variants are used depending on which glyph precedes/follows, keeping the flow within the words going. Another use for the contextual features are fonts that loop through letter variants like FF Trixie HD (by LettError) or FF Duper (by Martin Wenzel).
I know that’s all very abstract, so let’s proceed and define a more commonly used contextual feature for fractions. The contextual bit we need to consider is the divisor because all figures preceding it need to be numerators (small figures, superscript position) while the ones following it must be denominators (small figures, baseline position). The feature is designed to be flexible since it doesn’t trigger a predefined glyph holding a preassembeled fraction (like ¾). It allows any number of figures before and after the divisor.
Input: …|one|eight|slash|two|nine
Output: …|one.numr|eight.numr|fraction|two.dnom|nine.dnom
First let us create some classes for the various types of figures that help us to simplify the feature definitions, listing them in the right order with their proper names:
@standard = [zero one two three four five six seven eight nine];
@numerator = [zero.numr one.numr two.numr three.numr four.numr five.numr six.numr seven.numr eight.numr nine.numr];
@denominator = [zero.dnom one.dnom two.dnom three.dnom four.dnom five.dnom six.dnom seven.dnom eight.dnom nine.dnom];
This feature looks almost like any other but for the inconspicuous '
in the 3rd and 4th statement, marking the glyphs that we need to to transform to either numerators or denominators. All other glyph references in these two statements are used to define the context in which the substitution will take place. As in all features the order of the statements is of vital importance.
feature frac { # my Fractions feature sub slash by fraction; # 1st statement sub @standard by @numerator; # 2nd statement sub fraction @numerator' by @denominator; # 3rd statement sub @denominator @numerator' by @denominator; # 4th statement } frac;
1st statement:
For proper fractions we need the glyph named fraction
as our divisor, so if slash
was used, this statement will change it.
Output: …|one|eight|fraction|two|nine
2nd statement:
Now we take the standard figures from @standard
— still ignoring the context — and replace them by their resp. glpyh from @numerator
Output: …|one.numr|eight.numr|fraction|two.dnom|nine.numr
3rd statement (contextual):
All figures are now numerators (see 2nd statement). We now need to check whether a figure from @numerator
is preceded by the glyph fraction
. If that is the case, use the appropriate figure from @denominator
.
Output: …|one.numr|eight.numr|fraction|two.dnom|nine.numr
4th statement (contextual):
Before we write our final definition we need to know what substitutions have taken place in the previous statement. So when the feature finds the sequence of denominator|numerator it change the numerator figure to appropriate @denominator
.
Output: …|one.numr|eight.numr|fraction|two.dnom|nine.dnom
For good usability it might not be desirable that the standard figures are turned into numerators right away (2nd line) without the presence of the fraction glyph.
Can I use contextual substitution in any feature?
No, integrating contextual substitution should be confined to features that are expected to hold statements of that type. If, for example, your ligatures use contextual substitution you shouldn’t use the standard ligatures feature, liga
, but instead use clig
, the contextual ligatures feature. When you choose «Ligatures» in InDesign, both, liga
and clig
are applied.
If it doesn’t work
Sometimes features don’t do what they are supposed to. Usually syntax errors are easily corrected but logical flaws in a feature can be challenging. FontLab can detect an error in your syntax — for example, if a semicolon is missing, if your feature name at the beginning doesn’t match the one in the end, or if two classes don’t consist of the same number of glyphs. Outside of these syntax errors, the program does not know what you are trying to achieve. It can not detect logical errors as illustrated in the following examples.
Statements in the wrong order
Depending on which glyphs you want to replace, the order of your statements can be of the utmost importance. Let’s take the ligatures feature from the beginning of the article — but swap the order of the statements:
feature liga { sub f i by f_i; # 1st: if the sequence f|i is found, replace sub f f i by f_f_i; # 2nd: if the sequence f|f|i is found, replace } liga;
Now look closely at the following output and notice that the replacement of the sequence f
|f
|i
doesn’t work as desired anymore. What happened now is that the first line caused f
|f
|i
to be turned into f
|f_i
, thus f
|f
|i
triggering the ligature glyph f_f_i
isn’t available anymore.
Input: R|e|f|i|n|i|n|g|space|a|f|f|i|n|i|t|y|question
Output: R|e|f_i|n|i|n|g|space|a|f|f_i|n|i|t|y|question
So if you have an overlap in your replacement pattern (in both statements we are looking for f
|i
), make sure to put the longer sequence before the shorter.
Glyphs in classes/lists don’t match
When you define lists/classes you need to make sure that the resp. positions of the glyphs are corresponding, otherwise you’ll end up with results like the following. Here a
has been replaced by g.salt
and g
by a.salt
:
Input: D|o|n|quoteright|t|space|e|a|t|space|m|y|B|a|g|e|l|exclam|exclam|exclam
Output: D|o|n|quoteright|t|space|e|g.salt|t|space|m|y|B|g.salt|a.salt|e|l|exclam|exclam|exclam
This undesirable result is caused by the mix-up of the first and second position in the two lists: a
and g.salt
are listed first, g
and a.salt
second.
feature salt { # my Stylistic Alternates, mixed up sub [a g] by [g.salt a.salt]; } salt;
Not considering replaced glyphs
So far we have replaced glyphs that were in their basic state (a
became a.salt
). However, there are cases when you need to consider that a substitution might have already taken place, such as when the font contains more than two sets of figures (tabular, oldstyle, superscript ,…).
Example: your standard figures are tabular but the user has chosen to work with oldstyle figures and would like to change these to superscript figures. If your feature definition only lists the tabular figures to be substituted by superscript figures, then the user would see no change to the oldstyle figures. So you must consider the tabular figures as well as the old-style figures in your feature definition.
feature sups { # Superior Figures sub @standard_figures by @superscript_figures; # standard to superscript sub @oldstyle_figures by @superscript_figures; # oldstyle to superscript } sups;
Which feature works in which program?
Current layout and design applications usually support even the most sophisticated features. However in standard office programs you’ll find that there are some limitations, especially regarding contextual features. Check out the following table to see which feature and substitution type works in which application (this table is an update of Typotheque’s OpenType feature support in applications).
Chosen functionality: |
Activated feature(s): |
|||||||||||||||||||||
Proportional Oldstyle | pnum + onum |
|||||||||||||||||||||
Tabular Lining | tnum + lnum |
|||||||||||||||||||||
Proportional Lining | pnum + lnum |
|||||||||||||||||||||
Tabular Oldstyle | tnum + onum |
|||||||||||||||||||||
Standard Ligatures | liga |
|||||||||||||||||||||
Discretionary Ligatures | dlig |
|||||||||||||||||||||
Historical Ligatures | hlig |
|||||||||||||||||||||
All Caps | case + cpsp |
|||||||||||||||||||||
Small Caps | smcp |
|||||||||||||||||||||
Capitals to Small Caps | c2sc |
|||||||||||||||||||||
Superscript | sups |
|||||||||||||||||||||
Scientific Inferiors | sinf |
|||||||||||||||||||||
Subscript | subs |
|||||||||||||||||||||
Ordinals | ordn |
|||||||||||||||||||||
Titling Alternates | titl |
|||||||||||||||||||||
Swash | swsh |
|||||||||||||||||||||
Contextual Swash | cswh |
|||||||||||||||||||||
All Alternates | aalt |
|||||||||||||||||||||
Contextual Alternates | calt |
|||||||||||||||||||||
Contextual Ligatures | clig |
|||||||||||||||||||||
Fractions | frac |
|||||||||||||||||||||
Alternative Fractions | afrc |
|||||||||||||||||||||
Numerator | numr |
|||||||||||||||||||||
Denominator | dnom |
|||||||||||||||||||||
Ornaments | ornm |
|||||||||||||||||||||
Stylistic Alternates | salt |
|||||||||||||||||||||
Stylistic Sets | ss01…ss20 |
|||||||||||||||||||||
Historical Forms | hist |
|||||||||||||||||||||
Slashed Zero | zero |
|||||||||||||||||||||
Justification Alternates | jalt |
|||||||||||||||||||||
Alternate Annotation | nalt |
|||||||||||||||||||||
Mathematical Greek | mgrk |
|||||||||||||||||||||
Localized Forms | locl |
|||||||||||||||||||||
Petite Caps | pcap |
|||||||||||||||||||||
Capitals to Petite Caps | c2pc |
|||||||||||||||||||||
Unicase | unic |
|||||||||||||||||||||
Glyph de/composition | ccmp |
|||||||||||||||||||||
Required Ligatures | rlig |
|||||||||||||||||||||
Mark Positioning | mark |
|||||||||||||||||||||
Mark-to-mark Positioning | mkmk |
|||||||||||||||||||||
Mark Positioning via Subs. | mset |
|||||||||||||||||||||
Terminal Form | fina |
|||||||||||||||||||||
Initial Form | init |
|||||||||||||||||||||
Isolated Form | isol |
|||||||||||||||||||||
Medial Form | medi |
|||||||||||||||||||||
Which features are activated by which menu item?
The way programs handle the activation of features doesn’t always explain what precise feature is being called. Hover over/click on the highlighted areas in the following screen shot from InDesign and notice which features are applied.
All Caps
Changes all letters to uppercase and activates the features case
and cpsp
Small Caps
Activates smcp
Note: if no real small caps are available InDesign will use capitals and scale them according to your settings in Preferences > Advanced Type
Ligatures
Activates liga
and/or clig
Discretionary Ligatures
Activates dlig
and/or hlig
Fractions
Activates frac
Ordinal
Activates ordn
Swash
Activates swsh
and/or cswh
Titling Alternates
Activates titl
Contextual Alternates
Activates calt
and/or clig
All Small Caps
Activates c2sc
and smcp
Slashed Zero
Activates zero
Stylistic Set
Activates stylistic sets ss01
, ss02
, ss03
,…ss20
. Selection via sub menu
Positional Forms
Activates terminal forms (fina
), initial forms (init
), medial forms (medi
), and isolated forms (isol
). Selection via sub menu
Superscript/Superior
Activates sups
Subscript Inferior
Activates subs
Numerator
Activates numr
Denominator
Activates dnom
Tabular Lining
Activates tnum
and/or lnum
Proportional Oldstyle
Activates onum
and/or pnum
Proportional Lining
Activates pnum
and/or lnum
Tabular Oldstyle
Activates onum
and/or tnum
Default Figure Style
deactivates figure related features, including lnum
, pnum
, onum
, and tnum
You want to know more?
For all who want to get serious about this subject, we’ve compiled a list of links for further reading with more examples and pointed explanations.
Tools & Helpers
-
AFDKO at Typophile
Everything you need to know about the Adobe Font Development Kit for OpenType - Dancing Shoes
Python powered OpenType feature generator -
DTL FontTools
Modular suite of font editing/analysing/testing components -
FontForge
Powerful Open Source font editor -
FontLab Studio
One of the most common font editing applications -
Glyphs
Independent font editing software with a strong focus on innovative workflows -
Microsoft Typography
Specifications, tools, links – from the co-inventor of OpenType -
Nadyezhda
A font for testing feature-savvy applications -
Type Supply Tool Dept.
Suite of powerful UFO-based tools by Tal Leming
Testing your fonts
-
Adhesiontext
Powerful multi-language test text generator -
FeatureProof
Tool for testing features independently -
FontQA
Modular Python-based test suite for testing FontLab sources -
Just another test text generator
Powerful multi-language test text generator -
Text Layout Editor Demo Application
Online text editor that might be used for trying out features of installed fonts
Knowledge
-
Feature support in applications
Typotheque's overview of what will work in which application -
OpenType at Adobe
Adobe's introduction to OpenType with video -
OpenType at FontShop
FontShop's introduction to OpenType -
OpenType feature tags
Overview of all registered features -
OpenType Specification at Microsoft
The complete OpenType specification
What's in a font?
-
DTL OTmaster Light
Free tool for checking out what's contained in an OpenType font -
Windows Font properties extension
Analysing OpenType font files with a right mouse click
About the authors:
Martin Wenzel: He’s a Type and Communications Designer in Berlin, Germany. After earning his degree at the Royal Academy in The Hague, The Netherlands, he worked with Petr van Blokland in Delft for several years while setting up his one-man design studio MartinPlus.com. Originally a Berliner (not the jelly doughnut variety), he relocated to his hometown in 2005 to expand his design and font portfolio. Several of his typefaces are published under the FontFont label, including his award-winning sans-serif typeface FF Profile and last year’s FF Duper (both appearing in this article). He has recently launched his own foundry, MartinPlusFonts.com, which debuts his latest typeface Ode, also featured in the above article.
Christoph Koeberlin: I take care of FontFonts at FontShop International, show what’s nice about type on typefacts.com, spend every second that’s left with my wife and children and I’m glad that I could contribute to Martin’s article. (Martin: Christoph, I’m really glad you did. You where an enormous help!)