home *** CD-ROM | disk | FTP | other *** search
/ PC World 2001 April / PCWorld_2001-04_cd.bin / Software / Vyzkuste / gs / gs650w32.exe / gs6.50 / lib / pdfwrite.ps < prev    next >
Text File  |  2000-12-05  |  7KB  |  268 lines

  1. %    Copyright (C) 1999, 2000 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.3 2000/09/19 18:29:11 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. } def
  40.  
  41. % Map an object number.
  42. /omapnew {        % <oldobj#> omap <newobj#> <isnew>
  43.   RMap 1 index .knownget {
  44.     exch pop false
  45.   } {
  46.     RMap dup length 1 add 2 index exch dup 5 1 roll put pop true
  47.   } ifelse
  48. } def
  49. /omap {            % <oldobj#> omap <newobj#>
  50.   omapnew pop
  51. } bind def
  52.  
  53. % Save and restore the object map.
  54. % Note that currentomap either returns a copy or calls omapinit.
  55. /currentomap {        % <copy> currentomap <omap>
  56.   {
  57.     [RMap dup length dict copy XRef dup length dict copy]
  58.   } {
  59.     [RMap XRef] omapinit
  60.   } ifelse
  61. } bind def
  62. /setomap {        % <omap> setomap -
  63.   aload pop /XRef exch def /RMap exch def
  64. } bind def
  65.  
  66. % ================ Writing ================ %
  67.  
  68. % ---------------- Low-level output ---------------- %
  69.  
  70. % Write a string on the output file.
  71. /ows {            % <string> ows -
  72.   OFile exch writestring
  73. } def
  74.  
  75. % ---------------- Scalars ---------------- %
  76.  
  77. /pdfnamechars (!"$&'*+,-.0123456789:;=?@ABCDEFGHIJKLMNOPQRSTUVWXYZ\\^_`abcdefghijklmnopqrstuvwxyz|~) readonly def
  78. /pdfwritename {        % <name> pdfwritename -
  79.   (/) ows .namestring {
  80.     ( ) dup 0 4 -1 roll put
  81.     //pdfnamechars 1 index search {
  82.       pop pop pop
  83.     } {
  84.       pop 256 add 16 =string cvrs
  85.       dup 0 (#) 0 get put
  86.     } ifelse ows
  87.   } forall
  88. } def
  89.  
  90. % ---------------- Composite objects ---------------- %
  91.  
  92. /pdfwriteprocs mark
  93.   /resolveR { pdfwriteref }
  94.   /O { pdfwritenewref }
  95. .dicttomark readonly def
  96. /pdfwritearray {    % <array> pdfwritearray -
  97.   dup xcheck {
  98.     aload pop //pdfwriteprocs exch get exec
  99.   } {
  100.     ([) ows { pdfwritevalue (\n) ows } forall (]) ows
  101.   } ifelse
  102. } def
  103.  
  104. /pdfwritedict {        % <dict> pdfwritedict -
  105.   dup xcheck {
  106.     pdfwritestream
  107.   } {
  108.     (<<) ows {
  109.       exch pdfwritevalue ( ) ows pdfwritevalue (\n) ows
  110.     } forall (>>) ows
  111.   } ifelse
  112. } def
  113.  
  114. % ---------------- References ---------------- %
  115.  
  116. /pdfwritenewref {    % <newobj#> pdfwritenewref -
  117.   OFile exch write=only ( 0 R) ows
  118. } def
  119.  
  120. /pdfwriteref {        % <obj#> <gen#> pdfwriteref -
  121.   1 index omapnew {
  122.     ToWrite dup length 5 -2 roll 2 packedarray put
  123.   } {
  124.     exch pop exch pop
  125.   } ifelse
  126.   pdfwritenewref
  127. } def
  128.  
  129. /pdfcopystring 200 string def
  130. /pdfwritestream {    % <streamdict> pdfwritestream -
  131.     % Remove File, FilePosition, and StreamKey;
  132.     % optimize by replacing an indirect Length.
  133.   dup dup length dict copy
  134.     % Stack: origdict dict
  135.   dup /File undef dup /FilePosition undef dup /StreamKey undef
  136.   dup /Length get dup oforce ne {
  137.     dup /Length 2 copy oget put
  138.   } if
  139.   exch dup /File get dup 3 -1 roll /FilePosition get setfileposition
  140.   pdfcopystream
  141. } def
  142.  
  143. % We put copying the stream contents in separate procedures so that we
  144. % can replace this function if desired.
  145. /pdfcopybytes {        % <fromfile> <tofile> <length> pdfcopybytes -
  146.   {
  147.     dup 0 eq { exit } if
  148.     //pdfcopystring 0 2 index 2 index length .min getinterval
  149.     3 index exch readstring 3 1 roll
  150.     3 index 1 index writestring length sub exch not { exit } if
  151.   } loop pop pop pop
  152. } def
  153. /pdfcopystream {    % <newstreamdict> <file> pdfcopystream -
  154.             %   (file has been positioned)
  155.   1 index pdfwritevalue (stream\n) ows
  156.   exch /Length get OFile exch pdfcopybytes
  157.   (endstream) ows
  158. } def
  159.  
  160. % ---------------- General values/objects ---------------- %
  161.  
  162. /pdfwritetypes mark
  163.     % Scalars
  164.   /nulltype { =string cvs ows }
  165.   /integertype 1 index
  166.   /booleantype 1 index
  167.   /realtype { OFile exch write===only }
  168.   /stringtype 1 index
  169.   /nametype { pdfwritename }
  170.     % Composite/reference objects
  171.   /arraytype { pdfwritearray }
  172.   /packedarraytype 1 index
  173.   /dicttype { pdfwritedict }
  174. .dicttomark readonly def
  175.  
  176. /pdfwritevalue {    % <obj> pdfwritevalue -
  177.   PDEBUG { (****Writing: ) print dup === flush } if
  178.   //pdfwritetypes 1 index type get exec
  179. } def
  180.  
  181. % We make pdfwriteobjdef a separate procedure for external use.
  182. /pdfwriteobjheader {    % <newobj#> pdfwriteobjheader -
  183.   XRef 1 index OFile .fileposition put
  184.   OFile exch write=only ( 0 obj\n) ows
  185. } def
  186. /pdfwriteobjdef {    % <newobj#> <value> pdfwriteobjdef -
  187.   exch pdfwriteobjheader
  188.   pdfwritevalue (\nendobj\n) ows
  189. } def
  190. /pdfwriteobj {        % <obj#> <gen#> pdfwriteobj -
  191.   1 index exch resolveR exch omap exch pdfwriteobjdef
  192. } def
  193.  
  194. % ---------------- File-level entities ---------------- %
  195.  
  196. % Write a PDF file header.
  197. % Free variables: OFile, PDFversion.
  198. /pdfwriteheader {    % - pdfwriteheader -
  199.   (%PDF-) ows OFile PDFversion write=
  200.   (%\347\363\317\323\n) ows
  201. } bind def
  202.  
  203. % Write a cross-reference table and trailer.
  204. /pdfwritexref {        % <firstobj#> <#objs> pdfwritexref -
  205.   (xref\n) ows
  206.   OFile 2 index write=only ( ) ows OFile 1 index write=
  207.   1 index add 1 sub 1 exch {
  208.     dup 0 eq {
  209.       pop (0000000000 65535 f \n) ows
  210.     } {
  211.       XRef exch get 1000000000 add =string cvs
  212.       dup 0 (0) 0 get put
  213.       ows ( 00000 n \n) ows
  214.     } ifelse
  215.   } for
  216. } bind def
  217. /pdfwritetrailer {    % <trailer> pdfwritetrailer -
  218.   (trailer\n) ows pdfwritevalue (\n) ows
  219. } bind def
  220. /pdfwritestartxref {    % <startpos> pdfwritestartxref -
  221.   (startxref\n) ows OFile exch write=
  222.   (%%EOF\n) ows
  223. } bind def
  224.  
  225. % ================ Top-level control ================ %
  226.  
  227. /pdfwrite {        % <file> <trailer> pdfwrite -
  228.   10 dict begin
  229.   /trailer exch def
  230.   /OFile exch def
  231.   /ToWrite 100 dict def
  232.   omapinit
  233.  
  234.     % Write the PDF file header.
  235.  
  236.   pdfwriteheader
  237.  
  238.     % Write the objects.
  239.  
  240.   trailer {
  241.     exch pop dup xcheck {    % The only executable objects are references.
  242.       aload pop pop pdfwriteobj
  243.     } {
  244.       pop
  245.     } ifelse
  246.   } forall
  247.     % Walk the object graph.
  248.   {
  249.     ToWrite dup length dup 0 eq { pop pop exit } if
  250.     1 sub 2 copy get 3 1 roll undef aload pop pdfwriteobj
  251.   } loop
  252.  
  253.     % Write the xref table and trailer.
  254.  
  255.   /xref OFile fileposition def
  256.   0 XRef length 1 add pdfwritexref
  257.   trailer dup length 1 add dict copy
  258.   dup /Size XRef length 1 add put pdfwritetrailer
  259.   xref pdfwritestartxref
  260.  
  261.   end
  262. } def
  263.  
  264. .setglobal
  265.