Substitution lookups are always applied before positioning lookups. The order that is used in the .ot file is only relevant for specifying the order of positioning lookups relative to each other and the order of substitution lookups relative to each other. For example, imagine a lookup that turns lower-case letters into small capitals. This lookup should be applied before a ligature substitution that substitutes "f i" by "fi". If this order is turned around, the word "efficiently" will look like "efficiently". Let's use this very example for a bit of code to introduce the .ot file syntax.

#input "Garogier.ttf"
#output "Garogier.otf"

/*** Latin ***/

script latn {
    feature smallCaps;
    feature ligatures;
    language VIT {
        feature smallCaps;

feature smallCaps smcp {
    lookup smallCaps;

lookup smallCaps {
    sub [a - z] -> [A.small - Z.small];
    sub [alpha - sigma1] -> [Alpha.small - Sigma.small];
    sub [sigma - omega] -> [Sigma.small - Omega.small];

feature ligatures liga {
    lookup ffi;

lookup ffi {
    sub f i -> fi;


Scripts are specified by a tag and a number of languages. The features used for the DFLT language should be specified first, then the other languages (if any) may be put in. A required feature may be put in by saying required feature <feature name>.

All features contain lookups that tell what actions should happen for that feature. The feature tag is specified behind the feature name. It is perfectly legal to have a feature name that is the same as the feature tag, but you will need different names if you have features that should do different things for various scripts, e.g., a liga feature for Latin and one for Arabic.

The positions of the script and feature definitions in the file does not make any difference. It is also legal to have multiple features reference one lookup, or to reference multiple lookups from within one feature.