---lua ---imposition plan : Generic Booklet -- _fmt_ paper -- _fmt2_ --- ---It is said generic as it will try to determine ---automatically how to fit the booklet onto _fmt_ ---paper sheets, scaling pages if necessary. ---it is well suited for office documents for ---which you do not care too much about resulting ---imposition artefacts since it manages to save ---paper! --- -- print("Booklet") -- We output a booklet on _fmt_ paper -- _fmt2_ -- Interface notes ..... ---- Evidently PageCount, SourceWidth, and SourceHeight are ---- passed to us from the C++ program when we are called. ---- Evidently we are required to provide values for ---- PageWidth, PageHeight, and Scale ... which are used by ---- the C++ program after we return. Scale defaults to 1. ---- ---- Note that these Page-related names are unfortunate, ---- because they do *not* correspond to the pages as defined ---- by the source, or to the pages in the final booklet. ---- Really PageHeight should be called SheetHeight and ---- PageWidth should be called SheetWidth or something ---- like that. ---- ---- Note that we calculate our offsets and margins in ----_real_ units, not scaled units. That is significant ---- PushRecord will scale its arguments, so we will need -----to descale the offsets in the call to PushRecord. -- Useful units, measured in local units (i.e. postscript points): inch = 72 mm = inch / 25.4 PageWidth = _page_width_ PageHeight = _page_height_ -- Turn on TopMode if you want to print the top side of each sheet -- Turn on BottomMode if you want to print the bottm side of each sheet -- Turn on TopMode and BottomMode if you want both, as for a duplex printer TopMode = _top_ BottomMode = _bottom_ -- Turn on BoStack if your non-duplex printer has the property -- that the first thing printed winds up at the bottom of the -- stack, face up. BoStack = _bostack_ print("PageCount",PageCount) -- Note that we need to distinguish ---- the hw margins need to keep the printer happy ---- the /added/ margins we need to apply here. -- Worst case is when the source -- material bleeds right to the edge of its bounding box. -- Conversely, if the source material has a lot of margin -- already built into it, we may not need any /extra/ margin -- at all, and we could set UsableHeight = PageHeight here. -- Similarly if Ydelta/2 is larger than the hwBottomMargin -- we shouldn't need to add any /add/ margin. hwTopMargin = 0.1*inch hwBottomMargin = 0.5*inch hwLeftMargin = 0.1*inch hwRightMargin = 0.1*inch srcMargin = 0 addTopMargin = math.max(0, hwTopMargin - srcMargin) addBottomMargin = math.max(0, hwBottomMargin - srcMargin) addLeftMargin = math.max(0, hwLeftMargin - srcMargin) addRightMargin = math.max(0, hwRightMargin - srcMargin) -- When calculating wiggle room, assume paper will be used -- symmetrically. This is a nontrivial assumption, since -- e.g. we could use a paper cutter to chop off one edge -- and not the other ... but that would be beyond the -- scope of this analysis. Symmetry means that if we -- apply a margin to the recto page, we must apply the -- same margin to the verso page, even if the hardware -- would not require it. Hence the factors of 2 here: UsableHeight = PageHeight - 2*addTopMargin - 2*addBottomMargin UsableWidth = PageWidth - 2*addLeftMargin - 2*addRightMargin if(SourceWidth <= SourceHeight) then Scale = math.min(UsableHeight / (2*SourceWidth), UsableWidth / SourceHeight) rot = 90 Ywiggle = 0.5 * math.max(0, UsableHeight - 2*SourceWidth*Scale) Xwiggle = math.max(0, UsableWidth - SourceHeight*Scale) fudge = addTopMargin + 2*(addBottomMargin + Ywiggle) -- Apply a factor of /2 to Xwiggle here, -- because we want centering -- (not flush to right of sheet, i.e. bottom of page): -- Do not apply corresponding factor to Ywiggle, because -- we do want flush to top of sheet, i.e. right of page: xof = addLeftMargin + SourceHeight*Scale + Xwiggle/2 yofRtop = SourceWidth*Scale + fudge yofRbot = SourceWidth*Scale + fudge yofVtop = addBottomMargin + Ywiggle yofVbot = addBottomMargin + Ywiggle else Scale = math.min(UsableHeight / (2*SourceHeight), UsableWidth / SourceWidth) rot = 0 Ywiggle = 0.5 * math.max(0, UsableHeight - 2*SourceHeight*Scale) Xwiggle = math.max(0, UsableWidth - SourceWidth*Scale) fudge = addTopMargin + 2*(addBottomMargin + Ywiggle) xof = addLeftMargin + Xwiggle/2 yofRtop = SourceHeight*Scale + fudge yofRbot = SourceHeight*Scale + fudge yofVtop = addBottomMargin + Ywiggle yofVbot = addBottomMargin + Ywiggle end do rest = PageCount % 4 totp = PageCount if rest ~= 0 then totp = totp + ( 4 - rest) end -- "inc" counts input pages skipped as well as pages actually used: inc = 0 -- "outc" counts output pages: outc = 0; count = 0 imax = totp/4 middle = totp/2 while count < imax do -- We assume that podofoimpose will discard invalid records -- such as those with source page greater than PageCount -- print(totp, inc, outc, rot, xof, yofRtop, yofVtop, yofRbot, yofVbot) -- Top of sheet: (8 1) ... (6 3) if TopMode ~= 0 then -- We did all the interesting calculations in real units (above). -- We convert to nasty descaled units at the last moment: PushRecord(totp - inc, outc + 1, rot, xof/Scale, yofVtop/Scale) PushRecord(inc + 1, outc + 1, rot, xof/Scale, yofRtop/Scale) outc = outc + 1 end -- Bottom of sheet: if BottomMode ~= 0 then if BoStack ~= 0 then -- Reversed bottom: (4 5) ... (2 7) PushRecord(middle - inc, outc + 1, rot, xof/Scale, yofVbot/Scale) PushRecord(middle + 1 + inc, outc + 1, rot, xof/Scale, yofRbot/Scale) else -- Normal bottom: (2 7) ... (4 5) PushRecord(inc + 2, outc + 1, rot, xof/Scale, yofVbot/Scale) PushRecord(totp-(inc + 1), outc + 1, rot, xof/Scale, yofRbot/Scale) end outc = outc + 1 end count = count + 1 inc = inc + 2 end end