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