-- PatchImpl.mesa -- Last changed by Doug Wyatt, September 14, 1980 4:16 PM DIRECTORY Patch, Vector USING [Vec], Poly USING [NewRec], Area USING [Rec, Outside, Inside, Handle, Vertices, Rectangle, Rectangular, Free], Pipe USING [Handle, Object, Procs, Put, Ref, Free], Edge USING [Handle, New, NewPipe, Free], Memory USING [zone]; PatchImpl: PROGRAM IMPORTS Memory,Poly,Area,Pipe,Edge EXPORTS Patch SHARES Patch,Pipe = { OPEN Patch; zone: UNCOUNTED ZONE = Memory.zone; Data: PUBLIC TYPE = RECORD [ area: Area.Handle, elist: NodeRef ]; DataRef: TYPE = LONG POINTER TO Data; Node: TYPE = RECORD [ link: NodeRef, edge: Edge.Handle ]; NodeRef: TYPE = LONG POINTER TO Node; procs: LONG POINTER TO READONLY Procs = zone.NEW[Procs = [ NewPipe: CNewPipe, Copy: CCopy, Free: CFree ]]; New: PUBLIC PROC[area: Area.Handle] RETURNS[Handle] = { d: DataRef = zone.NEW[Data _ [area: area, elist: NIL]]; first: BOOLEAN_TRUE; fv,pv: Vector.Vec; Proc: PROC[v: Vector.Vec] = { IF first THEN { fv_v; first_FALSE } ELSE AddEdge[d,pv,v]; pv_v; }; Area.Vertices[area,Proc]; Proc[fv]; RETURN[zone.NEW[Object _ [procs: procs, data: d]]]; }; AddEdge: PROC[d: DataRef, v0,v1: Vector.Vec] = { e: NodeRef=zone.NEW[Node _ [link: NIL, edge: Edge.New[v0,v1]]]; e.link_d.elist; d.elist_e; }; FreeEdges: PROC[d: DataRef] = { list: NodeRef_d.elist; d.elist_NIL; UNTIL list=NIL DO e: NodeRef_list; list_e.link; Edge.Free[@e.edge]; zone.FREE[@e]; ENDLOOP; }; PData: PUBLIC TYPE = RECORD [ area: Area.Handle, ipipe,opipe: Pipe.Handle, epipe: Pipe.Handle ]; PDataRef: TYPE = LONG POINTER TO PData; pProcs: LONG POINTER TO READONLY Pipe.Procs= zone.NEW[Pipe.Procs = [Put: PPut, Free: PFree]]; rProcs: LONG POINTER TO READONLY Pipe.Procs= zone.NEW[Pipe.Procs = [Put: RPut, Free: PFree]]; CNewPipe: PROC[self: Handle, ipipe,opipe: Pipe.Handle] RETURNS[Pipe.Handle] = { d: DataRef=self.data; p: PDataRef=zone.NEW[PData _ [ area: d.area, ipipe: ipipe, opipe: opipe, epipe: Pipe.Ref[ipipe] ]]; FOR e: NodeRef_d.elist,e.link UNTIL e=NIL DO p.epipe_Edge.NewPipe[e.edge,p.epipe,Pipe.Ref[opipe]]; ENDLOOP; RETURN[zone.NEW[Pipe.Object _ [ procs: IF Area.Rectangular[d.area] THEN rProcs ELSE pProcs, data: LOOPHOLE[p]]]]; }; -- nonrectangular patch PPut: PROC[self: Pipe.Handle, area: Area.Handle] = { p: PDataRef=LOOPHOLE[self.data]; r: Area.Rec=Area.Rectangle[area]; rc: Area.Rec=Area.Rectangle[p.area]; IF Area.Outside[r,rc] THEN Pipe.Put[p.opipe,area] ELSE Pipe.Put[p.epipe,area]; }; -- rectangular patch RPut: PROC[self: Pipe.Handle, area: Area.Handle] = { p: PDataRef=LOOPHOLE[self.data]; r: Area.Rec_Area.Rectangle[area]; rc: Area.Rec=Area.Rectangle[p.area]; IF Area.Outside[r,rc] THEN Pipe.Put[p.opipe,area] ELSE IF Area.Inside[r,rc] THEN Pipe.Put[p.ipipe,area] ELSE IF Area.Rectangular[area] THEN { Area.Free[@area]; IF r.ll.xrc.ur.x THEN { rr: Area.Rec_r; rr.ll.x_r.ur.x_rc.ur.x; Pipe.Put[p.opipe,Poly.NewRec[rr]]; }; IF r.ur.y>rc.ur.y THEN { rr: Area.Rec_r; rr.ll.y_r.ur.y_rc.ur.y; Pipe.Put[p.opipe,Poly.NewRec[rr]]; }; Pipe.Put[p.ipipe,Poly.NewRec[r]]; } ELSE Pipe.Put[p.epipe,area]; }; PFree: PROC[self: Pipe.Handle] = { p: PDataRef_LOOPHOLE[self.data]; Pipe.Free[@p.epipe]; Pipe.Free[@p.ipipe]; Pipe.Free[@p.opipe]; zone.FREE[@p]; zone.FREE[@self]; }; CCopy: PROC[self: Handle] RETURNS[Handle] = { RETURN[NIL]; -- *** fix this }; CFree: PROC[self: Handle] = { d: DataRef_self.data; FreeEdges[d]; Area.Free[@d.area]; zone.FREE[@d]; zone.FREE[@self]; }; }.(670)