Skip to main content
Skip table of contents

Example montage control job


This page applies to Harlequin v13.1r0 and later; both Harlequin Core and Harlequin MultiRIP.

This example control job for a montage starts by defining a data structure to represent all the jobs in the montage together with the information required to position them on the media, and then proceeds to iterate over the array processing each job in turn.

The information about the jobs is stored in an array called jobs. This is an array of dictionaries, one for each job in the montage. The entries in these dictionaries are as follows:

  • jobname

A string giving the filename for the job on the RIP filing system.

  • pages

An array of dictionaries giving information about the placement of pages on the output page—see below.

It is expected that other entries giving other information about the jobs, such as screening requirements, would also appear in this dictionary.

The dictionaries in the pages array each contain the following entries:

  • position

A dictionary containing four numeric values called x , y , width, and height. These give the bounding box relative to the medium coordinate system of the position where the page is to be placed. The co-ordinates are subject to scaling and rotation of the job.

  • rotation

A numeric value giving a rotation in degrees to be applied to the page after it has been placed in position. This is optional, and defaults to zero. In the example given, non-multiples of 90 degrees may interact strangely.

  • pageoffset

Two numeric values, x and y, giving the relationship between the user coordinate system in the job and the bounding box given by the position entry. Optional, default to zeros.

  • scalefactor

Two numeric values, x and y, giving the scale factors in the x and y directions to be applied to the job after it has been placed in position. They are optional and default to 1.

(We could have decided to use arrays rather than dictionaries for the entries in the pages array. This is a matter of taste). The jobs array is stored in a dictionary, HLOdict, which must be in global VM.

The information included in these arrays and dictionaries would most likely be derived by looking at the comments in the job using a pre-processor.

Example definitions for this array follow:

First, an example where one multi-page job is placed four pages per output page, each page half-size and rotated 90 degrees. Because our example control job repeats itself so long as there are more pages, it does not matter how many pages are in the job.

First example montage


TEXT
HLOdict /jobs [
  <<
    /jobname (JOBS/thejob.ps)
    /pages [
      <<
        /position << /x 100 /y 100 /width 400 /height 500 >>
        /rotation 90
        /pageoffset << /x 0 /y 20 >>
        /scalefactor << /x 0.5 /y 0.5 >>
      >>
      <<
        /position << /x 600 /y 100 /width 400 /height 500 >>
        /rotation 90
        /pageoffset << /x 0 /y 20 >>
        /scalefactor << /x 0.5 /y 0.5 >>
      >>
      <<
        /position << /x 100 /y 700 /width 400 /height 500 >>
        /rotation 90
        /pageoffset << /x 0 /y 20 >>
        /scalefactor << /x 0.5 /y 0.5 >
      >>
      <<
        /position << /x 600 /y 700 /width 400 /height 500 >>
        /rotation 90
        /pageoffset << /x 0 /y 20 >>
        /scalefactor << /x 0.5 /y 0.5 >>
      >>
    ]
  >>
] put

The next definition puts two jobs side by side on the film; the first has two pages. Note that the origin of B1 is displaced by 20 points. This would be likely to have arisen from seeing a comment such as:

TEXT
%%BoundingBox: 20 20 220 620            

Second example montage


TEXT
          HLOdict /jobs [
            <<
              /jobname (JOBS/A.ps)
              /pages [
                <<
                  /position << /x 100 /y 100 /width 300 /height 300 >>
                >>
                <<
                  /position << /x 100 /y 400 /width 300 /height 300 >>
                >>
              ]
            >>
            <<
              /jobname (JOBS/B.ps)
              /pages [
                <<
                  /position << /x 450 /y 100 /width 200 /height 600 >>
                  /pageoffset << /x 20 >>
                >>
              ]
            >>
          ] put

In order to place pages on films, the example control job goes through the arrays of jobs and positions in order, initializing the graphics state appropriately before each new page begins, using BeginPage and EndPage as before.

TEXT
      % Initialization at start of control job:
      HLOdict begin
        /currentjob 0 def
        /currentpage 0 def
        /showpage-seen false def
      end

      <<
        /BeginPage {
          //HLOdict begin
            jobs currentjob get begin
              pages currentpage get begin
                position begin
                  % translate to centre of bounding box
                  width 2 div x add height 2 div y add translate
                end % position
                currentdict /scalefactor known {
                  1.0
                  scalefactor /x known { pop scalefactor /x get } if
                  1.0
                  scalefactor /y known { pop scalefactor /y get } if
                  scale
                } if
                currentdict /rotation known {
                  rotation rotate
                } if
                position begin
                  % translate to correct position
                  width 2 div neg height 2 div neg translate
                  0 0 width height rectclip
                end % position
                currentdict /pageoffset known {
                  0 pageoffset /x known { pop pageoffset /x get } if
                  0 pageoffset /y known { pop pageoffset /y get } if
                  translate
                } if
              end % current page
            end % current job
          end % HLOdict
        } bind % BeginPage

        /EndPage {
          pop pop % discard arguments
          currentglobal dup not { true setglobal } if
          //HLOdict /showpage-seen true put % See EPSF handler below
          % See whether a film is complete yet
          //HLOdict /jobs get //HLOdict /currentjob get get begin
            //HLOdict begin
              % Any more page positions specified in current job?
              /currentpage currentpage 1 add def currentpage pages length ge {
                /currentpage 0 def % no more pages
              } if
            end % HLOdict
          end % current job
          //HLOdict /currentpage get 0 ne {
            % another page position specified in current job false % film not complete yet
          } {
            % is there another job?
            //HLOdict begin
              currentjob 1 add jobs length lt {
                % yes, another job
                /currentjob currentjob 1 add def
                false % film not complete yet
              } {
                % Job page positions exhausted film is finished
                % montage will restart next time round.
                true % expose the film
              } ifelse
            end % HLOdict
          } ifelse
          exch % global state
          not { false setglobal } if
        } bind %EndPage
 
        /Imposition true
        /Override 1 % make sure the job does not interfere with the layout
      >> setpagedevice

The control job then executes each job file in turn. It is important to encapsulate each job using save and restore, to clean up the operand and dictionary stacks after the job, and to reset the streams used by each job using the statusdict operator setstdio. (This is because of a deficiency of some PostScript-language jobs; for details see Files, filters, and devices.)

In order to run jobs that do not call showpage (such as some EPS files), a Boolean variable called showpage-seen is used in this example. The control job sets it to false before each job and tests it afterwards. (For jobs run in the normal server loop environment, the system parameter AutoShowpage can be used to have this happen automatically, though that produces a page only if there is something on it.)

TEXT
/SaveDict 1 dict def % in local VM

/runjobs {
  //HLOdict /jobs get length {
    //HLOdict /showpage-seen false put
    //HLOdict begin
      jobs currentjob get /jobname get
    end
    //SaveDict /Save save put % encapsulate the job
      (r) file
      dup (%stdout%)(w) file statusdict /setstdio get exec
      cvx exec % equivalent to ‘run’, execute the job
      //HLOdict /showpage-seen get not { showpage } if
      clear cleardictstack % clean up after it
    //SaveDict /Save get restore
  } repeat
} bind def

currentdict /SaveDict undef
currentdict /HLOdict undef
currentdict /runjobs get
currentdict /runjobs undef
exec % runjobs



JavaScript errors detected

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

If this problem persists, please contact our support.