home *** CD-ROM | disk | FTP | other *** search
/ jppd.dyndns.org / jppd.dyndns.org.tar / jppd.dyndns.org / QUERYPRO / Actualizar / Impressora_PDF / converter.exe / GPLGS / pdfwrite.ps < prev    next >
Text File  |  2003-12-13  |  10KB  |  346 lines

  1. %    Copyright (C) 1999, 2000, 2001 Aladdin Enterprises.  All rights reserved.
  2. % This software is provided AS-IS with no warranty, either express or
  3. % implied.
  4. % This software is distributed under license and may not be copied,
  5. % modified or distributed except as expressly authorized under the terms
  6. % of the license contained in the file LICENSE in this distribution.
  7. % For more information about licensing, please refer to
  8. % http://www.ghostscript.com/licensing/. For information on
  9. % commercial licensing, go to http://www.artifex.com/licensing/ or
  10. % contact Artifex Software, Inc., 101 Lucas Valley Road #110,
  11. % San Rafael, CA  94903, U.S.A., +1(415)492-9861.
  12.  
  13. % $Id: pdfwrite.ps,v 1.10.2.1 2003/12/12 22:07:59 giles Exp $
  14. % Writer for transmuting PDF files.
  15.  
  16. % NOTES:
  17. % We do editing by replacing objects (in the cache) and then doing a
  18. %   simple recursive walk with object renumbering.
  19. % Free variables:
  20. %   RMap [per input file] (dict): input_obj# => output_obj#
  21. %   PDFfile (file): current input file
  22. %   OFile (file): current output file
  23. %   XRef (dict): output_obj# => output_file_pos
  24. %   ToWrite: 0..N-1 => [obj# gen#]
  25.  
  26. /.setlanguagelevel where { pop 2 .setlanguagelevel } if
  27. .currentglobal true .setglobal
  28.  
  29. /PDFWRDEBUG where { pop } { /PDFWRDEBUG false def } ifelse
  30.  
  31. % ======== Long dictionary support =============== %
  32.  
  33. % The key must be a non-negative iteger.
  34.  
  35. /ld_dict {          % <len> ld_dict <ldict>
  36.   pop << 0 <<>> >>
  37. } bind def
  38.  
  39. /ld_length {        % <ldict> ld_length <length>
  40.   0 exch { exch pop length add } forall
  41. } bind def
  42.  
  43. /ld_get {           % <ldict> <key> ld_get <any>
  44.   dup 3 1 roll -15 bitshift get exch get
  45. } bind def
  46.  
  47. /ld_put {           % <ldict> <key> <any> ld_put -
  48.   3 1 roll dup               % any ldict key key
  49.   4 1 roll -15 bitshift      % key any ldict key>>15
  50.   2 copy known {
  51.     get                      % key any subdict
  52.     3 1 roll put             % -
  53.   } {
  54.     64 dict dup 6 1 roll     % <<>> key any ldict key>>15 <<>>
  55.     put put
  56.   } ifelse                   % -
  57. } bind def
  58.                     
  59. /ld_known {         % <ldict> <key> ld_known <bool>
  60.   dup 3 1 roll -15 bitshift  % key <<>> key<<15
  61.   2 copy known {
  62.     get exch known
  63.   } {
  64.     pop pop pop //false
  65.   } ifelse
  66. } bind def
  67.                              
  68. /ld_knownget {      % <ldict> <key> ld_known false | <any> true
  69.   dup 3 1 roll -15 bitshift  % key <<>> key<<15
  70.   2 copy known {
  71.     get exch .knownget
  72.   } {
  73.     pop pop pop //false
  74.   } ifelse
  75. } bind def
  76.  
  77. /ld_def {           % <key> <any> ld_def -
  78.   currentdict 3 1 roll ld_put
  79. } bind def
  80.  
  81. /ld_forall {        % <ldict> <proc} ld_forall -
  82.   { forall exch pop } aload pop
  83.   4 2 roll 4 packedarray cvx forall
  84. } bind def
  85.  
  86. /ld_clone {         % <ldict> ld_clone <ldict copy>
  87.   << exch { dup length dict copy } forall >>
  88. } bind def
  89.  
  90. % ================ Object mapping ================ %
  91.  
  92. % Initialize the object number and location map.
  93. /omapinit {        % - omapinit -
  94.   /RMap 100 ld_dict def
  95.   /XRef 100 ld_dict def
  96.   PDFWRDEBUG { (omapinit) = } if
  97. } bind def
  98.  
  99. % Map an object number.
  100. /omapnew {        % <oldobj#> omap <newobj#> <isnew>
  101.   RMap 1 index ld_knownget {
  102.     exch pop //false
  103.   } {
  104.     PDFWRDEBUG { (omap\() print dup =only } if
  105.     RMap dup ld_length 1 add   % old# <<>> len+1
  106.     2 index exch dup           % old# <<>> old# len+1 len+1
  107.     5 1 roll                   % len+1 old# <<>> old# len+1
  108.     ld_put pop //true          % len+1 true
  109.     PDFWRDEBUG { (\) = ) print 1 index = } if
  110.   } ifelse
  111. } bind def
  112. /omap {            % <oldobj#> omap <newobj#>
  113.   omapnew pop
  114. } bind def
  115.  
  116. % Save and restore the object map.
  117. % Note that currentomap either returns a copy or calls omapinit.
  118. /currentomap {        % <copy> currentomap <omap>
  119.   {
  120.     [RMap ld_clone XRef ld_clone]
  121.   } {
  122.     [RMap XRef] omapinit
  123.   } ifelse
  124. } bind def
  125. /setomap {        % <omap> setomap -
  126.   aload pop /XRef exch def /RMap exch def
  127.   PDFWRDEBUG {
  128.     (setomap: #Xref = ) print XRef ld_length =only
  129.     (, #RMap = ) print RMap ld_length =
  130.   } if
  131. } bind def
  132.  
  133. % ================ Writing ================ %
  134.  
  135. % ---------------- Low-level output ---------------- %
  136.  
  137. % Write a string on the output file.
  138. /ows {            % <string> ows -
  139.   OFile exch writestring
  140. } bind def
  141.  
  142. % ---------------- Scalars ---------------- %
  143.  
  144. % Note that the '#' character isn't legal in a name unless it is a prefix
  145. % for a hex encoded character (for PDF 1.2 and later). The following assumes
  146. % that the names are already valid PDF 1.2+ names so that  we can treat the
  147. % '#' as a legal character. The next two hex characters are already in the
  148. % set of valid name characters. PDF 1.1 and earlier allowed spaces in names
  149. % which probably wouldn't make it past the tokenizer anyway.
  150. /pdfnamechars
  151.   (!"#$&'*+,-.0123456789:;=?@ABCDEFGHIJKLMNOPQRSTUVWXYZ\\^_`abcdefghijklmnopqrstuvwxyz|~)
  152. readonly def
  153. /pdfwritename {        % <name> pdfwritename -
  154.   (/) ows .namestring {
  155.     ( ) dup 0 4 -1 roll put
  156.     //pdfnamechars 1 index search {
  157.       pop pop pop
  158.     } {
  159.       pop 0 get 256 add 16 =string cvrs
  160.       dup 0 (#) 0 get put
  161.     } ifelse ows
  162.   } forall
  163. } bind def
  164.  
  165. % ---------------- Composite objects ---------------- %
  166.  
  167. /pdfwriteprocs mark
  168.   /resolveR { pdfwriteref }
  169.   /O { pdfwritenewref }
  170. .dicttomark readonly def
  171. /pdfwritearray {    % <array> pdfwritearray -
  172.   dup xcheck {
  173.     aload pop //pdfwriteprocs exch get exec
  174.   } {
  175.     % Because of a bug in Acrobat's parser for linearization parameters,
  176.     % we have to include some whitespace after the opening [ (!).
  177.     ([ ) ows { pdfwritevalue (\n) ows } forall (]) ows
  178.   } ifelse
  179. } bind def
  180.  
  181. /pdfwritedict {        % <dict> pdfwritedict -
  182.   dup xcheck {
  183.     pdfwritestream
  184.   } {
  185.     (<<) ows {
  186.       exch pdfwritevalue ( ) ows pdfwritevalue (\n) ows
  187.     } forall (>>) ows
  188.   } ifelse
  189. } bind def
  190.  
  191. % ---------------- References ---------------- %
  192.  
  193. /pdfwritenewref {    % <newobj#> pdfwritenewref -
  194.   OFile exch write=only ( 0 R) ows
  195. } bind def
  196.  
  197. /pdfwriteref {        % <obj#> <gen#> pdfwriteref -
  198.   1 index omapnew {
  199.     ToWrite dup length 5 -2 roll 2 packedarray put
  200.   } {
  201.     exch pop exch pop
  202.   } ifelse
  203.   pdfwritenewref
  204. } bind def
  205.  
  206. /pdfcopystring 200 string def
  207. /pdfwritestream {    % <streamdict> pdfwritestream -
  208.     % Remove File, FilePosition, and StreamKey;
  209.     % optimize by replacing an indirect Length.
  210.   dup dup length dict copy
  211.     % Stack: origdict dict
  212.   dup /File undef dup /FilePosition undef dup /StreamKey undef
  213.   dup /Length get dup oforce ne {
  214.     dup /Length 2 copy oget put
  215.   } if
  216.   exch dup /File get dup 3 -1 roll /FilePosition get setfileposition
  217.   pdfcopystream
  218. } bind def
  219.  
  220. % We put copying the stream contents in separate procedures so that we
  221. % can replace this function if desired.
  222. /pdfcopybytes {        % <fromfile> <tofile> <length> pdfcopybytes -
  223.   {
  224.     dup 0 eq { exit } if
  225.     //pdfcopystring 0 2 index 2 index length .min getinterval
  226.     3 index exch readstring 3 1 roll
  227.     3 index 1 index writestring length sub exch not { exit } if
  228.   } loop pop pop pop
  229. } bind def
  230. /pdfcopystream {    % <newstreamdict> <file> pdfcopystream -
  231.             %   (file has been positioned)
  232.   1 index pdfwritevalue (stream\n) ows
  233.   exch /Length get OFile exch pdfcopybytes
  234.   (endstream) ows
  235. } bind def
  236.  
  237. % ---------------- General values/objects ---------------- %
  238.  
  239. /pdfwritetypes mark
  240.     % Scalars
  241.   /nulltype { pop (null) ows } bind
  242.   /integertype { =string cvs ows } bind
  243.   /booleantype 1 index
  244.   /realtype { OFile exch write===only } bind
  245.   /stringtype 1 index
  246.   /nametype { pdfwritename } bind
  247.     % Composite/reference objects
  248.   /arraytype { pdfwritearray } bind
  249.   /packedarraytype 1 index
  250.   /dicttype { pdfwritedict } bind
  251. .dicttomark readonly def
  252.  
  253. /pdfwritevalue {    % <obj> pdfwritevalue -
  254.   PDFWRDEBUG { (****Writing: ) print dup === flush } if
  255.   //pdfwritetypes 1 index type get exec
  256. } bind def
  257.  
  258. % We make pdfwriteobjdef a separate procedure for external use.
  259. /pdfwriteobjheader {    % <newobj#> pdfwriteobjheader -
  260.   XRef 1 index OFile .fileposition ld_put
  261.   PDFWRDEBUG { (XRef\() print dup =only (\) = ) print XRef 1 index ld_get = } if
  262.   OFile exch write=only ( 0 obj\n) ows
  263. } bind def
  264. /pdfwriteobjdef {    % <newobj#> <value> pdfwriteobjdef -
  265.   exch pdfwriteobjheader
  266.   pdfwritevalue (\nendobj\n) ows
  267. } bind def
  268. /pdfwriteobj {        % <obj#> <gen#> pdfwriteobj -
  269.   1 index exch resolveR exch omap exch pdfwriteobjdef
  270. } bind def
  271.  
  272. % ---------------- File-level entities ---------------- %
  273.  
  274. % Write a PDF file header.
  275. % Free variables: OFile, PDFversion.
  276. /pdfwriteheader {    % - pdfwriteheader -
  277.   (%PDF-) ows OFile PDFversion write=
  278.   (%\347\363\317\323\n) ows
  279. } bind def
  280.  
  281. % Write a cross-reference table and trailer.
  282. /pdfwritexref {        % <firstobj#> <#objs> pdfwritexref -
  283.   (xref\n) ows
  284.   OFile 2 index write=only ( ) ows OFile 1 index write=
  285.   1 index add 1 sub 1 exch {
  286.     dup 0 eq {
  287.       pop (0000000000 65535 f \n) ows
  288.     } {
  289.       XRef exch ld_get 1000000000 add =string cvs
  290.       dup 0 (0) 0 get put
  291.       ows ( 00000 n \n) ows
  292.     } ifelse
  293.   } for
  294. } bind def
  295. /pdfwritetrailer {    % <trailer> pdfwritetrailer -
  296.   (trailer\n) ows pdfwritevalue (\n) ows
  297. } bind def
  298. /pdfwritestartxref {    % <startpos> pdfwritestartxref -
  299.   (startxref\n) ows OFile exch write=
  300.   (%%EOF\n) ows
  301. } bind def
  302.  
  303. % ================ Top-level control ================ %
  304.  
  305. /pdfwrite {        % <file> <trailer> pdfwrite -
  306.   10 dict begin
  307.   /trailer exch def
  308.   /OFile exch def
  309.   /ToWrite 100 dict def
  310.   omapinit
  311.  
  312.     % Write the PDF file header.
  313.  
  314.   pdfwriteheader
  315.  
  316.     % Write the objects.
  317.  
  318.   trailer {
  319.     exch pop dup xcheck {    % The only executable objects are references.
  320.       aload pop pop pdfwriteobj
  321.     } {
  322.       pop
  323.     } ifelse
  324.   } forall
  325.     % Walk the object graph.
  326.   {
  327.     ToWrite dup length dup 0 eq { pop pop exit } if
  328.     1 sub 2 copy get 3 1 roll undef aload pop pdfwriteobj
  329.   } loop
  330.  
  331.     % Write the xref table and trailer.
  332.  
  333.   /xref OFile fileposition def
  334.   0 XRef ld_length 1 add pdfwritexref
  335.   trailer dup length 1 add dict copy
  336.   dup /Size XRef ld_length 1 add put pdfwritetrailer
  337.   xref pdfwritestartxref
  338.  
  339.   end
  340. } bind def
  341.  
  342. .setglobal
  343.