gerbv
gerbv.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) 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 
24 
30 #include "gerbv.h"
31 
32 #include <assert.h>
33 #include <stdio.h>
34 #include <stdlib.h>
35 #include <math.h>
36 #include <errno.h>
37 
38 #ifdef HAVE_LIBGEN_H
39 # include <libgen.h> /* dirname */
40 #endif
41 
42 #ifdef HAVE_STRING_H
43 # include <string.h>
44 #endif
45 
46 #ifdef HAVE_UNISTD_H
47 # include <unistd.h>
48 #endif
49 
50 #ifdef HAVE_GETOPT_H
51 # include <getopt.h>
52 #endif
53 
54 #include <pango/pango.h>
55 
56 #include "common.h"
57 #include "gerber.h"
58 #include "drill.h"
59 #include "selection.h"
60 
61 #include "draw-gdk.h"
62 #include "draw.h"
63 
64 #include "pick-and-place.h"
65 #include "gerb_stats.h"
66 
67 /* DEBUG printing. #define DEBUG 1 in config.h to use this fcn. */
68 #undef DPRINTF
69 #define DPRINTF(...) do { if (DEBUG) printf(__VA_ARGS__); } while (0)
70 
73 {
74  /* These are the names of the valid apertures. Please keep this in
75  * sync with the gerbv_aperture_type_t enum defined in gerbv.h */
76  const char *names[] = {
77  N_("none"),
78  N_("circle"),
79  N_("rectangle"),
80  N_("oval"), /* ovular (obround) aperture */
81  N_("polygon"), /* polygon aperture */
82  N_("macro"), /* RS274X macro */
83  N_("circle macro"), /* RS274X circle macro */
84  N_("outline macro"), /* RS274X outline macro */
85  N_("polygon macro"), /* RS274X polygon macro */
86  N_("moire macro"), /* RS274X moire macro */
87  N_("thermal macro"), /* RS274X thermal macro */
88  N_("line20 macro"), /* RS274X line (code 20) macro */
89  N_("line21 macro"), /* RS274X line (code 21) macro */
90  N_("line22 macro"), /* RS274X line (code 22) macro */
91  N_("block"), /* block aperture (AB command) */
92  };
93 
94  if (type >=0 && type < sizeof(names)/sizeof(names[0]))
95  return names[type];
96 
97  return N_("<undefined>");
98 }
99 
101 {
102  const char* names[] = {
103  N_("off"),
104  N_("on"),
105  N_("flash"),
106  };
107 
108  if (state >= 0 && state < sizeof(names) / sizeof(names[0])) {
109  return names[state];
110  }
111 
112  return N_("<undefined>");
113 }
114 
117 {
118  /* These are the names of the interpolation method. Please keep this
119  * in sync with the gerbv_interpolation_t enum defined in gerbv.h */
120  const char *names[] = {
121  N_("1X linear"),
122  N_("10X linear"),
123  N_("0.1X linear"),
124  N_("0.01X linear"),
125  N_("CW circular"),
126  N_("CCW circular"),
127  N_("poly area start"),
128  N_("poly area stop"),
129  N_("deleted"),
130  };
131 
132  if (interp >= 0 && interp < sizeof(names)/sizeof(names[0]))
133  return names[interp];
134 
135  return N_("<undefined>");
136 }
137 
138 #define NUMBER_OF_DEFAULT_COLORS 18
139 #define NUMBER_OF_DEFAULT_TRANSFORMATIONS 20
140 
141 static int defaultColorIndex = 0;
142 
143 /* ------------------------------------------------------------------ */
144 static gerbv_layer_color defaultColors[NUMBER_OF_DEFAULT_COLORS] = {
145  {115,115,222,177},
146  {255,127,115,177},
147  {193,0,224,177},
148  {117,242,103,177},
149  {0,195,195,177},
150  {213,253,51,177},
151  {209,27,104,177},
152  {255,197,51,177},
153  {186,186,186,177},
154  {211,211,255,177},
155  {253,210,206,177},
156  {236,194,242,177},
157  {208,249,204,177},
158  {183,255,255,177},
159  {241,255,183,177},
160  {255,202,225,177},
161  {253,238,197,177},
162  {226,226,226,177}
163 };
164 
165 /* ------------------------------------------------------------------ */
166 static gerbv_user_transformation_t defaultTransformations[NUMBER_OF_DEFAULT_TRANSFORMATIONS] = {
167  {0,0,1,1,0,FALSE,FALSE,FALSE},
168  {0,0,1,1,0,FALSE,FALSE,FALSE},
169  {0,0,1,1,0,FALSE,FALSE,FALSE},
170  {0,0,1,1,0,FALSE,FALSE,FALSE},
171  {0,0,1,1,0,FALSE,FALSE,FALSE},
172  {0,0,1,1,0,FALSE,FALSE,FALSE},
173  {0,0,1,1,0,FALSE,FALSE,FALSE},
174  {0,0,1,1,0,FALSE,FALSE,FALSE},
175  {0,0,1,1,0,FALSE,FALSE,FALSE},
176  {0,0,1,1,0,FALSE,FALSE,FALSE},
177  {0,0,1,1,0,FALSE,FALSE,FALSE},
178  {0,0,1,1,0,FALSE,FALSE,FALSE},
179  {0,0,1,1,0,FALSE,FALSE,FALSE},
180  {0,0,1,1,0,FALSE,FALSE,FALSE},
181  {0,0,1,1,0,FALSE,FALSE,FALSE},
182  {0,0,1,1,0,FALSE,FALSE,FALSE},
183  {0,0,1,1,0,FALSE,FALSE,FALSE},
184  {0,0,1,1,0,FALSE,FALSE,FALSE},
185  {0,0,1,1,0,FALSE,FALSE,FALSE},
186  {0,0,1,1,0,FALSE,FALSE,FALSE},
187 };
188 
189 /* ------------------------------------------------------------------ */
192  gerbv_project_t *returnProject= (gerbv_project_t *) g_new0(gerbv_project_t,1);
193 
194  /* default to using the current directory path for our starting guesses
195  on future file loads */
196  returnProject->path = g_get_current_dir ();
197  /* Will be updated to 0 when first Gerber is loaded */
198  returnProject->last_loaded = -1;
199  returnProject->max_files = 1;
200  returnProject->check_before_delete = TRUE;
201  returnProject->file = g_new0 (gerbv_fileinfo_t *, returnProject->max_files);
202 
203  return returnProject;
204 }
205 
206 /* ------------------------------------------------------------------ */
207 void
209 {
210  int i;
211 
212  /* destroy all the files attached to the project */
213  for(i = gerbvProject->last_loaded; i >= 0; i--) {
214  if (gerbvProject->file[i]) {
215  gerbv_destroy_fileinfo (gerbvProject->file[i]);
216  g_free(gerbvProject->file[i]);
217  }
218  }
219  /* destroy strings */
220  g_free (gerbvProject->path);
221  g_free (gerbvProject->execname);
222  g_free (gerbvProject->execpath);
223  g_free (gerbvProject->project);
224  /* destroy the fileinfo array */
225  g_free (gerbvProject->file);
226  g_free (gerbvProject);
227 }
228 
229 /* ------------------------------------------------------------------ */
230 void
232  gerbv_destroy_image (fileInfo->image);
233  g_free (fileInfo->fullPathname);
234  g_free (fileInfo->name);
235  if (fileInfo->privateRenderData) {
236  cairo_surface_destroy ((cairo_surface_t *)
237  fileInfo->privateRenderData);
238  }
239 }
240 
241 /* ------------------------------------------------------------------ */
242 void
243 gerbv_open_layer_from_filename(gerbv_project_t *gerbvProject, gchar const* filename)
244 {
245  gint idx_loaded;
246  DPRINTF("Opening filename = %s\n", filename);
247 
248  if (gerbv_open_image(gerbvProject, filename, ++gerbvProject->last_loaded, FALSE, NULL, 0, TRUE) == -1) {
249  GERB_COMPILE_WARNING(_("Could not read \"%s\" (loaded %d)"),
250  filename, gerbvProject->last_loaded);
251  gerbvProject->last_loaded--;
252  } else {
253  idx_loaded = gerbvProject->last_loaded;
254  gerbvProject->file[idx_loaded]->layer_dirty = FALSE;
255  DPRINTF(" Successfully opened file!\n");
256  }
257 } /* gerbv_open_layer_from_filename */
258 
259 /* ------------------------------------------------------------------ */
260 void
261 gerbv_open_layer_from_filename_with_color(gerbv_project_t *gerbvProject, gchar const* filename,
262  guint16 red, guint16 green, guint16 blue, guint16 alpha)
263 {
264  gint idx_loaded;
265  DPRINTF("Opening filename = %s\n", filename);
266 
267  if (gerbv_open_image(gerbvProject, filename, ++gerbvProject->last_loaded, FALSE, NULL, 0, TRUE) == -1) {
268  GERB_COMPILE_WARNING(_("Could not read \"%s\" (loaded %d)"),
269  filename, gerbvProject->last_loaded);
270  gerbvProject->last_loaded--;
271  } else {
272  idx_loaded = gerbvProject->last_loaded;
273  gerbvProject->file[idx_loaded]->layer_dirty = FALSE;
274  GdkColor colorTemplate = {0, red, green, blue};
275  gerbvProject->file[idx_loaded]->color = colorTemplate;
276  gerbvProject->file[idx_loaded]->alpha = alpha;
277  DPRINTF(" Successfully opened file!\n");
278  }
279 } /* gerbv_open_layer_from_filename_with_color */
280 
281 /* ------------------------------------------------------------------ */
282 gboolean
283 gerbv_save_layer_from_index(gerbv_project_t *gerbvProject, gint index, gchar *filename)
284 {
285  gerbv_fileinfo_t *file = gerbvProject->file[index];
286  gerbv_user_transformation_t *trans = &file->transform;
287 
288  switch (file->image->layertype) {
290  if (trans) {
291  /* NOTE: mirrored file is not yet supported */
292  if (trans->mirrorAroundX || trans->mirrorAroundY) {
293  GERB_COMPILE_ERROR(_("Exporting mirrored file "
294  "is not supported!"));
295  return FALSE;
296  }
297 
298  /* NOTE: inverted file is not yet supported */
299  if (trans->inverted) {
300  GERB_COMPILE_ERROR(_("Exporting inverted file "
301  "is not supported!"));
302  return FALSE;
303  }
304  }
305 
307  file->image, trans);
308  break;
309 
311  if (trans) {
312  /* NOTE: inverted file is not yet supported */
313  if (trans->inverted) {
314  GERB_COMPILE_ERROR(_("Exporting inverted file "
315  "is not supported!"));
316  return FALSE;
317  }
318  }
319 
321  file->image, trans);
322  break;
323  default:
324  return FALSE;
325  }
326 
327  file->layer_dirty = FALSE;
328 
329  return TRUE;
330 }
331 
332 
333 /* ------------------------------------------------------------------ */
334 int
335 gerbv_revert_file(gerbv_project_t *gerbvProject, int idx){
336  int rv;
337 
338  rv = gerbv_open_image(gerbvProject, gerbvProject->file[idx]->fullPathname, idx, TRUE, NULL, 0, TRUE);
339  gerbvProject->file[idx]->layer_dirty = FALSE;
340  return rv;
341 }
342 
343 /* ------------------------------------------------------------------ */
344 void
345 gerbv_revert_all_files(gerbv_project_t *gerbvProject)
346 {
347  int idx;
348 
349  for (idx = 0; idx <= gerbvProject->last_loaded; idx++) {
350  if (gerbvProject->file[idx] && gerbvProject->file[idx]->fullPathname) {
351  (void) gerbv_revert_file (gerbvProject, idx);
352  gerbvProject->file[idx]->layer_dirty = FALSE;
353  }
354  }
355 } /* gerbv_revert_all_files */
356 
357 /* ------------------------------------------------------------------ */
358 void
359 gerbv_unload_layer(gerbv_project_t *gerbvProject, int index)
360 {
361  gint i;
362 
363  gerbv_destroy_fileinfo (gerbvProject->file[index]);
364  g_free (gerbvProject->file[index]);
365 
366  /* slide all later layers down to fill the empty slot */
367  for (i=index; i<(gerbvProject->last_loaded); i++) {
368  gerbvProject->file[i]=gerbvProject->file[i+1];
369  }
370  /* make sure the final spot is clear */
371  gerbvProject->file[gerbvProject->last_loaded] = NULL;
372  gerbvProject->last_loaded--;
373 } /* gerbv_unload_layer */
374 
375 /* ------------------------------------------------------------------ */
376 void
377 gerbv_unload_all_layers (gerbv_project_t *gerbvProject)
378 {
379  int index;
380 
381  /* Must count down since gerbv_unload_layer collapses
382  * layers down. Otherwise, layers slide past the index */
383  for (index = gerbvProject->last_loaded ; index >= 0; index--) {
384  if (gerbvProject->file[index] && gerbvProject->file[index]->name) {
385  gerbv_unload_layer (gerbvProject, index);
386  }
387  }
388 } /* gerbv_unload_all_layers */
389 
390 
391 /* ------------------------------------------------------------------ */
392 void
393 gerbv_change_layer_order(gerbv_project_t *gerbvProject, gint oldPosition, gint newPosition)
394 {
395  gerbv_fileinfo_t *temp_file;
396  int index;
397 
398  temp_file = gerbvProject->file[oldPosition];
399 
400  if (oldPosition < newPosition){
401  for (index = oldPosition; index < newPosition; index++) {
402  gerbvProject->file[index] = gerbvProject->file[index + 1];
403  }
404  } else {
405  for (index = oldPosition; index > newPosition; index--) {
406  gerbvProject->file[index] = gerbvProject->file[index - 1];
407  }
408  }
409  gerbvProject->file[newPosition] = temp_file;
410 } /* gerbv_change_layer_order */
411 
412 
413 /* ------------------------------------------------------------------ */
414 gint
415 gerbv_add_parsed_image_to_project (gerbv_project_t *gerbvProject, gerbv_image_t *parsed_image,
416  gchar const* filename, gchar const* baseName, int idx, int reload){
417  gerb_verify_error_t error = GERB_IMAGE_OK;
418  int r, g, b;
419 
420  DPRINTF("In open_image, now error check file....\n");
421  error = gerbv_image_verify(parsed_image);
422 
423  if (error) {
424  if (error & GERB_IMAGE_MISSING_NETLIST) {
425  GERB_COMPILE_ERROR(_("Missing netlist - aborting file read"));
426  gerbv_destroy_image(parsed_image);
427  return -1;
428  }
429  /* if the error was one of the following, try to open up the file anyways in case
430  the file is a poorly formatted RS-274X file */
431  if (error & GERB_IMAGE_MISSING_FORMAT)
432  g_warning(_("Missing format in file...trying to load anyways\n"));
433  if (error & GERB_IMAGE_MISSING_APERTURES) {
434  g_warning(_("Missing apertures/drill sizes...trying to load anyways\n"));
435  /* step through the file and check for aperture references. For each one found, create
436  a dummy aperture holder to visually draw something on the screen */
437  gerbv_image_create_dummy_apertures (parsed_image);
438  }
439  if (error & GERB_IMAGE_MISSING_INFO)
440  g_warning(_("Missing info...trying to load anyways\n"));
441  }
442 
443  /*
444  * If reload, just exchange the image. Else we have to allocate
445  * a new memory before we define anything more.
446  */
447  if (reload) {
448  gerbv_destroy_image(gerbvProject->file[idx]->image);
449  gerbvProject->file[idx]->image = parsed_image;
450  return 0;
451  } else {
452  /* Load new file. */
453  gerbvProject->file[idx] = (gerbv_fileinfo_t *) g_new0 (gerbv_fileinfo_t, 1);
454  gerbvProject->file[idx]->image = parsed_image;
455  }
456 
457  /*
458  * Store filename for eventual reload
459  */
460  gerbvProject->file[idx]->fullPathname = g_strdup (filename);
461  gerbvProject->file[idx]->name = g_strdup (baseName);
462 
463 
464  r = defaultColors[defaultColorIndex % NUMBER_OF_DEFAULT_COLORS].red*257;
465  g = defaultColors[defaultColorIndex % NUMBER_OF_DEFAULT_COLORS].green*257;
466  b = defaultColors[defaultColorIndex % NUMBER_OF_DEFAULT_COLORS].blue*257;
467 
468  GdkColor colorTemplate = {0, r, g, b};
469  gerbvProject->file[idx]->color = colorTemplate;
470  gerbvProject->file[idx]->alpha = defaultColors[defaultColorIndex % NUMBER_OF_DEFAULT_COLORS].alpha*257;
471  gerbvProject->file[idx]->isVisible = TRUE;
472  gerbvProject->file[idx]->transform = defaultTransformations[defaultColorIndex % NUMBER_OF_DEFAULT_TRANSFORMATIONS];
473  /* update the number of files if we need to */
474  if (gerbvProject->last_loaded <= idx) {
475  gerbvProject->last_loaded = idx;
476  }
477  defaultColorIndex++;
478  return 1;
479 }
480 
481 /* ------------------------------------------------------------------ */
482 int
483 gerbv_open_image(gerbv_project_t *gerbvProject, gchar const* filename, int idx, int reload,
484  gerbv_HID_Attribute *fattr, int n_fattr, gboolean forceLoadFile)
485 {
486  gerb_file_t *fd;
487  gerbv_image_t *parsed_image = NULL, *parsed_image2 = NULL;
488  gint retv = -1;
489  gboolean isPnpFile = FALSE, foundBinary;
490  gerbv_HID_Attribute *attr_list = NULL;
491  int n_attr = 0;
492  /* If we're reloading, we'll pass in our file format attribute list
493  * since this is our hook for letting the user override the fileformat.
494  */
495  if (reload)
496  {
497  /* We're reloading so use the attribute list in memory */
498  attr_list = gerbvProject->file[idx]->image->info->attr_list;
499  n_attr = gerbvProject->file[idx]->image->info->n_attr;
500  }
501  else
502  {
503  /* We're not reloading so use the attribute list read from the
504  * project file if given or NULL otherwise.
505  */
506  attr_list = fattr;
507  n_attr = n_fattr;
508  }
509  /* if we don't have enough spots, then grow the file list by 2 to account for the possible
510  loading of two images for PNP files */
511  if ((idx+1) >= gerbvProject->max_files) {
512  gerbvProject->file = g_renew (gerbv_fileinfo_t *,
513  gerbvProject->file, gerbvProject->max_files + 2);
514 
515  gerbvProject->file[gerbvProject->max_files] = NULL;
516  gerbvProject->file[gerbvProject->max_files+1] = NULL;
517  gerbvProject->max_files += 2;
518  }
519 
520  DPRINTF("In open_image, about to try opening filename = %s\n", filename);
521 
522  fd = gerb_fopen(filename);
523  if (fd == NULL) {
524  GERB_COMPILE_ERROR(_("Trying to open \"%s\": %s"),
525  filename, strerror(errno));
526  return -1;
527  }
528 
529  DPRINTF("In open_image, successfully opened file. Now check its type....\n");
530  /* Here's where we decide what file type we have */
531  /* Note: if the file has some invalid characters in it but still appears to
532  be a valid file, we check with the user if he wants to continue (only
533  if user opens the layer from the menu...if from the command line, we go
534  ahead and try to load it anyways) */
535 
536  if (gerber_is_rs274x_p(fd, &foundBinary)) {
537  DPRINTF("Found RS-274X file\n");
538  if (!foundBinary || forceLoadFile) {
539  /* figure out the directory path in case parse_gerb needs to
540  * load any include files */
541  gchar *currentLoadDirectory = g_path_get_dirname (filename);
542  parsed_image = parse_gerb(fd, currentLoadDirectory);
543  g_free (currentLoadDirectory);
544  }
545  } else if(drill_file_p(fd, &foundBinary)) {
546  DPRINTF("Found drill file\n");
547  if (!foundBinary || forceLoadFile)
548  parsed_image = parse_drillfile(fd, attr_list, n_attr, reload);
549 
550  } else if (pick_and_place_check_file_type(fd, &foundBinary)) {
551  DPRINTF("Found pick-n-place file\n");
552  if (!foundBinary || forceLoadFile) {
553  if (!reload) {
554  pick_and_place_parse_file_to_images(fd, &parsed_image, &parsed_image2);
555  } else {
556  switch (gerbvProject->file[idx]->image->layertype) {
558  /* Non NULL pointer is used as "not to reload" mark */
559  // parsed_image2 = (void *)!NULL;
561  parsed_image2 = (void *)1;
562  pick_and_place_parse_file_to_images(fd, &parsed_image, &parsed_image2);
563  parsed_image2 = NULL;
564  break;
566  /* Non NULL pointer is used as "not to reload" mark */
567  // parsed_image2 = (void *)!NULL;
569  parsed_image2 = (void *)1;
570  pick_and_place_parse_file_to_images(fd, &parsed_image2, &parsed_image);
571  parsed_image2 = NULL;
572  break;
573  default:
574  GERB_COMPILE_ERROR(_("%s: unknown pick-and-place board side to reload"), filename);
575  }
576  }
577 
578  isPnpFile = TRUE;
579  }
580  } else if (gerber_is_rs274d_p(fd)) {
581  gchar *str = g_strdup_printf(_("Most likely found a RS-274D file "
582  "\"%s\" ... trying to open anyways\n"), filename);
583  DPRINTF("%s", str);
584  g_warning("%s", str);
585  g_free (str);
586 
587  if (!foundBinary || forceLoadFile) {
588  /* figure out the directory path in case parse_gerb needs to
589  * load any include files */
590  gchar *currentLoadDirectory = g_path_get_dirname (filename);
591  parsed_image = parse_gerb(fd, currentLoadDirectory);
592  g_free (currentLoadDirectory);
593  }
594  } else {
595  /* This is not a known file */
596  DPRINTF("Unknown filetype");
597  GERB_COMPILE_ERROR(_("%s: Unknown file type."), filename);
598  parsed_image = NULL;
599  }
600 
601  gerb_fclose(fd);
602  if (parsed_image == NULL) {
603  return -1;
604  }
605 
606  if (parsed_image) {
607  /* Warn if the file parsed successfully but contains no geometry */
608  if ((parsed_image->netlist != NULL)
609  && (parsed_image->netlist->next == NULL)) {
610  if ((parsed_image->layertype == GERBV_LAYERTYPE_DRILL)
611  && (parsed_image->drill_stats != NULL)) {
612  gerbv_stats_printf(
613  parsed_image->drill_stats->error_list,
615  _("File \"%s\" contains no drill hits or routes"),
616  filename);
617  } else if (parsed_image->gerbv_stats != NULL) {
618  gerbv_stats_printf(
619  parsed_image->gerbv_stats->error_list,
621  _("File \"%s\" contains no drawing elements"),
622  filename);
623  }
624  }
625 
626  /* strip the filename to the base */
627  gchar *baseName = g_path_get_basename (filename);
628  gchar *displayedName;
629  if (isPnpFile)
630  displayedName = g_strconcat (baseName, _(" (top)"), NULL);
631  else
632  displayedName = g_strdup (baseName);
633  retv = gerbv_add_parsed_image_to_project (gerbvProject, parsed_image, filename, displayedName, idx, reload);
634  g_free (baseName);
635  g_free (displayedName);
636  }
637 
638  /* Set layer_dirty flag to FALSE */
639  gerbvProject->file[idx]->layer_dirty = FALSE;
640 
641  /* for PNP place files, we may need to add a second image for the other
642  board side */
643  if (parsed_image2) {
644  /* strip the filename to the base */
645  gchar *baseName = g_path_get_basename (filename);
646  gchar *displayedName;
647  displayedName = g_strconcat (baseName, _(" (bottom)"), NULL);
648  retv = gerbv_add_parsed_image_to_project (gerbvProject, parsed_image2, filename, displayedName, idx + 1, reload);
649  g_free (baseName);
650  g_free (displayedName);
651  }
652 
653  return retv;
654 } /* open_image */
655 
656 gboolean
657 gerbv_is_loadable_file(const char *filename)
658 {
659  gerb_file_t *fd;
660  gboolean foundBinary;
661 
662  fd = gerb_fopen(filename);
663  if (fd == NULL)
664  return FALSE;
665 
666  gboolean loadable = gerber_is_rs274x_p(fd, &foundBinary)
667  || drill_file_p(fd, &foundBinary)
668  || pick_and_place_check_file_type(fd, &foundBinary)
669  || gerber_is_rs274d_p(fd);
670 
671  gerb_fclose(fd);
672  return loadable;
673 }
674 
677 {
678  gerbv_image_t *returnImage;
679  gerb_file_t *fd;
680 
681  fd = gerb_fopen(filename);
682  if (fd == NULL) {
683  GERB_COMPILE_ERROR(_("Trying to open \"%s\": %s"),
684  filename, strerror(errno));
685  return NULL;
686  }
687  returnImage = parse_drillfile(fd, NULL, 0, 0);
688  gerb_fclose(fd);
689  return returnImage;
690 } /* gerbv_create_excellon_image_from_filename */
691 
694  gerbv_image_t *returnImage;
695  gerb_file_t *fd;
696 
697  fd = gerb_fopen(filename);
698  if (fd == NULL) {
699  GERB_COMPILE_ERROR(_("Trying to open \"%s\": %s"),
700  filename, strerror(errno));
701  return NULL;
702  }
703  gchar *currentLoadDirectory = g_path_get_dirname (filename);
704  returnImage = parse_gerb(fd, currentLoadDirectory);
705  g_free (currentLoadDirectory);
706  gerb_fclose(fd);
707  return returnImage;
708 }
709 
710 static inline int isnormal_or_zero(double x)
711 {
712  int cl = fpclassify(x);
713  return cl == FP_NORMAL || cl == FP_ZERO;
714 }
715 
716 /* ------------------------------------------------------------------ */
717 void
718 gerbv_render_get_boundingbox(gerbv_project_t *gerbvProject, gerbv_render_size_t *boundingbox)
719 {
720  double x1=HUGE_VAL,y1=HUGE_VAL, x2=-HUGE_VAL,y2=-HUGE_VAL;
721  int i;
722  gerbv_image_info_t *info;
723  gdouble minX, minY, maxX, maxY;
724 
725  for(i = 0; i <= gerbvProject->last_loaded; i++) {
726  if (gerbvProject->file[i] && gerbvProject->file[i]->isVisible){
727 
728 
729  info = gerbvProject->file[i]->image->info;
730  /*
731  * Find the biggest image and use as a size reference
732  */
733  /* cairo info already has offset calculated into min/max */
734 
735  minX = info->min_x;
736  minY = info->min_y;
737  maxX = info->max_x;
738  maxY = info->max_y;
739 
740  if (!isnormal_or_zero(minX) || !isnormal_or_zero(minY)
741  || !isnormal_or_zero(maxX) || !isnormal_or_zero(maxY)) {
742  continue;
743  }
744 
745  /* transform the bounding box based on the user transform */
746  cairo_matrix_t fullMatrix;
747  cairo_matrix_init (&fullMatrix, 1, 0, 0, 1, 0, 0);
748 
749  cairo_matrix_translate (&fullMatrix, gerbvProject->file[i]->transform.translateX,
750  gerbvProject->file[i]->transform.translateY);
751  // don't use mirroring for the scale matrix
752  gdouble scaleX = gerbvProject->file[i]->transform.scaleX;
753  gdouble scaleY = gerbvProject->file[i]->transform.scaleY;
754  if (gerbvProject->file[i]->transform.mirrorAroundX)
755  scaleY *= -1;
756  if (gerbvProject->file[i]->transform.mirrorAroundY)
757  scaleX *= -1;
758  cairo_matrix_scale (&fullMatrix, scaleX, scaleY);
759  cairo_matrix_rotate (&fullMatrix, gerbvProject->file[i]->transform.rotation);
760 
761  cairo_matrix_transform_point (&fullMatrix, &minX, &minY);
762  cairo_matrix_transform_point (&fullMatrix, &maxX, &maxY);
763  /* compare to both min and max, since a mirror transform may have made the "max"
764  number smaller than the "min" */
765  x1 = MIN(x1, minX);
766  x1 = MIN(x1, maxX);
767  y1 = MIN(y1, minY);
768  y1 = MIN(y1, maxY);
769  x2 = MAX(x2, minX);
770  x2 = MAX(x2, maxX);
771  y2 = MAX(y2, minY);
772  y2 = MAX(y2, maxY);
773  }
774  }
775  boundingbox->left = x1;
776  boundingbox->right = x2;
777  boundingbox->top = y1;
778  boundingbox->bottom = y2;
779 }
780 
781 /* ------------------------------------------------------------------ */
782 void
784 {
786  double width, height;
787  double x_scale, y_scale;
788 
789  /* Grab maximal width and height of all layers */
790  gerbv_render_get_boundingbox(gerbvProject, &bb);
791  width = bb.right - bb.left;
792  height = bb.bottom - bb.top;
793  /* add in a 5% buffer around the drawing */
794  width *= 1.05;
795  height *=1.05;
796 
797  /* if the values aren't sane (probably we have no models loaded), then
798  put in some defaults */
799  if (!isnormal(width)||!isnormal(height)||((width < 0.01) && (height < 0.01))) {
800  renderInfo->lowerLeftX = 0.0;
801  renderInfo->lowerLeftY = 0.0;
802  renderInfo->scaleFactorX = 200;
803  renderInfo->scaleFactorY = renderInfo->scaleFactorX;
804  return;
805  }
806  /*
807  * Calculate scale for both x axis and y axis
808  */
809  x_scale = renderInfo->displayWidth / width;
810  y_scale = renderInfo->displayHeight / height;
811  /*
812  * Take the scale that fits both directions with some extra checks
813  */
814  renderInfo->scaleFactorX = MIN(x_scale, y_scale);
815  renderInfo->scaleFactorX = MIN((gdouble)GERBV_SCALE_MAX,
816  renderInfo->scaleFactorX);
817  renderInfo->scaleFactorX = MAX((gdouble)GERBV_SCALE_MIN,
818  renderInfo->scaleFactorX);
819  renderInfo->scaleFactorY = renderInfo->scaleFactorX;
820  renderInfo->lowerLeftX = ((bb.left + bb.right) / 2.0) -
821  ((double) renderInfo->displayWidth / 2.0 / renderInfo->scaleFactorX);
822  renderInfo->lowerLeftY = ((bb.top + bb.bottom) / 2.0) -
823  ((double) renderInfo->displayHeight / 2.0 / renderInfo->scaleFactorY);
824 }
825 
826 /* ------------------------------------------------------------------ */
827 void
828 gerbv_render_translate_to_fit_display (gerbv_project_t *gerbvProject, gerbv_render_info_t *renderInfo) {
830 
831  /* Grab maximal width and height of all layers */
832  gerbv_render_get_boundingbox(gerbvProject, &bb);
833  renderInfo->lowerLeftX = ((bb.left + bb.right) / 2.0) -
834  ((double) renderInfo->displayWidth / 2.0 / renderInfo->scaleFactorX);
835  renderInfo->lowerLeftY = ((bb.top + bb.bottom) / 2.0) -
836  ((double) renderInfo->displayHeight / 2.0 / renderInfo->scaleFactorY);
837 }
838 
839 /* ------------------------------------------------------------------ */
840 void
841 gerbv_render_to_pixmap_using_gdk (gerbv_project_t *gerbvProject, GdkPixmap *pixmap,
842  gerbv_render_info_t *renderInfo, gerbv_selection_info_t *selectionInfo,
843  GdkColor *selectionColor){
844  GdkGC *gc = gdk_gc_new(pixmap);
845  GdkPixmap *colorStamp, *clipmask;
846  int i;
847 
848  /*
849  * Remove old pixmap, allocate a new one, draw the background.
850  */
851  if (!gerbvProject->background.pixel)
852  gdk_colormap_alloc_color(gdk_colormap_get_system(), &gerbvProject->background, FALSE, TRUE);
853  gdk_gc_set_foreground(gc, &gerbvProject->background);
854  gdk_draw_rectangle(pixmap, gc, TRUE, 0, 0, -1, -1);
855 
856  /*
857  * Allocate the pixmap and the clipmask (a one pixel pixmap)
858  */
859  colorStamp = gdk_pixmap_new(pixmap, renderInfo->displayWidth,
860  renderInfo->displayHeight, -1);
861  clipmask = gdk_pixmap_new(NULL, renderInfo->displayWidth,
862  renderInfo->displayHeight, 1);
863 
864  /*
865  * This now allows drawing several layers on top of each other.
866  * Higher layer numbers have higher priority in the Z-order.
867  */
868  for(i = gerbvProject->last_loaded; i >= 0; i--) {
869  if (gerbvProject->file[i] && gerbvProject->file[i]->isVisible) {
870  /*
871  * Fill up image with all the foreground color. Excess pixels
872  * will be removed by clipmask.
873  */
874  if (!gerbvProject->file[i]->color.pixel)
875  gdk_colormap_alloc_color(gdk_colormap_get_system(), &gerbvProject->file[i]->color, FALSE, TRUE);
876  gdk_gc_set_foreground(gc, &gerbvProject->file[i]->color);
877 
878  /* switch back to regular draw function for the initial
879  bitmap clear */
880  gdk_gc_set_function(gc, GDK_COPY);
881  gdk_draw_rectangle(colorStamp, gc, TRUE, 0, 0, -1, -1);
882 
883  if (renderInfo->renderType == GERBV_RENDER_TYPE_GDK) {
884  gdk_gc_set_function(gc, GDK_COPY);
885  }
886  else if (renderInfo->renderType == GERBV_RENDER_TYPE_GDK_XOR) {
887  gdk_gc_set_function(gc, GDK_XOR);
888  }
889  /*
890  * Translation is to get it inside the allocated pixmap,
891  * which is not always centered perfectly for GTK/X.
892  */
893  DPRINTF(" .... calling image2pixmap on image %d...\n", i);
894  // Dirty scaling solution when using GDK; simply use scaling factor for x-axis, ignore y-axis
895  draw_gdk_image_to_pixmap(&clipmask, gerbvProject->file[i]->image,
896  renderInfo->scaleFactorX, -(renderInfo->lowerLeftX * renderInfo->scaleFactorX),
897  (renderInfo->lowerLeftY * renderInfo->scaleFactorY) + renderInfo->displayHeight,
898  DRAW_IMAGE, NULL, renderInfo, gerbvProject->file[i]->transform);
899 
900  /*
901  * Set clipmask and draw the clipped out image onto the
902  * screen pixmap. Afterwards we remove the clipmask, else
903  * it will screw things up when run this loop again.
904  */
905  gdk_gc_set_clip_mask(gc, clipmask);
906  gdk_gc_set_clip_origin(gc, 0, 0);
907  gdk_draw_drawable(pixmap, gc, colorStamp, 0, 0, 0, 0, -1, -1);
908  gdk_gc_set_clip_mask(gc, NULL);
909  }
910  }
911 
912  /* Render the selection group to the top of the output */
913  if (selectionInfo && selectionInfo->selectedNodeArray
914  && (selection_length (selectionInfo) != 0)) {
915  if (!selectionColor->pixel)
916  gdk_colormap_alloc_color(gdk_colormap_get_system(), selectionColor, FALSE, TRUE);
917 
918  gdk_gc_set_foreground(gc, selectionColor);
919  gdk_gc_set_function(gc, GDK_COPY);
920  gdk_draw_rectangle(colorStamp, gc, TRUE, 0, 0, -1, -1);
921 
922  gerbv_selection_item_t sItem;
923  gerbv_fileinfo_t *file;
924  int j;
925  guint k;
926 
927  for (j = gerbvProject->last_loaded; j >= 0; j--) {
928  file = gerbvProject->file[j];
929  if (!file || (!gerbvProject->show_invisible_selection && !file->isVisible))
930  continue;
931 
932  for (k = 0; k < selection_length (selectionInfo); k++) {
933  sItem = selection_get_item_by_index (selectionInfo, k);
934 
935  if (file->image != sItem.image)
936  continue;
937 
938  /* Have selected image(s) on this layer, draw it */
939  draw_gdk_image_to_pixmap(&clipmask, file->image,
940  renderInfo->scaleFactorX,
941  -(renderInfo->lowerLeftX * renderInfo->scaleFactorX),
942  (renderInfo->lowerLeftY * renderInfo->scaleFactorY) + renderInfo->displayHeight,
943  DRAW_SELECTIONS, selectionInfo,
944  renderInfo, file->transform);
945 
946  gdk_gc_set_clip_mask(gc, clipmask);
947  gdk_gc_set_clip_origin(gc, 0, 0);
948  gdk_draw_drawable(pixmap, gc, colorStamp, 0, 0, 0, 0, -1, -1);
949  gdk_gc_set_clip_mask(gc, NULL);
950 
951  break;
952  }
953  }
954  }
955 
956  gdk_pixmap_unref(colorStamp);
957  gdk_pixmap_unref(clipmask);
958  gdk_gc_unref(gc);
959 }
960 
961 /* ------------------------------------------------------------------ */
962 void
963 gerbv_render_all_layers_to_cairo_target_for_vector_output (
964  gerbv_project_t *gerbvProject, cairo_t *cr,
965  gerbv_render_info_t *renderInfo)
966 {
967  GdkColor *bg = &gerbvProject->background;
968  int i;
969  double r, g, b;
970 
971  gerbv_render_cairo_set_scale_and_translation (cr, renderInfo);
972 
973  /* Fill the background with the appropriate not white and not black
974  * color for backward culpability. */
975  if ((bg->red != 0xffff || bg->green != 0xffff || bg->blue != 0xffff)
976  && (bg->red != 0x0000 || bg->green != 0x0000 || bg->blue != 0x0000)) {
977  r = (double) bg->red/G_MAXUINT16;
978  g = (double) bg->green/G_MAXUINT16;
979  b = (double) bg->blue/G_MAXUINT16;
980  cairo_set_source_rgba (cr, r, g, b, 1);
981  cairo_paint (cr);
982 
983  /* Set cairo user data with background color information, to be
984  * used for clear color. */
985  cairo_set_user_data (cr, (cairo_user_data_key_t *)0, &r, NULL);
986  cairo_set_user_data (cr, (cairo_user_data_key_t *)1, &g, NULL);
987  cairo_set_user_data (cr, (cairo_user_data_key_t *)2, &b, NULL);
988  }
989 
990  for (i = gerbvProject->last_loaded; i >= 0; i--) {
991  if (gerbvProject->file[i] && gerbvProject->file[i]->isVisible) {
992  gerbv_render_layer_to_cairo_target_without_transforming(
993  cr, gerbvProject->file[i],
994  renderInfo, FALSE);
995  }
996  }
997 }
998 
999 /* ------------------------------------------------------------------ */
1000 void
1001 gerbv_render_all_layers_to_cairo_target (gerbv_project_t *gerbvProject,
1002  cairo_t *cr, gerbv_render_info_t *renderInfo)
1003 {
1004  int i;
1005 
1006  /* Fill the background with the appropriate color. */
1007  cairo_set_source_rgba (cr,
1008  (double) gerbvProject->background.red/G_MAXUINT16,
1009  (double) gerbvProject->background.green/G_MAXUINT16,
1010  (double) gerbvProject->background.blue/G_MAXUINT16, 1);
1011  cairo_paint (cr);
1012 
1013  for (i = gerbvProject->last_loaded; i >= 0; i--) {
1014  if (gerbvProject->file[i] && gerbvProject->file[i]->isVisible) {
1015  cairo_push_group (cr);
1017  gerbvProject->file[i], renderInfo);
1018  cairo_pop_group_to_source (cr);
1019  cairo_paint_with_alpha (cr, (double)
1020  gerbvProject->file[i]->alpha/G_MAXUINT16);
1021  }
1022  }
1023 }
1024 
1025 /* ------------------------------------------------------------------ */
1026 void
1028  gerbv_render_info_t *renderInfo) {
1029  gerbv_render_cairo_set_scale_and_translation(cr, renderInfo);
1030  gerbv_render_layer_to_cairo_target_without_transforming(cr, fileInfo, renderInfo, TRUE);
1031 }
1032 
1033 /* ------------------------------------------------------------------ */
1034 void
1035 gerbv_render_cairo_set_scale_and_translation(cairo_t *cr, gerbv_render_info_t *renderInfo){
1036  gdouble translateX, translateY;
1037 
1038  translateX = (renderInfo->lowerLeftX * renderInfo->scaleFactorX);
1039  translateY = (renderInfo->lowerLeftY * renderInfo->scaleFactorY);
1040 
1041  /* renderTypes 0 and 1 use GDK rendering, so we shouldn't have made it
1042  this far */
1043  if (renderInfo->renderType == GERBV_RENDER_TYPE_CAIRO_NORMAL) {
1044  cairo_set_tolerance (cr, 1.0);
1045  cairo_set_antialias (cr, CAIRO_ANTIALIAS_NONE);
1046  }
1047  else if (renderInfo->renderType == GERBV_RENDER_TYPE_CAIRO_HIGH_QUALITY) {
1048  cairo_set_tolerance (cr, 0.1);
1049  cairo_set_antialias (cr, CAIRO_ANTIALIAS_DEFAULT);
1050  }
1051 
1052  /* translate the draw area before drawing. We must translate the whole
1053  drawing down an additional displayHeight to account for the negative
1054  y flip done later */
1055  cairo_translate (cr, -translateX, translateY + renderInfo->displayHeight);
1056  /* scale the drawing by the specified scale factor (inverting y since
1057  cairo y axis points down) */
1058  cairo_scale (cr, renderInfo->scaleFactorX, -renderInfo->scaleFactorY);
1059 }
1060 
1061 /* ------------------------------------------------------------------ */
1062 void
1063 gerbv_render_layer_to_cairo_target_without_transforming(cairo_t *cr, gerbv_fileinfo_t *fileInfo, gerbv_render_info_t *renderInfo, gboolean pixelOutput) {
1064  cairo_set_source_rgba (cr, (double) fileInfo->color.red/G_MAXUINT16,
1065  (double) fileInfo->color.green/G_MAXUINT16,
1066  (double) fileInfo->color.blue/G_MAXUINT16, 1);
1067 
1068  /* translate, rotate, and modify the image based on the layer-specific transformation struct */
1069  cairo_save (cr);
1070 
1071  draw_image_to_cairo_target (cr, fileInfo->image,
1072  1.0/MAX(renderInfo->scaleFactorX, renderInfo->scaleFactorY), DRAW_IMAGE, NULL,
1073  renderInfo, TRUE, fileInfo->transform, pixelOutput);
1074  cairo_restore (cr);
1075 }
1076 
1077 void
1078 gerbv_attribute_destroy_HID_attribute (gerbv_HID_Attribute *attributeList, int n_attr)
1079 {
1080  int i;
1081 
1082  /* free the string attributes and names */
1083  for (i = 0 ; i < n_attr ; i++) {
1084  if ( (attributeList[i].type == HID_String ||
1085  attributeList[i].type == HID_Label) &&
1086  attributeList[i].default_val.str_value != NULL) {
1087  free (attributeList[i].default_val.str_value);
1088  }
1089  if (attributeList[i].name != NULL) {
1090  free (attributeList[i].name);
1091  }
1092  }
1093 
1094  /* and free the attribute list */
1095  if (attributeList != NULL) {
1096  free (attributeList);
1097  }
1098 }
1099 
1100 
1101 /* allocate memory and make a copy of an attribute list */
1102 gerbv_HID_Attribute *
1103 gerbv_attribute_dup (gerbv_HID_Attribute *attributeList, int n_attr)
1104 {
1105  gerbv_HID_Attribute *nl;
1106  int i;
1107 
1108  nl = (gerbv_HID_Attribute *) malloc (n_attr * sizeof (gerbv_HID_Attribute));
1109  if (nl == NULL) {
1110  fprintf (stderr, "malloc failed in %s()\n", __FUNCTION__);
1111  exit (1);
1112  }
1113 
1114  /* deep-copy every entry: struct copy first, then strdup name and
1115  * string values so the copy owns all its memory independently */
1116  for (i = 0 ; i < n_attr ; i++) {
1117  nl[i] = attributeList[i];
1118  nl[i].name = attributeList[i].name ? strdup (attributeList[i].name) : NULL;
1119 
1120  if (attributeList[i].type == HID_String ||
1121  attributeList[i].type == HID_Label) {
1122  nl[i].default_val.str_value =
1123  attributeList[i].default_val.str_value
1124  ? strdup (attributeList[i].default_val.str_value) : NULL;
1125  }
1126  }
1127 
1128  return nl;
1129 }
1130 
1133  const gerbv_project_t *project)
1134 {
1135  int i;
1136 
1137  for (i = 0; i <= project->last_loaded; i++) {
1138  if (project->file[i]->image == image)
1139  return project->file[i];
1140  }
1141 
1142  return NULL;
1143 }
1144 
1145 inline void
1146 gerbv_rotate_coord(double *x, double *y, double rad)
1147 {
1148  double x0 = *x;
1149 
1150  *x = x0*cos(rad) - *y*sin(rad);
1151  *y = x0*sin(rad) + *y*cos(rad);
1152 }
1153 
1154 void
1155 gerbv_transform_coord(double *x, double *y,
1156  const gerbv_user_transformation_t *trans)
1157 {
1158 
1159  *x = trans->scaleX * *x;
1160  *y = trans->scaleY * *y;
1161 
1162  gerbv_rotate_coord(x, y, trans->rotation);
1163 
1164  if (trans->mirrorAroundY)
1165  *x = -*x;
1166 
1167  if (trans->mirrorAroundX)
1168  *y = -*y;
1169 
1170  *x += trans->translateX;
1171  *y += trans->translateY;
1172 }
1173 
1174 int
1175 gerbv_transform_coord_for_image(double *x, double *y,
1176  const gerbv_image_t *image, const gerbv_project_t *project)
1177 {
1178  gerbv_fileinfo_t *fileinfo =
1179  gerbv_get_fileinfo_for_image(image, project);
1180 
1181  if (fileinfo == NULL) {
1182  DPRINTF("%s(): NULL fileinfo\n", __func__);
1183  return -1;
1184  }
1185 
1186  gerbv_transform_coord(x, y, &fileinfo->transform);
1187 
1188  return 0;
1189 }
1190 
1191 gboolean
1192 gerbv_endswith(const char *path, const char *ext) {
1193  int plen = strlen(path);
1194  int elen = strlen(ext);
1195  if ( plen < elen ) return FALSE; // false if string too short to check
1196  return (strcmp(path+plen-elen, ext) == 0) ? TRUE // true if last chars match extension
1197  : FALSE;
1198 }
Header info for the GDK rendering functions.
Header info for the cairo rendering functions and the related selection calculating functions.
Header info for the Excellon drill parsing functions.
gboolean gerbv_export_drill_file_from_image(const gchar *filename, gerbv_image_t *inputImage, gerbv_user_transformation_t *transform)
Export an image to a new file in Excellon drill format.
Definition: export-drill.c:42
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:106
void gerbv_image_create_dummy_apertures(gerbv_image_t *parsed_image)
Create any missing apertures in the specified image.
Definition: gerb_image.c:1405
Header info for the statistics generating functions for RS274X files.
gboolean gerber_is_rs274d_p(gerb_file_t *fd)
Definition: gerber.c:927
gboolean gerber_is_rs274x_p(gerb_file_t *fd, gboolean *returnFoundBinary)
Definition: gerber.c:822
gerbv_image_t * parse_gerb(gerb_file_t *fd, gchar *directoryPath)
Definition: gerber.c:756
Header info for the RS274X parsing functions.
int gerbv_open_image(gerbv_project_t *gerbvProject, gchar const *filename, int idx, int reload, gerbv_HID_Attribute *fattr, int n_fattr, gboolean forceLoadFile)
Definition: gerbv.c:483
gerbv_image_t * gerbv_create_rs274x_image_from_filename(gchar const *filename)
Parse a RS274X file and return the parsed image.
Definition: gerbv.c:693
void gerbv_destroy_project(gerbv_project_t *gerbvProject)
Free a project and all related variables.
Definition: gerbv.c:208
const char * gerbv_interpolation_name(gerbv_interpolation_t interp)
Return string name of gerbv_interpolation_t interpolation.
Definition: gerbv.c:116
void gerbv_rotate_coord(double *x, double *y, double rad)
Definition: gerbv.c:1146
void gerbv_open_layer_from_filename_with_color(gerbv_project_t *gerbvProject, gchar const *filename, guint16 red, guint16 green, guint16 blue, guint16 alpha)
Open a file, parse the contents, and add a new layer to an existing project while setting the color o...
Definition: gerbv.c:261
gerbv_project_t * gerbv_create_project(void)
Create a new project structure and initialize some important variables.
Definition: gerbv.c:191
const char * gerbv_aperture_state_name(gerbv_aperture_state_t state)
Definition: gerbv.c:100
gboolean gerbv_is_loadable_file(const char *filename)
Definition: gerbv.c:657
gerbv_fileinfo_t * gerbv_get_fileinfo_for_image(const gerbv_image_t *image, const gerbv_project_t *project)
Definition: gerbv.c:1132
void gerbv_open_layer_from_filename(gerbv_project_t *gerbvProject, gchar const *filename)
Open a file, parse the contents, and add a new layer to an existing project.
Definition: gerbv.c:243
void gerbv_transform_coord(double *x, double *y, const gerbv_user_transformation_t *trans)
Definition: gerbv.c:1155
gboolean gerbv_endswith(const char *path, const char *ext)
Definition: gerbv.c:1192
void gerbv_destroy_fileinfo(gerbv_fileinfo_t *fileInfo)
Free a fileinfo structure.
Definition: gerbv.c:231
const char * gerbv_aperture_type_name(gerbv_aperture_type_t type)
Return string name of gerbv_aperture_type_t aperture type.
Definition: gerbv.c:72
void gerbv_render_zoom_to_fit_display(gerbv_project_t *gerbvProject, gerbv_render_info_t *renderInfo)
Calculate the zoom and translations to fit the rendered scene inside the given scene size.
Definition: gerbv.c:783
int gerbv_transform_coord_for_image(double *x, double *y, const gerbv_image_t *image, const gerbv_project_t *project)
Definition: gerbv.c:1175
gerbv_image_t * gerbv_create_excellon_image_from_filename(const gchar *filename)
Parse an Excellon drill file and return the parsed image.
Definition: gerbv.c:676
void gerbv_render_layer_to_cairo_target(cairo_t *cr, gerbv_fileinfo_t *fileInfo, gerbv_render_info_t *renderInfo)
Render a layer to a cairo context.
Definition: gerbv.c:1027
The main header file for the libgerbv library.
gerbv_aperture_state_t
Definition: gerbv.h:179
@ GERBV_RENDER_TYPE_CAIRO_HIGH_QUALITY
Definition: gerbv.h:371
@ GERBV_RENDER_TYPE_GDK_XOR
Definition: gerbv.h:369
@ GERBV_RENDER_TYPE_GDK
Definition: gerbv.h:368
@ GERBV_RENDER_TYPE_CAIRO_NORMAL
Definition: gerbv.h:370
@ GERBV_MESSAGE_WARNING
Definition: gerbv.h:151
gerbv_aperture_type_t
Definition: gerbv.h:158
gerbv_interpolation_t
Definition: gerbv.h:303
@ GERBV_LAYERTYPE_PICKANDPLACE_BOT
Definition: gerbv.h:332
@ GERBV_LAYERTYPE_RS274X
Definition: gerbv.h:329
@ GERBV_LAYERTYPE_PICKANDPLACE_TOP
Definition: gerbv.h:331
@ GERBV_LAYERTYPE_DRILL
Definition: gerbv.h:330
Header info for the PNP (pick-and-place) parsing functions.
Header info for the selection support functions for libgerbv.
guint16 alpha
Definition: gerbv.h:750
gchar * fullPathname
Definition: gerbv.h:753
gerbv_image_t * image
Definition: gerbv.h:748
gerbv_user_transformation_t transform
Definition: gerbv.h:755
gchar * name
Definition: gerbv.h:754
GdkColor color
Definition: gerbv.h:749
gboolean layer_dirty
Definition: gerbv.h:756
gpointer privateRenderData
Definition: gerbv.h:752
gboolean isVisible
Definition: gerbv.h:751
gerbv_stats_t * gerbv_stats
Definition: gerbv.h:742
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_image_info_t * info
Definition: gerbv.h:740
struct gerbv_net * next
Definition: gerbv.h:678
gerbv_fileinfo_t ** file
Definition: gerbv.h:764
gchar * project
Definition: gerbv.h:773
gboolean show_invisible_selection
Definition: gerbv.h:769
GdkColor background
Definition: gerbv.h:762
gboolean check_before_delete
Definition: gerbv.h:768
gchar * execname
Definition: gerbv.h:772
gchar * path
Definition: gerbv.h:770
gchar * execpath
Definition: gerbv.h:771
int max_files
Definition: gerbv.h:763
int last_loaded
Definition: gerbv.h:766
gdouble lowerLeftY
Definition: gerbv.h:790
gdouble scaleFactorX
Definition: gerbv.h:787
gint displayHeight
Definition: gerbv.h:793
gdouble lowerLeftX
Definition: gerbv.h:789
gerbv_render_types_t renderType
Definition: gerbv.h:791
gdouble scaleFactorY
Definition: gerbv.h:788