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.

323 lines
10 KiB

1 month ago
  1. %!PS
  2. % Copyright (C) 2001-2023 Artifex Software, Inc.
  3. % All Rights Reserved.
  4. %
  5. % This software is provided AS-IS with no warranty, either express or
  6. % implied.
  7. %
  8. % This software is distributed under license and may not be copied,
  9. % modified or distributed except as expressly authorized under the terms
  10. % of the license contained in the file LICENSE in this distribution.
  11. %
  12. % Refer to licensing information at http://www.artifex.com or contact
  13. % Artifex Software, Inc., 39 Mesa Street, Suite 108A, San Francisco,
  14. % CA 94129, USA, for further information.
  15. %
  16. %
  17. % $Id: pdf_info.ps 6300 2005-12-28 19:56:24Z alexcher $
  18. % Dump some info from a PDF file
  19. % usage: gs -dNODISPLAY -q -sFile=____.pdf [-dDumpMediaSizes=false] [-dDumpFontsNeeded=false] [-dDumpXML]
  20. % [-dDumpFontsUsed [-dShowEmbeddedFonts] ] lib/pdf_info.ps
  21. 128 dict begin
  22. /QUIET true def % in case they forgot
  23. /showoptions {
  24. ( where "options" are:) =
  25. ( -dDumpMediaSizes=false (default true) MediaBox and CropBox for each page) =
  26. ( -dDumpFontsNeeded=false (default true)Fonts used, but not embedded) =
  27. ( -dDumpXML print the XML Metadata from the PDF, if present) =
  28. ( -dDumpFontsUsed List all fonts used) =
  29. ( -dShowEmbeddedFonts only meaningful with -dDumpFontsUsed) =
  30. (\n If no options are given, the default is -dDumpMediaSizes -dDumpFontsNeeded) =
  31. () =
  32. flush
  33. } bind def
  34. /DumpMediaSizes where { pop } { /DumpMediaSizes true def } ifelse
  35. /DumpFontsNeeded where { pop } { /DumpFontsNeeded true def } ifelse
  36. [ {.shellarguments} stopped not
  37. {
  38. { counttomark 1 eq {
  39. dup 0 get (-) 0 get ne {
  40. % File specified on the command line using: -- lib/pdf_info.ps infile.pdf
  41. /File exch def
  42. false % don't show usage
  43. } {
  44. true % show usage and quit
  45. } ifelse
  46. } { true } ifelse
  47. {
  48. (\n*** Usage: gs [options] -- lib/pdf_info.ps infile.pdf ***\n\n) print
  49. showoptions
  50. quit
  51. } if
  52. } if
  53. } if
  54. /File where not {
  55. (\n *** Missing input file name \(use -sFile=____.pdf\)\n) =
  56. ( usage: gs -dNODISPLAY -q -sFile=____.pdf [ options ] lib/pdf_info.ps\n) =
  57. showoptions
  58. quit
  59. } if
  60. cleartomark % discard the dict from --where--
  61. % ---- No more executable code on the top level after this line -----
  62. % ---- except 2 lines at the very end -----
  63. % Write a character to the standard output.
  64. /putchar [ % int -> -
  65. (%stdout) (w) file
  66. /exch cvx /write cvx
  67. ] cvx bind def
  68. % Write U+xxxx to the standard output as UTF-8.
  69. /put-ucode { % int -> -
  70. dup 16#80 ge {
  71. dup 16#800 ge {
  72. dup 16#10000 ge {
  73. dup -18 bitshift 16#f0 or putchar
  74. dup -12 bitshift 16#3f and 16#80 or putchar
  75. } {
  76. dup -12 bitshift 16#e0 or putchar
  77. } ifelse
  78. dup -6 bitshift 16#3f and 16#80 or putchar
  79. } {
  80. dup -6 bitshift 16#C0 or putchar
  81. } ifelse
  82. 16#3f and 16#80 or
  83. } if
  84. putchar
  85. } bind def
  86. % PDFDocEncoding to U+xxxx decoding table.
  87. /doc-to-ucode [
  88. 0 1 23 {} for
  89. 16#2d8 16#2c7 16#2c6 16#2d9 16#2dd 16#2db 16#2da 16#2dc
  90. 32 1 127 {} for
  91. 16#2022 16#2020 16#2021 16#2026 16#2014 16#2013 16#192
  92. 16#2044 16#2039 16#203a 16#2212 16#2030 16#201e 16#201c
  93. 16#201d 16#2018 16#2019 16#201a 16#2122 16#fb01 16#fb02
  94. 16#141 16#152 16#160 16#178 16#17d 16#131 16#142 16#153
  95. 16#161 16#17e 0 16#20ac
  96. 161 1 255 {} for
  97. ] readonly def
  98. % Convert a doc string from PDFDocEncoding or UTF-16BE to UTF-8
  99. % and write it to standard output.
  100. /write-doc-string { % (string) -> -
  101. 1024 string cvs <feff> anchorsearch {
  102. pop
  103. 0 exch % hi16 (str)
  104. 0 2 2 index length 2 sub {
  105. 2 copy 2 copy % hi16 (str) i (str) i (str) i
  106. get 256 mul 3 1 roll % hi16 (str) i hi*256 (str) i
  107. 1 add get add % hi16 (str) i 256*hi+lo
  108. dup 16#fc00 and dup % hi16 (str) i 256*hi+lo tag tag
  109. 16#d800 eq { % High surrogate
  110. pop
  111. 16#3ff and
  112. 10 bitshift
  113. 16#10000 add % hi16 (str) i hi16'
  114. 4 1 roll % hi16' hi16 (str) i
  115. pop exch pop % hi16' (str)
  116. } {
  117. 16#dc00 eq { % Low surrogate
  118. 16#3ff and % hi16 (str) i (256*hi+lo)&0x3ff
  119. 4 -1 roll add % (str) i (256*hi+lo)&0x3ff+hi16
  120. put-ucode % (str) i
  121. pop 0 exch % 0 (str)
  122. } { % BMP plane
  123. put-ucode % hi16 (str) i
  124. pop % hi16 (str)
  125. } ifelse
  126. } ifelse
  127. } for
  128. pop pop % -
  129. } {
  130. { //doc-to-ucode exch get put-ucode
  131. } forall
  132. } ifelse
  133. } bind def
  134. % If running with -dSAFER, .sort may not be present. Define a (slower) PS alternative
  135. systemdict /.sort known not {
  136. % <array> <lt-proc> .sort <array>
  137. /.sort
  138. { 1 index length 1 sub -1 1
  139. { 2 index exch 2 copy get 3 copy % arr proc arr i arr[i] arr i arr[i]
  140. 0 1 3 index 1 sub
  141. { 3 index 1 index get % arr proc arr i arr[i] arr imax amax j arr[j]
  142. 2 index 1 index 10 index exec
  143. { % ... amax < arr[j]
  144. 4 2 roll
  145. }
  146. if pop pop
  147. }
  148. for % arr proc arr i arr[i] arr imax amax
  149. 4 -1 roll exch 4 1 roll put put
  150. }
  151. for
  152. pop
  153. } bind def
  154. } if
  155. /knownoget
  156. {
  157. 2 copy known {
  158. get
  159. true
  160. }{
  161. pop pop false
  162. } ifelse
  163. }bind def
  164. /PDFContext << >> .PDFInit def
  165. {File (r) file PDFContext .PDFStream} stopped not
  166. {
  167. PDFContext .PDFInfo
  168. File
  169. () = ( ) print print ( has ) print
  170. dup /NumPages get dup =print 10 mod 1 eq { ( page.\n) } { ( pages\n) } ifelse = flush
  171. /DumpXML where {/DumpXML get}{//false}ifelse
  172. {
  173. (\n*** DumpXML is no longer supported. ***\n\n) print
  174. }if
  175. dup /Title knownoget { (Title: ) print write-doc-string () = flush } if
  176. dup /Author knownoget { (Author: ) print write-doc-string () = flush } if
  177. dup /Subject knownoget { (Subject: ) print write-doc-string () = flush } if
  178. dup /Keywords knownoget { (Keywords: ) print write-doc-string () = flush } if
  179. dup /Creator knownoget { (Creator: ) print write-doc-string () = flush } if
  180. dup /Producer knownoget { (Producer: ) print write-doc-string () = flush } if
  181. dup /CreationDate knownoget { (CreationDate: ) print write-doc-string () = flush } if
  182. dup /ModDate knownoget { (ModDate: ) print write-doc-string () = flush } if
  183. dup /Trapped knownoget { (Trapped: ) print write-doc-string () = flush } if
  184. (\n) print flush
  185. /EmbeddedFonts 10 dict def
  186. /UnEmbeddedFonts 10 dict def
  187. /FontNumbers 10 dict def
  188. /NumPages get 0 1 3 -1 roll 1 sub
  189. {
  190. dup
  191. PDFContext exch .PDFPageInfoExt exch
  192. DumpMediaSizes {
  193. (Page ) print 1 add =print
  194. dup /UserUnit knownoget {( UserUnit: ) print =print} if
  195. dup /MediaBox knownoget {( MediaBox: ) print ==only} if
  196. dup /CropBox knownoget {( CropBox: ) print ==only} if
  197. dup /BleedBox knownoget {( BleedBox: ) print ==only} if
  198. dup /TrimBox knownoget {( TrimBox: ) print ==only} if
  199. dup /ArtBox knownoget {( ArtBox: ) print ==only} if
  200. dup /Rotate knownoget not {0}if ( Rotate = ) print =print
  201. dup /Annots knownoget {{( Page contains Annotations) print} if} if
  202. dup /UsesTransparency knownoget {{( Page uses transparency features) print} if} if
  203. dup /Spots knownoget {
  204. (\n Page Spot colors: ) =
  205. {( ) print (') print 256 string cvs print (') =} forall
  206. } if
  207. (\n) print flush
  208. (\n) print flush
  209. }
  210. {
  211. pop
  212. } ifelse
  213. /Fonts knownoget
  214. {
  215. {
  216. dup /ObjectNum known
  217. {
  218. %% Fonts with an ObjectNumber may have been previously referenced on another page
  219. dup /ObjectNum get
  220. dup FontNumbers exch known
  221. {
  222. pop
  223. %% found the ObjectNumber in the FontNumbers dictionary so we've seen this one.
  224. //false
  225. }
  226. {
  227. %% Not seen before, add the number to the array and process this font
  228. FontNumbers exch dup put
  229. //true
  230. }ifelse
  231. }{
  232. %% Fonts without an ObjectNumber are defined inline and so must be unique
  233. //true
  234. } ifelse
  235. {
  236. % First time we've seen the font
  237. dup /Descendants known
  238. {
  239. dup /BaseFont get
  240. EmbeddedFonts exch dup put % We class the Type 0 font as 'embedded', but it's really the descendant which is embedded or not.
  241. dup /Descendants get
  242. 1 index /BaseFont get
  243. 2 index /Embedded get
  244. {
  245. EmbeddedFonts exch dup put
  246. }
  247. {
  248. UnEmbeddedFonts exch dup put
  249. }ifelse
  250. pop
  251. }
  252. {
  253. dup /BaseFont get
  254. 1 index /Embedded get
  255. {
  256. EmbeddedFonts exch dup put
  257. }
  258. {
  259. UnEmbeddedFonts exch dup put
  260. } ifelse
  261. }ifelse
  262. pop
  263. }
  264. {
  265. pop
  266. } ifelse
  267. }forall
  268. } if
  269. } for
  270. /DumpFontsUsed where {/DumpFontsUsed get}{//false}ifelse
  271. {
  272. [
  273. UnEmbeddedFonts {pop} forall
  274. /ShowEmbeddedFonts where {/ShowEmbeddedFonts get}{//false}ifelse
  275. {
  276. EmbeddedFonts {pop} forall
  277. } if
  278. ]
  279. dup length 0 gt {
  280. { 100 string cvs exch 100 string cvs exch lt } .sort
  281. (\nFont or CIDFont resources used (plain name and ASCIIHEX string representation):) =
  282. { 128 string cvs dup print ( ) print (<) print 128 string cvs {16 8 string cvrs print} forall (>) print (\n) print} forall
  283. } if
  284. }
  285. {
  286. [
  287. DumpFontsNeeded
  288. {
  289. UnEmbeddedFonts {pop} forall
  290. } if
  291. ]
  292. dup length 0 gt {
  293. { 100 string cvs exch 100 string cvs exch lt } .sort
  294. (\nFonts Needed that are not embedded \(system fonts required\):) =
  295. { ( ) print 128 string cvs dup print ( ) print (<) print {16 8 string cvrs print} forall (>) print (\n) print} forall
  296. } if
  297. }ifelse
  298. } if
  299. PDFContext .PDFClose
  300. end
  301. quit