Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 25613b9

Browse files
committed
Recognize abbreviations of PostScript code
Type-1 fonts are required to have subroutines with specific contents but their names may vary. They are usually ND, NP and RD but names like | and |- appear too.
1 parent 920aed0 commit 25613b9

File tree

2 files changed

+24
-5
lines changed

2 files changed

+24
-5
lines changed

lib/matplotlib/tests/test_type1font.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ def test_Type1Font():
4141
assert slanted.prop['ItalicAngle'] == -45
4242
assert font.prop['Encoding'][5] == 'Pi'
4343
assert isinstance(font.prop['CharStrings']['Pi'], bytes)
44+
assert font._abbr['ND'] == 'ND'
4445

4546
differ = difflib.Differ()
4647
diff = list(differ.compare(
@@ -84,6 +85,7 @@ def test_Type1Font_2():
8485
assert font.prop['Encoding'][65] == 'A' # the font uses StandardEncoding
8586
(pos0, pos1), = font._pos['Encoding']
8687
assert font.parts[0][pos0:pos1] == b'/Encoding StandardEncoding'
88+
assert font._abbr['ND'] == '|-'
8789

8890

8991
def test_overprecision():

lib/matplotlib/type1font.py

Lines changed: 22 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -285,11 +285,14 @@ class Type1Font:
285285
Subrs - array of byte code subroutines
286286
OtherSubrs - bytes object encoding some PostScript code
287287
"""
288-
__slots__ = ('parts', 'decrypted', 'prop', '_pos')
288+
__slots__ = ('parts', 'decrypted', 'prop', '_pos', '_abbr')
289289
# the _pos dict contains (begin, end) indices to parts[0] + decrypted
290290
# so that they can be replaced when transforming the font;
291291
# but since sometimes a definition appears in both parts[0] and decrypted,
292292
# _pos[name] is an array of such pairs
293+
#
294+
# _abbr maps three standard abbreviations to their particular names in
295+
# this font (e.g. 'RD' is named '-|' in some fonts)
293296

294297
def __init__(self, input):
295298
"""
@@ -309,6 +312,7 @@ def __init__(self, input):
309312
self.parts = self._split(data)
310313

311314
self.decrypted = self._decrypt(self.parts[1], 'eexec')
315+
self._abbr = {'RD': 'RD', 'ND': 'ND', 'NP': 'NP'}
312316
self._parse()
313317

314318
def _read(self, file):
@@ -496,10 +500,18 @@ def _parse(self):
496500
break
497501

498502
# sometimes noaccess def and readonly def are abbreviated
499-
if kw.is_name(b'def', b'ND', b'RD', b'|-'):
503+
if kw.is_keyword('def', self._abbr['ND'], self._abbr['NP']):
500504
prop[key] = value
501505
pos.setdefault(key, []).append((keypos, kw.endpos()))
502506

507+
# detect the standard abbreviations
508+
if value == '{noaccess def}':
509+
self._abbr['ND'] = key
510+
elif value == '{noaccess put}':
511+
self._abbr['NP'] = key
512+
elif value == '{string currentfile exch readstring pop}':
513+
self._abbr['RD'] = key
514+
503515
# Fill in the various *Name properties
504516
if 'FontName' not in prop:
505517
prop['FontName'] = (prop.get('FullName') or
@@ -548,9 +560,14 @@ def _parse_subrs(self, tokens, _data):
548560
"Second token following dup in Subrs definition must "
549561
f"be a number, was {nbytes_token}"
550562
)
551-
token = next(tokens) # usually RD or |- but the font can define this to be anything
552-
binary_token = tokens.send(1+nbytes_token.numeric_value())
553-
array[index_token.numeric_value()] = binary_token.value[1:]
563+
token = next(tokens)
564+
if not token.is_keyword(self._abbr['RD']):
565+
raise RuntimeError(
566+
f"Token preceding subr must be {self._abbr['RD']}, "
567+
f"was {token}"
568+
)
569+
binary_token = tokens.send(1+nbytes_token.value())
570+
array[index_token.value()] = binary_token.value()
554571

555572
return array, next(tokens).endpos()
556573

0 commit comments

Comments
 (0)