fonttools 4.60.0__cp312-cp312-win_amd64.whl → 4.60.1__cp312-cp312-win_amd64.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of fonttools might be problematic. Click here for more details.

fontTools/__init__.py CHANGED
@@ -3,6 +3,6 @@ from fontTools.misc.loggingTools import configLogger
3
3
 
4
4
  log = logging.getLogger(__name__)
5
5
 
6
- version = __version__ = "4.60.0"
6
+ version = __version__ = "4.60.1"
7
7
 
8
8
  __all__ = ["version", "log", "configLogger"]
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
- @register_attr() or @register_attrs()) visit() functions.
82
+ ``@register_attr()`` or ``@register_attrs()``) ``visit()`` functions.
83
83
 
84
- If there is no user-registered visit function, of if there is and it
85
- returns True, or it returns None (or doesn't return anything) and
86
- visitor.defaultStop is False (default), then the visitor will proceed
87
- to call self.visitAttr()"""
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
- @register()) visit function for the type of object. If there is, it
128
- will be called, and (visitor, obj, *args, **kwargs) will be passed to
129
- the user visit function.
130
-
131
- If there is no user-registered visit function, of if there is and it
132
- returns True, or it returns None (or doesn't return anything) and
133
- visitor.defaultStop is False (default), then the visitor will proceed
134
- to dispatch to one of self.visitObject(), self.visitList(),
135
- self.visitDict(), or self.visitLeaf() (any of which can be overriden in
136
- a subclass)."""
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
@@ -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
- 'BASE', 'JSTF', 'DSIG', 'EBDT', 'EBLC', 'EBSC', 'PCLT', 'LTSH'
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
- base_indices = self.BaseCoverage.subset(s.glyphs)
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
- ligature_indices = self.LigatureCoverage.subset(s.glyphs)
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
- mark2_indices = self.Mark2Coverage.subset(s.glyphs)
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.subset_features(feature_indices)
2111
+ self.table.FeatureVariations.prune_features(feature_index_map)
1993
2112
  if self.table.ScriptList:
1994
- self.table.ScriptList.subset_features(
1995
- feature_indices, self.retain_empty_scripts()
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",
@@ -534,7 +534,7 @@ class UFOReader(_UFOBaseIO):
534
534
  raise UFOLibError(message)
535
535
  return groups
536
536
 
537
- def getKerningGroupRenameMaps(
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
- getKerningGroupRenameMaps method.
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.0
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,4 +1,4 @@
1
- fontTools/__init__.py,sha256=-tK8qTdJjP4_Cywkr803Z5-SQva92shSxi0NbjVPlgU,191
1
+ fontTools/__init__.py,sha256=Kx6CqtCPpUeyrf7vwLVhBcoe7feUBG34YBh7HlfUk2Q,191
2
2
  fontTools/__main__.py,sha256=T8Tg8xPKHOCVoYVG82p_zpQXfW7_ERRAphBkZVvhWN8,960
3
3
  fontTools/afmLib.py,sha256=YbmmjT8Du6qFUhFHwnAhOdvsyfXszODVjSJtd18CCjY,13603
4
4
  fontTools/agl.py,sha256=4aKwnbvSVUa39eV5Ka8e5ULwV-IEp4pcfwlMwEH_z3k,118208
@@ -26,7 +26,7 @@ fontTools/cu2qu/__main__.py,sha256=6Vb8Ler3yqJ5w84UwlMJV6cS01uhV4PN10OlXQ6jlqo,9
26
26
  fontTools/cu2qu/benchmark.py,sha256=FwdvNjKfWHo18_CX0CO8AY5c68XSBE4M4TJo_EkB4q8,1350
27
27
  fontTools/cu2qu/cli.py,sha256=CvWzC5a6XF_v5o0yrS4vGI1JXiVVLzSJahTIqpJmiPk,6274
28
28
  fontTools/cu2qu/cu2qu.c,sha256=2FsHl-S3Z_szu4zNH2Hv9ouU4Kg7jlK_GFax_U57xeU,653740
29
- fontTools/cu2qu/cu2qu.cp312-win_amd64.pyd,sha256=AwfNr0PO3Ov5gNjufzqGmGodRuIsbKv7Glti6ZhxA5w,101888
29
+ fontTools/cu2qu/cu2qu.cp312-win_amd64.pyd,sha256=ASHA6J4QxyZQ5kRDJuUWpXeRC6yCMQVUmaJQOjUA7aE,101888
30
30
  fontTools/cu2qu/cu2qu.py,sha256=nyniLf18Y6D7CBjp6NXZj2XOpYdaiiZVFprZLiFTwtc,18549
31
31
  fontTools/cu2qu/errors.py,sha256=uYyPSs_x-EMJKO2S3cLGWyk_KlHoOoh_XEtdB_oKBp0,2518
32
32
  fontTools/cu2qu/ufo.py,sha256=Mpd_7Be9jxNcOKFqkyRp8Oem3CS3R-ZYMMSD03LJL6o,12143
@@ -45,7 +45,7 @@ fontTools/feaLib/ast.py,sha256=q-UvEPZ97AAHpggVOzVHdgfTcE072kuOK08rdAYpCXU,76301
45
45
  fontTools/feaLib/builder.py,sha256=_ofuSJ9Jtz1Ybzk4ReCWSa431PXfIq-UcVkYZ2B0Ruo,75565
46
46
  fontTools/feaLib/error.py,sha256=pqi8F2tnH2h7pXVffxwzuBuWaSHMzZsXs5VckdQKQAI,670
47
47
  fontTools/feaLib/lexer.c,sha256=y9M2Lf0jZy0tYvxpZBWoPs5DZPOVIoZSzmD5Ab5jjRM,771641
48
- fontTools/feaLib/lexer.cp312-win_amd64.pyd,sha256=rUv7we0rzHcCNalFCw7qlcz6rUuDW44zNv0AaJFyaDU,118272
48
+ fontTools/feaLib/lexer.cp312-win_amd64.pyd,sha256=9kj3N-cmacDawX4hjWPiP3bJcWIHz-u-i5x4PrhPmPc,118272
49
49
  fontTools/feaLib/lexer.py,sha256=7VZ3NPFH7V1mvRbym111BNKvbB4hLfGLTMS0VV_3Ipw,11408
50
50
  fontTools/feaLib/location.py,sha256=teHrhjT8zzImcGBEJS1J43oaX9onCPu_pynxS8d-tUg,246
51
51
  fontTools/feaLib/lookupDebugInfo.py,sha256=h4Ig8kmEk5WlGf1C9JJAbbOKQK5OwkFLdj8CT7fOkmU,316
@@ -63,7 +63,7 @@ fontTools/merge/util.py,sha256=3alo4b7mhFNC6h8PjeqNU99dS7EuO8sdZkZpvRsEE6E,3521
63
63
  fontTools/misc/__init__.py,sha256=QoK6HlOoqtVqX5gOyv0bJiTXsVBbBRreUifdccWNp2k,76
64
64
  fontTools/misc/arrayTools.py,sha256=baENNALPvYRUhS4rdx_F3ltOmVIf1PV9G2EaMt7gAHM,11907
65
65
  fontTools/misc/bezierTools.c,sha256=wub0OhTy2OMmdZ6ppQxP1YTKNzEskK_i6lNfRiVNW9M,1861888
66
- fontTools/misc/bezierTools.cp312-win_amd64.pyd,sha256=q1vvMWda2Y1-6u4F46nDN0MCqJG3C7dUlZZE7jdfw40,336896
66
+ fontTools/misc/bezierTools.cp312-win_amd64.pyd,sha256=6ft5Hk_YHthLqKudHcSboVmD_1F559gGSlIT1uW5VQ0,336896
67
67
  fontTools/misc/bezierTools.py,sha256=m4j14ckKYtrKy8NhFFFY_Uv3kuL8g-SWNdEKUzqGjRQ,46535
68
68
  fontTools/misc/classifyTools.py,sha256=wLTjOhLiZaLiwwUTj2Ad5eZ5T_38W0Eo_uzRGWHWYvE,5783
69
69
  fontTools/misc/cliTools.py,sha256=7zKOXczaCKRMW6Yv5jdCZYHco8y0-lfimhIWzQ2IL8A,1915
@@ -95,7 +95,7 @@ fontTools/misc/timeTools.py,sha256=lmncKUKvxQKO4Kqx2k7UNFkYYpj2n5CwR1lPiLZv3tA,2
95
95
  fontTools/misc/transform.py,sha256=pCR0tbKzmhH6crB_rDT5hnAWySztW_XqL0efmKOVsCU,16314
96
96
  fontTools/misc/treeTools.py,sha256=IMopMUcuhelvz8gNra50Zc1w8DSlWywnL6DFaz1ijQs,1314
97
97
  fontTools/misc/vector.py,sha256=yaNixq5pXXpPCD_wRP-LsXYSLr4WPX_y92Po05FeLU0,4209
98
- fontTools/misc/visitor.py,sha256=30EPyUKvNsYU81uiYKjp_9gFj2KSqF8W2y_ldyIBJYQ,5760
98
+ fontTools/misc/visitor.py,sha256=jZ2I2yTiao67kUL2GPLx1Rpuw-X2gIx0ikqZOkcfYf8,5912
99
99
  fontTools/misc/xmlReader.py,sha256=gqYg3qlDkrKsO55DPaJ-dU0i5rltqZgnKlrXmR2Z7dQ,6768
100
100
  fontTools/misc/xmlWriter.py,sha256=rGn6BDiB2MPrhoNabDbY4vAHZC6-mEciwCJXtOL6hMA,7060
101
101
  fontTools/misc/filesystem/__init__.py,sha256=wAfcTDA9TBfzZpEN-jnlhNgJ-7tsvsEpbEb3TP9B8Vs,2079
@@ -133,7 +133,7 @@ fontTools/pens/filterPen.py,sha256=wvNVXLGKmNxJcpAKAnmev2wy6Rshq6aXgRfxL0Iobdg,1
133
133
  fontTools/pens/freetypePen.py,sha256=NqNzXrOTDckoH4N6WLnj-KuxGcg6z7DlqSCfmpq8qAE,20370
134
134
  fontTools/pens/hashPointPen.py,sha256=ZAU87uw5ge3Kb4i9kRV28a5VFeZ_TWSsJabyAzwAHrU,3662
135
135
  fontTools/pens/momentsPen.c,sha256=tccF2oegGdXqHhmkR_ReOr-SveDxltMm67E3XryuVbI,578781
136
- fontTools/pens/momentsPen.cp312-win_amd64.pyd,sha256=UcLkeVLhOy1C63aLmcHWIAzzAQphP5HyyctAH8_sK50,90624
136
+ fontTools/pens/momentsPen.cp312-win_amd64.pyd,sha256=83cji7dai7audUBxq_SRtv44kYjcgnfSj_bQq7YUgLY,90624
137
137
  fontTools/pens/momentsPen.py,sha256=Z-V5CjQBSj3qPxg3C_DBFKExqno89nOe3jWwHT9_xsM,26537
138
138
  fontTools/pens/perimeterPen.py,sha256=Zy5F8QzaNJAkkQQSb2QJCp-wZTvDAjBn-B099t2ABds,2222
139
139
  fontTools/pens/pointInsidePen.py,sha256=Hy48iR5NWV3x_wWoos-UC7GMtwvvUhd_q_ykiwaWdzQ,6547
@@ -157,9 +157,9 @@ fontTools/qu2cu/__main__.py,sha256=leKpToUNNyHf0nobr1I19vus2ziA1pO7rRKkreat-Xw,1
157
157
  fontTools/qu2cu/benchmark.py,sha256=PFxx2Bfu7-KuNrzdOIBXHPZvyNphqqcTVy4CneaCo3M,1456
158
158
  fontTools/qu2cu/cli.py,sha256=1QLBTSZW7e_VATJN9vjszRxIk_-Xjxu1KP53yX4T7q8,3839
159
159
  fontTools/qu2cu/qu2cu.c,sha256=zpMJuiGamoWxvBEqP84gp1DPDsSlvbqMxf0gkxgA0u8,707187
160
- fontTools/qu2cu/qu2cu.cp312-win_amd64.pyd,sha256=vhLN_yhwwFmQFIIn3-B6OSYNC8Z-xxH67vXxiO7wZVk,107520
160
+ fontTools/qu2cu/qu2cu.cp312-win_amd64.pyd,sha256=z2j1V_NoMKX3lyj4rtiUKVxi9cnnmqJfSw5oxB8ilQU,107520
161
161
  fontTools/qu2cu/qu2cu.py,sha256=dtp5Zqhcs_NePwA2U5fgG2LtWleRwmBilTurau8sLL0,12693
162
- fontTools/subset/__init__.py,sha256=BIx4NBKTps8oFRnB_3uN6MDsQh10IPkrId5VyR9AI9M,141672
162
+ fontTools/subset/__init__.py,sha256=ALzTEOHbFPSwQB7T6ro7vopxv-rud6d3oo-9KqPe9z0,147359
163
163
  fontTools/subset/__main__.py,sha256=cEIC52EtGOJvFDfHXzi0M2EAYmyHAcI-ZZ0lb2y4r7s,101
164
164
  fontTools/subset/cff.py,sha256=GSmxdsokxuFKvJJQVcAIOhd5hYQq8KkzxnXE_dgm8yo,6329
165
165
  fontTools/subset/svg.py,sha256=y_yTZuAm3bjcoEOFu5likXoHuG5u1oNiv0mOni2Z9fQ,9637
@@ -283,7 +283,7 @@ fontTools/ttLib/tables/sbixGlyph.py,sha256=a-mCmO5EibN_He7QQohG06Qg-fCOHWiNFMAbC
283
283
  fontTools/ttLib/tables/sbixStrike.py,sha256=Q1F4rFlj-SwUKFDJkcta1oz_b393dt9VYFOyxaFSc_o,6828
284
284
  fontTools/ttLib/tables/table_API_readme.txt,sha256=E9lwGW1P_dGqy1FYBcYLVEDDmikbsqW4pUtpv1RKCJU,2839
285
285
  fontTools/ttLib/tables/ttProgram.py,sha256=vkRtptH7QXD0Ng8LNzh-A_Ln27VPCxSJOXgW8878nSo,36482
286
- fontTools/ufoLib/__init__.py,sha256=oXmFxjiUSr4N4PEmjTsyS8EuTfK1cJOF4mKvJd5UeD4,101536
286
+ fontTools/ufoLib/__init__.py,sha256=SNoNeSIgQMccB0jZSnlCEPQ4nRF2aSVC8fSSlJZ0K4c,101556
287
287
  fontTools/ufoLib/converters.py,sha256=7B5JwsY2GrtgEcPirkkYnsWGvQpbntQRaERFH1LiG7c,13851
288
288
  fontTools/ufoLib/errors.py,sha256=pgJKS2A5RcsfQS2Z6Y_l3mIz62-VD_SrpIysKmywuYA,875
289
289
  fontTools/ufoLib/etree.py,sha256=kTUP1EzN2wSXZ4jwAX8waNfKz52u7jc2qQ2LrqPYLBw,237
@@ -315,7 +315,7 @@ fontTools/varLib/interpolatableTestContourOrder.py,sha256=Pbt0jW0LoVggIwrtADZ7HW
315
315
  fontTools/varLib/interpolatableTestStartingPoint.py,sha256=f5MJ3mj8MctJCvDJwqmW1fIVOgovUMYAOela9HweaRU,4403
316
316
  fontTools/varLib/interpolate_layout.py,sha256=tTPUes_K7MwooUO_wac9AeFEVgL1uGSz4ITYiOizaME,3813
317
317
  fontTools/varLib/iup.c,sha256=ah8enmoMLi_AO2jjHrcRou4Wip4X8Y-0ik8_N-KNGmw,847577
318
- fontTools/varLib/iup.cp312-win_amd64.pyd,sha256=freBLJaWki08w1XLinL16Vp0eNA7bLU8p3jXxexW_sE,131584
318
+ fontTools/varLib/iup.cp312-win_amd64.pyd,sha256=jLt87jbeFGG0PWCEZw83owF7wGEvShTpL1NW5BUGKUw,131584
319
319
  fontTools/varLib/iup.py,sha256=O_xPJOBECrNDbQqCC3e5xf9KsWXUd1i3BAp9Fl6Hv2Y,15474
320
320
  fontTools/varLib/merger.py,sha256=V-B17poOYbbrRsfUYJbdqt46GtRfG833MKwtv9NOB3Q,62519
321
321
  fontTools/varLib/models.py,sha256=ZqQb1Lapj5dCO8dwa3UTx1LsIpF0-GiDte32t_TMJJQ,23040
@@ -343,11 +343,11 @@ fontTools/voltLib/error.py,sha256=3TsaZBA82acFd2j5Beq3WUQTURTKM0zxOnUFGZovSNA,40
343
343
  fontTools/voltLib/lexer.py,sha256=v9V4zdBO2VqVJG__IWrL8fv_CRURmh2eD_1UpbIJn9g,3467
344
344
  fontTools/voltLib/parser.py,sha256=HS72gxtFzvcPSwEbUYj3E41CPK7ZqK9mSe0nLRxn-IY,26060
345
345
  fontTools/voltLib/voltToFea.py,sha256=nS-OSlx_a-TngGICFNKyFxMhjqkV3OQLcvyzw4sQFyk,37460
346
- fonttools-4.60.0.data/data/share/man/man1/ttx.1,sha256=E71F9mRNWlttVpzlnP7w_fqkQygPkph5s-AtVa0Js50,5601
347
- fonttools-4.60.0.dist-info/licenses/LICENSE,sha256=Ir74Bpfs-qF_l-YrmibfoSggvgVYPo3RKtFpskEnTJk,1093
348
- fonttools-4.60.0.dist-info/licenses/LICENSE.external,sha256=sIKl-Gd1smQfAbzLi5yCkISB3l9QK7JUseE7_CqfMD0,20410
349
- fonttools-4.60.0.dist-info/METADATA,sha256=PgJqP6RUEsuXOOvZS6DpPWUA9MQK6_-1-osJkq100CU,113831
350
- fonttools-4.60.0.dist-info/WHEEL,sha256=8UP9x9puWI0P1V_d7K2oMTBqfeLNm21CTzZ_Ptr0NXU,101
351
- fonttools-4.60.0.dist-info/entry_points.txt,sha256=8kVHddxfFWA44FSD4mBpmC-4uCynQnkoz_9aNJb227Y,147
352
- fonttools-4.60.0.dist-info/top_level.txt,sha256=rRgRylrXzekqWOsrhygzib12pQ7WILf7UGjqEwkIFDM,10
353
- fonttools-4.60.0.dist-info/RECORD,,
346
+ fonttools-4.60.1.data/data/share/man/man1/ttx.1,sha256=E71F9mRNWlttVpzlnP7w_fqkQygPkph5s-AtVa0Js50,5601
347
+ fonttools-4.60.1.dist-info/licenses/LICENSE,sha256=Ir74Bpfs-qF_l-YrmibfoSggvgVYPo3RKtFpskEnTJk,1093
348
+ fonttools-4.60.1.dist-info/licenses/LICENSE.external,sha256=sIKl-Gd1smQfAbzLi5yCkISB3l9QK7JUseE7_CqfMD0,20410
349
+ fonttools-4.60.1.dist-info/METADATA,sha256=jvqLM8U0BGUXOJ7jWp22ISqXYUaqovRTQppZhgkPJdE,114562
350
+ fonttools-4.60.1.dist-info/WHEEL,sha256=8UP9x9puWI0P1V_d7K2oMTBqfeLNm21CTzZ_Ptr0NXU,101
351
+ fonttools-4.60.1.dist-info/entry_points.txt,sha256=8kVHddxfFWA44FSD4mBpmC-4uCynQnkoz_9aNJb227Y,147
352
+ fonttools-4.60.1.dist-info/top_level.txt,sha256=rRgRylrXzekqWOsrhygzib12pQ7WILf7UGjqEwkIFDM,10
353
+ fonttools-4.60.1.dist-info/RECORD,,