1from . import DefaultTable
2from fontTools.misc import sstruct
3from fontTools.misc.textTools import bytesjoin
4from fontTools.ttLib.tables.TupleVariation import \
5    compileTupleVariationStore, decompileTupleVariationStore, TupleVariation
6
7
8# https://www.microsoft.com/typography/otspec/cvar.htm
9# https://www.microsoft.com/typography/otspec/otvarcommonformats.htm
10# https://developer.apple.com/fonts/TrueType-Reference-Manual/RM06/Chap6cvar.html
11
12CVAR_HEADER_FORMAT = """
13    > # big endian
14    majorVersion:        H
15    minorVersion:        H
16    tupleVariationCount: H
17    offsetToData:        H
18"""
19
20CVAR_HEADER_SIZE = sstruct.calcsize(CVAR_HEADER_FORMAT)
21
22
23class table__c_v_a_r(DefaultTable.DefaultTable):
24    dependencies = ["cvt ", "fvar"]
25
26    def __init__(self, tag=None):
27        DefaultTable.DefaultTable.__init__(self, tag)
28        self.majorVersion, self.minorVersion = 1, 0
29        self.variations = []
30
31    def compile(self, ttFont, useSharedPoints=False):
32        tupleVariationCount, tuples, data = compileTupleVariationStore(
33            variations=[v for v in self.variations if v.hasImpact()],
34            pointCount=len(ttFont["cvt "].values),
35            axisTags=[axis.axisTag for axis in ttFont["fvar"].axes],
36            sharedTupleIndices={},
37            useSharedPoints=useSharedPoints)
38        header = {
39            "majorVersion": self.majorVersion,
40            "minorVersion": self.minorVersion,
41            "tupleVariationCount": tupleVariationCount,
42            "offsetToData": CVAR_HEADER_SIZE + len(tuples),
43        }
44        return b''.join([
45            sstruct.pack(CVAR_HEADER_FORMAT, header),
46            tuples,
47            data
48        ])
49
50    def decompile(self, data, ttFont):
51        axisTags = [axis.axisTag for axis in ttFont["fvar"].axes]
52        header = {}
53        sstruct.unpack(CVAR_HEADER_FORMAT, data[0:CVAR_HEADER_SIZE], header)
54        self.majorVersion = header["majorVersion"]
55        self.minorVersion = header["minorVersion"]
56        assert self.majorVersion == 1, self.majorVersion
57        self.variations = decompileTupleVariationStore(
58            tableTag=self.tableTag, axisTags=axisTags,
59            tupleVariationCount=header["tupleVariationCount"],
60            pointCount=len(ttFont["cvt "].values), sharedTuples=None,
61            data=data, pos=CVAR_HEADER_SIZE, dataPos=header["offsetToData"])
62
63    def fromXML(self, name, attrs, content, ttFont):
64        if name == "version":
65            self.majorVersion = int(attrs.get("major", "1"))
66            self.minorVersion = int(attrs.get("minor", "0"))
67        elif name == "tuple":
68            valueCount = len(ttFont["cvt "].values)
69            var = TupleVariation({}, [None] * valueCount)
70            self.variations.append(var)
71            for tupleElement in content:
72                if isinstance(tupleElement, tuple):
73                    tupleName, tupleAttrs, tupleContent = tupleElement
74                    var.fromXML(tupleName, tupleAttrs, tupleContent)
75
76    def toXML(self, writer, ttFont):
77        axisTags = [axis.axisTag for axis in ttFont["fvar"].axes]
78        writer.simpletag("version",
79                         major=self.majorVersion, minor=self.minorVersion)
80        writer.newline()
81        for var in self.variations:
82            var.toXML(writer, axisTags)
83