1/*********************************************************************** 2 * * 3 * $Id: hpgs.c 390 2007-03-19 15:56:42Z softadm $ 4 * * 5 * hpgs - HPGl Script, a hpgl/2 interpreter, which uses a Postscript * 6 * API for rendering a scene and thus renders to a variety of * 7 * devices and fileformats. * 8 * * 9 * (C) 2004-2006 EV-i Informationstechnologie GmbH http://www.ev-i.at * 10 * * 11 * Author: Wolfgang Glas * 12 * * 13 * hpgs is free software; you can redistribute it and/or * 14 * modify it under the terms of the GNU Lesser General Public * 15 * License as published by the Free Software Foundation; either * 16 * version 2.1 of the License, or (at your option) any later version. * 17 * * 18 * hpgs is distributed in the hope that it will be useful, * 19 * but WITHOUT ANY WARRANTY; without even the implied warranty of * 20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * 21 * Lesser General Public License for more details. * 22 * * 23 * You should have received a copy of the GNU Lesser General Public * 24 * License along with this library; if not, write to the * 25 * Free Software Foundation, Inc., 59 Temple Place, Suite 330, * 26 * Boston, MA 02111-1307 USA * 27 * * 28 *********************************************************************** 29 * * 30 * The main program. * 31 * * 32 ***********************************************************************/ 33 34#include <hpgs.h> 35#include <string.h> 36#include <math.h> 37#include <errno.h> 38#include <locale.h> 39 40#if defined ( __MINGW32__ ) || defined ( _MSC_VER ) 41#include<malloc.h> 42#else 43#include<alloca.h> 44#endif 45 46/*! \mainpage The HPGS documentation 47 48 \section intro_sec Introduction 49 50 51 HPGS has been developed by 52 <A HREF="http://www.ev-i.at">EV-i Informationstechnologie GmbH</A> 53 and has been published under the 54 <A HREF="http://www.fsf.org/licenses/lgpl.html">LGPL</A>. 55 56 For Details visit the <A HREF="http://hpgs.berlios.de">project's homepage</A>. 57 58 \section install_sec Installation 59 60 See the file INSTALL of the distribution. 61 62 \section invoke_sec Invoking hpgs 63 64 \verbinclude hpgs-args.txt 65 66 \section api_sec The hpgs API. 67 68 HPGS is designed to be highly modular and may be used inside 69 C or C++ programs for either displaying HPGL files or 70 drawing a vector graphics sceneery to an image. 71 72 Refer to the \ref reader, \ref device, \ref paint_device and 73 \ref image modules in order to get an impression what the hpgs API 74 can do for you. 75 */ 76 77 78#ifdef WIN32 79 80#include <windows.h> 81 82static char *get_aux_path(void) 83{ 84 const char *key = "SOFTWARE\\ev-i\\hpgs"; 85 DWORD len; 86 HKEY hkey; 87 char *ret; 88 const char *prg; 89 90 if ((RegOpenKeyEx(HKEY_CURRENT_USER, 91 key, 0, KEY_READ, &hkey) == ERROR_SUCCESS || 92 RegOpenKeyEx(HKEY_LOCAL_MACHINE, 93 key, 0, KEY_READ, &hkey) == ERROR_SUCCESS )&& 94 RegQueryValueEx(hkey,"prefix",NULL,NULL,NULL,&len) == ERROR_SUCCESS) 95 { 96 ret = malloc(len+2); 97 98 if (RegQueryValueEx(hkey,"prefix",NULL,NULL,ret,&len) != ERROR_SUCCESS) 99 { free (ret); ret = 0; } 100 101 RegCloseKey(hkey); 102 103 return ret; 104 } 105 106 prg = getenv("PROGRAMFILES"); 107 108 if (prg) 109 return hpgs_sprintf_malloc("%s\\EV-i",prg); 110 111 return strdup("C:\\Programme\\EV-i"); 112} 113#else 114 115#ifndef HPGS_DEFAULT_PREFIX 116#define HPGS_DEFAULT_PREFIX "/usr/local" 117#endif 118 119static char *get_aux_path(void) 120{ 121 char *p=getenv("EV_I_PREFIX"); 122 123 if (!p) 124 return strdup(HPGS_DEFAULT_PREFIX); 125 126 return strdup(p); 127} 128#endif 129 130static int usage (void) 131{ 132 fprintf (stderr,hpgs_i18n( 133 "\n" 134 " hpgs v%s - HPGl Script, a hpgl/2 interpreter/renderer.\n" 135 "\n" 136 " (C) 2004-2006 ev-i Informationstechnologie GmbH (http://www.ev-i.at)\n" 137 " published under the LGPL (http://www.fsf.org/licenses/lgpl.html).\n" 138 "\n" 139 "Type `hpgs --help' for a detailed description of cmd line options.\n") 140 ,HPGS_VERSION ); 141 142 hpgs_cleanup(); 143 144 return 0; 145} 146 147static int help (void) 148{ 149 fprintf (stderr,hpgs_i18n( 150 "\n" 151 " hpgs v%s - HPGl Script, a hpgl/2 interpreter/renderer.\n" 152 "\n" 153 " (C) 2004-2006 ev-i Informationstechnologie GmbH (http://www.ev-i.at)\n" 154 " published under the LGPL (http://www.fsf.org/licenses/lgpl.html).\n" 155 "\n" 156 "usage: hpgs [-i] [-v] [-q] [-d <dev>] [options...] [-o <out>] <in1> <in2>...\n" 157 " -i ... Ignore plotsize from PS and determine\n" 158 " the plotsize from the file content.\n" 159 " --linewidth-size ... Account for linewidths in the plotsize\n" 160 " calculation for -i (default behaviour).\n" 161 " --no-linewidth-size ... Ignore linewidths in the plotsize\n" 162 " calculation for -i.\n" 163 " -v ... Increase verbosity.\n" 164 " -q ... Decrease verbosity, be quiet.\n" 165 " -o <out> ... specifiy the output filename. If not specified, write\n" 166 " to stdout.\n" 167 " -m ... Switch to multipage mode, if a single file is given on the.\n" 168 " command line. If not specified, only the first page of the input\n" 169 " file is processed.\n" 170 " -w ... Correct linewidth by given factor (default: 1).\n" 171 " -d ... Specifiy the output device. The default is the\n" 172 " native 'eps' device, which writes a simple eps file.\n" 173 " See section `Supported devices' below.\n" 174 " -a ... Use antialiasing when rendering to a png image.\n" 175 " --thin-alpha=<a>\n" 176 " Specifiy the minimal alpha value for thin lines.\n" 177 " allowed values lie in the interval [0.001,1.0] (default: 0.25).\n" 178 " -I ... Specifiy image interpolation.\n" 179 " --rop3 ... Use ROP3 raster operations for rendering on devices\n" 180 " with ROP3 capabilities (default).\n" 181 " --no-rop3 ... Suppress usage of ROP3 raster operations.\n" 182 " -c ... Specifiy the compression level for png writing.\n" 183 " -r ... Specifiy the device resolution in dpi.\n" 184 " If no y-resolution is given, the y-resolution\n" 185 " is set to the same value as the x-resolution.\n" 186 " -p ... Specifiy the maximum pixel size of the device.\n" 187 " This is in fact an alternate method to specify the\n" 188 " resolution of the device. If -p is given, the device\n" 189 " resolution is caclulated in a way, that the plot fits\n" 190 " into the given rectangle.\n" 191 " If no y-size is given, the size y-size\n" 192 " is set to the same value as the x-size.\n" 193 " -s<papersize> ... Specifiy the plot size in pt (1/72 inch).\n" 194 " If -s is not given, the size is calculated from\n" 195 " the contents of the hpgl file.\n" 196 " The <papersize> may be either one of the standard\n" 197 " paper sizes A0,A1,A2,A3 or A4, their landscape versions\n" 198 " A0l,A1l,A2l,A3l or A4l or a size in the format <width>x<height>\n" 199 " where <width> and <height> specify a physical length in one of the\n" 200 " formats <l>,<l>mm,<l>cm,<l>inch or <l>pt. <l> is a floating point\n" 201 " number, the default unit is PostScript pt (1/72 inch).\n" 202 " --paper=<papersize>\n" 203 " Specify a paper size of the output device. All plots\n" 204 " are scaled to this paper size respecting the given border.\n" 205 " If no fixed paper size is given, each page in the output\n" 206 " file has an individual size adapted to the size of the HPGL\n" 207 " content of the page.\n" 208 " The format of <papersize> is decribed above for -s.\n" 209 " --border=<border>\n" 210 " Specify a border for placing plots on output pages.\n" 211 " --rotation=<angle>\n" 212 " Specify an angle for placing plots on output pages.\n" 213 " --stamp=<stamp>\n" 214 " Specify a string, which is printed in the background.\n" 215 " --stamp-encoding=<enc>\n" 216 " Specify an the name of the encoding of the string, which\n" 217 " is given in --stamp. Default is iso-8859-1.\n" 218 " --stamp-size=<pt>\n" 219 " Specify the size of the stamp specified with --stamp\n" 220 " in point. Default value: 500pt.\n" 221 " --dump-png=<filename>\n" 222 " Specify a filename for dumping inline PCL images in.\n" 223 " PNG format. The actual filenames written are:\n" 224 " <filename>0001.png\n" 225 " <filename>0002.png\n" 226 " .....\n" 227 " If <filename> contains an extension '.png' the counter\n" 228 " is put between the basename and the '.png' extension.\n" 229 " --help\n" 230 " Displays this usage information.\n" 231 " --version\n" 232 " Displays the version information.\n" 233 "\n" 234 "Supported devices (option -d):\n" 235 "\n" 236 " bbox ... writes a PostScript BoundingBox to stdout.\n" 237 " ps ... writes a multipage PostScript file.\n" 238 " eps ... writes an eps files.\n" 239 " png_256 ... writes an indexed 8bpp png image.\n" 240 " png_gray... writes a grayscale 8bpp png image.\n" 241 " png_rgb ... writes a rgb 24bpp png image.\n" 242 " png_gray_alpha ... writes a grayscale 16bpp png image\n" 243 " with an alpha channel.\n" 244 " png_rgb_alpha ... writes a rgb 32bpp png image\n" 245 " with an alpha channel.\n" 246 " cairo_png ... writes a rgb 32bpp png image using\n" 247 " the cairo library (experimental).\n") 248 ,HPGS_VERSION ); 249 250 hpgs_cleanup(); 251 252 return 0; 253} 254 255static int get_double_arg(const char *arg, double *val) 256{ 257 char * endptr = (char*)arg; 258 *val = strtod(arg,&endptr); 259 return (*endptr || endptr == arg) ? -1 : 0; 260} 261 262static int get_double_pair(const char *arg, double *xval, double *yval) 263{ 264 char * endptr = (char*)arg; 265 *xval = strtod(arg,&endptr); 266 267 if (endptr == arg) return -1; 268 if (*endptr == '\0') { *yval = *xval; return 0; } 269 if (*endptr != 'x') return -1; 270 271 const char *yarg=endptr+1; 272 273 *yval = strtod(yarg,&endptr); 274 return (*endptr || endptr == yarg) ? -1 : 0; 275} 276 277static int get_int_arg(const char *arg, int *val) 278{ 279 char * endptr = (char*)arg; 280 *val = strtol(arg,&endptr,10); 281 return (*endptr) ? -1 : 0; 282} 283 284static int get_int_pair(const char *arg, int *xval, int *yval) 285{ 286 char * endptr = (char*)arg; 287 *xval = strtod(arg,&endptr); 288 289 if (*endptr == '\0') { *yval = *xval; return 0; } 290 if (*endptr != 'x') return -1; 291 292 const char *yarg=endptr+1; 293 294 *yval = strtod(yarg,&endptr); 295 return (*endptr || endptr == yarg) ? -1 : 0; 296} 297 298// helper function for supporting old device-specific options, which 299// are now global ones. 300static int get_dev_arg_value(const char *dev_name,int dev_name_len, 301 const char *opt, const char *argv[], 302 const char **value, int *narg) 303{ 304 char *opt_name = alloca(4+dev_name_len+strlen(opt)); 305 306 // contruct string --<dev_name><opt> 307 opt_name[1] = opt_name[0] = '-'; 308 memcpy(opt_name+2,dev_name,dev_name_len); 309 strcpy(&opt_name[2+dev_name_len],opt); 310 311 return hpgs_get_arg_value(opt_name,argv,value,narg); 312} 313 314/* 315 The main program analyses the cmd line argument and delegates the work. 316*/ 317 318#define HPGS_MAX_PLUGIN_ARGS 32 319 320int main(int argc, const char *argv[]) 321{ 322 const char *dev_name="eps"; 323 int dev_name_len = 3; 324 const char *out_fn=0; 325 const char *stamp=0; 326 const char *stamp_enc=0; 327 const char *png_dump_fn=0; 328 int ifile; 329 char *aux_path; 330 double x_dpi=72.0; 331 double y_dpi=72.0; 332 hpgs_bbox bbox= { 0.0, 0.0, 0.0, 0.0 }; 333 double paper_angle = 0.0; 334 double paper_border = 0.0; 335 double paper_width = 0.0; 336 double paper_height = 0.0; 337 double lw_factor=-1.0; 338 double thin_alpha=0.25; 339 double stamp_size=500.0; 340 int x_px_size=0; 341 int y_px_size=0; 342 hpgs_bool multipage=HPGS_FALSE; 343 hpgs_bool ignore_ps=HPGS_FALSE; 344 hpgs_bool do_linewidth=HPGS_TRUE; 345 hpgs_bool do_rop3=HPGS_TRUE; 346 int verbosity=1; 347 int compression=6; 348 hpgs_bool antialias=HPGS_FALSE; 349 int image_interpolation=0; 350 hpgs_device *size_dev = 0; 351 hpgs_device *plot_dev = 0; 352 hpgs_istream *in = 0; 353 hpgs_reader *reader = 0; 354 hpgs_png_image *image = 0; 355 const char *plugin_argv[HPGS_MAX_PLUGIN_ARGS]; 356 int plugin_argc = 0; 357 int ret = 1; 358 359#ifdef LC_MESSAGES 360 setlocale(LC_MESSAGES,""); 361#endif 362 setlocale(LC_CTYPE,""); 363 364 aux_path = get_aux_path(); 365 366 if (!aux_path) 367 { 368 fprintf(stderr,hpgs_i18n("Error getting installation path: %s.\n"), 369 strerror(errno)); 370 return 1; 371 } 372 373 hpgs_init(aux_path); 374 free(aux_path); 375 376 memset(plugin_argv,0,sizeof(plugin_argv)); 377 378 ++argv; 379 --argc; 380 381 while (argc>0) 382 { 383 int narg = 1; 384 const char *value; 385 386 if (strcmp(argv[0],"--") == 0) 387 { 388 ++argv; 389 --argc; 390 break; 391 } 392 else if (strcmp(argv[0],"-v") == 0) 393 { 394 ++verbosity; 395 } 396 else if (strcmp(argv[0],"-q") == 0 || strcmp(argv[0],"-dQUIET") == 0) 397 { 398 --verbosity; 399 } 400 else if (strcmp(argv[0],"-i") == 0) 401 { 402 ignore_ps=HPGS_TRUE; 403 } 404 else if (strcmp(argv[0],"-m") == 0) 405 { 406 multipage=HPGS_TRUE; 407 } 408 else if (hpgs_get_arg_value("-d",argv,&value,&narg)) 409 { 410 dev_name = value; 411 dev_name_len = strlen(dev_name); 412 413 if (plugin_argc) 414 { 415 fprintf(stderr,hpgs_i18n("Error: Device options specified before -d argument.\n")); 416 return usage(); 417 } 418 } 419 else if (hpgs_get_arg_value("--stamp=",argv,&value,&narg)) 420 { 421 stamp = value; 422 } 423 else if (hpgs_get_arg_value("--stamp-encoding=",argv,&value,&narg)) 424 { 425 stamp_enc = value; 426 } 427 else if (hpgs_get_arg_value("--stamp-size=",argv,&value,&narg)) 428 { 429 if (hpgs_parse_length(value,&stamp_size)) 430 { 431 fprintf(stderr,hpgs_i18n("Error: --stamp-size= must be followed by a valid length.\n")); 432 return usage(); 433 } 434 435 if (stamp_size < 20.0 || stamp_size > 2000.0) 436 { 437 fprintf(stderr,hpgs_i18n("Error: stamp-size must lie in the interval [20,2000]pt.\n")); 438 return usage(); 439 } 440 } 441 else if (hpgs_get_arg_value("--dump-png=",argv,&value,&narg)) 442 { 443 png_dump_fn = value; 444 } 445 else if (hpgs_get_arg_value("-o",argv,&value,&narg)) 446 { 447 out_fn = value; 448 } 449 else if (strcmp(argv[0],"-a") == 0) 450 { 451 antialias = HPGS_TRUE; 452 } 453 else if (hpgs_get_arg_value("-I",argv,&value,&narg)) 454 { 455 if (get_int_arg(value,&image_interpolation)) 456 { 457 if (narg == 1) 458 { 459 fprintf(stderr,hpgs_i18n("Error: -I must be followed by an integer number.\n")); 460 return usage(); 461 } 462 else 463 { 464 image_interpolation= 1; 465 narg = 1; 466 } 467 } 468 469 if (image_interpolation < 0 || image_interpolation > 1) 470 { 471 fprintf(stderr,hpgs_i18n("Error: The argument to -I must be 0 or 1.\n")); 472 return usage(); 473 } 474 } 475 else if (hpgs_get_arg_value("-c",argv,&value,&narg)) 476 { 477 if (get_int_arg(value,&compression)) 478 { 479 fprintf(stderr,hpgs_i18n("Error: -c must be followed by an integer number.\n")); 480 return usage(); 481 } 482 483 if (compression < 1 || compression > 9) 484 { 485 fprintf(stderr,hpgs_i18n("Error: compression factor must lie in the interval [1,9].\n")); 486 return usage(); 487 } 488 } 489 else if (hpgs_get_arg_value("-w",argv,&value,&narg)) 490 { 491 if (get_double_arg(value,&lw_factor)) 492 { 493 fprintf(stderr,hpgs_i18n("Error: -w must be followed by a floating point number.\n")); 494 return usage(); 495 } 496 497 if (lw_factor < 0.0 || lw_factor > 10.0) 498 { 499 fprintf(stderr,hpgs_i18n("Error: Linewidth factor must lie in the interval [0.0,10.0].\n")); 500 return usage(); 501 } 502 } 503 else if (hpgs_get_arg_value("--thin-alpha=",argv,&value,&narg)) 504 { 505 if (get_double_arg(value,&thin_alpha)) 506 { 507 fprintf(stderr,hpgs_i18n("Error: --thin-alpha= must be followed by a floating point number.\n")); 508 return usage(); 509 } 510 511 if (thin_alpha < 0.01 || thin_alpha > 10.0) 512 { 513 fprintf(stderr,hpgs_i18n("Error: Thin alpha must lie in the interval [0.01,10.0].\n")); 514 return usage(); 515 } 516 } 517 else if (hpgs_get_arg_value("-r",argv,&value,&narg)) 518 { 519 if (get_double_pair(value,&x_dpi,&y_dpi)) 520 { 521 fprintf(stderr,hpgs_i18n("Error: -r must be followed by <res> or <xres>x<yres>.\n")); 522 return usage(); 523 } 524 525 if (x_dpi < 5.0 || y_dpi < 5.0) 526 { 527 fprintf(stderr,hpgs_i18n("Error: Resolutions must be at least 5 dpi.\n")); 528 return usage(); 529 } 530 } 531 else if (hpgs_get_arg_value("-p",argv,&value,&narg)) 532 { 533 if (get_int_pair(value,&x_px_size,&y_px_size)) 534 { 535 fprintf(stderr,hpgs_i18n("Error: -p must be followed by <sz> or <xsz>x<ysz>.\n")); 536 return usage(); 537 } 538 539 if (y_px_size < 20 || x_px_size < 20) 540 { 541 fprintf(stderr,hpgs_i18n("Error: Pixel sizes must be at least 20px.\n")); 542 return usage(); 543 } 544 } 545 else if (hpgs_get_arg_value("-s",argv,&value,&narg)) 546 { 547 double x_size,y_size; 548 549 if (hpgs_parse_papersize(value,&x_size, &y_size)<0) 550 { 551 fprintf(stderr,hpgs_i18n("Error: -s must be followed by a valid paper size.\n")); 552 return usage(); 553 } 554 555 if (x_size < 72.0 || y_size < 72.0) 556 { 557 fprintf(stderr,hpgs_i18n("Error: The plot size must be at least 72 pt.\n")); 558 return usage(); 559 } 560 561 bbox.urx = x_size; 562 bbox.ury = y_size; 563 } 564 else if (hpgs_get_arg_value("--paper=",argv,&value,&narg)) 565 { 566 if (hpgs_parse_papersize(value,&paper_width,&paper_height)<0) 567 { 568 fprintf(stderr,hpgs_i18n("Error: --paper= must be followed by a valid paper size.\n")); 569 return usage(); 570 } 571 572 if (paper_width < 72.0 || paper_height < 72.0) 573 { 574 fprintf(stderr,hpgs_i18n("Error: The paper size must be at least 72 pt.\n")); 575 return usage(); 576 } 577 } 578 else if (hpgs_get_arg_value("--border=",argv,&value,&narg) || 579 // Allow old device-specific border parameters. 580 get_dev_arg_value(dev_name,dev_name_len,"-border=",argv,&value,&narg) ) 581 { 582 if (hpgs_parse_length(value,&paper_border)<0) 583 { 584 fprintf(stderr,hpgs_i18n("Error: --border= must be followed by a valid length.\n")); 585 return usage(); 586 } 587 588 if (paper_border < 0.0 || paper_border > 144.0) 589 { 590 fprintf(stderr,hpgs_i18n("Error: The page border must lie in the interval [0,144] pt.\n")); 591 return usage(); 592 } 593 } 594 else if (hpgs_get_arg_value("--rotation=",argv,&value,&narg) || 595 // Allow old device-specific rotation parameters. 596 get_dev_arg_value(dev_name,dev_name_len,"-rotation=",argv,&value,&narg) ) 597 { 598 if (hpgs_parse_length(value,&paper_angle)<0) 599 { 600 fprintf(stderr,hpgs_i18n("Error: --angle= must be followed by a valid angle.\n")); 601 return usage(); 602 } 603 } 604 else if (strcmp(argv[0],"--linewidth-size") == 0) 605 { 606 do_linewidth = HPGS_TRUE; 607 } 608 else if (strcmp(argv[0],"--no-linewidth-size") == 0) 609 { 610 do_linewidth = HPGS_FALSE; 611 } 612 else if (strcmp(argv[0],"--rop3") == 0) 613 { 614 do_rop3 = HPGS_TRUE; 615 } 616 else if (strcmp(argv[0],"--no-rop3") == 0) 617 { 618 do_rop3 = HPGS_FALSE; 619 } 620 else if (strcmp(argv[0],"--help") == 0) 621 { 622 return help(); 623 } 624 else if (strcmp(argv[0],"--version") == 0) 625 { 626 usage(); 627 return 0; 628 } 629 else if (strncmp(argv[0],"--",2) == 0 && 630 strncmp(argv[0]+2,dev_name,dev_name_len) == 0 && 631 argv[0][dev_name_len+2] == '-') 632 { 633 int l=strlen(argv[0]); 634 635 if (plugin_argc >= HPGS_MAX_PLUGIN_ARGS-1) 636 { 637 fprintf(stderr,hpgs_i18n("Error: Number of plugin-args exceeds maximum of %d.\n"), 638 HPGS_MAX_PLUGIN_ARGS-1); 639 return usage(); 640 } 641 642 plugin_argv[plugin_argc] = argv[0]+dev_name_len+2; 643 ++plugin_argc; 644 645 if (argv[0][l-1] == '=') 646 { 647 if (plugin_argc >= HPGS_MAX_PLUGIN_ARGS-1) 648 { 649 fprintf(stderr,hpgs_i18n("Error: Number of plugin-args exceed maximum of %d.\n"), 650 HPGS_MAX_PLUGIN_ARGS-1); 651 usage(); 652 } 653 654 plugin_argv[plugin_argc] = argv[2]; 655 ++plugin_argc; 656 657 narg=2; 658 } 659 } 660 else 661 { 662 if (argv[0][0] == '-') 663 { 664 fprintf(stderr,hpgs_i18n("Error: Unknown option %s given.\n"),argv[0]); 665 return usage(); 666 } 667 668 break; 669 } 670 671 argv+=narg; 672 argc-=narg; 673 } 674 675 if (argc < 1) 676 { 677 fprintf(stderr,hpgs_i18n("Error: No input file given.\n")); 678 return usage(); 679 } 680 681 if (argc > 1 && !multipage) 682 { 683 multipage = HPGS_TRUE; 684 } 685 686 // adjust default linewidth factor. 687 if (lw_factor < 0.0) 688 { 689 // This is the best choice for our basic, non-antialiased renderer, 690 // which rounds up pixel line widths. 691 if (antialias == 0 && strncmp(dev_name,"png_",4) == 0) 692 lw_factor = 0.5; 693 else 694 lw_factor = 1.0; 695 } 696 697 size_dev = (hpgs_device*)hpgs_new_plotsize_device(ignore_ps,do_linewidth); 698 699 if (!size_dev) 700 { 701 fprintf(stderr,hpgs_i18n("Error: Cannot create plotsize device.\n")); 702 goto cleanup; 703 } 704 705 in = hpgs_new_file_istream(argv[0]); 706 707 if (!in) 708 { 709 fprintf(stderr,hpgs_i18n("Error: Cannot open input file %s: %s\n"), 710 argv[0],strerror(errno)); 711 hpgs_device_destroy((hpgs_device*)size_dev); 712 goto cleanup; 713 } 714 715 reader = hpgs_new_reader(in,size_dev, 716 multipage,verbosity); 717 718 if (!reader) 719 { 720 fprintf(stderr,hpgs_i18n("Error: Cannot create hpgl reader: %s\n"),strerror(errno)); 721 goto cleanup; 722 } 723 724 hpgs_reader_set_lw_factor(reader,lw_factor); 725 726 // determine plot size, if not specified on the cmd line 727 if (bbox.urx < 72.0 || bbox.ury < 72.0) 728 { 729 // read in multiple pages. 730 for (ifile = 1; ifile < argc; ++ifile) 731 { 732 if (hpgs_read(reader,HPGS_FALSE)) 733 { 734 fprintf(stderr,hpgs_i18n("Error: Cannot determine plot size of file %s: %s\n"), 735 argv[ifile-1],hpgs_get_error()); 736 goto cleanup; 737 } 738 739 in = hpgs_new_file_istream(argv[ifile]); 740 741 if (!in) 742 { 743 fprintf(stderr,hpgs_i18n("Error: Cannot open input file %s: %s\n"), 744 argv[ifile],strerror(errno)); 745 goto cleanup; 746 } 747 748 hpgs_reader_attach(reader,in); 749 } 750 751 if (hpgs_read(reader,HPGS_TRUE)) 752 { 753 fprintf(stderr,hpgs_i18n("Error: Cannot determine plot size of file %s: %s\n"), 754 argv[ifile-1],hpgs_get_error()); 755 goto cleanup; 756 } 757 758 // get bounding box of first page. 759 // (will return overall boundingbox, if in singlepage mode.) 760 if (hpgs_getplotsize(size_dev,1,&bbox)<0) 761 { 762 fprintf(stderr,hpgs_i18n("Error: Cannot determine plotsize: %s\n"), 763 hpgs_get_error()); 764 goto cleanup; 765 } 766 767 if (hpgs_bbox_isempty(&bbox)) 768 { 769 fprintf(stderr,hpgs_i18n("Error: Empty bounding: %g %g %g %g.\n"), 770 bbox.llx,bbox.lly,bbox.urx,bbox.ury); 771 goto cleanup; 772 } 773 774 if (verbosity >= 1) 775 fprintf(stderr,"BoundingBox: %g %g %g %g.\n",bbox.llx,bbox.lly,bbox.urx,bbox.ury); 776 } 777 778 // set the appropriate page placement. 779 if (paper_width > 0.0 && paper_height > 0.0) 780 { 781 hpgs_reader_set_fixed_page(reader,&bbox, 782 paper_width,paper_height, 783 paper_border,paper_angle ); 784 } 785 else 786 { 787 paper_width = 200.0 * 72.0; 788 paper_height = 200.0 * 72.0; 789 790 hpgs_reader_set_dynamic_page(reader,&bbox, 791 paper_width,paper_height, 792 paper_border,paper_angle ); 793 } 794 795 if (strcmp(dev_name,"bbox") == 0) 796 { 797 int i; 798 FILE *out = out_fn ? fopen(out_fn,"wb") : stdout; 799 800 if (!out) 801 { 802 fprintf(stderr,hpgs_i18n("Error: Cannot open output file <%s>.\n"),out_fn); 803 goto cleanup; 804 } 805 806 for (i=0;i<10000;++i) 807 { 808 int r = hpgs_getplotsize(size_dev,i,&bbox); 809 810 if (r < 0) 811 { 812 fprintf(stderr,hpgs_i18n("Error: Cannot determine plotsize: %s\n"), 813 hpgs_get_error()); 814 fclose(out); 815 goto cleanup; 816 } 817 818 if (r) break; 819 820 if (i>0) 821 { 822 fprintf(out,"%%%%Page: %d %d.\n",i,i); 823 fprintf(out,"%%%%PageBoundingBox: %d %d %d %d.\n", 824 (int)floor(bbox.llx),(int)floor(bbox.lly), 825 (int)ceil(bbox.urx),(int)ceil(bbox.ury)); 826 fprintf(out,"%%%%PageHiResBoundingBox: %g %g %g %g.\n",bbox.llx,bbox.lly,bbox.urx,bbox.ury); 827 } 828 else 829 { 830 fprintf(out,"%%%%BoundingBox: %d %d %d %d.\n", 831 (int)floor(bbox.llx),(int)floor(bbox.lly), 832 (int)ceil(bbox.urx),(int)ceil(bbox.ury)); 833 fprintf(out,"%%%%HiResBoundingBox: %g %g %g %g.\n",bbox.llx,bbox.lly,bbox.urx,bbox.ury); 834 } 835 } 836 837 if (out != stdout) fclose(out); 838 839 ret=0; 840 goto cleanup; 841 } 842 else if (strcmp(dev_name,"eps") == 0) 843 { 844 plot_dev = 845 (hpgs_device*)hpgs_new_eps_device(out_fn,&bbox,do_rop3); 846 847 if (!plot_dev) 848 { 849 fprintf(stderr,hpgs_i18n("Error: Cannot create eps device.\n")); 850 goto cleanup; 851 } 852 } 853 else if (strcmp(dev_name,"ps") == 0) 854 { 855 plot_dev = 856 (hpgs_device*)hpgs_new_ps_device(out_fn,&bbox,do_rop3); 857 858 if (!plot_dev) 859 { 860 fprintf(stderr,hpgs_i18n("Error: Cannot create postscript device.\n")); 861 goto cleanup; 862 } 863 } 864 else if (strncmp(dev_name,"png_",4) == 0) 865 { 866 int depth = 8; 867 int palette = 0; 868 hpgs_paint_device *pdv; 869 870 if (strcmp(dev_name+4,"gray") == 0) 871 depth = 8; 872 else if (strcmp(dev_name+4,"gray_alpha") == 0) 873 depth = 16; 874 else if (strcmp(dev_name+4,"rgb") == 0) 875 depth = 24; 876 else if (strcmp(dev_name+4,"rgb_alpha") == 0) 877 depth = 32; 878 else if (strcmp(dev_name+4,"256") == 0) 879 palette = 1; 880 else 881 { 882 fprintf(stderr,hpgs_i18n("Error: png device %s in not supported.\n"), 883 dev_name); 884 goto cleanup; 885 } 886 887 if (x_px_size >= 20 && y_px_size >= 20) 888 { 889 // get overall bounding box, if pixel size is specified. 890 // This way no page image exceeds the given size and 891 // all images have the same resolution. 892 hpgs_bbox bb; 893 894 if (hpgs_getplotsize(size_dev,0,&bb)<0) 895 { 896 fprintf(stderr,hpgs_i18n("Error: Cannot determine overall plotsize: %s\n"), 897 hpgs_get_error()); 898 goto cleanup; 899 } 900 901 x_dpi = 72.0 * x_px_size / (bb.urx-bb.llx); 902 y_dpi = 72.0 * y_px_size / (bb.ury-bb.lly); 903 904 if (x_dpi > y_dpi) 905 { 906 x_dpi = y_dpi; 907 x_px_size = x_dpi * (bb.urx-bb.llx) / 72.0; 908 } 909 else 910 { 911 y_dpi = x_dpi; 912 y_px_size = y_dpi * (bb.ury-bb.lly) / 72.0; 913 } 914 } 915 else 916 { 917 // initialize the pixel size from the first page. 918 x_px_size = x_dpi * (bbox.urx-bbox.llx) / 72.0; 919 y_px_size = y_dpi * (bbox.ury-bbox.lly) / 72.0; 920 } 921 922 image = hpgs_new_png_image(x_px_size,y_px_size,depth,palette,do_rop3); 923 924 if (!image) 925 { 926 fprintf(stderr,hpgs_i18n("Error creating %dx%dx%d sized png image: %s.\n"), 927 x_px_size,y_px_size,depth,strerror(errno)); 928 goto cleanup; 929 } 930 931 hpgs_png_image_set_compression(image,compression); 932 933 pdv = hpgs_new_paint_device((hpgs_image*)image, 934 out_fn,&bbox, 935 antialias); 936 if (!pdv) 937 { 938 fprintf(stderr,hpgs_i18n("Error: Cannot create paint device.\n")); 939 goto cleanup; 940 } 941 942 hpgs_paint_device_set_image_interpolation(pdv,image_interpolation); 943 hpgs_paint_device_set_thin_alpha(pdv,thin_alpha); 944 // set the resolution of the image, although 945 // hpgs_new_paint_device has done this before. 946 // The reason is, that we know the resolution with more precision 947 // than hpgs_new_paint_device. 948 hpgs_image_set_resolution((hpgs_image*)image,x_dpi,y_dpi); 949 950 plot_dev = (hpgs_device *)pdv; 951 } 952 else 953 { 954 if (x_px_size >= 20 && y_px_size >= 20) 955 { 956 // calculate resolution from overall bounding box, 957 // if pixel size is specified. 958 // This way no page image exceeds the given size and 959 // all images have the same resolution. 960 hpgs_bbox bb; 961 962 if (hpgs_getplotsize(size_dev,0,&bb)<0) 963 { 964 fprintf(stderr,hpgs_i18n("Error: Cannot determine overall plotsize: %s\n"), 965 hpgs_get_error()); 966 goto cleanup; 967 } 968 969 x_dpi = 72.0 * x_px_size / (bb.urx-bb.llx); 970 y_dpi = 72.0 * y_px_size / (bb.ury-bb.lly); 971 972 if (x_dpi > y_dpi) 973 x_dpi = y_dpi; 974 else 975 y_dpi = x_dpi; 976 } 977 978 void *page_asset_ctxt = 0; 979 hpgs_reader_asset_func_t page_asset_func = 0; 980 void *frame_asset_ctxt = 0; 981 hpgs_reader_asset_func_t frame_asset_func = 0; 982 983 if (hpgs_new_plugin_device(&plot_dev, 984 &page_asset_ctxt, 985 &page_asset_func, 986 &frame_asset_ctxt, 987 &frame_asset_func, 988 dev_name,out_fn,&bbox, 989 x_dpi,y_dpi,do_rop3, 990 plugin_argc,plugin_argv)) 991 { 992 fprintf(stderr,hpgs_i18n("Error: Cannot create plugin device: %s\n"), 993 hpgs_get_error()); 994 goto cleanup; 995 } 996 997 if (page_asset_func) 998 hpgs_reader_set_page_asset_func(reader,page_asset_ctxt,page_asset_func); 999 1000 if (frame_asset_func) 1001 hpgs_reader_set_frame_asset_func(reader,frame_asset_ctxt,frame_asset_func); 1002 } 1003 1004 if (!plot_dev) 1005 { 1006 fprintf (stderr,hpgs_i18n("Error: invalid plot device name %s specified.\n"),dev_name); 1007 goto cleanup; 1008 } 1009 1010 if (png_dump_fn && hpgs_reader_set_png_dump(reader,png_dump_fn)) 1011 { 1012 fprintf(stderr,hpgs_i18n("Error: Cannot set png_dump filename to reader: %s\n"), 1013 hpgs_get_error()); 1014 goto cleanup; 1015 } 1016 1017 if (stamp && hpgs_device_stamp(plot_dev,&bbox,stamp,stamp_enc,stamp_size)) 1018 { 1019 fprintf(stderr,hpgs_i18n("Error: Cannot stamp plot: %s\n"), 1020 hpgs_get_error()); 1021 goto cleanup; 1022 } 1023 1024 if (hpgs_reader_imbue(reader,plot_dev)) 1025 { 1026 fprintf(stderr,hpgs_i18n("Error: Cannot imbue plot device to reader: %s\n"), 1027 hpgs_get_error()); 1028 goto cleanup; 1029 } 1030 1031 // re-open first file, if we have more than one input file. 1032 if (argc > 1) 1033 { 1034 in = hpgs_new_file_istream(argv[0]); 1035 1036 if (!in) 1037 { 1038 fprintf(stderr,hpgs_i18n("Error: Cannot open input file %s: %s\n"), 1039 argv[0],strerror(errno)); 1040 goto cleanup; 1041 } 1042 hpgs_reader_attach(reader,in); 1043 } 1044 1045 // read in multiple pages. 1046 for (ifile = 1; ifile < argc; ++ifile) 1047 { 1048 if (hpgs_read(reader,HPGS_FALSE)) 1049 { 1050 fprintf(stderr,hpgs_i18n("Error: Cannot process plot file %s: %s\n"), 1051 argv[ifile-1],hpgs_get_error()); 1052 goto cleanup; 1053 } 1054 1055 in = hpgs_new_file_istream(argv[ifile]); 1056 1057 if (!in) 1058 { 1059 fprintf(stderr,hpgs_i18n("Error: Cannot open input file %s: %s\n"), 1060 argv[ifile],strerror(errno)); 1061 goto cleanup; 1062 } 1063 1064 hpgs_reader_attach(reader,in); 1065 } 1066 1067 if (hpgs_read(reader,HPGS_TRUE)) 1068 { 1069 fprintf(stderr,hpgs_i18n("Error: Cannot process plot file %s: %s\n"), 1070 argv[ifile-1],hpgs_get_error()); 1071 goto cleanup; 1072 } 1073 1074 if (verbosity >= 2) 1075 fprintf(stderr,hpgs_i18n("Success.\n")); 1076 1077 ret = 0; 1078 1079 cleanup: 1080 if (reader) 1081 hpgs_destroy_reader(reader); 1082 1083 hpgs_cleanup(); 1084 1085 return ret; 1086} 1087