DIRECTORY Atom, Basics, BasicTime, CDBasics, CDMEBES, CDMEBESScan, CStitching, FS, IO, Rope; CDMEBESDropInImpl: CEDAR PROGRAM IMPORTS Atom, Basics, BasicTime, CDBasics, CDMEBES, CDMEBESScan, CStitching, FS, IO, Rope EXPORTS CDMEBES = BEGIN OPEN CDMEBES; InsertDropIn: PUBLIC PROC [ ms: MaskState, rects: Tesselation, di: DropIn, data: REF ] RETURNS [ newData: REF ] = BEGIN IF data = NIL THEN data _IO.PutFR[di.fileNamePattern, IO.rope[NARROW[ms.toolingSpec.GetPropFromList[ms.curMask.maskId], ToolingMaskSpec].maskNo]]; IF data = NIL THEN RETURN[NIL]; WITH data SELECT FROM fileName: Rope.ROPE => { tries: INT _ 0; fileLen: INT _ -2; did: REF ANY _ $NoInsert; [bytes: fileLen] _ FS.FileInfo[fileName ! FS.Error => IF error.code = $unknownFile THEN CONTINUE ELSE REJECT ]; SELECT fileLen FROM >= 2048 => did _ CDMEBESScan.ScanMebesPatternFile[fileName ! FS.Error => IF ((error.code = $connectionTimedOut) AND (tries < 5)) THEN {tries _ tries+1; RETRY} ELSE REJECT]; <= 0 => ERROR; ENDCASE => { s: IO.STREAM _ FS.StreamOpen[fileName]; token: Rope.ROPE _ IO.GetCedarTokenRope[s].token; s.Close[]; IF Rope.Equal[token, "EmptyMebesPatternFile"] THEN did _ $NoInsert ELSE ERROR; }; newData _ InsertDropIn[ms, rects, di, did]; }; atom: ATOM => newData _ atom; -- don't actually DO anything did: CDMEBESScan.DropInDescriptor => { scaleNtoM: Rational = [num: 1, denom: ms.mebesPixelPitch]; -- from Nm to MEBESPixels scaleMtoT: Rational = [num: ms.mebesPixelPitch*ms.tadsPerNm, denom: 1]; -- from MEBESPixels to Tads mebesStripeClip: MEBESRect = ScaleRect[ms.tadStripeClip, [num: 1, denom: ms.mebesPixelPitch*ms.tadsPerNm]]; dropInClip: MEBESRect; -- the current output stripe, translated to drop-in space and clipped to drop-in boundary dropInOffsetToReticleClip: MEBESPosition; -- position of drop-in file's [0,0] in reticleClip mebesStripeClipFromDropIn: MEBESRect; IF BasicTime.Period[did.lastChecked, BasicTime.Now[]] > 5*60 THEN { WHILE FS.FileInfo[did.fileName].created # did.created DO did _ CDMEBESScan.ScanMebesPatternFile[did.fileName]; -- needs updating ENDLOOP; did.lastChecked _ BasicTime.Now[]; }; IF ms.mebesPixelPitch -- nm -- *1.0E-9 > did.pixelSize -- Meters -- +5.0E-10 OR ms.mebesPixelPitch*1.0E-9 < did.pixelSize-5.0E-10 THEN ERROR; -- pixel sizes incompatible dropInOffsetToReticleClip _ ScalePoint[CDBasics.AddPoints[CDBasics.AddPoints[di.pos, ms.dieOffset], CDBasics.BaseOfRect[ms.nmReticleClip]], scaleNtoM]; mebesStripeClipFromDropIn _ CDBasics.MoveRect[mebesStripeClip, CDBasics.NegOffset[dropInOffsetToReticleClip]]; dropInClip _ CDBasics.Intersection[did.clip, mebesStripeClipFromDropIn]; IF CDBasics.NonEmpty[dropInClip] THEN { s: IO.STREAM; IF di.clearBackground THEN rects.ChangeRect[ ScaleRect[CDBasics.MoveRect[dropInClip, dropInOffsetToReticleClip], scaleMtoT], NIL]; FOR segment: CARDINAL _ dropInClip.x1/CDMEBES.maskWidth+segmentOrigin, segment+1 WHILE (segment-segmentOrigin)*CDMEBES.maskWidth < dropInClip.x2 DO FOR stripe: CARDINAL _ dropInClip.y1/did.stripeHeight+stripeOrigin, stripe+1 WHILE (stripe-stripeOrigin)*did.stripeHeight <= dropInClip.y2 DO offset: MEBESPosition = [x: (segment-segmentOrigin)*CDMEBES.maskWidth, y: (stripe-stripeOrigin)*did.stripeHeight]; IF did[segment][stripe] = [0, 0] THEN LOOP; IF s = NIL THEN s _ FS.StreamOpen[fileName: did.fileName, remoteCheck: FALSE]; s.SetIndex[CDMEBES.mebesBlockSize*(did[segment][stripe].firstBlock-1)+2*(did[segment][stripe].firstWordWithinBlock-1)]; ProcessStripe[source: s, dest: ms.s, stripeClip: CDBasics.Intersection[ [x1: 0, y1: 0, x2: CDMEBES.maskWidth, y2: did.stripeHeight], CDBasics.MoveRect[r: dropInClip, offset: CDBasics.NegOffset[offset]] ], destTrans: CDBasics.AddPoints[offset, CDBasics.SubPoints[dropInOffsetToReticleClip, CDBasics.BaseOfRect[mebesStripeClip]]] ]; ENDLOOP; -- stripe ENDLOOP; -- segment s.Close[]; s _ NIL; }; newData _ did; }; ENDCASE => ERROR; END; rectCmd: REF DrawRectangle _ NEW[DrawRectangle]; trapCmd: REF DrawTrapezoid _ NEW[DrawTrapezoid]; ProcessStripe: PROC [ source, dest: IO.STREAM, stripeClip: MEBESRect, destTrans: MEBESPosition ] = BEGIN MEBES16Pixels: TYPE = MEBESPixels; -- sixteenths of a MEBESPixel InsertRectangle: PROC [ x, y, width, height: MEBESPixels ] = { destRect: MEBESRect = CDBasics.Intersection[stripeClip, [x1: x, y1: y, x2: x+width, y2: y+height]]; IF CDBasics.NonEmpty[destRect] THEN { rectCmd.h _ destRect.y2-destRect.y1; rectCmd.w _ destRect.x2-destRect.x1; rectCmd.x _ destRect.x1+destTrans.x; rectCmd.y _ destRect.y1+destTrans.y; SendCommand[dest, rectCmd]; }; }; InsertTrapezoid: PROC [ x, width: MEBES16Pixels, y, height: MEBESPixels, leftEdge, rightEdge: MEBES16Pixels ] = { x1b, x1t, x2b, x2t: MEBES16Pixels; y1, y2: MEBESPixels; sx1: MEBES16Pixels = 16*stripeClip.x1; sx2: MEBES16Pixels = 16*stripeClip.x2; Low: PROC [ i: INT ] RETURNS [ n: CARDINAL ] = {RETURN[Basics.LowHalf[LOOPHOLE[i]]]}; High: PROC [ i: INT ] RETURNS [ n: [0..100B) ] = BEGIN hi: INTEGER; TRUSTED {hi _ LOOPHOLE[Basics.HighHalf[i]]}; IF ~ (hi IN [-40B..40B) ) THEN ERROR; RETURN[IF hi>=0 THEN hi ELSE hi+100B]; END; Interpolate: PROC [ b1, b2, a1, ax, a2: INT ] RETURNS [ bx: INT ] = { bx _ b1+((ax-a1)*(b2-b1))/(a2-a1); }; BasicTrapezoid: PROC [ym1, ym2: MEBESPixels] = { DoYSplit: PROC [ xb, xm, xt: MEBES16Pixels ] = { ySplit: MEBESPixels = MAX[ym1+1, MIN[ym2-1, Interpolate[y1, y2, xb, xm, xt]]]; BasicTrapezoid[ym1, ySplit]; BasicTrapezoid[ySplit, ym2]; }; SELECT TRUE FROM ym2 <= ym1 => RETURN; -- empty clipping region [ym1..ym2) ym1 = ym2-1 => { -- a single row of pixels, approximate with rectangle xm1: MEBESPixels _ Interpolate[x1b, x1t, y1, ym1, y2]/16; xm2: MEBESPixels _ Interpolate[x2b, x2t, y1, ym1, y2]/16; IF xm1 < xm2 THEN InsertRectangle[xm1, ym1, xm2-xm1, 1]; }; ENDCASE => { xm1b: MEBES16Pixels _ Interpolate[x1b, x1t, y1, ym1, y2]; xm2b: MEBES16Pixels _ Interpolate[x2b, x2t, y1, ym1, y2]; xm1t: MEBES16Pixels _ Interpolate[x1b, x1t, y1, ym2, y2]; xm2t: MEBES16Pixels _ Interpolate[x2b, x2t, y1, ym2, y2]; IF xm2b < xm1b OR xm2t < xm1t THEN ERROR; SELECT TRUE FROM xm1b < sx1+8 AND xm1t < sx1+8 => xm1b _ xm1t _ sx1; xm1b < sx1-8 OR xm1t < sx1-8 => { DoYSplit[x1b, sx1, x1t]; RETURN; }; xm1b < sx2+8 AND xm1t < sx2+8 => NULL; xm1b < sx2-8 OR xm1t < sx2-8 => { DoYSplit[x1b, sx2, x1t]; RETURN; }; ENDCASE => RETURN; SELECT TRUE FROM sx2-8 <= xm2b AND sx2-8 <= xm2t => { xm2b _ MIN[MAX[xm1b+1, xm2b], sx2]; xm2t _ MIN[xm2t, sx2]; }; sx2+8 <= xm2b OR sx2+8 <= xm2t => { DoYSplit[x2b, sx2, x2t]; RETURN; }; sx1-8 <= xm2b AND sx1-8 <= xm2t => { xm2b _ MAX[sx1, xm1b+1, xm2b]; xm2t _ MAX[sx1, xm1b+1, xm2t]; }; sx1+8 <= xm2b OR sx1+8 <= xm2t => { DoYSplit[x2b, sx1, x2t]; RETURN; }; ENDCASE => RETURN; IF xm2b <= xm1b -- width <= 0 OR xm2t < xm1t -- width < (dx1-dx2) OR xm1b < sx1 OR xm1t < sx1 OR sx2 < xm2b OR sx2 < xm2t THEN ERROR; -- just checking... trapCmd^ _ [ h: ym2-ym1, wLow: Low[xm2b-xm1b], x1Low: Low[xm1b+16*destTrans.x], deltaX2High: High[xm2t-xm2b], y1: ym1+destTrans.y, deltaX1Low: Low[xm1t-xm1b], deltaX2Low: Low[xm2t-xm2b], deltaX1High: High[xm1t-xm1b], x1High: High[xm1b+16*destTrans.x], wHigh: High[xm2b-xm1b] ]; SendCommand[dest, trapCmd]; }; }; -- end of BasicTrapezoid IF (width<0 OR height<0 OR width+rightEdge { -- Manhattan Rectangle x, width, y, height: INT; height _ t1/100B + 1; width _ CDMEBESScan.ReadMebesWord[source]; x _ CDMEBESScan.ReadMebesWord[source]; y _ CDMEBESScan.ReadMebesWord[source]; InsertRectangle[x, y, width, height]; }; 17 => { -- Parallelogram tmp1, x, width, leftEdge, y, height: INT; height _ t1/100B + 1; width _ CDMEBESScan.ReadMebesWord[source]; x _ CDMEBESScan.ReadMebesWord[source]; y _ CDMEBESScan.ReadMebesWord[source]; leftEdge _ CDMEBESScan.ReadMebesWord[source]; tmp1 _ CDMEBESScan.ReadMebesWord[source]; width _ width + (tmp1 MOD 40B)*200000B; tmp1 _ tmp1/40B; x _ x + (tmp1 MOD 40B)*200000B; tmp1 _ tmp1/40B; leftEdge _ leftEdge + (tmp1 MOD 100B)*200000B - (IF tmp1/40B # 0 THEN 20000000B ELSE 0); InsertTrapezoid[x, width, y, height, leftEdge, leftEdge]; }; 18 => { -- Trapezoid 1 tmp1, x, width, leftEdge, y, height: INT; height _ t1/100B + 1; width _ CDMEBESScan.ReadMebesWord[source]; x _ CDMEBESScan.ReadMebesWord[source]; y _ CDMEBESScan.ReadMebesWord[source]; leftEdge _ CDMEBESScan.ReadMebesWord[source]; tmp1 _ CDMEBESScan.ReadMebesWord[source]; width _ width + (tmp1 MOD 40B)*200000B; tmp1 _ tmp1/40B; x _ x + (tmp1 MOD 40B)*200000B; tmp1 _ tmp1/40B; leftEdge _ leftEdge + (tmp1 MOD 100B)*200000B - (IF tmp1/40B # 0 THEN 20000000B ELSE 0); InsertTrapezoid[x, width, y, height, leftEdge, 0]; }; 19 => { -- Trapezoid 2 tmp1, x, width, rightEdge, y, height: INT; height _ t1/100B + 1; width _ CDMEBESScan.ReadMebesWord[source]; x _ CDMEBESScan.ReadMebesWord[source]; y _ CDMEBESScan.ReadMebesWord[source]; rightEdge _ CDMEBESScan.ReadMebesWord[source]; tmp1 _ CDMEBESScan.ReadMebesWord[source]; width _ width + (tmp1 MOD 40B)*200000B; tmp1 _ tmp1/40B; x _ x + (tmp1 MOD 40B)*200000B; tmp1 _ tmp1/40B; rightEdge _ rightEdge + (tmp1 MOD 100B)*200000B - (IF tmp1/40B # 0 THEN 20000000B ELSE 0); InsertTrapezoid[x, width, y, height, 0, rightEdge]; }; 20 => { -- Trapezoid 3 tmp1, x, width, leftEdge, rightEdge, y, height: INT; height _ t1/100B + 1; width _ CDMEBESScan.ReadMebesWord[source]; x _ CDMEBESScan.ReadMebesWord[source]; y _ CDMEBESScan.ReadMebesWord[source]; leftEdge _ CDMEBESScan.ReadMebesWord[source]; rightEdge _ CDMEBESScan.ReadMebesWord[source]; tmp1 _ CDMEBESScan.ReadMebesWord[source]; width _ width + (tmp1 MOD 40B)*200000B; tmp1 _ tmp1/40B; x _ x + (tmp1 MOD 40B)*200000B; tmp1 _ tmp1/40B; leftEdge _ leftEdge + (tmp1 MOD 100B)*200000B - (IF tmp1/40B # 0 THEN 20000000B ELSE 0); tmp1 _ y/2000B; y _ y MOD 2000B; rightEdge _ rightEdge + (tmp1 MOD 100B)*200000B - (IF tmp1/40B # 0 THEN 20000000B ELSE 0); InsertTrapezoid[x, width, y, height, leftEdge, rightEdge]; }; 10, 7 => NULL; -- start of segment or small stripe number 2 => [] _ CDMEBESScan.ReadMebesWord[source]; -- start of large stripe number 8 => RETURN; -- end of stripe 4 => RETURN; -- end of drawing 9 => { -- end of buffer i: INT = source.GetIndex[]+CDMEBES.mebesBlockSize-1; source.SetIndex[i - (i MOD CDMEBES.mebesBlockSize)]; }; ENDCASE => ERROR CDMEBESScan.NotMEBESFormat; ENDLOOP; END; warnIfUnimplGeom: BOOL _ TRUE; UnimplementedGeom: PROC = {IF warnIfUnimplGeom THEN SIGNAL UnImplementedGeometry}; UnImplementedGeometry: SIGNAL = CODE; END. -- of CDMEBESDropInImpl CDMEBESDropInImpl.mesa Copyright c 1985 by Xerox Corporation. All rights reserved. written by E. McCreight, November 2, 1983 6:03 pm McCreight, May 1, 1987 6:38:41 pm PDT Last Edited by: McCreight November 23, 1987 2:54:46 pm PST This module drops a MEBES file into another MEBES file, one stripe at a time. This procedure incorporates the mask information referenced in data, translated by di.pos and then clipped to ms.mebesStripeClip, into the MEBES stream in ms.s. In this section, intervals are always closed on the left and open on the right, thus: [z1..z2). According to a conversation with Perkin-Elmer, a pixel is turned on if and only if its integer is included in the 1/16-resolution range. For example, [3.5..5.25) turns on pixels 4 and 5. A conversation with Keith Wires of MicroFab (415-965-1750) on 20 November 86 leads me (EMM) to the following statement of the Perkin-Elmer core pixel fill algorithm. A pixel (x, y) is turned on if and only if its center point (x+0.4999.., y+0.4999..) lies within the plotted figure. If that's true, the trapezoid scan conversion algorithm used by Perkin-Elmer can be represented like this: FOR dy: INT _ 1, dy+2 WHILE dy<2*height DO -- halves x1: INT = x+((dy*leftEdge)/(2*height))); -- sixteenths .. the left boundary at y-center of pixel row x2: INT = x+width+((dy*rightEdge)/(2*height))); -- sixteenths .. the right boundary at y-center of pixel row x1Frac: INT = x1 MOD 16; -- sixteenths FOR px: INT _ x1-x1Frac+(IF x1Frac<8 THEN 0 ELSE 16), px+16 WHILE px < x2 DO FillPixelRectangle[x1: (px-8)/16, y1: y+(dy-1)/2, x2: (px+8)/16, y: y+(dy+1)/2]; ENDLOOP; ENDLOOP; Examine the left boundary of the trapezoid within the y-range. .. both top and bottom of the trapezoid include the pixel stripeClip.x1 Find the value of y where the [x1b, y1] - [x1t, y2] edge crosses the line x=stripeClip.x1, and output two trapezoids. .. at this point, we know the [x1b, y1] - [x1t, y2] lies to the right of x=stripeClip.x1. Now check its relation to x=stripeClip.x2. .. no pixel off beyond stripeClip.x2 Find the value of y where the [x1b, y1] - [x1t, y2] edge crosses the line x=stripeClip.x2+0.5, and output two trapezoids. .. clips out to the right Examine the right boundary of the trapezoid within the y-range. .. both top and bottom of the trapezoid include the rightmost pixel Find the value of y where the [x2b, y1] - [x2t, y2] edge crosses the line x=stripeClip.x2, and output two trapezoids. .. at this point, we know the [x2b, y1] - [x2t, y2] lies to the left of x=stripeClip.x2. Now check its relation to x=stripeClip.x1. .. no pixel off beyond stripeClip.x1 Find the value of y where the [x2b, y1] - [x2t, y2] edge crosses the line x=stripeClip.x1, and output two trapezoids. .. clips out to the left At this point we have a trapezoid clipped x entirely within [sx1..sx2) for y in [ym1..ym2). We have a trapezoid in the source file whose corners are [x/16, y], [(x+leftEdge)/16, y+height], [(x+width+rightEdge)/16, y+height], [(x+width)/16, y] in clockwise order. trapezoid not in canonical form Module START code... Κ ”˜šœ™Icodešœ Οmœ1™˜>Jšœ/˜/—JšœH˜Hšžœžœ˜'Jšœžœžœ˜ šžœž˜šœ˜JšœO˜OJšžœ˜——š žœ žœžœ$žœžœž˜“šžœ žœ9žœ9ž˜Jšœ4žœ7˜rJšžœžœžœ˜+šžœžœž˜Jšœžœ1žœ˜>—Jšœ žœe˜wšœ$˜$šœ"˜"Jšœžœ"˜Jšœc˜cšžœžœ˜%Jšœ$˜$Jšœ$˜$Jšœ$˜$Jšœ$˜$Jšœ˜J˜—Jšœ˜J˜J˜—JšŸœžœ\˜q˜™‡J™š žœžœ žœ žœ  ™4šœžœ#  ™7J™-—Jšœžœ*  ™>J™0Jšœžœžœ  ™&š žœžœžœ žœžœ žœ ž™LJšœP™PJšžœ™—Jšžœ™J™——Jšœ"˜"Jšœ˜Jšœ&˜&Jšœ&˜&J˜š Ÿœžœžœžœžœ˜.Jšœžœžœ˜&J˜—šŸœžœžœžœ˜0Jšž˜Jšœžœ˜ Jšžœžœ˜,Jšžœžœžœžœ˜%Jšžœžœžœžœ ˜&Jšžœ˜J˜—š Ÿ œžœžœžœžœ˜EJšœ"˜"Jšœ˜J˜—šŸœžœ˜0J˜šŸœžœ"˜0Jšœžœžœ*˜NJšœ˜Jšœ˜Jšœ˜J˜—šžœžœž˜Jšœžœ #˜9šœ 5˜FJšœ9˜9Jšœ9˜9šžœ ž˜Jšœ&˜&—J˜—šžœ˜ Jšœ9˜9Jšœ9˜9Jšœ9˜9Jšœ9˜9J˜Jšžœ žœ žœžœ˜)J˜šžœžœž˜J™>šœ žœ˜ Jšœ˜Jš 0œ™G—šœ žœ˜!Jšœu™uJšœ˜Jšžœ˜Jšœ˜J˜—Jšœ…™…J˜šœ žœžœ˜&Jšœ$™$—šœ žœ˜!Jšœy™yJšœ˜Jšžœ˜Jšœ˜—šžœžœ˜Jšœ ™J™——šžœžœž˜J™?šœžœ˜$Jš 0œ™CJšœžœžœ˜#Jšœžœ ˜J˜—šœžœ˜#Jšœu™uJšœ˜Jšžœ˜Jšœ˜J˜—Jšœ„™„J˜šœžœ˜$Jšœ$™$Jšœžœ˜Jšœžœ˜Jšœ˜—šœžœ˜#Jšœu™uJšœ˜Jšžœ˜Jšœ˜—šžœžœ˜Jšœ™——J™Jšœ[™[J™šžœ  ˜Jšžœ  ˜#Jšžœ ˜ Jšžœ ˜ Jšžœ ˜ Jšžœ žœžœ ˜-—J˜šœ ˜ Jšœ ˜ J˜J˜ Jšœ˜Jšœ˜Jšœ˜Jšœ˜Jšœ˜Jšœ"˜"J˜J˜—Jšœ˜J˜——Jšœ ˜J˜—šœ8™8Jšœq™qJ™—š žœ žœ žœžœžœ˜@Jšœ™—Jšœ˜Jšœ˜Jšœ˜Jšœ˜Jšœ˜J˜Jšœžœžœ˜?Jšœ˜J˜—šž˜Jšœžœ%˜1šžœžœž˜šœ  ˜Jšœžœ˜J˜Jšœ*˜*Jšœ&˜&Jšœ&˜&J˜%J˜J˜—šœ ˜Jšœ%žœ˜)J˜Jšœ*˜*Jšœ&˜&Jšœ&˜&Jšœ-˜-Jšœ)˜)Jšœžœ˜'J˜Jšœžœ˜J˜˜ šœžœ˜$Jšœžœžœ žœ˜(——J˜9Jšœ˜—šœ ˜Jšœ%žœ˜)J˜Jšœ*˜*Jšœ&˜&Jšœ&˜&Jšœ-˜-Jšœ)˜)Jšœžœ˜'J˜Jšœžœ˜J˜˜ šœžœ˜$Jšœžœžœ žœ˜(——J˜2Jšœ˜—šœ ˜Jšœ&žœ˜*J˜Jšœ*˜*Jšœ&˜&Jšœ&˜&Jšœ.˜.Jšœ)˜)Jšœžœ˜'J˜Jšœžœ˜J˜˜ šœžœ˜%Jšœžœžœ žœ˜(——J˜3Jšœ˜—šœ  ˜Jšœ0žœ˜4J˜Jšœ*˜*Jšœ&˜&Jšœ&˜&Jšœ-˜-Jšœ.˜.Jšœ)˜)Jšœžœ˜'J˜Jšœžœ˜J˜˜ šœžœ˜$Jšœžœžœ žœ˜(——J˜Jšœžœ˜˜ šœžœ˜%Jšœžœžœ žœ˜(——J˜:J˜—Jšœ žœ *˜9Jšœ- ˜LJšœžœ ˜Jšœžœ ˜šœ ˜Jšœžœžœ˜4Jšœžœžœ˜4J˜—Jšžœžœ˜,—Jšžœ˜—Jšžœ˜J˜—Jšœžœžœ˜J˜šŸœžœ˜Jšœžœžœžœ˜8J˜—JšŸœžœžœ˜%J˜Jšœ™J™Jšžœ ˜—J˜J˜—…—)ΘCt