aboutsummaryrefslogtreecommitdiff
path: root/Lib/fontTools/ttLib/tables/_m_a_x_p.py
blob: f0e6c33ae3f0631b3c4a00963d1af4d6a6dc039e (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
from fontTools.misc import sstruct
from fontTools.misc.textTools import safeEval
from . import DefaultTable

maxpFormat_0_5 = """
		>	# big endian
		tableVersion:           i
		numGlyphs:              H
"""

maxpFormat_1_0_add = """
		>	# big endian
		maxPoints:              H
		maxContours:            H
		maxCompositePoints:     H
		maxCompositeContours:   H
		maxZones:               H
		maxTwilightPoints:      H
		maxStorage:             H
		maxFunctionDefs:        H
		maxInstructionDefs:     H
		maxStackElements:       H
		maxSizeOfInstructions:  H
		maxComponentElements:   H
		maxComponentDepth:      H
"""


class table__m_a_x_p(DefaultTable.DefaultTable):
    dependencies = ["glyf"]

    def decompile(self, data, ttFont):
        dummy, data = sstruct.unpack2(maxpFormat_0_5, data, self)
        self.numGlyphs = int(self.numGlyphs)
        if self.tableVersion != 0x00005000:
            dummy, data = sstruct.unpack2(maxpFormat_1_0_add, data, self)
        assert len(data) == 0

    def compile(self, ttFont):
        if "glyf" in ttFont:
            if ttFont.isLoaded("glyf") and ttFont.recalcBBoxes:
                self.recalc(ttFont)
        else:
            pass  # CFF
        self.numGlyphs = len(ttFont.getGlyphOrder())
        if self.tableVersion != 0x00005000:
            self.tableVersion = 0x00010000
        data = sstruct.pack(maxpFormat_0_5, self)
        if self.tableVersion == 0x00010000:
            data = data + sstruct.pack(maxpFormat_1_0_add, self)
        return data

    def recalc(self, ttFont):
        """Recalculate the font bounding box, and most other maxp values except
        for the TT instructions values. Also recalculate the value of bit 1
        of the flags field and the font bounding box of the 'head' table.
        """
        glyfTable = ttFont["glyf"]
        hmtxTable = ttFont["hmtx"]
        headTable = ttFont["head"]
        self.numGlyphs = len(glyfTable)
        INFINITY = 100000
        xMin = +INFINITY
        yMin = +INFINITY
        xMax = -INFINITY
        yMax = -INFINITY
        maxPoints = 0
        maxContours = 0
        maxCompositePoints = 0
        maxCompositeContours = 0
        maxComponentElements = 0
        maxComponentDepth = 0
        allXMinIsLsb = 1
        for glyphName in ttFont.getGlyphOrder():
            g = glyfTable[glyphName]
            if g.numberOfContours:
                if hmtxTable[glyphName][1] != g.xMin:
                    allXMinIsLsb = 0
                xMin = min(xMin, g.xMin)
                yMin = min(yMin, g.yMin)
                xMax = max(xMax, g.xMax)
                yMax = max(yMax, g.yMax)
                if g.numberOfContours > 0:
                    nPoints, nContours = g.getMaxpValues()
                    maxPoints = max(maxPoints, nPoints)
                    maxContours = max(maxContours, nContours)
                elif g.isComposite():
                    nPoints, nContours, componentDepth = g.getCompositeMaxpValues(
                        glyfTable
                    )
                    maxCompositePoints = max(maxCompositePoints, nPoints)
                    maxCompositeContours = max(maxCompositeContours, nContours)
                    maxComponentElements = max(maxComponentElements, len(g.components))
                    maxComponentDepth = max(maxComponentDepth, componentDepth)
        if xMin == +INFINITY:
            headTable.xMin = 0
            headTable.yMin = 0
            headTable.xMax = 0
            headTable.yMax = 0
        else:
            headTable.xMin = xMin
            headTable.yMin = yMin
            headTable.xMax = xMax
            headTable.yMax = yMax
        self.maxPoints = maxPoints
        self.maxContours = maxContours
        self.maxCompositePoints = maxCompositePoints
        self.maxCompositeContours = maxCompositeContours
        self.maxComponentElements = maxComponentElements
        self.maxComponentDepth = maxComponentDepth
        if allXMinIsLsb:
            headTable.flags = headTable.flags | 0x2
        else:
            headTable.flags = headTable.flags & ~0x2

    def testrepr(self):
        items = sorted(self.__dict__.items())
        print(". . . . . . . . .")
        for combo in items:
            print("  %s: %s" % combo)
        print(". . . . . . . . .")

    def toXML(self, writer, ttFont):
        if self.tableVersion != 0x00005000:
            writer.comment("Most of this table will be recalculated by the compiler")
            writer.newline()
        formatstring, names, fixes = sstruct.getformat(maxpFormat_0_5)
        if self.tableVersion != 0x00005000:
            formatstring, names_1_0, fixes = sstruct.getformat(maxpFormat_1_0_add)
            names = names + names_1_0
        for name in names:
            value = getattr(self, name)
            if name == "tableVersion":
                value = hex(value)
            writer.simpletag(name, value=value)
            writer.newline()

    def fromXML(self, name, attrs, content, ttFont):
        setattr(self, name, safeEval(attrs["value"]))