PathImpl.mesa
Doug Wyatt, June 28, 1984 11:21:20 am PDT
DIRECTORY
Path;
PathImpl: CEDAR MONITOR
EXPORTS Path
~ BEGIN OPEN Path;
RealsFromSegs: PROC[nSegs: NAT, type: SegType] RETURNS[NAT] ~ {
realsPerSeg: NAT ~ (SELECT type FROM curve => 6, conic => 5, arc => 4, ENDCASE => 2);
n: INT ~ nSegs*realsPerSeg;
RETURN[MIN[n, NAT.LAST]];
};
New: PUBLIC PROC[nSegs: NAT, expectedType: SegType ← move] RETURNS[PATH] ~ {
segsMax: NAT ~ MAX[4, nSegs];
realsMax: NAT ~ RealsFromSegs[segsMax, expectedType];
segs: Segs ~ NEW[SegsRep[segsMax] ← [length: 0, array: ]];
reals: Reals ~ NEW[RealsRep[realsMax] ← [length: 0, array: ]];
RETURN[NEW[PathRep ← [segs: segs, reals: reals, lp: [0, 0]]]];
};
nScratch: NAT ~ 3;
ScratchIndex: TYPE ~ [0..nScratch);
scratch: ARRAY ScratchIndex OF PATHALL[NIL];
Alloc: ENTRY PROC RETURNS[PATH] ~ {
FOR i: ScratchIndex IN ScratchIndex DO
path: PATH ~ scratch[i];
IF path#NIL THEN { scratch[i] ← NIL; RETURN[path] };
ENDLOOP;
RETURN[NIL];
};
Free: ENTRY PROC[path: PATH] ~ {
FOR i: ScratchIndex DECREASING IN ScratchIndex DO
IF scratch[i]=NIL THEN { scratch[i] ← path; RETURN };
ENDLOOP;
};
ObtainScratch: PUBLIC PROC[nSegs: NAT, expectedType: SegType ← move]
RETURNS[PATH] ~ {
ERROR;
};
ReleaseScratch: PUBLIC PROC[path: PATH] ~ {
ERROR;
};
LastPoint: PUBLIC PROC[path: PATH] RETURNS[x, y: REAL] ~ {
RETURN[path.lp.x, path.lp.y];
};
LastPointP: PUBLIC PROC[path: PATH] RETURNS[Pair] ~ {
RETURN[path.lp];
};
GetSegs: PROC[path: PATH] RETURNS[Segs] ~ {
segs: Segs ~ path.segs;
IF segs.length<segs.max THEN RETURN[segs]
ELSE ERROR;
};
GetReals: PROC[path: PATH, n: NAT] RETURNS[Reals] ~ {
reals: Reals ~ path.reals;
IF (reals.length+n)<=reals.max THEN RETURN[reals]
ELSE ERROR;
};
MoveTo: PUBLIC PROC[path: PATH, x, y: REAL] ~ {
segs: Segs ~ GetSegs[path];
reals: Reals ~ GetReals[path, 2];
s: NAT ~ segs.length;
i: NAT ~ reals.length;
segs[s] ← [type: move, index: i];
segs.length ← s+1;
reals[i] ← x;
reals[i+1] ← y;
reals.length ← i+2;
path.lp ← [x, y];
};
MoveToP: PUBLIC PROC[path: PATH, p: Pair] ~ {
MoveTo[path, p.x, p.y];
};
LineTo: PUBLIC PROC[path: PATH, x, y: REAL] ~ {
segs: Segs ~ GetSegs[path];
reals: Reals ~ GetReals[path, 2];
s: NAT ~ segs.length;
i: NAT ~ reals.length;
segs[s] ← [type: line, index: i];
segs.length ← s+1;
reals[i] ← x;
reals[i+1] ← y;
reals.length ← i+2;
path.lp ← [x, y];
};
LineToP: PUBLIC PROC[path: PATH, p: Pair] ~ {
LineTo[path, p.x, p.y];
};
LineToX: PUBLIC PROC[path: PATH, x: REAL] ~ {
LineTo[path, x, path.lp.y];
};
LineToY: PUBLIC PROC[path: PATH, y: REAL] ~ {
LineTo[path, path.lp.x, y];
};
CurveTo: PUBLIC PROC[path: PATH, x1, y1, x2, y2, x3, y3: REAL] ~ {
segs: Segs ~ GetSegs[path];
reals: Reals ~ GetReals[path, 6];
s: NAT ~ segs.length;
i: NAT ~ reals.length;
segs[s] ← [type: curve, index: i];
segs.length ← s+1;
reals[i] ← x1;
reals[i+1] ← y1;
reals[i+2] ← x2;
reals[i+3] ← y2;
reals[i+4] ← x3;
reals[i+5] ← y3;
reals.length ← i+6;
path.lp ← [x3, y3];
};
CurveToP: PUBLIC PROC[path: PATH, p1, p2, p3: Pair] ~ {
CurveTo[path, p1.x, p1.y, p2.x, p2.y, p3.x, p3.y];
};
ConicTo: PUBLIC PROC[path: PATH, x1, y1, x2, y2: REAL, r: REAL] ~ {
segs: Segs ~ GetSegs[path];
reals: Reals ~ GetReals[path, 5];
s: NAT ~ segs.length;
i: NAT ~ reals.length;
segs[s] ← [type: conic, index: i];
segs.length ← s+1;
reals[i] ← x1;
reals[i+1] ← y1;
reals[i+2] ← x2;
reals[i+3] ← y2;
reals[i+4] ← r;
reals.length ← i+5;
path.lp ← [x2, y2];
};
ConicToP: PUBLIC PROC[path: PATH, p1, p2: Pair, r: REAL] ~ {
ConicTo[path, p1.x, p1.y, p2.x, p2.y, r];
};
ArcTo: PUBLIC PROC[path: PATH, x1, y1, x2, y2: REAL] ~ {
segs: Segs ~ GetSegs[path];
reals: Reals ~ GetReals[path, 4];
s: NAT ~ segs.length;
i: NAT ~ reals.length;
segs[s] ← [type: arc, index: i];
segs.length ← s+1;
reals[i] ← x1;
reals[i+1] ← y1;
reals[i+2] ← x2;
reals[i+3] ← y2;
reals.length ← i+4;
path.lp ← [x2, y2];
};
ArcToP: PUBLIC PROC[path: PATH, p1, p2: Pair] ~ {
ArcTo[path, p1.x, p1.y, p2.x, p2.y];
};
MapPath: PUBLIC PathProc ~ {
path: PATH ~ NARROW[data];
segs: Segs ~ path.segs;
reals: Reals ~ path.reals;
FOR s: NAT IN[0..segs.length) DO
seg: Seg ~ segs[s];
i: NAT ~ seg.index;
SELECT seg.type FROM
move => moveToP[[reals[i], reals[i+1]]];
line => lineToP[[reals[i], reals[i+1]]];
curve => curveToP[[reals[i], reals[i+1]], [reals[i+2], reals[i+3]], [reals[i+4], reals[i+5]]];
conic => conicToP[[reals[i], reals[i+1]], [reals[i+2], reals[i+3]], reals[i+4]];
arc => arcToP[[reals[i], reals[i+1]], [reals[i+2], reals[i+3]]];
ENDCASE => ERROR;
ENDLOOP;
};
END.