/* * gerber.c - Gerber file input * * Written 2010 by Werner Almesberger * Copyright 2010 Werner Almesberger * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. */ /* * Note: this is limited to the Gerber produced by KiCad for the PCB Edge * layer. Furthermore, we ignore the tool diameter for now. * * The relevant details are nicely explained at * http://www.pcbmilling.com/Examples of Gerber and Excellon Data Files.htm */ #include #include #include #include "path.h" #include "gerber.h" /* KiCad Gerber uses 0.1 mil units */ #define KU2MM(in) ((in)/10000.0*25.4) struct path *gerber_read(const char *name, double r_tool_default) { FILE *file; int lineno = 0; char buf[1024]; struct path *paths = NULL, **anchor = &paths, *path = NULL; double start_x = 0, start_y = 0; int xi, yi, d; double x, y; file = name ? fopen(name, "r") : stdin; if (!file) { perror(name); exit(1); } while (fgets(buf, sizeof(buf), file)) { lineno++; if (!strncmp(buf, "%FS", 3)) { if (strcmp(buf, "%FSLAX34Y34*%\n")) { fprintf(stderr, "unrecognized format %s\n", buf); exit(1); } continue; } if (!strncmp(buf, "%MO", 3)) { if (strcmp(buf, "%MOIN*%\n")) { fprintf(stderr, "unrecognized mode %s\n", buf); exit(1); } continue; } if (sscanf(buf, "X%dY%dD%d*\n", &xi, &yi, &d) != 3) continue; x = KU2MM(xi); y = KU2MM(yi); switch (d) { case 1: if (!path) { path = path_new(r_tool_default, name); *anchor = path; anchor = &path->next; path_add(path, start_x, start_y, 0); } path_add(path, x, y, 0); break; case 2: path = NULL; start_x = x; start_y = y; break; default: fprintf(stderr, "don't recognize D%d\n", d); exit(1); } } fclose(file); return path_connect(paths); }