1 % Copyright (C) 2000, 2001 Aladdin Enterprises. All rights reserved.
3 % This software is provided AS-IS with no warranty, either express or
6 % This software is distributed under license and may not be copied,
7 % modified or distributed except as expressly authorized under the terms
8 % of the license contained in the file LICENSE in this distribution.
10 % For more information about licensing, please refer to
11 % http://www.ghostscript.com/licensing/. For information on
12 % commercial licensing, go to http://www.artifex.com/licensing/ or
13 % contact Artifex Software, Inc., 101 Lucas Valley Road #110,
14 % San Rafael, CA 94903, U.S.A., +1(415)492-9861.
16 % $Id: dumphint.ps,v 1.2 2004/04/08 16:18:25 giles Exp $
17 % Linearized PDF hint formatting utility.
20 % Linearized PDF hints generated by Acrobat suite seem to deviate from
21 % the published specification.
23 % /P (page offset hint table) key in hint stream is not generated by
24 % Adobe products. The key is no longer required in PDF 1.5.
26 % Per-page items 4 and 5 of the page offset hint table start from 1st
27 % page rather than 2nd page as the spec claims.
29 % All array entries start from the new byte boundary.
35 % Skip bits to the next byte boundary
36 /bytealign { % <stream> bytealign -
37 begin /N 0 def /B 0 def end
40 % Set bit stream position and align it to byte boundary
41 /set_align { % <<>> pos set_align -
43 S exch setfileposition
48 % Read requested number of bits from the bit stream.
49 /bitread { % <bstream> <width> bitwrite <value>
53 1 index N .min % bit val m
54 dup 3 1 roll % bit m val m
55 bitshift % bit m val<<m
56 B 2 index N sub % bit m val<<m B m-N
57 bitshift add % bit m val<<m+B>>(N-m)
58 3 -1 roll % m val' bit
59 2 index sub % m val' bit'
60 3 -1 roll % val' bit' m
61 N exch sub dup % val' bit' N' N'
62 1 exch bitshift % val' bit' N' 1<<N'
63 1 sub B and % val' bit' N' B&(1<<N')
64 /B exch def % val' bit' N'
65 /N exch def % val' bit'
70 /B B 8 bitshift S read not { 0 ( *** EOF! *** ) = } if add def
76 % Print a string several times
77 /multiprint { % cnt (s) multiprint -
78 exch { dup print } repeat pop
81 % Split the line into 2 substrings.
82 /split_line { % (s) split_line () ()
83 dup length col1_width gt {
87 3 index % (s) w i i ()
95 1 index exch % (s) (s) w'
102 4 1 roll % (pre) (s) (post) (match)
104 1 index length % (pre) (s) len
105 1 add % (pre) (s) len+1
108 1 index length % (pre) (s) len
110 1 index length % (pre) (s) len Len
111 1 index sub % (pre) (s) len Len-len
112 getinterval % (pre) (post)
115 % Print a 2 column table. The string is printed in 1st column
116 % left-aligned. The number is printed in 2nd column right-aligned.
117 /two_column { % n () two_column -
118 split_line % n (a) ()
120 dup length % () n (a) len
121 exch print % () n len
122 exch =string cvs % () len (n)
123 dup length % () len (n) len2
124 3 -1 roll add % () (n) len+len2
125 //table_width % () (n) len+len2 78
126 exch sub % () (n) 78-len+len2
127 ( ) multiprint % () (n)
129 { dup length 0 eq { exit } if
136 % Print the header of a hint table
137 /table_header { % () table_header -
139 table_width exch sub 2 idiv % () len sp
140 dup ( ) multiprint % () len sp
147 % Pretty-print an array on top level
148 /dump_array { % [ ] dump_array -
152 dup length dup % pos () len len
153 3 index add 1 add % pos () len len+pos+1
156 ( ) print % pos () len
158 3 1 roll print pop % pos'
160 ( ) print % pos () len
169 % Pretty-print an array on 2nd level
170 /dump_array2 { % [ ] dump_array2 -
174 dup length dup % pos () len len
175 3 index add 1 add % pos () len len+pos+1
176 table_width 2 sub gt {
178 ( ) print % pos () len
180 3 1 roll print pop % pos'
182 ( ) print % pos () len
191 % Print an array header
196 % Analyze the page offset hint table.
197 /dump_page_offset_table { % - dump_page_offset_table -
201 dup /hint_minnop exch def
202 (1. The least number of objects in a page.) two_column
205 dup /hint_1st_obj exch def
206 (2. Location of the first page's page object.) two_column
209 dup /hint_maxnopbits exch def
210 (3. Bits for difference between max and min number of page objects.) two_column
213 dup /hint_minpl exch def
214 (4. Least length of a page.) two_column
217 dup /hint_maxplbits exch def
218 (5. Bits for difference between max and min length of a page.) two_column
221 dup /hint_minsco exch def
222 (6. Least start of Contents offset. )
223 1 index 0 ne { (\n*** Acrobat expects 0 ***) concatstrings } if
227 dup /hint_maxscobits exch def
228 (7. Bits for difference between max and min offset to the start of the content stream.) two_column
231 dup /hint_mincl exch def
232 (8. Least contents length.) two_column
235 dup /hint_maxclbits exch def
236 (9. Bits needed to represent the greatest Contents length.) two_column
239 dup /hint_maxsorbits exch def
240 (10. Bits needed to represent the greatest number of Shared Object references.) two_column
243 dup /hint_sobits exch def
244 (11. Bits needed to identify a Shared Object.) two_column
247 dup /hint_numfbits exch def
248 (12. Bits needed to represent numerator of fraction.) two_column
251 dup /hint_denf exch def
252 (13. Denominator of fraction.) two_column
256 LinearizationParams /N get
258 % 1. Number of objects in the page.
259 hint_stream bytealign
262 hint_stream hint_maxnopbits bitread
267 (1. Number of objects on the page) array_header
268 hint_page_obj dump_array
270 % 2, Page length in bytes.
271 hint_stream bytealign
274 hint_stream hint_maxplbits bitread
279 (2. Page length in bytes.) array_header
280 hint_page_len dump_array
282 % 3, Number of shared objects referenced from the page
283 hint_stream bytealign
286 hint_stream hint_maxsorbits bitread
290 (3. Number of shared objects referenced from the page.) array_header
291 hint_page_sobj dump_array
293 % 4. Index into the shared objects hint table
294 hint_stream bytealign
297 hint_page_sobj exch get [
299 hint_stream hint_sobits bitread
305 (4. Index into the shared objects hint table.) array_header
307 hint_page_sobj_id { dump_array2 } forall
310 % 5. Fractional position for each shared object reference
311 hint_stream bytealign
312 /hint_page_sobj_pos [
314 hint_page_sobj exch get [
316 hint_stream hint_numfbits bitread
323 (5. Fractional position for each shared object reference. ) array_header
325 hint_page_sobj_pos { dump_array2 } forall
328 % 6. Offset of the page's content stream from the beginning of the page.
329 hint_stream bytealign
330 /hint_page_content_offset [
332 hint_stream hint_maxscobits bitread
337 (6. Offset of the page's content stream from the beginning of the page.) array_header
338 hint_page_content_offset dump_array
340 % 7. Length of the page's content stream in bytes.
341 hint_stream bytealign
342 /hint_page_content_len [
344 hint_stream hint_maxclbits bitread
349 (7. Length of the page's content stream in bytes.) array_header
350 hint_page_content_len dump_array
355 % Analyze tha shared object hint table
356 /dump_shared_object_table {
360 dup /shint_1st_obj_id exch def
361 (1. Object number of the first object in the shared objects section) two_column
364 dup /shint_1st_obj_pos exch def
365 (2. Location of the first object in the shared objects section.) two_column
368 dup /shint_1st_shared exch def
369 (3. The number of shared object entries for the first page.) two_column
372 dup /shint_all_shared exch def
373 (4. Number of shared object entries for the shared objects section including 1st page.) two_column
376 dup /shint_group_bits exch def
377 (5. Number of bits needed to represent the greatest number of objects in a shared object group.) two_column
380 dup /shint_group_least_sz exch def
381 (6. Least length of a shared object group in bytes.) two_column
384 dup /shint_group_diff_bits exch def
385 (7. Bits for the difference between the greatest and least length of a shared object group size.) two_column
388 (1. length of the object group in bytes.) array_header
389 hint_stream bytealign
392 hint_stream shint_group_diff_bits bitread
393 shint_group_least_sz add
397 shint_group_sz dump_array
399 (2. MD5 signature flag) array_header
400 hint_stream bytealign
403 { hint_stream 1 bitread
407 shint_md5_flags dump_array
409 (3. MD5 signature string) array_header
410 false shint_md5_flags { 0 ne or } forall {
415 hint_stream /S get 128 string
419 } { pop (Error reading nd5 string.) ==
427 (4. The number of objects in the group.) array_header
428 hint_stream bytealign
431 hint_stream shint_group_bits bitread
435 shint_group_cnt dump_array
439 % Analyze the thumbnail hint table.
440 /dump_thumbnail_table {
444 dup /thint_1st_obj_id exch def
445 (1. Object number of the first thumbnail image.) two_column
448 dup /thint_1st_obj_pos exch def
449 (2. Location of the first thumbnail image.) two_column
452 dup /thint_page_cnt exch def
453 (3. Number of pages that have thumbnail images.) two_column
456 dup /thint_no_thumbnail_bits exch def
457 (4. Bits for the max number of consecutive pages without a thumbnail image.) two_column
460 dup /thint_min_sz exch def
461 (5. The least length of a thumbnail image in bytes.) two_column
464 dup /thint_obj_sz_bits exch def
465 (6. Bits for the difference between max and min length of a thumbnail image.) two_column
468 dup /thint_min_obj_cnt exch def
469 (7. The least number of objects in a thumbnail image.) two_column
472 dup /thint_obj_cnt_bits exch def
473 (8. Bits for the difference between max and min number of objects in a thumbnail image.) two_column
476 dup /thint_1st_shared_obj exch def
477 (9. First object in the thumbnail shared objects section.) two_column
480 dup /thint_1st_shared_pos exch def
481 (10. Location of the first object in the thumbnail shared objects section.) two_column
484 dup /thint_shared_cnt exch def
485 (11. Number of thumbnail shared objects.) two_column
488 dup /thint_shared_section_sz exch def
489 (12. Length of the thumbnail shared objects section in bytes.) two_column
492 LinearizationParams /N get
494 (1. The number of preceding pages lacking a thumbnail image.) array_header
495 hint_stream bytealign
496 /thint_no_thumbnail_pages [
498 hint_stream thint_no_thumbnail_bits bitread
502 thint_no_thumbnail_pages dump_array
504 (2. Number of objects in this page's thumbnail image.) array_header
505 hint_stream bytealign
506 /thint_page_obj_cnt [
508 hint_stream thint_obj_cnt_bits bitread
509 thint_min_obj_cnt add
513 thint_page_obj_cnt dump_array
515 (3. Length of this page's thumbnail image in bytes.) array_header
516 hint_stream bytealign
519 hint_stream thint_obj_sz_bits bitread
524 thint_page_obj_sz dump_array
528 % Analyze the generic hint table.
529 % The hint field names are re-used.
530 /dump_generic_table {
534 dup /ghint_1st_obj exch def
535 (1. Object number of the first object in the group.) two_column
538 dup /ghint_1st_obj_pos exch def
539 (2. Location of the first object in the group.) two_column
542 dup /ghint_obj_cnt exch def
543 (3. Number of objects in the group.) two_column
546 dup /ghint_group_sz exch def
547 (4. Length of the object group in bytes.) two_column
552 % Analyze the interactive hint table.
553 % The hint field names are re-used.
554 /dump_interactive_table {
558 dup /ihint_1st_obj exch def
559 (1. Object number of the first object in the group.) two_column
562 dup /ihint_1st_obj_pos exch def
563 (2. Location of the first object in the group.) two_column
566 dup /ihint_obj_cnt exch def
567 (3. Number of objects in the group.) two_column
570 dup /ihint_group_sz exch def
571 (4. Length of the object group in bytes.) two_column
574 dup /ihint_shared_cnt exch def
575 (5. Number of shared object references.) two_column
578 dup /ihint_shared_obj_bits exch def
579 (6. Bits for the max shared object id used by the interactive form or the logical structure hierarchy.)
580 1 index hint_sobits ne {
581 (\n*** This fiels is not equal to max shared object ID bits ***) concatstrings
586 (7. Shared object identifier.) array_header
587 hint_stream bytealign
588 /ihint_shared_obj_id [
590 hint_stream hint_sobits bitread
594 ihint_shared_obj_id dump_array
597 % Enumerate all documented hint tables.
598 /dump_all_tables { % <<stream>> dump_all_tables -
599 (Page offset hint table) table_header
600 hint_stream 0 set_align
601 dump_page_offset_table
603 (S, Shared object hint table) table_header
605 hint_stream exch set_align
606 dump_shared_object_table
608 (Required table is not found.) error_msg
612 (T, Thumbnail hint table) table_header
613 hint_stream exch set_align
618 (O, Outline hint table) table_header
619 hint_stream exch set_align
624 (A, Thread information hint table) table_header
625 hint_stream exch set_align
630 (E, Named destination hint table) table_header
631 hint_stream exch set_align
636 (V, Interactive form hint table) table_header
637 hint_stream exch set_align
638 dump_interactive_table
642 (I, Information dictionary hint table) table_header
643 hint_stream exch set_align
648 (C, Logical structure hint table) table_header
649 hint_stream exch set_align
650 dump_interactive_table
654 (L, Page label hint table) table_header
655 hint_stream exch set_align
663 % Load PDF file and extract the hint stream.
664 /pdf_dump_hints { % <infile> pdf_dump_hints -
666 false exch % fname F file
668 dup 7 string readstring pop % fname F file ()
669 (%PDF-1.) ne { pop exit } if % fname F file
670 dup 0 setfileposition
671 dup token not { pop exit } if % fname F file obj
672 dup type /integertype ne { pop exit } if % fname F file obj
673 1 index token not { pop pop exit } if % fname F file obj gen
674 dup type /integertype ne {pop pop exit}if % fname F file obj gen
675 4 2 roll % fname obj gen F file
676 dup 0 setfileposition
677 exch true or % fname obj gen file T
682 pdfopenfile dup begin
687 % Read all objects into memory.
689 resolveR % fname <<>>
690 dup /Linearized known {
691 dup /L get % fname <<>> Len
692 3 -1 roll status not { 0 0 0 0 } if % <<>> Len
693 pop pop exch pop % <<>> Len len
695 /LinearizationParams exch def
696 LinearizationParams /H get
698 0 get PDFoffset add PDFfile exch setfileposition
701 resolveR dup true resolvestream
702 /ReusableStreamDecode filter
703 bitstream dup bytealign
704 /hint_stream exch def
709 (Overflow hint stream is not supported.) =
713 (Wrong file length in linearization dictionary.) =
716 pop (The file is not linearized.) =
723 (Input file is not a valid PDF file.) =
732 3000000 setvmthreshold
743 /shellarguments {false} def
744 (pdfopt.ps) runlibfile
745 currentdict /shellarguments undef
747 % Check for command line arguments.
748 mark shellarguments {
750 (Usage: gs -dNODISPLAY -- dumphint.ps input.pdf) = flush