fonttools 4.60.0__cp311-cp311-macosx_10_9_universal2.whl → 4.60.1__cp311-cp311-macosx_10_9_universal2.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/cu2qu/cu2qu.cpython-311-darwin.so +0 -0
- fontTools/feaLib/lexer.cpython-311-darwin.so +0 -0
- fontTools/misc/bezierTools.cpython-311-darwin.so +0 -0
- fontTools/misc/visitor.py +24 -16
- fontTools/pens/momentsPen.cpython-311-darwin.so +0 -0
- fontTools/qu2cu/qu2cu.cpython-311-darwin.so +0 -0
- fontTools/subset/__init__.py +178 -12
- fontTools/ufoLib/__init__.py +2 -2
- fontTools/varLib/iup.cpython-311-darwin.so +0 -0
- {fonttools-4.60.0.dist-info → fonttools-4.60.1.dist-info}/METADATA +13 -1
- {fonttools-4.60.0.dist-info → fonttools-4.60.1.dist-info}/RECORD +18 -18
- {fonttools-4.60.0.data → fonttools-4.60.1.data}/data/share/man/man1/ttx.1 +0 -0
- {fonttools-4.60.0.dist-info → fonttools-4.60.1.dist-info}/WHEEL +0 -0
- {fonttools-4.60.0.dist-info → fonttools-4.60.1.dist-info}/entry_points.txt +0 -0
- {fonttools-4.60.0.dist-info → fonttools-4.60.1.dist-info}/licenses/LICENSE +0 -0
- {fonttools-4.60.0.dist-info → fonttools-4.60.1.dist-info}/licenses/LICENSE.external +0 -0
- {fonttools-4.60.0.dist-info → fonttools-4.60.1.dist-info}/top_level.txt +0 -0
fontTools/__init__.py
CHANGED
|
Binary file
|
|
Binary file
|
|
Binary file
|
fontTools/misc/visitor.py
CHANGED
|
@@ -79,12 +79,15 @@ class Visitor(object):
|
|
|
79
79
|
def visitObject(self, obj, *args, **kwargs):
|
|
80
80
|
"""Called to visit an object. This function loops over all non-private
|
|
81
81
|
attributes of the objects and calls any user-registered (via
|
|
82
|
-
|
|
82
|
+
``@register_attr()`` or ``@register_attrs()``) ``visit()`` functions.
|
|
83
83
|
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
84
|
+
The visitor will proceed to call ``self.visitAttr()``, unless there is a
|
|
85
|
+
user-registered visit function and:
|
|
86
|
+
|
|
87
|
+
* It returns ``False``; or
|
|
88
|
+
* It returns ``None`` (or doesn't return anything) and
|
|
89
|
+
``visitor.defaultStop`` is ``True`` (non-default).
|
|
90
|
+
"""
|
|
88
91
|
|
|
89
92
|
keys = sorted(vars(obj).keys())
|
|
90
93
|
_visitors = self._visitorsFor(obj)
|
|
@@ -121,19 +124,24 @@ class Visitor(object):
|
|
|
121
124
|
|
|
122
125
|
def visit(self, obj, *args, **kwargs):
|
|
123
126
|
"""This is the main entry to the visitor. The visitor will visit object
|
|
124
|
-
obj
|
|
127
|
+
``obj``.
|
|
125
128
|
|
|
126
129
|
The visitor will first determine if there is a registered (via
|
|
127
|
-
|
|
128
|
-
will be called, and (visitor, obj, *args, **kwargs) will be passed
|
|
129
|
-
the user visit function.
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
130
|
+
``@register()``) visit function for the type of object. If there is, it
|
|
131
|
+
will be called, and ``(visitor, obj, *args, **kwargs)`` will be passed
|
|
132
|
+
to the user visit function.
|
|
133
|
+
|
|
134
|
+
The visitor will not recurse if there is a user-registered visit
|
|
135
|
+
function and:
|
|
136
|
+
|
|
137
|
+
* It returns ``False``; or
|
|
138
|
+
* It returns ``None`` (or doesn't return anything) and
|
|
139
|
+
``visitor.defaultStop`` is ``True`` (non-default)
|
|
140
|
+
|
|
141
|
+
Otherwise, the visitor will proceed to dispatch to one of
|
|
142
|
+
``self.visitObject()``, ``self.visitList()``, ``self.visitDict()``, or
|
|
143
|
+
``self.visitLeaf()`` (any of which can be overriden in a subclass).
|
|
144
|
+
"""
|
|
137
145
|
|
|
138
146
|
visitorFunc = self._visitorsFor(obj).get(None, None)
|
|
139
147
|
if visitorFunc is not None:
|
|
Binary file
|
|
Binary file
|
fontTools/subset/__init__.py
CHANGED
|
@@ -272,7 +272,7 @@ Font table options
|
|
|
272
272
|
Specify (=), add to (+=) or exclude from (-=) the comma-separated
|
|
273
273
|
set of tables that will be be dropped.
|
|
274
274
|
By default, the following tables are dropped:
|
|
275
|
-
'
|
|
275
|
+
'JSTF', 'DSIG', 'EBDT', 'EBLC', 'EBSC', 'PCLT', 'LTSH'
|
|
276
276
|
and Graphite tables: 'Feat', 'Glat', 'Gloc', 'Silf', 'Sill'.
|
|
277
277
|
The tool will attempt to subset the remaining tables.
|
|
278
278
|
|
|
@@ -827,13 +827,26 @@ def subset_glyphs(self, s):
|
|
|
827
827
|
self.MarkArray.MarkRecord, mark_indices
|
|
828
828
|
)
|
|
829
829
|
self.MarkArray.MarkCount = len(self.MarkArray.MarkRecord)
|
|
830
|
-
|
|
830
|
+
class_indices = _uniq_sort(v.Class for v in self.MarkArray.MarkRecord)
|
|
831
|
+
|
|
832
|
+
intersect_base_indices = self.BaseCoverage.intersect(s.glyphs)
|
|
833
|
+
base_records = self.BaseArray.BaseRecord
|
|
834
|
+
num_base_records = len(base_records)
|
|
835
|
+
base_indices = [
|
|
836
|
+
i
|
|
837
|
+
for i in intersect_base_indices
|
|
838
|
+
if i < num_base_records
|
|
839
|
+
and any(base_records[i].BaseAnchor[j] is not None for j in class_indices)
|
|
840
|
+
]
|
|
841
|
+
if not base_indices:
|
|
842
|
+
return False
|
|
843
|
+
|
|
844
|
+
self.BaseCoverage.remap(base_indices)
|
|
831
845
|
self.BaseArray.BaseRecord = _list_subset(
|
|
832
846
|
self.BaseArray.BaseRecord, base_indices
|
|
833
847
|
)
|
|
834
848
|
self.BaseArray.BaseCount = len(self.BaseArray.BaseRecord)
|
|
835
849
|
# Prune empty classes
|
|
836
|
-
class_indices = _uniq_sort(v.Class for v in self.MarkArray.MarkRecord)
|
|
837
850
|
self.ClassCount = len(class_indices)
|
|
838
851
|
for m in self.MarkArray.MarkRecord:
|
|
839
852
|
m.Class = class_indices.index(m.Class)
|
|
@@ -867,13 +880,31 @@ def subset_glyphs(self, s):
|
|
|
867
880
|
self.MarkArray.MarkRecord, mark_indices
|
|
868
881
|
)
|
|
869
882
|
self.MarkArray.MarkCount = len(self.MarkArray.MarkRecord)
|
|
870
|
-
|
|
883
|
+
class_indices = _uniq_sort(v.Class for v in self.MarkArray.MarkRecord)
|
|
884
|
+
|
|
885
|
+
intersect_ligature_indices = self.LigatureCoverage.intersect(s.glyphs)
|
|
886
|
+
ligature_array = self.LigatureArray.LigatureAttach
|
|
887
|
+
num_ligatures = self.LigatureArray.LigatureCount
|
|
888
|
+
|
|
889
|
+
ligature_indices = [
|
|
890
|
+
i
|
|
891
|
+
for i in intersect_ligature_indices
|
|
892
|
+
if i < num_ligatures
|
|
893
|
+
and any(
|
|
894
|
+
any(component.LigatureAnchor[j] is not None for j in class_indices)
|
|
895
|
+
for component in ligature_array[i].ComponentRecord
|
|
896
|
+
)
|
|
897
|
+
]
|
|
898
|
+
|
|
899
|
+
if not ligature_indices:
|
|
900
|
+
return False
|
|
901
|
+
|
|
902
|
+
self.LigatureCoverage.remap(ligature_indices)
|
|
871
903
|
self.LigatureArray.LigatureAttach = _list_subset(
|
|
872
904
|
self.LigatureArray.LigatureAttach, ligature_indices
|
|
873
905
|
)
|
|
874
906
|
self.LigatureArray.LigatureCount = len(self.LigatureArray.LigatureAttach)
|
|
875
907
|
# Prune empty classes
|
|
876
|
-
class_indices = _uniq_sort(v.Class for v in self.MarkArray.MarkRecord)
|
|
877
908
|
self.ClassCount = len(class_indices)
|
|
878
909
|
for m in self.MarkArray.MarkRecord:
|
|
879
910
|
m.Class = class_indices.index(m.Class)
|
|
@@ -915,13 +946,26 @@ def subset_glyphs(self, s):
|
|
|
915
946
|
self.Mark1Array.MarkRecord, mark1_indices
|
|
916
947
|
)
|
|
917
948
|
self.Mark1Array.MarkCount = len(self.Mark1Array.MarkRecord)
|
|
918
|
-
|
|
949
|
+
class_indices = _uniq_sort(v.Class for v in self.Mark1Array.MarkRecord)
|
|
950
|
+
|
|
951
|
+
intersect_mark2_indices = self.Mark2Coverage.intersect(s.glyphs)
|
|
952
|
+
mark2_records = self.Mark2Array.Mark2Record
|
|
953
|
+
num_mark2_records = len(mark2_records)
|
|
954
|
+
mark2_indices = [
|
|
955
|
+
i
|
|
956
|
+
for i in intersect_mark2_indices
|
|
957
|
+
if i < num_mark2_records
|
|
958
|
+
and any(mark2_records[i].Mark2Anchor[j] is not None for j in class_indices)
|
|
959
|
+
]
|
|
960
|
+
if not mark2_indices:
|
|
961
|
+
return False
|
|
962
|
+
|
|
963
|
+
self.Mark2Coverage.remap(mark2_indices)
|
|
919
964
|
self.Mark2Array.Mark2Record = _list_subset(
|
|
920
965
|
self.Mark2Array.Mark2Record, mark2_indices
|
|
921
966
|
)
|
|
922
967
|
self.Mark2Array.MarkCount = len(self.Mark2Array.Mark2Record)
|
|
923
968
|
# Prune empty classes
|
|
924
|
-
class_indices = _uniq_sort(v.Class for v in self.Mark1Array.MarkRecord)
|
|
925
969
|
self.ClassCount = len(class_indices)
|
|
926
970
|
for m in self.Mark1Array.MarkRecord:
|
|
927
971
|
m.Class = class_indices.index(m.Class)
|
|
@@ -1717,6 +1761,19 @@ def subset_features(self, feature_indices):
|
|
|
1717
1761
|
return bool(self.SubstitutionCount)
|
|
1718
1762
|
|
|
1719
1763
|
|
|
1764
|
+
@_add_method(otTables.FeatureTableSubstitution)
|
|
1765
|
+
def prune_features(self, feature_index_map):
|
|
1766
|
+
self.ensureDecompiled()
|
|
1767
|
+
self.SubstitutionRecord = [
|
|
1768
|
+
r for r in self.SubstitutionRecord if r.FeatureIndex in feature_index_map.keys()
|
|
1769
|
+
]
|
|
1770
|
+
# remap feature indices
|
|
1771
|
+
for r in self.SubstitutionRecord:
|
|
1772
|
+
r.FeatureIndex = feature_index_map[r.FeatureIndex]
|
|
1773
|
+
self.SubstitutionCount = len(self.SubstitutionRecord)
|
|
1774
|
+
return bool(self.SubstitutionCount)
|
|
1775
|
+
|
|
1776
|
+
|
|
1720
1777
|
@_add_method(otTables.FeatureVariations)
|
|
1721
1778
|
def subset_features(self, feature_indices):
|
|
1722
1779
|
self.ensureDecompiled()
|
|
@@ -1735,6 +1792,24 @@ def subset_features(self, feature_indices):
|
|
|
1735
1792
|
return bool(self.FeatureVariationCount)
|
|
1736
1793
|
|
|
1737
1794
|
|
|
1795
|
+
@_add_method(otTables.FeatureVariations)
|
|
1796
|
+
def prune_features(self, feature_index_map):
|
|
1797
|
+
self.ensureDecompiled()
|
|
1798
|
+
for r in self.FeatureVariationRecord:
|
|
1799
|
+
r.FeatureTableSubstitution.prune_features(feature_index_map)
|
|
1800
|
+
# Prune empty records at the end only
|
|
1801
|
+
# https://github.com/fonttools/fonttools/issues/1881
|
|
1802
|
+
while (
|
|
1803
|
+
self.FeatureVariationRecord
|
|
1804
|
+
and not self.FeatureVariationRecord[
|
|
1805
|
+
-1
|
|
1806
|
+
].FeatureTableSubstitution.SubstitutionCount
|
|
1807
|
+
):
|
|
1808
|
+
self.FeatureVariationRecord.pop()
|
|
1809
|
+
self.FeatureVariationCount = len(self.FeatureVariationRecord)
|
|
1810
|
+
return bool(self.FeatureVariationCount)
|
|
1811
|
+
|
|
1812
|
+
|
|
1738
1813
|
@_add_method(otTables.DefaultLangSys, otTables.LangSys)
|
|
1739
1814
|
def subset_features(self, feature_indices):
|
|
1740
1815
|
if self.ReqFeatureIndex in feature_indices:
|
|
@@ -1750,6 +1825,16 @@ def subset_features(self, feature_indices):
|
|
|
1750
1825
|
return bool(self.FeatureCount or self.ReqFeatureIndex != 65535)
|
|
1751
1826
|
|
|
1752
1827
|
|
|
1828
|
+
@_add_method(otTables.DefaultLangSys, otTables.LangSys)
|
|
1829
|
+
def prune_features(self, feature_index_map):
|
|
1830
|
+
self.ReqFeatureIndex = feature_index_map.get(self.ReqFeatureIndex, 65535)
|
|
1831
|
+
self.FeatureIndex = [
|
|
1832
|
+
feature_index_map[f] for f in self.FeatureIndex if f in feature_index_map.keys()
|
|
1833
|
+
]
|
|
1834
|
+
self.FeatureCount = len(self.FeatureIndex)
|
|
1835
|
+
return bool(self.FeatureCount or self.ReqFeatureIndex != 65535)
|
|
1836
|
+
|
|
1837
|
+
|
|
1753
1838
|
@_add_method(otTables.DefaultLangSys, otTables.LangSys)
|
|
1754
1839
|
def collect_features(self):
|
|
1755
1840
|
feature_indices = self.FeatureIndex[:]
|
|
@@ -1773,6 +1858,21 @@ def subset_features(self, feature_indices, keepEmptyDefaultLangSys=False):
|
|
|
1773
1858
|
return bool(self.LangSysCount or self.DefaultLangSys)
|
|
1774
1859
|
|
|
1775
1860
|
|
|
1861
|
+
@_add_method(otTables.Script)
|
|
1862
|
+
def prune_features(self, feature_index_map, keepEmptyDefaultLangSys=False):
|
|
1863
|
+
if (
|
|
1864
|
+
self.DefaultLangSys
|
|
1865
|
+
and not self.DefaultLangSys.prune_features(feature_index_map)
|
|
1866
|
+
and not keepEmptyDefaultLangSys
|
|
1867
|
+
):
|
|
1868
|
+
self.DefaultLangSys = None
|
|
1869
|
+
self.LangSysRecord = [
|
|
1870
|
+
l for l in self.LangSysRecord if l.LangSys.prune_features(feature_index_map)
|
|
1871
|
+
]
|
|
1872
|
+
self.LangSysCount = len(self.LangSysRecord)
|
|
1873
|
+
return bool(self.LangSysCount or self.DefaultLangSys)
|
|
1874
|
+
|
|
1875
|
+
|
|
1776
1876
|
@_add_method(otTables.Script)
|
|
1777
1877
|
def collect_features(self):
|
|
1778
1878
|
feature_indices = [l.LangSys.collect_features() for l in self.LangSysRecord]
|
|
@@ -1794,6 +1894,19 @@ def subset_features(self, feature_indices, retain_empty):
|
|
|
1794
1894
|
return bool(self.ScriptCount)
|
|
1795
1895
|
|
|
1796
1896
|
|
|
1897
|
+
@_add_method(otTables.ScriptList)
|
|
1898
|
+
def prune_features(self, feature_index_map, retain_empty):
|
|
1899
|
+
# https://bugzilla.mozilla.org/show_bug.cgi?id=1331737#c32
|
|
1900
|
+
self.ScriptRecord = [
|
|
1901
|
+
s
|
|
1902
|
+
for s in self.ScriptRecord
|
|
1903
|
+
if s.Script.prune_features(feature_index_map, s.ScriptTag == "DFLT")
|
|
1904
|
+
or retain_empty
|
|
1905
|
+
]
|
|
1906
|
+
self.ScriptCount = len(self.ScriptRecord)
|
|
1907
|
+
return bool(self.ScriptCount)
|
|
1908
|
+
|
|
1909
|
+
|
|
1797
1910
|
@_add_method(otTables.ScriptList)
|
|
1798
1911
|
def collect_features(self):
|
|
1799
1912
|
return _uniq_sort(sum((s.Script.collect_features() for s in self.ScriptRecord), []))
|
|
@@ -1981,21 +2094,74 @@ def subset_script_tags(self, tags):
|
|
|
1981
2094
|
|
|
1982
2095
|
@_add_method(ttLib.getTableClass("GSUB"), ttLib.getTableClass("GPOS"))
|
|
1983
2096
|
def prune_features(self):
|
|
1984
|
-
"""Remove unreferenced features
|
|
2097
|
+
"""Remove unreferenced and duplicate features in FeatureList
|
|
2098
|
+
Remove unreferenced features and remap duplicate feature indices in ScriptList and FeatureVariations
|
|
2099
|
+
"""
|
|
1985
2100
|
if self.table.ScriptList:
|
|
1986
2101
|
feature_indices = self.table.ScriptList.collect_features()
|
|
1987
2102
|
else:
|
|
1988
2103
|
feature_indices = []
|
|
2104
|
+
(feature_indices, feature_index_map) = self.remap_duplicate_features(
|
|
2105
|
+
feature_indices
|
|
2106
|
+
)
|
|
2107
|
+
|
|
1989
2108
|
if self.table.FeatureList:
|
|
1990
2109
|
self.table.FeatureList.subset_features(feature_indices)
|
|
1991
2110
|
if getattr(self.table, "FeatureVariations", None):
|
|
1992
|
-
self.table.FeatureVariations.
|
|
2111
|
+
self.table.FeatureVariations.prune_features(feature_index_map)
|
|
1993
2112
|
if self.table.ScriptList:
|
|
1994
|
-
self.table.ScriptList.
|
|
1995
|
-
|
|
2113
|
+
self.table.ScriptList.prune_features(
|
|
2114
|
+
feature_index_map, self.retain_empty_scripts()
|
|
1996
2115
|
)
|
|
1997
2116
|
|
|
1998
2117
|
|
|
2118
|
+
@_add_method(ttLib.getTableClass("GSUB"), ttLib.getTableClass("GPOS"))
|
|
2119
|
+
def remap_duplicate_features(self, feature_indices):
|
|
2120
|
+
"""Return retained feature indices(without duplicates) and remapped feature indices"""
|
|
2121
|
+
features = self.table.FeatureList.FeatureRecord
|
|
2122
|
+
|
|
2123
|
+
unique_features = {}
|
|
2124
|
+
duplicate_features = {}
|
|
2125
|
+
for i in feature_indices:
|
|
2126
|
+
f = features[i]
|
|
2127
|
+
tag = f.FeatureTag
|
|
2128
|
+
|
|
2129
|
+
same_tag_features = unique_features.get(tag)
|
|
2130
|
+
if same_tag_features is None:
|
|
2131
|
+
unique_features[tag] = set([i])
|
|
2132
|
+
duplicate_features[i] = i
|
|
2133
|
+
continue
|
|
2134
|
+
|
|
2135
|
+
found = False
|
|
2136
|
+
for other_i in same_tag_features:
|
|
2137
|
+
if features[other_i] == f:
|
|
2138
|
+
found = True
|
|
2139
|
+
duplicate_features[i] = other_i
|
|
2140
|
+
break
|
|
2141
|
+
|
|
2142
|
+
if not found:
|
|
2143
|
+
same_tag_features.add(i)
|
|
2144
|
+
duplicate_features[i] = i
|
|
2145
|
+
|
|
2146
|
+
## remap retained feature indices
|
|
2147
|
+
feature_map = {}
|
|
2148
|
+
new_idx = 0
|
|
2149
|
+
|
|
2150
|
+
for i in feature_indices:
|
|
2151
|
+
unique_i = duplicate_features.get(i, i)
|
|
2152
|
+
v = feature_map.get(unique_i)
|
|
2153
|
+
if v is None:
|
|
2154
|
+
feature_map[i] = new_idx
|
|
2155
|
+
new_idx += 1
|
|
2156
|
+
else:
|
|
2157
|
+
feature_map[i] = v
|
|
2158
|
+
|
|
2159
|
+
retained_feature_indices = _uniq_sort(
|
|
2160
|
+
sum((list(s) for s in unique_features.values()), [])
|
|
2161
|
+
)
|
|
2162
|
+
return (retained_feature_indices, feature_map)
|
|
2163
|
+
|
|
2164
|
+
|
|
1999
2165
|
@_add_method(ttLib.getTableClass("GSUB"), ttLib.getTableClass("GPOS"))
|
|
2000
2166
|
def prune_pre_subset(self, font, options):
|
|
2001
2167
|
# Drop undesired features
|
|
@@ -3145,7 +3311,6 @@ class Options(object):
|
|
|
3145
3311
|
|
|
3146
3312
|
# spaces in tag names (e.g. "SVG ", "cvt ") are stripped by the argument parser
|
|
3147
3313
|
_drop_tables_default = [
|
|
3148
|
-
"BASE",
|
|
3149
3314
|
"JSTF",
|
|
3150
3315
|
"DSIG",
|
|
3151
3316
|
"EBDT",
|
|
@@ -3157,6 +3322,7 @@ class Options(object):
|
|
|
3157
3322
|
_drop_tables_default += ["Feat", "Glat", "Gloc", "Silf", "Sill"] # Graphite
|
|
3158
3323
|
_no_subset_tables_default = [
|
|
3159
3324
|
"avar",
|
|
3325
|
+
"BASE",
|
|
3160
3326
|
"fvar",
|
|
3161
3327
|
"gasp",
|
|
3162
3328
|
"head",
|
fontTools/ufoLib/__init__.py
CHANGED
|
@@ -534,7 +534,7 @@ class UFOReader(_UFOBaseIO):
|
|
|
534
534
|
raise UFOLibError(message)
|
|
535
535
|
return groups
|
|
536
536
|
|
|
537
|
-
def
|
|
537
|
+
def getKerningGroupConversionRenameMaps(
|
|
538
538
|
self, validate: Optional[bool] = None
|
|
539
539
|
) -> KerningGroupRenameMaps:
|
|
540
540
|
"""
|
|
@@ -1263,7 +1263,7 @@ class UFOWriter(UFOReader):
|
|
|
1263
1263
|
}
|
|
1264
1264
|
|
|
1265
1265
|
This is the same form returned by UFOReader's
|
|
1266
|
-
|
|
1266
|
+
getKerningGroupConversionRenameMaps method.
|
|
1267
1267
|
"""
|
|
1268
1268
|
if self._formatVersion >= UFOFormatVersion.FORMAT_3_0:
|
|
1269
1269
|
return # XXX raise an error here
|
|
Binary file
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: fonttools
|
|
3
|
-
Version: 4.60.
|
|
3
|
+
Version: 4.60.1
|
|
4
4
|
Summary: Tools to manipulate font files
|
|
5
5
|
Home-page: http://github.com/fonttools/fonttools
|
|
6
6
|
Author: Just van Rossum
|
|
@@ -392,6 +392,18 @@ Have fun!
|
|
|
392
392
|
Changelog
|
|
393
393
|
~~~~~~~~~
|
|
394
394
|
|
|
395
|
+
4.60.1 (released 2025-09-29)
|
|
396
|
+
----------------------------
|
|
397
|
+
|
|
398
|
+
- [ufoLib] Reverted accidental method name change in ``UFOReader.getKerningGroupConversionRenameMaps``
|
|
399
|
+
that broke compatibility with downstream projects like defcon (#3948, #3947, robotools/defcon#478).
|
|
400
|
+
- [ufoLib] Added test coverage for ``getKerningGroupConversionRenameMaps`` method (#3950).
|
|
401
|
+
- [subset] Don't try to subset BASE table; pass it through by default instead (#3949).
|
|
402
|
+
- [subset] Remove empty BaseRecord entries in MarkBasePos lookups (#3897, #3892).
|
|
403
|
+
- [subset] Add pruning for MarkLigPos and MarkMarkPos lookups (#3946).
|
|
404
|
+
- [subset] Remove duplicate features when subsetting (#3945).
|
|
405
|
+
- [Docs] Added documentation for the visitor module (#3944).
|
|
406
|
+
|
|
395
407
|
4.60.0 (released 2025-09-17)
|
|
396
408
|
----------------------------
|
|
397
409
|
|
|
@@ -1,14 +1,14 @@
|
|
|
1
|
-
fonttools-4.60.
|
|
2
|
-
fonttools-4.60.
|
|
3
|
-
fonttools-4.60.
|
|
4
|
-
fonttools-4.60.
|
|
5
|
-
fonttools-4.60.
|
|
6
|
-
fonttools-4.60.
|
|
7
|
-
fonttools-4.60.
|
|
1
|
+
fonttools-4.60.1.dist-info/RECORD,,
|
|
2
|
+
fonttools-4.60.1.dist-info/WHEEL,sha256=VWNc5NH4DDoQDkc74R-nMZPza3RGJ6ac2abjVbvC-0k,141
|
|
3
|
+
fonttools-4.60.1.dist-info/entry_points.txt,sha256=8kVHddxfFWA44FSD4mBpmC-4uCynQnkoz_9aNJb227Y,147
|
|
4
|
+
fonttools-4.60.1.dist-info/top_level.txt,sha256=rRgRylrXzekqWOsrhygzib12pQ7WILf7UGjqEwkIFDM,10
|
|
5
|
+
fonttools-4.60.1.dist-info/METADATA,sha256=CIZ3DxcKqkgjQVIa68ndWbeo4HP-yrkBlOLu-dmZygM,112334
|
|
6
|
+
fonttools-4.60.1.dist-info/licenses/LICENSE,sha256=Z4cgj4P2Wcy8IiOy_elS_6b36KymLxqKK_W8UbsbI4M,1072
|
|
7
|
+
fonttools-4.60.1.dist-info/licenses/LICENSE.external,sha256=lKg6ruBymg8wLTSsxKzsvZ1YNm8mJCkHX-VX5KVLLmk,20022
|
|
8
8
|
fontTools/ttx.py,sha256=FxuGubujWCGJWSTrJEjoNH--25fVIPy-ZRtYy9H6iTk,17277
|
|
9
9
|
fontTools/fontBuilder.py,sha256=yF2-IYl_hao-Zy_FWSI4R-HnlFpzFrz0YBGQO8zfaOs,34130
|
|
10
10
|
fontTools/unicode.py,sha256=ZZ7OMmWvIyV1IL1k6ioTzaRAh3tUvm6gvK7QgFbOIHY,1237
|
|
11
|
-
fontTools/__init__.py,sha256=
|
|
11
|
+
fontTools/__init__.py,sha256=MfqTqdwYD_P2HKtnQkjibL8iy5ln62P1VIO9tT5epww,183
|
|
12
12
|
fontTools/tfmLib.py,sha256=UMbkM73JXRJVS9t2B-BJc13rSjImaWBuzCoehLwHFhs,14270
|
|
13
13
|
fontTools/afmLib.py,sha256=1MagIItOzRV4vV5kKPxeDZbPJsfxLB3wdHLFkQvl0uk,13164
|
|
14
14
|
fontTools/agl.py,sha256=05bm8Uq45uVWW8nPbP6xbNgmFyxQr8sWhYAiP0VSjnI,112975
|
|
@@ -19,7 +19,7 @@ fontTools/encodings/codecs.py,sha256=u50ruwz9fcRsrUrRGpR17Cr55Ovn1fvCHCKrElVumDE
|
|
|
19
19
|
fontTools/encodings/__init__.py,sha256=DJBWmoX_Haau7qlgmvWyfbhSzrX2qL636Rns7CG01pk,75
|
|
20
20
|
fontTools/encodings/MacRoman.py,sha256=4vEooUDm2gLCG8KIIDhRxm5-A64w7XrhP9cjDRr2Eo0,3576
|
|
21
21
|
fontTools/encodings/StandardEncoding.py,sha256=Eo3AGE8FE_p-IVYYuV097KouSsF3UrXoRRN0XyvYbrs,3581
|
|
22
|
-
fontTools/qu2cu/qu2cu.cpython-311-darwin.so,sha256=
|
|
22
|
+
fontTools/qu2cu/qu2cu.cpython-311-darwin.so,sha256=hrnZYNcMflgMHtsleU7qRgA6yRoeephhl57DXXU8660,342696
|
|
23
23
|
fontTools/qu2cu/benchmark.py,sha256=GMcr_4r7L6K9SmJ13itt-_XKhnKqSVUDPlXUG6IZmmM,1400
|
|
24
24
|
fontTools/qu2cu/__init__.py,sha256=Jfm1JljXbt91w4gyvZn6jzEmVnhRx50sh2fDongrOsE,618
|
|
25
25
|
fontTools/qu2cu/qu2cu.py,sha256=IYtpkwHdfKOXJr65Y_pJ9Lrt_MgJaISAKGMAs5ilFSM,12288
|
|
@@ -50,13 +50,13 @@ fontTools/misc/testTools.py,sha256=3vj_KllUQVEiVFbS0SzTmeuKv44-L-disI1dZ4XhOfw,7
|
|
|
50
50
|
fontTools/misc/lazyTools.py,sha256=BC6MmF-OzJ3GrBD8TYDZ-VCSN4UOx0pN0r3oF4GSoiw,1020
|
|
51
51
|
fontTools/misc/loggingTools.py,sha256=NOYROsLK5TzONK5967OGdVonNyXC6kP_CmPr7M2PW_c,19933
|
|
52
52
|
fontTools/misc/textTools.py,sha256=wNjH5zl1v9qNfmTl4BL52IO2IG1H5xY3o_pslqPPRjc,3483
|
|
53
|
-
fontTools/misc/visitor.py,sha256=
|
|
53
|
+
fontTools/misc/visitor.py,sha256=zwBAVfZ3MTsrbhNFj03pSSjNRyT6oGkare-kfWkN5ns,5754
|
|
54
54
|
fontTools/misc/macCreatorType.py,sha256=Je9jtqUr7EPbpH3QxlVl3pizoQ-1AOPMBIctHIMTM3k,1593
|
|
55
55
|
fontTools/misc/psCharStrings.py,sha256=Zn8mr7NRTfEJbnaXbOnSarrFBPcvPM0AupAxF2C80LY,43468
|
|
56
56
|
fontTools/misc/transform.py,sha256=OR8dPsAw87z77gkZQMq00iUkDWLIxYv-12XiKH1-erk,15798
|
|
57
57
|
fontTools/misc/etree.py,sha256=ZzJc6TvAS579deAgZLVDvTY_HeTm-ZsKJ5s3LYhZSSY,16304
|
|
58
58
|
fontTools/misc/xmlReader.py,sha256=igut4_d13RT4WarliqVvuuPybO1uSXVeoBOeW4j0_e4,6580
|
|
59
|
-
fontTools/misc/bezierTools.cpython-311-darwin.so,sha256=
|
|
59
|
+
fontTools/misc/bezierTools.cpython-311-darwin.so,sha256=mbLaoV3d7FfBr-JYd2oJmx5qzrWl3OZ1ySJQzN9xVk4,1078112
|
|
60
60
|
fontTools/misc/bezierTools.c,sha256=mFo2nrmrIq11WJ8Tj_cxR4M6U3tx75RVPcU-ODkHrbg,1821732
|
|
61
61
|
fontTools/misc/dictTools.py,sha256=VxjarsGJuk_wa3z29FSCtKZNCFfXtMBiNEu0RPAlpDk,2417
|
|
62
62
|
fontTools/misc/bezierTools.py,sha256=OmR3pzCGExNvZyTPrByH7gQHpAJsYOl1cmvfYQIVfQA,45038
|
|
@@ -79,7 +79,7 @@ fontTools/misc/filesystem/_zipfs.py,sha256=i3qolbkDRntB_oL3v79KuEgfVlVojecPBnBA0
|
|
|
79
79
|
fontTools/misc/plistlib/__init__.py,sha256=1HfhHPt3As6u2eRSlFfl6XdnXv_ypQImeQdWIw6wK7Y,21113
|
|
80
80
|
fontTools/misc/plistlib/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
81
81
|
fontTools/cu2qu/benchmark.py,sha256=wasPJmf8q9k9UHjpHChC3WQAGbBAyHN9PvJzXvWC0Fw,1296
|
|
82
|
-
fontTools/cu2qu/cu2qu.cpython-311-darwin.so,sha256=
|
|
82
|
+
fontTools/cu2qu/cu2qu.cpython-311-darwin.so,sha256=2Tv88KISNtyx4eKjrVtO3FdElsjRNyYFj4J738TeUAU,319704
|
|
83
83
|
fontTools/cu2qu/cu2qu.c,sha256=-7JwWBSeJ3I4vIs6ZaSVHzfBf46MSx25lG05NRqA6Zg,637967
|
|
84
84
|
fontTools/cu2qu/__init__.py,sha256=Cuc7Uglb0nSgaraTxXY5J8bReznH5wApW0uakN7MycY,618
|
|
85
85
|
fontTools/cu2qu/ufo.py,sha256=qZR70uWdCia19Ff8GLn5NeItscvvn69DegjDZVF4eNI,11794
|
|
@@ -89,7 +89,7 @@ fontTools/cu2qu/cu2qu.py,sha256=6LTe1ZI-jxW8y79s_UFjbkeFoFleIekTLm2jAE-uqGQ,1798
|
|
|
89
89
|
fontTools/cu2qu/__main__.py,sha256=kTUI-jczsHeelULLlory74QEeFjZWp9zigCc7PrdVQY,92
|
|
90
90
|
fontTools/subset/cff.py,sha256=rqMRJOlX5FacV1LW8aDlVOglgEM87TkMA9bdsYenask,6145
|
|
91
91
|
fontTools/subset/util.py,sha256=9SXFYb5Ef9Z58uXmYPCQil8B2i3Q7aFB_1fFDFSppdU,754
|
|
92
|
-
fontTools/subset/__init__.py,sha256=
|
|
92
|
+
fontTools/subset/__init__.py,sha256=R9VoZ2QWhqENHC5Ct1wyhLhEU-xo4mUXwCWl6EZGgwQ,143263
|
|
93
93
|
fontTools/subset/svg.py,sha256=8dLBzQlnIt4_fOKEFDAVlKTucdHvcbCcyG9-a6UBZZ0,9384
|
|
94
94
|
fontTools/subset/__main__.py,sha256=bhtfP2SqP4k799pxtksFgnC-XGNQDr3LcO4lc8T5e5g,95
|
|
95
95
|
fontTools/voltLib/error.py,sha256=phcQOQj-xOspCXu9hBJQRhSOBDzxHRgZd3fWQOFNJzw,395
|
|
@@ -120,7 +120,7 @@ fontTools/varLib/iup.c,sha256=I7snrACi_wloZDL67Fypk-7Dff5pxJhaVmluAXBUW_4,827723
|
|
|
120
120
|
fontTools/varLib/plot.py,sha256=NoSZkJ5ndxNcDvJIvd5pQ9_jX6X1oM1K2G_tR4sdPVs,7494
|
|
121
121
|
fontTools/varLib/cff.py,sha256=EVgaQcoROIrYQsRuftnxFuGGldEPYbrIh5yBckylJC4,22901
|
|
122
122
|
fontTools/varLib/models.py,sha256=sj_ENljh_qcMbfYzRIOlRgHq6tFOmL02Wv6WO8uofis,22398
|
|
123
|
-
fontTools/varLib/iup.cpython-311-darwin.so,sha256=
|
|
123
|
+
fontTools/varLib/iup.cpython-311-darwin.so,sha256=x3WHRg_KnDUmjGXCPWENyEWxPHBc2IQxS7geYc3tMss,433320
|
|
124
124
|
fontTools/varLib/__init__.py,sha256=SeAVSol0qvmw4Io5hvuVWxwx_onKadqr_1eXwjNUGkk,57322
|
|
125
125
|
fontTools/varLib/mutator.py,sha256=kzXiLFxRLgU2pcHzOzh9u0n0KkO3DuBk06xZ_RPhWz8,19804
|
|
126
126
|
fontTools/varLib/interpolatablePlot.py,sha256=w393P6mGLRhYkIjSxMww3qyoYxAUZzCXlmPBbI_84C0,44375
|
|
@@ -174,7 +174,7 @@ fontTools/pens/cairoPen.py,sha256=wuuOJ1qQDSt_K3zscM2nukRyHZTZMwMzzCXCirfq_qQ,59
|
|
|
174
174
|
fontTools/pens/wxPen.py,sha256=W9RRHlBWHp-CVC4Exvk3ytBmRaB4-LgJPP5Bv7o9BA0,680
|
|
175
175
|
fontTools/pens/boundsPen.py,sha256=wE3owOQA8DfhH-zBGC3lJvnVwp-oyIt0KZrEqXbmS9I,3129
|
|
176
176
|
fontTools/pens/recordingPen.py,sha256=VgFZ4NMhnZt1qSTzFEU0cma-gw3kBe47bfSxPYH73rs,12489
|
|
177
|
-
fontTools/pens/momentsPen.cpython-311-darwin.so,sha256=
|
|
177
|
+
fontTools/pens/momentsPen.cpython-311-darwin.so,sha256=c96jtVINSqD3sGaN0FFfJZKXNrPG_O43U_zXUgq370Y,282720
|
|
178
178
|
fontTools/pens/momentsPen.py,sha256=kjLVXhGe55Abl__Yr1gob0bl0dHe7fPSwyr7TRJnbug,25658
|
|
179
179
|
fontTools/pens/roundingPen.py,sha256=vh_FjikRd82-S4I8glgGMGEuGrj5IkCjRT_wmZ8jfqY,4620
|
|
180
180
|
fontTools/pens/freetypePen.py,sha256=HD-gXJSbgImJdBc8sIBk0HWBdjv3WKFofs6PgCCsGOY,19908
|
|
@@ -194,7 +194,7 @@ fontTools/ufoLib/pointPen.py,sha256=CuREcm3IYteZNBDAd_ZRAV4XqBsy0s07jdWc4en9r-8,
|
|
|
194
194
|
fontTools/ufoLib/kerning.py,sha256=o1BeJDVZ_CZZPzmOPwRKTqglYmhA_JZPjwq2JLgdQIk,4836
|
|
195
195
|
fontTools/ufoLib/filenames.py,sha256=hoyUhzzQMDaeckT7UdreISANq4-gLR2jGyk5yAyYtOA,10654
|
|
196
196
|
fontTools/ufoLib/validators.py,sha256=MWBqcLThGyYpst61QothA_BSlc6jGVhPvFiay-pobCY,32387
|
|
197
|
-
fontTools/ufoLib/__init__.py,sha256=
|
|
197
|
+
fontTools/ufoLib/__init__.py,sha256=nKG8gu6NEvqGJoZ781IARoQ7ii4LoWfMMvX3Yf5TsVw,98981
|
|
198
198
|
fontTools/ufoLib/glifLib.py,sha256=Y-xzf4qbTIOl3-dVLXvu3iFCIDtAEu_klId2_UNngWs,77170
|
|
199
199
|
fontTools/ufoLib/plistlib.py,sha256=jzMGOGvHO6XvS-IO8hS04ur7r8-v2dnVq-vKMoJZvqQ,1510
|
|
200
200
|
fontTools/ufoLib/utils.py,sha256=nZoJJqHXQSL-LXYE58_WHA97XlbTkEbYkdH3GL32SmQ,3192
|
|
@@ -213,7 +213,7 @@ fontTools/designspaceLib/split.py,sha256=FB1NuvhUO453UXveQZi9oyrW_caoCPM3RADp1rY
|
|
|
213
213
|
fontTools/designspaceLib/statNames.py,sha256=gXGKWVr1ju2_oL-R_DkyoZ3GlI7mfLORovpk1Ebgmvc,9237
|
|
214
214
|
fontTools/designspaceLib/__main__.py,sha256=xhtYXo1T1tsykhQDD0tcconSNYgWL5hoTBORpVDUYrc,103
|
|
215
215
|
fontTools/feaLib/error.py,sha256=Bz_5tNcNVcY7_nrAmFlQNhQldtqZWd8WUGQ2E3PWhZo,648
|
|
216
|
-
fontTools/feaLib/lexer.cpython-311-darwin.so,sha256=
|
|
216
|
+
fontTools/feaLib/lexer.cpython-311-darwin.so,sha256=vmiqfY1iISSxGZNOryO1UNmdkQUtJ006ZTWs0Hj2dUw,393640
|
|
217
217
|
fontTools/feaLib/variableScalar.py,sha256=f6sOg9cfFJRI3fw04uRohDeFux0xnZanaPT_lcxAVOw,4200
|
|
218
218
|
fontTools/feaLib/lexer.c,sha256=UaY5Hy0WYsGF9UMJnA2tMx0k5DwYA72N2IKxpRsAcCc,754285
|
|
219
219
|
fontTools/feaLib/__init__.py,sha256=jlIru2ghxvb1HhC5Je2BCXjFJmFQlYKpruorPoz3BvQ,213
|
|
@@ -350,4 +350,4 @@ fontTools/colorLib/builder.py,sha256=kmO7OuudQQb3fEOS7aLzgTDVjqS9i2xIQmk9p1uBe8A
|
|
|
350
350
|
fontTools/colorLib/geometry.py,sha256=3ScySrR2YDJa7d5K5_xM5Yt1-3NCV-ry8ikYA5VwVbI,5518
|
|
351
351
|
fontTools/colorLib/errors.py,sha256=CsaviiRxxrpgVX4blm7KCyK8553ljwL44xkJOeC5U7U,41
|
|
352
352
|
fontTools/colorLib/unbuilder.py,sha256=iW-E5I39WsV82K3NgCO4Cjzwm1WqzGrtypHt8epwbHM,2142
|
|
353
|
-
fonttools-4.60.
|
|
353
|
+
fonttools-4.60.1.data/data/share/man/man1/ttx.1,sha256=cLbm_pOOj1C76T2QXvDxzwDj9gk-GTd5RztvTMsouFw,5377
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|