fonttools 4.56.0__py3-none-any.whl → 4.57.0__py3-none-any.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/config/__init__.py +15 -0
- fontTools/feaLib/ast.py +8 -3
- fontTools/feaLib/builder.py +32 -9
- fontTools/feaLib/parser.py +58 -0
- fontTools/misc/testTools.py +2 -1
- fontTools/otlLib/optimize/gpos.py +7 -1
- 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/_c_m_a_p.py +19 -6
- fontTools/ttLib/tables/_g_l_y_f.py +9 -4
- fontTools/ttLib/tables/_g_v_a_r.py +4 -2
- 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/varLib/__init__.py +92 -89
- fontTools/varLib/hvar.py +113 -0
- fontTools/varLib/varStore.py +1 -1
- {fonttools-4.56.0.dist-info → fonttools-4.57.0.dist-info}/METADATA +16 -2
- {fonttools-4.56.0.dist-info → fonttools-4.57.0.dist-info}/RECORD +28 -27
- {fonttools-4.56.0.dist-info → fonttools-4.57.0.dist-info}/WHEEL +1 -1
- {fonttools-4.56.0.data → fonttools-4.57.0.data}/data/share/man/man1/ttx.1 +0 -0
- {fonttools-4.56.0.dist-info → fonttools-4.57.0.dist-info}/entry_points.txt +0 -0
- {fonttools-4.56.0.dist-info → fonttools-4.57.0.dist-info/licenses}/LICENSE +0 -0
- {fonttools-4.56.0.dist-info → fonttools-4.57.0.dist-info}/top_level.txt +0 -0
fontTools/__init__.py
CHANGED
fontTools/config/__init__.py
CHANGED
|
@@ -73,3 +73,18 @@ Config.register_option(
|
|
|
73
73
|
parse=Option.parse_optional_bool,
|
|
74
74
|
validate=Option.validate_optional_bool,
|
|
75
75
|
)
|
|
76
|
+
|
|
77
|
+
Config.register_option(
|
|
78
|
+
name="fontTools.ttLib:OPTIMIZE_FONT_SPEED",
|
|
79
|
+
help=dedent(
|
|
80
|
+
"""\
|
|
81
|
+
Enable optimizations that prioritize speed over file size. This
|
|
82
|
+
mainly affects how glyf table and gvar / VARC tables are compiled.
|
|
83
|
+
The produced fonts will be larger, but rendering performance will
|
|
84
|
+
be improved with HarfBuzz and other text layout engines.
|
|
85
|
+
"""
|
|
86
|
+
),
|
|
87
|
+
default=False,
|
|
88
|
+
parse=Option.parse_optional_bool,
|
|
89
|
+
validate=Option.validate_optional_bool,
|
|
90
|
+
)
|
fontTools/feaLib/ast.py
CHANGED
|
@@ -1828,15 +1828,16 @@ class BaseAxis(Statement):
|
|
|
1828
1828
|
"""An axis definition, being either a ``VertAxis.BaseTagList/BaseScriptList``
|
|
1829
1829
|
pair or a ``HorizAxis.BaseTagList/BaseScriptList`` pair."""
|
|
1830
1830
|
|
|
1831
|
-
def __init__(self, bases, scripts, vertical, location=None):
|
|
1831
|
+
def __init__(self, bases, scripts, vertical, minmax=None, location=None):
|
|
1832
1832
|
Statement.__init__(self, location)
|
|
1833
1833
|
self.bases = bases #: A list of baseline tag names as strings
|
|
1834
1834
|
self.scripts = scripts #: A list of script record tuplets (script tag, default baseline tag, base coordinate)
|
|
1835
1835
|
self.vertical = vertical #: Boolean; VertAxis if True, HorizAxis if False
|
|
1836
|
+
self.minmax = [] #: A set of minmax record
|
|
1836
1837
|
|
|
1837
1838
|
def build(self, builder):
|
|
1838
1839
|
"""Calls the builder object's ``set_base_axis`` callback."""
|
|
1839
|
-
builder.set_base_axis(self.bases, self.scripts, self.vertical)
|
|
1840
|
+
builder.set_base_axis(self.bases, self.scripts, self.vertical, self.minmax)
|
|
1840
1841
|
|
|
1841
1842
|
def asFea(self, indent=""):
|
|
1842
1843
|
direction = "Vert" if self.vertical else "Horiz"
|
|
@@ -1844,9 +1845,13 @@ class BaseAxis(Statement):
|
|
|
1844
1845
|
"{} {} {}".format(a[0], a[1], " ".join(map(str, a[2])))
|
|
1845
1846
|
for a in self.scripts
|
|
1846
1847
|
]
|
|
1848
|
+
minmaxes = [
|
|
1849
|
+
"\n{}Axis.MinMax {} {} {}, {};".format(direction, a[0], a[1], a[2], a[3])
|
|
1850
|
+
for a in self.minmax
|
|
1851
|
+
]
|
|
1847
1852
|
return "{}Axis.BaseTagList {};\n{}{}Axis.BaseScriptList {};".format(
|
|
1848
1853
|
direction, " ".join(self.bases), indent, direction, ", ".join(scripts)
|
|
1849
|
-
)
|
|
1854
|
+
) + "\n".join(minmaxes)
|
|
1850
1855
|
|
|
1851
1856
|
|
|
1852
1857
|
class OS2Field(Statement):
|
fontTools/feaLib/builder.py
CHANGED
|
@@ -341,6 +341,7 @@ class Builder(object):
|
|
|
341
341
|
table = self.font["head"] = newTable("head")
|
|
342
342
|
table.decompile(b"\0" * 54, self.font)
|
|
343
343
|
table.tableVersion = 1.0
|
|
344
|
+
table.magicNumber = 0x5F0F3CF5
|
|
344
345
|
table.created = table.modified = 3406620153 # 2011-12-13 11:22:33
|
|
345
346
|
table.fontRevision = self.fontRevision_
|
|
346
347
|
|
|
@@ -727,10 +728,16 @@ class Builder(object):
|
|
|
727
728
|
result.table = base
|
|
728
729
|
return result
|
|
729
730
|
|
|
731
|
+
def buildBASECoord(self, c):
|
|
732
|
+
coord = otTables.BaseCoord()
|
|
733
|
+
coord.Format = 1
|
|
734
|
+
coord.Coordinate = c
|
|
735
|
+
return coord
|
|
736
|
+
|
|
730
737
|
def buildBASEAxis(self, axis):
|
|
731
738
|
if not axis:
|
|
732
739
|
return
|
|
733
|
-
bases, scripts = axis
|
|
740
|
+
bases, scripts, minmax = axis
|
|
734
741
|
axis = otTables.Axis()
|
|
735
742
|
axis.BaseTagList = otTables.BaseTagList()
|
|
736
743
|
axis.BaseTagList.BaselineTag = bases
|
|
@@ -739,19 +746,35 @@ class Builder(object):
|
|
|
739
746
|
axis.BaseScriptList.BaseScriptRecord = []
|
|
740
747
|
axis.BaseScriptList.BaseScriptCount = len(scripts)
|
|
741
748
|
for script in sorted(scripts):
|
|
749
|
+
minmax_for_script = [
|
|
750
|
+
record[1:] for record in minmax if record[0] == script[0]
|
|
751
|
+
]
|
|
742
752
|
record = otTables.BaseScriptRecord()
|
|
743
753
|
record.BaseScriptTag = script[0]
|
|
744
754
|
record.BaseScript = otTables.BaseScript()
|
|
745
|
-
record.BaseScript.BaseLangSysCount = 0
|
|
746
755
|
record.BaseScript.BaseValues = otTables.BaseValues()
|
|
747
756
|
record.BaseScript.BaseValues.DefaultIndex = bases.index(script[1])
|
|
748
757
|
record.BaseScript.BaseValues.BaseCoord = []
|
|
749
758
|
record.BaseScript.BaseValues.BaseCoordCount = len(script[2])
|
|
759
|
+
record.BaseScript.BaseLangSysRecord = []
|
|
760
|
+
|
|
750
761
|
for c in script[2]:
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
|
|
762
|
+
record.BaseScript.BaseValues.BaseCoord.append(self.buildBASECoord(c))
|
|
763
|
+
for language, min_coord, max_coord in minmax_for_script:
|
|
764
|
+
minmax_record = otTables.MinMax()
|
|
765
|
+
minmax_record.MinCoord = self.buildBASECoord(min_coord)
|
|
766
|
+
minmax_record.MaxCoord = self.buildBASECoord(max_coord)
|
|
767
|
+
minmax_record.FeatMinMaxCount = 0
|
|
768
|
+
if language == "dflt":
|
|
769
|
+
record.BaseScript.DefaultMinMax = minmax_record
|
|
770
|
+
else:
|
|
771
|
+
lang_record = otTables.BaseLangSysRecord()
|
|
772
|
+
lang_record.BaseLangSysTag = language
|
|
773
|
+
lang_record.MinMax = minmax_record
|
|
774
|
+
record.BaseScript.BaseLangSysRecord.append(lang_record)
|
|
775
|
+
record.BaseScript.BaseLangSysCount = len(
|
|
776
|
+
record.BaseScript.BaseLangSysRecord
|
|
777
|
+
)
|
|
755
778
|
axis.BaseScriptList.BaseScriptRecord.append(record)
|
|
756
779
|
return axis
|
|
757
780
|
|
|
@@ -1235,11 +1258,11 @@ class Builder(object):
|
|
|
1235
1258
|
def add_cv_character(self, character, tag):
|
|
1236
1259
|
self.cv_characters_[tag].append(character)
|
|
1237
1260
|
|
|
1238
|
-
def set_base_axis(self, bases, scripts, vertical):
|
|
1261
|
+
def set_base_axis(self, bases, scripts, vertical, minmax=[]):
|
|
1239
1262
|
if vertical:
|
|
1240
|
-
self.base_vert_axis_ = (bases, scripts)
|
|
1263
|
+
self.base_vert_axis_ = (bases, scripts, minmax)
|
|
1241
1264
|
else:
|
|
1242
|
-
self.base_horiz_axis_ = (bases, scripts)
|
|
1265
|
+
self.base_horiz_axis_ = (bases, scripts, minmax)
|
|
1243
1266
|
|
|
1244
1267
|
def set_size_parameters(
|
|
1245
1268
|
self, location, DesignSize, SubfamilyID, RangeStart, RangeEnd
|
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
|
|
|
@@ -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_("<")
|
fontTools/misc/testTools.py
CHANGED
|
@@ -46,7 +46,8 @@ def parseXmlInto(font, parseInto, xmlSnippet):
|
|
|
46
46
|
parsed_xml = [e for e in parseXML(xmlSnippet.strip()) if not isinstance(e, str)]
|
|
47
47
|
for name, attrs, content in parsed_xml:
|
|
48
48
|
parseInto.fromXML(name, attrs, content, font)
|
|
49
|
-
parseInto
|
|
49
|
+
if hasattr(parseInto, "populateDefaults"):
|
|
50
|
+
parseInto.populateDefaults()
|
|
50
51
|
return parseInto
|
|
51
52
|
|
|
52
53
|
|
|
@@ -53,12 +53,18 @@ def compact(font: TTFont, level: int) -> TTFont:
|
|
|
53
53
|
# are not grouped together first; instead each subtable is treated
|
|
54
54
|
# independently, so currently this step is:
|
|
55
55
|
# Split existing subtables into more smaller subtables
|
|
56
|
-
gpos = font
|
|
56
|
+
gpos = font.get("GPOS")
|
|
57
|
+
|
|
58
|
+
# If the font does not contain a GPOS table, there is nothing to do.
|
|
59
|
+
if gpos is None:
|
|
60
|
+
return font
|
|
61
|
+
|
|
57
62
|
for lookup in gpos.table.LookupList.Lookup:
|
|
58
63
|
if lookup.LookupType == 2:
|
|
59
64
|
compact_lookup(font, level, lookup)
|
|
60
65
|
elif lookup.LookupType == 9 and lookup.SubTable[0].ExtensionLookupType == 2:
|
|
61
66
|
compact_ext_lookup(font, level, lookup)
|
|
67
|
+
|
|
62
68
|
return font
|
|
63
69
|
|
|
64
70
|
|
fontTools/ttLib/__init__.py
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
"""fontTools.ttLib -- a package for dealing with TrueType fonts."""
|
|
2
2
|
|
|
3
|
+
from fontTools.config import OPTIONS
|
|
3
4
|
from fontTools.misc.loggingTools import deprecateFunction
|
|
4
5
|
import logging
|
|
5
6
|
|
|
@@ -7,6 +8,9 @@ import logging
|
|
|
7
8
|
log = logging.getLogger(__name__)
|
|
8
9
|
|
|
9
10
|
|
|
11
|
+
OPTIMIZE_FONT_SPEED = OPTIONS["fontTools.ttLib:OPTIMIZE_FONT_SPEED"]
|
|
12
|
+
|
|
13
|
+
|
|
10
14
|
class TTLibError(Exception):
|
|
11
15
|
pass
|
|
12
16
|
|
fontTools/ttLib/__main__.py
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import sys
|
|
2
|
-
from fontTools.ttLib import TTLibError, TTLibFileIsCollectionError
|
|
2
|
+
from fontTools.ttLib import OPTIMIZE_FONT_SPEED, TTLibError, TTLibFileIsCollectionError
|
|
3
3
|
from fontTools.ttLib.ttFont import *
|
|
4
4
|
from fontTools.ttLib.ttCollection import TTCollection
|
|
5
5
|
|
|
@@ -51,7 +51,7 @@ def main(args=None):
|
|
|
51
51
|
)
|
|
52
52
|
parser.add_argument("font", metavar="font", nargs="*", help="Font file.")
|
|
53
53
|
parser.add_argument(
|
|
54
|
-
"-t", "--table", metavar="table",
|
|
54
|
+
"-t", "--table", metavar="table", action="append", help="Tables to decompile."
|
|
55
55
|
)
|
|
56
56
|
parser.add_argument(
|
|
57
57
|
"-o", "--output", metavar="FILE", default=None, help="Output file."
|
|
@@ -71,27 +71,66 @@ def main(args=None):
|
|
|
71
71
|
default=None,
|
|
72
72
|
help="Flavor of output font. 'woff' or 'woff2'.",
|
|
73
73
|
)
|
|
74
|
+
parser.add_argument(
|
|
75
|
+
"--no-recalc-timestamp",
|
|
76
|
+
dest="recalcTimestamp",
|
|
77
|
+
action="store_false",
|
|
78
|
+
help="Keep the original font 'modified' timestamp.",
|
|
79
|
+
)
|
|
80
|
+
parser.add_argument(
|
|
81
|
+
"-b",
|
|
82
|
+
dest="recalcBBoxes",
|
|
83
|
+
action="store_false",
|
|
84
|
+
help="Don't recalc glyph bounding boxes: use the values in the original font.",
|
|
85
|
+
)
|
|
86
|
+
parser.add_argument(
|
|
87
|
+
"--optimize-font-speed",
|
|
88
|
+
action="store_true",
|
|
89
|
+
help=(
|
|
90
|
+
"Enable optimizations that prioritize speed over file size. This "
|
|
91
|
+
"mainly affects how glyf table and gvar / VARC tables are compiled."
|
|
92
|
+
),
|
|
93
|
+
)
|
|
74
94
|
options = parser.parse_args(args)
|
|
75
95
|
|
|
76
96
|
fontNumber = int(options.y) if options.y is not None else None
|
|
77
97
|
outFile = options.output
|
|
78
98
|
lazy = options.lazy
|
|
79
99
|
flavor = options.flavor
|
|
80
|
-
tables = options.table
|
|
100
|
+
tables = options.table
|
|
101
|
+
recalcBBoxes = options.recalcBBoxes
|
|
102
|
+
recalcTimestamp = options.recalcTimestamp
|
|
103
|
+
optimizeFontSpeed = options.optimize_font_speed
|
|
81
104
|
|
|
82
105
|
fonts = []
|
|
83
106
|
for f in options.font:
|
|
84
107
|
try:
|
|
85
|
-
font = TTFont(
|
|
108
|
+
font = TTFont(
|
|
109
|
+
f,
|
|
110
|
+
recalcBBoxes=recalcBBoxes,
|
|
111
|
+
recalcTimestamp=recalcTimestamp,
|
|
112
|
+
fontNumber=fontNumber,
|
|
113
|
+
lazy=lazy,
|
|
114
|
+
)
|
|
115
|
+
if optimizeFontSpeed:
|
|
116
|
+
font.cfg[OPTIMIZE_FONT_SPEED] = optimizeFontSpeed
|
|
86
117
|
fonts.append(font)
|
|
87
118
|
except TTLibFileIsCollectionError:
|
|
88
119
|
collection = TTCollection(f, lazy=lazy)
|
|
89
120
|
fonts.extend(collection.fonts)
|
|
90
121
|
|
|
91
|
-
if
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
122
|
+
if tables is None:
|
|
123
|
+
if lazy is False:
|
|
124
|
+
tables = ["*"]
|
|
125
|
+
elif optimizeFontSpeed:
|
|
126
|
+
tables = {"glyf", "gvar", "VARC"}.intersection(font.keys())
|
|
127
|
+
else:
|
|
128
|
+
tables = []
|
|
129
|
+
for font in fonts:
|
|
130
|
+
if "GlyphOrder" in tables:
|
|
131
|
+
font.getGlyphOrder()
|
|
132
|
+
for table in tables if "*" not in tables else font.keys():
|
|
133
|
+
font[table] # Decompiles
|
|
95
134
|
|
|
96
135
|
if outFile is not None:
|
|
97
136
|
if len(fonts) == 1:
|
|
@@ -1,9 +1,15 @@
|
|
|
1
1
|
import json
|
|
2
|
+
from textwrap import indent
|
|
2
3
|
|
|
3
4
|
from . import DefaultTable
|
|
5
|
+
from fontTools.misc.textTools import tostr
|
|
4
6
|
|
|
5
7
|
|
|
6
8
|
class table_D__e_b_g(DefaultTable.DefaultTable):
|
|
9
|
+
def __init__(self, tag=None):
|
|
10
|
+
DefaultTable.DefaultTable.__init__(self, tag)
|
|
11
|
+
self.data = {}
|
|
12
|
+
|
|
7
13
|
def decompile(self, data, ttFont):
|
|
8
14
|
self.data = json.loads(data)
|
|
9
15
|
|
|
@@ -11,7 +17,19 @@ class table_D__e_b_g(DefaultTable.DefaultTable):
|
|
|
11
17
|
return json.dumps(self.data).encode("utf-8")
|
|
12
18
|
|
|
13
19
|
def toXML(self, writer, ttFont):
|
|
14
|
-
|
|
20
|
+
# make sure json indentation inside CDATA block matches XMLWriter's
|
|
21
|
+
data = json.dumps(self.data, indent=len(writer.indentwhite))
|
|
22
|
+
prefix = tostr(writer.indentwhite) * (writer.indentlevel + 1)
|
|
23
|
+
# but don't indent the first json line so it's adjacent to `<![CDATA[{`
|
|
24
|
+
cdata = indent(data, prefix, lambda ln: ln != "{\n")
|
|
25
|
+
|
|
26
|
+
writer.begintag("json")
|
|
27
|
+
writer.newline()
|
|
28
|
+
writer.writecdata(cdata)
|
|
29
|
+
writer.newline()
|
|
30
|
+
writer.endtag("json")
|
|
31
|
+
writer.newline()
|
|
15
32
|
|
|
16
33
|
def fromXML(self, name, attrs, content, ttFont):
|
|
17
|
-
|
|
34
|
+
if name == "json":
|
|
35
|
+
self.data = json.loads("".join(content))
|
|
@@ -141,6 +141,17 @@ class table__c_m_a_p(DefaultTable.DefaultTable):
|
|
|
141
141
|
result.setdefault(name, set()).add(codepoint)
|
|
142
142
|
return result
|
|
143
143
|
|
|
144
|
+
def buildReversedMin(self):
|
|
145
|
+
result = {}
|
|
146
|
+
for subtable in self.tables:
|
|
147
|
+
if subtable.isUnicode():
|
|
148
|
+
for codepoint, name in subtable.cmap.items():
|
|
149
|
+
if name in result:
|
|
150
|
+
result[name] = min(result[name], codepoint)
|
|
151
|
+
else:
|
|
152
|
+
result[name] = codepoint
|
|
153
|
+
return result
|
|
154
|
+
|
|
144
155
|
def decompile(self, data, ttFont):
|
|
145
156
|
tableVersion, numSubTables = struct.unpack(">HH", data[:4])
|
|
146
157
|
self.tableVersion = int(tableVersion)
|
|
@@ -1162,13 +1173,15 @@ class cmap_format_12_or_13(CmapSubtable):
|
|
|
1162
1173
|
charCodes = []
|
|
1163
1174
|
gids = []
|
|
1164
1175
|
pos = 0
|
|
1176
|
+
groups = array.array("I", data[: self.nGroups * 12])
|
|
1177
|
+
if sys.byteorder != "big":
|
|
1178
|
+
groups.byteswap()
|
|
1165
1179
|
for i in range(self.nGroups):
|
|
1166
|
-
startCharCode
|
|
1167
|
-
|
|
1168
|
-
|
|
1169
|
-
pos += 12
|
|
1180
|
+
startCharCode = groups[i * 3]
|
|
1181
|
+
endCharCode = groups[i * 3 + 1]
|
|
1182
|
+
glyphID = groups[i * 3 + 2]
|
|
1170
1183
|
lenGroup = 1 + endCharCode - startCharCode
|
|
1171
|
-
charCodes.extend(
|
|
1184
|
+
charCodes.extend(range(startCharCode, endCharCode + 1))
|
|
1172
1185
|
gids.extend(self._computeGIDs(glyphID, lenGroup))
|
|
1173
1186
|
self.data = data = None
|
|
1174
1187
|
self.cmap = _make_map(self.ttFont, charCodes, gids)
|
|
@@ -1299,7 +1312,7 @@ class cmap_format_12(cmap_format_12_or_13):
|
|
|
1299
1312
|
cmap_format_12_or_13.__init__(self, format)
|
|
1300
1313
|
|
|
1301
1314
|
def _computeGIDs(self, startingGlyph, numberOfGlyphs):
|
|
1302
|
-
return
|
|
1315
|
+
return range(startingGlyph, startingGlyph + numberOfGlyphs)
|
|
1303
1316
|
|
|
1304
1317
|
def _IsInSameRun(self, glyphID, lastGlyphID, charCode, lastCharCode):
|
|
1305
1318
|
return (glyphID == 1 + lastGlyphID) and (charCode == 1 + lastCharCode)
|
|
@@ -134,6 +134,8 @@ class table__g_l_y_f(DefaultTable.DefaultTable):
|
|
|
134
134
|
glyph.expand(self)
|
|
135
135
|
|
|
136
136
|
def compile(self, ttFont):
|
|
137
|
+
optimizeSpeed = ttFont.cfg[ttLib.OPTIMIZE_FONT_SPEED]
|
|
138
|
+
|
|
137
139
|
self.axisTags = (
|
|
138
140
|
[axis.axisTag for axis in ttFont["fvar"].axes] if "fvar" in ttFont else []
|
|
139
141
|
)
|
|
@@ -148,7 +150,12 @@ class table__g_l_y_f(DefaultTable.DefaultTable):
|
|
|
148
150
|
boundsDone = set()
|
|
149
151
|
for glyphName in self.glyphOrder:
|
|
150
152
|
glyph = self.glyphs[glyphName]
|
|
151
|
-
glyphData = glyph.compile(
|
|
153
|
+
glyphData = glyph.compile(
|
|
154
|
+
self,
|
|
155
|
+
recalcBBoxes,
|
|
156
|
+
boundsDone=boundsDone,
|
|
157
|
+
optimizeSize=not optimizeSpeed,
|
|
158
|
+
)
|
|
152
159
|
if padding > 1:
|
|
153
160
|
glyphData = pad(glyphData, size=padding)
|
|
154
161
|
locations.append(currentLocation)
|
|
@@ -714,7 +721,7 @@ class Glyph(object):
|
|
|
714
721
|
self.decompileCoordinates(data)
|
|
715
722
|
|
|
716
723
|
def compile(
|
|
717
|
-
self, glyfTable, recalcBBoxes=True, *, boundsDone=None, optimizeSize=
|
|
724
|
+
self, glyfTable, recalcBBoxes=True, *, boundsDone=None, optimizeSize=True
|
|
718
725
|
):
|
|
719
726
|
if hasattr(self, "data"):
|
|
720
727
|
if recalcBBoxes:
|
|
@@ -732,8 +739,6 @@ class Glyph(object):
|
|
|
732
739
|
if self.isComposite():
|
|
733
740
|
data = data + self.compileComponents(glyfTable)
|
|
734
741
|
else:
|
|
735
|
-
if optimizeSize is None:
|
|
736
|
-
optimizeSize = getattr(glyfTable, "optimizeSize", True)
|
|
737
742
|
data = data + self.compileCoordinates(optimizeSize=optimizeSize)
|
|
738
743
|
return data
|
|
739
744
|
|
|
@@ -3,6 +3,7 @@ from functools import partial
|
|
|
3
3
|
from fontTools.misc import sstruct
|
|
4
4
|
from fontTools.misc.textTools import safeEval
|
|
5
5
|
from fontTools.misc.lazyTools import LazyDict
|
|
6
|
+
from fontTools.ttLib import OPTIMIZE_FONT_SPEED
|
|
6
7
|
from fontTools.ttLib.tables.TupleVariation import TupleVariation
|
|
7
8
|
from . import DefaultTable
|
|
8
9
|
import array
|
|
@@ -57,6 +58,7 @@ class table__g_v_a_r(DefaultTable.DefaultTable):
|
|
|
57
58
|
self.variations = {}
|
|
58
59
|
|
|
59
60
|
def compile(self, ttFont):
|
|
61
|
+
|
|
60
62
|
axisTags = [axis.axisTag for axis in ttFont["fvar"].axes]
|
|
61
63
|
sharedTuples = tv.compileSharedTuples(
|
|
62
64
|
axisTags, itertools.chain(*self.variations.values())
|
|
@@ -91,9 +93,9 @@ class table__g_v_a_r(DefaultTable.DefaultTable):
|
|
|
91
93
|
return b"".join(result)
|
|
92
94
|
|
|
93
95
|
def compileGlyphs_(self, ttFont, axisTags, sharedCoordIndices):
|
|
96
|
+
optimizeSpeed = ttFont.cfg[OPTIMIZE_FONT_SPEED]
|
|
94
97
|
result = []
|
|
95
98
|
glyf = ttFont["glyf"]
|
|
96
|
-
optimizeSize = getattr(self, "optimizeSize", True)
|
|
97
99
|
for glyphName in ttFont.getGlyphOrder():
|
|
98
100
|
variations = self.variations.get(glyphName, [])
|
|
99
101
|
if not variations:
|
|
@@ -106,7 +108,7 @@ class table__g_v_a_r(DefaultTable.DefaultTable):
|
|
|
106
108
|
pointCountUnused,
|
|
107
109
|
axisTags,
|
|
108
110
|
sharedCoordIndices,
|
|
109
|
-
optimizeSize=
|
|
111
|
+
optimizeSize=not optimizeSpeed,
|
|
110
112
|
)
|
|
111
113
|
)
|
|
112
114
|
return result
|
|
@@ -10,7 +10,7 @@ from fontTools.ttLib.tables.TupleVariation import TupleVariation
|
|
|
10
10
|
from fontTools.misc.roundTools import nearestMultipleShortestRepr, otRound
|
|
11
11
|
from fontTools.misc.textTools import bytesjoin, tobytes, tostr, pad, safeEval
|
|
12
12
|
from fontTools.misc.lazyTools import LazyList
|
|
13
|
-
from fontTools.ttLib import getSearchRange
|
|
13
|
+
from fontTools.ttLib import OPTIMIZE_FONT_SPEED, getSearchRange
|
|
14
14
|
from .otBase import (
|
|
15
15
|
CountReference,
|
|
16
16
|
FormatSwitchingBaseTable,
|
|
@@ -1810,7 +1810,10 @@ class TupleValues:
|
|
|
1810
1810
|
return TupleVariation.decompileDeltas_(None, data)[0]
|
|
1811
1811
|
|
|
1812
1812
|
def write(self, writer, font, tableDict, values, repeatIndex=None):
|
|
1813
|
-
|
|
1813
|
+
optimizeSpeed = font.cfg[OPTIMIZE_FONT_SPEED]
|
|
1814
|
+
return bytes(
|
|
1815
|
+
TupleVariation.compileDeltaValues_(values, optimizeSize=not optimizeSpeed)
|
|
1816
|
+
)
|
|
1814
1817
|
|
|
1815
1818
|
def xmlRead(self, attrs, content, font):
|
|
1816
1819
|
return safeEval(attrs["value"])
|
|
@@ -11,6 +11,7 @@ from functools import reduce
|
|
|
11
11
|
from math import radians
|
|
12
12
|
import itertools
|
|
13
13
|
from collections import defaultdict, namedtuple
|
|
14
|
+
from fontTools.ttLib import OPTIMIZE_FONT_SPEED
|
|
14
15
|
from fontTools.ttLib.tables.TupleVariation import TupleVariation
|
|
15
16
|
from fontTools.ttLib.tables.otTraverse import dfs_base_table
|
|
16
17
|
from fontTools.misc.arrayTools import quantizeRect
|
|
@@ -236,6 +237,8 @@ class VarComponent:
|
|
|
236
237
|
return data[i:]
|
|
237
238
|
|
|
238
239
|
def compile(self, font):
|
|
240
|
+
optimizeSpeed = font.cfg[OPTIMIZE_FONT_SPEED]
|
|
241
|
+
|
|
239
242
|
data = []
|
|
240
243
|
|
|
241
244
|
flags = self.flags
|
|
@@ -259,7 +262,8 @@ class VarComponent:
|
|
|
259
262
|
data.append(_write_uint32var(self.axisIndicesIndex))
|
|
260
263
|
data.append(
|
|
261
264
|
TupleVariation.compileDeltaValues_(
|
|
262
|
-
[fl2fi(v, 14) for v in self.axisValues]
|
|
265
|
+
[fl2fi(v, 14) for v in self.axisValues],
|
|
266
|
+
optimizeSize=not optimizeSpeed,
|
|
263
267
|
)
|
|
264
268
|
)
|
|
265
269
|
else:
|
fontTools/ttLib/ttFont.py
CHANGED
|
@@ -593,10 +593,8 @@ class TTFont(object):
|
|
|
593
593
|
# temporary cmap and by the real cmap in case we don't find a unicode
|
|
594
594
|
# cmap.
|
|
595
595
|
numGlyphs = int(self["maxp"].numGlyphs)
|
|
596
|
-
glyphOrder = [
|
|
596
|
+
glyphOrder = ["glyph%.5d" % i for i in range(numGlyphs)]
|
|
597
597
|
glyphOrder[0] = ".notdef"
|
|
598
|
-
for i in range(1, numGlyphs):
|
|
599
|
-
glyphOrder[i] = "glyph%.5d" % i
|
|
600
598
|
# Set the glyph order, so the cmap parser has something
|
|
601
599
|
# to work with (so we don't get called recursively).
|
|
602
600
|
self.glyphOrder = glyphOrder
|
|
@@ -606,7 +604,7 @@ class TTFont(object):
|
|
|
606
604
|
# this naming table will usually not cover all glyphs in the font.
|
|
607
605
|
# If the font has no Unicode cmap table, reversecmap will be empty.
|
|
608
606
|
if "cmap" in self:
|
|
609
|
-
reversecmap = self["cmap"].
|
|
607
|
+
reversecmap = self["cmap"].buildReversedMin()
|
|
610
608
|
else:
|
|
611
609
|
reversecmap = {}
|
|
612
610
|
useCount = {}
|
|
@@ -616,7 +614,7 @@ class TTFont(object):
|
|
|
616
614
|
# If a font maps both U+0041 LATIN CAPITAL LETTER A and
|
|
617
615
|
# U+0391 GREEK CAPITAL LETTER ALPHA to the same glyph,
|
|
618
616
|
# we prefer naming the glyph as "A".
|
|
619
|
-
glyphName = self._makeGlyphName(
|
|
617
|
+
glyphName = self._makeGlyphName(reversecmap[tempName])
|
|
620
618
|
numUses = useCount[glyphName] = useCount.get(glyphName, 0) + 1
|
|
621
619
|
if numUses > 1:
|
|
622
620
|
glyphName = "%s.alt%d" % (glyphName, numUses - 1)
|
fontTools/ttLib/ttGlyphSet.py
CHANGED
|
@@ -104,16 +104,6 @@ class _TTGlyphSetGlyf(_TTGlyphSet):
|
|
|
104
104
|
return _TTGlyphGlyf(self, glyphName, recalcBounds=self.recalcBounds)
|
|
105
105
|
|
|
106
106
|
|
|
107
|
-
class _TTGlyphSetGlyf(_TTGlyphSet):
|
|
108
|
-
def __init__(self, font, location, recalcBounds=True):
|
|
109
|
-
self.glyfTable = font["glyf"]
|
|
110
|
-
super().__init__(font, location, self.glyfTable, recalcBounds=recalcBounds)
|
|
111
|
-
self.gvarTable = font.get("gvar")
|
|
112
|
-
|
|
113
|
-
def __getitem__(self, glyphName):
|
|
114
|
-
return _TTGlyphGlyf(self, glyphName, recalcBounds=self.recalcBounds)
|
|
115
|
-
|
|
116
|
-
|
|
117
107
|
class _TTGlyphSetCFF(_TTGlyphSet):
|
|
118
108
|
def __init__(self, font, location):
|
|
119
109
|
tableTag = "CFF2" if "CFF2" in font else "CFF "
|
fontTools/ttx.py
CHANGED
|
@@ -101,9 +101,15 @@ Compile options
|
|
|
101
101
|
--with-zopfli
|
|
102
102
|
Use Zopfli instead of Zlib to compress WOFF. The Python
|
|
103
103
|
extension is available at https://pypi.python.org/pypi/zopfli
|
|
104
|
+
--optimize-font-speed
|
|
105
|
+
Enable optimizations that prioritize speed over file size.
|
|
106
|
+
This mainly affects how glyf t able and gvar / VARC tables are
|
|
107
|
+
compiled. The produced fonts will be larger, but rendering
|
|
108
|
+
performance will be improved with HarfBuzz and other text
|
|
109
|
+
layout engines.
|
|
104
110
|
"""
|
|
105
111
|
|
|
106
|
-
from fontTools.ttLib import TTFont, TTLibError
|
|
112
|
+
from fontTools.ttLib import OPTIMIZE_FONT_SPEED, TTFont, TTLibError
|
|
107
113
|
from fontTools.misc.macCreatorType import getMacCreatorAndType
|
|
108
114
|
from fontTools.unicode import setUnicodeData
|
|
109
115
|
from fontTools.misc.textTools import Tag, tostr
|
|
@@ -141,6 +147,7 @@ class Options(object):
|
|
|
141
147
|
recalcTimestamp = None
|
|
142
148
|
flavor = None
|
|
143
149
|
useZopfli = False
|
|
150
|
+
optimizeFontSpeed = False
|
|
144
151
|
|
|
145
152
|
def __init__(self, rawOptions, numFiles):
|
|
146
153
|
self.onlyTables = []
|
|
@@ -229,6 +236,8 @@ class Options(object):
|
|
|
229
236
|
self.flavor = value
|
|
230
237
|
elif option == "--with-zopfli":
|
|
231
238
|
self.useZopfli = True
|
|
239
|
+
elif option == "--optimize-font-speed":
|
|
240
|
+
self.optimizeFontSpeed = True
|
|
232
241
|
if self.verbose and self.quiet:
|
|
233
242
|
raise getopt.GetoptError("-q and -v options are mutually exclusive")
|
|
234
243
|
if self.verbose:
|
|
@@ -324,6 +333,8 @@ def ttCompile(input, output, options):
|
|
|
324
333
|
recalcBBoxes=options.recalcBBoxes,
|
|
325
334
|
recalcTimestamp=options.recalcTimestamp,
|
|
326
335
|
)
|
|
336
|
+
if options.optimizeFontSpeed:
|
|
337
|
+
ttf.cfg[OPTIMIZE_FONT_SPEED] = options.optimizeFontSpeed
|
|
327
338
|
ttf.importXML(input)
|
|
328
339
|
|
|
329
340
|
if options.recalcTimestamp is None and "head" in ttf and input is not sys.stdin:
|
|
@@ -386,6 +397,7 @@ def parseOptions(args):
|
|
|
386
397
|
"version",
|
|
387
398
|
"with-zopfli",
|
|
388
399
|
"newline=",
|
|
400
|
+
"optimize-font-speed",
|
|
389
401
|
],
|
|
390
402
|
)
|
|
391
403
|
|
fontTools/varLib/__init__.py
CHANGED
|
@@ -12,13 +12,13 @@ a Glyphs source, eg., using noto-source as an example:
|
|
|
12
12
|
|
|
13
13
|
.. code-block:: sh
|
|
14
14
|
|
|
15
|
-
|
|
15
|
+
$ fontmake -o ttf-interpolatable -g NotoSansArabic-MM.glyphs
|
|
16
16
|
|
|
17
17
|
Then you can make a variable-font this way:
|
|
18
18
|
|
|
19
19
|
.. code-block:: sh
|
|
20
20
|
|
|
21
|
-
|
|
21
|
+
$ fonttools varLib master_ufo/NotoSansArabic.designspace
|
|
22
22
|
|
|
23
23
|
API *will* change in near future.
|
|
24
24
|
"""
|
|
@@ -479,7 +479,15 @@ def _merge_TTHinting(font, masterModel, master_ttfs):
|
|
|
479
479
|
|
|
480
480
|
_MetricsFields = namedtuple(
|
|
481
481
|
"_MetricsFields",
|
|
482
|
-
[
|
|
482
|
+
[
|
|
483
|
+
"tableTag",
|
|
484
|
+
"metricsTag",
|
|
485
|
+
"sb1",
|
|
486
|
+
"sb2",
|
|
487
|
+
"advMapping",
|
|
488
|
+
"vOrigMapping",
|
|
489
|
+
"phantomIndex",
|
|
490
|
+
],
|
|
483
491
|
)
|
|
484
492
|
|
|
485
493
|
HVAR_FIELDS = _MetricsFields(
|
|
@@ -489,6 +497,7 @@ HVAR_FIELDS = _MetricsFields(
|
|
|
489
497
|
sb2="RsbMap",
|
|
490
498
|
advMapping="AdvWidthMap",
|
|
491
499
|
vOrigMapping=None,
|
|
500
|
+
phantomIndex=0,
|
|
492
501
|
)
|
|
493
502
|
|
|
494
503
|
VVAR_FIELDS = _MetricsFields(
|
|
@@ -498,109 +507,43 @@ VVAR_FIELDS = _MetricsFields(
|
|
|
498
507
|
sb2="BsbMap",
|
|
499
508
|
advMapping="AdvHeightMap",
|
|
500
509
|
vOrigMapping="VOrgMap",
|
|
510
|
+
phantomIndex=1,
|
|
501
511
|
)
|
|
502
512
|
|
|
503
513
|
|
|
504
514
|
def _add_HVAR(font, masterModel, master_ttfs, axisTags):
|
|
505
|
-
|
|
515
|
+
getAdvanceMetrics = partial(
|
|
516
|
+
_get_advance_metrics, font, masterModel, master_ttfs, axisTags, HVAR_FIELDS
|
|
517
|
+
)
|
|
518
|
+
_add_VHVAR(font, axisTags, HVAR_FIELDS, getAdvanceMetrics)
|
|
506
519
|
|
|
507
520
|
|
|
508
521
|
def _add_VVAR(font, masterModel, master_ttfs, axisTags):
|
|
509
|
-
|
|
522
|
+
getAdvanceMetrics = partial(
|
|
523
|
+
_get_advance_metrics, font, masterModel, master_ttfs, axisTags, VVAR_FIELDS
|
|
524
|
+
)
|
|
525
|
+
_add_VHVAR(font, axisTags, VVAR_FIELDS, getAdvanceMetrics)
|
|
510
526
|
|
|
511
527
|
|
|
512
|
-
def _add_VHVAR(font,
|
|
528
|
+
def _add_VHVAR(font, axisTags, tableFields, getAdvanceMetrics):
|
|
513
529
|
tableTag = tableFields.tableTag
|
|
514
530
|
assert tableTag not in font
|
|
531
|
+
glyphOrder = font.getGlyphOrder()
|
|
515
532
|
log.info("Generating " + tableTag)
|
|
516
533
|
VHVAR = newTable(tableTag)
|
|
517
534
|
tableClass = getattr(ot, tableTag)
|
|
518
535
|
vhvar = VHVAR.table = tableClass()
|
|
519
536
|
vhvar.Version = 0x00010000
|
|
520
537
|
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
# Build list of source font advance widths for each glyph
|
|
524
|
-
metricsTag = tableFields.metricsTag
|
|
525
|
-
advMetricses = [m[metricsTag].metrics for m in master_ttfs]
|
|
526
|
-
|
|
527
|
-
# Build list of source font vertical origin coords for each glyph
|
|
528
|
-
if tableTag == "VVAR" and "VORG" in master_ttfs[0]:
|
|
529
|
-
vOrigMetricses = [m["VORG"].VOriginRecords for m in master_ttfs]
|
|
530
|
-
defaultYOrigs = [m["VORG"].defaultVertOriginY for m in master_ttfs]
|
|
531
|
-
vOrigMetricses = list(zip(vOrigMetricses, defaultYOrigs))
|
|
532
|
-
else:
|
|
533
|
-
vOrigMetricses = None
|
|
534
|
-
|
|
535
|
-
metricsStore, advanceMapping, vOrigMapping = _get_advance_metrics(
|
|
536
|
-
font,
|
|
537
|
-
masterModel,
|
|
538
|
-
master_ttfs,
|
|
539
|
-
axisTags,
|
|
540
|
-
glyphOrder,
|
|
541
|
-
advMetricses,
|
|
542
|
-
vOrigMetricses,
|
|
543
|
-
)
|
|
538
|
+
vhAdvanceDeltasAndSupports, vOrigDeltasAndSupports = getAdvanceMetrics()
|
|
544
539
|
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
setattr(vhvar, tableFields.advMapping, None)
|
|
540
|
+
if vOrigDeltasAndSupports:
|
|
541
|
+
singleModel = False
|
|
548
542
|
else:
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
setattr(vhvar, tableFields.vOrigMapping, vOrigMapping)
|
|
552
|
-
setattr(vhvar, tableFields.sb1, None)
|
|
553
|
-
setattr(vhvar, tableFields.sb2, None)
|
|
554
|
-
|
|
555
|
-
font[tableTag] = VHVAR
|
|
556
|
-
return
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
def _get_advance_metrics(
|
|
560
|
-
font,
|
|
561
|
-
masterModel,
|
|
562
|
-
master_ttfs,
|
|
563
|
-
axisTags,
|
|
564
|
-
glyphOrder,
|
|
565
|
-
advMetricses,
|
|
566
|
-
vOrigMetricses=None,
|
|
567
|
-
):
|
|
568
|
-
vhAdvanceDeltasAndSupports = {}
|
|
569
|
-
vOrigDeltasAndSupports = {}
|
|
570
|
-
# HACK: we treat width 65535 as a sentinel value to signal that a glyph
|
|
571
|
-
# from a non-default master should not participate in computing {H,V}VAR,
|
|
572
|
-
# as if it were missing. Allows to variate other glyph-related data independently
|
|
573
|
-
# from glyph metrics
|
|
574
|
-
sparse_advance = 0xFFFF
|
|
575
|
-
for glyph in glyphOrder:
|
|
576
|
-
vhAdvances = [
|
|
577
|
-
(
|
|
578
|
-
metrics[glyph][0]
|
|
579
|
-
if glyph in metrics and metrics[glyph][0] != sparse_advance
|
|
580
|
-
else None
|
|
581
|
-
)
|
|
582
|
-
for metrics in advMetricses
|
|
583
|
-
]
|
|
584
|
-
vhAdvanceDeltasAndSupports[glyph] = masterModel.getDeltasAndSupports(
|
|
585
|
-
vhAdvances, round=round
|
|
543
|
+
singleModel = models.allEqual(
|
|
544
|
+
id(v[1]) for v in vhAdvanceDeltasAndSupports.values()
|
|
586
545
|
)
|
|
587
546
|
|
|
588
|
-
singleModel = models.allEqual(id(v[1]) for v in vhAdvanceDeltasAndSupports.values())
|
|
589
|
-
|
|
590
|
-
if vOrigMetricses:
|
|
591
|
-
singleModel = False
|
|
592
|
-
for glyph in glyphOrder:
|
|
593
|
-
# We need to supply a vOrigs tuple with non-None default values
|
|
594
|
-
# for each glyph. vOrigMetricses contains values only for those
|
|
595
|
-
# glyphs which have a non-default vOrig.
|
|
596
|
-
vOrigs = [
|
|
597
|
-
metrics[glyph] if glyph in metrics else defaultVOrig
|
|
598
|
-
for metrics, defaultVOrig in vOrigMetricses
|
|
599
|
-
]
|
|
600
|
-
vOrigDeltasAndSupports[glyph] = masterModel.getDeltasAndSupports(
|
|
601
|
-
vOrigs, round=round
|
|
602
|
-
)
|
|
603
|
-
|
|
604
547
|
directStore = None
|
|
605
548
|
if singleModel:
|
|
606
549
|
# Build direct mapping
|
|
@@ -621,7 +564,7 @@ def _get_advance_metrics(
|
|
|
621
564
|
storeBuilder.setSupports(supports)
|
|
622
565
|
advMapping[glyphName] = storeBuilder.storeDeltas(deltas, round=noRound)
|
|
623
566
|
|
|
624
|
-
if
|
|
567
|
+
if vOrigDeltasAndSupports:
|
|
625
568
|
vOrigMap = {}
|
|
626
569
|
for glyphName in glyphOrder:
|
|
627
570
|
deltas, supports = vOrigDeltasAndSupports[glyphName]
|
|
@@ -633,7 +576,7 @@ def _get_advance_metrics(
|
|
|
633
576
|
advMapping = [mapping2[advMapping[g]] for g in glyphOrder]
|
|
634
577
|
advanceMapping = builder.buildVarIdxMap(advMapping, glyphOrder)
|
|
635
578
|
|
|
636
|
-
if
|
|
579
|
+
if vOrigDeltasAndSupports:
|
|
637
580
|
vOrigMap = [mapping2[vOrigMap[g]] for g in glyphOrder]
|
|
638
581
|
|
|
639
582
|
useDirect = False
|
|
@@ -657,10 +600,70 @@ def _get_advance_metrics(
|
|
|
657
600
|
advanceMapping = None
|
|
658
601
|
else:
|
|
659
602
|
metricsStore = indirectStore
|
|
660
|
-
if
|
|
603
|
+
if vOrigDeltasAndSupports:
|
|
661
604
|
vOrigMapping = builder.buildVarIdxMap(vOrigMap, glyphOrder)
|
|
662
605
|
|
|
663
|
-
|
|
606
|
+
vhvar.VarStore = metricsStore
|
|
607
|
+
setattr(vhvar, tableFields.advMapping, advanceMapping)
|
|
608
|
+
if vOrigMapping is not None:
|
|
609
|
+
setattr(vhvar, tableFields.vOrigMapping, vOrigMapping)
|
|
610
|
+
setattr(vhvar, tableFields.sb1, None)
|
|
611
|
+
setattr(vhvar, tableFields.sb2, None)
|
|
612
|
+
|
|
613
|
+
font[tableTag] = VHVAR
|
|
614
|
+
return
|
|
615
|
+
|
|
616
|
+
|
|
617
|
+
def _get_advance_metrics(font, masterModel, master_ttfs, axisTags, tableFields):
|
|
618
|
+
tableTag = tableFields.tableTag
|
|
619
|
+
glyphOrder = font.getGlyphOrder()
|
|
620
|
+
|
|
621
|
+
# Build list of source font advance widths for each glyph
|
|
622
|
+
metricsTag = tableFields.metricsTag
|
|
623
|
+
advMetricses = [m[metricsTag].metrics for m in master_ttfs]
|
|
624
|
+
|
|
625
|
+
# Build list of source font vertical origin coords for each glyph
|
|
626
|
+
if tableTag == "VVAR" and "VORG" in master_ttfs[0]:
|
|
627
|
+
vOrigMetricses = [m["VORG"].VOriginRecords for m in master_ttfs]
|
|
628
|
+
defaultYOrigs = [m["VORG"].defaultVertOriginY for m in master_ttfs]
|
|
629
|
+
vOrigMetricses = list(zip(vOrigMetricses, defaultYOrigs))
|
|
630
|
+
else:
|
|
631
|
+
vOrigMetricses = None
|
|
632
|
+
|
|
633
|
+
vhAdvanceDeltasAndSupports = {}
|
|
634
|
+
vOrigDeltasAndSupports = {}
|
|
635
|
+
# HACK: we treat width 65535 as a sentinel value to signal that a glyph
|
|
636
|
+
# from a non-default master should not participate in computing {H,V}VAR,
|
|
637
|
+
# as if it were missing. Allows to variate other glyph-related data independently
|
|
638
|
+
# from glyph metrics
|
|
639
|
+
sparse_advance = 0xFFFF
|
|
640
|
+
for glyph in glyphOrder:
|
|
641
|
+
vhAdvances = [
|
|
642
|
+
(
|
|
643
|
+
metrics[glyph][0]
|
|
644
|
+
if glyph in metrics and metrics[glyph][0] != sparse_advance
|
|
645
|
+
else None
|
|
646
|
+
)
|
|
647
|
+
for metrics in advMetricses
|
|
648
|
+
]
|
|
649
|
+
vhAdvanceDeltasAndSupports[glyph] = masterModel.getDeltasAndSupports(
|
|
650
|
+
vhAdvances, round=round
|
|
651
|
+
)
|
|
652
|
+
|
|
653
|
+
if vOrigMetricses:
|
|
654
|
+
for glyph in glyphOrder:
|
|
655
|
+
# We need to supply a vOrigs tuple with non-None default values
|
|
656
|
+
# for each glyph. vOrigMetricses contains values only for those
|
|
657
|
+
# glyphs which have a non-default vOrig.
|
|
658
|
+
vOrigs = [
|
|
659
|
+
metrics[glyph] if glyph in metrics else defaultVOrig
|
|
660
|
+
for metrics, defaultVOrig in vOrigMetricses
|
|
661
|
+
]
|
|
662
|
+
vOrigDeltasAndSupports[glyph] = masterModel.getDeltasAndSupports(
|
|
663
|
+
vOrigs, round=round
|
|
664
|
+
)
|
|
665
|
+
|
|
666
|
+
return vhAdvanceDeltasAndSupports, vOrigDeltasAndSupports
|
|
664
667
|
|
|
665
668
|
|
|
666
669
|
def _add_MVAR(font, masterModel, master_ttfs, axisTags):
|
fontTools/varLib/hvar.py
ADDED
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
from fontTools.misc.roundTools import noRound
|
|
2
|
+
from fontTools.ttLib import TTFont, newTable
|
|
3
|
+
from fontTools.ttLib.tables import otTables as ot
|
|
4
|
+
from fontTools.ttLib.tables.otBase import OTTableWriter
|
|
5
|
+
from fontTools.varLib import HVAR_FIELDS, VVAR_FIELDS, _add_VHVAR
|
|
6
|
+
from fontTools.varLib import builder, models, varStore
|
|
7
|
+
from fontTools.misc.fixedTools import fixedToFloat as fi2fl
|
|
8
|
+
from fontTools.misc.cliTools import makeOutputFileName
|
|
9
|
+
from functools import partial
|
|
10
|
+
import logging
|
|
11
|
+
|
|
12
|
+
log = logging.getLogger("fontTools.varLib.avar")
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
def _get_advance_metrics(font, axisTags, tableFields):
|
|
16
|
+
# There's two ways we can go from here:
|
|
17
|
+
# 1. For each glyph, at each master peak, compute the value of the
|
|
18
|
+
# advance width at that peak. Then pass these all to a VariationModel
|
|
19
|
+
# builder to compute back the deltas.
|
|
20
|
+
# 2. For each master peak, pull out the deltas of the advance width directly,
|
|
21
|
+
# and feed these to the VarStoreBuilder, forgoing the remoding step.
|
|
22
|
+
# We'll go with the second option, as it's simpler, faster, and more direct.
|
|
23
|
+
gvar = font["gvar"]
|
|
24
|
+
vhAdvanceDeltasAndSupports = {}
|
|
25
|
+
glyphOrder = font.getGlyphOrder()
|
|
26
|
+
phantomIndex = tableFields.phantomIndex
|
|
27
|
+
for glyphName in glyphOrder:
|
|
28
|
+
supports = []
|
|
29
|
+
deltas = []
|
|
30
|
+
variations = gvar.variations.get(glyphName, [])
|
|
31
|
+
|
|
32
|
+
for tv in variations:
|
|
33
|
+
supports.append(tv.axes)
|
|
34
|
+
phantoms = tv.coordinates[-4:]
|
|
35
|
+
phantoms = phantoms[phantomIndex * 2 : phantomIndex * 2 + 2]
|
|
36
|
+
assert len(phantoms) == 2
|
|
37
|
+
phantoms[0] = phantoms[0][phantomIndex] if phantoms[0] is not None else 0
|
|
38
|
+
phantoms[1] = phantoms[1][phantomIndex] if phantoms[1] is not None else 0
|
|
39
|
+
deltas.append(phantoms[1] - phantoms[0])
|
|
40
|
+
|
|
41
|
+
vhAdvanceDeltasAndSupports[glyphName] = (deltas, supports)
|
|
42
|
+
|
|
43
|
+
vOrigDeltasAndSupports = None # TODO
|
|
44
|
+
|
|
45
|
+
return vhAdvanceDeltasAndSupports, vOrigDeltasAndSupports
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
def add_HVAR(font):
|
|
49
|
+
if "HVAR" in font:
|
|
50
|
+
del font["HVAR"]
|
|
51
|
+
axisTags = [axis.axisTag for axis in font["fvar"].axes]
|
|
52
|
+
getAdvanceMetrics = partial(_get_advance_metrics, font, axisTags, HVAR_FIELDS)
|
|
53
|
+
_add_VHVAR(font, axisTags, HVAR_FIELDS, getAdvanceMetrics)
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
def add_VVAR(font):
|
|
57
|
+
if "VVAR" in font:
|
|
58
|
+
del font["VVAR"]
|
|
59
|
+
getAdvanceMetrics = partial(_get_advance_metrics, font, axisTags, HVAR_FIELDS)
|
|
60
|
+
axisTags = [axis.axisTag for axis in font["fvar"].axes]
|
|
61
|
+
_add_VHVAR(font, axisTags, VVAR_FIELDS, getAdvanceMetrics)
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
def main(args=None):
|
|
65
|
+
"""Add `HVAR` table to variable font."""
|
|
66
|
+
|
|
67
|
+
if args is None:
|
|
68
|
+
import sys
|
|
69
|
+
|
|
70
|
+
args = sys.argv[1:]
|
|
71
|
+
|
|
72
|
+
from fontTools import configLogger
|
|
73
|
+
from fontTools.designspaceLib import DesignSpaceDocument
|
|
74
|
+
import argparse
|
|
75
|
+
|
|
76
|
+
parser = argparse.ArgumentParser(
|
|
77
|
+
"fonttools varLib.hvar",
|
|
78
|
+
description="Add `HVAR` table from to variable font.",
|
|
79
|
+
)
|
|
80
|
+
parser.add_argument("font", metavar="varfont.ttf", help="Variable-font file.")
|
|
81
|
+
parser.add_argument(
|
|
82
|
+
"-o",
|
|
83
|
+
"--output-file",
|
|
84
|
+
type=str,
|
|
85
|
+
help="Output font file name.",
|
|
86
|
+
)
|
|
87
|
+
|
|
88
|
+
options = parser.parse_args(args)
|
|
89
|
+
|
|
90
|
+
configLogger(level="WARNING")
|
|
91
|
+
|
|
92
|
+
font = TTFont(options.font)
|
|
93
|
+
if not "fvar" in font:
|
|
94
|
+
log.error("Not a variable font.")
|
|
95
|
+
return 1
|
|
96
|
+
|
|
97
|
+
add_HVAR(font)
|
|
98
|
+
if "vmtx" in font:
|
|
99
|
+
add_VVAR(font)
|
|
100
|
+
|
|
101
|
+
if options.output_file is None:
|
|
102
|
+
outfile = makeOutputFileName(options.font, overWrite=True, suffix=".hvar")
|
|
103
|
+
else:
|
|
104
|
+
outfile = options.output_file
|
|
105
|
+
if outfile:
|
|
106
|
+
log.info("Saving %s", outfile)
|
|
107
|
+
font.save(outfile)
|
|
108
|
+
|
|
109
|
+
|
|
110
|
+
if __name__ == "__main__":
|
|
111
|
+
import sys
|
|
112
|
+
|
|
113
|
+
sys.exit(main())
|
fontTools/varLib/varStore.py
CHANGED
|
@@ -41,7 +41,7 @@ class OnlineVarStoreBuilder(object):
|
|
|
41
41
|
def setSupports(self, supports):
|
|
42
42
|
self._model = None
|
|
43
43
|
self._supports = list(supports)
|
|
44
|
-
if not self._supports[0]:
|
|
44
|
+
if self._supports and not self._supports[0]:
|
|
45
45
|
del self._supports[0] # Drop base master support
|
|
46
46
|
self._cache = None
|
|
47
47
|
self._data = None
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
Metadata-Version: 2.
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
2
|
Name: fonttools
|
|
3
|
-
Version: 4.
|
|
3
|
+
Version: 4.57.0
|
|
4
4
|
Summary: Tools to manipulate font files
|
|
5
5
|
Home-page: http://github.com/fonttools/fonttools
|
|
6
6
|
Author: Just van Rossum
|
|
@@ -80,6 +80,7 @@ Dynamic: description
|
|
|
80
80
|
Dynamic: description-content-type
|
|
81
81
|
Dynamic: home-page
|
|
82
82
|
Dynamic: license
|
|
83
|
+
Dynamic: license-file
|
|
83
84
|
Dynamic: maintainer
|
|
84
85
|
Dynamic: maintainer-email
|
|
85
86
|
Dynamic: platform
|
|
@@ -391,6 +392,19 @@ Have fun!
|
|
|
391
392
|
Changelog
|
|
392
393
|
~~~~~~~~~
|
|
393
394
|
|
|
395
|
+
4.57.0 (released 2025-04-03)
|
|
396
|
+
----------------------------
|
|
397
|
+
|
|
398
|
+
- [ttLib.__main__] Add `--no-recalc-timestamp` flag (#3771)
|
|
399
|
+
- [ttLib.__main__] Add `-b` (recalcBBoxes=False) flag (#3772)
|
|
400
|
+
- [cmap] Speed up glyphOrder loading from cmap (#3774)
|
|
401
|
+
- [ttLib.__main__] Improvements around the `-t` flag (#3776)
|
|
402
|
+
- [Debg] Fix parsing from XML; add roundtrip tests (#3781)
|
|
403
|
+
- [fealib] Support \*Base.MinMax tables (#3783, #3786)
|
|
404
|
+
- [config] Add OPTIMIZE_FONT_SPEED (#3784)
|
|
405
|
+
- [varLib.hvar] New module to add HVAR table to the font (#3780)
|
|
406
|
+
- [otlLib.optimize] Fix crash when the provided TTF does not contain a `GPOS` (#3794)
|
|
407
|
+
|
|
394
408
|
4.56.0 (released 2025-02-07)
|
|
395
409
|
----------------------------
|
|
396
410
|
|
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
fontTools/__init__.py,sha256=
|
|
1
|
+
fontTools/__init__.py,sha256=T6Ml6H9-1VxuIVSMFDaDfwROmdl2-KslvDAmyvrgNEU,183
|
|
2
2
|
fontTools/__main__.py,sha256=VjkGh1UD-i1zTDA1dXo1uecSs6PxHdGQ5vlCk_mCCYs,925
|
|
3
3
|
fontTools/afmLib.py,sha256=1MagIItOzRV4vV5kKPxeDZbPJsfxLB3wdHLFkQvl0uk,13164
|
|
4
4
|
fontTools/agl.py,sha256=05bm8Uq45uVWW8nPbP6xbNgmFyxQr8sWhYAiP0VSjnI,112975
|
|
5
5
|
fontTools/fontBuilder.py,sha256=ntG0lXnhXNcHK-C7bp0nGNQ68OutFA-84TNNpzntTcE,33952
|
|
6
6
|
fontTools/help.py,sha256=bAjatvIhV7TJyXI7WhsxdYO4YVlhScZXu_kRtHANEPo,1125
|
|
7
7
|
fontTools/tfmLib.py,sha256=UMbkM73JXRJVS9t2B-BJc13rSjImaWBuzCoehLwHFhs,14270
|
|
8
|
-
fontTools/ttx.py,sha256=
|
|
8
|
+
fontTools/ttx.py,sha256=FxuGubujWCGJWSTrJEjoNH--25fVIPy-ZRtYy9H6iTk,17277
|
|
9
9
|
fontTools/unicode.py,sha256=ZZ7OMmWvIyV1IL1k6ioTzaRAh3tUvm6gvK7QgFbOIHY,1237
|
|
10
10
|
fontTools/cffLib/CFF2ToCFF.py,sha256=pvwh6qxJ0D7c4xgXBcyAdmZGzpTiywMy45-jjp7dKck,6088
|
|
11
11
|
fontTools/cffLib/CFFToCFF2.py,sha256=Qnk7lYlsTRHnlZQ6NXNdr_f4MJwZQ21kcS08KFbsyY8,10119
|
|
@@ -19,7 +19,7 @@ fontTools/colorLib/errors.py,sha256=CsaviiRxxrpgVX4blm7KCyK8553ljwL44xkJOeC5U7U,
|
|
|
19
19
|
fontTools/colorLib/geometry.py,sha256=3ScySrR2YDJa7d5K5_xM5Yt1-3NCV-ry8ikYA5VwVbI,5518
|
|
20
20
|
fontTools/colorLib/table_builder.py,sha256=ZeltWY6n-YPiJv_hQ1iBXoEFAG70EKxZyScgsMKUFGU,7469
|
|
21
21
|
fontTools/colorLib/unbuilder.py,sha256=iW-E5I39WsV82K3NgCO4Cjzwm1WqzGrtypHt8epwbHM,2142
|
|
22
|
-
fontTools/config/__init__.py,sha256=
|
|
22
|
+
fontTools/config/__init__.py,sha256=JICOHIz06KuHCiBmrxj-ga19P6ZTuLXh0lHmPh-Ra1w,3154
|
|
23
23
|
fontTools/cu2qu/__init__.py,sha256=Cuc7Uglb0nSgaraTxXY5J8bReznH5wApW0uakN7MycY,618
|
|
24
24
|
fontTools/cu2qu/__main__.py,sha256=kTUI-jczsHeelULLlory74QEeFjZWp9zigCc7PrdVQY,92
|
|
25
25
|
fontTools/cu2qu/benchmark.py,sha256=wasPJmf8q9k9UHjpHChC3WQAGbBAyHN9PvJzXvWC0Fw,1296
|
|
@@ -38,13 +38,13 @@ fontTools/encodings/__init__.py,sha256=DJBWmoX_Haau7qlgmvWyfbhSzrX2qL636Rns7CG01
|
|
|
38
38
|
fontTools/encodings/codecs.py,sha256=u50ruwz9fcRsrUrRGpR17Cr55Ovn1fvCHCKrElVumDE,4721
|
|
39
39
|
fontTools/feaLib/__init__.py,sha256=jlIru2ghxvb1HhC5Je2BCXjFJmFQlYKpruorPoz3BvQ,213
|
|
40
40
|
fontTools/feaLib/__main__.py,sha256=Df2PA6LXwna98lSXiL7R4as_ZEdWCIk3egSM5w7GpvM,2240
|
|
41
|
-
fontTools/feaLib/ast.py,sha256=
|
|
42
|
-
fontTools/feaLib/builder.py,sha256=
|
|
41
|
+
fontTools/feaLib/ast.py,sha256=koL7JLGrNWbABNLq4QrkKBFETKNEjSSC7dirZTFemqU,74050
|
|
42
|
+
fontTools/feaLib/builder.py,sha256=1rLV3zwA3JFXpZ452DXM8Y8E6NxAvcszzmOwFNvomqA,72101
|
|
43
43
|
fontTools/feaLib/error.py,sha256=Bz_5tNcNVcY7_nrAmFlQNhQldtqZWd8WUGQ2E3PWhZo,648
|
|
44
44
|
fontTools/feaLib/lexer.py,sha256=emyMPmRoqNZkzxnJyI6JRCCtXrbCOFofwa9O6ABGLiw,11121
|
|
45
45
|
fontTools/feaLib/location.py,sha256=JXzHqGV56EHdcq823AwA5oaK05hf_1ySWpScbo3zGC0,234
|
|
46
46
|
fontTools/feaLib/lookupDebugInfo.py,sha256=gVRr5-APWfT_a5-25hRuawSVX8fEvXVsOSLWkH91T2w,304
|
|
47
|
-
fontTools/feaLib/parser.py,sha256=
|
|
47
|
+
fontTools/feaLib/parser.py,sha256=GRbPbMP2z9zOkScN-Zw7TCuPQ7UXT9UhZYENp4eaX1c,101085
|
|
48
48
|
fontTools/feaLib/variableScalar.py,sha256=Xu8tpDlQbfIfjnKnYDEf43EqVdyIJUy8_1ROVPg9_mg,4069
|
|
49
49
|
fontTools/merge/__init__.py,sha256=-l65-mbTwSh0gjarnojIfsAX-ZkMtdz3vGTjtYHQ2ws,8250
|
|
50
50
|
fontTools/merge/__main__.py,sha256=hDx3gfbUBO83AJKumSEhiV-xqNTJNNgK2uFjazOGTmw,94
|
|
@@ -81,7 +81,7 @@ fontTools/misc/py23.py,sha256=aPVCEUz_deggwLBCeTSsccX6QgJavZqvdVtuhpzrPvA,2238
|
|
|
81
81
|
fontTools/misc/roundTools.py,sha256=1RSXZ0gyi1qW42tz6WSBMJD1FlPdtgqKfWixVN9bd78,3173
|
|
82
82
|
fontTools/misc/sstruct.py,sha256=HuXwoRr9-mAbBxI3gJ3n34ML7NAGSHsAAazaaloWQB4,7158
|
|
83
83
|
fontTools/misc/symfont.py,sha256=SJtc3-9VdhT6fokx5Vvzs7YErqRib1u-rItNqXI0rTM,6991
|
|
84
|
-
fontTools/misc/testTools.py,sha256=
|
|
84
|
+
fontTools/misc/testTools.py,sha256=3vj_KllUQVEiVFbS0SzTmeuKv44-L-disI1dZ4XhOfw,7052
|
|
85
85
|
fontTools/misc/textTools.py,sha256=pbhr6LVhm3J-0Z4saYnJfxBDzyoiw4BR9pAgwypiOw8,3377
|
|
86
86
|
fontTools/misc/timeTools.py,sha256=e9h5pgzL04tBDXmCv_8eRGB4boFV8GKXlS6dq3ggEpw,2234
|
|
87
87
|
fontTools/misc/transform.py,sha256=OR8dPsAw87z77gkZQMq00iUkDWLIxYv-12XiKH1-erk,15798
|
|
@@ -100,7 +100,7 @@ fontTools/otlLib/error.py,sha256=cthuhBuOwZYpkTLi5gFPupUxkXkCHe-L_YgkE7N1wCI,335
|
|
|
100
100
|
fontTools/otlLib/maxContextCalc.py,sha256=3es4Kt84TaZ49sA2ev1zrlwPJikJCAECx5KavwhyB-I,3175
|
|
101
101
|
fontTools/otlLib/optimize/__init__.py,sha256=UUQRpNkHU2RczCRt-Gz7sEiYE9AQq9BHLXZEOyvsnX4,1530
|
|
102
102
|
fontTools/otlLib/optimize/__main__.py,sha256=BvP472kA9KxBb9RMyyehPNevAfpmgW9MfdazkUiAO3M,104
|
|
103
|
-
fontTools/otlLib/optimize/gpos.py,sha256=
|
|
103
|
+
fontTools/otlLib/optimize/gpos.py,sha256=tbIfKaPalP3FwNBxOBcNvSRUXLbysMmPAUvbeqofhXs,18595
|
|
104
104
|
fontTools/pens/__init__.py,sha256=DJBWmoX_Haau7qlgmvWyfbhSzrX2qL636Rns7CG01pk,75
|
|
105
105
|
fontTools/pens/areaPen.py,sha256=Y1WkmqzcC4z_bpGAR0IZUKrtHFtxKUQBmr5-64_zCOk,1472
|
|
106
106
|
fontTools/pens/basePen.py,sha256=eIGSKrKm6w4LLHuG6XJoQZ3eObtoKV5P6aF4gT4sk7U,17073
|
|
@@ -146,8 +146,8 @@ fontTools/svgLib/path/arc.py,sha256=-f5Ym6q4tDWQ76sMNSTUTWgL_7AfgXojvBhtBS7bWwQ,
|
|
|
146
146
|
fontTools/svgLib/path/parser.py,sha256=8T6okMstvgM9ufb2zBcwSzsuuoYbqfnUjNYgb6kjznU,10788
|
|
147
147
|
fontTools/svgLib/path/shapes.py,sha256=xvBUIckKyT9JLy7q_ZP50r6TjvZANyHdZP7wFDzErcI,5322
|
|
148
148
|
fontTools/t1Lib/__init__.py,sha256=p42y70wEIbuX0IIxZG7-b_I-gHto1VLy0gLsDvxCfkw,20865
|
|
149
|
-
fontTools/ttLib/__init__.py,sha256=
|
|
150
|
-
fontTools/ttLib/__main__.py,sha256=
|
|
149
|
+
fontTools/ttLib/__init__.py,sha256=1k7qp9z04gA3m6GvxDaINjqrKbzOkdTA_4RnqW_-LrA,661
|
|
150
|
+
fontTools/ttLib/__main__.py,sha256=lHMPWsnzjKPuMFavf6i1gpk9KexiAk4qzgDd50Mbby0,4733
|
|
151
151
|
fontTools/ttLib/macUtils.py,sha256=lj3oeFpyjV7ko_JqnluneITmAtlc119J-vwTTg2s73A,1737
|
|
152
152
|
fontTools/ttLib/removeOverlaps.py,sha256=YBtj1PX-d2jMgCiWGuI6ibghWApUWqH2trJGXNxrbjQ,12612
|
|
153
153
|
fontTools/ttLib/reorderGlyphs.py,sha256=8ClsX9-tnPfuiD8kHY4jPliGJ-31-JdybA4s1UNWx4w,10316
|
|
@@ -155,8 +155,8 @@ fontTools/ttLib/scaleUpem.py,sha256=U_-NGkwfS9GRIackdEXjGYZ-wSomcUPXQahDneLeArI,
|
|
|
155
155
|
fontTools/ttLib/sfnt.py,sha256=rkznKfteU_Rn9P65WSjFaiwQgpEAoh-TrQpvkQhdIlo,22832
|
|
156
156
|
fontTools/ttLib/standardGlyphOrder.py,sha256=7AY_fVWdtwZ4iv5uWdyKAUcbEQiSDt1lN4sqx9xXwE0,5785
|
|
157
157
|
fontTools/ttLib/ttCollection.py,sha256=aRph2MkBK3kd9-JCLqhJ1EN9pffN_lVX6WWmOTTewc8,3963
|
|
158
|
-
fontTools/ttLib/ttFont.py,sha256=
|
|
159
|
-
fontTools/ttLib/ttGlyphSet.py,sha256=
|
|
158
|
+
fontTools/ttLib/ttFont.py,sha256=rTGWNOiTW5mnFFN1HrYIi1HzihBXyJOvhhpsxhYwKnA,40965
|
|
159
|
+
fontTools/ttLib/ttGlyphSet.py,sha256=cUBhMGa5hszeVqOm2KpOdeJh-LsiqE7RNdyIUPZ2vO8,17476
|
|
160
160
|
fontTools/ttLib/ttVisitor.py,sha256=_tah4C42Tv6Pm9QeLNQwwVCxqI4VNEAqYCbmThp6cvY,1025
|
|
161
161
|
fontTools/ttLib/woff2.py,sha256=Ryw4WVwUFMtdEo9FcIejP1OTV92Z4B9y5Wq7nWDW3lE,61058
|
|
162
162
|
fontTools/ttLib/tables/B_A_S_E_.py,sha256=H71A9pJ850mvjbrWHqy8iFI2Dxg7102YRtAkfdCooig,369
|
|
@@ -168,7 +168,7 @@ fontTools/ttLib/tables/C_F_F__2.py,sha256=YoHfJQdF-ezx4OwRQ2Y2O7rRJEPjOkf3Hx5Y11
|
|
|
168
168
|
fontTools/ttLib/tables/C_O_L_R_.py,sha256=SHwFVNVmoUQR2e87KuTSe-J9LfeegS4f2hEpee29_2o,5993
|
|
169
169
|
fontTools/ttLib/tables/C_P_A_L_.py,sha256=odFjqM4GnjXyQYGEC-e0Gvqms1jQ5zHHG3SDg7y-BI0,11942
|
|
170
170
|
fontTools/ttLib/tables/D_S_I_G_.py,sha256=AgQPM9Cdro1P-ehJjTfsC9mRTTtSc16At0nnpb1XOGI,5517
|
|
171
|
-
fontTools/ttLib/tables/D__e_b_g.py,sha256=
|
|
171
|
+
fontTools/ttLib/tables/D__e_b_g.py,sha256=KDnfkNOUnm3F13wD_j3YNBOvYadZ40Gf_0170hFkJp0,1134
|
|
172
172
|
fontTools/ttLib/tables/DefaultTable.py,sha256=cOtgkLWPY9qmOH2BSPt4c4IUSdANWTKx2rK1CTxQ4h0,1487
|
|
173
173
|
fontTools/ttLib/tables/E_B_D_T_.py,sha256=uOpmt25gOJQeO1u1IGAyPWgVmh-4vSZqrQEHvOYwbwg,32534
|
|
174
174
|
fontTools/ttLib/tables/E_B_L_C_.py,sha256=LfEVzBg_yWr9dhChzS0U2G-7wNOwzwB0LWoXIUYNKKM,30054
|
|
@@ -216,7 +216,7 @@ fontTools/ttLib/tables/_a_n_k_r.py,sha256=MpAzIifmIi_3gx2oP6PC3R2lu36Ewsr2-W1rXj
|
|
|
216
216
|
fontTools/ttLib/tables/_a_v_a_r.py,sha256=QnjP8oO-hozKcI21_bRC-_SzZxVqcHC2VLDyNs4aH9U,7116
|
|
217
217
|
fontTools/ttLib/tables/_b_s_l_n.py,sha256=_848o7SQqztzBDfHYei-80u9ltxIHVBzXu1dYHLV57M,465
|
|
218
218
|
fontTools/ttLib/tables/_c_i_d_g.py,sha256=yt8rVIadpJSDUCoVH4dZetNiy0Azm5ESAxHjB2BX_eA,913
|
|
219
|
-
fontTools/ttLib/tables/_c_m_a_p.py,sha256=
|
|
219
|
+
fontTools/ttLib/tables/_c_m_a_p.py,sha256=0P0z1lYtQG4OgV_Bo3n1ciq1XKD2ANdfoOV5cSzN4Ig,62208
|
|
220
220
|
fontTools/ttLib/tables/_c_v_a_r.py,sha256=35ayk2kX1pcLGwyx0y4I1l-r7LHgdKv0ulVx8oBPteI,3527
|
|
221
221
|
fontTools/ttLib/tables/_c_v_t.py,sha256=mB7xAG_q-F4z_Gdwj0XLvfybTJ1bwsZkb2QDnhc0zjQ,1584
|
|
222
222
|
fontTools/ttLib/tables/_f_e_a_t.py,sha256=Fi1XnjhkCG0tp43AcvpIaivD-YRFpufo6feGIrenQDo,469
|
|
@@ -224,8 +224,8 @@ fontTools/ttLib/tables/_f_p_g_m.py,sha256=t1T6lfuoJv1ImKu7X4h6jg2S6B4rxQZSlDrnZ5
|
|
|
224
224
|
fontTools/ttLib/tables/_f_v_a_r.py,sha256=rV33H2BgHUl3Wuydsou1G-Hi4uASBppWaLj3FMmiLjs,8837
|
|
225
225
|
fontTools/ttLib/tables/_g_a_s_p.py,sha256=YvhAVDvdssN2fjPMTfSrO4WBCfTuh9T2cU5zquDVnSw,2203
|
|
226
226
|
fontTools/ttLib/tables/_g_c_i_d.py,sha256=AJ4uV7PTHbnsw4Tfw8c2Ezh0VMox3oAH0qhhq7y8hdM,362
|
|
227
|
-
fontTools/ttLib/tables/_g_l_y_f.py,sha256=
|
|
228
|
-
fontTools/ttLib/tables/_g_v_a_r.py,sha256=
|
|
227
|
+
fontTools/ttLib/tables/_g_l_y_f.py,sha256=37o4JyVctndRK0n_q4NwyDs4idlH1766a6QuEQs02Pc,85696
|
|
228
|
+
fontTools/ttLib/tables/_g_v_a_r.py,sha256=Fbm6ECXix65MGJvwIdKdgEJlaLhq_yEgkePdDGdYlQk,10824
|
|
229
229
|
fontTools/ttLib/tables/_h_d_m_x.py,sha256=kgydwtD1ibF3T0Vbohq-aM_QD8PY-vp4oUuWQWJJMNA,4271
|
|
230
230
|
fontTools/ttLib/tables/_h_e_a_d.py,sha256=yY2GTFq6Mn6nN8EegbMVJRMUWIqDYFln3FhTk3ziw6s,4926
|
|
231
231
|
fontTools/ttLib/tables/_h_h_e_a.py,sha256=X4t1aF1MZMuz3phCVSFwKcNTeoZdx-042wFtHc-nK9w,4767
|
|
@@ -250,9 +250,9 @@ fontTools/ttLib/tables/_v_m_t_x.py,sha256=AUuxtyQvMWrTBNbOIaL6uKcB_DNpNb0YX28JIu
|
|
|
250
250
|
fontTools/ttLib/tables/asciiTable.py,sha256=4c69jsAirUnDEpylf9CYBoCKTzwbmfbtUAOrtPnpHjY,637
|
|
251
251
|
fontTools/ttLib/tables/grUtils.py,sha256=hcOJ5oJPOd2uJWnWA7qwR7AfL37YZ5zUT7g8o5BBV80,2270
|
|
252
252
|
fontTools/ttLib/tables/otBase.py,sha256=Vq8fv4lm-e3oPCuSPcWTNMQI2KmX0iOIz_lO9kE1mKE,53355
|
|
253
|
-
fontTools/ttLib/tables/otConverters.py,sha256=
|
|
253
|
+
fontTools/ttLib/tables/otConverters.py,sha256=ihE_WMSKAKSaBbMvnFYDj2eMxf7PvRMMa8zGwfoYuYc,74202
|
|
254
254
|
fontTools/ttLib/tables/otData.py,sha256=-XXRwdVfP-Wz7oBjMPpku0A0QH9lw_fFGNzZlt9N0mo,197262
|
|
255
|
-
fontTools/ttLib/tables/otTables.py,sha256=
|
|
255
|
+
fontTools/ttLib/tables/otTables.py,sha256=IZQY8Scf8JFsUD28LY1csC8bvFbfY-aURH6YaQ3Ao24,97128
|
|
256
256
|
fontTools/ttLib/tables/otTraverse.py,sha256=HznEVAlVf_8eyqjsO2edgELtMlXnjnUqccK3PytvVUE,5518
|
|
257
257
|
fontTools/ttLib/tables/sbixGlyph.py,sha256=tjEUPVRfx6gr5yme8UytGTtVrimKN5qmbzT1GZPjXiM,5796
|
|
258
258
|
fontTools/ttLib/tables/sbixStrike.py,sha256=gFyOlhRIGnd59y0SrhtsT2Ce4L3yaBrLoFJ_dK9u9mQ,6663
|
|
@@ -274,7 +274,7 @@ fontTools/unicodedata/OTTags.py,sha256=wOPpbMsNcp_gdvPFeITtgVMnTN8TJSNAsVEdu_nuP
|
|
|
274
274
|
fontTools/unicodedata/ScriptExtensions.py,sha256=YTZr2bOteHiz_7I4108PRy0Is4kFof-32yFuoKjFHjc,28207
|
|
275
275
|
fontTools/unicodedata/Scripts.py,sha256=I0nY08ovsZ4pHU5wYchjat9DjnxcpoTzaXAn5oFaKNI,130271
|
|
276
276
|
fontTools/unicodedata/__init__.py,sha256=DOCX0X9-Eo3mEju7Zjgcod7d8aswTo3vjDRzV7-8Z4g,8824
|
|
277
|
-
fontTools/varLib/__init__.py,sha256=
|
|
277
|
+
fontTools/varLib/__init__.py,sha256=EOA9Tl3qOd72YtvmYBhE7H0MdcA2Oaxg7ZpPDeDnbmc,53619
|
|
278
278
|
fontTools/varLib/__main__.py,sha256=wbdYC5bPjWCxA0I4SKcLO88gl-UMtsYS8MxdW9ySTkY,95
|
|
279
279
|
fontTools/varLib/avar.py,sha256=Ye_u0HHznaPQaTzufNFKDj_v9o_LxOKJoa_eTK1D1F0,9647
|
|
280
280
|
fontTools/varLib/avarPlanner.py,sha256=uLMGsL6cBbEMq5YItwABG_vXlXV3bxquM93WGDJ1brA,27358
|
|
@@ -282,6 +282,7 @@ fontTools/varLib/builder.py,sha256=mSKOCcnnw-WzmZs15FayoqCDh77Ts7o9Tre9psh8CUc,6
|
|
|
282
282
|
fontTools/varLib/cff.py,sha256=EVgaQcoROIrYQsRuftnxFuGGldEPYbrIh5yBckylJC4,22901
|
|
283
283
|
fontTools/varLib/errors.py,sha256=dMo8eGj76I7H4hrBEiNbYrGs2J1K1SwdsUyTHpkVOrQ,6934
|
|
284
284
|
fontTools/varLib/featureVars.py,sha256=BCOBGjGUv2Rw_z0rlVi1ZYkTDcCMh0LyAUzDVJ2PYm4,25448
|
|
285
|
+
fontTools/varLib/hvar.py,sha256=4W5t3s7GOBN07x9KNDmA_4NGXxVEEahzkn3cWJZ4oGw,3693
|
|
285
286
|
fontTools/varLib/interpolatable.py,sha256=Bhlq_LhEZ-sXfLNY8aFEChFrsKuT2kzmnuMfG5qi0v4,45221
|
|
286
287
|
fontTools/varLib/interpolatableHelpers.py,sha256=lXd7kwfIVl-4opd-vxCDhf48RnJ7IQKv_uuFQM_6vaU,11496
|
|
287
288
|
fontTools/varLib/interpolatablePlot.py,sha256=w393P6mGLRhYkIjSxMww3qyoYxAUZzCXlmPBbI_84C0,44375
|
|
@@ -296,7 +297,7 @@ fontTools/varLib/mutator.py,sha256=YJkKFFWjwpYZ1MrC7UZYJ1BuYTGiwgi7jHnpqNpKfKg,1
|
|
|
296
297
|
fontTools/varLib/mvar.py,sha256=LTV77vH_3Ecg_qKBO5xQzjLOlJir_ppEr7mPVZRgad8,2449
|
|
297
298
|
fontTools/varLib/plot.py,sha256=NoSZkJ5ndxNcDvJIvd5pQ9_jX6X1oM1K2G_tR4sdPVs,7494
|
|
298
299
|
fontTools/varLib/stat.py,sha256=XuNKKZxGlBrl4OGFDAwVXhpBwJi23U3BdHmNTKoJnvE,4811
|
|
299
|
-
fontTools/varLib/varStore.py,sha256=
|
|
300
|
+
fontTools/varLib/varStore.py,sha256=2QA9SDI6jQyQ_zq82OOwa3FBkfl-ksaSo1KGmVFpa9Q,24069
|
|
300
301
|
fontTools/varLib/instancer/__init__.py,sha256=wFqRVbww2CjuJk3MPDQ2HGmpNBGNQd9JF58KQoBl8_c,71346
|
|
301
302
|
fontTools/varLib/instancer/__main__.py,sha256=zfULwcP01FhplS1IlcMgNQnLxk5RVfmOuinWjqeid-g,104
|
|
302
303
|
fontTools/varLib/instancer/featureVars.py,sha256=oPqSlnHLMDTtOsmQMi6gkzLox7ymCrqlRAkvC_EJ4bc,7110
|
|
@@ -308,10 +309,10 @@ fontTools/voltLib/error.py,sha256=phcQOQj-xOspCXu9hBJQRhSOBDzxHRgZd3fWQOFNJzw,39
|
|
|
308
309
|
fontTools/voltLib/lexer.py,sha256=OvuETOSvlS6v7iCVeJ3IdH2Cg71n3OJoEyiB3-h6vhE,3368
|
|
309
310
|
fontTools/voltLib/parser.py,sha256=wBSUrjLT3fSPv9Mjx6_ULIf8IcGlwjtb4Auxjh5wqnc,24916
|
|
310
311
|
fontTools/voltLib/voltToFea.py,sha256=igP7_E-7AzSl8f_LiN_GHMoNmFiXPBaXp_zZLndjU4c,28505
|
|
311
|
-
fonttools-4.
|
|
312
|
-
fonttools-4.
|
|
313
|
-
fonttools-4.
|
|
314
|
-
fonttools-4.
|
|
315
|
-
fonttools-4.
|
|
316
|
-
fonttools-4.
|
|
317
|
-
fonttools-4.
|
|
312
|
+
fonttools-4.57.0.data/data/share/man/man1/ttx.1,sha256=cLbm_pOOj1C76T2QXvDxzwDj9gk-GTd5RztvTMsouFw,5377
|
|
313
|
+
fonttools-4.57.0.dist-info/licenses/LICENSE,sha256=Z4cgj4P2Wcy8IiOy_elS_6b36KymLxqKK_W8UbsbI4M,1072
|
|
314
|
+
fonttools-4.57.0.dist-info/METADATA,sha256=lqvLLeINsYTJX7jelqex2SkxGaBysfnX87V4AT-_p9k,102535
|
|
315
|
+
fonttools-4.57.0.dist-info/WHEEL,sha256=CmyFI0kx5cdEMTLiONQRbGQwjIoR1aIYB7eCAQ4KPJ0,91
|
|
316
|
+
fonttools-4.57.0.dist-info/entry_points.txt,sha256=8kVHddxfFWA44FSD4mBpmC-4uCynQnkoz_9aNJb227Y,147
|
|
317
|
+
fonttools-4.57.0.dist-info/top_level.txt,sha256=rRgRylrXzekqWOsrhygzib12pQ7WILf7UGjqEwkIFDM,10
|
|
318
|
+
fonttools-4.57.0.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|