jvr | 9be387c | 2008-03-01 11:43:01 +0000 | [diff] [blame] | 1 | import sys |
jvr | 4cc0051 | 2006-10-21 13:27:25 +0000 | [diff] [blame] | 2 | import DefaultTable |
| 3 | import sstruct |
| 4 | import array |
jvr | 1b7d54f | 2008-03-04 15:25:27 +0000 | [diff] [blame] | 5 | import numpy |
jvr | 4cc0051 | 2006-10-21 13:27:25 +0000 | [diff] [blame] | 6 | from types import StringType |
| 7 | from fontTools.misc.textTools import safeEval, readHex |
| 8 | from fontTools import ttLib |
| 9 | |
| 10 | GPKGFormat = """ |
| 11 | > # big endian |
| 12 | version: H |
| 13 | flags: H |
| 14 | numGMAPs: H |
| 15 | numGlyplets: H |
| 16 | """ |
| 17 | # psFontName is a byte string which follows the record above. This is zero padded |
| 18 | # to the beginning of the records array. The recordsOffsst is 32 bit aligned. |
| 19 | |
| 20 | |
| 21 | class table_G_P_K_G_(DefaultTable.DefaultTable): |
| 22 | |
| 23 | def decompile(self, data, ttFont): |
| 24 | dummy, newData = sstruct.unpack2(GPKGFormat, data, self) |
| 25 | |
Behdad Esfahbod | 4ffd404 | 2013-08-16 13:02:23 -0400 | [diff] [blame^] | 26 | GMAPoffsets = array.array("I") |
jvr | 4cc0051 | 2006-10-21 13:27:25 +0000 | [diff] [blame] | 27 | endPos = (self.numGMAPs+1) * 4 |
| 28 | GMAPoffsets.fromstring(newData[:endPos]) |
jvr | 9be387c | 2008-03-01 11:43:01 +0000 | [diff] [blame] | 29 | if sys.byteorder <> "big": |
jvr | 4cc0051 | 2006-10-21 13:27:25 +0000 | [diff] [blame] | 30 | GMAPoffsets.byteswap() |
| 31 | self.GMAPs = [] |
| 32 | for i in range(self.numGMAPs): |
| 33 | start = GMAPoffsets[i] |
| 34 | end = GMAPoffsets[i+1] |
| 35 | self.GMAPs.append(data[start:end]) |
| 36 | pos = endPos |
| 37 | endPos = pos + (self.numGlyplets + 1)*4 |
Behdad Esfahbod | 4ffd404 | 2013-08-16 13:02:23 -0400 | [diff] [blame^] | 38 | glyphletOffsets = array.array("I") |
jvr | 4cc0051 | 2006-10-21 13:27:25 +0000 | [diff] [blame] | 39 | glyphletOffsets.fromstring(newData[pos:endPos]) |
jvr | 9be387c | 2008-03-01 11:43:01 +0000 | [diff] [blame] | 40 | if sys.byteorder <> "big": |
jvr | 4cc0051 | 2006-10-21 13:27:25 +0000 | [diff] [blame] | 41 | glyphletOffsets.byteswap() |
| 42 | self.glyphlets = [] |
| 43 | for i in range(self.numGlyplets): |
| 44 | start = glyphletOffsets[i] |
| 45 | end = glyphletOffsets[i+1] |
| 46 | self.glyphlets.append(data[start:end]) |
| 47 | |
| 48 | |
| 49 | def compile(self, ttFont): |
| 50 | self.numGMAPs = len(self.GMAPs) |
| 51 | self.numGlyplets = len(self.glyphlets) |
| 52 | GMAPoffsets = [0]*(self.numGMAPs + 1) |
| 53 | glyphletOffsets = [0]*(self.numGlyplets + 1) |
| 54 | |
| 55 | dataList =[ sstruct.pack(GPKGFormat, self)] |
| 56 | |
| 57 | pos = len(dataList[0]) + (self.numGMAPs + 1)*4 + (self.numGlyplets + 1)*4 |
| 58 | GMAPoffsets[0] = pos |
| 59 | for i in range(1, self.numGMAPs +1): |
| 60 | pos += len(self.GMAPs[i-1]) |
| 61 | GMAPoffsets[i] = pos |
jvr | 1b7d54f | 2008-03-04 15:25:27 +0000 | [diff] [blame] | 62 | gmapArray = numpy.array(GMAPoffsets, numpy.uint32) |
jvr | 9be387c | 2008-03-01 11:43:01 +0000 | [diff] [blame] | 63 | if sys.byteorder <> "big": |
jvr | 1b7d54f | 2008-03-04 15:25:27 +0000 | [diff] [blame] | 64 | gmapArray = gmapArray.byteswap() |
jvr | 4cc0051 | 2006-10-21 13:27:25 +0000 | [diff] [blame] | 65 | dataList.append(gmapArray.tostring()) |
| 66 | |
| 67 | glyphletOffsets[0] = pos |
| 68 | for i in range(1, self.numGlyplets +1): |
| 69 | pos += len(self.glyphlets[i-1]) |
| 70 | glyphletOffsets[i] = pos |
jvr | 1b7d54f | 2008-03-04 15:25:27 +0000 | [diff] [blame] | 71 | glyphletArray = numpy.array(glyphletOffsets, numpy.uint32) |
jvr | 9be387c | 2008-03-01 11:43:01 +0000 | [diff] [blame] | 72 | if sys.byteorder <> "big": |
jvr | 1b7d54f | 2008-03-04 15:25:27 +0000 | [diff] [blame] | 73 | glyphletArray = glyphletArray.byteswap() |
jvr | 4cc0051 | 2006-10-21 13:27:25 +0000 | [diff] [blame] | 74 | dataList.append(glyphletArray.tostring()) |
| 75 | dataList += self.GMAPs |
| 76 | dataList += self.glyphlets |
| 77 | data = "".join(dataList) |
| 78 | return data |
| 79 | |
| 80 | def toXML(self, writer, ttFont): |
| 81 | writer.comment("Most of this table will be recalculated by the compiler") |
| 82 | writer.newline() |
| 83 | formatstring, names, fixes = sstruct.getformat(GPKGFormat) |
| 84 | for name in names: |
| 85 | value = getattr(self, name) |
| 86 | writer.simpletag(name, value=value) |
| 87 | writer.newline() |
| 88 | |
| 89 | writer.begintag("GMAPs") |
| 90 | writer.newline() |
| 91 | for gmapData in self.GMAPs: |
| 92 | writer.begintag("hexdata") |
| 93 | writer.newline() |
| 94 | writer.dumphex(gmapData) |
| 95 | writer.endtag("hexdata") |
| 96 | writer.newline() |
| 97 | writer.endtag("GMAPs") |
| 98 | writer.newline() |
| 99 | |
| 100 | writer.begintag("glyphlets") |
| 101 | writer.newline() |
| 102 | for glyphletData in self.glyphlets: |
| 103 | writer.begintag("hexdata") |
| 104 | writer.newline() |
| 105 | writer.dumphex(glyphletData) |
| 106 | writer.endtag("hexdata") |
| 107 | writer.newline() |
| 108 | writer.endtag("glyphlets") |
| 109 | writer.newline() |
| 110 | |
| 111 | def fromXML(self, (name, attrs, content), ttFont): |
| 112 | if name == "GMAPs": |
| 113 | if not hasattr(self, "GMAPs"): |
| 114 | self.GMAPs = [] |
| 115 | for element in content: |
| 116 | if isinstance(element, StringType): |
| 117 | continue |
| 118 | itemName, itemAttrs, itemContent = element |
| 119 | if itemName == "hexdata": |
| 120 | self.GMAPs.append(readHex(itemContent)) |
| 121 | elif name == "glyphlets": |
| 122 | if not hasattr(self, "glyphlets"): |
| 123 | self.glyphlets = [] |
| 124 | for element in content: |
| 125 | if isinstance(element, StringType): |
| 126 | continue |
| 127 | itemName, itemAttrs, itemContent = element |
| 128 | if itemName == "hexdata": |
| 129 | self.glyphlets.append(readHex(itemContent)) |
| 130 | else: |
| 131 | value = attrs["value"] |
| 132 | try: |
| 133 | value = safeEval(value) |
| 134 | except OverflowError: |
| 135 | value = long(value) |
| 136 | setattr(self, name, value) |