DIRECTORY Commander USING [CommandProc, Register, Handle], Convert USING [CardFromRope, RealFromRope], FS USING [Error, FileInfo, StreamOpen], IO, Rope USING [Cat, Equal, ROPE], Imager USING [Color, Context, MaskVector, SetColor, SetStrokeEnd, SetStrokeWidth, StrokeEnd, VEC, white, black, MakeGray], ImagerColor USING[ColorFromRGB], ImagerInterpress USING [Close, Create, DoPage, Ref]; GerberToIP: CEDAR PROGRAM IMPORTS Commander, Convert, FS, Imager, ImagerColor, ImagerInterpress, IO, Rope = BEGIN ROPE: TYPE = Rope.ROPE; FileHandleRep: TYPE = RECORD[ ip: ROPE, parameters: ROPE, gerber: ROPE ]; FileHandle: TYPE = REF FileHandleRep; Shape: TYPE = {standard, donut, thermalRelief, target}; Aperture: TYPE = RECORD[ dx1, dx2: REAL _ 0, dy1, dy2: REAL _ 0, shape: Shape, color: Imager.Color, strokeEnd: Imager.StrokeEnd ]; Parameters: TYPE = RECORD[ invertAxis: BOOLEAN, scale: REAL, xSym: REAL, ySym: REAL, xTransl: REAL, yTransl: REAL, aperture: ARRAY[1..24] OF Aperture ]; BadCommandLine: SIGNAL []; CmdTokenBreak: PROC [char: CHAR] RETURNS [IO.CharClass] = { IF char = '_ THEN RETURN [break]; IF char = ' OR char = '\t OR char = ', OR char = '; OR char = '\n THEN RETURN [sepr]; RETURN [other]; }; GetCmdToken: PROC [stream: IO.STREAM] RETURNS [rope: ROPE] = { rope _ NIL; rope _ stream.GetTokenRope[CmdTokenBreak ! IO.EndOfStream => CONTINUE].token; }; ReadCommandLine: PROC [cmd: Commander.Handle] RETURNS [filehandle: FileHandle] ~ { file: ROPE; stream: IO.STREAM; filehandle _ NEW[FileHandleRep]; stream _ IO.RIS[cmd.commandLine]; file _ GetCmdToken[stream]; filehandle.ip _ Rope.Cat[file, ".ip"]; filehandle.gerber _ Rope.Cat[file, ".gerber"]; filehandle.parameters _ Rope.Cat[file, ".parameters"]; [] _ FS.FileInfo[filehandle.gerber ! FS.Error => { IF error.group = user THEN { cmd.out.PutRope[Rope.Cat[error.explanation, "\n"]]; SIGNAL BadCommandLine[]; CONTINUE; }; }]; [] _ FS.FileInfo[filehandle.parameters ! FS.Error => { IF error.group = user THEN { cmd.out.PutRope[Rope.Cat[error.explanation, "\n"]]; SIGNAL BadCommandLine[]; CONTINUE; }; }]; IF file = NIL THEN { cmd.out.PutRope["Usage:\nGerberToIP Filename\n(Transform the file Filename.gerber, into the file Filename.ip )\n"]; SIGNAL BadCommandLine[]; }; }; GetNumber: PROC [in: IO.STREAM] RETURNS [x: CARD _ 0] ~ { c: CHAR _ IO.GetChar[in]; WHILE c IN ['0..'9] DO x _ 10 * x + c - '0; c _ IO.GetChar[in]; ENDLOOP; IO.Backup[in, c]; }; SetAperture: PROC [d: CARD] RETURNS [number: CARD] ~ { SELECT d FROM IN[10..19] => number _ d-9; --This is Gerber standard definitions of apertures. IN[70..71] => number _ d-59; IN[20..29] => number _ d-7; IN[72..73] => number _ d-49; ENDCASE => ERROR; }; TokenProc: IO.BreakProc = { RETURN [SELECT char FROM '[, '], '(, '), '{, '}, '", '*, '/, '@, '_ => break, IN [IO.NUL .. IO.SP] => sepr, ',, ':, '; => sepr, ENDCASE => other]; }; ReadParameters: PROC [parametersFile: ROPE] RETURNS [parameters: Parameters] ~ { r, s: ROPE; index: CARD; in: IO.STREAM _ FS.StreamOpen[parametersFile]; parameters.invertAxis _ FALSE; parameters.scale _ 1.0; parameters.xSym _ 1.0; parameters.ySym _ 1.0; parameters.xTransl _ 0.0; parameters.yTransl _ 0.0; WHILE NOT IO.EndOf[in] DO r _ NIL; r _ IO.GetTokenRope[in! IO.EndOfStream => CONTINUE].token; SELECT TRUE FROM Rope.Equal[r, "invertaxis", FALSE] => { parameters.invertAxis _ TRUE; }; Rope.Equal[r, "scale", FALSE] => { parameters.scale _ Convert.RealFromRope[IO.GetTokenRope[in].token]; }; Rope.Equal[r, "xSymetry", FALSE] => { parameters.xSym _ -1.0; }; Rope.Equal[r, "ySymetry", FALSE] => { parameters.ySym _ -1.0; }; Rope.Equal[r, "xTranslation", FALSE] => { parameters.xTransl _ Convert.RealFromRope[IO.GetTokenRope[in, TokenProc].token]; }; Rope.Equal[r, "yTranslation", FALSE] => { parameters.yTransl _ Convert.RealFromRope[IO.GetTokenRope[in, TokenProc].token]; }; Rope.Equal[r, "aperture", FALSE] => { index _ Convert.CardFromRope[IO.GetTokenRope[in].token]; s _ IO.GetTokenRope[in].token; SELECT TRUE FROM Rope.Equal[s, "standard", FALSE] => { parameters.aperture[index].shape _ standard; }; Rope.Equal[s, "donut", FALSE] => { parameters.aperture[index].shape _ donut; }; Rope.Equal[s, "thermalRelief",FALSE] => { parameters.aperture[index].shape _ thermalRelief; }; Rope.Equal[s, "target",FALSE] => { parameters.aperture[index].shape _ target; }; ENDCASE => ERROR; s _ IO.GetTokenRope[in].token; SELECT TRUE FROM Rope.Equal[s, "round", FALSE] => { parameters.aperture[index].strokeEnd _ round; parameters.aperture[index].dx1 _ Convert.CardFromRope[IO.GetTokenRope[in].token]/2; parameters.aperture[index].dx2 _ parameters.aperture[index].dx1; parameters.aperture[index].dy1 _ parameters.aperture[index].dx1; parameters.aperture[index].dy2 _ parameters.aperture[index].dx1; }; Rope.Equal[s, "square", FALSE] => { parameters.aperture[index].strokeEnd _ square; parameters.aperture[index].dx1 _ Convert.CardFromRope[IO.GetTokenRope[in].token]/2; parameters.aperture[index].dx2 _ parameters.aperture[index].dx1; parameters.aperture[index].dy1 _ parameters.aperture[index].dx1; parameters.aperture[index].dy2 _ parameters.aperture[index].dx1; }; Rope.Equal[s, "rectangle", FALSE] => { parameters.aperture[index].strokeEnd _ square; parameters.aperture[index].dx1 _ Convert.CardFromRope[IO.GetTokenRope[in].token]; parameters.aperture[index].dx2 _ Convert.CardFromRope[IO.GetTokenRope[in].token]; parameters.aperture[index].dy1 _ Convert.CardFromRope[IO.GetTokenRope[in].token]; parameters.aperture[index].dy2 _ Convert.CardFromRope[IO.GetTokenRope[in].token]; }; ENDCASE => ERROR; s _ IO.GetTokenRope[in].token; SELECT TRUE FROM Rope.Equal[s, "White", FALSE] => { parameters.aperture[index].color _ Imager.white; }; Rope.Equal[s, "Gray", FALSE] => { parameters.aperture[index].color _ Imager.MakeGray[0.5]; }; Rope.Equal[s, "Black", FALSE] => { parameters.aperture[index].color _ Imager.black; }; Rope.Equal[s, "Red", FALSE] => { parameters.aperture[index].color _ ImagerColor.ColorFromRGB[[1, 0, 0]]; }; Rope.Equal[s, "Green", FALSE] => { parameters.aperture[index].color _ ImagerColor.ColorFromRGB[[0, 1, 0]]; }; Rope.Equal[s, "Blue", FALSE] => { parameters.aperture[index].color _ ImagerColor.ColorFromRGB[[0, 0, 1]]; }; Rope.Equal[s, "Cyan", FALSE] => { parameters.aperture[index].color _ ImagerColor.ColorFromRGB[[0, 1, 1]]; }; Rope.Equal[s, "Magenta", FALSE] => { parameters.aperture[index].color _ ImagerColor.ColorFromRGB[[1, 0, 1]]; }; Rope.Equal[s, "Yellow", FALSE] => { parameters.aperture[index].color _ ImagerColor.ColorFromRGB[[1, 1, 0]]; }; ENDCASE => ERROR; }; ENDCASE; ENDLOOP; }; ProduceIPMaster: PROC [cmd: Commander.Handle, fileHandle: FileHandle] ~ { DoPrint: PROC [context: Imager.Context] ~ { SetParam: PROC [] ~ { IF param.aperture[index].color = NIL THEN { IO.PutF[cmd.out, "The aperture %g is used in the %g file and is not defined in the %g file.\n", IO.card[index], IO.rope[fileHandle.gerber], IO.rope[fileHandle.parameters]]; param.aperture[index].color _ Imager.white; } ELSE { IF currentColor # param.aperture[index].color THEN { currentColor _ param.aperture[index].color; Imager.SetColor[context, currentColor]; }; IF currentStrokeEnd # param.aperture[index].strokeEnd THEN { currentStrokeEnd _ param.aperture[index].strokeEnd; Imager.SetStrokeEnd[context, currentStrokeEnd]; }; widthx _ param.aperture[index].dx1+param.aperture[index].dx2; widthy _ param.aperture[index].dy1+param.aperture[index].dy2; width _ MIN[widthx, widthy]; IF widthx # widthy THEN { delta1.x _ param.aperture[index].dx1-width/2; delta2.x _ param.aperture[index].dx2-width/2; delta1.y _ param.aperture[index].dy1-width/2; delta2.y _ param.aperture[index].dy2-width/2; IF param.invertAxis THEN { temp _ delta1.x; delta1.x _ delta1.y; delta1.y _ temp; temp _ delta2.x; delta2.x _ delta2.y; delta2.y _ temp; } } ELSE { delta1.x _ width/1000; delta2.x _ 0; delta1.y _ 0; delta2.y _ 0; }; IF currentStrokeWidth # MIN[widthx, widthy] THEN { currentStrokeWidth _ MIN[widthx, widthy]; Imager.SetStrokeWidth[context, currentStrokeWidth]; }; }; }; currentStrokeEnd: Imager.StrokeEnd; currentStrokeWidth: REAL; currentColor: Imager.Color; index: CARD; c: CHAR; d: INT; widthx, widthy, width, temp: REAL; p1, p2: Imager.VEC; oldPos, pos, delta1, delta2: Imager.VEC; in: IO.STREAM _ FS.StreamOpen[fileHandle.gerber]; d _ 0; WHILE NOT IO.EndOf[in] DO c _ IO.GetChar[in]; SELECT c FROM ='X => { IF NOT param.invertAxis THEN { pos.x _param.xTransl+param.xSym*GetNumber[in]; } ELSE { pos.y _param.yTransl+param.ySym*GetNumber[in]; }; }; ='Y => { IF NOT param.invertAxis THEN { pos.y _param.yTransl+param.ySym*GetNumber[in]; } ELSE { pos.x _param.xTransl+param.xSym*GetNumber[in]; }; }; ='D => d _ GetNumber[in]; ='* => { -- Action takes place after a '* SELECT d FROM =0 => d _ 0 ; --Not yet initialised =1 => { --Draw SetParam[]; Imager.MaskVector[context, oldPos, pos]; oldPos _ pos; }; =2 => { --Move oldPos _ pos; }; =3 => { --Flash SetParam[]; p1.x _ pos.x-delta1.x; p1.y _ pos.y-delta1.y; p2.x _ pos.x+delta2.x; p2.y _ pos.y+delta2.y; Imager.MaskVector[context, p1, p2]; oldPos _ pos; IF param.aperture[index].shape = target THEN { --add 2 white offset squares currentStrokeEnd _ square; Imager.SetStrokeEnd[context, currentStrokeEnd]; currentColor _ Imager.white; Imager.SetColor[context, currentColor]; p1.x _ pos.x-currentStrokeWidth*.5; p1.y _ pos.y-currentStrokeWidth*.5; p2.x _ pos.x-currentStrokeWidth*.6; p2.y _ pos.y-currentStrokeWidth*.5; Imager.MaskVector[context, p1, p2]; p1.x _ pos.x+currentStrokeWidth*.5; p1.y _ pos.y+currentStrokeWidth*.5; p2.x _ pos.x+currentStrokeWidth*.6; p2.y _ pos.y+currentStrokeWidth*.5; Imager.MaskVector[context, p1, p2]; }; IF param.aperture[index].shape = donut OR param.aperture[index].shape = thermalRelief THEN { --add a white center currentStrokeWidth _ currentStrokeWidth*.6; Imager.SetStrokeWidth[context, currentStrokeWidth]; currentColor _ Imager.white; Imager.SetColor[context, currentColor]; Imager.MaskVector[context, p1, p2]; }; IF param.aperture[index].shape = thermalRelief THEN { --add a white cross currentStrokeEnd _ square; Imager.SetStrokeEnd[context, currentStrokeEnd]; currentStrokeWidth _ currentStrokeWidth/3; Imager.SetStrokeWidth[context, currentStrokeWidth]; p1.x _ pos.x-currentStrokeWidth*2.1; p1.y _ pos.y; p2.x _ pos.x+currentStrokeWidth*2.1; p2.y _ pos.y; Imager.MaskVector[context, p1, p2]; p1.x _ pos.x; p1.y _ pos.y-currentStrokeWidth*2.1; p2.x _ pos.x; p2.y _ pos.y+currentStrokeWidth*2.1; Imager.MaskVector[context, p1, p2]; }; }; IN[4..99] => { index _ SetAperture[d]; IF param.aperture[index].color = NIL THEN { IO.PutF[cmd.out, "The aperture %g is selected in the %g file and is not defined in the %g file.\n", IO.card[index], IO.rope[fileHandle.gerber], IO.rope[fileHandle.parameters]]; param.aperture[index].color _ Imager.white; } }; ENDCASE => ERROR; }; ENDCASE; ENDLOOP; }; pressScale: REAL; param: Parameters _ ReadParameters[fileHandle.parameters]; ip: ImagerInterpress.Ref _ ImagerInterpress.Create[fileHandle.ip]; pressScale _ param.scale*0.0000256; ImagerInterpress.DoPage[ip, DoPrint, pressScale]; ImagerInterpress.Close[ip]; }; GerberToIPProc: Commander.CommandProc = BEGIN fault: BOOLEAN _ FALSE; fileHandle: FileHandle; fileHandle _ ReadCommandLine[cmd ! BadCommandLine => { fault _ TRUE; CONTINUE; }]; IF fault THEN RETURN; ProduceIPMaster[cmd, fileHandle]; END; Commander.Register[ key: "GerberToIP", proc: GerberToIPProc, doc: "Transform a gerber file into an interpress file.\n"]; END. ŠFile: GerberToIP.mesa Copyright Σ 1988 by Xerox Corporation. All rights reserved. Christophe Cuenod March 8, 1988 10:02:44 am PST Κ3–i(firstHeadersAfterPage) {1} .cvx .def (firstPageNumber) {1} .cvx .def (oneSidedFormat) {.false} .cvx .def– "Cedar" style˜– "Cedar" stylešΟnœ™Icode– "Cedar" style™K– "cedar" stylešœžœ˜ K– "cedar" stylešœ+žœžœ˜MKšœ˜K˜—šœžœžœ˜RKšœžœ˜ Kšœžœžœ˜Kšœ žœ˜ Kšœ žœžœ˜!Kšœ˜Kšœ&˜&Kšœ.˜.Kšœ6˜6šœžœžœ ˜3šžœžœ˜Jšœ3˜3Kšžœ˜Jšžœ˜ J˜—Jšœ˜—šœžœ#žœ ˜7šžœžœ˜Jšœ3˜3Kšžœ˜Jšžœ˜ J˜—Jšœ˜—šžœžœžœ˜Kšœs˜sKšžœ˜K˜—K˜—K˜š  œžœžœžœžœžœ ˜9Kšœžœžœ ˜šžœžœ ž˜K˜Kšœžœ ˜Kšžœ˜—Kšžœ˜K˜—š  œžœžœžœ žœ˜6šžœž˜ KšžœΟc3˜OKšžœ˜Kšžœ˜Kšžœ˜Kšžœžœ˜—K˜—š œžœ˜šžœžœž˜K˜4Kš žœžœžœžœžœ ˜Kšœ˜Kšžœ ˜—K˜K˜—K˜šœžœžœžœ˜PKšœžœ˜ Kšœžœ˜ Kšœžœžœžœ˜.Kšœžœ˜Kšœ˜Kšœ˜Kšœ˜Kšœ˜Kšœ˜K˜šžœžœžœ ž˜Kšœžœ˜Kšœžœžœžœ˜:šžœžœž˜šœžœ˜(Kšœžœ˜K˜—šœžœ˜#Kšœ(žœ˜CK˜—šœžœ˜&Kšœ˜K˜—šœžœ˜&Kšœ˜K˜—šœžœ˜*Kšœ*žœ$˜PK˜—šœžœ˜*Kšœ*žœ$˜PK˜—šœžœ˜'Kšœžœ˜8Kšœžœ˜šžœžœž˜šœžœ˜&Kšœ,˜,K˜—šœžœ˜#Kšœ)˜)K˜—šœžœ˜+Kšœ1˜1K˜—šœžœ˜$Kšœ*˜*K˜—Kšžœžœ˜—Kšœžœ˜šžœžœž˜šœžœ˜#Kšœ-˜-Kšœ6žœ˜SKšœ@˜@Kšœ@˜@Kšœ@˜@K˜—šœžœ˜$Kšœ.˜.Kšœ6žœ˜SKšœ@˜@Kšœ@˜@Kšœ@˜@K˜—šœžœ˜'Kšœ.˜.Kšœ6žœ˜QKšœ6žœ˜QKšœ6žœ˜QKšœ6žœ˜QK˜—Kšžœžœ˜—Kšœžœ˜šžœžœž˜šœžœ˜#Kšœ0˜0K˜—šœžœ˜"Kšœ8˜8K˜—šœžœ˜#Kšœ0˜0K˜—šœžœ˜!KšœG˜GK˜—šœžœ˜#KšœG˜GK˜—šœžœ˜"KšœG˜GK˜—šœžœ˜"KšœG˜GK˜—šœžœ˜%KšœG˜GK˜—šœžœ˜$KšœG˜GK˜—Kšžœžœ˜—K˜—Kšžœ˜—Kšžœ˜—K˜K˜—šœžœ5˜Jšœžœ˜+šœžœ˜šžœžœžœ˜+Kšžœ^žœžœžœ˜¬Kšœ+˜+K˜—šžœ˜šžœ,žœ˜4Kšœ+˜+Kšœ'˜'K˜—šžœ4žœ˜