DIRECTORY Commander USING [CommandProc, Register], FS USING [StreamOpen], GList USING [Reverse], IO, Rope USING [Equal, ROPE]; ModifyGerberFiles: CEDAR PROGRAM IMPORTS Commander, FS, GList, IO, Rope = BEGIN ROPE: TYPE = Rope.ROPE; Vector: TYPE = RECORD[ x: INT, y: INT ]; FileInfoRep: TYPE = RECORD[ oldName: ROPE, newName: ROPE, min: Vector _ [32000, 32000], max: Vector _ [0, 0], midLine: Vector ]; FileInfo: TYPE = REF FileInfoRep; FileList: TYPE = LIST OF FileInfo; CommandsRep: TYPE = RECORD[ fileList: FileList, newCommand: ARRAY[1..24] OF ROPE ]; Commands: TYPE = REF CommandsRep; GetNumber: PROC [in: IO.STREAM] RETURNS [x: INT _ 0] ~ { negatif: BOOLEAN _ FALSE; c: CHAR _ IO.GetChar[in]; IF c = '- THEN { negatif _ TRUE; c _ IO.GetChar[in]; }; IF c = '+ THEN c _ IO.GetChar[in]; WHILE c IN ['0..'9] DO x _ 10 * x + c - '0; c _ IO.GetChar[in]; ENDLOOP; IO.Backup[in, c]; IF negatif THEN x _ -x; }; PutNumber: PROC [out: IO.STREAM, x: INT] ~ { IO.PutF[out, "%g", IO.int[x]]; }; GerberToWheelNumber: 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; }; WheelToGerberNumber: PROC [d: CARD] RETURNS [number: CARD] ~ { SELECT d FROM IN[1..10] => number _ d+9; IN[11..12] => number _ d+59; IN[13..22] => number _ d+7; IN[23..24] => number _ d+49; ENDCASE => ERROR; }; FindPosition: PROC [fileInfo: FileInfo] ~ { oldPos, pos: Vector; d: CARD; c: CHAR; end: BOOLEAN _ FALSE; length, maxLength: CARD _ 0; in: IO.STREAM _ FS.StreamOpen[fileInfo.oldName]; WHILE NOT IO.EndOf[in] DO c _ IO.GetChar[in]; SELECT c FROM ='X => { pos.x _ GetNumber[in]; }; ='Y => { pos.y _ GetNumber[in]; }; ='D => { d _ GetNumber[in]; }; ='M => { end _ TRUE; }; ='* => { -- Action takes place after a '* SELECT d FROM =0 => d _ 0 ; --Not yet initialised =1 => { --Draw fileInfo.min.x _ MIN[fileInfo.min.x, pos.x]; fileInfo.min.y _ MIN[fileInfo.min.y, pos.y]; fileInfo.max.x _ MAX[fileInfo.max.x, pos.x]; fileInfo.max.y _ MAX[fileInfo.max.y, pos.y]; length _ ABS[oldPos.x-pos.x]+ABS[oldPos.y-pos.y]; IF length > maxLength THEN { -- Takes the biggest line maxLength _ length; fileInfo.midLine.x _ (oldPos.x+pos.x)/2; fileInfo.midLine.y _ (oldPos.y+pos.y)/2; }; IF (length = maxLength) AND (((oldPos.x+pos.x)/2 < fileInfo.midLine.x) OR ((oldPos.y+pos.y)/2 < fileInfo.midLine.y)) THEN { -- Order the lines of equal length fileInfo.midLine.x _ (oldPos.x+pos.x)/2; fileInfo.midLine.y _ (oldPos.y+pos.y)/2; }; oldPos _ pos; }; =2 => { --Move IF NOT end THEN { -- Moves to 0,0 at the end of the file ! fileInfo.min.x _ MIN[fileInfo.min.x, pos.x]; fileInfo.min.y _ MIN[fileInfo.min.y, pos.y]; fileInfo.max.x _ MAX[fileInfo.max.x, pos.x]; fileInfo.max.y _ MAX[fileInfo.max.y, pos.y]; }; oldPos _ pos; }; =3 => { --Flash fileInfo.min.x _ MIN[fileInfo.min.x, pos.x]; fileInfo.min.y _ MIN[fileInfo.min.y, pos.y]; fileInfo.max.x _ MAX[fileInfo.max.x, pos.x]; fileInfo.max.y _ MAX[fileInfo.max.y, pos.y]; }; ENDCASE; }; ENDCASE; ENDLOOP; }; ModifyEachFile: PROC [fileInfo: FileInfo, commands: Commands, dx: CARD , dy: CARD] ~ { pos, rel: Vector; c: CHAR; in2: IO.STREAM; aperture: CARD; d: INT _ 0; in: IO.STREAM _ FS.StreamOpen[fileInfo.oldName]; out: IO.STREAM _ FS.StreamOpen[fileInfo.newName, $create]; WHILE NOT IO.EndOf[in] DO c _ IO.GetChar[in]; SELECT c FROM ='G => { IO.PutChar[out, 'G]; PutNumber[out, GetNumber[in]]; }; ='X => { pos.x _ GetNumber[in]; IO.PutChar[out, 'X]; PutNumber[out, pos.x-fileInfo.midLine.x+dx]; }; ='Y => { pos.y _ GetNumber[in]; IO.PutChar[out, 'Y]; PutNumber[out, fileInfo.midLine.y-pos.y+dy]; }; ='D => { d _ GetNumber[in]; SELECT d FROM IN [1..2] => { IO.PutChar[out, c]; PutNumber[out, d]; --Draw or Move }; =3 => { --Flash }; -- Takes realy place after a * IN [4..99] => { --Select aperture IO.PutChar[out, c]; PutNumber[out, d]; aperture _ GerberToWheelNumber[d]; }; ENDCASE => ERROR; }; ='\n => IO.PutChar[out, c]; ='* => { IF d # 3 THEN { IO.PutChar[out, c] } ELSE { IF commands.newCommand[aperture] = NIL THEN { IO.PutF[out, "D3*"]; } ELSE { in2 _ IO.RIS[commands.newCommand[aperture]]; WHILE NOT IO.EndOf[in2] DO c _ IO.GetChar[in2]; SELECT c FROM ='X => { rel.x _ GetNumber[in2]; IO.PutChar[out, 'X]; PutNumber[out, rel.x+pos.x-fileInfo.midLine.x+dx]; }; ='Y => { rel.y _ GetNumber[in2]; IO.PutChar[out, 'Y]; PutNumber[out, rel.y+fileInfo.midLine.y-pos.y+dy]; }; ='\040 => { -- Skips spaces }; ENDCASE => { IO.PutChar[out, c]; }; ENDLOOP; IO.PutF[out, "\nG54D%g*X%gY%g", IO.card[WheelToGerberNumber[aperture]], IO.card[pos.x-fileInfo.midLine.x+dx], IO.card[fileInfo.midLine.y-pos.y+dy]]; }; }; }; ENDCASE; ENDLOOP; IO.Close[out]; }; ReadCommands: PROC [commandFile: ROPE] RETURNS [commands: Commands] ~ { r: ROPE; fileInfo: FileInfo; oldAperture: NAT; in: IO.STREAM _ FS.StreamOpen[commandFile]; commands _ NEW[CommandsRep]; FOR i: NAT IN [1..24] DO commands.newCommand[i] _ NIL; ENDLOOP; WHILE NOT IO.EndOf[in] DO r _ NIL; r _ IO.GetTokenRope[in! IO.EndOfStream => CONTINUE].token; SELECT TRUE FROM Rope.Equal[r, "ApertureModification", FALSE] => { oldAperture _ IO.GetCard[in]; commands.newCommand[oldAperture] _ IO.GetLineRope[in]; }; Rope.Equal[r, "File", FALSE] => { fileInfo _ NEW[FileInfoRep]; fileInfo.oldName _ IO.GetTokenRope[in].token; fileInfo.newName _ IO.GetTokenRope[in].token; commands.fileList _ CONS[fileInfo, commands.fileList]; }; r = NIL => r _ NIL; ENDCASE => ERROR; ENDLOOP; }; ModifyGerberFilesProc: Commander.CommandProc = BEGIN min, max: Vector _ [0,0]; commandFile: ROPE _ IO.GetTokenRope[IO.RIS[cmd.commandLine]].token; commands: Commands _ ReadCommands[commandFile]; commands.fileList _ NARROW[GList.Reverse[commands.fileList]]; IO.PutF[cmd.out, "Reading the source files to find how to justify them\n"]; FOR l: FileList _ commands.fileList, l.rest UNTIL l = NIL DO IO.PutF[cmd.out, "Reading %g \n", IO.rope[l.first.oldName]]; FindPosition[l.first]; ENDLOOP; FOR l: FileList _ commands.fileList, l.rest UNTIL l = NIL DO min.x _ MIN[min.x, l.first.min.x - l.first.midLine.x]; min.y _ MIN[min.y, l.first.min.y - l.first.midLine.y]; max.x _ MAX[max.x, l.first.max.x - l.first.midLine.x]; max.y _ MAX[max.y, l.first.max.y - l.first.midLine.y]; ENDLOOP; IO.PutF[cmd.out, "Generating the new files\n"]; FOR l: FileList _ commands.fileList, l.rest UNTIL l = NIL DO IO.PutF[cmd.out, "Reading %g and writing %g\n", IO.rope[l.first.oldName], IO.rope[l.first.newName]]; ModifyEachFile[l.first, commands, -min.x+100, max.y+100]; ENDLOOP; END; Commander.Register[ key: "ModifyGerberFiles", proc: ModifyGerberFilesProc, doc: "Transform a set of gerber files to prepare them for photoploting (Invert the Y axis, justify the drawings and change some aperture shooting by an arbitrary pattern).\n"]; END. nFile: ModifyGerberFiles.mesa Copyright Σ 1987 by Xerox Corporation. All rights reserved. Christophe Cuenod February 15, 1988 3:47:55 pm PST Taking the center of the longest line as reference what is the smallest rectangle fitting all the drawings The new coordinates are: newx _ oldx - midline.x - min.x + epsilon newy _ midline.y - oldy + max.y + epsilon Κ –i(firstHeadersAfterPage) {1} .cvx .def (firstPageNumber) {1} .cvx .def (oneSidedFormat) {.false} .cvx .def– "Cedar" style˜– "Cedar" stylešΟnœ™Icode– "Cedar" style™šžœž˜ KšžœΟc3˜OKšžœ˜Kšžœ˜Kšžœ˜Kšžœžœ˜—K˜—š œžœžœžœ žœ˜>šžœž˜ Kšžœ˜Kšžœ˜Kšžœ˜Kšžœ˜Kšžœžœ˜—K˜—K˜š œžœ˜,Kšœ˜Kšœžœ˜Kšœžœ˜Kšœ˜Kšœ˜Kšœžœžœžœ˜0šžœžœžœ ž˜Kšœžœ ˜šžœž˜ šœ ˜ Kšœ˜K˜—šœ ˜ Kšœ˜K˜—šœ ˜ Kšœ˜K˜—šœ ˜ Kšœ ˜ K˜—K˜šœ Ÿ ˜+šžœž˜ KšœŸ˜#šœŸ˜Kšœžœ˜,Kšœžœ˜,Kšœžœ˜,Kšœžœ˜,K˜Kšœ1˜1šœ6˜6Kšœ˜Kšœ(˜(Kšœ(˜(K˜—š žœžœ,žœ,žœŸ"˜žKšœ(˜(Kšœ(˜(K˜—K˜Kšœ ˜ Kšœ˜—šœŸ˜šžœžœžœŸ(˜:Kšœžœ˜,Kšœžœ˜,Kšœžœ˜,Kšœžœ˜,K˜—Kšœ ˜ Kšœ˜—šœŸ˜Kšœžœ˜,Kšœžœ˜,Kšœžœ˜,Kšœžœ˜,K˜—Kšžœ˜—K˜—Kšžœ˜—Kšžœ˜—K˜K˜—šœžœ.žœžœ˜WKšœ˜Kšœžœ˜Kšœžœžœ˜Kšœ žœ˜Kšœžœ˜ Kšœžœžœžœ˜0Kšœžœžœžœ'˜:šžœžœžœ ž˜Kšœžœ ˜šžœž˜ šœ ˜ Kšžœ˜Kšœ˜K˜—šœ ˜ Kšœ˜Kšžœ˜Kšœ,˜,K˜—šœ ˜ Kšœ˜Kšžœ˜Kšœ,˜,K˜—šœ ˜ Kšœ˜K˜šžœž˜ šžœ ˜Kšžœ˜KšœŸ˜!K˜—šœ Ÿ ˜JšœŸ˜!—šžœŸ˜#Kšžœ˜Kšœ˜Kšœ"˜"K˜—Kšžœžœ˜—K˜K˜—Kšœ žœ˜šœ ˜ šžœžœ˜Kšžœ˜K˜—šžœ˜šžœ%ž˜-Jšžœ˜J˜—šžœ˜Jšœžœžœ ˜,šžœžœžœ ž˜Kšœžœ˜šžœž˜ šœ ˜ Kšœ˜Kšžœ˜Kšœ2˜2K˜—šœ ˜ Kšœ˜Kšžœ˜Kšœ2˜2K˜—šœ Ÿ˜K˜—šžœ˜ Kšžœ˜K˜——Kšžœ˜—Jšžœžœ&žœ$žœ$˜”J˜—J˜—K˜—Kšžœ˜—Kšžœ˜—Kšžœ ˜K˜K˜K˜—š œžœžœžœ˜GKšœžœ˜Kšœ˜Kšœ žœ˜Kšœžœžœžœ˜+Kšœ žœ˜šžœžœžœ ž˜Kšœ˜Kšžœ˜—šžœžœžœ ž˜Kšœžœ˜Kšœžœžœžœ˜:šžœžœž˜šœ&žœ˜3Kšœžœ ˜Kšœ#žœ˜6K˜—šœžœ˜#Kšœ žœ˜Kšœžœ˜-Kšœžœ˜-Kšœžœ˜6K˜—Kšœžœžœ˜Kšžœžœ˜—Kšžœ˜—K˜K˜—šœž˜4J˜Jš œ žœžœžœžœ˜CKšœ/˜/Kšœžœ#˜=JšžœI˜Kšžœ)žœžœž˜