Convert all apertures and macros to inches during parsing, completing the storage...
[geda-gerbv.git] / src / export-rs274x.c
blobaa9c9eb03a04ebc30050f2c4bbb4e4c55f978760
1 /*
2 * gEDA - GNU Electronic Design Automation
3 * This file is a part of gerbv.
5 * Copyright (C) 2008 Julian Lamb
7 * $Id$
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111 USA
24 #ifdef HAVE_CONFIG_H
25 #include "config.h"
26 #endif
28 #include <glib.h>
29 #include <math.h>
31 #include <glib/gstdio.h>
32 #include "gerber.h"
33 #include <export-rs274x.h>
34 #include "draw-gdk.h"
36 /* DEBUG printing. #define DEBUG 1 in config.h to use this fcn. */
37 #define dprintf if(DEBUG) printf
38 #define round(x) floor(x+0.5)
40 void
41 export_rs274x_write_macro (FILE *fd, gerb_aperture_t *currentAperture,
42 gint apertureNumber) {
43 gerb_simplified_amacro_t *ls = currentAperture->simplified;
45 /* write the macro portion first */
46 fprintf(fd, "%%AMMACRO%d*\n",apertureNumber);
47 while (ls != NULL) {
48 if (ls->type == MACRO_CIRCLE) {
49 fprintf(fd, "1,%d,%f,%f,%f*\n",(int) ls->parameter[CIRCLE_EXPOSURE],
50 ls->parameter[CIRCLE_DIAMETER],ls->parameter[CIRCLE_CENTER_X],
51 ls->parameter[CIRCLE_CENTER_Y]);
53 else if (ls->type == MACRO_OUTLINE) {
54 int pointCounter;
55 int numberOfPoints = (int) ls->parameter[OUTLINE_NUMBER_OF_POINTS];
57 fprintf(fd, "4,%d,%d,\n",(int) ls->parameter[OUTLINE_EXPOSURE],
58 numberOfPoints);
60 for (pointCounter=0; pointCounter < numberOfPoints; pointCounter++) {
61 fprintf(fd, "%f,%f,",ls->parameter[pointCounter * 2 + OUTLINE_FIRST_X],
62 ls->parameter[pointCounter * 2 + OUTLINE_FIRST_Y]);
64 fprintf(fd, "%f*\n",ls->parameter[pointCounter * 2 + OUTLINE_FIRST_X]);
66 else if (ls->type == MACRO_POLYGON) {
67 fprintf(fd, "5,%d,%d,%f,%f,%f,%f*\n",(int) ls->parameter[POLYGON_EXPOSURE],
68 (int) ls->parameter[POLYGON_NUMBER_OF_POINTS],
69 ls->parameter[POLYGON_CENTER_X],ls->parameter[POLYGON_CENTER_Y],
70 ls->parameter[POLYGON_DIAMETER],ls->parameter[POLYGON_ROTATION]);
72 else if (ls->type == MACRO_MOIRE) {
73 fprintf(fd, "6,%f,%f,%f,%f,%f,%d,%f,%f,%f*\n",ls->parameter[MOIRE_CENTER_X],
74 ls->parameter[MOIRE_CENTER_Y],ls->parameter[MOIRE_OUTSIDE_DIAMETER],
75 ls->parameter[MOIRE_CIRCLE_THICKNESS],ls->parameter[MOIRE_GAP_WIDTH],
76 (int) ls->parameter[MOIRE_NUMBER_OF_CIRCLES],ls->parameter[MOIRE_CROSSHAIR_THICKNESS],
77 ls->parameter[MOIRE_CROSSHAIR_LENGTH],ls->parameter[MOIRE_ROTATION]);
79 else if (ls->type == MACRO_THERMAL) {
80 fprintf(fd, "7,%f,%f,%f,%f,%f,%f*\n",ls->parameter[THERMAL_CENTER_X],
81 ls->parameter[THERMAL_CENTER_Y],ls->parameter[THERMAL_OUTSIDE_DIAMETER],
82 ls->parameter[THERMAL_INSIDE_DIAMETER],ls->parameter[THERMAL_CROSSHAIR_THICKNESS],
83 ls->parameter[THERMAL_ROTATION]);
85 else if (ls->type == MACRO_LINE20) {
86 fprintf(fd, "20,%d,%f,%f,%f,%f,%f,%f*\n",(int) ls->parameter[LINE20_EXPOSURE],
87 ls->parameter[LINE20_LINE_WIDTH],ls->parameter[LINE20_START_X],
88 ls->parameter[LINE20_START_Y],ls->parameter[LINE20_END_X],
89 ls->parameter[LINE20_END_Y],ls->parameter[LINE20_ROTATION]);
91 else if (ls->type == MACRO_LINE21) {
92 fprintf(fd, "21,%d,%f,%f,%f,%f,%f*\n",(int) ls->parameter[LINE21_EXPOSURE],
93 ls->parameter[LINE21_WIDTH],ls->parameter[LINE21_HEIGHT],
94 ls->parameter[LINE21_CENTER_X],ls->parameter[LINE21_CENTER_Y],
95 ls->parameter[LINE21_ROTATION]);
97 else if (ls->type == MACRO_LINE22) {
98 fprintf(fd, "22,%d,%f,%f,%f,%f,%f*\n",(int) ls->parameter[LINE22_EXPOSURE],
99 ls->parameter[LINE22_WIDTH],ls->parameter[LINE22_HEIGHT],
100 ls->parameter[LINE22_LOWER_LEFT_X],ls->parameter[LINE22_LOWER_LEFT_Y],
101 ls->parameter[LINE22_ROTATION]);
103 ls = ls->next;
105 fprintf(fd, "%%\n");
106 /* and finally create an aperture definition to use the macro */
107 fprintf(fd, "%%ADD%dMACRO%d*%%\n",apertureNumber,apertureNumber);
110 void
111 export_rs274x_write_apertures (FILE *fd, gerb_image_t *image) {
112 gerb_aperture_t *currentAperture;
113 gint numberOfRequiredParameters=0,numberOfOptionalParameters=0,i,j;
115 for (i=APERTURE_MIN; i<APERTURE_MAX; i++) {
116 gboolean writeAperture=TRUE;
118 currentAperture = image->aperture[i];
120 if (!currentAperture)
121 continue;
123 switch (currentAperture->type) {
124 case CIRCLE:
125 fprintf(fd, "%%ADD%d",i);
126 fprintf(fd, "C,");
127 numberOfRequiredParameters = 1;
128 numberOfOptionalParameters = 2;
129 break;
130 case RECTANGLE:
131 fprintf(fd, "%%ADD%d",i);
132 fprintf(fd, "R,");
133 numberOfRequiredParameters = 2;
134 numberOfOptionalParameters = 2;
135 break;
136 case OVAL:
137 fprintf(fd, "%%ADD%d",i);
138 fprintf(fd, "O,");
139 numberOfRequiredParameters = 2;
140 numberOfOptionalParameters = 2;
141 break;
142 case POLYGON:
143 fprintf(fd, "%%ADD%d",i);
144 fprintf(fd, "P,");
145 numberOfRequiredParameters = 2;
146 numberOfOptionalParameters = 3;
147 break;
148 case MACRO:
149 export_rs274x_write_macro (fd, currentAperture, i);
150 writeAperture=FALSE;
151 break;
152 default:
153 writeAperture=FALSE;
154 break;
156 if (writeAperture) {
157 /* write the parameter list */
158 for (j=0; j<(numberOfRequiredParameters + numberOfOptionalParameters); j++) {
159 if ((j < numberOfRequiredParameters) || (currentAperture->parameter[j] != 0)) {
160 /* print the "X" character to separate the parameters */
161 if (j>0)
162 fprintf(fd, "X");
163 fprintf(fd, "%.4f",currentAperture->parameter[j]);
166 fprintf(fd, "*%%\n");
171 void
172 export_rs274x_write_layer_change (gerb_layer_t *oldLayer, gerb_layer_t *newLayer, FILE *fd) {
173 if (oldLayer->polarity != newLayer->polarity) {
174 /* polarity changed */
175 if ((newLayer->polarity == CLEAR))
176 fprintf(fd, "%%LPC*%%\n");
177 else
178 fprintf(fd, "%%LPD*%%\n");
182 void
183 export_rs274x_write_state_change (gerb_netstate_t *oldState, gerb_netstate_t *newState, FILE *fd) {
188 gboolean
189 export_rs274x_file_from_image (gchar *filename, gerb_image_t *image) {
190 FILE *fd;
191 gerb_netstate_t *oldState;
192 gerb_layer_t *oldLayer;
194 if ((fd = g_fopen(filename, "w")) == NULL) {
195 GERB_MESSAGE("Can't open file for writing: %s\n", filename);
196 return FALSE;
198 /* write header info */
199 fprintf(fd, "G04 Exported by Gerber Viewer version %s*\n",VERSION);
200 fprintf(fd, "G04 --Header info--*\n");
201 fprintf(fd, "%%MOIN*%%\n");
202 fprintf(fd, "%%FSLAX23Y23*%%\n");
204 /* check the image info struct for any non-default settings */
205 /* image offset */
206 if ((image->info->offsetA > 0.0) || (image->info->offsetB > 0.0))
207 fprintf(fd, "%%IOA%fB%f*%%\n",image->info->offsetA,image->info->offsetB);
208 /* image polarity */
209 if (image->info->polarity == CLEAR)
210 fprintf(fd, "%%IPNEG*%%\n");
211 else
212 fprintf(fd, "%%IPPOS*%%\n");
213 /* image name */
214 if (image->info->name)
215 fprintf(fd, "%%IN%s*%%\n",image->info->name);
216 /* plotter film */
217 if (image->info->plotterFilm)
218 fprintf(fd, "%%PF%s*%%\n",image->info->plotterFilm);
219 /* image rotation */
220 if (image->info->imageRotation != 0.0)
221 fprintf(fd, "%%IR%d*%%\n",(int) image->info->imageRotation);
222 if ((image->info->imageJustifyTypeA != NOJUSTIFY) ||
223 (image->info->imageJustifyTypeB != NOJUSTIFY)) {
224 fprintf(fd, "%%IJA");
225 if (image->info->imageJustifyTypeA == CENTERJUSTIFY)
226 fprintf(fd, "C");
227 else
228 fprintf(fd, "%.4f",image->info->imageJustifyOffsetA);
229 fprintf(fd, "B");
230 if (image->info->imageJustifyTypeB == CENTERJUSTIFY)
231 fprintf(fd, "C");
232 else
233 fprintf(fd, "%.4f",image->info->imageJustifyOffsetB);
234 fprintf(fd, "*%%\n");
237 /* define all apertures */
238 fprintf(fd, "G04 --Define apertures--*\n");
239 export_rs274x_write_apertures (fd, image);
241 /* write rest of image */
242 fprintf(fd, "G04 --Start main section--*\n");
243 gint currentAperture = 0;
244 gerb_net_t *currentNet;
246 oldLayer = image->layers;
247 oldState = image->states;
248 for (currentNet = image->netlist; currentNet; currentNet = currentNet->next){
249 /* check for "layer" changes (RS274X commands) */
250 if (currentNet->layer != oldLayer)
251 export_rs274x_write_layer_change (oldLayer, currentNet->layer, fd);
253 /* check for new "netstate" (more RS274X commands) */
254 if (currentNet->state != oldState)
255 export_rs274x_write_state_change (oldState, currentNet->state, fd);
257 /* check for tool changes */
258 /* also, make sure the aperture number is a valid one, since sometimes
259 the loaded file may refer to invalid apertures */
260 if ((currentNet->aperture != currentAperture)&&
261 (image->aperture[currentNet->aperture] != NULL)) {
262 fprintf(fd, "G54D%02d*\n",currentNet->aperture);
263 currentAperture = currentNet->aperture;
266 oldLayer = currentNet->layer;
267 oldState = currentNet->state;
269 long xVal,yVal,endX,endY,centerX,centerY;;
270 switch (currentNet->interpolation) {
271 case LINEARx10 :
272 case LINEARx01 :
273 case LINEARx001 :
274 case LINEARx1 :
275 xVal = (long) round(currentNet->stop_x * 1000.0);
276 yVal = (long) round(currentNet->stop_y * 1000.0);
277 fprintf(fd, "G01X%05ldY%05ld",xVal,yVal);
278 /* and finally, write the esposure value */
279 if (currentNet->aperture_state == OFF)
280 fprintf(fd, "D02*\n");
281 else if (currentNet->aperture_state == ON)
282 fprintf(fd, "D01*\n");
283 else
284 fprintf(fd, "D03*\n");
285 break;
286 case CW_CIRCULAR :
287 case CCW_CIRCULAR :
288 centerX= (long) round((currentNet->cirseg->cp_x - currentNet->start_x) * 1000.0);
289 centerY= (long) round((currentNet->cirseg->cp_y - currentNet->start_y) * 1000.0);
290 endX = (long) round(currentNet->stop_x * 1000.0);
291 endY = (long) round(currentNet->stop_y * 1000.0);
293 /* always use multi-quadrant, since it's much easier to export */
294 /* and most all software should support it */
295 fprintf(fd, "G75*\n");
296 /* figure out clockwise or c-clockwise */
297 if (currentNet->cirseg->angle2 > currentNet->cirseg->angle1)
298 fprintf(fd, "G03");
299 else
300 fprintf(fd, "G02");
301 /* don't write the I and J values if the exposure is off */
302 if (currentNet->aperture_state == ON)
303 fprintf(fd, "X%05ldY%05ldI%05ldJ%05ld",endX,endY,centerX,centerY);
304 else
305 fprintf(fd, "X%05ldY%05ld",endX,endY);
306 /* and finally, write the esposure value */
307 if (currentNet->aperture_state == OFF)
308 fprintf(fd, "D02*\n");
309 else if (currentNet->aperture_state == ON)
310 fprintf(fd, "D01*\n");
311 else
312 fprintf(fd, "D03*\n");
313 break;
314 case PAREA_START:
315 fprintf(fd, "G36*\n");
316 break;
317 case PAREA_END:
318 fprintf(fd, "G37*\n");
319 break;
320 default:
321 break;
325 /* write footer */
326 fprintf(fd, "G04 --Footer info--*\n");
327 fprintf(fd, "M02*\n");
329 fclose(fd);
330 return TRUE;