Skip to main content
Skip table of contents

(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


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 form

    0 <<...>> 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 parameter PaperTray that contains a string similar to the %papertray% example above. Note the cvx 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.

JavaScript errors detected

Please note, these errors can depend on your browser setup.

If this problem persists, please contact our support.