InterpressBookletImpl.mesa
Copyright Ó 1987, 1992 by Xerox Corporation. All rights reserved.
Wes Irish, December 3, 1987 4:14:02 pm PST
Michael Plass, May 15, 1992 12:07 pm PDT
InterpressBooklet creates a new Interpress master from an existing Interpress master. The input master is assumed to be a multiple-page Interpress master intended for 8-1/2 x 11 printing. When the resulting master is printed on a double sided 8-1/2 x 11 printer, and the pages folded in half, a "booklet" results. The pages of the resulting booklet will all be in the correct order with page one being the first or "cover" page.
The style CedarBooklet.style generates a print area appropriate for a booklet, no scaling is needed or done. If your document wasn't created with CedarBooklet.style then you may want InterpressBooklet to scale down the original so that if fits on the now 5.5 x 8.5 page, use the -f option for this purpose.
DIRECTORY
Commander USING [CommandProc, Handle, Register],
CommanderOps,
Convert,
FS,
Imager,
ImagerInterpress USING [Close, Create, DoPage, Ref ],
ImagerFont,
InterpressInterpreter USING [DoPage, LogProc, Master, Open ],
IO,
Rope USING [ Cat, ROPE, Fetch, Equal, Length, Substr ];
InterpressBookletImpl: CEDAR PROGRAM
IMPORTS Commander, CommanderOps, Convert, FS, Imager, ImagerInterpress, ImagerFont, InterpressInterpreter, IO, Rope ~ {
ROPE: TYPE = Rope.ROPE;
STREAM: TYPE = IO.STREAM;
BookletCmd: Commander.CommandProc ~ {
ENABLE FS.Error => CommanderOps.Failed[error.explanation];
argv: CommanderOps.ArgumentVector ¬ CommanderOps.Parse[cmd];
scaleIt: BOOL ¬ FALSE;
renumber: BOOL ¬ FALSE;
up: INT ¬ 0;
paperWidth: REAL ¬ 0.01 * 2.54 * 8.5; -- meters
paperHeight: REAL ¬ 0.01 * 2.54 * 11.0; -- meters
scaleFactor: REAL ¬ 0.0;
input: ROPE;
output: ROPE;
BookletLogProc: InterpressInterpreter.LogProc ~ {
cmd.err.PutRope["\n *** "];
cmd.err.PutRope[explanation];
cmd.err.PutRope[" *** "];
};
Booklet: PROC [output, input: ROPE, logProc: InterpressInterpreter.LogProc, ms: STREAM] ~ {
fullFName: ROPE ~ FS.FileInfo[input].fullFName;
master: InterpressInterpreter.Master ~ InterpressInterpreter.Open[fileName: fullFName, log: logProc];
ref: ImagerInterpress.Ref ~ ImagerInterpress.Create[fileName: output];
inPages: INT = master.pages;
outPages: INT = (inPages+3)/4;
lowPage: INT ¬ 1;
highPage: INT ¬ outPages * 4;
DoPage: PROC [context: Imager.Context, page: INT] ~ {
Renumber: PROC ~ {
font: ImagerFont.Font ~ Imager.FindFontScaled["Xerox/XC1-1-1/Modern", 9];
rope: ROPE ~ Convert.RopeFromInt[page];
Imager.ScaleT[context, 0.0254/72];
Imager.SetXY[context, [x: IF page MOD 2 = 0 THEN 36.0 ELSE 5.5*72-36-ImagerFont.RopeEscapement[font, rope].x, y: 8.5*72-36]];
Imager.SetFont[context, font];
Imager.ShowRope[context, rope];
};
IF renumber AND page > 1 THEN Imager.DoSave[context, Renumber];
IF scaleIt THEN Imager.ScaleT[context, scaleFactor];
IF up#0 THEN Imager.TranslateT[context, [0, up*0.5*0.0254]]; -- move up
InterpressInterpreter.DoPage[master: master, page: page, context: context, log: logProc];
};
WriteSide1: PROC [context: Imager.Context] ~ {
LowPageAction: PROC ~ {
IF lowPage > inPages THEN RETURN;
Imager.TranslateT[context, [paperWidth, paperHeight/2.0]];
Imager.RotateT[context, 90.0];
DoPage[context, lowPage];
lowPage ¬ lowPage + 1;
};
HighPageAction: PROC ~ {
IF highPage > inPages THEN {highPage ¬ highPage - 1; RETURN};
Imager.TranslateT[context, [paperWidth, 0]];
Imager.RotateT[context, 90.0];
DoPage[context, highPage];
highPage ¬ highPage - 1;
};
Imager.DoSave[context, LowPageAction];
Imager.DoSave[context, HighPageAction];
};
WriteSide2: PROC [context: Imager.Context] ~ {
LowPageAction: PROC ~ {
IF lowPage > inPages THEN RETURN;
Imager.TranslateT[context, [0, paperHeight]];
Imager.RotateT[context, 270.0];
DoPage[context, lowPage];
lowPage ¬ lowPage + 1;
};
HighPageAction: PROC ~ {
IF highPage > inPages THEN {highPage ¬ highPage - 1; RETURN};
Imager.TranslateT[context, [0, paperHeight/2.0]];
Imager.RotateT[context, 270.0];
DoPage[context, highPage];
highPage ¬ highPage - 1;
};
Imager.DoSave[context, LowPageAction];
Imager.DoSave[context, HighPageAction];
};
ms.PutFL["Making booklet %g (%g/4 pages) from %g (%g input pages) ... ", LIST[
[rope[output]],
[integer[outPages*4]],
[rope[input]],
[integer[inPages]]]];
WHILE lowPage < highPage DO
ms.PutF["[%g] [%g", [integer[(lowPage*2)-1]], [integer[lowPage*2]]];
ImagerInterpress.DoPage[self: ref, action: WriteSide1];
ms.PutF["] [%g] [%g", [integer[(lowPage*2)-1]], [integer[lowPage*2]]];
ImagerInterpress.DoPage[self: ref, action: WriteSide2];
ms.PutRope["] "];
ENDLOOP;
ImagerInterpress.Close[self: ref];
ms.PutF1["\n%g written.\n", [rope[output]]];
};
ProcessArgs: PROC [cmd: Commander.Handle, argv: CommanderOps.ArgumentVector]
RETURNS [msg: ROPE ¬ NIL] ~ {
i: INT ¬ 1;
arrowSpecified: BOOL ¬ FALSE;
inputWidth: REAL ¬ 0.01 * 2.54 * 8.5; -- meters
inputHeight: REAL ¬ 0.01 * 2.54 * 11.0; -- meters
input ¬ NIL;
output ¬ NIL;
scaleIt ¬ FALSE;
scaleFactor ¬ 0.0;
WHILE i < argv.argc DO
len: INT ~ Rope.Length[argv[i]];
IF len = 0 THEN { msg ¬ "Null argument"; GOTO Bad };
IF Rope.Fetch[argv[i], 0] = '-
THEN {
IF len = 1 THEN { msg ¬ "Missing option"; GOTO Bad };
SELECT Rope.Fetch[argv[i], 1] FROM
'b => scaleIt ¬ FALSE; -- booklet style, no scaling
'f => scaleIt ¬ TRUE; -- fit a "standard" 8.5 x 11
'n => { renumber ¬ TRUE }; -- renumber
'u => { up ¬ up + 1 }; -- up a little
's => { -- use an arbitrary scaling factor
scaleIt ¬ TRUE;
scaleFactor ¬ Convert.RealFromRope[Rope.Substr[argv[i], 2]];
};
'p => IF i+1 >= argv.argc THEN GOTO Bad ELSE {
arg: ROPE ~ argv[i+1];
i ¬ i + 1;
SELECT TRUE FROM
Rope.Equal[arg, "usletter", FALSE] => {
paperWidth ¬ 0.01 * 2.54 * 8.5; -- meters
paperHeight ¬ 0.01 * 2.54 * 11.0; -- meters
};
Rope.Equal[arg, "uslegal", FALSE] => {
paperWidth ¬ 0.01 * 2.54 * 8.5; -- meters
paperHeight ¬ 0.01 * 2.54 * 14.0; -- meters
};
Rope.Equal[arg, "usledger", FALSE] => {
paperWidth ¬ 0.01 * 2.54 * 11.0; -- meters
paperHeight ¬ 0.01 * 2.54 * 17.0; -- meters
};
Rope.Equal[arg, "a4", FALSE] => {
paperWidth ¬ 0.210; -- meters
paperHeight ¬ 0.297; -- meters
};
ENDCASE => msg ¬ "known paper sizes are: usletter, uslegal, usledger, a4";
};
'i => IF i+1 >= argv.argc THEN GOTO Bad ELSE {
arg: ROPE ~ argv[i+1];
i ¬ i + 1;
SELECT TRUE FROM
Rope.Equal[arg, "usletter", FALSE] => {
inputWidth ¬ 0.01 * 2.54 * 8.5; -- meters
inputHeight ¬ 0.01 * 2.54 * 11.0; -- meters
};
Rope.Equal[arg, "uslegal", FALSE] => {
inputWidth ¬ 0.01 * 2.54 * 8.5; -- meters
inputHeight ¬ 0.01 * 2.54 * 14.0; -- meters
};
Rope.Equal[arg, "usledger", FALSE] => {
inputWidth ¬ 0.01 * 2.54 * 11.0; -- meters
inputHeight ¬ 0.01 * 2.54 * 17.0; -- meters
};
Rope.Equal[arg, "a4", FALSE] => {
inputWidth ¬ 0.210; -- meters
inputHeight ¬ 0.297; -- meters
};
ENDCASE => msg ¬ "known paper sizes are: usletter, uslegal, usledger, a4";
};
ENDCASE => { msg ¬ "Invalid option"; GOTO Bad };
}
ELSE {
SELECT TRUE FROM
Rope.Equal[argv[i], "←"], Rope.Equal[argv[i], "¬"] => {
IF input = NIL THEN { msg ¬ "No output file specified"; GOTO Bad };
arrowSpecified ¬ TRUE;
};
input = NIL => input ¬ argv[i];
(output = NIL) AND arrowSpecified => {
output ¬ input;
input ¬ argv[i];
};
ENDCASE => {
IF arrowSpecified
THEN msg ¬ "Too much in command line"
ELSE msg ¬ "Missing \"¬\"";
GOTO Bad;
};
};
i ¬ i.SUCC;
ENDLOOP;
IF scaleFactor = 0.0 THEN scaleFactor ¬ MIN[(paperHeight*0.5)/inputWidth, paperWidth/inputHeight];
IF input = NIL OR output = NIL THEN { msg ¬ "File name missing"; GOTO Bad };
EXITS
Bad => { msg ¬ Rope.Cat[msg, ":\n", cmd.procData.doc]};
};
IF argv = NIL THEN RETURN;
msg ¬ ProcessArgs[cmd, argv];
IF msg # NIL THEN { result ¬ $Failure; RETURN };
Booklet[output, input, BookletLogProc, cmd.out];
};
doc: ROPE ¬ "Create a new IP master that will print as a booklet (paper folded in half, in correct page order).
-b booklet style, no scaling (default)
-f scale to fit
-s use an arbitrary scaling factor
-p <size name> specify paper size (default: USLetter)
-i <size name> specify image size (default: USLetter)
-n add page numbers";
Commander.Register["InterpressBooklet", BookletCmd, doc];
Commander.Register["IPBooklet", BookletCmd, doc];
}.