[feaLib] Implement the Attach statement
This commit is contained in:
parent
f8987125e7
commit
89ac1b2d0d
@ -195,6 +195,16 @@ class AnchorDefinition(Statement):
|
||||
self.name, self.x, self.y, self.contourpoint = name, x, y, contourpoint
|
||||
|
||||
|
||||
class AttachStatement(Statement):
|
||||
def __init__(self, location, glyphs, contourPoints):
|
||||
Statement.__init__(self, location)
|
||||
self.glyphs, self.contourPoints = (glyphs, contourPoints)
|
||||
|
||||
def build(self, builder):
|
||||
glyphs = self.glyphs.glyphSet()
|
||||
builder.add_attach_points(self.location, glyphs, self.contourPoints)
|
||||
|
||||
|
||||
class ChainContextPosStatement(Statement):
|
||||
def __init__(self, location, prefix, glyphs, suffix, lookups):
|
||||
Statement.__init__(self, location)
|
||||
|
@ -28,6 +28,7 @@ class Builder(object):
|
||||
self.cur_feature_name_ = None
|
||||
self.lookups_ = []
|
||||
self.features_ = {} # ('latn', 'DEU ', 'smcp') --> [LookupBuilder*]
|
||||
self.attachPoints_ = {} # "a" --> {3, 7}
|
||||
self.ligatureCaretByIndex_ = {} # "f_f_i" --> {3, 7}
|
||||
self.ligatureCaretByPos_ = {} # "f_f_i" --> {300, 600}
|
||||
self.parseTree = None
|
||||
@ -95,8 +96,8 @@ class Builder(object):
|
||||
gdef = otTables.GDEF()
|
||||
gdef.Version = 1.0
|
||||
gdef.GlyphClassDef = None
|
||||
gdef.AttachList = None
|
||||
gdef.LigCaretList = self.makeLigCaretList_()
|
||||
gdef.AttachList = self.makeGDEFAttachList_()
|
||||
gdef.LigCaretList = self.makeGDEFLigCaretList_()
|
||||
|
||||
inferredGlyphClass = {}
|
||||
for lookup in self.lookups_:
|
||||
@ -140,15 +141,31 @@ class Builder(object):
|
||||
coverage.glyphs = sorted(glyphs, key=self.font.getGlyphID)
|
||||
m.Coverage.append(coverage)
|
||||
|
||||
if (gdef.GlyphClassDef is None and
|
||||
gdef.LigCaretList is None and
|
||||
gdef.MarkAttachClassDef is None):
|
||||
if any((gdef.GlyphClassDef, gdef.AttachList,
|
||||
gdef.LigCaretList, gdef.MarkAttachClassDef)):
|
||||
result = getTableClass("GDEF")()
|
||||
result.table = gdef
|
||||
return result
|
||||
else:
|
||||
return None
|
||||
result = getTableClass("GDEF")()
|
||||
result.table = gdef
|
||||
|
||||
def makeGDEFAttachList_(self):
|
||||
glyphs = sorted(self.attachPoints_.keys(), key=self.font.getGlyphID)
|
||||
if not glyphs:
|
||||
return None
|
||||
result = otTables.AttachList()
|
||||
result.Coverage = otTables.Coverage()
|
||||
result.Coverage.glyphs = glyphs
|
||||
result.GlyphCount = len(glyphs)
|
||||
result.AttachPoint = []
|
||||
for glyph in glyphs:
|
||||
pt = otTables.AttachPoint()
|
||||
pt.PointIndex = sorted(self.attachPoints_[glyph])
|
||||
pt.PointCount = len(pt.PointIndex)
|
||||
result.AttachPoint.append(pt)
|
||||
return result
|
||||
|
||||
def makeLigCaretList_(self):
|
||||
def makeGDEFLigCaretList_(self):
|
||||
glyphs = set(self.ligatureCaretByPos_.keys())
|
||||
glyphs.update(self.ligatureCaretByIndex_.keys())
|
||||
glyphs = sorted(glyphs, key=self.font.getGlyphID)
|
||||
@ -425,6 +442,10 @@ class Builder(object):
|
||||
lookup_builders.append(None)
|
||||
return lookup_builders
|
||||
|
||||
def add_attach_points(self, location, glyphs, contourPoints):
|
||||
for glyph in glyphs:
|
||||
self.attachPoints_.setdefault(glyph, set()).update(contourPoints)
|
||||
|
||||
def add_chain_context_pos(self, location, prefix, glyphs, suffix, lookups):
|
||||
lookup = self.get_lookup_(location, ChainContextPosBuilder)
|
||||
lookup.rules.append((prefix, glyphs, suffix,
|
||||
|
@ -146,7 +146,7 @@ class BuilderTest(unittest.TestCase):
|
||||
self.build, "feature test { pos A 123; pos A 456; } test;")
|
||||
|
||||
def test_constructs(self):
|
||||
for name in ("enum markClass language_required "
|
||||
for name in ("Attach enum markClass language_required "
|
||||
"LigatureCaretByIndex LigatureCaretByPos "
|
||||
"lookup lookupflag").split():
|
||||
font = makeTTFont()
|
||||
|
@ -116,6 +116,16 @@ class Parser(object):
|
||||
self.anchors_.define(name, anchordef)
|
||||
return anchordef
|
||||
|
||||
def parse_attach_(self):
|
||||
assert self.is_cur_keyword_("Attach")
|
||||
location = self.cur_token_location_
|
||||
glyphs = self.parse_glyphclass_(accept_glyphname=True)
|
||||
contourPoints = {self.expect_number_()}
|
||||
while self.next_token_ != ";":
|
||||
contourPoints.add(self.expect_number_())
|
||||
self.expect_symbol_(";")
|
||||
return ast.AttachStatement(location, glyphs, contourPoints)
|
||||
|
||||
def parse_enumerate_(self, vertical):
|
||||
assert self.cur_token_ in {"enumerate", "enum"}
|
||||
self.advance_lexer_()
|
||||
@ -608,13 +618,16 @@ class Parser(object):
|
||||
statements = table.statements
|
||||
while self.next_token_ != "}":
|
||||
self.advance_lexer_()
|
||||
if self.is_cur_keyword_("LigatureCaretByIndex"):
|
||||
if self.is_cur_keyword_("Attach"):
|
||||
statements.append(self.parse_attach_())
|
||||
elif self.is_cur_keyword_("LigatureCaretByIndex"):
|
||||
statements.append(self.parse_ligatureCaretByIndex_())
|
||||
elif self.is_cur_keyword_("LigatureCaretByPos"):
|
||||
statements.append(self.parse_ligatureCaretByPos_())
|
||||
else:
|
||||
raise FeatureLibError(
|
||||
"Expected LigatureCaretByIndex or LigatureCaretByPos",
|
||||
"Expected Attach, LigatureCaretByIndex, "
|
||||
"or LigatureCaretByPos",
|
||||
self.cur_token_location_)
|
||||
|
||||
def parse_device_(self):
|
||||
|
@ -115,6 +115,13 @@ class ParserTest(unittest.TestCase):
|
||||
self.assertEqual(foo.y, 456)
|
||||
self.assertEqual(foo.contourpoint, 5)
|
||||
|
||||
def test_attach(self):
|
||||
doc = self.parse("table GDEF {Attach [a e] 2;} GDEF;")
|
||||
s = doc.statements[0].statements[0]
|
||||
self.assertIsInstance(s, ast.AttachStatement)
|
||||
self.assertEqual(glyphstr([s.glyphs]), "[a e]")
|
||||
self.assertEqual(s.contourPoints, {2})
|
||||
|
||||
def test_feature_block(self):
|
||||
[liga] = self.parse("feature liga {} liga;").statements
|
||||
self.assertEqual(liga.name, "liga")
|
||||
|
5
Lib/fontTools/feaLib/testdata/Attach.fea
vendored
Normal file
5
Lib/fontTools/feaLib/testdata/Attach.fea
vendored
Normal file
@ -0,0 +1,5 @@
|
||||
table GDEF {
|
||||
Attach [a e] 7;
|
||||
Attach a 23;
|
||||
Attach a 23;
|
||||
} GDEF;
|
24
Lib/fontTools/feaLib/testdata/Attach.ttx
vendored
Normal file
24
Lib/fontTools/feaLib/testdata/Attach.ttx
vendored
Normal file
@ -0,0 +1,24 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ttFont>
|
||||
|
||||
<GDEF>
|
||||
<Version value="1.0"/>
|
||||
<AttachList>
|
||||
<Coverage>
|
||||
<Glyph value="a"/>
|
||||
<Glyph value="e"/>
|
||||
</Coverage>
|
||||
<!-- GlyphCount=2 -->
|
||||
<AttachPoint index="0">
|
||||
<!-- PointCount=2 -->
|
||||
<PointIndex index="0" value="7"/>
|
||||
<PointIndex index="1" value="23"/>
|
||||
</AttachPoint>
|
||||
<AttachPoint index="1">
|
||||
<!-- PointCount=1 -->
|
||||
<PointIndex index="0" value="7"/>
|
||||
</AttachPoint>
|
||||
</AttachList>
|
||||
</GDEF>
|
||||
|
||||
</ttFont>
|
Loading…
x
Reference in New Issue
Block a user