Skip to main content
Skip table of contents

(v13) Extended example: packing a film

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

This example takes the approach of fixing an output page size, and putting as many input pages onto it as will fit. To do this it records the page size requested by the job (if any), but then overrides it on each occasion with the actual page size. The example catches the page size requested by the job. This example could easily be extended to produce a sheet of thumbnails with suitable scaling set up for each page in the BeginPage procedure.

Packing a film

First we set up a global dictionary to store the state. This must be global because when the position of the next page is calculated in EndPage and stored here, it is often in a save / restore (as in the section above, for example).

TEXT
            currentglobal true setglobal
            userdict /SW-Page-Imposition 32 dict put setglobal
            SW-Page-Imposition begin % for temporary variables statusdict /mediasize get exec % width height
            % 0 media size means unrestricted, so use page size instead dup 0 eq { pop currentpagedevice /PageSize get 1 get } if
            /MediaHeight exch def
            dup 0 eq { pop currentpagedevice /PageSize get 0 get } if
            /MediaWidth exch def
            % default the input page size to letter (8.5 x 11 inches)
            /PageWidth 8.5 72 mul def
            /PageHeight 11 72 mul def
            /LookingForPageSize 1 def
            /CurrentX 0 def
            /CurrentY 0 def
            /PageDeactivation 2 def
            /PageX 0 def /PageY 0 def

Now set up comment parsing procedures to catch a page size from the BoundingBox or PageBoundingBox comments. Note that this example does not take account of constructions such as %%PageBoundingBox: (at end) and that BoundingBox may have question marks rather than numbers after it, as in %%BoundingBox: ? ? ? ? . See (v13) Comment parsing for details of the comment parsing mechanism.

TEXT
            (%%dict) load begin (%%actions) load begin
            /BoundingBox: { % (x1 y1 x2 y2)
                //SW-Page-Imposition begin LookingForPageSize 1 le {
                    dup (?) search { pop pop pop pop
                  }{
                    pop
                    cvx exec
                      index sub exch
                      index sub exch
                    << /PageSize [5 -2 roll] >> setpagedevice
                    /PageY exch def
                    /PageX exch def
                  } ifelse
              } if end
            } bind def
            /PageBoundingBox: { % (x1 y1 x2 y2)
                //SW-Page-Imposition begin LookingForPageSize 1 le {
                  cvx exec
                      index sub exch
                      index sub exch
                    << /PageSize [5 -2 roll] >> setpagedevice
                    /PageY exch def
                    /PageX exch def
              } if end
            } bind def end end

Now we set up the page device. The SensePageDevice procedure catches page sizes set up by calls to setpagedevice (and therefore setpage and setpageparams ). SensePageDevice is a RIP extension to the page device (see (v13) Configuring the page device).

TEXT
            <<
            /Imposition true
            /SensePageDevice [
              currentpagedevice /SensePageDevice get /exec load
              1 index null eq { pop pop } if
              {
                  //SW-Page-Imposition begin currentpagedevice /PageSize get aload pop
                  2 copy MediaHeight ne exch MediaWidth ne and {
                    /PageHeight exch def
                    /PageWidth exch def
                    /PageX 0 def /PageY 0 def
                    /LookingForPageSize LookingForPageSize 1 add def
                    /PageSize [MediaWidth MediaHeight]
                } {pop pop} ifelse end
              } bind /exec load
            ] cvx

The BeginPage procedure in this example is quite simple: it just translates the page to its position on the output, and clips to its size. It works from the top down, hence the subtraction from MediaHeight less PageHeight . On the first page of each activation of the page device, the offsets are reset to zero to avoid extra blank pages being produced.

TEXT
            /BeginPage {
              //SW-Page-Imposition begin
                0 eq {
                  /CurrentX 0 def /CurrentY 0 def
                } if
                CurrentX PageX sub
                  MediaHeight PageHeight sub CurrentY PageY sub sub translate
              PageX neg PageY neg PageWidth PageHeight rectclip end
            } bind

The EndPage procedure does most of the hard work here. In the normal case it increments the offset in x by the width of each input page until it would go off the right hand edge, at which point it resets to the left margin and increments in the y direction. When the page goes off the top (or actually off the bottom, since BeginPage is inverting it), we reset to the origin and print the page by returning true.

On deactivation, we deliver a page if we are not at the origin: that is, if we have not just reset to the origin at the end of the previous page, which would imply that nothing had been done to the page yet.

TEXT
              /EndPage { % showpagecount code -> bool exch pop
              //SW-Page-Imposition begin
                //PageDeactivation eq {
                  CurrentX 0 ne CurrentY 0 ne or
                }{
                  /CurrentX CurrentX PageWidth add def CurrentX PageWidth add MediaWidth gt dup {
                    pop
                    /CurrentY CurrentY PageHeight add def
                    /CurrentX 0 def
                    CurrentY PageHeight add MediaHeight gt dup {
                      /CurrentY 0 def if
                    if
              } ifelse end
            } bind
            >> setpagedevice
            end % SW-Page-Imposition
            userdict /SW-Page-Imposition undef % for neatness’ sake
JavaScript errors detected

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

If this problem persists, please contact our support.