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;
InitMediFina;

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

  • @bariye: 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 evaluates 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.

BYFixOverhang can also take an optional integer value for the adjustment threshold, any adjustments less than the threshold will be dropped. e.g. BYFixOverhang 10 100 @bariye will drop any adjustments that are less than 100 units.

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;

Fractions

This plugin implements centered nut fractions for proportional numerator and denominator glyphs for up to four digits. (In theory it would be possible to expand this to an arbitrary number of digits, but I can’t work out the patterns used in centering the glyphs. Any help would be appreciated…)

It works as follows. First, it replaces one fraction-slash glyph with up to four fraction-slashes in a row, depending on the number of glyphs on the top or bottom of the fraction, whichever is the greater. For example, a fraction with two numerator glyphs and four denominator glyphs would be have four fraction slashes.

Next, it centers the glyphs over the fraction on the top and bottom.

Finally, it overlaps the fraction slashes by a user-specified value, which you will have to determine by experiment, but is likely to be somewhere around the width of the fraction slash minus the width of an average numerator/denominator glyph.

Here is a typical use:

LoadPlugin Fractions;
Feature dnom { Substitute /dnom$/~dnom -> /.dnom$/; };
Feature numr { Substitute /numr$/~numr -> /.numr$/; };
Feature frac {
  Fractions /numr$/ fraction /dnom$/ 152;
};

This says “Make a dnom feature by lopping the .dnom part off every glyph which ends with dnom and substituting those glyphs with the .dnom forms (and similarly for numr). Then make a fraction feature from the glyphs ending numr, the fraction glyph and the glyphs ending dnom, with multiple fraction slashes overlapping by 152 units.

For this to work:

  • The fraction slash needs to be a flat bar! We can’t make nut fractions from diagonal fraction slashes…

  • The numerator and denominator glyphs need to be aligned above and below the fraction slash bar respectively.

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;

Swap

Swaps two adjacent glyphs:

Swap A B;