1
2
3
4
5
6
7
8
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
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
|
def lookupKerningValue(
pair, kerning, groups, fallback=0, glyphToFirstGroup=None, glyphToSecondGroup=None
):
"""Retrieve the kerning value (if any) between a pair of elements.
The elments can be either individual glyphs (by name) or kerning
groups (by name), or any combination of the two.
Args:
pair:
A tuple, in logical order (first, second) with respect
to the reading direction, to query the font for kerning
information on. Each element in the tuple can be either
a glyph name or a kerning group name.
kerning:
A dictionary of kerning pairs.
groups:
A set of kerning groups.
fallback:
The fallback value to return if no kern is found between
the elements in ``pair``. Defaults to 0.
glyphToFirstGroup:
A dictionary mapping glyph names to the first-glyph kerning
groups to which they belong. Defaults to ``None``.
glyphToSecondGroup:
A dictionary mapping glyph names to the second-glyph kerning
groups to which they belong. Defaults to ``None``.
Returns:
The kerning value between the element pair. If no kerning for
the pair is found, the fallback value is returned.
Note: This function expects the ``kerning`` argument to be a flat
dictionary of kerning pairs, not the nested structure used in a
kerning.plist file.
Examples::
>>> groups = {
... "public.kern1.O" : ["O", "D", "Q"],
... "public.kern2.E" : ["E", "F"]
... }
>>> kerning = {
... ("public.kern1.O", "public.kern2.E") : -100,
... ("public.kern1.O", "F") : -200,
... ("D", "F") : -300
... }
>>> lookupKerningValue(("D", "F"), kerning, groups)
-300
>>> lookupKerningValue(("O", "F"), kerning, groups)
-200
>>> lookupKerningValue(("O", "E"), kerning, groups)
-100
>>> lookupKerningValue(("O", "O"), kerning, groups)
0
>>> lookupKerningValue(("E", "E"), kerning, groups)
0
>>> lookupKerningValue(("E", "O"), kerning, groups)
0
>>> lookupKerningValue(("X", "X"), kerning, groups)
0
>>> lookupKerningValue(("public.kern1.O", "public.kern2.E"),
... kerning, groups)
-100
>>> lookupKerningValue(("public.kern1.O", "F"), kerning, groups)
-200
>>> lookupKerningValue(("O", "public.kern2.E"), kerning, groups)
-100
>>> lookupKerningValue(("public.kern1.X", "public.kern2.X"), kerning, groups)
0
"""
# quickly check to see if the pair is in the kerning dictionary
if pair in kerning:
return kerning[pair]
# create glyph to group mapping
if glyphToFirstGroup is not None:
assert glyphToSecondGroup is not None
if glyphToSecondGroup is not None:
assert glyphToFirstGroup is not None
if glyphToFirstGroup is None:
glyphToFirstGroup = {}
glyphToSecondGroup = {}
for group, groupMembers in groups.items():
if group.startswith("public.kern1."):
for glyph in groupMembers:
glyphToFirstGroup[glyph] = group
elif group.startswith("public.kern2."):
for glyph in groupMembers:
glyphToSecondGroup[glyph] = group
# get group names and make sure first and second are glyph names
first, second = pair
firstGroup = secondGroup = None
if first.startswith("public.kern1."):
firstGroup = first
first = None
else:
firstGroup = glyphToFirstGroup.get(first)
if second.startswith("public.kern2."):
secondGroup = second
second = None
else:
secondGroup = glyphToSecondGroup.get(second)
# make an ordered list of pairs to look up
pairs = [
(first, second),
(first, secondGroup),
(firstGroup, second),
(firstGroup, secondGroup),
]
# look up the pairs and return any matches
for pair in pairs:
if pair in kerning:
return kerning[pair]
# use the fallback value
return fallback
if __name__ == "__main__":
import doctest
doctest.testmod()
|