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