home *** CD-ROM | disk | FTP | other *** search
/ Internet Magazine 2002 February / INTERNET88.ISO / pc / software / windows / bits / pdf995 / data1.cab / Program_Executable_Files / res / pdfwrite.ps < prev    next >
Encoding:
Text File  |  2001-12-08  |  7.5 KB  |  269 lines

  1. %    Copyright (C) 1999, 2000 Aladdin Enterprises.  All rights reserved.
  2. % This file is part of GNU Ghostscript.
  3. % GNU Ghostscript is distributed in the hope that it will be useful, but
  4. % WITHOUT ANY WARRANTY.  No author or distributor accepts responsibility
  5. % to anyone for the consequences of using it or for whether it serves any
  6. % particular purpose or works at all, unless he says so in writing.  Refer
  7. % to the GNU General Public License for full details.
  8. % Everyone is granted permission to copy, modify and redistribute GNU
  9. % Ghostscript, but only under the conditions described in the GNU General
  10. % Public License.  A copy of this license is supposed to have been given
  11. % to you along with GNU Ghostscript so you can know your rights and
  12. % responsibilities.  It should be in a file named COPYING.  Among other
  13. % things, the copyright notice and this notice must be preserved on all
  14. % copies.
  15.  
  16. % $RCSfile: pdfwrite.ps,v $ $Revision: 1.3.2.2 $
  17. % Writer for transmuting PDF files.
  18.  
  19. % NOTES:
  20. % We do editing by replacing objects (in the cache) and then doing a
  21. %   simple recursive walk with object renumbering.
  22. % Free variables:
  23. %   RMap [per input file] (dict): input_obj# => output_obj#
  24. %   PDFfile (file): current input file
  25. %   OFile (file): current output file
  26. %   XRef (dict): output_obj# => output_file_pos
  27. %   ToWrite: 0..N-1 => [obj# gen#]
  28.  
  29. /.setlanguagelevel where { pop 2 .setlanguagelevel } if
  30. .currentglobal true .setglobal
  31.  
  32. /PDEBUG where { pop } { /PDEBUG false def } ifelse
  33.  
  34. % ================ Object mapping ================ %
  35.  
  36. % Initialize the object number and location map.
  37. /omapinit {        % - omapinit -
  38.   /RMap 100 dict def
  39.   /XRef 100 dict def
  40. } def
  41.  
  42. % Map an object number.
  43. /omapnew {        % <oldobj#> omap <newobj#> <isnew>
  44.   RMap 1 index .knownget {
  45.     exch pop false
  46.   } {
  47.     RMap dup length 1 add 2 index exch dup 5 1 roll put pop true
  48.   } ifelse
  49. } def
  50. /omap {            % <oldobj#> omap <newobj#>
  51.   omapnew pop
  52. } bind def
  53.  
  54. % Save and restore the object map.
  55. % Note that currentomap either returns a copy or calls omapinit.
  56. /currentomap {        % <copy> currentomap <omap>
  57.   {
  58.     [RMap dup length dict copy XRef dup length dict copy]
  59.   } {
  60.     [RMap XRef] omapinit
  61.   } ifelse
  62. } bind def
  63. /setomap {        % <omap> setomap -
  64.   aload pop /XRef exch def /RMap exch def
  65. } bind def
  66.  
  67. % ================ Writing ================ %
  68.  
  69. % ---------------- Low-level output ---------------- %
  70.  
  71. % Write a string on the output file.
  72. /ows {            % <string> ows -
  73.   OFile exch writestring
  74. } def
  75.  
  76. % ---------------- Scalars ---------------- %
  77.  
  78. /pdfnamechars (!"$&'*+,-.0123456789:;=?@ABCDEFGHIJKLMNOPQRSTUVWXYZ\\^_`abcdefghijklmnopqrstuvwxyz|~) readonly def
  79. /pdfwritename {        % <name> pdfwritename -
  80.   (/) ows .namestring {
  81.     ( ) dup 0 4 -1 roll put
  82.     //pdfnamechars 1 index search {
  83.       pop pop pop
  84.     } {
  85.       pop 256 add 16 =string cvrs
  86.       dup 0 (#) 0 get put
  87.     } ifelse ows
  88.   } forall
  89. } def
  90.  
  91. % ---------------- Composite objects ---------------- %
  92.  
  93. /pdfwriteprocs mark
  94.   /resolveR { pdfwriteref }
  95.   /O { pdfwritenewref }
  96. .dicttomark readonly def
  97. /pdfwritearray {    % <array> pdfwritearray -
  98.   dup xcheck {
  99.     aload pop //pdfwriteprocs exch get exec
  100.   } {
  101.     ([) ows { pdfwritevalue (\n) ows } forall (]) ows
  102.   } ifelse
  103. } def
  104.  
  105. /pdfwritedict {        % <dict> pdfwritedict -
  106.   dup xcheck {
  107.     pdfwritestream
  108.   } {
  109.     (<<) ows {
  110.       exch pdfwritevalue ( ) ows pdfwritevalue (\n) ows
  111.     } forall (>>) ows
  112.   } ifelse
  113. } def
  114.  
  115. % ---------------- References ---------------- %
  116.  
  117. /pdfwritenewref {    % <newobj#> pdfwritenewref -
  118.   OFile exch write=only ( 0 R) ows
  119. } def
  120.  
  121. /pdfwriteref {        % <obj#> <gen#> pdfwriteref -
  122.   1 index omapnew {
  123.     ToWrite dup length 5 -2 roll 2 packedarray put
  124.   } {
  125.     exch pop exch pop
  126.   } ifelse
  127.   pdfwritenewref
  128. } def
  129.  
  130. /pdfcopystring 200 string def
  131. /pdfwritestream {    % <streamdict> pdfwritestream -
  132.     % Remove File, FilePosition, and StreamKey;
  133.     % optimize by replacing an indirect Length.
  134.   dup dup length dict copy
  135.     % Stack: origdict dict
  136.   dup /File undef dup /FilePosition undef dup /StreamKey undef
  137.   dup /Length get dup oforce ne {
  138.     dup /Length 2 copy oget put
  139.   } if
  140.   exch dup /File get dup 3 -1 roll /FilePosition get setfileposition
  141.   pdfcopystream
  142. } def
  143.  
  144. % We put copying the stream contents in separate procedures so that we
  145. % can replace this function if desired.
  146. /pdfcopybytes {        % <fromfile> <tofile> <length> pdfcopybytes -
  147.   {
  148.     dup 0 eq { exit } if
  149.     //pdfcopystring 0 2 index 2 index length .min getinterval
  150.     3 index exch readstring 3 1 roll
  151.     3 index 1 index writestring length sub exch not { exit } if
  152.   } loop pop pop pop
  153. } def
  154. /pdfcopystream {    % <newstreamdict> <file> pdfcopystream -
  155.             %   (file has been positioned)
  156.   1 index pdfwritevalue (stream\n) ows
  157.   exch /Length get OFile exch pdfcopybytes
  158.   (endstream) ows
  159. } def
  160.  
  161. % ---------------- General values/objects ---------------- %
  162.  
  163. /pdfwritetypes mark
  164.     % Scalars
  165.   /nulltype { pop (null) ows }
  166.   /integertype { =string cvs ows }
  167.   /booleantype 1 index
  168.   /realtype { OFile exch write===only }
  169.   /stringtype 1 index
  170.   /nametype { pdfwritename }
  171.     % Composite/reference objects
  172.   /arraytype { pdfwritearray }
  173.   /packedarraytype 1 index
  174.   /dicttype { pdfwritedict }
  175. .dicttomark readonly def
  176.  
  177. /pdfwritevalue {    % <obj> pdfwritevalue -
  178.   PDEBUG { (****Writing: ) print dup === flush } if
  179.   //pdfwritetypes 1 index type get exec
  180. } def
  181.  
  182. % We make pdfwriteobjdef a separate procedure for external use.
  183. /pdfwriteobjheader {    % <newobj#> pdfwriteobjheader -
  184.   XRef 1 index OFile .fileposition put
  185.   OFile exch write=only ( 0 obj\n) ows
  186. } def
  187. /pdfwriteobjdef {    % <newobj#> <value> pdfwriteobjdef -
  188.   exch pdfwriteobjheader
  189.   pdfwritevalue (\nendobj\n) ows
  190. } def
  191. /pdfwriteobj {        % <obj#> <gen#> pdfwriteobj -
  192.   1 index exch resolveR exch omap exch pdfwriteobjdef
  193. } def
  194.  
  195. % ---------------- File-level entities ---------------- %
  196.  
  197. % Write a PDF file header.
  198. % Free variables: OFile, PDFversion.
  199. /pdfwriteheader {    % - pdfwriteheader -
  200.   (%PDF-) ows OFile PDFversion write=
  201.   (%\347\363\317\323\n) ows
  202. } bind def
  203.  
  204. % Write a cross-reference table and trailer.
  205. /pdfwritexref {        % <firstobj#> <#objs> pdfwritexref -
  206.   (xref\n) ows
  207.   OFile 2 index write=only ( ) ows OFile 1 index write=
  208.   1 index add 1 sub 1 exch {
  209.     dup 0 eq {
  210.       pop (0000000000 65535 f \n) ows
  211.     } {
  212.       XRef exch get 1000000000 add =string cvs
  213.       dup 0 (0) 0 get put
  214.       ows ( 00000 n \n) ows
  215.     } ifelse
  216.   } for
  217. } bind def
  218. /pdfwritetrailer {    % <trailer> pdfwritetrailer -
  219.   (trailer\n) ows pdfwritevalue (\n) ows
  220. } bind def
  221. /pdfwritestartxref {    % <startpos> pdfwritestartxref -
  222.   (startxref\n) ows OFile exch write=
  223.   (%%EOF\n) ows
  224. } bind def
  225.  
  226. % ================ Top-level control ================ %
  227.  
  228. /pdfwrite {        % <file> <trailer> pdfwrite -
  229.   10 dict begin
  230.   /trailer exch def
  231.   /OFile exch def
  232.   /ToWrite 100 dict def
  233.   omapinit
  234.  
  235.     % Write the PDF file header.
  236.  
  237.   pdfwriteheader
  238.  
  239.     % Write the objects.
  240.  
  241.   trailer {
  242.     exch pop dup xcheck {    % The only executable objects are references.
  243.       aload pop pop pdfwriteobj
  244.     } {
  245.       pop
  246.     } ifelse
  247.   } forall
  248.     % Walk the object graph.
  249.   {
  250.     ToWrite dup length dup 0 eq { pop pop exit } if
  251.     1 sub 2 copy get 3 1 roll undef aload pop pdfwriteobj
  252.   } loop
  253.  
  254.     % Write the xref table and trailer.
  255.  
  256.   /xref OFile fileposition def
  257.   0 XRef length 1 add pdfwritexref
  258.   trailer dup length 1 add dict copy
  259.   dup /Size XRef length 1 add put pdfwritetrailer
  260.   xref pdfwritestartxref
  261.  
  262.   end
  263. } def
  264.  
  265. .setglobal
  266.