1
1
import matplotlib .type1font as t1f
2
2
import os .path
3
3
import difflib
4
+ import pytest
4
5
5
6
6
7
def test_Type1Font ():
@@ -13,25 +14,49 @@ def test_Type1Font():
13
14
assert font .parts [0 ] == rawdata [0x0006 :0x10c5 ]
14
15
assert font .parts [1 ] == rawdata [0x10cb :0x897f ]
15
16
assert font .parts [2 ] == rawdata [0x8985 :0x8ba6 ]
16
- assert font .parts [1 :] == slanted .parts [1 :]
17
- assert font .parts [1 :] == condensed .parts [1 :]
18
17
assert font .decrypted .startswith (b'dup\n /Private 18 dict dup begin' )
19
18
assert font .decrypted .endswith (b'mark currentfile closefile\n ' )
19
+ assert slanted .decrypted .startswith (b'dup\n /Private 18 dict dup begin' )
20
+ assert slanted .decrypted .endswith (b'mark currentfile closefile\n ' )
21
+ assert b'UniqueID 5000793' in font .parts [0 ]
22
+ assert b'UniqueID 5000793' in font .decrypted
23
+ assert font ._pos ['UniqueID' ] == [(797 , 818 ), (4483 , 4504 )]
24
+
25
+ len0 = len (font .parts [0 ])
26
+ for key in font ._pos .keys ():
27
+ for pos0 , pos1 in font ._pos [key ]:
28
+ if pos0 < len0 :
29
+ data = font .parts [0 ][pos0 :pos1 ]
30
+ else :
31
+ data = font .decrypted [pos0 - len0 :pos1 - len0 ]
32
+ assert data .startswith (f'/{ key } ' .encode ('ascii' ))
33
+ assert {'FontType' , 'FontMatrix' , 'PaintType' , 'ItalicAngle' , 'RD'
34
+ } < set (font ._pos .keys ())
35
+
36
+ assert b'UniqueID 5000793' not in slanted .parts [0 ]
37
+ assert b'UniqueID 5000793' not in slanted .decrypted
38
+ assert 'UniqueID' not in slanted ._pos
39
+ assert font .prop ['Weight' ] == 'Medium'
40
+ assert not font .prop ['isFixedPitch' ]
41
+ assert font .prop ['ItalicAngle' ] == 0
42
+ assert slanted .prop ['ItalicAngle' ] == - 45
43
+ assert font .prop ['Encoding' ][5 ] == 'Pi'
44
+ assert isinstance (font .prop ['CharStrings' ]['Pi' ], bytes )
45
+ assert font ._abbr ['ND' ] == 'ND'
20
46
21
47
differ = difflib .Differ ()
22
48
diff = list (differ .compare (
23
49
font .parts [0 ].decode ('latin-1' ).splitlines (),
24
50
slanted .parts [0 ].decode ('latin-1' ).splitlines ()))
25
51
for line in (
26
52
# Removes UniqueID
27
- '- FontDirectory/CMR10 known{/CMR10 findfont dup/UniqueID known{dup' ,
28
- '+ FontDirectory/CMR10 known{/CMR10 findfont dup' ,
53
+ '- /UniqueID 5000793 def' ,
29
54
# Changes the font name
30
55
'- /FontName /CMR10 def' ,
31
- '+ /FontName /CMR10_Slant_1000 def' ,
56
+ '+ /FontName/CMR10_Slant_1000 def' ,
32
57
# Alters FontMatrix
33
58
'- /FontMatrix [0.001 0 0 0.001 0 0 ]readonly def' ,
34
- '+ /FontMatrix [0.001 0 0.001 0.001 0 0]readonly def' ,
59
+ '+ /FontMatrix [0.001 0 0.001 0.001 0 0] readonly def' ,
35
60
# Alters ItalicAngle
36
61
'- /ItalicAngle 0 def' ,
37
62
'+ /ItalicAngle -45.0 def' ):
@@ -42,17 +67,73 @@ def test_Type1Font():
42
67
condensed .parts [0 ].decode ('latin-1' ).splitlines ()))
43
68
for line in (
44
69
# Removes UniqueID
45
- '- FontDirectory/CMR10 known{/CMR10 findfont dup/UniqueID known{dup' ,
46
- '+ FontDirectory/CMR10 known{/CMR10 findfont dup' ,
70
+ '- /UniqueID 5000793 def' ,
47
71
# Changes the font name
48
72
'- /FontName /CMR10 def' ,
49
- '+ /FontName /CMR10_Extend_500 def' ,
73
+ '+ /FontName/CMR10_Extend_500 def' ,
50
74
# Alters FontMatrix
51
75
'- /FontMatrix [0.001 0 0 0.001 0 0 ]readonly def' ,
52
- '+ /FontMatrix [0.0005 0 0 0.001 0 0]readonly def' ):
76
+ '+ /FontMatrix [0.0005 0 0 0.001 0 0] readonly def' ):
53
77
assert line in diff , 'diff to condensed font must contain %s' % line
54
78
55
79
80
+ def test_Type1Font_2 ():
81
+ filename = os .path .join (os .path .dirname (__file__ ),
82
+ 'Courier10PitchBT-Bold.pfb' )
83
+ font = t1f .Type1Font (filename )
84
+ assert font .prop ['Weight' ] == 'Bold'
85
+ assert font .prop ['isFixedPitch' ]
86
+ assert font .prop ['Encoding' ][65 ] == 'A' # the font uses StandardEncoding
87
+ (pos0 , pos1 ), = font ._pos ['Encoding' ]
88
+ assert font .parts [0 ][pos0 :pos1 ] == b'/Encoding StandardEncoding'
89
+ assert font ._abbr ['ND' ] == '|-'
90
+
91
+
92
+ def test_tokenize ():
93
+ data = (b'1234/abc false -9.81 Foo <<[0 1 2]<0 1ef a\t >>>\n '
94
+ b'(string with(nested\t \\ ) par)ens\\ \\ )' )
95
+ # 1 2 x 2 xx1
96
+ # 1 and 2 are matching parens, x means escaped character
97
+ n , w , num , kw , d = 'name' , 'whitespace' , 'number' , 'keyword' , 'delimiter'
98
+ b , s = 'boolean' , 'string'
99
+ correct = [
100
+ (num , 1234 ), (n , 'abc' ), (w , ' ' ), (b , False ), (w , ' ' ), (num , - 9.81 ),
101
+ (w , ' ' ), (kw , 'Foo' ), (w , ' ' ), (d , '<<' ), (d , '[' ), (num , 0 ),
102
+ (w , ' ' ), (num , 1 ), (w , ' ' ), (num , 2 ), (d , ']' ), (s , b'\x01 \xef \xa0 ' ),
103
+ (d , '>>' ), (w , '\n ' ), (s , 'string with(nested\t ) par)ens\\ ' )
104
+ ]
105
+ correct_no_ws = [x for x in correct if x [0 ] != w ]
106
+
107
+ def convert (tokens ):
108
+ return [(t .kind , t .value ()) for t in tokens ]
109
+
110
+ assert convert (t1f ._tokenize (data , False )) == correct
111
+ assert convert (t1f ._tokenize (data , True )) == correct_no_ws
112
+
113
+ def bin_after (n ):
114
+ tokens = t1f ._tokenize (data , True )
115
+ result = []
116
+ for _ in range (n ):
117
+ result .append (next (tokens ))
118
+ result .append (tokens .send (10 ))
119
+ return convert (result )
120
+
121
+ for n in range (1 , len (correct_no_ws )):
122
+ result = bin_after (n )
123
+ assert result [:- 1 ] == correct_no_ws [:n ]
124
+ assert result [- 1 ][0 ] == 'binary'
125
+ assert isinstance (result [- 1 ][1 ], bytes )
126
+
127
+
128
+ def test_tokenize_errors ():
129
+ with pytest .raises (ValueError ):
130
+ list (t1f ._tokenize (b'1234 (this (string) is unterminated\\ )' , True ))
131
+ with pytest .raises (ValueError ):
132
+ list (t1f ._tokenize (b'/Foo<01234' , True ))
133
+ with pytest .raises (ValueError ):
134
+ list (t1f ._tokenize (b'/Foo<01234abcg>/Bar' , True ))
135
+
136
+
56
137
def test_overprecision ():
57
138
# We used to output too many digits in FontMatrix entries and
58
139
# ItalicAngle, which could make Type-1 parsers unhappy.
0 commit comments