<> <> 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 PATH _ ALL[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> 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.