cmap.py 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102
  1. import struct
  2. from lxml.etree import Element
  3. from tables.common.cmapSubtables import cmapFormat0, cmapFormat4, cmapFormat12, cmapFormat14
  4. from transform.bytes import generateOffsets, outputTableBytes
  5. class cmap:
  6. """
  7. Class representing a cmap table.
  8. """
  9. def __init__(self, glyphs, no_vs16):
  10. self.version = 0 # hardcoded. no other version.
  11. # check what's what in this set to determine what subtables to toTTX.
  12. # ---------------------------------------------------------
  13. oneByte = []
  14. twoByte = []
  15. fourByte = []
  16. vs = []
  17. for g in glyphs['all']:
  18. if no_vs16 is False and g.codepoints.vs16:
  19. vs.append(g)
  20. if len(g) == 1:
  21. if g.codepoints.seq[0] <= int('ff', 16):
  22. oneByte.append(g)
  23. if g.codepoints.seq[0] <= int('ffff', 16):
  24. twoByte.append(g)
  25. if g.codepoints.seq[0] <= int('ffffff', 16):
  26. fourByte.append(g)
  27. self.subtables = []
  28. if oneByte:
  29. self.subtables.append(cmapFormat0(oneByte, platformID=1, platEncID=0, language=0))
  30. if twoByte:
  31. # platform ID 0 (Unicode)
  32. self.subtables.append(cmapFormat4(twoByte, platformID=0, platEncID=3, language=0))
  33. # platform ID 3 (Microsoft)
  34. # platEncID should be 1. This is what is required to make
  35. # this particular cmap subtable format work.
  36. self.subtables.append(cmapFormat4(twoByte, platformID=3, platEncID=1, language=0))
  37. if fourByte:
  38. # platform ID 0 (Unicode)
  39. self.subtables.append(cmapFormat12(fourByte, platformID=0, platEncID=10, language=0))
  40. # platform ID 3 (Microsoft)
  41. # platEncID should be 10. This is what is required to make
  42. # this particular cmap subtable format work.
  43. self.subtables.append(cmapFormat12(fourByte, platformID=3, platEncID=10, language=0))
  44. if vs:
  45. self.subtables.append(cmapFormat14(vs)) # IDs are specific to this cmap Subtable.
  46. def toTTX(self):
  47. cmap = Element("cmap")
  48. # - TTX doesnt have version for cmap table.
  49. cmap.append(Element("tableVersion", {"version": str(self.version)}))
  50. for sub in self.subtables:
  51. cmap.append(sub.toTTX())
  52. return cmap
  53. def toBytes(self):
  54. # initialise some stuff
  55. subtableOffsets = generateOffsets(self.subtables, 32, 4 + (8 * len(self.subtables))) ## placheholder. last one should be (8 * len(self.subtables)
  56. encodingRecords = b''
  57. # prepare the chunks
  58. header = struct.pack( ">HH"
  59. , self.version # UInt16
  60. , len(self.subtables) # UInt16
  61. )
  62. for num, subtable in enumerate(self.subtables):
  63. if subtable.format not in [4, 14]: # TEMP: skipping malformed cmaps for now.
  64. encodingEntry = struct.pack( ">HHI"
  65. , subtable.platformID # UInt16
  66. , subtable.platEncID # UInt16
  67. , subtableOffsets["offsetInts"][num] # Offset32 (UInt32)
  68. )
  69. encodingRecords += encodingEntry
  70. return outputTableBytes(header + encodingRecords + subtableOffsets["bytes"])