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