gerbv  2.6A
export-rs274x.c
Go to the documentation of this file.
1 /*
2  * gEDA - GNU Electronic Design Automation
3  * This file is a part of gerbv.
4  *
5  * Copyright (C) 2008 Julian Lamb
6  *
7  * $Id$
8  *
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.
13  *
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.
18  *
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
22  */
23 
30 #include "gerbv.h"
31 
32 #include <math.h>
33 #include <locale.h>
34 #include <glib/gstdio.h>
35 
36 #include "common.h"
37 #include "draw-gdk.h"
38 
39 #define dprintf if(DEBUG) printf
40 
41 #define round(x) floor(x+0.5)
42 
43 void
44 export_rs274x_write_macro (FILE *fd, gerbv_aperture_t *currentAperture,
45  gint apertureNumber) {
46  gerbv_simplified_amacro_t *ls = currentAperture->simplified;
47 
48  /* write the macro portion first */
49  fprintf(fd, "%%AMMACRO%d*\n",apertureNumber);
50  while (ls != NULL) {
51  if (ls->type == GERBV_APTYPE_MACRO_CIRCLE) {
52  fprintf(fd, "1,%d,%f,%f,%f*\n",(int) ls->parameter[CIRCLE_EXPOSURE],
53  ls->parameter[CIRCLE_DIAMETER],ls->parameter[CIRCLE_CENTER_X],
54  ls->parameter[CIRCLE_CENTER_Y]);
55  }
56  else if (ls->type == GERBV_APTYPE_MACRO_OUTLINE) {
57  int pointCounter;
58  int numberOfPoints = (int) ls->parameter[OUTLINE_NUMBER_OF_POINTS];
59 
60  fprintf(fd, "4,%d,%d,\n",(int) ls->parameter[OUTLINE_EXPOSURE],
61  numberOfPoints);
62  /* add 1 point for the starting point here */
63  for (pointCounter=0; pointCounter <= numberOfPoints; pointCounter++) {
64  fprintf(fd, "%f,%f,",ls->parameter[pointCounter * 2 + OUTLINE_FIRST_X],
65  ls->parameter[pointCounter * 2 + OUTLINE_FIRST_Y]);
66  }
67  fprintf(fd, "%f*\n",ls->parameter[pointCounter * 2 + OUTLINE_FIRST_X]);
68  }
69  else if (ls->type == GERBV_APTYPE_MACRO_POLYGON) {
70  fprintf(fd, "5,%d,%d,%f,%f,%f,%f*\n",(int) ls->parameter[POLYGON_EXPOSURE],
71  (int) ls->parameter[POLYGON_NUMBER_OF_POINTS],
72  ls->parameter[POLYGON_CENTER_X],ls->parameter[POLYGON_CENTER_Y],
73  ls->parameter[POLYGON_DIAMETER],ls->parameter[POLYGON_ROTATION]);
74  }
75  else if (ls->type == GERBV_APTYPE_MACRO_MOIRE) {
76  fprintf(fd, "6,%f,%f,%f,%f,%f,%d,%f,%f,%f*\n",ls->parameter[MOIRE_CENTER_X],
77  ls->parameter[MOIRE_CENTER_Y],ls->parameter[MOIRE_OUTSIDE_DIAMETER],
78  ls->parameter[MOIRE_CIRCLE_THICKNESS],ls->parameter[MOIRE_GAP_WIDTH],
79  (int) ls->parameter[MOIRE_NUMBER_OF_CIRCLES],ls->parameter[MOIRE_CROSSHAIR_THICKNESS],
80  ls->parameter[MOIRE_CROSSHAIR_LENGTH],ls->parameter[MOIRE_ROTATION]);
81  }
82  else if (ls->type == GERBV_APTYPE_MACRO_THERMAL) {
83  fprintf(fd, "7,%f,%f,%f,%f,%f,%f*\n",ls->parameter[THERMAL_CENTER_X],
84  ls->parameter[THERMAL_CENTER_Y],ls->parameter[THERMAL_OUTSIDE_DIAMETER],
85  ls->parameter[THERMAL_INSIDE_DIAMETER],ls->parameter[THERMAL_CROSSHAIR_THICKNESS],
86  ls->parameter[THERMAL_ROTATION]);
87  }
88  else if (ls->type == GERBV_APTYPE_MACRO_LINE20) {
89  fprintf(fd, "20,%d,%f,%f,%f,%f,%f,%f*\n",(int) ls->parameter[LINE20_EXPOSURE],
90  ls->parameter[LINE20_LINE_WIDTH],ls->parameter[LINE20_START_X],
91  ls->parameter[LINE20_START_Y],ls->parameter[LINE20_END_X],
92  ls->parameter[LINE20_END_Y],ls->parameter[LINE20_ROTATION]);
93  }
94  else if (ls->type == GERBV_APTYPE_MACRO_LINE21) {
95  fprintf(fd, "21,%d,%f,%f,%f,%f,%f*\n",(int) ls->parameter[LINE21_EXPOSURE],
96  ls->parameter[LINE21_WIDTH],ls->parameter[LINE21_HEIGHT],
97  ls->parameter[LINE21_CENTER_X],ls->parameter[LINE21_CENTER_Y],
98  ls->parameter[LINE21_ROTATION]);
99  }
100  else if (ls->type == GERBV_APTYPE_MACRO_LINE22) {
101  fprintf(fd, "22,%d,%f,%f,%f,%f,%f*\n",(int) ls->parameter[LINE22_EXPOSURE],
102  ls->parameter[LINE22_WIDTH],ls->parameter[LINE22_HEIGHT],
103  ls->parameter[LINE22_LOWER_LEFT_X],ls->parameter[LINE22_LOWER_LEFT_Y],
104  ls->parameter[LINE22_ROTATION]);
105  }
106  ls = ls->next;
107  }
108  fprintf(fd, "%%\n");
109  /* and finally create an aperture definition to use the macro */
110  fprintf(fd, "%%ADD%dMACRO%d*%%\n",apertureNumber,apertureNumber);
111 }
112 
113 void
114 export_rs274x_write_apertures (FILE *fd, gerbv_image_t *image) {
115  gerbv_aperture_t *currentAperture;
116  gint numberOfRequiredParameters=0,numberOfOptionalParameters=0,i,j;
117 
118  /* the image should already have been cleaned by a duplicate_image call, so we can safely
119  assume the aperture range is correct */
120  for (i=APERTURE_MIN; i<APERTURE_MAX; i++) {
121  gboolean writeAperture=TRUE;
122 
123  currentAperture = image->aperture[i];
124 
125  if (!currentAperture)
126  continue;
127 
128  switch (currentAperture->type) {
129  case GERBV_APTYPE_CIRCLE:
130  fprintf(fd, "%%ADD%d",i);
131  fprintf(fd, "C,");
132  numberOfRequiredParameters = 1;
133  numberOfOptionalParameters = 2;
134  break;
136  fprintf(fd, "%%ADD%d",i);
137  fprintf(fd, "R,");
138  numberOfRequiredParameters = 2;
139  numberOfOptionalParameters = 2;
140  break;
141  case GERBV_APTYPE_OVAL:
142  fprintf(fd, "%%ADD%d",i);
143  fprintf(fd, "O,");
144  numberOfRequiredParameters = 2;
145  numberOfOptionalParameters = 2;
146  break;
148  fprintf(fd, "%%ADD%d",i);
149  fprintf(fd, "P,");
150  numberOfRequiredParameters = 2;
151  numberOfOptionalParameters = 3;
152  break;
153  case GERBV_APTYPE_MACRO:
154  export_rs274x_write_macro (fd, currentAperture, i);
155  writeAperture=FALSE;
156  break;
157  default:
158  writeAperture=FALSE;
159  break;
160  }
161  if (writeAperture) {
162  /* write the parameter list */
163  for (j=0; j<(numberOfRequiredParameters + numberOfOptionalParameters); j++) {
164  if ((j < numberOfRequiredParameters) || (currentAperture->parameter[j] != 0)) {
165  /* print the "X" character to separate the parameters */
166  if (j>0)
167  fprintf(fd, "X");
168  fprintf(fd, "%.4f",currentAperture->parameter[j]);
169  }
170  }
171  fprintf(fd, "*%%\n");
172  }
173  }
174 }
175 
176 void
177 export_rs274x_write_layer_change (gerbv_layer_t *oldLayer, gerbv_layer_t *newLayer, FILE *fd) {
178  if (oldLayer->polarity != newLayer->polarity) {
179  /* polarity changed */
180  if ((newLayer->polarity == GERBV_POLARITY_CLEAR))
181  fprintf(fd, "%%LPC*%%\n");
182  else
183  fprintf(fd, "%%LPD*%%\n");
184  }
185 }
186 
187 void
188 export_rs274x_write_state_change (gerbv_netstate_t *oldState, gerbv_netstate_t *newState, FILE *fd) {
189 
190 
191 }
192 
193 gboolean
195  gerbv_user_transformation_t *transform) {
196  FILE *fd;
197  gerbv_netstate_t *oldState;
198  gerbv_layer_t *oldLayer;
199  gboolean insidePolygon=FALSE;
200  gerbv_user_transformation_t *thisTransform;
201 
202  // force gerbv to output decimals as dots (not commas for other locales)
203  setlocale(LC_NUMERIC, "C");
204 
205  if (transform != NULL) {
206  thisTransform = transform;
207  }
208  else {
209  gerbv_user_transformation_t identityTransform = {0,0,1,1,0,FALSE,FALSE,FALSE};
210  thisTransform = &identityTransform;
211  }
212  if ((fd = g_fopen(filename, "w")) == NULL) {
213  GERB_MESSAGE(_("Can't open file for writing: %s"), filename);
214  return FALSE;
215  }
216 
217  /* duplicate the image, cleaning it in the process */
218  gerbv_image_t *image = gerbv_image_duplicate_image (inputImage, thisTransform);
219 
220  /* write header info */
221  fprintf(fd, "G04 This is an RS-274x file exported by *\n");
222  fprintf(fd, "G04 gerbv version %s *\n",VERSION);
223  fprintf(fd, "G04 More information is available about gerbv at *\n");
224  fprintf(fd, "G04 http://gerbv.geda-project.org/ *\n");
225  fprintf(fd, "G04 --End of header info--*\n");
226  fprintf(fd, "%%MOIN*%%\n");
227  fprintf(fd, "%%FSLAX34Y34*%%\n");
228 
229  /* check the image info struct for any non-default settings */
230  /* image offset */
231  if ((image->info->offsetA > 0.0) || (image->info->offsetB > 0.0))
232  fprintf(fd, "%%IOA%fB%f*%%\n",image->info->offsetA,image->info->offsetB);
233  /* image polarity */
234  if (image->info->polarity == GERBV_POLARITY_CLEAR)
235  fprintf(fd, "%%IPNEG*%%\n");
236  else
237  fprintf(fd, "%%IPPOS*%%\n");
238  /* image name */
239  if (image->info->name)
240  fprintf(fd, "%%IN%s*%%\n",image->info->name);
241  /* plotter film */
242  if (image->info->plotterFilm)
243  fprintf(fd, "%%PF%s*%%\n",image->info->plotterFilm);
244  /* image rotation */
245  if ((image->info->imageRotation != 0.0)||(thisTransform->rotation != 0.0))
246  fprintf(fd, "%%IR%d*%%\n",(int) ((image->info->imageRotation + thisTransform->rotation)*180/M_PI)%360);
247  if ((image->info->imageJustifyTypeA != GERBV_JUSTIFY_NOJUSTIFY) ||
248  (image->info->imageJustifyTypeB != GERBV_JUSTIFY_NOJUSTIFY)) {
249  fprintf(fd, "%%IJA");
250  if (image->info->imageJustifyTypeA == GERBV_JUSTIFY_CENTERJUSTIFY)
251  fprintf(fd, "C");
252  else
253  fprintf(fd, "%.4f",image->info->imageJustifyOffsetA);
254  fprintf(fd, "B");
255  if (image->info->imageJustifyTypeB == GERBV_JUSTIFY_CENTERJUSTIFY)
256  fprintf(fd, "C");
257  else
258  fprintf(fd, "%.4f",image->info->imageJustifyOffsetB);
259  fprintf(fd, "*%%\n");
260 
261  }
262  /* handle scale user orientation transforms */
263  if ((fabs(thisTransform->scaleX - 1) > 0.00001) ||
264  (fabs(thisTransform->scaleY - 1) > 0.00001)) {
265  fprintf(fd, "%%SFA%.4fB%.4f*%%\n",thisTransform->scaleX,thisTransform->scaleY);
266  }
267  /* handle mirror image user orientation transform */
268  if ((thisTransform->mirrorAroundX)||(thisTransform->mirrorAroundY)) {
269  fprintf(fd, "%%MIA%dB%d*%%\n",thisTransform->mirrorAroundY,thisTransform->mirrorAroundX);
270  }
271 
272  /* define all apertures */
273  fprintf(fd, "G04 --Define apertures--*\n");
274  export_rs274x_write_apertures (fd, image);
275 
276  /* write rest of image */
277  fprintf(fd, "G04 --Start main section--*\n");
278  gint currentAperture = 0;
279  gerbv_net_t *currentNet;
280 
281  oldLayer = image->layers;
282  oldState = image->states;
283  /* skip the first net, since it's always zero due to the way we parse things */
284  for (currentNet = image->netlist->next; currentNet; currentNet = currentNet->next){
285  /* check for "layer" changes (RS274X commands) */
286  if (currentNet->layer != oldLayer)
287  export_rs274x_write_layer_change (oldLayer, currentNet->layer, fd);
288 
289  /* check for new "netstate" (more RS274X commands) */
290  if (currentNet->state != oldState)
291  export_rs274x_write_state_change (oldState, currentNet->state, fd);
292 
293  /* check for tool changes */
294  /* also, make sure the aperture number is a valid one, since sometimes
295  the loaded file may refer to invalid apertures */
296  if ((currentNet->aperture != currentAperture)&&
297  (image->aperture[currentNet->aperture] != NULL)) {
298  fprintf(fd, "G54D%02d*\n",currentNet->aperture);
299  currentAperture = currentNet->aperture;
300  }
301 
302  oldLayer = currentNet->layer;
303  oldState = currentNet->state;
304 
305  long xVal,yVal,endX,endY,centerX,centerY;
306  switch (currentNet->interpolation) {
311  /* see if we need to write an "aperture off" line to get
312  the pen to the right start point */
313  if ((!insidePolygon) && (currentNet->aperture_state == GERBV_APERTURE_STATE_ON)) {
314  xVal = (long) round(currentNet->start_x * 10000.0);
315  yVal = (long) round(currentNet->start_y * 10000.0);
316  fprintf(fd, "G01X%07ldY%07ldD02*\n",xVal,yVal);
317  }
318  xVal = (long) round(currentNet->stop_x * 10000.0);
319  yVal = (long) round(currentNet->stop_y * 10000.0);
320  fprintf(fd, "G01X%07ldY%07ld",xVal,yVal);
321  /* and finally, write the esposure value */
322  if (currentNet->aperture_state == GERBV_APERTURE_STATE_OFF)
323  fprintf(fd, "D02*\n");
324  else if (currentNet->aperture_state == GERBV_APERTURE_STATE_ON)
325  fprintf(fd, "D01*\n");
326  else
327  fprintf(fd, "D03*\n");
328  break;
331  /* see if we need to write an "aperture off" line to get
332  the pen to the right start point */
333  if ((!insidePolygon) && (currentNet->aperture_state == GERBV_APERTURE_STATE_ON)) {
334  xVal = (long) round(currentNet->start_x * 10000.0);
335  yVal = (long) round(currentNet->start_y * 10000.0);
336  fprintf(fd, "G01X%07ldY%07ldD02*\n",xVal,yVal);
337  }
338  centerX= (long) round((currentNet->cirseg->cp_x - currentNet->start_x) * 10000.0);
339  centerY= (long) round((currentNet->cirseg->cp_y - currentNet->start_y) * 10000.0);
340  endX = (long) round(currentNet->stop_x * 10000.0);
341  endY = (long) round(currentNet->stop_y * 10000.0);
342 
343  /* always use multi-quadrant, since it's much easier to export */
344  /* and most all software should support it */
345  fprintf(fd, "G75*\n");
346  /* figure out clockwise or c-clockwise */
347  if (currentNet->cirseg->angle2 > currentNet->cirseg->angle1)
348  fprintf(fd, "G03");
349  else
350  fprintf(fd, "G02");
351  /* don't write the I and J values if the exposure is off */
352  if (currentNet->aperture_state == GERBV_APERTURE_STATE_ON)
353  fprintf(fd, "X%07ldY%07ldI%07ldJ%07ld",endX,endY,centerX,centerY);
354  else
355  fprintf(fd, "X%07ldY%07ld",endX,endY);
356  /* and finally, write the esposure value */
357  if (currentNet->aperture_state == GERBV_APERTURE_STATE_OFF)
358  fprintf(fd, "D02*\n");
359  else if (currentNet->aperture_state == GERBV_APERTURE_STATE_ON)
360  fprintf(fd, "D01*\n");
361  else
362  fprintf(fd, "D03*\n");
363  break;
365  fprintf(fd, "G36*\n");
366  insidePolygon = TRUE;
367  break;
369  fprintf(fd, "G37*\n");
370  insidePolygon = FALSE;
371  break;
372  default:
373  break;
374  }
375  }
376 
377  fprintf(fd, "M02*\n");
378 
379  gerbv_destroy_image (image);
380  fclose(fd);
381 
382  // return to the default locale
383  setlocale(LC_NUMERIC, "");
384  return TRUE;
385 }