[feaLib] Handle the ignore pos
statement
https://github.com/behdad/fonttools/issues/503
This commit is contained in:
parent
4a23f8eb85
commit
b5d1124f43
@ -273,6 +273,20 @@ class FeatureReferenceStatement(Statement):
|
||||
builder.add_feature_reference(self.location, self.featureName)
|
||||
|
||||
|
||||
class IgnorePosStatement(Statement):
|
||||
def __init__(self, location, chainContexts):
|
||||
Statement.__init__(self, location)
|
||||
self.chainContexts = chainContexts
|
||||
|
||||
def build(self, builder):
|
||||
for prefix, glyphs, suffix in self.chainContexts:
|
||||
prefix = [p.glyphSet() for p in prefix]
|
||||
glyphs = [g.glyphSet() for g in glyphs]
|
||||
suffix = [s.glyphSet() for s in suffix]
|
||||
builder.add_chain_context_pos(
|
||||
self.location, prefix, glyphs, suffix, [])
|
||||
|
||||
|
||||
class IgnoreSubstStatement(Statement):
|
||||
def __init__(self, location, chainContexts):
|
||||
Statement.__init__(self, location)
|
||||
|
@ -284,29 +284,42 @@ class Parser(object):
|
||||
values = values[len(prefix):][:len(glyphs)]
|
||||
return (prefix, glyphs, lookups, values, suffix, hasMarks)
|
||||
|
||||
def parse_chain_context_(self):
|
||||
location = self.cur_token_location_
|
||||
prefix, glyphs, lookups, values, suffix, hasMarks = \
|
||||
self.parse_glyph_pattern_(vertical=False)
|
||||
chainContext = [(prefix, glyphs, suffix)]
|
||||
hasLookups = any(lookups)
|
||||
while self.next_token_ == ",":
|
||||
self.expect_symbol_(",")
|
||||
prefix, glyphs, lookups, values, suffix, hasMarks = \
|
||||
self.parse_glyph_pattern_(vertical=False)
|
||||
chainContext.append((prefix, glyphs, suffix))
|
||||
hasLookups = hasLookups or any(lookups)
|
||||
self.expect_symbol_(";")
|
||||
return chainContext, hasLookups
|
||||
|
||||
def parse_ignore_(self):
|
||||
assert self.is_cur_keyword_("ignore")
|
||||
location = self.cur_token_location_
|
||||
self.advance_lexer_()
|
||||
if self.cur_token_ in ["substitute", "sub"]:
|
||||
prefix, glyphs, lookups, values, suffix, hasMarks = \
|
||||
self.parse_glyph_pattern_(vertical=False)
|
||||
chainContext = [(prefix, glyphs, suffix)]
|
||||
hasLookups = any(lookups)
|
||||
while self.next_token_ == ",":
|
||||
self.expect_symbol_(",")
|
||||
prefix, glyphs, lookups, values, suffix, hasMarks = \
|
||||
self.parse_glyph_pattern_(vertical=False)
|
||||
chainContext.append((prefix, glyphs, suffix))
|
||||
hasLookups = hasLookups or any(lookups)
|
||||
self.expect_symbol_(";")
|
||||
chainContext, hasLookups = self.parse_chain_context_()
|
||||
if hasLookups:
|
||||
raise FeatureLibError(
|
||||
"No lookups can be specified for \"ignore sub\"",
|
||||
location)
|
||||
return ast.IgnoreSubstStatement(location, chainContext)
|
||||
if self.cur_token_ in ["position", "pos"]:
|
||||
chainContext, hasLookups = self.parse_chain_context_()
|
||||
if hasLookups:
|
||||
raise FeatureLibError(
|
||||
"No lookups can be specified for \"ignore pos\"",
|
||||
location)
|
||||
return ast.IgnorePosStatement(location, chainContext)
|
||||
raise FeatureLibError(
|
||||
"Expected \"substitute\"", self.next_token_location_)
|
||||
"Expected \"substitute\" or \"position\"",
|
||||
self.cur_token_location_)
|
||||
|
||||
def parse_language_(self):
|
||||
assert self.is_cur_keyword_("language")
|
||||
|
@ -289,6 +289,38 @@ class ParserTest(unittest.TestCase):
|
||||
self.assertIsNone(s.markGlyphs)
|
||||
self.assertIsNone(s.componentGlyphs)
|
||||
|
||||
def test_ignore_pos(self):
|
||||
doc = self.parse("feature test {ignore pos e t' c, q u' u' x;} test;")
|
||||
sub = doc.statements[0].statements[0]
|
||||
self.assertIsInstance(sub, ast.IgnorePosStatement)
|
||||
[(pref1, glyphs1, suff1), (pref2, glyphs2, suff2)] = sub.chainContexts
|
||||
self.assertEqual(glyphstr(pref1), "e")
|
||||
self.assertEqual(glyphstr(glyphs1), "t")
|
||||
self.assertEqual(glyphstr(suff1), "c")
|
||||
self.assertEqual(glyphstr(pref2), "q")
|
||||
self.assertEqual(glyphstr(glyphs2), "u u")
|
||||
self.assertEqual(glyphstr(suff2), "x")
|
||||
|
||||
def test_ignore_position(self):
|
||||
doc = self.parse(
|
||||
"feature test {"
|
||||
" ignore position f [a e] d' [a u]' [e y];"
|
||||
"} test;")
|
||||
sub = doc.statements[0].statements[0]
|
||||
self.assertIsInstance(sub, ast.IgnorePosStatement)
|
||||
[(prefix, glyphs, suffix)] = sub.chainContexts
|
||||
self.assertEqual(glyphstr(prefix), "f [a e]")
|
||||
self.assertEqual(glyphstr(glyphs), "d [a u]")
|
||||
self.assertEqual(glyphstr(suffix), "[e y]")
|
||||
|
||||
def test_ignore_position_with_lookup(self):
|
||||
self.assertRaisesRegex(
|
||||
FeatureLibError,
|
||||
'No lookups can be specified for "ignore pos"',
|
||||
self.parse,
|
||||
"lookup L { pos [A A.sc] -100; } L;"
|
||||
"feature test { ignore pos f' i', A' lookup L; } test;")
|
||||
|
||||
def test_ignore_sub(self):
|
||||
doc = self.parse("feature test {ignore sub e t' c, q u' u' x;} test;")
|
||||
sub = doc.statements[0].statements[0]
|
||||
|
Loading…
x
Reference in New Issue
Block a user