1*e1fe3e4aSElliott Hughesimport fontTools.ttLib as ttLib 2*e1fe3e4aSElliott Hughesfrom fontTools.ttLib.ttVisitor import TTVisitor 3*e1fe3e4aSElliott Hughesfrom fontTools.misc.textTools import Tag 4*e1fe3e4aSElliott Hughesfrom array import array 5*e1fe3e4aSElliott Hughes 6*e1fe3e4aSElliott Hughes 7*e1fe3e4aSElliott Hughesclass JsonVisitor(TTVisitor): 8*e1fe3e4aSElliott Hughes def _open(self, s): 9*e1fe3e4aSElliott Hughes print(s, file=self.file) 10*e1fe3e4aSElliott Hughes self._indent += self.indent 11*e1fe3e4aSElliott Hughes self.comma = False 12*e1fe3e4aSElliott Hughes 13*e1fe3e4aSElliott Hughes def _close(self, s): 14*e1fe3e4aSElliott Hughes self._indent = self._indent[: -len(self.indent)] 15*e1fe3e4aSElliott Hughes print("\n%s%s" % (self._indent, s), end="", file=self.file) 16*e1fe3e4aSElliott Hughes self.comma = True 17*e1fe3e4aSElliott Hughes 18*e1fe3e4aSElliott Hughes def __init__(self, file, indent=" "): 19*e1fe3e4aSElliott Hughes self.file = file 20*e1fe3e4aSElliott Hughes self.indent = indent 21*e1fe3e4aSElliott Hughes self._indent = "" 22*e1fe3e4aSElliott Hughes 23*e1fe3e4aSElliott Hughes def visitObject(self, obj): 24*e1fe3e4aSElliott Hughes self._open("{") 25*e1fe3e4aSElliott Hughes super().visitObject(obj) 26*e1fe3e4aSElliott Hughes if self.comma: 27*e1fe3e4aSElliott Hughes print(",", end="", file=self.file) 28*e1fe3e4aSElliott Hughes print( 29*e1fe3e4aSElliott Hughes '\n%s"type": "%s"' % (self._indent, obj.__class__.__name__), 30*e1fe3e4aSElliott Hughes end="", 31*e1fe3e4aSElliott Hughes file=self.file, 32*e1fe3e4aSElliott Hughes ) 33*e1fe3e4aSElliott Hughes self._close("}") 34*e1fe3e4aSElliott Hughes 35*e1fe3e4aSElliott Hughes def visitAttr(self, obj, attr, value): 36*e1fe3e4aSElliott Hughes if self.comma: 37*e1fe3e4aSElliott Hughes print(",", file=self.file) 38*e1fe3e4aSElliott Hughes print('%s"%s": ' % (self._indent, attr), end="", file=self.file) 39*e1fe3e4aSElliott Hughes self.visit(value) 40*e1fe3e4aSElliott Hughes self.comma = True 41*e1fe3e4aSElliott Hughes 42*e1fe3e4aSElliott Hughes def visitList(self, obj, *args, **kwargs): 43*e1fe3e4aSElliott Hughes self._open("[") 44*e1fe3e4aSElliott Hughes comma = False 45*e1fe3e4aSElliott Hughes for value in obj: 46*e1fe3e4aSElliott Hughes if comma: 47*e1fe3e4aSElliott Hughes print(",", end="", file=self.file) 48*e1fe3e4aSElliott Hughes print(file=self.file) 49*e1fe3e4aSElliott Hughes print(self._indent, end="", file=self.file) 50*e1fe3e4aSElliott Hughes self.visit(value, *args, **kwargs) 51*e1fe3e4aSElliott Hughes comma = True 52*e1fe3e4aSElliott Hughes self._close("]") 53*e1fe3e4aSElliott Hughes 54*e1fe3e4aSElliott Hughes def visitDict(self, obj, *args, **kwargs): 55*e1fe3e4aSElliott Hughes self._open("{") 56*e1fe3e4aSElliott Hughes comma = False 57*e1fe3e4aSElliott Hughes for key, value in obj.items(): 58*e1fe3e4aSElliott Hughes if comma: 59*e1fe3e4aSElliott Hughes print(",", end="", file=self.file) 60*e1fe3e4aSElliott Hughes print(file=self.file) 61*e1fe3e4aSElliott Hughes print('%s"%s": ' % (self._indent, key), end="", file=self.file) 62*e1fe3e4aSElliott Hughes self.visit(value, *args, **kwargs) 63*e1fe3e4aSElliott Hughes comma = True 64*e1fe3e4aSElliott Hughes self._close("}") 65*e1fe3e4aSElliott Hughes 66*e1fe3e4aSElliott Hughes def visitLeaf(self, obj): 67*e1fe3e4aSElliott Hughes if isinstance(obj, tuple): 68*e1fe3e4aSElliott Hughes obj = list(obj) 69*e1fe3e4aSElliott Hughes elif isinstance(obj, bytes): 70*e1fe3e4aSElliott Hughes obj = list(obj) 71*e1fe3e4aSElliott Hughes 72*e1fe3e4aSElliott Hughes if obj is None: 73*e1fe3e4aSElliott Hughes s = "null" 74*e1fe3e4aSElliott Hughes elif obj is True: 75*e1fe3e4aSElliott Hughes s = "true" 76*e1fe3e4aSElliott Hughes elif obj is False: 77*e1fe3e4aSElliott Hughes s = "false" 78*e1fe3e4aSElliott Hughes else: 79*e1fe3e4aSElliott Hughes s = repr(obj) 80*e1fe3e4aSElliott Hughes 81*e1fe3e4aSElliott Hughes if s[0] == "'": 82*e1fe3e4aSElliott Hughes s = '"' + s[1:-1] + '"' 83*e1fe3e4aSElliott Hughes 84*e1fe3e4aSElliott Hughes print("%s" % s, end="", file=self.file) 85*e1fe3e4aSElliott Hughes 86*e1fe3e4aSElliott Hughes 87*e1fe3e4aSElliott Hughes@JsonVisitor.register(ttLib.TTFont) 88*e1fe3e4aSElliott Hughesdef visit(self, font): 89*e1fe3e4aSElliott Hughes if hasattr(visitor, "font"): 90*e1fe3e4aSElliott Hughes print("{}", end="", file=self.file) 91*e1fe3e4aSElliott Hughes return False 92*e1fe3e4aSElliott Hughes visitor.font = font 93*e1fe3e4aSElliott Hughes 94*e1fe3e4aSElliott Hughes self._open("{") 95*e1fe3e4aSElliott Hughes for tag in font.keys(): 96*e1fe3e4aSElliott Hughes if self.comma: 97*e1fe3e4aSElliott Hughes print(",", file=self.file) 98*e1fe3e4aSElliott Hughes print('\n%s"%s": ' % (self._indent, tag), end="", file=self.file) 99*e1fe3e4aSElliott Hughes visitor.visit(font[tag]) 100*e1fe3e4aSElliott Hughes self._close("}") 101*e1fe3e4aSElliott Hughes 102*e1fe3e4aSElliott Hughes del visitor.font 103*e1fe3e4aSElliott Hughes return False 104*e1fe3e4aSElliott Hughes 105*e1fe3e4aSElliott Hughes 106*e1fe3e4aSElliott Hughes@JsonVisitor.register(ttLib.GlyphOrder) 107*e1fe3e4aSElliott Hughesdef visit(self, obj): 108*e1fe3e4aSElliott Hughes self.visitList(self.font.getGlyphOrder()) 109*e1fe3e4aSElliott Hughes return False 110*e1fe3e4aSElliott Hughes 111*e1fe3e4aSElliott Hughes 112*e1fe3e4aSElliott Hughes@JsonVisitor.register_attr(ttLib.getTableClass("glyf"), "glyphOrder") 113*e1fe3e4aSElliott Hughesdef visit(visitor, obj, attr, value): 114*e1fe3e4aSElliott Hughes return False 115*e1fe3e4aSElliott Hughes 116*e1fe3e4aSElliott Hughes 117*e1fe3e4aSElliott Hughes@JsonVisitor.register(ttLib.getTableModule("glyf").GlyphCoordinates) 118*e1fe3e4aSElliott Hughesdef visit(self, obj): 119*e1fe3e4aSElliott Hughes self.visitList(obj) 120*e1fe3e4aSElliott Hughes return False 121*e1fe3e4aSElliott Hughes 122*e1fe3e4aSElliott Hughes 123*e1fe3e4aSElliott Hughes@JsonVisitor.register(Tag) 124*e1fe3e4aSElliott Hughesdef visit(self, obj): 125*e1fe3e4aSElliott Hughes print('"%s"' % str(obj), end="", file=self.file) 126*e1fe3e4aSElliott Hughes return False 127*e1fe3e4aSElliott Hughes 128*e1fe3e4aSElliott Hughes 129*e1fe3e4aSElliott Hughes@JsonVisitor.register(array) 130*e1fe3e4aSElliott Hughesdef visit(self, obj): 131*e1fe3e4aSElliott Hughes self.visitList(obj) 132*e1fe3e4aSElliott Hughes return False 133*e1fe3e4aSElliott Hughes 134*e1fe3e4aSElliott Hughes 135*e1fe3e4aSElliott Hughes@JsonVisitor.register(bytearray) 136*e1fe3e4aSElliott Hughesdef visit(self, obj): 137*e1fe3e4aSElliott Hughes self.visitList(obj) 138*e1fe3e4aSElliott Hughes return False 139*e1fe3e4aSElliott Hughes 140*e1fe3e4aSElliott Hughes 141*e1fe3e4aSElliott Hughesif __name__ == "__main__": 142*e1fe3e4aSElliott Hughes from fontTools.ttLib import TTFont 143*e1fe3e4aSElliott Hughes import sys 144*e1fe3e4aSElliott Hughes 145*e1fe3e4aSElliott Hughes if len(sys.argv) != 2: 146*e1fe3e4aSElliott Hughes print("usage: print-json.py font") 147*e1fe3e4aSElliott Hughes sys.exit() 148*e1fe3e4aSElliott Hughes 149*e1fe3e4aSElliott Hughes font = TTFont(sys.argv[1]) 150*e1fe3e4aSElliott Hughes 151*e1fe3e4aSElliott Hughes visitor = JsonVisitor(sys.stdout) 152*e1fe3e4aSElliott Hughes visitor.visit(font) 153