• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1from __future__ import print_function, division, absolute_import
2from fontTools.misc.py23 import *
3from fontTools.misc import sstruct
4from fontTools.misc.textTools import readHex
5from fontTools.ttLib import TTLibError
6from . import DefaultTable
7
8# Apple's documentation of 'meta':
9# https://developer.apple.com/fonts/TrueType-Reference-Manual/RM06/Chap6meta.html
10
11META_HEADER_FORMAT = """
12    > # big endian
13    version:     L
14    flags:       L
15    dataOffset:  L
16    numDataMaps: L
17"""
18
19
20DATA_MAP_FORMAT = """
21    > # big endian
22    tag:         4s
23    dataOffset:  L
24    dataLength:  L
25"""
26
27
28class table__m_e_t_a(DefaultTable.DefaultTable):
29    def __init__(self, tag=None):
30        DefaultTable.DefaultTable.__init__(self, tag)
31        self.data = {}
32
33    def decompile(self, data, ttFont):
34        headerSize = sstruct.calcsize(META_HEADER_FORMAT)
35        header = sstruct.unpack(META_HEADER_FORMAT, data[0 : headerSize])
36        if header["version"] != 1:
37            raise TTLibError("unsupported 'meta' version %d" %
38                             header["version"])
39        dataMapSize = sstruct.calcsize(DATA_MAP_FORMAT)
40        for i in range(header["numDataMaps"]):
41            dataMapOffset = headerSize + i * dataMapSize
42            dataMap = sstruct.unpack(
43                DATA_MAP_FORMAT,
44                data[dataMapOffset : dataMapOffset + dataMapSize])
45            tag = dataMap["tag"]
46            offset = dataMap["dataOffset"]
47            self.data[tag] = data[offset : offset + dataMap["dataLength"]]
48            if tag in ["dlng", "slng"]:
49                self.data[tag] = self.data[tag].decode("utf-8")
50
51    def compile(self, ttFont):
52        keys = sorted(self.data.keys())
53        headerSize = sstruct.calcsize(META_HEADER_FORMAT)
54        dataOffset = headerSize + len(keys) * sstruct.calcsize(DATA_MAP_FORMAT)
55        header = sstruct.pack(META_HEADER_FORMAT, {
56                "version": 1,
57                "flags": 0,
58                "dataOffset": dataOffset,
59                "numDataMaps": len(keys)
60        })
61        dataMaps = []
62        dataBlocks = []
63        for tag in keys:
64            if tag in ["dlng", "slng"]:
65                data = self.data[tag].encode("utf-8")
66            else:
67                data = self.data[tag]
68            dataMaps.append(sstruct.pack(DATA_MAP_FORMAT, {
69                "tag": tag,
70                "dataOffset": dataOffset,
71                "dataLength": len(data)
72            }))
73            dataBlocks.append(data)
74            dataOffset += len(data)
75        return bytesjoin([header] + dataMaps + dataBlocks)
76
77    def toXML(self, writer, ttFont):
78        for tag in sorted(self.data.keys()):
79            if tag in ["dlng", "slng"]:
80                writer.begintag("text", tag=tag)
81                writer.newline()
82                writer.write(self.data[tag])
83                writer.newline()
84                writer.endtag("text")
85                writer.newline()
86            else:
87                writer.begintag("hexdata", tag=tag)
88                writer.newline()
89                writer.dumphex(self.data[tag])
90                writer.endtag("hexdata")
91                writer.newline()
92
93    def fromXML(self, name, attrs, content, ttFont):
94        if name == "hexdata":
95            self.data[attrs["tag"]] = readHex(content)
96        elif name == "text" and attrs["tag"] in ["dlng", "slng"]:
97            self.data[attrs["tag"]] = strjoin(content).strip()
98        else:
99            raise TTLibError("can't handle '%s' element" % name)
100