-- File: DJExtGraphics.mesa
-- Routines for generating graphical output for Disjoint
-- Written by Martin Newell/Dan Fitzpatrick February 1981
-- Last edited (Pilot): 12-Aug-81 14:27:
56

DIRECT
ORY

CIFUtilitiesDefs: FROM "CIFUtilitiesDefs" USING [DrawRectangleOutline, GetClipRectangle, Rectangle],
DisjointTypes: FROM "DisjointTypes" USING [Instance, Symbol, Rectangle, Geometry],
DisjointAllocDefs: FROM "DisjointAllocDefs" USING [EnumerateSymbols],
DJExtractDefs: FROM "DJExtractDefs" USING [Interrupt, GetSegmentList],
DJExtGraphicsDefs: FROM "DJExtGraphicsDefs",
DJExtTypes: FROM "DJExtTypes" USING [Segment],
IODefs: FROM "IODefs" USING [WriteLine],
JaMFnsDefs: FROM "JaMFnsDefs" USING [GetJaMBreak],
MoreCIFUtilitiesDefs: FROM "MoreCIFUtilitiesDefs" USING [DrawStringAt, SetStipple, DrawRectangleArea],
String: FROM "String" USING [AppendLongDecimal];

DJExtGraphics: PROGRAM
IMPORTS CIFUtilitiesDefs, Disj
ointAllocDefs, DJExtractDefs, IODefs, JaMFnsDefs, MoreCIFUtilitiesDefs, String
EXPORTS DJExtGraphicsDefs =
BEGIN
OPEN CIFUtilitiesDefs, DisjointTypes, DisjointAllocDefs, DJExtractDefs, DJExtTypes, IODefs, JaMFnsDefs, MoreCIFUtilitiesDefs, String;

DontDraw: PUBLIC PROCEDURE =
BEGIN
Draw ← FALSE;
END;

DrawLongDecimal: PUBLIC PROCEDURE[n:L
ONG INTEGER,x,y:REAL] =
BEGIN
str:STRING ← [50];
IF NOT Draw THEN RETURN;
x ← sx[x];y ← sy[y];
AppendLongDecimal[str,n];
DrawStringAt[str, x,y];
END;

DrawSegment: PUBLIC PROCEDURE[x0,y0,x1,y1:REAL] =
BEGIN
IF NOT Draw THEN RETURN;
IF x0 = x1 THEN {-- vertical line
IF y1 < y0 THEN {t:REAL←y1;y1←y0;y0←t;};
DrawRectangle[x0-w,y0,x0+w,y1,177777B];
RETURN;
};
IF y0 = y1 THEN {-- horizontal line
IF x1 < x0 THEN {t:REAL←x1;x1←x0;x0←t;};
DrawRectangle[x0,y0-w,x1,y0+w,177777B];
RETURN;
};
DrawRectangle[x0-w,y0-w,x0+w,y0+w,177777B];
END;

DrawSymbol: PUBLIC PROCEDURE[s: Symbol, callOnce: BOOLEAN,
level: INTEGER] =
--draw all instances of s at given level of hi
erarchy
--
level=0 is top level
--level=-1 will draw all geometry
--callOnce=TRUE will allow only the first call to each symbol
BEGIN

Mark: PROC[s: Symbol] RETURNS[BOOLEAN] =
BEGIN
--here .mark means symbol can still be called
s.mark ← TRUE;
RETURN[FALSE];
END;

r: CIFUtilitiesDefs.Rectangle;
count ← 0;
drawSegs ← TRUE;
IF NOT Draw THEN RETURN;
-- mark all the symbols
[] ← EnumerateSymbols[Mark];
r ← GetClipRectangle[];
[ClipL,ClipB,ClipR,ClipT] ← r;
InitMap[s];
DrawSymbolR[s, callOnce, 0,0, level];
END;

DrawSymbolR: PROCEDURE[s: Symbol, callOnce: BOOLEAN,
x,y: REAL, level: INTEGER] =
-- draw all instances of s at given level
of hierarchy
-- level=0 is top level
BEGIN
IF level=0 THEN DrawCellOffset[s, x,y, s.data]
ELSE {
-- IF level=1 OR level<0 THEN DrawGeomOffset[s, x,y];
FOR i:Instance ← s.insts, i.next UNTIL i=NIL DO
IF GetJaMBreak[] THEN SIGNAL Interrupt;
IF i.symbol.mark THEN
DrawSymbolR[i.symbol, callOnce, x+i.xOffset,y+i.yOffset, level-1];
IF callOnce THEN i.symbol.mark ← FALSE;
ENDLOOP;
};
END;

DrawCellOffset: PUBLIC PROCEDURE[us: Symbol, x,y: REAL, stipple: CARDINAL] =
BEGIN
r: DisjointTypes.Rectangle;
IF NOT Draw THEN RETURN;
FOR r ← us.windows, r.next UNTIL r=NIL DO
DrawRectangle[r.l+x,r.b+y,r.r+x,r.t+y, stipple];
ENDLOOP;
IF NOT drawSegs THEN RETURN;
FOR s: Segment ← GetSegmentList[us],s.next UNTIL s = NIL DO
IF count = 300 THEN {
WriteLine["Punt on internal segments"];
drawSegs ← FALSE;
EXIT;
};
count ← count + 1;
DrawSegment[s.bx+x,s.by+y,s.tx+x,s.ty+y];
ENDLOOP;
END;

DrawGeomOffset: PUBLIC PROCEDURE[us: Symbol, x,y: REAL] =
BEGIN
w: DisjointTypes.Rectangle;
IF NOT Draw THEN RETURN;
FOR w ← us.windows, w.next UNTIL w=NIL DO
DrawRectangleOutline[[sx[w.l+x],sy[w.b+y],sx[w.r+x],sy[w.t+y]]];
ENDLOOP;
FOR g:Geometry ← us.geom, g.next UNTIL g=NIL DO
DrawRectangle[g.l+x,g.b+y,g.r+x,g.t+y, Stipple[g.layer]];
ENDLOOP;
END;

DrawRectangle: PUBLIC PROCEDURE[l,b,r,t: REAL, stipple: CARDINAL] =
BEGIN
IF NOT Draw THEN RETURN;
SetStipple[stipple];
l ← sx[l];r ← sx[r];
b ← sy[b];t ← sy[t];
DrawRectangleArea[[l,b,r,t]];
END;

ClipL,ClipB,ClipR,ClipT: REAL;

BoundBox: PUBLIC PROCEDURE[s: Symbol] RETURNS[l,b,r,t: REAL] =
BEGIN
rec: DisjointTypes.Rectangle;
l ← s.windows.l;
b ← s.windows.b;
r ← s.windows.r;
t ← s.windows.t;
--always at least one window
FOR rec ← s.windows.next, rec.next UNTIL rec=NIL DO
l ← MIN[l,rec.l];
b ← MIN[b,rec.b];
r ← MAX[r,rec.r];
t ← MAX[t,rec.t];
ENDLOOP;
END;

scale,cx,cy,w: REAL;

InitMap: PUBLIC PROCEDURE[s: Symbol] =
BEGIN
l,b,r,t: REAL;
[l,b,r,t] ← BoundBox[s];
scale ← MIN[((ClipR-ClipL)/(r-l)),((ClipT-ClipB)/(t-b))];
cx ← (ClipL+ClipR)/2 - scale*(l+r)/2;
cy ← (ClipT+ClipB)/2 - scale*(t+b)/2;
w ← MAX[(r-l),(t-b)]/200;
END;

sx: PUBLIC PR
OCEDURE[x: REAL] RETURNS[REAL] =
BEGIN
RETURN[scale*x+cx];
END;

sy: PUBLIC PROCEDURE[y: REAL] RETURNS[REAL] =
BEGIN
RETURN[scale*y+cy];
END;


count: CARDINAL;
drawSegs: BOOLEAN;
Draw: BOOLEAN ← TRUE;

Stipple: ARRAY [0..16) OF CARDINAL ← ALL[177777B];
--undef

--Set up default stipples
Stipple[0] ← 000020B;
--implant
Stipple[1] ←
040501B;--diffusion
Stipple[2] ← 014102B;
--poly
Stipple[3] ← 165627B;
--contact
Stipple[4] ← 000050B;
--metal
Stipple[5] ← 001110B;
--buried
Stipple[6] ← 001122B;
--glass
Stipple[7] ← 177777B;
--undef

END.