O_S_2f_2.py revision 859967e5218bed974d05ddec93996b9aea2782a5
15f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencerimport DefaultTable
25f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencerimport sstruct
35f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencerfrom fontTools.misc.textTools import safeEval, num2binary, binary2num
45f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer
50bc735ffcfb223c0186419547abaa5c84482663eChris Lattner# panose classification
60bc735ffcfb223c0186419547abaa5c84482663eChris Lattner
75f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid SpencerpanoseFormat = """
85f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer	bFamilyType:        B
95f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer	bSerifStyle:        B
105f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer	bWeight:            B
115f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer	bProportion:        B
125f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer	bContrast:          B
135f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer	bStrokeVariation:   B
145f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer	bArmStyle:          B
155f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer	bLetterForm:        B
165f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer	bMidline:           B
17478851c3ed6bd784e7377dffd8e57b200c1b9ba9Benjamin Kramer	bXHeight:           B
185f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer"""
19eec51cf1ba5f0e62c9cdb81b5c63babdd6e649abJohn McCall
20d5532b6cfff2977e0c59fa6ead7f7973984a620dJohn McCallclass Panose:
2101d08018b7cf5ce1601707cfd7a84d22015fc04eDouglas Gregor
2201d08018b7cf5ce1601707cfd7a84d22015fc04eDouglas Gregor	def toXML(self, writer, ttFont):
2301d08018b7cf5ce1601707cfd7a84d22015fc04eDouglas Gregor		formatstring, names, fixes = sstruct.getformat(panoseFormat)
24aa49a7d70e58dac2aeb40664ba16d2ea571b8c95Daniel Dunbar		for name in names:
255f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer			writer.simpletag(name, value=getattr(self, name))
265f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer			writer.newline()
275f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer
28aa165f8458b51c546bebff947343e1a36f3594cbDouglas Gregor	def fromXML(self, (name, attrs, content), ttFont):
29aa165f8458b51c546bebff947343e1a36f3594cbDouglas Gregor		setattr(self, name, safeEval(attrs["value"]))
30aa165f8458b51c546bebff947343e1a36f3594cbDouglas Gregor
31aa165f8458b51c546bebff947343e1a36f3594cbDouglas Gregor
32aa165f8458b51c546bebff947343e1a36f3594cbDouglas Gregor# 'sfnt' OS/2 and Windows Metrics table - 'OS/2'
334c5d320a7581f4b80b151630c91cea5727fa9923Sebastian Redl
341060aff23f72135f8b50034a1e80f16725ebc56cTed KremenekOS2_format_0 = """
351060aff23f72135f8b50034a1e80f16725ebc56cTed Kremenek	>   # big endian
361060aff23f72135f8b50034a1e80f16725ebc56cTed Kremenek	version:                H       # version
371060aff23f72135f8b50034a1e80f16725ebc56cTed Kremenek	xAvgCharWidth:          h       # average character width
383fd95ce225393fe4a3623e429766a8c3f487ff9dDouglas Gregor	usWeightClass:          H       # degree of thickness of strokes
393fd95ce225393fe4a3623e429766a8c3f487ff9dDouglas Gregor	usWidthClass:           H       # aspect ratio
403fd95ce225393fe4a3623e429766a8c3f487ff9dDouglas Gregor	fsType:                 h       # type flags
413fd95ce225393fe4a3623e429766a8c3f487ff9dDouglas Gregor	ySubscriptXSize:        h       # subscript horizontal font size
423fd95ce225393fe4a3623e429766a8c3f487ff9dDouglas Gregor	ySubscriptYSize:        h       # subscript vertical font size
433fd95ce225393fe4a3623e429766a8c3f487ff9dDouglas Gregor	ySubscriptXOffset:      h       # subscript x offset
443fd95ce225393fe4a3623e429766a8c3f487ff9dDouglas Gregor	ySubscriptYOffset:      h       # subscript y offset
453fd95ce225393fe4a3623e429766a8c3f487ff9dDouglas Gregor	ySuperscriptXSize:      h       # superscript horizontal font size
463fd95ce225393fe4a3623e429766a8c3f487ff9dDouglas Gregor	ySuperscriptYSize:      h       # superscript vertical font size
473fd95ce225393fe4a3623e429766a8c3f487ff9dDouglas Gregor	ySuperscriptXOffset:    h       # superscript x offset
483fd95ce225393fe4a3623e429766a8c3f487ff9dDouglas Gregor	ySuperscriptYOffset:    h       # superscript y offset
493fd95ce225393fe4a3623e429766a8c3f487ff9dDouglas Gregor	yStrikeoutSize:         h       # strikeout size
503fd95ce225393fe4a3623e429766a8c3f487ff9dDouglas Gregor	yStrikeoutPosition:     h       # strikeout position
51b4609806e9232593ece09ce08b630836e825865cDouglas Gregor	sFamilyClass:           h       # font family class and subclass
52063daf6e196c51f162e0485478355d8e280eef5cDouglas Gregor	panose:                 10s     # panose classification number
53063daf6e196c51f162e0485478355d8e280eef5cDouglas Gregor	ulUnicodeRange1:        l       # character range
544548ca2912e5f2b78a20e50c58d8a1a9c5e9e67cArgyrios Kyrtzidis	ulUnicodeRange2:        l       # character range
55063daf6e196c51f162e0485478355d8e280eef5cDouglas Gregor	ulUnicodeRange3:        l       # character range
56be9af1288881110e406b87914162eaa59f1e5918Lang Hames	ulUnicodeRange4:        l       # character range
57be9af1288881110e406b87914162eaa59f1e5918Lang Hames	achVendID:              4s      # font vendor identification
58be9af1288881110e406b87914162eaa59f1e5918Lang Hames	fsSelection:            H       # font selection flags
59be9af1288881110e406b87914162eaa59f1e5918Lang Hames	fsFirstCharIndex:       H       # first unicode character index
60be9af1288881110e406b87914162eaa59f1e5918Lang Hames	fsLastCharIndex:        H       # last unicode character index
614548ca2912e5f2b78a20e50c58d8a1a9c5e9e67cArgyrios Kyrtzidis	usTypoAscender:         H       # typographic ascender
62b4609806e9232593ece09ce08b630836e825865cDouglas Gregor	usTypoDescender:        H       # typographic descender
631eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump	usTypoLineGap:          H       # typographic line gap
643b6bef9a213249c6ab6d67c07b1ac6380961be3eBenjamin Kramer	usWinAscent:            H       # Windows ascender
65be9af1288881110e406b87914162eaa59f1e5918Lang Hames	usWinDescent:           H       # Windows descender
663b6bef9a213249c6ab6d67c07b1ac6380961be3eBenjamin Kramer"""
67f89e55ab1bfb3ea997f8b02997c611a02254eb2dJohn McCall
68be9af1288881110e406b87914162eaa59f1e5918Lang HamesOS2_format_1_addition =  """
694548ca2912e5f2b78a20e50c58d8a1a9c5e9e67cArgyrios Kyrtzidis	ulCodePageRange1:   l
704548ca2912e5f2b78a20e50c58d8a1a9c5e9e67cArgyrios Kyrtzidis	ulCodePageRange2:   l
711eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump"""
72ba0a9006dbc4814e1e35f82812cb5a1dad65e8b8Argyrios Kyrtzidis
731eb4433ac451dc16f4133a88af2d002ac26c58efMike StumpOS2_format_2_addition =  OS2_format_1_addition + """
74b4609806e9232593ece09ce08b630836e825865cDouglas Gregor	sxHeight:           h
75b4609806e9232593ece09ce08b630836e825865cDouglas Gregor	sCapHeight:         h
76b4609806e9232593ece09ce08b630836e825865cDouglas Gregor	usDefaultChar:      H
77063daf6e196c51f162e0485478355d8e280eef5cDouglas Gregor	usBreakChar:        H
78b4609806e9232593ece09ce08b630836e825865cDouglas Gregor	usMaxContex:        H
79b4609806e9232593ece09ce08b630836e825865cDouglas Gregor"""
80b4609806e9232593ece09ce08b630836e825865cDouglas Gregor
81b4609806e9232593ece09ce08b630836e825865cDouglas Gregorbigendian = "	>	# big endian\n"
82b4609806e9232593ece09ce08b630836e825865cDouglas Gregor
83b4609806e9232593ece09ce08b630836e825865cDouglas GregorOS2_format_1 = OS2_format_0 + OS2_format_1_addition
84b4609806e9232593ece09ce08b630836e825865cDouglas GregorOS2_format_2 = OS2_format_0 + OS2_format_2_addition
85b4609806e9232593ece09ce08b630836e825865cDouglas GregorOS2_format_1_addition = bigendian + OS2_format_1_addition
864548ca2912e5f2b78a20e50c58d8a1a9c5e9e67cArgyrios KyrtzidisOS2_format_2_addition = bigendian + OS2_format_2_addition
871eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
881eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
891eb4433ac451dc16f4133a88af2d002ac26c58efMike Stumpclass table_O_S_2f_2(DefaultTable.DefaultTable):
90b4609806e9232593ece09ce08b630836e825865cDouglas Gregor
914548ca2912e5f2b78a20e50c58d8a1a9c5e9e67cArgyrios Kyrtzidis	"""the OS/2 table"""
92be9af1288881110e406b87914162eaa59f1e5918Lang Hames
93be9af1288881110e406b87914162eaa59f1e5918Lang Hames	def decompile(self, data, ttFont):
94be9af1288881110e406b87914162eaa59f1e5918Lang Hames		dummy, data = sstruct.unpack2(OS2_format_0, data, self)
95be9af1288881110e406b87914162eaa59f1e5918Lang Hames		if self.version == 1:
96be9af1288881110e406b87914162eaa59f1e5918Lang Hames			sstruct.unpack(OS2_format_1_addition, data, self)
97be9af1288881110e406b87914162eaa59f1e5918Lang Hames		elif self.version == 2:
98be9af1288881110e406b87914162eaa59f1e5918Lang Hames			sstruct.unpack(OS2_format_2_addition, data, self)
99be9af1288881110e406b87914162eaa59f1e5918Lang Hames		elif self.version <> 0:
1004548ca2912e5f2b78a20e50c58d8a1a9c5e9e67cArgyrios Kyrtzidis			from fontTools import ttLib
1014548ca2912e5f2b78a20e50c58d8a1a9c5e9e67cArgyrios Kyrtzidis			raise ttLib.TTLibError, "unknown format for OS/2 table: version %s" % self.version
102b4609806e9232593ece09ce08b630836e825865cDouglas Gregor		self.panose = sstruct.unpack(panoseFormat, self.panose, Panose())
103b4609806e9232593ece09ce08b630836e825865cDouglas Gregor
10488a3514f36de96b19cdf50141c640df1a5f13f6cDouglas Gregor	def compile(self, ttFont):
10588a3514f36de96b19cdf50141c640df1a5f13f6cDouglas Gregor		panose = self.panose
10688a3514f36de96b19cdf50141c640df1a5f13f6cDouglas Gregor		self.panose = sstruct.pack(panoseFormat, self.panose)
10788a3514f36de96b19cdf50141c640df1a5f13f6cDouglas Gregor		if self.version == 0:
10888a3514f36de96b19cdf50141c640df1a5f13f6cDouglas Gregor			data = sstruct.pack(OS2_format_0, self)
10988a3514f36de96b19cdf50141c640df1a5f13f6cDouglas Gregor		elif self.version == 1:
11088a3514f36de96b19cdf50141c640df1a5f13f6cDouglas Gregor			data = sstruct.pack(OS2_format_1, self)
11188a3514f36de96b19cdf50141c640df1a5f13f6cDouglas Gregor		elif self.version == 2:
11288a3514f36de96b19cdf50141c640df1a5f13f6cDouglas Gregor			data = sstruct.pack(OS2_format_2, self)
11388a3514f36de96b19cdf50141c640df1a5f13f6cDouglas Gregor		else:
1143b6bef9a213249c6ab6d67c07b1ac6380961be3eBenjamin Kramer			from fontTools import ttLib
115f89e55ab1bfb3ea997f8b02997c611a02254eb2dJohn McCall			raise ttLib.TTLibError, "unknown format for OS/2 table: version %s" % self.version
1163b6bef9a213249c6ab6d67c07b1ac6380961be3eBenjamin Kramer		self.panose = panose
11788a3514f36de96b19cdf50141c640df1a5f13f6cDouglas Gregor		return data
1181817bd483b538fd3f4530649f5cb900bad9e8a76Chris Lattner
1191817bd483b538fd3f4530649f5cb900bad9e8a76Chris Lattner	def toXML(self, writer, ttFont):
1201817bd483b538fd3f4530649f5cb900bad9e8a76Chris Lattner		if self.version == 1:
12188a3514f36de96b19cdf50141c640df1a5f13f6cDouglas Gregor			format = OS2_format_1
12288a3514f36de96b19cdf50141c640df1a5f13f6cDouglas Gregor		elif self.version == 2:
12388a3514f36de96b19cdf50141c640df1a5f13f6cDouglas Gregor			format = OS2_format_2
124b277159055933e610bbc80262b600d3ad7e0595cTed Kremenek		else:
125ba243b59a1074e0962f6abfa3bb9aa984eac1245David Blaikie			format = OS2_format_0
126b277159055933e610bbc80262b600d3ad7e0595cTed Kremenek		formatstring, names, fixes = sstruct.getformat(format)
127b277159055933e610bbc80262b600d3ad7e0595cTed Kremenek		for name in names:
12888a3514f36de96b19cdf50141c640df1a5f13f6cDouglas Gregor			value = getattr(self, name)
129007a9b1c632bfaac20e41c60cbe07fdc6d0e647cChandler Carruth			if type(value) == type(0L):
130007a9b1c632bfaac20e41c60cbe07fdc6d0e647cChandler Carruth				value = int(value)
131007a9b1c632bfaac20e41c60cbe07fdc6d0e647cChandler Carruth			if name=="panose":
132007a9b1c632bfaac20e41c60cbe07fdc6d0e647cChandler Carruth				writer.begintag("panose")
133007a9b1c632bfaac20e41c60cbe07fdc6d0e647cChandler Carruth				writer.newline()
1340cf3c0eecbff007cea2750c113894b47d9e09f33David Blaikie				value.toXML(writer, ttFont)
135007a9b1c632bfaac20e41c60cbe07fdc6d0e647cChandler Carruth				writer.endtag("panose")
1361eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump			elif name in ("ulUnicodeRange1", "ulUnicodeRange2",
13788a3514f36de96b19cdf50141c640df1a5f13f6cDouglas Gregor					"ulUnicodeRange3", "ulUnicodeRange4",
13888a3514f36de96b19cdf50141c640df1a5f13f6cDouglas Gregor					"ulCodePageRange1", "ulCodePageRange2"):
13988a3514f36de96b19cdf50141c640df1a5f13f6cDouglas Gregor				writer.simpletag(name, value=num2binary(value))
14088a3514f36de96b19cdf50141c640df1a5f13f6cDouglas Gregor			elif name in ("fsType", "fsSelection"):
141e08ce650a2b02410eddd1f60a4aa6b3d4be71e73Peter Collingbourne				writer.simpletag(name, value=num2binary(value, 16))
142e08ce650a2b02410eddd1f60a4aa6b3d4be71e73Peter Collingbourne			elif name == "achVendID":
143e08ce650a2b02410eddd1f60a4aa6b3d4be71e73Peter Collingbourne				writer.simpletag(name, value=repr(value)[1:-1])
144e08ce650a2b02410eddd1f60a4aa6b3d4be71e73Peter Collingbourne			else:
145e08ce650a2b02410eddd1f60a4aa6b3d4be71e73Peter Collingbourne				writer.simpletag(name, value=value)
146e08ce650a2b02410eddd1f60a4aa6b3d4be71e73Peter Collingbourne			writer.newline()
147e08ce650a2b02410eddd1f60a4aa6b3d4be71e73Peter Collingbourne
1483b6bef9a213249c6ab6d67c07b1ac6380961be3eBenjamin Kramer	def fromXML(self, (name, attrs, content), ttFont):
1493b6bef9a213249c6ab6d67c07b1ac6380961be3eBenjamin Kramer		if name == "panose":
1503b6bef9a213249c6ab6d67c07b1ac6380961be3eBenjamin Kramer			self.panose = panose = Panose()
151e08ce650a2b02410eddd1f60a4aa6b3d4be71e73Peter Collingbourne			for element in content:
152e08ce650a2b02410eddd1f60a4aa6b3d4be71e73Peter Collingbourne				if type(element) == type(()):
153e08ce650a2b02410eddd1f60a4aa6b3d4be71e73Peter Collingbourne					panose.fromXML(element, ttFont)
154e08ce650a2b02410eddd1f60a4aa6b3d4be71e73Peter Collingbourne		elif name in ("ulUnicodeRange1", "ulUnicodeRange2",
155e08ce650a2b02410eddd1f60a4aa6b3d4be71e73Peter Collingbourne				"ulUnicodeRange3", "ulUnicodeRange4",
156e08ce650a2b02410eddd1f60a4aa6b3d4be71e73Peter Collingbourne				"ulCodePageRange1", "ulCodePageRange2",
157e08ce650a2b02410eddd1f60a4aa6b3d4be71e73Peter Collingbourne				"fsType", "fsSelection"):
158e08ce650a2b02410eddd1f60a4aa6b3d4be71e73Peter Collingbourne			setattr(self, name, binary2num(attrs["value"]))
159e08ce650a2b02410eddd1f60a4aa6b3d4be71e73Peter Collingbourne		elif name == "achVendID":
160e08ce650a2b02410eddd1f60a4aa6b3d4be71e73Peter Collingbourne			setattr(self, name, safeEval("'''" + attrs["value"] + "'''"))
161e08ce650a2b02410eddd1f60a4aa6b3d4be71e73Peter Collingbourne		else:
162e08ce650a2b02410eddd1f60a4aa6b3d4be71e73Peter Collingbourne			setattr(self, name, safeEval(attrs["value"]))
163e08ce650a2b02410eddd1f60a4aa6b3d4be71e73Peter Collingbourne
164e08ce650a2b02410eddd1f60a4aa6b3d4be71e73Peter Collingbourne
165e08ce650a2b02410eddd1f60a4aa6b3d4be71e73Peter Collingbourne