(v13) SensePageDevice procedures
To view v13.x documentation, go to the top level of the legacy documentation.
This page applies to Harlequin v14.0r0 and later; and to Harlequin Core and Harlequin MultiRIP.
SensePageDevice
, an entry in the page device, is a RIP extension that takes a procedure as its value. The procedure is called just after the merge operation between the setpagedevice
operand dictionary and the current page device dictionary has been carried out, but before the media-matching algorithm is run.
The operand dictionary of setpagedevice
can be regarded as a set of requests for facilities or settings of the page device. The request is matched against what is available (in the central page device dictionary) and permitted (by the Policies
entry). Some features, such as Duplex
, express capabilities of a printer that tend not to change, so you can add them with ExtraPageDeviceKeys
. However, paper trays and media cassettes can often be changed while the interpreter is running, so the InputAttributes
entry, for example, needs to be changed regularly. It is not appropriate for the job asking for a particular page size also to say what page sizes are available; it does not know.
Therefore, a general mechanism is provided to allow page device entries to be varied by external means. This is the SensePageDevice
procedure; it can be set up directly in the Sys/ExtraPageDeviceKeys
file, or in some other start-up file with a call to setpagedevice
, or in a page feature in GUI versions or a configuration file in command-line versions.
From v11.0r2, the behavior of the RIP when SensePageDevice
is called has changed. Previously, if there was an error within SensePageDevice
it would not be reported. From v11.0r2 errors are reported. The objects left on the stack by SensePageDevice
are now checked:
- If the check finds that the keys on the stack are not name objects, this results in:
Warning: Key left on the stack by /SensePageDevice is not of type nametype
- If the check finds that
SensePageDevice
leaves an odd number of objects on the stack, this results in:
Warning: Key left on the stack by /SensePageDevice is not of type nametype
and,
Warning: Odd number of objects left on the stack by /SensePageDevice
The SensePageDevice
procedure should leave on the operand stack an arbitrary number of key/value pairs (not a dictionary); these are then treated as further items to be merged with the page device, possibly overriding the operands to setpagedevice
.
This means that you can use SensePageDevice
for two purposes:
- To prevent certain page device keys from being changed, by resetting them inside the
SensePageDevice
procedure, or to check and reject page device keys; and
- In an appropriate environment, interrogate a printer to find out what its current state is, especially which paper trays or film cassettes are actually available, and modify
InputAttributes
appropriately.
The first of these is straightforward. Consider the example where it is required that ImagingBBox
is not acted on (this is allowed by [RB2]). It can simply be reset to null, whenever the caller of setpagedevice
tries to change it later on:
<<
/SensePageDevice { /ImagingBBox null }
>> setpagedevice
A more involved variant might select the nearest resolution from a fixed set (say 1200 and 2400 dpi in this example) providing it is within 100 dpi and otherwise reject it:
<<
/SensePageDevice {
% look at the resolution that has been set and compare
% with candidate resolutions. The initial zero will be
% replaced with the one we match, or left alone if no match
0 currentpagedevice /HWResolution get aload pop
{ 1200 2400 } {
% stack: 0 xres yres candidate
2 copy sub abs 100 le
% stack: 0 xres yres candidate ytestresult
1 index 4 index sub abs 100 le and {
4 1 roll pop exit
} if pop
} forall
pop pop % the current resolution
% 0 still there if we didn’t find a close enough
% resolution, which will cause a rangecheck later on
% (the caller of SensePageDevice checks for errors so
% we cannot deliberately provoke an error here)
% leave the new page device params on the operand stack:
% remember that HWResolution is always an array [ exch dup ] /HWResolution exch
} bind
>> setpagedevice
The SensePageDevice
call may also look elsewhere to determine the information it requires. It could look in a file, but more likely it communicates with an appropriate bit of C code via the device interface. Information about files and devices in PostScript is given in (v13) Files, filters, and devices. In the GUI version the C code is in a plugin; see [HQPLUGIN], Chapter 3 for programming details. In core-RIP implementations, it is a custom device: see the Harlequin Core SDK Developer's Guide for programming details.
You can obtain the information by:
- Reading from a file opened on a device (just like an operating system file)
- Running the file (in which case the plugin or device implementation would wrap up the parameters in a suitable PostScript-language string). For example, consider a device called
%papertray%
, which returns on the operand stack a string of the form0 <<...>> 1 <<...>> ...
when a file opened on it is executed.SensePageDevice
is then very simple:
<< /SensePageDevice { /InputAttributes << (%papertray%) run >> } >> setpagedevice
- Obtaining suitable device parameters from the device with
currentdevparams
. If the parameter is a string, it could contain the appropriate PostScript-language fragment so that it can be executed immediately. - Core-RIP implementations can also choose to introduce such a parameter on the
%pagebuffer%
device rather than invent a whole new device just for this purpose. For example, consider the device parameterPaperTray
that contains a string similar to the%papertray%
example above. Note thecvx
in the example: basic PostScript semantics mean that the string is simply pushed back on the stack if left as a literal:
<<
/SensePageDevice {
/InputAttributes <<
(%pagebuffer%) currentdevparams /PaperTray get cvx exec
>>
} bind
>> setpagedevice
OperatorActions
(see below) causes SensePageDevice
and media matching to be re-executed. You can use the procedure SensePageDeviceInit
to clean up changes from a previous call to setpagedevice
before the calculations in SensePageDevice
. SensePageDeviceInit
defaults to an empty procedure; it takes no items from the operand stack and adds none.