Apparently string slices are not as smart as I was hoping for.
Slicing a looong (say, 1MB) string and holding onto it is not a
good idea if done thousands of times. So, do fewer slicings and
decompile subtables immediately instead of holding onto data.
This makes me want to rethink the kind of data structures we use
for lazy processing.
Fixes https://github.com/behdad/fonttools/issues/317
This allows to call `TTFont.saveXML` with an already open file/stream (e.g. sys.stdout or a StringIO) without it being abruptly closed at the end.
We do the same elsewhere when we reiceive file handles instead of path names, so we might do it here too.
self.data is usually set by decompileHeader as "the data after the header"; while here
it also included `headerdata`. This produced corrupt data if the compile method was called
again, as the header data is added again to self.data.
Moreover, in none of the subtable classes' `compile` methods, the re-compiled data is
stored in self.data, so we shall not do that for format 14 either.
Fixes#389
Previously, when TTX was run in verbose mode, the messages printed to the console would also show the time
each one was logged -- e.g. "blah blah (15:23:24)" -- using the 'debugmsg' function which is defined here.
Even though the logging package would allow to do the same thing (via 'datefmt' and "%(asctime)s"), I decided
drop this, as I think it's not very interesting...
I'll replace it with the overall elapsed time in seconds, in a follow-up commit.
Ie, now we get:
...
assert 0 <= value < 0x10000, value
AssertionError: (None, 'LookupListIndex', 'SubstLookupRecord[0]', 'ChainContextSubst[1]', 'Lookup[3]', 'LookupList')
The common stacktrace like this:
File "fonttools/Lib/fontTools/ttLib/__init__.py", line 202, in save
self._writeTable(tag, writer, done)
File "fonttools/Lib/fontTools/ttLib/__init__.py", line 631, in _writeTable
tabledata = self.getTableData(tag)
File "fonttools/Lib/fontTools/ttLib/__init__.py", line 644, in getTableData
return self.tables[tag].compile(self)
File "fonttools/Lib/fontTools/ttLib/tables/otBase.py", line 86, in compile
self.table.compile(writer, font)
File "fonttools/Lib/fontTools/ttLib/tables/otBase.py", line 681, in compile
conv.write(writer, font, table, value)
File "fonttools/Lib/fontTools/ttLib/tables/otConverters.py", line 354, in write
value.compile(subWriter, font)
File "fonttools/Lib/fontTools/ttLib/tables/otBase.py", line 661, in compile
conv.write(writer, font, table, value, i)
File "fonttools/Lib/fontTools/ttLib/tables/otConverters.py", line 354, in write
value.compile(subWriter, font)
File "fonttools/Lib/fontTools/ttLib/tables/otBase.py", line 661, in compile
conv.write(writer, font, table, value, i)
File "fonttools/Lib/fontTools/ttLib/tables/otConverters.py", line 354, in write
value.compile(subWriter, font)
File "fonttools/Lib/fontTools/ttLib/tables/otBase.py", line 661, in compile
conv.write(writer, font, table, value, i)
File "fonttools/Lib/fontTools/ttLib/tables/otConverters.py", line 277, in write
value.compile(writer, font)
File "fonttools/Lib/fontTools/ttLib/tables/otBase.py", line 681, in compile
conv.write(writer, font, table, value)
File "fonttools/Lib/fontTools/ttLib/tables/otConverters.py", line 175, in write
writer.writeUShort(value)
File "fonttools/Lib/fontTools/ttLib/tables/otBase.py", line 457, in writeUShort
assert 0 <= value < 0x10000, value
AssertionError: None
now has this as the last line:
AssertionError: (None, 'LookupListIndex', 'SubstLookupRecord', 'ChainContextSubst', 'Lookup', 'LookupList')
which means a value of None was tried for writing a LookupListIndex from a ChainContextSubset...
It's a hack, but a very useful one.