fonttools 4.58.5__cp312-cp312-musllinux_1_2_aarch64.whl → 4.59.1__cp312-cp312-musllinux_1_2_aarch64.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.

Files changed (67) hide show
  1. fontTools/__init__.py +1 -1
  2. fontTools/cffLib/CFF2ToCFF.py +40 -10
  3. fontTools/cffLib/transforms.py +11 -6
  4. fontTools/cu2qu/cu2qu.c +21 -6
  5. fontTools/cu2qu/cu2qu.cpython-312-aarch64-linux-musl.so +0 -0
  6. fontTools/feaLib/builder.py +6 -1
  7. fontTools/feaLib/lexer.c +21 -6
  8. fontTools/feaLib/lexer.cpython-312-aarch64-linux-musl.so +0 -0
  9. fontTools/merge/__init__.py +1 -1
  10. fontTools/misc/bezierTools.c +24 -9
  11. fontTools/misc/bezierTools.cpython-312-aarch64-linux-musl.so +0 -0
  12. fontTools/misc/filesystem/__init__.py +68 -0
  13. fontTools/misc/filesystem/_base.py +134 -0
  14. fontTools/misc/filesystem/_copy.py +45 -0
  15. fontTools/misc/filesystem/_errors.py +54 -0
  16. fontTools/misc/filesystem/_info.py +75 -0
  17. fontTools/misc/filesystem/_osfs.py +164 -0
  18. fontTools/misc/filesystem/_path.py +67 -0
  19. fontTools/misc/filesystem/_subfs.py +92 -0
  20. fontTools/misc/filesystem/_tempfs.py +34 -0
  21. fontTools/misc/filesystem/_tools.py +34 -0
  22. fontTools/misc/filesystem/_walk.py +55 -0
  23. fontTools/misc/filesystem/_zipfs.py +204 -0
  24. fontTools/misc/psCharStrings.py +17 -2
  25. fontTools/misc/sstruct.py +2 -6
  26. fontTools/misc/xmlWriter.py +28 -1
  27. fontTools/pens/momentsPen.c +11 -4
  28. fontTools/pens/momentsPen.cpython-312-aarch64-linux-musl.so +0 -0
  29. fontTools/pens/roundingPen.py +2 -2
  30. fontTools/qu2cu/qu2cu.c +23 -8
  31. fontTools/qu2cu/qu2cu.cpython-312-aarch64-linux-musl.so +0 -0
  32. fontTools/subset/__init__.py +11 -11
  33. fontTools/ttLib/sfnt.py +2 -3
  34. fontTools/ttLib/tables/S__i_l_f.py +2 -2
  35. fontTools/ttLib/tables/T_S_I__1.py +2 -5
  36. fontTools/ttLib/tables/T_S_I__5.py +2 -2
  37. fontTools/ttLib/tables/_c_m_a_p.py +1 -1
  38. fontTools/ttLib/tables/_c_v_t.py +1 -2
  39. fontTools/ttLib/tables/_g_l_y_f.py +9 -10
  40. fontTools/ttLib/tables/_g_v_a_r.py +6 -3
  41. fontTools/ttLib/tables/_h_d_m_x.py +4 -4
  42. fontTools/ttLib/tables/_h_m_t_x.py +7 -3
  43. fontTools/ttLib/tables/_l_o_c_a.py +2 -2
  44. fontTools/ttLib/tables/_p_o_s_t.py +3 -4
  45. fontTools/ttLib/tables/otBase.py +2 -4
  46. fontTools/ttLib/tables/otTables.py +7 -12
  47. fontTools/ttLib/tables/sbixStrike.py +3 -3
  48. fontTools/ttLib/ttFont.py +7 -16
  49. fontTools/ttLib/woff2.py +10 -13
  50. fontTools/ufoLib/__init__.py +20 -25
  51. fontTools/ufoLib/glifLib.py +12 -17
  52. fontTools/ufoLib/validators.py +2 -4
  53. fontTools/unicodedata/__init__.py +2 -0
  54. fontTools/varLib/featureVars.py +8 -0
  55. fontTools/varLib/hvar.py +1 -1
  56. fontTools/varLib/instancer/__init__.py +65 -5
  57. fontTools/varLib/iup.c +23 -8
  58. fontTools/varLib/iup.cpython-312-aarch64-linux-musl.so +0 -0
  59. fontTools/varLib/mutator.py +11 -0
  60. {fonttools-4.58.5.dist-info → fonttools-4.59.1.dist-info}/METADATA +42 -12
  61. {fonttools-4.58.5.dist-info → fonttools-4.59.1.dist-info}/RECORD +67 -55
  62. {fonttools-4.58.5.dist-info → fonttools-4.59.1.dist-info}/licenses/LICENSE.external +29 -0
  63. {fonttools-4.58.5.data → fonttools-4.59.1.data}/data/share/man/man1/ttx.1 +0 -0
  64. {fonttools-4.58.5.dist-info → fonttools-4.59.1.dist-info}/WHEEL +0 -0
  65. {fonttools-4.58.5.dist-info → fonttools-4.59.1.dist-info}/entry_points.txt +0 -0
  66. {fonttools-4.58.5.dist-info → fonttools-4.59.1.dist-info}/licenses/LICENSE +0 -0
  67. {fonttools-4.58.5.dist-info → fonttools-4.59.1.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,55 @@
1
+ from __future__ import annotations
2
+
3
+ import typing
4
+ from collections import deque
5
+ from collections.abc import Collection, Iterator
6
+
7
+ from ._path import combine
8
+
9
+ if typing.TYPE_CHECKING:
10
+ from typing import Callable
11
+
12
+ from ._base import FS
13
+ from ._info import Info
14
+
15
+
16
+ class BoundWalker:
17
+ def __init__(self, fs: FS):
18
+ self._fs = fs
19
+
20
+ def _iter_walk(
21
+ self, path: str, namespaces: Collection[str] | None = None
22
+ ) -> Iterator[tuple[str, Info | None]]:
23
+ """Walk files using a *breadth first* search."""
24
+ queue = deque([path])
25
+ push = queue.appendleft
26
+ pop = queue.pop
27
+ _scan = self._fs.scandir
28
+ _combine = combine
29
+
30
+ while queue:
31
+ dir_path = pop()
32
+ for info in _scan(dir_path, namespaces=namespaces):
33
+ if info.is_dir:
34
+ yield dir_path, info
35
+ push(_combine(dir_path, info.name))
36
+ else:
37
+ yield dir_path, info
38
+ yield path, None
39
+
40
+ def _filter(
41
+ self,
42
+ include: Callable[[str, Info], bool] = lambda path, info: True,
43
+ path: str = "/",
44
+ namespaces: Collection[str] | None = None,
45
+ ) -> Iterator[str]:
46
+ _combine = combine
47
+ for path, info in self._iter_walk(path, namespaces):
48
+ if info is not None and include(path, info):
49
+ yield _combine(path, info.name)
50
+
51
+ def files(self, path: str = "/") -> Iterator[str]:
52
+ yield from self._filter(lambda _, info: info.is_file, path)
53
+
54
+ def dirs(self, path: str = "/") -> Iterator[str]:
55
+ yield from self._filter(lambda _, info: info.is_dir, path)
@@ -0,0 +1,204 @@
1
+ from __future__ import annotations
2
+
3
+ import io
4
+ import os
5
+ import shutil
6
+ import stat
7
+ import typing
8
+ import zipfile
9
+ from datetime import datetime
10
+
11
+ from ._base import FS
12
+ from ._errors import FileExpected, ResourceNotFound, ResourceReadOnly
13
+ from ._info import Info
14
+ from ._path import dirname, forcedir, normpath, relpath
15
+ from ._tempfs import TempFS
16
+
17
+ if typing.TYPE_CHECKING:
18
+ from collections.abc import Collection
19
+ from typing import IO, Any
20
+
21
+ from ._subfs import SubFS
22
+
23
+
24
+ class ZipFS(FS):
25
+ """Read and write zip files."""
26
+
27
+ def __new__(
28
+ cls, file: str | os.PathLike, write: bool = False, encoding: str = "utf-8"
29
+ ):
30
+ if write:
31
+ return WriteZipFS(file, encoding)
32
+ else:
33
+ return ReadZipFS(file, encoding)
34
+
35
+ if typing.TYPE_CHECKING:
36
+
37
+ def __init__(
38
+ self, file: str | os.PathLike, write: bool = False, encoding: str = "utf-8"
39
+ ):
40
+ pass
41
+
42
+
43
+ class ReadZipFS(FS):
44
+ """A readable zip file."""
45
+
46
+ def __init__(self, file: str | os.PathLike, encoding: str = "utf-8"):
47
+ super().__init__()
48
+ self._file = os.fspath(file)
49
+ self.encoding = encoding # unused
50
+ self._zip = zipfile.ZipFile(file, "r")
51
+ self._directory_fs = None
52
+
53
+ def __repr__(self) -> str:
54
+ return f"ReadZipFS({self._file!r})"
55
+
56
+ def __str__(self) -> str:
57
+ return f"<zipfs '{self._file}'>"
58
+
59
+ def _path_to_zip_name(self, path: str) -> str:
60
+ """Convert a path to a zip file name."""
61
+ path = relpath(normpath(path))
62
+ if self._directory.isdir(path):
63
+ path = forcedir(path)
64
+ return path
65
+
66
+ @property
67
+ def _directory(self) -> TempFS:
68
+ if self._directory_fs is None:
69
+ self._directory_fs = _fs = TempFS()
70
+ for zip_name in self._zip.namelist():
71
+ resource_name = zip_name
72
+ if resource_name.endswith("/"):
73
+ _fs.makedirs(resource_name, recreate=True)
74
+ else:
75
+ _fs.makedirs(dirname(resource_name), recreate=True)
76
+ _fs.create(resource_name)
77
+ return self._directory_fs
78
+
79
+ def close(self):
80
+ super(ReadZipFS, self).close()
81
+ self._zip.close()
82
+ if self._directory_fs is not None:
83
+ self._directory_fs.close()
84
+
85
+ def getinfo(self, path: str, namespaces: Collection[str] | None = None) -> Info:
86
+ namespaces = namespaces or ()
87
+ raw_info = {}
88
+
89
+ if path == "/":
90
+ raw_info["basic"] = {"name": "", "is_dir": True}
91
+ if "details" in namespaces:
92
+ raw_info["details"] = {"type": stat.S_IFDIR}
93
+ else:
94
+ basic_info = self._directory.getinfo(path)
95
+ raw_info["basic"] = {"name": basic_info.name, "is_dir": basic_info.is_dir}
96
+
97
+ if "details" in namespaces:
98
+ zip_name = self._path_to_zip_name(path)
99
+ try:
100
+ zip_info = self._zip.getinfo(zip_name)
101
+ except KeyError:
102
+ pass
103
+ else:
104
+ if "details" in namespaces:
105
+ raw_info["details"] = {
106
+ "size": zip_info.file_size,
107
+ "type": int(
108
+ stat.S_IFDIR if basic_info.is_dir else stat.S_IFREG
109
+ ),
110
+ "modified": datetime(*zip_info.date_time).timestamp(),
111
+ }
112
+
113
+ return Info(raw_info)
114
+
115
+ def exists(self, path: str) -> bool:
116
+ self.check()
117
+ return self._directory.exists(path)
118
+
119
+ def isdir(self, path: str) -> bool:
120
+ self.check()
121
+ return self._directory.isdir(path)
122
+
123
+ def isfile(self, path: str) -> bool:
124
+ self.check()
125
+ return self._directory.isfile(path)
126
+
127
+ def listdir(self, path: str) -> str:
128
+ self.check()
129
+ return self._directory.listdir(path)
130
+
131
+ def makedir(self, path: str, recreate: bool = False) -> SubFS:
132
+ self.check()
133
+ raise ResourceReadOnly(path)
134
+
135
+ def makedirs(self, path: str, recreate: bool = False) -> SubFS:
136
+ self.check()
137
+ raise ResourceReadOnly(path)
138
+
139
+ def remove(self, path: str):
140
+ self.check()
141
+ raise ResourceReadOnly(path)
142
+
143
+ def removedir(self, path: str):
144
+ self.check()
145
+ raise ResourceReadOnly(path)
146
+
147
+ def removetree(self, path: str):
148
+ self.check()
149
+ raise ResourceReadOnly(path)
150
+
151
+ def movedir(self, src: str, dst: str, create: bool = False):
152
+ self.check()
153
+ raise ResourceReadOnly(src)
154
+
155
+ def readbytes(self, path: str) -> bytes:
156
+ self.check()
157
+ if not self._directory.isfile(path):
158
+ raise ResourceNotFound(path)
159
+ zip_name = self._path_to_zip_name(path)
160
+ zip_bytes = self._zip.read(zip_name)
161
+ return zip_bytes
162
+
163
+ def open(self, path: str, mode: str = "rb", **kwargs) -> IO[Any]:
164
+ self.check()
165
+ if self._directory.isdir(path):
166
+ raise FileExpected(f"{path!r} is a directory")
167
+
168
+ zip_mode = mode[0]
169
+ if zip_mode == "r" and not self._directory.exists(path):
170
+ raise ResourceNotFound(f"No such file or directory: {path!r}")
171
+
172
+ if any(m in mode for m in "wax+"):
173
+ raise ResourceReadOnly(path)
174
+
175
+ zip_name = self._path_to_zip_name(path)
176
+ stream = self._zip.open(zip_name, zip_mode)
177
+ if "b" in mode:
178
+ if kwargs:
179
+ raise ValueError("encoding args invalid for binary operation")
180
+ return stream
181
+ # Text mode
182
+ return io.TextIOWrapper(stream, **kwargs)
183
+
184
+
185
+ class WriteZipFS(TempFS):
186
+ """A writable zip file."""
187
+
188
+ def __init__(self, file: str | os.PathLike, encoding: str = "utf-8"):
189
+ super().__init__()
190
+ self._file = os.fspath(file)
191
+ self.encoding = encoding # unused
192
+
193
+ def __repr__(self) -> str:
194
+ return f"WriteZipFS({self._file!r})"
195
+
196
+ def __str__(self) -> str:
197
+ return f"<zipfs-write '{self._file}'>"
198
+
199
+ def close(self):
200
+ base_name = os.path.splitext(self._file)[0]
201
+ shutil.make_archive(base_name, format="zip", root_dir=self._temp_dir)
202
+ if self._file != base_name + ".zip":
203
+ shutil.move(base_name + ".zip", self._file)
204
+ super().close()
@@ -338,7 +338,7 @@ class SimpleT2Decompiler(object):
338
338
  self.numRegions = 0
339
339
  self.vsIndex = 0
340
340
 
341
- def execute(self, charString):
341
+ def execute(self, charString, *, pushToStack=None):
342
342
  self.callingStack.append(charString)
343
343
  needsDecompilation = charString.needsDecompilation()
344
344
  if needsDecompilation:
@@ -346,7 +346,8 @@ class SimpleT2Decompiler(object):
346
346
  pushToProgram = program.append
347
347
  else:
348
348
  pushToProgram = lambda x: None
349
- pushToStack = self.operandStack.append
349
+ if pushToStack is None:
350
+ pushToStack = self.operandStack.append
350
351
  index = 0
351
352
  while True:
352
353
  token, isOperator, index = charString.getToken(index)
@@ -551,6 +552,20 @@ t1Operators = [
551
552
  ]
552
553
 
553
554
 
555
+ class T2StackUseExtractor(SimpleT2Decompiler):
556
+
557
+ def execute(self, charString):
558
+ maxStackUse = 0
559
+
560
+ def pushToStack(value):
561
+ nonlocal maxStackUse
562
+ self.operandStack.append(value)
563
+ maxStackUse = max(maxStackUse, len(self.operandStack))
564
+
565
+ super().execute(charString, pushToStack=pushToStack)
566
+ return maxStackUse
567
+
568
+
554
569
  class T2WidthExtractor(SimpleT2Decompiler):
555
570
  def __init__(
556
571
  self,
fontTools/misc/sstruct.py CHANGED
@@ -64,10 +64,7 @@ def pack(fmt, obj):
64
64
  elements = []
65
65
  if not isinstance(obj, dict):
66
66
  obj = obj.__dict__
67
- string_index = formatstring
68
- if formatstring.startswith(">"):
69
- string_index = formatstring[1:]
70
- for ix, name in enumerate(names.keys()):
67
+ for name in names.keys():
71
68
  value = obj[name]
72
69
  if name in fixes:
73
70
  # fixed point conversion
@@ -96,8 +93,7 @@ def unpack(fmt, data, obj=None):
96
93
  else:
97
94
  d = obj.__dict__
98
95
  elements = struct.unpack(formatstring, data)
99
- for i in range(len(names)):
100
- name = list(names.keys())[i]
96
+ for i, name in enumerate(names.keys()):
101
97
  value = elements[i]
102
98
  if name in fixes:
103
99
  # fixed point conversion
@@ -4,8 +4,22 @@ from fontTools.misc.textTools import byteord, strjoin, tobytes, tostr
4
4
  import sys
5
5
  import os
6
6
  import string
7
+ import logging
8
+ import itertools
7
9
 
8
10
  INDENT = " "
11
+ TTX_LOG = logging.getLogger("fontTools.ttx")
12
+ REPLACEMENT = "?"
13
+ ILLEGAL_XML_CHARS = dict.fromkeys(
14
+ itertools.chain(
15
+ range(0x00, 0x09),
16
+ (0x0B, 0x0C),
17
+ range(0x0E, 0x20),
18
+ range(0xD800, 0xE000),
19
+ (0xFFFE, 0xFFFF),
20
+ ),
21
+ REPLACEMENT,
22
+ )
9
23
 
10
24
 
11
25
  class XMLWriter(object):
@@ -168,12 +182,25 @@ class XMLWriter(object):
168
182
 
169
183
 
170
184
  def escape(data):
185
+ """Escape characters not allowed in `XML 1.0 <https://www.w3.org/TR/xml/#NT-Char>`_."""
171
186
  data = tostr(data, "utf_8")
172
187
  data = data.replace("&", "&amp;")
173
188
  data = data.replace("<", "&lt;")
174
189
  data = data.replace(">", "&gt;")
175
190
  data = data.replace("\r", "&#13;")
176
- return data
191
+
192
+ newData = data.translate(ILLEGAL_XML_CHARS)
193
+ if newData != data:
194
+ maxLen = 10
195
+ preview = repr(data)
196
+ if len(data) > maxLen:
197
+ preview = repr(data[:maxLen])[1:-1] + "..."
198
+ TTX_LOG.warning(
199
+ "Illegal XML character(s) found; replacing offending " "string %r with %r",
200
+ preview,
201
+ REPLACEMENT,
202
+ )
203
+ return newData
177
204
 
178
205
 
179
206
  def escapeattr(data):
@@ -1,4 +1,4 @@
1
- /* Generated by Cython 3.1.2 */
1
+ /* Generated by Cython 3.1.3 */
2
2
 
3
3
  /* BEGIN: Cython Metadata
4
4
  {
@@ -26,8 +26,8 @@ END: Cython Metadata */
26
26
  #elif PY_VERSION_HEX < 0x03080000
27
27
  #error Cython requires Python 3.8+.
28
28
  #else
29
- #define __PYX_ABI_VERSION "3_1_2"
30
- #define CYTHON_HEX_VERSION 0x030102F0
29
+ #define __PYX_ABI_VERSION "3_1_3"
30
+ #define CYTHON_HEX_VERSION 0x030103F0
31
31
  #define CYTHON_FUTURE_DIVISION 1
32
32
  /* CModulePreamble */
33
33
  #include <stddef.h>
@@ -390,6 +390,9 @@ END: Cython Metadata */
390
390
  enum { __pyx_check_sizeof_voidp = 1 / (int)(SIZEOF_VOID_P == sizeof(void*)) };
391
391
  #endif
392
392
  #endif
393
+ #ifndef CYTHON_LOCK_AND_GIL_DEADLOCK_AVOIDANCE_TIME
394
+ #define CYTHON_LOCK_AND_GIL_DEADLOCK_AVOIDANCE_TIME 100
395
+ #endif
393
396
  #ifndef __has_attribute
394
397
  #define __has_attribute(x) 0
395
398
  #endif
@@ -10172,6 +10175,7 @@ static int __Pyx_fix_up_extension_type_from_spec(PyType_Spec *spec, PyTypeObject
10172
10175
  changed = 1;
10173
10176
  }
10174
10177
  #endif // CYTHON_METH_FASTCALL
10178
+ #if !CYTHON_COMPILING_IN_PYPY
10175
10179
  else if (strcmp(memb->name, "__module__") == 0) {
10176
10180
  PyObject *descr;
10177
10181
  assert(memb->type == T_OBJECT);
@@ -10186,11 +10190,13 @@ static int __Pyx_fix_up_extension_type_from_spec(PyType_Spec *spec, PyTypeObject
10186
10190
  }
10187
10191
  changed = 1;
10188
10192
  }
10193
+ #endif // !CYTHON_COMPILING_IN_PYPY
10189
10194
  }
10190
10195
  memb++;
10191
10196
  }
10192
10197
  }
10193
10198
  #endif // !CYTHON_COMPILING_IN_LIMITED_API
10199
+ #if !CYTHON_COMPILING_IN_PYPY
10194
10200
  slot = spec->slots;
10195
10201
  while (slot && slot->slot && slot->slot != Py_tp_getset)
10196
10202
  slot++;
@@ -10222,6 +10228,7 @@ static int __Pyx_fix_up_extension_type_from_spec(PyType_Spec *spec, PyTypeObject
10222
10228
  ++getset;
10223
10229
  }
10224
10230
  }
10231
+ #endif // !CYTHON_COMPILING_IN_PYPY
10225
10232
  if (changed)
10226
10233
  PyType_Modified(type);
10227
10234
  #endif // PY_VERSION_HEX > 0x030900B1
@@ -10354,7 +10361,7 @@ bad:
10354
10361
  }
10355
10362
 
10356
10363
  /* CommonTypesMetaclass */
10357
- PyObject* __pyx_CommonTypesMetaclass_get_module(CYTHON_UNUSED PyObject *self, CYTHON_UNUSED void* context) {
10364
+ static PyObject* __pyx_CommonTypesMetaclass_get_module(CYTHON_UNUSED PyObject *self, CYTHON_UNUSED void* context) {
10358
10365
  return PyUnicode_FromString(__PYX_ABI_MODULE_NAME);
10359
10366
  }
10360
10367
  static PyGetSetDef __pyx_CommonTypesMetaclass_getset[] = {
@@ -116,8 +116,8 @@ class RoundingPointPen(FilterPointPen):
116
116
  def addComponent(self, baseGlyphName, transformation, identifier=None, **kwargs):
117
117
  xx, xy, yx, yy, dx, dy = transformation
118
118
  self._outPen.addComponent(
119
- baseGlyphName=baseGlyphName,
120
- transformation=Transform(
119
+ baseGlyphName,
120
+ Transform(
121
121
  self.transformRoundFunc(xx),
122
122
  self.transformRoundFunc(xy),
123
123
  self.transformRoundFunc(yx),
fontTools/qu2cu/qu2cu.c CHANGED
@@ -1,4 +1,4 @@
1
- /* Generated by Cython 3.1.2 */
1
+ /* Generated by Cython 3.1.3 */
2
2
 
3
3
  /* BEGIN: Cython Metadata
4
4
  {
@@ -32,8 +32,8 @@ END: Cython Metadata */
32
32
  #elif PY_VERSION_HEX < 0x03080000
33
33
  #error Cython requires Python 3.8+.
34
34
  #else
35
- #define __PYX_ABI_VERSION "3_1_2"
36
- #define CYTHON_HEX_VERSION 0x030102F0
35
+ #define __PYX_ABI_VERSION "3_1_3"
36
+ #define CYTHON_HEX_VERSION 0x030103F0
37
37
  #define CYTHON_FUTURE_DIVISION 1
38
38
  /* CModulePreamble */
39
39
  #include <stddef.h>
@@ -396,6 +396,9 @@ END: Cython Metadata */
396
396
  enum { __pyx_check_sizeof_voidp = 1 / (int)(SIZEOF_VOID_P == sizeof(void*)) };
397
397
  #endif
398
398
  #endif
399
+ #ifndef CYTHON_LOCK_AND_GIL_DEADLOCK_AVOIDANCE_TIME
400
+ #define CYTHON_LOCK_AND_GIL_DEADLOCK_AVOIDANCE_TIME 100
401
+ #endif
399
402
  #ifndef __has_attribute
400
403
  #define __has_attribute(x) 0
401
404
  #endif
@@ -1963,7 +1966,7 @@ static void __Pyx_Raise(PyObject *type, PyObject *value, PyObject *tb, PyObject
1963
1966
  static PyObject *__Pyx_PyLong_AbsNeg(PyObject *num);
1964
1967
  #define __Pyx_PyNumber_Absolute(x)\
1965
1968
  ((likely(PyLong_CheckExact(x))) ?\
1966
- (likely(__Pyx_PyLong_IsNonNeg(x)) ? (Py_INCREF(x), (x)) : __Pyx_PyLong_AbsNeg(x)) :\
1969
+ (likely(__Pyx_PyLong_IsNonNeg(x)) ? __Pyx_NewRef(x) : __Pyx_PyLong_AbsNeg(x)) :\
1967
1970
  PyNumber_Absolute(x))
1968
1971
  #else
1969
1972
  #define __Pyx_PyNumber_Absolute(x) PyNumber_Absolute(x)
@@ -10557,7 +10560,7 @@ static PyObject *__Pyx_PyLong_AbsNeg(PyObject *n) {
10557
10560
  PyObject *copy = _PyLong_Copy((PyLongObject*)n);
10558
10561
  if (likely(copy)) {
10559
10562
  #if PY_VERSION_HEX >= 0x030C00A7
10560
- ((PyLongObject*)copy)->long_value.lv_tag = ((PyLongObject*)copy)->long_value.lv_tag & ~_PyLong_SIGN_MASK;
10563
+ ((PyLongObject*)copy)->long_value.lv_tag ^= ((PyLongObject*)copy)->long_value.lv_tag & _PyLong_SIGN_MASK;
10561
10564
  #else
10562
10565
  __Pyx_SET_SIZE(copy, -Py_SIZE(copy));
10563
10566
  #endif
@@ -11193,6 +11196,13 @@ try_unpack:
11193
11196
 
11194
11197
  /* PyObjectCallMethod0 */
11195
11198
  static PyObject* __Pyx_PyObject_CallMethod0(PyObject* obj, PyObject* method_name) {
11199
+ #if CYTHON_VECTORCALL && (__PYX_LIMITED_VERSION_HEX >= 0x030C0000 || (!CYTHON_COMPILING_IN_LIMITED_API && PY_VERSION_HEX >= 0x03090000))
11200
+ PyObject *args[1] = {obj};
11201
+ (void) __Pyx_PyObject_GetMethod;
11202
+ (void) __Pyx_PyObject_CallOneArg;
11203
+ (void) __Pyx_PyObject_CallNoArg;
11204
+ return PyObject_VectorcallMethod(method_name, args, 1 | PY_VECTORCALL_ARGUMENTS_OFFSET, NULL);
11205
+ #else
11196
11206
  PyObject *method = NULL, *result = NULL;
11197
11207
  int is_method = __Pyx_PyObject_GetMethod(obj, method_name, &method);
11198
11208
  if (likely(is_method)) {
@@ -11205,6 +11215,7 @@ static PyObject* __Pyx_PyObject_CallMethod0(PyObject* obj, PyObject* method_name
11205
11215
  Py_DECREF(method);
11206
11216
  bad:
11207
11217
  return result;
11218
+ #endif
11208
11219
  }
11209
11220
 
11210
11221
  /* CallUnboundCMethod0 */
@@ -11742,6 +11753,7 @@ static int __Pyx_fix_up_extension_type_from_spec(PyType_Spec *spec, PyTypeObject
11742
11753
  changed = 1;
11743
11754
  }
11744
11755
  #endif // CYTHON_METH_FASTCALL
11756
+ #if !CYTHON_COMPILING_IN_PYPY
11745
11757
  else if (strcmp(memb->name, "__module__") == 0) {
11746
11758
  PyObject *descr;
11747
11759
  assert(memb->type == T_OBJECT);
@@ -11756,11 +11768,13 @@ static int __Pyx_fix_up_extension_type_from_spec(PyType_Spec *spec, PyTypeObject
11756
11768
  }
11757
11769
  changed = 1;
11758
11770
  }
11771
+ #endif // !CYTHON_COMPILING_IN_PYPY
11759
11772
  }
11760
11773
  memb++;
11761
11774
  }
11762
11775
  }
11763
11776
  #endif // !CYTHON_COMPILING_IN_LIMITED_API
11777
+ #if !CYTHON_COMPILING_IN_PYPY
11764
11778
  slot = spec->slots;
11765
11779
  while (slot && slot->slot && slot->slot != Py_tp_getset)
11766
11780
  slot++;
@@ -11792,6 +11806,7 @@ static int __Pyx_fix_up_extension_type_from_spec(PyType_Spec *spec, PyTypeObject
11792
11806
  ++getset;
11793
11807
  }
11794
11808
  }
11809
+ #endif // !CYTHON_COMPILING_IN_PYPY
11795
11810
  if (changed)
11796
11811
  PyType_Modified(type);
11797
11812
  #endif // PY_VERSION_HEX > 0x030900B1
@@ -12227,7 +12242,7 @@ bad:
12227
12242
  }
12228
12243
 
12229
12244
  /* CommonTypesMetaclass */
12230
- PyObject* __pyx_CommonTypesMetaclass_get_module(CYTHON_UNUSED PyObject *self, CYTHON_UNUSED void* context) {
12245
+ static PyObject* __pyx_CommonTypesMetaclass_get_module(CYTHON_UNUSED PyObject *self, CYTHON_UNUSED void* context) {
12231
12246
  return PyUnicode_FromString(__PYX_ABI_MODULE_NAME);
12232
12247
  }
12233
12248
  static PyGetSetDef __pyx_CommonTypesMetaclass_getset[] = {
@@ -14847,7 +14862,7 @@ static CYTHON_INLINE PyObject* __Pyx_PyObject_Call2Args(PyObject* function, PyOb
14847
14862
  }
14848
14863
 
14849
14864
  /* PyObjectCallMethod1 */
14850
- #if !(CYTHON_VECTORCALL && __PYX_LIMITED_VERSION_HEX >= 0x030C0000)
14865
+ #if !(CYTHON_VECTORCALL && (__PYX_LIMITED_VERSION_HEX >= 0x030C0000 || (!CYTHON_COMPILING_IN_LIMITED_API && PY_VERSION_HEX >= 0x03090000)))
14851
14866
  static PyObject* __Pyx__PyObject_CallMethod1(PyObject* method, PyObject* arg) {
14852
14867
  PyObject *result = __Pyx_PyObject_CallOneArg(method, arg);
14853
14868
  Py_DECREF(method);
@@ -14855,7 +14870,7 @@ static PyObject* __Pyx__PyObject_CallMethod1(PyObject* method, PyObject* arg) {
14855
14870
  }
14856
14871
  #endif
14857
14872
  static PyObject* __Pyx_PyObject_CallMethod1(PyObject* obj, PyObject* method_name, PyObject* arg) {
14858
- #if CYTHON_VECTORCALL && __PYX_LIMITED_VERSION_HEX >= 0x030C0000
14873
+ #if CYTHON_VECTORCALL && (__PYX_LIMITED_VERSION_HEX >= 0x030C0000 || (!CYTHON_COMPILING_IN_LIMITED_API && PY_VERSION_HEX >= 0x03090000))
14859
14874
  PyObject *args[2] = {obj, arg};
14860
14875
  (void) __Pyx_PyObject_GetMethod;
14861
14876
  (void) __Pyx_PyObject_CallOneArg;
@@ -27,16 +27,16 @@ from collections import Counter, defaultdict
27
27
  from functools import reduce
28
28
  from types import MethodType
29
29
 
30
- __usage__ = "pyftsubset font-file [glyph...] [--option=value]..."
30
+ __usage__ = "fonttools subset font-file [glyph...] [--option=value]..."
31
31
 
32
32
  __doc__ = (
33
33
  """\
34
- pyftsubset -- OpenType font subsetter and optimizer
34
+ fonttools subset -- OpenType font subsetter and optimizer
35
35
 
36
- pyftsubset is an OpenType font subsetter and optimizer, based on fontTools.
37
- It accepts any TT- or CFF-flavored OpenType (.otf or .ttf) or WOFF (.woff)
38
- font file. The subsetted glyph set is based on the specified glyphs
39
- or characters, and specified OpenType layout features.
36
+ fonttools subset is an OpenType font subsetter and optimizer, based on
37
+ fontTools. It accepts any TT- or CFF-flavored OpenType (.otf or .ttf)
38
+ or WOFF (.woff) font file. The subsetted glyph set is based on the
39
+ specified glyphs or characters, and specified OpenType layout features.
40
40
 
41
41
  The tool also performs some size-reducing optimizations, aimed for using
42
42
  subset fonts as webfonts. Individual optimizations can be enabled or
@@ -130,11 +130,11 @@ you might need to escape the question mark, like this: '--glyph-names\\?'.
130
130
 
131
131
  Examples::
132
132
 
133
- $ pyftsubset --glyph-names?
133
+ $ fonttools subset --glyph-names?
134
134
  Current setting for 'glyph-names' is: False
135
- $ pyftsubset --name-IDs=?
135
+ $ fonttools subset --name-IDs=?
136
136
  Current setting for 'name-IDs' is: [0, 1, 2, 3, 4, 5, 6]
137
- $ pyftsubset --hinting? --no-hinting --hinting?
137
+ $ fonttools subset --hinting? --no-hinting --hinting?
138
138
  Current setting for 'hinting' is: True
139
139
  Current setting for 'hinting' is: False
140
140
 
@@ -445,7 +445,7 @@ Example
445
445
  Produce a subset containing the characters ' !"#$%' without performing
446
446
  size-reducing optimizations::
447
447
 
448
- $ pyftsubset font.ttf --unicodes="U+0020-0025" \\
448
+ $ fonttools subset font.ttf --unicodes="U+0020-0025" \\
449
449
  --layout-features=* --glyph-names --symbol-cmap --legacy-cmap \\
450
450
  --notdef-glyph --notdef-outline --recommended-glyphs \\
451
451
  --name-IDs=* --name-legacy --name-languages=*
@@ -3768,7 +3768,7 @@ def parse_glyphs(s):
3768
3768
 
3769
3769
  def usage():
3770
3770
  print("usage:", __usage__, file=sys.stderr)
3771
- print("Try pyftsubset --help for more information.\n", file=sys.stderr)
3771
+ print("Try fonttools subset --help for more information.\n", file=sys.stderr)
3772
3772
 
3773
3773
 
3774
3774
  @timer("make one with everything (TOTAL TIME)")
fontTools/ttLib/sfnt.py CHANGED
@@ -375,10 +375,9 @@ class SFNTWriter(object):
375
375
 
376
376
  def _calcMasterChecksum(self, directory):
377
377
  # calculate checkSumAdjustment
378
- tags = list(self.tables.keys())
379
378
  checksums = []
380
- for i in range(len(tags)):
381
- checksums.append(self.tables[tags[i]].checkSum)
379
+ for tag in self.tables.keys():
380
+ checksums.append(self.tables[tag].checkSum)
382
381
 
383
382
  if self.DirectoryEntry != SFNTDirectoryEntry:
384
383
  # Create a SFNT directory for checksum calculation purposes
@@ -948,7 +948,7 @@ class Pass(object):
948
948
  writer.newline()
949
949
  writer.begintag("rules")
950
950
  writer.newline()
951
- for i in range(len(self.actions)):
951
+ for i, action in enumerate(self.actions):
952
952
  writer.begintag(
953
953
  "rule",
954
954
  index=i,
@@ -958,7 +958,7 @@ class Pass(object):
958
958
  writer.newline()
959
959
  if len(self.ruleConstraints[i]):
960
960
  writecode("constraint", writer, self.ruleConstraints[i])
961
- writecode("action", writer, self.actions[i])
961
+ writecode("action", writer, action)
962
962
  writer.endtag("rule")
963
963
  writer.newline()
964
964
  writer.endtag("rules")