-- Compiler ShowObjects/n;bind griffin;griffin
-- mstone April 24, 1981 3:10 PM
-- geoff November 26, 1979 10:45 AM
-- Last Edited by: Stone, February 18, 1983 1:03 pm
-- Last Edited by: Pier, February 14, 1984 10:52:01 am PST
DIRECTORY
ScreenDefs,
GriffinViewer USING [PaintProc, DoPaint],
SplineDefs: FROM "SplineDefs",
StyleDefs: FROM "StyleDefs",
GriffinMemoryDefs USING [CZone],
Graphics USING [Context],
EncodingDefs: FROM "EncodingDefs",
GriffinDefs: FROM "GriffinDefs",
PointDefs: FROM "PointDefs",
MenuDefs: FROM "MenuDefs",
DebuggerSwap: FROM "DebuggerSwap",
ControllerDefs: FROM "ControllerDefs",
ObjectDefs: FROM "ObjectDefs";
ShowObjects: PROGRAM IMPORTS ScreenDefs, ObjectDefs, PointDefs, SplineDefs, MenuDefs, GriffinMemoryDefs, EncodingDefs, DebuggerSwap, ControllerDefs, GriffinViewer
EXPORTS ObjectDefs =
BEGIN OPEN ObjectDefs,PointDefs,GriffinMemoryDefs;
--upper level module has to start splines
Context: TYPE=Graphics.Context;
i: INTEGER; --the canonical loop counter
--put these somewhere as compile time constants
RuntimeBitmaps: ARRAY [0..3] OF ARRAY [0..8] OF CARDINAL;
Token: ScreenDefs.BlockPtr ← CZone.NEW[ScreenDefs.Block ← [NIL,1,0,0,9,9]];
SelectBitmaps: ARRAY [0..3] OF ARRAY [0..15] OF CARDINAL;
SelectToken: ScreenDefs.BlockPtr ← CZone.NEW[ScreenDefs.Block ← [NIL,1,3,3,10,10]];
selW: PUBLIC INTEGER ← 5;
HGrid,VGrid: ObjectHandle ← NIL;
hgridlx,hgridrx,vgridty,vgridby,gridt: INTEGER;
debug: BOOLEAN ← FALSE;
FNC: DisplayFnc ← write;
clipperState: ScreenDefs.ClipperState ← clip;
GridOn: PUBLIC PROCEDURE =
BEGIN
IF HGrid=NIL THEN
BEGIN
center,tl: ScrPt;
[center,hgridlx,hgridrx,vgridty,vgridby,gridt] ← ScreenDefs.GetGridParameters[];
VGrid ← StartObject[token];
HGrid ← StartObject[token];
tl ← [hgridlx,center[Y]-gridt/2]; --doing the obvious makes a compiler error
HGrid.body ← token[hgrid,ScrToObj[tl],NIL];
tl ← [center[X]-gridt/2,vgridty]; --doing the obvious makes a compiler error
VGrid.body ← token[vgrid,ScrToObj[tl],NIL];
HGrid.validEncoding ← VGrid.validEncoding ← FALSE;
HGrid.visible ← VGrid.visible ← FALSE;
END;
HGrid.visible ← TRUE;
WriteObject[HGrid];
VGrid.visible ← TRUE;
WriteObject[VGrid];
END;
GridOff: PUBLIC PROCEDURE =
BEGIN
EraseObject[HGrid];
HGrid.visible ← FALSE;
EraseObject[VGrid];
VGrid.visible ← FALSE;
END;
--replots all objects linked to allObjects
ReplotFromObject: PUBLIC PROCEDURE[startObj: ObjectHandle, dc: Context] =
BEGIN
obj: REF Object ← startObj;
FNC ← write;
UNTIL obj=NIL DO
PlotObject[obj, dc];
obj ← obj.link;
ENDLOOP;
END;
--calls the correct type of plotting routine, be it splines, encoding, whatever
PlotObject: PROCEDURE [object: ObjectHandle, dc: Context] =
BEGIN
IF object=NIL THEN RETURN;
IF ~Visible[object] THEN RETURN;
IF object.validEncoding
THEN clipperState ← ScreenDefs.PrimeClipper[object.tl,object.br];
IF clipperState=cull THEN {clipperState ← clip; RETURN};
WITH object SELECT FROM
obj: REF Object[shape] => BEGIN
IF NOT object.validEncoding THEN BEGIN
EncodingDefs.DeleteChainEncoding[obj.chainEncoding];
EncodingDefs.DeleteAreaEncoding[obj.areaEncoding];
obj.chainEncoding ← NIL;
obj.areaEncoding ← NIL;
END;
--Curves
IF NOT obj.closed THEN BEGIN
IF object.cluster=OpenCluster AND obj.style.outlined=FALSE
THEN SetFastStyle[] --half finished linked obj
ELSE SetTrajectoryStyle[obj.style];
IF obj.chainEncoding=NIL THEN EncodeTrajectory[obj,FALSE]; --sets chain encoding
PlotChainEncoding[obj.chainEncoding, dc];
RETURN;
END;
--Areas
IF obj.style.filled AND obj.closed THEN BEGIN
SetAreaStyle[obj.style];
IF obj.areaEncoding=NIL THEN EncodeArea[obj];
PlotAreaEncoding[obj.areaEncoding, dc];
END;
--Outlined Areas. TRUE = closed
IF obj.style.outlined THEN BEGIN
SetTrajectoryStyle[obj.style];
IF obj.chainEncoding=NIL THEN EncodeTrajectory[obj,TRUE]; --sets chain encoding
PlotChainEncoding[obj.chainEncoding, dc];
END;
END;
obj: REF Object[caption] => DisplayCaption[obj, dc];
obj: REF Object[menu] => MenuDefs.PlotMenu[obj, dc];
obj: REF Object[token] => SELECT obj.tokenType FROM
CP,open => DisplayCP[obj, dc];
selected => DisplaySelectToken[obj, dc];
vgrid,hgrid => DisplayGrid[obj, dc];
ENDCASE;
ENDCASE;
ScreenDefs.ClipOn[]; --clears PrimeClipper
clipperState ← clip;
END;
DisplayGrid: PROCEDURE[token: REF token Object, dc: Context]=
BEGIN
pt: ScrPt ← ObjToScr[token.p0];
IF token.tokenType=vgrid THEN BEGIN
ScreenDefs.BltVGrid[pt[X], dc] ;
token.tl ← [pt[X],vgridty];
token.br ← [pt[X]+gridt-1,vgridby];
END
ELSE BEGIN
ScreenDefs.BltHGrid[pt[Y], dc];
token.tl ← [hgridlx,pt[Y]];
token.br ← [hgridrx,pt[Y]+gridt-1];
END;
token.validEncoding ← TRUE;
END;
DisplayCP: PROCEDURE[token: REF token Object, dc: Context]=
BEGIN
i: CARDINAL ← IF token.tokenType=CP THEN 0 ELSE 2;
IF ~token.validEncoding THEN BEGIN
token.tl ← ObjToScr[token.p0];
token.br ← [token.tl[X]+8,token.tl[Y]+8];
token.validEncoding ← TRUE;
END;
--Token.base ← BASE[RuntimeBitmaps[i+1]];
--ScreenDefs.BLTBlockInScreen[Token,p0,erase];
ScreenDefs.EraseBox[token.tl,token.br, dc];
Token.base ← BASE[RuntimeBitmaps[i]];
ScreenDefs.BLTBlockInScreen[Token,token.tl,transparent, dc];
END;
DisplaySelectToken: PROCEDURE [token: REF token Object, dc: Context] =
BEGIN
selectedObject: ObjectHandle ← token.isSelected;
coverObj: ObjectHandle ← NIL;
covered: BOOLEAN ← FALSE;
--screen: ScreenDefs.ScreenPtr ← ScreenDefs.GetCurrentScreen[];
--stl: ScrPt ← [screen.lx,screen.ty];
--sbr: ScrPt ← [screen.rx,screen.by];
bm: CARDINAL;
IF selectedObject.validEncoding=FALSE THEN RETURN;
IF token.validEncoding = FALSE
THEN covered ← LocateSelectToken[token, selectedObject]
ELSE BEGIN
--is token covered?
coverObj ← GetObjectHandleBetweenObjects
[PointDefs.ObjToScr[token.p0], NIL, selectedObject] ;
--if not, is object covered at position of token?
IF coverObj=token THEN coverObj ←
GetObjectHandleBetweenObjects
[PointDefs.ObjToScr[token.p0],GetTopPictureObj[],selectedObject];
covered ← (coverObj#token AND coverObj#NIL);
END;
-- routine to relocate covered tokens... not used right now
-- IF covered THEN BEGIN
-- token.tl ← token.br ← [0,0];
-- so token doesn't interfere with search
-- covered ← LocateSelectToken[token, selectedObject];
-- END;
IF covered THEN bm ← 1 ELSE bm ← 0;
IF selectedObject.cluster # 0 THEN bm ← bm + 2;
SelectToken.base ← BASE[SelectBitmaps[bm]];
--ScreenDefs.ResetClipEdges[];
ScreenDefs.BLTBlockInScreen[SelectToken,token.tl,opaque, dc];
--ScreenDefs.SetClipEdges[stl,sbr];
END;
LocateSelectToken: PROCEDURE [token: REF token Object,
object: ObjectHandle] RETURNS [covered: BOOLEAN] =
BEGIN
screenLoc: PointDefs.ScrPt;
covered ← FALSE;
WITH typedObj: object SELECT FROM
caption => screenLoc ← ObjToScr[typedObj.p0];
shape => BEGIN
-- put token over second encoding chunk (encoding1.p0) if
-- it exists and isnt covered or if encoding0.p0 is covered.
encoding0: REF EncodingDefs.ChainEncoding
← typedObj.chainEncoding;
encoding1: REF EncodingDefs.ChainEncoding
← encoding0.link;
IF encoding1 = NIL THEN
BEGIN
covered ← (GetObjectHandleBetweenObjects
[encoding0.p0, NIL,object] # NIL);
screenLoc ← encoding0.p0;
END
ELSE IF covered ← (GetObjectHandleBetweenObjects
[encoding1.p0, NIL,object] # NIL)
THEN IF covered ←
(GetObjectHandleBetweenObjects
[encoding0.p0, NIL,object] # NIL)
THEN screenLoc ← encoding1.p0
ELSE screenLoc ← encoding0.p0
ELSE screenLoc ← encoding1.p0;
END;
ENDCASE => DebuggerSwap.CallDebugger
["Selected object is not caption or shape (in LocateSelectToken)"];
screenLoc[X] ← screenLoc[X] - 5;
screenLoc[Y] ← screenLoc[Y] - 5;
token.p0 ← PointDefs.ScrToObj[screenLoc];
token.tl ← screenLoc;
token.br ← [screenLoc[X]+10,screenLoc[Y]+10];
token.validEncoding ← TRUE;
RETURN;
END;
SetChainEncoding: PROCEDURE[object: REF shape Object]=
BEGIN
tl,br: ScrPt;
num: CARDINAL ← 0;
encoding: REF EncodingDefs.ChainEncoding ← EncodingDefs.MakeChainEncoding[];
IF object.chainEncoding=NIL THEN object.chainEncoding ← encoding
ELSE BEGIN
ptr: REF EncodingDefs.ChainEncoding ← object.chainEncoding;
UNTIL ptr.link=NIL DO ptr ← ptr.link; num ← ptr.linknumber; ENDLOOP;
ptr.link ← encoding;
--mark encoding chunks here
num ← num+1;
FOR ptr ← encoding, ptr ← ptr.link UNTIL ptr=NIL DO
ptr.linknumber ← num;
ENDLOOP;
END;
[tl,br] ← GetMbb[object.chainEncoding, object.style.width];
object.tl ← tl;
object.br ← br;
object.validEncoding ← TRUE;
EncodingDefs.DeleteAreaEncoding[object.areaEncoding];
object.areaEncoding ← NIL;
END;
GetMbb: PROCEDURE[encoding: REF EncodingDefs.ChainEncoding,width: REAL] RETURNS[tl,br: ScrPt]=
BEGIN
halfwidth: INTEGER ← (ObjValToScrVal[width]+1)/2;
ptr: REF EncodingDefs.ChainEncoding ← encoding;
IF ptr=NIL THEN RETURN[[0,0],[0,0]];
tl ← ptr.tl;
br ← ptr.br;
UNTIL ptr=NIL DO
IF ptr.tl[X] < tl[X] THEN tl[X] ← ptr.tl[X];
IF ptr.tl[Y] < tl[Y] THEN tl[Y] ← ptr.tl[Y];
IF ptr.br[X] > br[X] THEN br[X] ← ptr.br[X];
IF ptr.br[Y] > br[Y] THEN br[Y] ← ptr.br[Y];
ptr ← ptr.link;
ENDLOOP;
tl[X] ← tl[X]-halfwidth; tl[Y] ←tl[Y]-halfwidth;
br[X] ← br[X]+halfwidth; br[Y] 𡤋r[Y]+halfwidth;
END;
PlotChainEncoding: PROCEDURE[encoding: REF EncodingDefs.ChainEncoding, dc: Context]=
BEGIN OPEN encoding;
cState: ScreenDefs.ClipperState ← clip;
paint: GriffinViewer.PaintProc = {
UNTIL encoding=NIL DO
cState ← ScreenDefs.PrimeClipper[tl,br];
IF cState#cull THEN EncodingDefs.PlotChainChunk[encoding, dc];
encoding ← encoding.link;
ENDLOOP;
};
IF encoding=NIL THEN RETURN;
IF dc=NIL THEN GriffinViewer.DoPaint[paint] ELSE paint[dc];
ScreenDefs.ClipOn[];
END;
PlotAreaEncoding: PROCEDURE[encoding: REF EncodingDefs.AreaEncoding, dc: Context]=
BEGIN OPEN encoding;
cState: ScreenDefs.ClipperState ← clip;
paint: GriffinViewer.PaintProc = {
UNTIL encoding=NIL DO
cState ← ScreenDefs.PrimeClipper[tl,br];
IF cState#cull THEN EncodingDefs.PlotAreaChunk[encoding,dc];
encoding ← encoding.link;
ENDLOOP;
};
IF encoding=NIL THEN RETURN;
IF dc=NIL THEN GriffinViewer.DoPaint[paint] ELSE paint[dc];
ScreenDefs.ClipOn[];
END;
SetAreaStyle: PROCEDURE [style: REF StyleDefs.Style] =
BEGIN OPEN ScreenDefs;
IF FNC=write THEN ScreenDefs.SetFunction[opaque] ELSE DebuggerSwap.CallDebugger["erase case"];
ScreenDefs.SetFillParms[ControllerDefs.GreyOfColor[style.fillcolor]];
END;
SetTrajectoryStyle: PROCEDURE [style: REF StyleDefs.Style] =
BEGIN
IF FNC=write THEN ScreenDefs.SetFunction[opaque];
ScreenDefs.SetLineParms[
MAX[ObjValToScrVal[style.width],1],ControllerDefs.GreyOfColor[style.color]];
END;
SetFastStyle: PROCEDURE =
BEGIN
IF FNC=write THEN ScreenDefs.SetFunction[opaque];
--set it to plot oneline wide grey. grey is arbitray pick here
ScreenDefs.SetLineParms[1,ControllerDefs.GreyOfColor[[0,0,0]]];
END;
--Draws a trajectory
EncodeTrajectory: PROCEDURE [shape: REF shape Object,closed: BOOLEAN] =
BEGIN
traj: REF Trajectory ← shape.trajectory;
WITH traj SELECT FROM
thistraj: REF Trajectory[linked] => BEGIN
linkPtr: REF Link ← thistraj.links;
UNTIL linkPtr = NIL DO
EncodeLink[linkPtr,traj.splineType];
linkPtr ← linkPtr.link;
SetChainEncoding[shape]; --make it a link at a time
ENDLOOP;
END;
thistraj: REF Trajectory[cyclic] => BEGIN
EncodeCurve[thistraj.knots,traj.splineType,TRUE];
SetChainEncoding[shape];
END;
ENDCASE;
END;
EncodeLink: PROCEDURE[link: REF Link,spline: SplineDefs.SplineType]=
BEGIN
IF link.knots=NIL OR link.knots.length <=0 THEN RETURN;
SELECT link.degree FROM
D0 => NULL;
D1 => EncodeLines[link.knots];
D2 => NULL;
D3 => EncodeCurve[link.knots,spline,FALSE];
ENDCASE;
END;
--Encode Lines.
EncodeLines: PROCEDURE [knots: PointDefs.ObjPtSequence] =
BEGIN
i: INTEGER;
lastknot: INTEGER ← knots.length-1;
EncodingDefs.AddChainPoint[ObjToScr[knots[0]]];
FOR i IN [1..lastknot] DO
EncodingDefs.AddChainLine[ObjToScr[knots[i]]];
ENDLOOP;
END;
--Encodes a curve. description is in the knots and the splinetype
EncodeCurve: PROCEDURE [knots: PointDefs.ObjPtSequence,type: SplineDefs.SplineType,cyclic: BOOLEAN] =
BEGIN --makes an array. Don't forget to deallocate it
newknots: SplineDefs.KnotSequence ← XFormKnots[knots];
coeffs: SplineDefs.CoeffsSequence;
coeffs ← IF cyclic THEN MakeCyclicSpline[newknots,type]
ELSE SplineDefs.MakeSpline[newknots,type];
FOR i IN [0..coeffs.length) DO
SplineDefs.DisplayCubic[coeffs[i],EncodingDefs.AddChainPoint,EncodingDefs.AddChainLine];
ENDLOOP;
END;
XFormKnots: PROCEDURE[knots: PointDefs.ObjPtSequence ] RETURNS[ newknots: SplineDefs.KnotSequence]=
BEGIN
length: INTEGER ← knots.length;
newknots ← CZone.NEW[SplineDefs.KnotSequenceRec[length]];
FOR i IN [0..length) DO
newknots[i] ← PointDefs.ObjToScrReal[knots[i]];
ENDLOOP;
END;
MakeCyclicSpline: PROCEDURE[knots: SplineDefs.KnotSequence, type: SplineDefs.SplineType] RETURNS[coeffs: SplineDefs.CoeffsSequence]=
BEGIN
cycknots: SplineDefs.KnotSequence;
numknots: INTEGER ← (IF knots=NIL THEN 0 ELSE knots.length);
newLength: INTEGER;
IF numknots <= 0 THEN RETURN[NIL];
SELECT type FROM
naturalUM, naturalAL,bezier=> newLength ← numknots+1;
bspline, crspline=> newLength ← numknots+3;
ENDCASE;
cycknots ← CZone.NEW[SplineDefs.KnotSequenceRec[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];
RETURN;
END;
--makes a new linked trajectory with knuth splines in gaps
FillGaps: PROCEDURE[traj: REF linked Trajectory,closed: BOOLEAN] RETURNS[REF linked Trajectory] =
BEGIN
RETURN[traj];
END;
--Fills an area
EncodeArea: PROCEDURE [area: REF shape Object] =
BEGIN
--need chain encoding to make area encoding
IF area.chainEncoding=NIL THEN BEGIN
SetFastStyle;
EncodeTrajectory[area,TRUE];
--object doesn't have an outline (happens as it's being drawn or modified)
IF area.chainEncoding=NIL THEN RETURN;
END;
SetAreaStyle[area.style];
area.areaEncoding ← EncodingDefs.MakeAreaEncoding[area.chainEncoding];
area.validEncoding ← TRUE;
END;
--writes the object. Screen function set to replace or paint depending on type of obj
PlotOneObject: PUBLIC PROCEDURE [object: ObjectHandle,function: DisplayFnc] =
BEGIN
FNC ← function;
PlotObject[object, NIL];
END;
WriteObject: PUBLIC PROCEDURE [object: ObjectHandle] =
BEGIN
tl,br: ScrPt;
FNC ← write;
IF object=NIL THEN RETURN;
IF NOT object.validEncoding THEN BEGIN
PlotOneObject[object,write];
object ← object.link; --now clean up above it
IF object=NIL THEN RETURN;
END;
--a little slop to catch the select token
tl ← object.tl;
br ← object.br;
IF object.objectType#token AND object.objectType#menu THEN BEGIN
tl ← [tl[X]-selW,tl[Y]-selW];
br ← [br[X]+selW,br[Y]+selW];
END;
ReplotBoxFromObject[tl, br, object, NIL];
END;
ReplotBoxFromObject: PUBLIC PROCEDURE[tl,br: ScrPt, object: ObjectHandle, dc: Context]=
BEGIN
FNC ← write;
ScreenDefs.SetClipEdges[tl,br];
ReplotFromObject[object, dc];
ScreenDefs.ResetClipEdges[];
END;
ReplotBox: PUBLIC PROCEDURE[tl,br: ScrPt, dc: Context]=
BEGIN
FNC ← write;
ScreenDefs.SetClipEdges[tl,br];
ReplotAllObjects[dc];
--reset them
ScreenDefs.ResetClipEdges[];
END;
EraseObject: PUBLIC PROCEDURE [object: ObjectHandle] =
BEGIN
Screen: ObjectProc = BEGIN
IF obj#object THEN PlotObject[obj, NIL];
END;
tl,br: ScrPt;
erased: BOOLEAN ← FALSE;
IF object=NIL THEN RETURN;
IF NOT object.validEncoding THEN BEGIN
PlotOneObject[object,erase];
erased ← TRUE;
END;
--a little slop to catch the select token
tl ← object.tl;
br ← object.br;
IF object.objectType#token AND object.objectType#menu THEN BEGIN
tl ← [tl[X]-selW,tl[Y]-selW];
br ← [br[X]+selW,br[Y]+selW];
END;
ScreenDefs.SetClipEdges[tl, br];
IF NOT erased THEN ScreenDefs.ClearScreen[NIL];
FNC ← write;
ForAllObjects[Screen];
--reset them
ScreenDefs.ResetClipEdges[];
END;
WriteLink: PUBLIC PROCEDURE[obj: REF shape Object,link: REF Link]=
BEGIN
paint: GriffinViewer.PaintProc = {PlotChainEncoding[obj.chainEncoding, dc]};
FNC ← write;
--first link
WITH traj: obj.trajectory SELECT FROM
linked => IF traj.links=link THEN BEGIN
EncodingDefs.DeleteChainEncoding[obj.chainEncoding];
EncodingDefs.DeleteAreaEncoding[obj.areaEncoding];
obj.chainEncoding ← NIL;
obj.areaEncoding ← NIL;
END;
ENDCASE => ERROR;
IF obj.style.outlined THEN SetTrajectoryStyle[obj.style] ELSE SetFastStyle;
EncodeLink[link,obj.trajectory.splineType];
SetChainEncoding[obj];
GriffinViewer.DoPaint[paint];
END;
--no EraseLink. It's all in DeleteLink for now
RuntimeBitmaps[0] ←
[16000B,12000B,12000B,173600B,104200B,173600B,12000B,12000B,16000B]; --CP
RuntimeBitmaps[1] ←
[16000B,16000B,16000B,177600B,177600B,177600B,16000B,16000B,16000B]; --erase cp
RuntimeBitmaps[2] ← [37000B,61400B,140600B,100200B,104200B,100200B,140600B,61400B,37000B]; --open
RuntimeBitmaps[3] ← [37000B,77400B,177600B,177600B,177600B,177600B,177600B,77400B,37000B]; --erase open
SelectBitmaps[0] ← [0,0,0,17770B,17770B,14030B,14030B,14630B,14630B,14030B,
14030B,17770B,17770B,0,0,0]; --selected not hidden.
SelectBitmaps[1] ← [0,0,0,17770B,17770B,17030B,17430B,15630B,14730B,14370B,
14170B,17770B,17770B,0,0,0]; --selected and hidden.
SelectBitmaps[2] ← [0,0,0,17770B,17770B,14030B,15730B,15030B,15030B,15730B,
14030B,17770B,17770B,0,0,0]; --selected not hidden cluster.
SelectBitmaps[3] ← [0,0,0,17770B,17770B,14070B,15730B,15230B,15430B,15730B,
16030B,17770B,17770B,0,0,0]; --selected and hidden cluster.
--block for local variables
END.