You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

220 lines
6.7 KiB

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