[feaLib] Allow 63 chars in names of glyphs and glyph classes

Resolves https://github.com/behdad/fonttools/issues/460.
See https://github.com/adobe-type-tools/afdko/pull/99 for
the change to the OpenType Feature File format specification.
This commit is contained in:
Sascha Brawer 2016-01-13 16:31:05 +01:00
parent 11c40b7de9
commit cc749c9c73
4 changed files with 23 additions and 12 deletions

View File

@ -102,9 +102,9 @@ class Lexer(object):
glyphclass = text[start + 1:self.pos_]
if len(glyphclass) < 1:
raise FeatureLibError("Expected glyph class name", location)
if len(glyphclass) > 30:
if len(glyphclass) > 63:
raise FeatureLibError(
"Glyph class names must not be longer than 30 characters",
"Glyph class names must not be longer than 63 characters",
location)
if not Lexer.RE_GLYPHCLASS.match(glyphclass):
raise FeatureLibError(

View File

@ -40,8 +40,8 @@ class LexerTest(unittest.TestCase):
self.assertRaisesRegex(FeatureLibError,
"Expected glyph class", lex, "@ A")
self.assertRaisesRegex(FeatureLibError,
"not be longer than 30 characters",
lex, "@a123456789.a123456789.a123456789.x")
"not be longer than 63 characters",
lex, "@" + ("A" * 64))
self.assertRaisesRegex(FeatureLibError,
"Glyph class names must consist of",
lex, "@Ab:c")

View File

@ -192,19 +192,20 @@ class Parser(object):
glyphs = set()
location = self.cur_token_location_
while self.next_token_ != "]":
self.advance_lexer_()
if self.cur_token_type_ is Lexer.NAME:
if self.next_token_type_ is Lexer.NAME:
glyph = self.expect_glyph_()
if self.next_token_ == "-":
range_location = self.cur_token_location_
range_start = self.cur_token_
range_start = glyph
self.expect_symbol_("-")
range_end = self.expect_name_()
range_end = self.expect_glyph_()
glyphs.update(self.make_glyph_range_(range_location,
range_start,
range_end))
else:
glyphs.add(self.cur_token_)
elif self.cur_token_type_ is Lexer.CID:
glyphs.add(glyph)
elif self.next_token_type_ is Lexer.CID:
glyph = self.expect_glyph_()
if self.next_token_ == "-":
range_location = self.cur_token_location_
range_start = self.cur_token_
@ -214,7 +215,8 @@ class Parser(object):
range_start, range_end))
else:
glyphs.add("cid%05d" % self.cur_token_)
elif self.cur_token_type_ is Lexer.GLYPHCLASS:
elif self.next_token_type_ is Lexer.GLYPHCLASS:
self.advance_lexer_()
gc = self.glyphclasses_.resolve(self.cur_token_)
if gc is None:
raise FeatureLibError(
@ -225,7 +227,7 @@ class Parser(object):
raise FeatureLibError(
"Expected glyph name, glyph range, "
"or glyph class reference",
self.cur_token_location_)
self.next_token_location_)
self.expect_symbol_("]")
return ast.GlyphClass(location, glyphs)
@ -876,6 +878,10 @@ class Parser(object):
def expect_glyph_(self):
self.advance_lexer_()
if self.cur_token_type_ is Lexer.NAME:
if len(self.cur_token_) > 63:
raise FeatureLibError(
"Glyph names must not be longer than 63 characters",
self.cur_token_location_)
return self.cur_token_
elif self.cur_token_type_ is Lexer.CID:
return "cid%05d" % self.cur_token_

View File

@ -154,6 +154,11 @@ class ParserTest(unittest.TestCase):
self.assertEqual(gc.name, "dash")
self.assertEqual(gc.glyphs, {"endash", "emdash", "figuredash"})
def test_glyphclass_glyphNameTooLong(self):
self.assertRaisesRegex(
FeatureLibError, "must not be longer than 63 characters",
self.parse, "@GlyphClass = [%s];" % ("G" * 64))
def test_glyphclass_bad(self):
self.assertRaisesRegex(
FeatureLibError,