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
@@ -12,12 +12,15 @@ This allows the caller to provide more data for each point.
12
12
  For instance, whether or not a point is smooth, and its name.
13
13
  """
14
14
 
15
+ from __future__ import annotations
16
+
15
17
  import math
16
- from typing import Any, Optional, Tuple, Dict
18
+ from typing import Any, Dict, List, Optional, Tuple
17
19
 
20
+ from fontTools.misc.enumTools import StrEnum
18
21
  from fontTools.misc.loggingTools import LogMixin
19
- from fontTools.pens.basePen import AbstractPen, MissingComponentError, PenError
20
22
  from fontTools.misc.transform import DecomposedTransform, Identity
23
+ from fontTools.pens.basePen import AbstractPen, MissingComponentError, PenError
21
24
 
22
25
  __all__ = [
23
26
  "AbstractPointPen",
@@ -26,8 +29,30 @@ __all__ = [
26
29
  "SegmentToPointPen",
27
30
  "GuessSmoothPointPen",
28
31
  "ReverseContourPointPen",
32
+ "ReverseFlipped",
29
33
  ]
30
34
 
35
+ # Some type aliases to make it easier below
36
+ Point = Tuple[float, float]
37
+ PointName = Optional[str]
38
+ # [(pt, smooth, name, kwargs)]
39
+ SegmentPointList = List[Tuple[Optional[Point], bool, PointName, Any]]
40
+ SegmentType = Optional[str]
41
+ SegmentList = List[Tuple[SegmentType, SegmentPointList]]
42
+
43
+
44
+ class ReverseFlipped(StrEnum):
45
+ """How to handle flipped components during decomposition.
46
+
47
+ NO: Don't reverse flipped components
48
+ KEEP_START: Reverse flipped components, keeping original starting point
49
+ ON_CURVE_FIRST: Reverse flipped components, ensuring first point is on-curve
50
+ """
51
+
52
+ NO = "no"
53
+ KEEP_START = "keep_start"
54
+ ON_CURVE_FIRST = "on_curve_first"
55
+
31
56
 
32
57
  class AbstractPointPen:
33
58
  """Baseclass for all PointPens."""
@@ -88,7 +113,7 @@ class BasePointToSegmentPen(AbstractPointPen):
88
113
  care of all the edge cases.
89
114
  """
90
115
 
91
- def __init__(self):
116
+ def __init__(self) -> None:
92
117
  self.currentPath = None
93
118
 
94
119
  def beginPath(self, identifier=None, **kwargs):
@@ -96,7 +121,7 @@ class BasePointToSegmentPen(AbstractPointPen):
96
121
  raise PenError("Path already begun.")
97
122
  self.currentPath = []
98
123
 
99
- def _flushContour(self, segments):
124
+ def _flushContour(self, segments: SegmentList) -> None:
100
125
  """Override this method.
101
126
 
102
127
  It will be called for each non-empty sub path with a list
@@ -124,7 +149,7 @@ class BasePointToSegmentPen(AbstractPointPen):
124
149
  """
125
150
  raise NotImplementedError
126
151
 
127
- def endPath(self):
152
+ def endPath(self) -> None:
128
153
  if self.currentPath is None:
129
154
  raise PenError("Path not begun.")
130
155
  points = self.currentPath
@@ -134,7 +159,7 @@ class BasePointToSegmentPen(AbstractPointPen):
134
159
  if len(points) == 1:
135
160
  # Not much more we can do than output a single move segment.
136
161
  pt, segmentType, smooth, name, kwargs = points[0]
137
- segments = [("move", [(pt, smooth, name, kwargs)])]
162
+ segments: SegmentList = [("move", [(pt, smooth, name, kwargs)])]
138
163
  self._flushContour(segments)
139
164
  return
140
165
  segments = []
@@ -162,7 +187,7 @@ class BasePointToSegmentPen(AbstractPointPen):
162
187
  else:
163
188
  points = points[firstOnCurve + 1 :] + points[: firstOnCurve + 1]
164
189
 
165
- currentSegment = []
190
+ currentSegment: SegmentPointList = []
166
191
  for pt, segmentType, smooth, name, kwargs in points:
167
192
  currentSegment.append((pt, smooth, name, kwargs))
168
193
  if segmentType is None:
@@ -189,7 +214,7 @@ class PointToSegmentPen(BasePointToSegmentPen):
189
214
  and kwargs.
190
215
  """
191
216
 
192
- def __init__(self, segmentPen, outputImpliedClosingLine=False):
217
+ def __init__(self, segmentPen, outputImpliedClosingLine: bool = False) -> None:
193
218
  BasePointToSegmentPen.__init__(self)
194
219
  self.pen = segmentPen
195
220
  self.outputImpliedClosingLine = outputImpliedClosingLine
@@ -271,14 +296,14 @@ class SegmentToPointPen(AbstractPen):
271
296
  PointPen protocol.
272
297
  """
273
298
 
274
- def __init__(self, pointPen, guessSmooth=True):
299
+ def __init__(self, pointPen, guessSmooth=True) -> None:
275
300
  if guessSmooth:
276
301
  self.pen = GuessSmoothPointPen(pointPen)
277
302
  else:
278
303
  self.pen = pointPen
279
- self.contour = None
304
+ self.contour: Optional[List[Tuple[Point, SegmentType]]] = None
280
305
 
281
- def _flushContour(self):
306
+ def _flushContour(self) -> None:
282
307
  pen = self.pen
283
308
  pen.beginPath()
284
309
  for pt, segmentType in self.contour:
@@ -549,15 +574,20 @@ class DecomposingPointPen(LogMixin, AbstractPointPen):
549
574
  glyphSet,
550
575
  *args,
551
576
  skipMissingComponents=None,
552
- reverseFlipped=False,
577
+ reverseFlipped: bool | ReverseFlipped = False,
553
578
  **kwargs,
554
579
  ):
555
580
  """Takes a 'glyphSet' argument (dict), in which the glyphs that are referenced
556
581
  as components are looked up by their name.
557
582
 
558
- If the optional 'reverseFlipped' argument is True, components whose transformation
559
- matrix has a negative determinant will be decomposed with a reversed path direction
560
- to compensate for the flip.
583
+ If the optional 'reverseFlipped' argument is True or a ReverseFlipped enum value,
584
+ components whose transformation matrix has a negative determinant will be decomposed
585
+ with a reversed path direction to compensate for the flip.
586
+
587
+ The reverseFlipped parameter can be:
588
+ - False or ReverseFlipped.NO: Don't reverse flipped components
589
+ - True or ReverseFlipped.KEEP_START: Reverse, keeping original starting point
590
+ - ReverseFlipped.ON_CURVE_FIRST: Reverse, ensuring first point is on-curve
561
591
 
562
592
  The optional 'skipMissingComponents' argument can be set to True/False to
563
593
  override the homonymous class attribute for a given pen instance.
@@ -569,7 +599,13 @@ class DecomposingPointPen(LogMixin, AbstractPointPen):
569
599
  if skipMissingComponents is None
570
600
  else skipMissingComponents
571
601
  )
572
- self.reverseFlipped = reverseFlipped
602
+ # Handle backward compatibility and validate string inputs
603
+ if reverseFlipped is False:
604
+ self.reverseFlipped = ReverseFlipped.NO
605
+ elif reverseFlipped is True:
606
+ self.reverseFlipped = ReverseFlipped.KEEP_START
607
+ else:
608
+ self.reverseFlipped = ReverseFlipped(reverseFlipped)
573
609
 
574
610
  def addComponent(self, baseGlyphName, transformation, identifier=None, **kwargs):
575
611
  """Transform the points of the base glyph and draw it onto self.
@@ -590,11 +626,18 @@ class DecomposingPointPen(LogMixin, AbstractPointPen):
590
626
  pen = self
591
627
  if transformation != Identity:
592
628
  pen = TransformPointPen(pen, transformation)
593
- if self.reverseFlipped:
629
+ if self.reverseFlipped != ReverseFlipped.NO:
594
630
  # if the transformation has a negative determinant, it will
595
631
  # reverse the contour direction of the component
596
632
  a, b, c, d = transformation[:4]
597
- det = a * d - b * c
598
633
  if a * d - b * c < 0:
599
634
  pen = ReverseContourPointPen(pen)
635
+
636
+ if self.reverseFlipped == ReverseFlipped.ON_CURVE_FIRST:
637
+ from fontTools.pens.filterPen import OnCurveFirstPointPen
638
+
639
+ # Ensure the starting point is an on-curve.
640
+ # Wrap last so this filter runs first during drawPoints
641
+ pen = OnCurveFirstPointPen(pen)
642
+
600
643
  glyph.drawPoints(pen)
@@ -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),
@@ -1,10 +1,14 @@
1
1
  # Copyright (c) 2009 Type Supply LLC
2
2
  # Author: Tal Leming
3
3
 
4
- from fontTools.misc.roundTools import otRound, roundFunc
4
+ from __future__ import annotations
5
+
6
+ from typing import Any, Dict, List, Tuple
7
+
8
+ from fontTools.cffLib.specializer import commandsToProgram, specializeCommands
5
9
  from fontTools.misc.psCharStrings import T2CharString
10
+ from fontTools.misc.roundTools import otRound, roundFunc
6
11
  from fontTools.pens.basePen import BasePen
7
- from fontTools.cffLib.specializer import specializeCommands, commandsToProgram
8
12
 
9
13
 
10
14
  class T2CharStringPen(BasePen):
@@ -18,36 +22,52 @@ class T2CharStringPen(BasePen):
18
22
  which are close to their integral part within the tolerated range.
19
23
  """
20
24
 
21
- def __init__(self, width, glyphSet, roundTolerance=0.5, CFF2=False):
25
+ def __init__(
26
+ self,
27
+ width: float | None,
28
+ glyphSet: Dict[str, Any] | None,
29
+ roundTolerance: float = 0.5,
30
+ CFF2: bool = False,
31
+ ) -> None:
22
32
  super(T2CharStringPen, self).__init__(glyphSet)
23
33
  self.round = roundFunc(roundTolerance)
24
34
  self._CFF2 = CFF2
25
35
  self._width = width
26
- self._commands = []
36
+ self._commands: List[Tuple[str | bytes, List[float]]] = []
27
37
  self._p0 = (0, 0)
28
38
 
29
- def _p(self, pt):
39
+ def _p(self, pt: Tuple[float, float]) -> List[float]:
30
40
  p0 = self._p0
31
41
  pt = self._p0 = (self.round(pt[0]), self.round(pt[1]))
32
42
  return [pt[0] - p0[0], pt[1] - p0[1]]
33
43
 
34
- def _moveTo(self, pt):
44
+ def _moveTo(self, pt: Tuple[float, float]) -> None:
35
45
  self._commands.append(("rmoveto", self._p(pt)))
36
46
 
37
- def _lineTo(self, pt):
47
+ def _lineTo(self, pt: Tuple[float, float]) -> None:
38
48
  self._commands.append(("rlineto", self._p(pt)))
39
49
 
40
- def _curveToOne(self, pt1, pt2, pt3):
50
+ def _curveToOne(
51
+ self,
52
+ pt1: Tuple[float, float],
53
+ pt2: Tuple[float, float],
54
+ pt3: Tuple[float, float],
55
+ ) -> None:
41
56
  _p = self._p
42
57
  self._commands.append(("rrcurveto", _p(pt1) + _p(pt2) + _p(pt3)))
43
58
 
44
- def _closePath(self):
59
+ def _closePath(self) -> None:
45
60
  pass
46
61
 
47
- def _endPath(self):
62
+ def _endPath(self) -> None:
48
63
  pass
49
64
 
50
- def getCharString(self, private=None, globalSubrs=None, optimize=True):
65
+ def getCharString(
66
+ self,
67
+ private: Dict | None = None,
68
+ globalSubrs: List | None = None,
69
+ optimize: bool = True,
70
+ ) -> T2CharString:
51
71
  commands = self._commands
52
72
  if optimize:
53
73
  maxstack = 48 if not self._CFF2 else 513