O_S_2f_2.py revision 4acb76de2ef06f9dbf431a52abe0c6da7c5f2a8a
17842e56b97ce677b83bdab09cda48bc2d89ac75aJustimport DefaultTable
27842e56b97ce677b83bdab09cda48bc2d89ac75aJustimport sstruct
37842e56b97ce677b83bdab09cda48bc2d89ac75aJustfrom fontTools.misc.textTools import safeEval, num2binary, binary2num
422dcb9e6f9a9d087e87cece6caca6aa5d92f4d91jvrfrom types import TupleType
522dcb9e6f9a9d087e87cece6caca6aa5d92f4d91jvr
67842e56b97ce677b83bdab09cda48bc2d89ac75aJust
77842e56b97ce677b83bdab09cda48bc2d89ac75aJust# panose classification
87842e56b97ce677b83bdab09cda48bc2d89ac75aJust
97842e56b97ce677b83bdab09cda48bc2d89ac75aJustpanoseFormat = """
10859967e5218bed974d05ddec93996b9aea2782a5Just	bFamilyType:        B
11859967e5218bed974d05ddec93996b9aea2782a5Just	bSerifStyle:        B
12859967e5218bed974d05ddec93996b9aea2782a5Just	bWeight:            B
13859967e5218bed974d05ddec93996b9aea2782a5Just	bProportion:        B
14859967e5218bed974d05ddec93996b9aea2782a5Just	bContrast:          B
15859967e5218bed974d05ddec93996b9aea2782a5Just	bStrokeVariation:   B
16859967e5218bed974d05ddec93996b9aea2782a5Just	bArmStyle:          B
17859967e5218bed974d05ddec93996b9aea2782a5Just	bLetterForm:        B
18859967e5218bed974d05ddec93996b9aea2782a5Just	bMidline:           B
19859967e5218bed974d05ddec93996b9aea2782a5Just	bXHeight:           B
207842e56b97ce677b83bdab09cda48bc2d89ac75aJust"""
217842e56b97ce677b83bdab09cda48bc2d89ac75aJust
227842e56b97ce677b83bdab09cda48bc2d89ac75aJustclass Panose:
237842e56b97ce677b83bdab09cda48bc2d89ac75aJust
247842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def toXML(self, writer, ttFont):
257842e56b97ce677b83bdab09cda48bc2d89ac75aJust		formatstring, names, fixes = sstruct.getformat(panoseFormat)
267842e56b97ce677b83bdab09cda48bc2d89ac75aJust		for name in names:
277842e56b97ce677b83bdab09cda48bc2d89ac75aJust			writer.simpletag(name, value=getattr(self, name))
287842e56b97ce677b83bdab09cda48bc2d89ac75aJust			writer.newline()
297842e56b97ce677b83bdab09cda48bc2d89ac75aJust
307842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def fromXML(self, (name, attrs, content), ttFont):
317842e56b97ce677b83bdab09cda48bc2d89ac75aJust		setattr(self, name, safeEval(attrs["value"]))
327842e56b97ce677b83bdab09cda48bc2d89ac75aJust
337842e56b97ce677b83bdab09cda48bc2d89ac75aJust
347842e56b97ce677b83bdab09cda48bc2d89ac75aJust# 'sfnt' OS/2 and Windows Metrics table - 'OS/2'
357842e56b97ce677b83bdab09cda48bc2d89ac75aJust
367842e56b97ce677b83bdab09cda48bc2d89ac75aJustOS2_format_0 = """
37859967e5218bed974d05ddec93996b9aea2782a5Just	>   # big endian
38859967e5218bed974d05ddec93996b9aea2782a5Just	version:                H       # version
39859967e5218bed974d05ddec93996b9aea2782a5Just	xAvgCharWidth:          h       # average character width
40859967e5218bed974d05ddec93996b9aea2782a5Just	usWeightClass:          H       # degree of thickness of strokes
41859967e5218bed974d05ddec93996b9aea2782a5Just	usWidthClass:           H       # aspect ratio
42859967e5218bed974d05ddec93996b9aea2782a5Just	fsType:                 h       # type flags
43859967e5218bed974d05ddec93996b9aea2782a5Just	ySubscriptXSize:        h       # subscript horizontal font size
44859967e5218bed974d05ddec93996b9aea2782a5Just	ySubscriptYSize:        h       # subscript vertical font size
45859967e5218bed974d05ddec93996b9aea2782a5Just	ySubscriptXOffset:      h       # subscript x offset
46859967e5218bed974d05ddec93996b9aea2782a5Just	ySubscriptYOffset:      h       # subscript y offset
47859967e5218bed974d05ddec93996b9aea2782a5Just	ySuperscriptXSize:      h       # superscript horizontal font size
48859967e5218bed974d05ddec93996b9aea2782a5Just	ySuperscriptYSize:      h       # superscript vertical font size
49859967e5218bed974d05ddec93996b9aea2782a5Just	ySuperscriptXOffset:    h       # superscript x offset
50859967e5218bed974d05ddec93996b9aea2782a5Just	ySuperscriptYOffset:    h       # superscript y offset
51859967e5218bed974d05ddec93996b9aea2782a5Just	yStrikeoutSize:         h       # strikeout size
52859967e5218bed974d05ddec93996b9aea2782a5Just	yStrikeoutPosition:     h       # strikeout position
53859967e5218bed974d05ddec93996b9aea2782a5Just	sFamilyClass:           h       # font family class and subclass
54859967e5218bed974d05ddec93996b9aea2782a5Just	panose:                 10s     # panose classification number
5504985bfdded4d445c67524b018965df1f4a4c313fcoiffie	ulUnicodeRange1:        L       # character range
5604985bfdded4d445c67524b018965df1f4a4c313fcoiffie	ulUnicodeRange2:        L       # character range
5704985bfdded4d445c67524b018965df1f4a4c313fcoiffie	ulUnicodeRange3:        L       # character range
5804985bfdded4d445c67524b018965df1f4a4c313fcoiffie	ulUnicodeRange4:        L       # character range
59859967e5218bed974d05ddec93996b9aea2782a5Just	achVendID:              4s      # font vendor identification
60859967e5218bed974d05ddec93996b9aea2782a5Just	fsSelection:            H       # font selection flags
61859967e5218bed974d05ddec93996b9aea2782a5Just	fsFirstCharIndex:       H       # first unicode character index
62859967e5218bed974d05ddec93996b9aea2782a5Just	fsLastCharIndex:        H       # last unicode character index
636146b084c29234a873c31e3bfaee5df2d015e63ajvr	sTypoAscender:          h       # typographic ascender
646146b084c29234a873c31e3bfaee5df2d015e63ajvr	sTypoDescender:         h       # typographic descender
656146b084c29234a873c31e3bfaee5df2d015e63ajvr	sTypoLineGap:           h       # typographic line gap
66859967e5218bed974d05ddec93996b9aea2782a5Just	usWinAscent:            H       # Windows ascender
67859967e5218bed974d05ddec93996b9aea2782a5Just	usWinDescent:           H       # Windows descender
687842e56b97ce677b83bdab09cda48bc2d89ac75aJust"""
697842e56b97ce677b83bdab09cda48bc2d89ac75aJust
707842e56b97ce677b83bdab09cda48bc2d89ac75aJustOS2_format_1_addition =  """
7104985bfdded4d445c67524b018965df1f4a4c313fcoiffie	ulCodePageRange1:   L
7204985bfdded4d445c67524b018965df1f4a4c313fcoiffie	ulCodePageRange2:   L
737842e56b97ce677b83bdab09cda48bc2d89ac75aJust"""
747842e56b97ce677b83bdab09cda48bc2d89ac75aJust
757842e56b97ce677b83bdab09cda48bc2d89ac75aJustOS2_format_2_addition =  OS2_format_1_addition + """
76859967e5218bed974d05ddec93996b9aea2782a5Just	sxHeight:           h
77859967e5218bed974d05ddec93996b9aea2782a5Just	sCapHeight:         h
78859967e5218bed974d05ddec93996b9aea2782a5Just	usDefaultChar:      H
79859967e5218bed974d05ddec93996b9aea2782a5Just	usBreakChar:        H
80859967e5218bed974d05ddec93996b9aea2782a5Just	usMaxContex:        H
817842e56b97ce677b83bdab09cda48bc2d89ac75aJust"""
827842e56b97ce677b83bdab09cda48bc2d89ac75aJust
837842e56b97ce677b83bdab09cda48bc2d89ac75aJustbigendian = "	>	# big endian\n"
847842e56b97ce677b83bdab09cda48bc2d89ac75aJust
857842e56b97ce677b83bdab09cda48bc2d89ac75aJustOS2_format_1 = OS2_format_0 + OS2_format_1_addition
867842e56b97ce677b83bdab09cda48bc2d89ac75aJustOS2_format_2 = OS2_format_0 + OS2_format_2_addition
877842e56b97ce677b83bdab09cda48bc2d89ac75aJustOS2_format_1_addition = bigendian + OS2_format_1_addition
887842e56b97ce677b83bdab09cda48bc2d89ac75aJustOS2_format_2_addition = bigendian + OS2_format_2_addition
897842e56b97ce677b83bdab09cda48bc2d89ac75aJust
907842e56b97ce677b83bdab09cda48bc2d89ac75aJust
917842e56b97ce677b83bdab09cda48bc2d89ac75aJustclass table_O_S_2f_2(DefaultTable.DefaultTable):
927842e56b97ce677b83bdab09cda48bc2d89ac75aJust
937842e56b97ce677b83bdab09cda48bc2d89ac75aJust	"""the OS/2 table"""
947842e56b97ce677b83bdab09cda48bc2d89ac75aJust
957842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def decompile(self, data, ttFont):
967842e56b97ce677b83bdab09cda48bc2d89ac75aJust		dummy, data = sstruct.unpack2(OS2_format_0, data, self)
97481fb094956023aa7b158d6ed1582931bdcad1bfJust		if self.version == 1 and not data:
98481fb094956023aa7b158d6ed1582931bdcad1bfJust			# workaround for buggy Apple fonts
99481fb094956023aa7b158d6ed1582931bdcad1bfJust			self.version = 0
1007842e56b97ce677b83bdab09cda48bc2d89ac75aJust		if self.version == 1:
1014170cfd5e9e14094883c4676f8a172e7915c9cc4jvr			sstruct.unpack2(OS2_format_1_addition, data, self)
1024acb76de2ef06f9dbf431a52abe0c6da7c5f2a8ajvr		elif self.version in (2, 3, 4):
1034170cfd5e9e14094883c4676f8a172e7915c9cc4jvr			sstruct.unpack2(OS2_format_2_addition, data, self)
1047842e56b97ce677b83bdab09cda48bc2d89ac75aJust		elif self.version <> 0:
1057842e56b97ce677b83bdab09cda48bc2d89ac75aJust			from fontTools import ttLib
1067842e56b97ce677b83bdab09cda48bc2d89ac75aJust			raise ttLib.TTLibError, "unknown format for OS/2 table: version %s" % self.version
1077842e56b97ce677b83bdab09cda48bc2d89ac75aJust		self.panose = sstruct.unpack(panoseFormat, self.panose, Panose())
1087842e56b97ce677b83bdab09cda48bc2d89ac75aJust
1097842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def compile(self, ttFont):
1107842e56b97ce677b83bdab09cda48bc2d89ac75aJust		panose = self.panose
1117842e56b97ce677b83bdab09cda48bc2d89ac75aJust		self.panose = sstruct.pack(panoseFormat, self.panose)
1127842e56b97ce677b83bdab09cda48bc2d89ac75aJust		if self.version == 0:
1137842e56b97ce677b83bdab09cda48bc2d89ac75aJust			data = sstruct.pack(OS2_format_0, self)
1147842e56b97ce677b83bdab09cda48bc2d89ac75aJust		elif self.version == 1:
1157842e56b97ce677b83bdab09cda48bc2d89ac75aJust			data = sstruct.pack(OS2_format_1, self)
1164acb76de2ef06f9dbf431a52abe0c6da7c5f2a8ajvr		elif self.version in (2, 3, 4):
1177842e56b97ce677b83bdab09cda48bc2d89ac75aJust			data = sstruct.pack(OS2_format_2, self)
1187842e56b97ce677b83bdab09cda48bc2d89ac75aJust		else:
1197842e56b97ce677b83bdab09cda48bc2d89ac75aJust			from fontTools import ttLib
1207842e56b97ce677b83bdab09cda48bc2d89ac75aJust			raise ttLib.TTLibError, "unknown format for OS/2 table: version %s" % self.version
1217842e56b97ce677b83bdab09cda48bc2d89ac75aJust		self.panose = panose
1227842e56b97ce677b83bdab09cda48bc2d89ac75aJust		return data
1237842e56b97ce677b83bdab09cda48bc2d89ac75aJust
1247842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def toXML(self, writer, ttFont):
1257842e56b97ce677b83bdab09cda48bc2d89ac75aJust		if self.version == 1:
1267842e56b97ce677b83bdab09cda48bc2d89ac75aJust			format = OS2_format_1
1274acb76de2ef06f9dbf431a52abe0c6da7c5f2a8ajvr		elif self.version in (2, 3, 4):
1287842e56b97ce677b83bdab09cda48bc2d89ac75aJust			format = OS2_format_2
1297842e56b97ce677b83bdab09cda48bc2d89ac75aJust		else:
1307842e56b97ce677b83bdab09cda48bc2d89ac75aJust			format = OS2_format_0
1317842e56b97ce677b83bdab09cda48bc2d89ac75aJust		formatstring, names, fixes = sstruct.getformat(format)
1327842e56b97ce677b83bdab09cda48bc2d89ac75aJust		for name in names:
1337842e56b97ce677b83bdab09cda48bc2d89ac75aJust			value = getattr(self, name)
1347842e56b97ce677b83bdab09cda48bc2d89ac75aJust			if type(value) == type(0L):
1357842e56b97ce677b83bdab09cda48bc2d89ac75aJust				value = int(value)
1367842e56b97ce677b83bdab09cda48bc2d89ac75aJust			if name=="panose":
1377842e56b97ce677b83bdab09cda48bc2d89ac75aJust				writer.begintag("panose")
1387842e56b97ce677b83bdab09cda48bc2d89ac75aJust				writer.newline()
1397842e56b97ce677b83bdab09cda48bc2d89ac75aJust				value.toXML(writer, ttFont)
1407842e56b97ce677b83bdab09cda48bc2d89ac75aJust				writer.endtag("panose")
1417842e56b97ce677b83bdab09cda48bc2d89ac75aJust			elif name in ("ulUnicodeRange1", "ulUnicodeRange2",
1427842e56b97ce677b83bdab09cda48bc2d89ac75aJust					"ulUnicodeRange3", "ulUnicodeRange4",
1437842e56b97ce677b83bdab09cda48bc2d89ac75aJust					"ulCodePageRange1", "ulCodePageRange2"):
1447842e56b97ce677b83bdab09cda48bc2d89ac75aJust				writer.simpletag(name, value=num2binary(value))
1457842e56b97ce677b83bdab09cda48bc2d89ac75aJust			elif name in ("fsType", "fsSelection"):
1467842e56b97ce677b83bdab09cda48bc2d89ac75aJust				writer.simpletag(name, value=num2binary(value, 16))
1477842e56b97ce677b83bdab09cda48bc2d89ac75aJust			elif name == "achVendID":
1487842e56b97ce677b83bdab09cda48bc2d89ac75aJust				writer.simpletag(name, value=repr(value)[1:-1])
1497842e56b97ce677b83bdab09cda48bc2d89ac75aJust			else:
1507842e56b97ce677b83bdab09cda48bc2d89ac75aJust				writer.simpletag(name, value=value)
1517842e56b97ce677b83bdab09cda48bc2d89ac75aJust			writer.newline()
1527842e56b97ce677b83bdab09cda48bc2d89ac75aJust
1537842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def fromXML(self, (name, attrs, content), ttFont):
1547842e56b97ce677b83bdab09cda48bc2d89ac75aJust		if name == "panose":
1557842e56b97ce677b83bdab09cda48bc2d89ac75aJust			self.panose = panose = Panose()
1567842e56b97ce677b83bdab09cda48bc2d89ac75aJust			for element in content:
15722dcb9e6f9a9d087e87cece6caca6aa5d92f4d91jvr				if type(element) == TupleType:
1587842e56b97ce677b83bdab09cda48bc2d89ac75aJust					panose.fromXML(element, ttFont)
1597842e56b97ce677b83bdab09cda48bc2d89ac75aJust		elif name in ("ulUnicodeRange1", "ulUnicodeRange2",
1607842e56b97ce677b83bdab09cda48bc2d89ac75aJust				"ulUnicodeRange3", "ulUnicodeRange4",
1617842e56b97ce677b83bdab09cda48bc2d89ac75aJust				"ulCodePageRange1", "ulCodePageRange2",
1627842e56b97ce677b83bdab09cda48bc2d89ac75aJust				"fsType", "fsSelection"):
1637842e56b97ce677b83bdab09cda48bc2d89ac75aJust			setattr(self, name, binary2num(attrs["value"]))
1647842e56b97ce677b83bdab09cda48bc2d89ac75aJust		elif name == "achVendID":
1657842e56b97ce677b83bdab09cda48bc2d89ac75aJust			setattr(self, name, safeEval("'''" + attrs["value"] + "'''"))
1667842e56b97ce677b83bdab09cda48bc2d89ac75aJust		else:
1677842e56b97ce677b83bdab09cda48bc2d89ac75aJust			setattr(self, name, safeEval(attrs["value"]))
1687842e56b97ce677b83bdab09cda48bc2d89ac75aJust
1697842e56b97ce677b83bdab09cda48bc2d89ac75aJust
170