[feaLib] Support hhea table
This commit is contained in:
parent
a61b31a917
commit
5ceaa43d27
@ -631,3 +631,13 @@ class OS2Field(Statement):
|
||||
|
||||
def build(self, builder):
|
||||
builder.add_os2_field(self.key, self.value)
|
||||
|
||||
|
||||
class HheaField(Statement):
|
||||
def __init__(self, location, key, value):
|
||||
Statement.__init__(self, location)
|
||||
self.key = key
|
||||
self.value = value
|
||||
|
||||
def build(self, builder):
|
||||
builder.add_hhea_field(self.key, self.value)
|
||||
|
@ -69,12 +69,15 @@ class Builder(object):
|
||||
self.markFilterSets_ = {} # frozenset({"acute", "grave"}) --> 4
|
||||
# for table 'OS/2'
|
||||
self.os2_ = {}
|
||||
# for table 'hhea'
|
||||
self.hhea_ = {}
|
||||
|
||||
def build(self):
|
||||
self.parseTree = Parser(self.file).parse()
|
||||
self.parseTree.build(self)
|
||||
self.build_feature_aalt_()
|
||||
self.build_head()
|
||||
self.build_hhea()
|
||||
self.build_name()
|
||||
self.build_OS_2()
|
||||
for tag in ('GPOS', 'GSUB'):
|
||||
@ -185,6 +188,23 @@ class Builder(object):
|
||||
table.created = table.modified = 3406620153 # 2011-12-13 11:22:33
|
||||
table.fontRevision = self.fontRevision_
|
||||
|
||||
def build_hhea(self):
|
||||
if not self.hhea_:
|
||||
return
|
||||
table = self.font.get("hhea")
|
||||
if not table: # this only happens for unit tests
|
||||
table = self.font["hhea"] = getTableClass("hhea")()
|
||||
table.decompile(b"\0" * 36, self.font)
|
||||
table.tableVersion = 1.0
|
||||
if "caretoffset" in self.hhea_:
|
||||
table.caretOffset = self.hhea_["caretoffset"]
|
||||
if "ascender" in self.hhea_:
|
||||
table.ascent = self.hhea_["ascender"]
|
||||
if "descender" in self.hhea_:
|
||||
table.descent = self.hhea_["descender"]
|
||||
if "linegap" in self.hhea_:
|
||||
table.lineGap = self.hhea_["linegap"]
|
||||
|
||||
def get_user_name_id(self, table):
|
||||
# Try to find first unused font-specific name id
|
||||
nameIDs = [name.nameID for name in table.names]
|
||||
@ -922,6 +942,9 @@ class Builder(object):
|
||||
def add_os2_field(self, key, value):
|
||||
self.os2_[key] = value
|
||||
|
||||
def add_hhea_field(self, key, value):
|
||||
self.hhea_[key] = value
|
||||
|
||||
|
||||
def makeOpenTypeAnchor(anchor):
|
||||
"""ast.Anchor --> otTables.Anchor"""
|
||||
|
@ -57,7 +57,7 @@ class BuilderTest(unittest.TestCase):
|
||||
spec5f_ii_1 spec5f_ii_2 spec5f_ii_3 spec5f_ii_4
|
||||
spec5h1 spec6b_ii spec6d2 spec6e spec6f
|
||||
spec6h_ii spec6h_iii_1 spec6h_iii_3d spec8a spec8b spec8c
|
||||
spec9a spec9b spec9c1 spec9c2 spec9c3 spec9e spec9f
|
||||
spec9a spec9b spec9c1 spec9c2 spec9c3 spec9d spec9e spec9f
|
||||
bug453 bug463 bug501 bug502 bug505 bug506 bug509 bug512
|
||||
name size size2
|
||||
""".split()
|
||||
@ -104,7 +104,7 @@ class BuilderTest(unittest.TestCase):
|
||||
def expect_ttx(self, font, expected_ttx):
|
||||
path = self.temp_path(suffix=".ttx")
|
||||
font.saveXML(path, tables=['head', 'name', 'BASE', 'GDEF', 'GSUB',
|
||||
'GPOS', 'OS/2'])
|
||||
'GPOS', 'OS/2', 'hhea'])
|
||||
actual = self.read_ttx(path)
|
||||
expected = self.read_ttx(expected_ttx)
|
||||
if actual != expected:
|
||||
|
@ -698,6 +698,7 @@ class Parser(object):
|
||||
handler = {
|
||||
"GDEF": self.parse_table_GDEF_,
|
||||
"head": self.parse_table_head_,
|
||||
"hhea": self.parse_table_hhea_,
|
||||
"name": self.parse_table_name_,
|
||||
"BASE": self.parse_table_BASE_,
|
||||
"OS/2": self.parse_table_OS_2_,
|
||||
@ -743,6 +744,23 @@ class Parser(object):
|
||||
raise FeatureLibError("Expected FontRevision",
|
||||
self.cur_token_location_)
|
||||
|
||||
def parse_table_hhea_(self, table):
|
||||
statements = table.statements
|
||||
fields = ("CaretOffset", "Ascender", "Descender", "LineGap")
|
||||
while self.next_token_ != "}":
|
||||
self.advance_lexer_()
|
||||
if self.cur_token_type_ is Lexer.NAME and self.cur_token_ in fields:
|
||||
key = self.cur_token_.lower()
|
||||
value = self.expect_number_()
|
||||
statements.append(
|
||||
ast.HheaField(self.cur_token_location_, key, value))
|
||||
elif self.cur_token_ == ";":
|
||||
continue
|
||||
else:
|
||||
raise FeatureLibError("Expected CaretOffset, Ascender, "
|
||||
"Descender or LineGap",
|
||||
self.cur_token_location_)
|
||||
|
||||
def parse_table_name_(self, table):
|
||||
statements = table.statements
|
||||
while self.next_token_ != "}":
|
||||
|
6
Lib/fontTools/feaLib/testdata/spec9d.fea
vendored
Normal file
6
Lib/fontTools/feaLib/testdata/spec9d.fea
vendored
Normal file
@ -0,0 +1,6 @@
|
||||
table hhea {
|
||||
CaretOffset -50;
|
||||
Ascender 800;
|
||||
Descender 200;
|
||||
LineGap 200;
|
||||
} hhea;
|
24
Lib/fontTools/feaLib/testdata/spec9d.ttx
vendored
Normal file
24
Lib/fontTools/feaLib/testdata/spec9d.ttx
vendored
Normal file
@ -0,0 +1,24 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ttFont>
|
||||
|
||||
<hhea>
|
||||
<tableVersion value="1.0"/>
|
||||
<ascent value="800"/>
|
||||
<descent value="200"/>
|
||||
<lineGap value="200"/>
|
||||
<advanceWidthMax value="0"/>
|
||||
<minLeftSideBearing value="0"/>
|
||||
<minRightSideBearing value="0"/>
|
||||
<xMaxExtent value="0"/>
|
||||
<caretSlopeRise value="0"/>
|
||||
<caretSlopeRun value="0"/>
|
||||
<caretOffset value="-50"/>
|
||||
<reserved0 value="0"/>
|
||||
<reserved1 value="0"/>
|
||||
<reserved2 value="0"/>
|
||||
<reserved3 value="0"/>
|
||||
<metricDataFormat value="0"/>
|
||||
<numberOfHMetrics value="0"/>
|
||||
</hhea>
|
||||
|
||||
</ttFont>
|
Loading…
x
Reference in New Issue
Block a user