G_P_K_G_.py 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126
  1. from fontTools.misc import sstruct
  2. from fontTools.misc.textTools import bytesjoin, safeEval, readHex
  3. from . import DefaultTable
  4. import sys
  5. import array
  6. GPKGFormat = """
  7. > # big endian
  8. version: H
  9. flags: H
  10. numGMAPs: H
  11. numGlyplets: H
  12. """
  13. # psFontName is a byte string which follows the record above. This is zero padded
  14. # to the beginning of the records array. The recordsOffsst is 32 bit aligned.
  15. class table_G_P_K_G_(DefaultTable.DefaultTable):
  16. def decompile(self, data, ttFont):
  17. dummy, newData = sstruct.unpack2(GPKGFormat, data, self)
  18. GMAPoffsets = array.array("I")
  19. endPos = (self.numGMAPs + 1) * 4
  20. GMAPoffsets.frombytes(newData[:endPos])
  21. if sys.byteorder != "big":
  22. GMAPoffsets.byteswap()
  23. self.GMAPs = []
  24. for i in range(self.numGMAPs):
  25. start = GMAPoffsets[i]
  26. end = GMAPoffsets[i + 1]
  27. self.GMAPs.append(data[start:end])
  28. pos = endPos
  29. endPos = pos + (self.numGlyplets + 1) * 4
  30. glyphletOffsets = array.array("I")
  31. glyphletOffsets.frombytes(newData[pos:endPos])
  32. if sys.byteorder != "big":
  33. glyphletOffsets.byteswap()
  34. self.glyphlets = []
  35. for i in range(self.numGlyplets):
  36. start = glyphletOffsets[i]
  37. end = glyphletOffsets[i + 1]
  38. self.glyphlets.append(data[start:end])
  39. def compile(self, ttFont):
  40. self.numGMAPs = len(self.GMAPs)
  41. self.numGlyplets = len(self.glyphlets)
  42. GMAPoffsets = [0] * (self.numGMAPs + 1)
  43. glyphletOffsets = [0] * (self.numGlyplets + 1)
  44. dataList = [sstruct.pack(GPKGFormat, self)]
  45. pos = len(dataList[0]) + (self.numGMAPs + 1) * 4 + (self.numGlyplets + 1) * 4
  46. GMAPoffsets[0] = pos
  47. for i in range(1, self.numGMAPs + 1):
  48. pos += len(self.GMAPs[i - 1])
  49. GMAPoffsets[i] = pos
  50. gmapArray = array.array("I", GMAPoffsets)
  51. if sys.byteorder != "big":
  52. gmapArray.byteswap()
  53. dataList.append(gmapArray.tobytes())
  54. glyphletOffsets[0] = pos
  55. for i in range(1, self.numGlyplets + 1):
  56. pos += len(self.glyphlets[i - 1])
  57. glyphletOffsets[i] = pos
  58. glyphletArray = array.array("I", glyphletOffsets)
  59. if sys.byteorder != "big":
  60. glyphletArray.byteswap()
  61. dataList.append(glyphletArray.tobytes())
  62. dataList += self.GMAPs
  63. dataList += self.glyphlets
  64. data = bytesjoin(dataList)
  65. return data
  66. def toXML(self, writer, ttFont):
  67. writer.comment("Most of this table will be recalculated by the compiler")
  68. writer.newline()
  69. formatstring, names, fixes = sstruct.getformat(GPKGFormat)
  70. for name in names:
  71. value = getattr(self, name)
  72. writer.simpletag(name, value=value)
  73. writer.newline()
  74. writer.begintag("GMAPs")
  75. writer.newline()
  76. for gmapData in self.GMAPs:
  77. writer.begintag("hexdata")
  78. writer.newline()
  79. writer.dumphex(gmapData)
  80. writer.endtag("hexdata")
  81. writer.newline()
  82. writer.endtag("GMAPs")
  83. writer.newline()
  84. writer.begintag("glyphlets")
  85. writer.newline()
  86. for glyphletData in self.glyphlets:
  87. writer.begintag("hexdata")
  88. writer.newline()
  89. writer.dumphex(glyphletData)
  90. writer.endtag("hexdata")
  91. writer.newline()
  92. writer.endtag("glyphlets")
  93. writer.newline()
  94. def fromXML(self, name, attrs, content, ttFont):
  95. if name == "GMAPs":
  96. if not hasattr(self, "GMAPs"):
  97. self.GMAPs = []
  98. for element in content:
  99. if isinstance(element, str):
  100. continue
  101. itemName, itemAttrs, itemContent = element
  102. if itemName == "hexdata":
  103. self.GMAPs.append(readHex(itemContent))
  104. elif name == "glyphlets":
  105. if not hasattr(self, "glyphlets"):
  106. self.glyphlets = []
  107. for element in content:
  108. if isinstance(element, str):
  109. continue
  110. itemName, itemAttrs, itemContent = element
  111. if itemName == "hexdata":
  112. self.glyphlets.append(readHex(itemContent))
  113. else:
  114. setattr(self, name, safeEval(attrs["value"]))