• 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
24	dependencies = []
25
26	def decompile(self, data, ttFont):
27		dummy, rest = sstruct.unpack2(SINGFormat, data, self)
28		self.uniqueName = self.decompileUniqueName(self.uniqueName)
29		self.nameLength = byteord(self.nameLength)
30		assert len(rest) == self.nameLength
31		self.baseGlyphName = tostr(rest)
32
33		rawMETAMD5 = self.METAMD5
34		self.METAMD5 = "[" + hex(byteord(self.METAMD5[0]))
35		for char in rawMETAMD5[1:]:
36			self.METAMD5 = self.METAMD5 + ", " + hex(byteord(char))
37		self.METAMD5 = self.METAMD5 + "]"
38
39	def decompileUniqueName(self, data):
40		name = ""
41		for char in data:
42			val = byteord(char)
43			if val == 0:
44				break
45			if (val > 31) or (val < 128):
46				name += chr(val)
47			else:
48				octString = oct(val)
49				if len(octString) > 3:
50					octString = octString[1:] # chop off that leading zero.
51				elif len(octString) < 3:
52					octString.zfill(3)
53				name += "\\" + octString
54		return name
55
56	def compile(self, ttFont):
57		d = self.__dict__.copy()
58		d["nameLength"] = bytechr(len(self.baseGlyphName))
59		d["uniqueName"] = self.compilecompileUniqueName(self.uniqueName, 28)
60		METAMD5List = eval(self.METAMD5)
61		d["METAMD5"] = b""
62		for val in METAMD5List:
63			d["METAMD5"] += bytechr(val)
64		assert (len(d["METAMD5"]) == 16), "Failed to pack 16 byte MD5 hash in SING table"
65		data = sstruct.pack(SINGFormat, d)
66		data = data + tobytes(self.baseGlyphName)
67		return data
68
69	def compilecompileUniqueName(self, name, length):
70		nameLen = len(name)
71		if length <= nameLen:
72			name = name[:length-1] + "\000"
73		else:
74			name += (nameLen - length) * "\000"
75		return name
76
77	def toXML(self, writer, ttFont):
78		writer.comment("Most of this table will be recalculated by the compiler")
79		writer.newline()
80		formatstring, names, fixes = sstruct.getformat(SINGFormat)
81		for name in names:
82			value = getattr(self, name)
83			writer.simpletag(name, value=value)
84			writer.newline()
85		writer.simpletag("baseGlyphName", value=self.baseGlyphName)
86		writer.newline()
87
88	def fromXML(self, name, attrs, content, ttFont):
89		value = attrs["value"]
90		if name in ["uniqueName", "METAMD5", "baseGlyphName"]:
91			setattr(self, name, value)
92		else:
93			setattr(self, name, safeEval(value))
94