delorie.com/archives/browse.cgi   search  
Mail Archives: geda-user/2012/07/06/17:34:10

X-Authentication-Warning: delorie.com: mail set sender to geda-user-bounces using -f
X-Recipient: geda-user AT delorie DOT com
X-Envelope-From: paubert AT iram DOT es
Date: Fri, 6 Jul 2012 23:33:40 +0200
From: Gabriel Paubert <paubert AT iram DOT es>
To: geda-user AT delorie DOT com
Subject: Re: [geda-user] [PATCH] Allow to create metric Gerber and drill
files, hopefully final version.
Message-ID: <20120706213340.GA30622@visitor2.iram.es>
References: <20120703140236 DOT GA12646 AT visitor2 DOT iram DOT es>
<CAKakQcdTgG6E2h+UgWoh-ujP6vFDH=voY-PBJR3OFG2awqL0_A AT mail DOT gmail DOT com>
<20120705101614 DOT GA19974 AT visitor2 DOT iram DOT es>
<20120706202633 DOT GA28355 AT malakian DOT lan>
MIME-Version: 1.0
In-Reply-To: <20120706202633.GA28355@malakian.lan>
User-Agent: Mutt/1.5.20 (2009-06-14)
X-SPF-Received: 2
X-Spamina-Bogosity: Unsure
X-Spam-Score: -4.4 (----)
X-Spam-Report: Content analysis details: (-4.4 points)
pts rule name description
---- ---------------------- --------------------------------------------------
-1.8 ALL_TRUSTED Passed through trusted hosts only via SMTP
-2.6 BAYES_00 BODY: Bayesian spam probability is 0 to 1%
[score: 0.0000]
Reply-To: geda-user AT delorie DOT com
Errors-To: nobody AT delorie DOT com
X-Mailing-List: geda-user AT delorie DOT com
X-Unsubscribes-To: listserv AT delorie DOT com

This last version of the patch should satisfy everybody:
- by default the output stays as imperial, which I consider heretic,
  but so be it.

- it produces exactly the same output in imperial mode (modulo comment line
  specifying PCB dimensions) as before applying the patch. This has been tested
  on the few (3) testsuite files and a few more examples I have here.

- the testsuite for the gerber exporter passes even when forced to metric mode
  (comparing png files produced though gerbv)


Note that I explicitly put a METRIC,000.000 to specify that the drill file
is in micron resolution. The Excellon http://www.excellon.com/manuals/program.htm
seems to impy that this should be the default (see under M71), but at least gerbv
does not seem to default to this format. 

diff --git a/src/hid/gerber/gerber.c b/src/hid/gerber/gerber.c
index 2181718..6bf6843 100644
--- a/src/hid/gerber/gerber.c
+++ b/src/hid/gerber/gerber.c
@@ -82,6 +82,8 @@ static void gerber_fill_polygon (hidGC gc, int n_coords, Coord *x, Coord *y);
 
 static int verbose;
 static int all_layers;
+static int metric;
+static char *x_convspec, *y_convspec;
 static int is_mask, was_drill;
 static int is_drill;
 static int current_mask;
@@ -90,6 +92,12 @@ static int copy_outline_mode;
 static int name_style;
 static LayerType *outline_layer;
 
+#define print_xcoord(file, pcb, val)\
+	pcb_fprintf(file, x_convspec, gerberX(pcb, val))
+
+#define print_ycoord(file, pcb, val)\
+	pcb_fprintf(file, y_convspec, gerberY(pcb, val))
+
 enum ApertureShape
 {
   ROUND,			/* Shaped like a circle */
@@ -225,13 +233,14 @@ fprintAperture (FILE *f, Aperture *aptr)
   switch (aptr->shape)
     {
     case ROUND:
-      pcb_fprintf (f, "%%ADD%dC,%.4`mi*%%\r\n", aptr->dCode, aptr->width);
+      pcb_fprintf (f, metric ? "%%ADD%dC,%.3`mm*%%\r\n" : "%%ADD%dC,%.4`mi*%%\r\n", aptr->dCode, aptr->width);
       break;
     case SQUARE:
-      pcb_fprintf (f, "%%ADD%dR,%.4`miX%.4`mi*%%\r\n", aptr->dCode, aptr->width, aptr->width);
+      pcb_fprintf (f, metric ? "%%ADD%dR,%.3`mmX%.3`mm*%%\r\n" : "%%ADD%dR,%.4`miX%.4`mi*%%\r\n", aptr->dCode, aptr->width, aptr->width);
       break;
     case OCTAGON:
-      pcb_fprintf (f, "%%AMOCT%d*5,0,8,0,0,%.4`mi,22.5*%%\r\n"
+      pcb_fprintf (f, metric ? "%%AMOCT%d*5,0,8,0,0,%.3`mm,22.5*%%\r\n"
+	       "%%ADD%dOCT%d*%%\r\n" : "%%AMOCT%d*5,0,8,0,0,%.3`mm,22.5*%%\r\n"
 	       "%%ADD%dOCT%d*%%\r\n", aptr->dCode,
 	       (Coord) ((double) aptr->width / COS_22_5_DEGREE), aptr->dCode,
 	       aptr->dCode);
@@ -362,12 +371,22 @@ Print file names and aperture counts on stdout.
   {"verbose", "Print file names and aperture counts on stdout",
    HID_Boolean, 0, 0, {0, 0, 0}, 0, 0},
 #define HA_verbose 2
+/* %start-doc options "90 Gerber Export"
+@ftable @code
+@item --metric
+generate metric Gerber and drill files
+@end ftable
+%end-doc
+*/
+  {"metric", "Generate metric Gerber and drill files",
+   HID_Boolean, 0, 0, {0, 0, 0}, 0, 0},
+#define HA_metric 3
   {"copy-outline", "Copy outline onto other layers",
    HID_Enum, 0, 0, {0, 0, 0}, copy_outline_names, 0},
-#define HA_copy_outline 3
+#define HA_copy_outline 4
   {"name-style", "Naming style for individual gerber files",
    HID_Enum, 0, 0, {0, 0, 0}, name_style_names, 0},
-#define HA_name_style 4
+#define HA_name_style 5
 };
 
 #define NUM_OPTIONS (sizeof(gerber_options)/sizeof(gerber_options[0]))
@@ -531,6 +550,14 @@ gerber_do_export (HID_Attr_Val * options)
     fnbase = "pcb-out";
 
   verbose = options[HA_verbose].int_value;
+  metric = options[HA_metric].int_value;
+  if (metric) {
+	  x_convspec = "X%.0mu";
+	  y_convspec = "Y%.0mu";
+  } else {
+	  x_convspec = "X%.0mc";
+	  y_convspec = "Y%.0mc";
+  }
   all_layers = options[HA_all_layers].int_value;
 
   copy_outline_mode = options[HA_copy_outline].int_value;
@@ -668,7 +695,7 @@ gerber_set_layer (const char *name, int group, int empty)
 	    }
           /* Notice the last zeroes are literal zeroes here, a  *
            *  x10 scale factor.  v        v                     */
-          pcb_fprintf (f, "X%06.0ml0Y%06.0ml0\r\n",
+	  pcb_fprintf (f, metric ? "X%06.0muY%06.0mu\r\n" : "X%06.0ml0Y%06.0ml0\r\n",
 		   gerberDrX (PCB, pending_drills[i].x),
 		   gerberDrY (PCB, pending_drills[i].y));
 	}
@@ -733,10 +760,11 @@ gerber_set_layer (const char *name, int group, int empty)
       if (is_drill)
 	{
 	  /* We omit the ,TZ here because we are not omitting trailing zeros.  Our format is
-	     always six-digit 0.1 mil resolution (i.e. 001100 = 0.11")*/
-	  fprintf (f, "M48\r\n" "INCH\r\n");
+	     always six-digit 0.1 mil or µm resolution (i.e. 001100 = 0.11" or 1.1mm)*/
+	  fprintf (f, "M48\r\n");
+	  fprintf (f, metric ? "METRIC,000.000\r\n" : "INCH\r\n");
 	  for (search = aptr_list->data; search; search = search->next)
-	    pcb_fprintf (f, "T%02dC%.3`mi\r\n", search->dCode, search->width);
+		  pcb_fprintf (f, metric ? "T%02dC%.3`mm\r\n" : "T%02dC%.3`mi\r\n", search->dCode, search->width);
 	  fprintf (f, "%%\r\n");
 	  /* FIXME */
 	  return 1;
@@ -765,15 +793,16 @@ gerber_set_layer (const char *name, int group, int empty)
 #endif
 
       fprintf (f, "G04 Format: Gerber/RS-274X *\r\n");
-      pcb_fprintf (f, "G04 PCB-Dimensions: %.0mc %.0mc *\r\n",
+      pcb_fprintf (f, metric ? "G04 PCB-Dimensions (mm): %.2mm %.2mm *\r\n" :
+	       "G04 PCB-Dimensions (mil): %.2ml %.2ml *\r\n",
 	       PCB->MaxWidth, PCB->MaxHeight);
       fprintf (f, "G04 PCB-Coordinate-Origin: lower left *\r\n");
 
       /* Signal data in inches. */
-      fprintf (f, "%%MOIN*%%\r\n");
+      fprintf (f, metric ? "%%MOMM*%%\r\n" : "%%MOIN*%%\r\n");
 
-      /* Signal Leading zero suppression, Absolute Data, 2.5 format */
-      fprintf (f, "%%FSLAX25Y25*%%\r\n");
+      /* Signal Leading zero suppression, Absolute Data, 2.5 format in inch, 4.3 in mm */
+      fprintf (f, metric ? "%%FSLAX43Y43*%%\r\n" : "%%FSLAX25Y25*%%\r\n");
 
       /* build a legal identifier. */
       if (layername)
@@ -996,13 +1025,13 @@ gerber_draw_line (hidGC gc, Coord x1, Coord y1, Coord x2, Coord y2)
     {
       m = true;
       lastX = x1;
-      pcb_fprintf (f, "X%.0mc", gerberX (PCB, lastX));
+      print_xcoord (f, PCB, lastX);
     }
   if (y1 != lastY)
     {
       m = true;
       lastY = y1;
-      pcb_fprintf (f, "Y%.0mc", gerberY (PCB, lastY));
+      print_ycoord (f, PCB, lastY);
     }
   if ((x1 == x2) && (y1 == y2))
     fprintf (f, "D03*\r\n");
@@ -1013,13 +1042,12 @@ gerber_draw_line (hidGC gc, Coord x1, Coord y1, Coord x2, Coord y2)
       if (x2 != lastX)
 	{
 	  lastX = x2;
-	  pcb_fprintf (f, "X%.0mc", gerberX (PCB, lastX));
+	  print_xcoord (f, PCB, lastX);
 	}
       if (y2 != lastY)
 	{
 	  lastY = y2;
-	  pcb_fprintf (f, "Y%.0mc", gerberY (PCB, lastY));
-
+	  print_ycoord (f, PCB, lastY);
 	}
       fprintf (f, "D01*\r\n");
     }
@@ -1087,17 +1115,18 @@ gerber_draw_arc (hidGC gc, Coord cx, Coord cy, Coord width, Coord height,
     {
       m = true;
       lastX = arcStartX;
-      pcb_fprintf (f, "X%.0mc", gerberX (PCB, lastX));
+      print_xcoord (f, PCB, lastX);
     }
   if (arcStartY != lastY)
     {
       m = true;
       lastY = arcStartY;
-      pcb_fprintf (f, "Y%.0mc", gerberY (PCB, lastY));
+      print_ycoord (f, PCB, lastY);
     }
   if (m)
     fprintf (f, "D02*");
   pcb_fprintf (f,
+	   metric ? "G75*G0%1dX%.0muY%.0muI%.0muJ%.0muD01*G01*\r\n" :
 	   "G75*G0%1dX%.0mcY%.0mcI%.0mcJ%.0mcD01*G01*\r\n",
 	   (delta_angle < 0) ? 2 : 3,
 	   gerberX (PCB, arcStopX), gerberY (PCB, arcStopY),
@@ -1137,12 +1166,12 @@ gerber_fill_circle (hidGC gc, Coord cx, Coord cy, Coord radius)
   if (cx != lastX)
     {
       lastX = cx;
-      pcb_fprintf (f, "X%.0mc", gerberX (PCB, lastX));
+      print_xcoord (f, PCB, lastX);
     }
   if (cy != lastY)
     {
       lastY = cy;
-      pcb_fprintf (f, "Y%.0mc", gerberY (PCB, lastY));
+      print_ycoord (f, PCB, lastY);
     }
   fprintf (f, "D03*\r\n");
 }
@@ -1168,13 +1197,13 @@ gerber_fill_polygon (hidGC gc, int n_coords, Coord *x, Coord *y)
 	{
 	  m = true;
 	  lastX = x[i];
-	  pcb_fprintf (f, "X%.0mc", gerberX (PCB, lastX));
+	  print_xcoord (f, PCB, lastX);
 	}
       if (y[i] != lastY)
 	{
 	  m = true;
 	  lastY = y[i];
-	  pcb_fprintf (f, "Y%.0mc", gerberY (PCB, lastY));
+	  print_ycoord (f, PCB, lastY);
 	}
       if (firstTime)
 	{
@@ -1192,13 +1221,13 @@ gerber_fill_polygon (hidGC gc, int n_coords, Coord *x, Coord *y)
     {
       m = true;
       lastX = startX;
-      pcb_fprintf (f, "X%.0mc", gerberX (PCB, startX));
+      print_xcoord (f, PCB, startX);
     }
   if (startY != lastY)
     {
       m = true;
       lastY = startY;
-      pcb_fprintf (f, "Y%.0mc", gerberY (PCB, lastY));
+      print_ycoord (f, PCB, lastY);
     }
   if (m)
     fprintf (f, "D01*\r\n");

- Raw text -


  webmaster     delorie software   privacy  
  Copyright © 2019   by DJ Delorie     Updated Jul 2019