• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1from fontTools.misc import sstruct
2from fontTools.misc.textTools import bytechr, byteord, tobytes, tostr, safeEval
3from . import DefaultTable
4
5SINGFormat = """
6		>	# big endian
7		tableVersionMajor:	H
8		tableVersionMinor: 	H
9		glyphletVersion:	H
10		permissions:		h
11		mainGID:			H
12		unitsPerEm:			H
13		vertAdvance:		h
14		vertOrigin:			h
15		uniqueName:			28s
16		METAMD5:			16s
17		nameLength:			1s
18"""
19# baseGlyphName is a byte string which follows the record above.
20
21
22class table_S_I_N_G_(DefaultTable.DefaultTable):
23    dependencies = []
24
25    def decompile(self, data, ttFont):
26        dummy, rest = sstruct.unpack2(SINGFormat, data, self)
27        self.uniqueName = self.decompileUniqueName(self.uniqueName)
28        self.nameLength = byteord(self.nameLength)
29        assert len(rest) == self.nameLength
30        self.baseGlyphName = tostr(rest)
31
32        rawMETAMD5 = self.METAMD5
33        self.METAMD5 = "[" + hex(byteord(self.METAMD5[0]))
34        for char in rawMETAMD5[1:]:
35            self.METAMD5 = self.METAMD5 + ", " + hex(byteord(char))
36        self.METAMD5 = self.METAMD5 + "]"
37
38    def decompileUniqueName(self, data):
39        name = ""
40        for char in data:
41            val = byteord(char)
42            if val == 0:
43                break
44            if (val > 31) or (val < 128):
45                name += chr(val)
46            else:
47                octString = oct(val)
48                if len(octString) > 3:
49                    octString = octString[1:]  # chop off that leading zero.
50                elif len(octString) < 3:
51                    octString.zfill(3)
52                name += "\\" + octString
53        return name
54
55    def compile(self, ttFont):
56        d = self.__dict__.copy()
57        d["nameLength"] = bytechr(len(self.baseGlyphName))
58        d["uniqueName"] = self.compilecompileUniqueName(self.uniqueName, 28)
59        METAMD5List = eval(self.METAMD5)
60        d["METAMD5"] = b""
61        for val in METAMD5List:
62            d["METAMD5"] += bytechr(val)
63        assert len(d["METAMD5"]) == 16, "Failed to pack 16 byte MD5 hash in SING table"
64        data = sstruct.pack(SINGFormat, d)
65        data = data + tobytes(self.baseGlyphName)
66        return data
67
68    def compilecompileUniqueName(self, name, length):
69        nameLen = len(name)
70        if length <= nameLen:
71            name = name[: length - 1] + "\000"
72        else:
73            name += (nameLen - length) * "\000"
74        return name
75
76    def toXML(self, writer, ttFont):
77        writer.comment("Most of this table will be recalculated by the compiler")
78        writer.newline()
79        formatstring, names, fixes = sstruct.getformat(SINGFormat)
80        for name in names:
81            value = getattr(self, name)
82            writer.simpletag(name, value=value)
83            writer.newline()
84        writer.simpletag("baseGlyphName", value=self.baseGlyphName)
85        writer.newline()
86
87    def fromXML(self, name, attrs, content, ttFont):
88        value = attrs["value"]
89        if name in ["uniqueName", "METAMD5", "baseGlyphName"]:
90            setattr(self, name, value)
91        else:
92            setattr(self, name, safeEval(value))
93