2 * gEDA - GNU Electronic Design Automation
3 * This file is a part of gerbv.
5 * Copyright (C) 2008 Julian Lamb
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
31 #include <glib/gstdio.h>
33 #include <export-rs274x.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)
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
);
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
) {
55 int numberOfPoints
= (int) ls
->parameter
[OUTLINE_NUMBER_OF_POINTS
];
57 fprintf(fd
, "4,%d,%d,\n",(int) ls
->parameter
[OUTLINE_EXPOSURE
],
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
]);
106 /* and finally create an aperture definition to use the macro */
107 fprintf(fd
, "%%ADD%dMACRO%d*%%\n",apertureNumber
,apertureNumber
);
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
)
123 switch (currentAperture
->type
) {
125 fprintf(fd
, "%%ADD%d",i
);
127 numberOfRequiredParameters
= 1;
128 numberOfOptionalParameters
= 2;
131 fprintf(fd
, "%%ADD%d",i
);
133 numberOfRequiredParameters
= 2;
134 numberOfOptionalParameters
= 2;
137 fprintf(fd
, "%%ADD%d",i
);
139 numberOfRequiredParameters
= 2;
140 numberOfOptionalParameters
= 2;
143 fprintf(fd
, "%%ADD%d",i
);
145 numberOfRequiredParameters
= 2;
146 numberOfOptionalParameters
= 3;
149 export_rs274x_write_macro (fd
, currentAperture
, i
);
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 */
163 fprintf(fd
, "%.4f",currentAperture
->parameter
[j
]);
166 fprintf(fd
, "*%%\n");
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");
178 fprintf(fd
, "%%LPD*%%\n");
183 export_rs274x_write_state_change (gerb_netstate_t
*oldState
, gerb_netstate_t
*newState
, FILE *fd
) {
189 export_rs274x_file_from_image (gchar
*filename
, gerb_image_t
*image
) {
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
);
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 */
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
);
209 if (image
->info
->polarity
== CLEAR
)
210 fprintf(fd
, "%%IPNEG*%%\n");
212 fprintf(fd
, "%%IPPOS*%%\n");
214 if (image
->info
->name
)
215 fprintf(fd
, "%%IN%s*%%\n",image
->info
->name
);
217 if (image
->info
->plotterFilm
)
218 fprintf(fd
, "%%PF%s*%%\n",image
->info
->plotterFilm
);
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
)
228 fprintf(fd
, "%.4f",image
->info
->imageJustifyOffsetA
);
230 if (image
->info
->imageJustifyTypeB
== CENTERJUSTIFY
)
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
) {
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");
284 fprintf(fd
, "D03*\n");
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
)
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
);
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");
312 fprintf(fd
, "D03*\n");
315 fprintf(fd
, "G36*\n");
318 fprintf(fd
, "G37*\n");
326 fprintf(fd
, "G04 --Footer info--*\n");
327 fprintf(fd
, "M02*\n");