black
This commit is contained in:
parent
29ff42d15f
commit
9aeb48286d
@ -84,7 +84,6 @@ def deviceToString(device):
|
||||
return "<device %s>" % ", ".join("%d %d" % t for t in device)
|
||||
|
||||
|
||||
|
||||
fea_keywords = set(
|
||||
[
|
||||
"anchor",
|
||||
@ -260,7 +259,7 @@ class GlyphClass(Expression):
|
||||
|
||||
def add_range(self, start, end, glyphs):
|
||||
"""Add a range (e.g. ``A-Z``) to the class. ``start`` and ``end``
|
||||
are either :class:`GlyphName` objects or strings representing the
|
||||
are either :class:`GlyphName` objects or strings representing the
|
||||
start and end glyphs in the class, and ``glyphs`` is the full list of
|
||||
:class:`GlyphName` objects in the range."""
|
||||
if self.curr < len(self.glyphs):
|
||||
@ -555,7 +554,7 @@ class MarkClass(object):
|
||||
|
||||
|
||||
class MarkClassDefinition(Statement):
|
||||
"""A single ``markClass`` statement. The ``markClass`` should be a
|
||||
"""A single ``markClass`` statement. The ``markClass`` should be a
|
||||
:class:`MarkClass` object, the ``anchor`` an :class:`Anchor` object,
|
||||
and the ``glyphs`` parameter should be a `glyph-containing object`_ .
|
||||
|
||||
@ -857,7 +856,7 @@ class IgnorePosStatement(Statement):
|
||||
"""An ``ignore pos`` statement, containing `one or more` contexts to ignore.
|
||||
|
||||
``chainContexts`` should be a list of ``(prefix, glyphs, suffix)`` tuples,
|
||||
with each of ``prefix``, ``glyphs`` and ``suffix`` being
|
||||
with each of ``prefix``, ``glyphs`` and ``suffix`` being
|
||||
`glyph-containing objects`_ ."""
|
||||
|
||||
def __init__(self, chainContexts, location=None):
|
||||
@ -1173,7 +1172,7 @@ class MarkLigPosStatement(Statement):
|
||||
# ... add definitions to mark classes...
|
||||
|
||||
glyph = GlyphName("lam_meem_jeem")
|
||||
marks = [
|
||||
marks = [
|
||||
[ (Anchor(625,1800), m1) ], # Attachments on 1st component (lam)
|
||||
[ (Anchor(376,-378), m2) ], # Attachments on 2nd component (meem)
|
||||
[ ] # No attachments on the jeem
|
||||
@ -1910,6 +1909,7 @@ class STATDesignAxisStatement(Statement):
|
||||
axisOrder (int): an int
|
||||
names (list): a list of :class:`STATNameStatement` objects
|
||||
"""
|
||||
|
||||
def __init__(self, tag, axisOrder, names, location=None):
|
||||
Statement.__init__(self, location)
|
||||
self.tag = tag
|
||||
@ -1923,8 +1923,7 @@ class STATDesignAxisStatement(Statement):
|
||||
def asFea(self, indent=""):
|
||||
indent += SHIFT
|
||||
res = f"DesignAxis {self.tag} {self.axisOrder} {{ \n"
|
||||
res += ("\n" + indent).join([s.asFea(indent=indent) for s in
|
||||
self.names]) + "\n"
|
||||
res += ("\n" + indent).join([s.asFea(indent=indent) for s in self.names]) + "\n"
|
||||
res += "};"
|
||||
return res
|
||||
|
||||
@ -1935,6 +1934,7 @@ class ElidedFallbackName(Statement):
|
||||
Args:
|
||||
names: a list of :class:`STATNameStatement` objects
|
||||
"""
|
||||
|
||||
def __init__(self, names, location=None):
|
||||
Statement.__init__(self, location)
|
||||
self.names = names
|
||||
@ -1946,8 +1946,7 @@ class ElidedFallbackName(Statement):
|
||||
def asFea(self, indent=""):
|
||||
indent += SHIFT
|
||||
res = "ElidedFallbackName { \n"
|
||||
res += ("\n" + indent).join([s.asFea(indent=indent) for s in
|
||||
self.names]) + "\n"
|
||||
res += ("\n" + indent).join([s.asFea(indent=indent) for s in self.names]) + "\n"
|
||||
res += "};"
|
||||
return res
|
||||
|
||||
@ -1958,6 +1957,7 @@ class ElidedFallbackNameID(Statement):
|
||||
Args:
|
||||
value: an int pointing to an existing name table name ID
|
||||
"""
|
||||
|
||||
def __init__(self, value, location=None):
|
||||
Statement.__init__(self, location)
|
||||
self.value = value
|
||||
@ -1978,6 +1978,7 @@ class STATAxisValueStatement(Statement):
|
||||
locations (list): a list of :class:`AxisValueLocationStatement` objects
|
||||
flags (int): an int
|
||||
"""
|
||||
|
||||
def __init__(self, names, locations, flags, location=None):
|
||||
Statement.__init__(self, location)
|
||||
self.names = names
|
||||
@ -2017,6 +2018,7 @@ class AxisValueLocationStatement(Statement):
|
||||
tag (str): a 4 letter axis tag
|
||||
values (list): a list of ints and/or floats
|
||||
"""
|
||||
|
||||
def __init__(self, tag, values, location=None):
|
||||
Statement.__init__(self, location)
|
||||
self.tag = tag
|
||||
|
@ -551,11 +551,13 @@ class Builder(object):
|
||||
self.stat_["AxisValueRecords"] = []
|
||||
# Check for duplicate AxisValueRecords
|
||||
for record_ in self.stat_["AxisValueRecords"]:
|
||||
if ({n.asFea() for n in record_.names} ==
|
||||
{n.asFea() for n in axisValueRecord.names} and
|
||||
{n.asFea() for n in record_.locations} ==
|
||||
{n.asFea() for n in axisValueRecord.locations}
|
||||
and record_.flags == axisValueRecord.flags):
|
||||
if (
|
||||
{n.asFea() for n in record_.names}
|
||||
== {n.asFea() for n in axisValueRecord.names}
|
||||
and {n.asFea() for n in record_.locations}
|
||||
== {n.asFea() for n in axisValueRecord.locations}
|
||||
and record_.flags == axisValueRecord.flags
|
||||
):
|
||||
raise FeatureLibError(
|
||||
"An AxisValueRecord with these values is already defined.",
|
||||
location,
|
||||
@ -568,7 +570,7 @@ class Builder(object):
|
||||
|
||||
axes = self.stat_.get("DesignAxes")
|
||||
if not axes:
|
||||
raise FeatureLibError('DesignAxes not defined', None)
|
||||
raise FeatureLibError("DesignAxes not defined", None)
|
||||
axisValueRecords = self.stat_.get("AxisValueRecords")
|
||||
axisValues = {}
|
||||
format4_locations = []
|
||||
@ -578,52 +580,74 @@ class Builder(object):
|
||||
for avr in axisValueRecords:
|
||||
valuesDict = {}
|
||||
if avr.flags > 0:
|
||||
valuesDict['flags'] = avr.flags
|
||||
valuesDict["flags"] = avr.flags
|
||||
if len(avr.locations) == 1:
|
||||
location = avr.locations[0]
|
||||
values = location.values
|
||||
if len(values) == 1: #format1
|
||||
valuesDict.update({'value': values[0],'name': avr.names})
|
||||
if len(values) == 2: #format3
|
||||
valuesDict.update({ 'value': values[0],
|
||||
'linkedValue': values[1],
|
||||
'name': avr.names})
|
||||
if len(values) == 3: #format2
|
||||
if len(values) == 1: # format1
|
||||
valuesDict.update({"value": values[0], "name": avr.names})
|
||||
if len(values) == 2: # format3
|
||||
valuesDict.update(
|
||||
{
|
||||
"value": values[0],
|
||||
"linkedValue": values[1],
|
||||
"name": avr.names,
|
||||
}
|
||||
)
|
||||
if len(values) == 3: # format2
|
||||
nominal, minVal, maxVal = values
|
||||
valuesDict.update({ 'nominalValue': nominal,
|
||||
'rangeMinValue': minVal,
|
||||
'rangeMaxValue': maxVal,
|
||||
'name': avr.names})
|
||||
valuesDict.update(
|
||||
{
|
||||
"nominalValue": nominal,
|
||||
"rangeMinValue": minVal,
|
||||
"rangeMaxValue": maxVal,
|
||||
"name": avr.names,
|
||||
}
|
||||
)
|
||||
axisValues[location.tag].append(valuesDict)
|
||||
else:
|
||||
valuesDict.update({"location": {i.tag: i.values[0]
|
||||
for i in avr.locations},
|
||||
"name": avr.names})
|
||||
valuesDict.update(
|
||||
{
|
||||
"location": {i.tag: i.values[0] for i in avr.locations},
|
||||
"name": avr.names,
|
||||
}
|
||||
)
|
||||
format4_locations.append(valuesDict)
|
||||
|
||||
designAxes = [{"ordering": a.axisOrder,
|
||||
"tag": a.tag,
|
||||
"name": a.names,
|
||||
'values': axisValues[a.tag]} for a in axes]
|
||||
|
||||
designAxes = [
|
||||
{
|
||||
"ordering": a.axisOrder,
|
||||
"tag": a.tag,
|
||||
"name": a.names,
|
||||
"values": axisValues[a.tag],
|
||||
}
|
||||
for a in axes
|
||||
]
|
||||
|
||||
nameTable = self.font.get("name")
|
||||
if not nameTable: # this only happens for unit tests
|
||||
nameTable = self.font["name"] = newTable("name")
|
||||
nameTable.names = []
|
||||
|
||||
if "ElidedFallbackNameID" in self.stat_:
|
||||
nameID = self.stat_["ElidedFallbackNameID"]
|
||||
name = nameTable.getDebugName(nameID)
|
||||
nameID = self.stat_["ElidedFallbackNameID"]
|
||||
name = nameTable.getDebugName(nameID)
|
||||
if not name:
|
||||
raise FeatureLibError(f'ElidedFallbackNameID {nameID} points '
|
||||
'to a nameID that does not exist in the '
|
||||
'"name" table', None)
|
||||
raise FeatureLibError(
|
||||
f"ElidedFallbackNameID {nameID} points "
|
||||
"to a nameID that does not exist in the "
|
||||
'"name" table',
|
||||
None,
|
||||
)
|
||||
elif "ElidedFallbackName" in self.stat_:
|
||||
nameID = self.stat_["ElidedFallbackName"]
|
||||
|
||||
otl.buildStatTable(self.font, designAxes, locations=format4_locations,
|
||||
elidedFallbackName=nameID)
|
||||
nameID = self.stat_["ElidedFallbackName"]
|
||||
|
||||
otl.buildStatTable(
|
||||
self.font,
|
||||
designAxes,
|
||||
locations=format4_locations,
|
||||
elidedFallbackName=nameID,
|
||||
)
|
||||
|
||||
def build_codepages_(self, pages):
|
||||
pages2bits = {
|
||||
@ -833,8 +857,10 @@ class Builder(object):
|
||||
str(ix)
|
||||
]._replace(feature=key)
|
||||
except KeyError:
|
||||
warnings.warn("feaLib.Builder subclass needs upgrading to "
|
||||
"stash debug information. See fonttools#2065.")
|
||||
warnings.warn(
|
||||
"feaLib.Builder subclass needs upgrading to "
|
||||
"stash debug information. See fonttools#2065."
|
||||
)
|
||||
|
||||
feature_key = (feature_tag, lookup_indices)
|
||||
feature_index = feature_indices.get(feature_key)
|
||||
|
@ -1322,32 +1322,36 @@ class Parser(object):
|
||||
if self.is_cur_keyword_("name"):
|
||||
platformID, platEncID, langID, string = self.parse_stat_name_()
|
||||
nameRecord = self.ast.STATNameStatement(
|
||||
"stat", platformID, platEncID, langID, string,
|
||||
location=self.cur_token_location_
|
||||
"stat",
|
||||
platformID,
|
||||
platEncID,
|
||||
langID,
|
||||
string,
|
||||
location=self.cur_token_location_,
|
||||
)
|
||||
names.append(nameRecord)
|
||||
else:
|
||||
if self.cur_token_ != ";":
|
||||
raise FeatureLibError(f"Unexpected token {self.cur_token_} "
|
||||
f"in ElidedFallbackName",
|
||||
self.cur_token_location_)
|
||||
raise FeatureLibError(
|
||||
f"Unexpected token {self.cur_token_} " f"in ElidedFallbackName",
|
||||
self.cur_token_location_,
|
||||
)
|
||||
self.expect_symbol_("}")
|
||||
if not names:
|
||||
raise FeatureLibError('Expected "name"',
|
||||
self.cur_token_location_)
|
||||
raise FeatureLibError('Expected "name"', self.cur_token_location_)
|
||||
return names
|
||||
|
||||
def parse_STAT_design_axis(self):
|
||||
assert self.is_cur_keyword_('DesignAxis')
|
||||
assert self.is_cur_keyword_("DesignAxis")
|
||||
names = []
|
||||
axisTag = self.expect_tag_()
|
||||
if (axisTag not in ('ital', 'opsz', 'slnt', 'wdth', 'wght')
|
||||
and not axisTag.isupper()):
|
||||
log.warning(
|
||||
f'Unregistered axis tag {axisTag} should be uppercase.'
|
||||
)
|
||||
if (
|
||||
axisTag not in ("ital", "opsz", "slnt", "wdth", "wght")
|
||||
and not axisTag.isupper()
|
||||
):
|
||||
log.warning(f"Unregistered axis tag {axisTag} should be uppercase.")
|
||||
axisOrder = self.expect_number_()
|
||||
self.expect_symbol_('{')
|
||||
self.expect_symbol_("{")
|
||||
while self.next_token_ != "}" or self.cur_comments_:
|
||||
self.advance_lexer_()
|
||||
if self.cur_token_type_ is Lexer.COMMENT:
|
||||
@ -1362,11 +1366,14 @@ class Parser(object):
|
||||
elif self.cur_token_ == ";":
|
||||
continue
|
||||
else:
|
||||
raise FeatureLibError(f'Expected "name", got {self.cur_token_}',
|
||||
self.cur_token_location_)
|
||||
raise FeatureLibError(
|
||||
f'Expected "name", got {self.cur_token_}', self.cur_token_location_
|
||||
)
|
||||
|
||||
self.expect_symbol_("}")
|
||||
return self.ast.STATDesignAxisStatement(axisTag, axisOrder, names, self.cur_token_location_)
|
||||
return self.ast.STATDesignAxisStatement(
|
||||
axisTag, axisOrder, names, self.cur_token_location_
|
||||
)
|
||||
|
||||
def parse_STAT_axis_value_(self):
|
||||
assert self.is_cur_keyword_("AxisValue")
|
||||
@ -1393,39 +1400,45 @@ class Parser(object):
|
||||
elif self.cur_token_ == ";":
|
||||
continue
|
||||
else:
|
||||
raise FeatureLibError(f"Unexpected token {self.cur_token_} "
|
||||
f"in AxisValue", self.cur_token_location_)
|
||||
raise FeatureLibError(
|
||||
f"Unexpected token {self.cur_token_} " f"in AxisValue",
|
||||
self.cur_token_location_,
|
||||
)
|
||||
self.expect_symbol_("}")
|
||||
if not names:
|
||||
raise FeatureLibError('Expected "Axis Name"',
|
||||
self.cur_token_location_)
|
||||
raise FeatureLibError('Expected "Axis Name"', self.cur_token_location_)
|
||||
if not locations:
|
||||
raise FeatureLibError('Expected "Axis location"',
|
||||
self.cur_token_location_)
|
||||
raise FeatureLibError('Expected "Axis location"', self.cur_token_location_)
|
||||
if len(locations) > 1:
|
||||
for location in locations:
|
||||
if len(location.values) > 1:
|
||||
raise FeatureLibError("Only one value is allowed in a "
|
||||
"Format 4 Axis Value Record, but "
|
||||
f"{len(location.values)} were found.",
|
||||
self.cur_token_location_)
|
||||
raise FeatureLibError(
|
||||
"Only one value is allowed in a "
|
||||
"Format 4 Axis Value Record, but "
|
||||
f"{len(location.values)} were found.",
|
||||
self.cur_token_location_,
|
||||
)
|
||||
format4_tags = []
|
||||
for location in locations:
|
||||
tag = location.tag
|
||||
if tag in format4_tags:
|
||||
raise FeatureLibError(f"Axis tag {tag} already "
|
||||
"defined.",
|
||||
self.cur_token_location_)
|
||||
raise FeatureLibError(
|
||||
f"Axis tag {tag} already " "defined.", self.cur_token_location_
|
||||
)
|
||||
format4_tags.append(tag)
|
||||
|
||||
return self.ast.STATAxisValueStatement(names, locations, flags, self.cur_token_location_)
|
||||
return self.ast.STATAxisValueStatement(
|
||||
names, locations, flags, self.cur_token_location_
|
||||
)
|
||||
|
||||
def parse_STAT_location(self):
|
||||
values = []
|
||||
tag = self.expect_tag_()
|
||||
if len(tag.strip()) != 4:
|
||||
raise FeatureLibError(f"Axis tag {self.cur_token_} must be 4 "
|
||||
"characters", self.cur_token_location_)
|
||||
raise FeatureLibError(
|
||||
f"Axis tag {self.cur_token_} must be 4 " "characters",
|
||||
self.cur_token_location_,
|
||||
)
|
||||
|
||||
while self.next_token_ != ";":
|
||||
if self.next_token_type_ is Lexer.FLOAT:
|
||||
@ -1435,16 +1448,20 @@ class Parser(object):
|
||||
value = self.expect_number_()
|
||||
values.append(value)
|
||||
else:
|
||||
raise FeatureLibError(f'Unexpected value "{self.next_token_}". '
|
||||
'Expected integer or float.',
|
||||
self.next_token_location_)
|
||||
raise FeatureLibError(
|
||||
f'Unexpected value "{self.next_token_}". '
|
||||
"Expected integer or float.",
|
||||
self.next_token_location_,
|
||||
)
|
||||
if len(values) == 3:
|
||||
nominal, min_val, max_val = values
|
||||
if nominal < min_val or nominal > max_val:
|
||||
raise FeatureLibError(f'Default value {nominal} is outside '
|
||||
f'of specified range '
|
||||
f'{min_val}-{max_val}.',
|
||||
self.next_token_location_)
|
||||
raise FeatureLibError(
|
||||
f"Default value {nominal} is outside "
|
||||
f"of specified range "
|
||||
f"{min_val}-{max_val}.",
|
||||
self.next_token_location_,
|
||||
)
|
||||
return self.ast.AxisValueLocationStatement(tag, values)
|
||||
|
||||
def parse_table_STAT_(self, table):
|
||||
@ -1475,14 +1492,16 @@ class Parser(object):
|
||||
if location.tag not in design_axes:
|
||||
# Tag must be defined in a DesignAxis before it
|
||||
# can be referenced
|
||||
raise FeatureLibError("DesignAxis not defined for "
|
||||
f"{location.tag}.",
|
||||
self.cur_token_location_)
|
||||
raise FeatureLibError(
|
||||
"DesignAxis not defined for " f"{location.tag}.",
|
||||
self.cur_token_location_,
|
||||
)
|
||||
statements.append(axisValueRecord)
|
||||
self.expect_symbol_(";")
|
||||
else:
|
||||
raise FeatureLibError(f"Unexpected token {self.cur_token_}",
|
||||
self.cur_token_location_)
|
||||
raise FeatureLibError(
|
||||
f"Unexpected token {self.cur_token_}", self.cur_token_location_
|
||||
)
|
||||
elif self.cur_token_ == ";":
|
||||
continue
|
||||
|
||||
@ -2056,8 +2075,7 @@ class Parser(object):
|
||||
return self.expect_number_() / 10
|
||||
else:
|
||||
raise FeatureLibError(
|
||||
"Expected an integer or floating-point number",
|
||||
self.cur_token_location_
|
||||
"Expected an integer or floating-point number", self.cur_token_location_
|
||||
)
|
||||
|
||||
def expect_stat_flags(self):
|
||||
@ -2072,8 +2090,7 @@ class Parser(object):
|
||||
value = value | flags[name]
|
||||
else:
|
||||
raise FeatureLibError(
|
||||
f"Unexpected STAT flag {self.cur_token_}",
|
||||
self.cur_token_location_
|
||||
f"Unexpected STAT flag {self.cur_token_}", self.cur_token_location_
|
||||
)
|
||||
return value
|
||||
|
||||
@ -2084,8 +2101,7 @@ class Parser(object):
|
||||
return self.expect_number_()
|
||||
else:
|
||||
raise FeatureLibError(
|
||||
"Expected an integer or floating-point number",
|
||||
self.cur_token_location_
|
||||
"Expected an integer or floating-point number", self.cur_token_location_
|
||||
)
|
||||
|
||||
def expect_string_(self):
|
||||
|
@ -95,9 +95,10 @@ def buildLookup(subtables, flags=0, markFilterSet=None):
|
||||
subtables = [st for st in subtables if st is not None]
|
||||
if not subtables:
|
||||
return None
|
||||
assert all(t.LookupType == subtables[0].LookupType for t in subtables), (
|
||||
"all subtables must have the same LookupType; got %s"
|
||||
% repr([t.LookupType for t in subtables])
|
||||
assert all(
|
||||
t.LookupType == subtables[0].LookupType for t in subtables
|
||||
), "all subtables must have the same LookupType; got %s" % repr(
|
||||
[t.LookupType for t in subtables]
|
||||
)
|
||||
self = ot.Lookup()
|
||||
self.LookupType = subtables[0].LookupType
|
||||
@ -2576,7 +2577,9 @@ class ClassDefBuilder(object):
|
||||
self.classes_.add(glyphs)
|
||||
for glyph in glyphs:
|
||||
if glyph in self.glyphs_:
|
||||
raise OpenTypeLibError(f"Glyph {glyph} is already present in class.", None)
|
||||
raise OpenTypeLibError(
|
||||
f"Glyph {glyph} is already present in class.", None
|
||||
)
|
||||
self.glyphs_[glyph] = glyphs
|
||||
|
||||
def classes(self):
|
||||
@ -2688,7 +2691,7 @@ def buildStatTable(ttFont, axes, locations=None, elidedFallbackName=2):
|
||||
]
|
||||
|
||||
The optional 'elidedFallbackName' argument can be a name ID (int),
|
||||
a string, a dictionary containing multilingual names, or a list of
|
||||
a string, a dictionary containing multilingual names, or a list of
|
||||
STATNameStatements. It translates to the ElidedFallbackNameID field.
|
||||
|
||||
The 'ttFont' argument must be a TTFont instance that already has a
|
||||
@ -2802,9 +2805,13 @@ def _addName(nameTable, value, minNameID=0):
|
||||
nameID = nameTable._findUnusedNameID()
|
||||
for nameRecord in value:
|
||||
if isinstance(nameRecord, STATNameStatement):
|
||||
nameTable.setName(nameRecord.string,
|
||||
nameID,nameRecord.platformID,
|
||||
nameRecord.platEncID,nameRecord.langID)
|
||||
nameTable.setName(
|
||||
nameRecord.string,
|
||||
nameID,
|
||||
nameRecord.platformID,
|
||||
nameRecord.platEncID,
|
||||
nameRecord.langID,
|
||||
)
|
||||
else:
|
||||
raise TypeError("value must be a list of STATNameStatements")
|
||||
return nameID
|
||||
|
Loading…
x
Reference in New Issue
Block a user