fonttools 4.59.2__cp311-cp311-win32.whl → 4.60.1__cp311-cp311-win32.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.
- fontTools/__init__.py +1 -1
- fontTools/annotations.py +30 -0
- fontTools/cu2qu/cu2qu.c +1067 -946
- fontTools/cu2qu/cu2qu.cp311-win32.pyd +0 -0
- fontTools/cu2qu/cu2qu.py +19 -2
- fontTools/feaLib/lexer.c +18 -12
- fontTools/feaLib/lexer.cp311-win32.pyd +0 -0
- fontTools/misc/bezierTools.c +18 -12
- fontTools/misc/bezierTools.cp311-win32.pyd +0 -0
- fontTools/misc/enumTools.py +23 -0
- fontTools/misc/visitor.py +24 -16
- fontTools/pens/filterPen.py +218 -26
- fontTools/pens/momentsPen.c +18 -12
- fontTools/pens/momentsPen.cp311-win32.pyd +0 -0
- fontTools/pens/pointPen.py +40 -6
- fontTools/qu2cu/qu2cu.c +30 -16
- fontTools/qu2cu/qu2cu.cp311-win32.pyd +0 -0
- fontTools/subset/__init__.py +178 -12
- fontTools/ttLib/tables/_p_o_s_t.py +5 -5
- fontTools/ufoLib/__init__.py +278 -175
- fontTools/ufoLib/converters.py +14 -5
- fontTools/ufoLib/filenames.py +16 -6
- fontTools/ufoLib/glifLib.py +286 -190
- fontTools/ufoLib/kerning.py +32 -12
- fontTools/ufoLib/utils.py +41 -13
- fontTools/ufoLib/validators.py +121 -97
- 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/interpolatableHelpers.py +3 -0
- fontTools/varLib/iup.c +24 -14
- fontTools/varLib/iup.cp311-win32.pyd +0 -0
- {fonttools-4.59.2.dist-info → fonttools-4.60.1.dist-info}/METADATA +41 -2
- {fonttools-4.59.2.dist-info → fonttools-4.60.1.dist-info}/RECORD +44 -37
- {fonttools-4.59.2.data → fonttools-4.60.1.data}/data/share/man/man1/ttx.1 +0 -0
- {fonttools-4.59.2.dist-info → fonttools-4.60.1.dist-info}/WHEEL +0 -0
- {fonttools-4.59.2.dist-info → fonttools-4.60.1.dist-info}/entry_points.txt +0 -0
- {fonttools-4.59.2.dist-info → fonttools-4.60.1.dist-info}/licenses/LICENSE +0 -0
- {fonttools-4.59.2.dist-info → fonttools-4.60.1.dist-info}/licenses/LICENSE.external +0 -0
- {fonttools-4.59.2.dist-info → fonttools-4.60.1.dist-info}/top_level.txt +0 -0
fontTools/ufoLib/kerning.py
CHANGED
|
@@ -1,6 +1,20 @@
|
|
|
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
|
-
|
|
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:
|
|
4
18
|
"""Retrieve the kerning value (if any) between a pair of elements.
|
|
5
19
|
|
|
6
20
|
The elments can be either individual glyphs (by name) or kerning
|
|
@@ -72,11 +86,12 @@ def lookupKerningValue(
|
|
|
72
86
|
# quickly check to see if the pair is in the kerning dictionary
|
|
73
87
|
if pair in kerning:
|
|
74
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
|
+
)
|
|
75
94
|
# create glyph to group mapping
|
|
76
|
-
if glyphToFirstGroup is not None:
|
|
77
|
-
assert glyphToSecondGroup is not None
|
|
78
|
-
if glyphToSecondGroup is not None:
|
|
79
|
-
assert glyphToFirstGroup is not None
|
|
80
95
|
if glyphToFirstGroup is None:
|
|
81
96
|
glyphToFirstGroup = {}
|
|
82
97
|
glyphToSecondGroup = {}
|
|
@@ -87,25 +102,30 @@ def lookupKerningValue(
|
|
|
87
102
|
elif group.startswith("public.kern2."):
|
|
88
103
|
for glyph in groupMembers:
|
|
89
104
|
glyphToSecondGroup[glyph] = group
|
|
105
|
+
# ensure type safety for mappings
|
|
106
|
+
assert glyphToFirstGroup is not None
|
|
107
|
+
assert glyphToSecondGroup is not None
|
|
90
108
|
# get group names and make sure first and second are glyph names
|
|
91
109
|
first, second = pair
|
|
92
110
|
firstGroup = secondGroup = None
|
|
93
111
|
if first.startswith("public.kern1."):
|
|
94
112
|
firstGroup = first
|
|
95
|
-
|
|
113
|
+
firstGlyph = None
|
|
96
114
|
else:
|
|
97
115
|
firstGroup = glyphToFirstGroup.get(first)
|
|
116
|
+
firstGlyph = first
|
|
98
117
|
if second.startswith("public.kern2."):
|
|
99
118
|
secondGroup = second
|
|
100
|
-
|
|
119
|
+
secondGlyph = None
|
|
101
120
|
else:
|
|
102
121
|
secondGroup = glyphToSecondGroup.get(second)
|
|
122
|
+
secondGlyph = second
|
|
103
123
|
# make an ordered list of pairs to look up
|
|
104
124
|
pairs = [
|
|
105
|
-
(
|
|
106
|
-
(
|
|
107
|
-
(
|
|
108
|
-
|
|
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
|
|
109
129
|
]
|
|
110
130
|
# look up the pairs and return any matches
|
|
111
131
|
for pair in pairs:
|
fontTools/ufoLib/utils.py
CHANGED
|
@@ -5,14 +5,22 @@ define the :py:obj:`.deprecated` decorator that is used elsewhere in
|
|
|
5
5
|
the module.
|
|
6
6
|
"""
|
|
7
7
|
|
|
8
|
-
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
|
|
9
13
|
import functools
|
|
14
|
+
import warnings
|
|
10
15
|
|
|
16
|
+
F = TypeVar("F", bound=Callable[..., object])
|
|
17
|
+
FormatVersion = TypeVar("FormatVersion", bound="BaseFormatVersion")
|
|
18
|
+
FormatVersionInput = Optional[Union[int, tuple[int, int], FormatVersion]]
|
|
11
19
|
|
|
12
20
|
numberTypes = (int, float)
|
|
13
21
|
|
|
14
22
|
|
|
15
|
-
def deprecated(msg=""):
|
|
23
|
+
def deprecated(msg: str = "") -> Callable[[F], F]:
|
|
16
24
|
"""Decorator factory to mark functions as deprecated with given message.
|
|
17
25
|
|
|
18
26
|
>>> @deprecated("Enough!")
|
|
@@ -25,7 +33,7 @@ def deprecated(msg=""):
|
|
|
25
33
|
True
|
|
26
34
|
"""
|
|
27
35
|
|
|
28
|
-
def deprecated_decorator(func):
|
|
36
|
+
def deprecated_decorator(func: F) -> F:
|
|
29
37
|
@functools.wraps(func)
|
|
30
38
|
def wrapper(*args, **kwargs):
|
|
31
39
|
warnings.warn(
|
|
@@ -35,41 +43,61 @@ def deprecated(msg=""):
|
|
|
35
43
|
)
|
|
36
44
|
return func(*args, **kwargs)
|
|
37
45
|
|
|
38
|
-
return wrapper
|
|
46
|
+
return cast(F, wrapper)
|
|
39
47
|
|
|
40
48
|
return deprecated_decorator
|
|
41
49
|
|
|
42
50
|
|
|
43
|
-
|
|
44
|
-
|
|
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
|
+
|
|
45
73
|
@property
|
|
46
|
-
def major(self):
|
|
74
|
+
def major(self) -> int:
|
|
47
75
|
return self.value[0]
|
|
48
76
|
|
|
49
77
|
@property
|
|
50
|
-
def minor(self):
|
|
78
|
+
def minor(self) -> int:
|
|
51
79
|
return self.value[1]
|
|
52
80
|
|
|
53
81
|
@classmethod
|
|
54
|
-
def _missing_(cls, value):
|
|
82
|
+
def _missing_(cls, value: object) -> BaseFormatVersion:
|
|
55
83
|
# allow to initialize a version enum from a single (major) integer
|
|
56
84
|
if isinstance(value, int):
|
|
57
85
|
return cls((value, 0))
|
|
58
86
|
# or from None to obtain the current default version
|
|
59
87
|
if value is None:
|
|
60
88
|
return cls.default()
|
|
61
|
-
|
|
89
|
+
raise ValueError(f"{value!r} is not a valid {cls.__name__}")
|
|
62
90
|
|
|
63
|
-
def __str__(self):
|
|
91
|
+
def __str__(self) -> str:
|
|
64
92
|
return f"{self.major}.{self.minor}"
|
|
65
93
|
|
|
66
94
|
@classmethod
|
|
67
|
-
def default(cls):
|
|
95
|
+
def default(cls: Type[FormatVersion]) -> FormatVersion:
|
|
68
96
|
# get the latest defined version (i.e. the max of all versions)
|
|
69
97
|
return max(cls.__members__.values())
|
|
70
98
|
|
|
71
99
|
@classmethod
|
|
72
|
-
def supported_versions(cls):
|
|
100
|
+
def supported_versions(cls: Type[FormatVersion]) -> frozenset[FormatVersion]:
|
|
73
101
|
return frozenset(cls.__members__.values())
|
|
74
102
|
|
|
75
103
|
|