-- File CIFVersatecUtils.mesa -- Written by Martin Newell, June 1980 -- Last updated: April 28, 1981 5:42 PM DIRECTORY CIFDevicesDefs: FROM "CIFDevicesDefs" USING [MaxLENGTHLayerArray], CIFUtilitiesDefs: FROM "CIFUtilitiesDefs" USING [ScreenParams], CIFVersatecScanDefs: FROM "CIFVersatecScanDefs" USING[VersatecScanConvert], CIFVersatecTypeDefs: FROM "CIFVersatecTypeDefs" USING [Edge, EdgeRecord, EdgeAngle], CIFVersatecUtilsDefs: FROM "CIFVersatecUtilsDefs", InlineDefs: FROM "InlineDefs" USING[LongCOPY], Mopcodes: FROM "Mopcodes" USING [zWBL], SegmentDefs: FROM "SegmentDefs" USING[NewDataSegment, DefaultXMBase, LongDataSegmentAddress], SystemDefs: FROM "SystemDefs" USING[AllocateHeapNode, FreeHeapNode], TrapezoidDefs: FROM "TrapezoidDefs" USING[TrapezoidBlock, TrapezoidBlt], VersatecDefs: FROM "VersatecDefs" USING [StartVersatecPlot, EndVersatecPlot, WriteVersatecLine]; CIFVersatecUtils: PROGRAM IMPORTS CIFUtilitiesDefs, CIFVersatecScanDefs, InlineDefs, SegmentDefs, SystemDefs, TrapezoidDefs, VersatecDefs EXPORTS CIFVersatecUtilsDefs = BEGIN OPEN CIFDevicesDefs, CIFUtilitiesDefs, CIFVersatecScanDefs, CIFVersatecTypeDefs, InlineDefs, Mopcodes, SegmentDefs, SystemDefs, TrapezoidDefs, VersatecDefs; VersatecNextStripe: PUBLIC PROCEDURE = BEGIN --finish off and output current stripe, and step to next VersatecScanConvert[VStripeTop, FALSE]; VersatecScanConvert[VStripeTop, TRUE]; VersatecOutStripe[]; VersatecClearStripe[TRUE]; VStripeBottom _ VStripeTop; VStripeTop _ VStripeTop + VStripeHeight; END; OutputStripesUntil: PUBLIC PROCEDURE[y: REAL] = BEGIN WHILE y>=VStripeTop DO VersatecNextStripe[]; ENDLOOP; END; VersatecMakeEdge: PUBLIC PROCEDURE [xstart,ystart,xend,yend: REAL, up: BOOLEAN] RETURNS[edge: Edge] = BEGIN --make edge of appropriate type dx: REAL; dy: REAL _ yend-ystart; IF dy<=0 THEN RETURN[NIL]; dx _ xend-xstart; IF dx=0 THEN BEGIN --make vertical edge edge _ AllocateVerticalEdge[]; edge^ _ [ next: , xstart: xstart, ystart: ystart, yend: yend, lastouty: ystart, mate: NIL, up: up, flagout: FALSE, vert: TRUE, var: vertical[] ]; END ELSE BEGIN --make oblique edge edge _ AllocateObliqueEdge[]; edge^ _ [ next: , xstart: xstart, ystart: ystart, yend: yend, lastouty: ystart, mate: NIL, up: up, flagout: FALSE, vert: FALSE, var: oblique[ xend: xend, slope: dx/dy ] ]; END; RETURN[edge]; END; VersatecOutText: PUBLIC PROCEDURE[x,y: REAL, s: STRING] = BEGIN TextList _ AllocateText[TextList,x,y,s]; END; VersatecAllocateStripe: PUBLIC PROCEDURE = BEGIN --allocate space for VStripeHeight+1 lines (last one never output, but copied to 1st after buffer output to provide overlap) vPages: CARDINAL; [DisplayLongAddress, DisplayWidthWords, ] _ ScreenParams[]; VStripeWidthWords _ (VStripeWidth+15)/16; VStripeWidthBytes _ VStripeWidthWords*2; VStripeWords _ VStripeWidthWords*(VStripeHeight+1); vPages _ (VStripeWords+255)/256; VStripeLongAddress _ LongDataSegmentAddress[NewDataSegment[DefaultXMBase,vPages]]; END; MakeLongPointer: PROCEDURE[low,high: UNSPECIFIED] RETURNS[LONG POINTER] = MACHINE CODE BEGIN --nothing to do-- END; BreakLongPointer: PROCEDURE[lptr: LONG POINTER] RETURNS[low,high: UNSPECIFIED] = MACHINE CODE BEGIN --nothing to do-- END; VersatecOutStripe: PUBLIC PROCEDURE = BEGIN --write text onto buffer FOR t:Text _ TextList,t.next UNTIL t=NIL DO PutText[t]; ENDLOOP; FreeTextBuffer[TextList]; TextList _ NIL; --***copy part to screen for testing versatecAddress: LONG POINTER _ VStripeLongAddress; displayAddress: LONG POINTER _ DisplayLongAddress; offset: CARDINAL _ MAX[0,DisplayOffset]; offset _ MIN[VStripeWidthWords-DisplayWidthWords,offset]; THROUGH [1..VStripeHeight] DO LongCOPY[versatecAddress+offset,DisplayWidthWords,displayAddress]; WriteVersatecLine[versatecAddress, VStripeWidthBytes]; versatecAddress _ versatecAddress + VStripeWidthWords; displayAddress _ displayAddress + DisplayWidthWords; ENDLOOP; END; VersatecClearStripe: PUBLIC PROCEDURE[overlap: BOOLEAN] = --If overlap then copy line number VStripeHeight to line number 0 and -- clear lines 1..VStripeHeight inclusive, otherwise -- clear lines 0..VStripeHeight inclusive BEGIN first: CARDINAL; IF overlap THEN BEGIN --copy line number VStripeHeight to line number 0 LongCOPY[VStripeLongAddress + VStripeWords - VStripeWidthWords, VStripeWidthWords, VStripeLongAddress]; first _ VStripeWidthWords; END ELSE first _ 0; --clear lines first..VStripeHeight inclusive LongStore[0,VStripeLongAddress + first]; --zero in 1st word LongCOPY[VStripeLongAddress + first, VStripeWords - first - 1, VStripeLongAddress + first + 1]; --copy it to all others FreeTextBuffer[TextList]; END; LongStore: PROCEDURE[v: UNSPECIFIED, address: LONG POINTER] = MACHINE CODE BEGIN zWBL,0; END; LoadStipple: PUBLIC PROCEDURE[layer:CARDINAL, v0,v1,v2,v3: CARDINAL] = BEGIN Stipple[layer] _ [v0,v1,v2,v3]; END; AllocateVerticalEdge: PUBLIC PROCEDURE RETURNS[Edge] = BEGIN RETURN[AllocateHeapNode[SIZE[vertical EdgeRecord]]]; END; AllocateObliqueEdge: PUBLIC PROCEDURE RETURNS[Edge] = BEGIN RETURN[AllocateHeapNode[SIZE[oblique EdgeRecord]]]; END; FreeEdge: PUBLIC PROCEDURE[edge: Edge] = BEGIN FreeHeapNode[edge]; END; -- EdgeLessThan: PUBLIC PROCEDURE[e1,e2: Edge, y: REAL] RETURNS[BOOLEAN] = BEGIN --orders up/down within slope within x x1: REAL _ XatY[e1,y]; x2: REAL _ XatY[e2,y]; RETURN[x1 --i.e. oblique SELECT TRUE FROM y=e.ystart => e.xstart, y=e.yend => e.xend, ENDCASE => e.xstart + (y-e.ystart)*e.slope, --must compute from consistent end! ENDCASE => edge.xstart --i.e. vertical ]; END; Slope: PROCEDURE[edge: Edge] RETURNS[slope: REAL] = INLINE BEGIN RETURN[WITH e:edge SELECT IF edge.vert THEN vertical ELSE oblique FROM oblique => e.slope, ENDCASE => 0 --i.e.vertical ]; END; black: ARRAY [0..4) OF CARDINAL _ [177777B,177777B,177777B,177777B]; InitVersatecOut: PUBLIC PROCEDURE[fileName: STRING, height: CARDINAL] = BEGIN IF VStripeLongAddress=NIL THEN VersatecAllocateStripe[]; VersatecClearStripe[FALSE]; --clear overlap line VStripeBottom _ 0; VStripeTop _ VStripeHeight; StartVersatecPlot[fileName, VStripeWidth, height]; FreeTextBuffer[TextList]; END; FinishVersatecOut: PUBLIC PROCEDURE[y: REAL] = BEGIN UNTIL VStripeBottom>y+1 DO --1+ is kludge to make sure it all gets out VersatecNextStripe[]; ENDLOOP; VersatecOutStripe[]; EndVersatecPlot[]; END; HorLine: PUBLIC PROCEDURE[xleft,xright,y: REAL] = BEGIN t: TrapezoidBlock; IF xleft=xright THEN RETURN; t _ [ ystart: y - VStripeBottom, yend: y - VStripeBottom, xsleft: xleft, xsright: xright, xeleft: xleft, xeright: xright, function: paint, xbase: VStripeLongAddress, xwords: VStripeWidthWords, texture: @black ]; TrapezoidBlt[@t]; END; DrawTrap: PUBLIC PROCEDURE[left: Edge, ystart: REAL, right: Edge, yend: REAL, layer: CARDINAL] = BEGIN --draw left and right edges --left edge t: TrapezoidBlock _ [ ystart: ystart - VStripeBottom, yend: yend - VStripeBottom, xsleft: XatY[left,ystart], xsright: , xeleft: XatY[left,yend], xeright: , function: paint, xbase: VStripeLongAddress, xwords: VStripeWidthWords, texture: @black ]; t.xsright _ t.xsleft; t.xeright _ t.xeleft; TrapezoidBlt[@t]; --stipple t.xsright _ XatY[right,ystart]; t.xeright _ XatY[right,yend]; t.texture _ @Stipple[layer]; TrapezoidBlt[@t]; --right edge t.xsleft _ t.xsright; t.xeleft _ t.xeright; t.texture _ @black; TrapezoidBlt[@t]; END; Text: TYPE = POINTER TO TextRecord; TextRecord: TYPE = RECORD [ next: Text, x: CARDINAL, y: CARDINAL, nChars: CARDINAL, text: PACKED ARRAY [0..0) OF CHARACTER ]; PutText: PROCEDURE[t: Text] = BEGIN !!! --use GSys code as model --questions: -- what to do about clipping? - presently CIFOutput doesn't know about bounding boxes around strings - will need to make it use appropriate bounding box possibly via a new call to the current Output device. -- how to handle text that falls below baseline - bias it up so that it is always strictly on or above the baseline. -- need to replace text allocation procedures to use high memory END; AllocateText: PROCEDURE[next: Text, x,y: REAL, s: STRING] = BEGIN t: Text _ AllocateHeapNode[SIZE[TextRecord] + (s.length+1)/2]; t^ _ [ next: next, x: FixC[x], y: FixC[y - VStripeBottom], nChars: s.length, text ]; FOR i:CARDINAL IN [0..s.length) DO t.text[i] _ s[i]; ENDLOOP; END; FreeTextBuffer: PROCEDURE[first: Text] = BEGIN next: Text; FOR t:Text _ first, next UNTIL t=NIL DO next _ t.next; FreeHeapNode[t]; ENDLOOP; END; VStripeLongAddress: LONG POINTER _ NIL; --full address of versatec bitmap buffer DisplayLongAddress: LONG POINTER; --full address of display bitmap buffer DisplayWidthWords: CARDINAL; DisplayOffset: INTEGER _ 0; --in words - controls what part of VStripe is copied to screen. Set in debugger VStripeBottom,VStripeTop: REAL; --limits to be mapped onto current stripe VStripeWidth: CARDINAL _ 3472; --***should be wired to required buffer width VStripeHeight: CARDINAL _ 128; --this MUST be a multiple of 4 for stipple phase to work --***should be wired to required buffer height VStripeWidthWords: CARDINAL; --required buffer width in words VStripeWidthBytes: CARDINAL; --required buffer width in bytes VStripeWords: CARDINAL; --required buffer size in words TextList: Text _ NIL; Stipple: ARRAY [0..MaxLENGTHLayerArray) OF ARRAY [0..4) OF CARDINAL _ ALL[[177777B,177777B,177777B,177777B]]; --undef --Set up default stipples Stipple[0] _ [ 0, 0,010421B, 0]; --implant Stipple[1] _ [042104B,010421B,042104B,010421B]; --diffusion Stipple[2] _ [010421B,104210B,042104B,021042B]; --poly Stipple[3] _ [167356B,135673B,114631B,073567B]; --contact Stipple[4] _ [ 0, 0,021042B,104210B]; --metal Stipple[5] _ [ 0,021042B,042104B,104210B]; --buried Stipple[6] _ [ 0,021042B,052525B,021042B]; --glass Stipple[7] _ [177777B,177777B,177777B,177777B]; --undef END. (635)\111b9B769b16B318b18B294b18B99b16B787b15B99b22B496b15B105b16B112b17B695b19B733b9B87b11B107b20B103b19B102b8B72b12B249b4B374b5B270b15B307b17B192b7B361b8B867b7B471b12B289b14B