1
2
3def lookupKerningValue(pair, kerning, groups, fallback=0, glyphToFirstGroup=None, glyphToSecondGroup=None):
4	"""
5	Note: This expects kerning to be a flat dictionary
6	of kerning pairs, not the nested structure used
7	in kerning.plist.
8
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
41	"""
42	# quickly check to see if the pair is in the kerning dictionary
43	if pair in kerning:
44		return kerning[pair]
45	# 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	if glyphToFirstGroup is None:
51		glyphToFirstGroup = {}
52		glyphToSecondGroup = {}
53		for group, groupMembers in groups.items():
54			if group.startswith("public.kern1."):
55				for glyph in groupMembers:
56					glyphToFirstGroup[glyph] = group
57			elif group.startswith("public.kern2."):
58				for glyph in groupMembers:
59					glyphToSecondGroup[glyph] = group
60	# get group names and make sure first and second are glyph names
61	first, second = pair
62	firstGroup = secondGroup = None
63	if first.startswith("public.kern1."):
64		firstGroup = first
65		first = None
66	else:
67		firstGroup = glyphToFirstGroup.get(first)
68	if second.startswith("public.kern2."):
69		secondGroup = second
70		second = None
71	else:
72		secondGroup = glyphToSecondGroup.get(second)
73	# make an ordered list of pairs to look up
74	pairs = [
75		(first, second),
76		(first, secondGroup),
77		(firstGroup, second),
78		(firstGroup, secondGroup)
79	]
80	# look up the pairs and return any matches
81	for pair in pairs:
82		if pair in kerning:
83			return kerning[pair]
84	# use the fallback value
85	return fallback
86
87if __name__ == "__main__":
88	import doctest
89	doctest.testmod()
90