DIRECTORY Basics USING [BITSHIFT, BITAND, LongMult, logBitsPerWord], CD, CDInstances, CDBasics, CDColors, CDOps, CDOrient, CDPrivate, CDTexts, CDValue, CDVPrivate, CDVScale, Imager, ImagerFont, ImagerTransformation, VFonts, PrincOps USING [BBptr, BitAddress, BBTable, SrcDesc, BitBltFlags, GrayParm], PrincOpsUtils USING [BITBLT], Rope, RuntimeError, Terminal, ViewerClasses, ViewerSpecs; CDVDraw: CEDAR MONITOR IMPORTS Basics, CD, CDInstances, CDBasics, CDOps, CDOrient, CDValue, CDVPrivate, CDVScale, Imager, ImagerFont, ImagerTransformation, VFonts, PrincOpsUtils, RuntimeError, Terminal EXPORTS CDVPrivate, CD --DrawRef's private fields-- = BEGIN ViewerPrivateRep: PUBLIC TYPE = CDVPrivate.MyGraphicRec; ViewerSaveRep: PUBLIC TYPE = INTEGER; -- XXX placeholder MyGraphicRef: TYPE = CDVPrivate.MyGraphicRef; MyGraphicRec: TYPE = CDVPrivate.MyGraphicRec; maxInfluence: CD.Number = 0; virtual: Terminal.Virtual = Terminal.Current[]; defaultFont: Imager.Font = VFonts.DefaultFont[]; maskModBitsPerWord: CARDINAL = 15; errrorReport: RECORD [ text: Rope.ROPE, me: MyGraphicRef, r: CD.Rect, color: REF CDColors.Brick ]; bitBltFlagsForPaint: PrincOps.BitBltFlags = PrincOps.BitBltFlags[ direction: forward, disjoint: TRUE, disjointItems: TRUE, gray: TRUE, srcFunc: null, dstFunc: or ]; bitBltFlagsForOutline: PrincOps.BitBltFlags = PrincOps.BitBltFlags[ direction: forward, disjoint: TRUE, disjointItems: TRUE, gray: TRUE, srcFunc: null, dstFunc: or ]; bitBltFlagsForClearPattern: PrincOps.BitBltFlags = PrincOps.BitBltFlags[ direction: forward, disjoint: TRUE, disjointItems: TRUE, gray: TRUE, srcFunc: complement, dstFunc: and ]; blackBrick: REF CDColors.Brick = NEW[CDColors.Brick_ALL[LAST[CARDINAL]]]; whiteBrick: REF CDColors.Brick = NEW[CDColors.Brick_ALL[0]]; BitBlitDraw: PROC[me: MyGraphicRef, r: CD.Rect, color: REF CDColors.Brick] = TRUSTED --INLINE compiler overflows-- BEGIN ENABLE { UNWIND => NULL; RuntimeError.UNCAUGHT => { errrorReport.text _ "BitBlitDraw"; errrorReport.me _ me; errrorReport.r_r; errrorReport.color_color; IF CDVPrivate.catchAny THEN GOTO SomeError ELSE REJECT; }; }; xBit, x1, x2, y1, y2: CARDINAL; vr: CD.Rect; IF ~CDBasics.NonEmpty[r] THEN RETURN; vr _ CDVScale.DesignToViewerRect[me.scale, r]; x1 _ MAX[vr.x1, 0]; y1 _ MAX[vr.y1, 0]; IF vr.x2<=0 OR vr.y2<=0 THEN RETURN; x2 _ MIN[vr.x2, me.viewer.cw]; y2 _ MIN[vr.y2, me.viewer.ch]; IF x1>=x2 OR y1>=y2 THEN RETURN; xBit _ Basics.BITSHIFT[x1+me.vx, me.logbpp]; me.pBBptr.width _ Basics.BITSHIFT[x2-x1, me.logbpp]; me.pBBptr.height _ y2-y1; y1 _ me.vy-y2; me.pBBptr.dst _ [ me.screen + Basics.LongMult[y1, me.scWidthWords] + LONG[Basics.BITSHIFT[xBit, -Basics.logBitsPerWord]],, Basics.BITAND[xBit, maskModBitsPerWord] ]; me.pBBptr.src _ [ LOOPHOLE[ LOOPHOLE[color, LONG CARDINAL] + Basics.BITAND[y1, 3B], LONG POINTER],, Basics.BITAND[xBit, maskModBitsPerWord] ]; me.pBBptr.srcDesc.gray.yOffset _ Basics.BITAND[y1, 3B]; IF me.display=bw THEN PrincOpsUtils.BITBLT[me.pBBptr] ELSE { Blit: PROC [] = TRUSTED BEGIN PrincOpsUtils.BITBLT[me.pBBptr]; END; Terminal.ModifyColorFrame[vt: virtual, action: Blit, xmin: x1+me.vx, ymin: y1, xmax: x2+me.vx, ymax: y1+me.pBBptr.height ]; }; EXITS SomeError => NULL; END; BitBlitOutLine: ENTRY PROC[r: CD.Rect, pr: CD.DrawRef] = BEGIN ENABLE { UNWIND => NULL; RuntimeError.UNCAUGHT => { errrorReport.text _ "BitBlitOutLine"; errrorReport.me _ pr.viewerPrivate; errrorReport.r _ r; IF CDVPrivate.catchAny THEN GOTO SomeError ELSE REJECT; }; }; me: MyGraphicRef = pr.viewerPrivate; vr, clipr: CD.Rect; DrawBlack: PROC[me: MyGraphicRef, x1, y1, x2, y2: INTEGER] = TRUSTED INLINE BEGIN xBits: CARDINAL = Basics.BITSHIFT[x1+INTEGER[me.vx], me.logbpp]; me.xBBptr.width _ Basics.BITSHIFT[x2-x1, me.logbpp]; me.xBBptr.height _ y2-y1; me.xBBptr.dst _ [ me.screen + Basics.LongMult[INTEGER[me.vy]-y2, me.scWidthWords] + LONG[Basics.BITSHIFT[xBits, -Basics.logBitsPerWord]],, Basics.BITAND[xBits, maskModBitsPerWord] ]; PrincOpsUtils.BITBLT[me.xBBptr]; END; DoIt: PROC [] = BEGIN IF vr.x1>=clipr.x1 THEN DrawBlack[me, clipr.x1, clipr.y1, clipr.x1+1, clipr.y2]; --left IF vr.y2<=clipr.y2 THEN DrawBlack[me, clipr.x1, clipr.y2-1, clipr.x2, clipr.y2]; --top IF vr.x2<=clipr.x2 THEN DrawBlack[me, clipr.x2-1, clipr.y1, clipr.x2, clipr.y2]; --right IF vr.y1>=clipr.y1 THEN DrawBlack[me, clipr.x1, clipr.y1, clipr.x2, clipr.y1+1]; --bottom END; IF r.x2>me.dClip.x2 THEN r.x2 _ me.dClip.x2+1; IF r.y2>me.dClip.y2 THEN r.y2 _ me.dClip.y2+1; IF r.x1=clipr.x2 OR clipr.y1>=clipr.y2 THEN RETURN; --harder empty test than CDBasics --necessary because we add/subtract one TRUSTED { me.xBBptr.src _ [LOOPHOLE[blackBrick, LONG POINTER],,0]; me.xBBptr.flags _ bitBltFlagsForOutline; me.xBBptr.srcDesc _ PrincOps.SrcDesc[gray[PrincOps.GrayParm[ yOffset: 0, widthMinusOne: 0, --words heightMinusOne: 0 --lines ]]]; }; IF me.display=bw THEN { DoIt[]; } ELSE { Terminal.ModifyColorFrame[vt: virtual, action: DoIt, xmin: clipr.x1+me.vx, ymin: me.vy+1-clipr.y2, xmax: clipr.x2+me.vx-1, ymax: me.vy-clipr.y1 ]; }; EXITS SomeError => NULL; END; BitBlitDrawRectForViewers: ENTRY PROC[r: CD.Rect, l: CD.Layer, pr: CD.DrawRef] = BEGIN ENABLE UNWIND => NULL; me: MyGraphicRef = pr.viewerPrivate; BitBlitDraw[me, CDBasics.Intersection[r, pr.interestClip], me.colorTable[l]]; END; SetGround: --CD.SetGroundProc-- PROC [pr: CD.DrawRef, pushedOut: BOOL] = BEGIN WITH pr.devicePrivate SELECT FROM me: MyGraphicRef => me.colorTable _ me.personalColors[me.display][IF pushedOut THEN pushedOut ELSE normal] ENDCASE => NULL; END; DrawCommentForViewers: PUBLIC PROC[r: CD.Rect, comment: Rope.ROPE, pr: CD.DrawRef] = BEGIN topToFontLine: NAT = 9+2; fontHeight: NAT = 10; leftMargin: NAT = 2; bothMargin: NAT = 2*leftMargin; me: MyGraphicRef _ NARROW[pr.devicePrivate]; vr: CD.Rect _ CDVScale.DesignToViewerRect[me.scale, r]; IF vr.y2-vr.y1>fontHeight THEN { xw: REAL = ImagerFont.RopeWidth[font: defaultFont, rope: comment].x; IF vr.x2-vr.x1>xw+bothMargin THEN { Imager.SetColor[me.viewContext, Imager.black]; Imager.SetFont[me.viewContext, defaultFont]; Imager.SetXY[me.viewContext, [vr.x1+leftMargin, vr.y2-topToFontLine]]; Imager.ShowRope[me.viewContext, comment]; } }; END; RepaintRectAreaInViewer: PUBLIC PROC[me: MyGraphicRef, rect: CD.Rect, eraseFirst: BOOL] = BEGIN ENABLE { RuntimeError.UNCAUGHT => IF CDVPrivate.catchAny THEN GOTO SomeError ELSE REJECT }; interestRect: CD.Rect; UpdateDrawInformation[me]; me.deviceDrawRef.interestClip _ interestRect _ CDBasics.Intersection[rect, me.dClip]; IF CDBasics.NonEmpty[interestRect] THEN { RepaintBackground[me, interestRect, eraseFirst]; CDOps.QuickDrawDesign[me.actualDesign, me.deviceDrawRef]; FOR pl: CDVPrivate.PainterList _ me.painterList, pl.rest WHILE pl#NIL DO IF CDBasics.Intersect[interestRect, pl.first.rect] THEN pl.first.proc[me, pl.first, interestRect ! RuntimeError.UNCAUGHT => IF CDVPrivate.catchAny THEN CONTINUE ELSE REJECT ] ENDLOOP } EXITS SomeError=> NULL END; RepaintBackground: PUBLIC ENTRY PROC[me: MyGraphicRef, r: CD.Rect, eraseFirst: BOOL] = BEGIN ENABLE { UNWIND => NULL; RuntimeError.UNCAUGHT => { errrorReport.text _ "background"; errrorReport.me _ me; errrorReport.r _ r; IF CDVPrivate.catchAny THEN GOTO SomeError ELSE REJECT }; }; DrawOutside: PROC [r: CD.Rect] = BEGIN BitBlitDraw[me, CDBasics.Intersection[r, me.dClip], me.colorTable[CD.backGround]]; END; IF eraseFirst THEN { TRUSTED {me.pBBptr.flags.dstFunc _ null}; BitBlitDraw[me, CDBasics.Intersection[r, me.dClip], whiteBrick]; TRUSTED {me.pBBptr.flags.dstFunc _ or}; }; IF me.actualDesign.actual.first.mightReplace#NIL AND me.environment AND me.actualDesign.actual.first.mightReplace.ob#NIL THEN CDBasics.DecomposeRect[r: r, test: CDInstances.InstRectO[me.actualDesign.actual.first.mightReplace], outside: DrawOutside ]; EXITS SomeError => NULL; END; InitForBBLT: PROC [me: MyGraphicRef] = BEGIN IF me.viewer.column=color THEN TRUSTED { m: Terminal.ColorMode = Terminal.GetColorMode[virtual]; IF m.full OR m.bitsPerPixelChannelA=0 THEN ERROR CDVPrivate.notSupportedColorMode; me.bpp _ m.bitsPerPixelChannelA; me.frame _ Terminal.GetColorFrameBufferA[virtual]; IF me.bpp=8 THEN { me.display _ bit8; me.logbpp _ 3; } ELSE IF me.bpp=4 THEN { me.display _ bit4; me.logbpp _ 2; } ELSE IF me.bpp=2 THEN { me.display _ bit2; me.logbpp _ 1; } ELSE IF me.bpp=1 THEN { me.display _ bit1; me.logbpp _ 0; } ELSE IF me.bpp=16 THEN { --ERROR, but we try to avoid crashing... me.display _ bit1; me.logbpp _ 4; } ELSE ERROR; } ELSE { -- b+w me.frame _ Terminal.GetBWFrameBuffer[virtual]; me.display _ bw; me.logbpp _ 0; }; me.bpp _ me.frame.bitsPerPixel; me.screen _ me.frame.base; me.colorTable _ me.personalColors[me.display][normal]; me.vx _ me.viewer.cx+me.viewer.wx; me.vy _ me.frame.height-(me.viewer.cy+me.viewer.wy); me.scWidthWords _ me.frame.wordsPerLine; TRUSTED BEGIN me.pBBptr^ _ PrincOps.BBTable[ dst: TRASH, dstBpl: me.frame.width*me.frame.bitsPerPixel, src: TRASH, srcDesc: PrincOps.SrcDesc[gray[PrincOps.GrayParm[ yOffset: 0, --is actually trash widthMinusOne: 0, --words heightMinusOne: 3 --lines ]]], width: TRASH, height: TRASH, flags: bitBltFlagsForPaint ]; me.xBBptr^ _ me.pBBptr^; END; END; SetupContext: PROC [pr: CD.DrawRef, me: MyGraphicRef] = BEGIN s: REAL; pr.deviceContext _ me.viewContext; s _ CDVScale.DesignToViewerFactor[me.scale]; pr.scaleHint _ s*me.suppressFactorForCells; Imager.SetColor[me.viewContext, Imager.black]; Imager.SetFont[me.viewContext, defaultFont]; pr.b1 _ me.b1; pr.b2 _ me.b2; END; ViewerDrawContext: PROC [pr: CD.DrawRef, proc: CD.DrawContextLayerProc, ob: CD.Object, pos: CD.Position, orient: CD.Orientation, layer: CD.Layer] = BEGIN IF pr.deviceContext#NIL AND pr.contextFilter#NIL AND pr.contextFilter[layer].doit THEN { CreateTransform: PROC [ cellSize: CD.Position, cellInstOrient: CD.Orientation, cellInstPos: CD.Position _ [0,0]] RETURNS [Imager.Transformation] = INLINE BEGIN RETURN [SELECT cellInstOrient FROM --original--0 => ImagerTransformation.Create[1, 0, cellInstPos.x, 0, 1, cellInstPos.y], 1 => ImagerTransformation.Create[-1, 0, cellInstPos.x+cellSize.x, 0, 1, cellInstPos.y], -- reflection in x --rotate90-- 2 => ImagerTransformation.Create[0, -1, cellInstPos.x+cellSize.y, 1, 0, cellInstPos.y], -- 90 degrees clockwise 3 => ImagerTransformation.Create[0, 1, cellInstPos.x, 1, 0, cellInstPos.y], -- 90 degrees clockwise followed by reflection in x --rotate180-- 4 => ImagerTransformation.Create[-1, 0, cellInstPos.x+cellSize.x, 0, -1, cellInstPos.y+cellSize.y], -- 180 degrees clockwise 5 => ImagerTransformation.Create[1, 0, cellInstPos.x, 0, -1, cellInstPos.y+cellSize.y], -- 180 degrees clockwise followed by reflection in x --rotate270-- 6 => ImagerTransformation.Create[0, 1, cellInstPos.x, -1, 0, cellInstPos.y+cellSize.x], -- 270 degrees clockwise 7 => ImagerTransformation.Create[0, -1, cellInstPos.x+cellSize.y, -1, 0, cellInstPos.y+cellSize.x], -- 270 degrees clockwise followed by reflection in x ENDCASE => ERROR ]; END; Action: PROC [] = BEGIN me: MyGraphicRef = NARROW[pr.viewerPrivate]; Imager.ScaleT[pr.deviceContext, CDVScale.DesignToViewerFactor[me.scale]]; Imager.TranslateT[pr.deviceContext, [-me.scale.off.x, -me.scale.off.y]]; IF ob#NIL THEN { IF orient=CD.original THEN Imager.TranslateT[pr.deviceContext, [pos.x, pos.y]] ELSE Imager.ConcatT[pr.deviceContext, CreateTransform[ cellSize: ob.size, cellInstOrient: orient, cellInstPos: pos ]]; }; Imager.SetColor[pr.deviceContext, pr.contextFilter[layer].color]; proc[pr.deviceContext, ob, layer]; END; Imager.DoSave[pr.deviceContext, Action]; } END; InternalCreateDrawInformation: INTERNAL PROC [me: MyGraphicRef] = BEGIN pr: CD.DrawRef = CD.CreateDrawRef[me.actualDesign]; me.deviceDrawRef _ pr; pr.contextFilter _ me.contextFilter _ GetContextFilter[me]; pr.drawRect _ BitBlitDrawRectForViewers; pr.drawOutLine _ BitBlitOutLine; pr.drawComment _ DrawCommentForViewers; pr.drawContext _ ViewerDrawContext; pr.setGround _ SetGround; pr.devicePrivate _ me; pr.stopFlag _ me.stoprequest; pr.symbolics _ me.symbolics; pr.environment _ me.environment; pr.interestClip _ me.dClip _ CDVScale.GetClipRecord[me.scale, me.viewer.cw, me.viewer.ch]; pr.minimalSize _ --XXX-- MIN[(me.dClip.x2-me.dClip.x1)/8, (me.dClip.y2-me.dClip.y1)/8]; InitForBBLT[me]; pr.viewerPrivate _ me; -- this line last! it tells DummyNotify that the rest is initialized END; UpdateDrawInformation: ENTRY PROC [me: MyGraphicRef] = BEGIN ENABLE UNWIND => NULL; IF me.deviceDrawRef=NIL THEN InternalCreateDrawInformation[me]; SetupContext[me.deviceDrawRef, me]; END; CreateDrawInformation: PUBLIC ENTRY PROC [me: MyGraphicRef] = BEGIN ENABLE UNWIND => NULL; InternalCreateDrawInformation[me]; SetupContext[me.deviceDrawRef, me]; END; GetContextFilter: PROC [me: MyGraphicRef] RETURNS [REF CD.ContextFilter] = BEGIN WITH CDValue.Fetch[boundTo: me.actualDesign.technology, key: $ContextFilter, propagation: global] SELECT FROM rcf: REF CD.ContextFilter => RETURN [rcf]; ENDCASE => RETURN [defaultContextFilter] END; defaultContextFilter: REF CD.ContextFilter = NEW[CD.ContextFilter]; FOR l: CD.Layer IN CD.Layer DO defaultContextFilter[l].color _ Imager.black; defaultContextFilter[l].doit _ TRUE; ENDLOOP; defaultContextFilter[CD.backGround].doit _ FALSE; CDValue.EnregisterKey[$ContextFilter]; CDValue.Store[NIL, $ContextFilter, defaultContextFilter]; END. PCDVDraw.mesa Copyright c 1983, 1985 by Xerox Corporation. All rights reserved. Christian Jacobi, August 5, 1983 11:07 am last edited by Christian Jacobi, September 4, 1985 8:07:42 pm PDT -- r ALLREADY CLIPPED --DONE OUTSIDE r _ CDBasics.Intersection[r, me.deviceDrawRef.interestClip]; --draw exclusive high border pixels --no empty test; is guaranteed by caller --clip to area where --1) small enough: it does not crash on scaling later --2) big enogh: if drawn, it does not draw artificial lines IF vr.x1>=clipr.x1 THEN DrawBlack[me, clipr.x1, clipr.y1, clipr.x1+1, clipr.y2]; --left IF vr.y2<=clipr.y2 THEN DrawBlack[me, clipr.x1, clipr.y2-1, clipr.x2, clipr.y2]; --top IF vr.x2<=clipr.x2 THEN DrawBlack[me, clipr.x2-1, clipr.y1, clipr.x2, clipr.y2]; --right IF vr.y1>=clipr.y1 THEN DrawBlack[me, clipr.x1, clipr.y1, clipr.x2, clipr.y1+1]; --bottom --RepaintBackground -- me.vx _ distance from left of screen to left most pixel -- me.vy _ distance from top of screen to bottom most pixel -- in device in pixels ---------- --fixed pBBptr initializations --done in viewerprocess: me.pBBptr _ PrincOpsUtils.AlignedBBTable[@bBTableSpace]; --calls proc which may use context; mode and color are set to layer's need --call is suppressed if layer does not need drawing; this is default. --on recursive calls, the context may or may not include previous transformations -- Given the size of a cell, -- the position and orientation of an instance of that cell in "world" -- co-ordinates, returns the transformation to be applied to -- cell points to get world points. --old, slower version Imager.TranslateT[pr.deviceContext, [pos.x, pos.y]]; CDOrient.OrientateContext[pr.deviceContext, ob.size, orient]; PROCEDURE NOT USED because Qickdraw gives us no chance NamedDrawChild: PROC [inst: CD.Instance, pos: CD.Position, orient: CD.Orientation, pr: CD.DrawRef] = BEGIN Comment: PROC [comment: Rope.ROPE] = BEGIN me: MyGraphicRef _ NARROW[pr.devicePrivate]; vpos: CD.Position = CDVScale.DesignToViewerPosition[me.scale, pos]; pr.deviceContext.SetColor[Imager.black]; pr.deviceContext.SetCP[vpos.x+1, vpos.y+1]; pr.deviceContext.DrawRope[comment]; END; inst.ob.p.drawMe[inst, pos, orient, pr]; IF pr.b2 THEN { WITH CDProperties.GetPropFromInstance[from: inst, prop: $SignalName] SELECT FROM r: Rope.ROPE => Comment[r]; a: ATOM => Comment[Atom.GetPName[a]]; ENDCASE => NULL; }; END; ÊG˜šœ ™ Jšœ Ïmœ7™BJšœ)™)JšœA™AJ˜—šÏk ˜ Jšœžœžœžœ˜:Jšžœ˜J˜ J˜ J˜ J˜J˜ J˜ J˜Jšœ˜Jšœ ˜ J˜ Jšœ˜Jšœ ˜ Jšœ˜Jšœ˜Jšœ žœ>˜LJšœžœžœ˜J˜Jšœ ˜ Jšœ ˜ Jšœ˜J˜ J˜—šÏbœžœž˜Jšžœžœ ˜²Jšžœ žœÏcœ˜5—Jšž˜J˜Jšœžœžœ˜8Jšœžœžœžœ ˜:J˜Jšœžœ˜-Jšœžœ˜-Jšœžœ ˜Jšœ/˜/Jšœ0˜0Jšœžœ˜"J˜šœžœ˜Jšœ žœ˜Jšœ˜Jšœžœ˜ Jšœžœ˜Jšœ˜—J˜šœA˜AJ˜Jšœ žœ˜Jšœžœ˜Jšœžœ˜ Jšœ˜Jšœ ˜ J˜—J˜šœC˜CJ˜Jšœ žœ˜Jšœžœ˜Jšœžœ˜ Jšœ˜Jšœ ˜ J˜—J˜šœH˜HJ˜Jšœ žœ˜Jšœžœ˜Jšœžœ˜ Jšœ˜Jšœ ˜ J˜—J˜Jš œ žœžœžœžœžœ˜IJšœ žœžœžœ˜—Jšœ˜Jšœ D˜\Jšžœ˜—J˜Jš¡6™6š ¡œžœžœžœžœ ™RJšœžœ ™Jšž™J™š¡œžœžœ™$Jšž™Jšœžœ™,Jšœžœ;™CJšœ(™(Jšœ+™+Jšœ#™#Jšžœ™—J™Jšœ(™(šžœžœ™šžœAž ™PJšœžœ™Jšœžœ™%Jšžœžœ™—J™—Jšžœ™J™—š¡œžœžœ˜6šžœ˜Jšžœžœžœ˜—šžœžœžœ˜Jšœ"˜"—Jšœ#˜#Jšžœ˜J˜—š¡œžœžœžœ˜=šžœ˜Jšžœžœžœ˜—Jšœ"˜"Jšœ#˜#Jšžœ˜J˜—š ¡œžœžœžœžœ˜JJšžœ˜šžœ^žœž˜mJšœžœžœžœ˜*Jšžœžœ˜(—Jšžœ˜J˜—Jš œžœžœžœžœ˜Cš žœžœžœžœž˜Jšœ-˜-Jšœžœ˜$Jšžœ˜—Jšœžœžœ˜1Jšœ&˜&Jšœžœ(˜9Jšžœ˜J˜—…—5ÌRc