S_I_N_G_.py 3.0 KB

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