In earlier versions of the OpenType Feature File Format specification,
the example was mal-formed so we had invented our own test case.
Adobe has kindly fixed the format specification:
https://github.com/adobe-type-tools/afdko/issues/88
This change revealed a bug in the parser where mark classes did
not get recognized as glyph classes; this is now fixed, too.
https://github.com/behdad/fonttools/issues/445
Not sure whether it makes much sense to define a contextual chain
that points to a GSUB type 3, but the OpenType feature file syntax
does not explicitly forbid it. Adobe's `makeotf` tool rejects this
kind of input with "Contextual alternate rule not yet supported";
this implies that the construct is valid (albeit definitely exotic).
Resolves https://github.com/behdad/fonttools/issues/445 for single
substitutions. The compact forms for chaining to other GSUB types
are not yet supported; these will get fixed in follow-up changes.
For GPOS type 2, the OpenType Feature File format makes a semantic
difference between `glyph` and `[glyph]`, so we need to pass the
syntax tree for the kerned glyphs and glyph classes down to the builder.
Previously, we were expanding syntax tree nodes to glyphSets at
parsing time. Therefore, the builder could not distinguish a statement
for kerning two single glyphs from a statement for kerning two glyph
glasses, where each glyph class would consist of a singleton
glyph. (Debating whether or not it makes much sense to have this
distinction is outside the scope of fonttools; we want to implement
the language in its present form).
The builder does not yet use this information for building different
tables. This change is just about plumbing.
Again, this will be needed for eventually distinguishing `glyph`
from `[glyph]` or `@CLASS`, which makes a semantic difference
when building GPOS type 2 tables.
This will be needed for implementing class-based kerning. According
to the OpenType Feature File specification, a different table needs to
be built for `glyph` versus `[glyph]`.
Before this fix, the parser failed to process statements of the form
`lookupflag MarkAttachmentType @GLYPHCLASS;` when no other flag
were set after the glyph class. However, statements like
`lookupflag MarkAttachmentType @GLYPHCLASS RightToLeft;` were
getting recognized perfectly fine.
No output is generated yet, this change is just on the parser.
The OpenType Feature File specification is surprisingly vague about
the exact syntax of chaining contextual positioning rules, so I expect
that we will have to iterate on this parser. However, the test case
in parser_test.py gets recognized by `makeotf`, so the current
implementation is unlikely to be completely wrong.
While not really documented in the OpenType Feature File specification,
the AFDKO makeotf tool handles the `markClass` statement this way.
Also, some examples in the specification seem to imply this semantics.
The class names of tree nodes for substitution and positioning rules
are now consistent with `builder.py`, which in turn is consistent with
`otTables.py`.
However, not sure how to build the otTables object graph for emitting
GPOS tables with device values; the current code thus silently strips
off any device values. Left a TODO comment for implementing this.