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