Optional plugins

As well as the standard FEZ verbs, which allow you to do most of the “manual” layout operations which should be familiar to users of AFDKO, FEZ includes a number of additional plugins which are not loaded by default, but which provide higher-level functionality.

As well as being useful per se for font engineers, inspecting the source code to these plugins is also a good way to learn how to write your own plugins and add verbs to the language.

Arabic Glyph Shaping

The Arabic plugin automates the creation of Arabic positional shaping features. However, it requires you to have a particular glyph naming convention: initial forms must end with .init, medial forms with .medi and final forms with .fina.

Next, load the plugin and use the InitMediFina verb, which takes no arguments:

LoadPlugin Arabic;

This will define @init, @media and @fina classes, and create the init, medi and fina features.

Bari Ye Processing

This plugin provides some verbs which are extremely useful for handling the bari-ye sequence in the Nastaliq script, but which require a certain amount of set-up in advance from the user.

First, you must define the following glyph classes:

  • @inits: all initial forms

  • @medis: all medial forms

  • @bari_ye: all forms of final bari ye or glyphs that you wish to treat like bari ye. For example, final jim and final choti ye may have “bari ye like tendencies” in that they have a large negative right sidebearing that requires nukta repositioning.

  • @behs: all glyphs which may “carry” nuktas and marks under the rasm; typically medial and initial beh forms, but also medial and initial jim.

With this set-up in place, the BariYe plugin provides you with two verbs: BYMoveDots moves nuktas or marks such as kasra to underneath the swash of the bari ye (or jim etc…) by computing the length of the swash, the width and rise of all sequences, and emitting rules which match applicable sequences. BYMoveDots takes two arguments. The first depends on your preferred stylistic strategy for handling bari ne nuktas: either AlwaysDrop, which simply drops all dots underneath the swash, or TryToFit which only drops those dots which would not fit in the gap between the bari ye swash and the rasm. (One nice trick is to put BYMoveDots TryToFit into an rlig feature, and BYMoveDots AlwaysDrop into a stylistic set, so the user can choose where the dots should be.) The second is the list of all nuktas or marks (e.g. kasra) which sit under the rasm and need to be repositioned underneath the bari ye swash. Note carefully that this class should additionally contain a set of glyphs suffixed .yb which have no anchors defined. i.e. if your two-dots-below glyph is called ddb, then it should contain both ddb and ddb.yb, a copy of ddb with no anchors. You can use the FontEngineering plugin to generate these glyphs on the fly if necessary.

The other verb, BYFixOverhang deals with the problem of short bari ye sequences. Bari ye glyphs typically have a large negative right sidebearing, which means that sequences like “ابے” need additional kerning to stop the alif from being “drawn in” to the bari ye.

BYFixOverhang takes an integer value (an additional number of points to separate the end of the bari ye tail and the following glyph), and computes rules which act only on short sequences; it evalutes all possible short sequences (using width-binning to keep the number of combinations to a reasonable number), computes the total width of each sequence, compares this against the negative RSB of the bari ye, and emits appropriate kerning rules to generate the desired separation. e.g. BYFixOverhang 10 @bariye will ensure that there are at least 10 points between the end of the tail of each glyph in @bariye and any isolated/final glyph preceding the sequence.

Font Engineering

This plugin provides verbs which allow you to modify the font while processing it. For example, it’s common when engineering fonts for scripts with complex requirements to create a set of glyphs which act purely as markers, which are referred to by future substitution or positioning rules, or which connect to alternate anchor points, or which are used to guide contextual rules. These glyphs aren’t part of the design, and it’s annoying to have them sitting around in the design source; they’re really only a creation of the layout rules. This plugin allows you to create and modify such glyphs within your features file, so that they are available when needed but aren’t getting in the designer’s way.

The DuplicateGlyphs verb takes two glyph selectors, one for the existing glyphs and one for a new set of glyphs, and adds the new glyphs to the file with the outlines, metrics and glyph category of the existing glyphs. For example:

DuplicateGlyphs /^[a-z]$/ /^[a-z]$/.alt;

This will create copies of all the lowercase Latin letters.

The SetWidth verb takes a glyph selector and a width, which is either absolute (integer number of font units) or relative (percentage of existing width). Relative widths are specified by a percent sign suffix. The width of the glyph will be altered appropriately. Hence:

DuplicateGlyphs space space.ARA;
SetWidth space.ARA 50%;

This creates a new glyph space.ARA from the space glyph and then sets its advance width to be 50% of the width of space.

The SetCategory verb sets a glyph’s OpenType category:

DuplicateGlyphs tonemark tonemark.spacing;
SetCategory tonemark.spacing base;
SetWidth tonemark.spacing 120;

Matra selection

In Devanagari fonts, it is common to have a basic glyph to represent the “i” matra, and then a set of variant glyphs of differing widths. The “arm” of the “i” matra should reach the stem of the following base consonant, which leads to an interesting font engineering question: how do we produce a set of substitution rules which replaces the basic glyph for each width-specific variant most appropriate to the widths of the each consonant?

Obviously you don’t want to work that out manually, because the next time you engineer a Devanagari font you have to work it out again, and no programmer is going to do the same set of operations more than once without automating it.

The IMatra plugin provides a verb which matches the consonants to the matra variant with the appropriate sized arm and emits substitution rules. It takes a glyph selector to represent the consonants, the basic i-matra glyph, and a glyph selector for all the i-matra variants:

LoadPlugin IMatra;
DefineClass @consonants = /^dv.*A$/;
IMatra @consonants : dvmI -> /^dvmI/;

For more on how this plugin actually operates, see The IMatra Plugin.

Ligature Finder

Looks for ligature glyphs matching a glyph selector and tries to write ligature rules which compose them. e.g. given:

LoadPlugin LigatureFinder;
Routine ligatures {
    LigatureFinder /kinzi.*/;

If you have glyphs kinzi_ai, kinzi and ai, this will write a rule Substitute kinzi ai -> kinzi_ai;.

Medial Ra selection

Same as IMatra, but for Myanmar:

LoadPlugin MedialRa;
DefineClass @consonants = /^{1,3}a$/;
MedialRa @consonants : medial-ra -> @otherras;


Swaps two adjacent glyphs:

Swap A B;