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
@@ -1,52 +1,97 @@
1
+ from __future__ import annotations
2
+
3
+ from typing import Optional
4
+
5
+ from fontTools.annotations import KerningPair, KerningDict, KerningGroups, IntFloat
6
+
7
+ StrDict = dict[str, str]
8
+
9
+
1
10
  def lookupKerningValue(
2
- pair, kerning, groups, fallback=0, glyphToFirstGroup=None, glyphToSecondGroup=None
3
- ):
4
- """
5
- Note: This expects kerning to be a flat dictionary
6
- of kerning pairs, not the nested structure used
7
- in kerning.plist.
11
+ pair: KerningPair,
12
+ kerning: KerningDict,
13
+ groups: KerningGroups,
14
+ fallback: IntFloat = 0,
15
+ glyphToFirstGroup: Optional[StrDict] = None,
16
+ glyphToSecondGroup: Optional[StrDict] = None,
17
+ ) -> IntFloat:
18
+ """Retrieve the kerning value (if any) between a pair of elements.
19
+
20
+ The elments can be either individual glyphs (by name) or kerning
21
+ groups (by name), or any combination of the two.
22
+
23
+ Args:
24
+ pair:
25
+ A tuple, in logical order (first, second) with respect
26
+ to the reading direction, to query the font for kerning
27
+ information on. Each element in the tuple can be either
28
+ a glyph name or a kerning group name.
29
+ kerning:
30
+ A dictionary of kerning pairs.
31
+ groups:
32
+ A set of kerning groups.
33
+ fallback:
34
+ The fallback value to return if no kern is found between
35
+ the elements in ``pair``. Defaults to 0.
36
+ glyphToFirstGroup:
37
+ A dictionary mapping glyph names to the first-glyph kerning
38
+ groups to which they belong. Defaults to ``None``.
39
+ glyphToSecondGroup:
40
+ A dictionary mapping glyph names to the second-glyph kerning
41
+ groups to which they belong. Defaults to ``None``.
42
+
43
+ Returns:
44
+ The kerning value between the element pair. If no kerning for
45
+ the pair is found, the fallback value is returned.
46
+
47
+ Note: This function expects the ``kerning`` argument to be a flat
48
+ dictionary of kerning pairs, not the nested structure used in a
49
+ kerning.plist file.
50
+
51
+ Examples::
8
52
 
9
- >>> groups = {
10
- ... "public.kern1.O" : ["O", "D", "Q"],
11
- ... "public.kern2.E" : ["E", "F"]
12
- ... }
13
- >>> kerning = {
14
- ... ("public.kern1.O", "public.kern2.E") : -100,
15
- ... ("public.kern1.O", "F") : -200,
16
- ... ("D", "F") : -300
17
- ... }
18
- >>> lookupKerningValue(("D", "F"), kerning, groups)
19
- -300
20
- >>> lookupKerningValue(("O", "F"), kerning, groups)
21
- -200
22
- >>> lookupKerningValue(("O", "E"), kerning, groups)
23
- -100
24
- >>> lookupKerningValue(("O", "O"), kerning, groups)
25
- 0
26
- >>> lookupKerningValue(("E", "E"), kerning, groups)
27
- 0
28
- >>> lookupKerningValue(("E", "O"), kerning, groups)
29
- 0
30
- >>> lookupKerningValue(("X", "X"), kerning, groups)
31
- 0
32
- >>> lookupKerningValue(("public.kern1.O", "public.kern2.E"),
33
- ... kerning, groups)
34
- -100
35
- >>> lookupKerningValue(("public.kern1.O", "F"), kerning, groups)
36
- -200
37
- >>> lookupKerningValue(("O", "public.kern2.E"), kerning, groups)
38
- -100
39
- >>> lookupKerningValue(("public.kern1.X", "public.kern2.X"), kerning, groups)
40
- 0
53
+ >>> groups = {
54
+ ... "public.kern1.O" : ["O", "D", "Q"],
55
+ ... "public.kern2.E" : ["E", "F"]
56
+ ... }
57
+ >>> kerning = {
58
+ ... ("public.kern1.O", "public.kern2.E") : -100,
59
+ ... ("public.kern1.O", "F") : -200,
60
+ ... ("D", "F") : -300
61
+ ... }
62
+ >>> lookupKerningValue(("D", "F"), kerning, groups)
63
+ -300
64
+ >>> lookupKerningValue(("O", "F"), kerning, groups)
65
+ -200
66
+ >>> lookupKerningValue(("O", "E"), kerning, groups)
67
+ -100
68
+ >>> lookupKerningValue(("O", "O"), kerning, groups)
69
+ 0
70
+ >>> lookupKerningValue(("E", "E"), kerning, groups)
71
+ 0
72
+ >>> lookupKerningValue(("E", "O"), kerning, groups)
73
+ 0
74
+ >>> lookupKerningValue(("X", "X"), kerning, groups)
75
+ 0
76
+ >>> lookupKerningValue(("public.kern1.O", "public.kern2.E"),
77
+ ... kerning, groups)
78
+ -100
79
+ >>> lookupKerningValue(("public.kern1.O", "F"), kerning, groups)
80
+ -200
81
+ >>> lookupKerningValue(("O", "public.kern2.E"), kerning, groups)
82
+ -100
83
+ >>> lookupKerningValue(("public.kern1.X", "public.kern2.X"), kerning, groups)
84
+ 0
41
85
  """
42
86
  # quickly check to see if the pair is in the kerning dictionary
43
87
  if pair in kerning:
44
88
  return kerning[pair]
89
+ # ensure both or no glyph-to-group mappings are provided
90
+ if (glyphToFirstGroup is None) != (glyphToSecondGroup is None):
91
+ raise ValueError(
92
+ "Must provide both 'glyphToFirstGroup' and 'glyphToSecondGroup', or neither."
93
+ )
45
94
  # create glyph to group mapping
46
- if glyphToFirstGroup is not None:
47
- assert glyphToSecondGroup is not None
48
- if glyphToSecondGroup is not None:
49
- assert glyphToFirstGroup is not None
50
95
  if glyphToFirstGroup is None:
51
96
  glyphToFirstGroup = {}
52
97
  glyphToSecondGroup = {}
@@ -57,25 +102,30 @@ def lookupKerningValue(
57
102
  elif group.startswith("public.kern2."):
58
103
  for glyph in groupMembers:
59
104
  glyphToSecondGroup[glyph] = group
105
+ # ensure type safety for mappings
106
+ assert glyphToFirstGroup is not None
107
+ assert glyphToSecondGroup is not None
60
108
  # get group names and make sure first and second are glyph names
61
109
  first, second = pair
62
110
  firstGroup = secondGroup = None
63
111
  if first.startswith("public.kern1."):
64
112
  firstGroup = first
65
- first = None
113
+ firstGlyph = None
66
114
  else:
67
115
  firstGroup = glyphToFirstGroup.get(first)
116
+ firstGlyph = first
68
117
  if second.startswith("public.kern2."):
69
118
  secondGroup = second
70
- second = None
119
+ secondGlyph = None
71
120
  else:
72
121
  secondGroup = glyphToSecondGroup.get(second)
122
+ secondGlyph = second
73
123
  # make an ordered list of pairs to look up
74
124
  pairs = [
75
- (first, second),
76
- (first, secondGroup),
77
- (firstGroup, second),
78
- (firstGroup, secondGroup),
125
+ (a, b)
126
+ for a in (firstGlyph, firstGroup)
127
+ for b in (secondGlyph, secondGroup)
128
+ if a is not None and b is not None
79
129
  ]
80
130
  # look up the pairs and return any matches
81
131
  for pair in pairs:
fontTools/ufoLib/utils.py CHANGED
@@ -1,15 +1,26 @@
1
- """The module contains miscellaneous helpers.
2
- It's not considered part of the public ufoLib API.
1
+ """This module contains miscellaneous helpers.
2
+
3
+ It is not considered part of the public ufoLib API. It does, however,
4
+ define the :py:obj:`.deprecated` decorator that is used elsewhere in
5
+ the module.
3
6
  """
4
7
 
5
- import warnings
8
+ from __future__ import annotations
9
+
10
+ from typing import Optional, Type, TypeVar, Union, cast
11
+ from collections.abc import Callable
12
+ import enum
6
13
  import functools
14
+ import warnings
7
15
 
16
+ F = TypeVar("F", bound=Callable[..., object])
17
+ FormatVersion = TypeVar("FormatVersion", bound="BaseFormatVersion")
18
+ FormatVersionInput = Optional[Union[int, tuple[int, int], FormatVersion]]
8
19
 
9
20
  numberTypes = (int, float)
10
21
 
11
22
 
12
- def deprecated(msg=""):
23
+ def deprecated(msg: str = "") -> Callable[[F], F]:
13
24
  """Decorator factory to mark functions as deprecated with given message.
14
25
 
15
26
  >>> @deprecated("Enough!")
@@ -22,7 +33,7 @@ def deprecated(msg=""):
22
33
  True
23
34
  """
24
35
 
25
- def deprecated_decorator(func):
36
+ def deprecated_decorator(func: F) -> F:
26
37
  @functools.wraps(func)
27
38
  def wrapper(*args, **kwargs):
28
39
  warnings.warn(
@@ -32,41 +43,61 @@ def deprecated(msg=""):
32
43
  )
33
44
  return func(*args, **kwargs)
34
45
 
35
- return wrapper
46
+ return cast(F, wrapper)
36
47
 
37
48
  return deprecated_decorator
38
49
 
39
50
 
40
- # To be mixed with enum.Enum in UFOFormatVersion and GLIFFormatVersion
41
- class _VersionTupleEnumMixin:
51
+ def normalizeFormatVersion(
52
+ value: FormatVersionInput, cls: Type[FormatVersion]
53
+ ) -> FormatVersion:
54
+ # Needed for type safety of UFOFormatVersion and GLIFFormatVersion input
55
+ if value is None:
56
+ return cls.default()
57
+ if isinstance(value, cls):
58
+ return value
59
+ if isinstance(value, int):
60
+ return cls((value, 0))
61
+ if isinstance(value, tuple) and len(value) == 2:
62
+ return cls(value)
63
+ raise ValueError(f"Unsupported format version: {value!r}")
64
+
65
+
66
+ # Base class for UFOFormatVersion and GLIFFormatVersion
67
+ class BaseFormatVersion(tuple[int, int], enum.Enum):
68
+ value: tuple[int, int]
69
+
70
+ def __new__(cls: Type[FormatVersion], value: tuple[int, int]) -> BaseFormatVersion:
71
+ return super().__new__(cls, value)
72
+
42
73
  @property
43
- def major(self):
74
+ def major(self) -> int:
44
75
  return self.value[0]
45
76
 
46
77
  @property
47
- def minor(self):
78
+ def minor(self) -> int:
48
79
  return self.value[1]
49
80
 
50
81
  @classmethod
51
- def _missing_(cls, value):
82
+ def _missing_(cls, value: object) -> BaseFormatVersion:
52
83
  # allow to initialize a version enum from a single (major) integer
53
84
  if isinstance(value, int):
54
85
  return cls((value, 0))
55
86
  # or from None to obtain the current default version
56
87
  if value is None:
57
88
  return cls.default()
58
- return super()._missing_(value)
89
+ raise ValueError(f"{value!r} is not a valid {cls.__name__}")
59
90
 
60
- def __str__(self):
91
+ def __str__(self) -> str:
61
92
  return f"{self.major}.{self.minor}"
62
93
 
63
94
  @classmethod
64
- def default(cls):
95
+ def default(cls: Type[FormatVersion]) -> FormatVersion:
65
96
  # get the latest defined version (i.e. the max of all versions)
66
97
  return max(cls.__members__.values())
67
98
 
68
99
  @classmethod
69
- def supported_versions(cls):
100
+ def supported_versions(cls: Type[FormatVersion]) -> frozenset[FormatVersion]:
70
101
  return frozenset(cls.__members__.values())
71
102
 
72
103