From 22bfc305eef84115ff3e893a0438256394442e08 Mon Sep 17 00:00:00 2001 From: Khaled Hosny Date: Wed, 29 Jan 2020 22:34:25 +0200 Subject: [PATCH] [feaLib] fix mixed single/multiple substitutions If the single substitution involved a glyph class, we were incorrectly using only the first glyph in the class. Broken since ec6ff821f0e72022d7aec8794b6bb589d8f81808, apparently no one else uses this feature! --- Lib/fontTools/feaLib/parser.py | 19 ++++++++++++++----- Tests/feaLib/parser_test.py | 10 ++++++++++ 2 files changed, 24 insertions(+), 5 deletions(-) diff --git a/Lib/fontTools/feaLib/parser.py b/Lib/fontTools/feaLib/parser.py index d8670d6bd..54f9edac0 100644 --- a/Lib/fontTools/feaLib/parser.py +++ b/Lib/fontTools/feaLib/parser.py @@ -1452,12 +1452,21 @@ class Parser(object): # Upgrade all single substitutions to multiple substitutions. if has_single and has_multiple: - for i, s in enumerate(statements): + statements = [] + for s in block.statements: if isinstance(s, self.ast.SingleSubstStatement): - statements[i] = self.ast.MultipleSubstStatement( - s.prefix, s.glyphs[0].glyphSet()[0], s.suffix, - [r.glyphSet()[0] for r in s.replacements], - s.forceChain, location=s.location) + glyphs = s.glyphs[0].glyphSet() + replacements = s.replacements[0].glyphSet() + if len(replacements) == 1: + replacements *= len(glyphs) + for i, glyph in enumerate(glyphs): + statements.append( + self.ast.MultipleSubstStatement( + s.prefix, glyph, s.suffix, [replacements[i]], + s.forceChain, location=s.location)) + else: + statements.append(s) + block.statements = statements def is_cur_keyword_(self, k): if self.cur_token_type_ is Lexer.NAME: diff --git a/Tests/feaLib/parser_test.py b/Tests/feaLib/parser_test.py index a5b9f69c8..e11a68789 100644 --- a/Tests/feaLib/parser_test.py +++ b/Tests/feaLib/parser_test.py @@ -1396,12 +1396,22 @@ class ParserTest(unittest.TestCase): " sub f_f by f f;" " sub f by f;" " sub f_f_i by f f i;" + " sub [a a.sc] by a;" + " sub [a a.sc] by [b b.sc];" "} Look;") statements = doc.statements[0].statements for sub in statements: self.assertIsInstance(sub, ast.MultipleSubstStatement) self.assertEqual(statements[1].glyph, "f") self.assertEqual(statements[1].replacement, ["f"]) + self.assertEqual(statements[3].glyph, "a") + self.assertEqual(statements[3].replacement, ["a"]) + self.assertEqual(statements[4].glyph, "a.sc") + self.assertEqual(statements[4].replacement, ["a"]) + self.assertEqual(statements[5].glyph, "a") + self.assertEqual(statements[5].replacement, ["b"]) + self.assertEqual(statements[6].glyph, "a.sc") + self.assertEqual(statements[6].replacement, ["b.sc"]) def test_substitute_from(self): # GSUB LookupType 3 doc = self.parse("feature test {"