You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

368 lines
10 KiB

import os
import shutil
import unittest
import tempfile
from io import open
from fontTools.ufoLib import UFOReader, UFOWriter
from fontTools.ufoLib import plistlib
from .testSupport import expectedFontInfo1To2Conversion, expectedFontInfo2To1Conversion
# the format version 1 lib.plist contains some data
# that these tests shouldn't be concerned about.
removeFromFormatVersion1Lib = [
"org.robofab.opentype.classes",
"org.robofab.opentype.features",
"org.robofab.opentype.featureorder",
"org.robofab.postScriptHintData"
]
class ConversionFunctionsTestCase(unittest.TestCase):
def tearDown(self):
path = self.getFontPath("TestFont1 (UFO1) converted.ufo")
if os.path.exists(path):
shutil.rmtree(path)
path = self.getFontPath("TestFont1 (UFO2) converted.ufo")
if os.path.exists(path):
shutil.rmtree(path)
def getFontPath(self, fileName):
testdata = os.path.join(os.path.dirname(__file__), "testdata")
return os.path.join(testdata, fileName)
def compareFileStructures(self, path1, path2, expectedInfoData, testFeatures):
# result
metainfoPath1 = os.path.join(path1, "metainfo.plist")
fontinfoPath1 = os.path.join(path1, "fontinfo.plist")
kerningPath1 = os.path.join(path1, "kerning.plist")
groupsPath1 = os.path.join(path1, "groups.plist")
libPath1 = os.path.join(path1, "lib.plist")
featuresPath1 = os.path.join(path1, "features.plist")
glyphsPath1 = os.path.join(path1, "glyphs")
glyphsPath1_contents = os.path.join(glyphsPath1, "contents.plist")
glyphsPath1_A = os.path.join(glyphsPath1, "A_.glif")
glyphsPath1_B = os.path.join(glyphsPath1, "B_.glif")
# expected result
metainfoPath2 = os.path.join(path2, "metainfo.plist")
fontinfoPath2 = os.path.join(path2, "fontinfo.plist")
kerningPath2 = os.path.join(path2, "kerning.plist")
groupsPath2 = os.path.join(path2, "groups.plist")
libPath2 = os.path.join(path2, "lib.plist")
featuresPath2 = os.path.join(path2, "features.plist")
glyphsPath2 = os.path.join(path2, "glyphs")
glyphsPath2_contents = os.path.join(glyphsPath2, "contents.plist")
glyphsPath2_A = os.path.join(glyphsPath2, "A_.glif")
glyphsPath2_B = os.path.join(glyphsPath2, "B_.glif")
# look for existence
self.assertEqual(os.path.exists(metainfoPath1), True)
self.assertEqual(os.path.exists(fontinfoPath1), True)
self.assertEqual(os.path.exists(kerningPath1), True)
self.assertEqual(os.path.exists(groupsPath1), True)
self.assertEqual(os.path.exists(libPath1), True)
self.assertEqual(os.path.exists(glyphsPath1), True)
self.assertEqual(os.path.exists(glyphsPath1_contents), True)
self.assertEqual(os.path.exists(glyphsPath1_A), True)
self.assertEqual(os.path.exists(glyphsPath1_B), True)
if testFeatures:
self.assertEqual(os.path.exists(featuresPath1), True)
# look for aggrement
with open(metainfoPath1, "rb") as f:
data1 = plistlib.load(f)
with open(metainfoPath2, "rb") as f:
data2 = plistlib.load(f)
self.assertEqual(data1, data2)
with open(fontinfoPath1, "rb") as f:
data1 = plistlib.load(f)
self.assertEqual(sorted(data1.items()), sorted(expectedInfoData.items()))
with open(kerningPath1, "rb") as f:
data1 = plistlib.load(f)
with open(kerningPath2, "rb") as f:
data2 = plistlib.load(f)
self.assertEqual(data1, data2)
with open(groupsPath1, "rb") as f:
data1 = plistlib.load(f)
with open(groupsPath2, "rb") as f:
data2 = plistlib.load(f)
self.assertEqual(data1, data2)
with open(libPath1, "rb") as f:
data1 = plistlib.load(f)
with open(libPath2, "rb") as f:
data2 = plistlib.load(f)
if "UFO1" in libPath1:
for key in removeFromFormatVersion1Lib:
if key in data1:
del data1[key]
if "UFO1" in libPath2:
for key in removeFromFormatVersion1Lib:
if key in data2:
del data2[key]
self.assertEqual(data1, data2)
with open(glyphsPath1_contents, "rb") as f:
data1 = plistlib.load(f)
with open(glyphsPath2_contents, "rb") as f:
data2 = plistlib.load(f)
self.assertEqual(data1, data2)
with open(glyphsPath1_A, "rb") as f:
data1 = plistlib.load(f)
with open(glyphsPath2_A, "rb") as f:
data2 = plistlib.load(f)
self.assertEqual(data1, data2)
with open(glyphsPath1_B, "rb") as f:
data1 = plistlib.load(f)
with open(glyphsPath2_B, "rb") as f:
data2 = plistlib.load(f)
self.assertEqual(data1, data2)
# ---------------------
# kerning up conversion
# ---------------------
class TestInfoObject: pass
class KerningUpConversionTestCase(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,
("X", "A"): 13,
("X", "public.kern2.CGroup"): 14
}
expectedGroups = {
"BGroup": ["B"],
"CGroup": ["C", "Ccedilla"],
"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"],
"X": ["X", "X.sc"]
}
def setUp(self):
self.tempDir = tempfile.mktemp()
os.mkdir(self.tempDir)
self.ufoPath = os.path.join(self.tempDir, "test.ufo")
def tearDown(self):
shutil.rmtree(self.tempDir)
def makeUFO(self, formatVersion):
self.clearUFO()
if not os.path.exists(self.ufoPath):
os.mkdir(self.ufoPath)
# glyphs
glyphsPath = os.path.join(self.ufoPath, "glyphs")
if not os.path.exists(glyphsPath):
os.mkdir(glyphsPath)
glyphFile = "X_.glif"
glyphsContents = dict(X=glyphFile)
path = os.path.join(glyphsPath, "contents.plist")
with open(path, "wb") as f:
plistlib.dump(glyphsContents, f)
path = os.path.join(glyphsPath, glyphFile)
with open(path, "w") as f:
f.write('<?xml version="1.0" encoding="UTF-8"?>\n')
# metainfo.plist
metaInfo = dict(creator="test", formatVersion=formatVersion)
path = os.path.join(self.ufoPath, "metainfo.plist")
with open(path, "wb") as f:
plistlib.dump(metaInfo, f)
# kerning
kerning = {
"A" : {
"A" : 1,
"B" : 2,
"CGroup" : 3,
"DGroup" : 4
},
"BGroup" : {
"A" : 5,
"B" : 6,
"CGroup" : 7,
"DGroup" : 8
},
"CGroup" : {
"A" : 9,
"B" : 10,
"CGroup" : 11,
"DGroup" : 12
},
"X": {
"A" : 13,
"CGroup" : 14
}
}
path = os.path.join(self.ufoPath, "kerning.plist")
with open(path, "wb") as f:
plistlib.dump(kerning, f)
# groups
groups = {
"BGroup" : ["B"],
"CGroup" : ["C", "Ccedilla"],
"DGroup" : ["D"],
"Not A Kerning Group" : ["A"],
"X" : ["X", "X.sc"] # a group with a name that is also a glyph name
}
path = os.path.join(self.ufoPath, "groups.plist")
with open(path, "wb") as f:
plistlib.dump(groups, f)
# font info
fontInfo = {
"familyName" : "Test"
}
path = os.path.join(self.ufoPath, "fontinfo.plist")
with open(path, "wb") as f:
plistlib.dump(fontInfo, f)
def clearUFO(self):
if os.path.exists(self.ufoPath):
shutil.rmtree(self.ufoPath)
def testUFO1(self):
self.makeUFO(formatVersion=2)
reader = UFOReader(self.ufoPath, validate=True)
kerning = reader.readKerning()
self.assertEqual(self.expectedKerning, kerning)
groups = reader.readGroups()
self.assertEqual(self.expectedGroups, groups)
info = TestInfoObject()
reader.readInfo(info)
def testUFO2(self):
self.makeUFO(formatVersion=2)
reader = UFOReader(self.ufoPath, validate=True)
kerning = reader.readKerning()
self.assertEqual(self.expectedKerning, kerning)
groups = reader.readGroups()
self.assertEqual(self.expectedGroups, groups)
info = TestInfoObject()
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")
with open(path, "rb") as f:
writtenGroups = plistlib.load(f)
self.assertEqual(writtenGroups, self.expectedWrittenGroups)
# test kerning
path = os.path.join(self.dstDir, "kerning.plist")
with open(path, "rb") as f:
writtenKerning = plistlib.load(f)
self.assertEqual(writtenKerning, self.expectedWrittenKerning)
self.tearDownUFO()