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