fonttools 4.55.4__cp313-cp313-musllinux_1_2_aarch64.whl → 4.61.1__cp313-cp313-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.
Files changed (140) hide show
  1. fontTools/__init__.py +1 -1
  2. fontTools/annotations.py +30 -0
  3. fontTools/cffLib/CFF2ToCFF.py +65 -10
  4. fontTools/cffLib/__init__.py +61 -26
  5. fontTools/cffLib/specializer.py +4 -1
  6. fontTools/cffLib/transforms.py +11 -6
  7. fontTools/config/__init__.py +15 -0
  8. fontTools/cu2qu/cu2qu.c +6567 -5579
  9. fontTools/cu2qu/cu2qu.cpython-313-aarch64-linux-musl.so +0 -0
  10. fontTools/cu2qu/cu2qu.py +36 -4
  11. fontTools/cu2qu/ufo.py +14 -0
  12. fontTools/designspaceLib/__init__.py +8 -3
  13. fontTools/designspaceLib/statNames.py +14 -7
  14. fontTools/feaLib/ast.py +24 -15
  15. fontTools/feaLib/builder.py +139 -66
  16. fontTools/feaLib/error.py +1 -1
  17. fontTools/feaLib/lexer.c +7038 -7995
  18. fontTools/feaLib/lexer.cpython-313-aarch64-linux-musl.so +0 -0
  19. fontTools/feaLib/parser.py +75 -40
  20. fontTools/feaLib/variableScalar.py +6 -1
  21. fontTools/fontBuilder.py +50 -44
  22. fontTools/merge/__init__.py +1 -1
  23. fontTools/merge/cmap.py +33 -1
  24. fontTools/merge/tables.py +12 -1
  25. fontTools/misc/bezierTools.c +14913 -17013
  26. fontTools/misc/bezierTools.cpython-313-aarch64-linux-musl.so +0 -0
  27. fontTools/misc/bezierTools.py +4 -1
  28. fontTools/misc/configTools.py +3 -1
  29. fontTools/misc/enumTools.py +23 -0
  30. fontTools/misc/etree.py +4 -27
  31. fontTools/misc/filesystem/__init__.py +68 -0
  32. fontTools/misc/filesystem/_base.py +134 -0
  33. fontTools/misc/filesystem/_copy.py +45 -0
  34. fontTools/misc/filesystem/_errors.py +54 -0
  35. fontTools/misc/filesystem/_info.py +75 -0
  36. fontTools/misc/filesystem/_osfs.py +164 -0
  37. fontTools/misc/filesystem/_path.py +67 -0
  38. fontTools/misc/filesystem/_subfs.py +92 -0
  39. fontTools/misc/filesystem/_tempfs.py +34 -0
  40. fontTools/misc/filesystem/_tools.py +34 -0
  41. fontTools/misc/filesystem/_walk.py +55 -0
  42. fontTools/misc/filesystem/_zipfs.py +204 -0
  43. fontTools/misc/fixedTools.py +1 -1
  44. fontTools/misc/loggingTools.py +1 -1
  45. fontTools/misc/psCharStrings.py +17 -2
  46. fontTools/misc/sstruct.py +2 -6
  47. fontTools/misc/symfont.py +6 -8
  48. fontTools/misc/testTools.py +5 -1
  49. fontTools/misc/textTools.py +4 -2
  50. fontTools/misc/visitor.py +32 -16
  51. fontTools/misc/xmlWriter.py +44 -8
  52. fontTools/mtiLib/__init__.py +1 -3
  53. fontTools/otlLib/builder.py +402 -155
  54. fontTools/otlLib/optimize/gpos.py +49 -63
  55. fontTools/pens/filterPen.py +218 -26
  56. fontTools/pens/momentsPen.c +5514 -5584
  57. fontTools/pens/momentsPen.cpython-313-aarch64-linux-musl.so +0 -0
  58. fontTools/pens/pointPen.py +61 -18
  59. fontTools/pens/roundingPen.py +2 -2
  60. fontTools/pens/t2CharStringPen.py +31 -11
  61. fontTools/qu2cu/qu2cu.c +6581 -6168
  62. fontTools/qu2cu/qu2cu.cpython-313-aarch64-linux-musl.so +0 -0
  63. fontTools/subset/__init__.py +283 -25
  64. fontTools/subset/svg.py +2 -3
  65. fontTools/ttLib/__init__.py +4 -0
  66. fontTools/ttLib/__main__.py +47 -8
  67. fontTools/ttLib/removeOverlaps.py +7 -5
  68. fontTools/ttLib/reorderGlyphs.py +8 -7
  69. fontTools/ttLib/sfnt.py +11 -9
  70. fontTools/ttLib/tables/D__e_b_g.py +20 -2
  71. fontTools/ttLib/tables/G_V_A_R_.py +5 -0
  72. fontTools/ttLib/tables/S__i_l_f.py +2 -2
  73. fontTools/ttLib/tables/T_S_I__0.py +14 -3
  74. fontTools/ttLib/tables/T_S_I__1.py +2 -5
  75. fontTools/ttLib/tables/T_S_I__5.py +18 -7
  76. fontTools/ttLib/tables/__init__.py +1 -0
  77. fontTools/ttLib/tables/_a_v_a_r.py +12 -3
  78. fontTools/ttLib/tables/_c_m_a_p.py +20 -7
  79. fontTools/ttLib/tables/_c_v_t.py +3 -2
  80. fontTools/ttLib/tables/_f_p_g_m.py +3 -1
  81. fontTools/ttLib/tables/_g_l_y_f.py +45 -21
  82. fontTools/ttLib/tables/_g_v_a_r.py +67 -19
  83. fontTools/ttLib/tables/_h_d_m_x.py +4 -4
  84. fontTools/ttLib/tables/_h_m_t_x.py +7 -3
  85. fontTools/ttLib/tables/_l_o_c_a.py +2 -2
  86. fontTools/ttLib/tables/_n_a_m_e.py +11 -6
  87. fontTools/ttLib/tables/_p_o_s_t.py +9 -7
  88. fontTools/ttLib/tables/otBase.py +5 -12
  89. fontTools/ttLib/tables/otConverters.py +5 -2
  90. fontTools/ttLib/tables/otData.py +1 -1
  91. fontTools/ttLib/tables/otTables.py +33 -30
  92. fontTools/ttLib/tables/otTraverse.py +2 -1
  93. fontTools/ttLib/tables/sbixStrike.py +3 -3
  94. fontTools/ttLib/ttFont.py +666 -120
  95. fontTools/ttLib/ttGlyphSet.py +0 -10
  96. fontTools/ttLib/woff2.py +10 -13
  97. fontTools/ttx.py +13 -1
  98. fontTools/ufoLib/__init__.py +300 -202
  99. fontTools/ufoLib/converters.py +103 -30
  100. fontTools/ufoLib/errors.py +8 -0
  101. fontTools/ufoLib/etree.py +1 -1
  102. fontTools/ufoLib/filenames.py +171 -106
  103. fontTools/ufoLib/glifLib.py +303 -205
  104. fontTools/ufoLib/kerning.py +98 -48
  105. fontTools/ufoLib/utils.py +46 -15
  106. fontTools/ufoLib/validators.py +121 -99
  107. fontTools/unicodedata/Blocks.py +35 -20
  108. fontTools/unicodedata/Mirrored.py +446 -0
  109. fontTools/unicodedata/ScriptExtensions.py +63 -37
  110. fontTools/unicodedata/Scripts.py +173 -152
  111. fontTools/unicodedata/__init__.py +10 -2
  112. fontTools/varLib/__init__.py +198 -109
  113. fontTools/varLib/avar/__init__.py +0 -0
  114. fontTools/varLib/avar/__main__.py +72 -0
  115. fontTools/varLib/avar/build.py +79 -0
  116. fontTools/varLib/avar/map.py +108 -0
  117. fontTools/varLib/avar/plan.py +1004 -0
  118. fontTools/varLib/{avar.py → avar/unbuild.py} +70 -59
  119. fontTools/varLib/avarPlanner.py +3 -999
  120. fontTools/varLib/featureVars.py +21 -7
  121. fontTools/varLib/hvar.py +113 -0
  122. fontTools/varLib/instancer/__init__.py +180 -65
  123. fontTools/varLib/interpolatableHelpers.py +3 -0
  124. fontTools/varLib/iup.c +7564 -6903
  125. fontTools/varLib/iup.cpython-313-aarch64-linux-musl.so +0 -0
  126. fontTools/varLib/models.py +17 -2
  127. fontTools/varLib/mutator.py +11 -0
  128. fontTools/varLib/varStore.py +10 -38
  129. fontTools/voltLib/__main__.py +206 -0
  130. fontTools/voltLib/ast.py +4 -0
  131. fontTools/voltLib/parser.py +16 -8
  132. fontTools/voltLib/voltToFea.py +347 -166
  133. {fonttools-4.55.4.dist-info → fonttools-4.61.1.dist-info}/METADATA +269 -1410
  134. {fonttools-4.55.4.dist-info → fonttools-4.61.1.dist-info}/RECORD +318 -294
  135. {fonttools-4.55.4.dist-info → fonttools-4.61.1.dist-info}/WHEEL +1 -1
  136. fonttools-4.61.1.dist-info/licenses/LICENSE.external +388 -0
  137. {fonttools-4.55.4.data → fonttools-4.61.1.data}/data/share/man/man1/ttx.1 +0 -0
  138. {fonttools-4.55.4.dist-info → fonttools-4.61.1.dist-info}/entry_points.txt +0 -0
  139. {fonttools-4.55.4.dist-info → fonttools-4.61.1.dist-info/licenses}/LICENSE +0 -0
  140. {fonttools-4.55.4.dist-info → fonttools-4.61.1.dist-info}/top_level.txt +0 -0
fontTools/misc/visitor.py CHANGED
@@ -1,11 +1,19 @@
1
1
  """Generic visitor pattern implementation for Python objects."""
2
2
 
3
3
  import enum
4
+ import weakref
4
5
 
5
6
 
6
7
  class Visitor(object):
7
8
  defaultStop = False
8
9
 
10
+ _visitors = {
11
+ # By default we skip visiting weak references to avoid recursion
12
+ # issues. Users can override this by registering a visit
13
+ # function for weakref.ProxyType.
14
+ weakref.ProxyType: {None: lambda self, obj, *args, **kwargs: False}
15
+ }
16
+
9
17
  @classmethod
10
18
  def _register(celf, clazzes_attrs):
11
19
  assert celf != Visitor, "Subclass Visitor instead."
@@ -71,12 +79,15 @@ class Visitor(object):
71
79
  def visitObject(self, obj, *args, **kwargs):
72
80
  """Called to visit an object. This function loops over all non-private
73
81
  attributes of the objects and calls any user-registered (via
74
- @register_attr() or @register_attrs()) visit() functions.
82
+ ``@register_attr()`` or ``@register_attrs()``) ``visit()`` functions.
83
+
84
+ The visitor will proceed to call ``self.visitAttr()``, unless there is a
85
+ user-registered visit function and:
75
86
 
76
- If there is no user-registered visit function, of if there is and it
77
- returns True, or it returns None (or doesn't return anything) and
78
- visitor.defaultStop is False (default), then the visitor will proceed
79
- to call self.visitAttr()"""
87
+ * It returns ``False``; or
88
+ * It returns ``None`` (or doesn't return anything) and
89
+ ``visitor.defaultStop`` is ``True`` (non-default).
90
+ """
80
91
 
81
92
  keys = sorted(vars(obj).keys())
82
93
  _visitors = self._visitorsFor(obj)
@@ -113,19 +124,24 @@ class Visitor(object):
113
124
 
114
125
  def visit(self, obj, *args, **kwargs):
115
126
  """This is the main entry to the visitor. The visitor will visit object
116
- obj.
127
+ ``obj``.
117
128
 
118
129
  The visitor will first determine if there is a registered (via
119
- @register()) visit function for the type of object. If there is, it
120
- will be called, and (visitor, obj, *args, **kwargs) will be passed to
121
- the user visit function.
122
-
123
- If there is no user-registered visit function, of if there is and it
124
- returns True, or it returns None (or doesn't return anything) and
125
- visitor.defaultStop is False (default), then the visitor will proceed
126
- to dispatch to one of self.visitObject(), self.visitList(),
127
- self.visitDict(), or self.visitLeaf() (any of which can be overriden in
128
- 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
+ """
129
145
 
130
146
  visitorFunc = self._visitorsFor(obj).get(None, None)
131
147
  if visitorFunc is not None:
@@ -1,27 +1,49 @@
1
1
  """xmlWriter.py -- Simple XML authoring class"""
2
2
 
3
+ from __future__ import annotations
4
+
5
+ from typing import BinaryIO, Callable, TextIO
3
6
  from fontTools.misc.textTools import byteord, strjoin, tobytes, tostr
4
7
  import sys
5
8
  import os
6
9
  import string
10
+ import logging
11
+ import itertools
7
12
 
8
13
  INDENT = " "
14
+ TTX_LOG = logging.getLogger("fontTools.ttx")
15
+ REPLACEMENT = "?"
16
+ ILLEGAL_XML_CHARS = dict.fromkeys(
17
+ itertools.chain(
18
+ range(0x00, 0x09),
19
+ (0x0B, 0x0C),
20
+ range(0x0E, 0x20),
21
+ range(0xD800, 0xE000),
22
+ (0xFFFE, 0xFFFF),
23
+ ),
24
+ REPLACEMENT,
25
+ )
9
26
 
10
27
 
11
28
  class XMLWriter(object):
12
29
  def __init__(
13
30
  self,
14
- fileOrPath,
15
- indentwhite=INDENT,
16
- idlefunc=None,
17
- encoding="utf_8",
18
- newlinestr="\n",
19
- ):
31
+ fileOrPath: str | os.PathLike[str] | BinaryIO | TextIO,
32
+ indentwhite: str = INDENT,
33
+ idlefunc: Callable[[], None] | None = None,
34
+ encoding: str = "utf_8",
35
+ newlinestr: str | bytes = "\n",
36
+ ) -> None:
20
37
  if encoding.lower().replace("-", "").replace("_", "") != "utf8":
21
38
  raise Exception("Only UTF-8 encoding is supported.")
22
39
  if fileOrPath == "-":
23
40
  fileOrPath = sys.stdout
41
+ self.filename: str | os.PathLike[str] | None
24
42
  if not hasattr(fileOrPath, "write"):
43
+ if not isinstance(fileOrPath, (str, os.PathLike)):
44
+ raise TypeError(
45
+ "fileOrPath must be a file path (str or PathLike) if it isn't an object with a `write` method."
46
+ )
25
47
  self.filename = fileOrPath
26
48
  self.file = open(fileOrPath, "wb")
27
49
  self._closeStream = True
@@ -60,8 +82,9 @@ class XMLWriter(object):
60
82
  def __exit__(self, exception_type, exception_value, traceback):
61
83
  self.close()
62
84
 
63
- def close(self):
85
+ def close(self) -> None:
64
86
  if self._closeStream:
87
+ assert not isinstance(self.file, (str, os.PathLike))
65
88
  self.file.close()
66
89
 
67
90
  def write(self, string, indent=True):
@@ -168,12 +191,25 @@ class XMLWriter(object):
168
191
 
169
192
 
170
193
  def escape(data):
194
+ """Escape characters not allowed in `XML 1.0 <https://www.w3.org/TR/xml/#NT-Char>`_."""
171
195
  data = tostr(data, "utf_8")
172
196
  data = data.replace("&", "&amp;")
173
197
  data = data.replace("<", "&lt;")
174
198
  data = data.replace(">", "&gt;")
175
199
  data = data.replace("\r", "&#13;")
176
- return data
200
+
201
+ newData = data.translate(ILLEGAL_XML_CHARS)
202
+ if newData != data:
203
+ maxLen = 10
204
+ preview = repr(data)
205
+ if len(data) > maxLen:
206
+ preview = repr(data[:maxLen])[1:-1] + "..."
207
+ TTX_LOG.warning(
208
+ "Illegal XML character(s) found; replacing offending string %r with %r",
209
+ preview,
210
+ REPLACEMENT,
211
+ )
212
+ return newData
177
213
 
178
214
 
179
215
  def escapeattr(data):
@@ -1,5 +1,3 @@
1
- #!/usr/bin/python
2
-
3
1
  # FontDame-to-FontTools for OpenType Layout tables
4
2
  #
5
3
  # Source language spec is available at:
@@ -1377,7 +1375,7 @@ def main(args=None, font=None):
1377
1375
 
1378
1376
  for f in args.inputs:
1379
1377
  log.debug("Processing %s", f)
1380
- with open(f, "rt", encoding="utf-8") as f:
1378
+ with open(f, "rt", encoding="utf-8-sig") as f:
1381
1379
  table = build(f, font, tableTag=args.tableTag)
1382
1380
  blob = table.compile(font) # Make sure it compiles
1383
1381
  decompiled = table.__class__()