gerbv
main.c
Go to the documentation of this file.
1 /*
2  * gEDA - GNU Electronic Design Automation
3  * This file is a part of gerbv.
4  *
5  * Copyright (C) 2008 Julian Lamb
6  *
7  * $Id$
8  *
9  * This program is free software; you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License as published by
11  * the Free Software Foundation; either version 2 of the License, or
12  * (at your option) any later version.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program; if not, write to the Free Software
21  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111 USA
22  */
23 
29 #include "gerbv.h"
30 
31 #include <assert.h>
32 #include <stdio.h>
33 #include <stdlib.h>
34 #include <errno.h>
35 #include <math.h>
36 
37 #ifdef WIN32
38 # include <windows.h>
39 #endif
40 
41 #ifdef HAVE_STRING_H
42 # include <string.h>
43 #endif
44 
45 #ifdef HAVE_UNISTD_H
46 # include <unistd.h>
47 #endif
48 
49 #ifdef HAVE_GETOPT_H
50 # include <getopt.h>
51 #endif
52 
53 #include <glib/gstdio.h>
54 
55 #include "common.h"
56 #include "main.h"
57 #include "callbacks.h"
58 #include "interface.h"
59 #include "render.h"
60 #include "project.h"
61 
62 /* DEBUG printing. #define DEBUG 1 in config.h to use this fcn. */
63 #undef DPRINTF
64 #define DPRINTF(...) do { if (DEBUG) printf(__VA_ARGS__); } while (0)
65 
66 #define NUMBER_OF_DEFAULT_COLORS 18
67 #define NUMBER_OF_DEFAULT_TRANSFORMATIONS 20
68 
69 static void
70 gerbv_print_help(void);
71 
72 static int
73 getopt_configured(int argc, char * const argv[], const char *optstring,
74  const struct option *longopts, int *longindex);
75 static int
76 getopt_lengh_unit(const char *optarg, double *input_div,
77  gerbv_screen_t *screen);
78 
79 static gint
80 compare_strings(gconstpointer a, gconstpointer b)
81 {
82  return g_ascii_strcasecmp((const char *)a, (const char *)b);
83 }
84 
85 static GList *
86 scan_directory(const char *dirpath)
87 {
88  GDir *dir = g_dir_open(dirpath, 0, NULL);
89  if (!dir)
90  return NULL;
91 
92  GList *files = NULL;
93  const gchar *entry;
94  while ((entry = g_dir_read_name(dir)) != NULL) {
95  gchar *fullpath = g_build_filename(dirpath, entry, NULL);
96  if (g_file_test(fullpath, G_FILE_TEST_IS_REGULAR)
97  && gerbv_is_loadable_file(fullpath)) {
98  files = g_list_prepend(files, fullpath);
99  } else {
100  g_free(fullpath);
101  }
102  }
103  g_dir_close(dir);
104 
105  return g_list_sort(files, compare_strings);
106 }
107 
108 static gerbv_layer_color mainDefaultColors[NUMBER_OF_DEFAULT_COLORS] = {
109  {115,115,222,177},
110  {255,127,115,177},
111  {193,0,224,177},
112  {117,242,103,177},
113  {0,195,195,177},
114  {213,253,51,177},
115  {209,27,104,177},
116  {255,197,51,177},
117  {186,186,186,177},
118  {211,211,255,177},
119  {253,210,206,177},
120  {236,194,242,177},
121  {208,249,204,177},
122  {183,255,255,177},
123  {241,255,183,177},
124  {255,202,225,177},
125  {253,238,197,177},
126  {226,226,226,177}
127 };
128 
129 static gerbv_user_transformation_t mainDefaultTransformations[NUMBER_OF_DEFAULT_TRANSFORMATIONS] = {
130  {0,0,1,1,0,FALSE,FALSE,FALSE},
131  {0,0,1,1,0,FALSE,FALSE,FALSE},
132  {0,0,1,1,0,FALSE,FALSE,FALSE},
133  {0,0,1,1,0,FALSE,FALSE,FALSE},
134  {0,0,1,1,0,FALSE,FALSE,FALSE},
135  {0,0,1,1,0,FALSE,FALSE,FALSE},
136  {0,0,1,1,0,FALSE,FALSE,FALSE},
137  {0,0,1,1,0,FALSE,FALSE,FALSE},
138  {0,0,1,1,0,FALSE,FALSE,FALSE},
139  {0,0,1,1,0,FALSE,FALSE,FALSE},
140  {0,0,1,1,0,FALSE,FALSE,FALSE},
141  {0,0,1,1,0,FALSE,FALSE,FALSE},
142  {0,0,1,1,0,FALSE,FALSE,FALSE},
143  {0,0,1,1,0,FALSE,FALSE,FALSE},
144  {0,0,1,1,0,FALSE,FALSE,FALSE},
145  {0,0,1,1,0,FALSE,FALSE,FALSE},
146  {0,0,1,1,0,FALSE,FALSE,FALSE},
147  {0,0,1,1,0,FALSE,FALSE,FALSE},
148  {0,0,1,1,0,FALSE,FALSE,FALSE},
149  {0,0,1,1,0,FALSE,FALSE,FALSE},
150 };
151 
152 #ifdef HAVE_GETOPT_LONG
153 int longopt_val = 0;
154 int longopt_idx = 0;
155 const struct option longopts[] = {
156  /* name has_arg flag val */
157  {"border", required_argument, NULL, 'B'},
158  {"dpi", required_argument, NULL, 'D'},
159  {"version", no_argument, NULL, 'V'},
160  {"origin", required_argument, NULL, 'O'},
161  {"window_inch", required_argument, NULL, 'W'},
162  {"antialias", no_argument, NULL, 'a'},
163  {"background", required_argument, NULL, 'b'},
164  {"dump", no_argument, NULL, 'd'},
165  {"foreground", required_argument, NULL, 'f'},
166  {"rotate", required_argument, NULL, 'r'},
167  {"mirror", required_argument, NULL, 'm'},
168  {"help", no_argument, NULL, 'h'},
169  {"quiet", no_argument, NULL, 'q'},
170  {"log", required_argument, NULL, 'l'},
171  {"output", required_argument, NULL, 'o'},
172  {"project", required_argument, NULL, 'p'},
173  {"tools", required_argument, NULL, 't'},
174  {"translate", required_argument, NULL, 'T'},
175  {"units", required_argument, NULL, 'u'},
176  {"window", required_argument, NULL, 'w'},
177  {"export", required_argument, NULL, 'x'},
178  {"svg-layers", no_argument, &longopt_val, 3},
179  {"svg-cairo", no_argument, &longopt_val, 4},
180  {"geometry", required_argument, &longopt_val, 1},
181  /* GDK/GDK debug flags to be "let through" */
182  {"gtk-module", required_argument, &longopt_val, 2},
183  {"g-fatal-warnings",no_argument, &longopt_val, 2},
184  {"gtk-debug", required_argument, &longopt_val, 2},
185  {"gtk-no-debug", required_argument, &longopt_val, 2},
186  {"gdk-debug", required_argument, &longopt_val, 2},
187  {"gdk-no-debug", required_argument, &longopt_val, 2},
188  {"display", required_argument, &longopt_val, 2},
189  {"sync", no_argument, &longopt_val, 2},
190  {"no-xshm", no_argument, &longopt_val, 2},
191  {"name", required_argument, &longopt_val, 2},
192  {"class", required_argument, &longopt_val, 2},
193  {0, 0, 0, 0},
194 };
195 #endif /* HAVE_GETOPT_LONG*/
196 const char *opt_options = "VadqhB:D:O:W:b:f:r:m:l:o:p:t:T:u:w:x:";
197 
202 gerbv_screen_t screen;
203 
204 gboolean logToFileOption;
205 gchar *logToFileFilename;
206 static gboolean quietMode = FALSE;
207 static FILE *logFile = NULL;
208 
209 /* Coords like "0x2" parsed by "%fx%f" will result in first number = 2 and
210  second number 0. Replace 'x' in coordinate string with ';'*/
211 static void
212 care_for_x_in_cords(char *string)
213 {
214  char *found;
215  found = strchr(string, 'x');
216  if (!found)
217  found = strchr(string, 'X');
218  if (found)
219  *found = ';';
220 }
221 
222 /* ------------------------------------------------------------------ */
223 void
224 main_open_project_from_filename(gerbv_project_t *gerbvProject, gchar *filename)
225 {
226  project_list_t *list, *plist;
227  gint i, max_layer_num = -1;
228  gerbv_fileinfo_t *file_info;
229 
230  DPRINTF("Opening project = %s\n", (gchar *) filename);
231  list = read_project_file(filename);
232 
233  if (!list) {
234  GERB_COMPILE_WARNING(_("Could not read \"%s\" (loaded %d)"),
235  (gchar *) filename, gerbvProject->last_loaded);
236 
237  return;
238  }
239 
240  /* Get the max layer number in the project list */
241  plist = list;
242  while (plist) {
243  if (plist->layerno > max_layer_num)
244  max_layer_num = plist->layerno;
245 
246  plist = plist->next;
247  }
248 
249  /* Increase the layer count each time and find (if any) the
250  * corresponding entry */
251  for (i = -1; i <= max_layer_num; i++) {
252  plist = list;
253  while (plist) {
254  if (plist->layerno != i) {
255  plist = plist->next;
256  continue;
257  }
258 
259  GdkColor colorTemplate = {0,
260  plist->rgb[0], plist->rgb[1], plist->rgb[2]};
261  if (i == -1) {
262  screen.background_is_from_project= TRUE;
263  gerbvProject->background = colorTemplate;
264  plist = plist->next;
265  continue;
266  }
267 
268  gchar *fullName = NULL;
269  gchar *dirName = NULL;
270  gint fileIndex = gerbvProject->last_loaded + 1;
271 
272  if (!g_path_is_absolute (plist->filename)) {
273  /* Build the full pathname to the layer */
274  dirName = g_path_get_dirname (filename);
275  fullName = g_build_filename (dirName,
276  plist->filename, NULL);
277  } else {
278  fullName = g_strdup (plist->filename);
279  }
280 
281  if (gerbv_open_image(gerbvProject, fullName,
282  fileIndex, FALSE,
283  plist->attr_list,
284  plist->n_attr, TRUE) == -1) {
285  GERB_MESSAGE(_("could not read file: %s"),
286  fullName);
287  plist = plist->next;
288  continue;
289  }
290 
291  g_free (dirName);
292  g_free (fullName);
293 
294  /* Change color from default to from the project list */
295  file_info = gerbvProject->file[fileIndex];
296  file_info->color = colorTemplate;
297  file_info->alpha = plist->alpha;
298  file_info->transform.inverted = plist->inverted;
299  file_info->transform.translateX = plist->translate_x;
300  file_info->transform.translateY = plist->translate_y;
301  file_info->transform.rotation = plist->rotation;
302  file_info->transform.scaleX = plist->scale_x;
303  file_info->transform.scaleY = plist->scale_y;
304  file_info->transform.mirrorAroundX = plist->mirror_x;
305  file_info->transform.mirrorAroundY = plist->mirror_y;
306  file_info->isVisible = plist->visible;
307 
308  plist = plist->next;
309  }
310  }
311 
312  project_destroy_project_list(list);
313 
314  /* Save project filename for later use */
315  if (gerbvProject->project) {
316  g_free(gerbvProject->project);
317  gerbvProject->project = NULL;
318  }
319  gerbvProject->project = g_strdup(filename);
320  if (gerbvProject->project == NULL)
321  GERB_FATAL_ERROR("malloc gerbvProject->project failed in %s()",
322  __FUNCTION__);
323 } /* gerbv_open_project_from_filename */
324 
325 /* ------------------------------------------------------------------ */
326 void
327 main_save_project_from_filename(gerbv_project_t *gerbvProject, gchar *filename)
328 {
329  project_list_t *list, *plist;
330  gchar *dirName = g_path_get_dirname (filename);
331  gerbv_fileinfo_t *file_info;
332  int idx;
333 
334  list = g_new0 (project_list_t, 1);
335  list->next = NULL;
336  list->layerno = -1;
337  list->filename = g_strdup(gerbvProject->path);
338  list->rgb[0] = gerbvProject->background.red;
339  list->rgb[1] = gerbvProject->background.green;
340  list->rgb[2] = gerbvProject->background.blue;
341 
342  /* loop over all layer files */
343  for (idx = 0; idx <= gerbvProject->last_loaded; idx++) {
344  if (gerbvProject->file[idx]) {
345  plist = g_new0 (project_list_t, 1);
346  plist->next = list;
347  plist->layerno = idx;
348 
349  /* figure out the relative path to the layer from the project
350  directory */
351  if (strncmp (dirName, gerbvProject->file[idx]->fullPathname, strlen(dirName)) == 0) {
352  /* skip over the common dirname and the separator */
353  plist->filename = g_strdup(gerbvProject->file[idx]->fullPathname + strlen(dirName) + 1);
354  } else {
355  /* if we can't figure out a relative path, just save the
356  * absolute one */
357  plist->filename = g_strdup(gerbvProject->file[idx]->fullPathname);
358  }
359  file_info = gerbvProject->file[idx];
360  plist->rgb[0] = file_info->color.red;
361  plist->rgb[1] = file_info->color.green;
362  plist->rgb[2] = file_info->color.blue;
363  plist->alpha = file_info->alpha;
364  plist->inverted = file_info->transform.inverted;
365  plist->visible = file_info->isVisible;
366  plist->translate_x = file_info->transform.translateX;
367  plist->translate_y = file_info->transform.translateY;
368  plist->rotation = file_info->transform.rotation;
369  plist->scale_x = file_info->transform.scaleX;
370  plist->scale_y = file_info->transform.scaleY;
371  plist->mirror_x = file_info->transform.mirrorAroundX;
372  plist->mirror_y = file_info->transform.mirrorAroundY;
373  list= plist;
374  }
375  }
376 
377  if (write_project_file(gerbvProject, gerbvProject->project, list)) {
378  GERB_MESSAGE(_("Failed to write project"));
379  }
380  project_destroy_project_list(list);
381  g_free (dirName);
382 } /* gerbv_save_project_from_filename */
383 
384 /* ------------------------------------------------------------------ */
385 void
386 main_save_as_project_from_filename(gerbv_project_t *gerbvProject, gchar *filename)
387 {
388 
389  /*
390  * Save project filename for later use
391  */
392  if (gerbvProject->project) {
393  g_free(gerbvProject->project);
394  gerbvProject->project = NULL;
395  }
396  gerbvProject->project = g_strdup(filename);
397  if (gerbvProject->project == NULL)
398  GERB_FATAL_ERROR("malloc gerbvProject->project failed in %s()",
399  __FUNCTION__);
400  main_save_project_from_filename (gerbvProject, filename);
401 } /* gerbv_save_as_project_from_filename */
402 
403 GArray *log_array_tmp = NULL;
404 
405 /* Temporary log messages handler. It will store log messages before GUI
406  * initialization. In CLI mode this is the only handler, so it also formats
407  * messages for stderr with clean severity prefixes and respects --quiet. */
408 void
409 callbacks_temporary_handle_log_messages(const gchar *log_domain,
410  GLogLevelFlags log_level,
411  const gchar *message, gpointer user_data) {
412  struct log_struct item;
413  GLogLevelFlags level = log_level & G_LOG_LEVEL_MASK;
414 
415  /* Store for GUI replay */
416  item.domain = g_strdup (log_domain);
417  item.level = log_level;
418  item.message = g_strdup (message);
419  g_array_append_val (log_array_tmp, item);
420 
421  /* Print unless suppressed by quiet mode (INFO = note, DEBUG) */
422  if (!(quietMode && (level & (G_LOG_LEVEL_INFO | G_LOG_LEVEL_DEBUG)))) {
423  const gchar *prefix;
424 
425  switch (level) {
426  case G_LOG_LEVEL_ERROR: prefix = "fatal"; break;
427  case G_LOG_LEVEL_CRITICAL: prefix = "error"; break;
428  case G_LOG_LEVEL_WARNING: prefix = "warning"; break;
429  case G_LOG_LEVEL_MESSAGE: prefix = "info"; break;
430  case G_LOG_LEVEL_INFO: prefix = "note"; break;
431  case G_LOG_LEVEL_DEBUG: prefix = "debug"; break;
432  default: prefix = "log"; break;
433  }
434 
435  fprintf(stderr, "%s: %s\n", prefix, message);
436 
437  if (logFile)
438  fprintf(logFile, "%s: %s\n", prefix, message);
439  }
440 
441  /* GLib expects the default handler to abort on fatal errors */
442  if (log_level & G_LOG_FLAG_FATAL)
443  g_log_default_handler (log_domain, log_level, message, user_data);
444 }
445 
446 #ifdef WIN32
447 static void
448 wait_console_for_win(void)
449 {
450  FILE *console = fopen("CONOUT$", "w");
451 
452  fprintf(console, _("\n*** Press Enter to continue ***"));
453  fflush(console);
454 }
455 
456 /* Attach console in application which is build with -mwindows flag */
457 static void
458 attach_console_for_win(void)
459 {
460  if (((HANDLE)_get_osfhandle(fileno(stdout)) == INVALID_HANDLE_VALUE
461  || (HANDLE)_get_osfhandle(fileno(stderr)) == INVALID_HANDLE_VALUE)
462  && AttachConsole(ATTACH_PARENT_PROCESS)) {
463 
464  if ((HANDLE)_get_osfhandle(fileno (stdout)) == INVALID_HANDLE_VALUE)
465  freopen("CONOUT$", "w", stdout);
466 
467  if ((HANDLE)_get_osfhandle(fileno (stderr)) == INVALID_HANDLE_VALUE)
468  freopen("CONOUT$", "w", stderr);
469 
470  atexit(wait_console_for_win);
471  }
472 }
473 #else
474 static void
475 attach_console_for_win(void) {}
476 #endif
477 
478 /* ------------------------------------------------------------------ */
479 int
480 main(int argc, char *argv[])
481 {
482  int read_opt;
483  int i,r,g,b,a;
484  int req_width = -1, req_height = -1;
485 #ifdef HAVE_GETOPT_LONG
486  char *rest;
487 #endif
488  char *project_filename = NULL;
489  gboolean userSuppliedOrigin=FALSE, userSuppliedWindow=FALSE,
490  userSuppliedAntiAlias=FALSE, userSuppliedWindowInPixels=FALSE, userSuppliedDpi=FALSE;
491  gint layerctr =0, transformCount = 0;
492  gdouble initial_rotation = 0.0;
493  gdouble input_divisor = 1.0; /* 1.0 for inch */
494  int unit_flag_counter;
495  gboolean initial_mirror_x = FALSE;
496  gboolean initial_mirror_y = FALSE;
497  gboolean svgLayers = FALSE;
498  const gchar *exportFilename = NULL;
499  gfloat userSuppliedOriginX=0.0,userSuppliedOriginY=0.0,userSuppliedDpiX=72.0, userSuppliedDpiY=72.0,
500  userSuppliedWidth=0, userSuppliedHeight=0,
501  userSuppliedBorder = GERBV_DEFAULT_BORDER_COEFF;
502 
503  gerbv_image_t *exportImage;
504 
505  enum exp_type {
506  EXP_TYPE_NONE = -1,
507  EXP_TYPE_PNG,
508  EXP_TYPE_PDF,
509  EXP_TYPE_SVG,
510  EXP_TYPE_PS,
511  EXP_TYPE_RS274X,
512  EXP_TYPE_DRILL,
513  EXP_TYPE_IDRILL,
514  EXP_TYPE_DXF,
515  };
516  enum exp_type exportType = EXP_TYPE_NONE;
517  const char *export_type_names[] = {
518  "png",
519  "pdf",
520  "svg",
521  "ps",
522  "rs274x",
523  "drill",
524  "idrill",
525  "dxf",
526  NULL
527  };
528  const gchar *export_def_file_names[] = {
529  "output.png",
530  "output.pdf",
531  "output.svg",
532  "output.ps",
533  "output.gbx",
534  "output.cnc",
535  "output.ncp",
536  "output.dxf",
537  NULL
538  };
539 
540  const gchar *settings_schema_env = "GSETTINGS_SCHEMA_DIR";
541 #ifdef WIN32
542  /* On Windows executable can be not in bin/ dir */
543  const gchar *settings_schema_fallback_dir =
544  "share/glib-2.0/schemas" G_SEARCHPATH_SEPARATOR_S
545  "../share/glib-2.0/schemas";
546 #else
547  const gchar *settings_schema_fallback_dir = "../share/glib-2.0/schemas";
548 #endif
549  gchar *env_val;
550 
551 #ifdef ENABLE_NLS
552  setlocale(LC_ALL, "");
553  bindtextdomain(PACKAGE, GERBV_LOCALEDIR);
554 # ifdef WIN32
555  bind_textdomain_codeset(PACKAGE, "UTF-8");
556 # endif
557  textdomain(PACKAGE);
558 #endif
559 
560  attach_console_for_win();
561 
562 #ifdef WIN32
563  /* Convert argv from system codepage to UTF-8 for GLib functions.
564  * The original argv[i] pointers (owned by the C runtime) are
565  * intentionally overwritten and leaked — the converted strings
566  * must live for the entire process lifetime, and argv is not
567  * freed by the caller. This block only runs on Windows, so it
568  * will not appear in Linux Valgrind runs. */
569  for (i = 0; i < argc; i++) {
570  gchar *utf8_arg = g_locale_to_utf8(argv[i], -1, NULL, NULL, NULL);
571  if (utf8_arg) {
572  argv[i] = utf8_arg;
573  }
574  }
575 #endif
576 
577  /*
578  * Setup the screen info. Must do this before getopt, since getopt
579  * eventually will set some variables in screen.
580  */
581  memset((void *)&screen, 0, sizeof(gerbv_screen_t));
582  screen.state = NORMAL;
583  screen.unit = GERBV_DEFAULT_UNIT;
584 
586  mainProject->execname = g_strdup(argv[0]);
587  mainProject->execpath = g_path_get_dirname(argv[0]);
588 
589  /* Add "fallback" directory with settings schema file from this
590  * executable path */
591  if (NULL == g_getenv(settings_schema_env))
592  /* Empty env var */
593  env_val = g_strconcat(
594  mainProject->execpath, G_DIR_SEPARATOR_S,
595  settings_schema_fallback_dir,
596  NULL);
597  else
598  /* Not empty env var */
599  env_val = g_strconcat(g_getenv(settings_schema_env),
600  G_SEARCHPATH_SEPARATOR_S,
601  mainProject->execpath, G_DIR_SEPARATOR_S,
602  settings_schema_fallback_dir,
603  NULL);
604  g_setenv(settings_schema_env, env_val, TRUE);
605  g_free(env_val);
606 
607  /* set default rendering mode */
608 #ifdef WIN32
609  /* Cairo seems to render faster on Windows, so use it for default */
610  screenRenderInfo.renderType = GERBV_RENDER_TYPE_CAIRO_NORMAL;
611 #else
612  screenRenderInfo.renderType = GERBV_RENDER_TYPE_GDK;
613 #endif
614 
615  logToFileOption = FALSE;
616  logToFileFilename = NULL;
617 
618  log_array_tmp = g_array_new (TRUE, FALSE, sizeof (struct log_struct));
619  g_log_set_handler (NULL,
620  G_LOG_FLAG_FATAL | G_LOG_FLAG_RECURSION | G_LOG_LEVEL_MASK,
621  callbacks_temporary_handle_log_messages, NULL);
622 
623 
624  /* 1. Process flags needed before main option parsing */
625  unit_flag_counter = 0;
626  opterr = 0; /* Disable getopt() error messages */
627  while (-1 != (read_opt = getopt_configured(argc, argv, opt_options,
628  longopts, &longopt_idx))) {
629  switch (read_opt) {
630  case 'q':
631  quietMode = TRUE;
632  break;
633  case 'u':
634  unit_flag_counter++;
635 
636  if (!getopt_lengh_unit(optarg, &input_divisor, &screen))
637  GERB_COMPILE_WARNING(
638  _("Unrecognized length unit \"%s\" in command line"),
639  optarg);
640 
641  break;
642  }
643  }
644 
645  /* 2. Process all other command line flags */
646  optind = 0; /* Reset getopt() index */
647  opterr = 1; /* Enable getopt() error messages */
648  while (-1 != (read_opt = getopt_configured(argc, argv, opt_options,
649  longopts, &longopt_idx))) {
650  switch (read_opt) {
651 #ifdef HAVE_GETOPT_LONG
652  case 0:
653  /* Only long options like GDK/GTK debug */
654  switch (longopt_val) {
655  case 0: /* default value if nothing is set */
656  GERB_COMPILE_WARNING(
657  _("Not handled option \"%s\" in command line"),
658  longopts[longopt_idx].name);
659  break;
660  case 1: /* geometry */
661  errno = 0;
662  req_width = (int)strtol(optarg, &rest, 10);
663  if (errno) {
664  perror(_("Width"));
665  break;
666  }
667  if (rest[0] != 'x'){
668  fprintf(stderr, _("Split X and Y parameters with an x\n"));
669  break;
670  }
671  rest++;
672  errno = 0;
673  req_height = (int)strtol(rest, &rest, 10);
674  if (errno) {
675  perror(_("Height"));
676  break;
677  }
678  /*
679  if ((rest[0] == 0) || ((rest[0] != '-') && (rest[0] != '+')))
680  break;
681  errno = 0;
682  req_x = (int)strtol(rest, &rest, 10);
683  if (errno) {
684  perror("X");
685  break;
686  }
687  if ((rest[0] == 0) || ((rest[0] != '-') && (rest[0] != '+')))
688  break;
689  errno = 0;
690  req_y = (int)strtol(rest, &rest, 10);
691  if (errno) {
692  perror("Y");
693  break;
694  }
695  */
696  break;
697  case 3: /* svg-layers */
698  svgLayers = TRUE;
699  break;
700  case 4: /* svg-cairo */
701  mainProject->use_cairo_svg = TRUE;
702  break;
703  default:
704  break;
705  }
706  break;
707 #endif /* HAVE_GETOPT_LONG */
708  case 'B' :
709  if (optarg == NULL) {
710  fprintf(stderr, _("You must specify the border in the format <alpha>.\n"));
711  exit(1);
712  }
713  if (strlen (optarg) > 10) {
714  fprintf(stderr, _("Specified border is not recognized.\n"));
715  exit(1);
716  }
717  sscanf (optarg,"%f",&userSuppliedBorder);
718  if (userSuppliedBorder < 0) {
719  fprintf(stderr, _("Specified border is smaller than zero!\n"));
720  exit(1);
721  }
722  userSuppliedBorder/=100.0;
723  break;
724  case 'D' :
725  if (optarg == NULL) {
726  fprintf(stderr, _("You must give an resolution in the format <DPI_XxDPI_Y> or <DPI_X_and_Y>.\n"));
727  exit(1);
728  }
729  if (strlen (optarg) > 20) {
730  fprintf(stderr, _("Specified resolution is not recognized.\n"));
731  exit(1);
732  }
733  if(strchr(optarg, 'x')!=NULL){
734  sscanf (optarg,"%fx%f",&userSuppliedDpiX,&userSuppliedDpiY);
735  }else{
736  sscanf (optarg,"%f",&userSuppliedDpiX);
737  userSuppliedDpiY = userSuppliedDpiX;
738  }
739  if ((userSuppliedDpiX <= 0) || (userSuppliedDpiY <= 0)) {
740  fprintf(stderr, _("Specified resolution should be greater than 0.\n"));
741  exit(1);
742  }
743  userSuppliedDpi=TRUE;
744  break;
745  case 'O' :
746  if (optarg == NULL) {
747  fprintf(stderr, _("You must give an origin in the format "
748  "<XxY> or <X;Y>.\n"));
749  exit(1);
750  }
751  if (strlen (optarg) > 20) {
752  fprintf(stderr, _("Specified origin is not recognized.\n"));
753  exit(1);
754  }
755 
756  care_for_x_in_cords(optarg);
757  sscanf(optarg,"%f;%f", &userSuppliedOriginX, &userSuppliedOriginY);
758  userSuppliedOriginX /= input_divisor;
759  userSuppliedOriginY /= input_divisor;
760  userSuppliedOrigin=TRUE;
761  break;
762  case 'V' :
763  printf(_("gerbv version %s\n"), VERSION);
764  printf(_("Copyright (C) 2001-2008 by Stefan Petersen\n"
765  "and the respective original authors listed in the source files.\n"));
766  exit(0);
767  case 'a' :
768  userSuppliedAntiAlias = TRUE;
769  break;
770  case 'b' : // Set background to this color
771  if (optarg == NULL) {
772  fprintf(stderr, _("You must give an background color "
773  "in the hex-format <#RRGGBB>.\n"));
774  exit(1);
775  }
776  if ((strlen (optarg) != 7)||(optarg[0]!='#')) {
777  fprintf(stderr, _("Specified color format "
778  "is not recognized.\n"));
779  exit(1);
780  }
781  r=g=b=-1;
782  sscanf (optarg,"#%2x%2x%2x",&r,&g,&b);
783  if ( (r<0)||(r>255)||(g<0)||(g>255)||(b<0)||(b>255)) {
784 
785  fprintf(stderr, _("Specified color values should be "
786  "between 00 and FF.\n"));
787  exit(1);
788  }
789 
790  screen.background_is_from_cmdline = TRUE;
791  mainProject->background.red = r*257;
792  mainProject->background.green = g*257;
793  mainProject->background.blue = b*257;
794 
795  break;
796  case 'f' : // Set layer colors to this color (foreground color)
797  if (optarg == NULL) {
798  fprintf(stderr, _("You must give an foreground color in the hex-format <#RRGGBB> or <#RRGGBBAA>.\n"));
799  exit(1);
800  }
801  if (((strlen (optarg) != 7)&&(strlen (optarg) != 9))||(optarg[0]!='#')) {
802  fprintf(stderr, _("Specified color format is not recognized.\n"));
803  exit(1);
804  }
805  r=g=b=a=-1;
806  if(strlen(optarg)==7){
807  sscanf (optarg,"#%2x%2x%2x",&r,&g,&b);
808  a=177;
809  }
810  else{
811  sscanf (optarg,"#%2x%2x%2x%2x",&r,&g,&b,&a);
812  }
813 
814  if ( (r<0)||(r>255)||(g<0)||(g>255)||(b<0)||(b>255)||(a<0)||(a>255) ) {
815 
816  fprintf(stderr, _("Specified color values should be between 0x00 (0) and 0xFF (255).\n"));
817  exit(1);
818  }
819  mainDefaultColors[layerctr].red = r;
820  mainDefaultColors[layerctr].green = g;
821  mainDefaultColors[layerctr].blue = b;
822  mainDefaultColors[layerctr].alpha = a;
823  layerctr++;
824  /* just reset the counter back to 0 if we read too many */
825  if (layerctr == NUMBER_OF_DEFAULT_COLORS)
826  layerctr = 0;
827  break;
828  case 'r' : // Set initial orientation for all layers (rotation)
829  if (optarg == NULL) {
830  fprintf(stderr, _("You must give the initial rotation angle\n"));
831  exit(1);
832  }
833  errno = 0;
834  initial_rotation = (gdouble)strtod(optarg, &rest);
835  if (errno) {
836  perror(_("Rotate"));
837  exit(1);
838  }
839  if (*rest) {
840  fprintf(stderr, _("Failed parsing rotate value\n"));
841  exit(1);
842  }
843  break;
844  case 'm' : // Set initial mirroring state for all layers
845  if (optarg == NULL) {
846  fprintf(stderr, _("You must give the axis to mirror about\n"));
847  exit(1);
848  }
849  if (strchr(optarg, 'x') != NULL || strchr(optarg, 'X') != NULL) {
850  initial_mirror_x = TRUE;
851  }
852  if (strchr(optarg, 'y') != NULL || strchr(optarg, 'Y') != NULL) {
853  initial_mirror_y = TRUE;
854  }
855  if (!(initial_mirror_x || initial_mirror_y)) {
856  fprintf(stderr, _("Failed parsing mirror axis\n"));
857  exit(1);
858  }
859  break;
860  case 'l' :
861  if (optarg == NULL) {
862  fprintf(stderr, _("You must give a filename to send log to\n"));
863  exit(1);
864  }
865  logToFileOption = TRUE;
866  logToFileFilename = optarg;
867  break;
868  case 'o' :
869  if (optarg == NULL) {
870  fprintf(stderr, _("You must give a filename to export to.\n"));
871  exit(1);
872  }
873  exportFilename = optarg;
874  break;
875  case 'p' :
876  if (optarg == NULL) {
877  fprintf(stderr, _("You must give a project filename\n"));
878  exit(1);
879  }
880  project_filename = optarg;
881  break;
882  case 't' :
883  if (optarg == NULL) {
884  fprintf(stderr, _("You must give a filename to read the tools from.\n"));
885  exit(1);
886  }
887  if (!gerbv_process_tools_file(optarg)) {
888  fprintf(stderr, _("*** ERROR processing tools file \"%s\".\n"), optarg);
889  fprintf(stderr, _("Make sure all lines of the file are formatted like this:\n"
890  "T01 0.024\nT02 0.032\nT03 0.040\n...\n"
891  "*** EXITING to prevent erroneous display.\n"));
892  exit(1);
893  }
894  break;
895  case 'T' : // Translate the layer
896  if (optarg == NULL) {
897  fprintf(stderr, _("You must give a translation in the format "
898  "<XxY> or <X;Y>.\n"));
899  exit(1);
900  }
901  if (strlen (optarg) > 30) {
902  fprintf(stderr, _("The translation format is not recognized.\n"));
903  exit(1);
904  }
905 
906  float transX = 0, transY = 0, rotate = 0;
907 
908  care_for_x_in_cords(optarg);
909  sscanf(optarg, "%f;%fr%f", &transX, &transY, &rotate);
910  transX /= input_divisor;
911  transY /= input_divisor;
912  mainDefaultTransformations[transformCount].translateX = transX;
913  mainDefaultTransformations[transformCount].translateY = transY;
914  mainDefaultTransformations[transformCount].rotation = DEG2RAD(rotate);
915  transformCount++;
916  /* just reset the counter back to 0 if we read too many */
917  if (transformCount == NUMBER_OF_DEFAULT_TRANSFORMATIONS)
918  transformCount = 0;
919  break;
920  case 'u':
921  if (unit_flag_counter == 1)
922  /* Length unit flag occurred only once and processed */
923  break;
924 
925  /* Length unit flag occurred more than once, process each one */
926  if (!getopt_lengh_unit(optarg, &input_divisor, &screen))
927  GERB_COMPILE_WARNING(
928  _("Unrecognized length unit \"%s\" in command line"),
929  optarg);
930 
931  break;
932 
933  case 'w':
934  userSuppliedWindowInPixels = TRUE;
935  [[fallthrough]];
936  case 'W' :
937  if (optarg == NULL) {
938  fprintf(stderr, _("You must give a window size in the format <width x height>.\n"));
939  exit(1);
940  }
941  if (strlen (optarg) > 20) {
942  fprintf(stderr, _("Specified window size is not recognized.\n"));
943  exit(1);
944  }
945  sscanf (optarg, "%fx%f", &userSuppliedWidth, &userSuppliedHeight);
946  if (((userSuppliedWidth < 0.001) || (userSuppliedHeight < 0.001)) ||
947  ((userSuppliedWidth > 2000) || (userSuppliedHeight > 2000))) {
948  fprintf(stderr, _("Specified window size is out of bounds.\n"));
949  exit(1);
950  }
951  userSuppliedWindow = TRUE;
952  break;
953  case 'x' :
954  if (optarg == NULL) {
955  fprintf(stderr, _("You must supply an export type.\n"));
956  exit(1);
957  }
958 
959  for (i = 0; export_type_names[i] != NULL; i++) {
960  if (strcmp (optarg, export_type_names[i]) == 0) {
961  exportType = i;
962  break;
963  }
964  }
965 
966  if (exportType == EXP_TYPE_NONE) {
967  fprintf(stderr, _("Unrecognized \"%s\" export type.\n"),
968  optarg);
969  exit(1);
970  }
971  break;
972  case 'd':
973  screen.dump_parsed_image = 1;
974  break;
975  case 'q':
976  quietMode = TRUE;
977  break;
978  case '?':
979  case 'h':
980  gerbv_print_help();
981 
982  exit(1);
983  break;
984  default :
985  /* This should not be reached */
986  GERB_COMPILE_WARNING(_("Not handled option '%c' in command line"),
987  read_opt);
988  }
989  }
990 
991  if (logToFileOption) {
992  logFile = g_fopen(logToFileFilename, "w");
993  if (!logFile) {
994  int saved_errno = errno;
995  fprintf(stderr, "error: cannot open log file '%s': %s\n",
996  logToFileFilename, strerror(saved_errno));
997  exit(1);
998  }
999  }
1000 
1001  /*
1002  * If no project_filename and only file ends in .gvp, use as project file. -erco 02/20/2020
1003  */
1004  if ( !project_filename && // project not set?
1005  optind == (argc-1) && // only one file specified?
1006  gerbv_endswith(argv[optind], ".gvp") ) { // only file ends in .gvp?
1007  project_filename = argv[optind];
1008  }
1009 
1010  /*
1011  * If project is given, load that one and use it for files and colors.
1012  * Else load files (eventually) given on the command line.
1013  * This limits you to either give files on the commandline or just load
1014  * a project.
1015  */
1016 
1017  if (project_filename) {
1018  DPRINTF(_("Loading project %s...\n"), project_filename);
1019  /* calculate the absolute pathname to the project if the user
1020  used a relative path */
1021  g_free (mainProject->path);
1022  if (!g_path_is_absolute(project_filename)) {
1023  gchar *currentDir = g_get_current_dir ();
1024  gchar *fullName = g_build_filename (currentDir,
1025  project_filename, NULL);
1026  main_open_project_from_filename (mainProject, fullName);
1027  mainProject->path = g_path_get_dirname (fullName);
1028  g_free (fullName);
1029  g_free (currentDir);
1030  } else {
1031  main_open_project_from_filename (mainProject, project_filename);
1032  mainProject->path = g_path_get_dirname (project_filename);
1033  }
1034  } else {
1035  gint loadedIndex = 0;
1036  for(i = optind ; i < argc; i++) {
1037  gchar *arg = argv[i];
1038  gchar *absArg;
1039 
1040  if (!g_path_is_absolute(arg)) {
1041  gchar *currentDir = g_get_current_dir();
1042  absArg = g_build_filename(currentDir, arg, NULL);
1043  g_free(currentDir);
1044  } else {
1045  absArg = g_strdup(arg);
1046  }
1047 
1048  if (g_file_test(absArg, G_FILE_TEST_IS_DIR)) {
1049  GList *files = scan_directory(absArg);
1050  if (!files) {
1051  fprintf(stderr,
1052  _("No loadable files found in \"%s\"\n"), arg);
1053  }
1054  for (GList *l = files; l != NULL; l = l->next) {
1055  g_free(mainProject->path);
1057  (gchar *)l->data,
1058  mainDefaultColors[loadedIndex % NUMBER_OF_DEFAULT_COLORS].red*257,
1059  mainDefaultColors[loadedIndex % NUMBER_OF_DEFAULT_COLORS].green*257,
1060  mainDefaultColors[loadedIndex % NUMBER_OF_DEFAULT_COLORS].blue*257,
1061  mainDefaultColors[loadedIndex % NUMBER_OF_DEFAULT_COLORS].alpha*257);
1062  mainProject->path = g_path_get_dirname((gchar *)l->data);
1063  loadedIndex++;
1064  }
1065  g_list_free_full(files, g_free);
1066  } else {
1067  g_free(mainProject->path);
1069  mainDefaultColors[loadedIndex % NUMBER_OF_DEFAULT_COLORS].red*257,
1070  mainDefaultColors[loadedIndex % NUMBER_OF_DEFAULT_COLORS].green*257,
1071  mainDefaultColors[loadedIndex % NUMBER_OF_DEFAULT_COLORS].blue*257,
1072  mainDefaultColors[loadedIndex % NUMBER_OF_DEFAULT_COLORS].alpha*257);
1073  mainProject->path = g_path_get_dirname(absArg);
1074  loadedIndex++;
1075  }
1076  g_free(absArg);
1077  }
1078  }
1079 
1080  if (initial_rotation != 0.0) {
1081  /* Set initial layer orientation */
1082 
1083  gdouble initial_radians = DEG2RAD(initial_rotation);
1084 
1085  DPRINTF("Rotating all layers by %.0f degrees\n", (float) initial_rotation);
1086  for(i = 0; i < mainProject->max_files; i++) {
1087  if (mainProject->file[i])
1088  mainProject->file[i]->transform.rotation = initial_radians;
1089  }
1090  }
1091 
1092  if (initial_mirror_x || initial_mirror_y) {
1093  /* Set initial mirroring of all layers */
1094 
1095  if (initial_mirror_x) {
1096  DPRINTF("Mirroring all layers about x axis\n");
1097  }
1098  if (initial_mirror_y) {
1099  DPRINTF("Mirroring all layers about y axis\n");
1100  }
1101 
1102  for (i = 0; i < mainProject->max_files; i++) {
1103  if (mainProject->file[i]) {
1104  mainProject->file[i]->transform.mirrorAroundX = initial_mirror_x;
1105  mainProject->file[i]->transform.mirrorAroundY = initial_mirror_y;
1106  }
1107  }
1108  }
1109 
1110  if (exportType != EXP_TYPE_NONE) {
1111  /* load the info struct with the default values */
1112 
1113  if (!exportFilename)
1114  exportFilename = export_def_file_names[exportType];
1115 
1117  gerbv_render_get_boundingbox(mainProject, &bb);
1118  // Set origin to the left-bottom corner if it is not specified
1119  if(!userSuppliedOrigin){
1120  userSuppliedOriginX = bb.left;
1121  userSuppliedOriginY = bb.top;
1122  }
1123 
1124  float width = bb.right - userSuppliedOriginX + 0.001; // Plus a little extra to prevent from
1125  float height = bb.bottom - userSuppliedOriginY + 0.001; // missing items due to round-off errors
1126  // If the user did not specify a height and width, autoscale w&h till full size from origin.
1127  if(!userSuppliedWindow){
1128  userSuppliedWidth = width;
1129  userSuppliedHeight = height;
1130  }else{
1131  // If size was specified in pixels, and no resolution was specified, autoscale resolution till fit
1132  if( (!userSuppliedDpi)&& userSuppliedWindowInPixels){
1133  userSuppliedDpiX = MIN((userSuppliedWidth-0.5)/width,
1134  (userSuppliedHeight-0.5)/height);
1135  userSuppliedDpiY = userSuppliedDpiX;
1136  userSuppliedOriginX -= 0.5/userSuppliedDpiX;
1137  userSuppliedOriginY -= 0.5/userSuppliedDpiY;
1138  }
1139  }
1140 
1141  // Add the border size (if there is one)
1142  if(userSuppliedBorder!=0){
1143  // If supplied in inches, add a border around the image
1144  if(!userSuppliedWindowInPixels){
1145  userSuppliedOriginX -= (userSuppliedWidth*userSuppliedBorder)/2.0;
1146  userSuppliedOriginY -= (userSuppliedHeight*userSuppliedBorder)/2.0;
1147  userSuppliedWidth += userSuppliedWidth*userSuppliedBorder;
1148  userSuppliedHeight += userSuppliedHeight*userSuppliedBorder;
1149  }
1150  // If supplied in pixels, shrink image content for border_size
1151  else{
1152  userSuppliedOriginX -= ((userSuppliedWidth/userSuppliedDpiX)*userSuppliedBorder)/2.0;
1153  userSuppliedOriginY -= ((userSuppliedHeight/userSuppliedDpiX)*userSuppliedBorder)/2.0;
1154  userSuppliedDpiX -= (userSuppliedDpiX*userSuppliedBorder);
1155  userSuppliedDpiY -= (userSuppliedDpiY*userSuppliedBorder);
1156  }
1157  }
1158 
1159  if(!userSuppliedWindowInPixels){
1160  userSuppliedWidth *= userSuppliedDpiX;
1161  userSuppliedHeight *= userSuppliedDpiY;
1162  }
1163 
1164  // Make sure there is something valid in it. It could become negative if
1165  // the userSuppliedOrigin is further than the bb.right or bb.top.
1166  if(userSuppliedWidth <=0)
1167  userSuppliedWidth = 1;
1168  if(userSuppliedHeight <=0)
1169  userSuppliedHeight = 1;
1170 
1171 
1172  gerbv_render_info_t renderInfo = {userSuppliedDpiX, userSuppliedDpiY,
1173  userSuppliedOriginX, userSuppliedOriginY,
1175  userSuppliedWidth,userSuppliedHeight };
1176 
1177  switch (exportType) {
1178  case EXP_TYPE_PNG:
1180  &renderInfo, exportFilename);
1181  break;
1182  case EXP_TYPE_PDF:
1184  &renderInfo, exportFilename);
1185  break;
1186  case EXP_TYPE_SVG:
1188  &renderInfo, exportFilename, svgLayers);
1189  break;
1190  case EXP_TYPE_PS:
1192  &renderInfo, exportFilename);
1193  break;
1194  case EXP_TYPE_RS274X:
1195  case EXP_TYPE_DRILL:
1196  case EXP_TYPE_IDRILL:
1197  case EXP_TYPE_DXF:
1198  if (!mainProject->file[0]->image) {
1199  fprintf(stderr, _("A valid file was not loaded.\n"));
1200  if (logFile)
1201  fclose(logFile);
1202  exit(1);
1203  }
1204 
1205  exportImage = gerbv_image_duplicate_image(
1206  mainProject->file[0]->image,
1207  &mainDefaultTransformations[0]);
1208 
1209  /* If more than one file, merge them before exporting */
1210  for (i = mainProject->last_loaded; i > 0; i--) {
1211  if (mainProject->file[i])
1213  &mainDefaultTransformations[i], exportImage);
1214  }
1215 
1216  switch (exportType) {
1217  case EXP_TYPE_RS274X:
1218  gerbv_export_rs274x_file_from_image(exportFilename,
1219  exportImage, &mainProject->file[0]->transform);
1220  break;
1221  case EXP_TYPE_DRILL:
1222  gerbv_export_drill_file_from_image(exportFilename,
1223  exportImage, &mainProject->file[0]->transform);
1224  break;
1225  case EXP_TYPE_IDRILL:
1227  exportImage, &mainProject->file[0]->transform);
1228  break;
1229  case EXP_TYPE_DXF:
1230  gerbv_export_dxf_file_from_image(exportFilename,
1231  exportImage, &mainProject->file[0]->transform);
1232  break;
1233  default:
1234  break;
1235  }
1236 
1237  gerbv_destroy_image (exportImage);
1238  break;
1239  default:
1240  fprintf(stderr, _("A valid file was not loaded.\n"));
1241  if (logFile)
1242  fclose(logFile);
1243  exit(1);
1244  }
1245 
1246  /* exit now and don't start up gtk if this is a command line export */
1247  if (logFile)
1248  fclose(logFile);
1249  exit(0);
1250  }
1251  gtk_init (&argc, &argv);
1252  interface_create_gui (req_width, req_height);
1253 
1254  /* we've exited the GTK loop, so free all resources */
1255  render_free_screen_resources();
1257  if (logFile)
1258  fclose(logFile);
1259  return 0;
1260 } /* main */
1261 
1262 static int
1263 getopt_configured(int argc, char * const argv[], const char *optstring,
1264  const struct option *longopts, int *longindex)
1265 {
1266 #ifdef HAVE_GETOPT_LONG
1267  return getopt_long(argc, argv, optstring, longopts, longindex);
1268 #else
1269  return getopt(argc, argv, optstring);
1270 #endif
1271 }
1272 
1273 static int
1274 getopt_lengh_unit(const char *optarg, double *input_div, gerbv_screen_t *screen)
1275 {
1276  if (strncasecmp(optarg, "mm", 2) == 0) {
1277  *input_div = 25.4;
1278  screen->unit = GERBV_MMS;
1279  screen->unit_is_from_cmdline = TRUE;
1280  } else if (strncasecmp(optarg, "mil", 3) == 0) {
1281  *input_div = 1000.0;
1282  screen->unit = GERBV_MILS;
1283  screen->unit_is_from_cmdline = TRUE;
1284  } else if (strncasecmp(optarg, "inch", 4) == 0) {
1285  *input_div = 1.0;
1286  screen->unit = GERBV_INS;
1287  screen->unit_is_from_cmdline = TRUE;
1288  } else {
1289  return 0;
1290  }
1291 
1292  return 1;
1293 }
1294 
1295 static void
1296 gerbv_print_help(void)
1297 {
1298  printf(_(
1299 "Usage: gerbv [OPTIONS...] [FILE...]\n"
1300 "\n"
1301 "Available options:\n"));
1302 
1303 #ifdef HAVE_GETOPT_LONG
1304  printf(_(
1305 " -B, --border=<b> Border around the image in percent of the\n"
1306 " width/height. Defaults to %d%%.\n"),
1307  (int)(100*GERBV_DEFAULT_BORDER_COEFF));
1308 #else
1309  printf(_(
1310 " -B<b> Border around the image in percent of the\n"
1311 " width/height. Defaults to %d%%.\n"),
1312  (int)(100*GERBV_DEFAULT_BORDER_COEFF));
1313 #endif
1314 
1315 #ifdef HAVE_GETOPT_LONG
1316  printf(_(
1317 " -D, --dpi=<XxY|R> Resolution (Dots per inch) for the output\n"
1318 " bitmap. With the format <XxY>, different\n"
1319 " resolutions for X- and Y-direction are used.\n"
1320 " With the format <R>, both are the same.\n"));
1321 #else
1322  printf(_(
1323 " -D<XxY|R> Resolution (Dots per inch) for the output\n"
1324 " bitmap. With the format <XxY>, different\n"
1325 " resolutions for X- and Y-direction are used.\n"
1326 " With the format <R>, both are the same.\n"));
1327 #endif
1328 
1329 #ifdef HAVE_GETOPT_LONG
1330  printf(_(
1331 " -O, --origin=<XxY|X;Y> Use the specified coordinates (in inches)\n"
1332 " for the lower left corner.\n"));
1333 #else
1334  printf(_(
1335 " -O<XxY|X;Y> Use the specified coordinates (in inches)\n"
1336 " for the lower left corner.\n"));
1337 #endif
1338 
1339 #ifdef HAVE_GETOPT_LONG
1340  printf(_(
1341 " -V, --version Print version of Gerbv.\n"));
1342 #else
1343  printf(_(
1344 " -V Print version of Gerbv.\n"));
1345 #endif
1346 
1347 #ifdef HAVE_GETOPT_LONG
1348  printf(_(
1349 " -a, --antialias Use antialiasing for generated bitmap output.\n"));
1350 #else
1351  printf(_(
1352 " -a Use antialiasing for generated bitmap output.\n"));
1353 #endif
1354 
1355 #ifdef HAVE_GETOPT_LONG
1356  printf(_(
1357 " -b, --background=<hex> Use background color <hex> (like #RRGGBB).\n"));
1358 #else
1359  printf(_(
1360 " -b<hexcolor> Use background color <hexcolor> (like #RRGGBB).\n"));
1361 #endif
1362 
1363 #ifdef HAVE_GETOPT_LONG
1364  printf(_(
1365 " -f, --foreground=<hex> Use foreground color <hex> (like #RRGGBB or\n"
1366 " #RRGGBBAA for setting the alpha).\n"
1367 " Use multiple -f flags to set the color for\n"
1368 " multiple layers.\n"));
1369 #else
1370  printf(_(
1371 " -f<hexcolor> Use foreground color <hexcolor> (like #RRGGBB or\n"
1372 " #RRGGBBAA for setting the alpha).\n"
1373 " Use multiple -f flags to set the color for\n"
1374 " multiple layers.\n"));
1375 #endif
1376 
1377 #ifdef HAVE_GETOPT_LONG
1378  printf(_(
1379 " -r, --rotate=<degree> Set initial orientation for all layers.\n"));
1380 #else
1381  printf(_(
1382 " -r<degree> Set initial orientation for all layers.\n"));
1383 #endif
1384 
1385 #ifdef HAVE_GETOPT_LONG
1386  printf(_(
1387 " -m, --mirror=<axis> Set initial mirroring axis (X or Y).\n"));
1388 #else
1389  printf(_(
1390 " -m<axis> Set initial mirroring axis (X or Y).\n"));
1391 #endif
1392 
1393 #ifdef HAVE_GETOPT_LONG
1394  printf(_(
1395 " -h, --help Print this help message.\n"));
1396 #else
1397  printf(_(
1398 " -h Print this help message.\n"));
1399 #endif
1400 
1401 #ifdef HAVE_GETOPT_LONG
1402  printf(_(
1403 " -l, --log=<logfile> Send error messages to <logfile>.\n"));
1404 #else
1405  printf(_(
1406 " -l<logfile> Send error messages to <logfile>.\n"));
1407 #endif
1408 
1409 #ifdef HAVE_GETOPT_LONG
1410  printf(_(
1411 " -q, --quiet Suppress note-level messages.\n"));
1412 #else
1413  printf(_(
1414 " -q Suppress note-level messages.\n"));
1415 #endif
1416 
1417 #ifdef HAVE_GETOPT_LONG
1418  printf(_(
1419 " -o, --output=<filename> Export to <filename>.\n"));
1420 #else
1421  printf(_(
1422 " -o<filename> Export to <filename>.\n"));
1423 #endif
1424 
1425 #ifdef HAVE_GETOPT_LONG
1426  printf(_(
1427 " -p, --project=<prjfile> Load project file <prjfile>.\n"));
1428 #else
1429  printf(_(
1430 " -p<prjfile> Load project file <prjfile>.\n"));
1431 #endif
1432 
1433 #ifdef HAVE_GETOPT_LONG
1434  printf(_(
1435 " -u, --units=<inch|mm|mil>\n"
1436 " Use given unit for coordinates.\n"
1437 " Default to inch.\n"));
1438 #else
1439  printf(_(
1440 " -u<inch|mm|mil> Use given unit for coordinates.\n"
1441 " Default to inch.\n"));
1442 #endif
1443 
1444 #ifdef HAVE_GETOPT_LONG
1445  printf(_(
1446 " -W, --window_inch=<WxH> Window size in inches <WxH> for the exported image.\n"));
1447 #else
1448  printf(_(
1449 " -W<WxH> Window size in inches <WxH> for the exported image.\n"));
1450 #endif
1451 
1452 #ifdef HAVE_GETOPT_LONG
1453  printf(_(
1454 " -w, --window=<WxH> Window size in pixels <WxH> for the exported image.\n"
1455 " Autoscales to fit if no resolution is specified.\n"
1456 " If a resolution is specified, it will clip\n"
1457 " exported image.\n"));
1458 #else
1459  printf(_(
1460 " -w<WxH> Window size in pixels <WxH> for the exported image.\n"
1461 " Autoscales to fit if no resolution is specified.\n"
1462 " If a resolution is specified, it will clip\n"
1463 " exported image.\n"));
1464 #endif
1465 
1466 #ifdef HAVE_GETOPT_LONG
1467  printf(_(
1468 " -t, --tools=<toolfile> Read Excellon tools from file <toolfile>.\n"));
1469 #else
1470  printf(_(
1471 " -t<toolfile> Read Excellon tools from file <toolfile>\n"));
1472 #endif
1473 
1474 #ifdef HAVE_GETOPT_LONG
1475  printf(_(
1476 " -T, --translate=<XxYrR| Translate image by X and Y and rotate by R degree.\n"
1477 " X;YrR> Useful for arranging panels.\n"
1478 " Use multiple -T flags for multiple layers.\n"
1479 " Only evaluated when exporting as RS274X or drill.\n"));
1480 #else
1481  printf(_(
1482 " -T<XxYrR|X;YrR> Translate image by X and Y and rotate by R degree.\n"
1483 " Useful for arranging panels.\n"
1484 " Use multiple -T flags for multiple files.\n"
1485 " Only evaluated when exporting as RS274X or drill.\n"));
1486 #endif
1487 
1488 #ifdef HAVE_GETOPT_LONG
1489  printf(_(
1490 " -x, --export=<png|pdf|ps|svg|rs274x|drill|idrill|dxf>\n"
1491 " Export a rendered picture to a file with\n"
1492 " the specified format.\n"));
1493  printf(_(
1494 " --svg-layers Export visible layers as Inkscape SVG layers.\n"
1495 " Only used with --export=svg.\n"));
1496  printf(_(
1497 " --svg-cairo Use Cairo SVG surface (legacy, larger output).\n"
1498 " Only used with --export=svg.\n"));
1499 #else
1500  printf(_(
1501 " -x<png|pdf|ps|svg| Export a rendered picture to a file with\n"
1502 " rs274x|drill| the specified format.\n"
1503 " idrill|dxf>\n"
1504 ));
1505  printf(_(
1506 " --svg-layers Export visible layers as Inkscape SVG layers.\n"
1507 " Only used with -xsvg.\n"));
1508  printf(_(
1509 " --svg-cairo Use Cairo SVG surface (legacy, larger output).\n"
1510 " Only used with -xsvg.\n"));
1511 #endif
1512 
1513 }
Header info for the GUI callback 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_dxf_file_from_image(const gchar *file_name, gerbv_image_t *input_img, gerbv_user_transformation_t *trans)
Export an image to a new file in DXF format.
Definition: export-dxf.cpp:78
void gerbv_export_png_file_from_project(gerbv_project_t *gerbvProject, gerbv_render_info_t *renderInfo, gchar const *filename)
Render a project to a PNG file using user-specified render info.
Definition: export-image.c:229
void gerbv_export_postscript_file_from_project(gerbv_project_t *gerbvProject, gerbv_render_info_t *renderInfo, gchar const *filename)
Render a project to a Postscript file using user-specified render info.
Definition: export-image.c:259
void gerbv_export_svg_file_from_project_with_options(gerbv_project_t *gerbvProject, gerbv_render_info_t *renderInfo, gchar const *filename, gboolean exportLayersAsSvgLayers)
Render a project to a SVG file using user-specified render info and export options.
Definition: export-image.c:283
void gerbv_export_pdf_file_from_project(gerbv_project_t *gerbvProject, gerbv_render_info_t *renderInfo, gchar const *filename)
Render a project to a PDF file using user-specified render info.
Definition: export-image.c:246
gboolean gerbv_export_isel_drill_file_from_image(const gchar *filename, gerbv_image_t *inputImage, gerbv_user_transformation_t *transform)
Export an image to a new file in ISEL NCP drill format.
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_copy_image(gerbv_image_t *sourceImage, gerbv_user_transformation_t *transform, gerbv_image_t *destinationImage)
Copy an image into an existing image, effectively merging the two together.
Definition: gerb_image.c:958
gerbv_image_t * gerbv_image_duplicate_image(gerbv_image_t *sourceImage, gerbv_user_transformation_t *transform)
Duplicate an existing image and return the new copy.
Definition: gerb_image.c:920
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
void gerbv_destroy_project(gerbv_project_t *gerbvProject)
Free a project and all related variables.
Definition: gerbv.c:207
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
gboolean gerbv_is_loadable_file(const char *filename)
Definition: gerbv.c:655
gboolean gerbv_endswith(const char *path, const char *ext)
Definition: gerbv.c:1190
The main header file for the libgerbv library.
@ GERBV_RENDER_TYPE_CAIRO_HIGH_QUALITY
Definition: gerbv.h:370
@ GERBV_RENDER_TYPE_GDK
Definition: gerbv.h:367
@ GERBV_RENDER_TYPE_CAIRO_NORMAL
Definition: gerbv.h:369
Header info for the GUI building functions for Gerber Viewer.
gerbv_project_t * mainProject
Global state variable to keep track of what's happening on the screen.
Definition: main.c:201
Header info for common structs and functions used for the GUI application.
project_list_t * read_project_file(char const *filename)
Reads the content of a project file.
Definition: project.c:944
Header info for loading and saving project files.
Header info for the rendering support functions for gerbv.
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
GdkColor color
Definition: gerbv.h:737
gboolean isVisible
Definition: gerbv.h:739
gboolean use_cairo_svg
Definition: gerbv.h:762
gerbv_fileinfo_t ** file
Definition: gerbv.h:752
gchar * project
Definition: gerbv.h:761
GdkColor background
Definition: gerbv.h:750
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
gerbv_render_types_t renderType
Definition: gerbv.h:779