@@ -263,11 +263,14 @@ class Type1Font:
263
263
Subrs - array of byte code subroutines
264
264
OtherSubrs - bytes object encoding some PostScript code
265
265
"""
266
- __slots__ = ('parts' , 'decrypted' , 'prop' , '_pos' )
266
+ __slots__ = ('parts' , 'decrypted' , 'prop' , '_pos' , '_abbr' )
267
267
# the _pos dict contains (begin, end) indices to parts[0] + decrypted
268
268
# so that they can be replaced when transforming the font;
269
269
# but since sometimes a definition appears in both parts[0] and decrypted,
270
270
# _pos[name] is an array of such pairs
271
+ #
272
+ # _abbr maps three standard abbreviations to their particular names in
273
+ # this font (e.g. 'RD' is named '-|' in some fonts)
271
274
272
275
def __init__ (self , input ):
273
276
"""
@@ -287,6 +290,7 @@ def __init__(self, input):
287
290
self .parts = self ._split (data )
288
291
289
292
self .decrypted = self ._decrypt (self .parts [1 ], 'eexec' )
293
+ self ._abbr = {'RD' : b'RD' , 'ND' : b'ND' , 'NP' : b'NP' }
290
294
self ._parse ()
291
295
292
296
def _read (self , file ):
@@ -486,10 +490,18 @@ def convert(x): return x.decode('ascii', 'replace')
486
490
break
487
491
488
492
# sometimes noaccess def and readonly def are abbreviated
489
- if kw .is_name (b'def' , b 'ND', b'RD' , b'|-' ):
493
+ if kw .is_name (b'def' , self . _abbr [ 'ND' ], self . _abbr [ 'NP' ] ):
490
494
prop [key ] = value
491
495
pos .setdefault (key , []).append ((keypos , kw .endpos ()))
492
496
497
+ # detect the standard abbreviations
498
+ if value == b'{noaccess def}' :
499
+ self ._abbr ['ND' ] = key .encode ('ascii' )
500
+ elif value == b'{noaccess put}' :
501
+ self ._abbr ['NP' ] = key .encode ('ascii' )
502
+ elif value == b'{string currentfile exch readstring pop}' :
503
+ self ._abbr ['RD' ] = key .encode ('ascii' )
504
+
493
505
# Fill in the various *Name properties
494
506
if 'FontName' not in prop :
495
507
prop ['FontName' ] = (prop .get ('FullName' ) or
@@ -515,8 +527,7 @@ def convert(x): return x.decode('ascii', 'replace')
515
527
self .prop = prop
516
528
self ._pos = pos
517
529
518
- @staticmethod
519
- def _parse_subrs (tokens , _data ):
530
+ def _parse_subrs (self , tokens , _data ):
520
531
count_token = next (tokens )
521
532
if not count_token .is_number ():
522
533
raise RuntimeError (
@@ -543,7 +554,12 @@ def _parse_subrs(tokens, _data):
543
554
"Second token following dup in Subrs definition must "
544
555
f"be a number, was { nbytes_token } "
545
556
)
546
- token = next (tokens ) # usually RD or |- but the font can define this to be anything
557
+ token = next (tokens )
558
+ if not token .is_name (self ._abbr ['RD' ]):
559
+ raise RuntimeError (
560
+ "Token preceding subr must be RD or equivalent, "
561
+ f"was { token } "
562
+ )
547
563
binary_token = tokens .send (1 + nbytes_token .numeric_value ())
548
564
array [index_token .numeric_value ()] = binary_token .value [1 :]
549
565
0 commit comments