cblc.py 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131
  1. import struct
  2. from lxml.etree import Element
  3. from tables.common.ebxMetrics import SbitLineMetrics
  4. from tables.common.ebxIndexes import IndexSubTable1
  5. from transform.bytes import outputTableBytes
  6. class CBLCBitmapSize:
  7. """
  8. A class representation of an CBLC BitmapSize subtable.
  9. This is similar to, but not the same as, an EBLC BitmapSize subtable.
  10. """
  11. def __init__(self, metrics, ppem, glyphs):
  12. self.indexSubTables = []
  13. self.indexSubTables.append(IndexSubTable1(glyphs))
  14. self.colorRef = 0 # TODO: ???
  15. self.hori = SbitLineMetrics('hori', metrics)
  16. self.vert = SbitLineMetrics('vert', metrics)
  17. self.ppemX = ppem
  18. self.ppemY = ppem
  19. self.bitDepth = 32 # 32 is the bitdepth for colour emoji. hard-coded for now.
  20. self.flags = 1 # TODO: figure out how this actually works.
  21. glyphIDList = []
  22. for id, g in enumerate(glyphs['img_empty']):
  23. if g.imgDict:
  24. glyphIDList.append(id)
  25. self.startGlyphIndex = glyphIDList[0]
  26. self.endGlyphIndex = glyphIDList[-1]
  27. def toTTX(self, index):
  28. """
  29. Returns a TTX version of this table element.
  30. TTX structures BitmapSize tables differently to a normal binary font -
  31. BitmapSizes and IndexSubtables that correspond to the same strike are
  32. bundled together as a '<strike>'.)
  33. """
  34. strike = Element("strike", {"index": str(index) })
  35. bSizeTable = Element("bitmapSizeTable")
  36. bSizeTable.append(self.hori.toTTX())
  37. bSizeTable.append(self.vert.toTTX())
  38. bSizeTable.append(Element("colorRef", {"value": str(self.colorRef) }))
  39. bSizeTable.append(Element("startGlyphIndex", {"value": str(self.startGlyphIndex) }))
  40. bSizeTable.append(Element("endGlyphIndex", {"value": str(self.endGlyphIndex) }))
  41. bSizeTable.append(Element("ppemX", {"value": str(self.ppemX) }))
  42. bSizeTable.append(Element("ppemY", {"value": str(self.ppemY) }))
  43. bSizeTable.append(Element("bitDepth", {"value": str(self.bitDepth) }))
  44. bSizeTable.append(Element("flags", {"value": str(self.flags) }))
  45. strike.append(bSizeTable)
  46. for s in self.indexSubTables:
  47. strike.append(s.toTTX())
  48. return strike
  49. def toBytes(self):
  50. """
  51. Returns a bytes version of this table element.
  52. Fonts structure BitmapSize differently to TTX. Each chunk of
  53. data is laid out linearly:
  54. - Array of all BitmapSizes (containing offsets to attached IndexSubTable(s))
  55. - Array of all IndexSubTables
  56. TODO: figure out how to do this.
  57. """
  58. class CBLC:
  59. def __init__(self, m, glyphs):
  60. self.majorVersion = 3
  61. self.minorVersion = 0
  62. # hardcoded; the only CBLC version that exists.
  63. self.bitmapSizeTables = []
  64. # iterate over each strike.
  65. for imageFormat, image in glyphs["img"][0].imgDict.items():
  66. if imageFormat.split('-')[0] == "png":
  67. self.bitmapSizeTables.append(CBLCBitmapSize(m["metrics"], image.strike, glyphs))
  68. def toTTX(self):
  69. cblc = Element("CBLC")
  70. cblc.append(Element("header", {"version": f"{self.majorVersion}.{self.minorVersion}" }))
  71. strikeIndex = 0
  72. for s in self.bitmapSizeTables:
  73. cblc.append(s.toTTX(strikeIndex))
  74. strikeIndex += 1
  75. return cblc
  76. def toBytes(self):
  77. cblc = struct.pack( ">HHI"
  78. , self.majorVersion # UInt16
  79. , self.minorVersion # UInt16
  80. , len(self.bitmapSizeTables) # UInt32 (numSizes)
  81. # pack all of the BitmapSize tables immediately after.
  82. )
  83. return outputTableBytes(cblc)