diff options
Diffstat (limited to 'misc/pylib/robofab/test')
-rwxr-xr-x | misc/pylib/robofab/test/__init__.py | 8 | ||||
-rw-r--r-- | misc/pylib/robofab/test/runAll.py | 27 | ||||
-rwxr-xr-x | misc/pylib/robofab/test/testSupport.py | 278 | ||||
-rw-r--r-- | misc/pylib/robofab/test/test_RInfoFL.py | 111 | ||||
-rw-r--r-- | misc/pylib/robofab/test/test_RInfoRF.py | 56 | ||||
-rw-r--r-- | misc/pylib/robofab/test/test_dialogs.py | 218 | ||||
-rw-r--r-- | misc/pylib/robofab/test/test_fontLabUFOReadWrite.py | 565 | ||||
-rw-r--r-- | misc/pylib/robofab/test/test_glifLib.py | 150 | ||||
-rw-r--r-- | misc/pylib/robofab/test/test_noneLabUFOReadWrite.py | 321 | ||||
-rwxr-xr-x | misc/pylib/robofab/test/test_objectsFL.py | 54 | ||||
-rwxr-xr-x | misc/pylib/robofab/test/test_objectsUFO.py | 203 | ||||
-rwxr-xr-x | misc/pylib/robofab/test/test_pens.py | 149 | ||||
-rw-r--r-- | misc/pylib/robofab/test/test_psHints.py | 110 | ||||
-rw-r--r-- | misc/pylib/robofab/test/test_ufoLib.py | 1659 |
14 files changed, 3909 insertions, 0 deletions
diff --git a/misc/pylib/robofab/test/__init__.py b/misc/pylib/robofab/test/__init__.py new file mode 100755 index 000000000..f34415804 --- /dev/null +++ b/misc/pylib/robofab/test/__init__.py @@ -0,0 +1,8 @@ +"""Directory for unit tests. + +Modules here are typically named text_<something>.py, where <something> is +usually a module name, for example "test_flPen.py", but it can also be the name +of an area or concept to be tested, for example "test_drawing.py". + +Testmodules should use the unittest framework. +""" diff --git a/misc/pylib/robofab/test/runAll.py b/misc/pylib/robofab/test/runAll.py new file mode 100644 index 000000000..28446a7b8 --- /dev/null +++ b/misc/pylib/robofab/test/runAll.py @@ -0,0 +1,27 @@ +import os +import glob +import unittest + +import robofab.test + +if __name__ == "__main__": + testDir = os.path.dirname(robofab.test.__file__) + testFiles = glob.glob1(testDir, "test_*.py") + + loader = unittest.TestLoader() + suites = [] + for fileName in testFiles: + modName = "robofab.test." + fileName[:-3] + print "importing", fileName + try: + mod = __import__(modName, {}, {}, ["*"]) + except ImportError: + print "*** skipped", fileName + continue + + suites.append(loader.loadTestsFromModule(mod)) + + print "running tests..." + testRunner = unittest.TextTestRunner(verbosity=0) + testSuite = unittest.TestSuite(suites) + testRunner.run(testSuite) diff --git a/misc/pylib/robofab/test/testSupport.py b/misc/pylib/robofab/test/testSupport.py new file mode 100755 index 000000000..f7f96c9ff --- /dev/null +++ b/misc/pylib/robofab/test/testSupport.py @@ -0,0 +1,278 @@ +"""Miscellaneous helpers for our test suite.""" + + +import sys +import os +import types +import unittest + + +def getDemoFontPath(): + """Return the path to Data/DemoFont.ufo/.""" + import robofab + root = os.path.dirname(os.path.dirname(os.path.dirname(robofab.__file__))) + return os.path.join(root, "Data", "DemoFont.ufo") + + +def getDemoFontGlyphSetPath(): + """Return the path to Data/DemoFont.ufo/glyphs/.""" + return os.path.join(getDemoFontPath(), "glyphs") + + +def _gatherTestCasesFromCallerByMagic(): + # UGLY magic: fetch TestClass subclasses from the globals of our + # caller's caller. + frame = sys._getframe(2) + return _gatherTestCasesFromDict(frame.f_globals) + + +def _gatherTestCasesFromDict(d): + testCases = [] + for ob in d.values(): + if isinstance(ob, type) and issubclass(ob, unittest.TestCase): + testCases.append(ob) + return testCases + + +def runTests(testCases=None, verbosity=1): + """Run a series of tests.""" + if testCases is None: + testCases = _gatherTestCasesFromCallerByMagic() + loader = unittest.TestLoader() + suites = [] + for testCase in testCases: + suites.append(loader.loadTestsFromTestCase(testCase)) + + testRunner = unittest.TextTestRunner(verbosity=verbosity) + testSuite = unittest.TestSuite(suites) + testRunner.run(testSuite) + +# font info values used by several tests + +fontInfoVersion1 = { + "familyName" : "Some Font (Family Name)", + "styleName" : "Regular (Style Name)", + "fullName" : "Some Font-Regular (Postscript Full Name)", + "fontName" : "SomeFont-Regular (Postscript Font Name)", + "menuName" : "Some Font Regular (Style Map Family Name)", + "fontStyle" : 64, + "note" : "A note.", + "versionMajor" : 1, + "versionMinor" : 0, + "year" : 2008, + "copyright" : "Copyright Some Foundry.", + "notice" : "Some Font by Some Designer for Some Foundry.", + "trademark" : "Trademark Some Foundry", + "license" : "License info for Some Foundry.", + "licenseURL" : "http://somefoundry.com/license", + "createdBy" : "Some Foundry", + "designer" : "Some Designer", + "designerURL" : "http://somedesigner.com", + "vendorURL" : "http://somefoundry.com", + "unitsPerEm" : 1000, + "ascender" : 750, + "descender" : -250, + "capHeight" : 750, + "xHeight" : 500, + "defaultWidth" : 400, + "slantAngle" : -12.5, + "italicAngle" : -12.5, + "widthName" : "Medium (normal)", + "weightName" : "Medium", + "weightValue" : 500, + "fondName" : "SomeFont Regular (FOND Name)", + "otFamilyName" : "Some Font (Preferred Family Name)", + "otStyleName" : "Regular (Preferred Subfamily Name)", + "otMacName" : "Some Font Regular (Compatible Full Name)", + "msCharSet" : 0, + "fondID" : 15000, + "uniqueID" : 4000000, + "ttVendor" : "SOME", + "ttUniqueID" : "OpenType name Table Unique ID", + "ttVersion" : "OpenType name Table Version", +} + +fontInfoVersion2 = { + "familyName" : "Some Font (Family Name)", + "styleName" : "Regular (Style Name)", + "styleMapFamilyName" : "Some Font Regular (Style Map Family Name)", + "styleMapStyleName" : "regular", + "versionMajor" : 1, + "versionMinor" : 0, + "year" : 2008, + "copyright" : "Copyright Some Foundry.", + "trademark" : "Trademark Some Foundry", + "unitsPerEm" : 1000, + "descender" : -250, + "xHeight" : 500, + "capHeight" : 750, + "ascender" : 750, + "italicAngle" : -12.5, + "note" : "A note.", + "openTypeHeadCreated" : "2000/01/01 00:00:00", + "openTypeHeadLowestRecPPEM" : 10, + "openTypeHeadFlags" : [0, 1], + "openTypeHheaAscender" : 750, + "openTypeHheaDescender" : -250, + "openTypeHheaLineGap" : 200, + "openTypeHheaCaretSlopeRise" : 1, + "openTypeHheaCaretSlopeRun" : 0, + "openTypeHheaCaretOffset" : 0, + "openTypeNameDesigner" : "Some Designer", + "openTypeNameDesignerURL" : "http://somedesigner.com", + "openTypeNameManufacturer" : "Some Foundry", + "openTypeNameManufacturerURL" : "http://somefoundry.com", + "openTypeNameLicense" : "License info for Some Foundry.", + "openTypeNameLicenseURL" : "http://somefoundry.com/license", + "openTypeNameVersion" : "OpenType name Table Version", + "openTypeNameUniqueID" : "OpenType name Table Unique ID", + "openTypeNameDescription" : "Some Font by Some Designer for Some Foundry.", + "openTypeNamePreferredFamilyName" : "Some Font (Preferred Family Name)", + "openTypeNamePreferredSubfamilyName" : "Regular (Preferred Subfamily Name)", + "openTypeNameCompatibleFullName" : "Some Font Regular (Compatible Full Name)", + "openTypeNameSampleText" : "Sample Text for Some Font.", + "openTypeNameWWSFamilyName" : "Some Font (WWS Family Name)", + "openTypeNameWWSSubfamilyName" : "Regular (WWS Subfamily Name)", + "openTypeOS2WidthClass" : 5, + "openTypeOS2WeightClass" : 500, + "openTypeOS2Selection" : [3], + "openTypeOS2VendorID" : "SOME", + "openTypeOS2Panose" : [0, 1, 2, 3, 4, 5, 6, 7, 8, 9], + "openTypeOS2FamilyClass" : [1, 1], + "openTypeOS2UnicodeRanges" : [0, 1], + "openTypeOS2CodePageRanges" : [0, 1], + "openTypeOS2TypoAscender" : 750, + "openTypeOS2TypoDescender" : -250, + "openTypeOS2TypoLineGap" : 200, + "openTypeOS2WinAscent" : 750, + "openTypeOS2WinDescent" : -250, + "openTypeOS2Type" : [], + "openTypeOS2SubscriptXSize" : 200, + "openTypeOS2SubscriptYSize" : 400, + "openTypeOS2SubscriptXOffset" : 0, + "openTypeOS2SubscriptYOffset" : -100, + "openTypeOS2SuperscriptXSize" : 200, + "openTypeOS2SuperscriptYSize" : 400, + "openTypeOS2SuperscriptXOffset" : 0, + "openTypeOS2SuperscriptYOffset" : 200, + "openTypeOS2StrikeoutSize" : 20, + "openTypeOS2StrikeoutPosition" : 300, + "openTypeVheaVertTypoAscender" : 750, + "openTypeVheaVertTypoDescender" : -250, + "openTypeVheaVertTypoLineGap" : 200, + "openTypeVheaCaretSlopeRise" : 0, + "openTypeVheaCaretSlopeRun" : 1, + "openTypeVheaCaretOffset" : 0, + "postscriptFontName" : "SomeFont-Regular (Postscript Font Name)", + "postscriptFullName" : "Some Font-Regular (Postscript Full Name)", + "postscriptSlantAngle" : -12.5, + "postscriptUniqueID" : 4000000, + "postscriptUnderlineThickness" : 20, + "postscriptUnderlinePosition" : -200, + "postscriptIsFixedPitch" : False, + "postscriptBlueValues" : [500, 510], + "postscriptOtherBlues" : [-250, -260], + "postscriptFamilyBlues" : [500, 510], + "postscriptFamilyOtherBlues" : [-250, -260], + "postscriptStemSnapH" : [100, 120], + "postscriptStemSnapV" : [80, 90], + "postscriptBlueFuzz" : 1, + "postscriptBlueShift" : 7, + "postscriptBlueScale" : 0.039625, + "postscriptForceBold" : True, + "postscriptDefaultWidthX" : 400, + "postscriptNominalWidthX" : 400, + "postscriptWeightName" : "Medium", + "postscriptDefaultCharacter" : ".notdef", + "postscriptWindowsCharacterSet" : 1, + "macintoshFONDFamilyID" : 15000, + "macintoshFONDName" : "SomeFont Regular (FOND Name)", +} + +expectedFontInfo1To2Conversion = { + "familyName" : "Some Font (Family Name)", + "styleMapFamilyName" : "Some Font Regular (Style Map Family Name)", + "styleMapStyleName" : "regular", + "styleName" : "Regular (Style Name)", + "unitsPerEm" : 1000, + "ascender" : 750, + "capHeight" : 750, + "xHeight" : 500, + "descender" : -250, + "italicAngle" : -12.5, + "versionMajor" : 1, + "versionMinor" : 0, + "year" : 2008, + "copyright" : "Copyright Some Foundry.", + "trademark" : "Trademark Some Foundry", + "note" : "A note.", + "macintoshFONDFamilyID" : 15000, + "macintoshFONDName" : "SomeFont Regular (FOND Name)", + "openTypeNameCompatibleFullName" : "Some Font Regular (Compatible Full Name)", + "openTypeNameDescription" : "Some Font by Some Designer for Some Foundry.", + "openTypeNameDesigner" : "Some Designer", + "openTypeNameDesignerURL" : "http://somedesigner.com", + "openTypeNameLicense" : "License info for Some Foundry.", + "openTypeNameLicenseURL" : "http://somefoundry.com/license", + "openTypeNameManufacturer" : "Some Foundry", + "openTypeNameManufacturerURL" : "http://somefoundry.com", + "openTypeNamePreferredFamilyName" : "Some Font (Preferred Family Name)", + "openTypeNamePreferredSubfamilyName": "Regular (Preferred Subfamily Name)", + "openTypeNameCompatibleFullName" : "Some Font Regular (Compatible Full Name)", + "openTypeNameUniqueID" : "OpenType name Table Unique ID", + "openTypeNameVersion" : "OpenType name Table Version", + "openTypeOS2VendorID" : "SOME", + "openTypeOS2WeightClass" : 500, + "openTypeOS2WidthClass" : 5, + "postscriptDefaultWidthX" : 400, + "postscriptFontName" : "SomeFont-Regular (Postscript Font Name)", + "postscriptFullName" : "Some Font-Regular (Postscript Full Name)", + "postscriptSlantAngle" : -12.5, + "postscriptUniqueID" : 4000000, + "postscriptWeightName" : "Medium", + "postscriptWindowsCharacterSet" : 1 +} + +expectedFontInfo2To1Conversion = { + "familyName" : "Some Font (Family Name)", + "menuName" : "Some Font Regular (Style Map Family Name)", + "fontStyle" : 64, + "styleName" : "Regular (Style Name)", + "unitsPerEm" : 1000, + "ascender" : 750, + "capHeight" : 750, + "xHeight" : 500, + "descender" : -250, + "italicAngle" : -12.5, + "versionMajor" : 1, + "versionMinor" : 0, + "copyright" : "Copyright Some Foundry.", + "trademark" : "Trademark Some Foundry", + "note" : "A note.", + "fondID" : 15000, + "fondName" : "SomeFont Regular (FOND Name)", + "fullName" : "Some Font Regular (Compatible Full Name)", + "notice" : "Some Font by Some Designer for Some Foundry.", + "designer" : "Some Designer", + "designerURL" : "http://somedesigner.com", + "license" : "License info for Some Foundry.", + "licenseURL" : "http://somefoundry.com/license", + "createdBy" : "Some Foundry", + "vendorURL" : "http://somefoundry.com", + "otFamilyName" : "Some Font (Preferred Family Name)", + "otStyleName" : "Regular (Preferred Subfamily Name)", + "otMacName" : "Some Font Regular (Compatible Full Name)", + "ttUniqueID" : "OpenType name Table Unique ID", + "ttVersion" : "OpenType name Table Version", + "ttVendor" : "SOME", + "weightValue" : 500, + "widthName" : "Medium (normal)", + "defaultWidth" : 400, + "fontName" : "SomeFont-Regular (Postscript Font Name)", + "fullName" : "Some Font-Regular (Postscript Full Name)", + "slantAngle" : -12.5, + "uniqueID" : 4000000, + "weightName" : "Medium", + "msCharSet" : 0, + "year" : 2008 +} diff --git a/misc/pylib/robofab/test/test_RInfoFL.py b/misc/pylib/robofab/test/test_RInfoFL.py new file mode 100644 index 000000000..bfbd13477 --- /dev/null +++ b/misc/pylib/robofab/test/test_RInfoFL.py @@ -0,0 +1,111 @@ +import unittest +from cStringIO import StringIO +import sys +from robofab import ufoLib +from robofab.objects.objectsFL import NewFont +from robofab.test.testSupport import fontInfoVersion1, fontInfoVersion2 + + +class RInfoRFTestCase(unittest.TestCase): + + def testRoundTripVersion2(self): + font = NewFont() + infoObject = font.info + for attr, value in fontInfoVersion2.items(): + if attr in infoObject._ufoToFLAttrMapping and infoObject._ufoToFLAttrMapping[attr]["nakedAttribute"] is None: + continue + setattr(infoObject, attr, value) + newValue = getattr(infoObject, attr) + self.assertEqual((attr, newValue), (attr, value)) + font.close() + + def testVersion2UnsupportedSet(self): + saveStderr = sys.stderr + saveStdout = sys.stdout + tempStderr = StringIO() + sys.stderr = tempStderr + sys.stdout = tempStderr + font = NewFont() + infoObject = font.info + requiredWarnings = [] + try: + for attr, value in fontInfoVersion2.items(): + if attr in infoObject._ufoToFLAttrMapping and infoObject._ufoToFLAttrMapping[attr]["nakedAttribute"] is not None: + continue + setattr(infoObject, attr, value) + s = "The attribute %s is not supported by FontLab." % attr + requiredWarnings.append((attr, s)) + finally: + sys.stderr = saveStderr + sys.stdout = saveStdout + tempStderr = tempStderr.getvalue() + for attr, line in requiredWarnings: + self.assertEquals((attr, line in tempStderr), (attr, True)) + font.close() + + def testVersion2UnsupportedGet(self): + saveStderr = sys.stderr + saveStdout = sys.stdout + tempStderr = StringIO() + sys.stderr = tempStderr + sys.stdout = tempStderr + font = NewFont() + infoObject = font.info + requiredWarnings = [] + try: + for attr, value in fontInfoVersion2.items(): + if attr in infoObject._ufoToFLAttrMapping and infoObject._ufoToFLAttrMapping[attr]["nakedAttribute"] is not None: + continue + getattr(infoObject, attr, value) + s = "The attribute %s is not supported by FontLab." % attr + requiredWarnings.append((attr, s)) + finally: + sys.stderr = saveStderr + sys.stdout = saveStdout + tempStderr = tempStderr.getvalue() + for attr, line in requiredWarnings: + self.assertEquals((attr, line in tempStderr), (attr, True)) + font.close() + + def testRoundTripVersion1(self): + font = NewFont() + infoObject = font.info + for attr, value in fontInfoVersion1.items(): + if attr not in ufoLib.deprecatedFontInfoAttributesVersion2: + setattr(infoObject, attr, value) + for attr, expectedValue in fontInfoVersion1.items(): + if attr not in ufoLib.deprecatedFontInfoAttributesVersion2: + value = getattr(infoObject, attr) + self.assertEqual((attr, expectedValue), (attr, value)) + font.close() + + def testVersion1DeprecationRoundTrip(self): + saveStderr = sys.stderr + saveStdout = sys.stdout + tempStderr = StringIO() + sys.stderr = tempStderr + sys.stdout = tempStderr + font = NewFont() + infoObject = font.info + requiredWarnings = [] + try: + for attr, value in fontInfoVersion1.items(): + if attr in ufoLib.deprecatedFontInfoAttributesVersion2: + setattr(infoObject, attr, value) + v = getattr(infoObject, attr) + self.assertEquals((attr, value), (attr, v)) + s = "DeprecationWarning: The %s attribute has been deprecated." % attr + requiredWarnings.append((attr, s)) + finally: + sys.stderr = saveStderr + sys.stdout = saveStdout + tempStderr = tempStderr.getvalue() + for attr, line in requiredWarnings: + self.assertEquals((attr, line in tempStderr), (attr, True)) + font.close() + + +if __name__ == "__main__": + from robofab.test.testSupport import runTests + runTests() + diff --git a/misc/pylib/robofab/test/test_RInfoRF.py b/misc/pylib/robofab/test/test_RInfoRF.py new file mode 100644 index 000000000..3a8747033 --- /dev/null +++ b/misc/pylib/robofab/test/test_RInfoRF.py @@ -0,0 +1,56 @@ +import unittest +from cStringIO import StringIO +import sys +from robofab import ufoLib +from robofab.objects.objectsRF import RInfo +from robofab.test.testSupport import fontInfoVersion1, fontInfoVersion2 + + +class RInfoRFTestCase(unittest.TestCase): + + def testRoundTripVersion2(self): + infoObject = RInfo() + for attr, value in fontInfoVersion2.items(): + setattr(infoObject, attr, value) + newValue = getattr(infoObject, attr) + self.assertEqual((attr, newValue), (attr, value)) + + def testRoundTripVersion1(self): + infoObject = RInfo() + for attr, value in fontInfoVersion1.items(): + if attr not in ufoLib.deprecatedFontInfoAttributesVersion2: + setattr(infoObject, attr, value) + for attr, expectedValue in fontInfoVersion1.items(): + if attr not in ufoLib.deprecatedFontInfoAttributesVersion2: + value = getattr(infoObject, attr) + self.assertEqual((attr, expectedValue), (attr, value)) + + def testVersion1DeprecationRoundTrip(self): + """ + unittest doesn't catch warnings in self.assertRaises, + so some hackery is required to catch the warnings + that are raised when setting deprecated attributes. + """ + saveStderr = sys.stderr + tempStderr = StringIO() + sys.stderr = tempStderr + infoObject = RInfo() + requiredWarnings = [] + try: + for attr, value in fontInfoVersion1.items(): + if attr in ufoLib.deprecatedFontInfoAttributesVersion2: + setattr(infoObject, attr, value) + v = getattr(infoObject, attr) + self.assertEquals((attr, value), (attr, v)) + s = "DeprecationWarning: The %s attribute has been deprecated." % attr + requiredWarnings.append((attr, s)) + finally: + sys.stderr = saveStderr + tempStderr = tempStderr.getvalue() + for attr, line in requiredWarnings: + self.assertEquals((attr, line in tempStderr), (attr, True)) + + +if __name__ == "__main__": + from robofab.test.testSupport import runTests + runTests() diff --git a/misc/pylib/robofab/test/test_dialogs.py b/misc/pylib/robofab/test/test_dialogs.py new file mode 100644 index 000000000..c296a6bd7 --- /dev/null +++ b/misc/pylib/robofab/test/test_dialogs.py @@ -0,0 +1,218 @@ +import robofab.interface.all.dialogs +reload(robofab.interface.all.dialogs) +from robofab.interface.all.dialogs import * + +import unittest + + +__all__ = [ + "AskString", #x + "AskYesNoCancel", #x + "FindGlyph", + "GetFile", #x + "GetFolder", #x + "GetFileOrFolder", #x + "Message", #x + "OneList", + "PutFile", #x + "SearchList", + "SelectFont", + "SelectGlyph", + "TwoChecks", + "TwoFields", + "ProgressBar", +] + +class DialogRunner(object): + def __init__(self): + prompt = "The prompt for %s." + message = "The message for %s." + title = "The title for %s." + informativeText = "The informative text for %s." + fileTypes = ['ufo'] + fileName = "The_filename.txt" + + self.fonts = fonts = [self.makeTestFont(n) for n in range(4)] + + t = "AskString" + try: + print "About to try", t + print "\t>>>", AskString( + message=prompt%t, + value='', + title=title%t + ) + except NotImplementedError: + print t, "is not implemented." + + t = "AskYesNoCancel" + try: + print "About to try", t + print "\t>>>", AskYesNoCancel( + message=prompt%t+" default set to 0", + title=title%t, + default=0, + informativeText=informativeText%t + ) + print "\t>>>", AskYesNoCancel( + message=prompt%t+" default set to 1", + title=title%t, + default=1, + informativeText=informativeText%t + ) + except NotImplementedError: + print t, "is not implemented." + + t = "GetFile" + try: + print "About to try", t + print "\t>>>", GetFile( + message=message%t+" Only fileTypes "+`fileTypes`, + title=title%t, + directory=None, + fileName=fileName, + allowsMultipleSelection=False, + fileTypes=fileTypes + ) + print "\t>>>", GetFile( + message=message%t+" All filetypes, allow multiple selection.", + title=title%t, + directory=None, + fileName=fileName, + allowsMultipleSelection=True, + fileTypes=None + ) + except NotImplementedError: + print t, "is not implemented." + + t = "GetFolder" + try: + print "About to try", t + print "\t>>>", GetFolder( + message=message%t, + title=title%t, + directory=None, + allowsMultipleSelection=False + ) + print "\t>>>", GetFolder( + message=message%t + " Allow multiple selection.", + title=title%t, + directory=None, + allowsMultipleSelection=True + ) + except NotImplementedError: + print t, "is not implemented." + + t = "GetFileOrFolder" + try: + print "About to try", t + print "\t>>>", GetFileOrFolder( + message=message%t+" Only fileTypes "+`fileTypes`, + title=title%t, + directory=None, + fileName=fileName, + allowsMultipleSelection=False, + fileTypes=fileTypes + ) + print "\t>>>", GetFileOrFolder( + message=message%t + " Allow multiple selection.", + title=title%t, + directory=None, + fileName=fileName, + allowsMultipleSelection=True, + fileTypes=None + ) + except NotImplementedError: + print t, "is not implemented." + + t = "Message" + try: + print "About to try", t + print "\t>>>", Message( + message=message%t, + title=title%t, + informativeText=informativeText%t + ) + except NotImplementedError: + print t, "is not implemented." + + t = "PutFile" + try: + print "About to try", t + print "\t>>>", PutFile( + message=message%t, + fileName=fileName, + ) + except NotImplementedError: + print t, "is not implemented." + + # t = "SelectFont" + # try: + #print "About to try", t + # print "\t>>>", SelectFont( + # message=message%t, + # title=title%t, + # allFonts=fonts, + # ) + # except NotImplementedError: + # print t, "is not implemented." + + # t = 'SelectGlyph' + # try: + #print "About to try", t + # print "\t>>>", SelectGlyph( + # font=fonts[0], + # message=message%t, + # title=title%t, + # ) + # except NotImplementedError: + # print t, "is not implemented." + + print 'No more tests.' + + def makeTestFont(self, number): + from robofab.objects.objectsRF import RFont as _RFont + f = _RFont() + f.info.familyName = "TestFamily" + f.info.styleName = "weight%d"%number + f.info.postscriptFullName = "%s %s"%(f.info.familyName, f.info.styleName) + # make some glyphs + for name in ['A', 'B', 'C']: + g = f.newGlyph(name) + pen = g.getPen() + pen.moveTo((0,0)) + pen.lineTo((500, 0)) + pen.lineTo((500, 800)) + pen.lineTo((0, 800)) + pen.closePath() + return f + + +class DialogTests(unittest.TestCase): + def setUp(self): + from robofab.interface.all.dialogs import test + test() + + def tearDown(self): + pass + + def testDialogs(self): + import robofab.interface.all.dialogs + dialogModuleName = robofab.interface.all.dialogs.platformApplicationModuleName + application = robofab.interface.all.dialogs.application + + if application is None and dialogModuleName == "dialogs_mac_vanilla": + # in vanilla, but not in a host application, run with executeVanillaTest + print + print "I'm running these tests with executeVanillaTest" + from vanilla.test.testTools import executeVanillaTest + executeVanillaTest(DialogRunner) + else: + print + print "I'm running these tests natively in" + DialogRunner() + + +if __name__ == "__main__": + from robofab.test.testSupport import runTests + runTests() diff --git a/misc/pylib/robofab/test/test_fontLabUFOReadWrite.py b/misc/pylib/robofab/test/test_fontLabUFOReadWrite.py new file mode 100644 index 000000000..91c072d26 --- /dev/null +++ b/misc/pylib/robofab/test/test_fontLabUFOReadWrite.py @@ -0,0 +1,565 @@ +import os +import shutil +import unittest +import tempfile +from robofab.plistlib import readPlist +import robofab +from robofab.ufoLib import UFOReader, UFOWriter +from robofab.test.testSupport import fontInfoVersion2, expectedFontInfo1To2Conversion +from robofab.objects.objectsFL import NewFont, OpenFont + +vfbPath = os.path.dirname(robofab.__file__) +vfbPath = os.path.dirname(vfbPath) +vfbPath = os.path.dirname(vfbPath) +vfbPath = os.path.join(vfbPath, "TestData", "TestFont1.vfb") + +ufoPath1 = os.path.dirname(robofab.__file__) +ufoPath1 = os.path.dirname(ufoPath1) +ufoPath1 = os.path.dirname(ufoPath1) +ufoPath1 = os.path.join(ufoPath1, "TestData", "TestFont1 (UFO1).ufo") +ufoPath2 = ufoPath1.replace("TestFont1 (UFO1).ufo", "TestFont1 (UFO2).ufo") + + +expectedFormatVersion1Features = """@myClass = [A B]; + +feature liga { + sub A A by b; +} liga; +""" + +# robofab should remove these from the lib after a load. +removeFromFormatVersion1Lib = [ + "org.robofab.opentype.classes", + "org.robofab.opentype.features", + "org.robofab.opentype.featureorder", + "org.robofab.postScriptHintData" +] + + +class ReadUFOFormatVersion1TestCase(unittest.TestCase): + + def setUpFont(self, doInfo=False, doKerning=False, doGroups=False, doLib=False, doFeatures=False): + self.font = NewFont() + self.ufoPath = ufoPath1 + self.font.readUFO(ufoPath1, doInfo=doInfo, doKerning=doKerning, doGroups=doGroups, doLib=doLib, doFeatures=doFeatures) + self.font.update() + + def tearDownFont(self): + self.font.close() + self.font = None + + def compareToUFO(self, doInfo=True, doKerning=True, doGroups=True, doLib=True, doFeatures=True): + reader = UFOReader(self.ufoPath) + results = {} + if doInfo: + infoMatches = True + info = self.font.info + for attr, expectedValue in expectedFontInfo1To2Conversion.items(): + writtenValue = getattr(info, attr) + if expectedValue != writtenValue: + infoMatches = False + break + results["info"]= infoMatches + if doKerning: + kerning = self.font.kerning.asDict() + expectedKerning = reader.readKerning() + results["kerning"] = expectedKerning == kerning + if doGroups: + groups = dict(self.font.groups) + expectedGroups = reader.readGroups() + results["groups"] = expectedGroups == groups + if doFeatures: + features = self.font.features.text + expectedFeatures = expectedFormatVersion1Features + # FontLab likes to add lines to the features, so skip blank lines. + features = [line for line in features.splitlines() if line] + expectedFeatures = [line for line in expectedFeatures.splitlines() if line] + results["features"] = expectedFeatures == features + if doLib: + lib = dict(self.font.lib) + expectedLib = reader.readLib() + for key in removeFromFormatVersion1Lib: + if key in expectedLib: + del expectedLib[key] + results["lib"] = expectedLib == lib + return results + + def testFull(self): + self.setUpFont(doInfo=True, doKerning=True, doGroups=True, doFeatures=True, doLib=True) + otherResults = self.compareToUFO() + self.assertEqual(otherResults["info"], True) + self.assertEqual(otherResults["kerning"], True) + self.assertEqual(otherResults["groups"], True) + self.assertEqual(otherResults["features"], True) + self.assertEqual(otherResults["lib"], True) + self.tearDownFont() + + def testInfo(self): + self.setUpFont(doInfo=True) + otherResults = self.compareToUFO(doInfo=False) + self.assertEqual(otherResults["kerning"], False) + self.assertEqual(otherResults["groups"], False) + self.assertEqual(otherResults["features"], False) + self.assertEqual(otherResults["lib"], False) + info = self.font.info + for attr, expectedValue in expectedFontInfo1To2Conversion.items(): + writtenValue = getattr(info, attr) + self.assertEqual((attr, expectedValue), (attr, writtenValue)) + self.tearDownFont() + + def testFeatures(self): + self.setUpFont(doFeatures=True) + otherResults = self.compareToUFO() + self.assertEqual(otherResults["info"], False) + self.assertEqual(otherResults["kerning"], False) + self.assertEqual(otherResults["groups"], False) + self.assertEqual(otherResults["features"], True) + self.assertEqual(otherResults["lib"], False) + self.tearDownFont() + + def testKerning(self): + self.setUpFont(doKerning=True) + otherResults = self.compareToUFO() + self.assertEqual(otherResults["info"], False) + self.assertEqual(otherResults["kerning"], True) + self.assertEqual(otherResults["groups"], False) + self.assertEqual(otherResults["features"], False) + self.assertEqual(otherResults["lib"], False) + self.tearDownFont() + + def testGroups(self): + self.setUpFont(doGroups=True) + otherResults = self.compareToUFO() + self.assertEqual(otherResults["info"], False) + self.assertEqual(otherResults["kerning"], False) + self.assertEqual(otherResults["groups"], True) + self.assertEqual(otherResults["features"], False) + self.assertEqual(otherResults["lib"], False) + self.tearDownFont() + + def testLib(self): + self.setUpFont(doLib=True) + otherResults = self.compareToUFO() + self.assertEqual(otherResults["info"], False) + self.assertEqual(otherResults["kerning"], False) + self.assertEqual(otherResults["groups"], False) + self.assertEqual(otherResults["features"], False) + self.assertEqual(otherResults["lib"], True) + self.tearDownFont() + + +class ReadUFOFormatVersion2TestCase(unittest.TestCase): + + def setUpFont(self, doInfo=False, doKerning=False, doGroups=False, doLib=False, doFeatures=False): + self.font = NewFont() + self.ufoPath = ufoPath2 + self.font.readUFO(ufoPath2, doInfo=doInfo, doKerning=doKerning, doGroups=doGroups, doLib=doLib, doFeatures=doFeatures) + self.font.update() + + def tearDownFont(self): + self.font.close() + self.font = None + + def compareToUFO(self, doInfo=True, doKerning=True, doGroups=True, doLib=True, doFeatures=True): + reader = UFOReader(self.ufoPath) + results = {} + if doInfo: + infoMatches = True + info = self.font.info + for attr, expectedValue in fontInfoVersion2.items(): + # cheat by skipping attrs that aren't supported + if info._ufoToFLAttrMapping[attr]["nakedAttribute"] is None: + continue + writtenValue = getattr(info, attr) + if expectedValue != writtenValue: + infoMatches = False + break + results["info"]= infoMatches + if doKerning: + kerning = self.font.kerning.asDict() + expectedKerning = reader.readKerning() + results["kerning"] = expectedKerning == kerning + if doGroups: + groups = dict(self.font.groups) + expectedGroups = reader.readGroups() + results["groups"] = expectedGroups == groups + if doFeatures: + features = self.font.features.text + expectedFeatures = reader.readFeatures() + results["features"] = expectedFeatures == features + if doLib: + lib = dict(self.font.lib) + expectedLib = reader.readLib() + results["lib"] = expectedLib == lib + return results + + def testFull(self): + self.setUpFont(doInfo=True, doKerning=True, doGroups=True, doFeatures=True, doLib=True) + otherResults = self.compareToUFO() + self.assertEqual(otherResults["info"], True) + self.assertEqual(otherResults["kerning"], True) + self.assertEqual(otherResults["groups"], True) + self.assertEqual(otherResults["features"], True) + self.assertEqual(otherResults["lib"], True) + self.tearDownFont() + + def testInfo(self): + self.setUpFont(doInfo=True) + otherResults = self.compareToUFO(doInfo=False) + self.assertEqual(otherResults["kerning"], False) + self.assertEqual(otherResults["groups"], False) + self.assertEqual(otherResults["features"], False) + self.assertEqual(otherResults["lib"], False) + info = self.font.info + for attr, expectedValue in fontInfoVersion2.items(): + # cheat by skipping attrs that aren't supported + if info._ufoToFLAttrMapping[attr]["nakedAttribute"] is None: + continue + writtenValue = getattr(info, attr) + self.assertEqual((attr, expectedValue), (attr, writtenValue)) + self.tearDownFont() + + def testFeatures(self): + self.setUpFont(doFeatures=True) + otherResults = self.compareToUFO() + self.assertEqual(otherResults["info"], False) + self.assertEqual(otherResults["kerning"], False) + self.assertEqual(otherResults["groups"], False) + self.assertEqual(otherResults["features"], True) + self.assertEqual(otherResults["lib"], False) + self.tearDownFont() + + def testKerning(self): + self.setUpFont(doKerning=True) + otherResults = self.compareToUFO() + self.assertEqual(otherResults["info"], False) + self.assertEqual(otherResults["kerning"], True) + self.assertEqual(otherResults["groups"], False) + self.assertEqual(otherResults["features"], False) + self.assertEqual(otherResults["lib"], False) + self.tearDownFont() + + def testGroups(self): + self.setUpFont(doGroups=True) + otherResults = self.compareToUFO() + self.assertEqual(otherResults["info"], False) + self.assertEqual(otherResults["kerning"], False) + self.assertEqual(otherResults["groups"], True) + self.assertEqual(otherResults["features"], False) + self.assertEqual(otherResults["lib"], False) + self.tearDownFont() + + def testLib(self): + self.setUpFont(doLib=True) + otherResults = self.compareToUFO() + self.assertEqual(otherResults["info"], False) + self.assertEqual(otherResults["kerning"], False) + self.assertEqual(otherResults["groups"], False) + self.assertEqual(otherResults["features"], False) + self.assertEqual(otherResults["lib"], True) + self.tearDownFont() + + +class WriteUFOFormatVersion1TestCase(unittest.TestCase): + + def setUpFont(self, doInfo=False, doKerning=False, doGroups=False): + self.dstDir = tempfile.mktemp() + os.mkdir(self.dstDir) + self.font = OpenFont(vfbPath) + self.font.writeUFO(self.dstDir, doInfo=doInfo, doKerning=doKerning, doGroups=doGroups, formatVersion=1) + self.font.close() + + def tearDownFont(self): + shutil.rmtree(self.dstDir) + + def compareToUFO(self, doInfo=True, doKerning=True, doGroups=True, doLib=True, doFeatures=True): + readerExpected = UFOReader(ufoPath1) + readerWritten = UFOReader(self.dstDir) + results = {} + if doInfo: + matches = True + expectedPath = os.path.join(ufoPath1, "fontinfo.plist") + writtenPath = os.path.join(self.dstDir, "fontinfo.plist") + if not os.path.exists(writtenPath): + matches = False + else: + expected = readPlist(expectedPath) + written = readPlist(writtenPath) + for attr, expectedValue in expected.items(): + if expectedValue != written[attr]: + matches = False + break + results["info"] = matches + if doKerning: + matches = True + expectedPath = os.path.join(ufoPath1, "kerning.plist") + writtenPath = os.path.join(self.dstDir, "kerning.plist") + if not os.path.exists(writtenPath): + matches = False + else: + matches = readPlist(expectedPath) == readPlist(writtenPath) + results["kerning"] = matches + if doGroups: + matches = True + expectedPath = os.path.join(ufoPath1, "groups.plist") + writtenPath = os.path.join(self.dstDir, "groups.plist") + if not os.path.exists(writtenPath): + matches = False + else: + matches = readPlist(expectedPath) == readPlist(writtenPath) + results["groups"] = matches + if doFeatures: + matches = True + featuresPath = os.path.join(self.dstDir, "features.fea") + libPath = os.path.join(self.dstDir, "lib.plist") + if os.path.exists(featuresPath): + matches = False + else: + fontLib = readPlist(libPath) + writtenText = [fontLib.get("org.robofab.opentype.classes", "")] + features = fontLib.get("org.robofab.opentype.features", {}) + featureOrder= fontLib.get("org.robofab.opentype.featureorder", []) + for featureName in featureOrder: + writtenText.append(features.get(featureName, "")) + writtenText = "\n".join(writtenText) + # FontLab likes to add lines to the features, so skip blank lines. + expectedText = [line for line in expectedFormatVersion1Features.splitlines() if line] + writtenText = [line for line in writtenText.splitlines() if line] + matches = "\n".join(expectedText) == "\n".join(writtenText) + results["features"] = matches + if doLib: + matches = True + expectedPath = os.path.join(ufoPath1, "lib.plist") + writtenPath = os.path.join(self.dstDir, "lib.plist") + if not os.path.exists(writtenPath): + matches = False + else: + # the test file doesn't have the glyph order + # so purge it from the written + writtenLib = readPlist(writtenPath) + del writtenLib["org.robofab.glyphOrder"] + matches = readPlist(expectedPath) == writtenLib + results["lib"] = matches + return results + + def testFull(self): + self.setUpFont(doInfo=True, doKerning=True, doGroups=True) + otherResults = self.compareToUFO() + self.assertEqual(otherResults["info"], True) + self.assertEqual(otherResults["kerning"], True) + self.assertEqual(otherResults["groups"], True) + self.assertEqual(otherResults["features"], True) + self.assertEqual(otherResults["lib"], True) + self.tearDownFont() + + def testInfo(self): + self.setUpFont(doInfo=True) + otherResults = self.compareToUFO(doInfo=False) + self.assertEqual(otherResults["kerning"], False) + self.assertEqual(otherResults["groups"], False) + expectedPath = os.path.join(ufoPath1, "fontinfo.plist") + writtenPath = os.path.join(self.dstDir, "fontinfo.plist") + expected = readPlist(expectedPath) + written = readPlist(writtenPath) + for attr, expectedValue in expected.items(): + self.assertEqual((attr, expectedValue), (attr, written[attr])) + self.tearDownFont() + + def testFeatures(self): + self.setUpFont() + otherResults = self.compareToUFO() + self.assertEqual(otherResults["info"], False) + self.assertEqual(otherResults["kerning"], False) + self.assertEqual(otherResults["groups"], False) + self.assertEqual(otherResults["features"], True) + self.tearDownFont() + + def testKerning(self): + self.setUpFont(doKerning=True) + otherResults = self.compareToUFO() + self.assertEqual(otherResults["info"], False) + self.assertEqual(otherResults["kerning"], True) + self.assertEqual(otherResults["groups"], False) + self.tearDownFont() + + def testGroups(self): + self.setUpFont(doGroups=True) + otherResults = self.compareToUFO() + self.assertEqual(otherResults["info"], False) + self.assertEqual(otherResults["kerning"], False) + self.assertEqual(otherResults["groups"], True) + self.tearDownFont() + + def testLib(self): + self.setUpFont() + otherResults = self.compareToUFO() + self.assertEqual(otherResults["info"], False) + self.assertEqual(otherResults["kerning"], False) + self.assertEqual(otherResults["groups"], False) + self.assertEqual(otherResults["lib"], True) + self.tearDownFont() + + + +class WriteUFOFormatVersion2TestCase(unittest.TestCase): + + def setUpFont(self, doInfo=False, doKerning=False, doGroups=False, doLib=False, doFeatures=False): + self.dstDir = tempfile.mktemp() + os.mkdir(self.dstDir) + self.font = OpenFont(vfbPath) + self.font.writeUFO(self.dstDir, doInfo=doInfo, doKerning=doKerning, doGroups=doGroups, doLib=doLib, doFeatures=doFeatures) + self.font.close() + + def tearDownFont(self): + shutil.rmtree(self.dstDir) + + def compareToUFO(self, doInfo=True, doKerning=True, doGroups=True, doLib=True, doFeatures=True): + readerExpected = UFOReader(ufoPath2) + readerWritten = UFOReader(self.dstDir) + results = {} + if doInfo: + matches = True + expectedPath = os.path.join(ufoPath2, "fontinfo.plist") + writtenPath = os.path.join(self.dstDir, "fontinfo.plist") + if not os.path.exists(writtenPath): + matches = False + else: + dummyFont = NewFont() + _ufoToFLAttrMapping = dict(dummyFont.info._ufoToFLAttrMapping) + dummyFont.close() + expected = readPlist(expectedPath) + written = readPlist(writtenPath) + for attr, expectedValue in expected.items(): + # cheat by skipping attrs that aren't supported + if _ufoToFLAttrMapping[attr]["nakedAttribute"] is None: + continue + if expectedValue != written[attr]: + matches = False + break + results["info"] = matches + if doKerning: + matches = True + expectedPath = os.path.join(ufoPath2, "kerning.plist") + writtenPath = os.path.join(self.dstDir, "kerning.plist") + if not os.path.exists(writtenPath): + matches = False + else: + matches = readPlist(expectedPath) == readPlist(writtenPath) + results["kerning"] = matches + if doGroups: + matches = True + expectedPath = os.path.join(ufoPath2, "groups.plist") + writtenPath = os.path.join(self.dstDir, "groups.plist") + if not os.path.exists(writtenPath): + matches = False + else: + matches = readPlist(expectedPath) == readPlist(writtenPath) + results["groups"] = matches + if doFeatures: + matches = True + expectedPath = os.path.join(ufoPath2, "features.fea") + writtenPath = os.path.join(self.dstDir, "features.fea") + if not os.path.exists(writtenPath): + matches = False + else: + f = open(expectedPath, "r") + expectedText = f.read() + f.close() + f = open(writtenPath, "r") + writtenText = f.read() + f.close() + # FontLab likes to add lines to the features, so skip blank lines. + expectedText = [line for line in expectedText.splitlines() if line] + writtenText = [line for line in writtenText.splitlines() if line] + matches = "\n".join(expectedText) == "\n".join(writtenText) + results["features"] = matches + if doLib: + matches = True + expectedPath = os.path.join(ufoPath2, "lib.plist") + writtenPath = os.path.join(self.dstDir, "lib.plist") + if not os.path.exists(writtenPath): + matches = False + else: + # the test file doesn't have the glyph order + # so purge it from the written + writtenLib = readPlist(writtenPath) + del writtenLib["org.robofab.glyphOrder"] + matches = readPlist(expectedPath) == writtenLib + results["lib"] = matches + return results + + def testFull(self): + self.setUpFont(doInfo=True, doKerning=True, doGroups=True, doFeatures=True, doLib=True) + otherResults = self.compareToUFO() + self.assertEqual(otherResults["info"], True) + self.assertEqual(otherResults["kerning"], True) + self.assertEqual(otherResults["groups"], True) + self.assertEqual(otherResults["features"], True) + self.assertEqual(otherResults["lib"], True) + self.tearDownFont() + + def testInfo(self): + self.setUpFont(doInfo=True) + otherResults = self.compareToUFO(doInfo=False) + self.assertEqual(otherResults["kerning"], False) + self.assertEqual(otherResults["groups"], False) + self.assertEqual(otherResults["features"], False) + self.assertEqual(otherResults["lib"], False) + expectedPath = os.path.join(ufoPath2, "fontinfo.plist") + writtenPath = os.path.join(self.dstDir, "fontinfo.plist") + expected = readPlist(expectedPath) + written = readPlist(writtenPath) + dummyFont = NewFont() + _ufoToFLAttrMapping = dict(dummyFont.info._ufoToFLAttrMapping) + dummyFont.close() + for attr, expectedValue in expected.items(): + # cheat by skipping attrs that aren't supported + if _ufoToFLAttrMapping[attr]["nakedAttribute"] is None: + continue + self.assertEqual((attr, expectedValue), (attr, written[attr])) + self.tearDownFont() + + def testFeatures(self): + self.setUpFont(doFeatures=True) + otherResults = self.compareToUFO() + self.assertEqual(otherResults["info"], False) + self.assertEqual(otherResults["kerning"], False) + self.assertEqual(otherResults["groups"], False) + self.assertEqual(otherResults["features"], True) + self.assertEqual(otherResults["lib"], False) + self.tearDownFont() + + def testKerning(self): + self.setUpFont(doKerning=True) + otherResults = self.compareToUFO() + self.assertEqual(otherResults["info"], False) + self.assertEqual(otherResults["kerning"], True) + self.assertEqual(otherResults["groups"], False) + self.assertEqual(otherResults["features"], False) + self.assertEqual(otherResults["lib"], False) + self.tearDownFont() + + def testGroups(self): + self.setUpFont(doGroups=True) + otherResults = self.compareToUFO() + self.assertEqual(otherResults["info"], False) + self.assertEqual(otherResults["kerning"], False) + self.assertEqual(otherResults["groups"], True) + self.assertEqual(otherResults["features"], False) + self.assertEqual(otherResults["lib"], False) + self.tearDownFont() + + def testLib(self): + self.setUpFont(doLib=True) + otherResults = self.compareToUFO() + self.assertEqual(otherResults["info"], False) + self.assertEqual(otherResults["kerning"], False) + self.assertEqual(otherResults["groups"], False) + self.assertEqual(otherResults["features"], False) + self.assertEqual(otherResults["lib"], True) + self.tearDownFont() + + +if __name__ == "__main__": + from robofab.test.testSupport import runTests + runTests() diff --git a/misc/pylib/robofab/test/test_glifLib.py b/misc/pylib/robofab/test/test_glifLib.py new file mode 100644 index 000000000..13eca3a6a --- /dev/null +++ b/misc/pylib/robofab/test/test_glifLib.py @@ -0,0 +1,150 @@ +import os +import tempfile +import shutil +import unittest + +from robofab.test.testSupport import getDemoFontGlyphSetPath +from robofab.glifLib import GlyphSet, glyphNameToFileName, READ_MODE +from robofab.tools.glyphNameSchemes import glyphNameToShortFileName + + +GLYPHSETDIR = getDemoFontGlyphSetPath() + + +class GlyphSetTests(unittest.TestCase): + + def setUp(self): + self.dstDir = tempfile.mktemp() + os.mkdir(self.dstDir) + + def tearDown(self): + shutil.rmtree(self.dstDir) + + def testRoundTrip(self): + srcDir = GLYPHSETDIR + dstDir = self.dstDir + src = GlyphSet(srcDir) + dst = GlyphSet(dstDir) + for glyphName in src.keys(): + g = src[glyphName] + g.drawPoints(None) # load attrs + dst.writeGlyph(glyphName, g, g.drawPoints) + # compare raw file data: + for glyphName in src.keys(): + fileName = src.contents[glyphName] + org = file(os.path.join(srcDir, fileName), READ_MODE).read() + new = file(os.path.join(dstDir, fileName), READ_MODE).read() + self.assertEqual(org, new, "%r .glif file differs after round tripping" % glyphName) + + def testRebuildContents(self): + gset = GlyphSet(GLYPHSETDIR) + contents = gset.contents + gset.rebuildContents() + self.assertEqual(contents, gset.contents) + + def testReverseContents(self): + gset = GlyphSet(GLYPHSETDIR) + d = {} + for k, v in gset.getReverseContents().items(): + d[v] = k + org = {} + for k, v in gset.contents.items(): + org[k] = v.lower() + self.assertEqual(d, org) + + def testReverseContents2(self): + src = GlyphSet(GLYPHSETDIR) + dst = GlyphSet(self.dstDir) + dstMap = dst.getReverseContents() + self.assertEqual(dstMap, {}) + for glyphName in src.keys(): + g = src[glyphName] + g.drawPoints(None) # load attrs + dst.writeGlyph(glyphName, g, g.drawPoints) + self.assertNotEqual(dstMap, {}) + srcMap = dict(src.getReverseContents()) # copy + self.assertEqual(dstMap, srcMap) + del srcMap["a.glif"] + dst.deleteGlyph("a") + self.assertEqual(dstMap, srcMap) + + def testCustomFileNamingScheme(self): + def myGlyphNameToFileName(glyphName, glyphSet): + return "prefix" + glyphNameToFileName(glyphName, glyphSet) + src = GlyphSet(GLYPHSETDIR) + dst = GlyphSet(self.dstDir, myGlyphNameToFileName) + for glyphName in src.keys(): + g = src[glyphName] + g.drawPoints(None) # load attrs + dst.writeGlyph(glyphName, g, g.drawPoints) + d = {} + for k, v in src.contents.items(): + print k, v + d[k] = "prefix" + v + self.assertEqual(d, dst.contents) + + def testGetUnicodes(self): + src = GlyphSet(GLYPHSETDIR) + unicodes = src.getUnicodes() + for glyphName in src.keys(): + g = src[glyphName] + g.drawPoints(None) # load attrs + if not hasattr(g, "unicodes"): + self.assertEqual(unicodes[glyphName], []) + else: + self.assertEqual(g.unicodes, unicodes[glyphName]) + + +class FileNameTests(unittest.TestCase): + + def testDefaultFileNameScheme(self): + self.assertEqual(glyphNameToFileName("a", None), "a.glif") + self.assertEqual(glyphNameToFileName("A", None), "A_.glif") + self.assertEqual(glyphNameToFileName("Aring", None), "Aring_.glif") + self.assertEqual(glyphNameToFileName("F_A_B", None), "F__A__B_.glif") + self.assertEqual(glyphNameToFileName("A.alt", None), "A_.alt.glif") + self.assertEqual(glyphNameToFileName("A.Alt", None), "A_.Alt_.glif") + self.assertEqual(glyphNameToFileName(".notdef", None), "_notdef.glif") + self.assertEqual(glyphNameToFileName("T_H", None), "T__H_.glif") + self.assertEqual(glyphNameToFileName("T_h", None), "T__h.glif") + self.assertEqual(glyphNameToFileName("t_h", None), "t_h.glif") + self.assertEqual(glyphNameToFileName('F_F_I', None), "F__F__I_.glif") + self.assertEqual(glyphNameToFileName('f_f_i', None), "f_f_i.glif") + + + def testShortFileNameScheme(self): + print "testShortFileNameScheme" + self.assertEqual(glyphNameToShortFileName("a", None), "a.glif") + self.assertEqual(glyphNameToShortFileName("A", None), "A_.glif") + self.assertEqual(glyphNameToShortFileName("aE", None), "aE_.glif") + self.assertEqual(glyphNameToShortFileName("AE", None), "A_E_.glif") + self.assertEqual(glyphNameToShortFileName("a.alt", None), "a_alt.glif") + self.assertEqual(glyphNameToShortFileName("A.alt", None), "A__alt.glif") + self.assertEqual(glyphNameToShortFileName("a.alt#swash", None), "a_alt_swash.glif") + self.assertEqual(glyphNameToShortFileName("A.alt", None), "A__alt.glif") + self.assertEqual(glyphNameToShortFileName(".notdef", None), "_notdef.glif") + self.assertEqual(glyphNameToShortFileName("f_f_i", None), "f_f_i.glif") + self.assertEqual(glyphNameToShortFileName("F_F_I", None), "F__F__I_.glif") + self.assertEqual(glyphNameToShortFileName("acircumflexdieresis.swash.alt1", None), "acircumflexdieresi0cfc8352.glif") + self.assertEqual(glyphNameToShortFileName("acircumflexdieresis.swash.alt2", None), "acircumflexdieresi95f5d2e8.glif") + self.assertEqual(glyphNameToShortFileName("Acircumflexdieresis.swash.alt1", None), "A_circumflexdieresed24fb56.glif") + self.assertEqual(glyphNameToShortFileName("F#weight0.800_width0.425", None), "F__weight0_800_width0_425.glif") + self.assertEqual(glyphNameToShortFileName("F#weight0.83245511_width0.425693567", None), "F__weight0_8324551c9a4143c.glif") + self.assertEqual(len(glyphNameToShortFileName("F#weight0.83245511_width0.425693567", None)), 31) + + def testShortFileNameScheme_clashes(self): + # test for the condition in code.robofab.com ticket #5 + name1 = glyphNameToShortFileName('Adieresis', None) + name2 = glyphNameToShortFileName('a_dieresis', None) + self.assertNotEqual(name1, name2) + name1 = glyphNameToShortFileName('AE', None) + name2 = glyphNameToShortFileName('aE', None) + self.assertNotEqual(name1, name2) + + +if __name__ == "__main__": + from robofab.test.testSupport import runTests + import sys + if len(sys.argv) > 1 and os.path.isdir(sys.argv[-1]): + GLYPHSETDIR = sys.argv.pop() + runTests() diff --git a/misc/pylib/robofab/test/test_noneLabUFOReadWrite.py b/misc/pylib/robofab/test/test_noneLabUFOReadWrite.py new file mode 100644 index 000000000..36dcc0582 --- /dev/null +++ b/misc/pylib/robofab/test/test_noneLabUFOReadWrite.py @@ -0,0 +1,321 @@ +import os +import shutil +import unittest +import tempfile +from robofab.plistlib import readPlist +import robofab +from robofab.test.testSupport import fontInfoVersion2, expectedFontInfo1To2Conversion, expectedFontInfo2To1Conversion +from robofab.objects.objectsRF import NewFont, OpenFont +from robofab.ufoLib import UFOReader + +ufoPath1 = os.path.dirname(robofab.__file__) +ufoPath1 = os.path.dirname(ufoPath1) +ufoPath1 = os.path.dirname(ufoPath1) +ufoPath1 = os.path.join(ufoPath1, "TestData", "TestFont1 (UFO1).ufo") +ufoPath2 = ufoPath1.replace("TestFont1 (UFO1).ufo", "TestFont1 (UFO2).ufo") + +# robofab should remove these from the lib after a load. +removeFromFormatVersion1Lib = [ + "org.robofab.opentype.classes", + "org.robofab.opentype.features", + "org.robofab.opentype.featureorder", + "org.robofab.postScriptHintData" +] + + +class ReadUFOFormatVersion1TestCase(unittest.TestCase): + + def setUpFont(self): + self.font = OpenFont(ufoPath1) + self.font.update() + + def tearDownFont(self): + self.font.close() + self.font = None + + def compareToUFO(self, doInfo=True): + reader = UFOReader(ufoPath1) + results = {} + # info + infoMatches = True + info = self.font.info + for attr, expectedValue in expectedFontInfo1To2Conversion.items(): + writtenValue = getattr(info, attr) + if expectedValue != writtenValue: + infoMatches = False + break + results["info"]= infoMatches + # kerning + kerning = self.font.kerning.asDict() + expectedKerning = reader.readKerning() + results["kerning"] = expectedKerning == kerning + # groups + groups = dict(self.font.groups) + expectedGroups = reader.readGroups() + results["groups"] = expectedGroups == groups + # features + features = self.font.features.text + f = open(os.path.join(ufoPath2, "features.fea"), "r") + expectedFeatures = f.read() + f.close() + match = True + features = [line for line in features.splitlines() if line] + expectedFeatures = [line for line in expectedFeatures.splitlines() if line] + if expectedFeatures != features or reader.readFeatures() != "": + match = False + results["features"] = match + # lib + lib = dict(self.font.lib) + expectedLib = reader.readLib() + for key in removeFromFormatVersion1Lib: + if key in expectedLib: + del expectedLib[key] + results["lib"] = expectedLib == lib + return results + + def testFull(self): + self.setUpFont() + otherResults = self.compareToUFO() + self.assertEqual(otherResults["info"], True) + self.assertEqual(otherResults["kerning"], True) + self.assertEqual(otherResults["groups"], True) + self.assertEqual(otherResults["features"], True) + self.assertEqual(otherResults["lib"], True) + self.tearDownFont() + + def testInfo(self): + self.setUpFont() + info = self.font.info + for attr, expectedValue in expectedFontInfo1To2Conversion.items(): + writtenValue = getattr(info, attr) + self.assertEqual((attr, expectedValue), (attr, writtenValue)) + self.tearDownFont() + + +class ReadUFOFormatVersion2TestCase(unittest.TestCase): + + def setUpFont(self): + self.font = OpenFont(ufoPath2) + self.font.update() + + def tearDownFont(self): + self.font.close() + self.font = None + + def compareToUFO(self, doInfo=True): + reader = UFOReader(ufoPath2) + results = {} + # info + infoMatches = True + info = self.font.info + for attr, expectedValue in fontInfoVersion2.items(): + writtenValue = getattr(info, attr) + if expectedValue != writtenValue: + infoMatches = False + break + results["info"]= infoMatches + # kerning + kerning = self.font.kerning.asDict() + expectedKerning = reader.readKerning() + results["kerning"] = expectedKerning == kerning + # groups + groups = dict(self.font.groups) + expectedGroups = reader.readGroups() + results["groups"] = expectedGroups == groups + # features + features = self.font.features.text + expectedFeatures = reader.readFeatures() + results["features"] = expectedFeatures == features + # lib + lib = dict(self.font.lib) + expectedLib = reader.readLib() + results["lib"] = expectedLib == lib + return results + + def testFull(self): + self.setUpFont() + otherResults = self.compareToUFO() + self.assertEqual(otherResults["info"], True) + self.assertEqual(otherResults["kerning"], True) + self.assertEqual(otherResults["groups"], True) + self.assertEqual(otherResults["features"], True) + self.assertEqual(otherResults["lib"], True) + self.tearDownFont() + + def testInfo(self): + self.setUpFont() + info = self.font.info + for attr, expectedValue in fontInfoVersion2.items(): + writtenValue = getattr(info, attr) + self.assertEqual((attr, expectedValue), (attr, writtenValue)) + self.tearDownFont() + + +class WriteUFOFormatVersion1TestCase(unittest.TestCase): + + def setUpFont(self): + self.dstDir = tempfile.mktemp() + os.mkdir(self.dstDir) + self.font = OpenFont(ufoPath2) + self.font.save(self.dstDir, formatVersion=1) + + def tearDownFont(self): + shutil.rmtree(self.dstDir) + + def compareToUFO(self): + readerExpected = UFOReader(ufoPath1) + readerWritten = UFOReader(self.dstDir) + results = {} + # info + matches = True + expectedPath = os.path.join(ufoPath1, "fontinfo.plist") + writtenPath = os.path.join(self.dstDir, "fontinfo.plist") + if not os.path.exists(writtenPath): + matches = False + else: + expected = readPlist(expectedPath) + written = readPlist(writtenPath) + for attr, expectedValue in expected.items(): + if expectedValue != written.get(attr): + matches = False + break + results["info"] = matches + # kerning + matches = True + expectedPath = os.path.join(ufoPath1, "kerning.plist") + writtenPath = os.path.join(self.dstDir, "kerning.plist") + if not os.path.exists(writtenPath): + matches = False + else: + matches = readPlist(expectedPath) == readPlist(writtenPath) + results["kerning"] = matches + # groups + matches = True + expectedPath = os.path.join(ufoPath1, "groups.plist") + writtenPath = os.path.join(self.dstDir, "groups.plist") + if not os.path.exists(writtenPath): + matches = False + else: + matches = readPlist(expectedPath) == readPlist(writtenPath) + results["groups"] = matches + # features + matches = True + expectedPath = os.path.join(ufoPath1, "features.fea") + writtenPath = os.path.join(self.dstDir, "features.fea") + if os.path.exists(writtenPath): + matches = False + results["features"] = matches + # lib + matches = True + expectedPath = os.path.join(ufoPath1, "lib.plist") + writtenPath = os.path.join(self.dstDir, "lib.plist") + if not os.path.exists(writtenPath): + matches = False + else: + writtenLib = readPlist(writtenPath) + matches = readPlist(expectedPath) == writtenLib + results["lib"] = matches + return results + + def testFull(self): + self.setUpFont() + otherResults = self.compareToUFO() + self.assertEqual(otherResults["info"], True) + self.assertEqual(otherResults["kerning"], True) + self.assertEqual(otherResults["groups"], True) + self.assertEqual(otherResults["features"], True) + self.assertEqual(otherResults["lib"], True) + self.tearDownFont() + + +class WriteUFOFormatVersion2TestCase(unittest.TestCase): + + def setUpFont(self): + self.dstDir = tempfile.mktemp() + os.mkdir(self.dstDir) + self.font = OpenFont(ufoPath2) + self.font.save(self.dstDir) + + def tearDownFont(self): + shutil.rmtree(self.dstDir) + + def compareToUFO(self): + readerExpected = UFOReader(ufoPath2) + readerWritten = UFOReader(self.dstDir) + results = {} + # info + matches = True + expectedPath = os.path.join(ufoPath2, "fontinfo.plist") + writtenPath = os.path.join(self.dstDir, "fontinfo.plist") + if not os.path.exists(writtenPath): + matches = False + else: + expected = readPlist(expectedPath) + written = readPlist(writtenPath) + for attr, expectedValue in expected.items(): + if expectedValue != written[attr]: + matches = False + break + results["info"] = matches + # kerning + matches = True + expectedPath = os.path.join(ufoPath2, "kerning.plist") + writtenPath = os.path.join(self.dstDir, "kerning.plist") + if not os.path.exists(writtenPath): + matches = False + else: + matches = readPlist(expectedPath) == readPlist(writtenPath) + results["kerning"] = matches + # groups + matches = True + expectedPath = os.path.join(ufoPath2, "groups.plist") + writtenPath = os.path.join(self.dstDir, "groups.plist") + if not os.path.exists(writtenPath): + matches = False + else: + matches = readPlist(expectedPath) == readPlist(writtenPath) + results["groups"] = matches + # features + matches = True + expectedPath = os.path.join(ufoPath2, "features.fea") + writtenPath = os.path.join(self.dstDir, "features.fea") + if not os.path.exists(writtenPath): + matches = False + else: + f = open(expectedPath, "r") + expectedText = f.read() + f.close() + f = open(writtenPath, "r") + writtenText = f.read() + f.close() + # FontLab likes to add lines to the features, so skip blank lines. + expectedText = [line for line in expectedText.splitlines() if line] + writtenText = [line for line in writtenText.splitlines() if line] + matches = "\n".join(expectedText) == "\n".join(writtenText) + results["features"] = matches + # lib + matches = True + expectedPath = os.path.join(ufoPath2, "lib.plist") + writtenPath = os.path.join(self.dstDir, "lib.plist") + if not os.path.exists(writtenPath): + matches = False + else: + writtenLib = readPlist(writtenPath) + matches = readPlist(expectedPath) == writtenLib + results["lib"] = matches + return results + + def testFull(self): + self.setUpFont() + otherResults = self.compareToUFO() + self.assertEqual(otherResults["info"], True) + self.assertEqual(otherResults["kerning"], True) + self.assertEqual(otherResults["groups"], True) + self.assertEqual(otherResults["features"], True) + self.assertEqual(otherResults["lib"], True) + self.tearDownFont() + + +if __name__ == "__main__": + from robofab.test.testSupport import runTests + runTests() diff --git a/misc/pylib/robofab/test/test_objectsFL.py b/misc/pylib/robofab/test/test_objectsFL.py new file mode 100755 index 000000000..948897097 --- /dev/null +++ b/misc/pylib/robofab/test/test_objectsFL.py @@ -0,0 +1,54 @@ +"""This test suite for various FontLab-specific tests.""" + + +import FL # needed to quickly raise ImportError if run outside of FL + + +import os +import tempfile +import unittest + +from robofab.world import NewFont +from robofab.test.testSupport import getDemoFontPath, getDemoFontGlyphSetPath +from robofab.tools.glifImport import importAllGlifFiles +from robofab.pens.digestPen import DigestPointPen +from robofab.pens.adapterPens import SegmentToPointPen + + +def getDigests(font): + digests = {} + for glyphName in font.keys(): + pen = DigestPointPen() + font[glyphName].drawPoints(pen) + digests[glyphName] = pen.getDigest() + return digests + + +class FLTestCase(unittest.TestCase): + + def testUFOVersusGlifImport(self): + font = NewFont() + font.readUFO(getDemoFontPath(), doProgress=False) + d1 = getDigests(font) + font.close(False) + font = NewFont() + importAllGlifFiles(font.naked(), getDemoFontGlyphSetPath(), doProgress=False) + d2 = getDigests(font) + self.assertEqual(d1, d2) + font.close(False) + + def testTwoUntitledFonts(self): + font1 = NewFont() + font2 = NewFont() + font1.unitsPerEm = 1024 + font2.unitsPerEm = 2048 + self.assertNotEqual(font1.unitsPerEm, font2.unitsPerEm) + font1.update() + font2.update() + font1.close(False) + font2.close(False) + + +if __name__ == "__main__": + from robofab.test.testSupport import runTests + runTests() diff --git a/misc/pylib/robofab/test/test_objectsUFO.py b/misc/pylib/robofab/test/test_objectsUFO.py new file mode 100755 index 000000000..c974a121c --- /dev/null +++ b/misc/pylib/robofab/test/test_objectsUFO.py @@ -0,0 +1,203 @@ +"""This test suite for ufo glyph methods""" + + +import unittest +import os +import tempfile +import shutil + +from robofab.objects.objectsRF import RFont +from robofab.test.testSupport import getDemoFontPath +from robofab.pens.digestPen import DigestPointPen +from robofab.pens.adapterPens import SegmentToPointPen, FabToFontToolsPenAdapter + + +class ContourMethodsTestCase(unittest.TestCase): + + def setUp(self): + self.font = RFont(getDemoFontPath()) + + def testReverseContour(self): + for glyph in self.font: + pen = DigestPointPen() + glyph.drawPoints(pen) + digest1 = pen.getDigest() + for contour in glyph: + contour.reverseContour() + contour.reverseContour() + pen = DigestPointPen() + glyph.drawPoints(pen) + digest2 = pen.getDigest() + self.assertEqual(digest1, digest2, "%r not the same after reversing twice" % glyph.name) + + def testStartSegment(self): + for glyph in self.font: + pen = DigestPointPen() + glyph.drawPoints(pen) + digest1 = pen.getDigest() + for contour in glyph: + contour.setStartSegment(2) + contour.setStartSegment(-2) + pen = DigestPointPen() + glyph.drawPoints(pen) + digest2 = pen.getDigest() + self.assertEqual(digest1, digest2, "%r not the same after seting start segment twice" % glyph.name) + + def testAppendSegment(self): + for glyph in self.font: + pen = DigestPointPen() + glyph.drawPoints(pen) + digest1 = pen.getDigest() + for contour in glyph: + contour.insertSegment(2, "curve", [(100, 100), (200, 200), (300, 300)]) + contour.removeSegment(2) + pen = DigestPointPen() + glyph.drawPoints(pen) + digest2 = pen.getDigest() + self.assertEqual(digest1, digest2, "%r not the same after inserting and removing segment" % glyph.name) + + +class GlyphsMethodsTestCase(ContourMethodsTestCase): + + def testCopyGlyph(self): + for glyph in self.font: + pen = DigestPointPen() + glyph.drawPoints(pen) + digest1 = pen.getDigest() + copy = glyph.copy() + pen = DigestPointPen() + copy.drawPoints(pen) + digest2 = pen.getDigest() + self.assertEqual(digest1, digest2, "%r not the same after copying" % glyph.name) + self.assertEqual(glyph.lib, copy.lib, "%r's lib not the same after copying" % glyph.name) + self.assertEqual(glyph.width, copy.width, "%r's width not the same after copying" % glyph.name) + self.assertEqual(glyph.unicodes, copy.unicodes, "%r's unicodes not the same after copying" % glyph.name) + + def testMoveGlyph(self): + for glyph in self.font: + pen = DigestPointPen() + glyph.drawPoints(pen) + digest1 = pen.getDigest() + glyph.move((100, 200)) + glyph.move((-100, -200)) + pen = DigestPointPen() + glyph.drawPoints(pen) + digest2 = pen.getDigest() + self.assertEqual(digest1, digest2, "%r not the same after moving twice" % glyph.name) + + def testScaleGlyph(self): + for glyph in self.font: + pen = DigestPointPen() + glyph.drawPoints(pen) + digest1 = pen.getDigest() + glyph.scale((2, 2)) + glyph.scale((.5, .5)) + pen = DigestPointPen() + glyph.drawPoints(pen) + digest2 = pen.getDigest() + self.assertEqual(digest1, digest2, "%r not the same after scaling twice" % glyph.name) + + def testSegmentPenInterface(self): + for glyph in self.font: + digestPen = DigestPointPen(ignoreSmoothAndName=True) + pen = SegmentToPointPen(digestPen) + glyph.draw(pen) + digest1 = digestPen.getDigest() + digestPen = DigestPointPen(ignoreSmoothAndName=True) + glyph.drawPoints(digestPen) + digest2 = digestPen.getDigest() + self.assertEqual(digest1, digest2, "%r not the same for gl.draw() and gl.drawPoints()" % glyph.name) + + def testFabPenCompatibility(self): + for glyph in self.font: + digestPen = DigestPointPen(ignoreSmoothAndName=True) + pen = FabToFontToolsPenAdapter(SegmentToPointPen(digestPen)) + glyph.draw(pen) + digest1 = digestPen.getDigest() + digestPen = DigestPointPen(ignoreSmoothAndName=True) + glyph.drawPoints(digestPen) + digest2 = digestPen.getDigest() + self.assertEqual(digest1, digest2, "%r not the same for gl.draw() and gl.drawPoints()" % glyph.name) + + def testComponentTransformations(self): + from robofab.objects.objectsRF import RComponent + name = "baseGlyphName" + c = RComponent(name, transform=(1,0,0,1,0,0)) + # get values + assert c.baseGlyph == "baseGlyphName" + assert c.transformation == c.transformation + assert c.scale == (1,1) + assert c.offset == (0,0) + # set values + c.offset = (12,34) + assert c.transformation == (1, 0, 0, 1, 12, 34) + c.offset = (0,0) + assert c.transformation == (1,0,0,1,0,0) + c.scale = (12,34) + assert c.transformation == (12, 0, 0, 34, 0, 0) + + +class SaveTestCase(ContourMethodsTestCase): + + def testSaveAs(self): + path = tempfile.mktemp(".ufo") + try: + keys1 = self.font.keys() + self.font.save(path) + keys2 = self.font.keys() + keys1.sort() + keys2.sort() + self.assertEqual(keys1, keys2) + self.assertEqual(self.font.path, path) + font2 = RFont(path) + keys3 = font2.keys() + keys3.sort() + self.assertEqual(keys1, keys3) + finally: + if os.path.exists(path): + shutil.rmtree(path) + + def testSaveAs2(self): + path = tempfile.mktemp(".ufo") + # copy a glyph + self.font["X"] = self.font["a"].copy() +# self.assertEqual(self.font["X"].name, "X") + # remove a glyph + self.font.removeGlyph("a") + keys1 = self.font.keys() + try: + self.font.save(path) + self.assertEqual(self.font.path, path) + keys2 = self.font.keys() + keys1.sort() + keys2.sort() + self.assertEqual(keys1, keys2) + font2 = RFont(path) + keys3 = font2.keys() + keys3.sort() + self.assertEqual(keys1, keys3) + finally: + if os.path.exists(path): + shutil.rmtree(path) + + def testCustomFileNameScheme(self): + path = tempfile.mktemp(".ufo") + libKey = "org.robofab.glyphNameToFileNameFuncName" + self.font.lib[libKey] = "robofab.test.test_objectsUFO.testGlyphNameToFileName" + try: + self.font.save(path) + self.assertEqual(os.path.exists(os.path.join(path, + "glyphs", "test_a.glif")), True) + finally: + if os.path.exists(path): + shutil.rmtree(path) + + +def testGlyphNameToFileName(glyphName, glyphSet): + from robofab.glifLib import glyphNameToFileName + return "test_" + glyphNameToFileName(glyphName, glyphSet) + + +if __name__ == "__main__": + from robofab.test.testSupport import runTests + runTests() diff --git a/misc/pylib/robofab/test/test_pens.py b/misc/pylib/robofab/test/test_pens.py new file mode 100755 index 000000000..a2a773cb2 --- /dev/null +++ b/misc/pylib/robofab/test/test_pens.py @@ -0,0 +1,149 @@ +"""This test suite test general Pen stuff, it should not contain +FontLab-specific code. +""" + +import unittest + +from robofab.pens.digestPen import DigestPointPen +from robofab.pens.adapterPens import SegmentToPointPen, PointToSegmentPen +from robofab.pens.adapterPens import GuessSmoothPointPen +from robofab.pens.reverseContourPointPen import ReverseContourPointPen +from robofab.test.testSupport import getDemoFontGlyphSetPath +from robofab.glifLib import GlyphSet + + +class TestShapes: + + # Collection of test shapes. It's probably better to add these as + # glyphs to the demo font. + + def square(pen): + # a simple square as a closed path (100, 100, 600, 600) + pen.beginPath() + pen.addPoint((100, 100), "line") + pen.addPoint((100, 600), "line") + pen.addPoint((600, 600), "line") + pen.addPoint((600, 100), "line") + pen.endPath() + square = staticmethod(square) + + def onCurveLessQuadShape(pen): + pen.beginPath() + pen.addPoint((100, 100)) + pen.addPoint((100, 600)) + pen.addPoint((600, 600)) + pen.addPoint((600, 100)) + pen.endPath() + onCurveLessQuadShape = staticmethod(onCurveLessQuadShape) + + def openPath(pen): + # a simple square as a closed path (100, 100, 600, 600) + pen.beginPath() + pen.addPoint((100, 100), "move") + pen.addPoint((100, 600), "line") + pen.addPoint((600, 600), "line") + pen.addPoint((600, 100), "line") + pen.endPath() + openPath = staticmethod(openPath) + + def circle(pen): + pen.beginPath() + pen.addPoint((0, 500), "curve") + pen.addPoint((0, 800)) + pen.addPoint((200, 1000)) + pen.addPoint((500, 1000), "curve") + pen.addPoint((800, 1000)) + pen.addPoint((1000, 800)) + pen.addPoint((1000, 500), "curve") + pen.addPoint((1000, 200)) + pen.addPoint((800, 0)) + pen.addPoint((500, 0), "curve") + pen.addPoint((200, 0)) + pen.addPoint((0, 200)) + pen.endPath() + circle = staticmethod(circle) + + +class RoundTripTestCase(unittest.TestCase): + + def _doTest(self, shapeFunc, shapeName): + pen = DigestPointPen(ignoreSmoothAndName=True) + shapeFunc(pen) + digest1 = pen.getDigest() + + digestPen = DigestPointPen(ignoreSmoothAndName=True) + pen = PointToSegmentPen(SegmentToPointPen(digestPen)) + shapeFunc(pen) + digest2 = digestPen.getDigest() + self.assertEqual(digest1, digest2, "%r failed round tripping" % shapeName) + + def testShapes(self): + for name in dir(TestShapes): + if name[0] != "_": + self._doTest(getattr(TestShapes, name), name) + + def testShapesFromGlyphSet(self): + glyphSet = GlyphSet(getDemoFontGlyphSetPath()) + for name in glyphSet.keys(): + self._doTest(glyphSet[name].drawPoints, name) + + def testGuessSmoothPen(self): + glyphSet = GlyphSet(getDemoFontGlyphSetPath()) + for name in glyphSet.keys(): + digestPen = DigestPointPen() + glyphSet[name].drawPoints(digestPen) + digest1 = digestPen.getDigest() + digestPen = DigestPointPen() + pen = GuessSmoothPointPen(digestPen) + glyphSet[name].drawPoints(pen) + digest2 = digestPen.getDigest() + self.assertEqual(digest1, digest2) + + +class ReverseContourTestCase(unittest.TestCase): + + def testReverseContourClosedPath(self): + digestPen = DigestPointPen() + TestShapes.square(digestPen) + d1 = digestPen.getDigest() + digestPen = DigestPointPen() + pen = ReverseContourPointPen(digestPen) + pen.beginPath() + pen.addPoint((100, 100), "line") + pen.addPoint((600, 100), "line") + pen.addPoint((600, 600), "line") + pen.addPoint((100, 600), "line") + pen.endPath() + d2 = digestPen.getDigest() + self.assertEqual(d1, d2) + + def testReverseContourOpenPath(self): + digestPen = DigestPointPen() + TestShapes.openPath(digestPen) + d1 = digestPen.getDigest() + digestPen = DigestPointPen() + pen = ReverseContourPointPen(digestPen) + pen.beginPath() + pen.addPoint((600, 100), "move") + pen.addPoint((600, 600), "line") + pen.addPoint((100, 600), "line") + pen.addPoint((100, 100), "line") + pen.endPath() + d2 = digestPen.getDigest() + self.assertEqual(d1, d2) + + def testReversContourFromGlyphSet(self): + glyphSet = GlyphSet(getDemoFontGlyphSetPath()) + digestPen = DigestPointPen() + glyphSet["testglyph1"].drawPoints(digestPen) + digest1 = digestPen.getDigest() + digestPen = DigestPointPen() + pen = ReverseContourPointPen(digestPen) + glyphSet["testglyph1.reversed"].drawPoints(pen) + digest2 = digestPen.getDigest() + self.assertEqual(digest1, digest2) + + +if __name__ == "__main__": + from robofab.test.testSupport import runTests + runTests() diff --git a/misc/pylib/robofab/test/test_psHints.py b/misc/pylib/robofab/test/test_psHints.py new file mode 100644 index 000000000..991e9d9cc --- /dev/null +++ b/misc/pylib/robofab/test/test_psHints.py @@ -0,0 +1,110 @@ +def test(): + """ + # some tests for the ps Hints operations + >>> from robofab.world import RFont, RGlyph + >>> g = RGlyph() + >>> g.psHints.isEmpty() + True + + >>> h = RGlyph() + >>> i = g + h + >>> i.psHints.isEmpty() + True + + >>> i = g - h + >>> i.psHints.isEmpty() + True + + >>> i = g * 2 + >>> i.psHints.isEmpty() + True + + >>> i = g / 2 + >>> i.psHints.isEmpty() + True + + >>> g.psHints.vHints = [(100, 50), (200, 50)] + >>> g.psHints.hHints = [(100, 50), (200, 5)] + + >>> not g.psHints.isEmpty() + True + + >>> gc = g.copy() + >>> gc.psHints.asDict() == g.psHints.asDict() + True + + # multiplication + >>> v = g.psHints * 2 + >>> v.asDict() == {'vHints': [[200, 100], [400, 100]], 'hHints': [[200, 100], [400, 10]]} + True + + # division + >>> v = g.psHints / 2 + >>> v.asDict() == {'vHints': [[50.0, 25.0], [100.0, 25.0]], 'hHints': [[50.0, 25.0], [100.0, 2.5]]} + True + + # multiplication with x, y, factor + # vertically oriented values should respond different + >>> v = g.psHints * (.5, 10) + >>> v.asDict() == {'vHints': [[1000, 500], [2000, 500]], 'hHints': [[50.0, 25.0], [100.0, 2.5]]} + True + + # division with x, y, factor + # vertically oriented values should respond different + >>> v = g.psHints / (.5, 10) + >>> v.asDict() == {'vHints': [[10.0, 5.0], [20.0, 5.0]], 'hHints': [[200.0, 100.0], [400.0, 10.0]]} + True + + # rounding to integer + >>> v = g.psHints / 2 + >>> v.round() + >>> v.asDict() == {'vHints': [(50, 25), (100, 25)], 'hHints': [(50, 25), (100, 3)]} + True + + # "ps hint values calculating with a glyph" + # ps hint values as part of glyphmath operations. + # multiplication + >>> h = g * 10 + >>> h.psHints.asDict() == {'vHints': [[1000, 500], [2000, 500]], 'hHints': [[1000, 500], [2000, 50]]} + True + + # division + >>> h = g / 2 + >>> h.psHints.asDict() == {'vHints': [[50.0, 25.0], [100.0, 25.0]], 'hHints': [[50.0, 25.0], [100.0, 2.5]]} + True + + # x, y factor multiplication + >>> h = g * (.5, 10) + >>> h.psHints.asDict() == {'vHints': [[1000, 500], [2000, 500]], 'hHints': [[50.0, 25.0], [100.0, 2.5]]} + True + + # x, y factor division + >>> h = g / (.5, 10) + >>> h.psHints.asDict() == {'vHints': [[10.0, 5.0], [20.0, 5.0]], 'hHints': [[200.0, 100.0], [400.0, 10.0]]} + True + + # "font ps hint values" + >>> f = RFont() + >>> f.psHints.isEmpty() + True + + >>> f.psHints.blueScale = .5 + >>> f.psHints.blueShift = 1 + >>> f.psHints.blueFuzz = 1 + >>> f.psHints.forceBold = True + >>> f.psHints.hStems = (100, 90) + >>> f.psHints.vStems = (500, 10) + + >>> not f.psHints.isEmpty() + True + + >>> f.insertGlyph(g, name="new") + <RGlyph for None.new> + >>> f["new"].psHints.asDict() == g.psHints.asDict() + True + """ + +if __name__ == "__main__": + import doctest + doctest.testmod() + diff --git a/misc/pylib/robofab/test/test_ufoLib.py b/misc/pylib/robofab/test/test_ufoLib.py new file mode 100644 index 000000000..e1da807bb --- /dev/null +++ b/misc/pylib/robofab/test/test_ufoLib.py @@ -0,0 +1,1659 @@ +import os +import shutil +import unittest +import tempfile +from plistlib import writePlist, readPlist +from robofab.ufoLib import UFOReader, UFOWriter, UFOLibError, \ + convertUFOFormatVersion1ToFormatVersion2, convertUFOFormatVersion2ToFormatVersion1 +from robofab.test.testSupport import fontInfoVersion1, fontInfoVersion2, 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 TestInfoObject(object): pass + + +class ReadFontInfoVersion1TestCase(unittest.TestCase): + + def setUp(self): + self.dstDir = tempfile.mktemp() + os.mkdir(self.dstDir) + metaInfo = { + "creator": "test", + "formatVersion": 1 + } + path = os.path.join(self.dstDir, "metainfo.plist") + writePlist(metaInfo, path) + + def tearDown(self): + shutil.rmtree(self.dstDir) + + def _writeInfoToPlist(self, info): + path = os.path.join(self.dstDir, "fontinfo.plist") + writePlist(info, path) + + def testRead(self): + originalData = dict(fontInfoVersion1) + self._writeInfoToPlist(originalData) + infoObject = TestInfoObject() + reader = UFOReader(self.dstDir) + reader.readInfo(infoObject) + for attr in dir(infoObject): + if attr not in fontInfoVersion2: + continue + originalValue = fontInfoVersion2[attr] + readValue = getattr(infoObject, attr) + self.assertEqual(originalValue, readValue) + + def testFontStyleConversion(self): + fontStyle1To2 = { + 64 : "regular", + 1 : "italic", + 32 : "bold", + 33 : "bold italic" + } + for old, new in fontStyle1To2.items(): + info = dict(fontInfoVersion1) + info["fontStyle"] = old + self._writeInfoToPlist(info) + reader = UFOReader(self.dstDir) + infoObject = TestInfoObject() + reader.readInfo(infoObject) + self.assertEqual(new, infoObject.styleMapStyleName) + + def testWidthNameConversion(self): + widthName1To2 = { + "Ultra-condensed" : 1, + "Extra-condensed" : 2, + "Condensed" : 3, + "Semi-condensed" : 4, + "Medium (normal)" : 5, + "Semi-expanded" : 6, + "Expanded" : 7, + "Extra-expanded" : 8, + "Ultra-expanded" : 9 + } + for old, new in widthName1To2.items(): + info = dict(fontInfoVersion1) + info["widthName"] = old + self._writeInfoToPlist(info) + reader = UFOReader(self.dstDir) + infoObject = TestInfoObject() + reader.readInfo(infoObject) + self.assertEqual(new, infoObject.openTypeOS2WidthClass) + + +class ReadFontInfoVersion2TestCase(unittest.TestCase): + + def setUp(self): + self.dstDir = tempfile.mktemp() + os.mkdir(self.dstDir) + metaInfo = { + "creator": "test", + "formatVersion": 2 + } + path = os.path.join(self.dstDir, "metainfo.plist") + writePlist(metaInfo, path) + + def tearDown(self): + shutil.rmtree(self.dstDir) + + def _writeInfoToPlist(self, info): + path = os.path.join(self.dstDir, "fontinfo.plist") + writePlist(info, path) + + def testRead(self): + originalData = dict(fontInfoVersion2) + self._writeInfoToPlist(originalData) + infoObject = TestInfoObject() + reader = UFOReader(self.dstDir) + reader.readInfo(infoObject) + readData = {} + for attr in fontInfoVersion2.keys(): + readData[attr] = getattr(infoObject, attr) + self.assertEqual(originalData, readData) + + def testGenericRead(self): + # familyName + info = dict(fontInfoVersion2) + info["familyName"] = 123 + self._writeInfoToPlist(info) + reader = UFOReader(self.dstDir) + self.assertRaises(UFOLibError, reader.readInfo, info=TestInfoObject()) + # styleName + info = dict(fontInfoVersion2) + info["styleName"] = 123 + self._writeInfoToPlist(info) + reader = UFOReader(self.dstDir) + self.assertRaises(UFOLibError, reader.readInfo, info=TestInfoObject()) + # styleMapFamilyName + info = dict(fontInfoVersion2) + info["styleMapFamilyName"] = 123 + self._writeInfoToPlist(info) + reader = UFOReader(self.dstDir) + self.assertRaises(UFOLibError, reader.readInfo, info=TestInfoObject()) + # styleMapStyleName + ## not a string + info = dict(fontInfoVersion2) + info["styleMapStyleName"] = 123 + self._writeInfoToPlist(info) + reader = UFOReader(self.dstDir) + self.assertRaises(UFOLibError, reader.readInfo, info=TestInfoObject()) + ## out of range + info = dict(fontInfoVersion2) + info["styleMapStyleName"] = "REGULAR" + self._writeInfoToPlist(info) + reader = UFOReader(self.dstDir) + self.assertRaises(UFOLibError, reader.readInfo, info=TestInfoObject()) + # versionMajor + info = dict(fontInfoVersion2) + info["versionMajor"] = "1" + self._writeInfoToPlist(info) + reader = UFOReader(self.dstDir) + self.assertRaises(UFOLibError, reader.readInfo, info=TestInfoObject()) + # versionMinor + info = dict(fontInfoVersion2) + info["versionMinor"] = "0" + self._writeInfoToPlist(info) + reader = UFOReader(self.dstDir) + self.assertRaises(UFOLibError, reader.readInfo, info=TestInfoObject()) + # copyright + info = dict(fontInfoVersion2) + info["copyright"] = 123 + self._writeInfoToPlist(info) + reader = UFOReader(self.dstDir) + self.assertRaises(UFOLibError, reader.readInfo, info=TestInfoObject()) + # trademark + info = dict(fontInfoVersion2) + info["trademark"] = 123 + self._writeInfoToPlist(info) + reader = UFOReader(self.dstDir) + self.assertRaises(UFOLibError, reader.readInfo, info=TestInfoObject()) + # unitsPerEm + info = dict(fontInfoVersion2) + info["unitsPerEm"] = "abc" + self._writeInfoToPlist(info) + reader = UFOReader(self.dstDir) + self.assertRaises(UFOLibError, reader.readInfo, info=TestInfoObject()) + # descender + info = dict(fontInfoVersion2) + info["descender"] = "abc" + self._writeInfoToPlist(info) + reader = UFOReader(self.dstDir) + self.assertRaises(UFOLibError, reader.readInfo, info=TestInfoObject()) + # xHeight + info = dict(fontInfoVersion2) + info["xHeight"] = "abc" + self._writeInfoToPlist(info) + reader = UFOReader(self.dstDir) + self.assertRaises(UFOLibError, reader.readInfo, info=TestInfoObject()) + # capHeight + info = dict(fontInfoVersion2) + info["capHeight"] = "abc" + self._writeInfoToPlist(info) + reader = UFOReader(self.dstDir) + self.assertRaises(UFOLibError, reader.readInfo, info=TestInfoObject()) + # ascender + info = dict(fontInfoVersion2) + info["ascender"] = "abc" + self._writeInfoToPlist(info) + reader = UFOReader(self.dstDir) + self.assertRaises(UFOLibError, reader.readInfo, info=TestInfoObject()) + # italicAngle + info = dict(fontInfoVersion2) + info["italicAngle"] = "abc" + self._writeInfoToPlist(info) + reader = UFOReader(self.dstDir) + self.assertRaises(UFOLibError, reader.readInfo, info=TestInfoObject()) + + def testHeadRead(self): + # openTypeHeadCreated + ## not a string + info = dict(fontInfoVersion2) + info["openTypeHeadCreated"] = 123 + self._writeInfoToPlist(info) + reader = UFOReader(self.dstDir) + self.assertRaises(UFOLibError, reader.readInfo, info=TestInfoObject()) + ## invalid format + info = dict(fontInfoVersion2) + info["openTypeHeadCreated"] = "2000-Jan-01 00:00:00" + self._writeInfoToPlist(info) + reader = UFOReader(self.dstDir) + self.assertRaises(UFOLibError, reader.readInfo, info=TestInfoObject()) + # openTypeHeadLowestRecPPEM + info = dict(fontInfoVersion2) + info["openTypeHeadLowestRecPPEM"] = "abc" + self._writeInfoToPlist(info) + reader = UFOReader(self.dstDir) + self.assertRaises(UFOLibError, reader.readInfo, info=TestInfoObject()) + # openTypeHeadFlags + info = dict(fontInfoVersion2) + info["openTypeHeadFlags"] = [-1] + self._writeInfoToPlist(info) + reader = UFOReader(self.dstDir) + self.assertRaises(UFOLibError, reader.readInfo, info=TestInfoObject()) + + def testHheaRead(self): + # openTypeHheaAscender + info = dict(fontInfoVersion2) + info["openTypeHheaAscender"] = "abc" + self._writeInfoToPlist(info) + reader = UFOReader(self.dstDir) + self.assertRaises(UFOLibError, reader.readInfo, info=TestInfoObject()) + # openTypeHheaDescender + info = dict(fontInfoVersion2) + info["openTypeHheaDescender"] = "abc" + self._writeInfoToPlist(info) + reader = UFOReader(self.dstDir) + self.assertRaises(UFOLibError, reader.readInfo, info=TestInfoObject()) + # openTypeHheaLineGap + info = dict(fontInfoVersion2) + info["openTypeHheaLineGap"] = "abc" + self._writeInfoToPlist(info) + reader = UFOReader(self.dstDir) + self.assertRaises(UFOLibError, reader.readInfo, info=TestInfoObject()) + # openTypeHheaCaretSlopeRise + info = dict(fontInfoVersion2) + info["openTypeHheaCaretSlopeRise"] = "abc" + self._writeInfoToPlist(info) + reader = UFOReader(self.dstDir) + self.assertRaises(UFOLibError, reader.readInfo, info=TestInfoObject()) + # openTypeHheaCaretSlopeRun + info = dict(fontInfoVersion2) + info["openTypeHheaCaretSlopeRun"] = "abc" + self._writeInfoToPlist(info) + reader = UFOReader(self.dstDir) + self.assertRaises(UFOLibError, reader.readInfo, info=TestInfoObject()) + # openTypeHheaCaretOffset + info = dict(fontInfoVersion2) + info["openTypeHheaCaretOffset"] = "abc" + self._writeInfoToPlist(info) + reader = UFOReader(self.dstDir) + self.assertRaises(UFOLibError, reader.readInfo, info=TestInfoObject()) + + def testNameRead(self): + # openTypeNameDesigner + info = dict(fontInfoVersion2) + info["openTypeNameDesigner"] = 123 + self._writeInfoToPlist(info) + reader = UFOReader(self.dstDir) + self.assertRaises(UFOLibError, reader.readInfo, info=TestInfoObject()) + # openTypeNameDesignerURL + info = dict(fontInfoVersion2) + info["openTypeNameDesignerURL"] = 123 + self._writeInfoToPlist(info) + reader = UFOReader(self.dstDir) + self.assertRaises(UFOLibError, reader.readInfo, info=TestInfoObject()) + # openTypeNameManufacturer + info = dict(fontInfoVersion2) + info["openTypeNameManufacturer"] = 123 + self._writeInfoToPlist(info) + reader = UFOReader(self.dstDir) + self.assertRaises(UFOLibError, reader.readInfo, info=TestInfoObject()) + # openTypeNameManufacturerURL + info = dict(fontInfoVersion2) + info["openTypeNameManufacturerURL"] = 123 + self._writeInfoToPlist(info) + reader = UFOReader(self.dstDir) + self.assertRaises(UFOLibError, reader.readInfo, info=TestInfoObject()) + # openTypeNameLicense + info = dict(fontInfoVersion2) + info["openTypeNameLicense"] = 123 + self._writeInfoToPlist(info) + reader = UFOReader(self.dstDir) + self.assertRaises(UFOLibError, reader.readInfo, info=TestInfoObject()) + # openTypeNameLicenseURL + info = dict(fontInfoVersion2) + info["openTypeNameLicenseURL"] = 123 + self._writeInfoToPlist(info) + reader = UFOReader(self.dstDir) + self.assertRaises(UFOLibError, reader.readInfo, info=TestInfoObject()) + # openTypeNameVersion + info = dict(fontInfoVersion2) + info["openTypeNameVersion"] = 123 + self._writeInfoToPlist(info) + reader = UFOReader(self.dstDir) + self.assertRaises(UFOLibError, reader.readInfo, info=TestInfoObject()) + # openTypeNameUniqueID + info = dict(fontInfoVersion2) + info["openTypeNameUniqueID"] = 123 + self._writeInfoToPlist(info) + reader = UFOReader(self.dstDir) + self.assertRaises(UFOLibError, reader.readInfo, info=TestInfoObject()) + # openTypeNameDescription + info = dict(fontInfoVersion2) + info["openTypeNameDescription"] = 123 + self._writeInfoToPlist(info) + reader = UFOReader(self.dstDir) + self.assertRaises(UFOLibError, reader.readInfo, info=TestInfoObject()) + # openTypeNamePreferredFamilyName + info = dict(fontInfoVersion2) + info["openTypeNamePreferredFamilyName"] = 123 + self._writeInfoToPlist(info) + reader = UFOReader(self.dstDir) + self.assertRaises(UFOLibError, reader.readInfo, info=TestInfoObject()) + # openTypeNamePreferredSubfamilyName + info = dict(fontInfoVersion2) + info["openTypeNamePreferredSubfamilyName"] = 123 + self._writeInfoToPlist(info) + reader = UFOReader(self.dstDir) + self.assertRaises(UFOLibError, reader.readInfo, info=TestInfoObject()) + # openTypeNameCompatibleFullName + info = dict(fontInfoVersion2) + info["openTypeNameCompatibleFullName"] = 123 + self._writeInfoToPlist(info) + reader = UFOReader(self.dstDir) + self.assertRaises(UFOLibError, reader.readInfo, info=TestInfoObject()) + # openTypeNameSampleText + info = dict(fontInfoVersion2) + info["openTypeNameSampleText"] = 123 + self._writeInfoToPlist(info) + reader = UFOReader(self.dstDir) + self.assertRaises(UFOLibError, reader.readInfo, info=TestInfoObject()) + # openTypeNameWWSFamilyName + info = dict(fontInfoVersion2) + info["openTypeNameWWSFamilyName"] = 123 + self._writeInfoToPlist(info) + reader = UFOReader(self.dstDir) + self.assertRaises(UFOLibError, reader.readInfo, info=TestInfoObject()) + # openTypeNameWWSSubfamilyName + info = dict(fontInfoVersion2) + info["openTypeNameWWSSubfamilyName"] = 123 + self._writeInfoToPlist(info) + reader = UFOReader(self.dstDir) + self.assertRaises(UFOLibError, reader.readInfo, info=TestInfoObject()) + + def testOS2Read(self): + # openTypeOS2WidthClass + ## not an int + info = dict(fontInfoVersion2) + info["openTypeOS2WidthClass"] = "abc" + self._writeInfoToPlist(info) + reader = UFOReader(self.dstDir) + self.assertRaises(UFOLibError, reader.readInfo, info=TestInfoObject()) + ## out or range + info = dict(fontInfoVersion2) + info["openTypeOS2WidthClass"] = 15 + self._writeInfoToPlist(info) + reader = UFOReader(self.dstDir) + self.assertRaises(UFOLibError, reader.readInfo, info=TestInfoObject()) + # openTypeOS2WeightClass + info = dict(fontInfoVersion2) + ## not an int + info["openTypeOS2WeightClass"] = "abc" + self._writeInfoToPlist(info) + reader = UFOReader(self.dstDir) + self.assertRaises(UFOLibError, reader.readInfo, info=TestInfoObject()) + ## out of range + info["openTypeOS2WeightClass"] = -50 + self._writeInfoToPlist(info) + reader = UFOReader(self.dstDir) + self.assertRaises(UFOLibError, reader.readInfo, info=TestInfoObject()) + # openTypeOS2Selection + info = dict(fontInfoVersion2) + info["openTypeOS2Selection"] = [-1] + self._writeInfoToPlist(info) + reader = UFOReader(self.dstDir) + self.assertRaises(UFOLibError, reader.readInfo, info=TestInfoObject()) + # openTypeOS2VendorID + info = dict(fontInfoVersion2) + info["openTypeOS2VendorID"] = 1234 + self._writeInfoToPlist(info) + reader = UFOReader(self.dstDir) + self.assertRaises(UFOLibError, reader.readInfo, info=TestInfoObject()) + # openTypeOS2Panose + ## not an int + info = dict(fontInfoVersion2) + info["openTypeOS2Panose"] = [0, 1, 2, 3, 4, 5, 6, 7, 8, str(9)] + self._writeInfoToPlist(info) + reader = UFOReader(self.dstDir) + self.assertRaises(UFOLibError, reader.readInfo, info=TestInfoObject()) + ## too few values + info = dict(fontInfoVersion2) + info["openTypeOS2Panose"] = [0, 1, 2, 3] + self._writeInfoToPlist(info) + reader = UFOReader(self.dstDir) + self.assertRaises(UFOLibError, reader.readInfo, info=TestInfoObject()) + ## too many values + info = dict(fontInfoVersion2) + info["openTypeOS2Panose"] = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10] + self._writeInfoToPlist(info) + reader = UFOReader(self.dstDir) + self.assertRaises(UFOLibError, reader.readInfo, info=TestInfoObject()) + # openTypeOS2FamilyClass + ## not an int + info = dict(fontInfoVersion2) + info["openTypeOS2FamilyClass"] = [1, str(1)] + self._writeInfoToPlist(info) + reader = UFOReader(self.dstDir) + self.assertRaises(UFOLibError, reader.readInfo, info=TestInfoObject()) + ## too few values + info = dict(fontInfoVersion2) + info["openTypeOS2FamilyClass"] = [1] + self._writeInfoToPlist(info) + reader = UFOReader(self.dstDir) + self.assertRaises(UFOLibError, reader.readInfo, info=TestInfoObject()) + ## too many values + info = dict(fontInfoVersion2) + info["openTypeOS2FamilyClass"] = [1, 1, 1] + self._writeInfoToPlist(info) + reader = UFOReader(self.dstDir) + self.assertRaises(UFOLibError, reader.readInfo, info=TestInfoObject()) + ## out of range + info = dict(fontInfoVersion2) + info["openTypeOS2FamilyClass"] = [1, 201] + self._writeInfoToPlist(info) + reader = UFOReader(self.dstDir) + self.assertRaises(UFOLibError, reader.readInfo, info=TestInfoObject()) + # openTypeOS2UnicodeRanges + ## not an int + info = dict(fontInfoVersion2) + info["openTypeOS2UnicodeRanges"] = ["0"] + self._writeInfoToPlist(info) + reader = UFOReader(self.dstDir) + self.assertRaises(UFOLibError, reader.readInfo, info=TestInfoObject()) + ## out of range + info = dict(fontInfoVersion2) + info["openTypeOS2UnicodeRanges"] = [-1] + self._writeInfoToPlist(info) + reader = UFOReader(self.dstDir) + self.assertRaises(UFOLibError, reader.readInfo, info=TestInfoObject()) + # openTypeOS2CodePageRanges + ## not an int + info = dict(fontInfoVersion2) + info["openTypeOS2CodePageRanges"] = ["0"] + self._writeInfoToPlist(info) + reader = UFOReader(self.dstDir) + self.assertRaises(UFOLibError, reader.readInfo, info=TestInfoObject()) + ## out of range + info = dict(fontInfoVersion2) + info["openTypeOS2CodePageRanges"] = [-1] + self._writeInfoToPlist(info) + reader = UFOReader(self.dstDir) + self.assertRaises(UFOLibError, reader.readInfo, info=TestInfoObject()) + # openTypeOS2TypoAscender + info = dict(fontInfoVersion2) + info["openTypeOS2TypoAscender"] = "abc" + self._writeInfoToPlist(info) + reader = UFOReader(self.dstDir) + self.assertRaises(UFOLibError, reader.readInfo, info=TestInfoObject()) + # openTypeOS2TypoDescender + info = dict(fontInfoVersion2) + info["openTypeOS2TypoDescender"] = "abc" + self._writeInfoToPlist(info) + reader = UFOReader(self.dstDir) + self.assertRaises(UFOLibError, reader.readInfo, info=TestInfoObject()) + # openTypeOS2TypoLineGap + info = dict(fontInfoVersion2) + info["openTypeOS2TypoLineGap"] = "abc" + self._writeInfoToPlist(info) + reader = UFOReader(self.dstDir) + self.assertRaises(UFOLibError, reader.readInfo, info=TestInfoObject()) + # openTypeOS2WinAscent + info = dict(fontInfoVersion2) + info["openTypeOS2WinAscent"] = "abc" + self._writeInfoToPlist(info) + reader = UFOReader(self.dstDir) + self.assertRaises(UFOLibError, reader.readInfo, info=TestInfoObject()) + # openTypeOS2WinDescent + info = dict(fontInfoVersion2) + info["openTypeOS2WinDescent"] = "abc" + self._writeInfoToPlist(info) + reader = UFOReader(self.dstDir) + self.assertRaises(UFOLibError, reader.readInfo, info=TestInfoObject()) + # openTypeOS2Type + ## not an int + info = dict(fontInfoVersion2) + info["openTypeOS2Type"] = ["1"] + self._writeInfoToPlist(info) + reader = UFOReader(self.dstDir) + self.assertRaises(UFOLibError, reader.readInfo, info=TestInfoObject()) + ## out of range + info = dict(fontInfoVersion2) + info["openTypeOS2Type"] = [-1] + self._writeInfoToPlist(info) + reader = UFOReader(self.dstDir) + self.assertRaises(UFOLibError, reader.readInfo, info=TestInfoObject()) + # openTypeOS2SubscriptXSize + info = dict(fontInfoVersion2) + info["openTypeOS2SubscriptXSize"] = "abc" + self._writeInfoToPlist(info) + reader = UFOReader(self.dstDir) + self.assertRaises(UFOLibError, reader.readInfo, info=TestInfoObject()) + # openTypeOS2SubscriptYSize + info = dict(fontInfoVersion2) + info["openTypeOS2SubscriptYSize"] = "abc" + self._writeInfoToPlist(info) + reader = UFOReader(self.dstDir) + self.assertRaises(UFOLibError, reader.readInfo, info=TestInfoObject()) + # openTypeOS2SubscriptXOffset + info = dict(fontInfoVersion2) + info["openTypeOS2SubscriptXOffset"] = "abc" + self._writeInfoToPlist(info) + reader = UFOReader(self.dstDir) + self.assertRaises(UFOLibError, reader.readInfo, info=TestInfoObject()) + # openTypeOS2SubscriptYOffset + info = dict(fontInfoVersion2) + info["openTypeOS2SubscriptYOffset"] = "abc" + self._writeInfoToPlist(info) + reader = UFOReader(self.dstDir) + self.assertRaises(UFOLibError, reader.readInfo, info=TestInfoObject()) + # openTypeOS2SuperscriptXSize + info = dict(fontInfoVersion2) + info["openTypeOS2SuperscriptXSize"] = "abc" + self._writeInfoToPlist(info) + reader = UFOReader(self.dstDir) + self.assertRaises(UFOLibError, reader.readInfo, info=TestInfoObject()) + # openTypeOS2SuperscriptYSize + info = dict(fontInfoVersion2) + info["openTypeOS2SuperscriptYSize"] = "abc" + self._writeInfoToPlist(info) + reader = UFOReader(self.dstDir) + self.assertRaises(UFOLibError, reader.readInfo, info=TestInfoObject()) + # openTypeOS2SuperscriptXOffset + info = dict(fontInfoVersion2) + info["openTypeOS2SuperscriptXOffset"] = "abc" + self._writeInfoToPlist(info) + reader = UFOReader(self.dstDir) + self.assertRaises(UFOLibError, reader.readInfo, info=TestInfoObject()) + # openTypeOS2SuperscriptYOffset + info = dict(fontInfoVersion2) + info["openTypeOS2SuperscriptYOffset"] = "abc" + self._writeInfoToPlist(info) + reader = UFOReader(self.dstDir) + self.assertRaises(UFOLibError, reader.readInfo, info=TestInfoObject()) + # openTypeOS2StrikeoutSize + info = dict(fontInfoVersion2) + info["openTypeOS2StrikeoutSize"] = "abc" + self._writeInfoToPlist(info) + reader = UFOReader(self.dstDir) + self.assertRaises(UFOLibError, reader.readInfo, info=TestInfoObject()) + # openTypeOS2StrikeoutPosition + info = dict(fontInfoVersion2) + info["openTypeOS2StrikeoutPosition"] = "abc" + self._writeInfoToPlist(info) + reader = UFOReader(self.dstDir) + self.assertRaises(UFOLibError, reader.readInfo, info=TestInfoObject()) + + def testVheaRead(self): + # openTypeVheaVertTypoAscender + info = dict(fontInfoVersion2) + info["openTypeVheaVertTypoAscender"] = "abc" + self._writeInfoToPlist(info) + reader = UFOReader(self.dstDir) + self.assertRaises(UFOLibError, reader.readInfo, info=TestInfoObject()) + # openTypeVheaVertTypoDescender + info = dict(fontInfoVersion2) + info["openTypeVheaVertTypoDescender"] = "abc" + self._writeInfoToPlist(info) + reader = UFOReader(self.dstDir) + self.assertRaises(UFOLibError, reader.readInfo, info=TestInfoObject()) + # openTypeVheaVertTypoLineGap + info = dict(fontInfoVersion2) + info["openTypeVheaVertTypoLineGap"] = "abc" + self._writeInfoToPlist(info) + reader = UFOReader(self.dstDir) + self.assertRaises(UFOLibError, reader.readInfo, info=TestInfoObject()) + # openTypeVheaCaretSlopeRise + info = dict(fontInfoVersion2) + info["openTypeVheaCaretSlopeRise"] = "abc" + self._writeInfoToPlist(info) + reader = UFOReader(self.dstDir) + self.assertRaises(UFOLibError, reader.readInfo, info=TestInfoObject()) + # openTypeVheaCaretSlopeRun + info = dict(fontInfoVersion2) + info["openTypeVheaCaretSlopeRun"] = "abc" + self._writeInfoToPlist(info) + reader = UFOReader(self.dstDir) + self.assertRaises(UFOLibError, reader.readInfo, info=TestInfoObject()) + # openTypeVheaCaretOffset + info = dict(fontInfoVersion2) + info["openTypeVheaCaretOffset"] = "abc" + self._writeInfoToPlist(info) + reader = UFOReader(self.dstDir) + self.assertRaises(UFOLibError, reader.readInfo, info=TestInfoObject()) + + def testFONDRead(self): + # macintoshFONDFamilyID + info = dict(fontInfoVersion2) + info["macintoshFONDFamilyID"] = "abc" + self._writeInfoToPlist(info) + reader = UFOReader(self.dstDir) + self.assertRaises(UFOLibError, reader.readInfo, info=TestInfoObject()) + # macintoshFONDName + info = dict(fontInfoVersion2) + info["macintoshFONDName"] = 123 + self._writeInfoToPlist(info) + reader = UFOReader(self.dstDir) + self.assertRaises(UFOLibError, reader.readInfo, info=TestInfoObject()) + + def testPostscriptRead(self): + # postscriptFontName + info = dict(fontInfoVersion2) + info["postscriptFontName"] = 123 + self._writeInfoToPlist(info) + reader = UFOReader(self.dstDir) + self.assertRaises(UFOLibError, reader.readInfo, info=TestInfoObject()) + # postscriptFullName + info = dict(fontInfoVersion2) + info["postscriptFullName"] = 123 + self._writeInfoToPlist(info) + reader = UFOReader(self.dstDir) + self.assertRaises(UFOLibError, reader.readInfo, info=TestInfoObject()) + # postscriptSlantAngle + info = dict(fontInfoVersion2) + info["postscriptSlantAngle"] = "abc" + self._writeInfoToPlist(info) + reader = UFOReader(self.dstDir) + self.assertRaises(UFOLibError, reader.readInfo, info=TestInfoObject()) + # postscriptUniqueID + info = dict(fontInfoVersion2) + info["postscriptUniqueID"] = "abc" + self._writeInfoToPlist(info) + reader = UFOReader(self.dstDir) + self.assertRaises(UFOLibError, reader.readInfo, TestInfoObject()) + # postscriptUnderlineThickness + info = dict(fontInfoVersion2) + info["postscriptUnderlineThickness"] = "abc" + self._writeInfoToPlist(info) + reader = UFOReader(self.dstDir) + self.assertRaises(UFOLibError, reader.readInfo, TestInfoObject()) + # postscriptUnderlinePosition + info = dict(fontInfoVersion2) + info["postscriptUnderlinePosition"] = "abc" + self._writeInfoToPlist(info) + reader = UFOReader(self.dstDir) + self.assertRaises(UFOLibError, reader.readInfo, TestInfoObject()) + # postscriptIsFixedPitch + info = dict(fontInfoVersion2) + info["postscriptIsFixedPitch"] = 2 + self._writeInfoToPlist(info) + reader = UFOReader(self.dstDir) + self.assertRaises(UFOLibError, reader.readInfo, TestInfoObject()) + # postscriptBlueValues + ## not a list + info = dict(fontInfoVersion2) + info["postscriptBlueValues"] = "abc" + self._writeInfoToPlist(info) + reader = UFOReader(self.dstDir) + self.assertRaises(UFOLibError, reader.readInfo, TestInfoObject()) + ## uneven value count + info = dict(fontInfoVersion2) + info["postscriptBlueValues"] = [500] + self._writeInfoToPlist(info) + reader = UFOReader(self.dstDir) + self.assertRaises(UFOLibError, reader.readInfo, TestInfoObject()) + ## too many values + info = dict(fontInfoVersion2) + info["postscriptBlueValues"] = [10, 20, 30, 40, 50, 60, 70, 80, 90, 100, 110, 120, 130, 140, 150, 160] + self._writeInfoToPlist(info) + reader = UFOReader(self.dstDir) + self.assertRaises(UFOLibError, reader.readInfo, TestInfoObject()) + # postscriptOtherBlues + ## not a list + info = dict(fontInfoVersion2) + info["postscriptOtherBlues"] = "abc" + self._writeInfoToPlist(info) + reader = UFOReader(self.dstDir) + self.assertRaises(UFOLibError, reader.readInfo, TestInfoObject()) + ## uneven value count + info = dict(fontInfoVersion2) + info["postscriptOtherBlues"] = [500] + self._writeInfoToPlist(info) + reader = UFOReader(self.dstDir) + self.assertRaises(UFOLibError, reader.readInfo, TestInfoObject()) + ## too many values + info = dict(fontInfoVersion2) + info["postscriptOtherBlues"] = [10, 20, 30, 40, 50, 60, 70, 80, 90, 100, 110, 120, 130, 140, 150, 160] + self._writeInfoToPlist(info) + reader = UFOReader(self.dstDir) + self.assertRaises(UFOLibError, reader.readInfo, TestInfoObject()) + # postscriptFamilyBlues + ## not a list + info = dict(fontInfoVersion2) + info["postscriptFamilyBlues"] = "abc" + self._writeInfoToPlist(info) + reader = UFOReader(self.dstDir) + self.assertRaises(UFOLibError, reader.readInfo, TestInfoObject()) + ## uneven value count + info = dict(fontInfoVersion2) + info["postscriptFamilyBlues"] = [500] + self._writeInfoToPlist(info) + reader = UFOReader(self.dstDir) + self.assertRaises(UFOLibError, reader.readInfo, TestInfoObject()) + ## too many values + info = dict(fontInfoVersion2) + info["postscriptFamilyBlues"] = [10, 20, 30, 40, 50, 60, 70, 80, 90, 100, 110, 120, 130, 140, 150, 160] + self._writeInfoToPlist(info) + reader = UFOReader(self.dstDir) + self.assertRaises(UFOLibError, reader.readInfo, TestInfoObject()) + # postscriptFamilyOtherBlues + ## not a list + info = dict(fontInfoVersion2) + info["postscriptFamilyOtherBlues"] = "abc" + self._writeInfoToPlist(info) + reader = UFOReader(self.dstDir) + self.assertRaises(UFOLibError, reader.readInfo, TestInfoObject()) + ## uneven value count + info = dict(fontInfoVersion2) + info["postscriptFamilyOtherBlues"] = [500] + self._writeInfoToPlist(info) + reader = UFOReader(self.dstDir) + self.assertRaises(UFOLibError, reader.readInfo, TestInfoObject()) + ## too many values + info = dict(fontInfoVersion2) + info["postscriptFamilyOtherBlues"] = [10, 20, 30, 40, 50, 60, 70, 80, 90, 100, 110, 120, 130, 140, 150, 160] + self._writeInfoToPlist(info) + reader = UFOReader(self.dstDir) + self.assertRaises(UFOLibError, reader.readInfo, TestInfoObject()) + # postscriptStemSnapH + ## not list + info = dict(fontInfoVersion2) + info["postscriptStemSnapH"] = "abc" + self._writeInfoToPlist(info) + reader = UFOReader(self.dstDir) + self.assertRaises(UFOLibError, reader.readInfo, TestInfoObject()) + ## too many values + info = dict(fontInfoVersion2) + info["postscriptStemSnapH"] = [10, 20, 30, 40, 50, 60, 70, 80, 90, 100, 110, 120, 130, 140, 150, 160] + self._writeInfoToPlist(info) + reader = UFOReader(self.dstDir) + self.assertRaises(UFOLibError, reader.readInfo, TestInfoObject()) + # postscriptStemSnapV + ## not list + info = dict(fontInfoVersion2) + info["postscriptStemSnapV"] = "abc" + self._writeInfoToPlist(info) + reader = UFOReader(self.dstDir) + self.assertRaises(UFOLibError, reader.readInfo, TestInfoObject()) + ## too many values + info = dict(fontInfoVersion2) + info["postscriptStemSnapV"] = [10, 20, 30, 40, 50, 60, 70, 80, 90, 100, 110, 120, 130, 140, 150, 160] + self._writeInfoToPlist(info) + reader = UFOReader(self.dstDir) + self.assertRaises(UFOLibError, reader.readInfo, TestInfoObject()) + # postscriptBlueFuzz + info = dict(fontInfoVersion2) + info["postscriptBlueFuzz"] = "abc" + self._writeInfoToPlist(info) + reader = UFOReader(self.dstDir) + self.assertRaises(UFOLibError, reader.readInfo, TestInfoObject()) + # postscriptBlueShift + info = dict(fontInfoVersion2) + info["postscriptBlueShift"] = "abc" + self._writeInfoToPlist(info) + reader = UFOReader(self.dstDir) + self.assertRaises(UFOLibError, reader.readInfo, TestInfoObject()) + # postscriptBlueScale + info = dict(fontInfoVersion2) + info["postscriptBlueScale"] = "abc" + self._writeInfoToPlist(info) + reader = UFOReader(self.dstDir) + self.assertRaises(UFOLibError, reader.readInfo, TestInfoObject()) + # postscriptForceBold + info = dict(fontInfoVersion2) + info["postscriptForceBold"] = "abc" + self._writeInfoToPlist(info) + reader = UFOReader(self.dstDir) + self.assertRaises(UFOLibError, reader.readInfo, TestInfoObject()) + # postscriptDefaultWidthX + info = dict(fontInfoVersion2) + info["postscriptDefaultWidthX"] = "abc" + self._writeInfoToPlist(info) + reader = UFOReader(self.dstDir) + self.assertRaises(UFOLibError, reader.readInfo, TestInfoObject()) + # postscriptNominalWidthX + info = dict(fontInfoVersion2) + info["postscriptNominalWidthX"] = "abc" + self._writeInfoToPlist(info) + reader = UFOReader(self.dstDir) + self.assertRaises(UFOLibError, reader.readInfo, TestInfoObject()) + # postscriptWeightName + info = dict(fontInfoVersion2) + info["postscriptWeightName"] = 123 + self._writeInfoToPlist(info) + reader = UFOReader(self.dstDir) + self.assertRaises(UFOLibError, reader.readInfo, TestInfoObject()) + # postscriptDefaultCharacter + info = dict(fontInfoVersion2) + info["postscriptDefaultCharacter"] = 123 + self._writeInfoToPlist(info) + reader = UFOReader(self.dstDir) + self.assertRaises(UFOLibError, reader.readInfo, TestInfoObject()) + # postscriptWindowsCharacterSet + info = dict(fontInfoVersion2) + info["postscriptWindowsCharacterSet"] = -1 + self._writeInfoToPlist(info) + reader = UFOReader(self.dstDir) + self.assertRaises(UFOLibError, reader.readInfo, TestInfoObject()) + # macintoshFONDFamilyID + info = dict(fontInfoVersion2) + info["macintoshFONDFamilyID"] = "abc" + self._writeInfoToPlist(info) + reader = UFOReader(self.dstDir) + self.assertRaises(UFOLibError, reader.readInfo, TestInfoObject()) + # macintoshFONDName + info = dict(fontInfoVersion2) + info["macintoshFONDName"] = 123 + self._writeInfoToPlist(info) + reader = UFOReader(self.dstDir) + self.assertRaises(UFOLibError, reader.readInfo, TestInfoObject()) + + +class WriteFontInfoVersion1TestCase(unittest.TestCase): + + def setUp(self): + self.dstDir = tempfile.mktemp() + os.mkdir(self.dstDir) + + def tearDown(self): + shutil.rmtree(self.dstDir) + + def makeInfoObject(self): + infoObject = TestInfoObject() + for attr, value in fontInfoVersion2.items(): + setattr(infoObject, attr, value) + return infoObject + + def readPlist(self): + path = os.path.join(self.dstDir, "fontinfo.plist") + return readPlist(path) + + def testWrite(self): + infoObject = self.makeInfoObject() + writer = UFOWriter(self.dstDir, formatVersion=1) + writer.writeInfo(infoObject) + writtenData = self.readPlist() + for attr, originalValue in fontInfoVersion1.items(): + newValue = writtenData[attr] + self.assertEqual(newValue, originalValue) + + def testFontStyleConversion(self): + fontStyle1To2 = { + 64 : "regular", + 1 : "italic", + 32 : "bold", + 33 : "bold italic" + } + for old, new in fontStyle1To2.items(): + infoObject = self.makeInfoObject() + infoObject.styleMapStyleName = new + writer = UFOWriter(self.dstDir, formatVersion=1) + writer.writeInfo(infoObject) + writtenData = self.readPlist() + self.assertEqual(writtenData["fontStyle"], old) + + def testWidthNameConversion(self): + widthName1To2 = { + "Ultra-condensed" : 1, + "Extra-condensed" : 2, + "Condensed" : 3, + "Semi-condensed" : 4, + "Medium (normal)" : 5, + "Semi-expanded" : 6, + "Expanded" : 7, + "Extra-expanded" : 8, + "Ultra-expanded" : 9 + } + for old, new in widthName1To2.items(): + infoObject = self.makeInfoObject() + infoObject.openTypeOS2WidthClass = new + writer = UFOWriter(self.dstDir, formatVersion=1) + writer.writeInfo(infoObject) + writtenData = self.readPlist() + self.assertEqual(writtenData["widthName"], old) + + +class WriteFontInfoVersion2TestCase(unittest.TestCase): + + def setUp(self): + self.dstDir = tempfile.mktemp() + os.mkdir(self.dstDir) + + def tearDown(self): + shutil.rmtree(self.dstDir) + + def makeInfoObject(self): + infoObject = TestInfoObject() + for attr, value in fontInfoVersion2.items(): + setattr(infoObject, attr, value) + return infoObject + + def readPlist(self): + path = os.path.join(self.dstDir, "fontinfo.plist") + return readPlist(path) + + def testWrite(self): + infoObject = self.makeInfoObject() + writer = UFOWriter(self.dstDir) + writer.writeInfo(infoObject) + writtenData = self.readPlist() + for attr, originalValue in fontInfoVersion2.items(): + newValue = writtenData[attr] + self.assertEqual(newValue, originalValue) + + def testGenericWrite(self): + # familyName + infoObject = self.makeInfoObject() + infoObject.familyName = 123 + writer = UFOWriter(self.dstDir) + self.assertRaises(UFOLibError, writer.writeInfo, info=infoObject) + # styleName + infoObject = self.makeInfoObject() + infoObject.styleName = 123 + writer = UFOWriter(self.dstDir) + self.assertRaises(UFOLibError, writer.writeInfo, info=infoObject) + # styleMapFamilyName + infoObject = self.makeInfoObject() + infoObject.styleMapFamilyName = 123 + writer = UFOWriter(self.dstDir) + self.assertRaises(UFOLibError, writer.writeInfo, info=infoObject) + # styleMapStyleName + ## not a string + infoObject = self.makeInfoObject() + infoObject.styleMapStyleName = 123 + writer = UFOWriter(self.dstDir) + self.assertRaises(UFOLibError, writer.writeInfo, info=infoObject) + ## out of range + infoObject = self.makeInfoObject() + infoObject.styleMapStyleName = "REGULAR" + writer = UFOWriter(self.dstDir) + self.assertRaises(UFOLibError, writer.writeInfo, info=infoObject) + # versionMajor + infoObject = self.makeInfoObject() + infoObject.versionMajor = "1" + writer = UFOWriter(self.dstDir) + self.assertRaises(UFOLibError, writer.writeInfo, info=infoObject) + # versionMinor + infoObject = self.makeInfoObject() + infoObject.versionMinor = "0" + writer = UFOWriter(self.dstDir) + self.assertRaises(UFOLibError, writer.writeInfo, info=infoObject) + # copyright + infoObject = self.makeInfoObject() + infoObject.copyright = 123 + writer = UFOWriter(self.dstDir) + self.assertRaises(UFOLibError, writer.writeInfo, info=infoObject) + # trademark + infoObject = self.makeInfoObject() + infoObject.trademark = 123 + writer = UFOWriter(self.dstDir) + self.assertRaises(UFOLibError, writer.writeInfo, info=infoObject) + # unitsPerEm + infoObject = self.makeInfoObject() + infoObject.unitsPerEm = "abc" + writer = UFOWriter(self.dstDir) + self.assertRaises(UFOLibError, writer.writeInfo, info=infoObject) + # descender + infoObject = self.makeInfoObject() + infoObject.descender = "abc" + writer = UFOWriter(self.dstDir) + self.assertRaises(UFOLibError, writer.writeInfo, info=infoObject) + # xHeight + infoObject = self.makeInfoObject() + infoObject.xHeight = "abc" + writer = UFOWriter(self.dstDir) + self.assertRaises(UFOLibError, writer.writeInfo, info=infoObject) + # capHeight + infoObject = self.makeInfoObject() + infoObject.capHeight = "abc" + writer = UFOWriter(self.dstDir) + self.assertRaises(UFOLibError, writer.writeInfo, info=infoObject) + # ascender + infoObject = self.makeInfoObject() + infoObject.ascender = "abc" + writer = UFOWriter(self.dstDir) + self.assertRaises(UFOLibError, writer.writeInfo, info=infoObject) + # italicAngle + infoObject = self.makeInfoObject() + infoObject.italicAngle = "abc" + writer = UFOWriter(self.dstDir) + self.assertRaises(UFOLibError, writer.writeInfo, info=infoObject) + + def testHeadWrite(self): + # openTypeHeadCreated + ## not a string + infoObject = self.makeInfoObject() + infoObject.openTypeHeadCreated = 123 + writer = UFOWriter(self.dstDir) + self.assertRaises(UFOLibError, writer.writeInfo, info=infoObject) + ## invalid format + infoObject = self.makeInfoObject() + infoObject.openTypeHeadCreated = "2000-Jan-01 00:00:00" + writer = UFOWriter(self.dstDir) + self.assertRaises(UFOLibError, writer.writeInfo, info=infoObject) + # openTypeHeadLowestRecPPEM + infoObject = self.makeInfoObject() + infoObject.openTypeHeadLowestRecPPEM = "abc" + writer = UFOWriter(self.dstDir) + self.assertRaises(UFOLibError, writer.writeInfo, info=infoObject) + # openTypeHeadFlags + infoObject = self.makeInfoObject() + infoObject.openTypeHeadFlags = [-1] + writer = UFOWriter(self.dstDir) + self.assertRaises(UFOLibError, writer.writeInfo, info=infoObject) + + def testHheaWrite(self): + # openTypeHheaAscender + infoObject = self.makeInfoObject() + infoObject.openTypeHheaAscender = "abc" + writer = UFOWriter(self.dstDir) + self.assertRaises(UFOLibError, writer.writeInfo, info=infoObject) + # openTypeHheaDescender + infoObject = self.makeInfoObject() + infoObject.openTypeHheaDescender = "abc" + writer = UFOWriter(self.dstDir) + self.assertRaises(UFOLibError, writer.writeInfo, info=infoObject) + # openTypeHheaLineGap + infoObject = self.makeInfoObject() + infoObject.openTypeHheaLineGap = "abc" + writer = UFOWriter(self.dstDir) + self.assertRaises(UFOLibError, writer.writeInfo, info=infoObject) + # openTypeHheaCaretSlopeRise + infoObject = self.makeInfoObject() + infoObject.openTypeHheaCaretSlopeRise = "abc" + writer = UFOWriter(self.dstDir) + self.assertRaises(UFOLibError, writer.writeInfo, info=infoObject) + # openTypeHheaCaretSlopeRun + infoObject = self.makeInfoObject() + infoObject.openTypeHheaCaretSlopeRun = "abc" + writer = UFOWriter(self.dstDir) + self.assertRaises(UFOLibError, writer.writeInfo, info=infoObject) + # openTypeHheaCaretOffset + infoObject = self.makeInfoObject() + infoObject.openTypeHheaCaretOffset = "abc" + writer = UFOWriter(self.dstDir) + self.assertRaises(UFOLibError, writer.writeInfo, info=infoObject) + + def testNameWrite(self): + # openTypeNameDesigner + infoObject = self.makeInfoObject() + infoObject.openTypeNameDesigner = 123 + writer = UFOWriter(self.dstDir) + self.assertRaises(UFOLibError, writer.writeInfo, info=infoObject) + # openTypeNameDesignerURL + infoObject = self.makeInfoObject() + infoObject.openTypeNameDesignerURL = 123 + writer = UFOWriter(self.dstDir) + self.assertRaises(UFOLibError, writer.writeInfo, info=infoObject) + # openTypeNameManufacturer + infoObject = self.makeInfoObject() + infoObject.openTypeNameManufacturer = 123 + writer = UFOWriter(self.dstDir) + self.assertRaises(UFOLibError, writer.writeInfo, info=infoObject) + # openTypeNameManufacturerURL + infoObject = self.makeInfoObject() + infoObject.openTypeNameManufacturerURL = 123 + writer = UFOWriter(self.dstDir) + self.assertRaises(UFOLibError, writer.writeInfo, info=infoObject) + # openTypeNameLicense + infoObject = self.makeInfoObject() + infoObject.openTypeNameLicense = 123 + writer = UFOWriter(self.dstDir) + self.assertRaises(UFOLibError, writer.writeInfo, info=infoObject) + # openTypeNameLicenseURL + infoObject = self.makeInfoObject() + infoObject.openTypeNameLicenseURL = 123 + writer = UFOWriter(self.dstDir) + self.assertRaises(UFOLibError, writer.writeInfo, info=infoObject) + # openTypeNameVersion + infoObject = self.makeInfoObject() + infoObject.openTypeNameVersion = 123 + writer = UFOWriter(self.dstDir) + self.assertRaises(UFOLibError, writer.writeInfo, info=infoObject) + # openTypeNameUniqueID + infoObject = self.makeInfoObject() + infoObject.openTypeNameUniqueID = 123 + writer = UFOWriter(self.dstDir) + self.assertRaises(UFOLibError, writer.writeInfo, info=infoObject) + # openTypeNameDescription + infoObject = self.makeInfoObject() + infoObject.openTypeNameDescription = 123 + writer = UFOWriter(self.dstDir) + self.assertRaises(UFOLibError, writer.writeInfo, info=infoObject) + # openTypeNamePreferredFamilyName + infoObject = self.makeInfoObject() + infoObject.openTypeNamePreferredFamilyName = 123 + writer = UFOWriter(self.dstDir) + self.assertRaises(UFOLibError, writer.writeInfo, info=infoObject) + # openTypeNamePreferredSubfamilyName + infoObject = self.makeInfoObject() + infoObject.openTypeNamePreferredSubfamilyName = 123 + writer = UFOWriter(self.dstDir) + self.assertRaises(UFOLibError, writer.writeInfo, info=infoObject) + # openTypeNameCompatibleFullName + infoObject = self.makeInfoObject() + infoObject.openTypeNameCompatibleFullName = 123 + writer = UFOWriter(self.dstDir) + self.assertRaises(UFOLibError, writer.writeInfo, info=infoObject) + # openTypeNameSampleText + infoObject = self.makeInfoObject() + infoObject.openTypeNameSampleText = 123 + writer = UFOWriter(self.dstDir) + self.assertRaises(UFOLibError, writer.writeInfo, info=infoObject) + # openTypeNameWWSFamilyName + infoObject = self.makeInfoObject() + infoObject.openTypeNameWWSFamilyName = 123 + writer = UFOWriter(self.dstDir) + self.assertRaises(UFOLibError, writer.writeInfo, info=infoObject) + # openTypeNameWWSSubfamilyName + infoObject = self.makeInfoObject() + infoObject.openTypeNameWWSSubfamilyName = 123 + writer = UFOWriter(self.dstDir) + self.assertRaises(UFOLibError, writer.writeInfo, info=infoObject) + + def testOS2Write(self): + # openTypeOS2WidthClass + ## not an int + infoObject = self.makeInfoObject() + infoObject.openTypeOS2WidthClass = "abc" + writer = UFOWriter(self.dstDir) + self.assertRaises(UFOLibError, writer.writeInfo, info=infoObject) + ## out or range + infoObject = self.makeInfoObject() + infoObject.openTypeOS2WidthClass = 15 + writer = UFOWriter(self.dstDir) + self.assertRaises(UFOLibError, writer.writeInfo, info=infoObject) + # openTypeOS2WeightClass + infoObject = self.makeInfoObject() + ## not an int + infoObject.openTypeOS2WeightClass = "abc" + writer = UFOWriter(self.dstDir) + self.assertRaises(UFOLibError, writer.writeInfo, info=infoObject) + ## out of range + infoObject.openTypeOS2WeightClass = -50 + writer = UFOWriter(self.dstDir) + self.assertRaises(UFOLibError, writer.writeInfo, info=infoObject) + # openTypeOS2Selection + infoObject = self.makeInfoObject() + infoObject.openTypeOS2Selection = [-1] + writer = UFOWriter(self.dstDir) + self.assertRaises(UFOLibError, writer.writeInfo, info=infoObject) + # openTypeOS2VendorID + infoObject = self.makeInfoObject() + infoObject.openTypeOS2VendorID = 1234 + writer = UFOWriter(self.dstDir) + self.assertRaises(UFOLibError, writer.writeInfo, info=infoObject) + # openTypeOS2Panose + ## not an int + infoObject = self.makeInfoObject() + infoObject.openTypeOS2Panose = [0, 1, 2, 3, 4, 5, 6, 7, 8, str(9)] + writer = UFOWriter(self.dstDir) + self.assertRaises(UFOLibError, writer.writeInfo, info=infoObject) + ## too few values + infoObject = self.makeInfoObject() + infoObject.openTypeOS2Panose = [0, 1, 2, 3] + writer = UFOWriter(self.dstDir) + self.assertRaises(UFOLibError, writer.writeInfo, info=infoObject) + ## too many values + infoObject = self.makeInfoObject() + infoObject.openTypeOS2Panose = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10] + writer = UFOWriter(self.dstDir) + self.assertRaises(UFOLibError, writer.writeInfo, info=infoObject) + # openTypeOS2FamilyClass + ## not an int + infoObject = self.makeInfoObject() + infoObject.openTypeOS2FamilyClass = [0, str(1)] + writer = UFOWriter(self.dstDir) + self.assertRaises(UFOLibError, writer.writeInfo, info=infoObject) + ## too few values + infoObject = self.makeInfoObject() + infoObject.openTypeOS2FamilyClass = [1] + writer = UFOWriter(self.dstDir) + self.assertRaises(UFOLibError, writer.writeInfo, info=infoObject) + ## too many values + infoObject = self.makeInfoObject() + infoObject.openTypeOS2FamilyClass = [1, 1, 1] + writer = UFOWriter(self.dstDir) + self.assertRaises(UFOLibError, writer.writeInfo, info=infoObject) + ## out of range + infoObject = self.makeInfoObject() + infoObject.openTypeOS2FamilyClass = [1, 20] + writer = UFOWriter(self.dstDir) + self.assertRaises(UFOLibError, writer.writeInfo, info=infoObject) + # openTypeOS2UnicodeRanges + ## not an int + infoObject = self.makeInfoObject() + infoObject.openTypeOS2UnicodeRanges = ["0"] + writer = UFOWriter(self.dstDir) + self.assertRaises(UFOLibError, writer.writeInfo, info=infoObject) + ## out of range + infoObject = self.makeInfoObject() + infoObject.openTypeOS2UnicodeRanges = [-1] + writer = UFOWriter(self.dstDir) + self.assertRaises(UFOLibError, writer.writeInfo, info=infoObject) + # openTypeOS2CodePageRanges + ## not an int + infoObject = self.makeInfoObject() + infoObject.openTypeOS2CodePageRanges = ["0"] + writer = UFOWriter(self.dstDir) + self.assertRaises(UFOLibError, writer.writeInfo, info=infoObject) + ## out of range + infoObject = self.makeInfoObject() + infoObject.openTypeOS2CodePageRanges = [-1] + writer = UFOWriter(self.dstDir) + self.assertRaises(UFOLibError, writer.writeInfo, info=infoObject) + # openTypeOS2TypoAscender + infoObject = self.makeInfoObject() + infoObject.openTypeOS2TypoAscender = "abc" + writer = UFOWriter(self.dstDir) + self.assertRaises(UFOLibError, writer.writeInfo, info=infoObject) + # openTypeOS2TypoDescender + infoObject = self.makeInfoObject() + infoObject.openTypeOS2TypoDescender = "abc" + writer = UFOWriter(self.dstDir) + self.assertRaises(UFOLibError, writer.writeInfo, info=infoObject) + # openTypeOS2TypoLineGap + infoObject = self.makeInfoObject() + infoObject.openTypeOS2TypoLineGap = "abc" + writer = UFOWriter(self.dstDir) + self.assertRaises(UFOLibError, writer.writeInfo, info=infoObject) + # openTypeOS2WinAscent + infoObject = self.makeInfoObject() + infoObject.openTypeOS2WinAscent = "abc" + writer = UFOWriter(self.dstDir) + self.assertRaises(UFOLibError, writer.writeInfo, info=infoObject) + # openTypeOS2WinDescent + infoObject = self.makeInfoObject() + infoObject.openTypeOS2WinDescent = "abc" + writer = UFOWriter(self.dstDir) + self.assertRaises(UFOLibError, writer.writeInfo, info=infoObject) + # openTypeOS2Type + ## not an int + infoObject = self.makeInfoObject() + infoObject.openTypeOS2Type = ["1"] + writer = UFOWriter(self.dstDir) + self.assertRaises(UFOLibError, writer.writeInfo, info=infoObject) + ## out of range + infoObject = self.makeInfoObject() + infoObject.openTypeOS2Type = [-1] + writer = UFOWriter(self.dstDir) + self.assertRaises(UFOLibError, writer.writeInfo, info=infoObject) + # openTypeOS2SubscriptXSize + infoObject = self.makeInfoObject() + infoObject.openTypeOS2SubscriptXSize = "abc" + writer = UFOWriter(self.dstDir) + self.assertRaises(UFOLibError, writer.writeInfo, info=infoObject) + # openTypeOS2SubscriptYSize + infoObject = self.makeInfoObject() + infoObject.openTypeOS2SubscriptYSize = "abc" + writer = UFOWriter(self.dstDir) + self.assertRaises(UFOLibError, writer.writeInfo, info=infoObject) + # openTypeOS2SubscriptXOffset + infoObject = self.makeInfoObject() + infoObject.openTypeOS2SubscriptXOffset = "abc" + writer = UFOWriter(self.dstDir) + self.assertRaises(UFOLibError, writer.writeInfo, info=infoObject) + # openTypeOS2SubscriptYOffset + infoObject = self.makeInfoObject() + infoObject.openTypeOS2SubscriptYOffset = "abc" + writer = UFOWriter(self.dstDir) + self.assertRaises(UFOLibError, writer.writeInfo, info=infoObject) + # openTypeOS2SuperscriptXSize + infoObject = self.makeInfoObject() + infoObject.openTypeOS2SuperscriptXSize = "abc" + writer = UFOWriter(self.dstDir) + self.assertRaises(UFOLibError, writer.writeInfo, info=infoObject) + # openTypeOS2SuperscriptYSize + infoObject = self.makeInfoObject() + infoObject.openTypeOS2SuperscriptYSize = "abc" + writer = UFOWriter(self.dstDir) + self.assertRaises(UFOLibError, writer.writeInfo, info=infoObject) + # openTypeOS2SuperscriptXOffset + infoObject = self.makeInfoObject() + infoObject.openTypeOS2SuperscriptXOffset = "abc" + writer = UFOWriter(self.dstDir) + self.assertRaises(UFOLibError, writer.writeInfo, info=infoObject) + # openTypeOS2SuperscriptYOffset + infoObject = self.makeInfoObject() + infoObject.openTypeOS2SuperscriptYOffset = "abc" + writer = UFOWriter(self.dstDir) + self.assertRaises(UFOLibError, writer.writeInfo, info=infoObject) + # openTypeOS2StrikeoutSize + infoObject = self.makeInfoObject() + infoObject.openTypeOS2StrikeoutSize = "abc" + writer = UFOWriter(self.dstDir) + self.assertRaises(UFOLibError, writer.writeInfo, info=infoObject) + # openTypeOS2StrikeoutPosition + infoObject = self.makeInfoObject() + infoObject.openTypeOS2StrikeoutPosition = "abc" + writer = UFOWriter(self.dstDir) + self.assertRaises(UFOLibError, writer.writeInfo, info=infoObject) + + def testVheaWrite(self): + # openTypeVheaVertTypoAscender + infoObject = self.makeInfoObject() + infoObject.openTypeVheaVertTypoAscender = "abc" + writer = UFOWriter(self.dstDir) + self.assertRaises(UFOLibError, writer.writeInfo, info=infoObject) + # openTypeVheaVertTypoDescender + infoObject = self.makeInfoObject() + infoObject.openTypeVheaVertTypoDescender = "abc" + writer = UFOWriter(self.dstDir) + self.assertRaises(UFOLibError, writer.writeInfo, info=infoObject) + # openTypeVheaVertTypoLineGap + infoObject = self.makeInfoObject() + infoObject.openTypeVheaVertTypoLineGap = "abc" + writer = UFOWriter(self.dstDir) + self.assertRaises(UFOLibError, writer.writeInfo, info=infoObject) + # openTypeVheaCaretSlopeRise + infoObject = self.makeInfoObject() + infoObject.openTypeVheaCaretSlopeRise = "abc" + writer = UFOWriter(self.dstDir) + self.assertRaises(UFOLibError, writer.writeInfo, info=infoObject) + # openTypeVheaCaretSlopeRun + infoObject = self.makeInfoObject() + infoObject.openTypeVheaCaretSlopeRun = "abc" + writer = UFOWriter(self.dstDir) + self.assertRaises(UFOLibError, writer.writeInfo, info=infoObject) + # openTypeVheaCaretOffset + infoObject = self.makeInfoObject() + infoObject.openTypeVheaCaretOffset = "abc" + writer = UFOWriter(self.dstDir) + self.assertRaises(UFOLibError, writer.writeInfo, info=infoObject) + + def testFONDWrite(self): + # macintoshFONDFamilyID + infoObject = self.makeInfoObject() + infoObject.macintoshFONDFamilyID = "abc" + writer = UFOWriter(self.dstDir) + self.assertRaises(UFOLibError, writer.writeInfo, info=infoObject) + # macintoshFONDName + infoObject = self.makeInfoObject() + infoObject.macintoshFONDName = 123 + writer = UFOWriter(self.dstDir) + self.assertRaises(UFOLibError, writer.writeInfo, info=infoObject) + + def testPostscriptWrite(self): + # postscriptFontName + infoObject = self.makeInfoObject() + infoObject.postscriptFontName = 123 + writer = UFOWriter(self.dstDir) + self.assertRaises(UFOLibError, writer.writeInfo, info=infoObject) + # postscriptFullName + infoObject = self.makeInfoObject() + infoObject.postscriptFullName = 123 + writer = UFOWriter(self.dstDir) + self.assertRaises(UFOLibError, writer.writeInfo, info=infoObject) + # postscriptSlantAngle + infoObject = self.makeInfoObject() + infoObject.postscriptSlantAngle = "abc" + writer = UFOWriter(self.dstDir) + self.assertRaises(UFOLibError, writer.writeInfo, info=infoObject) + # postscriptUniqueID + infoObject = self.makeInfoObject() + infoObject.postscriptUniqueID = "abc" + writer = UFOWriter(self.dstDir) + self.assertRaises(UFOLibError, writer.writeInfo, info=infoObject) + # postscriptUnderlineThickness + infoObject = self.makeInfoObject() + infoObject.postscriptUnderlineThickness = "abc" + writer = UFOWriter(self.dstDir) + self.assertRaises(UFOLibError, writer.writeInfo, info=infoObject) + # postscriptUnderlinePosition + infoObject = self.makeInfoObject() + infoObject.postscriptUnderlinePosition = "abc" + writer = UFOWriter(self.dstDir) + self.assertRaises(UFOLibError, writer.writeInfo, info=infoObject) + # postscriptIsFixedPitch + infoObject = self.makeInfoObject() + infoObject.postscriptIsFixedPitch = 2 + writer = UFOWriter(self.dstDir) + self.assertRaises(UFOLibError, writer.writeInfo, info=infoObject) + # postscriptBlueValues + ## not a list + infoObject = self.makeInfoObject() + infoObject.postscriptBlueValues = "abc" + writer = UFOWriter(self.dstDir) + self.assertRaises(UFOLibError, writer.writeInfo, info=infoObject) + ## uneven value count + infoObject = self.makeInfoObject() + infoObject.postscriptBlueValues = [500] + writer = UFOWriter(self.dstDir) + self.assertRaises(UFOLibError, writer.writeInfo, info=infoObject) + ## too many values + infoObject = self.makeInfoObject() + infoObject.postscriptBlueValues = [10, 20, 30, 40, 50, 60, 70, 80, 90, 100, 110, 120, 130, 140, 150, 160] + writer = UFOWriter(self.dstDir) + self.assertRaises(UFOLibError, writer.writeInfo, info=infoObject) + # postscriptOtherBlues + ## not a list + infoObject = self.makeInfoObject() + infoObject.postscriptOtherBlues = "abc" + writer = UFOWriter(self.dstDir) + self.assertRaises(UFOLibError, writer.writeInfo, info=infoObject) + ## uneven value count + infoObject = self.makeInfoObject() + infoObject.postscriptOtherBlues = [500] + writer = UFOWriter(self.dstDir) + self.assertRaises(UFOLibError, writer.writeInfo, info=infoObject) + ## too many values + infoObject = self.makeInfoObject() + infoObject.postscriptOtherBlues = [10, 20, 30, 40, 50, 60, 70, 80, 90, 100, 110, 120, 130, 140, 150, 160] + writer = UFOWriter(self.dstDir) + self.assertRaises(UFOLibError, writer.writeInfo, info=infoObject) + # postscriptFamilyBlues + ## not a list + infoObject = self.makeInfoObject() + infoObject.postscriptFamilyBlues = "abc" + writer = UFOWriter(self.dstDir) + self.assertRaises(UFOLibError, writer.writeInfo, info=infoObject) + ## uneven value count + infoObject = self.makeInfoObject() + infoObject.postscriptFamilyBlues = [500] + writer = UFOWriter(self.dstDir) + self.assertRaises(UFOLibError, writer.writeInfo, info=infoObject) + ## too many values + infoObject = self.makeInfoObject() + infoObject.postscriptFamilyBlues = [10, 20, 30, 40, 50, 60, 70, 80, 90, 100, 110, 120, 130, 140, 150, 160] + writer = UFOWriter(self.dstDir) + self.assertRaises(UFOLibError, writer.writeInfo, info=infoObject) + # postscriptFamilyOtherBlues + ## not a list + infoObject = self.makeInfoObject() + infoObject.postscriptFamilyOtherBlues = "abc" + writer = UFOWriter(self.dstDir) + self.assertRaises(UFOLibError, writer.writeInfo, info=infoObject) + ## uneven value count + infoObject = self.makeInfoObject() + infoObject.postscriptFamilyOtherBlues = [500] + writer = UFOWriter(self.dstDir) + self.assertRaises(UFOLibError, writer.writeInfo, info=infoObject) + ## too many values + infoObject = self.makeInfoObject() + infoObject.postscriptFamilyOtherBlues = [10, 20, 30, 40, 50, 60, 70, 80, 90, 100, 110, 120, 130, 140, 150, 160] + writer = UFOWriter(self.dstDir) + self.assertRaises(UFOLibError, writer.writeInfo, info=infoObject) + # postscriptStemSnapH + ## not list + infoObject = self.makeInfoObject() + infoObject.postscriptStemSnapH = "abc" + writer = UFOWriter(self.dstDir) + self.assertRaises(UFOLibError, writer.writeInfo, info=infoObject) + ## too many values + infoObject = self.makeInfoObject() + infoObject.postscriptStemSnapH = [10, 20, 30, 40, 50, 60, 70, 80, 90, 100, 110, 120, 130, 140, 150, 160] + writer = UFOWriter(self.dstDir) + self.assertRaises(UFOLibError, writer.writeInfo, info=infoObject) + # postscriptStemSnapV + ## not list + infoObject = self.makeInfoObject() + infoObject.postscriptStemSnapV = "abc" + writer = UFOWriter(self.dstDir) + self.assertRaises(UFOLibError, writer.writeInfo, info=infoObject) + ## too many values + infoObject = self.makeInfoObject() + infoObject.postscriptStemSnapV = [10, 20, 30, 40, 50, 60, 70, 80, 90, 100, 110, 120, 130, 140, 150, 160] + writer = UFOWriter(self.dstDir) + self.assertRaises(UFOLibError, writer.writeInfo, info=infoObject) + # postscriptBlueFuzz + infoObject = self.makeInfoObject() + infoObject.postscriptBlueFuzz = "abc" + writer = UFOWriter(self.dstDir) + self.assertRaises(UFOLibError, writer.writeInfo, info=infoObject) + # postscriptBlueShift + infoObject = self.makeInfoObject() + infoObject.postscriptBlueShift = "abc" + writer = UFOWriter(self.dstDir) + self.assertRaises(UFOLibError, writer.writeInfo, info=infoObject) + # postscriptBlueScale + infoObject = self.makeInfoObject() + infoObject.postscriptBlueScale = "abc" + writer = UFOWriter(self.dstDir) + self.assertRaises(UFOLibError, writer.writeInfo, info=infoObject) + # postscriptForceBold + infoObject = self.makeInfoObject() + infoObject.postscriptForceBold = "abc" + writer = UFOWriter(self.dstDir) + self.assertRaises(UFOLibError, writer.writeInfo, info=infoObject) + # postscriptDefaultWidthX + infoObject = self.makeInfoObject() + infoObject.postscriptDefaultWidthX = "abc" + writer = UFOWriter(self.dstDir) + self.assertRaises(UFOLibError, writer.writeInfo, info=infoObject) + # postscriptNominalWidthX + infoObject = self.makeInfoObject() + infoObject.postscriptNominalWidthX = "abc" + writer = UFOWriter(self.dstDir) + self.assertRaises(UFOLibError, writer.writeInfo, info=infoObject) + # postscriptWeightName + infoObject = self.makeInfoObject() + infoObject.postscriptWeightName = 123 + writer = UFOWriter(self.dstDir) + self.assertRaises(UFOLibError, writer.writeInfo, info=infoObject) + # postscriptDefaultCharacter + infoObject = self.makeInfoObject() + infoObject.postscriptDefaultCharacter = 123 + writer = UFOWriter(self.dstDir) + self.assertRaises(UFOLibError, writer.writeInfo, info=infoObject) + # postscriptWindowsCharacterSet + infoObject = self.makeInfoObject() + infoObject.postscriptWindowsCharacterSet = -1 + writer = UFOWriter(self.dstDir) + self.assertRaises(UFOLibError, writer.writeInfo, info=infoObject) + # macintoshFONDFamilyID + infoObject = self.makeInfoObject() + infoObject.macintoshFONDFamilyID = "abc" + writer = UFOWriter(self.dstDir) + self.assertRaises(UFOLibError, writer.writeInfo, info=infoObject) + # macintoshFONDName + infoObject = self.makeInfoObject() + infoObject.macintoshFONDName = 123 + writer = UFOWriter(self.dstDir) + self.assertRaises(UFOLibError, writer.writeInfo, info=infoObject) + + + + +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): + import robofab + path = os.path.dirname(robofab.__file__) + path = os.path.dirname(path) + path = os.path.dirname(path) + path = os.path.join(path, "TestData", fileName) + return path + + 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 + data1 = readPlist(metainfoPath1) + data2 = readPlist(metainfoPath2) + self.assertEqual(data1, data2) + data1 = readPlist(fontinfoPath1) + self.assertEqual(sorted(data1.items()), sorted(expectedInfoData.items())) + data1 = readPlist(kerningPath1) + data2 = readPlist(kerningPath2) + self.assertEqual(data1, data2) + data1 = readPlist(groupsPath1) + data2 = readPlist(groupsPath2) + self.assertEqual(data1, data2) + data1 = readPlist(libPath1) + data2 = readPlist(libPath2) + 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) + data1 = readPlist(glyphsPath1_contents) + data2 = readPlist(glyphsPath2_contents) + self.assertEqual(data1, data2) + data1 = readPlist(glyphsPath1_A) + data2 = readPlist(glyphsPath2_A) + self.assertEqual(data1, data2) + data1 = readPlist(glyphsPath1_B) + data2 = readPlist(glyphsPath2_B) + self.assertEqual(data1, data2) + + def test1To2(self): + path1 = self.getFontPath("TestFont1 (UFO1).ufo") + path2 = self.getFontPath("TestFont1 (UFO1) converted.ufo") + path3 = self.getFontPath("TestFont1 (UFO2).ufo") + 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) + + +if __name__ == "__main__": + from robofab.test.testSupport import runTests + runTests() |