35
35
def ord (x ):
36
36
return x
37
37
38
+
38
39
class Type1Font (object ):
39
40
"""
40
41
A class representing a Type-1 font, for use by backends.
@@ -75,13 +76,13 @@ def _read(self, file):
75
76
data = b''
76
77
while len (rawdata ) > 0 :
77
78
if not rawdata .startswith (b'\x80 ' ):
78
- raise RuntimeError ('Broken pfb file (expected byte 128, got %d)' % \
79
- ord (rawdata [0 ]))
79
+ raise RuntimeError ('Broken pfb file (expected byte 128, '
80
+ 'got %d)' % ord (rawdata [0 ]))
80
81
type = ord (rawdata [1 ])
81
- if type in (1 ,2 ):
82
+ if type in (1 , 2 ):
82
83
length , = struct .unpack ('<i' , rawdata [2 :6 ])
83
- segment = rawdata [6 :6 + length ]
84
- rawdata = rawdata [6 + length :]
84
+ segment = rawdata [6 :6 + length ]
85
+ rawdata = rawdata [6 + length :]
85
86
86
87
if type == 1 : # ASCII text: include verbatim
87
88
data += segment
@@ -91,7 +92,8 @@ def _read(self, file):
91
92
elif type == 3 : # end of file
92
93
break
93
94
else :
94
- raise RuntimeError ('Unknown segment type %d in pfb file' % type )
95
+ raise RuntimeError ('Unknown segment type %d in pfb file' %
96
+ type )
95
97
96
98
return data
97
99
@@ -129,7 +131,7 @@ def _split(self, data):
129
131
# but if we read a pfa file, this part is already in hex, and
130
132
# I am not quite sure if even the pfb format guarantees that
131
133
# it will be in binary).
132
- binary = b'' .join ([unichr (int (data [i :i + 2 ], 16 )).encode ('latin-1' )
134
+ binary = b'' .join ([unichr (int (data [i :i + 2 ], 16 )).encode ('latin-1' )
133
135
for i in range (len1 , idx , 2 )])
134
136
135
137
return data [:len1 ], binary , data [idx :]
@@ -138,6 +140,7 @@ def _split(self, data):
138
140
_token = re .compile (br'/{0,2}[^]\0\t\r\v\n ()<>{}/%[]+' )
139
141
_comment = re .compile (br'%[^\r\n\v]*' )
140
142
_instring = re .compile (br'[()\\]' )
143
+
141
144
@classmethod
142
145
def _tokens (cls , text ):
143
146
"""
@@ -146,7 +149,8 @@ def _tokens(cls, text):
146
149
"""
147
150
pos = 0
148
151
while pos < len (text ):
149
- match = cls ._comment .match (text [pos :]) or cls ._whitespace .match (text [pos :])
152
+ match = cls ._comment .match (text [pos :]) or \
153
+ cls ._whitespace .match (text [pos :])
150
154
if match :
151
155
yield ('whitespace' , match .group ())
152
156
pos += match .end ()
@@ -156,17 +160,18 @@ def _tokens(cls, text):
156
160
depth = 1
157
161
while depth :
158
162
match = cls ._instring .search (text [pos :])
159
- if match is None : return
163
+ if match is None :
164
+ return
160
165
pos += match .end ()
161
166
if match .group () == '(' :
162
167
depth += 1
163
168
elif match .group () == ')' :
164
169
depth -= 1
165
- else : # a backslash - skip the next character
170
+ else : # a backslash - skip the next character
166
171
pos += 1
167
172
yield ('string' , text [start :pos ])
168
- elif text [pos :pos + 2 ] in ('<<' , '>>' ):
169
- yield ('delimiter' , text [pos :pos + 2 ])
173
+ elif text [pos :pos + 2 ] in ('<<' , '>>' ):
174
+ yield ('delimiter' , text [pos :pos + 2 ])
170
175
pos += 2
171
176
elif text [pos ] == '<' :
172
177
start = pos
@@ -192,8 +197,8 @@ def _parse(self):
192
197
Compatibility" of the Type-1 spec.
193
198
"""
194
199
# Start with reasonable defaults
195
- prop = { 'weight' : 'Regular' , 'ItalicAngle' : 0.0 , 'isFixedPitch' : False ,
196
- 'UnderlinePosition' : - 100 , 'UnderlineThickness' : 50 }
200
+ prop = {'weight' : 'Regular' , 'ItalicAngle' : 0.0 , 'isFixedPitch' : False ,
201
+ 'UnderlinePosition' : - 100 , 'UnderlineThickness' : 50 }
197
202
tokenizer = self ._tokens (self .parts [0 ])
198
203
filtered = itertools .ifilter (lambda x : x [0 ] != 'whitespace' , tokenizer )
199
204
for token , value in filtered :
@@ -208,16 +213,20 @@ def _parse(self):
208
213
elif token == b'string' :
209
214
value = value .lstrip (b'(' ).rstrip (b')' )
210
215
elif token == b'number' :
211
- if b'.' in value : value = float (value )
212
- else : value = int (value )
213
- else : # more complicated value such as an array
216
+ if b'.' in value :
217
+ value = float (value )
218
+ else :
219
+ value = int (value )
220
+ else : # more complicated value such as an array
214
221
value = None
215
222
if key != b'FontInfo' and value is not None :
216
223
prop [key ] = value
217
224
218
225
# Fill in the various *Name properties
219
226
if 'FontName' not in prop :
220
- prop ['FontName' ] = prop .get ('FullName' ) or prop .get ('FamilyName' ) or 'Unknown'
227
+ prop ['FontName' ] = (prop .get ('FullName' ) or
228
+ prop .get ('FamilyName' ) or
229
+ 'Unknown' )
221
230
if 'FullName' not in prop :
222
231
prop ['FullName' ] = prop ['FontName' ]
223
232
if 'FamilyName' not in prop :
@@ -230,25 +239,27 @@ def _parse(self):
230
239
def _transformer (cls , tokens , slant , extend ):
231
240
def fontname (name ):
232
241
result = name
233
- if slant : result += '_Slant_' + str (int (1000 * slant ))
234
- if extend != 1.0 : result += '_Extend_' + str (int (1000 * extend ))
242
+ if slant :
243
+ result += '_Slant_' + str (int (1000 * slant ))
244
+ if extend != 1.0 :
245
+ result += '_Extend_' + str (int (1000 * extend ))
235
246
return result
236
247
237
248
def italicangle (angle ):
238
- return str (float (angle ) - np .arctan (slant )/ np .pi * 180 )
249
+ return str (float (angle ) - np .arctan (slant ) / np .pi * 180 )
239
250
240
251
def fontmatrix (array ):
241
252
array = array .lstrip ('[' ).rstrip (']' ).strip ().split ()
242
- array = [ float (x ) for x in array ]
243
- oldmatrix = np .eye (3 ,3 )
244
- oldmatrix [0 :3 ,0 ] = array [::2 ]
245
- oldmatrix [0 :3 ,1 ] = array [1 ::2 ]
253
+ array = [float (x ) for x in array ]
254
+ oldmatrix = np .eye (3 , 3 )
255
+ oldmatrix [0 :3 , 0 ] = array [::2 ]
256
+ oldmatrix [0 :3 , 1 ] = array [1 ::2 ]
246
257
modifier = np .array ([[extend , 0 , 0 ],
247
258
[slant , 1 , 0 ],
248
259
[0 , 0 , 1 ]])
249
260
newmatrix = np .dot (modifier , oldmatrix )
250
- array [::2 ] = newmatrix [0 :3 ,0 ]
251
- array [1 ::2 ] = newmatrix [0 :3 ,1 ]
261
+ array [::2 ] = newmatrix [0 :3 , 0 ]
262
+ array [1 ::2 ] = newmatrix [0 :3 , 1 ]
252
263
return '[' + ' ' .join (str (x ) for x in array ) + ']'
253
264
254
265
def replace (fun ):
@@ -275,15 +286,16 @@ def suppress(tokens):
275
286
pass
276
287
yield ''
277
288
278
- table = { '/FontName' : replace (fontname ),
279
- '/ItalicAngle' : replace (italicangle ),
280
- '/FontMatrix' : replace (fontmatrix ),
281
- '/UniqueID' : suppress }
289
+ table = {'/FontName' : replace (fontname ),
290
+ '/ItalicAngle' : replace (italicangle ),
291
+ '/FontMatrix' : replace (fontmatrix ),
292
+ '/UniqueID' : suppress }
282
293
283
294
while True :
284
295
token , value = next (tokens )
285
296
if token == 'name' and value in table :
286
- for value in table [value ](itertools .chain ([(token , value )], tokens )):
297
+ for value in table [value ](itertools .chain ([(token , value )],
298
+ tokens )):
287
299
yield value
288
300
else :
289
301
yield value
@@ -311,4 +323,3 @@ def transform(self, effects):
311
323
buffer .close ()
312
324
313
325
return Type1Font ((result , self .parts [1 ], self .parts [2 ]))
314
-
0 commit comments