@@ -54,13 +54,13 @@ def _to_int(x):
5454_to_str = str
5555
5656def _to_list_of_ints (s ):
57- s = s .replace (',' , ' ' )
57+ s = s .replace (b ',' , b ' ' )
5858 return [_to_int (val ) for val in s .split ()]
5959
6060def _to_list_of_floats (s ):
6161 return [_to_float (val ) for val in s .split ()]
6262def _to_bool (s ):
63- if s .lower ().strip () in ('false' , '0' , 'no' ): return False
63+ if s .lower ().strip () in (b 'false' , b '0' , b 'no' ): return False
6464 else : return True
6565
6666
@@ -82,7 +82,7 @@ def _sanity_check(fh):
8282 # version number] must be the first line in the file, and the
8383 # EndFontMetrics keyword must be the last non-empty line in the
8484 # file. We just check the first line.
85- if not line .startswith ('StartFontMetrics' ):
85+ if not line .startswith (b 'StartFontMetrics' ):
8686 raise RuntimeError ('Not an AFM file' )
8787
8888def _parse_header (fh ):
@@ -104,38 +104,38 @@ def _parse_header(fh):
104104
105105 """
106106 headerConverters = {
107- 'StartFontMetrics' : _to_float ,
108- 'FontName' : _to_str ,
109- 'FullName' : _to_str ,
110- 'FamilyName' : _to_str ,
111- 'Weight' : _to_str ,
112- 'ItalicAngle' : _to_float ,
113- 'IsFixedPitch' : _to_bool ,
114- 'FontBBox' : _to_list_of_ints ,
115- 'UnderlinePosition' : _to_int ,
116- 'UnderlineThickness' : _to_int ,
117- 'Version' : _to_str ,
118- 'Notice' : _to_str ,
119- 'EncodingScheme' : _to_str ,
120- 'CapHeight' : _to_float , # Is the second version a mistake, or
121- 'Capheight' : _to_float , # do some AFM files contain 'Capheight'? -JKS
122- 'XHeight' : _to_float ,
123- 'Ascender' : _to_float ,
124- 'Descender' : _to_float ,
125- 'StdHW' : _to_float ,
126- 'StdVW' : _to_float ,
127- 'StartCharMetrics' : _to_int ,
128- 'CharacterSet' : _to_str ,
129- 'Characters' : _to_int ,
107+ b 'StartFontMetrics' : _to_float ,
108+ b 'FontName' : _to_str ,
109+ b 'FullName' : _to_str ,
110+ b 'FamilyName' : _to_str ,
111+ b 'Weight' : _to_str ,
112+ b 'ItalicAngle' : _to_float ,
113+ b 'IsFixedPitch' : _to_bool ,
114+ b 'FontBBox' : _to_list_of_ints ,
115+ b 'UnderlinePosition' : _to_int ,
116+ b 'UnderlineThickness' : _to_int ,
117+ b 'Version' : _to_str ,
118+ b 'Notice' : _to_str ,
119+ b 'EncodingScheme' : _to_str ,
120+ b 'CapHeight' : _to_float , # Is the second version a mistake, or
121+ b 'Capheight' : _to_float , # do some AFM files contain 'Capheight'? -JKS
122+ b 'XHeight' : _to_float ,
123+ b 'Ascender' : _to_float ,
124+ b 'Descender' : _to_float ,
125+ b 'StdHW' : _to_float ,
126+ b 'StdVW' : _to_float ,
127+ b 'StartCharMetrics' : _to_int ,
128+ b 'CharacterSet' : _to_str ,
129+ b 'Characters' : _to_int ,
130130 }
131131
132132 d = {}
133133 while 1 :
134134 line = fh .readline ()
135135 if not line : break
136136 line = line .rstrip ()
137- if line .startswith ('Comment' ): continue
138- lst = line .split ( ' ' , 1 )
137+ if line .startswith (b 'Comment' ): continue
138+ lst = line .split (b ' ' , 1 )
139139 #print '%-s\t%-d line :: %-s' % ( fh.name, len(lst), line )
140140 key = lst [0 ]
141141 if len ( lst ) == 2 :
@@ -150,7 +150,7 @@ def _parse_header(fh):
150150 except KeyError :
151151 print ('Found an unknown keyword in AFM header (was %s)' % key , file = sys .stderr )
152152 continue
153- if key == 'StartCharMetrics' : return d
153+ if key == b 'StartCharMetrics' : return d
154154 raise RuntimeError ('Bad parse' )
155155
156156def _parse_char_metrics (fh ):
@@ -170,12 +170,13 @@ def _parse_char_metrics(fh):
170170 line = fh .readline ()
171171 if not line : break
172172 line = line .rstrip ()
173- if line .startswith ('EndCharMetrics' ): return ascii_d , name_d
174- vals = line .split (';' )[:4 ]
173+ if line .startswith (b 'EndCharMetrics' ): return ascii_d , name_d
174+ vals = line .split (b ';' )[:4 ]
175175 if len (vals ) != 4 : raise RuntimeError ('Bad char metrics line: %s' % line )
176176 num = _to_int (vals [0 ].split ()[1 ])
177177 wx = _to_float (vals [1 ].split ()[1 ])
178178 name = vals [2 ].split ()[1 ]
179+ name = name .decode ('ascii' )
179180 bbox = _to_list_of_floats (vals [3 ][2 :])
180181 bbox = map (int , bbox )
181182 # Workaround: If the character name is 'Euro', give it the corresponding
@@ -200,7 +201,7 @@ def _parse_kern_pairs(fh):
200201 """
201202
202203 line = fh .readline ()
203- if not line .startswith ('StartKernPairs' ):
204+ if not line .startswith (b 'StartKernPairs' ):
204205 raise RuntimeError ('Bad start of kern pairs data: %s' % line )
205206
206207 d = {}
@@ -209,11 +210,11 @@ def _parse_kern_pairs(fh):
209210 if not line : break
210211 line = line .rstrip ()
211212 if len (line )== 0 : continue
212- if line .startswith ('EndKernPairs' ):
213+ if line .startswith (b 'EndKernPairs' ):
213214 fh .readline () # EndKernData
214215 return d
215216 vals = line .split ()
216- if len (vals )!= 4 or vals [0 ]!= 'KPX' :
217+ if len (vals )!= 4 or vals [0 ]!= b 'KPX' :
217218 raise RuntimeError ('Bad kern pairs line: %s' % line )
218219 c1 , c2 , val = vals [1 ], vals [2 ], _to_float (vals [3 ])
219220 d [(c1 ,c2 )] = val
@@ -239,9 +240,9 @@ def _parse_composites(fh):
239240 if not line : break
240241 line = line .rstrip ()
241242 if len (line )== 0 : continue
242- if line .startswith ('EndComposites' ):
243+ if line .startswith (b 'EndComposites' ):
243244 return d
244- vals = line .split (';' )
245+ vals = line .split (b ';' )
245246 cc = vals [0 ].split ()
246247 name , numParts = cc [1 ], _to_int (cc [2 ])
247248 pccParts = []
@@ -263,11 +264,11 @@ def _parse_optional(fh):
263264 otherwise
264265 """
265266 optional = {
266- 'StartKernData' : _parse_kern_pairs ,
267- 'StartComposites' : _parse_composites ,
267+ b 'StartKernData' : _parse_kern_pairs ,
268+ b 'StartComposites' : _parse_composites ,
268269 }
269270
270- d = {'StartKernData' :{}, 'StartComposites' :{}}
271+ d = {b 'StartKernData' :{}, b 'StartComposites' :{}}
271272 while 1 :
272273 line = fh .readline ()
273274 if not line : break
@@ -277,7 +278,7 @@ def _parse_optional(fh):
277278
278279 if key in optional : d [key ] = optional [key ](fh )
279280
280- l = ( d ['StartKernData' ], d ['StartComposites' ] )
281+ l = ( d [b 'StartKernData' ], d [b 'StartComposites' ] )
281282 return l
282283
283284def parse_afm (fh ):
@@ -357,7 +358,7 @@ def get_str_bbox_and_descent(self, s):
357358 maxy = 0
358359 left = 0
359360 if not isinstance (s , unicode ):
360- s = s .decode ()
361+ s = s .decode ('ascii' )
361362 for c in s :
362363 if c == '\n ' : continue
363364 name = uni2type1 .get (ord (c ), 'question' )
@@ -441,59 +442,59 @@ def get_kern_dist_from_name(self, name1, name2):
441442
442443 def get_fontname (self ):
443444 "Return the font name, eg, 'Times-Roman'"
444- return self ._header ['FontName' ]
445+ return self ._header [b 'FontName' ]
445446
446447 def get_fullname (self ):
447448 "Return the font full name, eg, 'Times-Roman'"
448449 name = self ._header .get ('FullName' )
449450 if name is None : # use FontName as a substitute
450- name = self ._header ['FontName' ]
451+ name = self ._header [b 'FontName' ]
451452 return name
452453
453454 def get_familyname (self ):
454455 "Return the font family name, eg, 'Times'"
455- name = self ._header .get ('FamilyName' )
456+ name = self ._header .get (b 'FamilyName' )
456457 if name is not None :
457458 return name
458459
459460 # FamilyName not specified so we'll make a guess
460461 name = self .get_fullname ()
461- extras = r '(?i)([ -](regular|plain|italic|oblique|bold|semibold|light|ultralight|extra|condensed))+$'
462+ extras = br '(?i)([ -](regular|plain|italic|oblique|bold|semibold|light|ultralight|extra|condensed))+$'
462463 return re .sub (extras , '' , name )
463464
464465 def get_weight (self ):
465466 "Return the font weight, eg, 'Bold' or 'Roman'"
466- return self ._header ['Weight' ]
467+ return self ._header [b 'Weight' ]
467468
468469 def get_angle (self ):
469470 "Return the fontangle as float"
470- return self ._header ['ItalicAngle' ]
471+ return self ._header [b 'ItalicAngle' ]
471472
472473 def get_capheight (self ):
473474 "Return the cap height as float"
474- return self ._header ['CapHeight' ]
475+ return self ._header [b 'CapHeight' ]
475476
476477 def get_xheight (self ):
477478 "Return the xheight as float"
478- return self ._header ['XHeight' ]
479+ return self ._header [b 'XHeight' ]
479480
480481 def get_underline_thickness (self ):
481482 "Return the underline thickness as float"
482- return self ._header ['UnderlineThickness' ]
483+ return self ._header [b 'UnderlineThickness' ]
483484
484485 def get_horizontal_stem_width (self ):
485486 """
486487 Return the standard horizontal stem width as float, or *None* if
487488 not specified in AFM file.
488489 """
489- return self ._header .get ('StdHW' , None )
490+ return self ._header .get (b 'StdHW' , None )
490491
491492 def get_vertical_stem_width (self ):
492493 """
493494 Return the standard vertical stem width as float, or *None* if
494495 not specified in AFM file.
495496 """
496- return self ._header .get ('StdVW' , None )
497+ return self ._header .get (b 'StdVW' , None )
497498
498499
499500if __name__ == '__main__' :
0 commit comments