• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1from fontTools.misc import sstruct
2from fontTools.misc.textTools import safeEval
3from . import DefaultTable
4
5maxpFormat_0_5 = """
6		>	# big endian
7		tableVersion:           i
8		numGlyphs:              H
9"""
10
11maxpFormat_1_0_add = """
12		>	# big endian
13		maxPoints:              H
14		maxContours:            H
15		maxCompositePoints:     H
16		maxCompositeContours:   H
17		maxZones:               H
18		maxTwilightPoints:      H
19		maxStorage:             H
20		maxFunctionDefs:        H
21		maxInstructionDefs:     H
22		maxStackElements:       H
23		maxSizeOfInstructions:  H
24		maxComponentElements:   H
25		maxComponentDepth:      H
26"""
27
28
29class table__m_a_x_p(DefaultTable.DefaultTable):
30
31	dependencies = ['glyf']
32
33	def decompile(self, data, ttFont):
34		dummy, data = sstruct.unpack2(maxpFormat_0_5, data, self)
35		self.numGlyphs = int(self.numGlyphs)
36		if self.tableVersion != 0x00005000:
37			dummy, data = sstruct.unpack2(maxpFormat_1_0_add, data, self)
38		assert len(data) == 0
39
40	def compile(self, ttFont):
41		if 'glyf' in ttFont:
42			if ttFont.isLoaded('glyf') and ttFont.recalcBBoxes:
43				self.recalc(ttFont)
44		else:
45			pass  # CFF
46		self.numGlyphs = len(ttFont.getGlyphOrder())
47		if self.tableVersion != 0x00005000:
48			self.tableVersion = 0x00010000
49		data = sstruct.pack(maxpFormat_0_5, self)
50		if self.tableVersion == 0x00010000:
51			data = data + sstruct.pack(maxpFormat_1_0_add, self)
52		return data
53
54	def recalc(self, ttFont):
55		"""Recalculate the font bounding box, and most other maxp values except
56		for the TT instructions values. Also recalculate the value of bit 1
57		of the flags field and the font bounding box of the 'head' table.
58		"""
59		glyfTable = ttFont['glyf']
60		hmtxTable = ttFont['hmtx']
61		headTable = ttFont['head']
62		self.numGlyphs = len(glyfTable)
63		INFINITY = 100000
64		xMin = +INFINITY
65		yMin = +INFINITY
66		xMax = -INFINITY
67		yMax = -INFINITY
68		maxPoints = 0
69		maxContours = 0
70		maxCompositePoints = 0
71		maxCompositeContours = 0
72		maxComponentElements = 0
73		maxComponentDepth = 0
74		allXMinIsLsb = 1
75		for glyphName in ttFont.getGlyphOrder():
76			g = glyfTable[glyphName]
77			if g.numberOfContours:
78				if hmtxTable[glyphName][1] != g.xMin:
79					allXMinIsLsb = 0
80				xMin = min(xMin, g.xMin)
81				yMin = min(yMin, g.yMin)
82				xMax = max(xMax, g.xMax)
83				yMax = max(yMax, g.yMax)
84				if g.numberOfContours > 0:
85					nPoints, nContours = g.getMaxpValues()
86					maxPoints = max(maxPoints, nPoints)
87					maxContours = max(maxContours, nContours)
88				else:
89					nPoints, nContours, componentDepth = g.getCompositeMaxpValues(glyfTable)
90					maxCompositePoints = max(maxCompositePoints, nPoints)
91					maxCompositeContours = max(maxCompositeContours, nContours)
92					maxComponentElements = max(maxComponentElements, len(g.components))
93					maxComponentDepth = max(maxComponentDepth, componentDepth)
94		if xMin == +INFINITY:
95			headTable.xMin = 0
96			headTable.yMin = 0
97			headTable.xMax = 0
98			headTable.yMax = 0
99		else:
100			headTable.xMin = xMin
101			headTable.yMin = yMin
102			headTable.xMax = xMax
103			headTable.yMax = yMax
104		self.maxPoints = maxPoints
105		self.maxContours = maxContours
106		self.maxCompositePoints = maxCompositePoints
107		self.maxCompositeContours = maxCompositeContours
108		self.maxComponentElements = maxComponentElements
109		self.maxComponentDepth = maxComponentDepth
110		if allXMinIsLsb:
111			headTable.flags = headTable.flags | 0x2
112		else:
113			headTable.flags = headTable.flags & ~0x2
114
115	def testrepr(self):
116		items = sorted(self.__dict__.items())
117		print(". . . . . . . . .")
118		for combo in items:
119			print("  %s: %s" % combo)
120		print(". . . . . . . . .")
121
122	def toXML(self, writer, ttFont):
123		if self.tableVersion != 0x00005000:
124			writer.comment("Most of this table will be recalculated by the compiler")
125			writer.newline()
126		formatstring, names, fixes = sstruct.getformat(maxpFormat_0_5)
127		if self.tableVersion != 0x00005000:
128			formatstring, names_1_0, fixes = sstruct.getformat(maxpFormat_1_0_add)
129			names = names + names_1_0
130		for name in names:
131			value = getattr(self, name)
132			if name == "tableVersion":
133				value = hex(value)
134			writer.simpletag(name, value=value)
135			writer.newline()
136
137	def fromXML(self, name, attrs, content, ttFont):
138		setattr(self, name, safeEval(attrs["value"]))
139