1from __future__ import absolute_import, unicode_literals
2
3
4def lookupKerningValue(pair, kerning, groups, fallback=0, glyphToFirstGroup=None, glyphToSecondGroup=None):
5	"""
6	Note: This expects kerning to be a flat dictionary
7	of kerning pairs, not the nested structure used
8	in kerning.plist.
9
10	>>> groups = {
11	...     "public.kern1.O" : ["O", "D", "Q"],
12	...     "public.kern2.E" : ["E", "F"]
13	... }
14	>>> kerning = {
15	...     ("public.kern1.O", "public.kern2.E") : -100,
16	...     ("public.kern1.O", "F") : -200,
17	...     ("D", "F") : -300
18	... }
19	>>> lookupKerningValue(("D", "F"), kerning, groups)
20	-300
21	>>> lookupKerningValue(("O", "F"), kerning, groups)
22	-200
23	>>> lookupKerningValue(("O", "E"), kerning, groups)
24	-100
25	>>> lookupKerningValue(("O", "O"), kerning, groups)
26	0
27	>>> lookupKerningValue(("E", "E"), kerning, groups)
28	0
29	>>> lookupKerningValue(("E", "O"), kerning, groups)
30	0
31	>>> lookupKerningValue(("X", "X"), kerning, groups)
32	0
33	>>> lookupKerningValue(("public.kern1.O", "public.kern2.E"),
34	...     kerning, groups)
35	-100
36	>>> lookupKerningValue(("public.kern1.O", "F"), kerning, groups)
37	-200
38	>>> lookupKerningValue(("O", "public.kern2.E"), kerning, groups)
39	-100
40	>>> lookupKerningValue(("public.kern1.X", "public.kern2.X"), kerning, groups)
41	0
42	"""
43	# quickly check to see if the pair is in the kerning dictionary
44	if pair in kerning:
45		return kerning[pair]
46	# create glyph to group mapping
47	if glyphToFirstGroup is not None:
48		assert glyphToSecondGroup is not None
49	if glyphToSecondGroup is not None:
50		assert glyphToFirstGroup is not None
51	if glyphToFirstGroup is None:
52		glyphToFirstGroup = {}
53		glyphToSecondGroup = {}
54		for group, groupMembers in groups.items():
55			if group.startswith("public.kern1."):
56				for glyph in groupMembers:
57					glyphToFirstGroup[glyph] = group
58			elif group.startswith("public.kern2."):
59				for glyph in groupMembers:
60					glyphToSecondGroup[glyph] = group
61	# get group names and make sure first and second are glyph names
62	first, second = pair
63	firstGroup = secondGroup = None
64	if first.startswith("public.kern1."):
65		firstGroup = first
66		first = None
67	else:
68		firstGroup = glyphToFirstGroup.get(first)
69	if second.startswith("public.kern2."):
70		secondGroup = second
71		second = None
72	else:
73		secondGroup = glyphToSecondGroup.get(second)
74	# make an ordered list of pairs to look up
75	pairs = [
76		(first, second),
77		(first, secondGroup),
78		(firstGroup, second),
79		(firstGroup, secondGroup)
80	]
81	# look up the pairs and return any matches
82	for pair in pairs:
83		if pair in kerning:
84			return kerning[pair]
85	# use the fallback value
86	return fallback
87
88if __name__ == "__main__":
89	import doctest
90	doctest.testmod()
91