G__l_o_c.py 2.6 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485
  1. from fontTools.misc import sstruct
  2. from fontTools.misc.textTools import safeEval
  3. from . import DefaultTable
  4. import array
  5. import sys
  6. Gloc_header = """
  7. > # big endian
  8. version: 16.16F # Table version
  9. flags: H # bit 0: 1=long format, 0=short format
  10. # bit 1: 1=attribute names, 0=no names
  11. numAttribs: H # NUmber of attributes
  12. """
  13. class table_G__l_o_c(DefaultTable.DefaultTable):
  14. """Graphite Index to Glyph Atttributes table
  15. See also https://graphite.sil.org/graphite_techAbout#graphite-font-tables
  16. """
  17. dependencies = ["Glat"]
  18. def __init__(self, tag=None):
  19. DefaultTable.DefaultTable.__init__(self, tag)
  20. self.attribIds = None
  21. self.numAttribs = 0
  22. def decompile(self, data, ttFont):
  23. _, data = sstruct.unpack2(Gloc_header, data, self)
  24. flags = self.flags
  25. del self.flags
  26. self.locations = array.array("I" if flags & 1 else "H")
  27. self.locations.frombytes(data[: len(data) - self.numAttribs * (flags & 2)])
  28. if sys.byteorder != "big":
  29. self.locations.byteswap()
  30. self.attribIds = array.array("H")
  31. if flags & 2:
  32. self.attribIds.frombytes(data[-self.numAttribs * 2 :])
  33. if sys.byteorder != "big":
  34. self.attribIds.byteswap()
  35. def compile(self, ttFont):
  36. data = sstruct.pack(
  37. Gloc_header,
  38. dict(
  39. version=1.0,
  40. flags=(bool(self.attribIds) << 1) + (self.locations.typecode == "I"),
  41. numAttribs=self.numAttribs,
  42. ),
  43. )
  44. if sys.byteorder != "big":
  45. self.locations.byteswap()
  46. data += self.locations.tobytes()
  47. if sys.byteorder != "big":
  48. self.locations.byteswap()
  49. if self.attribIds:
  50. if sys.byteorder != "big":
  51. self.attribIds.byteswap()
  52. data += self.attribIds.tobytes()
  53. if sys.byteorder != "big":
  54. self.attribIds.byteswap()
  55. return data
  56. def set(self, locations):
  57. long_format = max(locations) >= 65536
  58. self.locations = array.array("I" if long_format else "H", locations)
  59. def toXML(self, writer, ttFont):
  60. writer.simpletag("attributes", number=self.numAttribs)
  61. writer.newline()
  62. def fromXML(self, name, attrs, content, ttFont):
  63. if name == "attributes":
  64. self.numAttribs = int(safeEval(attrs["number"]))
  65. def __getitem__(self, index):
  66. return self.locations[index]
  67. def __len__(self):
  68. return len(self.locations)
  69. def __iter__(self):
  70. return iter(self.locations)