O_S_2f_2.py revision f1e8c3e8a0bd12858e1ab361973c286eb7cad30a
17842e56b97ce677b83bdab09cda48bc2d89ac75aJustimport DefaultTable
28413c108d21e8cf0e9059bbfffde8d13f2616340Behdad Esfahbodfrom fontTools.misc import sstruct
37842e56b97ce677b83bdab09cda48bc2d89ac75aJustfrom fontTools.misc.textTools import safeEval, num2binary, binary2num
422dcb9e6f9a9d087e87cece6caca6aa5d92f4d91jvrfrom types import TupleType
5b3c860477c42c4c0adc1197dcf47bb899db258c4Behdad Esfahbodimport warnings
622dcb9e6f9a9d087e87cece6caca6aa5d92f4d91jvr
77842e56b97ce677b83bdab09cda48bc2d89ac75aJust
87842e56b97ce677b83bdab09cda48bc2d89ac75aJust# panose classification
97842e56b97ce677b83bdab09cda48bc2d89ac75aJust
107842e56b97ce677b83bdab09cda48bc2d89ac75aJustpanoseFormat = """
11859967e5218bed974d05ddec93996b9aea2782a5Just	bFamilyType:        B
12859967e5218bed974d05ddec93996b9aea2782a5Just	bSerifStyle:        B
13859967e5218bed974d05ddec93996b9aea2782a5Just	bWeight:            B
14859967e5218bed974d05ddec93996b9aea2782a5Just	bProportion:        B
15859967e5218bed974d05ddec93996b9aea2782a5Just	bContrast:          B
16859967e5218bed974d05ddec93996b9aea2782a5Just	bStrokeVariation:   B
17859967e5218bed974d05ddec93996b9aea2782a5Just	bArmStyle:          B
18859967e5218bed974d05ddec93996b9aea2782a5Just	bLetterForm:        B
19859967e5218bed974d05ddec93996b9aea2782a5Just	bMidline:           B
20859967e5218bed974d05ddec93996b9aea2782a5Just	bXHeight:           B
217842e56b97ce677b83bdab09cda48bc2d89ac75aJust"""
227842e56b97ce677b83bdab09cda48bc2d89ac75aJust
237842e56b97ce677b83bdab09cda48bc2d89ac75aJustclass Panose:
247842e56b97ce677b83bdab09cda48bc2d89ac75aJust
257842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def toXML(self, writer, ttFont):
267842e56b97ce677b83bdab09cda48bc2d89ac75aJust		formatstring, names, fixes = sstruct.getformat(panoseFormat)
277842e56b97ce677b83bdab09cda48bc2d89ac75aJust		for name in names:
287842e56b97ce677b83bdab09cda48bc2d89ac75aJust			writer.simpletag(name, value=getattr(self, name))
297842e56b97ce677b83bdab09cda48bc2d89ac75aJust			writer.newline()
307842e56b97ce677b83bdab09cda48bc2d89ac75aJust
317842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def fromXML(self, (name, attrs, content), ttFont):
327842e56b97ce677b83bdab09cda48bc2d89ac75aJust		setattr(self, name, safeEval(attrs["value"]))
337842e56b97ce677b83bdab09cda48bc2d89ac75aJust
347842e56b97ce677b83bdab09cda48bc2d89ac75aJust
357842e56b97ce677b83bdab09cda48bc2d89ac75aJust# 'sfnt' OS/2 and Windows Metrics table - 'OS/2'
367842e56b97ce677b83bdab09cda48bc2d89ac75aJust
377842e56b97ce677b83bdab09cda48bc2d89ac75aJustOS2_format_0 = """
38859967e5218bed974d05ddec93996b9aea2782a5Just	>   # big endian
39859967e5218bed974d05ddec93996b9aea2782a5Just	version:                H       # version
40859967e5218bed974d05ddec93996b9aea2782a5Just	xAvgCharWidth:          h       # average character width
41859967e5218bed974d05ddec93996b9aea2782a5Just	usWeightClass:          H       # degree of thickness of strokes
42859967e5218bed974d05ddec93996b9aea2782a5Just	usWidthClass:           H       # aspect ratio
43859967e5218bed974d05ddec93996b9aea2782a5Just	fsType:                 h       # type flags
44859967e5218bed974d05ddec93996b9aea2782a5Just	ySubscriptXSize:        h       # subscript horizontal font size
45859967e5218bed974d05ddec93996b9aea2782a5Just	ySubscriptYSize:        h       # subscript vertical font size
46859967e5218bed974d05ddec93996b9aea2782a5Just	ySubscriptXOffset:      h       # subscript x offset
47859967e5218bed974d05ddec93996b9aea2782a5Just	ySubscriptYOffset:      h       # subscript y offset
48859967e5218bed974d05ddec93996b9aea2782a5Just	ySuperscriptXSize:      h       # superscript horizontal font size
49859967e5218bed974d05ddec93996b9aea2782a5Just	ySuperscriptYSize:      h       # superscript vertical font size
50859967e5218bed974d05ddec93996b9aea2782a5Just	ySuperscriptXOffset:    h       # superscript x offset
51859967e5218bed974d05ddec93996b9aea2782a5Just	ySuperscriptYOffset:    h       # superscript y offset
52859967e5218bed974d05ddec93996b9aea2782a5Just	yStrikeoutSize:         h       # strikeout size
53859967e5218bed974d05ddec93996b9aea2782a5Just	yStrikeoutPosition:     h       # strikeout position
54859967e5218bed974d05ddec93996b9aea2782a5Just	sFamilyClass:           h       # font family class and subclass
55859967e5218bed974d05ddec93996b9aea2782a5Just	panose:                 10s     # panose classification number
5604985bfdded4d445c67524b018965df1f4a4c313fcoiffie	ulUnicodeRange1:        L       # character range
5704985bfdded4d445c67524b018965df1f4a4c313fcoiffie	ulUnicodeRange2:        L       # character range
5804985bfdded4d445c67524b018965df1f4a4c313fcoiffie	ulUnicodeRange3:        L       # character range
5904985bfdded4d445c67524b018965df1f4a4c313fcoiffie	ulUnicodeRange4:        L       # character range
60859967e5218bed974d05ddec93996b9aea2782a5Just	achVendID:              4s      # font vendor identification
61859967e5218bed974d05ddec93996b9aea2782a5Just	fsSelection:            H       # font selection flags
62859967e5218bed974d05ddec93996b9aea2782a5Just	fsFirstCharIndex:       H       # first unicode character index
63859967e5218bed974d05ddec93996b9aea2782a5Just	fsLastCharIndex:        H       # last unicode character index
646146b084c29234a873c31e3bfaee5df2d015e63ajvr	sTypoAscender:          h       # typographic ascender
656146b084c29234a873c31e3bfaee5df2d015e63ajvr	sTypoDescender:         h       # typographic descender
666146b084c29234a873c31e3bfaee5df2d015e63ajvr	sTypoLineGap:           h       # typographic line gap
67859967e5218bed974d05ddec93996b9aea2782a5Just	usWinAscent:            H       # Windows ascender
68859967e5218bed974d05ddec93996b9aea2782a5Just	usWinDescent:           H       # Windows descender
697842e56b97ce677b83bdab09cda48bc2d89ac75aJust"""
707842e56b97ce677b83bdab09cda48bc2d89ac75aJust
717842e56b97ce677b83bdab09cda48bc2d89ac75aJustOS2_format_1_addition =  """
7204985bfdded4d445c67524b018965df1f4a4c313fcoiffie	ulCodePageRange1:   L
7304985bfdded4d445c67524b018965df1f4a4c313fcoiffie	ulCodePageRange2:   L
747842e56b97ce677b83bdab09cda48bc2d89ac75aJust"""
757842e56b97ce677b83bdab09cda48bc2d89ac75aJust
767842e56b97ce677b83bdab09cda48bc2d89ac75aJustOS2_format_2_addition =  OS2_format_1_addition + """
77859967e5218bed974d05ddec93996b9aea2782a5Just	sxHeight:           h
78859967e5218bed974d05ddec93996b9aea2782a5Just	sCapHeight:         h
79859967e5218bed974d05ddec93996b9aea2782a5Just	usDefaultChar:      H
80859967e5218bed974d05ddec93996b9aea2782a5Just	usBreakChar:        H
81859967e5218bed974d05ddec93996b9aea2782a5Just	usMaxContex:        H
827842e56b97ce677b83bdab09cda48bc2d89ac75aJust"""
837842e56b97ce677b83bdab09cda48bc2d89ac75aJust
84aa37c0aa7d4e692cc85c70a9bb22be16433c2394Olivier BertenOS2_format_5_addition =  OS2_format_2_addition + """
85aa37c0aa7d4e692cc85c70a9bb22be16433c2394Olivier Berten	usLowerOpticalPointSize:    H
86aa37c0aa7d4e692cc85c70a9bb22be16433c2394Olivier Berten	usUpperOpticalPointSize:    H
87aa37c0aa7d4e692cc85c70a9bb22be16433c2394Olivier Berten"""
88aa37c0aa7d4e692cc85c70a9bb22be16433c2394Olivier Berten
897842e56b97ce677b83bdab09cda48bc2d89ac75aJustbigendian = "	>	# big endian\n"
907842e56b97ce677b83bdab09cda48bc2d89ac75aJust
917842e56b97ce677b83bdab09cda48bc2d89ac75aJustOS2_format_1 = OS2_format_0 + OS2_format_1_addition
927842e56b97ce677b83bdab09cda48bc2d89ac75aJustOS2_format_2 = OS2_format_0 + OS2_format_2_addition
93aa37c0aa7d4e692cc85c70a9bb22be16433c2394Olivier BertenOS2_format_5 = OS2_format_0 + OS2_format_5_addition
947842e56b97ce677b83bdab09cda48bc2d89ac75aJustOS2_format_1_addition = bigendian + OS2_format_1_addition
957842e56b97ce677b83bdab09cda48bc2d89ac75aJustOS2_format_2_addition = bigendian + OS2_format_2_addition
96aa37c0aa7d4e692cc85c70a9bb22be16433c2394Olivier BertenOS2_format_5_addition = bigendian + OS2_format_5_addition
977842e56b97ce677b83bdab09cda48bc2d89ac75aJust
987842e56b97ce677b83bdab09cda48bc2d89ac75aJust
997842e56b97ce677b83bdab09cda48bc2d89ac75aJustclass table_O_S_2f_2(DefaultTable.DefaultTable):
1007842e56b97ce677b83bdab09cda48bc2d89ac75aJust
1017842e56b97ce677b83bdab09cda48bc2d89ac75aJust	"""the OS/2 table"""
1027842e56b97ce677b83bdab09cda48bc2d89ac75aJust
1037842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def decompile(self, data, ttFont):
1047842e56b97ce677b83bdab09cda48bc2d89ac75aJust		dummy, data = sstruct.unpack2(OS2_format_0, data, self)
105b3c860477c42c4c0adc1197dcf47bb899db258c4Behdad Esfahbod
1067842e56b97ce677b83bdab09cda48bc2d89ac75aJust		if self.version == 1:
107b3c860477c42c4c0adc1197dcf47bb899db258c4Behdad Esfahbod			dummy, data = sstruct.unpack2(OS2_format_1_addition, data, self)
1084acb76de2ef06f9dbf431a52abe0c6da7c5f2a8ajvr		elif self.version in (2, 3, 4):
109b3c860477c42c4c0adc1197dcf47bb899db258c4Behdad Esfahbod			dummy, data = sstruct.unpack2(OS2_format_2_addition, data, self)
110aa37c0aa7d4e692cc85c70a9bb22be16433c2394Olivier Berten		elif self.version == 5:
111b3c860477c42c4c0adc1197dcf47bb899db258c4Behdad Esfahbod			dummy, data = sstruct.unpack2(OS2_format_5_addition, data, self)
112170fc9d40fb1abf5bf5582f603ba4e9a0a441a0cBehdad Esfahbod			self.usLowerOpticalPointSize /= 20.
113170fc9d40fb1abf5bf5582f603ba4e9a0a441a0cBehdad Esfahbod			self.usUpperOpticalPointSize /= 20.
1147842e56b97ce677b83bdab09cda48bc2d89ac75aJust		elif self.version <> 0:
1157842e56b97ce677b83bdab09cda48bc2d89ac75aJust			from fontTools import ttLib
1167842e56b97ce677b83bdab09cda48bc2d89ac75aJust			raise ttLib.TTLibError, "unknown format for OS/2 table: version %s" % self.version
117b3c860477c42c4c0adc1197dcf47bb899db258c4Behdad Esfahbod		if len(data):
118f1e8c3e8a0bd12858e1ab361973c286eb7cad30aBehdad Esfahbod			warnings.warn("too much 'OS/2' table data")
119b3c860477c42c4c0adc1197dcf47bb899db258c4Behdad Esfahbod
1207842e56b97ce677b83bdab09cda48bc2d89ac75aJust		self.panose = sstruct.unpack(panoseFormat, self.panose, Panose())
1217842e56b97ce677b83bdab09cda48bc2d89ac75aJust
1227842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def compile(self, ttFont):
1237842e56b97ce677b83bdab09cda48bc2d89ac75aJust		panose = self.panose
1247842e56b97ce677b83bdab09cda48bc2d89ac75aJust		self.panose = sstruct.pack(panoseFormat, self.panose)
1257842e56b97ce677b83bdab09cda48bc2d89ac75aJust		if self.version == 0:
1267842e56b97ce677b83bdab09cda48bc2d89ac75aJust			data = sstruct.pack(OS2_format_0, self)
1277842e56b97ce677b83bdab09cda48bc2d89ac75aJust		elif self.version == 1:
1287842e56b97ce677b83bdab09cda48bc2d89ac75aJust			data = sstruct.pack(OS2_format_1, self)
1294acb76de2ef06f9dbf431a52abe0c6da7c5f2a8ajvr		elif self.version in (2, 3, 4):
1307842e56b97ce677b83bdab09cda48bc2d89ac75aJust			data = sstruct.pack(OS2_format_2, self)
131aa37c0aa7d4e692cc85c70a9bb22be16433c2394Olivier Berten		elif self.version == 5:
132170fc9d40fb1abf5bf5582f603ba4e9a0a441a0cBehdad Esfahbod			lower = self.usLowerOpticalPointSize
133170fc9d40fb1abf5bf5582f603ba4e9a0a441a0cBehdad Esfahbod			upper = self.usUpperOpticalPointSize
134170fc9d40fb1abf5bf5582f603ba4e9a0a441a0cBehdad Esfahbod			self.usLowerOpticalPointSize = int(round(self.usLowerOpticalPointSize * 20))
135170fc9d40fb1abf5bf5582f603ba4e9a0a441a0cBehdad Esfahbod			self.usUpperOpticalPointSize = int(round(self.usUpperOpticalPointSize * 20))
136aa37c0aa7d4e692cc85c70a9bb22be16433c2394Olivier Berten			data = sstruct.pack(OS2_format_5, self)
137170fc9d40fb1abf5bf5582f603ba4e9a0a441a0cBehdad Esfahbod			self.usLowerOpticalPointSize = lower
138170fc9d40fb1abf5bf5582f603ba4e9a0a441a0cBehdad Esfahbod			self.usUpperOpticalPointSize = upper
1397842e56b97ce677b83bdab09cda48bc2d89ac75aJust		else:
1407842e56b97ce677b83bdab09cda48bc2d89ac75aJust			from fontTools import ttLib
1417842e56b97ce677b83bdab09cda48bc2d89ac75aJust			raise ttLib.TTLibError, "unknown format for OS/2 table: version %s" % self.version
1427842e56b97ce677b83bdab09cda48bc2d89ac75aJust		self.panose = panose
1437842e56b97ce677b83bdab09cda48bc2d89ac75aJust		return data
1447842e56b97ce677b83bdab09cda48bc2d89ac75aJust
1457842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def toXML(self, writer, ttFont):
1467842e56b97ce677b83bdab09cda48bc2d89ac75aJust		if self.version == 1:
1477842e56b97ce677b83bdab09cda48bc2d89ac75aJust			format = OS2_format_1
1484acb76de2ef06f9dbf431a52abe0c6da7c5f2a8ajvr		elif self.version in (2, 3, 4):
1497842e56b97ce677b83bdab09cda48bc2d89ac75aJust			format = OS2_format_2
150aa37c0aa7d4e692cc85c70a9bb22be16433c2394Olivier Berten		elif self.version == 5:
151aa37c0aa7d4e692cc85c70a9bb22be16433c2394Olivier Berten			format = OS2_format_5
1527842e56b97ce677b83bdab09cda48bc2d89ac75aJust		else:
1537842e56b97ce677b83bdab09cda48bc2d89ac75aJust			format = OS2_format_0
1547842e56b97ce677b83bdab09cda48bc2d89ac75aJust		formatstring, names, fixes = sstruct.getformat(format)
1557842e56b97ce677b83bdab09cda48bc2d89ac75aJust		for name in names:
1567842e56b97ce677b83bdab09cda48bc2d89ac75aJust			value = getattr(self, name)
1577842e56b97ce677b83bdab09cda48bc2d89ac75aJust			if type(value) == type(0L):
1587842e56b97ce677b83bdab09cda48bc2d89ac75aJust				value = int(value)
1597842e56b97ce677b83bdab09cda48bc2d89ac75aJust			if name=="panose":
1607842e56b97ce677b83bdab09cda48bc2d89ac75aJust				writer.begintag("panose")
1617842e56b97ce677b83bdab09cda48bc2d89ac75aJust				writer.newline()
1627842e56b97ce677b83bdab09cda48bc2d89ac75aJust				value.toXML(writer, ttFont)
1637842e56b97ce677b83bdab09cda48bc2d89ac75aJust				writer.endtag("panose")
1647842e56b97ce677b83bdab09cda48bc2d89ac75aJust			elif name in ("ulUnicodeRange1", "ulUnicodeRange2",
1657842e56b97ce677b83bdab09cda48bc2d89ac75aJust					"ulUnicodeRange3", "ulUnicodeRange4",
1667842e56b97ce677b83bdab09cda48bc2d89ac75aJust					"ulCodePageRange1", "ulCodePageRange2"):
1677842e56b97ce677b83bdab09cda48bc2d89ac75aJust				writer.simpletag(name, value=num2binary(value))
1687842e56b97ce677b83bdab09cda48bc2d89ac75aJust			elif name in ("fsType", "fsSelection"):
1697842e56b97ce677b83bdab09cda48bc2d89ac75aJust				writer.simpletag(name, value=num2binary(value, 16))
1707842e56b97ce677b83bdab09cda48bc2d89ac75aJust			elif name == "achVendID":
1717842e56b97ce677b83bdab09cda48bc2d89ac75aJust				writer.simpletag(name, value=repr(value)[1:-1])
1727842e56b97ce677b83bdab09cda48bc2d89ac75aJust			else:
1737842e56b97ce677b83bdab09cda48bc2d89ac75aJust				writer.simpletag(name, value=value)
1747842e56b97ce677b83bdab09cda48bc2d89ac75aJust			writer.newline()
1757842e56b97ce677b83bdab09cda48bc2d89ac75aJust
1767842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def fromXML(self, (name, attrs, content), ttFont):
1777842e56b97ce677b83bdab09cda48bc2d89ac75aJust		if name == "panose":
1787842e56b97ce677b83bdab09cda48bc2d89ac75aJust			self.panose = panose = Panose()
1797842e56b97ce677b83bdab09cda48bc2d89ac75aJust			for element in content:
18022dcb9e6f9a9d087e87cece6caca6aa5d92f4d91jvr				if type(element) == TupleType:
1817842e56b97ce677b83bdab09cda48bc2d89ac75aJust					panose.fromXML(element, ttFont)
1827842e56b97ce677b83bdab09cda48bc2d89ac75aJust		elif name in ("ulUnicodeRange1", "ulUnicodeRange2",
1837842e56b97ce677b83bdab09cda48bc2d89ac75aJust				"ulUnicodeRange3", "ulUnicodeRange4",
1847842e56b97ce677b83bdab09cda48bc2d89ac75aJust				"ulCodePageRange1", "ulCodePageRange2",
1857842e56b97ce677b83bdab09cda48bc2d89ac75aJust				"fsType", "fsSelection"):
1867842e56b97ce677b83bdab09cda48bc2d89ac75aJust			setattr(self, name, binary2num(attrs["value"]))
1877842e56b97ce677b83bdab09cda48bc2d89ac75aJust		elif name == "achVendID":
1887842e56b97ce677b83bdab09cda48bc2d89ac75aJust			setattr(self, name, safeEval("'''" + attrs["value"] + "'''"))
1897842e56b97ce677b83bdab09cda48bc2d89ac75aJust		else:
1907842e56b97ce677b83bdab09cda48bc2d89ac75aJust			setattr(self, name, safeEval(attrs["value"]))
1917842e56b97ce677b83bdab09cda48bc2d89ac75aJust
1927842e56b97ce677b83bdab09cda48bc2d89ac75aJust
193