<> <> <> <> <> <> DIRECTORY Atom, Basics, BasicTime, CDBasics, CDMEBES, CDMEBESScan, CStitching, FS, IO, Process, Rope; CDMEBESDropInImpl: CEDAR PROGRAM IMPORTS Atom, Basics, BasicTime, CDBasics, CDMEBES, CDMEBESScan, CStitching, FS, IO, Process, 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; { ENABLE FS.Error => SELECT error.code FROM $connectionTimedOut, $connectionRejected => IF tries < 10 THEN { tries _ tries+1; Process.PauseMsec[10000]; RETRY; } ELSE REJECT; ENDCASE => REJECT; fileLen: INT _ -2; did: REF ANY; [bytes: fileLen] _ FS.FileInfo[fileName]; SELECT fileLen FROM >= 2048 => did _ CDMEBESScan.ScanMebesPatternFile[fileName]; <= 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 ] = { <> <<>> <> <> <<.. the left boundary at y-center of pixel row>> <> << .. the right boundary at y-center of pixel row>> <> <> <> <> <> <<>> 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; <<.. both top and bottom of the trapezoid include the pixel stripeClip.x1>> xm1b < sx1-8 OR xm1t < sx1-8 => { <> DoYSplit[x1b, sx1, x1t]; RETURN; }; <<.. 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.>> xm1b < sx2+8 AND xm1t < sx2+8 => NULL; <<.. no pixel off beyond stripeClip.x2>> xm1b < sx2-8 OR xm1t < sx2-8 => { <> DoYSplit[x1b, sx2, x1t]; RETURN; }; ENDCASE => RETURN; <<.. clips out to the right>> <<>> SELECT TRUE FROM <> sx2-8 <= xm2b AND sx2-8 <= xm2t => { <<.. both top and bottom of the trapezoid include the rightmost pixel>> xm2b _ MIN[MAX[xm1b+1, xm2b], sx2]; xm2t _ MIN[xm2t, sx2]; }; sx2+8 <= xm2b OR sx2+8 <= xm2t => { <> DoYSplit[x2b, sx2, x2t]; RETURN; }; <<.. 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.>> sx1-8 <= xm2b AND sx1-8 <= xm2t => { <<.. no pixel off beyond stripeClip.x1>> 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; <<.. clips out to the left>> <<>> <> <<>> 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 <> <<[x/16, y], [(x+leftEdge)/16, y+height], [(x+width+rightEdge)/16, y+height], [(x+width)/16, y] in clockwise order.>> <<>> IF (width<0 OR height<0 OR width+rightEdge> x1b _ x; x1t _ x+leftEdge; x2b _ x+width; x2t _ x+width+rightEdge; y1 _ y; y2 _ y+height; BasicTrapezoid[MAX[y1, stripeClip.y1], MIN[y2, stripeClip.y2]]; }; DO t1: CARDINAL _ CDMEBESScan.ReadMebesWord[source]; SELECT t1 MOD 100B FROM 16 => { -- 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