DIRECTORY Atom, Basics, CD, CDBasics, CDMEBES, CDVArrow, CDViewer, CStitching, D2Basic, IO, Rope, TerminalIO; CDMEBESUtilitiesImpl: CEDAR PROGRAM IMPORTS Atom, CDBasics, CDViewer, CDVArrow, CStitching, IO, Rope, TerminalIO EXPORTS CDMEBES = BEGIN OPEN CDMEBES; SendCommand: PUBLIC PROC [ s: IO.STREAM, comm: REF ] = BEGIN sizeInWords: NAT; WITH comm SELECT FROM c: REF DrawRectangle => sizeInWords _ SIZE[DrawRectangle]; c: REF DrawTrapezoid => sizeInWords _ SIZE[DrawTrapezoid]; c: REF BasicCommand => sizeInWords _ SIZE[BasicCommand]; c: REF Mode12StartStripe => sizeInWords _ SIZE[Mode12StartStripe]; c: REF Mode12StartDrawing => sizeInWords _ SIZE[Mode12StartDrawing]; c: REF ExtAddrModeStartDrawing => sizeInWords _ SIZE[ExtAddrModeStartDrawing]; c: REF SegDirectoryEntry => sizeInWords _ SIZE[SegDirectoryEntry]; c: REF ExtAddrModeStartStripe => sizeInWords _ SIZE[ExtAddrModeStartStripe]; c: REF StartSegment => sizeInWords _ SIZE[StartSegment]; c: REF Date => sizeInWords _ SIZE[Date]; c: REF PatternFileName => sizeInWords _ SIZE[PatternFileName]; c: REF CARDINAL => sizeInWords _ SIZE[CARDINAL]; ENDCASE => ERROR; TRUSTED {s.UnsafePutBlock[[base: LOOPHOLE[comm], startIndex: 0, count: Basics.bytesPerWord*sizeInWords]]}; END; EBESStreamStateRef: TYPE = REF EBESStreamState; EBESStreamState: TYPE = RECORD [ dest: IO.STREAM, destIndexMod: [0..mebesBlockSize), eor: BOOL, buf: REF TEXT]; ebesStreamProcs: REF IO.StreamProcs = IO.CreateStreamProcs[ variety: output, class: $EBESOutputStream, putChar: PutEBESChar, unsafePutBlock: PutEBESBlock, flush: FlushEBES, getIndex: GetIndexEBES, setIndex: SetIndexEBES, close: CloseEBES ]; EBESOpen: PUBLIC PROC [ dest: IO.STREAM, eor: BOOL _ TRUE ] RETURNS [ self: IO.STREAM ] = BEGIN state: EBESStreamStateRef = NEW[EBESStreamState _ [ dest: dest, destIndexMod: dest.GetIndex[] MOD mebesBlockSize, eor: eor, buf: NEW[TEXT[mebesBlockSize]] ]]; state.buf.length _ 0; self _ IO.CreateStream[ streamProcs: ebesStreamProcs, streamData: state ]; END; PutEBESChar: PROC [ self: IO.STREAM, char: CHAR ] = TRUSTED BEGIN state: EBESStreamStateRef = NARROW[self.streamData]; FlushEBESIfNecessary[state, 1]; state.buf[state.buf.length] _ char; state.buf.length _ state.buf.length+1; END; PutEBESBlock: PROC [ self: IO.STREAM, block: IO.UnsafeBlock ] = TRUSTED BEGIN state: EBESStreamStateRef = NARROW[self.streamData]; FlushEBESIfNecessary[state, block.count]; FOR i: INT IN [0..block.count) DO CharArrayPtr: TYPE = LONG POINTER TO PACKED ARRAY [0..0) OF CHAR; state.buf[state.buf.length+i] _ LOOPHOLE[block.base, CharArrayPtr][block.startIndex+i]; ENDLOOP; state.buf.length _ state.buf.length+block.count; END; FlushEBESIfNecessary: PROC [state: EBESStreamStateRef, newBytes: NAT] = INLINE BEGIN IF mebesBlockSize0 OR state.destIndexMod>0 THEN BEGIN IF state.eor THEN BEGIN IF state.buf.length+2 <= mebesBlockSize-state.destIndexMod THEN TRUSTED BEGIN -- append an end-of-record command to the buffer endRec: PACKED ARRAY [0..2) OF CHAR = LOOPHOLE[endRecord]; state.buf[state.buf.length] _ endRec[0]; state.buf[state.buf.length+1] _ endRec[1]; state.buf.length _ state.buf.length+2; END ELSE ERROR; -- can't terminate buffer properly END; FOR i: INT IN [state.buf.length..mebesBlockSize-state.destIndexMod) DO state.buf[i] _ 000C; -- pad out with 0's ENDLOOP; state.buf.length _ mebesBlockSize-state.destIndexMod; state.dest.PutBlock[state.buf]; END; state.buf.length _ 0; state.destIndexMod _ 0; END; GetIndexEBES: PROC [ self: IO.STREAM ] RETURNS [ index: INT ] = BEGIN state: EBESStreamStateRef = NARROW[self.streamData]; index _ state.dest.GetIndex[]+state.buf.length; END; SetIndexEBES: PROC [ self: IO.STREAM, index: INT ] = BEGIN state: EBESStreamStateRef = NARROW[self.streamData]; IF state.buf.length>0 THEN state.dest.PutBlock[state.buf]; state.buf.length _ 0; state.dest.SetIndex[index]; state.destIndexMod _ state.dest.GetIndex[] MOD mebesBlockSize; END; CloseEBES: PROC [ self: IO.STREAM, abort: BOOL _ FALSE ] = BEGIN state: EBESStreamStateRef = NARROW[self.streamData]; self.Flush[]; state.dest.Close[]; END; UserWantsToDebug: SIGNAL = CODE; ComplainAt: PUBLIC PROC [ ms: MaskState, pos: TadPosition, explanation: ROPE _ NIL, choice: LIST OF ROPE _ NIL ] RETURNS [ chosen: NAT ] = BEGIN radius: Tad = 20*ms.nmPerLambda*ms.tadsPerNm; cdRect: CD.Rect = ScaleTadToCD[ms, [x1: pos.x-radius, y1: pos.y-radius, x2: pos.x+radius, y2: pos.y+radius]]; CDVArrow.ShowArrow[ms.design, CDBasics.Center[cdRect]]; TerminalIO.PutRope[IO.PutFR["\nMEBES generation problem: %g\n", IO.rope[explanation]]]; chosen _ 0; DO ENABLE UNWIND => CDVArrow.ShowArrow[ms.design, ms.viewerArrow]; selected: NAT; viewerList: CDViewer.ViewerList = CDViewer.ViewersOf[ms.design]; CDVArrow.ShowArrow[ms.design, CDBasics.Center[cdRect]]; IF viewerList # NIL THEN CDViewer.ShowAndScale[viewerList.first, cdRect]; SELECT (selected _ TerminalIO.RequestSelection[header: "Action..", choice: CONS["Abort", CONS["Debug", choice]]]) FROM 0 => {chosen _ 0; EXIT}; 1 => ERROR ABORTED; 2 => {SIGNAL UserWantsToDebug; LOOP}; ENDCASE => {chosen _ selected-2; EXIT}; ENDLOOP; CDVArrow.ShowArrow[ms.design, ms.viewerArrow]; END; NewTesselation: PUBLIC PROC [ initValue: REF _ NIL ] RETURNS [ tess: Tesselation ] = BEGIN tess _ CStitching.NewTesselation[]; tess.ChangeRect[CDBasics.universe, initValue]; END; DisposeTesselation: PUBLIC PROC [ tess: Tesselation ] RETURNS [ Tesselation ] = BEGIN CStitching.ResetTesselation[plane: tess]; RETURN[NIL]; END; RopeNeeded: PUBLIC SIGNAL [ ref: REF REF ] = CODE; ToRope: PUBLIC PROC [ ref: REF ] RETURNS [ rope: ROPE ] = BEGIN IF ref = NIL THEN rope _ NIL ELSE WITH ref SELECT FROM r: ROPE => rope _ r; rt: REF TEXT => rope _ Rope.FromRefText[rt]; a: ATOM => rope _ Atom.GetPName[a]; ri: REF INT => rope _ IO.PutFR[format: "%d", v1: IO.int[ri^]]; ENDCASE => BEGIN refRef: REF REF = NEW[REF _ ref]; SIGNAL RopeNeeded[refRef]; rope _ ToRope[refRef^ ! RopeNeeded => GOTO NoHelp]; EXITS NoHelp => ERROR; END; END; ScaleCDToTad: PUBLIC PROC [ ms: MaskState, cdr: CD.Rect ] RETURNS [ tr: TadRect ] = BEGIN tr _ CDBasics.ReInterpreteRect[ [x1: RatIntMul[ms.scale, cdr.x1], y1: RatIntMul[ms.scale, cdr.y1], x2: RatIntMul[ms.scale, cdr.x2], y2: RatIntMul[ms.scale, cdr.y2]]]; END; ScaleTadToCD: PUBLIC PROC [ ms: MaskState, tr: TadRect ] RETURNS [ cdr: CD.Rect ] = BEGIN cdr _ CDBasics.ReInterpreteRect[ [x1: RatIntDiv[ms.scale, tr.x1], y1: RatIntDiv[ms.scale, tr.y1], x2: RatIntDiv[ms.scale, tr.x2], y2: RatIntDiv[ms.scale, tr.y2]]]; END; Bloat: PUBLIC PROC [ r: TadRect, deltaDiameter: Tad ] RETURNS [ br: TadRect ] = BEGIN b: Tad = deltaDiameter/2; -- split in "half" for radius IF deltaDiameter<0 THEN ERROR; IF (deltaDiameter MOD 2) # 0 THEN ERROR TadTooLarge; br _ [x1: MAX[FIRST[D2Basic.Number]+b, r.x1]-b, y1: MAX[FIRST[D2Basic.Number]+b, r.y1]-b, x2: MIN[LAST[D2Basic.Number]-b, r.x2]+b, y2: MIN[LAST[D2Basic.Number]-b, r.y2]+b]; END; TadTooLarge: PUBLIC ERROR = CODE; ScaleRect: PUBLIC PROC [ r: D2Basic.Rect, factor: Rational ] RETURNS [ sr: D2Basic.Rect ] = BEGIN sr _ CDBasics.ReInterpreteRect[ [x1: RatIntMul[factor, r.x1], y1: RatIntMul[factor, r.y1], x2: RatIntMul[factor, r.x2], y2: RatIntMul[factor, r.y2]]]; END; ScalePoint: PUBLIC PROC [ p: D2Basic.Vector, factor: Rational ] RETURNS [ sp: D2Basic.Vector ] = {sp _ [x: RatIntMul[factor, p.x], y: RatIntMul[factor, p.y]]}; RatAdd: PUBLIC PROC [ r1, r2: Rational ] RETURNS [ Rational ] = {RETURN[ReduceRational[[num: r2.denom*r1.num+r1.denom*r2.num, denom: r1.denom*r2.denom]]]}; RatNeg: PUBLIC PROC [ r: Rational ] RETURNS [ Rational ] = {RETURN[[num: -r.num, denom: r.denom]]}; RatMul: PUBLIC PROC [ r1, r2: Rational ] RETURNS [ Rational ] = {RETURN[ReduceRational[[num: r1.num*r2.num, denom: r1.denom*r2.denom]]]}; RatInv: PUBLIC PROC [ r: Rational ] RETURNS [ Rational ] = {RETURN[ReduceRational[[num: r.denom, denom: r.num]]]}; RatIntMul: PROC [ mul: Rational, z: INT ] RETURNS [ INT ] = INLINE {RETURN[(mul.num*z)/mul.denom]}; RatIntDiv: PUBLIC PROC [ div: Rational, z: INT ] RETURNS [ INT ] = INLINE {RETURN[(div.denom*z)/div.num]}; ReduceRational: PUBLIC PROC [ r: Rational ] RETURNS [ Rational ] = BEGIN gcd: INT = IF r.num=0 THEN r.denom ELSE GCD[r.num, r.denom]; RETURN[[num: r.num/gcd, denom: r.denom/gcd]]; END; GCD: PUBLIC PROC [ m, n: INT ] RETURNS [ INT ] = BEGIN r: INT; SELECT m FROM <0 => m _ -m; ENDCASE => NULL; SELECT n FROM <0 => n _ -n; >0 => NULL; ENDCASE => RETURN[m]; r _ m MOD n; WHILE r>0 DO m _ n; n _ r; r _ m MOD n; ENDLOOP; RETURN[n]; END; Ceiling: PUBLIC PROC [ r: Rational ] RETURNS [ c: INT ] = BEGIN c _ r.num/r.denom; IF ((r.num>0) = (r.denom>0)) AND r.num MOD r.denom # 0 THEN c _ c+1; END; END. -- of CDMEBESUtilitiesImpl LCDMEBESUtilitiesImpl.mesa Copyright c 1985 by Xerox Corporation. All rights reserved. McCreight, December 11, 1986 1:32:24 pm PST EBES IO Stream Types and Procedures Auxiliary Procedures Be careful not to exceed the limits of a D2Basic.Number, even temporarily Basic Rational Arithmetic c = SGN[r.num]*SGN[r.denom]*FLOOR[ABS[r.num]/ABS[r.denom]] if r.denom#0 McCreight December 10, 1986 3:45:16 pm PST Denotching by a diameter that was an odd number of pixels moved the geometry by one pixel. Denotching consists of a positive Enlarge followed by a negative Enlarge. That called Bloat first on the geometry and then on its complement. The problem is that for odd pixel diameters, Bloat grew a smaller number of pixels on the bottom left than on the top right. Doing that first on the geometry and then on its complement had the effect of moving the geometry one pixel up and to the right. The fix is to have the units of measure in the Tesselations be Tad's, and to complain when Bloating by a non-even Tad diameter. changes to: CDMEBESUtilitiesImpl, CDMEBESGeomFnsImpl, FlushEBES Κ :˜Jšœ™Icodešœ Οmœ1™Jš œžœžœžœžœ˜0Jšžœžœ˜—JšžœžœA˜jJšžœ˜J˜J˜—šΠbkΟb‘’™#J˜Jšœžœžœ˜/šœžœžœ˜ Jšœžœžœ˜Jšœ"˜"Jšœžœ˜ Jšœžœžœ˜—J˜šœžœžœžœ˜;Jšœ˜Jšœ˜Jšœ˜Jšœ˜Jšœ˜Jšœ˜Jšœ˜Jšœ˜Jšœ˜—J˜J˜š œžœžœ žœžœžœžœžœ žœžœ˜YJšž˜šœžœ˜3Jšœ ˜ Jšœžœ˜1Jšœ ˜ Jšœžœžœ˜Jšœ˜—Jšœ˜šœžœ˜Jšœ˜Jšœ˜Jšœ˜—Jšžœ˜J˜—J˜š   œžœ žœžœžœ˜3Jšžœž˜ Jšœžœ˜4Jšœ˜Jšœ#˜#Jšœ&˜&Jšžœ˜J˜J˜—š   œžœ žœžœ žœ˜?Jšžœž˜ Jšœžœ˜4Jšœ)˜)šžœžœžœž˜!Jšœžœžœžœžœžœžœžœžœ˜AJšœ žœ/˜WJšžœ˜—Jšœ0˜0Jšžœ˜J˜J˜—š œžœ'žœž˜NJšž˜š žœ?žœ žœžœΟcœžœž˜ŒJšœ˜—Jšžœ˜J˜J˜—š   œžœ žœžœžœ˜MJ˜J˜—š  œžœ ˜1Jšž˜šžœžœž˜2Jšž˜šžœ ž˜Jšž˜šžœ9ž˜?Jšžœžœ£0˜>Jš œžœžœžœžœžœ ˜:Jšœ(˜(Jšœ*˜*Jšœ&˜&Jšž˜—Jšžœžœ£"˜.Jšžœ˜—šžœžœžœ7ž˜FJšœ£˜(Jšžœ˜—Jšœ5˜5Jšœ˜Jšžœ˜—Jšœ˜Jšœ˜Jšžœ˜J˜J˜—š   œžœ žœžœžœ žœ˜?Jšž˜Jšœžœ˜4Jšœ/˜/Jšžœ˜J˜J˜—š   œžœ žœžœ žœ˜4Jšž˜Jšœžœ˜4Jšžœžœ ˜:Jšœ˜Jšœ˜Jšœ+žœ˜>Jšžœ˜J˜J˜—š   œžœ žœžœ žœžœ˜:Jšž˜Jšœžœ˜4Jšœ ˜ Jšœ˜Jšžœ˜J˜—J˜—Jš’™J™˜Jš œžœžœ˜ J˜š  œžœžœ1žœžœ žœžœžœžœžœ žœ˜ŠJšž˜Jšœ-˜-Jšœžœc˜mJšœ7˜7Jšœžœ+žœ˜WJšœ ˜ šžœžœžœ2˜BJšœ žœ˜Jšœ@˜@Jšœ7˜7Jšžœžœžœ1˜IšžœEžœ žœž˜vJšœžœ˜Jšœžœžœ˜Jšœžœžœ˜%Jšžœžœ˜'—Jšžœ˜—Jšœ.˜.Jšžœ˜J˜—š  œžœžœžœžœžœ˜TJšž˜Jšœ#˜#Jšœ.˜.Jšžœ˜J˜—š œžœžœžœ˜OJšž˜Jšœ)˜)Jšžœžœ˜ Jšžœ˜J˜—J˜Jš   œžœžœžœžœžœ˜2J˜š  œžœžœžœžœ žœ˜9Jšž˜Jšžœžœžœž˜šžœžœžœž˜Jšœžœ ˜Jšœžœžœ ˜,Jšœžœ˜#Jš œžœžœ žœžœ ˜>šžœ˜ Jšž˜Jš œžœžœžœžœ˜!Jšžœ˜Jšœ&žœ ˜3šž˜Jšœ žœ˜—Jšžœ˜——Jšžœ˜J˜J˜—š   œžœžœžœžœ˜SJšž˜šœ˜Jšœ†˜†—Jšžœ˜J˜J˜—š   œžœžœ žœžœ ˜SJšž˜šœ ˜ Jšœ‚˜‚—Jšžœ˜J˜J˜—š œžœžœ$žœ˜PJšž˜Jšœ£˜8Jšžœžœžœ˜šžœžœžœžœ ˜4J˜—JšœI™IJšœ žœžœ!žœžœ!žœžœ!žœžœ˜¬Jšžœ˜J˜—Jš  œžœžœžœ˜!J˜J˜š  œžœžœ'žœ˜\Jšž˜šœ˜Jšœv˜v—Jšžœ˜J˜J˜—š  œžœžœ)žœ˜aJšœ>˜>J˜J˜J˜—JšΠln™J˜š œžœžœžœ˜?JšœžœT˜[J˜—š ž œžœ˜:Jšœžœ!˜(J˜—š œž œžœ˜?JšœžœB˜IJ˜—š ž œžœ˜:Jšœžœ0˜7—J˜š   œžœžœžœžœ˜;Jšžœžœ˜'J˜—š   œž œžœžœžœ˜BJšžœžœ˜'J˜—š œžœžœžœ˜BJšž˜Jš œžœžœ žœ žœžœ˜