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