1175f04812343b1d149971dca7fe32ba49c623cc2jvr#! /usr/bin/env python 2a0af6c7dffb109a2918332ff9eca7b7e439f2499jvr 3a0af6c7dffb109a2918332ff9eca7b7e439f2499jvr"""usage: ttroundtrip [options] font1 ... fontN 4a0af6c7dffb109a2918332ff9eca7b7e439f2499jvr 5a0af6c7dffb109a2918332ff9eca7b7e439f2499jvr Dump each TT/OT font as a TTX file, compile again to TTF or OTF 6a0af6c7dffb109a2918332ff9eca7b7e439f2499jvr and dump again. Then do a diff on the two TTX files. Append problems 7a0af6c7dffb109a2918332ff9eca7b7e439f2499jvr and diffs to a file called "report.txt" in the current directory. 8a0af6c7dffb109a2918332ff9eca7b7e439f2499jvr This is only for testing FontTools/TTX, the resulting files are 9a0af6c7dffb109a2918332ff9eca7b7e439f2499jvr deleted afterwards. 10a0af6c7dffb109a2918332ff9eca7b7e439f2499jvr 11848d25d97dd1d9d9ff6ea9ff8c5ae59374526488jvr This tool supports some of ttx's command line options (-i, -t 12848d25d97dd1d9d9ff6ea9ff8c5ae59374526488jvr and -x). Specifying -t or -x implies ttx -m <originalfile> on 13848d25d97dd1d9d9ff6ea9ff8c5ae59374526488jvr the way back. 14a0af6c7dffb109a2918332ff9eca7b7e439f2499jvr""" 15a0af6c7dffb109a2918332ff9eca7b7e439f2499jvr 16a0af6c7dffb109a2918332ff9eca7b7e439f2499jvr 17a0af6c7dffb109a2918332ff9eca7b7e439f2499jvrimport sys 18a0af6c7dffb109a2918332ff9eca7b7e439f2499jvrimport os 19a0af6c7dffb109a2918332ff9eca7b7e439f2499jvrimport tempfile 20a0af6c7dffb109a2918332ff9eca7b7e439f2499jvrimport getopt 21a0af6c7dffb109a2918332ff9eca7b7e439f2499jvrimport traceback 22a0af6c7dffb109a2918332ff9eca7b7e439f2499jvrfrom fontTools import ttx 23a0af6c7dffb109a2918332ff9eca7b7e439f2499jvr 24a0af6c7dffb109a2918332ff9eca7b7e439f2499jvrclass Error(Exception): pass 25a0af6c7dffb109a2918332ff9eca7b7e439f2499jvr 26a0af6c7dffb109a2918332ff9eca7b7e439f2499jvr 27a0af6c7dffb109a2918332ff9eca7b7e439f2499jvrdef usage(): 283ec6a258238b6068e4eef3fe579f1f5c0a06bbbaBehdad Esfahbod print(__doc__) 29a0af6c7dffb109a2918332ff9eca7b7e439f2499jvr sys.exit(2) 30a0af6c7dffb109a2918332ff9eca7b7e439f2499jvr 31a0af6c7dffb109a2918332ff9eca7b7e439f2499jvr 32a0af6c7dffb109a2918332ff9eca7b7e439f2499jvrdef roundTrip(ttFile1, options, report): 33a0af6c7dffb109a2918332ff9eca7b7e439f2499jvr fn = os.path.basename(ttFile1) 34a0af6c7dffb109a2918332ff9eca7b7e439f2499jvr xmlFile1 = tempfile.mktemp(".%s.ttx1" % fn) 35a0af6c7dffb109a2918332ff9eca7b7e439f2499jvr ttFile2 = tempfile.mktemp(".%s" % fn) 36a0af6c7dffb109a2918332ff9eca7b7e439f2499jvr xmlFile2 = tempfile.mktemp(".%s.ttx2" % fn) 37a0af6c7dffb109a2918332ff9eca7b7e439f2499jvr 38a0af6c7dffb109a2918332ff9eca7b7e439f2499jvr try: 39a0af6c7dffb109a2918332ff9eca7b7e439f2499jvr ttx.ttDump(ttFile1, xmlFile1, options) 40a0af6c7dffb109a2918332ff9eca7b7e439f2499jvr if options.onlyTables or options.skipTables: 41a0af6c7dffb109a2918332ff9eca7b7e439f2499jvr options.mergeFile = ttFile1 42a0af6c7dffb109a2918332ff9eca7b7e439f2499jvr ttx.ttCompile(xmlFile1, ttFile2, options) 43a0af6c7dffb109a2918332ff9eca7b7e439f2499jvr options.mergeFile = None 44a0af6c7dffb109a2918332ff9eca7b7e439f2499jvr ttx.ttDump(ttFile2, xmlFile2, options) 45a0af6c7dffb109a2918332ff9eca7b7e439f2499jvr 46044f8988d6f4ba4b956fae6799e2c81a86bf24c2pabs diffcmd = 'diff -U2 -I ".*modified value\|checkSumAdjustment.*" "%s" "%s"' % (xmlFile1, xmlFile2) 47a0af6c7dffb109a2918332ff9eca7b7e439f2499jvr output = os.popen(diffcmd, "r", 1) 48a0af6c7dffb109a2918332ff9eca7b7e439f2499jvr lines = [] 49ac1b4359467ca3deab03186a15eae1d55eb35567Behdad Esfahbod while True: 50a0af6c7dffb109a2918332ff9eca7b7e439f2499jvr line = output.readline() 51a0af6c7dffb109a2918332ff9eca7b7e439f2499jvr if not line: 52a0af6c7dffb109a2918332ff9eca7b7e439f2499jvr break 53a0af6c7dffb109a2918332ff9eca7b7e439f2499jvr sys.stdout.write(line) 54a0af6c7dffb109a2918332ff9eca7b7e439f2499jvr lines.append(line) 55a0af6c7dffb109a2918332ff9eca7b7e439f2499jvr if lines: 56a0af6c7dffb109a2918332ff9eca7b7e439f2499jvr report.write("=============================================================\n") 57a0af6c7dffb109a2918332ff9eca7b7e439f2499jvr report.write(" \"%s\" differs after round tripping\n" % ttFile1) 58a0af6c7dffb109a2918332ff9eca7b7e439f2499jvr report.write("-------------------------------------------------------------\n") 59a0af6c7dffb109a2918332ff9eca7b7e439f2499jvr report.writelines(lines) 60a0af6c7dffb109a2918332ff9eca7b7e439f2499jvr else: 613ec6a258238b6068e4eef3fe579f1f5c0a06bbbaBehdad Esfahbod print("(TTX files are the same)") 62a0af6c7dffb109a2918332ff9eca7b7e439f2499jvr finally: 63a0af6c7dffb109a2918332ff9eca7b7e439f2499jvr for tmpFile in (xmlFile1, ttFile2, xmlFile2): 64a0af6c7dffb109a2918332ff9eca7b7e439f2499jvr if os.path.exists(tmpFile): 65a0af6c7dffb109a2918332ff9eca7b7e439f2499jvr os.remove(tmpFile) 66a0af6c7dffb109a2918332ff9eca7b7e439f2499jvr 67a0af6c7dffb109a2918332ff9eca7b7e439f2499jvr 68a0af6c7dffb109a2918332ff9eca7b7e439f2499jvrdef main(args): 69a0af6c7dffb109a2918332ff9eca7b7e439f2499jvr try: 70848d25d97dd1d9d9ff6ea9ff8c5ae59374526488jvr rawOptions, files = getopt.getopt(args, "it:x:") 71a0af6c7dffb109a2918332ff9eca7b7e439f2499jvr except getopt.GetoptError: 72a0af6c7dffb109a2918332ff9eca7b7e439f2499jvr usage() 73a0af6c7dffb109a2918332ff9eca7b7e439f2499jvr 74a0af6c7dffb109a2918332ff9eca7b7e439f2499jvr if not files: 75a0af6c7dffb109a2918332ff9eca7b7e439f2499jvr usage() 76a0af6c7dffb109a2918332ff9eca7b7e439f2499jvr 77a0af6c7dffb109a2918332ff9eca7b7e439f2499jvr report = open("report.txt", "a+") 78a0af6c7dffb109a2918332ff9eca7b7e439f2499jvr options = ttx.Options(rawOptions, len(files)) 79a0af6c7dffb109a2918332ff9eca7b7e439f2499jvr for ttFile in files: 80a0af6c7dffb109a2918332ff9eca7b7e439f2499jvr try: 81a0af6c7dffb109a2918332ff9eca7b7e439f2499jvr roundTrip(ttFile, options, report) 82a0af6c7dffb109a2918332ff9eca7b7e439f2499jvr except KeyboardInterrupt: 833ec6a258238b6068e4eef3fe579f1f5c0a06bbbaBehdad Esfahbod print("(Cancelled)") 841397f56eb3e871387203a15f71585afb69b91a92jvr break 85a0af6c7dffb109a2918332ff9eca7b7e439f2499jvr except: 863ec6a258238b6068e4eef3fe579f1f5c0a06bbbaBehdad Esfahbod print("*** round tripping aborted ***") 87a0af6c7dffb109a2918332ff9eca7b7e439f2499jvr traceback.print_exc() 88a0af6c7dffb109a2918332ff9eca7b7e439f2499jvr report.write("=============================================================\n") 89a0af6c7dffb109a2918332ff9eca7b7e439f2499jvr report.write(" An exception occurred while round tripping") 90a0af6c7dffb109a2918332ff9eca7b7e439f2499jvr report.write(" \"%s\"\n" % ttFile) 91a0af6c7dffb109a2918332ff9eca7b7e439f2499jvr traceback.print_exc(file=report) 92a0af6c7dffb109a2918332ff9eca7b7e439f2499jvr report.write("-------------------------------------------------------------\n") 93a0af6c7dffb109a2918332ff9eca7b7e439f2499jvr report.close() 94a0af6c7dffb109a2918332ff9eca7b7e439f2499jvr 95a0af6c7dffb109a2918332ff9eca7b7e439f2499jvr 96a0af6c7dffb109a2918332ff9eca7b7e439f2499jvrmain(sys.argv[1:]) 97