@@ -85,25 +85,6 @@ def _to_bool(s):
85
85
return True
86
86
87
87
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
-
107
88
def _parse_header (fh ):
108
89
"""
109
90
Reads the font metrics header (up to the char metrics) and returns
@@ -152,18 +133,26 @@ def _parse_header(fh):
152
133
}
153
134
154
135
d = {}
136
+ first_line = True
155
137
for line in fh :
156
138
line = line .rstrip ()
157
139
if line .startswith (b'Comment' ):
158
140
continue
159
141
lst = line .split (b' ' , 1 )
160
-
161
142
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
162
152
if len (lst ) == 2 :
163
153
val = lst [1 ]
164
154
else :
165
155
val = b''
166
-
167
156
try :
168
157
converter = header_converters [key ]
169
158
except KeyError :
@@ -175,8 +164,10 @@ def _parse_header(fh):
175
164
_log .error ('Value error parsing header in AFM: %s, %s' , key , val )
176
165
continue
177
166
if key == b'StartCharMetrics' :
178
- return d
179
- raise RuntimeError ('Bad parse' )
167
+ break
168
+ else :
169
+ raise RuntimeError ('Bad parse' )
170
+ return d
180
171
181
172
182
173
CharMetrics = namedtuple ('CharMetrics' , 'width, name, bbox' )
@@ -366,40 +357,13 @@ def _parse_optional(fh):
366
357
return d [b'StartKernData' ], d [b'StartComposites' ]
367
358
368
359
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
-
394
360
class AFM :
395
361
396
362
def __init__ (self , fh ):
397
363
"""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 )
403
367
404
368
def get_bbox_char (self , c , isord = False ):
405
369
if not isord :
0 commit comments