CDColorVersatecImpl:
CEDAR
MONITOR
IMPORTS Atom, CD, -- CDCallSpecific,-- CDViewer, CDInline, CDOps, CDProperties, CDSequencer, CornerStitching, IO, Menus, PDFileWriter, Process, Real, TerminalIO, VFonts
EXPORTS =
BEGIN
Ink: TYPE = PDFileFormat.Toner; -- {black, cyan, magenta, yellow};
ColorLoad:
TYPE =
ARRAY Ink
OF PDFileWriter.LoadReference;
-- a color associated with a level is a collection of textures associated with inks
TexVector:
TYPE =
ARRAY Ink
OF
CARDINAL;
-- used to generate LoadReferences through indexes, there are four textures to a color
whiteLoadRef: PDFileWriter.LoadReference ←
LAST[PDFileWriter.LoadReference];
-- used to identify tiles without toner
localFile: Rope.ROPE ← "///temp/plot0.pd";
versatec: PDFileFormat.DeviceCode ← last; -- ???
sRes, fRes: CARDINAL ← 200; -- pixels per inch
pdState: PDFileWriter.PDState;
pdx, pdy : CARDINAL ← 0; -- origin of band in pixel coords
cdx, cdy,
-- origin of band in chipndale coords
xoffset, yoffset : INT ← 0; -- offset in transforming bet coord systems
plotScale:
REAL;
-- scale factor between systems, is negative for y
axis due to reversed direction of increasing values
numStipples:
CARDINAL = 27;
-- number of stipple patterns defined by MakeLoadref
texValue:
REF
ARRAY [0..100]
OF PDFileWriter.LoadReference
← NEW[ARRAY [0..100] OF PDFileWriter.LoadReference] ;
-- used to make sure that a given texture is only put into the load once
ColorRef: TYPE = REF ColorLoad←NIL;
maxScanLineWidth:
CARDINAL = 8000;
the wide-bed Versatec, length in the "fast" direction
scanLineWidth: CARDINAL ← maxScanLineWidth;
imageSSize: REAL ← 0;
imageFSize: CARDINAL ← maxScanLineWidth;
bandSSize: CARDINAL ← 64;
debugging: BOOL ← FALSE;
numBands, numRectangles: INT ← 0;
PlotStateRef: TYPE = REF PlotState;
PlotState:
TYPE =
RECORD [
text: REF CornerStitching.Tesselation ← NIL,
tes: ARRAY CD.Level OF REF CornerStitching.Tesselation ← ALL[NIL],
-- enumerates all the rectangles in a given level
scale: REAL ← 1.0, -- pixels per CD.DesignNumber
totalPlotClip, bandClip:
CD.DesignRect ← [0,0,0,0],
rectangles in design space touching all geometry in the plot, or this band
colorLoads: REF ARRAY CD.Level OF ColorRef
];
currentFlavor: ViewerClasses.ViewerFlavor = $ChipndaleVersatecPlot;
Init:
ENTRY
PROC ~ {
menu: Menus.Menu = Menus.CreateMenu[];
Menus.AppendMenuEntry[menu: menu,
entry: Menus.CreateEntry[name: "AbortPlot", proc: AbortProc, guarded: TRUE]];
CDSequencer.ImplementCommand[a~$VPlotLocal, p~PlotDesignToLocalFile];
CDSequencer.ImplementCommand[a~$VersatecColorPlot, p~PlotDesignToAny];
CDSequencer.ImplementCommand[a~$VPlot, p~PlotDesignToAny];
signalFont ← VFonts.GraphicsFont[VFonts.EstablishFont[family: "Helvetica", size: 18, bold: TRUE]];
TerminalIO.WriteRope["ChipNDale COLOR Versatec plotter loaded\n"];
};
NewPlotName:
PROC [index:
INTEGER]
RETURNS [name: Rope.
ROPE] =
BEGIN
name ← IO.PutFR[ "///temp/plot%d.pd", IO.int[index+1]];
END;
PlotDesignToAny:
ENTRY
PROC [ c: CDSequencer.Command ] =
BEGIN ENABLE UNWIND => NULL;
n: CARDINAL ← 0;
TerminalIO.WriteRope["Color plot\n"];
p: CARDINAL ← TerminalIO.RequestSelection[
label: "Debugging",
choice: LIST["yes", "no"]
];
SELECT p FROM
1 => debugging ← TRUE;
2 => debugging ← FALSE;
ENDCASE => debugging ← FALSE;
n ← 2;
TerminalIO.RequestSelection[
label: "Versatec Plot",
choice: LIST[" plotter", " local", " read name", " remote"]
];
SELECT n
FROM
1 => {
TerminalIO.WriteRope["plotter is not yet implemented\n"];
PlotDesign[c: c, to: plotter]
};
2 => PlotDesign[c: c, to: localFile];
3 => {
TerminalIO.WriteRope[" requestFilename is not yet implemented\n"]
PlotDesign[c: c, to: requestFilename]
};
4 => {
TerminalIO.WriteRope["remote is not yet implemented\n"];
PlotDesign[c: c, to: remoteFile];
};
ENDCASE => TerminalIO.WriteRope["skipped\n"];
END;
PlotDesignToLocalFile:
ENTRY
PROC [ c: CDSequencer.Command ] =
BEGIN ENABLE UNWIND => NULL;
TerminalIO.WriteRope["Color plot to local file\n"];
PlotDesign[c: c, to: localFile];
END;
PlotDesignToRemoteFile:
ENTRY
PROC [ c: CDSequencer.Command ] =
BEGIN ENABLE UNWIND => NULL;
TerminalIO.WriteRope["Color plot to remote file\n"];
PlotDesign[c: c, to: remoteFile];
END;
PlotDesignToPlotter:
ENTRY
PROC [ c: CDSequencer.Command ] =
BEGIN ENABLE UNWIND => NULL;
TerminalIO.WriteRope["Color plot directly to plotter\n"];
PlotDesign[c: c, to: plotter];
END;
signalFont: Graphics.FontRef ← NIL;
viewer: ViewerClasses.Viewer ← NIL;
plotter: Rope.ROPE ← "vice";
plotFileToSpool: Rope.ROPE ← "[vice]<sysdir>plot.pd";
plotFileOnPlotter: Rope.ROPE ← "<sysdir>plot.pd";
plotFileOnLocalMachine: Rope.ROPE ← "plot0.pd";
plotFileOnServer: Rope.ROPE ← "[Luther.alpine]<McCreight.pa>plot.pd";
latestPlotFile: Rope.ROPE ← NIL;
spoolToPlotter: BOOL ← TRUE;
abortPlot: BOOL ← FALSE;
PlotDesign:
INTERNAL
PROC [ c: CDSequencer.Command, to: {localFile, remoteFile, plotter, requestFilename}] =
BEGIN
s: IO.STREAM ← NIL;
n: INT ← TerminalIO.RequestInt["How many vertical strips? [1..10] "];
strips: INT ← MAX[1, MIN[10, n]];
BEGIN
ENABLE
-- for ERRORs
BEGIN
???x.Error =>
BEGIN
TerminalIO.WriteRope[];
GOTO AbortPlot;
END;
UNWIND => {s ← AbortFile[s]; CDViewer.RemoveArrow[design: c.design]; TerminalIO.WriteRope[" ** plot aborted ** "]};
END;
design: CD.Design = c.design;
plotClip:
CD.DesignRect = CDInline.ToRect[c.pos, c.sPos];
-- takes the right and left sides of the square outlined by
-- the user and returns normalized rectangle coordinates
dr: CD.DrawRef = CD.NewNullDeviceDrawRef[design];
scale:
REAL ←
MIN[32.0/
CD.lambda, (
REAL[scanLineWidth]+
REAL[scanLineWidth-150]*(strips-1))/(plotClip.x2-plotClip.x1)];
Center the x range of the selected area of the design on the plotter bed, with at most 32 pixels per lambda. If multiple strips are called for, overlap adjacent ones by 150 pixels.
-- total number of pixels in plot = REAL[scanLineWidth]+REAL[scanLineWidth-150]*(strips-1))
-- total width of design = plotClip.x2-plotClip.x1
ps: PlotStateRef =
NEW[ PlotState ← [
text: CornerStitching.NewTesselation[],
scale: scale,
totalPlotClip: plotClip,
colorLoads: NEW[ARRAY CD.Level OF ColorRef←ALL[NIL]]
] ];
usedLevels: REF PACKED ARRAY CD.Level OF BOOL ← NIL;
imageSSize ← (plotClip.y2-plotClip.y1)* scale;
-- length of plot <in slow direction> in pixels
plotScale ← scale;
IF debugging
THEN {
TerminalIO.WriteRope[" Scale factor (pixels/design#)*100 --> "];
TerminalIO.WriteInt[Real.RoundLI[plotScale*100]];
TerminalIO.WriteLn[];
};
abortPlot ← FALSE;
TerminalIO.WriteRope["Starting Color Versatec plot "];
TerminalIO.WriteLn[];
TRUSTED {Process.SetPriority[Process.priorityBackground]};
dr.minimalSize ← 0;
dr.drawRect ← dr.saveRect ← NoteLevel;
dr.devicePrivate ← usedLevels;
dr.worldClip ← CDInline.universe;
dr.devicePrivate ← usedLevels ← NEW[PACKED ARRAY CD.Level OF BOOL ← ALL[FALSE]];
CDOps.DrawDesign[design, dr]; -- mark used levels
dr.drawRect ← dr.saveRect ← NoteRectangle;
dr.devicePrivate ← ps;
localFile ← "///temp/plot0.pd";
For each strip in the design
FOR strip: INT IN [0..strips) DO
-- Determine clip rectangle for strip
clip:
CD.DesignRect = [
x1: plotClip.x1+strip*((plotClip.x2-plotClip.x1)/strips),
y1: plotClip.y1,
x2: plotClip.x1+(strip+1)*((plotClip.x2-plotClip.x1)/strips)+
Real.Fix[150./scale]+1,
y2: plotClip.y2];
tonerSet: PDFileWriter.TonerSet ← ALL[TRUE];
TerminalIO.WriteRope["Recording strip on file "];
TerminalIO.WriteRope[localFile];
TerminalIO.WriteLn[];
pdState ← PDFileWriter.Create[ fileName: localFile, deviceCode: versatec, sResolution: sRes, fResolution: fRes, imageSSize: Real.RoundC[imageSSize + 1], imageFSize: imageFSize, bandSSize: bandSSize, leftOverMode: FALSE];
ps.colorLoads^ ← ALL[NIL];
numBands ← 0;
numRectangles ← 0;
PDFileWriter.StartImage[pdState: pdState, toners: tonerSet];
For each band in the strip
FOR topLine:
INT ← 0, topLine+bandSSize
WHILE topLine<imageSSize
DO
x1, y1, x2, y2: REAL;
dc: CD.DesignRect;
IF abortPlot THEN GOTO AbortPlot;
-- Determine coordinate transformations
pdx ← 0;
pdy ← topLine;
cdx ← clip.x1;
cdy ← clip.y2 - Real.Fix[topLine*(1./scale)];
xoffset ← pdx - Real.Fix[cdx*scale];
yoffset ← pdy - Real.Fix[cdy*(-1*scale)];
-- (negative scale to account for CD increasing y north, PD increasing y going south)
x1 ← (-1 - xoffset )/scale;
y1 ← ((pdy + bandSSize +1) - yoffset)/(-scale);
x2 ← (scanLineWidth - xoffset)/scale;
y2 ← (pdy - yoffset)/(-scale);
dc ← CDInline.NormalizeRect[[x1: Real.Fix[x1], y1: Real.Fix[y1], x2: Real.Fix[x2], y2: Real.Fix[y2]]] ;
ps.bandClip ← dr.worldClip ← [x1:
MAX[plotClip.x1, dc.x1-1], y1:
MAX[plotClip.y1, dc.y1-1], x2:
MIN[plotClip.x2, dc.x2+1], y2:
MIN[plotClip.y2, dc.y2+1]];
-- rectangle in design space that ChipNDale can use to clip its recursive drawing
IF debugging
THEN {
TerminalIO.WriteLn;
TerminalIO.WriteRope[" pdy: "];
TerminalIO.WriteInt[pdy];
TerminalIO.WriteLn;
TerminalIO.WriteRope[" CD band: "];
TerminalIO.WriteInt[ps.bandClip.x1];
TerminalIO.WriteInt[ps.bandClip.y1];
TerminalIO.WriteInt[ps.bandClip.x2];
TerminalIO.WriteInt[ps.bandClip.y2];
TerminalIO.WriteLn
};
Display current band under consideration to pacify user
CDViewer.ShowArrow[design: design,
pos: [x: (dr.worldClip.x1+dr.worldClip.x2)/2, y: (dr.worldClip.y1+dr.worldClip.y2)/2]];
FOR l:
CD.Level
IN
CD.Level
DO
IF ps.tes[l]#
NIL
THEN
-- clear previous tessalations
CornerStitching.ChangeRect[plane: ps.tes[l], rect: CDInline.universe, newvalue: NIL, checkOldvalue: FALSE];
ENDLOOP;
CDOps.DrawDesign[design, dr]; -- build tesselations of the relevant design rectangle
AnalyzeTesselations[ps];
-- assign each level a texture and draw all the rectangles in the region
TerminalIO.WriteRope["."];
numBands ← numBands + 1;
ENDLOOP; -- for each band in the strip
PDFileWriter.EndPage[pdState];
TerminalIO.WriteRope["*"];
TerminalIO.WriteLn[];
PDFileWriter.Close[pdState];
localFile ← NewPlotName[strip];
ENDLOOP; -- for each strip
TerminalIO.WriteRope[" finished plot(s)\n"];
IF debugging
THEN {
TerminalIO.WriteRope["# bands -> "];
TerminalIO.WriteInt[numBands];
TerminalIO.WriteRope[" # rectangles -> "];
TerminalIO.WriteInt[numRectangles];
TerminalIO.WriteLn;
};
CDViewer.RemoveArrow[design: design];
EXITS
AbortPlot => {s ← AbortFile[s]; CDViewer.RemoveArrow[design: c.design]; TerminalIO.WriteRope[" ** plot aborted ** "]; abortPlot ← FALSE};
END; -- enable
END; -- PlotDesign
NoteLevel:
PROC [ r:
CD.DesignRect, l:
CD.Level, pr:
CD.DrawRef ] =
BEGIN
ps: REF PACKED ARRAY CD.Level OF BOOL = NARROW[pr.devicePrivate];
ps[l] ← TRUE;
END;
NoteRectangle:
PROC [ r:
CD.DesignRect, l:
CD.Level, pr:
CD.DrawRef ] =
BEGIN
ps: PlotStateRef = NARROW[pr.devicePrivate];
IF CDInline.NonEmpty[r]
THEN
BEGIN
IF ps.tes[l]=NIL THEN ps.tes[l] ← CornerStitching.NewTesselation[];
ps.tes[l].ChangeRect[rect: r, newvalue: $covered, checkOldvalue: FALSE];
END;
END;
tonerKey: ARRAY [PDFileFormat.Toner] OF ATOM ←
[$CDxVersatecBlack, $CDxVersatecCyan, $CDxVersatecMagenta, $CDxVersatecYellow];
tonerKey:
PROC [toner: PDFileFormat.Toner]
RETURNS [
ATOM] =
INLINE {
RETURN [
SELECT toner
FROM
black => $CDxVersatecBlack,
cyan => $CDxVersatecCyan,
magenta => $CDxVersatecMagenta,
yellow => $CDxVersatecYellow,
ENDCASE => $CDxVersatecBlack
]
};
AnalyzeTesselations:
PROC [ ps: PlotStateRef ] =
BEGIN
FOR lev:
CD.Level
IN
CD.Level
DO
IF ps.tes[lev]#
NIL
THEN {
IF ps.colorLoads^[lev]=
NIL
THEN {
tex: REF;
ps.colorLoads^[lev] ← NEW[ColorLoad];
FOR toner: Ink
IN Ink
DO
tex ← CDProperties.GetPropFromLevel[from: lev, prop: tonerKey[toner]];
ps.colorLoads^[lev][toner] ←
(IF tex = NIL THEN whiteLoadRef ELSE MakeLoadref[tex]);
ENDLOOP;
};
FOR toner: Ink
IN Ink
DO
IF ps.colorLoads^[lev][toner] = whiteLoadRef
THEN
PDFileWriter.SetColorOff[pdState, toner]
ELSE
PDFileWriter.SetColorTile[pdState, toner, ps.colorLoads^[lev][toner], transparent];
ENDLOOP;
[] ← ps.tes[lev].EnumerateArea[
rect: ps.bandClip,
perTile: ProcessTile,
data: ps,
backgroundValue: $none
];
};
ENDLOOP;
END;
ProcessTile:
PROCEDURE [tile: CornerStitching.TilePtr, data:
REF
ANY]
RETURNS [
REF
ANY]
-- CornerStitching.PerTileProc -- =
BEGIN -- only called on covered tiles
rightBound, x1, y1, x2, y2: INT;
pdx1, pdx2, pdy1, pdy2 : CARDINAL;
sSize, fSize : CARDINAL;
t: CornerStitching.TilePtr;
ps: PlotStateRef = NARROW[data];
tileValue: REF = tile.Value;
IF tileValue = $covered
THEN
BEGIN
r: CD.DesignRect = tile.Area;
Calculate absolute coords of rectangle here as offset from plot origin
x1 ← Real.RoundLI[xoffset + r.x1*plotScale];
y1 ← Real.RoundLI[yoffset + r.y1*(-plotScale)];
x2 ← Real.RoundLI[xoffset + r.x2*plotScale];
y2 ← Real.RoundLI[yoffset + r.y2*(-plotScale)];
rightBound ← Real.RoundLI[xoffset + ps.bandClip.x2*plotScale];
-- if rectangle is in bandarea, clip and write; otherwise disregard rectangle
IF
NOT ((( x1 > rightBound)
OR (x2 < 0))
OR
(( y1 < pdy) OR (y2 > MIN[imageSSize, pdy+bandSSize]))) THEN {
pdx1 ← MAX[x1, 0];
pdx2 ← MIN[x2, rightBound, imageFSize];
pdy1 ← MIN[y1, pdy+bandSSize];
pdy2 ← MAX[y2, pdy];
fSize ← pdx2 - pdx1;
sSize ← pdy1 - pdy2;
-- can't have rectangles landing on or over the imageSSize
IF pdy1 >= imageSSize
THEN
sSize ← Real.Fix[imageSSize - pdy2] ;
-- disregard rectangles without area
IF ((sSize # 0)
AND (fSize # 0))
THEN {
PDFileWriter.MaskRectangle[pdState: pdState, sMin: pdy2, fMin: pdx1, sSize: sSize, fSize: fSize];
TerminalIO.WriteRope["+"];
numRectangles ← numRectangles + 1;
IF debugging
THEN {
TerminalIO.WriteRope[" position -> "];
TerminalIO.WriteInt[Real.RoundLI[y1]];
TerminalIO.WriteInt[Real.RoundLI[x1]];
TerminalIO.WriteRope[" size -> "];
TerminalIO.WriteInt[sSize];
TerminalIO.WriteInt[fSize];
TerminalIO.WriteLn;
}
}
}
END;
Put lines at boundaries with regions of other color
FOR t ← tile.NEastNeighbour, t.WSouthNeighbour WHILE tile.SouthEdge<t.NorthEdge DO
going south along east edge of tile
IF t.Value#tileValue THEN
BEGIN
ps.context[black].SetCP[x: tile.EastEdge, y: MAX[tile.SouthEdge, t.SouthEdge]];
ps.context[black].DrawTo[x: tile.EastEdge, y: MIN[tile.NorthEdge, t.NorthEdge]];
END;
ENDLOOP;
FOR t ← tile.ENorthNeighbour, t.SWestNeighbour WHILE tile.WestEdge<t.EastEdge DO
going west along north edge of tile
IF t.Value#tileValue THEN
BEGIN
ps.context[black].SetCP[x: MAX[tile.WestEdge, t.WestEdge], y: tile.NorthEdge];
ps.context[black].DrawTo[x: MIN[tile.EastEdge, t.EastEdge], y: tile.NorthEdge];
END;
ENDLOOP;
RETURN[data];
END;
SignalValueRef: TYPE = REF SignalValue;
SignalValue: TYPE = RECORD [s: Rope.ROPE];
LookForSignalName:
PROC [ design:
CD.Design, aptr:
CD.ApplicationPtr, x:
REF ]
RETURNS [done:
BOOL←
FALSE, removeMe:
BOOL←
FALSE, include:
CD.ApplicationList←
NIL,
repaintMe:
BOOL←
FALSE, repaintInclude:
BOOL←
FALSE]
-- CDCallSpecific.CallProc -- =
BEGIN
This area needs considerable improvement. The ultimate goal is to find a place to put the signal name where it will not be confused with any other geometry (than the named piece, or continuations on the same layer) or signal name.
GetSignalName:
PROC [signal:
REF]
RETURNS [s: Rope.
ROPE] =
BEGIN
WITH signal
SELECT
FROM
atom: ATOM => s ← Atom.GetPName[atom];
rope: Rope.ROPE => s ← rope;
ENDCASE => s ← "?";
END;
ps: PlotStateRef = NARROW[x];
r: CD.DesignRect = CDInline.Intersection[ps.totalPlotClip, CDApplications.ApplicationRect[aptr]];
signal: REF = CDProperties.GetProp[from: aptr, prop: $SignalName];
IF signal # NIL AND CDInline.NonEmpty[r] THEN
BEGIN
signalValue: SignalValueRef = NEW[SignalValue ← [s: GetSignalName[signal]]];
others: LIST OF REF CornerStitching.Region = NARROW[ps.text.EnumerateArea[rect: r]];
ps.text.ChangeRect[rect: r, newvalue: signalValue, checkOldvalue: FALSE];
FOR other: LIST OF REF CornerStitching.Region ← others, other.rest WHILE other#NIL DO
ps.text.ChangeRect[rect: other.first.rect, newvalue: other.first.value, checkOldvalue: FALSE];
ENDLOOP;
END
ELSE done ← FALSE;
END;
PaintASignalName:
PROC [tile: CornerStitching.TilePtr, data:
REF
ANY]
RETURNS [
REF
ANY]
-- CornerStitching.PerTileProc -- =
BEGIN
ps: PlotStateRef = NARROW[data];
textContext: Graphics.Context = ps.vPatch[black].CopyContext[];
signalValue: SignalValueRef = NARROW[tile.Value[]];
dx, dy, xmin, xmax, ymin, ymax: REAL;
r: CD.DesignRect = CDInline.Intersection[tile.Area, ps.totalPlotClip];
ctr: CD.DesignPosition = Center[r];
[dx: dx, dy: dy] ← Graphics.Map[sc: ps.context[black], dc: ps.vPatch,
sx: ctr.x, sy: ctr.y];
[xmin: xmin, ymin: ymin, xmax: xmax, ymax: ymax] ← Graphics.RopeBox[font: signalFont, rope: signalValue.s];
textContext.Translate[tx: dx-(xmax+xmin)/2, ty: dy-(ymax+ymin)/2]; -- centers the text in r
IF ((xmax-xmin)>(ymax-ymin)) # ((r.x2-r.x1)>(r.y2-r.y1)) THEN
textContext.Rotate[270];
textContext.SetColor[Graphics.white];
textContext.DrawBox[[xmin: -2, ymin: -2, xmax: xmax-xmin+2, ymax: ymax-ymin+2]];
leave a two-scan-line white patch all around
textContext.SetColor[Graphics.black];
textContext.SetCP[x: 0, y: 0];
textContext.DrawRope[rope: signalValue.s, font: signalFont];
RETURN[data];
END;
Center:
PROC [ r:
CD.Rect ]
RETURNS [
CD.Position ] =
{RETURN[[x: (r.x1+r.x2)/2, y: (r.y1+r.y2)/2]]};
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;
MakeLoadref:
PROC [pattern:
REF
ANY]
RETURNS [PDFileWriter.LoadReference] =
TRUSTED BEGIN
loadRef: PDFileWriter.LoadReference;
texture: Stipple16 ← ToTexture[pattern];
loadRef ← PDFileWriter.LoadContiguousColorTile[pdState: pdState, phase: 0, sMin: 0, fMin: 0, sSize: 16, fSize: 16, bitsPtr: @texture];
RETURN[loadRef];
END;
AbortProc: Menus.MenuProc = {abortPlot ←
TRUE};
AbortFile:
PROC [s:
IO.
STREAM ]
RETURNS [
IO.
STREAM ] =
{IF s#NIL THEN s.Close[abort: TRUE]; RETURN[NIL]};
Module START code...
END. -- of VersatecImpl