Skip to content

Bookbinders’ Fun

Vector 13:4, page 130

applications programming techniques

Transcribed from the printed issue; not yet reviewed. Read it in the PDF of the issue, page 130

Causeway’s NewLeaf is being used for highest quality PostScript™ printing. Most of business printing is just on single or multiple leaflets and gathered to bunches of A4-format reports when appropriate. Sometimes however we want to create a booklet of say 16 or more pages. Then we need to do one of the following:

  1. either take a post academic course in Algebraic Group theory,
  2. take a bookbinders course,
  3. or just fold an A4 sheet once if you want A5 as a result, or an A3 format twice, and so on, put page numbers in the right place on the pages, e.g. bottom right on each page, unfold and watch the picture.

We want to print in the obtained order on a duplex printer in such a way that every successive bunch of say 4 or 5 sheets forms a complete booklet ready for folding and stapling.

The whole process is being done in two major steps:

  1. Make detailed layout designs of each single page in the booklet, flow the text and send to spool.
  2. Make one layout page with two frames (in the case of A4 to A5) without borders to speak of and flow each previously page made by 1. into it by Fetching & Including.

Adrian has provided leaf.Fetch and leaf.Include for that purpose.

A book consists of sections, a booklet has one section and 2000 booklets have 2000 sections. For making a book the sheets are folded into sections, sections are gathered, milled and melted to a book block; the book block is cut at three sides and put in a cover. A booklet may just be stapled.

APL does it like this:

 ....
[9]   ⍝ How many sections does it have?
[10]   →(0≠⎕NC'sn')↑⎕LC+1 ⋄ sn←1
[11]  ⍝ How many pages does it have?
[12]   all←leaf.NumPages fi
[13]   ct←0 ⋄ Loop←sn⍴Begin
 ....

Now we need to fetch the pages for one booklet,

 ....
[15]  Begin:
[16]   np←⌊all÷sn
[17]  ⍝ Grab one booklet at a time into pre-set array
[18]   pages←(4×⌈0.25×np)⍴⊂''
[19]   pages[⍳np]←(⊂fi)leaf.Fetch¨(ct×np)+1+⍳np
[20]
[21]  ⍝ Round up to a multiple of 4 and count 2up
[22]   pg←⍳4×⌈0.25×np ⋄ np←0.5×⍴pg
 ....

Watch, the bookbinder’s fun is coming!!

 ....
[24]  ⍝ ... and reorder into facing sets
[25]   set1←⌽(np⍴0 1)/(np↑pg),[0.5](⌽(-np)↑pg)
[26]   set2←⊖⌽(np⍴1 0)/(np↑pg),[0.5](⌽(-np)↑pg)
 ....

set1 and set2 are just matrices with page numbers in the order we need and are used as indices for leaf.Including pages from the stack.

 ....
[31]        leaf.Include(set1[1;this])⊃pages
 ....

So, not just fun, but practical and very gratifying leaf.Include applications for ‘state of the art’ printing and binding jobs.

Exercise

Interesting for the bookbinder’s business, or just for fun, might be to generalize for layouts from A0, A1, …. to A4, A5, …., or to find the most efficient layout (publishers are thinking in thousandths of cents!) for a complex book - one of my first dreams when I learned APL.

Acknowledgements

Mid sixties I was involved in a large bookbinder’s progress control process: the Time Life series, tens of millions of books in seven languages, printed by Smeets Weert, Holland and bound and shipped by Proost & Brandt Amsterdam, Holland. Note that the bookbinder is responsible for the layout of the book.

I still have admiration for (the late) Mr Hangoor who designed the complex layouts for these books and from whom I learned the basic techniques.

Thanks, Adrian, for your ingeniously simple APL bookbinder’s trick in line [25] and line [26]!

Function listing

    ∇ r←(sn)Booklet fi;np;pages;this;pg;set1;set2;sink;ct;all
[1]   ⍝ Adrian's single booklet function
[2]   ⍝ ... adjusted for multiple by JK
[3]   ⍝ Multiple (jk) booklet production. Will take any NewLeaf report
[4]   ⍝ and reduce to 2-up facing pages, ordering in the
[5]   ⍝ correct sequence for double-sided duplex mode (jk) printing.
[6]   ⍝ <fi> can be a spooled file name or just PG from the WS.
[7]
[8]    leaf.ChOrient'l'      ⍝ check and force orientation
[9]   ⍝ How many sections does it have?  ⍝ (jk)
[10]   →(0≠⎕NC'sn')↑⎕LC+1 ⋄ sn←1
[11]  ⍝ How many pages does it have?
[12]   all←leaf.NumPages fi
[13]   ct←0 ⋄ Loop←sn⍴Begin              ⍝ (jk)
[14]
[15]  Begin:
[16]   np←⌊all÷sn
[17]  ⍝ Grab one booklet at a time into pre-set array
[18]   pages←(4×⌈0.25×np)⍴⊂''
[19]   pages[⍳np]←(⊂fi)leaf.Fetch¨(ct×np)+1+⍳np
[20]
[21]  ⍝ Round up to a multiple of 4 and count 2up
[22]   pg←⍳4×⌈0.25×np ⋄ np←0.5×⍴pg
[23]
[24]  ⍝ ... and reorder into facing sets
[25]   set1←⌽(np⍴0 1)/(np↑pg),[0.5](⌽(-np)↑pg)
[26]   set2←⊖⌽(np⍴1 0)/(np↑pg),[0.5](⌽(-np)↑pg)  ⍝ first ⌽ for duplex
[27]                                             ⍝ without for 2 runs
[28]  ⍝ Run all through the printer ...
[29]   ⍎'leaf.',(⊃(ct=0)↓'Switch' 'Use'),' nob.ebs.booklet'
[30]   :For this :In ⍳¯1↑⍴set1
[31]       leaf.Include(set1[1;this])⊃pages
[32]       leaf.Include(set1[2;this])⊃pages
[33]       leaf.Include(set2[1;this])⊃pages
[34]       leaf.Include(set2[2;this])⊃pages
[35]   :End
[36]   ct+←1 ⋄ →Loop↑1↓Loop
[37]
[38]   sink←leaf.Spool'run1'
[39]   r←'PostScrp.Print ''run1'''
    ∇