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