-- Compiler PressObjs/n -- Stone October 15, 1981 7:06 PM DIRECTORY SplineDefs: FROM "SplineDefs", PressDefs: FROM "PressDefs", GriffinMemoryDefs: FROM "GriffinMemoryDefs", PointDefs: FROM "PointDefs", StyleDefs: FROM "StyleDefs", GriffinFontDefs: FROM "GriffinFontDefs", Real: FROM "Real", RealConvert: FROM "RealConvert", ControllerDefs: FROM "ControllerDefs", PressLineDefs: FROM "PressLineDefs", ScreenDefs: FROM "ScreenDefs", ObjectDefs: FROM "ObjectDefs"; PressObjs: PROGRAM IMPORTS ObjectDefs, PressDefs, SplineDefs, GriffinMemoryDefs,Real,ControllerDefs,PressLineDefs, ScreenDefs,RealConvert EXPORTS ObjectDefs = BEGIN OPEN ObjectDefs,PointDefs,GriffinMemoryDefs; RABS: PROCEDURE [r: REAL] RETURNS[REAL] = INLINE BEGIN IF r<0 THEN RETURN[-r] ELSE RETURN[r]; END; pressXscale: REAL ←1; pressYscale: REAL ← 1; --magic centering numbers to center display on press page --the distance (in micas) is the difference between 32 micas/pixel and --2540 micas/inch for a full page. --Y is also shifted about 1/4 inch empirically --X is also shifted about 1/8 inch empirically xOffset: REAL ← 1067+327; yOffset: REAL ← 1042-635; currentColor: PressDefs.ColorDescriptor ← [0,0,0]; inObject: BOOLEAN ← FALSE; --makes a press file of all objects linked to obj PressAllObjects: PUBLIC PROCEDURE [s: STRING]= BEGIN IF NOT PressDefs.BeginPress[s,TRUE,1] THEN ERROR; --no good on begin press PressDefs.BeginPage[]; ObjectDefs.ForAllObjects[PressObject]; PressDefs.EndPage[]; IF NOT PressDefs.EndPress[] THEN ERROR; END; --calls the correct type of formatting routine PressObject: ObjectDefs.ObjectProc = BEGIN pcolor: PressDefs.ColorDescriptor; thisScreen: ScreenDefs.ScreenPtr ← ScreenDefs.GetCurrentScreen[]; IF obj=NIL THEN RETURN; IF ~Visible[obj] THEN RETURN; --outside, other view, or deleted --partials also get tossed IF (obj.br[X] > thisScreen.rx OR obj.tl[X] <thisScreen.lx OR obj.br[Y] > thisScreen.by OR obj.tl[Y] <thisScreen.ty ) THEN RETURN; WITH object: obj SELECT FROM shape => IF ~object.closed THEN PlotTrajectory[object.trajectory,object.style,FALSE] ELSE BEGIN --areas have trajectories too. TRUE = closed IF object.style.filled THEN FillArea[object]; IF object.style.outlined THEN PlotTrajectory[object.trajectory,object.style,TRUE]; END; caption => BEGIN pcolor ← [hue: object.style.color.hue, saturation: object.style.color.saturation, brightness: object.style.color.brightness]; PressDefs.ShowText [pcolor, object.text, ObjToPress[object.p0], object.style.orientation,object.style.anchor, ControllerDefs.FontWithNumber [object.style.fontid]]; END; token => NULL; ENDCASE; END; --first set in second set BoxInsideBox: PROCEDURE[tl0,br0,tl1,br1: ScrPt] RETURNS [BOOLEAN]= BEGIN IF (tl0[X] IN [tl1[X]..br1[X]] AND br0[X] IN [tl1[X]..br1[X]] AND tl0[Y] IN [tl1[Y]..br1[Y]] AND br0[Y] IN [tl1[Y]..br1[Y]]) THEN RETURN[TRUE] ELSE RETURN[FALSE]; END; --Draws a trajectory PlotTrajectory: PROCEDURE [traj: Trajectory,style: POINTER TO StyleDefs.Style,closed: BOOLEAN] = BEGIN currentColor ← [hue: style.color.hue, saturation: style.color.saturation, brightness: style.color.brightness]; WITH shape: traj SELECT FROM linked => BEGIN lshape: POINTER TO linked Trajectory ← FillGaps[@shape,closed]; linkPtr: POINTER TO Link ← lshape.links; UNTIL linkPtr = NIL DO SELECT linkPtr.degree FROM D0 => PlotDots[linkPtr.knots]; D1 => PlotLines[linkPtr.knots,style]; D2 => NULL; D3 => PlotCurve[linkPtr.knots,style,lshape.splineType,FALSE]; ENDCASE; linkPtr ← linkPtr.link; ENDLOOP; --do something here about releasing the object made by FillGaps END; cyclic => PlotCurve[shape.knots,style,traj.splineType,TRUE]; ENDCASE; END; PressCurve: PROCEDURE [coeffs: POINTER TO SplineDefs.Coeffs,newObject: BOOLEAN] = BEGIN zeropt: ObjPt ← [0,0]; IF newObject THEN BEGIN IF inObject THEN PressDefs.EndObject[]; PressDefs.BeginObject[currentColor]; inObject ← TRUE; PressDefs.MoveTo[ObjToPress[coeffs.t0]]; END; IF coeffs.t3=coeffs.t2 AND coeffs.t2=zeropt THEN BEGIN pt: ObjPt ← [coeffs.t1[X]+coeffs.t0[X],coeffs.t1[Y]+coeffs.t0[Y]]; PressDefs.DrawTo[ObjToPress[pt]]; END ELSE BEGIN p: PressDefs.PressSpline ← CoeffsToPressSpline[coeffs↑]; PressDefs.DrawCurve[p]; END; END; --Plots Dots PlotDots: PROCEDURE [knots: DESCRIPTOR FOR ARRAY OF PointDefs.ObjPt] = BEGIN END; --Contours and Press's lines. Ignores the junction specification for now. PlotLines: PROCEDURE [knots: DESCRIPTOR FOR ARRAY OF PointDefs.ObjPt,style: POINTER TO StyleDefs.Style] = BEGIN i: INTEGER; p0,p1: ObjPt; end0,end1: PressLineDefs.End; lastknot: INTEGER ← LENGTH[knots]-1; end0 ← (SELECT style.firstend.type FROM flat => flat, angled => square, ENDCASE => round); end1 ← round; p0 ← knots[0]; IF lastknot=0 THEN PressLineDefs.ContourLine[p0,p0,style.width/2,end0,end1,PressCurve]; FOR i IN [1..lastknot] DO p1 ← knots[i]; IF i=lastknot THEN end1 ← (SELECT style.lastend.type FROM flat => flat, angled => square, ENDCASE => round); PressLineDefs.ContourLine[p0,p1,style.width/2,end0,end1,PressCurve]; IF i = 0 THEN end0 ← round; p0 ← p1; ENDLOOP; PressDefs.EndObject[]; inObject ← FALSE; END; --Plots a curve. description is in the knots and the splinetype PlotCurve: PROCEDURE [knots: DESCRIPTOR FOR ARRAY OF PointDefs.ObjPt,style: POINTER TO StyleDefs.Style,type: SplineDefs.SplineType,cyclic: BOOLEAN] = BEGIN coeffs: DESCRIPTOR FOR ARRAY OF SplineDefs.Coeffs; end0,end1: PressLineDefs.End; lastseg: INTEGER; i: INTEGER ← 0; end0 ← (SELECT style.firstend.type FROM flat => square, angled => square, ENDCASE => round); end1 ← round; IF cyclic THEN end0 ← end1 ← round; coeffs ← IF cyclic THEN MakeCyclicSpline[knots,type] ELSE SplineDefs.MakeSpline[knots,type ]; lastseg ← LENGTH[coeffs]-1; FOR i IN [0..lastseg] DO IF i=lastseg THEN end1 ← (SELECT style.lastend.type FROM flat => square, angled => square, ENDCASE => round); PressLineDefs.ContourCubic[@coeffs[i],style.width/2,end0,end1,PressCurve]; IF i = 0 THEN end0 ← round; ENDLOOP; PressDefs.EndObject[]; inObject ← FALSE; SplineDefs.FreeCoeffs[coeffs]; END; MakeCyclicSpline: PROCEDURE[knots: DESCRIPTOR FOR ARRAY OF ObjPt, type: SplineDefs.SplineType] RETURNS[coeffs: DESCRIPTOR FOR ARRAY OF SplineDefs.Coeffs]= BEGIN i: INTEGER; cycknots: DESCRIPTOR FOR ARRAY OF ObjPt; numknots: INTEGER ← LENGTH[knots]; newLength: INTEGER; IF numknots <= 0 THEN RETURN[DESCRIPTOR[NIL,0]]; SELECT type FROM naturalUM, naturalAL,bezier=> newLength ← numknots+1; bspline, crspline=> newLength ← numknots+3; ENDCASE; cycknots ← DESCRIPTOR[Allocate[newLength*SIZE[ObjPt]],newLength]; FOR i IN [0..numknots) DO cycknots[i] ← knots[i]; ENDLOOP; cycknots[numknots] ← cycknots[0]; SELECT type FROM naturalUM=> type ← cyclicUM; naturalAL=> type ← cyclicAL; bspline=> BEGIN cycknots[numknots +1] ← cycknots[1]; cycknots[numknots+2] ← cycknots[2]; END; crspline=> BEGIN cycknots[numknots +1] ← cycknots[1]; cycknots[numknots+2] ← cycknots[2]; END; ENDCASE; coeffs ← SplineDefs.MakeSpline[cycknots,type]; Free[BASE[cycknots]]; RETURN; END; --makes a new linked trajectory with knuth splines in gaps FillGaps: PROCEDURE[traj: POINTER TO linked Trajectory,closed: BOOLEAN] RETURNS[POINTER TO linked Trajectory] = BEGIN RETURN[traj]; END; --Fills an area FillArea: PROCEDURE [area: shape Object] = BEGIN i: INTEGER; first: BOOLEAN ← TRUE; p: PressDefs.PressSpline; color: PressDefs.ColorDescriptor← [hue: area.style.fillcolor.hue, saturation: area.style.fillcolor.saturation, brightness: area.style.fillcolor.brightness]; PressDefs.BeginObject[color]; WITH shape: area.trajectory SELECT FROM linked => BEGIN i: INTEGER; type: POINTER TO Link ← shape.links; UNTIL type = NIL DO SELECT type.degree FROM D0 => NULL; D1 => BEGIN IF first THEN PressDefs.MoveTo[ObjToPress[type.knots[0]]]; FOR i IN [1..LENGTH[type.knots]) DO PressDefs.DrawTo [ObjToPress[type.knots[i]]]; ENDLOOP; END; D2 => NULL; D3 => BEGIN allCoeffs: DESCRIPTOR FOR ARRAY OF SplineDefs.Coeffs; SplineDefs.InitSplines[Allocate,Free]; allCoeffs ← SplineDefs.MakeSpline[type.knots,shape.splineType]; IF first THEN PressDefs.MoveTo[ObjToPress[allCoeffs[0].t0]]; FOR i IN [0..LENGTH[allCoeffs]) DO p ← CoeffsToPressSpline[allCoeffs[i]]; PressDefs.DrawCurve[p]; ENDLOOP; SplineDefs.FreeCoeffs[allCoeffs]; END; ENDCASE; type ← type.link; first ← FALSE; ENDLOOP; --do something here about releasing the object made by FillGaps END; cyclic => BEGIN allCoeffs: DESCRIPTOR FOR ARRAY OF SplineDefs.Coeffs; SplineDefs.InitSplines[Allocate,Free]; allCoeffs ← MakeCyclicSpline[shape.knots,shape.splineType]; PressDefs.MoveTo[ObjToPress[allCoeffs[0].t0]]; FOR i IN [0..LENGTH[allCoeffs]) DO p ← CoeffsToPressSpline[allCoeffs[i]]; PressDefs.DrawCurve[p]; ENDLOOP; SplineDefs.FreeCoeffs[allCoeffs]; END; ENDCASE; PressDefs.EndObject[]; END; ObjToPress: PROCEDURE[pt: ObjPt] RETURNS[pc: PressDefs.PressCoords]= BEGIN pt[X] ← pt[X]+xOffset; pt[Y] ← pt[Y]+yOffset; pc[PressDefs.X] ← Real.RoundC[pt[X]]; pc[PressDefs.Y] ← Real.RoundC[pt[Y]]; END; CoeffsToPressSpline: PROCEDURE[coeffs: SplineDefs.Coeffs] RETURNS[p: PressDefs.PressSpline]= BEGIN p.Ax ← FloatToPressFloat[pressXscale*coeffs.t3[X]]; p.Bx ← FloatToPressFloat[pressXscale*coeffs.t2[X]]; p.Cx ← FloatToPressFloat[pressXscale*coeffs.t1[X]]; p.Ay ← FloatToPressFloat[pressYscale*coeffs.t3[Y]]; p.By ← FloatToPressFloat[pressYscale*coeffs.t2[Y]]; p.Cy ← FloatToPressFloat[pressYscale*coeffs.t1[Y]]; END; FloatToPressFloat: PUBLIC PROCEDURE [r: REAL] RETURNS [p: PressDefs.PressFloat] = BEGIN --hack for press. Will be ok since r is already scaled to press coords IF RABS[r] < (0.1) THEN RETURN[0]; --on to the conversion RETURN[RealConvert.IeeeToBcpl[r]]; END; END.