OT feature “exclude_dflt” directive — FontForge syntax compliance

Adam Jagosz
Adam Jagosz Posts: 689
edited September 2018 in Font Technology
Today I decided to write a Python script to manipulate .fea files. I probably learned the fea language “the wrong way” — by examining files exported from FontForge and Googling what I didn't understand, after some time finding the Adobe docs and whatnot. So what I determined was that I had to shape my files in a quite cumbersome way for FontForge to understand them the way I wanted it to:
feature smcp {<br>script DFLT ;<br>&nbsp;&nbsp;&nbsp; language dflt ;<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; lookup smallcaps_decompose_accents_lc;<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; lookup smallcaps_0;<br>script latn ;<br>&nbsp;&nbsp;&nbsp; language dflt ;<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; lookup smallcaps_decompose_accents_lc;<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; lookup smallcaps_0;<br>script latn ;<br>&nbsp;&nbsp;&nbsp; language CAT ;<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; lookup smallcaps_decompose_accents_lc;<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; lookup smallcaps_0;<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; lookup smallcaps_CAT;<br>script latn ;<br>&nbsp;&nbsp;&nbsp; language NLD ;<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; lookup smallcaps_decompose_accents_lc;<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; lookup smallcaps_0;<br>script latn ;<br>&nbsp;&nbsp;&nbsp; language TRK ;<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; lookup smallcaps_decompose_accents_lc;<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; lookup smallcaps_0;<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; lookup smallcaps_TRK;<br>} smcp;
In other words, specify (repeat) the general/common lookups for every language I want to also have language-specific lookups for. I've been doing it this way since forever, so today I got around to rigging up a Python script to speed things up and rule out omissions... I kind of made up my own syntax inspired by CSS preprocessors. Only to discover what I invented is already described in the standard!

Rules specified between the start of a feature definition and the first 'script' are added to all language-systems, unless a language statement specifies the 'exclude_dflt' keyword. Rules specified between the occurrence of the 'script' statement and the first language statement other than 'dflt' are added to explicitly specified languages for the current script, but not to other scripts, nor to other languages of the same script that are not named in the feature. If your font has several languages for a given script, and you need language specific rules for only some of the languages, you should still explicitly name all of the languages so that they will inherit the script-level default rules.
So I tried to shape my code as follows:
languagesystem DFLT dflt ;<br>languagesystem latn dflt ;<br>languagesystem latn CAT ; <br>languagesystem latn NLD ; <br>languagesystem latn TRK ; <br><br>feature smcp {<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; lookup smallcaps_decompose_accents_lc;<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; lookup smallcaps_0;<br>script latn;<br>&nbsp;&nbsp;&nbsp; language dflt ; <br>&nbsp;&nbsp;&nbsp; language NLD ; <br>&nbsp;&nbsp;&nbsp; <b>language TRK exclude_dflt;</b><br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; lookup smallcaps_TRK;<br>&nbsp;&nbsp;&nbsp; language CAT include_dflt;<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; lookup smallcaps_CAT;<br>} smcp;
I expected (having just read the docs) that language TRK will employ only the smallcaps_TRK lookup (and ignore the top two lookups). But from what I could deduce, FontForge actually treats “exclude_dflt” as “don't register the following lookups with the dflt tag”. While the docs say it should be “don't register the default lookups (from the top of the feature) with this tag” (here: TRK). Btw, this makes it pointless to include a language tag without an “exclude_dflt” directive — otherwise FontForge will apply the following lookups to 'dflt' language as well.

So since FontForge doesn't respect the official syntax :s , I might be better off using my custom script in lieu.

FWIW, my version of FF is 31-July-2017.