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