]> git.lizzy.rs Git - plan9front.git/blob - sys/lib/ghostscript/dumphint.ps
merge
[plan9front.git] / sys / lib / ghostscript / dumphint.ps
1 % Copyright (C) 2000, 2001 Aladdin Enterprises.  All rights reserved.
2
3 % This software is provided AS-IS with no warranty, either express or
4 % implied.
5
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.
9
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.
15
16 % $Id: dumphint.ps,v 1.2 2004/04/08 16:18:25 giles Exp $
17 % Linearized PDF hint formatting utility.
18
19 %
20 % Linearized PDF hints generated by Acrobat suite seem to deviate from
21 % the published specification.
22 %
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.
25 %
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.
28 %
29 % All array entries start from the new byte boundary.
30 %
31
32 /table_width 79 def 
33 /col1_width  66 def
34
35 % Skip bits to the next byte boundary
36 /bytealign {            % <stream> bytealign -
37   begin /N 0 def /B 0 def end
38 } bind def
39
40 % Set bit stream position and align it to byte boundary
41 /set_align {            % <<>> pos set_align -
42   exch begin
43   S exch setfileposition
44   /N 0 def /B 0 def
45   end
46 } bind def
47
48 % Read requested number of bits from the bit stream.
49 /bitread {              % <bstream> <width> bitwrite <value>
50   exch begin
51   0                     %  bit val
52   { 
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'
66     dup 0 le {
67       pop exit          %  val'
68     } if
69     /N N 8 add def
70     /B B 8 bitshift S read not { 0 ( *** EOF! *** ) = } if add def
71     exch
72   } loop                %  bit' val'
73   end
74 } bind def
75
76 % Print a string several times
77 /multiprint {           % cnt (s) multiprint -
78   exch { dup print } repeat pop
79 } bind def
80
81 % Split the line into 2 substrings.
82 /split_line {           % (s) split_line () ()
83   dup length col1_width gt {
84     col1_width 1 sub
85     dup -1 0 {
86       dup               % (s) w i i
87       3 index           % (s) w i i ()
88       exch get          % (s) w i c
89       32 eq {
90         exch pop exit
91       } if
92       pop
93     } for
94     1 add               % (s) w'
95     1 index exch        % (s) (s) w'
96     0 exch              % (s) (s) 0 w'
97     getinterval         % (s) (v)
98   } {
99     dup                 % (s) (s)
100   } ifelse                  
101   (\n) search {
102     4 1 roll            % (pre) (s) (post) (match)
103     pop pop             % (pre) (s)
104     1 index length      % (pre) (s) len
105     1 add               % (pre) (s) len+1
106   } {
107     exch                % (pre) (s)
108     1 index length      % (pre) (s) len
109   } ifelse
110   1 index length        % (pre) (s) len Len
111   1 index sub           % (pre) (s) len Len-len
112   getinterval           % (pre) (post)
113 } bind def
114
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) ()
119   3 1 roll              % () 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)
128   =                     % ()
129   { dup length 0 eq { exit } if
130     split_line exch =
131   } loop
132   pop
133   () =
134 } bind def
135
136 % Print the header of a hint table
137 /table_header {               % () table_header -
138   dup length dup
139   table_width exch sub 2 idiv % () len sp
140   dup ( ) multiprint          % () len sp
141   3 -1 roll =                 % len sp
142   ( ) multiprint              % len
143   (=) multiprint
144   ()= ()=
145 } bind def
146
147 % Pretty-print an array on top level
148 /dump_array {               % [ ] dump_array -
149   ([) = ( ) print
150   1 exch {
151     =string cvs         % pos ()
152     dup length dup      % pos () len len
153     3 index add 1 add   % pos () len len+pos+1
154     table_width gt {
155       () =
156       (  ) print        % pos () len
157       2 add             % pos () pos'
158       3 1 roll print pop % pos'
159     } {
160       ( ) print         % pos () len
161       exch print        % pos len
162       add 1 add         % pos'
163     } ifelse
164   } forall
165   pop
166   () = (]) =
167 } bind def
168
169 % Pretty-print an array on 2nd level
170 /dump_array2 {             % [ ] dump_array2 -
171   (  [) print
172   3 exch {
173     =string cvs            % pos ()
174     dup length dup         % pos () len len
175     3 index add 1 add      % pos () len len+pos+1
176     table_width 2 sub gt {
177       () =
178       (    ) print         % pos () len
179       4 add                % pos () pos'
180       3 1 roll print pop   % pos'
181     } {
182       ( ) print            % pos () len
183       exch print           % pos len
184       add 1 add            % pos'
185     } ifelse
186   } forall
187   pop
188   ( ]) =
189 } bind def
190
191 % Print an array header
192 /array_header {
193   () = =
194 } bind def
195
196 % Analyze the page offset hint table.
197 /dump_page_offset_table {  % - dump_page_offset_table -
198   hint_stream
199     
200   dup 32 bitread
201   dup /hint_minnop exch def
202   (1. The least number of objects in a page.) two_column
203
204   dup 32 bitread
205   dup /hint_1st_obj exch def
206   (2. Location of the first page's page object.) two_column
207
208   dup 16 bitread
209   dup /hint_maxnopbits exch def
210   (3. Bits for difference between max and min number of page objects.) two_column
211
212   dup 32 bitread
213   dup /hint_minpl exch def
214   (4. Least length of a page.) two_column
215
216   dup 16 bitread
217   dup /hint_maxplbits exch def
218   (5. Bits for difference between max and min length of a page.) two_column
219
220   dup 32 bitread
221   dup /hint_minsco exch def
222   (6. Least start of Contents offset. ) 
223   1 index 0 ne { (\n*** Acrobat expects 0 ***) concatstrings } if
224   two_column
225
226   dup 16 bitread
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
229
230   dup 32 bitread
231   dup /hint_mincl exch def
232   (8. Least contents length.) two_column
233
234   dup 16 bitread
235   dup /hint_maxclbits exch def
236   (9. Bits needed to represent the greatest Contents length.) two_column
237
238   dup 16 bitread
239   dup /hint_maxsorbits exch def
240   (10. Bits needed to represent the greatest number of Shared Object references.) two_column
241
242   dup 16 bitread
243   dup /hint_sobits exch def
244   (11. Bits needed to identify a Shared Object.) two_column
245
246   dup 16 bitread
247   dup /hint_numfbits exch def
248   (12. Bits needed to represent numerator of fraction.) two_column
249
250   dup 16 bitread
251   dup /hint_denf exch def
252   (13. Denominator of fraction.) two_column
253
254   pop 
255
256   LinearizationParams /N get
257
258   % 1. Number of objects in the page.
259   hint_stream bytealign
260   /hint_page_obj [
261     2 index {
262       hint_stream hint_maxnopbits bitread
263       hint_minnop add
264     } repeat
265   ] readonly def
266
267   (1. Number of objects on the page) array_header
268   hint_page_obj dump_array
269
270   % 2, Page length in bytes.
271   hint_stream bytealign
272   /hint_page_len [
273     2 index {
274       hint_stream hint_maxplbits bitread
275       hint_minpl add
276     } repeat
277   ] readonly def
278
279   (2. Page length in bytes.) array_header
280   hint_page_len dump_array
281
282   % 3, Number of shared objects referenced from the page
283   hint_stream bytealign
284   /hint_page_sobj [
285     2 index {
286       hint_stream hint_maxsorbits bitread
287     } repeat
288   ] readonly def
289
290   (3. Number of shared objects referenced from the page.) array_header
291   hint_page_sobj dump_array
292
293   % 4. Index into the shared objects hint table
294   hint_stream bytealign
295   /hint_page_sobj_id [
296     0 1 4 index 1 sub {
297       hint_page_sobj exch get [
298         exch {
299           hint_stream hint_sobits bitread
300         } repeat
301       ] readonly
302     } for
303   ] readonly def
304
305   (4. Index into the shared objects hint table.) array_header
306   ([) =
307   hint_page_sobj_id { dump_array2 } forall
308   (])=
309
310   % 5. Fractional position for each shared object reference
311   hint_stream bytealign
312   /hint_page_sobj_pos [
313     0 1 4 index 1 sub {
314       hint_page_sobj exch get [
315         exch {
316           hint_stream hint_numfbits bitread
317           hint_denf div
318         } repeat
319       ] readonly
320     } for
321   ] readonly def
322
323   (5. Fractional position for each shared object reference. ) array_header
324   ([)=
325   hint_page_sobj_pos { dump_array2 } forall
326   (])=
327
328   % 6. Offset of the page's content stream from the beginning of the page.
329   hint_stream bytealign
330   /hint_page_content_offset [
331     2 index {
332       hint_stream hint_maxscobits bitread
333       hint_minsco add
334     } repeat
335   ] readonly def
336
337   (6. Offset of the page's content stream from the beginning of the page.) array_header
338   hint_page_content_offset dump_array
339
340   % 7. Length of the page's content stream in bytes.
341   hint_stream bytealign
342   /hint_page_content_len [
343     2 index {
344       hint_stream hint_maxclbits bitread
345       hint_mincl add
346     } repeat
347   ] readonly def
348
349   (7. Length of the page's content stream in bytes.) array_header
350   hint_page_content_len dump_array
351
352   pop
353 } bind def
354
355 % Analyze tha shared object hint table
356 /dump_shared_object_table { 
357   hint_stream
358     
359   dup 32 bitread
360   dup /shint_1st_obj_id exch def
361   (1. Object number of the first object in the shared objects section) two_column
362
363   dup 32 bitread
364   dup /shint_1st_obj_pos exch def
365   (2. Location of the first object in the shared objects section.) two_column
366
367   dup 32 bitread
368   dup /shint_1st_shared exch def
369   (3. The number of shared object entries for the first page.) two_column
370
371   dup 32 bitread
372   dup /shint_all_shared exch def
373   (4. Number of shared object entries for the shared objects section including 1st page.) two_column
374
375   dup 16 bitread
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
378
379   dup 32 bitread
380   dup /shint_group_least_sz exch def
381   (6. Least length of a shared object group in bytes.) two_column
382
383   dup 16 bitread
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
386   pop
387
388   (1. length of the object group in bytes.) array_header
389   hint_stream bytealign
390   /shint_group_sz [
391     shint_all_shared {
392       hint_stream shint_group_diff_bits bitread
393       shint_group_least_sz add
394     } repeat
395   ] readonly def
396
397   shint_group_sz dump_array
398
399   (2. MD5 signature flag) array_header
400     hint_stream bytealign
401     /shint_md5_flags
402     [ shint_all_shared 
403       { hint_stream 1 bitread
404       } repeat
405     ] readonly def
406
407     shint_md5_flags dump_array
408
409     (3. MD5 signature string) array_header
410     false shint_md5_flags { 0 ne or } forall { 
411       shint_md5_flags {
412         0 eq {
413           (<>)=
414         } {
415           hint_stream /S get 128 string
416           readstring pop
417           dup length 128 eq {
418             ==
419           } { pop (Error reading nd5 string.) ==
420           } ifelse
421         } ifelse
422       } forall   
423     } {
424       () = (none) =
425     } ifelse
426
427     (4. The number of objects in the group.) array_header
428     hint_stream bytealign
429     /shint_group_cnt [
430       shint_all_shared {
431         hint_stream shint_group_bits bitread
432       } repeat
433     ] readonly def
434
435     shint_group_cnt dump_array
436
437   } bind def
438
439 % Analyze the thumbnail hint table.
440 /dump_thumbnail_table {
441   hint_stream
442
443   dup 32 bitread
444   dup /thint_1st_obj_id exch def
445   (1. Object number of the first thumbnail image.) two_column
446
447   dup 32 bitread
448   dup /thint_1st_obj_pos exch def
449   (2. Location of the first thumbnail image.) two_column
450
451   dup 32 bitread
452   dup /thint_page_cnt exch def
453   (3. Number of pages that have thumbnail images.) two_column
454
455   dup 16 bitread
456   dup /thint_no_thumbnail_bits exch def
457   (4. Bits for the max number of consecutive pages without a thumbnail image.) two_column
458
459   dup 32 bitread
460   dup /thint_min_sz exch def
461   (5. The least length of a thumbnail image in bytes.) two_column
462
463   dup 15 bitread
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
466
467   dup 32 bitread
468   dup /thint_min_obj_cnt exch def
469   (7. The least number of objects in a thumbnail image.) two_column
470
471   dup 16 bitread
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
474
475   dup 32 bitread
476   dup /thint_1st_shared_obj exch def
477   (9. First object in the thumbnail shared objects section.) two_column
478
479   dup 32 bitread
480   dup /thint_1st_shared_pos exch def
481   (10. Location of the first object in the thumbnail shared objects section.) two_column
482
483   dup 32 bitread
484   dup /thint_shared_cnt exch def
485   (11. Number of thumbnail shared objects.) two_column
486
487   dup 32 bitread
488   dup /thint_shared_section_sz exch def
489   (12. Length of the thumbnail shared objects section in bytes.) two_column
490
491   pop
492   LinearizationParams /N get
493
494   (1. The number of preceding pages lacking a thumbnail image.) array_header
495   hint_stream bytealign
496   /thint_no_thumbnail_pages [
497     2 index {
498       hint_stream thint_no_thumbnail_bits bitread
499     } repeat
500   ] readonly def
501
502   thint_no_thumbnail_pages dump_array
503
504   (2. Number of objects in this page's thumbnail image.) array_header
505   hint_stream bytealign
506   /thint_page_obj_cnt [
507     2 index {
508       hint_stream thint_obj_cnt_bits bitread
509       thint_min_obj_cnt add
510     } repeat
511   ] readonly def
512
513   thint_page_obj_cnt dump_array
514
515   (3. Length of this page's thumbnail image in bytes.) array_header
516   hint_stream bytealign
517   /thint_page_obj_sz [
518     2 index {
519       hint_stream thint_obj_sz_bits bitread
520       thint_min_sz add
521     } repeat
522   ] readonly def
523
524   thint_page_obj_sz dump_array
525   pop
526 } bind def
527
528 % Analyze the generic hint table.
529 % The hint field names are re-used. 
530 /dump_generic_table { 
531   hint_stream
532
533   dup 32 bitread
534   dup /ghint_1st_obj exch def
535   (1. Object number of the first object in the group.) two_column
536
537   dup 32 bitread
538   dup /ghint_1st_obj_pos exch def
539   (2. Location of the first object in the group.) two_column
540
541   dup 32 bitread
542   dup /ghint_obj_cnt exch def
543   (3. Number of objects in the group.) two_column
544
545   dup 32 bitread
546   dup /ghint_group_sz exch def
547   (4. Length of the object group in bytes.) two_column
548
549   pop
550 } bind def
551
552 % Analyze the interactive hint table.
553 % The hint field names are re-used.
554 /dump_interactive_table {
555   hint_stream
556
557   dup 32 bitread
558   dup /ihint_1st_obj exch def
559   (1. Object number of the first object in the group.) two_column
560
561   dup 32 bitread
562   dup /ihint_1st_obj_pos exch def
563   (2. Location of the first object in the group.) two_column
564
565   dup 32 bitread
566   dup /ihint_obj_cnt exch def
567   (3. Number of objects in the group.) two_column
568
569   dup 32 bitread
570   dup /ihint_group_sz exch def
571   (4. Length of the object group in bytes.) two_column
572
573   dup 32 bitread
574   dup /ihint_shared_cnt exch def
575   (5. Number of shared object references.) two_column
576
577   dup 16 bitread
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 
582   } if
583
584   pop
585
586   (7. Shared object identifier.) array_header
587   hint_stream bytealign
588   /ihint_shared_obj_id [
589     ihint_shared_cnt {
590       hint_stream hint_sobits bitread
591     } repeat
592   ] readonly def
593
594   ihint_shared_obj_id dump_array
595 } bind def
596
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
602
603   (S, Shared object hint table) table_header
604   dup /S .knownget {
605     hint_stream exch set_align
606     dump_shared_object_table
607   } {
608     (Required table is not found.) error_msg
609   } ifelse
610
611   dup /T .knownget {
612     (T, Thumbnail hint table) table_header
613     hint_stream exch set_align
614     dump_thumbnail_table
615   } if   
616
617   dup /O .knownget {
618     (O, Outline hint table) table_header
619     hint_stream exch set_align
620     dump_generic_table
621   } if
622
623   dup /A .knownget {
624     (A, Thread information hint table) table_header 
625     hint_stream exch set_align
626     dump_generic_table
627   } if
628
629   dup /E .knownget {
630     (E, Named destination hint table) table_header
631     hint_stream exch set_align
632     dump_generic_table
633   } if
634
635   dup /V .knownget {
636     (V, Interactive form hint table) table_header
637     hint_stream exch set_align
638     dump_interactive_table
639   } if
640
641   dup /I .knownget {
642     (I, Information dictionary hint table) table_header
643     hint_stream exch set_align
644     dump_generic_table
645   } if
646
647   dup /C .knownget {
648     (C, Logical structure hint table) table_header
649     hint_stream exch set_align
650     dump_interactive_table
651   } if
652
653   dup /L .knownget {
654     (L, Page label hint table) table_header
655     hint_stream exch set_align
656     dump_generic_table
657   } if
658
659     pop
660 } bind def
661
662
663 % Load PDF file and extract the hint stream.
664 /pdf_dump_hints {                             % <infile> pdf_dump_hints -
665   dup (r) file                                % fname
666   false exch                                  % fname F file 
667   {
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
678     exit
679   } loop
680   {
681     pdfdict begin
682     pdfopenfile dup begin
683     40 dict begin
684     /IDict exch def
685     .setsafe
686
687     % Read all objects into memory.
688     Trailer touch
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
694       eq {
695         /LinearizationParams exch def
696         LinearizationParams /H get
697         dup length 2 eq {
698           0 get PDFoffset add PDFfile exch setfileposition
699           PDFfile token pop 
700           PDFfile token pop
701           resolveR dup true resolvestream
702           /ReusableStreamDecode filter 
703           bitstream dup bytealign
704           /hint_stream exch def
705
706           dump_all_tables
707         } {
708           pop
709           (Overflow hint stream is not supported.) =
710         } ifelse
711       } {
712         pop
713         (Wrong file length in linearization dictionary.) =
714       } ifelse
715     } {
716       pop (The file is not linearized.) =
717     } ifelse
718     end         % temporary dict
719     end         % IDict
720     end
721   } {
722     pop
723     (Input file is not a valid PDF file.) =
724   } ifelse
725 } bind def
726
727 % Initial setup
728 /dump_hints {
729   counttomark 1 eq {
730     exch pop
731     save exch
732     3000000 setvmthreshold
733     pdfoptdict begin 
734     pdf_dump_hints
735     end
736     restore
737     true
738   } {
739     cleartomark false
740   } ifelse
741 } bind def
742
743 /shellarguments {false} def
744 (pdfopt.ps) runlibfile
745 currentdict /shellarguments undef
746
747 % Check for command line arguments.
748 mark shellarguments {
749   dump_hints not {
750     (Usage: gs -dNODISPLAY  -- dumphint.ps input.pdf) = flush
751   } if
752 } {
753   pop
754 } ifelse
755
756 % EOF