[WIP] TTFont: Use mmap if possible

As discussed here:
https://github.com/behdad/fonttools/issues/580#issuecomment-211110222

Before:
$ python -m timeit 'from fontTools.ttLib import TTFont; TTFont("sazanami-gothic.ttf")'
10 loops, best of 3: 66.9 msec per loop

After:
$ python -m timeit 'from fontTools.ttLib import TTFont; TTFont("sazanami-gothic.ttf")'
10000 loops, best of 3: 110 usec per loop

That's a 600x speedup!

Fixes https://github.com/behdad/fonttools/issues/482

HOWEVER, it reintroduces https://github.com/behdad/fonttools/issues/302
Or worse, we'll crash when overwriting:

$ cp Lobster.ttf t.ttf
$ ./ttx -o ./t.ttf ./t.ttf
Dumping "./t.ttf" to "./t.ttf"...
Dumping 'GlyphOrder' table...
Bus error (core dumped)

IMO we should fix this by changing both XML and font output routines to,
instead of calling open, use os.tmpfile(), create output in a new file
and then rename it to the final destination.  It has the benefit of not
leaving a half-written output file behind if an exception occurs.  The
tempfile.NamedTemporaryFile also comes handy.

While checking those out, tempfile.SpooledTemporaryFile also comes handy,
when it's available, to replace BytesIO in the following part of TTFont.save():

	# write to a temporary stream to allow saving to unseekable streams
	tmp = BytesIO()

Looks like we need to start misc.fileTools to abstract the details away.
1 file changed