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