kerning.py 2.9 KB

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