#!/usr/bin/perl # convert Fig file to GERBER files and aperture table # Andrew Daviel TRIUMF Feb 2002 advax@triumf.ca unless ($ARGV[2]) { &usage ; exit ; } if (open(IN,$ARGV[0])) { while (){ tr/\r//d ; chomp ; tr/ / /s ; ($n,$t,$s,$s2,$z,$c) = split(/ /) ; if (length($t) > 1) { $s /= 1000 ; $s2 /= 1000 ; } $size{$n} = $s ; $size2{$n} = $s2 ; if ($t eq 'RECTANGULAR' && $s == $s2) { $t = 'S' ; } # square if ($t eq 'ROUNDED' && $s == $s2 && $c eq 'LINE') { $t = 'D' ; } # draw if ($t eq 'ROUNDED' && $s == $s2) { $t = 'R' ; } # round $type{$n} = $t ; $nn = $n ; $nn =~ s/^D// ; if ($nn > $apn) { $apn = $nn ; } if ($t eq 'R') { $flash_r{$s} = $n ; } if ($t eq 'S') { $flash_s{$s} = $n ; } if ($t eq 'D') { $draw_r{$s} = $n ; } if ($t eq 'RECTANGULAR') { $flash_rect{"$s;$s2"} = $n ; } print "$n $t $s $s2\n" ; } close (IN) ; } # text see /home/andrew/vrweb/fonts open (IN,$ARGV[1]) or die ; open (OUT,">$ARGV[2]") or die ; unless ($apn) { $apn = 9 ; } $indepth = 0 ; if ($ARGV[3]) { $indepth = $ARGV[3] ; } print OUT "G54*\n" ; while () { chomp ; tr/ / /s ; if (/^1 3 /) { # circle # 1 x sty wid fg bg dep x fil angle x x X Y R R X Y ($t,$t2,$style,$width,$fg,$bg,$depth,$u2,$fill,$angle,$u3,$u4,$x,$y,$r,$r2,$x2,$y2,$z,$z2) = split(/ /) ; if ($depth == $indepth || !$indepth) { print "circle $x,$y,$r\n" ; $dia = int($r*1000/1200+0.5) ; $dia = $dia*2/1000 ; $ap = $flash_r{$dia} ; unless ($ap) { $apn++ ; $ap = sprintf("D%2.2d",$apn) ; $flash_r{$dia} = $ap ; $ftype{$ap} = 'R' ; print "add flash R $dia $ap\n" ; push(@apr,"$ap R $dia") ; } unless ($ap eq $current_ap) { print OUT "$flash_r{$dia}*\n" ; $current_ap = $ap ; } printf OUT ("X%5.5dY%5.5dD02*D03*\n",int($y*1000/1200+0.5),int($x*1000/1200+0.5)) ; } } elsif (/^2 2 /) { # box ($t,$t2,$style,$width,$fg,$bg,$depth,$u2,$fill,$angle,$u3,$u4,$u5,$u6,$u7,$npts) = split(/ /) ; $_ = () ; chomp ; tr/ \t/ /s ; s/^ // ; @xy = split(/ /) ; $x1 = $x2 = $y1 = $y2 = '' ; for ($i=0;$i<4;$i++) { $x = shift(@xy) ; $y = shift(@xy) ; if ($x1 eq '' || $x < $x1) { $x1 = $x ; } if ($x2 eq '' || $x > $x2) { $x2 = $x ; } if ($y1 eq '' || $y < $y1) { $y1 = $y ; } if ($y2 eq '' || $y > $y2) { $y2 = $y ; } } if ($depth == $indepth || !$indepth) { $x = int(($x1+$x2)/2+0.5) ; $y = int(($y1+$y2)/2+0.5) ; $h = ($x2 - $x1) ; $w = $y2 - $y1 ; if ($w<0) { $w = -$w ; } if ($h<0) { $h = -$h ; } $w = int($w*1000/1200+0.5) ; $w = $w / 1000 ; $h = int($h*1000/1200+0.5) ; $h = $h / 1000 ; if ($w == $h) { $ap = $flash_s{$w} ; unless ($ap) { $apn++ ; $ap = sprintf("D%2.2d",$apn) ; $flash_s{$w} = $ap ; $ftype{$ap} = 'S' ; print "add flash S $w $ap\n" ; push(@apr,"$ap S $w") ; } } else { # rectangular $ap = $flash_rect{"$w;$h"} ; unless ($ap) { $apn++ ; $ap = sprintf("D%2.2d",$apn) ; $flash_rect{"$w;$h"} = $ap ; $ftype{$ap} = 'RECTANGULAR' ; print "add flash rect $w x $h $ap\n" ; $w *= 1000 ; $h *= 1000 ; push(@apr,"$ap RECTANGULAR $w $h") ; } } unless ($ap eq $current_ap) { print OUT "$ap\*\n" ; $current_ap = $ap ; } printf OUT ("X%5.5dY%5.5dD02*D03*\n",int($y*1000/1200+0.5),int($x*1000/1200+0.5)) ; } } elsif (/^2 1 /) { # line ($t,$t2,$style,$width,$fg,$bg,$depth,$u2,$fill,$angle,$u3,$u4,$u5,$u6,$u7,$npts) = split(/ /) ; if ($depth == $indepth || !$indepth) { print "line $width $npts points\n" ; $wid = $width*0.012 ; $ap = $draw_r{$wid} ; unless ($ap) { $apn++ ; $ap = sprintf("D%2.2d",$apn) ; $draw_r{$wid} = $ap ; $ftype{$ap} = 'D' ; print "add draw $wid $ap\n" ; push(@apr,"$ap D $wid") ; } unless ($ap eq $current_ap) { print OUT "$ap\*\n" ; $current_ap = $ap ; } $start = 1 ; while (1) { unless ($npts) { last ; } $_ = () ; chomp ; unless (/^\t[\s]*[\d]+/) { print "expected TAB + digits\n" ; } tr/ \t/ /s ; s/^ // ; @pts = split(/ /) ; $npts2 = @pts ; unless ($npts2/2 == $npts || $npts2 == 12) { print "expected $npts points got $npts2 pairs\n" ; } $npts -= $npts2/2 ; if ($start) { $x = shift(@pts) ; $y = shift(@pts) ; print "x $x y $y\n" ; printf OUT ("X%5.5dY%5.5dD02*\n",int($y*1000/1200+0.5),int($x*1000/1200+0.5)) ; } for ($i=$start;$i<$npts2/2;$i++) { $x = shift(@pts) ; $y = shift(@pts) ; print "x $x y $y\n" ; printf OUT ("X%5.5dY%5.5dD01*\n",int($y*1000/1200+0.5),int($x*1000/1200+0.5)) ; } $start = 0 ; } } } elsif(/^4 [\d] /) { # 4 u fg depth u font pt angle flags # 0 times add 1 bold add 2 oblique 0 # 4 av ss 1 # 8 bookman 2 # 12 courier 3 # 16 helvetica ss 4 # 20 helveitic narrow ss 5 # 24 new sc 6 # 28 palatino 7 # 33 chancery $ptz{0} = 1.2 ; $ptz{1} = 1.4 ; $ptz{2} = 1.4 ; $ptz{3} = 1.7 ; $ptz{4} = 1.4 ; $ptz{5} = 1.1 ; $ptz{6} = 1.4 ; $ptz{7} = 1.4 ; $ptz{8} = 1 ; @f = split(/ /) ; $fg = $f[2]; $depth = $f[3] ; $font = $f[5] ; $pt = $f[6] ; $angle = $f[7] ; $x = $f[11] ; $y = $f[12] ; if ($depth == $indepth || !$indepth) { $fntype = int($font/4) ; $fnsty = $font - 4*$fntype ; if ($fntype == 1 || $fntype == 4 || $fntype == 5) { unless ($gotsans) { &loadsans ; } } else { unless ($gotserif) { &loadserif ; } } for ($i=0;$i<13;$i++) { shift(@f) ; } $text = join(' ',@f) ; $text =~ s/\\001$// ; $text =~ s/\\([\d][\d][\d])/pack("C",oct($1))/ge; print "text at $x $y font $font $pt pt fntype $fntype fnsty $fnsty\n$text\n" ; $xmag = $ptz{$fntype}*$pt ; $ymag = 1.6*$pt ; $xoff = $x ; $yoff = $y ; $fwidth = sprintf("%f.1",$pt/18) ; if ($font & 2) { $fwidth *= 1.5 ; } $wid = $fwidth*0.012 ; $ap = $draw_r{$wid} ; unless ($ap) { $apn++ ; $ap = sprintf("D%2.2d",$apn) ; $draw_r{$wid} = $ap ; $ftype{$ap} = 'D' ; print "add draw $wid $ap\n" ; push(@apr,"$ap D $wid") ; } unless ($ap eq $current_ap) { print OUT "$ap\*\n" ; $current_ap = $ap ; } @word = unpack("C*",$text) ; foreach $ch (@word) { &cdraw(chr($ch)) ; } } } elsif(/^[\d] [\d] /) { print "Unknown type $_\n" ; } } print OUT "M02*\n" ; foreach $k ( keys %flash_r ) { print "Flash R $k $flash_r{$k}\n" ; } foreach $k ( keys %flash_s ) { print "Flash S $k $flash_s{$k}\n" ; } foreach $k ( keys %flash_rect ) { print "Flash RECT $k $flash_rect{$k}\n" ; } foreach $k ( keys %draw_r ) { print "Draw $k $draw_r{$k}\n" ; } close(OUT) ; if (open(OUT,">>$ARGV[0]") || open(OUT,">$ARGV[0]")) { foreach $_ (@apr) { print OUT "$_\n" ; } } sub usage { print STDERR< (or all) elements from Fig to GERBER PCB plot. If the aperture table exists it will be used and perhaps extended, otherwise it is created. Circles are translated to round flash, square boxes to square flash and lines to lines (D). EOT } sub loadsans { my $line = $_ ; open (WRL,"/home/andrew/gerber/wfsans.wrl") ; while () { if (/DEF chr(.*) Separator/) { $char = $1 ; $charc = chr(hex($char)) ; } elsif (/Coordinate3 /) { s/.*point . // ; s/, \] }// ; $chr{$charc} = $_ ; } elsif (/coordIndex/) { s/.*coordIndex \[ // ; s/, \].*// ; $set{$charc} = $_ ; } } $fudge{'l'} = 0.5 ; $fudge{'!'} = 0.5 ; $fudge{'I'} = 0.5 ; $fudge{'j'} = 0.5 ; $fudge{'J'} = 0.8 ; $fudge{'t'} = 0.7 ; $fudge{'f'} = 0.8 ; $fudge{'i'} = 0.5 ; $fudge{' '} = 0.6 ; $fudge{'|'} = 0.5 ; $fudge{'m'} = 1.5 ; close(WRL) ; $gotsans = 1 ; $_ = $line ; } sub loadserif { my $line = $_ ; open (WRL,"/home/andrew/gerber/wfserf.wrl") ; while () { if (/DEF chr(.*) Separator/) { $char = $1 ; $charc = chr(hex($char)) ; } elsif (/Coordinate3 /) { s/.*point . // ; s/, \] }// ; $chrsf{$charc} = $_ ; } elsif (/coordIndex/) { s/.*coordIndex \[ // ; s/, \].*// ; $setsf{$charc} = $_ ; } } close (WRL) ; $fudge{'l'} = 0.6 ; $fudge{'!'} = 0.6 ; $fudge{' '} = 0.6 ; $fudge{'I'} = 0.7 ; $fudge{'j'} = 0.7 ; $fudge{'J'} = 0.8 ; $fudge{'t'} = 0.8 ; $fudge{'g'} = 0.8 ; $fudge{'i'} = 0.6 ; $fudge{'|'} = 0.6 ; $fudge{'m'} = 1.5 ; $gotserif = 1 ; $_ = $line ; } sub cdraw { if ($fntype == 1 || $fntype == 4 || $fntype == 5) { @chr = split(/, /,$chr{$_[0]}) ; @set = split(/, /,$set{$_[0]}) ; } else { @chr = split(/, /,$chrsf{$_[0]}) ; @set = split(/, /,$setsf{$_[0]}) ; } $npts = @chr ; undef(@stroke) ; while (1) { $idx = shift(@set) ; if ($idx eq '') { last ; } if ($idx < 0) { ($x,$y,$z) = split(/ /,shift(@stroke)) ; if ($font & 1) { $x = $x + $y/6 ; } $Y = $x*$xmag+$xoff ; $X = -$y*$ymag+$yoff ; printf OUT ("X%5.5dY%5.5dD02*\n",int($X*1000/1200+0.5),int($Y*1000/1200+0.5)) ; foreach $point (@stroke) { ($x,$y,$z) = split(/ /,$point) ; if ($font & 1) { $x = $x + $y/6 ; } $Y = $x*$xmag+$xoff ; $X = -$y*$ymag+$yoff ; printf OUT ("X%5.5dY%5.5dD01*\n",int($X*1000/1200+0.5),int($Y*1000/1200+0.5)) ; } undef(@stroke) ; } else { push(@stroke,shift(@chr) ) ; } } $fudge = $fudge{$_[0]} ; unless ($fudge) { $fudge = 1 ; } $xoff += 6*$xmag*$fudge ; }