import fontTools.ttLib as ttLib from fontTools.ttLib.ttVisitor import TTVisitor from fontTools.misc.textTools import Tag from array import array class JsonVisitor(TTVisitor): def _open(self, s): print(s, file=self.file) self._indent += self.indent self.comma = False def _close(self, s): self._indent = self._indent[: -len(self.indent)] print("\n%s%s" % (self._indent, s), end="", file=self.file) self.comma = True def __init__(self, file, indent=" "): self.file = file self.indent = indent self._indent = "" def visitObject(self, obj): self._open("{") super().visitObject(obj) if self.comma: print(",", end="", file=self.file) print( '\n%s"type": "%s"' % (self._indent, obj.__class__.__name__), end="", file=self.file, ) self._close("}") def visitAttr(self, obj, attr, value): if self.comma: print(",", file=self.file) print('%s"%s": ' % (self._indent, attr), end="", file=self.file) self.visit(value) self.comma = True def visitList(self, obj, *args, **kwargs): self._open("[") comma = False for value in obj: if comma: print(",", end="", file=self.file) print(file=self.file) print(self._indent, end="", file=self.file) self.visit(value, *args, **kwargs) comma = True self._close("]") def visitDict(self, obj, *args, **kwargs): self._open("{") comma = False for key, value in obj.items(): if comma: print(",", end="", file=self.file) print(file=self.file) print('%s"%s": ' % (self._indent, key), end="", file=self.file) self.visit(value, *args, **kwargs) comma = True self._close("}") def visitLeaf(self, obj): if isinstance(obj, tuple): obj = list(obj) elif isinstance(obj, bytes): obj = list(obj) if obj is None: s = "null" elif obj is True: s = "true" elif obj is False: s = "false" else: s = repr(obj) if s[0] == "'": s = '"' + s[1:-1] + '"' print("%s" % s, end="", file=self.file) @JsonVisitor.register(ttLib.TTFont) def visit(self, font): if hasattr(visitor, "font"): print("{}", end="", file=self.file) return False visitor.font = font self._open("{") for tag in font.keys(): if self.comma: print(",", file=self.file) print('\n%s"%s": ' % (self._indent, tag), end="", file=self.file) visitor.visit(font[tag]) self._close("}") del visitor.font return False @JsonVisitor.register(ttLib.GlyphOrder) def visit(self, obj): self.visitList(self.font.getGlyphOrder()) return False @JsonVisitor.register_attr(ttLib.getTableClass("glyf"), "glyphOrder") def visit(visitor, obj, attr, value): return False @JsonVisitor.register(ttLib.getTableModule("glyf").GlyphCoordinates) def visit(self, obj): self.visitList(obj) return False @JsonVisitor.register(Tag) def visit(self, obj): print('"%s"' % str(obj), end="", file=self.file) return False @JsonVisitor.register(array) def visit(self, obj): self.visitList(obj) return False @JsonVisitor.register(bytearray) def visit(self, obj): self.visitList(obj) return False if __name__ == "__main__": from fontTools.ttLib import TTFont import sys if len(sys.argv) != 2: print("usage: print-json.py font") sys.exit() font = TTFont(sys.argv[1]) visitor = JsonVisitor(sys.stdout) visitor.visit(font)