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'.
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.
A multiple substitution may have a single destination, in which case
it will look just like a single substitution. So if there are both
multiple and single substitutions, upgrade all the single ones to
multiple substitutions. Previously we would just give an error message
in the builder and abort, which means certain valid OpenType lookups
can’t be represented by feature files.
This is the same logic implemented by FontForge (actually the
explanation above is almost copied verbatim from its source), makeotf
does not do this AFAIK but I consider it a bug not a feature.
Fixes https://github.com/fonttools/fonttools/issues/612
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.
We now correctly handle nameid statements with surrogate pairs and
old-style macOS-encoded names (provided that fonttools supports the
specified encoding).
Resolves https://github.com/fonttools/fonttools/issues/842.
* First round of adding fea output
No format tests but all test files give reasonable output so far.
* Get existing tests working
* Initial tests that work for fea2fea
* Get more tests working
Bug fixes and re-layout some tests to compare with fea2fea output.
Ranges and name parameters are not optimised yet.
* Handle vertical default values in fea2fea
* Hide fea2fea differences in lookupflags
* No reduce() in py3 so use a for loop
Fixes https://github.com/fonttools/fonttools/issues/457
Backslash-prefixed glyph name can be used in a Feature file to distinguish them from identically-named keywords.
From section "2.f.i. Glyph name" of Adobe's Feature File Specification:
> An initial backslash serves to differentiate a glyph name from an identical keyword in the feature file language. For example, a glyph named "table" must be specified in the feature file as: \table
Thus, when we parse a glyph name that begins with a backslash, we need to ignore the first character.
Note that makeotf rejects feature files with glyph names that start with or contain backslashes, even when escaped with another backslash.
feature liga {
sub \\glyphWithBackslash by A;
} liga;
This yields:
makeotfexe [FATAL] <Backslash-Regular> invalid token (text was "\") [features 2]
http://www.adobe.com/devnet/opentype/afdko/topic_feature_file_syntax.html#10
For example, @mhosken is interested in experimenting with inlining
custom syntax (such as Python snippets) into feature files. After this
change, such experiments can be done on top of feaLib because the
Abstract Syntax Tree now contains the tag and content of `anonymous`
blocks.