Added a kerning validator. This must be run by the caller since groups are required. This should resolve ticket #8.
git-svn-id: http://svn.robofab.com/branches/ufo3k@507 b5fa9d6c-a76f-4ffd-b3cb-f825fc41095c
This commit is contained in:
parent
b836b3287a
commit
ff01e27763
@ -352,6 +352,13 @@ class UFOReader(object):
|
|||||||
def readKerning(self):
|
def readKerning(self):
|
||||||
"""
|
"""
|
||||||
Read kerning.plist. Returns a dict.
|
Read kerning.plist. Returns a dict.
|
||||||
|
|
||||||
|
This performs structural validation of the kerning data,
|
||||||
|
but it does not check the validity of the kerning as
|
||||||
|
dictated in the UFO spec. To do that, pass the kerning
|
||||||
|
obtained from this method and the groups obtained from
|
||||||
|
readGroups to the kerningvalidator function in the
|
||||||
|
validators module.
|
||||||
"""
|
"""
|
||||||
# handle up conversion
|
# handle up conversion
|
||||||
if self._formatVersion < 3:
|
if self._formatVersion < 3:
|
||||||
@ -834,6 +841,11 @@ class UFOWriter(object):
|
|||||||
"""
|
"""
|
||||||
Write kerning.plist. This method requires a
|
Write kerning.plist. This method requires a
|
||||||
dict of kerning pairs as an argument.
|
dict of kerning pairs as an argument.
|
||||||
|
|
||||||
|
This performs basic structural validation of the kerning,
|
||||||
|
but it does not check for compliance with the spec in
|
||||||
|
regards to conflicting pairs. The assumption is that the
|
||||||
|
kerning data being passed is standards compliant.
|
||||||
"""
|
"""
|
||||||
invalidFormatMessage = "The kerning is not properly formatted."
|
invalidFormatMessage = "The kerning is not properly formatted."
|
||||||
if not isDictEnough(kerning):
|
if not isDictEnough(kerning):
|
||||||
|
@ -3,7 +3,6 @@
|
|||||||
import os
|
import os
|
||||||
import calendar
|
import calendar
|
||||||
|
|
||||||
|
|
||||||
# -------
|
# -------
|
||||||
# Generic
|
# Generic
|
||||||
# -------
|
# -------
|
||||||
@ -887,6 +886,92 @@ def groupsValidator(value):
|
|||||||
d[glyphName] = groupName
|
d[glyphName] = groupName
|
||||||
return True, None
|
return True, None
|
||||||
|
|
||||||
|
# -------------
|
||||||
|
# kerning.plist
|
||||||
|
# -------------
|
||||||
|
|
||||||
|
def kerningValidator(kerning, groups):
|
||||||
|
"""
|
||||||
|
This validates a passed kerning dictionary
|
||||||
|
using the provided groups. The validation
|
||||||
|
checks to make sure that there are no conflicting
|
||||||
|
glyph + group and group + glyph exceptions.
|
||||||
|
|
||||||
|
>>> 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,
|
||||||
|
... }
|
||||||
|
>>> kerningValidator(kerning, groups)
|
||||||
|
True
|
||||||
|
>>> kerning = {
|
||||||
|
... ("public.kern1.O", "public.kern2.E") : -100,
|
||||||
|
... ("public.kern1.O", "F") : -200,
|
||||||
|
... ("Q", "public.kern2.E") : -250,
|
||||||
|
... ("D", "F") : -300,
|
||||||
|
... }
|
||||||
|
>>> kerningValidator(kerning, groups)
|
||||||
|
False
|
||||||
|
"""
|
||||||
|
# flatten the groups
|
||||||
|
flatFirstGroups = {}
|
||||||
|
flatSecondGroups = {}
|
||||||
|
for groupName, glyphList in groups.items():
|
||||||
|
if not groupName.startswith("public.kern1.") and not groupName.startswith("public.kern2."):
|
||||||
|
continue
|
||||||
|
if groupName.startswith("public.kern1."):
|
||||||
|
d = flatFirstGroups
|
||||||
|
elif groupName.startswith("public.kern2."):
|
||||||
|
d = flatSecondGroups
|
||||||
|
for glyphName in glyphList:
|
||||||
|
d[glyphName] = groupName
|
||||||
|
# search for conflicts
|
||||||
|
for first, second in kerning.keys():
|
||||||
|
firstIsGroup = first.startswith("public.kern1.")
|
||||||
|
secondIsGroup = second.startswith("public.kern2.")
|
||||||
|
# skip anything other than glyph + group and group + glyph
|
||||||
|
if firstIsGroup and secondIsGroup:
|
||||||
|
continue
|
||||||
|
if not firstIsGroup and not secondIsGroup:
|
||||||
|
continue
|
||||||
|
# if the first is a glyph and it isn't in a group, skip
|
||||||
|
if not firstIsGroup:
|
||||||
|
if first not in flatFirstGroups:
|
||||||
|
continue
|
||||||
|
# if the second is a glyph and it isn't in a group, skip
|
||||||
|
if not secondIsGroup:
|
||||||
|
if second not in flatSecondGroups:
|
||||||
|
continue
|
||||||
|
# skip unknown things
|
||||||
|
if firstIsGroup and first not in groups:
|
||||||
|
continue
|
||||||
|
if firstIsGroup and second not in flatSecondGroups:
|
||||||
|
continue
|
||||||
|
if secondIsGroup and second not in groups:
|
||||||
|
continue
|
||||||
|
if secondIsGroup and first not in flatFirstGroups:
|
||||||
|
continue
|
||||||
|
# validate group + glyph
|
||||||
|
if firstIsGroup:
|
||||||
|
firstOptions = groups[first]
|
||||||
|
secondGroup = flatSecondGroups[second]
|
||||||
|
for glyph in firstOptions:
|
||||||
|
if (glyph, secondGroup) in kerning:
|
||||||
|
return False
|
||||||
|
# validate glyph + group
|
||||||
|
if secondIsGroup:
|
||||||
|
secondOptions = groups[second]
|
||||||
|
firstGroup = flatFirstGroups[first]
|
||||||
|
for glyph in secondOptions:
|
||||||
|
if (firstGroup, glyph) in kerning:
|
||||||
|
return False
|
||||||
|
# fallback
|
||||||
|
return True
|
||||||
|
|
||||||
# -------------
|
# -------------
|
||||||
# lib.plist/lib
|
# lib.plist/lib
|
||||||
# -------------
|
# -------------
|
||||||
|
Loading…
x
Reference in New Issue
Block a user