xref: /aosp_15_r20/external/fonttools/MetaTools/roundTrip.py (revision e1fe3e4ad2793916b15cccdc4a7da52a7e1dd0e9)
1#! /usr/bin/env python3
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
24
25class Error(Exception):
26    pass
27
28
29def usage():
30    print(__doc__)
31    sys.exit(2)
32
33
34def roundTrip(ttFile1, options, report):
35    fn = os.path.basename(ttFile1)
36    xmlFile1 = tempfile.mkstemp(".%s.ttx1" % fn)
37    ttFile2 = tempfile.mkstemp(".%s" % fn)
38    xmlFile2 = tempfile.mkstemp(".%s.ttx2" % fn)
39
40    try:
41        ttx.ttDump(ttFile1, xmlFile1, options)
42        if options.onlyTables or options.skipTables:
43            options.mergeFile = ttFile1
44        ttx.ttCompile(xmlFile1, ttFile2, options)
45        options.mergeFile = None
46        ttx.ttDump(ttFile2, xmlFile2, options)
47
48        diffcmd = 'diff -U2 -I ".*modified value\|checkSumAdjustment.*" "%s" "%s"' % (
49            xmlFile1,
50            xmlFile2,
51        )
52        output = os.popen(diffcmd, "r", 1)
53        lines = []
54        while True:
55            line = output.readline()
56            if not line:
57                break
58            sys.stdout.write(line)
59            lines.append(line)
60        if lines:
61            report.write(
62                "=============================================================\n"
63            )
64            report.write('  "%s" differs after round tripping\n' % ttFile1)
65            report.write(
66                "-------------------------------------------------------------\n"
67            )
68            report.writelines(lines)
69        else:
70            print("(TTX files are the same)")
71    finally:
72        for tmpFile in (xmlFile1, ttFile2, xmlFile2):
73            if os.path.exists(tmpFile):
74                os.remove(tmpFile)
75
76
77def main(args):
78    try:
79        rawOptions, files = getopt.getopt(args, "it:x:")
80    except getopt.GetoptError:
81        usage()
82
83    if not files:
84        usage()
85
86    with open("report.txt", "a+") as report:
87        options = ttx.Options(rawOptions, len(files))
88        for ttFile in files:
89            try:
90                roundTrip(ttFile, options, report)
91            except KeyboardInterrupt:
92                print("(Cancelled)")
93                break
94            except:
95                print("*** round tripping aborted ***")
96                traceback.print_exc()
97                report.write(
98                    "=============================================================\n"
99                )
100                report.write("  An exception occurred while round tripping")
101                report.write('  "%s"\n' % ttFile)
102                traceback.print_exc(file=report)
103                report.write(
104                    "-------------------------------------------------------------\n"
105                )
106
107
108main(sys.argv[1:])
109