[feaLib] Support BASE table
Just the parts documented a currently implemented by Adobe’s implementation.
This commit is contained in:
parent
40be0e6f3a
commit
1ac37d7d00
@ -610,3 +610,14 @@ class SizeParameters(Statement):
|
||||
def build(self, builder):
|
||||
builder.set_size_parameters(self.location, self.DesignSize,
|
||||
self.SubfamilyID, self.RangeStart, self.RangeEnd)
|
||||
|
||||
|
||||
class BaseAxis(Statement):
|
||||
def __init__(self, location, bases, scripts, vertical):
|
||||
Statement.__init__(self, location)
|
||||
self.bases = bases
|
||||
self.scripts = scripts
|
||||
self.vertical = vertical
|
||||
|
||||
def build(self, builder):
|
||||
builder.set_base_axis(self.bases, self.scripts, self.vertical)
|
||||
|
@ -44,6 +44,9 @@ class Builder(object):
|
||||
self.fontRevision_ = None # 2.71
|
||||
# for table 'name'
|
||||
self.names_ = []
|
||||
# for table 'BASE'
|
||||
self.base_horiz_axis_ = None
|
||||
self.base_vert_axis_ = None
|
||||
# for table 'GDEF'
|
||||
self.attachPoints_ = {} # "a" --> {3, 7}
|
||||
self.ligCaretCoords_ = {} # "f_f_i" --> {300, 600}
|
||||
@ -73,6 +76,11 @@ class Builder(object):
|
||||
self.font["GDEF"] = gdef
|
||||
elif "GDEF" in self.font:
|
||||
del self.font["GDEF"]
|
||||
base = self.buildBASE()
|
||||
if base:
|
||||
self.font["BASE"] = base
|
||||
elif "BASE" in self.font:
|
||||
del self.font["BASE"]
|
||||
|
||||
def get_chained_lookup_(self, location, builder_class):
|
||||
result = builder_class(self.font, location)
|
||||
@ -204,6 +212,46 @@ class Builder(object):
|
||||
nameID = self.featureNames_ids_[tag]
|
||||
table.setName(string, nameID, platformID, platEncID, langID)
|
||||
|
||||
def buildBASE(self):
|
||||
if not self.base_horiz_axis_ and not self.base_vert_axis_:
|
||||
return None
|
||||
base = otTables.BASE()
|
||||
base.Version = 0x00010000
|
||||
base.HorizAxis = self.buildBASEAxis(self.base_horiz_axis_)
|
||||
base.VertAxis = self.buildBASEAxis(self.base_vert_axis_)
|
||||
|
||||
result = getTableClass("BASE")()
|
||||
result.table = base
|
||||
return result
|
||||
|
||||
def buildBASEAxis(self, axis):
|
||||
if not axis:
|
||||
return
|
||||
bases, scripts = axis
|
||||
axis = otTables.Axis()
|
||||
axis.BaseTagList = otTables.BaseTagList()
|
||||
axis.BaseTagList.BaselineTag = bases
|
||||
axis.BaseTagList.BaseTagCount = len(bases)
|
||||
axis.BaseScriptList = otTables.BaseScriptList()
|
||||
axis.BaseScriptList.BaseScriptRecord = []
|
||||
axis.BaseScriptList.BaseScriptCount = len(scripts)
|
||||
for script in sorted(scripts):
|
||||
record = otTables.BaseScriptRecord()
|
||||
record.BaseScriptTag = script[0]
|
||||
record.BaseScript = otTables.BaseScript()
|
||||
record.BaseScript.BaseLangSysCount = 0
|
||||
record.BaseScript.BaseValues = otTables.BaseValues()
|
||||
record.BaseScript.BaseValues.DefaultIndex = bases.index(script[1])
|
||||
record.BaseScript.BaseValues.BaseCoord = []
|
||||
record.BaseScript.BaseValues.BaseCoordCount = len(script[2])
|
||||
for c in script[2]:
|
||||
coord = otTables.BaseCoord()
|
||||
coord.Format = 1
|
||||
coord.Coordinate = c
|
||||
record.BaseScript.BaseValues.BaseCoord.append(coord)
|
||||
axis.BaseScriptList.BaseScriptRecord.append(record)
|
||||
return axis
|
||||
|
||||
def buildGDEF(self):
|
||||
gdef = otTables.GDEF()
|
||||
gdef.GlyphClassDef = self.buildGDEFGlyphClassDef_()
|
||||
@ -566,6 +614,12 @@ class Builder(object):
|
||||
def add_featureName(self, location, tag):
|
||||
self.featureNames_.append(tag)
|
||||
|
||||
def set_base_axis(self, bases, scripts, vertical):
|
||||
if vertical:
|
||||
self.base_vert_axis_ = (bases, scripts)
|
||||
else:
|
||||
self.base_horiz_axis_ = (bases, scripts)
|
||||
|
||||
def set_size_parameters(self, location, DesignSize, SubfamilyID,
|
||||
RangeStart, RangeEnd):
|
||||
if self.cur_feature_name_ != 'size':
|
||||
|
@ -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
|
||||
spec9b spec9c1 spec9c2 spec9c3 spec9e
|
||||
spec9a spec9b spec9c1 spec9c2 spec9c3 spec9e
|
||||
bug453 bug463 bug501 bug502 bug505 bug506 bug509 bug512
|
||||
name size size2
|
||||
""".split()
|
||||
@ -103,7 +103,8 @@ class BuilderTest(unittest.TestCase):
|
||||
|
||||
def expect_ttx(self, font, expected_ttx):
|
||||
path = self.temp_path(suffix=".ttx")
|
||||
font.saveXML(path, tables=['head', 'name', 'GDEF', 'GSUB', 'GPOS'])
|
||||
font.saveXML(path, tables=['head', 'name', 'BASE', 'GDEF', 'GSUB',
|
||||
'GPOS'])
|
||||
actual = self.read_ttx(path)
|
||||
expected = self.read_ttx(expected_ttx)
|
||||
if actual != expected:
|
||||
|
@ -695,6 +695,7 @@ class Parser(object):
|
||||
"GDEF": self.parse_table_GDEF_,
|
||||
"head": self.parse_table_head_,
|
||||
"name": self.parse_table_name_,
|
||||
"BASE": self.parse_table_BASE_,
|
||||
}.get(name)
|
||||
if handler:
|
||||
handler(table)
|
||||
@ -810,6 +811,52 @@ class Parser(object):
|
||||
|
||||
return re.sub(r'\\[0-9a-zAZ]{4}', unescape, string)
|
||||
|
||||
def parse_table_BASE_(self, table):
|
||||
statements = table.statements
|
||||
while self.next_token_ != "}":
|
||||
self.advance_lexer_()
|
||||
if self.is_cur_keyword_("HorizAxis.BaseTagList"):
|
||||
horiz_bases = self.parse_base_tag_list_()
|
||||
elif self.is_cur_keyword_("HorizAxis.BaseScriptList"):
|
||||
horiz_scripts = self.parse_base_script_list_(len(horiz_bases))
|
||||
statements.append(
|
||||
ast.BaseAxis(self.cur_token_location_, horiz_bases,
|
||||
horiz_scripts, False))
|
||||
elif self.is_cur_keyword_("VertAxis.BaseTagList"):
|
||||
vert_bases = self.parse_base_tag_list_()
|
||||
elif self.is_cur_keyword_("VertAxis.BaseScriptList"):
|
||||
vert_scripts = self.parse_base_script_list_(len(vert_bases))
|
||||
statements.append(
|
||||
ast.BaseAxis(self.cur_token_location_, vert_bases,
|
||||
vert_scripts, True))
|
||||
elif self.cur_token_ == ";":
|
||||
continue
|
||||
|
||||
def parse_base_tag_list_(self):
|
||||
assert self.cur_token_ in ("HorizAxis.BaseTagList",
|
||||
"VertAxis.BaseTagList"), self.cur_token_
|
||||
bases = []
|
||||
while self.next_token_ != ";":
|
||||
bases.append(self.expect_script_tag_())
|
||||
self.expect_symbol_(";")
|
||||
return bases
|
||||
|
||||
def parse_base_script_list_(self, count):
|
||||
assert self.cur_token_ in ("HorizAxis.BaseScriptList",
|
||||
"VertAxis.BaseScriptList"), self.cur_token_
|
||||
scripts = [(self.parse_base_script_record_(count))]
|
||||
while self.next_token_ == ",":
|
||||
self.expect_symbol_(",")
|
||||
scripts.append(self.parse_base_script_record_(count))
|
||||
self.expect_symbol_(";")
|
||||
return scripts
|
||||
|
||||
def parse_base_script_record_(self, count):
|
||||
script_tag = self.expect_script_tag_()
|
||||
base_tag = self.expect_script_tag_()
|
||||
coords = [self.expect_number_() for i in range(count)]
|
||||
return script_tag, base_tag, coords
|
||||
|
||||
def parse_device_(self):
|
||||
result = None
|
||||
self.expect_symbol_("<")
|
||||
|
6
Lib/fontTools/feaLib/testdata/spec9a.fea
vendored
Normal file
6
Lib/fontTools/feaLib/testdata/spec9a.fea
vendored
Normal file
@ -0,0 +1,6 @@
|
||||
table BASE {
|
||||
HorizAxis.BaseTagList ideo romn;
|
||||
HorizAxis.BaseScriptList latn romn -120 0, cyrl romn -120 0,
|
||||
grek romn -120 0, hani ideo -120 0,
|
||||
kana ideo -120 0, hang ideo -120 0;
|
||||
} BASE;
|
114
Lib/fontTools/feaLib/testdata/spec9a.ttx
vendored
Normal file
114
Lib/fontTools/feaLib/testdata/spec9a.ttx
vendored
Normal file
@ -0,0 +1,114 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ttFont>
|
||||
|
||||
<BASE>
|
||||
<Version value="1.0"/>
|
||||
<HorizAxis>
|
||||
<BaseTagList>
|
||||
<!-- BaseTagCount=2 -->
|
||||
<BaselineTag index="0" value="ideo"/>
|
||||
<BaselineTag index="1" value="romn"/>
|
||||
</BaseTagList>
|
||||
<BaseScriptList>
|
||||
<!-- BaseScriptCount=6 -->
|
||||
<BaseScriptRecord index="0">
|
||||
<BaseScriptTag value="cyrl"/>
|
||||
<BaseScript>
|
||||
<BaseValues>
|
||||
<DefaultIndex value="1"/>
|
||||
<!-- BaseCoordCount=2 -->
|
||||
<BaseCoord index="0" Format="1">
|
||||
<Coordinate value="-120"/>
|
||||
</BaseCoord>
|
||||
<BaseCoord index="1" Format="1">
|
||||
<Coordinate value="0"/>
|
||||
</BaseCoord>
|
||||
</BaseValues>
|
||||
<!-- BaseLangSysCount=0 -->
|
||||
</BaseScript>
|
||||
</BaseScriptRecord>
|
||||
<BaseScriptRecord index="1">
|
||||
<BaseScriptTag value="grek"/>
|
||||
<BaseScript>
|
||||
<BaseValues>
|
||||
<DefaultIndex value="1"/>
|
||||
<!-- BaseCoordCount=2 -->
|
||||
<BaseCoord index="0" Format="1">
|
||||
<Coordinate value="-120"/>
|
||||
</BaseCoord>
|
||||
<BaseCoord index="1" Format="1">
|
||||
<Coordinate value="0"/>
|
||||
</BaseCoord>
|
||||
</BaseValues>
|
||||
<!-- BaseLangSysCount=0 -->
|
||||
</BaseScript>
|
||||
</BaseScriptRecord>
|
||||
<BaseScriptRecord index="2">
|
||||
<BaseScriptTag value="hang"/>
|
||||
<BaseScript>
|
||||
<BaseValues>
|
||||
<DefaultIndex value="0"/>
|
||||
<!-- BaseCoordCount=2 -->
|
||||
<BaseCoord index="0" Format="1">
|
||||
<Coordinate value="-120"/>
|
||||
</BaseCoord>
|
||||
<BaseCoord index="1" Format="1">
|
||||
<Coordinate value="0"/>
|
||||
</BaseCoord>
|
||||
</BaseValues>
|
||||
<!-- BaseLangSysCount=0 -->
|
||||
</BaseScript>
|
||||
</BaseScriptRecord>
|
||||
<BaseScriptRecord index="3">
|
||||
<BaseScriptTag value="hani"/>
|
||||
<BaseScript>
|
||||
<BaseValues>
|
||||
<DefaultIndex value="0"/>
|
||||
<!-- BaseCoordCount=2 -->
|
||||
<BaseCoord index="0" Format="1">
|
||||
<Coordinate value="-120"/>
|
||||
</BaseCoord>
|
||||
<BaseCoord index="1" Format="1">
|
||||
<Coordinate value="0"/>
|
||||
</BaseCoord>
|
||||
</BaseValues>
|
||||
<!-- BaseLangSysCount=0 -->
|
||||
</BaseScript>
|
||||
</BaseScriptRecord>
|
||||
<BaseScriptRecord index="4">
|
||||
<BaseScriptTag value="kana"/>
|
||||
<BaseScript>
|
||||
<BaseValues>
|
||||
<DefaultIndex value="0"/>
|
||||
<!-- BaseCoordCount=2 -->
|
||||
<BaseCoord index="0" Format="1">
|
||||
<Coordinate value="-120"/>
|
||||
</BaseCoord>
|
||||
<BaseCoord index="1" Format="1">
|
||||
<Coordinate value="0"/>
|
||||
</BaseCoord>
|
||||
</BaseValues>
|
||||
<!-- BaseLangSysCount=0 -->
|
||||
</BaseScript>
|
||||
</BaseScriptRecord>
|
||||
<BaseScriptRecord index="5">
|
||||
<BaseScriptTag value="latn"/>
|
||||
<BaseScript>
|
||||
<BaseValues>
|
||||
<DefaultIndex value="1"/>
|
||||
<!-- BaseCoordCount=2 -->
|
||||
<BaseCoord index="0" Format="1">
|
||||
<Coordinate value="-120"/>
|
||||
</BaseCoord>
|
||||
<BaseCoord index="1" Format="1">
|
||||
<Coordinate value="0"/>
|
||||
</BaseCoord>
|
||||
</BaseValues>
|
||||
<!-- BaseLangSysCount=0 -->
|
||||
</BaseScript>
|
||||
</BaseScriptRecord>
|
||||
</BaseScriptList>
|
||||
</HorizAxis>
|
||||
</BASE>
|
||||
|
||||
</ttFont>
|
Loading…
x
Reference in New Issue
Block a user