O_S_2f_2.py revision 7718d95951335e4122f934d0ed23bd2cd41e2391
1import DefaultTable
2import sstruct
3from fontTools.misc.textTools import safeEval, num2binary, binary2num
4from types import TupleType
5
6
7# panose classification
8
9panoseFormat = """
10	bFamilyType:        B
11	bSerifStyle:        B
12	bWeight:            B
13	bProportion:        B
14	bContrast:          B
15	bStrokeVariation:   B
16	bArmStyle:          B
17	bLetterForm:        B
18	bMidline:           B
19	bXHeight:           B
20"""
21
22class Panose:
23
24	def toXML(self, writer, ttFont):
25		formatstring, names, fixes = sstruct.getformat(panoseFormat)
26		for name in names:
27			writer.simpletag(name, value=getattr(self, name))
28			writer.newline()
29
30	def fromXML(self, (name, attrs, content), ttFont):
31		setattr(self, name, safeEval(attrs["value"]))
32
33
34# 'sfnt' OS/2 and Windows Metrics table - 'OS/2'
35
36OS2_format_0 = """
37	>   # big endian
38	version:                H       # version
39	xAvgCharWidth:          h       # average character width
40	usWeightClass:          H       # degree of thickness of strokes
41	usWidthClass:           H       # aspect ratio
42	fsType:                 h       # type flags
43	ySubscriptXSize:        h       # subscript horizontal font size
44	ySubscriptYSize:        h       # subscript vertical font size
45	ySubscriptXOffset:      h       # subscript x offset
46	ySubscriptYOffset:      h       # subscript y offset
47	ySuperscriptXSize:      h       # superscript horizontal font size
48	ySuperscriptYSize:      h       # superscript vertical font size
49	ySuperscriptXOffset:    h       # superscript x offset
50	ySuperscriptYOffset:    h       # superscript y offset
51	yStrikeoutSize:         h       # strikeout size
52	yStrikeoutPosition:     h       # strikeout position
53	sFamilyClass:           h       # font family class and subclass
54	panose:                 10s     # panose classification number
55	ulUnicodeRange1:        l       # character range
56	ulUnicodeRange2:        l       # character range
57	ulUnicodeRange3:        l       # character range
58	ulUnicodeRange4:        l       # character range
59	achVendID:              4s      # font vendor identification
60	fsSelection:            H       # font selection flags
61	fsFirstCharIndex:       H       # first unicode character index
62	fsLastCharIndex:        H       # last unicode character index
63	sTypoAscender:          h       # typographic ascender
64	sTypoDescender:         h       # typographic descender
65	sTypoLineGap:           h       # typographic line gap
66	usWinAscent:            H       # Windows ascender
67	usWinDescent:           H       # Windows descender
68"""
69
70OS2_format_1_addition =  """
71	ulCodePageRange1:   l
72	ulCodePageRange2:   l
73"""
74
75OS2_format_2_addition =  OS2_format_1_addition + """
76	sxHeight:           h
77	sCapHeight:         h
78	usDefaultChar:      H
79	usBreakChar:        H
80	usMaxContex:        H
81"""
82
83bigendian = "	>	# big endian\n"
84
85OS2_format_1 = OS2_format_0 + OS2_format_1_addition
86OS2_format_2 = OS2_format_0 + OS2_format_2_addition
87OS2_format_1_addition = bigendian + OS2_format_1_addition
88OS2_format_2_addition = bigendian + OS2_format_2_addition
89
90
91class table_O_S_2f_2(DefaultTable.DefaultTable):
92
93	"""the OS/2 table"""
94
95	def decompile(self, data, ttFont):
96		dummy, data = sstruct.unpack2(OS2_format_0, data, self)
97		if self.version == 1 and not data:
98			# workaround for buggy Apple fonts
99			self.version = 0
100		if self.version == 1:
101			sstruct.unpack2(OS2_format_1_addition, data, self)
102		elif self.version in (2, 3):
103			sstruct.unpack2(OS2_format_2_addition, data, self)
104		elif self.version <> 0:
105			from fontTools import ttLib
106			raise ttLib.TTLibError, "unknown format for OS/2 table: version %s" % self.version
107		self.panose = sstruct.unpack(panoseFormat, self.panose, Panose())
108
109	def compile(self, ttFont):
110		panose = self.panose
111		self.panose = sstruct.pack(panoseFormat, self.panose)
112		if self.version == 0:
113			data = sstruct.pack(OS2_format_0, self)
114		elif self.version == 1:
115			data = sstruct.pack(OS2_format_1, self)
116		elif self.version in (2, 3):
117			data = sstruct.pack(OS2_format_2, self)
118		else:
119			from fontTools import ttLib
120			raise ttLib.TTLibError, "unknown format for OS/2 table: version %s" % self.version
121		self.panose = panose
122		return data
123
124	def toXML(self, writer, ttFont):
125		if self.version == 1:
126			format = OS2_format_1
127		elif self.version in (2, 3):
128			format = OS2_format_2
129		else:
130			format = OS2_format_0
131		formatstring, names, fixes = sstruct.getformat(format)
132		for name in names:
133			value = getattr(self, name)
134			if type(value) == type(0L):
135				value = int(value)
136			if name=="panose":
137				writer.begintag("panose")
138				writer.newline()
139				value.toXML(writer, ttFont)
140				writer.endtag("panose")
141			elif name in ("ulUnicodeRange1", "ulUnicodeRange2",
142					"ulUnicodeRange3", "ulUnicodeRange4",
143					"ulCodePageRange1", "ulCodePageRange2"):
144				writer.simpletag(name, value=num2binary(value))
145			elif name in ("fsType", "fsSelection"):
146				writer.simpletag(name, value=num2binary(value, 16))
147			elif name == "achVendID":
148				writer.simpletag(name, value=repr(value)[1:-1])
149			else:
150				writer.simpletag(name, value=value)
151			writer.newline()
152
153	def fromXML(self, (name, attrs, content), ttFont):
154		if name == "panose":
155			self.panose = panose = Panose()
156			for element in content:
157				if type(element) == TupleType:
158					panose.fromXML(element, ttFont)
159		elif name in ("ulUnicodeRange1", "ulUnicodeRange2",
160				"ulUnicodeRange3", "ulUnicodeRange4",
161				"ulCodePageRange1", "ulCodePageRange2",
162				"fsType", "fsSelection"):
163			setattr(self, name, binary2num(attrs["value"]))
164		elif name == "achVendID":
165			setattr(self, name, safeEval("'''" + attrs["value"] + "'''"))
166		else:
167			setattr(self, name, safeEval(attrs["value"]))
168
169
170