hhea.py 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105
  1. import struct
  2. from lxml.etree import Element
  3. from data import VFixed
  4. from transform.bytes import outputTableBytes
  5. class hhea:
  6. """
  7. Class representing an hhea table.
  8. """
  9. def __init__(self, m):
  10. metrics = m['metrics']
  11. self.majorVersion = 1
  12. self.minorVersion = 0
  13. self.ascent = metrics['horiAscent']
  14. self.descent = metrics['horiDescent']
  15. self.lineGap = 0 # hard-coded based on best practices
  16. self.advanceWidthMax = metrics['xMax']
  17. self.minLeftSideBearing = 0
  18. self.minRightSideBearing = metrics['xMax']
  19. self.xMaxExtent = 0
  20. # carets should be this ratio for emoji fonts.
  21. self.caretSlopeRise = 1
  22. self.caretSlopeRun = 0
  23. self.caretOffset = 0
  24. # reserved, hardcoded; meant to be 0.
  25. self.reserved0 = 0
  26. self.reserved1 = 0
  27. self.reserved2 = 0
  28. self.reserved3 = 0
  29. self.metricDataFormat = 0 # hardcoded, meant to be 0.
  30. self.numberofHMetrics = 0 # TODO: try to actually generate this based on the actual number of hmetrics that exist.
  31. def toTTX(self):
  32. """
  33. Compiles table to TTX.
  34. """
  35. hhea = Element("hhea")
  36. hhea.append(Element("tableVersion", {'value': VFixed(f"{self.majorVersion}.{self.minorVersion}").toHexStr() })) # TTX wants the version in this particular format.
  37. hhea.append(Element("ascent", {'value': str(self.ascent) }))
  38. hhea.append(Element("descent", {'value': str(self.descent) }))
  39. hhea.append(Element("lineGap", {'value': str(self.lineGap) }))
  40. hhea.append(Element("advanceWidthMax", {'value': str(self.advanceWidthMax) }))
  41. hhea.append(Element("minLeftSideBearing", {'value': str(self.minLeftSideBearing) }))
  42. hhea.append(Element("minRightSideBearing", {'value': str(self.minRightSideBearing) }))
  43. hhea.append(Element("xMaxExtent", {'value': str(self.xMaxExtent) }))
  44. hhea.append(Element("caretSlopeRise", {'value': str(self.caretSlopeRise) }))
  45. hhea.append(Element("caretSlopeRun", {'value': str(self.caretSlopeRun) }))
  46. hhea.append(Element("caretOffset", {'value': str(self.caretOffset) }))
  47. hhea.append(Element("reserved0", {'value': str(self.reserved0) }))
  48. hhea.append(Element("reserved1", {'value': str(self.reserved1) }))
  49. hhea.append(Element("reserved2", {'value': str(self.reserved2) }))
  50. hhea.append(Element("reserved3", {'value': str(self.reserved3) }))
  51. hhea.append(Element("metricDataFormat", {'value': str(self.metricDataFormat) }))
  52. hhea.append(Element("numberOfHMetrics", {'value': str(self.numberofHMetrics) }))
  53. return hhea
  54. def toBytes(self):
  55. hhea = struct.pack('>HHhhhHhhhhhhhhhhhH'
  56. , self.majorVersion # UInt16
  57. , self.minorVersion # UInt16
  58. , self.ascent # Int16
  59. , self.descent # Int16
  60. , self.lineGap # Int16
  61. , self.advanceWidthMax # UInt16 (yep, definitely unsigned)
  62. , self.minLeftSideBearing # Int16
  63. , self.minRightSideBearing # Int16
  64. , self.xMaxExtent # Int16
  65. , self.caretSlopeRise # Int16
  66. , self.caretSlopeRun # Int16
  67. , self.caretOffset # Int16
  68. , self.reserved0 # Int16
  69. , self.reserved1 # Int16
  70. , self.reserved2 # Int16
  71. , self.reserved3 # Int16
  72. , self.metricDataFormat # Int16
  73. , self.numberofHMetrics # UInt16
  74. )
  75. return outputTableBytes(hhea)