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 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> <20120705101614 DOT GA19974 AT visitor2 DOT iram DOT es> <20120706202633 DOT GA28355 AT malakian DOT lan> MIME-Version: 1.0 Content-Type: text/plain; charset=iso-8859-1 Content-Disposition: inline Content-Transfer-Encoding: 8bit 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 Precedence: bulk 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");