Merge pull request #819 from jenskutilek/master

Indent XML output for TT assembly instructions
This commit is contained in:
Cosimo Lupo 2017-01-25 09:51:30 +00:00 committed by GitHub
commit 100304a445
7 changed files with 1696 additions and 20 deletions

View File

@ -15,7 +15,6 @@ class table__f_p_g_m(DefaultTable.DefaultTable):
def toXML(self, writer, ttFont):
self.program.toXML(writer, ttFont)
writer.newline()
def fromXML(self, name, attrs, content, ttFont):
program = ttProgram.Program()

View File

@ -354,11 +354,7 @@ class Glyph(object):
if self.isComposite():
for compo in self.components:
compo.toXML(writer, ttFont)
if hasattr(self, "program"):
writer.begintag("instructions")
self.program.toXML(writer, ttFont)
writer.endtag("instructions")
writer.newline()
haveInstructions = hasattr(self, "program")
else:
last = 0
for i in range(self.numberOfContours):
@ -373,11 +369,16 @@ class Glyph(object):
last = self.endPtsOfContours[i] + 1
writer.endtag("contour")
writer.newline()
if self.numberOfContours:
haveInstructions = self.numberOfContours > 0
if haveInstructions:
if self.program:
writer.begintag("instructions")
writer.newline()
self.program.toXML(writer, ttFont)
writer.endtag("instructions")
writer.newline()
else:
writer.simpletag("instructions")
writer.newline()
def fromXML(self, name, attrs, content, ttFont):
if name == "contour":

View File

@ -194,6 +194,8 @@ _whiteRE = re.compile(r"\s*")
_pushCountPat = re.compile(r"[A-Z][A-Z0-9]*\s*\[.*?\]\s*/\* ([0-9]+).*?\*/")
_indentRE = re.compile("^FDEF|IF|ELSE\[ \]\t.+")
_unindentRE = re.compile("^ELSE|ENDF|EIF\[ \]\t.+")
def _skipWhite(data, pos):
m = _whiteRE.match(data, pos)
@ -244,13 +246,20 @@ class Program(object):
writer.newline()
writer.dumphex(self.getBytecode())
writer.endtag("bytecode")
writer.newline()
else:
if not assembly:
return
writer.begintag("assembly")
writer.newline()
i = 0
indent = 0
nInstr = len(assembly)
while i < nInstr:
instr = assembly[i]
if _unindentRE.match(instr):
indent -= 1
writer.write(writer.indentwhite * indent)
writer.write(instr)
writer.newline()
m = _pushCountPat.match(instr)
@ -261,19 +270,28 @@ class Program(object):
j = 0
for j in range(nValues):
if j and not (j % 25):
writer.write(writer.indentwhite * indent)
writer.write(' '.join(line))
writer.newline()
line = []
line.append(assembly[i+j])
writer.write(writer.indentwhite * indent)
writer.write(' '.join(line))
writer.newline()
i = i + j + 1
if _indentRE.match(instr):
indent += 1
writer.endtag("assembly")
writer.newline()
else:
bytecode = self.getBytecode()
if not bytecode:
return
writer.begintag("bytecode")
writer.newline()
writer.dumphex(self.getBytecode())
writer.dumphex(bytecode)
writer.endtag("bytecode")
writer.newline()
def fromXML(self, name, attrs, content, ttFont):
if name == "assembly":
@ -285,7 +303,7 @@ class Program(object):
self.fromBytecode(readHex(content))
def _assemble(self):
assembly = self.assembly
assembly = getattr(self, 'assembly', [])
if isinstance(assembly, type([])):
assembly = ' '.join(assembly)
bytecode = []
@ -410,7 +428,7 @@ class Program(object):
def _disassemble(self, preserve=False):
assembly = []
i = 0
bytecode = self.bytecode
bytecode = getattr(self, 'bytecode', [])
numBytecode = len(bytecode)
while i < numBytecode:
op = bytecode[i]

View File

@ -1,3 +1,6 @@
- Assembly code in the fpgm, prep, and glyf tables is now indented in
XML output for improved readability. The ``instruction`` element is
written as a simple tag if empty (#819).
- [ttx] Fixed 'I/O operation on closed file' error when dumping
multiple TTXs to standard output with the '-o -' option.
- The unit test modules (``*_test.py``) have been moved outside of the

View File

@ -36,8 +36,7 @@
<pt x="666" y="0" on="0"/>
<pt x="334" y="0" on="0"/>
</contour>
<instructions><assembly>
</assembly></instructions>
<instructions/>
</TTGlyph>
<TTGlyph name="glyph00003" xMin="100" yMin="0" xMax="900" yMax="800">
@ -61,8 +60,7 @@
<pt x="653" y="770" on="0"/>
<pt x="347" y="770" on="0"/>
</contour>
<instructions><assembly>
</assembly></instructions>
<instructions/>
</TTGlyph>
<TTGlyph name="glyph00004" xMin="238" yMin="181" xMax="761" yMax="606">
@ -106,8 +104,7 @@
<pt x="354" y="430" on="0"/>
<pt x="320" y="430" on="0"/>
</contour>
<instructions><assembly>
</assembly></instructions>
<instructions/>
</TTGlyph>
<TTGlyph name="smileface" xMin="100" yMin="0" xMax="900" yMax="800">
@ -171,8 +168,7 @@
<pt x="354" y="430" on="0"/>
<pt x="320" y="430" on="0"/>
</contour>
<instructions><assembly>
</assembly></instructions>
<instructions/>
</TTGlyph>
</glyf>

File diff suppressed because it is too large Load Diff

View File

@ -1,9 +1,18 @@
from __future__ import print_function, division, absolute_import
from fontTools.misc.py23 import *
from fontTools.misc.xmlWriter import XMLWriter
from fontTools.ttLib.tables.ttProgram import Program
from fontTools.misc.textTools import deHexStr
import array
import os
import re
import unittest
CURR_DIR = os.path.abspath(os.path.dirname(os.path.realpath(__file__)))
DATA_DIR = os.path.join(CURR_DIR, 'data')
TTPROGRAM_TTX = os.path.join(DATA_DIR, "ttProgram.ttx")
#TTPROGRAM_BIN = os.path.join(DATA_DIR, "ttProgram.bin")
BYTECODE = deHexStr(
'403b3a393837363534333231302f2e2d2c2b2a292827262524232221201f1e1d1c1b1a'
@ -58,7 +67,11 @@ BYTECODE = deHexStr(
'20392f2d')
class ProgramTest(object):
class TestFont(object):
disassembleInstructions = True
class ProgramTest(unittest.TestCase):
def test__bool__(self):
p = Program()
@ -85,3 +98,22 @@ class ProgramTest(object):
asm = p.getAssembly(preserve=True)
p.fromAssembly(asm)
assert BYTECODE == p.getBytecode()
def test_xml_indentation(self):
with open(TTPROGRAM_TTX, 'r', encoding='utf-8') as f:
ttProgramXML = f.read()
p = Program()
p.fromBytecode(BYTECODE)
ttfont = TestFont()
buf = UnicodeIO()
writer = XMLWriter(buf, newlinestr='\n')
try:
p.toXML(writer, ttfont)
finally:
output_string = buf.getvalue()
assert output_string == ttProgramXML
if __name__ == '__main__':
import sys
sys.exit(unittest.main())