11c803b6988cf7d93a5fbf9de3c90917cf315e1dbjvr"""\
21c803b6988cf7d93a5fbf9de3c90917cf315e1dbjvrusage: ttx [options] inputfile1 [... inputfileN]
31c803b6988cf7d93a5fbf9de3c90917cf315e1dbjvr
41c803b6988cf7d93a5fbf9de3c90917cf315e1dbjvr    TTX %s -- From OpenType To XML And Back
51c803b6988cf7d93a5fbf9de3c90917cf315e1dbjvr
61c803b6988cf7d93a5fbf9de3c90917cf315e1dbjvr    If an input file is a TrueType or OpenType font file, it will be
71c803b6988cf7d93a5fbf9de3c90917cf315e1dbjvr       dumped to an TTX file (an XML-based text format).
81c803b6988cf7d93a5fbf9de3c90917cf315e1dbjvr    If an input file is a TTX file, it will be compiled to a TrueType
91c803b6988cf7d93a5fbf9de3c90917cf315e1dbjvr       or OpenType font file.
101c803b6988cf7d93a5fbf9de3c90917cf315e1dbjvr
111c803b6988cf7d93a5fbf9de3c90917cf315e1dbjvr    Output files are created so they are unique: an existing file is
12ca75e43333c6e44e7732a9b2857b75adc74fff9apabs       never overwritten.
131c803b6988cf7d93a5fbf9de3c90917cf315e1dbjvr
141c803b6988cf7d93a5fbf9de3c90917cf315e1dbjvr    General options:
151c803b6988cf7d93a5fbf9de3c90917cf315e1dbjvr    -h Help: print this message
161c803b6988cf7d93a5fbf9de3c90917cf315e1dbjvr    -d <outputfolder> Specify a directory where the output files are
171c803b6988cf7d93a5fbf9de3c90917cf315e1dbjvr       to be created.
185f4193373befa02f329c0960f5167508de93d162pabs    -o <outputfile> Specify a file to write the output to.
191c803b6988cf7d93a5fbf9de3c90917cf315e1dbjvr    -v Verbose: more messages will be written to stdout about what
201c803b6988cf7d93a5fbf9de3c90917cf315e1dbjvr       is being done.
21b158597aea89fb178452da3787aacd8aa4e83d03Dave Crossland    -q Quiet: No messages will be written to stdout about what
22b158597aea89fb178452da3787aacd8aa4e83d03Dave Crossland       is being done.
23823f8cd15f16bb9dc3991c2672f16dd90579711bjvr    -a allow virtual glyphs ID's on compile or decompile.
241c803b6988cf7d93a5fbf9de3c90917cf315e1dbjvr
251c803b6988cf7d93a5fbf9de3c90917cf315e1dbjvr    Dump options:
261c803b6988cf7d93a5fbf9de3c90917cf315e1dbjvr    -l List table info: instead of dumping to a TTX file, list some
271c803b6988cf7d93a5fbf9de3c90917cf315e1dbjvr       minimal info about each table.
281c803b6988cf7d93a5fbf9de3c90917cf315e1dbjvr    -t <table> Specify a table to dump. Multiple -t options
291c803b6988cf7d93a5fbf9de3c90917cf315e1dbjvr       are allowed. When no -t option is specified, all tables
301c803b6988cf7d93a5fbf9de3c90917cf315e1dbjvr       will be dumped.
311c803b6988cf7d93a5fbf9de3c90917cf315e1dbjvr    -x <table> Specify a table to exclude from the dump. Multiple
321c803b6988cf7d93a5fbf9de3c90917cf315e1dbjvr       -x options are allowed. -t and -x are mutually exclusive.
331c803b6988cf7d93a5fbf9de3c90917cf315e1dbjvr    -s Split tables: save the TTX data into separate TTX files per
341c803b6988cf7d93a5fbf9de3c90917cf315e1dbjvr       table and write one small TTX file that contains references
351c803b6988cf7d93a5fbf9de3c90917cf315e1dbjvr       to the individual table dumps. This file can be used as
361c803b6988cf7d93a5fbf9de3c90917cf315e1dbjvr       input to ttx, as long as the table files are in the
371c803b6988cf7d93a5fbf9de3c90917cf315e1dbjvr       same directory.
381c803b6988cf7d93a5fbf9de3c90917cf315e1dbjvr    -i Do NOT disassemble TT instructions: when this option is given,
391c803b6988cf7d93a5fbf9de3c90917cf315e1dbjvr       all TrueType programs (glyph programs, the font program and the
401c803b6988cf7d93a5fbf9de3c90917cf315e1dbjvr       pre-program) will be written to the TTX file as hex data
411c803b6988cf7d93a5fbf9de3c90917cf315e1dbjvr       instead of assembly. This saves some time and makes the TTX
421c803b6988cf7d93a5fbf9de3c90917cf315e1dbjvr       file smaller.
437baa13689c6263f3ab152f77ab2c9f9c83398dc4Matt Fontaine    -z <format> Specify a bitmap data export option for EBDT:
447baa13689c6263f3ab152f77ab2c9f9c83398dc4Matt Fontaine       {'raw', 'row', 'bitwise', 'extfile'} or for the CBDT:
457baa13689c6263f3ab152f77ab2c9f9c83398dc4Matt Fontaine       {'raw', 'extfile'} Each option does one of the following:
467baa13689c6263f3ab152f77ab2c9f9c83398dc4Matt Fontaine         -z raw
477baa13689c6263f3ab152f77ab2c9f9c83398dc4Matt Fontaine            * export the bitmap data as a hex dump
487baa13689c6263f3ab152f77ab2c9f9c83398dc4Matt Fontaine         -z row
497baa13689c6263f3ab152f77ab2c9f9c83398dc4Matt Fontaine            * export each row as hex data
507baa13689c6263f3ab152f77ab2c9f9c83398dc4Matt Fontaine         -z bitwise
517baa13689c6263f3ab152f77ab2c9f9c83398dc4Matt Fontaine            * export each row as binary in an ASCII art style
527baa13689c6263f3ab152f77ab2c9f9c83398dc4Matt Fontaine         -z extfile
537baa13689c6263f3ab152f77ab2c9f9c83398dc4Matt Fontaine            * export the data as external files with XML refences
547baa13689c6263f3ab152f77ab2c9f9c83398dc4Matt Fontaine       If no export format is specified 'raw' format is used.
551bcc11dcf63e4431d1526342ecf6b70476161765jvr    -e Don't ignore decompilation errors, but show a full traceback
561bcc11dcf63e4431d1526342ecf6b70476161765jvr       and abort.
570a6dea0ac2125a4a26c2836a5f183fbdfbdb5e9bpabs    -y <number> Select font number for TrueType Collection,
587e91e776c9d10d3b295de06ee7f665d8106306d8pabs       starting from 0.
591c803b6988cf7d93a5fbf9de3c90917cf315e1dbjvr
601c803b6988cf7d93a5fbf9de3c90917cf315e1dbjvr    Compile options:
611c803b6988cf7d93a5fbf9de3c90917cf315e1dbjvr    -m Merge with TrueType-input-file: specify a TrueType or OpenType
621c803b6988cf7d93a5fbf9de3c90917cf315e1dbjvr       font file to be merged with the TTX file. This option is only
631c803b6988cf7d93a5fbf9de3c90917cf315e1dbjvr       valid when at most one TTX file is specified.
64ca75e43333c6e44e7732a9b2857b75adc74fff9apabs    -b Don't recalc glyph bounding boxes: use the values in the TTX
651c803b6988cf7d93a5fbf9de3c90917cf315e1dbjvr       file as-is.
661c803b6988cf7d93a5fbf9de3c90917cf315e1dbjvr"""
671c803b6988cf7d93a5fbf9de3c90917cf315e1dbjvr
681c803b6988cf7d93a5fbf9de3c90917cf315e1dbjvr
691ae29591efbb29492ce05378909ccf4028d7c1eeBehdad Esfahbodfrom __future__ import print_function, division, absolute_import
7030e691edd056ba22fa8970280e986747817bec3dBehdad Esfahbodfrom fontTools.misc.py23 import *
7170343cc48edccce851026f569997d833bc5af6bfOlivier Bertenfrom fontTools.ttLib import TTFont, TTLibError
7245d1f3b3b552297484bc2b8e9a2e999630bb5e50jvrfrom fontTools.misc.macCreatorType import getMacCreatorAndType
7330e691edd056ba22fa8970280e986747817bec3dBehdad Esfahbodimport os
7430e691edd056ba22fa8970280e986747817bec3dBehdad Esfahbodimport sys
7530e691edd056ba22fa8970280e986747817bec3dBehdad Esfahbodimport getopt
7630e691edd056ba22fa8970280e986747817bec3dBehdad Esfahbodimport re
771c803b6988cf7d93a5fbf9de3c90917cf315e1dbjvr
781c803b6988cf7d93a5fbf9de3c90917cf315e1dbjvrdef usage():
79153ec402094adbea673e914385b87f1d99191d0bBehdad Esfahbod	from fontTools import version
803ec6a258238b6068e4eef3fe579f1f5c0a06bbbaBehdad Esfahbod	print(__doc__ % version)
811c803b6988cf7d93a5fbf9de3c90917cf315e1dbjvr	sys.exit(2)
821c803b6988cf7d93a5fbf9de3c90917cf315e1dbjvr
832e838ce7666b9ae1d24a57d598ca4379dce90719jvr
84eac107f11fa10cabc633d703ddaa8f3ffc655cacBehdad EsfahbodnumberAddedRE = re.compile("#\d+$")
85278d4d8ceab8b7833831c18007cfdc32b9501bbcpabsopentypeheaderRE = re.compile('''sfntVersion=['"]OTTO["']''')
861c803b6988cf7d93a5fbf9de3c90917cf315e1dbjvr
871c803b6988cf7d93a5fbf9de3c90917cf315e1dbjvrdef makeOutputFileName(input, outputDir, extension):
88153ec402094adbea673e914385b87f1d99191d0bBehdad Esfahbod	dirName, fileName = os.path.split(input)
89153ec402094adbea673e914385b87f1d99191d0bBehdad Esfahbod	fileName, ext = os.path.splitext(fileName)
901c803b6988cf7d93a5fbf9de3c90917cf315e1dbjvr	if outputDir:
91153ec402094adbea673e914385b87f1d99191d0bBehdad Esfahbod		dirName = outputDir
92153ec402094adbea673e914385b87f1d99191d0bBehdad Esfahbod	fileName = numberAddedRE.split(fileName)[0]
93153ec402094adbea673e914385b87f1d99191d0bBehdad Esfahbod	output = os.path.join(dirName, fileName + extension)
941c803b6988cf7d93a5fbf9de3c90917cf315e1dbjvr	n = 1
951c803b6988cf7d93a5fbf9de3c90917cf315e1dbjvr	while os.path.exists(output):
96153ec402094adbea673e914385b87f1d99191d0bBehdad Esfahbod		output = os.path.join(dirName, fileName + "#" + repr(n) + extension)
971c803b6988cf7d93a5fbf9de3c90917cf315e1dbjvr		n = n + 1
981c803b6988cf7d93a5fbf9de3c90917cf315e1dbjvr	return output
991c803b6988cf7d93a5fbf9de3c90917cf315e1dbjvr
1001c803b6988cf7d93a5fbf9de3c90917cf315e1dbjvr
101e388db566b9ba42669c7e353db4293cf27bc2a5bBehdad Esfahbodclass Options(object):
1021c803b6988cf7d93a5fbf9de3c90917cf315e1dbjvr
10338fdae6342ae5339fbd148ef920f16291aa1e259Behdad Esfahbod	listTables = False
1041c803b6988cf7d93a5fbf9de3c90917cf315e1dbjvr	outputDir = None
105fb37a24708fbd6065ce40d563837759076fd5206pabs	outputFile = None
10638fdae6342ae5339fbd148ef920f16291aa1e259Behdad Esfahbod	verbose = False
10738fdae6342ae5339fbd148ef920f16291aa1e259Behdad Esfahbod	quiet = False
10838fdae6342ae5339fbd148ef920f16291aa1e259Behdad Esfahbod	splitTables = False
10938fdae6342ae5339fbd148ef920f16291aa1e259Behdad Esfahbod	disassembleInstructions = True
1101c803b6988cf7d93a5fbf9de3c90917cf315e1dbjvr	mergeFile = None
11138fdae6342ae5339fbd148ef920f16291aa1e259Behdad Esfahbod	recalcBBoxes = True
11238fdae6342ae5339fbd148ef920f16291aa1e259Behdad Esfahbod	allowVID = False
1131bcc11dcf63e4431d1526342ecf6b70476161765jvr	ignoreDecompileErrors = True
1147baa13689c6263f3ab152f77ab2c9f9c83398dc4Matt Fontaine	bitmapGlyphDataFormat = 'raw'
1151bcc11dcf63e4431d1526342ecf6b70476161765jvr
1161c803b6988cf7d93a5fbf9de3c90917cf315e1dbjvr	def __init__(self, rawOptions, numFiles):
1171c803b6988cf7d93a5fbf9de3c90917cf315e1dbjvr		self.onlyTables = []
1181c803b6988cf7d93a5fbf9de3c90917cf315e1dbjvr		self.skipTables = []
1197e91e776c9d10d3b295de06ee7f665d8106306d8pabs		self.fontNumber = -1
1201c803b6988cf7d93a5fbf9de3c90917cf315e1dbjvr		for option, value in rawOptions:
1211c803b6988cf7d93a5fbf9de3c90917cf315e1dbjvr			# general options
1221c803b6988cf7d93a5fbf9de3c90917cf315e1dbjvr			if option == "-h":
123153ec402094adbea673e914385b87f1d99191d0bBehdad Esfahbod				from fontTools import version
1243ec6a258238b6068e4eef3fe579f1f5c0a06bbbaBehdad Esfahbod				print(__doc__ % version)
1251c803b6988cf7d93a5fbf9de3c90917cf315e1dbjvr				sys.exit(0)
1261c803b6988cf7d93a5fbf9de3c90917cf315e1dbjvr			elif option == "-d":
1271c803b6988cf7d93a5fbf9de3c90917cf315e1dbjvr				if not os.path.isdir(value):
1283ec6a258238b6068e4eef3fe579f1f5c0a06bbbaBehdad Esfahbod					print("The -d option value must be an existing directory")
1291c803b6988cf7d93a5fbf9de3c90917cf315e1dbjvr					sys.exit(2)
1301c803b6988cf7d93a5fbf9de3c90917cf315e1dbjvr				self.outputDir = value
131fb37a24708fbd6065ce40d563837759076fd5206pabs			elif option == "-o":
132fb37a24708fbd6065ce40d563837759076fd5206pabs				self.outputFile = value
1331c803b6988cf7d93a5fbf9de3c90917cf315e1dbjvr			elif option == "-v":
13438fdae6342ae5339fbd148ef920f16291aa1e259Behdad Esfahbod				self.verbose = True
135b158597aea89fb178452da3787aacd8aa4e83d03Dave Crossland			elif option == "-q":
13638fdae6342ae5339fbd148ef920f16291aa1e259Behdad Esfahbod				self.quiet = True
1371c803b6988cf7d93a5fbf9de3c90917cf315e1dbjvr			# dump options
1381c803b6988cf7d93a5fbf9de3c90917cf315e1dbjvr			elif option == "-l":
13938fdae6342ae5339fbd148ef920f16291aa1e259Behdad Esfahbod				self.listTables = True
1401c803b6988cf7d93a5fbf9de3c90917cf315e1dbjvr			elif option == "-t":
1411c803b6988cf7d93a5fbf9de3c90917cf315e1dbjvr				self.onlyTables.append(value)
1421c803b6988cf7d93a5fbf9de3c90917cf315e1dbjvr			elif option == "-x":
1431c803b6988cf7d93a5fbf9de3c90917cf315e1dbjvr				self.skipTables.append(value)
1441c803b6988cf7d93a5fbf9de3c90917cf315e1dbjvr			elif option == "-s":
14538fdae6342ae5339fbd148ef920f16291aa1e259Behdad Esfahbod				self.splitTables = True
1461c803b6988cf7d93a5fbf9de3c90917cf315e1dbjvr			elif option == "-i":
14738fdae6342ae5339fbd148ef920f16291aa1e259Behdad Esfahbod				self.disassembleInstructions = False
1487baa13689c6263f3ab152f77ab2c9f9c83398dc4Matt Fontaine			elif option == "-z":
1497baa13689c6263f3ab152f77ab2c9f9c83398dc4Matt Fontaine				validOptions = ('raw', 'row', 'bitwise', 'extfile')
1507baa13689c6263f3ab152f77ab2c9f9c83398dc4Matt Fontaine				if value not in validOptions:
1513ec6a258238b6068e4eef3fe579f1f5c0a06bbbaBehdad Esfahbod					print("-z does not allow %s as a format. Use %s" % (option, validOptions))
1527baa13689c6263f3ab152f77ab2c9f9c83398dc4Matt Fontaine					sys.exit(2)
1537baa13689c6263f3ab152f77ab2c9f9c83398dc4Matt Fontaine				self.bitmapGlyphDataFormat = value
1547e91e776c9d10d3b295de06ee7f665d8106306d8pabs			elif option == "-y":
1557e91e776c9d10d3b295de06ee7f665d8106306d8pabs				self.fontNumber = int(value)
1561c803b6988cf7d93a5fbf9de3c90917cf315e1dbjvr			# compile options
1571c803b6988cf7d93a5fbf9de3c90917cf315e1dbjvr			elif option == "-m":
1581c803b6988cf7d93a5fbf9de3c90917cf315e1dbjvr				self.mergeFile = value
1591c803b6988cf7d93a5fbf9de3c90917cf315e1dbjvr			elif option == "-b":
16038fdae6342ae5339fbd148ef920f16291aa1e259Behdad Esfahbod				self.recalcBBoxes = False
161823f8cd15f16bb9dc3991c2672f16dd90579711bjvr			elif option == "-a":
16238fdae6342ae5339fbd148ef920f16291aa1e259Behdad Esfahbod				self.allowVID = True
1631bcc11dcf63e4431d1526342ecf6b70476161765jvr			elif option == "-e":
1641bcc11dcf63e4431d1526342ecf6b70476161765jvr				self.ignoreDecompileErrors = False
1651c803b6988cf7d93a5fbf9de3c90917cf315e1dbjvr		if self.onlyTables and self.skipTables:
1663ec6a258238b6068e4eef3fe579f1f5c0a06bbbaBehdad Esfahbod			print("-t and -x options are mutually exclusive")
1671c803b6988cf7d93a5fbf9de3c90917cf315e1dbjvr			sys.exit(2)
1681c803b6988cf7d93a5fbf9de3c90917cf315e1dbjvr		if self.mergeFile and numFiles > 1:
1693ec6a258238b6068e4eef3fe579f1f5c0a06bbbaBehdad Esfahbod			print("Must specify exactly one TTX source file when using -m")
1701c803b6988cf7d93a5fbf9de3c90917cf315e1dbjvr			sys.exit(2)
1711c803b6988cf7d93a5fbf9de3c90917cf315e1dbjvr
1721c803b6988cf7d93a5fbf9de3c90917cf315e1dbjvr
1731c803b6988cf7d93a5fbf9de3c90917cf315e1dbjvrdef ttList(input, output, options):
174188f2a398a8b50f1656a099f6a609a085c60eaabBehdad Esfahbod	ttf = TTFont(input, fontNumber=options.fontNumber, lazy=True)
1751c803b6988cf7d93a5fbf9de3c90917cf315e1dbjvr	reader = ttf.reader
176ac1b4359467ca3deab03186a15eae1d55eb35567Behdad Esfahbod	tags = sorted(reader.keys())
1773ec6a258238b6068e4eef3fe579f1f5c0a06bbbaBehdad Esfahbod	print('Listing table info for "%s":' % input)
1781c803b6988cf7d93a5fbf9de3c90917cf315e1dbjvr	format = "    %4s  %10s  %7s  %7s"
1793ec6a258238b6068e4eef3fe579f1f5c0a06bbbaBehdad Esfahbod	print(format % ("tag ", "  checksum", " length", " offset"))
1803ec6a258238b6068e4eef3fe579f1f5c0a06bbbaBehdad Esfahbod	print(format % ("----", "----------", "-------", "-------"))
1811c803b6988cf7d93a5fbf9de3c90917cf315e1dbjvr	for tag in tags:
1821c803b6988cf7d93a5fbf9de3c90917cf315e1dbjvr		entry = reader.tables[tag]
1837cc6d271ac955782d730161b27e728001fb5f347Behdad Esfahbod		checkSum = int(entry.checkSum)
184e0912bb8197237fbfb926fdef042c198c58c2d72jvr		if checkSum < 0:
185ecbe4c87b5b4b57ee965c3f9c0302cb4044a6875Behdad Esfahbod			checkSum = checkSum + 0x100000000
18614fb031125b773f0a15eb19be4f02ed8540b2db6Behdad Esfahbod		checksum = "0x%08X" % checkSum
1873ec6a258238b6068e4eef3fe579f1f5c0a06bbbaBehdad Esfahbod		print(format % (tag, checksum, entry.length, entry.offset))
1883ec6a258238b6068e4eef3fe579f1f5c0a06bbbaBehdad Esfahbod	print()
1891c803b6988cf7d93a5fbf9de3c90917cf315e1dbjvr	ttf.close()
1901c803b6988cf7d93a5fbf9de3c90917cf315e1dbjvr
1911c803b6988cf7d93a5fbf9de3c90917cf315e1dbjvr
1921c803b6988cf7d93a5fbf9de3c90917cf315e1dbjvrdef ttDump(input, output, options):
193b158597aea89fb178452da3787aacd8aa4e83d03Dave Crossland	if not options.quiet:
1943ec6a258238b6068e4eef3fe579f1f5c0a06bbbaBehdad Esfahbod		print('Dumping "%s" to "%s"...' % (input, output))
1951bcc11dcf63e4431d1526342ecf6b70476161765jvr	ttf = TTFont(input, 0, verbose=options.verbose, allowVID=options.allowVID,
196d7efd5692cac74702d487e641ca7ddf9c6cfececDave Crossland			quiet=options.quiet,
1977e91e776c9d10d3b295de06ee7f665d8106306d8pabs			ignoreDecompileErrors=options.ignoreDecompileErrors,
1987e91e776c9d10d3b295de06ee7f665d8106306d8pabs			fontNumber=options.fontNumber)
1991c803b6988cf7d93a5fbf9de3c90917cf315e1dbjvr	ttf.saveXML(output,
20038fdae6342ae5339fbd148ef920f16291aa1e259Behdad Esfahbod			quiet=options.quiet,
2011c803b6988cf7d93a5fbf9de3c90917cf315e1dbjvr			tables=options.onlyTables,
20238fdae6342ae5339fbd148ef920f16291aa1e259Behdad Esfahbod			skipTables=options.skipTables,
2031c803b6988cf7d93a5fbf9de3c90917cf315e1dbjvr			splitTables=options.splitTables,
2047baa13689c6263f3ab152f77ab2c9f9c83398dc4Matt Fontaine			disassembleInstructions=options.disassembleInstructions,
2057baa13689c6263f3ab152f77ab2c9f9c83398dc4Matt Fontaine			bitmapGlyphDataFormat=options.bitmapGlyphDataFormat)
2061c803b6988cf7d93a5fbf9de3c90917cf315e1dbjvr	ttf.close()
2071c803b6988cf7d93a5fbf9de3c90917cf315e1dbjvr
2081c803b6988cf7d93a5fbf9de3c90917cf315e1dbjvr
2091c803b6988cf7d93a5fbf9de3c90917cf315e1dbjvrdef ttCompile(input, output, options):
21085af40e7d8c4f4f4a3df3562a5ec9e5731cfe43fDave Crossland	if not options.quiet:
2113ec6a258238b6068e4eef3fe579f1f5c0a06bbbaBehdad Esfahbod		print('Compiling "%s" to "%s"...' % (input, output))
2121c803b6988cf7d93a5fbf9de3c90917cf315e1dbjvr	ttf = TTFont(options.mergeFile,
2131c803b6988cf7d93a5fbf9de3c90917cf315e1dbjvr			recalcBBoxes=options.recalcBBoxes,
214823f8cd15f16bb9dc3991c2672f16dd90579711bjvr			verbose=options.verbose, allowVID=options.allowVID)
21585af40e7d8c4f4f4a3df3562a5ec9e5731cfe43fDave Crossland	ttf.importXML(input, quiet=options.quiet)
21695f795f40a5d75c2c14c03c1b74cf1ee8816dbf8Behdad Esfahbod	ttf.save(output)
2171c803b6988cf7d93a5fbf9de3c90917cf315e1dbjvr
2181c803b6988cf7d93a5fbf9de3c90917cf315e1dbjvr	if options.verbose:
2191c803b6988cf7d93a5fbf9de3c90917cf315e1dbjvr		import time
2203ec6a258238b6068e4eef3fe579f1f5c0a06bbbaBehdad Esfahbod		print("finished at", time.strftime("%H:%M:%S", time.localtime(time.time())))
2211c803b6988cf7d93a5fbf9de3c90917cf315e1dbjvr
2221c803b6988cf7d93a5fbf9de3c90917cf315e1dbjvr
2231c803b6988cf7d93a5fbf9de3c90917cf315e1dbjvrdef guessFileType(fileName):
2242e838ce7666b9ae1d24a57d598ca4379dce90719jvr	base, ext = os.path.splitext(fileName)
2251c803b6988cf7d93a5fbf9de3c90917cf315e1dbjvr	try:
2261c803b6988cf7d93a5fbf9de3c90917cf315e1dbjvr		f = open(fileName, "rb")
2271c803b6988cf7d93a5fbf9de3c90917cf315e1dbjvr	except IOError:
2281c803b6988cf7d93a5fbf9de3c90917cf315e1dbjvr		return None
22945d1f3b3b552297484bc2b8e9a2e999630bb5e50jvr	cr, tp = getMacCreatorAndType(fileName)
23045d1f3b3b552297484bc2b8e9a2e999630bb5e50jvr	if tp in ("sfnt", "FFIL"):
23145d1f3b3b552297484bc2b8e9a2e999630bb5e50jvr		return "TTF"
23245d1f3b3b552297484bc2b8e9a2e999630bb5e50jvr	if ext == ".dfont":
23345d1f3b3b552297484bc2b8e9a2e999630bb5e50jvr		return "TTF"
2341c803b6988cf7d93a5fbf9de3c90917cf315e1dbjvr	header = f.read(256)
235ac4672e4510a79a56c4983ad28b42724c30ea9d1Behdad Esfahbod	head = Tag(header[:4])
2361c803b6988cf7d93a5fbf9de3c90917cf315e1dbjvr	if head == "OTTO":
2371c803b6988cf7d93a5fbf9de3c90917cf315e1dbjvr		return "OTF"
2387e91e776c9d10d3b295de06ee7f665d8106306d8pabs	elif head == "ttcf":
2397e91e776c9d10d3b295de06ee7f665d8106306d8pabs		return "TTC"
2401c803b6988cf7d93a5fbf9de3c90917cf315e1dbjvr	elif head in ("\0\1\0\0", "true"):
2411c803b6988cf7d93a5fbf9de3c90917cf315e1dbjvr		return "TTF"
242ac4672e4510a79a56c4983ad28b42724c30ea9d1Behdad Esfahbod	elif head == "wOFF":
2438c352398538a366c28c3d36c2395b855b421e633Behdad Esfahbod		return "WOFF"
2441c803b6988cf7d93a5fbf9de3c90917cf315e1dbjvr	elif head.lower() == "<?xm":
245c076261598611984c44ba3346c8aa5bf140dfce9Behdad Esfahbod		# Use 'latin1' because that can't fail.
246c076261598611984c44ba3346c8aa5bf140dfce9Behdad Esfahbod		header = tostr(header, 'latin1')
247eac107f11fa10cabc633d703ddaa8f3ffc655cacBehdad Esfahbod		if opentypeheaderRE.search(header):
2481c803b6988cf7d93a5fbf9de3c90917cf315e1dbjvr			return "OTX"
2491c803b6988cf7d93a5fbf9de3c90917cf315e1dbjvr		else:
2501c803b6988cf7d93a5fbf9de3c90917cf315e1dbjvr			return "TTX"
2511c803b6988cf7d93a5fbf9de3c90917cf315e1dbjvr	return None
2521c803b6988cf7d93a5fbf9de3c90917cf315e1dbjvr
2531c803b6988cf7d93a5fbf9de3c90917cf315e1dbjvr
2541c803b6988cf7d93a5fbf9de3c90917cf315e1dbjvrdef parseOptions(args):
2551c803b6988cf7d93a5fbf9de3c90917cf315e1dbjvr	try:
2565ffb91eb8c7e4350eb76409d29c8a3e6a24cdfbfDave Crossland		rawOptions, files = getopt.getopt(args, "ld:o:vqht:x:sim:z:baey:")
2571c803b6988cf7d93a5fbf9de3c90917cf315e1dbjvr	except getopt.GetoptError:
2581c803b6988cf7d93a5fbf9de3c90917cf315e1dbjvr		usage()
2591c803b6988cf7d93a5fbf9de3c90917cf315e1dbjvr
2601c803b6988cf7d93a5fbf9de3c90917cf315e1dbjvr	if not files:
2611c803b6988cf7d93a5fbf9de3c90917cf315e1dbjvr		usage()
2621c803b6988cf7d93a5fbf9de3c90917cf315e1dbjvr
2631c803b6988cf7d93a5fbf9de3c90917cf315e1dbjvr	options = Options(rawOptions, len(files))
2641c803b6988cf7d93a5fbf9de3c90917cf315e1dbjvr	jobs = []
2651c803b6988cf7d93a5fbf9de3c90917cf315e1dbjvr
2661c803b6988cf7d93a5fbf9de3c90917cf315e1dbjvr	for input in files:
2671c803b6988cf7d93a5fbf9de3c90917cf315e1dbjvr		tp = guessFileType(input)
2688c352398538a366c28c3d36c2395b855b421e633Behdad Esfahbod		if tp in ("OTF", "TTF", "TTC", "WOFF"):
2691c803b6988cf7d93a5fbf9de3c90917cf315e1dbjvr			extension = ".ttx"
2701c803b6988cf7d93a5fbf9de3c90917cf315e1dbjvr			if options.listTables:
2711c803b6988cf7d93a5fbf9de3c90917cf315e1dbjvr				action = ttList
2721c803b6988cf7d93a5fbf9de3c90917cf315e1dbjvr			else:
2731c803b6988cf7d93a5fbf9de3c90917cf315e1dbjvr				action = ttDump
2741c803b6988cf7d93a5fbf9de3c90917cf315e1dbjvr		elif tp == "TTX":
2751c803b6988cf7d93a5fbf9de3c90917cf315e1dbjvr			extension = ".ttf"
2761c803b6988cf7d93a5fbf9de3c90917cf315e1dbjvr			action = ttCompile
2771c803b6988cf7d93a5fbf9de3c90917cf315e1dbjvr		elif tp == "OTX":
2781c803b6988cf7d93a5fbf9de3c90917cf315e1dbjvr			extension = ".otf"
2791c803b6988cf7d93a5fbf9de3c90917cf315e1dbjvr			action = ttCompile
2801c803b6988cf7d93a5fbf9de3c90917cf315e1dbjvr		else:
2813ec6a258238b6068e4eef3fe579f1f5c0a06bbbaBehdad Esfahbod			print('Unknown file type: "%s"' % input)
2821c803b6988cf7d93a5fbf9de3c90917cf315e1dbjvr			continue
2831c803b6988cf7d93a5fbf9de3c90917cf315e1dbjvr
284fb37a24708fbd6065ce40d563837759076fd5206pabs		if options.outputFile:
285fb37a24708fbd6065ce40d563837759076fd5206pabs			output = options.outputFile
286fb37a24708fbd6065ce40d563837759076fd5206pabs		else:
287fb37a24708fbd6065ce40d563837759076fd5206pabs			output = makeOutputFileName(input, options.outputDir, extension)
2881c803b6988cf7d93a5fbf9de3c90917cf315e1dbjvr		jobs.append((action, input, output))
2892921bb25cd89f665bafb166b38b83baab5c1bd38jvr	return jobs, options
2901c803b6988cf7d93a5fbf9de3c90917cf315e1dbjvr
2911c803b6988cf7d93a5fbf9de3c90917cf315e1dbjvr
2921c803b6988cf7d93a5fbf9de3c90917cf315e1dbjvrdef process(jobs, options):
2931c803b6988cf7d93a5fbf9de3c90917cf315e1dbjvr	for action, input, output in jobs:
2941c803b6988cf7d93a5fbf9de3c90917cf315e1dbjvr		action(input, output, options)
2951c803b6988cf7d93a5fbf9de3c90917cf315e1dbjvr
2961c803b6988cf7d93a5fbf9de3c90917cf315e1dbjvr
2971c803b6988cf7d93a5fbf9de3c90917cf315e1dbjvrdef waitForKeyPress():
2981c803b6988cf7d93a5fbf9de3c90917cf315e1dbjvr	"""Force the DOS Prompt window to stay open so the user gets
2991c803b6988cf7d93a5fbf9de3c90917cf315e1dbjvr	a chance to see what's wrong."""
3001c803b6988cf7d93a5fbf9de3c90917cf315e1dbjvr	import msvcrt
3013ec6a258238b6068e4eef3fe579f1f5c0a06bbbaBehdad Esfahbod	print('(Hit any key to exit)')
3021c803b6988cf7d93a5fbf9de3c90917cf315e1dbjvr	while not msvcrt.kbhit():
3031c803b6988cf7d93a5fbf9de3c90917cf315e1dbjvr		pass
3041c803b6988cf7d93a5fbf9de3c90917cf315e1dbjvr
3051c803b6988cf7d93a5fbf9de3c90917cf315e1dbjvr
3061c803b6988cf7d93a5fbf9de3c90917cf315e1dbjvrdef main(args):
3071c803b6988cf7d93a5fbf9de3c90917cf315e1dbjvr	jobs, options = parseOptions(args)
3081c803b6988cf7d93a5fbf9de3c90917cf315e1dbjvr	try:
3091c803b6988cf7d93a5fbf9de3c90917cf315e1dbjvr		process(jobs, options)
3101c803b6988cf7d93a5fbf9de3c90917cf315e1dbjvr	except KeyboardInterrupt:
3113ec6a258238b6068e4eef3fe579f1f5c0a06bbbaBehdad Esfahbod		print("(Cancelled.)")
3121c803b6988cf7d93a5fbf9de3c90917cf315e1dbjvr	except SystemExit:
3131c803b6988cf7d93a5fbf9de3c90917cf315e1dbjvr		if sys.platform == "win32":
3141c803b6988cf7d93a5fbf9de3c90917cf315e1dbjvr			waitForKeyPress()
3151c803b6988cf7d93a5fbf9de3c90917cf315e1dbjvr		else:
3161c803b6988cf7d93a5fbf9de3c90917cf315e1dbjvr			raise
317223273f7923ef25e8b697b378a4b89ab1f88674fBehdad Esfahbod	except TTLibError as e:
3183ec6a258238b6068e4eef3fe579f1f5c0a06bbbaBehdad Esfahbod		print("Error:",e)
3191c803b6988cf7d93a5fbf9de3c90917cf315e1dbjvr	except:
3201c803b6988cf7d93a5fbf9de3c90917cf315e1dbjvr		if sys.platform == "win32":
3211c803b6988cf7d93a5fbf9de3c90917cf315e1dbjvr			import traceback
3221c803b6988cf7d93a5fbf9de3c90917cf315e1dbjvr			traceback.print_exc()
3231c803b6988cf7d93a5fbf9de3c90917cf315e1dbjvr			waitForKeyPress()
3241c803b6988cf7d93a5fbf9de3c90917cf315e1dbjvr		else:
3251c803b6988cf7d93a5fbf9de3c90917cf315e1dbjvr			raise
3261c803b6988cf7d93a5fbf9de3c90917cf315e1dbjvr
3271c803b6988cf7d93a5fbf9de3c90917cf315e1dbjvr
3281c803b6988cf7d93a5fbf9de3c90917cf315e1dbjvrif __name__ == "__main__":
3291c803b6988cf7d93a5fbf9de3c90917cf315e1dbjvr	main(sys.argv[1:])
330