% Copyright (C) 2000, 2001 Aladdin Enterprises. 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. % % For more information about licensing, please refer to % http://www.ghostscript.com/licensing/. For information on % commercial licensing, go to http://www.artifex.com/licensing/ or % contact Artifex Software, Inc., 101 Lucas Valley Road #110, % San Rafael, CA 94903, U.S.A., +1(415)492-9861. % $Id: dumphint.ps,v 1.2 2004/04/08 16:18:25 giles Exp $ % Linearized PDF hint formatting utility. % % Linearized PDF hints generated by Acrobat suite seem to deviate from % the published specification. % % /P (page offset hint table) key in hint stream is not generated by % Adobe products. The key is no longer required in PDF 1.5. % % Per-page items 4 and 5 of the page offset hint table start from 1st % page rather than 2nd page as the spec claims. % % All array entries start from the new byte boundary. % /table_width 79 def /col1_width 66 def % Skip bits to the next byte boundary /bytealign { % bytealign - begin /N 0 def /B 0 def end } bind def % Set bit stream position and align it to byte boundary /set_align { % <<>> pos set_align - exch begin S exch setfileposition /N 0 def /B 0 def end } bind def % Read requested number of bits from the bit stream. /bitread { % bitwrite exch begin 0 % bit val { 1 index N .min % bit val m dup 3 1 roll % bit m val m bitshift % bit m val<>(N-m) 3 -1 roll % m val' bit 2 index sub % m val' bit' 3 -1 roll % val' bit' m N exch sub dup % val' bit' N' N' 1 exch bitshift % val' bit' N' 1<)= } { hint_stream /S get 128 string readstring pop dup length 128 eq { == } { pop (Error reading nd5 string.) == } ifelse } ifelse } forall } { () = (none) = } ifelse (4. The number of objects in the group.) array_header hint_stream bytealign /shint_group_cnt [ shint_all_shared { hint_stream shint_group_bits bitread } repeat ] readonly def shint_group_cnt dump_array } bind def % Analyze the thumbnail hint table. /dump_thumbnail_table { hint_stream dup 32 bitread dup /thint_1st_obj_id exch def (1. Object number of the first thumbnail image.) two_column dup 32 bitread dup /thint_1st_obj_pos exch def (2. Location of the first thumbnail image.) two_column dup 32 bitread dup /thint_page_cnt exch def (3. Number of pages that have thumbnail images.) two_column dup 16 bitread dup /thint_no_thumbnail_bits exch def (4. Bits for the max number of consecutive pages without a thumbnail image.) two_column dup 32 bitread dup /thint_min_sz exch def (5. The least length of a thumbnail image in bytes.) two_column dup 15 bitread dup /thint_obj_sz_bits exch def (6. Bits for the difference between max and min length of a thumbnail image.) two_column dup 32 bitread dup /thint_min_obj_cnt exch def (7. The least number of objects in a thumbnail image.) two_column dup 16 bitread dup /thint_obj_cnt_bits exch def (8. Bits for the difference between max and min number of objects in a thumbnail image.) two_column dup 32 bitread dup /thint_1st_shared_obj exch def (9. First object in the thumbnail shared objects section.) two_column dup 32 bitread dup /thint_1st_shared_pos exch def (10. Location of the first object in the thumbnail shared objects section.) two_column dup 32 bitread dup /thint_shared_cnt exch def (11. Number of thumbnail shared objects.) two_column dup 32 bitread dup /thint_shared_section_sz exch def (12. Length of the thumbnail shared objects section in bytes.) two_column pop LinearizationParams /N get (1. The number of preceding pages lacking a thumbnail image.) array_header hint_stream bytealign /thint_no_thumbnail_pages [ 2 index { hint_stream thint_no_thumbnail_bits bitread } repeat ] readonly def thint_no_thumbnail_pages dump_array (2. Number of objects in this page's thumbnail image.) array_header hint_stream bytealign /thint_page_obj_cnt [ 2 index { hint_stream thint_obj_cnt_bits bitread thint_min_obj_cnt add } repeat ] readonly def thint_page_obj_cnt dump_array (3. Length of this page's thumbnail image in bytes.) array_header hint_stream bytealign /thint_page_obj_sz [ 2 index { hint_stream thint_obj_sz_bits bitread thint_min_sz add } repeat ] readonly def thint_page_obj_sz dump_array pop } bind def % Analyze the generic hint table. % The hint field names are re-used. /dump_generic_table { hint_stream dup 32 bitread dup /ghint_1st_obj exch def (1. Object number of the first object in the group.) two_column dup 32 bitread dup /ghint_1st_obj_pos exch def (2. Location of the first object in the group.) two_column dup 32 bitread dup /ghint_obj_cnt exch def (3. Number of objects in the group.) two_column dup 32 bitread dup /ghint_group_sz exch def (4. Length of the object group in bytes.) two_column pop } bind def % Analyze the interactive hint table. % The hint field names are re-used. /dump_interactive_table { hint_stream dup 32 bitread dup /ihint_1st_obj exch def (1. Object number of the first object in the group.) two_column dup 32 bitread dup /ihint_1st_obj_pos exch def (2. Location of the first object in the group.) two_column dup 32 bitread dup /ihint_obj_cnt exch def (3. Number of objects in the group.) two_column dup 32 bitread dup /ihint_group_sz exch def (4. Length of the object group in bytes.) two_column dup 32 bitread dup /ihint_shared_cnt exch def (5. Number of shared object references.) two_column dup 16 bitread dup /ihint_shared_obj_bits exch def (6. Bits for the max shared object id used by the interactive form or the logical structure hierarchy.) 1 index hint_sobits ne { (\n*** This fiels is not equal to max shared object ID bits ***) concatstrings } if pop (7. Shared object identifier.) array_header hint_stream bytealign /ihint_shared_obj_id [ ihint_shared_cnt { hint_stream hint_sobits bitread } repeat ] readonly def ihint_shared_obj_id dump_array } bind def % Enumerate all documented hint tables. /dump_all_tables { % <> dump_all_tables - (Page offset hint table) table_header hint_stream 0 set_align dump_page_offset_table (S, Shared object hint table) table_header dup /S .knownget { hint_stream exch set_align dump_shared_object_table } { (Required table is not found.) error_msg } ifelse dup /T .knownget { (T, Thumbnail hint table) table_header hint_stream exch set_align dump_thumbnail_table } if dup /O .knownget { (O, Outline hint table) table_header hint_stream exch set_align dump_generic_table } if dup /A .knownget { (A, Thread information hint table) table_header hint_stream exch set_align dump_generic_table } if dup /E .knownget { (E, Named destination hint table) table_header hint_stream exch set_align dump_generic_table } if dup /V .knownget { (V, Interactive form hint table) table_header hint_stream exch set_align dump_interactive_table } if dup /I .knownget { (I, Information dictionary hint table) table_header hint_stream exch set_align dump_generic_table } if dup /C .knownget { (C, Logical structure hint table) table_header hint_stream exch set_align dump_interactive_table } if dup /L .knownget { (L, Page label hint table) table_header hint_stream exch set_align dump_generic_table } if pop } bind def % Load PDF file and extract the hint stream. /pdf_dump_hints { % pdf_dump_hints - dup (r) file % fname false exch % fname F file { dup 7 string readstring pop % fname F file () (%PDF-1.) ne { pop exit } if % fname F file dup 0 setfileposition dup token not { pop exit } if % fname F file obj dup type /integertype ne { pop exit } if % fname F file obj 1 index token not { pop pop exit } if % fname F file obj gen dup type /integertype ne {pop pop exit}if % fname F file obj gen 4 2 roll % fname obj gen F file dup 0 setfileposition exch true or % fname obj gen file T exit } loop { pdfdict begin pdfopenfile dup begin 40 dict begin /IDict exch def .setsafe % Read all objects into memory. Trailer touch resolveR % fname <<>> dup /Linearized known { dup /L get % fname <<>> Len 3 -1 roll status not { 0 0 0 0 } if % <<>> Len pop pop exch pop % <<>> Len len eq { /LinearizationParams exch def LinearizationParams /H get dup length 2 eq { 0 get PDFoffset add PDFfile exch setfileposition PDFfile token pop PDFfile token pop resolveR dup true resolvestream /ReusableStreamDecode filter bitstream dup bytealign /hint_stream exch def dump_all_tables } { pop (Overflow hint stream is not supported.) = } ifelse } { pop (Wrong file length in linearization dictionary.) = } ifelse } { pop (The file is not linearized.) = } ifelse end % temporary dict end % IDict end } { pop (Input file is not a valid PDF file.) = } ifelse } bind def % Initial setup /dump_hints { counttomark 1 eq { exch pop save exch 3000000 setvmthreshold pdfoptdict begin pdf_dump_hints end restore true } { cleartomark false } ifelse } bind def /shellarguments {false} def (pdfopt.ps) runlibfile currentdict /shellarguments undef % Check for command line arguments. mark shellarguments { dump_hints not { (Usage: gs -dNODISPLAY -- dumphint.ps input.pdf) = flush } if } { pop } ifelse % EOF