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@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;
Swap¶
Swaps two adjacent glyphs:
Swap A B;