NectarinePdImpl.mesa
Copyright Ó 1986, 1987, 1988 by Xerox Corporation. All rights reserved.
Giordano Bruno Beretta, April 11, 1986 7:57:41 pm PST
gbb October 13, 1988 2:44:38 pm PDT
Jean-Marc Frailong December 12, 1988 12:04:47 pm PST
Last Edited by: Richley September 17, 1990 4:36:34 pm PDT
Implements an alternate way to produce Interpress masters from ChipNDale drawings. The difference is in the user interface. It is similar to the one in programs by Imaging Folks, and it is simpler to use for casual users.
Fuzzless and sweeter than peaches (S. Williams)
DIRECTORY
Args USING [Arg, ArgsGet, Error, NArgs],
BasicTime USING [GMT, Now, Period],
Commander USING [CommandProc, Register],
FS USING [ComponentPositions, Copy, Delete, Error, ExpandName, FileInfo, Position, SetKeep],
Imager USING [Context, Rectangle],
ImagerBrick USING [Brick],
ImagerInterpress USING [Close, Create, DoPage, Ref],
ImagerSample USING [NewSampleMap, Put],
Interpress USING [classAppearanceError, classAppearanceWarning, classComment, classMasterError, classMasterWarning, Close, DoPage, LogProc, Master, Open],
InterpressCC USING [InitCC, StandardCC],
InterpressToPD USING [DoCommand, ParamsFromPrinterType, PDParams, ProgressProc],
IO USING [int, PutFR, PutFR1, real, rope],
MessageWindow USING [Append, Blink, Clear],
NectarinePd,
PeachPrint USING [DoPeachPrintCommand, PupAborted],
Process USING [CheckForAbort, Detach, priorityBackground, SetPriority],
Real USING [InlineRound],
Rope USING [Cat, Concat, IsEmpty, Replace, ROPE, Substr],
RuntimeError USING [UNCAUGHT],
SafeStorage USING [ReclaimCollectibleObjects],
SimpleMailer USING [SendMessage, SendMessageInfo],
SimpleMailer USING [SendMessage],
TerminalIO USING [TOS, PutF, PutRope],
UserCredentials USING [Get],
UserProfile USING [Boolean, Token];
NectarinePdImpl: CEDAR PROGRAM
IMPORTS Args, BasicTime, Commander, FS, ImagerInterpress, ImagerSample, Interpress, InterpressCC, InterpressToPD, IO, MessageWindow, PeachPrint, Process, Real, Rope, RuntimeError, SafeStorage, SimpleMailer, TerminalIO, UserCredentials, UserProfile
EXPORTS NectarinePd ~ BEGIN
OPEN Real;
communicationsFailure: PUBLIC SIGNAL ~ CODE;
pause: SIGNAL ~ CODE;
ROPE: TYPE ~ Rope.ROPE;
Brick: TYPE ~ ImagerBrick.Brick;
brickK: REF Brick ← NEW [Brick]; brickC: REF Brick ← NEW [Brick];
brickM: REF Brick ← NEW [Brick]; brickY: REF Brick ← NEW [Brick];
medium: Imager.Rectangle ~ [x: 0.0, y: 0.0, w: 215.9, h: 279.4]; -- in mm
field: PUBLIC Imager.Rectangle ← [x: medium.x + 10.0, y: medium.y + 10.0, w: medium.w - 20.0, h: medium.h - 20.0]; -- in mm
mmXin: REAL ~ 25.4;
debug: BOOLFALSE;
Printing
ForcedDelete: PROC [fileName: ROPE] ~ BEGIN
Sorry, but that is the only way to get rid of the temporary files.
TRUSTED BEGIN
SafeStorage.ReclaimCollectibleObjects; SafeStorage.ReclaimCollectibleObjects;
SafeStorage.ReclaimCollectibleObjects; SafeStorage.ReclaimCollectibleObjects;
SafeStorage.ReclaimCollectibleObjects; SafeStorage.ReclaimCollectibleObjects;
SafeStorage.ReclaimCollectibleObjects; SafeStorage.ReclaimCollectibleObjects;
SafeStorage.ReclaimCollectibleObjects; SafeStorage.ReclaimCollectibleObjects;
Process.Detach [FORK FS.Delete [fileName ! FS.Error => CONTINUE; RuntimeError.UNCAUGHT => CONTINUE]]
END
END; -- ForcedDelete
MergeRegisterMarks: PROC [masterName: ROPE] RETURNS [newName: ROPE] ~ BEGIN
Merges an Interpress master with the register marks produced with NectarineAids. (In reality, this procedure is a little more general). Because of the hold goal, it must work independently of the number of pages in the image.
pos: FS.ComponentPositions; fullName: ROPE;
out: ImagerInterpress.Ref; image, marks: Interpress.Master;
[fullName, pos] ← FS.ExpandName [masterName];
newName ← fullName.Substr [pos.base.start, pos.base.length].Concat ["-Bis"];
newName ← fullName.Replace [pos.base.start, pos.base.length, newName];
out ← ImagerInterpress.Create [newName];
image ← Interpress.Open [masterName, LogInterpress];
IF DoLineArt[] AND (NOT UseProcessColors[]) THEN marks ← Interpress.Open ["[DATools7.0]<Nectarine>MechanicRegisterMarks.Interpress", LogInterpress]
ELSE marks ← Interpress.Open ["[DATools7.0]<Nectarine>ProcessRegisterMarks.Interpress", LogInterpress];
FOR page: INT IN [1 .. image.pages] DO
pageM: INT ~ ((page-1) MOD marks.pages) + 1;
DoIt: PROC [context: Imager.Context] ~ BEGIN
Write out the ith page of the image, then write out the register marks.
Interpress.DoPage [master: image, page: page, context: context, log: LogInterpress];
Interpress.DoPage [master: marks, page: pageM, context: context, log: LogInterpress]
END; -- DoIt
ImagerInterpress.DoPage [self: out, action: DoIt]
ENDLOOP;
image.Close; out.Close; marks.Close;
image ← NIL; out← NIL; marks ← NIL; ForcedDelete [masterName];
TerminalIO.PutF ["\n%g copied to %g with register marks.\n", IO.rope [masterName], IO.rope [newName]]
END; -- MergeRegisterMarks
LogInterpress: Interpress.LogProc ~ BEGIN
Called for errors during interpress execution. [class: INT, code: ATOM, explanation: ROPE]
TerminalIO.PutRope [SELECT class FROM
Interpress.classMasterError => "Master Error: ",
Interpress.classMasterWarning => "Master Warning: ",
Interpress.classAppearanceError => "Appearance Error: ",
Interpress.classAppearanceWarning => "Appearance Warning: ",
Interpress.classComment => "Comment: ",
ENDCASE
=> IO.PutFR1 ["Class %g error: ", IO.int [class]]];
TerminalIO.PutRope [explanation]; TerminalIO.PutRope [" . . . \n"]
END; -- LogInterpress
ProgressLog: InterpressToPD.ProgressProc ~ BEGIN
[begin: BOOL, page: INT]
IF begin THEN TerminalIO.PutRope [IO.PutFR1 ["[%g", IO.int [page]]]
ELSE TerminalIO.PutRope ["] "]
END; -- ProgressLog
UseProcessColors: PROC RETURNS [BOOL] ~ INLINE BEGIN
RETURN [UserProfile.Boolean [key: "Nectarine.ProcessColors", default: TRUE]]
END; -- UseProcessColors
DoLineArt: PROC RETURNS [BOOL] ~ INLINE BEGIN
RETURN [UserProfile.Boolean [key: "Nectarine.LineArt", default: FALSE]]
END; -- DoLineArt
ImportantMessage: PROC [msg: ROPE] ~ BEGIN
Writes a message in the ChipNDale terminal viewer and in the Message Window at the top of the LF screen and makes it blink.
TerminalIO.PutRope [msg]; TerminalIO.PutRope ["\n"];
MessageWindow.Clear []; MessageWindow.Append [msg]; MessageWindow.Blink []
END; -- ImportantMessage
TimeToRope: PROC [from, to: BasicTime.GMT] RETURNS [time: ROPE] ~ BEGIN
Although the INT returned BasicTime.Period is the same as GMT and might hence be loopholed to use IO.time from Conversions, the latter uses BasicTime.Unpack which allows only values that give a valid date.
TwoPosInt: PROC [i: INT] RETURNS [ROPE] ~ BEGIN
RETURN [SELECT i FROM
= 0 => "00",
< 10 => Rope.Cat ["0", IO.PutFR1 [value: IO.int [i]]],
ENDCASE => IO.PutFR1 [value: IO.int [i]]]
END;
s: INT ← BasicTime.Period [from, to];
m: INT ← s / 60; h: INT ← m / 60; d: INT ~ h / 24;
s ← s MOD 60; m ← m MOD 60; h ← h MOD 24;
IF (d > 0) THEN time ← Rope.Cat ["d:h:m:s ", TwoPosInt[d], ":"]
ELSE time ← "h:m:s ";
time ← time.Cat [TwoPosInt[h], ":"];
RETURN [time.Cat [TwoPosInt[m], ":", TwoPosInt[s]]]
END; -- TimeToRope
PdPrintProcess: PUBLIC PROC [masterName, peachName: Rope.ROPE, printerKey: ATOM, copies: INT, doNotScale, mergeRegister: BOOL, sizeHint: REF Imager.Rectangle ← NIL, abortFlag: REF BOOL] ~ BEGIN
This is a mess. The religion asks me to propagate the error I get from PeachPrint to my client. However, PeachPrint just sits there until all printing is done or aborts locking up ChipNDale. Therefore, until PeachPrint is not fixed and forks off a process by its own, I do it myself and swallow that bloody event.
If the image is in portrait format and the printer uses roll paper, the rectangle usedField from DoInterpress can be specified as a sizeHint to increase the scale so a to use the full roll width.
Note: the origin in PDParams refers to the field, not to the medium.
{ENABLE BEGIN
PeachPrint.PupAborted => GOTO peachFailure;
END;
serverName: ROPE; startTime: BasicTime.GMT;
deviceParameters: InterpressToPD.PDParams;
doGreyBalance: BOOL ~ UserProfile.Boolean ["Nectarine.GreyBalance", FALSE];
doColorCorrection: BOOL ~ UserProfile.Boolean ["Nectarine.ColorCorrection", FALSE];
scale: REAL;
TRUSTED {Process.SetPriority [Process.priorityBackground]};
IF doColorCorrection THEN TerminalIO.PutRope ["Will perform color correction\n"];
IF doGreyBalance AND (NOT doColorCorrection) THEN TerminalIO.PutRope ["Will balance greys\n"];
SELECT printerKey FROM
$NVersatec => BEGIN
Roll paper.
deviceParameters ← InterpressToPD.ParamsFromPrinterType [$versatec];
IF (sizeHint # NIL) AND (sizeHint.h > sizeHint.w) THEN BEGIN
scale (mmXin * deviceParameters.pageFSize) / sizeHint.w;
IF (scale*sizeHint.h > (mmXin*deviceParameters.pageSSize)) THEN
scale (mmXin * deviceParameters.pageSSize) / field.h;
IF (scale * sizeHint.h > 2000) THEN
ImportantMessage [" Your plot will be longer than 2 metres. Printing anyway"]
END
ELSE scale (mmXin * deviceParameters.pageFSize) / field.w;
serverName ← UserProfile.Token ["Nectarine.Versatec", "Sleepy"]
END;
$NColorVersatec, $NPeachExpand => BEGIN
Roll paper.
deviceParameters ← InterpressToPD.ParamsFromPrinterType [$colorVersatec];
IF (sizeHint # NIL) AND (sizeHint.w = 40*mmXin) THEN scale 1.0
ELSE BEGIN
IF (sizeHint # NIL) AND (sizeHint.h > sizeHint.w) THEN BEGIN
scale (mmXin * deviceParameters.pageFSize) / sizeHint.w;
IF (scale*sizeHint.h > (mmXin*deviceParameters.pageSSize)) THEN
scale (mmXin * deviceParameters.pageSSize) / field.h;
IF (scale * sizeHint.h > 2000) THEN
ImportantMessage [" Your plot will be longer than 2 metres. Printing anyway"]
END
ELSE scale (mmXin * deviceParameters.pageFSize) / field.w
END;
serverName ← IF (printerKey = $NColorVersatec) THEN
UserProfile.Token ["Nectarine.ColorVersatec", "Sleepy"]
ELSE UserProfile.Token ["Nectarine.PeachExpand", "Kearsarge"];
IF (doGreyBalance OR doColorCorrection) THEN BEGIN
InterpressToPD.ParamsFromPrinterType does not pass the name of the colorCorrectionSpec file, so I stick it in by brute force.
deviceParameters.colorCorrectionProc ← InterpressCC.StandardCC;
deviceParameters.colorCorrectionData ← InterpressCC.InitCC ["Versatec.CCSpec", doColorCorrection]
END
ELSE BEGIN
IF UserProfile.Boolean ["Nectarine.SprayHalftone", TRUE] THEN BEGIN
Use the following three statements to obtain very fast colors:
deviceParameters.bricks [black] ← brickK;
deviceParameters.bricks [cyan] ← brickC;
deviceParameters.bricks [magenta] ← brickM;
deviceParameters.bricks [yellow] ← brickY
END
Or use the following statement to obtain quality colors (rotated screens):
ELSE deviceParameters.ppd ← 3.0
END
END;
$NBw400 => BEGIN
Roll paper.
deviceParameters ← InterpressToPD.ParamsFromPrinterType [$bw400];
scale ← (mmXin * deviceParameters.pageFSize) / field.w;
serverName ← UserProfile.Token ["Nectarine.Bw400", "MtFuji"]
END;
$NColor400 => BEGIN
Roll paper.
deviceParameters ← InterpressToPD.ParamsFromPrinterType [$color400];
IF (doGreyBalance OR doColorCorrection) THEN BEGIN
InterpressToPD.ParamsFromPrinterType does not pass the name of the colorCorrectionSpec file, so I stick it in by brute force.
deviceParameters.colorCorrectionProc ← InterpressCC.StandardCC;
deviceParameters.colorCorrectionData ← InterpressCC.InitCC ["NectarineColor400.CCSpec", doColorCorrection]
deviceParameters.colorCorrectionData ← InterpressCC.InitCC ["Color400.CCSpec", doColorCorrection]
END
ELSE BEGIN
IF UserProfile.Boolean ["Nectarine.SprayHalftone", TRUE] THEN BEGIN
Use the following three statements to obtain very fast colors:
deviceParameters.bricks [black] ← brickK;
deviceParameters.bricks [cyan] ← brickC;
deviceParameters.bricks [magenta] ← brickM;
deviceParameters.bricks [yellow] ← brickY
END
Or use the following statement to obtain quality colors (rotated screens):
ELSE deviceParameters.ppd ← 3.0
END;
scale ← (mmXin * deviceParameters.pageFSize) / field.w;
serverName ← UserProfile.Token ["Nectarine.Color400", "MtFuji"]
END;
$NPlateMaker => BEGIN
Cut paper.
deviceParameters ← InterpressToPD.ParamsFromPrinterType [$platemaker];
deviceParameters.tonerUniverse ← LIST [black, cyan, magenta, yellow];
IF UserProfile.Boolean ["Nectarine.SprayHalftone", TRUE] AND (NOT DoLineArt[]) THEN TerminalIO.PutRope ["Your user profile requests so-called spray halftoning. However, this is not usable on a process printer.\nWill use conventional halftoning instead.\n"]
Implementation notice: because of some possible arcane bug in the compiler, if the scales in x and y would have been first defined either as contants or variables, the compiler would set them to the value 0.0. Therefore you should not change the next line.
NOTE: The Interpress master is now being merged with the alignment marks. This means, that it is no longer possible to translate or scale during the InterpressToPD conversion; the user has to live with the 1 cm margin.
scale ← MIN [(mmXin*deviceParameters.pageFSize)/field.w, (mmXin*deviceParameters.pageSSize)/field.h]
END;
$NRaven300 => ERROR; -- an Interpress printer, not PD
$NRaven384 => deviceParameters ← InterpressToPD.ParamsFromPrinterType [$raven384];
ENDCASE => NULL; -- should never happen
The adjustement of the field to the left end of the printer head has to be scaled, because the field is included in the coordinates in the Interpress master. If the output is scaled to a fixed  value, then we simply overwrite the scale factor here.
IF doNotScale OR fieldHasBeenSet THEN scale ← 1.0;
IF abortFlag^ THEN ERROR ABORTED; Process.CheckForAbort;
startTime ← BasicTime.Now [];
SELECT printerKey FROM
$NRaven384 => BEGIN
InterpressToPD.DoCommand [inputName: masterName,
outputName: peachName,
params: deviceParameters,
logProc: LogInterpress, progressProc: ProgressLog];
TerminalIO.PutRope [Rope.Cat ["PD file for Raven384 created. Stuff the following line in a Command Tool viewer to send it to a 384 dpi Press-printer like Stinger:\nPrint -h Stinger ", peachName, "\n"]]
END;
$NPlateMaker => BEGIN
NOTE: The Interpress master is now being merged with the alignment marks. This means, that it is no longer possible to translate or scale during the InterpressToPD conversion; the user has to live with the 1 cm margin.
tx: REAL ~ - (field.x * scale) / mmXin;
ty: REAL ~ - (field.y * scale) / mmXin;
user: ROPE ~ UserCredentials.Get[].name;
prefix: ROPE ← "[]<>Temp>Nectarine>Erie";
public: BOOL;
gNameK, gNameC, gNameM, gNameY, suffix, separation, erieSeparations: ROPE;
IF mergeRegister THEN masterName ← MergeRegisterMarks [masterName];
IF DoLineArt[] AND (NOT UseProcessColors[]) THEN TerminalIO.PutRope ["\nStarting production of separations for mechanic colors.\n"]
ELSE TerminalIO.PutRope ["\nStarting production of separations for process colors.\n"];
erieSeparations ← UserProfile.Token ["Nectarine.PlatemakerSeparations"];
public ← NOT erieSeparations.IsEmpty;
deviceParameters.toners ← LIST [black];
suffix ← IF UseProcessColors[] THEN "-Black.PD" ELSE "-GT4Green.PD";
separation ← prefix.Concat [suffix];
InterpressToPD.DoCommand [inputName: masterName,
outputName: separation,
params: deviceParameters,
tx: 8.0 / mmXin, ty: 12.0 / mmXin,
logProc: LogInterpress, progressProc: ProgressLog];
IF abortFlag^ THEN GOTO platemakerAbort;
IF public THEN BEGIN
gNameK ← FS.Copy [from: separation, to: erieSeparations.Cat [user, ">", peachName, suffix]];
IF NOT gNameK.IsEmpty THEN ForcedDelete [separation]
END;
IF abortFlag^ THEN GOTO platemakerAbort;
deviceParameters.toners ← LIST [cyan];
suffix ← IF UseProcessColors[] THEN "-Cyan.PD" ELSE "-C28Blue.PD";
separation ← prefix.Concat [suffix];
InterpressToPD.DoCommand [inputName: masterName,
outputName: separation,
params: deviceParameters,
tx: 8.0 / mmXin, ty: 12.0 / mmXin,
logProc: LogInterpress, progressProc: ProgressLog];
IF abortFlag^ THEN GOTO platemakerAbort;
IF public THEN BEGIN
gNameC ← FS.Copy [from: separation, to: erieSeparations.Cat [user, ">", peachName, suffix]];
IF NOT gNameC.IsEmpty THEN ForcedDelete [separation]
END;
IF abortFlag^ THEN GOTO platemakerAbort;
deviceParameters.toners ← LIST [magenta];
suffix ← IF UseProcessColors[] THEN "-Magenta.PD" ELSE "-RT6Red.PD";
separation ← prefix.Concat [suffix];
InterpressToPD.DoCommand [inputName: masterName,
outputName: separation,
params: deviceParameters,
tx: 8.0 / mmXin, ty: 12.0 / mmXin,
logProc: LogInterpress, progressProc: ProgressLog];
IF abortFlag^ THEN GOTO platemakerAbort;
IF public THEN BEGIN
gNameM ← FS.Copy [from: separation, to: erieSeparations.Cat [user, ">", peachName, suffix]];
IF NOT gNameM.IsEmpty THEN ForcedDelete [separation]
END;
IF abortFlag^ THEN GOTO platemakerAbort;
deviceParameters.toners ← LIST [yellow];
suffix ← IF UseProcessColors[] THEN "-Yellow.PD" ELSE "-M35Slash2Magenta.PD";
separation ← prefix.Concat [suffix];
InterpressToPD.DoCommand [inputName: masterName,
outputName: separation,
params: deviceParameters,
tx: 8.0 / mmXin, ty: 12.0 / mmXin,
logProc: LogInterpress, progressProc: ProgressLog];
IF abortFlag^ THEN GOTO platemakerAbort;
IF public THEN BEGIN
gNameY ← FS.Copy [from: separation, to: erieSeparations.Cat [user, ">", peachName, suffix]];
IF NOT gNameY.IsEmpty THEN ForcedDelete [separation]
END;
IF abortFlag^ THEN GOTO platemakerAbort;
IF debug THEN pause;
IF public THEN BEGIN
IF (gNameK.IsEmpty OR gNameC.IsEmpty OR gNameM.IsEmpty OR gNameY.IsEmpty) THEN ImportantMessage ["Was not able to store all the required separations."];
IF DoLineArt [] AND (NOT UseProcessColors []) THEN BEGIN
gNameK ← gNameK.Cat ["\nC28 blue: ", gNameC, "\nRT6 red: ", gNameM];
gNameK ← gNameK.Cat ["\nM35/2 magenta: ", gNameY];
[] ← SimpleMailer.SendMessage [from: "Nectarine", to: LIST [[$gv, "Platemaker.PA"]], cc: LIST [[$gv, user], [$gv, "Wallgren.PARC"]], subject: Rope.Concat ["Erie Print Request ", peachName], body: Rope.Cat ["Hi Bridget or Steve,\n\nPlease print for me on film:\n\nGT4 green: ", gNameK, "\n\n\tIMPORTANT: If I tell you to actually do Cromalin proofs, make positives with the Reverse button on. If I need separations to be stripped by Kedie/Orent, I will probably want negatives with the emulsion up.\n\nIf I need a Cromalin proof, please make it using the custom colors mentioned in the file names in the order GT4 green, C28 blue, M35/2 magenta, and RT6 red.\n\nThank you,\n", user]];
END
ELSE BEGIN
gNameK ← gNameK.Cat ["\nCyan: ", gNameC, "\nMagenta: ", gNameM];
gNameK ← gNameK.Cat ["\nYellow: ", gNameY];
[] ← SimpleMailer.SendMessage [from: "Nectarine", to: LIST [[$gv, "Platemaker.PA"]], cc: LIST [[$gv, user], [$gv, "Wallgren.PARC"]], subject: Rope.Concat ["Erie Print Request ", peachName], body: Rope.Cat ["Hi Bridget or Steve,\n\nPlease print for me on film:\n\nBlack: ", gNameK, "\n\n\tIMPORTANT: If I tell you to actually do Cromalin proofs, make positives with the Reverse button on. If I need separations to be stripped by Kedie/Orent, I will probably want negatives with the emulsion up.\n\nIf I will tell you to prepare a Cromalin proof, then please use the Cromalin process inks SOP-Cyan, SOP-Magenta, SOP-Yellow, and, SOP-Black. Apply the colors in the order yellow, cyan, magenta, and black.\n\nThank you,\n", user]]
END
END
ELSE TerminalIO.PutF ["\nThe separations are on your disk in %g-{mechanic/process color name}.PD. You have not set the user profile option Nectarine.PlatemakerSeparations, hence I cannot take care of them.\nDebrouillez vous.\n", IO.rope [prefix]]
END;
ENDCASE => BEGIN
tx, ty: REAL;
IF abortFlag^ THEN ERROR ABORTED; Process.CheckForAbort;
IF (printerKey = $NColorVersatec) AND (sizeHint # NIL) AND (sizeHint.w = 40*mmXin) THEN {tx ← ty ← 0}
ELSE IF (sizeHint # NIL) THEN
{tx ← - (sizeHint.x * scale) / mmXin; ty ← - (sizeHint.y * scale) / mmXin}
ELSE
{tx ← - (field.x * scale) / mmXin; ty ← - (field.y * scale) / mmXin};
InterpressToPD.DoCommand [inputName: masterName,
outputName: peachName,
params: deviceParameters,
sx: scale, sy: scale, tx: tx, ty: ty,
logProc: LogInterpress, progressProc: ProgressLog];
The keep of PD files is 1. Unfortunately PeachPrint does not lock a file between the time it posts a request and the request is served. This can not only cause the files to get lost, but it may even hang some print servers. The solution implemented here, i.e., changing the keep to 3, it to be considered as a mild temporary hack until a proper solution becomes available in 3 weeks from the time these lines are written.
FS.SetKeep [peachName, 5];
TerminalIO.PutRope [Rope.Cat ["\nDuration of Interpress to PD conversion: ", TimeToRope [startTime, BasicTime.Now[]], "\n"]];
peachName ← FS.FileInfo [name: peachName, remoteCheck: FALSE].fullFName; -- with version number
Calling FS.SetKeep will have the side effect of deleting files that are obsolete relative to the new keep, even when the keep is not changed.
IF abortFlag^ THEN ERROR ABORTED; Process.CheckForAbort;
TerminalIO.PutF ["%g being submitted to %g.\n", IO.rope [peachName], IO.rope [serverName]];
PeachPrint.DoPeachPrintCommand [serverName, peachName, TerminalIO.TOS[], TRUE, copies]
END;
IF (printerKey = $NPeachExpand) THEN BEGIN
pos: FS.ComponentPositions ~ FS.ExpandName[peachName].cp;
server2Name: ROPE ~ UserProfile.Token ["Nectarine.ExpandedPeach", "Sleepy"];
simpleName: ROPE ~ peachName.Substr [pos.base.start, pos.base.length];
IF abortFlag^ THEN ERROR ABORTED; Process.CheckForAbort;
peachName ← Rope.Cat ["[", serverName, "]<Cedar>PD>", simpleName, "-1.PD"];
TerminalIO.PutF ["%g being submitted to %g.\n", IO.rope [peachName], IO.rope [server2Name]];
PeachPrint.DoPeachPrintCommand [server2Name, peachName, TerminalIO.TOS[], TRUE, copies]
END;
TerminalIO.PutRope [Rope.Cat ["\nDuration of Interpress to PD conversion and print submission: ", TimeToRope [startTime, BasicTime.Now[]], " for ", peachName, "\n"]];
EXITS
peachFailure => BEGIN
ImportantMessage [Rope.Cat ["Communications failure. File saved on ", peachName, " for manual retry."]];
SIGNAL communicationsFailure
END;
platemakerAbort => BEGIN
user: ROPE ~ UserCredentials.Get[].name;
[] ← SimpleMailer.SendMessage [from: "Nectarine", to: LIST [[$gv, "Platemaker.PA"]], cc: LIST [[$gv, user]], subject: peachName, body: Rope.Cat ["Hi again,\n\nNever mind, I have changed my mind.\n\nSorry for bothering you,\n", user]];
ERROR ABORTED
END}
END; -- PdPrintProcess
Initialization
fieldDoc: ROPE ~ "explicitly set the field size to perform image ganging. Specify the field in mm\n\t-x lower left corner x\n\t-y lower left corner y\n\t-w width\n\t-h height\nDefaults: x: medium.x + 10.0, y: medium.y + 10.0, w: medium.w - 20.0, h: medium.h - 20.0; where medium = [x: 0.0, y: 0.0, w: 215.9, h: 279.4]";
argError: ROPE;
fieldHasBeenSet: BOOLFALSE;
SetField: Commander.CommandProc ~ BEGIN
PROC [cmd: Handle] RETURNS [result: REFNIL, msg: ROPENIL]
Explicitly set the field to perform image ganging.
x, y, w, h: Args.Arg;
field ← [x: medium.x + 10.0, y: medium.y + 10.0, w: medium.w - 20.0, h: medium.h - 20.0];
fieldHasBeenSet ← FALSE;
IF (Args.NArgs [cmd] # 0) THEN BEGIN
[x, y, w, h] ← Args.ArgsGet [cmd, "-x%r-y%r-w%r-h%r" ! Args.Error => {argError ← reason; GOTO failure}];
fieldHasBeenSet ← TRUE;
IF x.ok THEN field.x ← x.real;
IF y.ok THEN field.y ← y.real;
IF w.ok THEN field.w ← w.real;
IF h.ok THEN field.h ← h.real
END;
msg ← IO.PutFR ["NectarineField -x %g -y %g -w %g -h %g",
IO.real [field.x], IO.real [field.y], IO.real [field.w], IO.real [field.h]];
EXITS
failure => RETURN [$Failure, argError.Cat ["\n", fieldDoc]]
END; -- SetField
InitBricks: PROC ~ BEGIN
Matrix: TYPE ~ ARRAY [1 .. 4] OF ARRAY [1 .. 4] OF REAL;
FillSample: PROC [s: REF Brick, a, b, c, d: REAL] ~ BEGIN
Set: PROC [i, j: INTEGER, val: REAL] ~ BEGIN
ImagerSample.Put [map: s.sampleMap, index: [i, j], value: InlineRound [255*val]];
END;
s^ ← [maxSample: 255, sampleMap: ImagerSample.NewSampleMap [box: [max:[2, 2]], bitsPerSample: 8], phase: 0];
Set [0, 0, a]; Set [0, 1, b]; Set [1, 0, c]; Set [1, 1, d]
END; -- FillSample
FillSample9: PROC [s: REF Brick, a11, a12, a13, a21, a22, a23, a31, a32, a33: REAL] ~ BEGIN
Set: PROC [i, j: INTEGER, val: REAL] ~ BEGIN
ImagerSample.Put [map: s.sampleMap, index: [i, j], value: InlineRound [255*val]];
END;
s^ ← [maxSample: 255, sampleMap: ImagerSample.NewSampleMap [box: [max:[3, 3]], bitsPerSample: 8], phase: 0];
Set [0, 0, a11]; Set [0, 1, a12]; Set [0, 2, a13];
Set [1, 0, a21]; Set [1, 1, a22]; Set [1, 2, a23];
Set [2, 0, a31]; Set [2, 1, a32]; Set [2, 2, a33]
END; -- FillSample9
FillSample16: PROC [s: REF Brick, a: Matrix] ~ BEGIN
Set: PROC [i, j: INTEGER, val: REAL] ~ BEGIN
ImagerSample.Put [map: s.sampleMap, index: [i, j], value: InlineRound [255*val]];
END;
s^ ← [maxSample: 255, sampleMap: ImagerSample.NewSampleMap [box: [max:[4, 4]], bitsPerSample: 8], phase: 0];
FOR i: [1 .. 4] IN [1 .. 4] DO
FOR j: [1 .. 4] IN [1 .. 4] DO a[i][j] ← a[i][j] / 17.0 ENDLOOP
ENDLOOP;
Set [0, 0, a[1][1]]; Set [0, 1, a[1][2]]; Set [0, 2, a[1][3]]; Set [0, 3, a[1][4]];
Set [1, 0, a[2][1]]; Set [1, 1, a[2][2]]; Set [1, 2, a[2][3]]; Set [1, 3, a[2][4]];
Set [2, 0, a[3][1]]; Set [2, 1, a[3][2]]; Set [2, 2, a[3][3]]; Set [2, 3, a[3][4]];
Set [3, 0, a[4][1]]; Set [3, 1, a[4][2]]; Set [3, 2, a[4][3]]; Set [3, 3, a[4][4]]
END; -- FillSample16
FillSample [brickK, 0.6, 0.4, 0.2, 0.8];
FillSample [brickC, 0.2, 0.8, 0.6, 0.4];
FillSample [brickM, 0.6, 0.4, 0.2, 0.8];
FillSample [brickY, 0.42, 0.15, 0.7, 0.3]; -- delicate !
FillSample9 [brickC, 0.4, 0.5, 0.6, 0.1, 0.3, 0.2, 0.7, 0.8, 0.9];
FillSample9 [brickM, 0.6, 0.1, 0.7, 0.5, 0.3, 0.8, 0.4, 0.2, 0.9];
FillSample9 [brickK, 0.1, 0.6, 0.4, 0.7, 0.2, 0.9, 0.5, 0.8, 0.3];
FillSample9 [brickY, 0.5, 0.8, 0.3, 0.9, 0.2, 0.6, 0.1, 0.7, 0.4];
FillSample16 [brickC, [[8.0, 6.0, 7.0, 5.0], [1.0, 3.0, 2.0, 4.0], [16.0, 14.0, 15.0, 13.0], [9.0, 11.0, 10.0, 12.0]]];
FillSample16 [brickM, [[8.0, 1.0, 9.0, 16.0], [6.0, 3.0, 11.0, 14.0], [7.0, 2.0, 10.0, 15.0], [5.0, 4.0, 12.0, 13.0]]];
FillSample16 [brickY, [[8.0, 9.0, 11.0, 4.0], [10.0, 7.0, 3.0, 13.0], [12.0, 2.0, 6.0, 15.0], [1.0, 14.0, 16.0, 5.0]]];
FillSample16 [brickK, [[1.0, 13.0, 15.0, 5.0], [11.0, 2.0, 6.0, 16.0], [9.0, 7.0, 3.0, 14.0], [8.0, 10.0, 12.0, 4.0]]]
END; -- InitBricks
InitBricks [];
Commander.Register [key: "NectarineField", proc: SetField, doc: fieldDoc]
END.
gbb June 6, 1988 3:03:34 pm PDT
Inihibtion of scaling when fieldHasBeenSet.
changes to: DIRECTORY, IMPORTS, OPEN, PdPrintProcess, argError, fieldHasBeenSet, SetField
gbb October 13, 1988 2:43:31 pm PDT
Changed ajustement of margin for PD printers to be done depending on the bounding box instead of the field.
changes to: PdPrintProcess