[feaLib] Support hhea table
This commit is contained in:
parent
a61b31a917
commit
5ceaa43d27
@ -631,3 +631,13 @@ class OS2Field(Statement):
|
|||||||
|
|
||||||
def build(self, builder):
|
def build(self, builder):
|
||||||
builder.add_os2_field(self.key, self.value)
|
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
|
self.markFilterSets_ = {} # frozenset({"acute", "grave"}) --> 4
|
||||||
# for table 'OS/2'
|
# for table 'OS/2'
|
||||||
self.os2_ = {}
|
self.os2_ = {}
|
||||||
|
# for table 'hhea'
|
||||||
|
self.hhea_ = {}
|
||||||
|
|
||||||
def build(self):
|
def build(self):
|
||||||
self.parseTree = Parser(self.file).parse()
|
self.parseTree = Parser(self.file).parse()
|
||||||
self.parseTree.build(self)
|
self.parseTree.build(self)
|
||||||
self.build_feature_aalt_()
|
self.build_feature_aalt_()
|
||||||
self.build_head()
|
self.build_head()
|
||||||
|
self.build_hhea()
|
||||||
self.build_name()
|
self.build_name()
|
||||||
self.build_OS_2()
|
self.build_OS_2()
|
||||||
for tag in ('GPOS', 'GSUB'):
|
for tag in ('GPOS', 'GSUB'):
|
||||||
@ -185,6 +188,23 @@ class Builder(object):
|
|||||||
table.created = table.modified = 3406620153 # 2011-12-13 11:22:33
|
table.created = table.modified = 3406620153 # 2011-12-13 11:22:33
|
||||||
table.fontRevision = self.fontRevision_
|
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):
|
def get_user_name_id(self, table):
|
||||||
# Try to find first unused font-specific name id
|
# Try to find first unused font-specific name id
|
||||||
nameIDs = [name.nameID for name in table.names]
|
nameIDs = [name.nameID for name in table.names]
|
||||||
@ -922,6 +942,9 @@ class Builder(object):
|
|||||||
def add_os2_field(self, key, value):
|
def add_os2_field(self, key, value):
|
||||||
self.os2_[key] = value
|
self.os2_[key] = value
|
||||||
|
|
||||||
|
def add_hhea_field(self, key, value):
|
||||||
|
self.hhea_[key] = value
|
||||||
|
|
||||||
|
|
||||||
def makeOpenTypeAnchor(anchor):
|
def makeOpenTypeAnchor(anchor):
|
||||||
"""ast.Anchor --> otTables.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
|
spec5f_ii_1 spec5f_ii_2 spec5f_ii_3 spec5f_ii_4
|
||||||
spec5h1 spec6b_ii spec6d2 spec6e spec6f
|
spec5h1 spec6b_ii spec6d2 spec6e spec6f
|
||||||
spec6h_ii spec6h_iii_1 spec6h_iii_3d spec8a spec8b spec8c
|
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
|
bug453 bug463 bug501 bug502 bug505 bug506 bug509 bug512
|
||||||
name size size2
|
name size size2
|
||||||
""".split()
|
""".split()
|
||||||
@ -104,7 +104,7 @@ class BuilderTest(unittest.TestCase):
|
|||||||
def expect_ttx(self, font, expected_ttx):
|
def expect_ttx(self, font, expected_ttx):
|
||||||
path = self.temp_path(suffix=".ttx")
|
path = self.temp_path(suffix=".ttx")
|
||||||
font.saveXML(path, tables=['head', 'name', 'BASE', 'GDEF', 'GSUB',
|
font.saveXML(path, tables=['head', 'name', 'BASE', 'GDEF', 'GSUB',
|
||||||
'GPOS', 'OS/2'])
|
'GPOS', 'OS/2', 'hhea'])
|
||||||
actual = self.read_ttx(path)
|
actual = self.read_ttx(path)
|
||||||
expected = self.read_ttx(expected_ttx)
|
expected = self.read_ttx(expected_ttx)
|
||||||
if actual != expected:
|
if actual != expected:
|
||||||
|
@ -698,6 +698,7 @@ class Parser(object):
|
|||||||
handler = {
|
handler = {
|
||||||
"GDEF": self.parse_table_GDEF_,
|
"GDEF": self.parse_table_GDEF_,
|
||||||
"head": self.parse_table_head_,
|
"head": self.parse_table_head_,
|
||||||
|
"hhea": self.parse_table_hhea_,
|
||||||
"name": self.parse_table_name_,
|
"name": self.parse_table_name_,
|
||||||
"BASE": self.parse_table_BASE_,
|
"BASE": self.parse_table_BASE_,
|
||||||
"OS/2": self.parse_table_OS_2_,
|
"OS/2": self.parse_table_OS_2_,
|
||||||
@ -743,6 +744,23 @@ class Parser(object):
|
|||||||
raise FeatureLibError("Expected FontRevision",
|
raise FeatureLibError("Expected FontRevision",
|
||||||
self.cur_token_location_)
|
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):
|
def parse_table_name_(self, table):
|
||||||
statements = table.statements
|
statements = table.statements
|
||||||
while self.next_token_ != "}":
|
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