fonttools 4.58.5__py3-none-any.whl → 4.59.1__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/cffLib/CFF2ToCFF.py +40 -10
- fontTools/cffLib/transforms.py +11 -6
- fontTools/feaLib/builder.py +6 -1
- fontTools/merge/__init__.py +1 -1
- fontTools/misc/filesystem/__init__.py +68 -0
- fontTools/misc/filesystem/_base.py +134 -0
- fontTools/misc/filesystem/_copy.py +45 -0
- fontTools/misc/filesystem/_errors.py +54 -0
- fontTools/misc/filesystem/_info.py +75 -0
- fontTools/misc/filesystem/_osfs.py +164 -0
- fontTools/misc/filesystem/_path.py +67 -0
- fontTools/misc/filesystem/_subfs.py +92 -0
- fontTools/misc/filesystem/_tempfs.py +34 -0
- fontTools/misc/filesystem/_tools.py +34 -0
- fontTools/misc/filesystem/_walk.py +55 -0
- fontTools/misc/filesystem/_zipfs.py +204 -0
- fontTools/misc/psCharStrings.py +17 -2
- fontTools/misc/sstruct.py +2 -6
- fontTools/misc/xmlWriter.py +28 -1
- fontTools/pens/roundingPen.py +2 -2
- fontTools/subset/__init__.py +11 -11
- fontTools/ttLib/sfnt.py +2 -3
- fontTools/ttLib/tables/S__i_l_f.py +2 -2
- fontTools/ttLib/tables/T_S_I__1.py +2 -5
- fontTools/ttLib/tables/T_S_I__5.py +2 -2
- fontTools/ttLib/tables/_c_m_a_p.py +1 -1
- fontTools/ttLib/tables/_c_v_t.py +1 -2
- fontTools/ttLib/tables/_g_l_y_f.py +9 -10
- fontTools/ttLib/tables/_g_v_a_r.py +6 -3
- fontTools/ttLib/tables/_h_d_m_x.py +4 -4
- fontTools/ttLib/tables/_h_m_t_x.py +7 -3
- fontTools/ttLib/tables/_l_o_c_a.py +2 -2
- fontTools/ttLib/tables/_p_o_s_t.py +3 -4
- fontTools/ttLib/tables/otBase.py +2 -4
- fontTools/ttLib/tables/otTables.py +7 -12
- fontTools/ttLib/tables/sbixStrike.py +3 -3
- fontTools/ttLib/ttFont.py +7 -16
- fontTools/ttLib/woff2.py +10 -13
- fontTools/ufoLib/__init__.py +20 -25
- fontTools/ufoLib/glifLib.py +12 -17
- fontTools/ufoLib/validators.py +2 -4
- fontTools/unicodedata/__init__.py +2 -0
- fontTools/varLib/featureVars.py +8 -0
- fontTools/varLib/hvar.py +1 -1
- fontTools/varLib/instancer/__init__.py +65 -5
- fontTools/varLib/mutator.py +11 -0
- {fonttools-4.58.5.dist-info → fonttools-4.59.1.dist-info}/METADATA +42 -12
- {fonttools-4.58.5.dist-info → fonttools-4.59.1.dist-info}/RECORD +55 -43
- {fonttools-4.58.5.dist-info → fonttools-4.59.1.dist-info}/licenses/LICENSE.external +29 -0
- {fonttools-4.58.5.data → fonttools-4.59.1.data}/data/share/man/man1/ttx.1 +0 -0
- {fonttools-4.58.5.dist-info → fonttools-4.59.1.dist-info}/WHEEL +0 -0
- {fonttools-4.58.5.dist-info → fonttools-4.59.1.dist-info}/entry_points.txt +0 -0
- {fonttools-4.58.5.dist-info → fonttools-4.59.1.dist-info}/licenses/LICENSE +0 -0
- {fonttools-4.58.5.dist-info → fonttools-4.59.1.dist-info}/top_level.txt +0 -0
fontTools/ufoLib/__init__.py
CHANGED
|
@@ -32,30 +32,27 @@ Value conversion functions are available for converting
|
|
|
32
32
|
- :func:`.convertFontInfoValueForAttributeFromVersion3ToVersion2`
|
|
33
33
|
"""
|
|
34
34
|
|
|
35
|
-
import
|
|
36
|
-
from copy import deepcopy
|
|
37
|
-
from os import fsdecode
|
|
35
|
+
import enum
|
|
38
36
|
import logging
|
|
37
|
+
import os
|
|
39
38
|
import zipfile
|
|
40
|
-
import enum
|
|
41
39
|
from collections import OrderedDict
|
|
42
|
-
import
|
|
43
|
-
import
|
|
44
|
-
|
|
45
|
-
import fs
|
|
46
|
-
import fs.copy
|
|
47
|
-
import fs.osfs
|
|
48
|
-
import fs.zipfs
|
|
49
|
-
import fs.tempfs
|
|
50
|
-
import fs.tools
|
|
40
|
+
from copy import deepcopy
|
|
41
|
+
from os import fsdecode
|
|
42
|
+
|
|
43
|
+
from fontTools.misc import filesystem as fs
|
|
51
44
|
from fontTools.misc import plistlib
|
|
52
|
-
from fontTools.ufoLib.validators import *
|
|
53
|
-
from fontTools.ufoLib.filenames import userNameToFileName
|
|
54
45
|
from fontTools.ufoLib.converters import convertUFO1OrUFO2KerningToUFO3Kerning
|
|
55
46
|
from fontTools.ufoLib.errors import UFOLibError
|
|
56
|
-
from fontTools.ufoLib.
|
|
47
|
+
from fontTools.ufoLib.filenames import userNameToFileName
|
|
48
|
+
from fontTools.ufoLib.utils import _VersionTupleEnumMixin, numberTypes
|
|
49
|
+
from fontTools.ufoLib.validators import *
|
|
50
|
+
|
|
51
|
+
# client code can check this to see if the upstream `fs` package is being used
|
|
52
|
+
haveFS = fs._haveFS
|
|
57
53
|
|
|
58
54
|
__all__ = [
|
|
55
|
+
"haveFS",
|
|
59
56
|
"makeUFOPath",
|
|
60
57
|
"UFOLibError",
|
|
61
58
|
"UFOReader",
|
|
@@ -184,7 +181,7 @@ class _UFOBaseIO:
|
|
|
184
181
|
return
|
|
185
182
|
self.fs.writebytes(fileName, data)
|
|
186
183
|
else:
|
|
187
|
-
with self.fs.
|
|
184
|
+
with self.fs.open(fileName, mode="wb") as fp:
|
|
188
185
|
try:
|
|
189
186
|
plistlib.dump(obj, fp)
|
|
190
187
|
except Exception as e:
|
|
@@ -412,7 +409,7 @@ class UFOReader(_UFOBaseIO):
|
|
|
412
409
|
path = fsdecode(path)
|
|
413
410
|
try:
|
|
414
411
|
if encoding is None:
|
|
415
|
-
return self.fs.
|
|
412
|
+
return self.fs.open(path, mode="rb")
|
|
416
413
|
else:
|
|
417
414
|
return self.fs.open(path, mode="r", encoding=encoding)
|
|
418
415
|
except fs.errors.ResourceNotFound:
|
|
@@ -818,7 +815,7 @@ class UFOReader(_UFOBaseIO):
|
|
|
818
815
|
# systems often have hidden directories
|
|
819
816
|
continue
|
|
820
817
|
if validate:
|
|
821
|
-
with imagesFS.
|
|
818
|
+
with imagesFS.open(path.name, "rb") as fp:
|
|
822
819
|
valid, error = pngValidator(fileObj=fp)
|
|
823
820
|
if valid:
|
|
824
821
|
result.append(path.name)
|
|
@@ -984,18 +981,16 @@ class UFOWriter(UFOReader):
|
|
|
984
981
|
% len(rootDirs)
|
|
985
982
|
)
|
|
986
983
|
else:
|
|
987
|
-
|
|
988
|
-
# when its root subdirectory is closed
|
|
989
|
-
self.fs = parentFS.opendir(
|
|
990
|
-
rootDirs[0], factory=fs.subfs.ClosingSubFS
|
|
991
|
-
)
|
|
984
|
+
rootDir = rootDirs[0]
|
|
992
985
|
else:
|
|
993
986
|
# if the output zip file didn't exist, we create the root folder;
|
|
994
987
|
# we name it the same as input 'path', but with '.ufo' extension
|
|
995
988
|
rootDir = os.path.splitext(os.path.basename(path))[0] + ".ufo"
|
|
996
989
|
parentFS = fs.zipfs.ZipFS(path, write=True, encoding="utf-8")
|
|
997
990
|
parentFS.makedir(rootDir)
|
|
998
|
-
|
|
991
|
+
# 'ClosingSubFS' ensures that the parent filesystem is closed
|
|
992
|
+
# when its root subdirectory is closed
|
|
993
|
+
self.fs = parentFS.opendir(rootDir, factory=fs.subfs.ClosingSubFS)
|
|
999
994
|
else:
|
|
1000
995
|
self.fs = fs.osfs.OSFS(path, create=True)
|
|
1001
996
|
self._fileStructure = structure
|
fontTools/ufoLib/glifLib.py
CHANGED
|
@@ -3,7 +3,7 @@ Generic module for reading and writing the .glif format.
|
|
|
3
3
|
|
|
4
4
|
More info about the .glif format (GLyphInterchangeFormat) can be found here:
|
|
5
5
|
|
|
6
|
-
|
|
6
|
+
http://unifiedfontobject.org
|
|
7
7
|
|
|
8
8
|
The main class in this module is :class:`GlyphSet`. It manages a set of .glif files
|
|
9
9
|
in a folder. It offers two ways to read glyph data, and one way to write
|
|
@@ -12,33 +12,28 @@ glyph data. See the class doc string for details.
|
|
|
12
12
|
|
|
13
13
|
from __future__ import annotations
|
|
14
14
|
|
|
15
|
-
import logging
|
|
16
15
|
import enum
|
|
17
|
-
|
|
16
|
+
import logging
|
|
18
17
|
from collections import OrderedDict
|
|
19
|
-
import
|
|
20
|
-
|
|
21
|
-
import fs
|
|
22
|
-
import
|
|
23
|
-
import fs.path
|
|
18
|
+
from warnings import warn
|
|
19
|
+
|
|
20
|
+
import fontTools.misc.filesystem as fs
|
|
21
|
+
from fontTools.misc import etree, plistlib
|
|
24
22
|
from fontTools.misc.textTools import tobytes
|
|
25
|
-
from fontTools.misc import plistlib
|
|
26
23
|
from fontTools.pens.pointPen import AbstractPointPen, PointToSegmentPen
|
|
24
|
+
from fontTools.ufoLib import UFOFormatVersion, _UFOBaseIO
|
|
27
25
|
from fontTools.ufoLib.errors import GlifLibError
|
|
28
26
|
from fontTools.ufoLib.filenames import userNameToFileName
|
|
27
|
+
from fontTools.ufoLib.utils import _VersionTupleEnumMixin, numberTypes
|
|
29
28
|
from fontTools.ufoLib.validators import (
|
|
30
|
-
|
|
29
|
+
anchorsValidator,
|
|
31
30
|
colorValidator,
|
|
31
|
+
genericTypeValidator,
|
|
32
|
+
glyphLibValidator,
|
|
32
33
|
guidelinesValidator,
|
|
33
|
-
anchorsValidator,
|
|
34
34
|
identifierValidator,
|
|
35
35
|
imageValidator,
|
|
36
|
-
glyphLibValidator,
|
|
37
36
|
)
|
|
38
|
-
from fontTools.misc import etree
|
|
39
|
-
from fontTools.ufoLib import _UFOBaseIO, UFOFormatVersion
|
|
40
|
-
from fontTools.ufoLib.utils import numberTypes, _VersionTupleEnumMixin
|
|
41
|
-
|
|
42
37
|
|
|
43
38
|
__all__ = [
|
|
44
39
|
"GlyphSet",
|
|
@@ -206,7 +201,7 @@ class GlyphSet(_UFOBaseIO):
|
|
|
206
201
|
# 'dirName' is kept for backward compatibility only, but it's DEPRECATED
|
|
207
202
|
# as it's not guaranteed that it maps to an existing OSFS directory.
|
|
208
203
|
# Client could use the FS api via the `self.fs` attribute instead.
|
|
209
|
-
self.dirName = fs.path.
|
|
204
|
+
self.dirName = fs.path.basename(path)
|
|
210
205
|
self.fs = filesystem
|
|
211
206
|
# if glyphSet contains no 'contents.plist', we consider it empty
|
|
212
207
|
self._havePreviousFile = filesystem.exists(CONTENTS_FILENAME)
|
fontTools/ufoLib/validators.py
CHANGED
|
@@ -1,14 +1,12 @@
|
|
|
1
1
|
"""Various low level data validators."""
|
|
2
2
|
|
|
3
3
|
import calendar
|
|
4
|
+
from collections.abc import Mapping
|
|
4
5
|
from io import open
|
|
5
|
-
import fs.base
|
|
6
|
-
import fs.osfs
|
|
7
6
|
|
|
8
|
-
|
|
7
|
+
import fontTools.misc.filesystem as fs
|
|
9
8
|
from fontTools.ufoLib.utils import numberTypes
|
|
10
9
|
|
|
11
|
-
|
|
12
10
|
# -------
|
|
13
11
|
# Generic
|
|
14
12
|
# -------
|
fontTools/varLib/featureVars.py
CHANGED
|
@@ -95,6 +95,14 @@ def addFeatureVariations(font, conditionalSubstitutions, featureTag="rvrn"):
|
|
|
95
95
|
|
|
96
96
|
addFeatureVariationsRaw(font, font["GSUB"].table, conditionsAndLookups, featureTags)
|
|
97
97
|
|
|
98
|
+
# Update OS/2.usMaxContext in case the font didn't have features before, but
|
|
99
|
+
# does now, if the OS/2 table exists. The table may be required, but
|
|
100
|
+
# fontTools needs to be able to deal with non-standard fonts. Since feature
|
|
101
|
+
# variations are always 1:1 mappings, we can set the value to at least 1
|
|
102
|
+
# instead of recomputing it with `otlLib.maxContextCalc.maxCtxFont()`.
|
|
103
|
+
if (os2 := font.get("OS/2")) is not None:
|
|
104
|
+
os2.usMaxContext = max(1, os2.usMaxContext)
|
|
105
|
+
|
|
98
106
|
|
|
99
107
|
def _existingVariableFeatures(table):
|
|
100
108
|
existingFeatureVarsTags = set()
|
fontTools/varLib/hvar.py
CHANGED
|
@@ -56,7 +56,7 @@ def add_HVAR(font):
|
|
|
56
56
|
def add_VVAR(font):
|
|
57
57
|
if "VVAR" in font:
|
|
58
58
|
del font["VVAR"]
|
|
59
|
-
getAdvanceMetrics = partial(_get_advance_metrics, font, axisTags,
|
|
59
|
+
getAdvanceMetrics = partial(_get_advance_metrics, font, axisTags, VVAR_FIELDS)
|
|
60
60
|
axisTags = [axis.axisTag for axis in font["fvar"].axes]
|
|
61
61
|
_add_VHVAR(font, axisTags, VVAR_FIELDS, getAdvanceMetrics)
|
|
62
62
|
|
|
@@ -120,6 +120,7 @@ from fontTools.cffLib.specializer import (
|
|
|
120
120
|
specializeCommands,
|
|
121
121
|
generalizeCommands,
|
|
122
122
|
)
|
|
123
|
+
from fontTools.cffLib.CFF2ToCFF import convertCFF2ToCFF
|
|
123
124
|
from fontTools.varLib import builder
|
|
124
125
|
from fontTools.varLib.mvar import MVAR_ENTRIES
|
|
125
126
|
from fontTools.varLib.merger import MutatorMerger
|
|
@@ -136,6 +137,7 @@ from enum import IntEnum
|
|
|
136
137
|
import logging
|
|
137
138
|
import os
|
|
138
139
|
import re
|
|
140
|
+
import io
|
|
139
141
|
from typing import Dict, Iterable, Mapping, Optional, Sequence, Tuple, Union
|
|
140
142
|
import warnings
|
|
141
143
|
|
|
@@ -643,7 +645,11 @@ def instantiateCFF2(
|
|
|
643
645
|
# the Private dicts.
|
|
644
646
|
#
|
|
645
647
|
# Then prune unused things and possibly drop the VarStore if it's empty.
|
|
646
|
-
#
|
|
648
|
+
#
|
|
649
|
+
# If the downgrade parameter is True, no actual downgrading is done, but
|
|
650
|
+
# the function returns True if the VarStore was empty after instantiation,
|
|
651
|
+
# and hence a downgrade to CFF is possible. In all other cases it returns
|
|
652
|
+
# False.
|
|
647
653
|
|
|
648
654
|
log.info("Instantiating CFF2 table")
|
|
649
655
|
|
|
@@ -882,9 +888,9 @@ def instantiateCFF2(
|
|
|
882
888
|
del private.vstore
|
|
883
889
|
|
|
884
890
|
if downgrade:
|
|
885
|
-
|
|
891
|
+
return True
|
|
886
892
|
|
|
887
|
-
|
|
893
|
+
return False
|
|
888
894
|
|
|
889
895
|
|
|
890
896
|
def _instantiateGvarGlyph(
|
|
@@ -1377,6 +1383,52 @@ def _isValidAvarSegmentMap(axisTag, segmentMap):
|
|
|
1377
1383
|
return True
|
|
1378
1384
|
|
|
1379
1385
|
|
|
1386
|
+
def downgradeCFF2ToCFF(varfont):
|
|
1387
|
+
|
|
1388
|
+
# Save these properties
|
|
1389
|
+
recalcTimestamp = varfont.recalcTimestamp
|
|
1390
|
+
recalcBBoxes = varfont.recalcBBoxes
|
|
1391
|
+
|
|
1392
|
+
# Disable them
|
|
1393
|
+
varfont.recalcTimestamp = False
|
|
1394
|
+
varfont.recalcBBoxes = False
|
|
1395
|
+
|
|
1396
|
+
# Save to memory, reload, downgrade and save again, reload.
|
|
1397
|
+
# We do this dance because the convertCFF2ToCFF changes glyph
|
|
1398
|
+
# names, so following save would fail if any other table was
|
|
1399
|
+
# loaded and referencing glyph names.
|
|
1400
|
+
#
|
|
1401
|
+
# The second save+load is unfortunate but also necessary.
|
|
1402
|
+
|
|
1403
|
+
stream = io.BytesIO()
|
|
1404
|
+
log.info("Saving CFF2 font to memory for downgrade")
|
|
1405
|
+
varfont.save(stream)
|
|
1406
|
+
stream.seek(0)
|
|
1407
|
+
varfont = TTFont(stream, recalcTimestamp=False, recalcBBoxes=False)
|
|
1408
|
+
|
|
1409
|
+
convertCFF2ToCFF(varfont)
|
|
1410
|
+
|
|
1411
|
+
stream = io.BytesIO()
|
|
1412
|
+
log.info("Saving downgraded CFF font to memory")
|
|
1413
|
+
varfont.save(stream)
|
|
1414
|
+
stream.seek(0)
|
|
1415
|
+
varfont = TTFont(stream, recalcTimestamp=False, recalcBBoxes=False)
|
|
1416
|
+
|
|
1417
|
+
# Uncomment, to see test all tables can be loaded. This fails without
|
|
1418
|
+
# the extra save+load above.
|
|
1419
|
+
"""
|
|
1420
|
+
for tag in varfont.keys():
|
|
1421
|
+
print("Loading", tag)
|
|
1422
|
+
varfont[tag]
|
|
1423
|
+
"""
|
|
1424
|
+
|
|
1425
|
+
# Restore them
|
|
1426
|
+
varfont.recalcTimestamp = recalcTimestamp
|
|
1427
|
+
varfont.recalcBBoxes = recalcBBoxes
|
|
1428
|
+
|
|
1429
|
+
return varfont
|
|
1430
|
+
|
|
1431
|
+
|
|
1380
1432
|
def instantiateAvar(varfont, axisLimits):
|
|
1381
1433
|
# 'axisLimits' dict must contain user-space (non-normalized) coordinates.
|
|
1382
1434
|
|
|
@@ -1665,7 +1717,9 @@ def instantiateVariableFont(
|
|
|
1665
1717
|
instantiateVARC(varfont, normalizedLimits)
|
|
1666
1718
|
|
|
1667
1719
|
if "CFF2" in varfont:
|
|
1668
|
-
instantiateCFF2(
|
|
1720
|
+
downgradeCFF2 = instantiateCFF2(
|
|
1721
|
+
varfont, normalizedLimits, downgrade=downgradeCFF2
|
|
1722
|
+
)
|
|
1669
1723
|
|
|
1670
1724
|
if "gvar" in varfont:
|
|
1671
1725
|
instantiateGvar(varfont, normalizedLimits, optimize=optimize)
|
|
@@ -1720,6 +1774,12 @@ def instantiateVariableFont(
|
|
|
1720
1774
|
# name table has been updated.
|
|
1721
1775
|
setRibbiBits(varfont)
|
|
1722
1776
|
|
|
1777
|
+
if downgradeCFF2:
|
|
1778
|
+
origVarfont = varfont
|
|
1779
|
+
varfont = downgradeCFF2ToCFF(varfont)
|
|
1780
|
+
if inplace:
|
|
1781
|
+
origVarfont.__dict__ = varfont.__dict__.copy()
|
|
1782
|
+
|
|
1723
1783
|
return varfont
|
|
1724
1784
|
|
|
1725
1785
|
|
|
@@ -1929,7 +1989,7 @@ def main(args=None):
|
|
|
1929
1989
|
if limit is None or limit[0] == limit[2]
|
|
1930
1990
|
}.issuperset(axis.axisTag for axis in varfont["fvar"].axes)
|
|
1931
1991
|
|
|
1932
|
-
instantiateVariableFont(
|
|
1992
|
+
varfont = instantiateVariableFont(
|
|
1933
1993
|
varfont,
|
|
1934
1994
|
axisLimits,
|
|
1935
1995
|
inplace=True,
|
fontTools/varLib/mutator.py
CHANGED
|
@@ -4,9 +4,16 @@ Instantiate a variation font. Run, eg:
|
|
|
4
4
|
.. code-block:: sh
|
|
5
5
|
|
|
6
6
|
$ fonttools varLib.mutator ./NotoSansArabic-VF.ttf wght=140 wdth=85
|
|
7
|
+
|
|
8
|
+
.. warning::
|
|
9
|
+
``fontTools.varLib.mutator`` is deprecated in favor of :mod:`fontTools.varLib.instancer`
|
|
10
|
+
which provides equivalent full instancing and also supports partial instancing.
|
|
11
|
+
Please migrate CLI usage to ``fonttools varLib.instancer`` and API usage to
|
|
12
|
+
:func:`fontTools.varLib.instancer.instantiateVariableFont`.
|
|
7
13
|
"""
|
|
8
14
|
|
|
9
15
|
from fontTools.misc.fixedTools import floatToFixedToFloat, floatToFixed
|
|
16
|
+
from fontTools.misc.loggingTools import deprecateFunction
|
|
10
17
|
from fontTools.misc.roundTools import otRound
|
|
11
18
|
from fontTools.pens.boundsPen import BoundsPen
|
|
12
19
|
from fontTools.ttLib import TTFont, newTable
|
|
@@ -159,6 +166,10 @@ def interpolate_cff2_metrics(varfont, topDict, glyphOrder, loc):
|
|
|
159
166
|
hmtx[gname] = tuple(entry)
|
|
160
167
|
|
|
161
168
|
|
|
169
|
+
@deprecateFunction(
|
|
170
|
+
"use fontTools.varLib.instancer.instantiateVariableFont instead "
|
|
171
|
+
"for either full or partial instancing",
|
|
172
|
+
)
|
|
162
173
|
def instantiateVariableFont(varfont, location, inplace=False, overlap=True):
|
|
163
174
|
"""Generate a static instance from a variable TTFont and a dictionary
|
|
164
175
|
defining the desired location along the variable font's axes.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: fonttools
|
|
3
|
-
Version: 4.
|
|
3
|
+
Version: 4.59.1
|
|
4
4
|
Summary: Tools to manipulate font files
|
|
5
5
|
Home-page: http://github.com/fonttools/fonttools
|
|
6
6
|
Author: Just van Rossum
|
|
@@ -31,7 +31,6 @@ Description-Content-Type: text/x-rst
|
|
|
31
31
|
License-File: LICENSE
|
|
32
32
|
License-File: LICENSE.external
|
|
33
33
|
Provides-Extra: ufo
|
|
34
|
-
Requires-Dist: fs<3,>=2.2.0; extra == "ufo"
|
|
35
34
|
Provides-Extra: lxml
|
|
36
35
|
Requires-Dist: lxml>=4.0; extra == "lxml"
|
|
37
36
|
Provides-Extra: woff
|
|
@@ -57,7 +56,6 @@ Requires-Dist: skia-pathops>=0.5.0; extra == "pathops"
|
|
|
57
56
|
Provides-Extra: repacker
|
|
58
57
|
Requires-Dist: uharfbuzz>=0.23.0; extra == "repacker"
|
|
59
58
|
Provides-Extra: all
|
|
60
|
-
Requires-Dist: fs<3,>=2.2.0; extra == "all"
|
|
61
59
|
Requires-Dist: lxml>=4.0; extra == "all"
|
|
62
60
|
Requires-Dist: brotli>=1.0.1; platform_python_implementation == "CPython" and extra == "all"
|
|
63
61
|
Requires-Dist: brotlicffi>=0.8.0; platform_python_implementation != "CPython" and extra == "all"
|
|
@@ -170,15 +168,6 @@ are required to unlock the extra features named "ufo", etc.
|
|
|
170
168
|
|
|
171
169
|
*Extra:* ``lxml``
|
|
172
170
|
|
|
173
|
-
- ``Lib/fontTools/ufoLib``
|
|
174
|
-
|
|
175
|
-
Package for reading and writing UFO source files; it requires:
|
|
176
|
-
|
|
177
|
-
* `fs <https://pypi.org/pypi/fs>`__: (aka ``pyfilesystem2``) filesystem
|
|
178
|
-
abstraction layer.
|
|
179
|
-
|
|
180
|
-
*Extra:* ``ufo``
|
|
181
|
-
|
|
182
171
|
- ``Lib/fontTools/ttLib/woff2.py``
|
|
183
172
|
|
|
184
173
|
Module to compress/decompress WOFF 2.0 web fonts; it requires:
|
|
@@ -271,6 +260,17 @@ are required to unlock the extra features named "ufo", etc.
|
|
|
271
260
|
|
|
272
261
|
*Extra:* ``pathops``
|
|
273
262
|
|
|
263
|
+
- ``Lib/fontTools/ufoLib``
|
|
264
|
+
|
|
265
|
+
Package for reading and writing UFO source files; if available, it will use:
|
|
266
|
+
|
|
267
|
+
* `fs <https://pypi.org/pypi/fs>`__: (aka ``pyfilesystem2``) filesystem abstraction layer
|
|
268
|
+
|
|
269
|
+
for reading and writing UFOs to the local filesystem or zip files (.ufoz), instead of
|
|
270
|
+
the built-in ``fontTools.misc.filesystem`` package.
|
|
271
|
+
The reader and writer classes can in theory also accept any object compatible the
|
|
272
|
+
``fs.base.FS`` interface, although not all have been tested.
|
|
273
|
+
|
|
274
274
|
- ``Lib/fontTools/pens/cocoaPen.py`` and ``Lib/fontTools/pens/quartzPen.py``
|
|
275
275
|
|
|
276
276
|
Pens for drawing glyphs with Cocoa ``NSBezierPath`` or ``CGPath`` require:
|
|
@@ -388,6 +388,36 @@ Have fun!
|
|
|
388
388
|
Changelog
|
|
389
389
|
~~~~~~~~~
|
|
390
390
|
|
|
391
|
+
4.59.1 (released 2025-08-14)
|
|
392
|
+
----------------------------
|
|
393
|
+
|
|
394
|
+
- [featureVars] Update OS/2.usMaxContext if possible after addFeatureVariationsRaw (#3894).
|
|
395
|
+
- [vhmtx] raise TTLibError('not enough data...') when hmtx/vmtx are truncated (#3843, #3901).
|
|
396
|
+
- [feaLib] Combine duplicate features that have the same set of lookups regardless of the order in which those lookups are added to the feature (#3895).
|
|
397
|
+
- [varLib] Deprecate ``varLib.mutator`` in favor of ``varLib.instancer``. The latter
|
|
398
|
+
provides equivalent full (static font) instancing in addition to partial VF instancing.
|
|
399
|
+
CLI users should replace ``fonttools varLib.mutator`` with ``fonttools varLib.instancer``.
|
|
400
|
+
API users should migrate to ``fontTools.varLib.instancer.instantiateVariableFont`` (#2680).
|
|
401
|
+
|
|
402
|
+
|
|
403
|
+
4.59.0 (released 2025-07-16)
|
|
404
|
+
----------------------------
|
|
405
|
+
|
|
406
|
+
- Removed hard-dependency on pyfilesystem2 (``fs`` package) from ``fonttools[ufo]`` extra.
|
|
407
|
+
This is replaced by the `fontTools.misc.filesystem` package, a stdlib-only, drop-in
|
|
408
|
+
replacement for the subset of the pyfilesystem2's API used by ``fontTools.ufoLib``.
|
|
409
|
+
The latter should continue to work with the upstream ``fs`` (we even test with/without).
|
|
410
|
+
Clients who wish to continue using ``fs`` can do so by depending on it directly instead
|
|
411
|
+
of via the ``fonttools[ufo]`` extra (#3885, #3620).
|
|
412
|
+
- [xmlWriter] Replace illegal XML characters (e.g. control or non-characters) with "?"
|
|
413
|
+
when dumping to ttx (#3868, #71).
|
|
414
|
+
- [varLib.hvar] Fixed vertical metrics fields copy/pasta error (#3884).
|
|
415
|
+
- Micro optimizations in ttLib and sstruct modules (#3878, #3879).
|
|
416
|
+
- [unicodedata] Add Garay script to RTL_SCRIPTS (#3882).
|
|
417
|
+
- [roundingPen] Remove unreliable kwarg usage. Argument names aren’t consistent among
|
|
418
|
+
point pens’ ``.addComponent()`` implementations, in particular ``baseGlyphName``
|
|
419
|
+
vs ``glyphName`` (#3880).
|
|
420
|
+
|
|
391
421
|
4.58.5 (released 2025-07-03)
|
|
392
422
|
----------------------------
|
|
393
423
|
|