home *** CD-ROM | disk | FTP | other *** search
/ Chip 2002 October / Chip_2002-10_cd1.bin / zkuste / pdf / download / gs704w32.exe / gs7.04 / lib / pdfwrite.ps < prev    next >
Encoding:
Text File  |  2002-01-31  |  8.3 KB  |  286 lines

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