home *** CD-ROM | disk | FTP | other *** search
/ swCHIP 1991 January / swCHIP_95-1.bin / utility / gs333ini / gs3.33 / gs_setpd.ps < prev    next >
Text File  |  1995-12-09  |  11KB  |  325 lines

  1. %    Copyright (C) 1994, 1995 Aladdin Enterprises.  All rights reserved.
  2. % This file is part of Aladdin Ghostscript.
  3. % Aladdin Ghostscript is distributed with NO WARRANTY OF ANY KIND.  No author
  4. % or distributor accepts any responsibility for the consequences of using it,
  5. % or for whether it serves any particular purpose or works at all, unless he
  6. % or she says so in writing.  Refer to the Aladdin Ghostscript Free Public
  7. % License (the "License") for full details.
  8. % Every copy of Aladdin Ghostscript must include a copy of the License,
  9. % normally in a plain ASCII text file named PUBLIC.  The License grants you
  10. % the right to copy, modify and redistribute Aladdin Ghostscript, but only
  11. % under certain conditions described in the License.  Among other things, the
  12. % License requires that the copyright notice and this notice be preserved on
  13. % all copies.
  14.  
  15. % The current implementation of setpagedevice has the following problems:
  16. %    - It doesn't save the CTM after the Install procedure as the
  17. % one for initmatrix or defaultmatrix.
  18. %    - It doesn't interact properly with gsave/grestore.
  19. %    - It doesn't do the automatic 90 degree rotation if the PageSize
  20. % dimensions need to be swapped.
  21. %    - It doesn't handle Policy values other than 1 or non-1.
  22.  
  23. languagelevel 1 .setlanguagelevel
  24. level2dict begin
  25.  
  26. % Define currentpagedevice so it creates the dictionary on demand if needed.
  27. % The only entry we add automatically is Policies.
  28. /currentpagedevice
  29.  { .currentpagedevice dup length 0 eq
  30.     { pop currentdevice null .getdeviceparams
  31.         % In case of duplicate keys, .dicttomark takes the entry
  32.         % lower on the stack, so we can just append the defaults here.
  33.       /Policies .defaultpolicies .dicttomark
  34.       dup .setpagedevice
  35.     }
  36.    if
  37.  } bind odef
  38.  
  39. % The implementation of setpagedevice is quite complex.  Currently,
  40. % everything but the media matching algorithm is implemented here.
  41.  
  42. % Define the parameters that require special action to merge into the
  43. % combined page device dictionary.  The procedures are called as follows:
  44. %    <merged> <key> <new_value> -proc- <merged> <key> <new_value'>
  45. /.mergespecial mark
  46.   /InputAttributes
  47.    { dup null eq
  48.       { pop null
  49.       }
  50.       { 3 copy pop .knownget
  51.      { dup null eq
  52.         { pop dup length dict }
  53.         { dup length 2 index length add dict copy }
  54.        ifelse
  55.      }
  56.      { dup length dict
  57.      }
  58.         ifelse copy readonly
  59.       }
  60.      ifelse
  61.    } bind
  62.   /OutputAttributes 1 index
  63.   /Policies
  64.     { 3 copy pop .knownget
  65.        { dup length 2 index length add dict copy }
  66.        { dup length dict }
  67.       ifelse copy readonly
  68.     } bind
  69. .dicttomark readonly def
  70.  
  71. % Define the keys used in input attribute matching.
  72. /.inputattrkeys [
  73.   /PageSize /MediaColor /MediaWeight /MediaType /InsertSheet
  74. ] readonly def
  75.  
  76. % Define the keys used in output attribute matching.
  77. /.outputattrkeys [
  78.   /OutputType
  79. ] readonly def
  80.  
  81. % Define the parameters that should not be presented to the device.
  82. % The procedures are called as follows:
  83. %    <merged> <key> <value> -proc-
  84. % The procedure leaves all its operands on the stack and returns
  85. % true iff the key/value pair should be presented to .putdeviceparams.
  86. /.presentspecial mark
  87.   /Name false
  88.   /OutputDevice false
  89.   /InputAttributes false
  90.   .inputattrkeys { pop { 2 index /InputAttributes get null eq } } forall
  91.   /OutputAttributes false
  92.   .outputattrkeys { pop { 2 index /OutputAttributes get null eq } } forall
  93.   /Install false
  94.   /BeginPage false
  95.   /EndPage false
  96.   /Policies false
  97. .dicttomark readonly def
  98.  
  99. % Define the required attributes of all page devices, and their default values.
  100. % We don't include attributes such as PageSize, which all devices
  101. % are guaranteed to supply on their own.
  102. /.defaultpolicies mark
  103.   /PolicyNotFound 1
  104.   /PageSize 0
  105.   /PolicyReport {pop} bind
  106. .dicttomark readonly def
  107. /.requiredattrs mark
  108.   /InputAttributes mark 0 0 dict .dicttomark
  109.   /OutputAttributes mark 0 0 dict .dicttomark
  110.   /Install {.callinstall} bind
  111.   /BeginPage {.callbeginpage} bind
  112.   /EndPage {.callendpage} bind
  113.   /Policies .defaultpolicies
  114. .dicttomark readonly def
  115.  
  116. % Define access to device defaults.
  117. /.defaultdevicename 0 .getdevice .devicename def
  118. /.defaultdeviceparams
  119.  { finddevice null .getdeviceparams
  120.  } bind def
  121.  
  122. % Select media (input or output).  The hard work is done in an operator:
  123. %    <pagedict> <attrdict> <keys> .matchmedia <key> true
  124. %    <pagedict> <attrdict> <keys> .matchmedia false
  125. %    <pagedict> null <keys> .matchmedia null true
  126. /.selectmedia        % <orig> <request> <merged> <failed>
  127.             %   (these are retained)
  128.             %   <attrdict> <attrkeys> <mediakey> .selectmedia
  129.  { 4 index 4 -1 roll 3 index .matchmedia
  130.     { 4 index 3 1 roll put pop
  131.     }
  132.     {    % Adobe's implementations have a "big hairy heuristic"
  133.     % to choose the set of keys to report as having failed the match.
  134.     % For the moment, we report any keys that are in the request
  135.     % and don't have the same value as in the original dictionary.
  136.       3 index exch undef
  137.        {    % Stack: <orig> <request> <merged> <failed> <attrkey>
  138.      3 index 1 index .knownget
  139.       { 5 index 2 index .knownget { ne } { pop true } ifelse }
  140.       { true }
  141.      ifelse        % Stack: ... <failed> <attrkey> <report>
  142.       { 2 copy /rangecheck put }
  143.      if pop
  144.        }
  145.       forall
  146.     }
  147.    ifelse
  148.  } bind def
  149.  
  150. % Apply Policies to any unprocessed failed requests.
  151. % As we process each request entry, we replace the error name
  152. % in the <failed> dictionary with the policy value,
  153. % and we remove the key from the <merged> dictionary.
  154. /.applypolicies        % <merged> <failed> .applypolicies <merged'> <failed'>
  155.  { 1 index /Policies get 1 index
  156.     { type /integertype eq
  157.        { pop        % already processed
  158.        }
  159.        { 2 copy .knownget not { 1 index /PolicyNotFound get } if
  160.             % Stack: <merged> <failed> <Policies> <key> <policy>
  161.      dup 1 ne
  162.       {    % Set errorinfo and signal a configurationerror.
  163.         % Note that we currently treat all Policy values other than 1
  164.         % the same as 0.
  165.         pop dup 4 index exch get 2 array astore
  166.         $error /errorinfo 3 -1 roll put
  167.         cleartomark
  168.         /setpagedevice load /configurationerror signalerror
  169.       }
  170.       {    % Ignore the failed request.
  171.         3 index 2 index 3 -1 roll put
  172.         3 index exch undef
  173.       }
  174.      ifelse
  175.        }
  176.       ifelse
  177.     }
  178.    forall pop
  179.  } bind def
  180.  
  181. % Try setting the device parameters from the merged request.
  182. /.trysetparams        % ... <merged> <(ignored)> <device> <Policies>
  183.             %   .trysetparams
  184.  { true mark 5 index dup
  185.     {            % Stack: <merged> <key> <value>
  186.       .presentspecial 2 index .knownget
  187.        { exec { 3 -1 roll } { pop pop } ifelse }
  188.        { 3 -1 roll }
  189.       ifelse
  190.     }
  191.    forall pop
  192. DEBUG { (Putting.\n) print pstack flush } if
  193.    .putdeviceparams
  194. DEBUG { (Result of putting.\n) print pstack flush } if
  195.  } bind def
  196.  
  197. % Finally, define setpagedevice.
  198. /setpagedevice
  199.  {
  200.    mark exch currentpagedevice
  201.  
  202.         % Check whether we are changing OutputDevice;
  203.         % also handle the case where the current device
  204.         % is not a page device.
  205.         % Stack: mark <request> <current>
  206. DEBUG { (Checking.\n) print pstack flush } if
  207.  
  208.    dup /OutputDevice .knownget
  209.     {        % Current device is a page device.
  210.       2 index /OutputDevice .knownget
  211.        {    % A specific OutputDevice was requested.
  212.      2 copy eq
  213.       { pop pop null }
  214.       { exch pop }
  215.      ifelse
  216.        }
  217.        { pop null
  218.        }
  219.       ifelse
  220.     }
  221.     {        % Current device is not a page device.
  222.         % Use the default device.
  223.       1 index /OutputDevice .knownget not { .defaultdevicename } if
  224.     }
  225.    ifelse
  226.    dup null eq
  227.     { pop
  228.     }
  229.     { exch pop .defaultdeviceparams
  230.         % In case of duplicate keys, .dicttomark takes the entry
  231.         % lower on the stack, so we can just append the defaults here.
  232.       .requiredattrs { } forall .dicttomark
  233.     }
  234.    ifelse
  235.  
  236.         % Merge the current and requested dictionaries.
  237.         % Stack: mark <request> <orig>
  238. DEBUG { (Merging.\n) print pstack flush } if
  239.  
  240.    exch 1 index dup length 2 index length add dict copy
  241.    dup 2 index
  242.     {        % stack: <orig> <request> <merged> <merged> <rkey> <rvalue>
  243.       .mergespecial 2 index .knownget { exec } if
  244.       put dup
  245.     }
  246.    forall pop
  247.  
  248.         % Select input and output media.
  249.         % Stack: mark <orig> <request> <merged>
  250. DEBUG { (Selecting.\n) print pstack flush } if
  251.  
  252.    0 dict    % <failed>
  253.    1 index /InputAttributes .knownget
  254.     { .inputattrkeys (%MediaSource) cvn .selectmedia } if
  255.    1 index /OutputAttributes .knownget
  256.     { .outputattrkeys (%MediaDestination) cvn .selectmedia } if
  257.    .applypolicies
  258.  
  259.         % Construct the new device, and attempt to set its attributes.
  260.         % Stack: mark <orig> <request> <merged> <failed>
  261. DEBUG { (Constructing.\n) print pstack flush } if
  262.  
  263.    currentdevice .devicename 2 index /OutputDevice get eq
  264.     { currentdevice }
  265.     { 1 index /OutputDevice get finddevice }
  266.    ifelse
  267.         %**************** We should copy the device here,
  268.         %**************** but since we can't close the old device,
  269.         %**************** we don't.  This is WRONG.
  270.     %****************copydevice
  271.    2 index /Policies get
  272.    .trysetparams
  273.    dup type /nametype eq
  274.     {        % The request failed.
  275.         % Stack: ... <failed> <device> <Policies> true mark
  276.         %   <name> <errorname> ...
  277.       counttomark 5 add -1 roll
  278.       counttomark 2 idiv { dup 4 -2 roll put } repeat
  279.       exch pop 4 1 roll pop
  280.         % Stack: mark ... <merged> <failed> <device> <Policies>
  281.       4 2 roll .applypolicies 4 -2 roll
  282.       .trysetparams        % shouldn't fail!
  283.       dup type /booleantype ne
  284.        { 2 { counttomark 1 add 1 roll cleartomark } repeat
  285.          /setpagedevice load exch signalerror
  286.        }
  287.       if
  288.     }
  289.    if
  290.  
  291.         % The attempt succeeded.  Install the new device.
  292.         % Stack: mark ... <merged> <failed> <device> <eraseflag>
  293. DEBUG { (Installing.\n) print pstack flush } if
  294.  
  295.    pop 2 .endpage
  296.     { 1 true .outputpage
  297.       (>>setpagedevice, press <return> to continue<<\n) .confirm
  298.     }
  299.    if
  300.    .setdevice pop
  301.    1 index /Install .knownget { exec } if
  302.    erasepage initgraphics
  303.    1 index .setpagedevice .beginpage
  304.  
  305.         % Clean up, calling PolicyReport if needed.
  306.         % Stack: mark ... <merged> <failed>
  307. DEBUG { (Finishing.\n) print pstack flush } if
  308.  
  309.    dup length 0 ne
  310.     { 1 index /Policies get /PolicyReport get
  311.       counttomark 1 add 2 roll cleartomark
  312.       exec
  313.     }
  314.     { cleartomark
  315.     }
  316.    ifelse
  317.  
  318.  } odef
  319.  
  320. end                % level2dict
  321. .setlanguagelevel
  322.