-- 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.