@@ -85,25 +85,6 @@ def _to_bool(s):
8585 return True
8686
8787
88- def _sanity_check (fh ):
89- """
90- Check if the file looks like AFM; if it doesn't, raise `RuntimeError`.
91- """
92- # Remember the file position in case the caller wants to
93- # do something else with the file.
94- pos = fh .tell ()
95- try :
96- line = next (fh )
97- finally :
98- fh .seek (pos , 0 )
99- # AFM spec, Section 4: The StartFontMetrics keyword [followed by a
100- # version number] must be the first line in the file, and the
101- # EndFontMetrics keyword must be the last non-empty line in the
102- # file. We just check the first line.
103- if not line .startswith (b'StartFontMetrics' ):
104- raise RuntimeError ('Not an AFM file' )
105-
106-
10788def _parse_header (fh ):
10889 """
10990 Reads the font metrics header (up to the char metrics) and returns
@@ -152,18 +133,26 @@ def _parse_header(fh):
152133 }
153134
154135 d = {}
136+ first_line = True
155137 for line in fh :
156138 line = line .rstrip ()
157139 if line .startswith (b'Comment' ):
158140 continue
159141 lst = line .split (b' ' , 1 )
160-
161142 key = lst [0 ]
143+ if first_line :
144+ # AFM spec, Section 4: The StartFontMetrics keyword
145+ # [followed by a version number] must be the first line in
146+ # the file, and the EndFontMetrics keyword must be the
147+ # last non-empty line in the file. We just check the
148+ # first header entry.
149+ if key != b'StartFontMetrics' :
150+ raise RuntimeError ('Not an AFM file' )
151+ first_line = False
162152 if len (lst ) == 2 :
163153 val = lst [1 ]
164154 else :
165155 val = b''
166-
167156 try :
168157 converter = header_converters [key ]
169158 except KeyError :
@@ -175,8 +164,10 @@ def _parse_header(fh):
175164 _log .error ('Value error parsing header in AFM: %s, %s' , key , val )
176165 continue
177166 if key == b'StartCharMetrics' :
178- return d
179- raise RuntimeError ('Bad parse' )
167+ break
168+ else :
169+ raise RuntimeError ('Bad parse' )
170+ return d
180171
181172
182173CharMetrics = namedtuple ('CharMetrics' , 'width, name, bbox' )
@@ -366,40 +357,13 @@ def _parse_optional(fh):
366357 return d [b'StartKernData' ], d [b'StartComposites' ]
367358
368359
369- def _parse_afm (fh ):
370- """
371- Parse the Adobe Font Metrics file in file handle *fh*.
372-
373- Returns
374- -------
375- header : dict
376- A header dict. See :func:`_parse_header`.
377- cmetrics_by_ascii : dict
378- From :func:`_parse_char_metrics`.
379- cmetrics_by_name : dict
380- From :func:`_parse_char_metrics`.
381- kernpairs : dict
382- From :func:`_parse_kern_pairs`.
383- composites : dict
384- From :func:`_parse_composites`
385-
386- """
387- _sanity_check (fh )
388- header = _parse_header (fh )
389- cmetrics_by_ascii , cmetrics_by_name = _parse_char_metrics (fh )
390- kernpairs , composites = _parse_optional (fh )
391- return header , cmetrics_by_ascii , cmetrics_by_name , kernpairs , composites
392-
393-
394360class AFM :
395361
396362 def __init__ (self , fh ):
397363 """Parse the AFM file in file object *fh*."""
398- (self ._header ,
399- self ._metrics ,
400- self ._metrics_by_name ,
401- self ._kern ,
402- self ._composite ) = _parse_afm (fh )
364+ self ._header = _parse_header (fh )
365+ self ._metrics , self ._metrics_by_name = _parse_char_metrics (fh )
366+ self ._kern , self ._composite = _parse_optional (fh )
403367
404368 def get_bbox_char (self , c , isord = False ):
405369 if not isord :
0 commit comments