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.
- fontTools/__init__.py +1 -1
- fontTools/annotations.py +30 -0
- fontTools/cffLib/CFF2ToCFF.py +65 -10
- fontTools/cffLib/__init__.py +61 -26
- fontTools/cffLib/specializer.py +4 -1
- fontTools/cffLib/transforms.py +11 -6
- fontTools/config/__init__.py +15 -0
- fontTools/cu2qu/cu2qu.c +6567 -5579
- fontTools/cu2qu/cu2qu.cpython-313-aarch64-linux-musl.so +0 -0
- fontTools/cu2qu/cu2qu.py +36 -4
- fontTools/cu2qu/ufo.py +14 -0
- fontTools/designspaceLib/__init__.py +8 -3
- fontTools/designspaceLib/statNames.py +14 -7
- fontTools/feaLib/ast.py +24 -15
- fontTools/feaLib/builder.py +139 -66
- fontTools/feaLib/error.py +1 -1
- fontTools/feaLib/lexer.c +7038 -7995
- fontTools/feaLib/lexer.cpython-313-aarch64-linux-musl.so +0 -0
- fontTools/feaLib/parser.py +75 -40
- fontTools/feaLib/variableScalar.py +6 -1
- fontTools/fontBuilder.py +50 -44
- fontTools/merge/__init__.py +1 -1
- fontTools/merge/cmap.py +33 -1
- fontTools/merge/tables.py +12 -1
- fontTools/misc/bezierTools.c +14913 -17013
- fontTools/misc/bezierTools.cpython-313-aarch64-linux-musl.so +0 -0
- fontTools/misc/bezierTools.py +4 -1
- fontTools/misc/configTools.py +3 -1
- fontTools/misc/enumTools.py +23 -0
- fontTools/misc/etree.py +4 -27
- fontTools/misc/filesystem/__init__.py +68 -0
- fontTools/misc/filesystem/_base.py +134 -0
- fontTools/misc/filesystem/_copy.py +45 -0
- fontTools/misc/filesystem/_errors.py +54 -0
- fontTools/misc/filesystem/_info.py +75 -0
- fontTools/misc/filesystem/_osfs.py +164 -0
- fontTools/misc/filesystem/_path.py +67 -0
- fontTools/misc/filesystem/_subfs.py +92 -0
- fontTools/misc/filesystem/_tempfs.py +34 -0
- fontTools/misc/filesystem/_tools.py +34 -0
- fontTools/misc/filesystem/_walk.py +55 -0
- fontTools/misc/filesystem/_zipfs.py +204 -0
- fontTools/misc/fixedTools.py +1 -1
- fontTools/misc/loggingTools.py +1 -1
- fontTools/misc/psCharStrings.py +17 -2
- fontTools/misc/sstruct.py +2 -6
- fontTools/misc/symfont.py +6 -8
- fontTools/misc/testTools.py +5 -1
- fontTools/misc/textTools.py +4 -2
- fontTools/misc/visitor.py +32 -16
- fontTools/misc/xmlWriter.py +44 -8
- fontTools/mtiLib/__init__.py +1 -3
- fontTools/otlLib/builder.py +402 -155
- fontTools/otlLib/optimize/gpos.py +49 -63
- fontTools/pens/filterPen.py +218 -26
- fontTools/pens/momentsPen.c +5514 -5584
- fontTools/pens/momentsPen.cpython-313-aarch64-linux-musl.so +0 -0
- fontTools/pens/pointPen.py +61 -18
- fontTools/pens/roundingPen.py +2 -2
- fontTools/pens/t2CharStringPen.py +31 -11
- fontTools/qu2cu/qu2cu.c +6581 -6168
- fontTools/qu2cu/qu2cu.cpython-313-aarch64-linux-musl.so +0 -0
- fontTools/subset/__init__.py +283 -25
- fontTools/subset/svg.py +2 -3
- fontTools/ttLib/__init__.py +4 -0
- fontTools/ttLib/__main__.py +47 -8
- fontTools/ttLib/removeOverlaps.py +7 -5
- fontTools/ttLib/reorderGlyphs.py +8 -7
- fontTools/ttLib/sfnt.py +11 -9
- fontTools/ttLib/tables/D__e_b_g.py +20 -2
- fontTools/ttLib/tables/G_V_A_R_.py +5 -0
- fontTools/ttLib/tables/S__i_l_f.py +2 -2
- fontTools/ttLib/tables/T_S_I__0.py +14 -3
- fontTools/ttLib/tables/T_S_I__1.py +2 -5
- fontTools/ttLib/tables/T_S_I__5.py +18 -7
- fontTools/ttLib/tables/__init__.py +1 -0
- fontTools/ttLib/tables/_a_v_a_r.py +12 -3
- fontTools/ttLib/tables/_c_m_a_p.py +20 -7
- fontTools/ttLib/tables/_c_v_t.py +3 -2
- fontTools/ttLib/tables/_f_p_g_m.py +3 -1
- fontTools/ttLib/tables/_g_l_y_f.py +45 -21
- fontTools/ttLib/tables/_g_v_a_r.py +67 -19
- fontTools/ttLib/tables/_h_d_m_x.py +4 -4
- fontTools/ttLib/tables/_h_m_t_x.py +7 -3
- fontTools/ttLib/tables/_l_o_c_a.py +2 -2
- fontTools/ttLib/tables/_n_a_m_e.py +11 -6
- fontTools/ttLib/tables/_p_o_s_t.py +9 -7
- fontTools/ttLib/tables/otBase.py +5 -12
- fontTools/ttLib/tables/otConverters.py +5 -2
- fontTools/ttLib/tables/otData.py +1 -1
- fontTools/ttLib/tables/otTables.py +33 -30
- fontTools/ttLib/tables/otTraverse.py +2 -1
- fontTools/ttLib/tables/sbixStrike.py +3 -3
- fontTools/ttLib/ttFont.py +666 -120
- fontTools/ttLib/ttGlyphSet.py +0 -10
- fontTools/ttLib/woff2.py +10 -13
- fontTools/ttx.py +13 -1
- fontTools/ufoLib/__init__.py +300 -202
- fontTools/ufoLib/converters.py +103 -30
- fontTools/ufoLib/errors.py +8 -0
- fontTools/ufoLib/etree.py +1 -1
- fontTools/ufoLib/filenames.py +171 -106
- fontTools/ufoLib/glifLib.py +303 -205
- fontTools/ufoLib/kerning.py +98 -48
- fontTools/ufoLib/utils.py +46 -15
- fontTools/ufoLib/validators.py +121 -99
- fontTools/unicodedata/Blocks.py +35 -20
- fontTools/unicodedata/Mirrored.py +446 -0
- fontTools/unicodedata/ScriptExtensions.py +63 -37
- fontTools/unicodedata/Scripts.py +173 -152
- fontTools/unicodedata/__init__.py +10 -2
- fontTools/varLib/__init__.py +198 -109
- fontTools/varLib/avar/__init__.py +0 -0
- fontTools/varLib/avar/__main__.py +72 -0
- fontTools/varLib/avar/build.py +79 -0
- fontTools/varLib/avar/map.py +108 -0
- fontTools/varLib/avar/plan.py +1004 -0
- fontTools/varLib/{avar.py → avar/unbuild.py} +70 -59
- fontTools/varLib/avarPlanner.py +3 -999
- fontTools/varLib/featureVars.py +21 -7
- fontTools/varLib/hvar.py +113 -0
- fontTools/varLib/instancer/__init__.py +180 -65
- fontTools/varLib/interpolatableHelpers.py +3 -0
- fontTools/varLib/iup.c +7564 -6903
- fontTools/varLib/iup.cpython-313-aarch64-linux-musl.so +0 -0
- fontTools/varLib/models.py +17 -2
- fontTools/varLib/mutator.py +11 -0
- fontTools/varLib/varStore.py +10 -38
- fontTools/voltLib/__main__.py +206 -0
- fontTools/voltLib/ast.py +4 -0
- fontTools/voltLib/parser.py +16 -8
- fontTools/voltLib/voltToFea.py +347 -166
- {fonttools-4.55.4.dist-info → fonttools-4.61.1.dist-info}/METADATA +269 -1410
- {fonttools-4.55.4.dist-info → fonttools-4.61.1.dist-info}/RECORD +318 -294
- {fonttools-4.55.4.dist-info → fonttools-4.61.1.dist-info}/WHEEL +1 -1
- fonttools-4.61.1.dist-info/licenses/LICENSE.external +388 -0
- {fonttools-4.55.4.data → fonttools-4.61.1.data}/data/share/man/man1/ttx.1 +0 -0
- {fonttools-4.55.4.dist-info → fonttools-4.61.1.dist-info}/entry_points.txt +0 -0
- {fonttools-4.55.4.dist-info → fonttools-4.61.1.dist-info/licenses}/LICENSE +0 -0
- {fonttools-4.55.4.dist-info → fonttools-4.61.1.dist-info}/top_level.txt +0 -0
fontTools/ufoLib/kerning.py
CHANGED
|
@@ -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
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
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
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
(
|
|
76
|
-
(
|
|
77
|
-
(
|
|
78
|
-
|
|
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
|
-
"""
|
|
2
|
-
|
|
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
|
|
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
|
-
|
|
41
|
-
|
|
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
|
-
|
|
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
|
|