1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
|
% Copyright (C) 2001-2021 Artifex Software, Inc.
% All Rights Reserved.
%
% This software is provided AS-IS with no warranty, either express or
% implied.
%
% This software is distributed under license and may not be copied,
% modified or distributed except as expressly authorized under the terms
% of the license contained in the file LICENSE in this distribution.
%
% Refer to licensing information at http://www.artifex.com or contact
% Artifex Software, Inc., 1305 Grant Avenue - Suite 200, Novato,
% CA 94945, U.S.A., +1(415)492-9861, for further information.
%
% Print Linearized PDF hint streams
% Utilities
/read1 { % <file> read1 <value>
read not {
(**** Unexpected EOF) = flush quit
} if
} bind def
/read2 { % <file> read2 <value>
dup read1 8 bitshift exch read1 add
} bind def
/read4 { % <file> read4 <value>
dup read2 16 bitshift exch read2 add
} bind def
% Free variables: Bits, Bitsleft
/readninit { % - <readninit> -
/Bits 0 def
/Bitsleft 0 def
} bind def
/pdftoken { % <file> pdftoken <token>
dup token pop
dup type /nametype eq 1 index xcheck and {
dup dup (<<) cvn eq exch ([) eq or {
exec exch {
dup pdftoken dup dup (>>) cvn eq exch (]) eq or {
exch pop exec exit
} if exch
} loop
} {
exch pop
} ifelse
} {
exch pop
} ifelse
} bind def
/makemask { % <nbits> makemask <mask>
1 exch bitshift 1 sub
} bind def
/readn { % <file> <nbits> readn <value>
dup Bitsleft le {
exch pop
/Bitsleft Bitsleft 2 index sub def
makemask Bits Bitsleft neg bitshift and
} {
Bitsleft makemask Bits and
exch Bitsleft sub exch 1 index bitshift 3 1 roll
/Bits 2 index read1 def /Bitsleft 8 def
readn add
} ifelse
} bind def
/sread { % <string> sread <file>
0 () /SubFileDecode filter
} bind def
/ptag { % <pre-tag> <proc> <post-tag> ptag -
3 -1 roll print (: ) print
exch exec
( % ) print =
} bind def
% Print the linearization parameters dictionary.
/plpkeys <<
/E (end of p. 1 objects)
/L (total file length)
/H (PHS start + length)
/N (# of pages)
/O (p. 1 object #)
/T (offset of first main xref entry)
>> def
/plpdict { % <dict> plpdict -
(<<) = plpkeys {
2 index 2 index .knownget {
% Stack: dict key label value
( ) print 3 -1 roll ===only ( ) print ===only
( % ) print =
} {
pop pop
} ifelse
} forall {
plpkeys 2 index known {
pop pop
} {
( ) print exch ===only ( ) print ===
} ifelse
} forall (>>) =
} bind def
% Print the Page Offset Hint Table.
/ppoht { % <npages> <file> ppoht -
20 dict begin
/f exch def
/npages exch def
readninit
(1) { f read4 =only } (least # objs/page) ptag
(2) { f read4 =only } (offset of p. 1 object (+PHS length if beyond PHS)) ptag
(3) { f read2 dup =only /nb3 exch def } (# bits for # objs/page delta) ptag
(4) { f read4 =only } (least # bytes/page) ptag
(5) { f read2 dup =only /nb5 exch def } (# bits for # bytes/page delta) ptag
(6) { f read4 =only } (least content stream offset-in-page) ptag
(7) { f read2 dup =only /nb7 exch def } (# bits for content stream offset delta) ptag
(8) { f read4 =only } (least content stream length) ptag
(9) { f read2 dup =only /nb9 exch def } (# bits for content stream length delta) ptag
(10) { f read2 dup =only /nb10 exch def } (# bits for # of shared obj refs) ptag
(11) { f read2 dup =only /nb11 exch def } (# bits for shared obj indices) ptag
(12) { f read2 dup =only /nb12 exch def } (# bits for shared obj ref pos numerators) ptag
(13) { f read2 =only } (shared obj ref pos denominator) ptag
(*1) { [ npages { f nb3 readn } repeat ] ==only } (# objs/page deltas (see 1,3)) ptag
(*2) { [ npages { f nb5 readn } repeat ] ==only } (# bytes/page deltas (see 4,5)) ptag
(*3) { [ npages { f nb10 readn } repeat ] dup ==only /nso exch def } (# of shared obj refs (see 10)) ptag
(*4) { [ nso { [ exch { f nb11 readn } repeat ] } forall ] ==only } (shared obj indices (see 11)) ptag
(*5) { [ nso { [ exch { f nb12 readn } repeat ] } forall ] ==only } (shared obj ref pos numerators (see 12)) ptag
(*6) { [ npages { f nb7 readn } repeat ] ==only } (content stream offset-in-page deltas (see 6,7)) ptag
(*7) { [ npages { f nb9 readn } repeat ] ==only } (content stream length deltas (see 8,9)) ptag
end % temp dict
} bind def
% Print the Shared Objects Hint Table.
/psoht { % <file> psoht -
20 dict begin
/f exch def
readninit
(1) { f read4 =only } (first shared obj #) ptag
(2) { f read4 =only } (first shared obj offset (+PHS length if beyond PHS)) ptag
(3) { f read4 dup =only /n3 exch def } (# of p. 1 shared objs) ptag
(4) { f read4 dup =only /n4 exch def } (total # of shared objs) ptag
(5) { f read2 dup =only /nb5 exch def } (# bits for # of shared objs/group) ptag
(6) { f read4 =only } (least shared obj group length) ptag
(7) { f read2 dup =only /nb7 exch def } (# bits for shared obj group length delta) ptag
/nse n4 def
(*1) { [ nse { f nb7 readn } repeat ] ==only } (shared obj group length deltas (see 6,7)) ptag
(*2) { [ nse { f 1 readn } repeat ] dup ==only /md5s exch def } (MD5 present?) ptag
(*3:) = md5s {
0 ne {
( ) print f 16 string readstring pop
(%stdout) (w) file dup 3 -1 roll writehexstring closefile () =
} if
} forall
(*4) { [ nse { f nb5 readn } repeat ] ==only } (# objs/group (see 5)) ptag
end % temp dict
} bind def
% Print the Primary Hint Stream of a PDF file.
/pphs { % <file> pphs -
/pdf exch def
% Read the linearization parameter dictionary.
{ pdf pdftoken /obj eq { exit } if } loop
pdf pdftoken /lpdict exch def
/lpdict type /dicttype eq { lpdict /Linearized known } { false } ifelse {
(Not a linearized PDF file.) = stop
} if
lpdict plpdict flush
% Read the primary hint stream.
null {
pdf pdftoken dup /stream eq { pop exit } if
exch pop
} loop
/phsdict exch def
% Remove Length if indirect reference.
phsdict 0 known {
phsdict 0 undef phsdict /Length undef
} if
(PHS: ) print phsdict === flush
pdf 0 (endstream) /SubFileDecode filter
dup 64000 string readstring pop exch closefile
sread /phsdata exch def
% Decode the hint stream data if necessary.
phsdict /Filter .knownget {
phsdata exch filter
dup 5000 string readstring pop exch closefile
sread /phsdata exch def
} if
% Adobe says we can assume /P = 0.
(Page Offset Hint Table:) =
lpdict /N get
phsdata phsdict /S get string readstring pop sread
ppoht
(Shared Objects Hint Table:) =
phsdata psoht
} bind def
% Check for command line arguments.
[ .shellarguments
{ ] dup length 1 eq
{ 0 get (r) file dup pphs closefile }
{ (Usage: pphs filename.pdf\n) print flush }
ifelse
}
{ pop }
ifelse
|