Add write time kerning group down conversion to UFOWriter.
This allows the UFO 3 up converted kerning group names to be reset to their original names at the time of writing in UFO <= 2.
This commit is contained in:
parent
0f6b6d741a
commit
8dc8742959
@ -591,6 +591,7 @@ class UFOWriter(object):
|
||||
self._path = path
|
||||
self._formatVersion = formatVersion
|
||||
self._fileCreator = fileCreator
|
||||
self._downConversionKerningData = None
|
||||
# if the file already exists, get the format version.
|
||||
# this will be needed for up and down conversion.
|
||||
previousFormatVersion = None
|
||||
@ -815,14 +816,67 @@ class UFOWriter(object):
|
||||
|
||||
# groups.plist
|
||||
|
||||
def setKerningGroupConversionRenameMaps(self, maps):
|
||||
"""
|
||||
Set maps defining the renaming that should be done
|
||||
when writing groups and kerning in UFO 1 and UFO 2.
|
||||
This will effectively undo the conversion done when
|
||||
UFOReader reads this data. The dictionary should have
|
||||
this form:
|
||||
|
||||
{
|
||||
"side1" : {"group name to use when writing" : "group name in data"},
|
||||
"side2" : {"group name to use when writing" : "group name in data"}
|
||||
}
|
||||
|
||||
This is the same form returned by UFOReader's
|
||||
getKerningGroupConversionRenameMaps method.
|
||||
"""
|
||||
if self._formatVersion >= 3:
|
||||
return # XXX raise an error here
|
||||
# flip the dictionaries
|
||||
remap = {}
|
||||
for side in ("side1", "side2"):
|
||||
for writeName, dataName in maps[side].items():
|
||||
remap[dataName] = writeName
|
||||
self._downConversionKerningData = dict(groupRenameMap=remap)
|
||||
|
||||
def writeGroups(self, groups):
|
||||
"""
|
||||
Write groups.plist. This method requires a
|
||||
dict of glyph groups as an argument.
|
||||
"""
|
||||
# validate the data structure
|
||||
valid, message = groupsValidator(groups)
|
||||
if not valid:
|
||||
raise UFOLibError(message)
|
||||
# down convert
|
||||
if self._formatVersion < 3 and self._downConversionKerningData is not None:
|
||||
remap = self._downConversionKerningData["groupRenameMap"]
|
||||
remappedGroups = {}
|
||||
# there are some edge cases here that are ignored:
|
||||
# 1. if a group is being renamed to a name that
|
||||
# already exists, the existing group is always
|
||||
# overwritten. (this is why there are two loops
|
||||
# below.) there doesn't seem to be a logical
|
||||
# solution to groups mismatching and overwriting
|
||||
# with the specifiecd group seems like a better
|
||||
# solution than throwing an error.
|
||||
# 2. if side 1 and side 2 groups are being renamed
|
||||
# to the same group name there is no check to
|
||||
# ensure that the contents are identical. that
|
||||
# is left up to the caller.
|
||||
for name, contents in groups.items():
|
||||
if name in remap:
|
||||
continue
|
||||
remappedGroups[name] = contents
|
||||
for name, contents in groups.items():
|
||||
if name not in remap:
|
||||
continue
|
||||
name = remap[name]
|
||||
remappedGroups[name] = contents
|
||||
groups = remappedGroups
|
||||
# pack and write
|
||||
self._makeDirectory()
|
||||
path = os.path.join(self._path, GROUPS_FILENAME)
|
||||
groupsNew = {}
|
||||
@ -881,6 +935,7 @@ class UFOWriter(object):
|
||||
regards to conflicting pairs. The assumption is that the
|
||||
kerning data being passed is standards compliant.
|
||||
"""
|
||||
# validate the data structure
|
||||
invalidFormatMessage = "The kerning is not properly formatted."
|
||||
if not isDictEnough(kerning):
|
||||
raise UFOLibError(invalidFormatMessage)
|
||||
@ -895,6 +950,16 @@ class UFOWriter(object):
|
||||
raise UFOLibError(invalidFormatMessage)
|
||||
if not isinstance(value, (int, float)):
|
||||
raise UFOLibError(invalidFormatMessage)
|
||||
# down convert
|
||||
if self._formatVersion < 3 and self._downConversionKerningData is not None:
|
||||
remap = self._downConversionKerningData["groupRenameMap"]
|
||||
remappedKerning = {}
|
||||
for (side1, side2), value in kerning.items():
|
||||
side1 = remap.get(side1, side1)
|
||||
side2 = remap.get(side2, side2)
|
||||
remappedKerning[side1, side2] = value
|
||||
kerning = remappedKerning
|
||||
# pack and write
|
||||
self._makeDirectory()
|
||||
path = os.path.join(self._path, KERNING_FILENAME)
|
||||
kerningDict = {}
|
||||
|
@ -6,7 +6,7 @@ import unittest
|
||||
import tempfile
|
||||
import codecs
|
||||
from plistlib import writePlist, readPlist
|
||||
from ufoLib import convertUFOFormatVersion1ToFormatVersion2, UFOReader
|
||||
from ufoLib import convertUFOFormatVersion1ToFormatVersion2, UFOReader, UFOWriter
|
||||
from testSupport import expectedFontInfo1To2Conversion, expectedFontInfo2To1Conversion
|
||||
|
||||
|
||||
@ -113,13 +113,6 @@ class ConversionFunctionsTestCase(unittest.TestCase):
|
||||
convertUFOFormatVersion1ToFormatVersion2(path1, path2)
|
||||
self.compareFileStructures(path2, path3, expectedFontInfo1To2Conversion, False)
|
||||
|
||||
# def test2To1(self):
|
||||
# path1 = self.getFontPath("TestFont1 (UFO2).ufo")
|
||||
# path2 = self.getFontPath("TestFont1 (UFO2) converted.ufo")
|
||||
# path3 = self.getFontPath("TestFont1 (UFO1).ufo")
|
||||
# convertUFOFormatVersion2ToFormatVersion1(path1, path2)
|
||||
# self.compareFileStructures(path2, path3, expectedFontInfo2To1Conversion, False)
|
||||
|
||||
|
||||
# ---------------------
|
||||
# kerning up conversion
|
||||
@ -236,6 +229,115 @@ class KerningUpConversionTestCase(unittest.TestCase):
|
||||
reader.readInfo(info)
|
||||
|
||||
|
||||
class KerningDownConversionTestCase(unittest.TestCase):
|
||||
|
||||
expectedKerning = {
|
||||
("public.kern1.BGroup", "public.kern2.CGroup"): 7,
|
||||
("public.kern1.BGroup", "public.kern2.DGroup"): 8,
|
||||
("public.kern1.BGroup", "A"): 5,
|
||||
("public.kern1.BGroup", "B"): 6,
|
||||
("public.kern1.CGroup", "public.kern2.CGroup"): 11,
|
||||
("public.kern1.CGroup", "public.kern2.DGroup"): 12,
|
||||
("public.kern1.CGroup", "A"): 9,
|
||||
("public.kern1.CGroup", "B"): 10,
|
||||
("A", "public.kern2.CGroup"): 3,
|
||||
("A", "public.kern2.DGroup"): 4,
|
||||
("A", "A"): 1,
|
||||
("A", "B"): 2
|
||||
}
|
||||
|
||||
groups = {
|
||||
"BGroup": ["B"],
|
||||
"CGroup": ["C"],
|
||||
"DGroup": ["D"],
|
||||
"public.kern1.BGroup": ["B"],
|
||||
"public.kern1.CGroup": ["C", "Ccedilla"],
|
||||
"public.kern2.CGroup": ["C", "Ccedilla"],
|
||||
"public.kern2.DGroup": ["D"],
|
||||
"Not A Kerning Group" : ["A"]
|
||||
}
|
||||
expectedWrittenGroups = {
|
||||
"BGroup": ["B"],
|
||||
"CGroup": ["C", "Ccedilla"],
|
||||
"DGroup": ["D"],
|
||||
"Not A Kerning Group" : ["A"]
|
||||
}
|
||||
|
||||
kerning = {
|
||||
("public.kern1.BGroup", "public.kern2.CGroup"): 7,
|
||||
("public.kern1.BGroup", "public.kern2.DGroup"): 8,
|
||||
("public.kern1.BGroup", "A"): 5,
|
||||
("public.kern1.BGroup", "B"): 6,
|
||||
("public.kern1.CGroup", "public.kern2.CGroup"): 11,
|
||||
("public.kern1.CGroup", "public.kern2.DGroup"): 12,
|
||||
("public.kern1.CGroup", "A"): 9,
|
||||
("public.kern1.CGroup", "B"): 10,
|
||||
("A", "public.kern2.CGroup"): 3,
|
||||
("A", "public.kern2.DGroup"): 4,
|
||||
("A", "A"): 1,
|
||||
("A", "B"): 2
|
||||
}
|
||||
expectedWrittenKerning = {
|
||||
"BGroup" : {
|
||||
"CGroup" : 7,
|
||||
"DGroup" : 8,
|
||||
"A" : 5,
|
||||
"B" : 6
|
||||
},
|
||||
"CGroup" : {
|
||||
"CGroup" : 11,
|
||||
"DGroup" : 12,
|
||||
"A" : 9,
|
||||
"B" : 10
|
||||
},
|
||||
"A" : {
|
||||
"CGroup" : 3,
|
||||
"DGroup" : 4,
|
||||
"A" : 1,
|
||||
"B" : 2
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
downConversionMapping = {
|
||||
"side1" : {
|
||||
"BGroup" : "public.kern1.BGroup",
|
||||
"CGroup" : "public.kern1.CGroup"
|
||||
},
|
||||
"side2" : {
|
||||
"CGroup" : "public.kern2.CGroup",
|
||||
"DGroup" : "public.kern2.DGroup"
|
||||
}
|
||||
}
|
||||
|
||||
def setUp(self):
|
||||
self.tempDir = tempfile.mktemp()
|
||||
os.mkdir(self.tempDir)
|
||||
self.dstDir = os.path.join(self.tempDir, "test.ufo")
|
||||
|
||||
def tearDown(self):
|
||||
shutil.rmtree(self.tempDir)
|
||||
|
||||
def tearDownUFO(self):
|
||||
shutil.rmtree(self.dstDir)
|
||||
|
||||
def testWrite(self):
|
||||
writer = UFOWriter(self.dstDir, formatVersion=2)
|
||||
writer.setKerningGroupConversionRenameMaps(self.downConversionMapping)
|
||||
writer.writeKerning(self.kerning)
|
||||
writer.writeGroups(self.groups)
|
||||
# test groups
|
||||
path = os.path.join(self.dstDir, "groups.plist")
|
||||
writtenGroups = readPlist(path)
|
||||
self.assertEqual(writtenGroups, self.expectedWrittenGroups)
|
||||
# test kerning
|
||||
path = os.path.join(self.dstDir, "kerning.plist")
|
||||
writtenKerning = readPlist(path)
|
||||
self.assertEqual(writtenKerning, self.expectedWrittenKerning)
|
||||
self.tearDownUFO()
|
||||
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
from robofab.test.testSupport import runTests
|
||||
runTests()
|
||||
|
Loading…
x
Reference in New Issue
Block a user