CDPlotPDImpl.mesa
Copyright © 1983, 1985 by Xerox Corporation. All rights reserved.
written by E. McCreight, August 1, 1983 2:00 PM
Last Edited by: Jacobi, October 23, 1985 12:33:24 pm PDT
Last Edited by: McCreight, November 23, 1983 4:58 pm
Last Edited by: Jacobi, October 27, 1983 12:36 pm
Last Edited by: Jacobi, April 11, 1985 3:21:48 pm PST
Last Edited by: Kimr, October 29, 1984 9:49:48 am PST
Last Edited by: Curry, March 27, 1986 7:57:50 pm PST
DIRECTORY
CD, CDBasics, CDCommandOps, CDDefaultProcs, CDMenus, CDOps, CDOrient, CDPlot, CDPolygons, CDSequencer, CDVArrow, CGArea, CGClipper, CGReducer, Commander, CStitching, GraphicsBasic, IO, PDFileFormat, PDFileWriter, PeachPrint, Process, Real, Rope, TerminalIO, ViewerClasses, ViewerSpecs;
CDPlotPDImpl: CEDAR PROGRAM
IMPORTS CD, CDBasics, CDCommandOps, CDDefaultProcs, CDMenus, CDOps, CDOrient, CDPlot, CDPolygons, CDSequencer, CDVArrow, CGArea, CGClipper, CGReducer, Commander, CStitching, IO, PDFileWriter, PeachPrint, Process, Real, TerminalIO =
BEGIN
--handling colors
stipples:   REF CDPlot.LayerTonerSipples ← NIL;
whiteLoadRef: PDFileWriter.LoadReference = LAST[PDFileWriter.LoadReference]; -- blank tile ID
--device description
printerType:   CDPlot.PrinterType ← nil;
toners:    PDFileWriter.TonerSet  ← ALL[FALSE];
sRes:     CARDINAL ← 200; -- resolution (slow directition), pixels / inch
fRes:     CARDINAL ← 200; -- resolution (fast direction), pixels / inch
scanLineWidth:  CARDINAL ← 8000; --for wide-bed Versatec, length in the "fast" direction;
leftOverMode:  BOOL   ← FALSE;
bandSSize:   CARDINAL ← 64; -- number chosen because of buffer-size of versatec
overLap:    CARDINAL ← 300; -- number of pixels by which to overlap strips
maxPixPerLambda: NAT   ← 20; -- maximum # of pixels to make lambda
paged:    BOOL   ← FALSE;
slowLimited:   BOOL   ← FALSE; --only interesting if ~paged
pageSlowSize:  CARDINAL ← 0;
F: BOOL = FALSE;
PrinterToners: TYPE = ARRAY CDPlot.PrinterType OF PDFileWriter.TonerSet;
printerToners: PrinterToners ← [
--          black cyan  mag yellow
nil:    [F,  F,  F,  F,  F,F,F,F,F,F,F,F,F,F,F,F],
raven300:   [TRUE, F,  F,  F,  F,F,F,F,F,F,F,F,F,F,F,F],
raven384:   [TRUE, F,  F,  F,  F,F,F,F,F,F,F,F,F,F,F,F],
o3:     [F,  F,  F,  F,  F,F,F,F,F,F,F,F,F,F,F,F],
plateMaker:  [TRUE, F,  F,  F,  F,F,F,F,F,F,F,F,F,F,F,F],
o5:     [F,  F,  F,  F,  F,F,F,F,F,F,F,F,F,F,F,F],
puffin:   [F,  TRUE, TRUE, TRUE, F,F,F,F,F,F,F,F,F,F,F,F],
colorVersatec: [TRUE, TRUE, TRUE, TRUE, F,F,F,F,F,F,F,F,F,F,F,F],
versatec:   [TRUE, F,  F,  F,  F,F,F,F,F,F,F,F,F,F,F,F],
color400:   [TRUE, TRUE, TRUE, TRUE, F,F,F,F,F,F,F,F,F,F,F,F],
c150:    [TRUE, TRUE, TRUE, TRUE, F,F,F,F,F,F,F,F,F,F,F,F],
d4020:    [F,  F,  F,  F,  F,F,F,F,F,F,F,F,F,F,F,F], -- ???
bw400:   [TRUE, F,  F,  F,  F,F,F,F,F,F,F,F,F,F,F,F],
o13:    [F,  F,  F,  F,  F,F,F,F,F,F,F,F,F,F,F,F],
o14:    [F,  F,  F,  F,  F,F,F,F,F,F,F,F,F,F,F,F],
o15:    [F,  F,  F,  F,  F,F,F,F,F,F,F,F,F,F,F,F] ];
ColorVersatec: PROC [] = {
sRes     ← 200; -- resolution (slow directition), pixels / inch
fRes     ← 200; -- resolution (fast direction), pixels / inch
scanLineWidth  ← 8000; --for the wide-bed Versatec, length in the "fast" direction;
bandSSize   ← 64; -- number chosen because of buffer-size of versatec
overLap    ← 300; -- number of pixels by which to overlap strips
maxPixPerLambda ← 20; -- maximum # of pixels to make lambda
paged     ← FALSE;
slowLimited   ← FALSE;
leftOverMode  ← FALSE;
TerminalIO.WriteRope["color versatec"] };
InkJetC150: PROC [] = {
sRes     ← 120; -- resolution (slow directition), pixels / inch
fRes     ← 120; -- resolution (fast direction), pixels / inch
scanLineWidth  ← 1020;
bandSSize   ← 48; --
overLap    ← 30; -- number of pixels by which to overlap strips
maxPixPerLambda ← 20; -- maximum # of pixels to make lambda
paged     ← FALSE;
slowLimited   ← TRUE;
pageSlowSize   ← 1020;
leftOverMode  ← FALSE;
TerminalIO.WriteRope["ink jet"] };
Color400: PROC [] = {
sRes     ← 400; -- resolution (slow directition), pixels / inch
fRes     ← 400; -- resolution (fast direction), pixels / inch
scanLineWidth  ← 4096;
bandSSize   ← 50; --
overLap    ← 30; -- number of pixels by which to overlap strips
maxPixPerLambda ← 60; -- maximum # of pixels to make lambda
paged     ← TRUE;
pageSlowSize   ← 5500;
leftOverMode  ← FALSE;
TerminalIO.WriteRope["Color400"] };
Puffin: PROC [] = {
sRes     ← 384; -- resolution (slow directition), pixels / inch
fRes     ← 384; -- resolution (fast direction), pixels / inch
scanLineWidth  ← fRes * 17 / 2;
bandSSize   ← 16; --
overLap    ← 30; -- number of pixels by which to overlap strips
maxPixPerLambda ← 20; -- maximum # of pixels to make lambda
paged     ← TRUE;
pageSlowSize   ← sRes*11;
leftOverMode  ← TRUE;
TerminalIO.WriteRope["Puffin"] };
PlateMaker: PROC [] = {
sRes     ← 1200; -- resolution (slow directition), pixels / inch
fRes     ← 1200; -- resolution (fast direction), pixels / inch
scanLineWidth  ← fRes * 17 / 2;
bandSSize   ← 16; --
overLap    ← 30; -- number of pixels by which to overlap strips
maxPixPerLambda ← 20; -- maximum # of pixels to make lambda
paged     ← TRUE;
pageSlowSize   ← sRes*11;
leftOverMode  ← TRUE;
TerminalIO.WriteRope["Raven or platemaker"] };
--state of the plot
abortPlot:    REF BOOLNEW[BOOLFALSE];
plottingInProgress: BOOLFALSE;
pdy:     CARDINAL ← 0;  -- top of band in pixel coords
stripClip:    CD.Rect;   -- clip for a page; not reduced to real design clip
plotScale:    REAL;
imageSSize:   CARDINAL;
imageFSize:   CARDINAL;
ps:    PlotStateRef;
PlotStateRef: TYPE = REF PlotState;
PlotState:  TYPE = RECORD [
tes:    ARRAY CD.Layer OF CStitching.Tesselation ← ALL[NIL],
scale:    REAL ← 1.0, -- pixels per CD.Number
bandClip:   CD.Rect ← [0, 0, 0, 0], -- design space rect, touches all geometry in band
totalPlotClip:  CD.Rect ← [0, 0, 0, 0], -- design space rect, touches all geometry in plot
pdState:   PDFileWriter.PDState,
stipples:   REF CDPlot.LayerTonerSipples, -- tidy sequence
colorLoads:  REF CDPlot.LayerTonerLoadRef, -- stipples expanded into LoadRefs
anouncedLayer: INT ← -1 ];
ClipArea: PROC [comm: CDSequencer.Command] RETURNS [plotClip: CD.Rect] = {
SELECT TerminalIO.RequestSelection["Plot", LIST["complete design", "rectangle"]] FROM
2 => {
plotClip ← CDBasics.ToRect[comm.pos, comm.sPos];
TerminalIO.WriteRope["plot rectangle\n"] };
ENDCASE => {
plotClip ← CDCommandOps.BoundingBox[comm.design];
TerminalIO.WriteRope["plot all\n"] };
IF plotClip.x1>=plotClip.x2 OR plotClip.y1>=plotClip.y2 THEN {
TerminalIO.WriteRope["**cannot plot empty area\n"];
ERROR ABORTED } };
ProtectedAutoPlot: PROC [comm: CDSequencer.Command] = {
design:  CD.Design = comm.design;
plotClip:  CD.Rect;
plotSize:  CD.Position;
strips:   INT ← 1;
pdc:   REF CDPlot.PDControlRec;
IF comm=NIL OR comm.data=NIL THEN RETURN;
pdc     ← NARROW[comm.data];
strips     ← pdc.stripes;
plotClip    ← pdc.clip;
printerType   ← pdc.ipType;
plottingInProgress ← TRUE;
TerminalIO.WriteRope["Starting Color plot for "];
SELECT printerType FROM
colorVersatec => ColorVersatec[];
c150   => InkJetC150[];
puffin  => Puffin[];
plateMaker => PlateMaker[];
color400  => Color400[];
ENDCASE  => ERROR;
toners  ← printerToners[printerType];
stipples ← CDPlot.GetStipples[design, printerType];
TerminalIO.WriteLn[];
plotSize ← CDBasics.SizeOfRect[plotClip];
IF plotSize.x<=0 OR plotSize.y<=0
THEN {TerminalIO.WriteRope["**cannot plot empty area\n"]; RETURN};
TRUSTED {Process.SetPriority[Process.priorityBackground]};
PlotDesignBasic[design, plotClip, plotSize, strips]};
ProtectedPlotDesign: PROC [comm: CDSequencer.Command] = {
design: CD.Design = comm.design;
plotClip: CD.Rect;
plotSize: CD.Position;
strips:  INT;
plottingInProgress ← TRUE;
TerminalIO.WriteRope["Starting Color plot for "];
SELECT comm.key FROM
$VersatecColorPlot  => {printerType ← colorVersatec; ColorVersatec[]};
$C150ColorPlot   => {printerType ← c150;   InkJetC150[]};
$PuffinColorPlot   => {printerType ← puffin;   Puffin[]};
$PlatemakerColorPlot => {printerType ← plateMaker; PlateMaker[]};
$Color400Plot    => {printerType ← color400;  Color400[]};
ENDCASE     => ERROR;
toners  ← printerToners[printerType];
stipples ← CDPlot.GetStipples[design, printerType];
PrepareContextFilter[];
TerminalIO.WriteLn[];
plotClip ← ClipArea[comm];
plotSize ← CDBasics.SizeOfRect[plotClip];
TRUSTED {Process.SetPriority[Process.priorityBackground]};
strips  ← 1;
IF ~paged AND ~slowLimited THEN {
IF TerminalIO.Confirm[label: "plot multiple vertical strips", choice: "yes"] THEN
strips ← TerminalIO.RequestInt["How many vertical strips? [1..10] "]};
strips ← MAX[1, MIN[10, strips]];
PlotDesignBasic[design, plotClip, plotSize, strips]};
PlotDesignBasic: PROC[
design:  CD.Design,
plotClip:  CD.Rect,
plotSize:  CD.Position,
strips:   INT] = {
ENABLE { -- for ERRORs
UNWIND => {
CDVArrow.RemoveArrow[design];
TerminalIO.WriteRope[" ** plot aborted ** "]} };
dr: CD.DrawRef = CD.CreateDrawRef[[
design:  design,
stopFlag:  abortPlot,
drawRect:  NoteRectangle,
drawContext: DrawContext,
contextFilter: contextFilter ]];
scale: REALMIN[
REAL[maxPixPerLambda] / design.technology.lambda,
REAL[(scanLineWidth-overLap)*strips+overLap] / plotSize.x
];
--Center the x range of the selected area of the design on the plotter bed, with at most maxPixPerLambda pixels per lambda. If multiple strips are called for, overlap adjacent ones by "overLap" pixels.
-- total number of pixels across plot = REAL[scanLineWidth]+REAL[scanLineWidth-overLap]*(strips-1))
pageStep: CD.Position;
pageWidth: CD.Position;
imageFSize ← scanLineWidth;
imageSSize ← Real.FixC[plotSize.y*scale]+1;
IF paged THEN {
imageSSize ← MIN[imageSSize, pageSlowSize];
scale   ← MIN[scale, REAL[pageSlowSize]/(plotSize.y+1)] };
ps ← NEW[PlotState ← [
scale:   scale,
totalPlotClip: plotClip,
stipples:  stipples,
colorLoads: NEW[CDPlot.LayerTonerLoadRef ← ALL[NIL]] ]];
pageStep   ← [plotSize.x/strips, plotSize.y];
pageWidth  ← [Real.Round[scanLineWidth/scale], plotSize.y];
plotScale   ← scale;
dr.devicePrivate ← ps;
FOR strip: INT IN [0..strips) DO
localFileName: Rope.ROPE = PeachPrint.FileName[long, primary, strip+1, ".pd"];
TerminalIO.WriteRopes["Recording strip on file ", localFileName, "\n"];
stripClip ← [ --but not yet intersected with complete design clip
x1: plotClip.x1+strip*pageStep.x,
y1: plotClip.y1,
x2: plotClip.x1+strip*pageStep.x+pageWidth.x,
y2: plotClip.y2 ];
ps.pdState ← PDFileWriter.Create[
fileName: localFileName,
deviceCode: LOOPHOLE[printerType],
sResolution: sRes,
fResolution: fRes,
imageSSize: imageSSize,
imageFSize: imageFSize,
bandSSize: bandSSize,
leftOverMode: leftOverMode ];
ps.colorLoads^ ← ALL[NIL];
PDFileWriter.StartImage[pdState: ps.pdState, toners: toners];
-- For each band in the strip
FOR bandYtop: INT ← 0, bandYtop+bandSSize WHILE bandYtop<imageSSize DO
dc: CD.Rect; --clip for band in design coordinates; little larger than band
Process.CheckForAbort[! ABORTED => {abortPlot^ ← TRUE; CONTINUE}];
IF abortPlot^ THEN GOTO AbortPlot;
-- Determine coordinate transformations
pdy ← bandYtop;
dc ← CDBasics.NormalizeRect[[
x1: stripClip.x1-1,
y1: stripClip.y2-Real.Fix[(bandYtop+bandSSize)/scale]-1,
x2: stripClip.x1+Real.Fix[scanLineWidth/scale]+1,
y2: stripClip.y2-Real.Fix[bandYtop/scale]+1 ]] ;
dr.interestClip ← ps.bandClip ← CDBasics.Intersection[plotClip, dc];
--Display current band under consideration to pacify user
CDVArrow.ShowArrow[design: design, pos: [
x: (dr.interestClip.x1+dr.interestClip.x2)/2,
y: (dr.interestClip.y1+dr.interestClip.y2)/2] ];
-- clear previous tessalations
ps.anouncedLayer ← -1;
FOR l: CD.Layer IN CD.Layer DO
IF ps.tes[l]#NIL THEN
CStitching.ChangeRect[plane: ps.tes[l], rect: CDBasics.universe, new: NIL];
ENDLOOP;
CDOps.DrawDesign[design, dr]; -- build tesselations of the relevant design rectangle
AnalyzeTesselations[ps]; --will actually draw
TerminalIO.WriteRope["."];
ENDLOOP; -- for each band in the strip
PDFileWriter.EndPage[ps.pdState];
PDFileWriter.Close[ps.pdState];
TerminalIO.WriteRope["*\n"];
ENDLOOP; -- for each strip
TerminalIO.WriteRope[" finished plot(s)\n"];
TerminalIO.WriteF[" Example usage:\n PeachPrint Sleepy %g ",
IO.rope[ PeachPrint.FileName[long, primary, 1, ".pd"]]];
CDVArrow.RemoveArrow[design: design];
plottingInProgress ← FALSE;
EXITS
AbortPlot => {
CDVArrow.RemoveArrow[design];
TerminalIO.WriteRope[" ** plot aborted ** "] };
}; -- PlotDesign
NoteRectangle: PROC [r: CD.Rect, l: CD.Layer, pr: CD.DrawRef] = {
ps: PlotStateRef = NARROW[pr.devicePrivate];
IF CDBasics.NonEmpty[r] THEN {
IF ps.tes[l]=NIL THEN ps.tes[l] ← CStitching.NewTesselation[];
ps.tes[l].ChangeRect[rect: r, new: $covered]} };
SetColor: PROC [ps: PlotStateRef, lev: CD.Layer] = {
MakeLoadref: PROC [pattern: REF ANY] RETURNS [loadRef: PDFileWriter.LoadReference] =
TRUSTED {
texture:  CDPlot.Stipple16;
texturePtr: LONG POINTER TO CDPlot.Stipple16 ← @texture;
longPtr:  LONG POINTERLOOPHOLE[texturePtr];
IF pattern=NIL THEN texture ← ALL[0]; -- error
WITH pattern SELECT FROM
s16: REF CDPlot.Stipple16 => texture ← s16^;
s8: REF CDPlot.Stipple8 =>
FOR i: [0..8) IN [0..8) DO
texture[i] ← texture[i+8] ← (256+1)*s8[i];
ENDLOOP;
s4: REF CDPlot.Stipple4 =>
FOR i: [0..4) IN [0..4) DO
texture[i] ← texture[i+4] ← texture[i+8] ← texture[i+12] ← s4[i]*1111H;
ENDLOOP;
ENDCASE => texture ← [1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0FFFFH]; -- error
loadRef ← PDFileWriter.LoadContiguousColorTile[pdState: ps.pdState, phase: 0, sMin: 0, fMin: 0, sSize: 16, fSize: 16, bitsPtr: longPtr] };
MakeLoad: PROC [ps: PlotStateRef, lev: CD.Layer] = {
IF ps.colorLoads^[lev]=NIL THEN { -- makes the load if it does not already exist
ps.colorLoads^[lev] ← NEW[CDPlot.TonerLoadRef];
FOR toner: CDPlot.Toner IN CDPlot.Toner DO
tex: REFIF ps.stipples.size<=lev THEN NIL ELSE ps.stipples[lev][toner];
ps.colorLoads^[lev][toner] ← IF tex=NIL THEN whiteLoadRef ELSE MakeLoadref[tex]
ENDLOOP } };
--SetColor
IF ps.anouncedLayer=lev THEN RETURN;
IF ps.colorLoads^[lev]=NIL THEN MakeLoad[ps, lev];
FOR toner: CDPlot.Toner IN CDPlot.Toner DO
IF ps.colorLoads^[lev][toner] = whiteLoadRef
THEN PDFileWriter.SetColorOff[ps.pdState, toner]
ELSE PDFileWriter.SetColorTile[ps.pdState, toner, ps.colorLoads^[lev][toner], transparent];
ENDLOOP;
ps.anouncedLayer ← lev};
contextFilter: REF CD.ContextFilter = NEW[CD.ContextFilter←ALL[TRUE]];
PrepareContextFilter: PROC [] = {
contextFilter^ ← ALL[FALSE];
FOR l: CD.Layer IN [0..stipples.size) DO
FOR toner: CDPlot.Toner IN CDPlot.Toner DO
IF stipples[l][toner]#NIL THEN {contextFilter[l] ← TRUE; EXIT}; ENDLOOP;
ENDLOOP };
PlotPolygon: PROC [ob: CD.Object, pos: CD.Position, orient: CD.Orientation] =
BEGIN
OutputTrapezoid: PROC [xbotL: REAL, xbotR: REAL, ybot: REAL, xtopL: REAL, xtopR: REAL, ytop: REAL] =
--lower left x, lower right x, lower y, upper left x, upper right x, upper y
BEGIN
--global variables ps, stripClip, plotScale, imageFSize, imageSSize, pdy
--x-Fast
--y-Slow
PDFileWriter.MaskTrapezoid[
pdState: ps.pdState,
sMin: Real.RoundC[ybot],
sSize: Real.RoundC[ytop-ybot],
fMin: Real.RoundC[xbotL],
fSize: Real.RoundC[xbotR-xbotL],
fMinLast: Real.RoundC[xtopL],
fSizeLast: Real.RoundC[xtopR-xtopL]
];
END; --OutputTrapezoid
--PlotPolygon
pp: CDPolygons.PolygonPtr = NARROW[ob.specificRef];
polygon: CGReducer.Ref = CGReducer.New[size: 8];
tiling: CGArea.Ref = CGArea.New[size: 4];
clipRef: CGClipper.Ref = CGClipper.New[size: 4];
clip: GraphicsBasic.Box ← [
xmin: 0,
ymin: pdy,
xmax: MIN[(ps.bandClip.x2-stripClip.x1)*plotScale, imageFSize],
ymax: MIN[pdy+bandSSize, imageSSize]
];
CGClipper.SetBox[self: clipRef, box: clip];
CGClipper.Load[self: clipRef, reducer: polygon];
FOR p: LIST OF CD.Position ← pp.points, p.rest WHILE p#NIL DO
at: CD.Position = CDOrient.MapPoint[
pointInCell: p.first,
cellSize: ob.size,
cellInstOrient: orient,
cellInstPos: pos
];
CGReducer.Vertex[self: polygon, v: [
x: (at.x-stripClip.x1)*plotScale,
y: (stripClip.y2-at.y)*plotScale
]]
ENDLOOP;
CGReducer.Close[polygon];
CGReducer.Generate[self: polygon, area: tiling];
UNTIL CGArea.Empty[tiling] DO
t: GraphicsBasic.Trap = CGArea.Remove[tiling];
OutputTrapezoid[t.xbotL, t.xbotR, t.ybot, t.xtopL, t.xtopR, t.ytop];
ENDLOOP;
END; --PlotPolygon
DrawContext: PROC [pr: CD.DrawRef, proc: CD.DrawContextLayerProc, ob: CD.Object, pos: CD.Position, orient: CD.Orientation, layer: CD.Layer] =
BEGIN
IF CDPolygons.IsPolygon[ob] THEN {
SetColor[ps, layer];
PlotPolygon[ob, pos, orient];
}
ELSE CDDefaultProcs.DrawContext[pr, proc, ob, pos, orient, layer]
END;
AnalyzeTesselations: PROC [ps: PlotStateRef] =
BEGIN
FOR lev: CD.Layer IN CD.Layer DO
IF ps.tes[lev]#NIL THEN {
SetColor[ps, lev];
CStitching.EnumerateArea[plane: ps.tes[lev], rect: ps.bandClip, eachTile: ProcessTile, data: ps];
};
ENDLOOP;
END;
ProcessTile: PROC [tile: CStitching.Tile, data: REF ANY] =
BEGIN
IF tile.value = $covered THEN {
rightBound, xStart, xStop, yStart, yStop: INT;
cxStart, cxStop, cyStop, cyStart: CARDINAL;
sSize, fSize: CARDINAL;
ps: PlotStateRef = NARROW[data];
r: CD.Rect = tile.Area;
-- calculate device coords of rectangle
xStart ← Real.Round[(r.x1-stripClip.x1)*plotScale];
yStop ← Real.Round[(stripClip.y2-r.y1)*plotScale];
xStop ← Real.Round[(r.x2-stripClip.x1)*plotScale];
yStart ← Real.Round[(stripClip.y2-r.y2)*plotScale];
-- clip device rectangle
rightBound ← Real.Round[(ps.bandClip.x2-stripClip.x1)*plotScale];
IF xStart>rightBound OR xStop<0 THEN RETURN;
IF yStop<pdy OR yStart>MIN[imageSSize, pdy+bandSSize] THEN RETURN;
-- print device rectangle
cxStart ← MAX[xStart, 0];
cxStop ← MIN[xStop, rightBound, imageFSize];
cyStart ← MAX[yStart, pdy];
cyStop ← MIN[yStop, pdy+bandSSize, imageSSize];
fSize ← cxStop - cxStart;
sSize ← cyStop - cyStart;
IF sSize>0 AND fSize>0 THEN PDFileWriter.MaskRectangle[pdState: ps.pdState, sMin: cyStart, fMin: cxStart, sSize: sSize, fSize: fSize];
};
END;
WaitPlotFinishedCommand: Commander.CommandProc =
BEGIN
prio: Process.Priority = Process.GetPriority[];
IF ~plottingInProgress THEN {
IO.PutRope[cmd.out, " waiting for plot to start"];
WHILE ~plottingInProgress DO
Process.Pause[Process.SecondsToTicks[1]];
ENDLOOP;
IO.PutRope[cmd.out, ". plot started...\n"]
};
Process.SetPriority[Process.priorityBackground];
WHILE plottingInProgress DO
Process.Pause[Process.SecondsToTicks[2]];
ENDLOOP;
Process.SetPriority[prio];
IO.PutRope[cmd.out, " finished\n"]
END;
PDAutoPlotComm: PROC [comm: CDSequencer.Command] = {
TerminalIO.WriteRope["Color plot - non interactive\n"];
[] ← CDCommandOps.CallWithResource[ProtectedAutoPlot, comm, $ColorPlot, abortPlot]};
PDColorPlotComm: PROC [comm: CDSequencer.Command] = {
TerminalIO.WriteRope["Color plot\n"];
[] ← CDCommandOps.CallWithResource[ProtectedPlotDesign, comm, $ColorPlot, abortPlot]};
Init: PROC [] =
BEGIN
OPEN CDS: CDSequencer;
CDS.ImplementCommand[key: $PDAutoPlot,   proc: PDAutoPlotComm, queue: dontQueue];
CDS.ImplementCommand[key: $VersatecColorPlot, proc: PDColorPlotComm, queue: doQueue];
CDS.ImplementCommand[key: $C150ColorPlot,  proc: PDColorPlotComm, queue: doQueue];
CDS.ImplementCommand[key: $Color400Plot,   proc: PDColorPlotComm, queue: doQueue];
CDS.ImplementCommand[key: $PuffinColorPlot,  proc: PDColorPlotComm, queue: doQueue];
CDS.ImplementCommand[key: $PlatemakerColorPlot, proc: PDColorPlotComm, queue: doQueue];
CDMenus.CreateEntry[$HardCopyMenu, "PD Color Versatec",  $VersatecColorPlot];
CDMenus.CreateEntry[$HardCopyMenu, "PD C150",    $C150ColorPlot];
CDMenus.CreateEntry[$HardCopyMenu, "PD Color400",   $Color400Plot];
CDMenus.CreateEntry[$HardCopyMenu, "PD Puffin, (1 page)", $PuffinColorPlot];
CDMenus.CreateEntry[$HardCopyMenu, "PD Platemaker",   $PlatemakerColorPlot];
Commander.Register[
key: "///Commands/CDWaitPlotFinished",
proc: WaitPlotFinishedCommand,
doc: "waits until ChipNDale pd plotting is finished"];
TerminalIO.WriteRope["ChipNDale color plot program loaded.\n"];
END;
Init[];
END.