From 7db9ba6ef6c33f2b84bf399c9d552aa7a0cfca1a Mon Sep 17 00:00:00 2001 From: Khaled Hosny Date: Fri, 7 Aug 2020 17:57:23 +0200 Subject: [PATCH] [feaLib] Allow anonymous glyphclass in LookupFlags Almost everywhere else when a glyph class name is accepted, anonymous glyph classes are also accepted. This is rather inconsistent and inconvenient. --- Lib/fontTools/feaLib/parser.py | 17 ++--------------- Tests/feaLib/data/lookupflag.fea | 10 ++++++++++ Tests/feaLib/data/lookupflag.ttx | 27 ++++++++++++++++++++++++++- Tests/feaLib/parser_test.py | 24 ++++++++++++++++++++++++ 4 files changed, 62 insertions(+), 16 deletions(-) diff --git a/Lib/fontTools/feaLib/parser.py b/Lib/fontTools/feaLib/parser.py index ab6928ff7..7439fbf34 100644 --- a/Lib/fontTools/feaLib/parser.py +++ b/Lib/fontTools/feaLib/parser.py @@ -408,19 +408,6 @@ class Parser(object): self.expect_symbol_("]") return glyphs - def parse_class_name_(self): - # Parses named class - either a glyph class or mark class. - name = self.expect_class_name_() - gc = self.glyphclasses_.resolve(name) - if gc is None: - raise FeatureLibError( - "Unknown glyph class @%s" % name, self.cur_token_location_ - ) - if isinstance(gc, self.ast.MarkClass): - return self.ast.MarkClassName(gc, location=self.cur_token_location_) - else: - return self.ast.GlyphClassName(gc, location=self.cur_token_location_) - def parse_glyph_pattern_(self, vertical): # Parses a glyph pattern, including lookups and context, e.g.:: # @@ -633,10 +620,10 @@ class Parser(object): seen.add(self.next_token_) if self.next_token_ == "MarkAttachmentType": self.expect_keyword_("MarkAttachmentType") - markAttachment = self.parse_class_name_() + markAttachment = self.parse_glyphclass_(accept_glyphname=False) elif self.next_token_ == "UseMarkFilteringSet": self.expect_keyword_("UseMarkFilteringSet") - markFilteringSet = self.parse_class_name_() + markFilteringSet = self.parse_glyphclass_(accept_glyphname=False) elif self.next_token_ in flags: value_seen = True value = value | flags[self.expect_name_()] diff --git a/Tests/feaLib/data/lookupflag.fea b/Tests/feaLib/data/lookupflag.fea index 1828c43ed..0210ab42f 100644 --- a/Tests/feaLib/data/lookupflag.fea +++ b/Tests/feaLib/data/lookupflag.fea @@ -147,3 +147,13 @@ feature test { pos two 2; } X; } test; + +lookup Y { + lookupflag UseMarkFilteringSet [acute grave macron]; + pos Y 1; +} Y; + +lookup Z { + lookupflag MarkAttachmentType [acute grave macron]; + pos Z 1; +} Z; diff --git a/Tests/feaLib/data/lookupflag.ttx b/Tests/feaLib/data/lookupflag.ttx index 760eab313..16ea751f5 100644 --- a/Tests/feaLib/data/lookupflag.ttx +++ b/Tests/feaLib/data/lookupflag.ttx @@ -107,7 +107,7 @@ - + @@ -400,6 +400,31 @@ + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Tests/feaLib/parser_test.py b/Tests/feaLib/parser_test.py index 580902969..db505950c 100644 --- a/Tests/feaLib/parser_test.py +++ b/Tests/feaLib/parser_test.py @@ -718,6 +718,18 @@ class ParserTest(unittest.TestCase): self.assertEqual(flag.asFea(), "lookupflag RightToLeft MarkAttachmentType @TOP_MARKS;") + def test_lookupflag_format_A_MarkAttachmentType_glyphClass(self): + flag = self.parse_lookupflag_( + "lookupflag RightToLeft MarkAttachmentType [acute grave macron];") + self.assertIsInstance(flag, ast.LookupFlagStatement) + self.assertEqual(flag.value, 1) + self.assertIsInstance(flag.markAttachment, ast.GlyphClass) + self.assertEqual(flag.markAttachment.glyphSet(), + ("acute", "grave", "macron")) + self.assertIsNone(flag.markFilteringSet) + self.assertEqual(flag.asFea(), + "lookupflag RightToLeft MarkAttachmentType [acute grave macron];") + def test_lookupflag_format_A_UseMarkFilteringSet(self): flag = self.parse_lookupflag_( "@BOTTOM_MARKS = [cedilla ogonek];" @@ -731,6 +743,18 @@ class ParserTest(unittest.TestCase): self.assertEqual(flag.asFea(), "lookupflag IgnoreLigatures UseMarkFilteringSet @BOTTOM_MARKS;") + def test_lookupflag_format_A_UseMarkFilteringSet_glyphClass(self): + flag = self.parse_lookupflag_( + "lookupflag UseMarkFilteringSet [cedilla ogonek] IgnoreLigatures;") + self.assertIsInstance(flag, ast.LookupFlagStatement) + self.assertEqual(flag.value, 4) + self.assertIsNone(flag.markAttachment) + self.assertIsInstance(flag.markFilteringSet, ast.GlyphClass) + self.assertEqual(flag.markFilteringSet.glyphSet(), + ("cedilla", "ogonek")) + self.assertEqual(flag.asFea(), + "lookupflag IgnoreLigatures UseMarkFilteringSet [cedilla ogonek];") + def test_lookupflag_format_B(self): flag = self.parse_lookupflag_("lookupflag 7;") self.assertIsInstance(flag, ast.LookupFlagStatement)