-- color screen drawing module of silicon (pretty picture) program
-- last modified by E. McCreight, December 30, 1982 12:38 PM
DIRECTORY
BitBltDefs,
ChipOrient,
InlineDefs,
IODefs,
AltoDefs,
AltoFileDefs,
multiGraphicsDefs,
SegmentDefs,
ProcessDefs,
ppdddefs,ppddefs,
ppdefs;
ppdrawCol: PROGRAM
IMPORTS
BitBltDefs, ChipOrient, ppdefs, ppddefs, InlineDefs,
multiGraphicsDefs, ProcessDefs,
SegmentDefs, ppdddefs
EXPORTS ppdefs, ppddefs =
BEGIN
OPEN ppdefs, ppddefs, ppdddefs,InlineDefs, multiGraphicsDefs,
SegmentDefs, IODefs;
cScale: PUBLIC INTEGER ← 9;
cScaleN: PUBLIC INTEGER ← 1;
cScaleD: PUBLIC INTEGER ← 1;
cxoff, cyoff: PUBLIC INTEGER ← 0;
selColOffset: CARDINAL ← 16;
cClipx1: PUBLIC INTEGER ← 0;
cClipx2: PUBLIC INTEGER ← xColorMax;
cClipy1: PUBLIC INTEGER ← 0;
cClipy2: PUBLIC INTEGER ← yColorMax;
-- Colors! note, in the array "colors", color 0 is at top, 15 at bottom
-- R G B
--Colors 0:background 1:grn 2:blue
-- 3: blue & grn 4:red 5:red & grn
-- 6:red & blue 7:red & grn & blue 8:ovg cut:maroon?
-- 9:contact cut: black 10:sel.outln,curs,wht 11:burr?
-- 12:outline undrawn cell 13:? 14:yellow (dots)
-- 15:outline - white (also dots, curs?)
cTabCnt: PUBLIC CARDINAL;
colorTabs: PUBLIC LONG POINTER TO ARRAY [0..0) OF ARRAY [0..49) OF CARDINAL ←
LOOPHOLE[1322400B];
currentCTab: PUBLIC CARDINAL;
anyCTChanges: PUBLIC BOOLEAN ← FALSE;
background: Color = 0;
maroon: Color = 8;
black: Color = 9;
white: Color = 15;
-- orLtab: PUBLIC ARRAY level OF Color ← [1231B, 1020B, 1004B,
--1040B, 76B, 8, 33B, 10,
-- 9,1,10,62B,10,8,10,10];
orLtab: PUBLIC ARRAY level OF Color ← [11B, 1, 4, 2, 76B, 8, 33B, 10,
9,1,10,62B,10,8,10,10];
showColorLevel: PUBLIC ARRAY level OF BOOLEAN ← ALL[TRUE];
-- note: meaning of levels = cut,dif,pol,met,impl,ovg,?,?
-- note: color of levels = blk,grn,red,blu,yell,mron,?,?
-- note: color number of lev= 9 , 1 , 4 , 2 , 16B, 8 ,?,?
colPatternTabs:PUBLIC ARRAY [0..colPatNum) OF ARRAY level OF CARDINAL;
colPatternBits:PUBLIC ARRAY [0..colPatNum) OF CARDINAL←ALL[0];
cscale: PROCEDURE [x, y: INTEGER] RETURNS [INTEGER, INTEGER] = INLINE
BEGIN
RETURN[((cxoff + x)*cScaleN)/cScaleD, ((cyoff + y)*cScaleN)/cScaleD];
END;
cscaleRect: PUBLIC PROCEDURE [x1, y1, x2, y2: INTEGER]
RETURNS [BOOLEAN, INTEGER, INTEGER, INTEGER, INTEGER] =
BEGIN
t: INTEGER;
IF x1 > x2 THEN BEGIN t ← x1; x1 ← x2; x2 ← t; END;
IF y1 > y2 THEN BEGIN t ← y1; y1 ← y2; y2 ← t; END;
IF x1 > cClipx2 OR x2 < cClipx1 OR y1 > cClipy2 OR y2 < cClipy1 THEN
RETURN[FALSE, 0, 0, 0, 0];
[x1, y1] ← cscale[MAX[x1, cClipx1], MAX[y1, cClipy1]];
[x2, y2] ← cscale[MIN[x2, cClipx2], MIN[y2, cClipy2]];
RETURN[TRUE, x1, y1, x2, y2];
END;
csAndClip: PROCEDURE [x1, y1, x2, y2: INTEGER, cr: POINTER TO Rect]
RETURNS [BOOLEAN, INTEGER, INTEGER, INTEGER, INTEGER] = INLINE
BEGIN
IF x1 > cr.x2 OR x2 < cr.x1 OR y1 > cr.y2 OR y2 < cr.y1 THEN
RETURN[FALSE, 0, 0, 0, 0];
[x1, y1] ← cscale[MAX[x1, cr.x1], MAX[y1, cr.y1]];
[x2, y2] ← cscale[MIN[x2, cr.x2], MIN[y2, cr.y2]];
RETURN[TRUE, x1, y1, x2, y2];
END;
outlineCol: PUBLIC PROCEDURE [
w, x, y, z: INTEGER, q: color, clip: POINTER TO Rect ← NIL] =
BEGIN
oulColArea[w, x, w, z, q, clip,0,1];
oulColArea[y, x, y, z, q, clip,1,1];
oulColArea[w, z, y, z, q, clip,1,1];
oulColArea[w, x, y, x, q, clip,1,0];
END;
-- Note: The following two procedures are thought to be
-- executed very often, and have therefore been optimized heavily. The code
-- has been taken from multiGraphicsGefs and cbitfns.
BLT: BLTBlockPtr ← AllocateBLT[];
logBitsPerPixel: CARDINAL = 2; -- 4 bits/point
levColorGray, levMaskGray: ARRAY level OF GrayPattern;
orColArea: PUBLIC PROCEDURE [
w, x, y, z: INTEGER, l: level, clip: POINTER TO Rect ← NIL] =
BEGIN
a, b, c, d: INTEGER;
bb: BOOLEAN;
-- w, x, y, and z form an oriented rectangle
[bb, a, b, c, d] ← csAndClip[w, x, y, z, clip];
IF bb THEN
BEGIN
-- 0<=a<=c<= and 0<=b<=d
BLT.blk.function ← paint;
BLT.blk.dlx ← BITSHIFT[a, logBitsPerPixel];
BLT.blk.dty ← b;
BLT.blk.dw ← BITSHIFT[c-a, logBitsPerPixel];
BLT.blk.dh ← d-b;
SetupBitBltGray[BLT: BLT, gray: @levColorGray[l]];
BitBltDefs.BITBLT[@BLT.blk];
END;
END;
levMaskGrayPtrs: ARRAY level OF POINTER TO GrayPattern;
repColArea: PUBLIC PROCEDURE [
w, x, y, z: INTEGER, l: level, clip: POINTER TO Rect ← NIL] =
BEGIN
a, b, c, d: INTEGER;
bb: BOOLEAN;
IF clip = NIL THEN [bb, a, b, c, d] ← cscaleRect[w, x, y, z]
ELSE [bb, a, b, c, d] ← csAndClip[w, x, y, z, clip];
IF bb THEN
BEGIN
-- 0<=a<=c<= and 0<=b<=d
BLT.blk.dlx ← BITSHIFT[a, logBitsPerPixel];
BLT.blk.dty ← b;
BLT.blk.dw ← BITSHIFT[c-a, logBitsPerPixel];
BLT.blk.dh ← d-b;
IF levMaskGrayPtrs[l]#NIL THEN
BEGIN
BLT.blk.function ← erase;
SetupBitBltGray[BLT: BLT, gray: levMaskGrayPtrs[l]];
BitBltDefs.BITBLT[@BLT.blk];
BLT.blk.function ← paint;
END
ELSE BLT.blk.function ← replace;
SetupBitBltGray[BLT: BLT, gray: @levColorGray[l]];
BitBltDefs.BITBLT[@BLT.blk];
END;
END;
whiteGray: GrayPattern;
oulColArea: PROCEDURE [
w, x, y, z: INTEGER, q: color, clip: POINTER TO Rect,offx,offy:INTEGER] =
BEGIN
a, b, c, d: INTEGER;
bb: BOOLEAN;
[bb, a, b, c, d] ← csAndClip[w, x, y, z, clip];
IF bb THEN
BEGIN
IF q=white THEN
DoColorArea[a, b, c-offx, d-offy, replace, TRUE, @whiteGray]
ELSE
BEGIN
otherGray: GrayPattern ← GetColorGray[q];
DoColorArea[a, b, c-offx, d-offy, replace, TRUE, @otherGray];
END;
END;
END;
fuzzColWithBackground: PROC [r: Rect] = {fuzzOutColArea[r]};
fuzzColWithBlack: PROC [r: Rect] = {fuzzOutColArea[r, black]};
fuzzPattern: Color ← 64;
fuzzOutColArea: PUBLIC PROCEDURE [r: Rect, color: Color ← background,
clip: POINTER TO Rect ← NIL] =
BEGIN
background: CARDINAL = 0;
a, b, c, d: INTEGER;
bb: BOOLEAN;
IF clip = NIL THEN [bb, a, b, c, d] ← cscaleRect[r.x1, r.y1, r.x2, r.y2]
ELSE [bb, a, b, c, d] ← csAndClip[r.x1, r.y1, r.x2, r.y2, clip];
IF bb THEN
BEGIN
fuzzColorGray: GrayPattern ← GetColorGray[fuzzPattern+color];
fuzzMaskGray: GrayPattern ← GetMaskGray[fuzzPattern+color];
DoColorArea[a, b, c, d, replace, TRUE, @fuzzColorGray, @fuzzMaskGray];
END;
END;
backgroundGray: GrayPattern;
eraseScreen: PUBLIC PROCEDURE [w, x, y, z: INTEGER] =
BEGIN
DoColorArea[w, x, y, z, replace, FALSE, @backgroundGray];
EraseArea[w, x, y, z];
END;
eraseArea: PUBLIC PROCEDURE [w, x, y, z: INTEGER] =
BEGIN
a, b, c, d: INTEGER;
bb: BOOLEAN;
[bb, a, b, c, d] ← cscaleRect[w, x, y, z];
IF bb THEN DoColorArea[a, b, c, d, replace, FALSE, @backgroundGray];
eraseBwArea[w, x, y, z];
END;
eraseColArea: PUBLIC PROCEDURE [w, x, y, z: INTEGER] =
BEGIN
a, b, c, d: INTEGER;
bb: BOOLEAN;
[bb, a, b, c, d] ← cscaleRect[w, x, y, z];
IF bb THEN DoColorArea[a, b, c, d, replace, TRUE, @backgroundGray];
END;
drawArea: PUBLIC PROCEDURE [w, x, y, z: INTEGER, c: color] =
BEGIN
a, b, q, d: INTEGER;
bb: BOOLEAN;
[bb, a, b, q, d] ← cscaleRect[w, x, y, z];
IF bb THEN
BEGIN
color: GrayPattern ← GetColorGray[c];
mask: GrayPattern ← GetMaskGray[c];
DoColorArea[a, b, q, d, replace, FALSE, @color, @mask];
END;
[bb, a, b, q, d] ← bwscaleRect[w, x, y, z];
IF bb THEN BEGIN SetGrayLevel[c]; ReplaceGray[a, b, q, d]; END;
END;
setSelColor: PUBLIC PROCEDURE [a: CARDINAL] = BEGIN selColOffset ← a; END;
drawMark: PUBLIC PROCEDURE [x, y: INTEGER] =
BEGIN
a, b, c, d: INTEGER;
bb: BOOLEAN;
[bb, a, b, c, d] ← cscaleRect[x, y, x, y];
IF bb THEN
BEGIN
colorPat: GrayPattern;
SetColorFromSource[source: @cursorBox, x: a, y: b, fn: erase];
colorPat ← GetColorGray[c: black];
SetColorFromSource[source: @cursorBox, x: a, y: b,
fn: paint, sourceType: andgray, gray: @colorPat];
colorPat ← GetColorGray[c: black-maroon];
SetColorFromSource[source: @insideCBox, x: a, y: b, fn: invert,
sourceType: andgray, gray: @colorPat];
END;
END;
drawColText: PROCEDURE [
x, y, sx, sy: INTEGER, s: STRING, clip: POINTER TO Rect] =
BEGIN
a, b, c, d: INTEGER;
bb: BOOLEAN;
[bb, a, b, c, d] ← csAndClip[x, y, x, y, clip];
c ← MIN[a + 5, colWidth];
d ← MIN[b + 5, colHeight];
IF bb THEN PutColorArea[x1: a, y1: b, x2: c, y2: d, c: white];
END;
--**** stuff that used to be in ppprocs:
cremArray: LONG DESCRIPTOR FOR ARRAY OF rems ← DESCRIPTOR[
LongDataSegmentAddress[NewDataSegment[DefaultANYBase, remPages]], remLen];
cremIdx: CARDINAL ← 0;
colDrR: drRecord ← [
[0, 0, 0, 0], [0, 0, 0, 0], orColArea, rememberCol, outlineCol, drawColText, 1];
abortColor: PUBLIC BOOLEAN ← FALSE;
savCBbox: PUBLIC Rect;
updateColor: PUBLIC PROC =
BEGIN
ColorPaintList: PROC [head: LONG POINTER TO listPtr,
background: BOOLEAN ← FALSE] =
BEGIN
next: listPtr;
finished: BOOLEAN ← FALSE;
WHILE NOT (finished OR abortColor) DO
FOR lp: listPtr ← head↑, next WHILE lp # NIL DO
next ← lp.nxt;
IF abortColor OR lp.deleted THEN EXIT;
IF lp.ob # NIL THEN
BEGIN
lp.ob.p.drawme[lp.idx][lp.ob, lp.lx, lp.ly, @colDrR];
IF lp.selected AND NOT background THEN
BEGIN
ii: [0..1] = ChipOrient.Rot90[lp.idx];
outlineCol[
lp.lx, lp.ly, lp.lx + lp.ob.size[ii], lp.ly + lp.ob.size[1-ii],
white, @colScreenRect];
END;
END;
IF lp.gotText AND NOT background THEN
BEGIN
tp: LONG POINTER TO text prop ← getTextProp[lp];
drawColText[lp.lx, lp.ly, 0, 0, tp.s, @colScreenRect];
END;
REPEAT
FINISHED => finished ← TRUE;
ENDLOOP;
ENDLOOP;
END; -- of ColorPaintList
doColorRemember: PROC [first, afterLast: CARDINAL,
background: BOOLEAN ← FALSE, cellBB: Rect ← [0,0,0,0]] =
BEGIN
r: Rect;
l: level;
FOR i: CARDINAL IN [first..afterLast) DO
IF abortColor THEN RETURN;
[r: r, l: l] ← cremArray[i];
repColArea[r.x1, r.y1, r.x2, r.y2, l];
IF background THEN
ChipOrient.DecomposeRect[r: r, test: cellBB, rInsideTest: fuzzColWithBackground,
rOutsideTest: fuzzColWithBlack];
ENDLOOP;
END; -- of doColorRemember
colScreenRect: Rect;
cmd: sCmd;
ProcessDefs.SetPriority[0];
abortColor ← FALSE;
SetupColorAreaBLT[BLT: BLT, x1: 0, x2: 0, y1: 0, y2: 0, fn: replace];
DO
cmd ← getColNewRect[];
backgroundGray ← GetColorGray[background];
whiteGray ← GetColorGray[white];
FOR l: level IN level DO
levColorGray[l] ← GetColorGray[orLtab[l]];
levMaskGray[l] ← GetMaskGray[orLtab[l]];
levMaskGrayPtrs[l] ← IF levMaskGray[l]#solid THEN @levMaskGray[l] ELSE NIL;
ENDLOOP;
colScreenRect ← [cClipx1, cClipy1, cClipx2, cClipy2];
-- design coords of entire color screen, could be changed by user command
colDrR.minSize ← (colGrain*cScaleD)/cScaleN;
SELECT cmd.cmd FROM
rect, all =>
BEGIN
cs: cellSEPtr = cellStack;
r, cmprect: Rect;
colRemBkgIdx: CARDINAL;
markX, markY: locNum;
onColorScreen: BOOLEAN;
sx1, sx2, sy1, sy2: INTEGER; -- screen units
SELECT cmd.cmd FROM
all => r ← colScreenRect;
ENDCASE =>
BEGIN
cmd.r ← cannonRect[cmd.r];
r ← ClipRect[cmd.r, colScreenRect];
END;
cmprect ← colDrR.bigr ←
[x1: MAX[colScreenRect.x1, r.x1 - wellSurround],
x2: MIN[colScreenRect.x2, r.x2 + wellSurround],
y1: MAX[colScreenRect.y1, r.y1 - wellSurround],
y2: MIN[colScreenRect.y2, r.y2 + wellSurround]];
colDrR.r ← r ← IF NOT cmd.ers THEN r ELSE cmprect;
[onColorScreen, sx1, sy1, sx2, sy2] ←
cscaleRect[r.x1, r.y1, r.x2, r.y2]; -- scale it to screen coords
gonnaDoCrect[sx1, sy1, sx2, sy2]; -- remove cursor from this screen rectangle
IF cmd.ers THEN
SELECT cmd.cmd FROM
all => DoColorArea[0,0,xColorMax,yColorMax,replace,FALSE,
@backgroundGray];
ENDCASE => eraseColArea[r.x1, r.y1, r.x2, r.y2];
cremIdx ← 0;
IF cs#NIL THEN
BEGIN
NoOpRect: PROC [r: Rect] = {NULL};
RestoreBackground: PROC [r: Rect] =
BEGIN
clippedR: Rect = ClipRect[r, colDrR.r];
IF NOT Empty[clippedR] THEN
BEGIN
BkgColArea: PROC [w, x, y, z: INTEGER, l: level,
clip: POINTER TO Rect ← NIL] =
BEGIN
a, b, c, d: INTEGER;
bb: BOOLEAN;
IF clip = NIL THEN [bb, a, b, c, d] ← cscaleRect[w, x, y, z]
ELSE [bb, a, b, c, d] ← csAndClip[w, x, y, z, clip];
IF bb THEN DoColorArea[a, b, c, d, replace, TRUE, @backgroundGray];
END;
resBkgDrR: drRecord ←
[clippedR, clippedR, BkgColArea, BkgColArea, outlineCol, drawColText, 1];
FOR lp: listPtr ← masterList, lp.nxt WHILE lp#NIL DO
IF lp.ob#NIL THEN
lp.ob.p.drawme[lp.idx][lp.ob, lp.lx, lp.ly, @resBkgDrR];
ENDLOOP;
END;
END;
FOR bkg: cellSEPtr ← cs, bkg.nxt
WHILE bkg#NIL AND bkg.instance#NIL DO
IF abortColor THEN EXIT;
ColorPaintList[head: @bkg.lp, background: TRUE];
ENDLOOP;
ChipOrient.DecomposeRect[r: r, test: cs.origBB,
rInsideTest: fuzzColWithBackground,
rOutsideTest: fuzzColWithBlack];
ChipOrient.DecomposeRect[r: ChipOrient.BoundingRect[masterList],
test: cs.origBB,
rInsideTest: NoOpRect, rOutsideTest: RestoreBackground];
END;
colRemBkgIdx ← cremIdx;
ColorPaintList[IF cellNameMode THEN @cnList ELSE @masterList];
IF cs#NIL THEN
BEGIN
doColorRemember[first: 0, afterLast: colRemBkgIdx, background: TRUE,
cellBB: cs.origBB]; -- make these dim
END;
doColorRemember[first: colRemBkgIdx, afterLast: cremIdx];
doneCrect[]; -- put the cursor back
[markX, markY] ← markPnt;
[onColorScreen, sx1, sy1, , ] ←
cscaleRect[markX, markY, markX, markY];
IF onColorScreen AND NOT abortColor THEN
BEGIN
gonnaDoCrect[sx1, sy1, sx1 + 16, sy1 + 16];
drawMark[markX, markY];
doneCrect[];
END;
IF tickGrid # 0 AND NOT abortColor THEN
BEGIN
t: locNum = tickGrid*Lambda;
scaledT: Pixel = (t*cScaleN)/cScaleD;
IF scaledT >= tickOff*2 THEN -- we should paint ticks
BEGIN
ticksRect: Rect ← ClipRect[r, [cClipx1, cClipy1, cClipx2, cClipy2]];
modNeg: Point ← [x: (-ticksRect.x1) MOD t, y: (-ticksRect.y1) MOD t];
ticksRect.x1 ← ticksRect.x1+modNeg.x+
(IF modNeg.x<0 THEN -- Mesa screwed up !! -- t ELSE 0);
ticksRect.y1 ← ticksRect.y1+modNeg.y+
(IF modNeg.y<0 THEN -- Mesa screwed up !! -- t ELSE 0);
IF NOT Empty[ticksRect] THEN
BEGIN
[, sx1, sy1, sx2, sy2] ←
cscaleRect[ticksRect.x1, ticksRect.y1, ticksRect.x2, ticksRect.y2];
gonnaDoCrect[sx1, sy1, sx2, sy2];
drawTicks[[x1: sx1, y1: sy1, x2: sx2, y2: sy2], scaledT];
doneCrect[];
END;
END;
END;
END;
sel =>
BEGIN
lp: listPtr = cmd.p;
ii: [0..1] = ChipOrient.Rot90[lp.idx];
r: Rect = [x1: lp.lx, y1: lp.ly,
x2: lp.lx + lp.ob.size[ii], y2: lp.ly + lp.ob.size[1-ii]];
sx1, sx2, sy1, sy2: Pixel;
[, sx1, sx2, sy1, sy2] ← cscaleRect[r.x1, r.y1, r.x2, r.y2];
gonnaDoCrect[sx1, sx2, sy1, sy2];
outlineCol[r.x1, r.y1, r.x2, r.y2, white, @colScreenRect];
doneCrect[];
END;
ENDCASE => ERROR;
ENDLOOP;
END;
drawTicks: PROC [r: ScreenRect, t: Pixel] =
BEGIN
FOR y: Pixel ← r.y1, y+t WHILE y <= r.y2 DO
IF abortColor THEN RETURN;
FOR x: Pixel ← r.x1, x+t WHILE x <= r.x2 DO
PutColorPoint[x: x, y: y, c: white];
ENDLOOP;
ENDLOOP;
END;
redoCBBox: PUBLIC PROCEDURE =
BEGIN
r, s: ScreenRect ← savCBbox;
r.x1 ← r.x2;
reDrawRect[r, 1, TRUE, FALSE, FALSE];
r.x2 ← r.x1 ← s.x1;
reDrawRect[r, 1, TRUE, FALSE, FALSE];
r.x2 ← s.x2;
r.y1 ← r.y2;
reDrawRect[r, 1, TRUE, FALSE, FALSE];
r.y2 ← r.y1 ← s.y1;
reDrawRect[r, 1, TRUE, FALSE, FALSE];
END;
rememberCol: PROCEDURE [
x1, y1, x2, y2: INTEGER, l: level, clip: POINTER TO Rect] =
BEGIN
IF cremIdx >= remLen OR (l = cut AND cScale < 8) THEN RETURN;
cremArray[cremIdx].r ← ClipRect[[x1, y1, x2, y2], clip↑];
IF NOT Empty[cremArray[cremIdx].r] THEN
BEGIN
cremArray[cremIdx].l ← l;
cremIdx ← cremIdx + 1;
END;
END;
END.