summaryrefslogtreecommitdiff
path: root/Master/tlpkg/tlgs/lib/pdf_info.ps
blob: 18725ac4eaedc39d56b8005d2c6f6759b2f38805 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
%!PS
% Copyright (C) 2001-2023 Artifex Software, Inc.
% 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.
%
% Refer to licensing information at http://www.artifex.com or contact
% Artifex Software, Inc.,  39 Mesa Street, Suite 108A, San Francisco,
% CA 94129, USA, for further information.
%
%
% $Id: pdf_info.ps 6300 2005-12-28 19:56:24Z alexcher $

% Dump some info from a PDF file

% usage: gs -dNODISPLAY -q -sFile=____.pdf [-dDumpMediaSizes=false] [-dDumpFontsNeeded=false] [-dDumpXML]
%                                          [-dDumpFontsUsed [-dShowEmbeddedFonts] ] lib/pdf_info.ps

128 dict begin

/QUIET true def		% in case they forgot

/showoptions {
  (           where "options" are:) =
  (           -dDumpMediaSizes=false    (default true) MediaBox and CropBox for each page) =
  (           -dDumpFontsNeeded=false   (default true)Fonts used, but not embedded) =
  (           -dDumpXML                 print the XML Metadata from the PDF, if present) =
  (           -dDumpFontsUsed           List all fonts used) =
  (           -dShowEmbeddedFonts       only meaningful with -dDumpFontsUsed) =
  (\n          If no options are given, the default is -dDumpMediaSizes -dDumpFontsNeeded) =
  () =
  flush
} bind def

/DumpMediaSizes where { pop } { /DumpMediaSizes true def } ifelse
/DumpFontsNeeded where { pop } { /DumpFontsNeeded true def } ifelse

[ {.shellarguments} stopped not
  {
    { counttomark 1 eq {
        dup 0 get (-) 0 get ne {
          % File specified on the command line using:  -- lib/pdf_info.ps infile.pdf
          /File exch def
          false   % don't show usage
        } {
          true    % show usage and quit
        } ifelse
      } { true } ifelse
      {
        (\n*** Usage: gs [options] -- lib/pdf_info.ps infile.pdf  ***\n\n) print
        showoptions
        quit
      } if
    } if
  } if
/File where not {
  (\n   *** Missing input file name \(use -sFile=____.pdf\)\n) =
  (    usage: gs -dNODISPLAY -q -sFile=____.pdf [ options ] lib/pdf_info.ps\n) =
  showoptions
  quit
} if
cleartomark		% discard the dict from --where--

% ---- No more executable code on the top level after this line -----
% ---- except 2 lines at the very end                           -----

% Write a character to the standard output.
/putchar [ % int -> -
  (%stdout) (w) file
  /exch cvx /write cvx
] cvx bind def

% Write U+xxxx to the standard output as UTF-8.
/put-ucode { % int -> -
  dup 16#80 ge {
    dup 16#800 ge {
      dup 16#10000 ge {
        dup -18 bitshift 16#f0 or putchar
        dup -12 bitshift 16#3f and 16#80 or putchar
      } {
        dup -12 bitshift 16#e0 or putchar
      } ifelse
      dup -6  bitshift 16#3f and 16#80 or putchar
    } {
      dup -6 bitshift 16#C0 or putchar
    } ifelse
    16#3f and 16#80 or
  } if
  putchar
} bind def

% PDFDocEncoding to U+xxxx decoding table.
/doc-to-ucode [
  0 1 23 {} for
  16#2d8 16#2c7 16#2c6 16#2d9 16#2dd 16#2db 16#2da 16#2dc
  32 1 127 {} for
  16#2022 16#2020 16#2021 16#2026 16#2014 16#2013 16#192
  16#2044 16#2039 16#203a 16#2212 16#2030 16#201e 16#201c 
  16#201d 16#2018 16#2019 16#201a 16#2122 16#fb01 16#fb02
  16#141 16#152 16#160 16#178 16#17d 16#131 16#142 16#153
  16#161 16#17e 0 16#20ac
  161 1 255 {} for
] readonly def

% Convert a doc string from PDFDocEncoding or UTF-16BE to UTF-8
% and write it to standard output. 
/write-doc-string { % (string) -> -
  1024 string cvs <feff> anchorsearch {
    pop
    0 exch                 % hi16 (str) 
    0 2 2 index length 2 sub {
      2 copy 2 copy        % hi16 (str) i (str) i (str) i
      get 256 mul 3 1 roll % hi16 (str) i hi*256 (str) i
      1 add get add        % hi16 (str) i 256*hi+lo
      dup 16#fc00 and dup  % hi16 (str) i 256*hi+lo tag tag
      16#d800 eq { % High surrogate
        pop
        16#3ff and
        10 bitshift
        16#10000 add       % hi16  (str) i hi16'
        4 1 roll           % hi16' hi16 (str) i
        pop exch pop       % hi16' (str)
      } {
        16#dc00 eq { % Low surrogate
          16#3ff and       % hi16 (str) i (256*hi+lo)&0x3ff
          4 -1 roll add    % (str) i (256*hi+lo)&0x3ff+hi16
          put-ucode        % (str) i
          pop 0 exch       % 0 (str)
        } { % BMP plane
          put-ucode        % hi16 (str) i
          pop              % hi16 (str)
        } ifelse
      } ifelse
    } for
    pop pop                % -
  } {
    { //doc-to-ucode exch get put-ucode 
    } forall
  } ifelse
} bind def

% If running with -dSAFER, .sort may not be present. Define a (slower) PS alternative
systemdict /.sort known not {
% <array> <lt-proc> .sort <array>
 /.sort
   { 1 index length 1 sub -1 1
       { 2 index exch 2 copy get 3 copy % arr proc arr i arr[i] arr i arr[i]
         0 1 3 index 1 sub
           { 3 index 1 index get        % arr proc arr i arr[i] arr imax amax j arr[j]
             2 index 1 index 10 index exec
               {                        % ... amax < arr[j]
                 4 2 roll
               }
             if pop pop
           }
         for                            % arr proc arr i arr[i] arr imax amax
         4 -1 roll exch 4 1 roll put put
       }
     for
     pop
   } bind def
} if

/knownoget
{
  2 copy known {
    get
    true
  }{
    pop pop false
  } ifelse
}bind def

/PDFContext << >> .PDFInit def
{File (r) file PDFContext .PDFStream} stopped not
{
  PDFContext .PDFInfo
  File
  () = (        ) print print ( has ) print
  dup /NumPages get dup =print 10 mod 1 eq { ( page.\n) } { ( pages\n) } ifelse = flush

  /DumpXML where {/DumpXML get}{//false}ifelse
  {
    (\n*** DumpXML is no longer supported. ***\n\n) print
  }if

  dup /Title knownoget { (Title: ) print write-doc-string () = flush } if
  dup /Author knownoget { (Author: ) print write-doc-string () = flush } if
  dup /Subject knownoget { (Subject: ) print write-doc-string () = flush } if
  dup /Keywords knownoget { (Keywords: ) print write-doc-string () = flush } if
  dup /Creator knownoget { (Creator: ) print write-doc-string () = flush } if
  dup /Producer knownoget { (Producer: ) print write-doc-string () = flush } if
  dup /CreationDate knownoget { (CreationDate: ) print write-doc-string () = flush } if
  dup /ModDate knownoget { (ModDate: ) print write-doc-string () = flush } if
  dup /Trapped knownoget { (Trapped: ) print write-doc-string () = flush } if
  (\n) print flush

  /EmbeddedFonts 10 dict def
  /UnEmbeddedFonts 10 dict def
  /FontNumbers 10 dict def

  /NumPages get 0 1 3 -1 roll 1 sub
  {
    dup
    PDFContext exch .PDFPageInfoExt exch
    DumpMediaSizes {
      (Page ) print 1 add =print
      dup /UserUnit knownoget {( UserUnit: ) print =print} if
      dup /MediaBox knownoget {( MediaBox: ) print ==only} if
      dup /CropBox knownoget  {( CropBox: )  print ==only} if
      dup /BleedBox knownoget {( BleedBox: ) print ==only} if
      dup /TrimBox knownoget  {( TrimBox: )  print ==only} if
      dup /ArtBox knownoget   {( ArtBox: )   print ==only} if
      dup /Rotate knownoget not {0}if ( Rotate = ) print =print
      dup /Annots knownoget {{(     Page contains Annotations) print} if} if
      dup /UsesTransparency knownoget {{(     Page uses transparency features) print} if} if
      dup /Spots knownoget {
        (\n    Page Spot colors: ) =
        {(        ) print (') print 256 string cvs print (') =} forall
      } if
      (\n) print flush
      (\n) print flush
    }
    {
      pop
    } ifelse

    /Fonts knownoget
    {
      {
        dup /ObjectNum known
        {
          %% Fonts with an ObjectNumber may have been previously referenced on another page
          dup /ObjectNum get
          dup FontNumbers exch known
          {
            pop
            %% found the ObjectNumber in the FontNumbers dictionary so we've seen this one.
            //false
          }
          {
            %% Not seen before, add the number to the array and process this font
            FontNumbers exch dup put
            //true
          }ifelse
        }{
          %% Fonts without an ObjectNumber are defined inline and so must be unique
          //true
        } ifelse
        {
          % First time we've seen the font
          dup /Descendants known
          {
            dup /BaseFont get
            EmbeddedFonts exch dup put    % We class the Type 0 font as 'embedded', but it's really the descendant which is embedded or not.
            dup /Descendants get
            1 index /BaseFont get
            2 index /Embedded get
            {
              EmbeddedFonts exch dup put
            }
            {
              UnEmbeddedFonts exch dup put
            }ifelse
            pop
          }
          {
            dup /BaseFont get
            1 index /Embedded get
            {
              EmbeddedFonts exch dup put
            }
            {
              UnEmbeddedFonts exch dup put
            } ifelse
          }ifelse
          pop
        }
        {
          pop
        } ifelse
      }forall
    } if
  } for

  /DumpFontsUsed where {/DumpFontsUsed get}{//false}ifelse
  {
    [
    UnEmbeddedFonts {pop} forall
    /ShowEmbeddedFonts where {/ShowEmbeddedFonts get}{//false}ifelse
    {
      EmbeddedFonts {pop} forall
    } if
    ]
    dup length 0 gt {
      { 100 string cvs exch 100 string cvs exch lt } .sort
      (\nFont or CIDFont resources used (plain name and ASCIIHEX string representation):) =
      { 128 string cvs dup print (    ) print (<) print 128 string cvs {16 8 string cvrs print} forall (>) print (\n) print} forall
    } if
  }
  {
    [
    DumpFontsNeeded
    {
      UnEmbeddedFonts {pop} forall
    } if
    ]
    dup length 0 gt {
      { 100 string cvs exch 100 string cvs exch lt } .sort
      (\nFonts Needed that are not embedded \(system fonts required\):) =
      { (    ) print 128 string cvs dup print (    ) print (<) print {16 8 string cvrs print} forall (>) print (\n) print} forall
    } if
  }ifelse
} if
PDFContext .PDFClose

end
quit