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  g_free (gerbvProject->file[index]);
364 
365  /* slide all later layers down to fill the empty slot */
366  for (i=index; i<(gerbvProject->last_loaded); i++) {
367  gerbvProject->file[i]=gerbvProject->file[i+1];
368  }
369  /* make sure the final spot is clear */
370  gerbvProject->file[gerbvProject->last_loaded] = NULL;
371  gerbvProject->last_loaded--;
372 } /* gerbv_unload_layer */
373 
374 /* ------------------------------------------------------------------ */
375 void
376 gerbv_unload_all_layers (gerbv_project_t *gerbvProject)
377 {
378  int index;
379 
380  /* Must count down since gerbv_unload_layer collapses
381  * layers down. Otherwise, layers slide past the index */
382  for (index = gerbvProject->last_loaded ; index >= 0; index--) {
383  if (gerbvProject->file[index] && gerbvProject->file[index]->name) {
384  gerbv_unload_layer (gerbvProject, index);
385  }
386  }
387 } /* gerbv_unload_all_layers */
388 
389 
390 /* ------------------------------------------------------------------ */
391 void
392 gerbv_change_layer_order(gerbv_project_t *gerbvProject, gint oldPosition, gint newPosition)
393 {
394  gerbv_fileinfo_t *temp_file;
395  int index;
396 
397  temp_file = gerbvProject->file[oldPosition];
398 
399  if (oldPosition < newPosition){
400  for (index = oldPosition; index < newPosition; index++) {
401  gerbvProject->file[index] = gerbvProject->file[index + 1];
402  }
403  } else {
404  for (index = oldPosition; index > newPosition; index--) {
405  gerbvProject->file[index] = gerbvProject->file[index - 1];
406  }
407  }
408  gerbvProject->file[newPosition] = temp_file;
409 } /* gerbv_change_layer_order */
410 
411 
412 /* ------------------------------------------------------------------ */
413 gint
414 gerbv_add_parsed_image_to_project (gerbv_project_t *gerbvProject, gerbv_image_t *parsed_image,
415  gchar const* filename, gchar const* baseName, int idx, int reload){
416  gerb_verify_error_t error = GERB_IMAGE_OK;
417  int r, g, b;
418 
419  DPRINTF("In open_image, now error check file....\n");
420  error = gerbv_image_verify(parsed_image);
421 
422  if (error) {
423  if (error & GERB_IMAGE_MISSING_NETLIST) {
424  GERB_COMPILE_ERROR(_("Missing netlist - aborting file read"));
425  gerbv_destroy_image(parsed_image);
426  return -1;
427  }
428  /* if the error was one of the following, try to open up the file anyways in case
429  the file is a poorly formatted RS-274X file */
430  if (error & GERB_IMAGE_MISSING_FORMAT)
431  g_warning(_("Missing format in file...trying to load anyways\n"));
432  if (error & GERB_IMAGE_MISSING_APERTURES) {
433  g_warning(_("Missing apertures/drill sizes...trying to load anyways\n"));
434  /* step through the file and check for aperture references. For each one found, create
435  a dummy aperture holder to visually draw something on the screen */
436  gerbv_image_create_dummy_apertures (parsed_image);
437  }
438  if (error & GERB_IMAGE_MISSING_INFO)
439  g_warning(_("Missing info...trying to load anyways\n"));
440  }
441 
442  /*
443  * If reload, just exchange the image. Else we have to allocate
444  * a new memory before we define anything more.
445  */
446  if (reload) {
447  gerbv_destroy_image(gerbvProject->file[idx]->image);
448  gerbvProject->file[idx]->image = parsed_image;
449  return 0;
450  } else {
451  /* Load new file. */
452  gerbvProject->file[idx] = (gerbv_fileinfo_t *) g_new0 (gerbv_fileinfo_t, 1);
453  gerbvProject->file[idx]->image = parsed_image;
454  }
455 
456  /*
457  * Store filename for eventual reload
458  */
459  gerbvProject->file[idx]->fullPathname = g_strdup (filename);
460  gerbvProject->file[idx]->name = g_strdup (baseName);
461 
462 
463  r = defaultColors[defaultColorIndex % NUMBER_OF_DEFAULT_COLORS].red*257;
464  g = defaultColors[defaultColorIndex % NUMBER_OF_DEFAULT_COLORS].green*257;
465  b = defaultColors[defaultColorIndex % NUMBER_OF_DEFAULT_COLORS].blue*257;
466 
467  GdkColor colorTemplate = {0, r, g, b};
468  gerbvProject->file[idx]->color = colorTemplate;
469  gerbvProject->file[idx]->alpha = defaultColors[defaultColorIndex % NUMBER_OF_DEFAULT_COLORS].alpha*257;
470  gerbvProject->file[idx]->isVisible = TRUE;
471  gerbvProject->file[idx]->transform = defaultTransformations[defaultColorIndex % NUMBER_OF_DEFAULT_TRANSFORMATIONS];
472  /* update the number of files if we need to */
473  if (gerbvProject->last_loaded <= idx) {
474  gerbvProject->last_loaded = idx;
475  }
476  defaultColorIndex++;
477  return 1;
478 }
479 
480 /* ------------------------------------------------------------------ */
481 int
482 gerbv_open_image(gerbv_project_t *gerbvProject, gchar const* filename, int idx, int reload,
483  gerbv_HID_Attribute *fattr, int n_fattr, gboolean forceLoadFile)
484 {
485  gerb_file_t *fd;
486  gerbv_image_t *parsed_image = NULL, *parsed_image2 = NULL;
487  gint retv = -1;
488  gboolean isPnpFile = FALSE, foundBinary;
489  gerbv_HID_Attribute *attr_list = NULL;
490  int n_attr = 0;
491  /* If we're reloading, we'll pass in our file format attribute list
492  * since this is our hook for letting the user override the fileformat.
493  */
494  if (reload)
495  {
496  /* We're reloading so use the attribute list in memory */
497  attr_list = gerbvProject->file[idx]->image->info->attr_list;
498  n_attr = gerbvProject->file[idx]->image->info->n_attr;
499  }
500  else
501  {
502  /* We're not reloading so use the attribute list read from the
503  * project file if given or NULL otherwise.
504  */
505  attr_list = fattr;
506  n_attr = n_fattr;
507  }
508  /* if we don't have enough spots, then grow the file list by 2 to account for the possible
509  loading of two images for PNP files */
510  if ((idx+1) >= gerbvProject->max_files) {
511  gerbvProject->file = g_renew (gerbv_fileinfo_t *,
512  gerbvProject->file, gerbvProject->max_files + 2);
513 
514  gerbvProject->file[gerbvProject->max_files] = NULL;
515  gerbvProject->file[gerbvProject->max_files+1] = NULL;
516  gerbvProject->max_files += 2;
517  }
518 
519  DPRINTF("In open_image, about to try opening filename = %s\n", filename);
520 
521  fd = gerb_fopen(filename);
522  if (fd == NULL) {
523  GERB_COMPILE_ERROR(_("Trying to open \"%s\": %s"),
524  filename, strerror(errno));
525  return -1;
526  }
527 
528  DPRINTF("In open_image, successfully opened file. Now check its type....\n");
529  /* Here's where we decide what file type we have */
530  /* Note: if the file has some invalid characters in it but still appears to
531  be a valid file, we check with the user if he wants to continue (only
532  if user opens the layer from the menu...if from the command line, we go
533  ahead and try to load it anyways) */
534 
535  if (gerber_is_rs274x_p(fd, &foundBinary)) {
536  DPRINTF("Found RS-274X file\n");
537  if (!foundBinary || forceLoadFile) {
538  /* figure out the directory path in case parse_gerb needs to
539  * load any include files */
540  gchar *currentLoadDirectory = g_path_get_dirname (filename);
541  parsed_image = parse_gerb(fd, currentLoadDirectory);
542  g_free (currentLoadDirectory);
543  }
544  } else if(drill_file_p(fd, &foundBinary)) {
545  DPRINTF("Found drill file\n");
546  if (!foundBinary || forceLoadFile)
547  parsed_image = parse_drillfile(fd, attr_list, n_attr, reload);
548 
549  } else if (pick_and_place_check_file_type(fd, &foundBinary)) {
550  DPRINTF("Found pick-n-place file\n");
551  if (!foundBinary || forceLoadFile) {
552  if (!reload) {
553  pick_and_place_parse_file_to_images(fd, &parsed_image, &parsed_image2);
554  } else {
555  switch (gerbvProject->file[idx]->image->layertype) {
557  /* Non NULL pointer is used as "not to reload" mark */
558  // parsed_image2 = (void *)!NULL;
560  parsed_image2 = (void *)1;
561  pick_and_place_parse_file_to_images(fd, &parsed_image, &parsed_image2);
562  parsed_image2 = NULL;
563  break;
565  /* Non NULL pointer is used as "not to reload" mark */
566  // parsed_image2 = (void *)!NULL;
568  parsed_image2 = (void *)1;
569  pick_and_place_parse_file_to_images(fd, &parsed_image2, &parsed_image);
570  parsed_image2 = NULL;
571  break;
572  default:
573  GERB_COMPILE_ERROR(_("%s: unknown pick-and-place board side to reload"), filename);
574  }
575  }
576 
577  isPnpFile = TRUE;
578  }
579  } else if (gerber_is_rs274d_p(fd)) {
580  gchar *str = g_strdup_printf(_("Most likely found a RS-274D file "
581  "\"%s\" ... trying to open anyways\n"), filename);
582  DPRINTF("%s", str);
583  g_warning("%s", str);
584  g_free (str);
585 
586  if (!foundBinary || forceLoadFile) {
587  /* figure out the directory path in case parse_gerb needs to
588  * load any include files */
589  gchar *currentLoadDirectory = g_path_get_dirname (filename);
590  parsed_image = parse_gerb(fd, currentLoadDirectory);
591  g_free (currentLoadDirectory);
592  }
593  } else {
594  /* This is not a known file */
595  DPRINTF("Unknown filetype");
596  GERB_COMPILE_ERROR(_("%s: Unknown file type."), filename);
597  parsed_image = NULL;
598  }
599 
600  gerb_fclose(fd);
601  if (parsed_image == NULL) {
602  return -1;
603  }
604 
605  if (parsed_image) {
606  /* Warn if the file parsed successfully but contains no geometry */
607  if ((parsed_image->netlist != NULL)
608  && (parsed_image->netlist->next == NULL)) {
609  if ((parsed_image->layertype == GERBV_LAYERTYPE_DRILL)
610  && (parsed_image->drill_stats != NULL)) {
611  gerbv_stats_printf(
612  parsed_image->drill_stats->error_list,
614  _("File \"%s\" contains no drill hits or routes"),
615  filename);
616  } else if (parsed_image->gerbv_stats != NULL) {
617  gerbv_stats_printf(
618  parsed_image->gerbv_stats->error_list,
620  _("File \"%s\" contains no drawing elements"),
621  filename);
622  }
623  }
624 
625  /* strip the filename to the base */
626  gchar *baseName = g_path_get_basename (filename);
627  gchar *displayedName;
628  if (isPnpFile)
629  displayedName = g_strconcat (baseName, _(" (top)"), NULL);
630  else
631  displayedName = g_strdup (baseName);
632  retv = gerbv_add_parsed_image_to_project (gerbvProject, parsed_image, filename, displayedName, idx, reload);
633  g_free (baseName);
634  g_free (displayedName);
635  }
636 
637  /* Set layer_dirty flag to FALSE */
638  gerbvProject->file[idx]->layer_dirty = FALSE;
639 
640  /* for PNP place files, we may need to add a second image for the other
641  board side */
642  if (parsed_image2) {
643  /* strip the filename to the base */
644  gchar *baseName = g_path_get_basename (filename);
645  gchar *displayedName;
646  displayedName = g_strconcat (baseName, _(" (bottom)"), NULL);
647  retv = gerbv_add_parsed_image_to_project (gerbvProject, parsed_image2, filename, displayedName, idx + 1, reload);
648  g_free (baseName);
649  g_free (displayedName);
650  }
651 
652  return retv;
653 } /* open_image */
654 
655 gboolean
656 gerbv_is_loadable_file(const char *filename)
657 {
658  gerb_file_t *fd;
659  gboolean foundBinary;
660 
661  fd = gerb_fopen(filename);
662  if (fd == NULL)
663  return FALSE;
664 
665  gboolean loadable = gerber_is_rs274x_p(fd, &foundBinary)
666  || drill_file_p(fd, &foundBinary)
667  || pick_and_place_check_file_type(fd, &foundBinary)
668  || gerber_is_rs274d_p(fd);
669 
670  gerb_fclose(fd);
671  return loadable;
672 }
673 
676 {
677  gerbv_image_t *returnImage;
678  gerb_file_t *fd;
679 
680  fd = gerb_fopen(filename);
681  if (fd == NULL) {
682  GERB_COMPILE_ERROR(_("Trying to open \"%s\": %s"),
683  filename, strerror(errno));
684  return NULL;
685  }
686  returnImage = parse_drillfile(fd, NULL, 0, 0);
687  gerb_fclose(fd);
688  return returnImage;
689 } /* gerbv_create_excellon_image_from_filename */
690 
693  gerbv_image_t *returnImage;
694  gerb_file_t *fd;
695 
696  fd = gerb_fopen(filename);
697  if (fd == NULL) {
698  GERB_COMPILE_ERROR(_("Trying to open \"%s\": %s"),
699  filename, strerror(errno));
700  return NULL;
701  }
702  gchar *currentLoadDirectory = g_path_get_dirname (filename);
703  returnImage = parse_gerb(fd, currentLoadDirectory);
704  g_free (currentLoadDirectory);
705  gerb_fclose(fd);
706  return returnImage;
707 }
708 
709 static inline int isnormal_or_zero(double x)
710 {
711  int cl = fpclassify(x);
712  return cl == FP_NORMAL || cl == FP_ZERO;
713 }
714 
715 /* ------------------------------------------------------------------ */
716 void
717 gerbv_render_get_boundingbox(gerbv_project_t *gerbvProject, gerbv_render_size_t *boundingbox)
718 {
719  double x1=HUGE_VAL,y1=HUGE_VAL, x2=-HUGE_VAL,y2=-HUGE_VAL;
720  int i;
721  gerbv_image_info_t *info;
722  gdouble minX, minY, maxX, maxY;
723 
724  for(i = 0; i <= gerbvProject->last_loaded; i++) {
725  if (gerbvProject->file[i] && gerbvProject->file[i]->isVisible){
726 
727 
728  info = gerbvProject->file[i]->image->info;
729  /*
730  * Find the biggest image and use as a size reference
731  */
732  /* cairo info already has offset calculated into min/max */
733 
734  minX = info->min_x;
735  minY = info->min_y;
736  maxX = info->max_x;
737  maxY = info->max_y;
738 
739  if (!isnormal_or_zero(minX) || !isnormal_or_zero(minY)
740  || !isnormal_or_zero(maxX) || !isnormal_or_zero(maxY)) {
741  continue;
742  }
743 
744  /* transform the bounding box based on the user transform */
745  cairo_matrix_t fullMatrix;
746  cairo_matrix_init (&fullMatrix, 1, 0, 0, 1, 0, 0);
747 
748  cairo_matrix_translate (&fullMatrix, gerbvProject->file[i]->transform.translateX,
749  gerbvProject->file[i]->transform.translateY);
750  // don't use mirroring for the scale matrix
751  gdouble scaleX = gerbvProject->file[i]->transform.scaleX;
752  gdouble scaleY = gerbvProject->file[i]->transform.scaleY;
753  if (gerbvProject->file[i]->transform.mirrorAroundX)
754  scaleY *= -1;
755  if (gerbvProject->file[i]->transform.mirrorAroundY)
756  scaleX *= -1;
757  cairo_matrix_scale (&fullMatrix, scaleX, scaleY);
758  cairo_matrix_rotate (&fullMatrix, gerbvProject->file[i]->transform.rotation);
759 
760  cairo_matrix_transform_point (&fullMatrix, &minX, &minY);
761  cairo_matrix_transform_point (&fullMatrix, &maxX, &maxY);
762  /* compare to both min and max, since a mirror transform may have made the "max"
763  number smaller than the "min" */
764  x1 = MIN(x1, minX);
765  x1 = MIN(x1, maxX);
766  y1 = MIN(y1, minY);
767  y1 = MIN(y1, maxY);
768  x2 = MAX(x2, minX);
769  x2 = MAX(x2, maxX);
770  y2 = MAX(y2, minY);
771  y2 = MAX(y2, maxY);
772  }
773  }
774  boundingbox->left = x1;
775  boundingbox->right = x2;
776  boundingbox->top = y1;
777  boundingbox->bottom = y2;
778 }
779 
780 /* ------------------------------------------------------------------ */
781 void
783 {
785  double width, height;
786  double x_scale, y_scale;
787 
788  /* Grab maximal width and height of all layers */
789  gerbv_render_get_boundingbox(gerbvProject, &bb);
790  width = bb.right - bb.left;
791  height = bb.bottom - bb.top;
792  /* add in a 5% buffer around the drawing */
793  width *= 1.05;
794  height *=1.05;
795 
796  /* if the values aren't sane (probably we have no models loaded), then
797  put in some defaults */
798  if (!isnormal(width)||!isnormal(height)||((width < 0.01) && (height < 0.01))) {
799  renderInfo->lowerLeftX = 0.0;
800  renderInfo->lowerLeftY = 0.0;
801  renderInfo->scaleFactorX = 200;
802  renderInfo->scaleFactorY = renderInfo->scaleFactorX;
803  return;
804  }
805  /*
806  * Calculate scale for both x axis and y axis
807  */
808  x_scale = renderInfo->displayWidth / width;
809  y_scale = renderInfo->displayHeight / height;
810  /*
811  * Take the scale that fits both directions with some extra checks
812  */
813  renderInfo->scaleFactorX = MIN(x_scale, y_scale);
814  renderInfo->scaleFactorX = MIN((gdouble)GERBV_SCALE_MAX,
815  renderInfo->scaleFactorX);
816  renderInfo->scaleFactorX = MAX((gdouble)GERBV_SCALE_MIN,
817  renderInfo->scaleFactorX);
818  renderInfo->scaleFactorY = renderInfo->scaleFactorX;
819  renderInfo->lowerLeftX = ((bb.left + bb.right) / 2.0) -
820  ((double) renderInfo->displayWidth / 2.0 / renderInfo->scaleFactorX);
821  renderInfo->lowerLeftY = ((bb.top + bb.bottom) / 2.0) -
822  ((double) renderInfo->displayHeight / 2.0 / renderInfo->scaleFactorY);
823 }
824 
825 /* ------------------------------------------------------------------ */
826 void
827 gerbv_render_translate_to_fit_display (gerbv_project_t *gerbvProject, gerbv_render_info_t *renderInfo) {
829 
830  /* Grab maximal width and height of all layers */
831  gerbv_render_get_boundingbox(gerbvProject, &bb);
832  renderInfo->lowerLeftX = ((bb.left + bb.right) / 2.0) -
833  ((double) renderInfo->displayWidth / 2.0 / renderInfo->scaleFactorX);
834  renderInfo->lowerLeftY = ((bb.top + bb.bottom) / 2.0) -
835  ((double) renderInfo->displayHeight / 2.0 / renderInfo->scaleFactorY);
836 }
837 
838 /* ------------------------------------------------------------------ */
839 void
840 gerbv_render_to_pixmap_using_gdk (gerbv_project_t *gerbvProject, GdkPixmap *pixmap,
841  gerbv_render_info_t *renderInfo, gerbv_selection_info_t *selectionInfo,
842  GdkColor *selectionColor){
843  GdkGC *gc = gdk_gc_new(pixmap);
844  GdkPixmap *colorStamp, *clipmask;
845  int i;
846 
847  /*
848  * Remove old pixmap, allocate a new one, draw the background.
849  */
850  if (!gerbvProject->background.pixel)
851  gdk_colormap_alloc_color(gdk_colormap_get_system(), &gerbvProject->background, FALSE, TRUE);
852  gdk_gc_set_foreground(gc, &gerbvProject->background);
853  gdk_draw_rectangle(pixmap, gc, TRUE, 0, 0, -1, -1);
854 
855  /*
856  * Allocate the pixmap and the clipmask (a one pixel pixmap)
857  */
858  colorStamp = gdk_pixmap_new(pixmap, renderInfo->displayWidth,
859  renderInfo->displayHeight, -1);
860  clipmask = gdk_pixmap_new(NULL, renderInfo->displayWidth,
861  renderInfo->displayHeight, 1);
862 
863  /*
864  * This now allows drawing several layers on top of each other.
865  * Higher layer numbers have higher priority in the Z-order.
866  */
867  for(i = gerbvProject->last_loaded; i >= 0; i--) {
868  if (gerbvProject->file[i] && gerbvProject->file[i]->isVisible) {
869  /*
870  * Fill up image with all the foreground color. Excess pixels
871  * will be removed by clipmask.
872  */
873  if (!gerbvProject->file[i]->color.pixel)
874  gdk_colormap_alloc_color(gdk_colormap_get_system(), &gerbvProject->file[i]->color, FALSE, TRUE);
875  gdk_gc_set_foreground(gc, &gerbvProject->file[i]->color);
876 
877  /* switch back to regular draw function for the initial
878  bitmap clear */
879  gdk_gc_set_function(gc, GDK_COPY);
880  gdk_draw_rectangle(colorStamp, gc, TRUE, 0, 0, -1, -1);
881 
882  if (renderInfo->renderType == GERBV_RENDER_TYPE_GDK) {
883  gdk_gc_set_function(gc, GDK_COPY);
884  }
885  else if (renderInfo->renderType == GERBV_RENDER_TYPE_GDK_XOR) {
886  gdk_gc_set_function(gc, GDK_XOR);
887  }
888  /*
889  * Translation is to get it inside the allocated pixmap,
890  * which is not always centered perfectly for GTK/X.
891  */
892  DPRINTF(" .... calling image2pixmap on image %d...\n", i);
893  // Dirty scaling solution when using GDK; simply use scaling factor for x-axis, ignore y-axis
894  draw_gdk_image_to_pixmap(&clipmask, gerbvProject->file[i]->image,
895  renderInfo->scaleFactorX, -(renderInfo->lowerLeftX * renderInfo->scaleFactorX),
896  (renderInfo->lowerLeftY * renderInfo->scaleFactorY) + renderInfo->displayHeight,
897  DRAW_IMAGE, NULL, renderInfo, gerbvProject->file[i]->transform);
898 
899  /*
900  * Set clipmask and draw the clipped out image onto the
901  * screen pixmap. Afterwards we remove the clipmask, else
902  * it will screw things up when run this loop again.
903  */
904  gdk_gc_set_clip_mask(gc, clipmask);
905  gdk_gc_set_clip_origin(gc, 0, 0);
906  gdk_draw_drawable(pixmap, gc, colorStamp, 0, 0, 0, 0, -1, -1);
907  gdk_gc_set_clip_mask(gc, NULL);
908  }
909  }
910 
911  /* Render the selection group to the top of the output */
912  if (selectionInfo && selectionInfo->selectedNodeArray
913  && (selection_length (selectionInfo) != 0)) {
914  if (!selectionColor->pixel)
915  gdk_colormap_alloc_color(gdk_colormap_get_system(), selectionColor, FALSE, TRUE);
916 
917  gdk_gc_set_foreground(gc, selectionColor);
918  gdk_gc_set_function(gc, GDK_COPY);
919  gdk_draw_rectangle(colorStamp, gc, TRUE, 0, 0, -1, -1);
920 
921  gerbv_selection_item_t sItem;
922  gerbv_fileinfo_t *file;
923  int j;
924  guint k;
925 
926  for (j = gerbvProject->last_loaded; j >= 0; j--) {
927  file = gerbvProject->file[j];
928  if (!file || (!gerbvProject->show_invisible_selection && !file->isVisible))
929  continue;
930 
931  for (k = 0; k < selection_length (selectionInfo); k++) {
932  sItem = selection_get_item_by_index (selectionInfo, k);
933 
934  if (file->image != sItem.image)
935  continue;
936 
937  /* Have selected image(s) on this layer, draw it */
938  draw_gdk_image_to_pixmap(&clipmask, file->image,
939  renderInfo->scaleFactorX,
940  -(renderInfo->lowerLeftX * renderInfo->scaleFactorX),
941  (renderInfo->lowerLeftY * renderInfo->scaleFactorY) + renderInfo->displayHeight,
942  DRAW_SELECTIONS, selectionInfo,
943  renderInfo, file->transform);
944 
945  gdk_gc_set_clip_mask(gc, clipmask);
946  gdk_gc_set_clip_origin(gc, 0, 0);
947  gdk_draw_drawable(pixmap, gc, colorStamp, 0, 0, 0, 0, -1, -1);
948  gdk_gc_set_clip_mask(gc, NULL);
949 
950  break;
951  }
952  }
953  }
954 
955  gdk_pixmap_unref(colorStamp);
956  gdk_pixmap_unref(clipmask);
957  gdk_gc_unref(gc);
958 }
959 
960 /* ------------------------------------------------------------------ */
961 void
962 gerbv_render_all_layers_to_cairo_target_for_vector_output (
963  gerbv_project_t *gerbvProject, cairo_t *cr,
964  gerbv_render_info_t *renderInfo)
965 {
966  GdkColor *bg = &gerbvProject->background;
967  int i;
968  double r, g, b;
969 
970  gerbv_render_cairo_set_scale_and_translation (cr, renderInfo);
971 
972  /* Fill the background with the appropriate not white and not black
973  * color for backward culpability. */
974  if ((bg->red != 0xffff || bg->green != 0xffff || bg->blue != 0xffff)
975  && (bg->red != 0x0000 || bg->green != 0x0000 || bg->blue != 0x0000)) {
976  r = (double) bg->red/G_MAXUINT16;
977  g = (double) bg->green/G_MAXUINT16;
978  b = (double) bg->blue/G_MAXUINT16;
979  cairo_set_source_rgba (cr, r, g, b, 1);
980  cairo_paint (cr);
981 
982  /* Set cairo user data with background color information, to be
983  * used for clear color. */
984  cairo_set_user_data (cr, (cairo_user_data_key_t *)0, &r, NULL);
985  cairo_set_user_data (cr, (cairo_user_data_key_t *)1, &g, NULL);
986  cairo_set_user_data (cr, (cairo_user_data_key_t *)2, &b, NULL);
987  }
988 
989  for (i = gerbvProject->last_loaded; i >= 0; i--) {
990  if (gerbvProject->file[i] && gerbvProject->file[i]->isVisible) {
991  gerbv_render_layer_to_cairo_target_without_transforming(
992  cr, gerbvProject->file[i],
993  renderInfo, FALSE);
994  }
995  }
996 }
997 
998 /* ------------------------------------------------------------------ */
999 void
1000 gerbv_render_all_layers_to_cairo_target (gerbv_project_t *gerbvProject,
1001  cairo_t *cr, gerbv_render_info_t *renderInfo)
1002 {
1003  int i;
1004 
1005  /* Fill the background with the appropriate color. */
1006  cairo_set_source_rgba (cr,
1007  (double) gerbvProject->background.red/G_MAXUINT16,
1008  (double) gerbvProject->background.green/G_MAXUINT16,
1009  (double) gerbvProject->background.blue/G_MAXUINT16, 1);
1010  cairo_paint (cr);
1011 
1012  for (i = gerbvProject->last_loaded; i >= 0; i--) {
1013  if (gerbvProject->file[i] && gerbvProject->file[i]->isVisible) {
1014  cairo_push_group (cr);
1016  gerbvProject->file[i], renderInfo);
1017  cairo_pop_group_to_source (cr);
1018  cairo_paint_with_alpha (cr, (double)
1019  gerbvProject->file[i]->alpha/G_MAXUINT16);
1020  }
1021  }
1022 }
1023 
1024 /* ------------------------------------------------------------------ */
1025 void
1027  gerbv_render_info_t *renderInfo) {
1028  gerbv_render_cairo_set_scale_and_translation(cr, renderInfo);
1029  gerbv_render_layer_to_cairo_target_without_transforming(cr, fileInfo, renderInfo, TRUE);
1030 }
1031 
1032 /* ------------------------------------------------------------------ */
1033 void
1034 gerbv_render_cairo_set_scale_and_translation(cairo_t *cr, gerbv_render_info_t *renderInfo){
1035  gdouble translateX, translateY;
1036 
1037  translateX = (renderInfo->lowerLeftX * renderInfo->scaleFactorX);
1038  translateY = (renderInfo->lowerLeftY * renderInfo->scaleFactorY);
1039 
1040  /* renderTypes 0 and 1 use GDK rendering, so we shouldn't have made it
1041  this far */
1042  if (renderInfo->renderType == GERBV_RENDER_TYPE_CAIRO_NORMAL) {
1043  cairo_set_tolerance (cr, 1.0);
1044  cairo_set_antialias (cr, CAIRO_ANTIALIAS_NONE);
1045  }
1046  else if (renderInfo->renderType == GERBV_RENDER_TYPE_CAIRO_HIGH_QUALITY) {
1047  cairo_set_tolerance (cr, 0.1);
1048  cairo_set_antialias (cr, CAIRO_ANTIALIAS_DEFAULT);
1049  }
1050 
1051  /* translate the draw area before drawing. We must translate the whole
1052  drawing down an additional displayHeight to account for the negative
1053  y flip done later */
1054  cairo_translate (cr, -translateX, translateY + renderInfo->displayHeight);
1055  /* scale the drawing by the specified scale factor (inverting y since
1056  cairo y axis points down) */
1057  cairo_scale (cr, renderInfo->scaleFactorX, -renderInfo->scaleFactorY);
1058 }
1059 
1060 /* ------------------------------------------------------------------ */
1061 void
1062 gerbv_render_layer_to_cairo_target_without_transforming(cairo_t *cr, gerbv_fileinfo_t *fileInfo, gerbv_render_info_t *renderInfo, gboolean pixelOutput) {
1063  cairo_set_source_rgba (cr, (double) fileInfo->color.red/G_MAXUINT16,
1064  (double) fileInfo->color.green/G_MAXUINT16,
1065  (double) fileInfo->color.blue/G_MAXUINT16, 1);
1066 
1067  /* translate, rotate, and modify the image based on the layer-specific transformation struct */
1068  cairo_save (cr);
1069 
1070  draw_image_to_cairo_target (cr, fileInfo->image,
1071  1.0/MAX(renderInfo->scaleFactorX, renderInfo->scaleFactorY), DRAW_IMAGE, NULL,
1072  renderInfo, TRUE, fileInfo->transform, pixelOutput);
1073  cairo_restore (cr);
1074 }
1075 
1076 void
1077 gerbv_attribute_destroy_HID_attribute (gerbv_HID_Attribute *attributeList, int n_attr)
1078 {
1079  int i;
1080 
1081  /* free the string attributes and names */
1082  for (i = 0 ; i < n_attr ; i++) {
1083  if ( (attributeList[i].type == HID_String ||
1084  attributeList[i].type == HID_Label) &&
1085  attributeList[i].default_val.str_value != NULL) {
1086  free (attributeList[i].default_val.str_value);
1087  }
1088  if (attributeList[i].name != NULL) {
1089  free (attributeList[i].name);
1090  }
1091  }
1092 
1093  /* and free the attribute list */
1094  if (attributeList != NULL) {
1095  free (attributeList);
1096  }
1097 }
1098 
1099 
1100 /* allocate memory and make a copy of an attribute list */
1101 gerbv_HID_Attribute *
1102 gerbv_attribute_dup (gerbv_HID_Attribute *attributeList, int n_attr)
1103 {
1104  gerbv_HID_Attribute *nl;
1105  int i;
1106 
1107  nl = (gerbv_HID_Attribute *) malloc (n_attr * sizeof (gerbv_HID_Attribute));
1108  if (nl == NULL) {
1109  fprintf (stderr, "malloc failed in %s()\n", __FUNCTION__);
1110  exit (1);
1111  }
1112 
1113  /* deep-copy every entry: struct copy first, then strdup name and
1114  * string values so the copy owns all its memory independently */
1115  for (i = 0 ; i < n_attr ; i++) {
1116  nl[i] = attributeList[i];
1117  nl[i].name = attributeList[i].name ? strdup (attributeList[i].name) : NULL;
1118 
1119  if (attributeList[i].type == HID_String ||
1120  attributeList[i].type == HID_Label) {
1121  nl[i].default_val.str_value =
1122  attributeList[i].default_val.str_value
1123  ? strdup (attributeList[i].default_val.str_value) : NULL;
1124  }
1125  }
1126 
1127  return nl;
1128 }
1129 
1132  const gerbv_project_t *project)
1133 {
1134  int i;
1135 
1136  for (i = 0; i <= project->last_loaded; i++) {
1137  if (project->file[i]->image == image)
1138  return project->file[i];
1139  }
1140 
1141  return NULL;
1142 }
1143 
1144 inline void
1145 gerbv_rotate_coord(double *x, double *y, double rad)
1146 {
1147  double x0 = *x;
1148 
1149  *x = x0*cos(rad) - *y*sin(rad);
1150  *y = x0*sin(rad) + *y*cos(rad);
1151 }
1152 
1153 void
1154 gerbv_transform_coord(double *x, double *y,
1155  const gerbv_user_transformation_t *trans)
1156 {
1157 
1158  *x = trans->scaleX * *x;
1159  *y = trans->scaleY * *y;
1160 
1161  gerbv_rotate_coord(x, y, trans->rotation);
1162 
1163  if (trans->mirrorAroundY)
1164  *x = -*x;
1165 
1166  if (trans->mirrorAroundX)
1167  *y = -*y;
1168 
1169  *x += trans->translateX;
1170  *y += trans->translateY;
1171 }
1172 
1173 int
1174 gerbv_transform_coord_for_image(double *x, double *y,
1175  const gerbv_image_t *image, const gerbv_project_t *project)
1176 {
1177  gerbv_fileinfo_t *fileinfo =
1178  gerbv_get_fileinfo_for_image(image, project);
1179 
1180  if (fileinfo == NULL) {
1181  DPRINTF("%s(): NULL fileinfo\n", __func__);
1182  return -1;
1183  }
1184 
1185  gerbv_transform_coord(x, y, &fileinfo->transform);
1186 
1187  return 0;
1188 }
1189 
1190 gboolean
1191 gerbv_endswith(const char *path, const char *ext) {
1192  int plen = strlen(path);
1193  int elen = strlen(ext);
1194  if ( plen < elen ) return FALSE; // false if string too short to check
1195  return (strcmp(path+plen-elen, ext) == 0) ? TRUE // true if last chars match extension
1196  : FALSE;
1197 }
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:482
gerbv_image_t * gerbv_create_rs274x_image_from_filename(gchar const *filename)
Parse a RS274X file and return the parsed image.
Definition: gerbv.c:692
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:1145
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:656
gerbv_fileinfo_t * gerbv_get_fileinfo_for_image(const gerbv_image_t *image, const gerbv_project_t *project)
Definition: gerbv.c:1131
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:1154
gboolean gerbv_endswith(const char *path, const char *ext)
Definition: gerbv.c:1191
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:782
int gerbv_transform_coord_for_image(double *x, double *y, const gerbv_image_t *image, const gerbv_project_t *project)
Definition: gerbv.c:1174
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:675
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:1026
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:745
gchar * fullPathname
Definition: gerbv.h:748
gerbv_image_t * image
Definition: gerbv.h:743
gerbv_user_transformation_t transform
Definition: gerbv.h:750
gchar * name
Definition: gerbv.h:749
GdkColor color
Definition: gerbv.h:744
gboolean layer_dirty
Definition: gerbv.h:751
gpointer privateRenderData
Definition: gerbv.h:747
gboolean isVisible
Definition: gerbv.h:746
gerbv_stats_t * gerbv_stats
Definition: gerbv.h:737
gerbv_layertype_t layertype
Definition: gerbv.h:729
gerbv_net_t * netlist
Definition: gerbv.h:736
gerbv_drill_stats_t * drill_stats
Definition: gerbv.h:738
gerbv_image_info_t * info
Definition: gerbv.h:735
struct gerbv_net * next
Definition: gerbv.h:673
gerbv_fileinfo_t ** file
Definition: gerbv.h:759
gchar * project
Definition: gerbv.h:768
gboolean show_invisible_selection
Definition: gerbv.h:764
GdkColor background
Definition: gerbv.h:757
gboolean check_before_delete
Definition: gerbv.h:763
gchar * execname
Definition: gerbv.h:767
gchar * path
Definition: gerbv.h:765
gchar * execpath
Definition: gerbv.h:766
int max_files
Definition: gerbv.h:758
int last_loaded
Definition: gerbv.h:761
gdouble lowerLeftY
Definition: gerbv.h:785
gdouble scaleFactorX
Definition: gerbv.h:782
gint displayHeight
Definition: gerbv.h:788
gdouble lowerLeftX
Definition: gerbv.h:784
gerbv_render_types_t renderType
Definition: gerbv.h:786
gdouble scaleFactorY
Definition: gerbv.h:783