• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1from fontTools.misc.textTools import bytesjoin, safeEval
2from . import DefaultTable
3import struct
4
5
6class table_V_O_R_G_(DefaultTable.DefaultTable):
7    """This table is structured so that you can treat it like a dictionary keyed by glyph name.
8
9    ``ttFont['VORG'][<glyphName>]`` will return the vertical origin for any glyph.
10
11    ``ttFont['VORG'][<glyphName>] = <value>`` will set the vertical origin for any glyph.
12    """
13
14    def decompile(self, data, ttFont):
15        self.getGlyphName = (
16            ttFont.getGlyphName
17        )  # for use in get/set item functions, for access by GID
18        (
19            self.majorVersion,
20            self.minorVersion,
21            self.defaultVertOriginY,
22            self.numVertOriginYMetrics,
23        ) = struct.unpack(">HHhH", data[:8])
24        assert (
25            self.majorVersion <= 1
26        ), "Major version of VORG table is higher than I know how to handle"
27        data = data[8:]
28        vids = []
29        gids = []
30        pos = 0
31        for i in range(self.numVertOriginYMetrics):
32            gid, vOrigin = struct.unpack(">Hh", data[pos : pos + 4])
33            pos += 4
34            gids.append(gid)
35            vids.append(vOrigin)
36
37        self.VOriginRecords = vOrig = {}
38        glyphOrder = ttFont.getGlyphOrder()
39        try:
40            names = [glyphOrder[gid] for gid in gids]
41        except IndexError:
42            getGlyphName = self.getGlyphName
43            names = map(getGlyphName, gids)
44
45        for name, vid in zip(names, vids):
46            vOrig[name] = vid
47
48    def compile(self, ttFont):
49        vorgs = list(self.VOriginRecords.values())
50        names = list(self.VOriginRecords.keys())
51        nameMap = ttFont.getReverseGlyphMap()
52        try:
53            gids = [nameMap[name] for name in names]
54        except KeyError:
55            nameMap = ttFont.getReverseGlyphMap(rebuild=True)
56            gids = [nameMap[name] for name in names]
57        vOriginTable = list(zip(gids, vorgs))
58        self.numVertOriginYMetrics = len(vorgs)
59        vOriginTable.sort()  # must be in ascending GID order
60        dataList = [struct.pack(">Hh", rec[0], rec[1]) for rec in vOriginTable]
61        header = struct.pack(
62            ">HHhH",
63            self.majorVersion,
64            self.minorVersion,
65            self.defaultVertOriginY,
66            self.numVertOriginYMetrics,
67        )
68        dataList.insert(0, header)
69        data = bytesjoin(dataList)
70        return data
71
72    def toXML(self, writer, ttFont):
73        writer.simpletag("majorVersion", value=self.majorVersion)
74        writer.newline()
75        writer.simpletag("minorVersion", value=self.minorVersion)
76        writer.newline()
77        writer.simpletag("defaultVertOriginY", value=self.defaultVertOriginY)
78        writer.newline()
79        writer.simpletag("numVertOriginYMetrics", value=self.numVertOriginYMetrics)
80        writer.newline()
81        vOriginTable = []
82        glyphNames = self.VOriginRecords.keys()
83        for glyphName in glyphNames:
84            try:
85                gid = ttFont.getGlyphID(glyphName)
86            except:
87                assert 0, (
88                    "VORG table contains a glyph name not in ttFont.getGlyphNames(): "
89                    + str(glyphName)
90                )
91            vOriginTable.append([gid, glyphName, self.VOriginRecords[glyphName]])
92        vOriginTable.sort()
93        for entry in vOriginTable:
94            vOriginRec = VOriginRecord(entry[1], entry[2])
95            vOriginRec.toXML(writer, ttFont)
96
97    def fromXML(self, name, attrs, content, ttFont):
98        if not hasattr(self, "VOriginRecords"):
99            self.VOriginRecords = {}
100        self.getGlyphName = (
101            ttFont.getGlyphName
102        )  # for use in get/set item functions, for access by GID
103        if name == "VOriginRecord":
104            vOriginRec = VOriginRecord()
105            for element in content:
106                if isinstance(element, str):
107                    continue
108                name, attrs, content = element
109                vOriginRec.fromXML(name, attrs, content, ttFont)
110            self.VOriginRecords[vOriginRec.glyphName] = vOriginRec.vOrigin
111        elif "value" in attrs:
112            setattr(self, name, safeEval(attrs["value"]))
113
114    def __getitem__(self, glyphSelector):
115        if isinstance(glyphSelector, int):
116            # its a gid, convert to glyph name
117            glyphSelector = self.getGlyphName(glyphSelector)
118
119        if glyphSelector not in self.VOriginRecords:
120            return self.defaultVertOriginY
121
122        return self.VOriginRecords[glyphSelector]
123
124    def __setitem__(self, glyphSelector, value):
125        if isinstance(glyphSelector, int):
126            # its a gid, convert to glyph name
127            glyphSelector = self.getGlyphName(glyphSelector)
128
129        if value != self.defaultVertOriginY:
130            self.VOriginRecords[glyphSelector] = value
131        elif glyphSelector in self.VOriginRecords:
132            del self.VOriginRecords[glyphSelector]
133
134    def __delitem__(self, glyphSelector):
135        del self.VOriginRecords[glyphSelector]
136
137
138class VOriginRecord(object):
139    def __init__(self, name=None, vOrigin=None):
140        self.glyphName = name
141        self.vOrigin = vOrigin
142
143    def toXML(self, writer, ttFont):
144        writer.begintag("VOriginRecord")
145        writer.newline()
146        writer.simpletag("glyphName", value=self.glyphName)
147        writer.newline()
148        writer.simpletag("vOrigin", value=self.vOrigin)
149        writer.newline()
150        writer.endtag("VOriginRecord")
151        writer.newline()
152
153    def fromXML(self, name, attrs, content, ttFont):
154        value = attrs["value"]
155        if name == "glyphName":
156            setattr(self, name, value)
157        else:
158            setattr(self, name, safeEval(value))
159