28
28
import six
29
29
30
30
import binascii
31
+ import enum
31
32
import io
32
33
import itertools
33
34
import re
@@ -40,6 +41,11 @@ def ord(x):
40
41
return x
41
42
42
43
44
+ # token types
45
+ _TokenType = enum .Enum ('_TokenType' ,
46
+ 'whitespace name string delimiter number' )
47
+
48
+
43
49
class Type1Font (object ):
44
50
"""
45
51
A class representing a Type-1 font, for use by backends.
@@ -143,25 +149,18 @@ def _split(self, data):
143
149
_comment_re = re .compile (br'%[^\r\n\v]*' )
144
150
_instring_re = re .compile (br'[()\\]' )
145
151
146
- # token types, compared via object identity (poor man's enum)
147
- _whitespace = object ()
148
- _name = object ()
149
- _string = object ()
150
- _delimiter = object ()
151
- _number = object ()
152
-
153
152
@classmethod
154
153
def _tokens (cls , text ):
155
154
"""
156
155
A PostScript tokenizer. Yield (token, value) pairs such as
157
- (cls._whitespace , ' ') or (cls._name , '/Foobar').
156
+ (_TokenType.whitespace , ' ') or (_TokenType.name , '/Foobar').
158
157
"""
159
158
pos = 0
160
159
while pos < len (text ):
161
160
match = (cls ._comment_re .match (text [pos :]) or
162
161
cls ._whitespace_re .match (text [pos :]))
163
162
if match :
164
- yield (cls . _whitespace , match .group ())
163
+ yield (_TokenType . whitespace , match .group ())
165
164
pos += match .end ()
166
165
elif text [pos ] == b'(' :
167
166
start = pos
@@ -178,25 +177,25 @@ def _tokens(cls, text):
178
177
depth -= 1
179
178
else : # a backslash - skip the next character
180
179
pos += 1
181
- yield (cls . _string , text [start :pos ])
180
+ yield (_TokenType . string , text [start :pos ])
182
181
elif text [pos :pos + 2 ] in (b'<<' , b'>>' ):
183
- yield (cls . _delimiter , text [pos :pos + 2 ])
182
+ yield (_TokenType . delimiter , text [pos :pos + 2 ])
184
183
pos += 2
185
184
elif text [pos ] == b'<' :
186
185
start = pos
187
186
pos += text [pos :].index (b'>' )
188
- yield (cls . _string , text [start :pos ])
187
+ yield (_TokenType . string , text [start :pos ])
189
188
else :
190
189
match = cls ._token_re .match (text [pos :])
191
190
if match :
192
191
try :
193
192
float (match .group ())
194
- yield (cls . _number , match .group ())
193
+ yield (_TokenType . number , match .group ())
195
194
except ValueError :
196
- yield (cls . _name , match .group ())
195
+ yield (_TokenType . name , match .group ())
197
196
pos += match .end ()
198
197
else :
199
- yield (cls . _delimiter , text [pos :pos + 1 ])
198
+ yield (_TokenType . delimiter , text [pos :pos + 1 ])
200
199
pos += 1
201
200
202
201
def _parse (self ):
@@ -210,23 +209,23 @@ def _parse(self):
210
209
'UnderlinePosition' : - 100 , 'UnderlineThickness' : 50 }
211
210
filtered = ((token , value )
212
211
for token , value in self ._tokens (self .parts [0 ])
213
- if token is not self . _whitespace )
212
+ if token is not _TokenType . whitespace )
214
213
# The spec calls this an ASCII format; in Python 2.x we could
215
214
# just treat the strings and names as opaque bytes but let's
216
215
# turn them into proper Unicode, and be lenient in case of high bytes.
217
216
convert = lambda x : x .decode ('ascii' , 'replace' )
218
217
for token , value in filtered :
219
- if token is self . _name and value .startswith (b'/' ):
218
+ if token is _TokenType . name and value .startswith (b'/' ):
220
219
key = convert (value [1 :])
221
220
token , value = next (filtered )
222
- if token is self . _name :
221
+ if token is _TokenType . name :
223
222
if value in (b'true' , b'false' ):
224
223
value = value == b'true'
225
224
else :
226
225
value = convert (value .lstrip (b'/' ))
227
- elif token is self . _string :
226
+ elif token is _TokenType . string :
228
227
value = convert (value .lstrip (b'(' ).rstrip (b')' ))
229
- elif token is self . _number :
228
+ elif token is _TokenType . number :
230
229
if b'.' in value :
231
230
value = float (value )
232
231
else :
@@ -284,7 +283,7 @@ def replacer(tokens):
284
283
token , value = next (tokens ) # name, e.g., /FontMatrix
285
284
yield bytes (value )
286
285
token , value = next (tokens ) # possible whitespace
287
- while token is cls . _whitespace :
286
+ while token is _TokenType . whitespace :
288
287
yield bytes (value )
289
288
token , value = next (tokens )
290
289
if value != b'[' : # name/number/etc.
@@ -309,7 +308,7 @@ def suppress(tokens):
309
308
b'/UniqueID' : suppress }
310
309
311
310
for token , value in tokens :
312
- if token is cls . _name and value in table :
311
+ if token is _TokenType . name and value in table :
313
312
for value in table [value ](itertools .chain ([(token , value )],
314
313
tokens )):
315
314
yield value
0 commit comments