* rework export svg/pdf/ps functionality to export images with 1:1 scale. Previously...
[geda-gerbv.git] / src / main.c
blob936f1c8d9abc48ce1544ee3716494c53517e2e05
1 /*
2 * gEDA - GNU Electronic Design Automation
3 * This file is a part of gerbv.
5 * Copyright (C) 2008 Julian Lamb
7 * $Id$
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.
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.
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
24 /** \file main.c
25 \brief The main code for the Gerber Viewer GUI application and command line processing
26 \ingroup gerbv
29 #ifdef HAVE_CONFIG_H
30 #include "config.h"
31 #endif
33 #include <assert.h>
34 #include <stdio.h>
35 #include <stdlib.h>
36 #include <errno.h>
38 #ifdef HAVE_STRING_H
39 #include <string.h>
40 #endif
42 #ifdef HAVE_UNISTD_H
43 #include <unistd.h>
44 #endif
46 #include <glib.h>
47 #include <gtk/gtk.h>
48 #include <gdk/gdk.h>
49 #include <gdk/gdkkeysyms.h>
51 #ifdef HAVE_GETOPT_H
52 #include <getopt.h>
53 #endif
55 #include <locale.h>
57 #include "gerbv.h"
58 #include "main.h"
59 #include "callbacks.h"
60 #include "interface.h"
61 #include "render.h"
62 #include "project.h"
64 /* DEBUG printing. #define DEBUG 1 in config.h to use this fcn. */
65 #ifdef DEBUG
66 #define dprintf printf("%s(): ", __FUNCTION__); printf
67 #else
68 #define dprintf if(0) printf
69 #endif
71 #define NUMBER_OF_DEFAULT_COLORS 18
72 #define NUMBER_OF_DEFAULT_TRANSFORMATIONS 20
74 static gerbv_layer_color mainDefaultColors[NUMBER_OF_DEFAULT_COLORS] = {
75 {115,115,222,177},
76 {255,127,115,177},
77 {193,0,224,177},
78 {117,242,103,177},
79 {0,195,195,177},
80 {213,253,51,177},
81 {209,27,104,177},
82 {255,197,51,177},
83 {186,186,186,177},
84 {211,211,255,177},
85 {253,210,206,177},
86 {236,194,242,177},
87 {208,249,204,177},
88 {183,255,255,177},
89 {241,255,183,177},
90 {255,202,225,177},
91 {253,238,197,177},
92 {226,226,226,177}
95 static gerbv_user_transformation_t mainDefaultTransformations[NUMBER_OF_DEFAULT_TRANSFORMATIONS] = {
96 {0,0,1,1,0,FALSE,FALSE,FALSE},
97 {0,0,1,1,0,FALSE,FALSE,FALSE},
98 {0,0,1,1,0,FALSE,FALSE,FALSE},
99 {0,0,1,1,0,FALSE,FALSE,FALSE},
100 {0,0,1,1,0,FALSE,FALSE,FALSE},
101 {0,0,1,1,0,FALSE,FALSE,FALSE},
102 {0,0,1,1,0,FALSE,FALSE,FALSE},
103 {0,0,1,1,0,FALSE,FALSE,FALSE},
104 {0,0,1,1,0,FALSE,FALSE,FALSE},
105 {0,0,1,1,0,FALSE,FALSE,FALSE},
106 {0,0,1,1,0,FALSE,FALSE,FALSE},
107 {0,0,1,1,0,FALSE,FALSE,FALSE},
108 {0,0,1,1,0,FALSE,FALSE,FALSE},
109 {0,0,1,1,0,FALSE,FALSE,FALSE},
110 {0,0,1,1,0,FALSE,FALSE,FALSE},
111 {0,0,1,1,0,FALSE,FALSE,FALSE},
112 {0,0,1,1,0,FALSE,FALSE,FALSE},
113 {0,0,1,1,0,FALSE,FALSE,FALSE},
114 {0,0,1,1,0,FALSE,FALSE,FALSE},
115 {0,0,1,1,0,FALSE,FALSE,FALSE},
118 #ifdef HAVE_GETOPT_LONG
119 int longopt_val = 0;
120 int longopt_idx = 0;
121 const struct option longopts[] = {
122 /* name has_arg flag val */
123 {"border", required_argument, NULL, 'B'},
124 {"dpi", required_argument, NULL, 'D'},
125 {"version", no_argument, NULL, 'V'},
126 {"origin", required_argument, NULL, 'O'},
127 {"window_inch", required_argument, NULL, 'W'},
128 {"antialias", no_argument, NULL, 'a'},
129 {"background", required_argument, NULL, 'b'},
130 {"dump", no_argument, NULL, 'd'},
131 {"foreground", required_argument, NULL, 'f'},
132 {"help", no_argument, NULL, 'h'},
133 {"log", required_argument, NULL, 'l'},
134 {"output", required_argument, NULL, 'o'},
135 {"project", required_argument, NULL, 'p'},
136 {"tools", required_argument, NULL, 't'},
137 {"translate", required_argument, NULL, 'T'},
138 {"window", required_argument, NULL, 'w'},
139 {"export", required_argument, NULL, 'x'},
140 {"geometry", required_argument, &longopt_val, 1},
141 /* GDK/GDK debug flags to be "let through" */
142 {"gtk-module", required_argument, &longopt_val, 2},
143 {"g-fatal-warnings",no_argument, &longopt_val, 2},
144 {"gtk-debug", required_argument, &longopt_val, 2},
145 {"gtk-no-debug", required_argument, &longopt_val, 2},
146 {"gdk-debug", required_argument, &longopt_val, 2},
147 {"gdk-no-debug", required_argument, &longopt_val, 2},
148 {"display", required_argument, &longopt_val, 2},
149 {"sync", no_argument, &longopt_val, 2},
150 {"no-xshm", no_argument, &longopt_val, 2},
151 {"name", required_argument, &longopt_val, 2},
152 {"class", required_argument, &longopt_val, 2},
153 {0, 0, 0, 0},
155 #endif /* HAVE_GETOPT_LONG*/
156 const char *opt_options = "Vadh:B:D:O:W:b:f:l:o:p:t:T:w:x:";
158 /**Global state variable to keep track of what's happening on the screen.
159 Declared extern in gerbv_screen.h
161 gerbv_project_t *mainProject;
162 gerbv_screen_t screen;
164 gboolean logToFileOption;
165 gchar *logToFileFilename;
167 /* ------------------------------------------------------------------ */
168 void
169 main_open_project_from_filename(gerbv_project_t *gerbvProject, gchar *filename)
171 project_list_t *project_list, *originalList;
172 gint i,maxLayerNumber = -1;
174 dprintf("Opening project = %s\n", (gchar *) filename);
175 originalList = project_list = read_project_file(filename);
177 if (project_list) {
178 /* first, get the max layer number in the project list */
179 while (project_list) {
180 if (project_list->layerno > maxLayerNumber)
181 maxLayerNumber = project_list->layerno;
182 project_list = project_list->next;
184 project_list = originalList;
185 /* increase the layer count each time and find (if any) the corresponding entry */
186 for (i = -1; i<=maxLayerNumber; i++){
187 project_list = originalList;
188 while (project_list) {
189 if (project_list->layerno == i) {
190 GdkColor colorTemplate = {0,project_list->rgb[0],
191 project_list->rgb[1],project_list->rgb[2]};
192 if (i == -1) {
193 gerbvProject->background = colorTemplate;
195 else {
196 gchar *fullName = NULL;
197 gchar *dirName = NULL;
198 gint fileIndex = gerbvProject->last_loaded + 1;
200 if (!g_path_is_absolute (project_list->filename)) {
201 /* build the full pathname to the layer */
202 dirName = g_path_get_dirname (filename);
203 fullName = g_build_filename (dirName,
204 project_list->filename, NULL);
206 else {
207 fullName = g_strdup (project_list->filename);
209 if (gerbv_open_image(gerbvProject, fullName,
210 fileIndex, FALSE,
211 project_list->attr_list,
212 project_list->n_attr, TRUE) == -1) {
213 GERB_MESSAGE("could not read file: %s", fullName);
215 else {
216 g_free (dirName);
217 g_free (fullName);
219 * Change color from default to from the project list
221 gerbvProject->file[fileIndex]->color = colorTemplate;
222 gerbvProject->file[fileIndex]->transform.inverted = project_list->inverted;
223 gerbvProject->file[fileIndex]->isVisible = project_list->visible;
227 project_list = project_list->next;
230 project_destroy_project_list (originalList);
232 * Save project filename for later use
234 if (gerbvProject->project) {
235 g_free(gerbvProject->project);
236 gerbvProject->project = NULL;
238 gerbvProject->project = g_strdup (filename);
239 if (gerbvProject->project == NULL)
240 GERB_FATAL_ERROR("malloc gerbvProject->project failed\n");
242 else {
243 GERB_MESSAGE("could not read %s[%d]\n", (gchar *) filename,
244 gerbvProject->last_loaded);
246 } /* gerbv_open_project_from_filename */
248 /* ------------------------------------------------------------------ */
249 void
250 main_save_project_from_filename(gerbv_project_t *gerbvProject, gchar *filename)
252 project_list_t *project_list = NULL, *tmp;
253 int idx;
254 gchar *dirName = g_path_get_dirname (filename);
256 project_list = g_new0 (project_list_t, 1);
257 project_list->next = project_list;
258 project_list->layerno = -1;
259 project_list->filename = g_strdup(gerbvProject->path);
260 project_list->rgb[0] = gerbvProject->background.red;
261 project_list->rgb[1] = gerbvProject->background.green;
262 project_list->rgb[2] = gerbvProject->background.blue;
263 project_list->next = NULL;
265 /* loop over all layer files */
266 for (idx = 0; idx <= gerbvProject->last_loaded; idx++) {
267 if (gerbvProject->file[idx]) {
268 tmp = g_new0 (project_list_t, 1);
269 tmp->next = project_list;
270 tmp->layerno = idx;
272 /* figure out the relative path to the layer from the project
273 directory */
274 if (strncmp (dirName, gerbvProject->file[idx]->fullPathname, strlen(dirName)) == 0) {
275 /* skip over the common dirname and the separator */
276 tmp->filename = g_strdup(gerbvProject->file[idx]->fullPathname + strlen(dirName) + 1);
277 } else {
278 /* if we can't figure out a relative path, just save the
279 * absolute one */
280 tmp->filename = g_strdup(gerbvProject->file[idx]->fullPathname);
282 tmp->rgb[0] = gerbvProject->file[idx]->color.red;
283 tmp->rgb[1] = gerbvProject->file[idx]->color.green;
284 tmp->rgb[2] = gerbvProject->file[idx]->color.blue;
285 tmp->inverted = gerbvProject->file[idx]->transform.inverted;
286 tmp->visible = gerbvProject->file[idx]->isVisible;
288 project_list = tmp;
292 if (write_project_file(gerbvProject, gerbvProject->project, project_list)) {
293 GERB_MESSAGE("Failed to write project\n");
295 project_destroy_project_list (project_list);
296 g_free (dirName);
297 } /* gerbv_save_project_from_filename */
299 /* ------------------------------------------------------------------ */
300 void
301 main_save_as_project_from_filename(gerbv_project_t *gerbvProject, gchar *filename)
305 * Save project filename for later use
307 if (gerbvProject->project) {
308 g_free(gerbvProject->project);
309 gerbvProject->project = NULL;
311 gerbvProject->project = g_strdup(filename);
312 if (gerbvProject->project == NULL)
313 GERB_FATAL_ERROR("malloc gerbvProject->project failed\n");
314 main_save_project_from_filename (gerbvProject, filename);
315 } /* gerbv_save_as_project_from_filename */
318 /* ------------------------------------------------------------------ */
320 main(int argc, char *argv[])
322 int read_opt;
323 int i,r,g,b,a;
324 int req_width = -1, req_height = -1;
325 #ifdef HAVE_GETOPT_LONG
326 int req_x = 0, req_y = 0;
327 char *rest;
328 #endif
329 char *project_filename = NULL;
330 gboolean exportFromCommandline = FALSE, userSuppliedOrigin=FALSE, userSuppliedWindow=FALSE,
331 userSuppliedAntiAlias=FALSE, userSuppliedWindowInPixels=FALSE, userSuppliedDpi=FALSE;
332 gint layerctr =0, transformCount = 0, exportType = 0;
333 gchar *exportFilename = NULL;
334 gfloat userSuppliedOriginX=0.0,userSuppliedOriginY=0.0,userSuppliedDpiX=72.0, userSuppliedDpiY=72.0,
335 userSuppliedWidth=0, userSuppliedHeight=0, userSuppliedBorder=0.05;
338 * Setup the screen info. Must do this before getopt, since getopt
339 * eventually will set some variables in screen.
341 memset((void *)&screen, 0, sizeof(gerbv_screen_t));
342 screen.state = NORMAL;
344 mainProject = gerbv_create_project();
345 mainProject->execname = g_strdup(argv[0]);
346 mainProject->execpath = g_path_get_dirname(argv[0]);
348 /* set default rendering mode */
349 #ifdef WIN32
350 /* Cairo seems to render faster on Windows, so use it for default */
351 screenRenderInfo.renderType = 2;
352 #else
353 screenRenderInfo.renderType = 0;
354 #endif
356 logToFileOption = FALSE;
357 logToFileFilename = NULL;
359 * Now process command line flags
361 while (
362 #ifdef HAVE_GETOPT_LONG
363 (read_opt = getopt_long(argc, argv, opt_options,
364 longopts, &longopt_idx))
365 #else
366 (read_opt = getopt(argc, argv, opt_options))
367 #endif /* HAVE_GETOPT_LONG */
368 != -1) {
370 switch (read_opt) {
371 #ifdef HAVE_GETOPT_LONG
372 case 0:
373 /* Only long options like GDK/GTK debug */
374 switch (longopt_val) {
375 case 0: /* default value if nothing is set */
376 fprintf(stderr, "Not handled option %s\n", longopts[longopt_idx].name);
377 break;
378 case 1: /* geometry */
379 errno = 0;
380 req_width = (int)strtol(optarg, &rest, 10);
381 if (errno) {
382 perror("Width");
383 break;
385 if (rest[0] != 'x'){
386 fprintf(stderr, "Split X and Y parameters with an x\n");
387 break;
389 rest++;
390 errno = 0;
391 req_height = (int)strtol(rest, &rest, 10);
392 if (errno) {
393 perror("Height");
394 break;
396 if ((rest[0] == 0) || ((rest[0] != '-') && (rest[0] != '+')))
397 break;
398 errno = 0;
399 req_x = (int)strtol(rest, &rest, 10);
400 if (errno) {
401 perror("X");
402 break;
404 if ((rest[0] == 0) || ((rest[0] != '-') && (rest[0] != '+')))
405 break;
406 errno = 0;
407 req_y = (int)strtol(rest, &rest, 10);
408 if (errno) {
409 perror("Y");
410 break;
412 break;
413 default:
414 break;
416 break;
417 #endif /* HAVE_GETOPT_LONG */
418 case 'B' :
419 if (optarg == NULL) {
420 fprintf(stderr, "You must specify the border in the format <alpha>.\n");
421 exit(1);
423 if (strlen (optarg) > 10) {
424 fprintf(stderr, "Specified border is not recognized.\n");
425 exit(1);
427 sscanf (optarg,"%f",&userSuppliedBorder);
428 if (userSuppliedBorder < 0) {
429 fprintf(stderr, "Specified border is smaller than zero!\n");
430 exit(1);
432 userSuppliedBorder/=100.0;
433 break;
434 case 'D' :
435 if (optarg == NULL) {
436 fprintf(stderr, "You must give an resolution in the format <DPI X,DPI Y> or <DPI_X_and_Y>.\n");
437 exit(1);
439 if (strlen (optarg) > 20) {
440 fprintf(stderr, "Specified resolution is not recognized.\n");
441 exit(1);
443 if(strchr(optarg, 'x')!=NULL){
444 sscanf (optarg,"%fx%f",&userSuppliedDpiX,&userSuppliedDpiY);
445 }else{
446 sscanf (optarg,"%f",&userSuppliedDpiX);
447 userSuppliedDpiY = userSuppliedDpiX;
449 if ((userSuppliedDpiX <= 0) || (userSuppliedDpiY <= 0)) {
450 fprintf(stderr, "Specified resolution should be greater than 0.\n");
451 exit(1);
453 userSuppliedDpi=TRUE;
454 break;
455 case 'O' :
456 if (optarg == NULL) {
457 fprintf(stderr, "You must give an origin in the format <lower_left_X x lower_left_Y>.\n");
458 exit(1);
460 if (strlen (optarg) > 20) {
461 fprintf(stderr, "Specified origin is not recognized.\n");
462 exit(1);
464 sscanf (optarg,"%fx%f",&userSuppliedOriginX,&userSuppliedOriginY);
465 userSuppliedOrigin=TRUE;
466 break;
467 case 'V' :
468 printf("gerbv version %s\n", VERSION);
469 printf("Copyright (C) 2001 -- 2008 by Stefan Petersen\n");
470 printf("and the respective original authors listed in the source files.\n");
471 exit(0);
472 case 'a' :
473 userSuppliedAntiAlias = TRUE;
474 break;
475 case 'b' : // Set background to this color
476 if (optarg == NULL) {
477 fprintf(stderr, "You must give an background color in the hex-format <#RRGGBB>.\n");
478 exit(1);
480 if ((strlen (optarg) != 7)||(optarg[0]!='#')) {
481 fprintf(stderr, "Specified color format is not recognized.\n");
482 exit(1);
484 r=g=b=-1;
485 sscanf (optarg,"#%2x%2x%2x",&r,&g,&b);
486 if ( (r<0)||(r>255)||(g<0)||(g>255)||(b<0)||(b>255)) {
488 fprintf(stderr, "Specified color values should be between 00 and FF.\n");
489 exit(1);
491 mainProject->background.red = r*257;
492 mainProject->background.green = g*257;
493 mainProject->background.blue = b*257;
494 break;
495 case 'f' : // Set layer colors to this color (foreground color)
496 if (optarg == NULL) {
497 fprintf(stderr, "You must give an foreground color in the hex-format <#RRGGBB> or <#RRGGBBAA>.\n");
498 exit(1);
500 if (((strlen (optarg) != 7)&&(strlen (optarg) != 9))||(optarg[0]!='#')) {
501 fprintf(stderr, "Specified color format is not recognized.\n");
502 exit(1);
504 r=g=b=a=-1;
505 if(strlen(optarg)==7){
506 sscanf (optarg,"#%2x%2x%2x",&r,&g,&b);
507 a=177;
509 else{
510 sscanf (optarg,"#%2x%2x%2x%2x",&r,&g,&b,&a);
513 if ( (r<0)||(r>255)||(g<0)||(g>255)||(b<0)||(b>255)||(a<0)||(a>255) ) {
515 fprintf(stderr, "Specified color values should be between 0x00 (0) and 0xFF (255).\n");
516 exit(1);
518 mainDefaultColors[layerctr].red = r;
519 mainDefaultColors[layerctr].green = g;
520 mainDefaultColors[layerctr].blue = b;
521 mainDefaultColors[layerctr].alpha = a;
522 layerctr++;
523 /* just reset the counter back to 0 if we read too many */
524 if (layerctr == NUMBER_OF_DEFAULT_COLORS)
525 layerctr = 0;
526 break;
527 case 'l' :
528 if (optarg == NULL) {
529 fprintf(stderr, "You must give a filename to send log to\n");
530 exit(1);
532 logToFileOption = TRUE;
533 logToFileFilename = optarg;
534 break;
535 case 'o' :
536 if (optarg == NULL) {
537 fprintf(stderr, "You must give a filename to export to.\n");
538 exit(1);
540 exportFilename = optarg;
541 break;
542 case 'p' :
543 if (optarg == NULL) {
544 fprintf(stderr, "You must give a project filename\n");
545 exit(1);
547 project_filename = optarg;
548 break;
549 case 't' :
550 if (optarg == NULL) {
551 fprintf(stderr, "You must give a filename to read the tools from.\n");
552 exit(1);
554 if (!gerbv_process_tools_file(optarg)) {
555 fprintf(stderr, "*** ERROR processing tools file \"%s\".\n", optarg);
556 fprintf(stderr, "Make sure all lines of the file are formatted like this:\n");
557 fprintf(stderr, "T01 0.024\nT02 0.032\nT03 0.040\n...\n");
558 fprintf(stderr, "*** EXITING to prevent erroneous display.\n");
559 exit(1);
561 break;
562 case 'T' : // Translate the layer
563 if (optarg == NULL) {
564 fprintf(stderr, "You must give a translation in the format <X,Y>.\n");
565 exit(1);
567 if (strlen (optarg) > 30) {
568 fprintf(stderr, "The translation format is not recognized.\n");
569 exit(1);
571 float transX=0, transY=0;
573 sscanf (optarg,"%f,%f",&transX,&transY);
574 mainDefaultTransformations[transformCount].translateX = transX;
575 mainDefaultTransformations[transformCount].translateY = transY;
576 transformCount++;
577 /* just reset the counter back to 0 if we read too many */
578 if (transformCount == NUMBER_OF_DEFAULT_TRANSFORMATIONS)
579 transformCount = 0;
580 break;
581 case 'w':
582 userSuppliedWindowInPixels = TRUE;
583 case 'W' :
584 if (optarg == NULL) {
585 fprintf(stderr, "You must give a window size in the format <width x height>.\n");
586 exit(1);
588 if (strlen (optarg) > 20) {
589 fprintf(stderr, "Specified window size is not recognized.\n");
590 exit(1);
592 sscanf (optarg, "%fx%f", &userSuppliedWidth, &userSuppliedHeight);
593 if (((userSuppliedWidth < 0.001) || (userSuppliedHeight < 0.001)) ||
594 ((userSuppliedWidth > 2000) || (userSuppliedHeight > 2000))) {
595 fprintf(stderr, "Specified window size is out of bounds.\n");
596 exit(1);
598 userSuppliedWindow = TRUE;
599 break;
600 case 'x' :
601 if (optarg == NULL) {
602 fprintf(stderr, "You must supply an export type.\n");
603 exit(1);
605 if (strcmp (optarg,"png") == 0) {
606 exportType = 1;
607 exportFromCommandline = TRUE;
609 else if (strcmp (optarg,"pdf") == 0) {
610 exportType = 2;
611 exportFromCommandline = TRUE;
612 } else if (strcmp (optarg,"svg") == 0) {
613 exportType = 3;
614 exportFromCommandline = TRUE;
615 } else if (strcmp (optarg,"ps") == 0) {
616 exportType = 4;
617 exportFromCommandline = TRUE;
619 else if (strcmp (optarg,"rs274x") == 0) {
620 exportType = 5;
621 exportFromCommandline = TRUE;
623 else if (strcmp (optarg,"drill") == 0) {
624 exportType = 6;
625 exportFromCommandline = TRUE;
627 else {
628 fprintf(stderr, "Unrecognized export type.\n");
629 exit(1);
631 break;
632 case 'd':
633 screen.dump_parsed_image = 1;
634 break;
635 case '?':
636 case 'h':
637 #ifdef HAVE_GETOPT_LONG
638 printf("Usage: gerbv [OPTIONS...] [FILE...]\n\n");
639 printf("Available options:\n");
640 printf(" -B, --border=<b> Border around the image in percent of the\n");
641 printf(" width/height. Defaults to 5%%.\n");
642 printf(" -D, --dpi=<XxY>or<R> Resolution (Dots per inch) for the output\n");
643 printf(" bitmap. With the format <XxY>, different\n");
644 printf(" resolutions for X- and Y-direction are used.\n");
645 printf(" With the format <R>, both are the same.\n");
646 printf(" -O, --origin=<XxY> Use the specified coordinates (in inches)\n");
647 printf(" for the lower left corner.\n");
648 printf(" -V, --version Print version of gerbv.\n");
649 printf(" -a, --antialias Use antialiasing for generated bitmap output.\n");
650 printf(" -b, --background=<hex> Use background color <hex> (like #RRGGBB).\n");
651 printf(" -f, --foreground=<hex> Use foreground color <hex> (like #RRGGBB or\n");
652 printf(" #RRGGBBAA for setting the alpha).\n");
653 printf(" Use multiple -f flags to set the color for\n");
654 printf(" multiple layers.\n");
655 printf(" -h, --help Print this help message.\n");
656 printf(" -l, --log=<logfile> Send error messages to <logfile>.\n");
657 printf(" -o, --output=<filename> Export to <filename>\n");
658 printf(" -p, --project=<prjfile> Load project file <prjfile>\n");
659 printf(" -W, --window_inch=<WxH> Window size in inches <WxH> for the\n");
660 printf(" exported image.\n");
661 printf(" -w, --window=<WxH> Window size in pixels <WxH> for the\n");
662 printf(" exported image. Autoscales to fit\n");
663 printf(" if no resolution is specified. If a\n");
664 printf(" resolution is specified, it will clip.\n");
665 printf(" -t, --tools=<toolfile> Read Excellon tools from file <toolfile>.\n");
666 printf(" -T, --translate=<X,Y> Translate the image by <X,Y> (useful for\n");
667 printf(" arranging panels). Use multiple -T flags\n");
668 printf(" for multiple layers.\n");
669 printf(" -x, --export=<png/pdf/ps/svg/ Export a rendered picture to a file with\n");
670 printf(" rs274x/drill> the specified format.\n");
673 #else
674 printf("Usage: gerbv [OPTIONS...] [FILE...]\n\n");
675 printf("Available options:\n");
676 printf(" -B<b> Border around the image in percent of the\n");
677 printf(" width/height. Defaults to 5%%.\n");
678 printf(" -D<XxY>or<R> Resolution (Dots per inch) for the output\n");
679 printf(" bitmap. With the format <XxY>, different\n");
680 printf(" resolutions for X- and Y-direction are used.\n");
681 printf(" With the format <R>, both are the same.\n");
682 printf(" -O<XxY> Use the specified coordinates (in inches)\n");
683 printf(" for the lower left corner.\n");
684 printf(" -V Print version of gerbv.\n");
685 printf(" -a Use antialiasing for generated bitmap output.\n");
686 printf(" -b<hexcolor> Use background color <hexcolor> (like #RRGGBB)\n");
687 printf(" -f<hexcolor> Use foreground color <hexcolor> (like #RRGGBB or\n");
688 printf(" #RRGGBBAA for setting the alpha).\n");
689 printf(" Use multiple -f flags to set the color for\n");
690 printf(" multiple layers.\n");
691 printf(" -h Print this help message.\n");
692 printf(" -l<logfile> Send error messages to <logfile>\n");
693 printf(" -o<filename> Export to <filename>\n");
694 printf(" -p<prjfile> Load project file <prjfile>\n");
695 printf(" -W<WxH> Window size in inches <WxH> for the\n");
696 printf(" exported image\n");
697 printf(" -w<WxH> Window size in pixels <WxH> for the\n");
698 printf(" exported image. Autoscales to fit\n");
699 printf(" if no resolution is specified. If a\n");
700 printf(" resolution is specified, it will clip.\n");
701 printf(" exported image\n");
702 printf(" -t<toolfile> Read Excellon tools from file <toolfile>\n");
703 printf(" -T<X,Y> Translate the image by <X,Y> (useful for\n");
704 printf(" arranging panels). Use multiple -T flags\n");
705 printf(" for multiple layers.\n");
706 printf(" -x <png/pdf/ps/svg/ Export a rendered picture to a file with\n");
707 printf(" rs274x/drill> the specified format\n");
709 #endif /* HAVE_GETOPT_LONG */
710 exit(1);
711 break;
712 default :
713 printf("Not handled option [%d=%c]\n", read_opt, read_opt);
718 * If project is given, load that one and use it for files and colors.
719 * Else load files (eventually) given on the command line.
720 * This limits you to either give files on the commandline or just load
721 * a project.
723 if (project_filename) {
724 printf("Loading project %s...\n", project_filename);
725 /* calculate the absolute pathname to the project if the user
726 used a relative path */
727 g_free (mainProject->path);
728 if (!g_path_is_absolute(project_filename)) {
729 gchar *fullName = g_build_filename (g_get_current_dir (),
730 project_filename, NULL);
731 main_open_project_from_filename (mainProject, fullName);
732 mainProject->path = g_path_get_dirname (fullName);
733 g_free (fullName);
734 } else {
735 main_open_project_from_filename (mainProject, project_filename);
736 mainProject->path = g_path_get_dirname (project_filename);
738 } else {
739 gint loadedIndex = 0;
740 for(i = optind ; i < argc; i++) {
741 g_free (mainProject->path);
742 if (!g_path_is_absolute(argv[i])) {
743 gchar *fullName = g_build_filename (g_get_current_dir (),
744 argv[i], NULL);
745 gerbv_open_layer_from_filename_with_color (mainProject, fullName,
746 mainDefaultColors[loadedIndex % NUMBER_OF_DEFAULT_COLORS].red*257,
747 mainDefaultColors[loadedIndex % NUMBER_OF_DEFAULT_COLORS].green*257,
748 mainDefaultColors[loadedIndex % NUMBER_OF_DEFAULT_COLORS].blue*257,
749 mainDefaultColors[loadedIndex % NUMBER_OF_DEFAULT_COLORS].alpha*257);
750 mainProject->path = g_path_get_dirname (fullName);
751 g_free (fullName);
752 } else {
753 gerbv_open_layer_from_filename_with_color (mainProject, argv[i],
754 mainDefaultColors[loadedIndex % NUMBER_OF_DEFAULT_COLORS].red*257,
755 mainDefaultColors[loadedIndex % NUMBER_OF_DEFAULT_COLORS].green*257,
756 mainDefaultColors[loadedIndex % NUMBER_OF_DEFAULT_COLORS].blue*257,
757 mainDefaultColors[loadedIndex % NUMBER_OF_DEFAULT_COLORS].alpha*257);
758 mainProject->path = g_path_get_dirname (argv[i]);
760 loadedIndex++;
764 screen.unit = GERBV_DEFAULT_UNIT;
765 if (exportFromCommandline) {
766 /* load the info struct with the default values */
768 gboolean freeFilename = FALSE;
770 if (!exportFilename) {
771 if (exportType == 1) {
772 exportFilename = g_strdup ("output.png");
773 } else if (exportType == 2) {
774 exportFilename = g_strdup ("output.pdf");
775 } else if (exportType == 3) {
776 exportFilename = g_strdup ("output.svg");
777 } else if (exportType == 4){
778 exportFilename = g_strdup ("output.ps");
779 } else if (exportType == 5){
780 exportFilename = g_strdup ("output.gbx");
781 } else {
782 exportFilename = g_strdup ("output.cnc");
784 freeFilename = TRUE;
787 gerbv_render_size_t bb;
788 gerbv_render_get_boundingbox(mainProject, &bb);
789 // Set origin to the left-bottom corner if it is not specified
790 if(!userSuppliedOrigin){
791 userSuppliedOriginX = bb.left;
792 userSuppliedOriginY = bb.top;
795 float width = bb.right - userSuppliedOriginX + 0.001; // Plus a little extra to prevent from
796 float height = bb.bottom - userSuppliedOriginY + 0.001; // missing items due to round-off errors
797 // If the user did not specify a height and width, autoscale w&h till full size from origin.
798 if(!userSuppliedWindow){
799 userSuppliedWidth = width;
800 userSuppliedHeight = height;
801 }else{
802 // If size was specified in pixels, and no resolution was specified, autoscale resolution till fit
803 if( (!userSuppliedDpi)&& userSuppliedWindowInPixels){
804 userSuppliedDpiX = MIN(((userSuppliedWidth-0.5) / width),((userSuppliedHeight-0.5) / height));
805 userSuppliedDpiY = userSuppliedDpiX;
806 userSuppliedOriginX -= 0.5/userSuppliedDpiX;
807 userSuppliedOriginY -= 0.5/userSuppliedDpiY;
811 // Add the border size (if there is one)
812 if(userSuppliedBorder!=0){
813 // If supplied in inches, add a border around the image
814 if(!userSuppliedWindowInPixels){
815 userSuppliedOriginX -= (userSuppliedWidth*userSuppliedBorder)/2.0;
816 userSuppliedOriginY -= (userSuppliedHeight*userSuppliedBorder)/2.0;
817 userSuppliedWidth += userSuppliedWidth*userSuppliedBorder;
818 userSuppliedHeight += userSuppliedHeight*userSuppliedBorder;
820 // If supplied in pixels, shrink image content for border_size
821 else{
822 userSuppliedOriginX -= ((userSuppliedWidth/userSuppliedDpiX)*userSuppliedBorder)/2.0;
823 userSuppliedOriginY -= ((userSuppliedHeight/userSuppliedDpiX)*userSuppliedBorder)/2.0;
824 userSuppliedDpiX -= (userSuppliedDpiX*userSuppliedBorder);
825 userSuppliedDpiY -= (userSuppliedDpiY*userSuppliedBorder);
829 if(!userSuppliedWindowInPixels){
830 userSuppliedWidth *= userSuppliedDpiX;
831 userSuppliedHeight *= userSuppliedDpiY;
834 // Make sure there is something valid in it. It could become negative if
835 // the userSuppliedOrigin is further than the bb.right or bb.top.
836 if(userSuppliedWidth <=0)
837 userSuppliedWidth = 1;
838 if(userSuppliedHeight <=0)
839 userSuppliedHeight = 1;
842 gerbv_render_info_t renderInfo = {userSuppliedDpiX, userSuppliedDpiY,
843 userSuppliedOriginX, userSuppliedOriginY, userSuppliedAntiAlias?3:2,
844 userSuppliedWidth,userSuppliedHeight };
846 if (exportType == 1) {
847 gerbv_export_png_file_from_project (mainProject, &renderInfo, exportFilename);
848 } else if (exportType == 2) {
849 gerbv_export_pdf_file_from_project (mainProject, &renderInfo, exportFilename);
850 } else if (exportType == 3) {
851 gerbv_export_svg_file_from_project (mainProject, &renderInfo, exportFilename);
852 } else if (exportType == 4) {
853 gerbv_export_postscript_file_from_project (mainProject, &renderInfo, exportFilename);
854 } else if (exportType == 5) {
855 if (mainProject->file[0]->image) {
856 gerbv_image_t *exportImage;
857 exportImage = gerbv_image_duplicate_image (mainProject->file[0]->image, &mainDefaultTransformations[0]);
858 /* if we have more than one file, we need to merge them before exporting */
859 for(i = mainProject->last_loaded; i > 0; i--) {
860 if (mainProject->file[i]) {
861 gerbv_image_copy_image (mainProject->file[i]->image, &mainDefaultTransformations[i], exportImage);
864 gerbv_export_rs274x_file_from_image (exportFilename, exportImage,
865 &mainProject->file[0]->transform);
866 gerbv_destroy_image (exportImage);
868 else {
869 fprintf(stderr, "A valid file was not loaded.\n");
870 exit(1);
872 } else if (exportType == 6) {
873 if (mainProject->file[0]->image) {
874 gerbv_image_t *exportImage;
875 exportImage = gerbv_image_duplicate_image (mainProject->file[0]->image, &mainDefaultTransformations[0]);
876 /* if we have more than one file, we need to merge them before exporting */
877 for(i = mainProject->last_loaded; i > 0; i--) {
878 if (mainProject->file[i]) {
879 gerbv_image_copy_image (mainProject->file[i]->image, &mainDefaultTransformations[i], exportImage);
882 gerbv_export_drill_file_from_image (exportFilename, exportImage,
883 &mainProject->file[0]->transform);
884 gerbv_destroy_image (exportImage);
886 else {
887 fprintf(stderr, "A valid file was not loaded.\n");
888 exit(1);
892 if (freeFilename)
893 free (exportFilename);
894 /* exit now and don't start up gtk if this is a command line export */
895 exit(0);
897 gtk_init (&argc, &argv);
898 interface_create_gui (req_width, req_height);
900 /* we've exited the GTK loop, so free all resources */
901 render_free_screen_resources();
902 gerbv_destroy_project (mainProject);
903 return 0;
904 } /* main */