ValueRecord had a makeString() method that takes an optional “vertical”
argument, but no code outside the tests sets this argument. Renamed it
to asFea() and dropped the “vertical”, so that it consistent with the
rest of feaLib.ast classes.
If Coverage is None then the subtable is a noop that does nothing and
there is no point in building it. As a bonus, it makes OTS happy since
it will reject subtables where coverageOffset is NULL (0) and the spec
does not say whether this is allowed or not.
ufo2ft feature writer calls feaLib builder with tables=[GSUB] first, to run closure
over glyph substitutions; if the GSUB features contains 'featureNames' blocks, then
an AssertionError will be raised; in this case, we can simply skip building the
FeatureParams tables as we haven't build the name records they point to.
This would make it easier to construct feaLib AST from code,
where the location is not defined and thus should be None.
Also, we can make other arguments as kwargs with a default
value, now that the first parameter is no longer 'location'.
`tables=None` by default will build all supported tables;
To build only some of these and ignore the others, one can pass a
subset of supported tables tags: .e.g. `tables={'GSUB'}` will only
build the GSUB, even if the feature file may contain e.g. GPOS
related features.
Currently, the feature file parser always resolves included files,
parses their content and inserts it in the resulting AST. The original
`include` statement is lost.
This commit introduces an option to not follow inclusions. Instead, the
output AST will contain an `include` statement. This allows to process a
feature file on its own, and allows to round-trip it.
For example in glyphsLib, when going from a UFO to a .glyphs file, a
UFO feature file will be sliced up into Glyphs.app classes (e.g. a
GSFeaturePrefix with code `include(../family.fea);`) and when going back
from .glyphs to UFO, the feature file will be patched back together.
As Martin Hosken reported in https://github.com/fonttools/fonttools/pull/1096,
feaLib currently incorrectly handles the case where a marked input
glyph sequence in a contextual chaining sub/pos rule is split into
multiple runs, rather than being a single continuous run of ' marked
glyphs.
The consensus there was to raise a syntax error like makeotf instead of
second-guessing and silently fixing it like fontforge does.
... instead of a glyphMap dict.
The parser does not actually need a reverse glyph order mapping as
it is not interested in knowing the glyphID from the glyph name,
but only whether a glyph is in the font or not.
This makes it easier for client code (e.g. ufo2ft feature compiler)
to use the feaLib Parser, without having to first construct and pass
it a glyphMap argument.
Before this change, the following glyph class:
@Vowels = [@Vowels.lc @Vowels.uc y Y];
Would be written back as:
@Vowels = [@Vowels.lc = [a e i o u]; @Vowels.uc = [A E I O U]; y Y];
Which is clearly invalid. It seems for GlyphClass.asFea() to work
correctly here we should be using GlyphClassName not GlyphClass
for the nested classes (similar to the code at the beginning of
parse_glyphclass_()).
The syntax tree representation now reflects the syntax of feature files.
Before this change, FeatureNames did not have their own `ast.Block`,
which had made the code quite messy.
Before this change, some table statements would allow empty statements
(just a semicolon) while others would not allow them. After this change,
we're more consistent.