CDColorPDPlot.mesa
Jacobi, February 28, 1986 5:18:25 pm PST
Copyright © 1983, 1985 by Xerox Corporation. All rights reserved.
written by E. McCreight, August 1, 1983 2:00 PM
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
DIRECTORY
CD,
CDBasics,
CDCommandOps,
CDDefaultProcs,
CDExtras,
CDIO,
CDViewer,
CDPolygons,
CDMenus,
CDOps,
CDOrient,
CDProperties,
CDSequencer,
CDValue,
GraphicsBasic,
CGArea,
CGClipper,
CGReducer,
Commander,
CornerStitching,
Imager,
IO,
PDFileFormat,
PDFileWriter,
Process,
Real,
Rope,
TerminalIO,
ViewerClasses,
ViewerSpecs;
CDColorPDPlot: CEDAR PROGRAM
IMPORTS CD, CDBasics, CDCommandOps, CDDefaultProcs, CDExtras, CDIO, CDMenus, CDValue, CDViewer, CDOps, CDOrient, CDPolygons, CDProperties, CDSequencer, CGArea, CGClipper, CGReducer, Commander, CornerStitching, Imager, IO, PDFileWriter, Process, Real, TerminalIO =
BEGIN
plottingInProgress: BOOLFALSE;
--handling colors
Toner: TYPE = PDFileFormat.Toner; -- {black, cyan, magenta, yellow, .. 15};
TonerKeys: TYPE = ARRAY Toner OF REF;
LoadArray: TYPE = ARRAY Toner OF PDFileWriter.LoadReference;
ColorDescription: TYPE = ARRAY CD.Layer OF REF LoadArray ← ALL[NIL];
whiteLoadRef: PDFileWriter.LoadReference = LAST[PDFileWriter.LoadReference];
-- used to identify tiles without toner so that you can avoid recording them
tonerToKeyKeys: REF TonerKeys = NEW[TonerKeys ← ALL[NIL]];
--gives a key to get the keys to get the color stipple as property of the layers
--device description
deviceCode: PDFileFormat.DeviceCode ← last;
sRes: CARDINAL ← 200; -- resolution (slow directition), pixels / inch
fRes: CARDINAL ← 200; -- resolution (fast direction), pixels / inch
scanLineWidth: CARDINAL ← 8000; --for the wide-bed Versatec, length in the "fast" direction;
toners: PDFileWriter.TonerSet ← ALL[FALSE];
leftOverMode: BOOLFALSE;
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: BOOLFALSE;
slowLimited: BOOLFALSE; --only interesting if ~paged
pageSlowSize: CARDINAL ← 0; --only interesting if paged or slowLimited
stippleKey: ATOM ← $CDxVersatec;
tonerToKey: REF TonerKeys ← NIL;
--gives a key to get the color stipple as property of the layers
ColorVersatec: PROC [] =
BEGIN
deviceCode ← last; --does not yet has an assigned value, use "last"
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;
toners ← ALL[FALSE];
toners[black] ← TRUE;
toners[cyan] ← TRUE;
toners[magenta] ← TRUE;
toners[yellow] ← TRUE;
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 ← slowLimited ← FALSE;
leftOverMode ← FALSE;
stippleKey ← $CDxVersatec;
TerminalIO.WriteRope["color versatec"];
END;
InkJetC150: PROC [] =
BEGIN
deviceCode ← VAL[10];
sRes ← 120; -- resolution (slow directition), pixels / inch
fRes ← 120; -- resolution (fast direction), pixels / inch
scanLineWidth ← 1020;
toners ← ALL[FALSE];
toners[black] ← TRUE;
toners[cyan] ← TRUE;
toners[magenta] ← TRUE;
toners[yellow] ← TRUE;
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;
stippleKey ← $CDxVersatec;
TerminalIO.WriteRope["ink jet"];
END;
Color400: PROC [] =
BEGIN
deviceCode ← VAL[9];
sRes ← 400; -- resolution (slow directition), pixels / inch
fRes ← 400; -- resolution (fast direction), pixels / inch
scanLineWidth ← 4096;
toners ← ALL[FALSE];
toners[black] ← TRUE;
toners[cyan] ← TRUE;
toners[magenta] ← TRUE;
toners[yellow] ← TRUE;
bandSSize ← 50; --
overLap ← 30; -- number of pixels by which to overlap strips
maxPixPerLambda ← 240; -- maximum # of pixels to make lambda
paged ← TRUE;
pageSlowSize ← 5500;
leftOverMode ← FALSE;
stippleKey ← $CDxC400;
TerminalIO.WriteRope["Color400"];
END;
Puffin: PROC [] =
BEGIN
deviceCode ← PDFileFormat.DeviceCode[puffin];
sRes ← 384; -- resolution (slow directition), pixels / inch
fRes ← 384; -- resolution (fast direction), pixels / inch
scanLineWidth ← fRes * 17 / 2;
toners ← ALL[FALSE];
toners[black] ← FALSE;
toners[cyan] ← TRUE;
toners[magenta] ← TRUE;
toners[yellow] ← TRUE;
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;
stippleKey ← $CDxPuffin;
TerminalIO.WriteRope["Puffin"];
END;
PlateMaker: PROC [] =
BEGIN
deviceCode ← PDFileFormat.DeviceCode[last];
sRes ← 1200; -- resolution (slow directition), pixels / inch
fRes ← 1200; -- resolution (fast direction), pixels / inch
scanLineWidth ← fRes * 17 / 2;
toners ← ALL[FALSE];
toners[black] ← TRUE;
toners[cyan] ← FALSE;
toners[magenta] ← FALSE;
toners[yellow] ← FALSE;
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;
stippleKey ← $CDxRaven;
TerminalIO.WriteRope["Raven or platemaker"];
END;
--state of the plot
technologyPropertyKey: REF ← $CDxLastTechnology; --a property of the stippleKey
abortPlot: REF BOOLNEW[BOOLFALSE];
PlotStateRef: TYPE = REF PlotState;
PlotState: TYPE = RECORD [
tes: ARRAY CD.Layer OF REF CornerStitching.Tesselation ← ALL[NIL],
scale: REAL ← 1.0, -- pixels per CD.Number
totalPlotClip, bandClip: CD.Rect ← [0, 0, 0, 0],
--rectangles in design space touching all geometry in the plot, or this band
pdState: PDFileWriter.PDState,
colorLoads: REF ColorDescription,
anouncedLayer: INT ← -1
];
pdy: CARDINAL ← 0;  -- top of band in pixel coords
xoffset: INT ← -stripClip.x1*scale;
yoffset: INT ← stripClip.y2*scale;
stripClip: CD.Rect;  -- clip for a page; not reduced to real design clip
plotScale: REAL;
imageSSize: CARDINAL;
imageFSize: CARDINAL;
ps: PlotStateRef;
PrepareContextFilter: PROC [] =
BEGIN
contextFilter^ ← ALL[NIL];
FOR l: CD.Layer IN CD.Layer DO
FOR toner: Toner IN Toner DO
IF tonerToKey[toner]#NIL AND CDProperties.GetPropFromLayer[from: l, prop: tonerToKey[toner]]#NIL THEN {
contextFilter^[l] ← Imager.black;
EXIT
};
ENDLOOP;
ENDLOOP;
END;
CheckStipples: PROC [technology: CD.Technology] =
BEGIN
x: REF ← CDValue.Fetch[technology, stippleKey];
WITH x SELECT FROM
r: Rope.ROPE => TerminalIO.WriteRopes["color stipples used: [", r, "]\n"];
ENDCASE => {
TerminalIO.WriteRope["**color stipples are not defined\n"];
ERROR ABORTED
};
IF technology.key#CDProperties.GetPropFromAtom[stippleKey, technologyPropertyKey] THEN
TerminalIO.WriteRope["**Warning: another technology registered in the meantime; the technology independent stipples are redefined\n"];
tonerToKey ← NEW[TonerKeys ← ALL[NIL]];
FOR t: PDFileWriter.Toner IN PDFileWriter.Toner DO
tonerToKey^[t] ← CDProperties.GetPropFromAtom[stippleKey, tonerToKeyKeys[t]];
IF ~toners[t] OR tonerToKey^[t]=NIL THEN {
toners[t] ← FALSE;
tonerToKey^[t] ← NEW[INT];
}
ENDLOOP;
PrepareContextFilter[];
END;
ClipArea: PROC [comm: CDSequencer.Command] RETURNS [plotClip: CD.Rect] =
BEGIN
SELECT TerminalIO.RequestSelection["Plot", LIST["complete design", "rectangle"]] FROM
2 => {
plotClip ← CDBasics.ToRect[comm.pos, comm.sPos];
TerminalIO.WriteRope["plot rectangle\n"];
};
ENDCASE => {
plotClip ← CDExtras.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
};
END;
ProtectedPlotDesign: PROC [comm: CDSequencer.Command] =
BEGIN
--ENABLE UNWIND => plottingInProgress ← FALSE;
--dont, we better wait longer...
design: CD.Design = comm.design;
plotClip: CD.Rect;
plotSize: CD.Position;
s: IO.STREAMNIL;
strips: INT;
plottingInProgress ← TRUE;
TerminalIO.WriteRope["Starting Color plot for "];
SELECT comm.a FROM
$VersatecColorPlot => ColorVersatec[];
$C150ColorPlot => InkJetC150[];
$PuffinColorPlot => Puffin[];
$PlatemakerColorPlot => PlateMaker[];
$Color400Plot => Color400[];
ENDCASE => ERROR;
TerminalIO.WriteLn[];
CheckStipples[design.technology];
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]];
BEGIN
ENABLE { -- for ERRORs
UNWIND => {
s ← AbortFile[s];
CDViewer.RemoveArrow[design];
TerminalIO.WriteRope[" ** plot aborted ** "]
};
};
dr: CD.DrawRef = CD.CreateDrawRef[design];
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,
colorLoads: NEW[ColorDescription ← ALL[NIL]]
]];
pageStep ← [plotSize.x/strips, plotSize.y];
pageWidth ← [Real.Round[scanLineWidth/scale], plotSize.y];
plotScale ← scale;
dr.minimalSize ← 0;
dr.stopFlag ← abortPlot;
dr.drawRect ← NoteRectangle;
dr.drawContext ← DrawContext;
dr.contextFilter ← contextFilter;
dr.devicePrivate ← ps;
FOR strip: INT IN [0..strips) DO
localFileName: Rope.ROPE = CDIO.MakeName[wDir: "///temp/", base: "plot", modifier: IO.PutFR["%d", IO.int[strip+1]], ext: "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: deviceCode,
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
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
CDViewer.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
CornerStitching.ChangeRect[plane: ps.tes[l], rect: CDBasics.universe, newValue: 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"];
CDViewer.RemoveArrow[design: design];
plottingInProgress ← FALSE;
EXITS
AbortPlot => {
s ← AbortFile[s];
CDViewer.RemoveArrow[design];
TerminalIO.WriteRope[" ** plot aborted ** "];
};
END; -- enable
END; -- PlotDesign
NoteRectangle: PROC [r: CD.Rect, l: CD.Layer, pr: CD.DrawRef] =
BEGIN
ps: PlotStateRef = NARROW[pr.devicePrivate];
IF CDBasics.NonEmpty[r] THEN {
IF ps.tes[l]=NIL THEN ps.tes[l] ← CornerStitching.NewTesselation[];
ps.tes[l].ChangeRect[rect: r, newValue: $covered];
};
END;
SetColor: PROC [ps: PlotStateRef, lev: CD.Layer] =
BEGIN
Stipple16: TYPE = ARRAY[0..16) OF CARDINAL;
Stipple8: TYPE = ARRAY[0..8) OF [0..256);
Stipple4: TYPE = ARRAY[0..4) OF [0..16);
ToTexture: PROC [pattern: REF ANY] RETURNS [texture: Stipple16] =
--tries to convert pattern to a texture stipple
BEGIN
IF pattern=NIL THEN RETURN[Stipple16[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]]; -- should not occur
WITH pattern SELECT FROM
s16: REF Stipple16 => texture ← s16^;
s8: REF Stipple8 =>
FOR i: [0..8) IN [0..8) DO
texture[i] ← texture[i+8] ← (256+1)*s8[i];
ENDLOOP;
s4: REF 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 => RETURN[Stipple16[1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0FFFFH]]; -- error texture
RETURN [texture]
END; -- ToTexture
MakeLoadref: PROC [pattern: REF ANY] RETURNS [loadRef: PDFileWriter.LoadReference] =
TRUSTED BEGIN
texture: Stipple16 ← ToTexture[pattern];
loadRef ← PDFileWriter.LoadContiguousColorTile[pdState: ps.pdState, phase: 0, sMin: 0, fMin: 0, sSize: 16, fSize: 16, bitsPtr: @texture];
END; -- MakeLoadref
MakeLoad: PROC [ps: PlotStateRef, lev: CD.Layer] =
--makes the load if it does not already exist
BEGIN
IF ps.colorLoads^[lev]=NIL THEN {
ps.colorLoads^[lev] ← NEW[LoadArray];
FOR toner: Toner IN Toner DO
tex: REF ← CDProperties.GetPropFromLayer[from: lev, prop: tonerToKey[toner]];
IF tex=NIL THEN ps.colorLoads^[lev][toner] ← whiteLoadRef
ELSE ps.colorLoads^[lev][toner] ← MakeLoadref[tex]
ENDLOOP;
};
END; --MakeLoad
--SetColor
IF ps.anouncedLayer=lev THEN RETURN;
IF ps.colorLoads^[lev]=NIL THEN MakeLoad[ps, lev];
FOR toner: Toner IN 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
END;
contextFilter: REF CD.ContextFilter = NEW[CD.ContextFilter←ALL[Imager.black]];
PlotPolygon: PROC [ob: CD.Object, pos: CD.Position, orient: CD.Orientation] =
BEGIN
OutputTrapezoid: PROCEDURE [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];
CornerStitching.EnumerateArea[plane: ps.tes[lev], rect: ps.bandClip, perTile: ProcessTile, data: ps];
};
ENDLOOP;
END;
ProcessTile: PROCEDURE [tile: REF CornerStitching.Tile, data: REF ANY] =
--CornerStitching.PerTileProc
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;
AbortFile: PROC [s: IO.STREAM] RETURNS [IO.STREAM] = {
IF s#NIL THEN s.Close[abort: TRUE];
RETURN[NIL]
};
PDColorPlotComm: PROC [comm: CDSequencer.Command] =
BEGIN
TerminalIO.WriteRope["Color plot\n"];
[] ← CDCommandOps.CallWithResource[ProtectedPlotDesign, comm, $ColorPlot, abortPlot];
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;
Init: PROC [] =
BEGIN
tonerToKeyKeys[black] ← $CDxColorPDPlotBlack;
tonerToKeyKeys[cyan] ← $CDxColorPDPlotCyan;
tonerToKeyKeys[magenta] ← $CDxColorPDPlotMagenta;
tonerToKeyKeys[yellow] ← $CDxColorPDPlotYellow;
CDSequencer.ImplementCommand[a: $VersatecColorPlot, p: PDColorPlotComm, queue: doQueue];
CDSequencer.ImplementCommand[a: $C150ColorPlot, p: PDColorPlotComm, queue: doQueue];
CDSequencer.ImplementCommand[a: $Color400Plot, p: PDColorPlotComm, queue: doQueue];
CDSequencer.ImplementCommand[a: $PuffinColorPlot, p: PDColorPlotComm, queue: doQueue];
CDSequencer.ImplementCommand[a: $PlatemakerColorPlot, p: PDColorPlotComm, queue: doQueue];
CDMenus.CreateEntry[$HardCopyMenu, "PD Color Versatec", $VersatecColorPlot];
CDMenus.CreateEntry[$HardCopyMenu, "PD C150", $C150ColorPlot];
CDMenus.CreateEntry[$HardCopyMenu, "PD Puffin, (1 page)", $PuffinColorPlot];
CDMenus.CreateEntry[$HardCopyMenu, "PD Platemaker", $PlatemakerColorPlot];
CDMenus.CreateEntry[$HardCopyMenu, "PD Color400", $Color400Plot];
Commander.Register[
key: "CDWaitPlotFinished",
proc: WaitPlotFinishedCommand,
doc: "waits until ChipNDale pd plotting is finished"
];
TerminalIO.WriteRope["ChipNDale color plot program loaded\n"];
END;
Init[];
END.