Why setstdio is needed
This page applies to Harlequin v13.1r0 and later; both Harlequin Core and Harlequin MultiRIP.
Why not use %terminal%
directly? There are three reasons:
- The
print
operator, and procedures which use it (such as ==), direct their output to%stdout%
by definition;setstdio
allows this output to be re-routed. - Predefined fragments of the PostScript language and some built-in operators automatically use
%stdin%
,%stdout%
, and%stderr%
as their input and output channels. For example, the executive always reads from standard input, and the default error handlers (which you could of course redefine—but so could an application) write their messages to%stdout%
using theprint
operator. - The Apple LaserWriter and other simple printers read their PostScript-language jobs from
%stdin%
—indeed this may be the only input “device” such a printer knows about. Unfortunately, some PostScript-language producing applications make assumptions that rely on this behavior.
In the last case, an application might write, for example:
/infile (%stdin%) (r) file def
/str 512 string def
...
{ infile str readstring pop } image
... image data ...
when it should correctly (and more simply) write1 :
/str 512 string def
...
{ currentfile str readstring pop } image
... image data ...
Therefore, unless you are certain that the PostScript language to be executed does not make this mistake, you should not write:
(%disk0%image.ps) run
Instead, write something like this:
(%disk0%image.ps) (r) file dup (%console%) (w) file
statusdict /setstdio get exec cvx exec % the input file
Recall that run
is simply a shortcut for (r) file cvx exec
. If the stream of PostScript being executed to do this is not part of a procedure, you may need a save
and restore
to reinstate the previous associations of %stdin%
and %stdout%
to continue executing your PostScript when the file is complete.
1. It is not relevant to the point being made, but for greater efficiency (which is often very important when processing images) the line with the procedure is better written:
{ currentfile //str readstring pop } bind image
or better still, use currentfile
as a direct DataSource
in the Level 2 dictionary form of the image
operator. The examples are, however, typical of actual applications.
So defineresource
for an externally defined filter looks like this:
filtername dict
/Filter defineresource
where filtername is a name object identifying the filter type, and dict is a dictionary containing keys that identify the implementation of the filter, as described below; defineresource
returns filtername as its result in this case.
Where the filter is coded in a plugin, the filtername must correspond to the name of the channel class which implements the filter. Core-RIP implementations can use any name. To override a built-in filter, the name must be that of the built-in filter, which means that the channel class name must also have this name as listed in Table 3.6 in [RB2]. In other cases, we recommend using your OEM name or number as part of the filter name to ensure uniqueness.