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