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