gerbv
gerb_image.c
Go to the documentation of this file.
1 /*
2  * gEDA - GNU Electronic Design Automation
3  * This files is a part of gerbv.
4  *
5  * Copyright (C) 2000-2003 Stefan Petersen (spe@stacken.kth.se)
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 <stdlib.h>
32 #include <string.h>
33 #include <math.h>
34 
35 #include "common.h"
36 #include "gerb_image.h"
37 #include "gerber.h"
38 #include "amacro.h"
39 
40 typedef struct {
41  int oldAperture;
42  int newAperture;
43 } gerb_translation_entry_t;
44 
46 gerbv_create_image(gerbv_image_t *image, const gchar *type)
47 {
48  gerbv_destroy_image(image);
49 
50  /* Malloc space for image */
51  if (NULL == (image = g_new0(gerbv_image_t, 1))) {
52  return NULL;
53  }
54 
55  /* Malloc space for image->netlist */
56  if (NULL == (image->netlist = g_new0(gerbv_net_t, 1))) {
57  g_free(image);
58  return NULL;
59  }
60 
61  /* Malloc space for image->info */
62  if (NULL == (image->info = g_new0(gerbv_image_info_t, 1))) {
63  g_free(image->netlist);
64  g_free(image);
65  return NULL;
66  }
67 
68  /* Set aside position for stats struct */
69  image->gerbv_stats = NULL;
70  image->drill_stats = NULL;
71 
72  image->info->min_x = HUGE_VAL;
73  image->info->min_y = HUGE_VAL;
74  image->info->max_x = -HUGE_VAL;
75  image->info->max_y = -HUGE_VAL;
76 
77  /* create our first layer and fill with non-zero default values */
78  image->layers = g_new0 (gerbv_layer_t, 1);
79  image->layers->stepAndRepeat.X = 1;
80  image->layers->stepAndRepeat.Y = 1;
82 
83  /* create our first netstate and fill with non-zero default values */
84  image->states = g_new0 (gerbv_netstate_t, 1);
85  image->states->scaleA = 1;
86  image->states->scaleB = 1;
87 
88  /* fill in some values for our first net */
89  image->netlist->layer = image->layers;
90  image->netlist->state = image->states;
91 
92  if (type == NULL)
93  image->info->type = g_strdup (_("unknown"));
94  else
95  image->info->type = g_strdup (type);
96 
97  /* the individual file parsers will have to set this. */
98  image->info->attr_list = NULL;
99  image->info->n_attr = 0;
100 
101  return image;
102 }
103 
104 
105 void
107 {
108  int i;
109  gerbv_net_t *net, *tmp;
110  gerbv_layer_t *layer;
111  gerbv_netstate_t *state;
112  gerbv_simplified_amacro_t *sam,*sam2;
113 
114  if(image==NULL)
115  return;
116 
117  /*
118  * Free apertures
119  */
120  for (i = 0; i < APERTURE_MAX; i++)
121  if (image->aperture[i] != NULL) {
122  for (sam = image->aperture[i]->simplified; sam != NULL; ){
123  sam2 = sam->next;
124  g_free (sam);
125  sam = sam2;
126  }
127  /* Free block aperture net list */
128  if (image->aperture[i]->type == GERBV_APTYPE_BLOCK) {
129  gerbv_net_t *bnet = image->aperture[i]->block_netlist;
130  while (bnet != NULL) {
131  gerbv_net_t *bnext = bnet->next;
132  if (bnet->cirseg)
133  g_free (bnet->cirseg);
134  if (bnet->label)
135  g_string_free (bnet->label, TRUE);
136  g_free (bnet);
137  bnet = bnext;
138  }
139  }
140 
141  g_free(image->aperture[i]);
142  image->aperture[i] = NULL;
143  }
144 
145  /*
146  * Free aperture macro
147  */
148 
149  if (image->amacro) {
150  free_amacro(image->amacro);
151  }
152 
153  /*
154  * Free format
155  */
156  if (image->format)
157  g_free(image->format);
158 
159  /*
160  * Free info
161  */
162  if (image->info) {
163  g_free(image->info->name);
164  g_free(image->info->type);
165  gerbv_attribute_destroy_HID_attribute (image->info->attr_list, image->info->n_attr);
166  g_free(image->info);
167  }
168 
169  /*
170  * Free netlist
171  */
172  for (net = image->netlist; net != NULL; ) {
173  tmp = net;
174  net = net->next;
175  if (tmp->cirseg != NULL) {
176  g_free(tmp->cirseg);
177  tmp->cirseg = NULL;
178  }
179  if (tmp->label) {
180  g_string_free (tmp->label, TRUE);
181  }
182  g_free(tmp);
183  tmp = NULL;
184  }
185  for (layer = image->layers; layer != NULL; ) {
186  gerbv_layer_t *tempLayer = layer;
187 
188  layer = layer->next;
189  g_free (tempLayer->name);
190  g_free (tempLayer);
191  }
192  for (state = image->states; state != NULL; ) {
193  gerbv_netstate_t *tempState = state;
194 
195  state = state->next;
196  g_free (tempState);
197  }
200 
201  /*
202  * Free and reset the final image
203  */
204  g_free(image);
205  image = NULL;
206 
207  return;
208 }
209 
210 
211 /*
212  * Check that the parsed gerber image is complete.
213  * Returned errorcodes are:
214  * 0: No problems
215  * 1: Missing netlist
216  * 2: Missing format
217  * 4: Missing apertures
218  * 8: Missing info
219  * It could be any of above or'ed together
220  */
221 gerb_verify_error_t
222 gerbv_image_verify(gerbv_image_t const* image)
223 {
224  gerb_verify_error_t error = GERB_IMAGE_OK;
225  int i;
226  gerbv_net_t *net;
227  gboolean needs_aperture = FALSE;
228  gboolean in_parea = FALSE;
229 
230  if (image->netlist == NULL) error |= GERB_IMAGE_MISSING_NETLIST;
231  if (image->format == NULL) error |= GERB_IMAGE_MISSING_FORMAT;
232  if (image->info == NULL) error |= GERB_IMAGE_MISSING_INFO;
233 
234  /* Check if any net actually requires an aperture (i.e., draws or
235  * flashes outside a polygon area fill). G36/G37 polygon fills
236  * don't need apertures, so files using only polygon fills should
237  * not trigger a missing-apertures warning. */
238  if (image->netlist != NULL) {
239  for (net = image->netlist->next ; net != NULL; net = net->next) {
241  in_parea = TRUE;
243  in_parea = FALSE;
244  else if (!in_parea &&
247  needs_aperture = TRUE;
248  }
249  }
250 
251  /* If we have nets that need apertures but none are defined, complain */
252  if (needs_aperture) {
253  for (i = 0; i < APERTURE_MAX && image->aperture[i] == NULL; i++);
254  if (i == APERTURE_MAX) error |= GERB_IMAGE_MISSING_APERTURES;
255  }
256 
257  return error;
258 } /* gerb_image_verify */
259 
260 static void
261 gerbv_image_aperture_state(gerbv_aperture_state_t state)
262 {
263  switch (state) {
265  printf(_("..state off"));
266  break;
268  printf(_("..state on"));
269  break;
271  printf(_("..state flash"));
272  break;
273  default:
274  printf(_("..state unknown"));
275  }
276 }
277 
278 /* Dumps a written version of image to stdout */
279 void
280 gerbv_image_dump(gerbv_image_t const* image)
281 {
282  int i, j;
283  gerbv_aperture_t * const* aperture;
284  gerbv_net_t const * net;
285 
286  /* Apertures */
287  printf(_("Apertures:\n"));
288  aperture = image->aperture;
289  for (i = 0; i < APERTURE_MAX; i++) {
290  if (aperture[i]) {
291  printf(_(" Aperture no:%d is an "), i);
292  switch(aperture[i]->type) {
293  case GERBV_APTYPE_CIRCLE:
294  printf(_("circle"));
295  break;
297  printf(_("rectangle"));
298  break;
299  case GERBV_APTYPE_OVAL:
300  printf(_("oval"));
301  break;
303  printf(_("polygon"));
304  break;
305  case GERBV_APTYPE_MACRO:
306  printf(_("macro"));
307  break;
308  default:
309  printf(_("unknown"));
310  }
311  for (j = 0; j < aperture[i]->nuf_parameters; j++) {
312  printf(" %f", aperture[i]->parameter[j]);
313  }
314  printf("\n");
315  }
316  }
317 
318  /* Netlist */
319  net = image->netlist;
320  while (net){
321  printf(_("(%f,%f)->(%f,%f) with %d ("), net->start_x, net->start_y,
322  net->stop_x, net->stop_y, net->aperture);
323  printf("%s", _(gerbv_interpolation_name(net->interpolation)));
324  gerbv_image_aperture_state(net->aperture_state);
325  printf(")\n");
326  net = net->next;
327  }
328 } /* gerbv_image_dump */
329 
330 
332 gerbv_image_return_new_layer (gerbv_layer_t *previousLayer)
333 {
334  gerbv_layer_t *newLayer = g_new0 (gerbv_layer_t, 1);
335 
336  *newLayer = *previousLayer;
337  previousLayer->next = newLayer;
338  /* clear this boolean so we only draw the knockout once */
339  newLayer->knockout.firstInstance = FALSE;
340  newLayer->name = NULL;
341  newLayer->next = NULL;
342 
343  return newLayer;
344 } /* gerbv_image_return_new_layer */
345 
346 
348 gerbv_image_return_new_netstate (gerbv_netstate_t *previousState)
349 {
350  gerbv_netstate_t *newState = g_new0 (gerbv_netstate_t, 1);
351 
352  *newState = *previousState;
353  previousState->next = newState;
354  /* `rotation` (LR), `mirrorState` (LM), `unit` (MO), and `axisSelect`
355  * (AS) all persist across netstate boundaries per the Gerber X2
356  * spec — they're set by the corresponding RS274X command and stay
357  * active until the next explicit command. The struct copy above
358  * propagates them correctly; do NOT reset them here.
359  *
360  * scaleA/scaleB (LS) carry a pre-existing reset that has the same
361  * spec-violating behaviour. Left alone to keep this PR scoped to
362  * the LR fix Stefan flagged — a separate change should remove the
363  * scale reset too. */
364  newState->next = NULL;
365 
366  return newState;
367 } /* gerbv_image_return_new_netstate */
368 
370 gerbv_image_duplicate_layer (gerbv_layer_t *oldLayer) {
371  gerbv_layer_t *newLayer = g_new (gerbv_layer_t,1);
372 
373  *newLayer = *oldLayer;
374  newLayer->name = g_strdup (oldLayer->name);
375  newLayer->next = NULL;
376  return newLayer;
377 }
378 
379 static gerbv_netstate_t *
380 gerbv_image_duplicate_state (gerbv_netstate_t *oldState)
381 {
382  gerbv_netstate_t *newState = g_new (gerbv_netstate_t, 1);
383 
384  *newState = *oldState;
385  newState->next = NULL;
386  return newState;
387 }
388 
389 static gerbv_aperture_t *
390 gerbv_image_duplicate_aperture (gerbv_aperture_t *oldAperture)
391 {
392  gerbv_aperture_t *newAperture = g_new0 (gerbv_aperture_t,1);
393  gerbv_simplified_amacro_t *simplifiedMacro, *tempSimplified;
394 
395  *newAperture = *oldAperture;
396 
397  /* delete the amacro section, since we really don't need it anymore
398  now that we have the simplified section */
399  newAperture->amacro = NULL;
400  newAperture->simplified = NULL;
401 
402  /* copy any simplified macros over */
403  tempSimplified = NULL;
404  for (simplifiedMacro = oldAperture->simplified; simplifiedMacro != NULL; simplifiedMacro = simplifiedMacro->next) {
405  gerbv_simplified_amacro_t *newSimplified = g_new0 (gerbv_simplified_amacro_t,1);
406  *newSimplified = *simplifiedMacro;
407  if (tempSimplified)
408  tempSimplified->next = newSimplified;
409  else
410  newAperture->simplified = newSimplified;
411  tempSimplified = newSimplified;
412  }
413  return newAperture;
414 }
415 
416 static void
417 gerbv_image_copy_all_nets (gerbv_image_t *sourceImage,
418  gerbv_image_t *destImage, gerbv_layer_t *lastLayer,
419  gerbv_netstate_t *lastState, gerbv_net_t *lastNet,
421  GArray *translationTable)
422 {
423  /* NOTE: destImage already contains apertures and data,
424  * latest data is: lastLayer, lastState, lastNet. */
425 
426  gerbv_net_t *currentNet, *newNet;
427  gerbv_layer_t *srcLayer = NULL;
428  gerbv_netstate_t *srcState = NULL;
429  gerbv_aperture_type_t aper_type;
430  gerbv_aperture_t *aper;
431  gerbv_simplified_amacro_t *sam;
432  int *trans_apers = NULL; /* Transformed apertures */
433  int aper_last_id = 0;
434  guint err_scale_circle = 0,
435  err_scale_line_macro = 0,
436  err_scale_poly_macro = 0,
437  err_scale_thermo_macro = 0,
438  err_scale_moire_macro = 0,
439  err_unknown_aperture = 0,
440  err_unknown_macro_aperture = 0,
441  err_rotate_oval = 0,
442  err_rotate_rect = 0;
443 
444  if (trans && (trans->mirrorAroundX || trans->mirrorAroundY)) {
445  if (sourceImage->layertype != GERBV_LAYERTYPE_DRILL) {
446  GERB_COMPILE_ERROR(_("Exporting mirrored file "
447  "is not supported!"));
448  return;
449  }
450  }
451 
452  if (trans && trans->inverted) {
453  GERB_COMPILE_ERROR(_("Exporting inverted file "
454  "is not supported!"));
455  return;
456  }
457 
458  if (trans) {
459  /* Find last used aperture to add transformed apertures if
460  * needed */
461  for (aper_last_id = APERTURE_MAX - 1; aper_last_id > 0;
462  aper_last_id--) {
463  if (destImage->aperture[aper_last_id] != NULL)
464  break;
465  }
466 
467  trans_apers = g_new (int, aper_last_id + 1);
468  /* Initialize trans_apers array */
469  for (int i = 0; i < aper_last_id + 1; i++)
470  trans_apers[i] = -1;
471  }
472 
473  for (currentNet = sourceImage->netlist; currentNet != NULL;
474  currentNet = currentNet->next) {
475 
476  /* Check for any new layers and duplicate them if needed.
477  * Compare against the source pointer, not the duplicated
478  * pointer, to avoid creating redundant duplicates when
479  * consecutive nets share the same layer. */
480  if (currentNet->layer != srcLayer) {
481  srcLayer = currentNet->layer;
482  lastLayer->next =
483  gerbv_image_duplicate_layer (currentNet->layer);
484  lastLayer = lastLayer->next;
485  }
486 
487  /* Check for any new states and duplicate them if needed.
488  * Same source-pointer tracking as layers above. */
489  if (currentNet->state != srcState) {
490  srcState = currentNet->state;
491  lastState->next =
492  gerbv_image_duplicate_state (currentNet->state);
493  lastState = lastState->next;
494  }
495 
496  /* Create and copy the actual net over */
497  newNet = g_new (gerbv_net_t, 1);
498  *newNet = *currentNet;
499 
500  if (currentNet->cirseg) {
501  newNet->cirseg = g_new (gerbv_cirseg_t, 1);
502  *(newNet->cirseg) = *(currentNet->cirseg);
503  }
504 
505  if (currentNet->label)
506  newNet->label = g_string_new (currentNet->label->str);
507  else
508  newNet->label = NULL;
509 
510  newNet->state = lastState;
511  newNet->layer = lastLayer;
512 
513  if (lastNet)
514  lastNet->next = newNet;
515  else
516  destImage->netlist = newNet;
517 
518  lastNet = newNet;
519 
520  /* Check if we need to translate the aperture number */
521  if (translationTable) {
522  for (guint i = 0; i < translationTable->len; i++) {
523  gerb_translation_entry_t translationEntry;
524 
525  translationEntry =
526  g_array_index (translationTable,
527  gerb_translation_entry_t, i);
528 
529  if (translationEntry.oldAperture ==
530  newNet->aperture) {
531  newNet->aperture =
532  translationEntry.newAperture;
533  break;
534  }
535  }
536  }
537 
538  if (trans == NULL)
539  continue;
540 
541  /* Transforming coords */
542  gerbv_transform_coord (&newNet->start_x,
543  &newNet->start_y, trans);
544  gerbv_transform_coord (&newNet->stop_x,
545  &newNet->stop_y, trans);
546 
547  if (newNet->cirseg) {
548  /* Circular interpolation only exported by start, stop
549  * end center coordinates. */
550  gerbv_transform_coord (&newNet->cirseg->cp_x,
551  &newNet->cirseg->cp_y, trans);
552  }
553 
554  if (destImage->aperture[newNet->aperture] == NULL)
555  continue;
556 
557  if (trans->scaleX == 1.0 && trans->scaleY == 1.0
558  && fabs(trans->rotation) < GERBV_PRECISION_ANGLE_RAD)
559  continue;
560 
561  /* Aperture is already transformed, use it */
562  if (trans_apers[newNet->aperture] != -1) {
563  newNet->aperture = trans_apers[newNet->aperture];
564  continue;
565  }
566 
567  /* Transforming apertures */
568  aper_type = destImage->aperture[newNet->aperture]->type;
569  switch (aper_type) {
570  case GERBV_APTYPE_NONE:
572  break;
573 
574  case GERBV_APTYPE_CIRCLE:
575  if (trans->scaleX == trans->scaleY
576  && trans->scaleX == 1.0) {
577  break;
578  }
579 
580  if (trans->scaleX == trans->scaleY) {
581  aper = gerbv_image_duplicate_aperture (
582  destImage->aperture[
583  newNet->aperture]);
584  aper->parameter[0] *= trans->scaleX;
585 
586  trans_apers[newNet->aperture] = ++aper_last_id;
587  destImage->aperture[aper_last_id] = aper;
588  newNet->aperture = aper_last_id;
589  } else {
590  err_scale_circle++;
591  }
592  break;
593 
595  case GERBV_APTYPE_OVAL:
596  if (trans->scaleX == 1.0 && trans->scaleY == 1.0
597  && fabs(fabs(trans->rotation) - M_PI)
598  < GERBV_PRECISION_ANGLE_RAD)
599  break;
600 
601  aper = gerbv_image_duplicate_aperture (
602  destImage->aperture[newNet->aperture]);
603  aper->parameter[0] *= trans->scaleX;
604  aper->parameter[1] *= trans->scaleY;
605 
606  if (fabs(fabs(trans->rotation) - M_PI_2)
607  < GERBV_PRECISION_ANGLE_RAD
608  || fabs(fabs(trans->rotation) - (M_PI+M_PI_2))
609  < GERBV_PRECISION_ANGLE_RAD) {
610  double t = aper->parameter[0];
611  aper->parameter[0] = aper->parameter[1];
612  aper->parameter[1] = t;
613  } else {
614  if (aper_type == GERBV_APTYPE_RECTANGLE)
615  err_rotate_rect++; /* TODO: make line21 macro */
616  else
617  err_rotate_oval++;
618 
619  break;
620  }
621 
622  trans_apers[newNet->aperture] = ++aper_last_id;
623  destImage->aperture[aper_last_id] = aper;
624  newNet->aperture = aper_last_id;
625 
626  break;
627 
628  case GERBV_APTYPE_MACRO:
629  aper = gerbv_image_duplicate_aperture (
630  destImage->aperture[newNet->aperture]);
631  sam = aper->simplified;
632 
633  for (; sam != NULL; sam = sam->next) {
634  switch (sam->type) {
636  sam->parameter[CIRCLE_CENTER_X] *=
637  trans->scaleX;
638  sam->parameter[CIRCLE_CENTER_Y] *=
639  trans->scaleY;
640  sam->parameter[CIRCLE_ROTATION] +=
641  RAD2DEG(trans->rotation);
642 
643  if (trans->scaleX != trans->scaleY) {
644  err_scale_circle++;
645  break;
646  }
647  sam->parameter[CIRCLE_DIAMETER] *=
648  trans->scaleX;
649  break;
650 
652  /* Vector line rectangle */
653  if (trans->scaleX == trans->scaleY) {
654  sam->parameter[LINE20_LINE_WIDTH] *=
655  trans->scaleX;
656  } else if (sam->parameter[LINE20_START_X] ==
657  sam->parameter[LINE20_END_X]) {
658  sam->parameter[LINE20_LINE_WIDTH] *=
659  trans->scaleX; /* Vertical */
660  } else if (sam->parameter[LINE20_START_Y] ==
661  sam->parameter[LINE20_END_Y]) {
662  sam->parameter[LINE20_LINE_WIDTH] *=
663  trans->scaleY; /* Horizontal */
664  } else {
665  /* TODO: make outline macro */
666  err_scale_line_macro++;
667  break;
668  }
669 
670  sam->parameter[LINE20_START_X] *=
671  trans->scaleX;
672  sam->parameter[LINE20_START_Y] *=
673  trans->scaleY;
674  sam->parameter[LINE20_END_X] *=
675  trans->scaleX;
676  sam->parameter[LINE20_END_Y] *=
677  trans->scaleY;
678 
679  /* LINE20_START_X, LINE20_START_Y,
680  * LINE20_END_X, LINE20_END_Y are not
681  * rotated, change only rotation angle */
682  sam->parameter[LINE20_ROTATION] +=
683  RAD2DEG(trans->rotation);
684  break;
685 
686 /* Compile time check if LINE21 and LINE22 parameters indexes are equal */
687 #if (LINE21_WIDTH != LINE22_WIDTH) \
688  || (LINE21_HEIGHT != LINE22_HEIGHT) \
689  || (LINE21_ROTATION != LINE22_ROTATION) \
690  || (LINE21_CENTER_X != LINE22_LOWER_LEFT_X) \
691  || (LINE21_CENTER_Y != LINE22_LOWER_LEFT_Y)
692 # error "LINE21 and LINE22 indexes are not equal"
693 #endif
694 
696  /* Centered line rectangle */
698  /* Lower left line rectangle */
699 
700  /* Using LINE21 parameters array
701  * indexes for LINE21 and LINE22, as
702  * they are equal */
703  if (trans->scaleX == trans->scaleY) {
704  sam->parameter[LINE21_WIDTH] *=
705  trans->scaleX;
706  sam->parameter[LINE21_HEIGHT] *=
707  trans->scaleX;
708 
709  } else if (fabs(sam->parameter[LINE21_ROTATION]) == 0
710  || fabs(sam->parameter[LINE21_ROTATION]) == 180) {
711  sam->parameter[LINE21_WIDTH] *=
712  trans->scaleX;
713  sam->parameter[LINE21_HEIGHT] *=
714  trans->scaleY;
715 
716  } else if (fabs(sam->parameter[LINE21_ROTATION]) == 90
717  || fabs(sam->parameter[LINE21_ROTATION]) == 270) {
718  double t;
719  t = sam->parameter[LINE21_WIDTH];
720  sam->parameter[LINE21_WIDTH] =
721  trans->scaleY *
722  sam->parameter[
723  LINE21_HEIGHT];
724  sam->parameter[LINE21_HEIGHT] =
725  trans->scaleX * t;
726  } else {
727  /* TODO: make outline macro */
728  err_scale_line_macro++;
729  break;
730  }
731 
732  sam->parameter[LINE21_CENTER_X] *=
733  trans->scaleX;
734  sam->parameter[LINE21_CENTER_Y] *=
735  trans->scaleY;
736 
737  sam->parameter[LINE21_ROTATION] +=
738  RAD2DEG(trans->rotation);
739  break;
740 
742  for (int i = 0; i < 1 + sam->parameter[
743  OUTLINE_NUMBER_OF_POINTS]; i++) {
744  sam->parameter[OUTLINE_X_IDX_OF_POINT(i)] *=
745  trans->scaleX;
746  sam->parameter[OUTLINE_Y_IDX_OF_POINT(i)] *=
747  trans->scaleY;
748  }
749 
750  sam->parameter[OUTLINE_ROTATION_IDX(sam->parameter)] +=
751  RAD2DEG(trans->rotation);
752  break;
753 #if 0
754 {
755 /* TODO */
756 #include "main.h"
757 gerbv_selection_item_t sItem = {sourceImage, currentNet};
758 selection_add_item (&screen.selectionInfo, &sItem);
759 }
760 #endif
761 
763  if (trans->scaleX == trans->scaleY) {
764  sam->parameter[POLYGON_CENTER_X]
765  *= trans->scaleX;
766  sam->parameter[POLYGON_CENTER_Y]
767  *= trans->scaleX;
768  sam->parameter[POLYGON_DIAMETER]
769  *= trans->scaleX;
770  } else {
771  /* TODO: make outline macro */
772  err_scale_poly_macro++;
773  break;
774  }
775 
776  sam->parameter[POLYGON_ROTATION] +=
777  RAD2DEG(trans->rotation);
778  break;
779 
781  if (trans->scaleX == trans->scaleY) {
782  sam->parameter[MOIRE_CENTER_X]
783  *= trans->scaleX;
784  sam->parameter[MOIRE_CENTER_Y]
785  *= trans->scaleX;
786  sam->parameter[MOIRE_OUTSIDE_DIAMETER]
787  *= trans->scaleX;
788  sam->parameter[MOIRE_CIRCLE_THICKNESS]
789  *= trans->scaleX;
790  sam->parameter[MOIRE_GAP_WIDTH]
791  *= trans->scaleX;
792  sam->parameter[MOIRE_CROSSHAIR_THICKNESS]
793  *= trans->scaleX;
794  sam->parameter[MOIRE_CROSSHAIR_LENGTH]
795  *= trans->scaleX;
796  } else {
797  err_scale_moire_macro++;
798  break;
799  }
800 
801  sam->parameter[MOIRE_ROTATION] +=
802  RAD2DEG(trans->rotation);
803  break;
804 
806  if (trans->scaleX == trans->scaleY) {
807  sam->parameter[THERMAL_CENTER_X]
808  *= trans->scaleX;
809  sam->parameter[THERMAL_CENTER_Y]
810  *= trans->scaleX;
811  sam->parameter[THERMAL_INSIDE_DIAMETER]
812  *= trans->scaleX;
813  sam->parameter[THERMAL_OUTSIDE_DIAMETER]
814  *= trans->scaleX;
815  sam->parameter[THERMAL_CROSSHAIR_THICKNESS]
816  *= trans->scaleX;
817  } else {
818  err_scale_thermo_macro++;
819  break;
820  }
821 
822  sam->parameter[THERMAL_ROTATION] +=
823  RAD2DEG(trans->rotation);
824  break;
825 
826  default:
827  /* TODO: free aper if it is skipped (i.e. unused)? */
828  err_unknown_macro_aperture++;
829  }
830  }
831 
832  trans_apers[newNet->aperture] = ++aper_last_id;
833  destImage->aperture[aper_last_id] = aper;
834  newNet->aperture = aper_last_id;
835 
836  break;
837  default:
838  err_unknown_aperture++;
839  }
840  }
841 
842  if (err_rotate_rect)
843  GERB_COMPILE_ERROR(ngettext(
844  "Can't rotate %u rectangular aperture to %.2f "
845  "degrees (non 90 multiply)!",
846  "Can't rotate %u rectangular apertures to %.2f "
847  "degrees (non 90 multiply)!", err_rotate_rect),
848  err_rotate_rect, RAD2DEG(trans->rotation));
849 
850  if (err_scale_line_macro)
851  GERB_COMPILE_ERROR(ngettext(
852  "Can't scale %u line macro!",
853  "Can't scale %u line macros!",
854  err_scale_line_macro), err_scale_line_macro);
855 
856  if (err_scale_poly_macro)
857  GERB_COMPILE_ERROR(ngettext(
858  "Can't scale %u polygon macro!",
859  "Can't scale %u polygon macros!",
860  err_scale_poly_macro), err_scale_poly_macro);
861 
862  if (err_scale_thermo_macro)
863  GERB_COMPILE_ERROR(ngettext(
864  "Can't scale %u thermal macro!",
865  "Can't scale %u thermal macros!",
866  err_scale_poly_macro), err_scale_poly_macro);
867 
868  if (err_scale_moire_macro)
869  GERB_COMPILE_ERROR(ngettext(
870  "Can't scale %u moire macro!",
871  "Can't scale %u moire macros!",
872  err_scale_poly_macro), err_scale_poly_macro);
873 
874  if (err_rotate_oval)
875  GERB_COMPILE_ERROR(ngettext(
876  "Can't rotate %u oval aperture to %.2f "
877  "degrees (non 90 multiply)!",
878  "Can't rotate %u oval apertures to %.2f "
879  "degrees (non 90 multiply)!", err_rotate_oval),
880  err_rotate_oval, RAD2DEG(trans->rotation));
881 
882  if (err_scale_circle)
883  GERB_COMPILE_ERROR(ngettext(
884  "Can't scale %u circle aperture to ellipse!",
885  "Can't scale %u circle apertures to ellipse!",
886  err_scale_circle), err_scale_circle);
887 
888  if (err_unknown_aperture)
889  GERB_COMPILE_ERROR(ngettext(
890  "Skipped %u aperture with unknown type!",
891  "Skipped %u apertures with unknown type!",
892  err_unknown_aperture), err_unknown_aperture);
893 
894  if (err_unknown_macro_aperture)
895  GERB_COMPILE_ERROR(ngettext(
896  "Skipped %u macro aperture!",
897  "Skipped %u macro apertures!",
898  err_unknown_macro_aperture),
899  err_unknown_macro_aperture);
900 
901  g_free (trans_apers);
902 }
903 
904 gint
905 gerbv_image_find_existing_aperture_match (gerbv_aperture_t *checkAperture, gerbv_image_t *imageToSearch) {
906  int i,j;
907  gboolean isMatch;
908 
909  for (i = 0; i < APERTURE_MAX; i++) {
910  if (imageToSearch->aperture[i] != NULL) {
911  if ((imageToSearch->aperture[i]->type == checkAperture->type) &&
912  (imageToSearch->aperture[i]->simplified == NULL) &&
913  (imageToSearch->aperture[i]->unit == checkAperture->unit)) {
914  /* check all parameters match too */
915  isMatch=TRUE;
916  for (j=0; j<APERTURE_PARAMETERS_MAX; j++){
917  if (imageToSearch->aperture[i]->parameter[j] != checkAperture->parameter[j])
918  isMatch = FALSE;
919  }
920  if (isMatch)
921  return i;
922  }
923  }
924  }
925  return 0;
926 }
927 
928 int
929 gerbv_image_find_unused_aperture_number (int startIndex, gerbv_image_t *image){
930  int i;
931 
932  for (i = startIndex; i < APERTURE_MAX; i++) {
933  if (image->aperture[i] == NULL) {
934  return i;
935  }
936  }
937  return -1;
938 }
939 
942  gerbv_image_t *newImage = gerbv_create_image(NULL, sourceImage->info->type);
943  int i;
944  int lastUsedApertureNumber = APERTURE_MIN - 1;
945  GArray *apertureNumberTable = g_array_new(FALSE,FALSE,sizeof(gerb_translation_entry_t));
946 
947  newImage->layertype = sourceImage->layertype;
948 
949  /* Free the type string allocated by gerbv_create_image() before the
950  * struct copy overwrites the pointer (would leak otherwise). */
951  g_free(newImage->info->type);
952 
953  /* Free the sentinel netlist node — gerbv_image_copy_all_nets() will
954  * replace newImage->netlist with a fresh copy of the source nets. */
955  g_free(newImage->netlist);
956  newImage->netlist = NULL;
957 
958  /* copy information layer over */
959  *(newImage->info) = *(sourceImage->info);
960  newImage->info->name = g_strdup (sourceImage->info->name);
961  newImage->info->type = g_strdup (sourceImage->info->type);
962  newImage->info->plotterFilm = g_strdup (sourceImage->info->plotterFilm);
963  newImage->info->attr_list = gerbv_attribute_dup (sourceImage->info->attr_list,
964  sourceImage->info->n_attr);
965 
966  /* copy apertures over, compressing all the numbers down for a cleaner output, and
967  moving and apertures less than 10 up to the correct range */
968  for (i = 0; i < APERTURE_MAX; i++) {
969  if (sourceImage->aperture[i] != NULL) {
970  gerbv_aperture_t *newAperture = gerbv_image_duplicate_aperture (sourceImage->aperture[i]);
971 
972  lastUsedApertureNumber = gerbv_image_find_unused_aperture_number (lastUsedApertureNumber + 1, newImage);
973  /* store the aperture numbers (new and old) in the translation table */
974  gerb_translation_entry_t translationEntry={i,lastUsedApertureNumber};
975  g_array_append_val (apertureNumberTable,translationEntry);
976 
977  newImage->aperture[lastUsedApertureNumber] = newAperture;
978  }
979  }
980 
981  /* step through all nets and create new layers and states on the fly, since
982  we really don't have any other way to figure out where states and layers are used */
983  gerbv_image_copy_all_nets (sourceImage, newImage, newImage->layers, newImage->states, NULL, transform, apertureNumberTable);
984  g_array_free (apertureNumberTable, TRUE);
985  return newImage;
986 }
987 
988 void
989 gerbv_image_copy_image (gerbv_image_t *sourceImage, gerbv_user_transformation_t *transform, gerbv_image_t *destinationImage) {
990  int lastUsedApertureNumber = APERTURE_MIN - 1;
991  int i;
992  GArray *apertureNumberTable = g_array_new(FALSE,FALSE,sizeof(gerb_translation_entry_t));
993 
994  /* copy apertures over */
995  for (i = 0; i < APERTURE_MAX; i++) {
996  if (sourceImage->aperture[i] != NULL) {
997  gint existingAperture = gerbv_image_find_existing_aperture_match (sourceImage->aperture[i], destinationImage);
998 
999  /* if we already have an existing aperture in the destination image that matches what
1000  we want, just use it instead */
1001  if (existingAperture > 0) {
1002  gerb_translation_entry_t translationEntry={i,existingAperture};
1003  g_array_append_val (apertureNumberTable,translationEntry);
1004  }
1005  /* else, create a new aperture and put it in the destination image */
1006  else {
1007  gerbv_aperture_t *newAperture = gerbv_image_duplicate_aperture (sourceImage->aperture[i]);
1008 
1009  lastUsedApertureNumber = gerbv_image_find_unused_aperture_number (lastUsedApertureNumber + 1, destinationImage);
1010  /* store the aperture numbers (new and old) in the translation table */
1011  gerb_translation_entry_t translationEntry={i,lastUsedApertureNumber};
1012  g_array_append_val (apertureNumberTable,translationEntry);
1013 
1014  destinationImage->aperture[lastUsedApertureNumber] = newAperture;
1015  }
1016  }
1017  }
1018  /* find the last layer, state, and net in the linked chains */
1019  gerbv_netstate_t *lastState;
1020  gerbv_layer_t *lastLayer;
1021  gerbv_net_t *lastNet;
1022 
1023  for (lastState = destinationImage->states; lastState->next; lastState=lastState->next){}
1024  for (lastLayer = destinationImage->layers; lastLayer->next; lastLayer=lastLayer->next){}
1025  for (lastNet = destinationImage->netlist; lastNet->next; lastNet=lastNet->next){}
1026 
1027  /* and then copy them all to the destination image, using the aperture translation table we just built */
1028  gerbv_image_copy_all_nets (sourceImage, destinationImage, lastLayer, lastState, lastNet, transform, apertureNumberTable);
1029  g_array_free (apertureNumberTable, TRUE);
1030 }
1031 
1032 void
1034  gerbv_net_t *tempNet;
1035 
1036  g_assert (currentNet);
1037  /* we have a match, so just zero out all the important data fields */
1038  currentNet->aperture = 0;
1040 
1041  /* if this is a polygon start, we need to erase all the rest of the
1042  nets in this polygon too */
1043  if (currentNet->interpolation == GERBV_INTERPOLATION_PAREA_START){
1044  for (tempNet = currentNet->next; tempNet; tempNet = tempNet->next){
1045  tempNet->aperture = 0;
1047 
1048  if (tempNet->interpolation == GERBV_INTERPOLATION_PAREA_END) {
1050  break;
1051  }
1052  /* make sure we don't leave a polygon interpolation in, since
1053  it will still draw if it is */
1055  }
1056  }
1057  /* make sure we don't leave a polygon interpolation in, since
1058  it will still draw if it is */
1060 }
1061 
1062 void
1064  gdouble coordinateY, gdouble width, gdouble height) {
1065  gerbv_net_t *currentNet;
1066 
1067  /* run through and find last net pointer */
1068  for (currentNet = image->netlist; currentNet->next; currentNet = currentNet->next){}
1069 
1070  /* create the polygon start node */
1071  currentNet = gerber_create_new_net (currentNet, NULL, NULL);
1073 
1074  /* go to start point (we need this to create correct RS274X export code) */
1075  currentNet = gerber_create_new_net (currentNet, NULL, NULL);
1078  currentNet->start_x = coordinateX;
1079  currentNet->start_y = coordinateY;
1080  currentNet->stop_x = coordinateX;
1081  currentNet->stop_y = coordinateY;
1082 
1083  /* draw the 4 corners */
1084  currentNet = gerber_create_new_net (currentNet, NULL, NULL);
1087  currentNet->start_x = coordinateX;
1088  currentNet->start_y = coordinateY;
1089  currentNet->stop_x = coordinateX + width;
1090  currentNet->stop_y = coordinateY;
1091  gerber_update_min_and_max (&currentNet->boundingBox,currentNet->stop_x,currentNet->stop_y,
1092  0,0,0,0);
1093  gerber_update_image_min_max (&currentNet->boundingBox, 0, 0, image);
1094 
1095  currentNet = gerber_create_new_net (currentNet, NULL, NULL);
1098  currentNet->stop_x = coordinateX + width;
1099  currentNet->stop_y = coordinateY + height;
1100  gerber_update_min_and_max (&currentNet->boundingBox,currentNet->stop_x,currentNet->stop_y,
1101  0,0,0,0);
1102  gerber_update_image_min_max (&currentNet->boundingBox, 0, 0, image);
1103 
1104  currentNet = gerber_create_new_net (currentNet, NULL, NULL);
1107  currentNet->stop_x = coordinateX;
1108  currentNet->stop_y = coordinateY + height;
1109  gerber_update_min_and_max (&currentNet->boundingBox,currentNet->stop_x,currentNet->stop_y,
1110  0,0,0,0);
1111  gerber_update_image_min_max (&currentNet->boundingBox, 0, 0, image);
1112 
1113  currentNet = gerber_create_new_net (currentNet, NULL, NULL);
1116  currentNet->stop_x = coordinateX;
1117  currentNet->stop_y = coordinateY;
1118  gerber_update_min_and_max (&currentNet->boundingBox,currentNet->stop_x,currentNet->stop_y,
1119  0,0,0,0);
1120  gerber_update_image_min_max (&currentNet->boundingBox, 0, 0, image);
1121 
1122  /* create the polygon end node */
1123  currentNet = gerber_create_new_net (currentNet, NULL, NULL);
1125 
1126  return;
1127 }
1128 
1129 gerbv_net_t *
1130 gerb_image_return_aperture_index (gerbv_image_t *image, gdouble lineWidth, int *apertureIndex){
1131  gerbv_net_t *currentNet;
1132  gerbv_aperture_t *aperture=NULL;
1133  int i;
1134 
1135  /* run through and find last net pointer */
1136  for (currentNet = image->netlist; currentNet->next; currentNet = currentNet->next){}
1137 
1138  /* try to find an existing aperture that matches the requested width and type */
1139  for (i = 0; i < APERTURE_MAX; i++) {
1140  if (image->aperture[i] != NULL) {
1141  if ((image->aperture[i]->type == GERBV_APTYPE_CIRCLE) &&
1142  (fabs (image->aperture[i]->parameter[0] - lineWidth) < 0.001)){
1143  aperture = image->aperture[i];
1144  *apertureIndex = i;
1145  break;
1146  }
1147  }
1148  }
1149 
1150  if (!aperture) {
1151  /* we didn't find a useable old aperture, so create a new one */
1152  if (!gerber_create_new_aperture (image, apertureIndex,
1153  GERBV_APTYPE_CIRCLE, lineWidth, 0)) {
1154  /* if we didn't succeed, then return */
1155  return FALSE;
1156  }
1157  }
1158  return currentNet;
1159 }
1160 
1161 void
1162 gerbv_image_create_arc_object (gerbv_image_t *image, gdouble centerX, gdouble centerY,
1163  gdouble radius, gdouble startAngle, gdouble endAngle, gdouble lineWidth,
1164  gerbv_aperture_type_t apertureType) {
1165  int apertureIndex;
1166  gerbv_net_t *currentNet;
1167  gerbv_cirseg_t cirSeg = {centerX, centerY, radius, radius, startAngle, endAngle};
1168 
1169  currentNet = gerb_image_return_aperture_index(image, lineWidth, &apertureIndex);
1170 
1171  if (!currentNet)
1172  return;
1173 
1174  /* draw the arc */
1175  currentNet = gerber_create_new_net (currentNet, NULL, NULL);
1178  currentNet->aperture = apertureIndex;
1179  currentNet->start_x = centerX + (cos(DEG2RAD(startAngle)) * radius);
1180  currentNet->start_y = centerY + (sin(DEG2RAD(startAngle)) * radius);
1181  currentNet->stop_x = centerX + (cos(DEG2RAD(endAngle)) * radius);
1182  currentNet->stop_y = centerY + (sin(DEG2RAD(endAngle)) * radius);
1183  currentNet->cirseg = g_new0 (gerbv_cirseg_t,1);
1184  *(currentNet->cirseg) = cirSeg;
1185 
1186  gdouble angleDiff = currentNet->cirseg->angle2 - currentNet->cirseg->angle1;
1187  gint i, steps = fabs(angleDiff);
1188  for (i=0; i<=steps; i++){
1189  gdouble tempX = currentNet->cirseg->cp_x + currentNet->cirseg->width / 2.0 *
1190  cos (DEG2RAD(currentNet->cirseg->angle1 +
1191  (i*angleDiff)/steps));
1192  gdouble tempY = currentNet->cirseg->cp_y + currentNet->cirseg->width / 2.0 *
1193  sin (DEG2RAD(currentNet->cirseg->angle1 +
1194  (i*angleDiff)/steps));
1195  gerber_update_min_and_max (&currentNet->boundingBox,
1196  tempX, tempY,
1197  lineWidth/2,lineWidth/2,
1198  lineWidth/2,lineWidth/2);
1199  }
1200  gerber_update_image_min_max (&currentNet->boundingBox, 0, 0, image);
1201  return;
1202 }
1203 
1204 void
1205 gerbv_image_create_line_object (gerbv_image_t *image, gdouble startX, gdouble startY,
1206  gdouble endX, gdouble endY, gdouble lineWidth, gerbv_aperture_type_t apertureType) {
1207  int apertureIndex;
1208  gerbv_net_t *currentNet;
1209 
1210  currentNet = gerb_image_return_aperture_index(image, lineWidth, &apertureIndex);
1211 
1212  if (!currentNet)
1213  return;
1214 
1215  /* draw the line */
1216  currentNet = gerber_create_new_net (currentNet, NULL, NULL);
1218 
1219  /* if the start and end coordinates are the same, use a "flash" aperture state */
1220  if ((fabs(startX - endX) < 0.001) && (fabs(startY - endY) < 0.001))
1222  else
1224  currentNet->aperture = apertureIndex;
1225  currentNet->start_x = startX;
1226  currentNet->start_y = startY;
1227  currentNet->stop_x = endX;
1228  currentNet->stop_y = endY;
1229 
1230  gerber_update_min_and_max (&currentNet->boundingBox,currentNet->stop_x,currentNet->stop_y,
1231  lineWidth/2,lineWidth/2,lineWidth/2,lineWidth/2);
1232  gerber_update_min_and_max (&currentNet->boundingBox,currentNet->start_x,currentNet->start_y,
1233  lineWidth/2,lineWidth/2,lineWidth/2,lineWidth/2);
1234  gerber_update_image_min_max (&currentNet->boundingBox, 0, 0, image);
1235  return;
1236 }
1237 
1238 void
1239 gerbv_image_create_window_pane_objects (gerbv_image_t *image, gdouble lowerLeftX,
1240  gdouble lowerLeftY, gdouble width, gdouble height, gdouble areaReduction,
1241  gint paneRows, gint paneColumns, gdouble paneSeparation){
1242  int i,j;
1243  gdouble startX,startY,boxWidth,boxHeight;
1244 
1245  startX = lowerLeftX + (areaReduction * width) / 2.0;
1246  startY = lowerLeftY + (areaReduction * height) / 2.0;
1247  boxWidth = (width * (1.0 - areaReduction) - (paneSeparation * (paneColumns - 1))) / paneColumns;
1248  boxHeight = (height * (1.0 - areaReduction) - (paneSeparation * (paneRows - 1))) / paneRows;
1249 
1250  for (i=0; i<paneColumns; i++){
1251  for (j=0; j<paneRows; j++) {
1252  gerbv_image_create_rectangle_object (image, startX + (i * (boxWidth + paneSeparation)),
1253  startY + (j * (boxHeight + paneSeparation)),boxWidth, boxHeight);
1254  }
1255  }
1256 
1257  return;
1258 }
1259 
1260 gboolean
1261 gerbv_image_reduce_area_of_selected_objects (GArray *selectionArray,
1262  gdouble areaReduction, gint paneRows, gint paneColumns, gdouble paneSeparation){
1263  gdouble minX,minY,maxX,maxY;
1264 
1265  for (guint i=0; i<selectionArray->len; i++) {
1266  gerbv_selection_item_t sItem = g_array_index (selectionArray,gerbv_selection_item_t, i);
1267  gerbv_image_t *image = sItem.image;
1268  gerbv_net_t *currentNet = sItem.net;
1269 
1270  /* determine the object type first */
1271  minX = HUGE_VAL;
1272  maxX = -HUGE_VAL;
1273  minY = HUGE_VAL;
1274  maxY = -HUGE_VAL;
1275 
1276  switch (currentNet->interpolation) {
1278  /* if it's a polygon, just determine the overall area of it and delete it */
1280 
1281  for (currentNet = currentNet->next; currentNet; currentNet = currentNet->next){
1282  if (currentNet->interpolation == GERBV_INTERPOLATION_PAREA_END)
1283  break;
1285  if (currentNet->stop_x < minX)
1286  minX = currentNet->stop_x;
1287  if (currentNet->stop_y < minY)
1288  minY = currentNet->stop_y;
1289  if (currentNet->stop_x > maxX)
1290  maxX = currentNet->stop_x;
1291  if (currentNet->stop_y > maxY)
1292  maxY = currentNet->stop_y;
1293  }
1295 
1296  break;
1297 
1302  gdouble dx=0,dy=0;
1303  gerbv_aperture_t *apert =
1304  image->aperture[currentNet->aperture];
1305 
1306  /* figure out the overall size of this element */
1307  switch (apert->type) {
1308  case GERBV_APTYPE_CIRCLE :
1309  case GERBV_APTYPE_OVAL :
1310  case GERBV_APTYPE_POLYGON :
1311  dx = dy = apert->parameter[0];
1312  break;
1313  case GERBV_APTYPE_RECTANGLE :
1314  dx = apert->parameter[0]/2;
1315  dy = apert->parameter[1]/2;
1316  break;
1317  default :
1318  break;
1319  }
1320  if (currentNet->start_x-dx < minX)
1321  minX = currentNet->start_x-dx;
1322  if (currentNet->start_y-dy < minY)
1323  minY = currentNet->start_y-dy;
1324  if (currentNet->start_x+dx > maxX)
1325  maxX = currentNet->start_x+dx;
1326  if (currentNet->start_y+dy > maxY)
1327  maxY = currentNet->start_y+dy;
1328 
1329  if (currentNet->stop_x-dx < minX)
1330  minX = currentNet->stop_x-dx;
1331  if (currentNet->stop_y-dy < minY)
1332  minY = currentNet->stop_y-dy;
1333  if (currentNet->stop_x+dx > maxX)
1334  maxX = currentNet->stop_x+dx;
1335  if (currentNet->stop_y+dy > maxY)
1336  maxY = currentNet->stop_y+dy;
1337 
1338  /* finally, delete node */
1340 
1341  break;
1342  }
1343 
1344  default:
1345  /* we don't current support arcs */
1346  return FALSE;
1347  }
1348 
1349  /* create new structures */
1350  gerbv_image_create_window_pane_objects (image, minX, minY, maxX - minX, maxY - minY,
1351  areaReduction, paneRows, paneColumns, paneSeparation);
1352  }
1353  return TRUE;
1354 }
1355 
1356 gboolean
1357 gerbv_image_move_selected_objects (GArray *selectionArray, gdouble translationX,
1358  gdouble translationY)
1359 {
1360  for (guint i=0; i<selectionArray->len; i++) {
1361  gerbv_selection_item_t sItem = g_array_index (selectionArray,gerbv_selection_item_t, i);
1362  gerbv_net_t *currentNet = sItem.net;
1363 
1364  if (currentNet->interpolation == GERBV_INTERPOLATION_PAREA_START) {
1365  /* if it's a polygon, step through every vertex and translate the point */
1366  for (currentNet = currentNet->next; currentNet; currentNet = currentNet->next){
1367  if (currentNet->interpolation == GERBV_INTERPOLATION_PAREA_END)
1368  break;
1369  currentNet->start_x += translationX;
1370  currentNet->start_y += translationY;
1371  currentNet->stop_x += translationX;
1372  currentNet->stop_y += translationY;
1373  }
1374  }
1375  else {
1376  /* otherwise, just move the single element */
1377  currentNet->start_x += translationX;
1378  currentNet->start_y += translationY;
1379  currentNet->stop_x += translationX;
1380  currentNet->stop_y += translationY;
1381  }
1382  }
1383  return TRUE;
1384 }
1385 
1386 gerbv_net_t *
1388  gerbv_net_t *currentNet=oldNet;
1389 
1390  if (currentNet->interpolation == GERBV_INTERPOLATION_PAREA_START) {
1391  /* if it's a polygon, step to the next non-polygon net */
1392  for (currentNet = currentNet->next; currentNet; currentNet = currentNet->next){
1393  if (currentNet->interpolation == GERBV_INTERPOLATION_PAREA_END) {
1394  return currentNet->next;
1395  }
1396  }
1397  return NULL;
1398  }
1399  else {
1400  return currentNet->next;
1401  }
1402 }
1403 
1404 void
1406  gerbv_net_t *currentNet;
1407 
1408  /* run through and find last net pointer */
1409  for (currentNet = parsed_image->netlist; currentNet->next; currentNet = currentNet->next){
1410  if (parsed_image->aperture[currentNet->aperture] == NULL) {
1411  parsed_image->aperture[currentNet->aperture] = g_new0 (gerbv_aperture_t, 1);
1412  parsed_image->aperture[currentNet->aperture]->type = GERBV_APTYPE_CIRCLE;
1413  parsed_image->aperture[currentNet->aperture]->parameter[0] = 0;
1414  parsed_image->aperture[currentNet->aperture]->parameter[1] = 0;
1415  }
1416  }
1417 }
Aperture macro parsing header info.
void gerbv_drill_stats_destroy(gerbv_drill_stats_t *stats)
Definition: drill_stats.c:101
void gerbv_destroy_image(gerbv_image_t *image)
Free an image structure.
Definition: gerb_image.c:106
void gerbv_image_create_rectangle_object(gerbv_image_t *image, gdouble coordinateX, gdouble coordinateY, gdouble width, gdouble height)
Draw a filled rectangle on the specified image
Definition: gerb_image.c:1063
void gerbv_image_copy_image(gerbv_image_t *sourceImage, gerbv_user_transformation_t *transform, gerbv_image_t *destinationImage)
Copy an image into an existing image, effectively merging the two together.
Definition: gerb_image.c:989
gerbv_image_t * gerbv_create_image(gerbv_image_t *image, const gchar *type)
Allocate a new gerbv_image structure.
Definition: gerb_image.c:46
void gerbv_image_create_line_object(gerbv_image_t *image, gdouble startX, gdouble startY, gdouble endX, gdouble endY, gdouble lineWidth, gerbv_aperture_type_t apertureType)
Draw a line on the specified image.
Definition: gerb_image.c:1205
void gerbv_image_delete_net(gerbv_net_t *currentNet)
Delete a net in an existing image.
Definition: gerb_image.c:1033
gerbv_net_t * gerbv_image_return_next_renderable_object(gerbv_net_t *oldNet)
Return the next net entry which corresponds to a unique visible object.
Definition: gerb_image.c:1387
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:941
void gerbv_image_create_dummy_apertures(gerbv_image_t *parsed_image)
Create any missing apertures in the specified image.
Definition: gerb_image.c:1405
void gerbv_image_create_arc_object(gerbv_image_t *image, gdouble centerX, gdouble centerY, gdouble radius, gdouble startAngle, gdouble endAngle, gdouble lineWidth, gerbv_aperture_type_t apertureType)
Draw an arc on the specified image.
Definition: gerb_image.c:1162
Header info for the image editing and support functions.
void gerbv_stats_destroy(gerbv_stats_t *stats)
Definition: gerb_stats.c:103
Header info for the RS274X parsing functions.
const char * gerbv_interpolation_name(gerbv_interpolation_t interp)
Return string name of gerbv_interpolation_t interpolation.
Definition: gerbv.c:116
void gerbv_transform_coord(double *x, double *y, const gerbv_user_transformation_t *trans)
Definition: gerbv.c:1155
The main header file for the libgerbv library.
gerbv_aperture_state_t
Definition: gerbv.h:179
@ GERBV_APERTURE_STATE_OFF
Definition: gerbv.h:179
@ GERBV_APERTURE_STATE_ON
Definition: gerbv.h:180
@ GERBV_APERTURE_STATE_FLASH
Definition: gerbv.h:181
@ GERBV_POLARITY_DARK
Definition: gerbv.h:284
gerbv_aperture_type_t
Definition: gerbv.h:158
@ GERBV_APTYPE_MACRO_LINE20
Definition: gerbv.h:170
@ GERBV_APTYPE_MACRO_LINE21
Definition: gerbv.h:171
@ GERBV_APTYPE_OVAL
Definition: gerbv.h:162
@ GERBV_APTYPE_MACRO_OUTLINE
Definition: gerbv.h:166
@ GERBV_APTYPE_MACRO_CIRCLE
Definition: gerbv.h:165
@ GERBV_APTYPE_MACRO
Definition: gerbv.h:164
@ GERBV_APTYPE_CIRCLE
Definition: gerbv.h:160
@ GERBV_APTYPE_NONE
Definition: gerbv.h:159
@ GERBV_APTYPE_POLYGON
Definition: gerbv.h:163
@ GERBV_APTYPE_MACRO_POLYGON
Definition: gerbv.h:167
@ GERBV_APTYPE_RECTANGLE
Definition: gerbv.h:161
@ GERBV_APTYPE_MACRO_THERMAL
Definition: gerbv.h:169
@ GERBV_APTYPE_MACRO_LINE22
Definition: gerbv.h:172
@ GERBV_APTYPE_MACRO_MOIRE
Definition: gerbv.h:168
@ GERBV_APTYPE_BLOCK
Definition: gerbv.h:173
@ GERBV_INTERPOLATION_LINEARx01
Definition: gerbv.h:305
@ GERBV_INTERPOLATION_PAREA_START
Definition: gerbv.h:309
@ GERBV_INTERPOLATION_LINEARx001
Definition: gerbv.h:306
@ GERBV_INTERPOLATION_DELETED
Definition: gerbv.h:311
@ GERBV_INTERPOLATION_PAREA_END
Definition: gerbv.h:310
@ GERBV_INTERPOLATION_LINEARx10
Definition: gerbv.h:304
@ GERBV_INTERPOLATION_CCW_CIRCULAR
Definition: gerbv.h:308
@ GERBV_INTERPOLATION_LINEARx1
Definition: gerbv.h:303
@ GERBV_LAYERTYPE_DRILL
Definition: gerbv.h:330
Header info for common structs and functions used for the GUI application.
gerbv_amacro_t * amacro
Definition: gerbv.h:738
gerbv_stats_t * gerbv_stats
Definition: gerbv.h:742
gerbv_format_t * format
Definition: gerbv.h:739
gerbv_layer_t * layers
Definition: gerbv.h:736
gerbv_layertype_t layertype
Definition: gerbv.h:734
gerbv_net_t * netlist
Definition: gerbv.h:741
gerbv_drill_stats_t * drill_stats
Definition: gerbv.h:743
gerbv_aperture_t * aperture[APERTURE_MAX]
Definition: gerbv.h:735
gerbv_netstate_t * states
Definition: gerbv.h:737
gerbv_image_info_t * info
Definition: gerbv.h:740
gchar * name
Definition: gerbv.h:650
gerbv_step_and_repeat_t stepAndRepeat
Definition: gerbv.h:646
gerbv_polarity_t polarity
Definition: gerbv.h:649
gerbv_knockout_t knockout
Definition: gerbv.h:647
gpointer next
Definition: gerbv.h:651
gerbv_render_size_t boundingBox
Definition: gerbv.h:673
gerbv_layer_t * layer
Definition: gerbv.h:680
double stop_y
Definition: gerbv.h:672
GString * label
Definition: gerbv.h:679
gerbv_aperture_state_t aperture_state
Definition: gerbv.h:675
double stop_x
Definition: gerbv.h:671
double start_x
Definition: gerbv.h:669
gerbv_netstate_t * state
Definition: gerbv.h:681
struct gerbv_net * next
Definition: gerbv.h:678
double start_y
Definition: gerbv.h:670
gerbv_interpolation_t interpolation
Definition: gerbv.h:676
gerbv_cirseg_t * cirseg
Definition: gerbv.h:677
int aperture
Definition: gerbv.h:674
gdouble scaleA
Definition: gerbv.h:661
gdouble scaleB
Definition: gerbv.h:662
gpointer next
Definition: gerbv.h:664