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
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:
%%BoundingBox: 20 20 220 620
Second example montage
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.
% 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.)
/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