fonttools 4.56.0__cp313-cp313-win_amd64.whl → 4.58.0__cp313-cp313-win_amd64.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of fonttools might be problematic. Click here for more details.
- fontTools/__init__.py +1 -1
- fontTools/cffLib/__init__.py +61 -26
- fontTools/config/__init__.py +15 -0
- fontTools/cu2qu/cu2qu.c +15345 -14829
- fontTools/cu2qu/cu2qu.cp313-win_amd64.pyd +0 -0
- fontTools/designspaceLib/statNames.py +14 -7
- fontTools/feaLib/ast.py +92 -13
- fontTools/feaLib/builder.py +52 -13
- fontTools/feaLib/lexer.c +17143 -17986
- fontTools/feaLib/lexer.cp313-win_amd64.pyd +0 -0
- fontTools/feaLib/parser.py +59 -39
- fontTools/fontBuilder.py +6 -0
- fontTools/misc/bezierTools.c +39936 -41831
- fontTools/misc/bezierTools.cp313-win_amd64.pyd +0 -0
- fontTools/misc/etree.py +4 -27
- fontTools/misc/testTools.py +2 -1
- fontTools/mtiLib/__init__.py +0 -2
- fontTools/otlLib/builder.py +195 -145
- fontTools/otlLib/optimize/gpos.py +49 -63
- fontTools/pens/momentsPen.c +13266 -13448
- fontTools/pens/momentsPen.cp313-win_amd64.pyd +0 -0
- fontTools/pens/pointPen.py +21 -12
- fontTools/qu2cu/qu2cu.c +16538 -16269
- fontTools/qu2cu/qu2cu.cp313-win_amd64.pyd +0 -0
- fontTools/subset/__init__.py +11 -0
- fontTools/ttLib/__init__.py +4 -0
- fontTools/ttLib/__main__.py +47 -8
- fontTools/ttLib/tables/D__e_b_g.py +20 -2
- fontTools/ttLib/tables/G_V_A_R_.py +5 -0
- fontTools/ttLib/tables/T_S_I__0.py +14 -3
- fontTools/ttLib/tables/T_S_I__5.py +16 -5
- fontTools/ttLib/tables/__init__.py +1 -0
- fontTools/ttLib/tables/_c_m_a_p.py +19 -6
- fontTools/ttLib/tables/_c_v_t.py +2 -0
- fontTools/ttLib/tables/_f_p_g_m.py +3 -1
- fontTools/ttLib/tables/_g_l_y_f.py +11 -10
- fontTools/ttLib/tables/_g_v_a_r.py +62 -17
- fontTools/ttLib/tables/_p_o_s_t.py +5 -2
- fontTools/ttLib/tables/otBase.py +1 -0
- fontTools/ttLib/tables/otConverters.py +5 -2
- fontTools/ttLib/tables/otTables.py +5 -1
- fontTools/ttLib/ttFont.py +3 -5
- fontTools/ttLib/ttGlyphSet.py +0 -10
- fontTools/ttx.py +13 -1
- fontTools/ufoLib/__init__.py +2 -2
- fontTools/ufoLib/converters.py +89 -25
- fontTools/ufoLib/errors.py +8 -0
- fontTools/ufoLib/etree.py +1 -1
- fontTools/ufoLib/filenames.py +155 -100
- fontTools/ufoLib/glifLib.py +9 -2
- fontTools/ufoLib/kerning.py +66 -36
- fontTools/ufoLib/utils.py +5 -2
- fontTools/unicodedata/Mirrored.py +446 -0
- fontTools/unicodedata/__init__.py +6 -2
- fontTools/varLib/__init__.py +94 -89
- fontTools/varLib/hvar.py +113 -0
- fontTools/varLib/iup.c +19630 -19154
- fontTools/varLib/iup.cp313-win_amd64.pyd +0 -0
- fontTools/varLib/varStore.py +1 -1
- fontTools/voltLib/__main__.py +206 -0
- fontTools/voltLib/ast.py +4 -0
- fontTools/voltLib/parser.py +16 -8
- fontTools/voltLib/voltToFea.py +347 -166
- {fonttools-4.56.0.dist-info → fonttools-4.58.0.dist-info}/METADATA +60 -12
- {fonttools-4.56.0.dist-info → fonttools-4.58.0.dist-info}/RECORD +71 -66
- {fonttools-4.56.0.dist-info → fonttools-4.58.0.dist-info}/WHEEL +1 -1
- fonttools-4.58.0.dist-info/licenses/LICENSE.external +359 -0
- {fonttools-4.56.0.data → fonttools-4.58.0.data}/data/share/man/man1/ttx.1 +0 -0
- {fonttools-4.56.0.dist-info → fonttools-4.58.0.dist-info}/entry_points.txt +0 -0
- {fonttools-4.56.0.dist-info → fonttools-4.58.0.dist-info/licenses}/LICENSE +0 -0
- {fonttools-4.56.0.dist-info → fonttools-4.58.0.dist-info}/top_level.txt +0 -0
|
Binary file
|
fontTools/feaLib/parser.py
CHANGED
|
@@ -1286,6 +1286,19 @@ class Parser(object):
|
|
|
1286
1286
|
n = match.group(0)[1:]
|
|
1287
1287
|
return bytechr(int(n, 16)).decode(encoding)
|
|
1288
1288
|
|
|
1289
|
+
def find_previous(self, statements, class_):
|
|
1290
|
+
for previous in reversed(statements):
|
|
1291
|
+
if isinstance(previous, self.ast.Comment):
|
|
1292
|
+
continue
|
|
1293
|
+
elif isinstance(previous, class_):
|
|
1294
|
+
return previous
|
|
1295
|
+
else:
|
|
1296
|
+
# If we find something that doesn't match what we're looking
|
|
1297
|
+
# for, and isn't a comment, fail
|
|
1298
|
+
return None
|
|
1299
|
+
# Out of statements to look at
|
|
1300
|
+
return None
|
|
1301
|
+
|
|
1289
1302
|
def parse_table_BASE_(self, table):
|
|
1290
1303
|
statements = table.statements
|
|
1291
1304
|
while self.next_token_ != "}" or self.cur_comments_:
|
|
@@ -1306,6 +1319,19 @@ class Parser(object):
|
|
|
1306
1319
|
location=self.cur_token_location_,
|
|
1307
1320
|
)
|
|
1308
1321
|
)
|
|
1322
|
+
elif self.is_cur_keyword_("HorizAxis.MinMax"):
|
|
1323
|
+
base_script_list = self.find_previous(statements, ast.BaseAxis)
|
|
1324
|
+
if base_script_list is None:
|
|
1325
|
+
raise FeatureLibError(
|
|
1326
|
+
"MinMax must be preceded by BaseScriptList",
|
|
1327
|
+
self.cur_token_location_,
|
|
1328
|
+
)
|
|
1329
|
+
if base_script_list.vertical:
|
|
1330
|
+
raise FeatureLibError(
|
|
1331
|
+
"HorizAxis.MinMax must be preceded by HorizAxis statements",
|
|
1332
|
+
self.cur_token_location_,
|
|
1333
|
+
)
|
|
1334
|
+
base_script_list.minmax.append(self.parse_base_minmax_())
|
|
1309
1335
|
elif self.is_cur_keyword_("VertAxis.BaseTagList"):
|
|
1310
1336
|
vert_bases = self.parse_base_tag_list_()
|
|
1311
1337
|
elif self.is_cur_keyword_("VertAxis.BaseScriptList"):
|
|
@@ -1318,6 +1344,19 @@ class Parser(object):
|
|
|
1318
1344
|
location=self.cur_token_location_,
|
|
1319
1345
|
)
|
|
1320
1346
|
)
|
|
1347
|
+
elif self.is_cur_keyword_("VertAxis.MinMax"):
|
|
1348
|
+
base_script_list = self.find_previous(statements, ast.BaseAxis)
|
|
1349
|
+
if base_script_list is None:
|
|
1350
|
+
raise FeatureLibError(
|
|
1351
|
+
"MinMax must be preceded by BaseScriptList",
|
|
1352
|
+
self.cur_token_location_,
|
|
1353
|
+
)
|
|
1354
|
+
if not base_script_list.vertical:
|
|
1355
|
+
raise FeatureLibError(
|
|
1356
|
+
"VertAxis.MinMax must be preceded by VertAxis statements",
|
|
1357
|
+
self.cur_token_location_,
|
|
1358
|
+
)
|
|
1359
|
+
base_script_list.minmax.append(self.parse_base_minmax_())
|
|
1321
1360
|
elif self.cur_token_ == ";":
|
|
1322
1361
|
continue
|
|
1323
1362
|
|
|
@@ -1574,7 +1613,7 @@ class Parser(object):
|
|
|
1574
1613
|
"HorizAxis.BaseScriptList",
|
|
1575
1614
|
"VertAxis.BaseScriptList",
|
|
1576
1615
|
), self.cur_token_
|
|
1577
|
-
scripts = [
|
|
1616
|
+
scripts = [self.parse_base_script_record_(count)]
|
|
1578
1617
|
while self.next_token_ == ",":
|
|
1579
1618
|
self.expect_symbol_(",")
|
|
1580
1619
|
scripts.append(self.parse_base_script_record_(count))
|
|
@@ -1587,6 +1626,25 @@ class Parser(object):
|
|
|
1587
1626
|
coords = [self.expect_number_() for i in range(count)]
|
|
1588
1627
|
return script_tag, base_tag, coords
|
|
1589
1628
|
|
|
1629
|
+
def parse_base_minmax_(self):
|
|
1630
|
+
script_tag = self.expect_script_tag_()
|
|
1631
|
+
language = self.expect_language_tag_()
|
|
1632
|
+
min_coord = self.expect_number_()
|
|
1633
|
+
self.advance_lexer_()
|
|
1634
|
+
if not (self.cur_token_type_ is Lexer.SYMBOL and self.cur_token_ == ","):
|
|
1635
|
+
raise FeatureLibError(
|
|
1636
|
+
"Expected a comma between min and max coordinates",
|
|
1637
|
+
self.cur_token_location_,
|
|
1638
|
+
)
|
|
1639
|
+
max_coord = self.expect_number_()
|
|
1640
|
+
if self.next_token_ == ",": # feature tag...
|
|
1641
|
+
raise FeatureLibError(
|
|
1642
|
+
"Feature tags are not yet supported in BASE table",
|
|
1643
|
+
self.cur_token_location_,
|
|
1644
|
+
)
|
|
1645
|
+
|
|
1646
|
+
return script_tag, language, min_coord, max_coord
|
|
1647
|
+
|
|
1590
1648
|
def parse_device_(self):
|
|
1591
1649
|
result = None
|
|
1592
1650
|
self.expect_symbol_("<")
|
|
@@ -2004,44 +2062,6 @@ class Parser(object):
|
|
|
2004
2062
|
)
|
|
2005
2063
|
self.expect_symbol_(";")
|
|
2006
2064
|
|
|
2007
|
-
# A multiple substitution may have a single destination, in which case
|
|
2008
|
-
# it will look just like a single substitution. So if there are both
|
|
2009
|
-
# multiple and single substitutions, upgrade all the single ones to
|
|
2010
|
-
# multiple substitutions.
|
|
2011
|
-
|
|
2012
|
-
# Check if we have a mix of non-contextual singles and multiples.
|
|
2013
|
-
has_single = False
|
|
2014
|
-
has_multiple = False
|
|
2015
|
-
for s in statements:
|
|
2016
|
-
if isinstance(s, self.ast.SingleSubstStatement):
|
|
2017
|
-
has_single = not any([s.prefix, s.suffix, s.forceChain])
|
|
2018
|
-
elif isinstance(s, self.ast.MultipleSubstStatement):
|
|
2019
|
-
has_multiple = not any([s.prefix, s.suffix, s.forceChain])
|
|
2020
|
-
|
|
2021
|
-
# Upgrade all single substitutions to multiple substitutions.
|
|
2022
|
-
if has_single and has_multiple:
|
|
2023
|
-
statements = []
|
|
2024
|
-
for s in block.statements:
|
|
2025
|
-
if isinstance(s, self.ast.SingleSubstStatement):
|
|
2026
|
-
glyphs = s.glyphs[0].glyphSet()
|
|
2027
|
-
replacements = s.replacements[0].glyphSet()
|
|
2028
|
-
if len(replacements) == 1:
|
|
2029
|
-
replacements *= len(glyphs)
|
|
2030
|
-
for i, glyph in enumerate(glyphs):
|
|
2031
|
-
statements.append(
|
|
2032
|
-
self.ast.MultipleSubstStatement(
|
|
2033
|
-
s.prefix,
|
|
2034
|
-
glyph,
|
|
2035
|
-
s.suffix,
|
|
2036
|
-
[replacements[i]],
|
|
2037
|
-
s.forceChain,
|
|
2038
|
-
location=s.location,
|
|
2039
|
-
)
|
|
2040
|
-
)
|
|
2041
|
-
else:
|
|
2042
|
-
statements.append(s)
|
|
2043
|
-
block.statements = statements
|
|
2044
|
-
|
|
2045
2065
|
def is_cur_keyword_(self, k):
|
|
2046
2066
|
if self.cur_token_type_ is Lexer.NAME:
|
|
2047
2067
|
if isinstance(k, type("")): # basestring is gone in Python3
|
fontTools/fontBuilder.py
CHANGED
|
@@ -714,6 +714,12 @@ class FontBuilder(object):
|
|
|
714
714
|
gvar.reserved = 0
|
|
715
715
|
gvar.variations = variations
|
|
716
716
|
|
|
717
|
+
def setupGVAR(self, variations):
|
|
718
|
+
gvar = self.font["GVAR"] = newTable("GVAR")
|
|
719
|
+
gvar.version = 1
|
|
720
|
+
gvar.reserved = 0
|
|
721
|
+
gvar.variations = variations
|
|
722
|
+
|
|
717
723
|
def calcGlyphBounds(self):
|
|
718
724
|
"""Calculate the bounding boxes of all glyphs in the `glyf` table.
|
|
719
725
|
This is usually not called explicitly by client code.
|