-- color screen drawing module of silicon (pretty picture) program -- last modified by E. McCreight, January 31, 1984 4:27 PM DIRECTORY BitBltDefs, ChipOrient, InlineDefs, IODefs, AltoDefs, AltoFileDefs, MiscDefs, multiGraphicsDefs, SegmentDefs, ProcessDefs, ppCache, ppdddefs,ppddefs, ppoutdefs, ppdefs; ppdrawCol: PROGRAM IMPORTS BitBltDefs, ChipOrient, InlineDefs, MiscDefs, multiGraphicsDefs, ppCache, ppdddefs, ppddefs, ppdefs, ppoutdefs, ProcessDefs, SegmentDefs 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 _ background; -- reset every time we repaint Black: PROC RETURNS [Color] = BEGIN dimmestColor: Color _ 0; dimmest: INTEGER _ 1000; FOR color: [0..15] IN [0..15] DO intensity: INTEGER _ 0; FOR j: [0..2] IN [0..2] -- r, g, b -- DO(1792) intensity _ intensity-getCurrenColor[color, j]; -- getCurrenColor returns dimmer more positive than brighter ENDLOOP; IF intensity 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]; RETURN[TRUE, cscale[cxoff+MAX[x1, cClipx1]], cscale[cyoff+MAX[y1, cClipy1]], cscale[cxoff+MIN[x2, cClipx2]], cscale[cyoff+MIN[y2, cClipy2]]]; END; cClipScale: PROCEDURE [x1, y1, x2, y2: INTEGER, cr: POINTER TO Rect] RETURNS [BOOLEAN, INTEGER, INTEGER, INTEGER, INTEGER] = INLINE BEGIN -- assumes design space translated by offset IF x1 > cr.x2 OR x2 < cr.x1 OR y1 > cr.y2 OR y2 < cr.y1 THEN RETURN[FALSE, 0, 0, 0, 0]; RETURN[TRUE, cscale[MAX[x1, cr.x1]], cscale[MAX[y1, cr.y1]], cscale[MIN[x2, cr.x2]], cscale[MIN[y2, cr.y2]]]; END; outlineCol: PUBLIC PROCEDURE [ w, x, y, z: INTEGER, q: color, clip: POINTER TO Rect _ NIL] = {NULL}; -- 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[]; destRaster: RasterDesc; colBitsPerPixel: CARDINAL = 4; -- 4 bits/pixel logBitsPerPixel: CARDINAL = 2; 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] _ cClipScale[w, x, y, z, clip]; IF bb AND showColorLevel[l] 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[MAX[1, c-a], logBitsPerPixel]; BLT.blk.dh _ MAX[1, 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 clip _ @universe; [bb, a, b, c, d] _ cClipScale[w, x, y, z, clip]; IF bb AND showColorLevel[l] THEN BEGIN -- 0<=a<=c<= and 0<=b<=d BLT.blk.dlx _ BITSHIFT[a, logBitsPerPixel]; BLT.blk.dty _ b; BLT.blk.dw _ BITSHIFT[MAX[1, c-a], logBitsPerPixel]; BLT.blk.dh _ MAX[1, 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; 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; [bb, a, b, c, d] _ cClipScale[r.x1, r.y1, r.x2, r.y2, IF clip#NIL THEN clip ELSE @universe]; 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; 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] _ cClipScale[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; whiteGray: GrayPattern; ShowSelected: PROC [lp: listPtr, saveCursor: BOOLEAN] = BEGIN bb: BOOLEAN; size: Point = ChipOrient.Size[size: [x: lp.ob.size[0], y: lp.ob.size[1]], orient: lp.idx]; sx1, sx2, sy1, sy2: Pixel; [bb, sx1, sy1, sx2, sy2] _ cscaleRect[lp.lx, lp.ly, lp.lx+size.x, lp.ly+size.y]; IF bb THEN BEGIN ref: Rect = ChipOrient.MapRect[itemInCell: [1,1,2,2], cellSize: [x: lp.ob.size[0], y: lp.ob.size[1]], cellInstOrient: lp.idx, cellInstPos: [x: lp.lx, y: lp.ly]]; IF saveCursor THEN gonnaDoCrect[sx1, sy1, sx2, sy2]; DoColorArea[sx1, sy1, sx2, sy1, replace, FALSE, @whiteGray]; DoColorArea[sx1, sy1, sx1, sy2, replace, FALSE, @whiteGray]; DoColorArea[sx1, sy2, sx2, sy2, replace, FALSE, @whiteGray]; DoColorArea[sx2, sy1, sx2, sy2, replace, FALSE, @whiteGray]; [, sx1, sy1, sx2, sy2] _ cscaleRect[ref.x1, ref.y1, ref.x2, ref.y2]; DoColorArea[sx1, sy1, sx2, sy2, replace, FALSE, @whiteGray]; -- mark reference corner IF saveCursor THEN doneCrect[]; END; 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 _ [ -- expressed in design coordinates translated by [cxoff, cyoff] [0, 0, 0, 0], [0, 0, 0, 0], orColArea, rememberCol, outlineCol, drawColText, 1]; abortColor: PUBLIC BOOLEAN _ FALSE; savCBbox: PUBLIC Rect; updateColor: PUBLIC PROC = BEGIN OPEN ProcessDefs; DO bp: LONG CARDINAL; dangerousUpdateColor[! ANY => {MiscDefs.CallDebugger[ "Color repainter signalled, ^P to continue after next backup pass"]; CONTINUE}]; bp _ ppoutdefs.backupPass; WHILE ppoutdefs.backupPass=bp DO Pause[SecondsToTicks[1]] ENDLOOP; ENDLOOP; END; dangerousUpdateColor: PROC = BEGIN ColorPaintList: PROC [head: LONG POINTER TO listPtr, background: BOOLEAN _ FALSE, pushee: listPtr _ NIL] = 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 # pushee THEN BEGIN ppCache.DrawWithCaching[ob: lp.ob, orient: lp.idx, x: lp.lx+offset.x, y: lp.ly+offset.y, pr: @colDrR, dest: @destRaster]; IF lp.selected AND NOT background THEN ShowSelected[lp: lp, saveCursor: FALSE]; END; IF NOT background AND lp.props # NIL THEN drawColText[lp.lx+offset.x, lp.ly+offset.y, 0, 0, "prop", @colScreenRect]; 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]; destRaster.nPixels _ [x: xColorMax*colBitsPerPixel, y: yColorMax]; destRaster.scanLineWords _ BLT.blk.dbmr; destRaster.map _ LOOPHOLE[BLT.blk.dlbca]; DO cmd _ getColNewRect[]; black _ Black[]; 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; ppCache.SetupCacheGrayTables[]; offset _ [cxoff, cyoff]; colScreenRect _ [cClipx1+offset.x, cClipy1+offset.y, cClipx2+offset.x, cClipy2+offset.y]; -- translated design coords of entire color screen, can be changed by user command colDrR.minSize _ (colGrain*cScaleD)/cScaleN; SELECT cmd.cmd FROM rect, all => BEGIN cs: cellSEPtr = cellStack; r, cmprect, xcbb: 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[[x1: cmd.r.x1+offset.x, y1: cmd.r.y1+offset.y, x2: cmd.r.x2+offset.x, y2: cmd.r.y2+offset.y], colScreenRect]; END; colDrR.bigr _ cmprect _ -- expanded to include wells and the like [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] _ cClipScale[r.x1, r.y1, r.x2, r.y2, @colScreenRect]; -- scale design rect to screen coords gonnaDoCrect[sx1, sy1, sx2, sy2]; -- remove cursor from this screen rectangle IF cmd.ers THEN BEGIN a, b, c, d: INTEGER; bb: BOOLEAN; [bb, a, b, c, d] _ cClipScale[r.x1, r.y1, r.x2, r.y2, @colScreenRect]; IF bb THEN DoColorArea[a, b, c, d, replace, TRUE, @backgroundGray]; END; cremIdx _ 0; IF cs#NIL THEN BEGIN NoOpRect: PROC [r: Rect] = {NULL}; RestoreBackground: PROC [r: Rect] = BEGIN clippedR: Rect = ClipRect[r, cmprect]; 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; [bb, a, b, c, d] _ cClipScale[w, x, y, z, IF clip#NIL THEN clip ELSE @universe]; IF bb THEN DoColorArea[a, b, c, d, replace, TRUE, @backgroundGray]; END; resBkgDrR: drRecord _ [clippedR, clippedR, BkgColArea, BkgColArea, NIL, NIL, 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; mbb: Rect = ChipOrient.BoundingRect[masterList]; xmbb: Rect = [x1: mbb.x1+offset.x, y1: mbb.y1+offset.y, x2: mbb.x2+offset.x, y2: mbb.y2+offset.y]; xcbb _ [x1: cs.origBB.x1+offset.x, y1: cs.origBB.y1+offset.y, x2: cs.origBB.x2+offset.x, y2: cs.origBB.y2+offset.y]; FOR bkg: cellSEPtr _ cs, bkg.nxt WHILE bkg#NIL AND bkg.instance#NIL DO IF abortColor THEN EXIT; ColorPaintList[head: @bkg.lp, background: TRUE, pushee: bkg.instance]; ENDLOOP; ChipOrient.DecomposeRect[r: r, test: xcbb, rInsideTest: fuzzColWithBackground, rOutsideTest: fuzzColWithBlack]; ChipOrient.DecomposeRect[r: xmbb, test: xcbb, rInsideTest: NoOpRect, rOutsideTest: RestoreBackground]; END; colRemBkgIdx _ cremIdx; ColorPaintList[IF cellNameMode THEN @cnList ELSE @masterList]; IF cs#NIL THEN doColorRemember[first: 0, afterLast: colRemBkgIdx, background: TRUE, cellBB: xcbb]; -- make these dim 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 = [x1: r.x1+Mod[-r.x1, t], y1: r.y1+Mod[-r.y1, t], x2: r.x2, y2: r.y2]; IF NOT Empty[ticksRect] THEN BEGIN [, sx1, sy1, sx2, sy2] _ cClipScale[ticksRect.x1, ticksRect.y1, ticksRect.x2, ticksRect.y2, @universe]; gonnaDoCrect[sx1, sy1, sx2, sy2]; drawTicks[[x1: sx1, y1: sy1, x2: sx2, y2: sy2], scaledT]; doneCrect[]; END; END; END; END; sel => ShowSelected[lp: cmd.p, saveCursor: TRUE]; 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 showColorLevel[l] AND cremIdx=8) THEN BEGIN 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; END.