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
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()
|