Just to preface: I know this is a big feature request and I don’t expect you to accept it or to handle it in any timely manner. Still, this is something that is useful and fills a gap to other feature languages like FEE.
I propose an additional glyph class predicate field: classes. This allows to check whether a glyph is part of a glyph class or not.
$[classes contains "CombiningMarks"]
This predicate can, of course, be combined with other predicates like isAligned, countOfUnicodes, etc. But, it is also very useful on its own because it allows to perform all basic set operations on glyphs classes.
Set operations
Identity (trivial)
# @A
[ $[classes contains "A"] ]
Identity is trivial since it is the same as writing @A.
Complement
# complement(@A)
[ $[not classes contains "A"] ]
Union (trivial)
# union(@A, @B)
[ $[classes contains "A" or classes contains "B"] ]
Set union is the second trivial example since [@A @B] already does a similar thing. The difference is that a union does not contain duplicate members.
Intersection
# intersection(@A, @B)
[ $[classes contains "A" and classes contains "B"] ]
Difference
# difference(@A, @B)
[ $[classes contains "A" and not classes contains "B"] ]
Symmetric difference
# symmetric_difference(@A, @B)
# -- expressed as union of differences:
[ $[(classes contains "A" and not classes contains "B") or (not classes contains "A" and classes contains "B")] ]
# -- expressed as “in one but not both”:
[ $[(classes contains "A" or classes contains "B") and not (classes contains "A" and classes contains "B")] ]
(I don’t think the symmetric difference is particularly useful for font-design, but it is neat that it is possible.)
Details
The new classes field would be a list of strings where each string corresponds to a glyph class that contains the respective glyph. Using the standard contains operator one can check whether a glyph belongs to a class or not.
For example, all non-digit glyphs:
$[not classes contains "Digits"]
The classes field should probably contain only class names of classes defined above the token. This also makes recursive predicates impossible.




