Beispiel #1
0
/* 
  Internal 
*/
static int hpgs_reader_set_number_of_pens(hpgs_reader *reader, int npens)
{
  double *pw =(double *)realloc(reader->pen_widths,npens*sizeof(double));

  if (!pw)
    return hpgs_set_error(hpgs_i18n("Out of memory growing pen width array."));
  
  reader->pen_widths = pw;

  hpgs_color *pc = (hpgs_color *)realloc(reader->pen_colors,npens*sizeof(hpgs_color));

  if (!pc)
    return hpgs_set_error(hpgs_i18n("Out of memory growing pen color array."));
  
  reader->pen_colors = pc;

  for (;reader->npens<npens;++reader->npens)
    {
      reader->pen_widths[reader->npens] = 1.0;
      reader->pen_colors[reader->npens].r = 0.0;
      reader->pen_colors[reader->npens].g = 0.0;
      reader->pen_colors[reader->npens].b = 0.0;
    }

  return 0;
}
Beispiel #2
0
// a function which recovers from a malformed command.
static int hpgl_recover(hpgs_reader *reader)
{
  size_t pos;

  if (hpgs_istream_tell(reader->in,&pos))
    return -1;

  reader->bytes_ignored = 0;
  
  while (reader->bytes_ignored < 256 &&
         (reader->last_byte = hpgs_getc(reader->in)) != ';')
    {
      if (reader->last_byte == EOF)
        return hpgs_set_error(hpgs_i18n("EOF during recovery from malformed HPGL command at file position %lu."),(unsigned long)pos);

      ++reader->bytes_ignored;
    }

  if (reader->bytes_ignored >= 256)
    return hpgs_set_error(hpgs_i18n("No semicolon in the next 256 bytes during recovery from malformed HPGL command at file position %lu."),(unsigned long)pos);

  reader->bytes_ignored = 0;
  reader->eoc = 1;

  return 0;
}
/* 
  HPGL command SC (SCale)
*/
int hpgs_reader_do_SC (hpgs_reader *reader)
{
  double xmin,xmax,ymin,ymax,left=50.0,bottom=50.0;
  int type=0;

  if (reader->eoc)
    {
      reader->sc_type = -1;
      hpgs_reader_set_default_transformation(reader);
      return 0;
    }

  if (hpgs_reader_read_double(reader,&xmin)) return -1;
  if (reader->eoc) return -1;
  if (hpgs_reader_read_double(reader,&xmax)) return -1;
  if (reader->eoc) return -1;

  if (xmin == xmax)
    return hpgs_set_error(hpgs_i18n("Empty x range."));

  if (hpgs_reader_read_double(reader,&ymin)) return -1;
  if (reader->eoc) return -1;
  if (hpgs_reader_read_double(reader,&ymax)) return -1;

  if (ymin == ymax)
    return hpgs_set_error(hpgs_i18n("Empty y range."));

  if (!reader->eoc &&
      hpgs_reader_read_int(reader,&type)) return -1;

  if (type == 1 && !reader->eoc)
    {
      if (hpgs_reader_read_double(reader,&left)) return -1;
      if (reader->eoc) return -1;
      if (hpgs_reader_read_double(reader,&bottom)) return -1;
    }

  reader->sc_type = type;
  reader->sc_xmin = xmin;
  reader->sc_xmax = xmax;
  reader->sc_ymin = ymin;
  reader->sc_ymax = ymax;
  reader->sc_bottom = bottom;
  reader->sc_left = left;

  hpgs_reader_set_default_transformation(reader);
  return 0;
}
Beispiel #4
0
/*
  Do the pen select.
*/
int hpgs_reader_do_setpen(hpgs_reader *reader, int pen)
{
  double width;

  if (hpgs_reader_checkpath(reader)) return -1;

  if (pen < 0)
    return hpgs_set_error(hpgs_i18n("Illegal pen numer %d."),pen);

  if (pen >= reader->npens)
    {
      if (pen < 256)
        {
          if (hpgs_reader_set_number_of_pens(reader,pen+1))
            return -1;
        }
      else
        {
          if (reader->verbosity)
            hpgs_log(hpgs_i18n("Illegal pen number %d replaced by %d.\n"),
                     pen, pen % reader->npens);
          pen = pen %  reader->npens;
        }
    }

  reader->current_pen = pen;

  width = reader->pen_widths[pen];

  if (reader->pen_width_relative)
    width *= hypot(reader->P2.x-reader->P1.x,
		   reader->P2.y-reader->P1.y ) * 0.001 * HP_TO_PT;
  else
    width *= HP_TO_PT / reader->world_scale;

  width *= reader->page_scale;

  if (hpgs_setlinewidth(reader->device,width*reader->lw_factor))
    return -1;

  return hpgs_setrgbcolor(reader->device,
			  &reader->pen_colors[pen]);
}
Beispiel #5
0
/*!
   Get the error message of the current thread.
*/
const char *hpgs_get_error()
{
  const char *ret;
#ifdef WIN32
  ret = (char *)TlsGetValue(tls_handle);
#else
  ret = (char *)pthread_getspecific (key);
#endif

  if (!ret) ret = hpgs_i18n("(no error)");
  return ret;
}
static int grow_clip_lines (hpgs_device *device,
                            hpgs_img_clip_line **clip_lines,
                            size_t *clip_lines_sz)
{
  size_t nsz = *clip_lines_sz*2;
  hpgs_img_clip_line *ncl=realloc(*clip_lines,nsz*sizeof(hpgs_img_clip_line));

  if (!ncl)
    return hpgs_set_error(hpgs_i18n("hpgs_image_rop3_clip: Out of memory growing temporary storage."));

  *clip_lines = ncl;
  *clip_lines_sz = nsz;
  return 0;
}
Beispiel #7
0
static int usage (void)
{
  fprintf (stderr,hpgs_i18n(
	   "\n"
	   " hpgs v%s - HPGl Script, a hpgl/2 interpreter/renderer.\n"
	   "\n"
	   " (C) 2004-2009 ev-i Informationstechnologie GmbH (http://www.ev-i.at)\n"
	   "     published under the LGPL (http://www.fsf.org/licenses/lgpl.html).\n"
	   "\n"
	   "Type `hpgs --help' for a detailed description of cmd line options.\n")
	   ,HPGS_VERSION  );

  hpgs_cleanup();

  return 0;
}
Beispiel #8
0
/*
  HPGL command LT (Line Type)
*/
int hpgs_reader_do_LT(hpgs_reader *reader)
{
  float dashes[20];
  int i,ndash;
  int linetype=0;
  double patlen = 4.0;
  int    mode = 0;

  if (hpgs_reader_checkpath(reader)) return -1;

  if (!reader->eoc &&
      hpgs_reader_read_int(reader,&linetype)) return -1;

  if (!reader->eoc &&
      hpgs_reader_read_double(reader,&patlen)) return -1;

  if (!reader->eoc &&
      hpgs_reader_read_int(reader,&mode)) return -1;

  if (linetype < -8 || linetype > 8)
    {
      if (reader->verbosity)
	hpgs_log(hpgs_i18n("LT: Illegal linetype %d.\n"),linetype);
      return 0;
    }

  // line type are store as percentages.
  patlen *= 0.01;

  if (mode)
    patlen *= MM_TO_PT;
  else
    patlen *= hypot(reader->P2.x-reader->P1.x,
		    reader->P2.y-reader->P1.y ) * 0.01 * HP_TO_PT;

  ndash = reader->linetype_nsegs[linetype+8];
  if (ndash > 20) ndash = 20;

  for (i=0;i<ndash;++i)
    dashes[i] = reader->linetype_segs[linetype+8][i] * patlen;
  
  return hpgs_setdash(reader->device,
		      dashes,ndash,0.0);
}
Beispiel #9
0
int main(int argc, const char *argv[])
{
  const char *dev_name="eps";
  int dev_name_len = 3;
  const char *out_fn=0;
  const char *stamp=0;
  const char *stamp_enc=0;
  const char *png_dump_fn=0;
  int ifile;
  char *aux_path;
  double x_dpi=72.0;
  double y_dpi=72.0;
  hpgs_bbox bbox= { 0.0, 0.0, 0.0, 0.0 };
  double paper_angle = 0.0;
  double paper_border = 0.0;
  double paper_width = 0.0;
  double paper_height = 0.0;
  double lw_factor=-1.0;
  double thin_alpha=0.25;
  double stamp_size=500.0;
  int x_px_size=0;
  int y_px_size=0;
  hpgs_bool multipage=HPGS_FALSE;
  hpgs_bool ignore_ps=HPGS_FALSE;
  hpgs_bool do_linewidth=HPGS_TRUE;
  hpgs_bool do_rop3=HPGS_TRUE;
  int verbosity=1;
  int compression=6;
  hpgs_bool antialias=HPGS_FALSE;
  int image_interpolation=0;
  hpgs_device *size_dev = 0;
  hpgs_device *plot_dev = 0;
  hpgs_istream *in = 0;
  hpgs_reader  *reader = 0;
  hpgs_png_image *image = 0;
  const char *plugin_argv[HPGS_MAX_PLUGIN_ARGS];
  int plugin_argc = 0;
  int ret = 1;

#ifdef LC_MESSAGES
  setlocale(LC_MESSAGES,"");
#endif
  setlocale(LC_CTYPE,"");

  aux_path = get_aux_path();

  if (!aux_path)
    {
      fprintf(stderr,hpgs_i18n("Error getting installation path: %s.\n"),
	      strerror(errno));
      return 1;
    }
  
  hpgs_init(aux_path);
  free(aux_path);

  memset(plugin_argv,0,sizeof(plugin_argv));

  ++argv;
  --argc;

  while (argc>0)
    {
      int narg = 1;
      const char *value;

      if (strcmp(argv[0],"--") == 0)
	{
	  ++argv;
	  --argc;
	  break;
	}
      else       if (strcmp(argv[0],"-v") == 0)
	{
	  ++verbosity;
	}
      else if (strcmp(argv[0],"-q") == 0 || strcmp(argv[0],"-dQUIET") == 0)
	{
	  --verbosity;
	}
      else if (strcmp(argv[0],"-i") == 0)
	{
	  ignore_ps=HPGS_TRUE;
	}
      else if (strcmp(argv[0],"-m") == 0)
	{
	  multipage=HPGS_TRUE;
	}
      else if (hpgs_get_arg_value("-d",argv,&value,&narg))
	{
	  dev_name = value;
          dev_name_len = strlen(dev_name);

          if (plugin_argc)
	    {
	      fprintf(stderr,hpgs_i18n("Error: Device options specified before -d argument.\n"));
	      return usage();
	    }
	}
      else if (hpgs_get_arg_value("--stamp=",argv,&value,&narg))
	{
	  stamp = value;
	}
      else if (hpgs_get_arg_value("--stamp-encoding=",argv,&value,&narg))
	{
	  stamp_enc = value;
	}
      else if (hpgs_get_arg_value("--stamp-size=",argv,&value,&narg))
	{
          if (hpgs_parse_length(value,&stamp_size))
	    {
	      fprintf(stderr,hpgs_i18n("Error: --stamp-size= must be followed by a valid length.\n"));
	      return usage();
	    }

	  if (stamp_size < 20.0 || stamp_size > 2000.0)
	    {
	      fprintf(stderr,hpgs_i18n("Error: stamp-size must lie in the interval [20,2000]pt.\n"));
	      return usage();
	    }
	}
      else if (hpgs_get_arg_value("--dump-png=",argv,&value,&narg))
	{
          png_dump_fn = value;
	}
       else if (hpgs_get_arg_value("-o",argv,&value,&narg))
	{
	  out_fn = value;
	}
      else if (strcmp(argv[0],"-a") == 0)
	{
          antialias = HPGS_TRUE;
	}
      else if (hpgs_get_arg_value("-I",argv,&value,&narg))
	{
	  if (get_int_arg(value,&image_interpolation))
	    {
	      if (narg == 1)
		{
		  fprintf(stderr,hpgs_i18n("Error: -I must be followed by an integer number.\n"));
		  return usage();
		}
	      else
		{
		  image_interpolation= 1;
		  narg = 1;
		}
	    }

	  if (image_interpolation < 0 || image_interpolation > 1)
	    {
	      fprintf(stderr,hpgs_i18n("Error: The argument to -I must be 0 or 1.\n"));
	      return usage();
	    }
	}
      else if (hpgs_get_arg_value("-c",argv,&value,&narg))
	{
	  if (get_int_arg(value,&compression))
	    {
	      fprintf(stderr,hpgs_i18n("Error: -c must be followed by an integer number.\n"));
	      return usage();
	    }
	  
	  if (compression < 1 || compression > 9)
	    {
	      fprintf(stderr,hpgs_i18n("Error: compression factor must lie in the interval [1,9].\n"));
	      return usage();
	    }
	}
      else if (hpgs_get_arg_value("-w",argv,&value,&narg))
	{
	  if (get_double_arg(value,&lw_factor))
	    {
	      fprintf(stderr,hpgs_i18n("Error: -w must be followed by a floating point number.\n"));
	      return usage();
	    }
	  
	  if (lw_factor < 0.0 || lw_factor > 10.0)
	    {
	      fprintf(stderr,hpgs_i18n("Error: Linewidth factor must lie in the interval [0.0,10.0].\n"));
	      return usage();
	    }
	}
      else if (hpgs_get_arg_value("--thin-alpha=",argv,&value,&narg))
	{
	  if (get_double_arg(value,&thin_alpha))
	    {
	      fprintf(stderr,hpgs_i18n("Error: --thin-alpha= must be followed by a floating point number.\n"));
	      return usage();
	    }
	  
	  if (thin_alpha < 0.01 || thin_alpha > 10.0)
	    {
	      fprintf(stderr,hpgs_i18n("Error: Thin alpha must lie in the interval [0.01,10.0].\n"));
	      return usage();
	    }
	}
      else if (hpgs_get_arg_value("-r",argv,&value,&narg))
	{
	  if (get_double_pair(value,&x_dpi,&y_dpi))
	    {
	      fprintf(stderr,hpgs_i18n("Error: -r must be followed by <res> or <xres>x<yres>.\n"));
	      return usage();
            }

          if (x_dpi < 5.0 || y_dpi < 5.0)
            {
              fprintf(stderr,hpgs_i18n("Error: Resolutions must be at least 5 dpi.\n"));
              return usage();
            }
	}
      else if (hpgs_get_arg_value("-p",argv,&value,&narg))
	{
	  if (get_int_pair(value,&x_px_size,&y_px_size))
	    {
	      fprintf(stderr,hpgs_i18n("Error: -p must be followed by <sz> or <xsz>x<ysz>.\n"));
	      return usage();
            }

          if (y_px_size < 20 ||  x_px_size < 20)
            {
              fprintf(stderr,hpgs_i18n("Error: Pixel sizes must be at least 20px.\n"));
              return usage();
            }
	}
      else if (hpgs_get_arg_value("-s",argv,&value,&narg))
	{
          double x_size,y_size;

          if (hpgs_parse_papersize(value,&x_size, &y_size)<0)
            {
	      fprintf(stderr,hpgs_i18n("Error: -s must be followed by a valid paper size.\n"));
	      return usage();
            }

          if (x_size < 72.0 || y_size < 72.0)
            {
              fprintf(stderr,hpgs_i18n("Error: The plot size must be at least 72 pt.\n"));
              return usage();
            }

          bbox.urx = bbox.llx + x_size;
          bbox.ury = bbox.lly + y_size;
	}
      else if (hpgs_get_arg_value("--origin=",argv,&value,&narg))
	{
          double xo,yo;

          if (hpgs_parse_papersize(value,&xo, &yo)<0)
            {
	      fprintf(stderr,hpgs_i18n("Error: --origin= must be followed by a valid pair of length specification.\n"));
	      return usage();
            }

          

          bbox.urx = (bbox.urx - bbox.llx) + xo;
          bbox.ury = (bbox.ury - bbox.lly) + yo;
          bbox.llx = xo;
          bbox.lly = yo;
	}
      else if (hpgs_get_arg_value("--paper=",argv,&value,&narg))
	{
          if (hpgs_parse_papersize(value,&paper_width,&paper_height)<0)
            {
	      fprintf(stderr,hpgs_i18n("Error: --paper= must be followed by a valid paper size.\n"));
	      return usage();
            }

          if (paper_width < 72.0 || paper_height < 72.0)
            {
              fprintf(stderr,hpgs_i18n("Error: The paper size must be at least 72 pt.\n"));
              return usage();
            }
	}
      else if (hpgs_get_arg_value("--border=",argv,&value,&narg) ||
               // Allow old device-specific border parameters.
               get_dev_arg_value(dev_name,dev_name_len,"-border=",argv,&value,&narg)     )
	{
          if (hpgs_parse_length(value,&paper_border)<0)
            {
	      fprintf(stderr,hpgs_i18n("Error: --border= must be followed by a valid length.\n"));
	      return usage();
            }

          if (paper_border < 0.0 || paper_border > 144.0)
            {
              fprintf(stderr,hpgs_i18n("Error: The page border must lie in the interval [0,144] pt.\n"));
              return usage();
            }
	}
      else if (hpgs_get_arg_value("--rotation=",argv,&value,&narg) ||
               // Allow old device-specific rotation parameters.
               get_dev_arg_value(dev_name,dev_name_len,"-rotation=",argv,&value,&narg)       )
	{
          if (hpgs_parse_length(value,&paper_angle)<0)
            {
	      fprintf(stderr,hpgs_i18n("Error: --angle= must be followed by a valid angle.\n"));
	      return usage();
            }
	}
      else if (strcmp(argv[0],"--linewidth-size") == 0)
	{
	  do_linewidth = HPGS_TRUE;
	}
      else if (strcmp(argv[0],"--no-linewidth-size") == 0)
  	{
	  do_linewidth = HPGS_FALSE;
	}
      else if (strcmp(argv[0],"--rop3") == 0)
	{
	  do_rop3 = HPGS_TRUE;
	}
      else if (strcmp(argv[0],"--no-rop3") == 0)
	{
	  do_rop3 = HPGS_FALSE;
	}
      else if (strcmp(argv[0],"--help") == 0)
	{
	  return help();
	}
      else if (strcmp(argv[0],"--version") == 0)
	{
	  usage();
	  return 0;
	}
      else if (strncmp(argv[0],"--",2) == 0 &&
               strncmp(argv[0]+2,dev_name,dev_name_len) == 0 &&
               argv[0][dev_name_len+2] == '-')
	{
          int l=strlen(argv[0]);

          if (plugin_argc >= HPGS_MAX_PLUGIN_ARGS-1)
	    {
	      fprintf(stderr,hpgs_i18n("Error: Number of plugin-args exceeds maximum of %d.\n"),
                      HPGS_MAX_PLUGIN_ARGS-1);
	      return usage();
	    }

          plugin_argv[plugin_argc] = argv[0]+dev_name_len+2;
          ++plugin_argc;

          if (argv[0][l-1] == '=')
            {
              if (plugin_argc >= HPGS_MAX_PLUGIN_ARGS-1)
                {
                  fprintf(stderr,hpgs_i18n("Error: Number of plugin-args exceed maximum of %d.\n"),
                          HPGS_MAX_PLUGIN_ARGS-1);
                  usage();
                }

              plugin_argv[plugin_argc] = argv[2];
              ++plugin_argc;

              narg=2;
            }
	}
      else
	{
	  if (argv[0][0] == '-')
	    {
	      fprintf(stderr,hpgs_i18n("Error: Unknown option %s given.\n"),argv[0]);
	      return usage();
	    }

          break;
	}

      argv+=narg;
      argc-=narg;
    }
  
  if (argc < 1)
    {
      fprintf(stderr,hpgs_i18n("Error: No input file given.\n"));
      return usage();
    }

  if (argc > 1 && !multipage)
    {
      multipage = HPGS_TRUE;
    }

  // adjust default linewidth factor.
  if (lw_factor < 0.0)
    {
      // This is the best choice for our basic, non-antialiased renderer,
      // which rounds up pixel line widths.
      if (antialias == 0 && strncmp(dev_name,"png_",4) == 0)
        lw_factor = 0.5;
      else
        lw_factor = 1.0;
    }

  size_dev = (hpgs_device*)hpgs_new_plotsize_device(ignore_ps,do_linewidth);

  if (!size_dev)
    {
      fprintf(stderr,hpgs_i18n("Error: Cannot create plotsize device.\n"));
      goto cleanup;
    }

  in = hpgs_new_file_istream(argv[0]);

  if (!in)
    {
      fprintf(stderr,hpgs_i18n("Error: Cannot open input file %s: %s\n"),
	      argv[0],strerror(errno));
      hpgs_device_destroy((hpgs_device*)size_dev);
      goto cleanup;
    }

  reader = hpgs_new_reader(in,size_dev,
			   multipage,verbosity);

  if (!reader)
    {
      fprintf(stderr,hpgs_i18n("Error: Cannot create hpgl reader: %s\n"),strerror(errno));
      goto cleanup;
    }
 
  hpgs_reader_set_lw_factor(reader,lw_factor);

  // determine plot size, if not specified on the cmd line
  if (bbox.urx-bbox.llx < 72.0 || bbox.ury-bbox.lly < 72.0)
    {
      // read in multiple pages.
      for (ifile = 1; ifile < argc; ++ifile)
        {
          if (hpgs_read(reader,HPGS_FALSE))
            {
              fprintf(stderr,hpgs_i18n("Error: Cannot determine plot size of file %s: %s\n"),
                      argv[ifile-1],hpgs_get_error());
              goto cleanup;
            }

          in = hpgs_new_file_istream(argv[ifile]);

          if (!in)
            {
              fprintf(stderr,hpgs_i18n("Error: Cannot open input file %s: %s\n"),
                      argv[ifile],strerror(errno));
              goto cleanup;
            }

          hpgs_reader_attach(reader,in);
        }
      
      if (hpgs_read(reader,HPGS_TRUE))
	{
	  fprintf(stderr,hpgs_i18n("Error: Cannot determine plot size of file %s: %s\n"),
		  argv[ifile-1],hpgs_get_error());
	  goto cleanup;
	}

      // get bounding box of first page.
      // (will return overall boundingbox, if in singlepage mode.)
      if (hpgs_getplotsize(size_dev,1,&bbox)<0)
	{
	  fprintf(stderr,hpgs_i18n("Error: Cannot determine plotsize: %s\n"),
		  hpgs_get_error());
	  goto cleanup;
	}

      if (hpgs_bbox_isempty(&bbox))
	{
	  fprintf(stderr,hpgs_i18n("Error: Empty bounding:  %g %g %g %g.\n"),
		  bbox.llx,bbox.lly,bbox.urx,bbox.ury);
	  goto cleanup;
	}

      if (verbosity >= 1)
	fprintf(stderr,"BoundingBox: %g %g %g %g.\n",bbox.llx,bbox.lly,bbox.urx,bbox.ury);
    }

  // set the appropriate page placement.
  if (paper_width > 0.0 && paper_height > 0.0)
    {
      hpgs_reader_set_fixed_page(reader,&bbox,
                                 paper_width,paper_height,
                                 paper_border,paper_angle );
    }
  else
    {
      paper_width = 200.0 * 72.0;
      paper_height = 200.0 * 72.0;

      hpgs_reader_set_dynamic_page(reader,&bbox,
                                   paper_width,paper_height,
                                   paper_border,paper_angle );
    }

  if (strcmp(dev_name,"bbox") == 0)
    {
      int i;
      FILE *out = out_fn ? fopen(out_fn,"wb") : stdout;

      if (!out)
	{
	  fprintf(stderr,hpgs_i18n("Error: Cannot open output file <%s>.\n"),out_fn);
	  goto cleanup;
	}

      for (i=0;i<10000;++i)
        {
          int r = hpgs_getplotsize(size_dev,i,&bbox);

          if (r < 0)
            {
              fprintf(stderr,hpgs_i18n("Error: Cannot determine plotsize: %s\n"),
                      hpgs_get_error());
              fclose(out);
              goto cleanup;
            }

          if (r) break;

          if (i>0)
            {
              fprintf(out,"%%%%Page: %d %d.\n",i,i);
              fprintf(out,"%%%%PageBoundingBox: %d %d %d %d.\n",
                      (int)floor(bbox.llx),(int)floor(bbox.lly),
                      (int)ceil(bbox.urx),(int)ceil(bbox.ury));
              fprintf(out,"%%%%PageHiResBoundingBox: %g %g %g %g.\n",bbox.llx,bbox.lly,bbox.urx,bbox.ury);
            }
          else
            {
              fprintf(out,"%%%%BoundingBox: %d %d %d %d.\n",
                      (int)floor(bbox.llx),(int)floor(bbox.lly),
                      (int)ceil(bbox.urx),(int)ceil(bbox.ury));
              fprintf(out,"%%%%HiResBoundingBox: %g %g %g %g.\n",bbox.llx,bbox.lly,bbox.urx,bbox.ury);
            }
        }

      if (out != stdout) fclose(out);

      ret=0;
      goto cleanup;
    }
  else if (strcmp(dev_name,"eps") == 0)
    {
      plot_dev =
	(hpgs_device*)hpgs_new_eps_device(out_fn,&bbox,do_rop3);

      if (!plot_dev)
	{
	  fprintf(stderr,hpgs_i18n("Error: Cannot create eps device.\n"));
	  goto cleanup;
	}
    }
  else if (strcmp(dev_name,"ps") == 0)
    {
      plot_dev =
	(hpgs_device*)hpgs_new_ps_device(out_fn,&bbox,do_rop3);

      if (!plot_dev)
	{
	  fprintf(stderr,hpgs_i18n("Error: Cannot create postscript device.\n"));
	  goto cleanup;
	}
    }
  else if (strncmp(dev_name,"png_",4) == 0)
    {
      int depth = 8;
      int palette = 0;
      hpgs_paint_device *pdv;

      if (strcmp(dev_name+4,"gray") == 0)
	depth = 8;
      else if (strcmp(dev_name+4,"gray_alpha") == 0)
	depth = 16;
      else if (strcmp(dev_name+4,"rgb") == 0)
	depth = 24;
      else if (strcmp(dev_name+4,"rgb_alpha") == 0)
	depth = 32;
      else if (strcmp(dev_name+4,"256") == 0)
	palette = 1;
      else
	{
	  fprintf(stderr,hpgs_i18n("Error: png device %s in not supported.\n"),
		  dev_name);
	  goto cleanup;
	}

      if (x_px_size >= 20 && y_px_size >= 20)
	{
          // get overall bounding box, if pixel size is specified.
          // This way no page image exceeds the given size and
          // all images have the same resolution.
          hpgs_bbox bb;

          if (hpgs_getplotsize(size_dev,0,&bb)<0)
            {
              fprintf(stderr,hpgs_i18n("Error: Cannot determine overall plotsize: %s\n"),
                      hpgs_get_error());
              goto cleanup;
            }

	  x_dpi = 72.0 * x_px_size / (bb.urx-bb.llx);
	  y_dpi = 72.0 * y_px_size / (bb.ury-bb.lly);

	  if (x_dpi > y_dpi)
	    {
	      x_dpi = y_dpi;
	      x_px_size = x_dpi * (bb.urx-bb.llx) / 72.0;
	    }
	  else
	    {
	      y_dpi = x_dpi;
	      y_px_size = y_dpi * (bb.ury-bb.lly) / 72.0;
	    }
	}
      else
	{
          // initialize the pixel size from the first page.
	  x_px_size = x_dpi * (bbox.urx-bbox.llx) / 72.0;
	  y_px_size = y_dpi * (bbox.ury-bbox.lly) / 72.0;
	}

      image = hpgs_new_png_image(x_px_size,y_px_size,depth,palette,do_rop3);
	
      if (!image)
	{
	  fprintf(stderr,hpgs_i18n("Error creating %dx%dx%d sized png image: %s.\n"),
		  x_px_size,y_px_size,depth,strerror(errno));
	  goto cleanup;
	}

      hpgs_png_image_set_compression(image,compression);

      pdv = hpgs_new_paint_device((hpgs_image*)image,
                                  out_fn,&bbox,
                                  antialias);
      if (!pdv)
	{
	  fprintf(stderr,hpgs_i18n("Error: Cannot create paint device.\n"));
	  goto cleanup;
	}

      hpgs_paint_device_set_image_interpolation(pdv,image_interpolation);
      hpgs_paint_device_set_thin_alpha(pdv,thin_alpha);
      // set the resolution of the image, although
      // hpgs_new_paint_device has done this before.
      // The reason is, that we know the resolution with more precision
      // than hpgs_new_paint_device.
      hpgs_image_set_resolution((hpgs_image*)image,x_dpi,y_dpi);

      plot_dev = (hpgs_device *)pdv;
    }
  else
    {
      if (x_px_size >= 20 && y_px_size >= 20)
	{
          // calculate resolution from overall bounding box,
          // if pixel size is specified.
          // This way no page image exceeds the given size and
          // all images have the same resolution.
          hpgs_bbox bb;

          if (hpgs_getplotsize(size_dev,0,&bb)<0)
            {
              fprintf(stderr,hpgs_i18n("Error: Cannot determine overall plotsize: %s\n"),
                      hpgs_get_error());
              goto cleanup;
            }

	  x_dpi = 72.0 * x_px_size / (bb.urx-bb.llx);
	  y_dpi = 72.0 * y_px_size / (bb.ury-bb.lly);

	  if (x_dpi > y_dpi)
	    x_dpi = y_dpi;
	  else
	    y_dpi = x_dpi;
	}

      void *page_asset_ctxt = 0;
      hpgs_reader_asset_func_t page_asset_func = 0;
      void *frame_asset_ctxt = 0;
      hpgs_reader_asset_func_t frame_asset_func = 0;

      if (hpgs_new_plugin_device(&plot_dev,
                                 &page_asset_ctxt,
                                 &page_asset_func,
                                 &frame_asset_ctxt,
                                 &frame_asset_func,
                                 dev_name,out_fn,&bbox,
                                 x_dpi,y_dpi,do_rop3,
                                 plugin_argc,plugin_argv))
	{
	  fprintf(stderr,hpgs_i18n("Error: Cannot create plugin device: %s\n"),
                  hpgs_get_error());
	  goto cleanup;
	}

      if (page_asset_func)
        hpgs_reader_set_page_asset_func(reader,page_asset_ctxt,page_asset_func);

      if (frame_asset_func)
        hpgs_reader_set_frame_asset_func(reader,frame_asset_ctxt,frame_asset_func);
    }

  if (!plot_dev)
    {
      fprintf (stderr,hpgs_i18n("Error: invalid plot device name %s specified.\n"),dev_name);
      goto cleanup;
    }

  if (png_dump_fn && hpgs_reader_set_png_dump(reader,png_dump_fn))
    {
      fprintf(stderr,hpgs_i18n("Error: Cannot set png_dump filename to reader: %s\n"),
	      hpgs_get_error());
      goto cleanup;
    }

  if (stamp && hpgs_device_stamp(plot_dev,&bbox,stamp,stamp_enc,stamp_size))
    {
      fprintf(stderr,hpgs_i18n("Error: Cannot stamp plot: %s\n"),
	      hpgs_get_error());
      goto cleanup;
    }

  if (hpgs_reader_imbue(reader,plot_dev))
    {
      fprintf(stderr,hpgs_i18n("Error: Cannot imbue plot device to reader: %s\n"),
	      hpgs_get_error());
      goto cleanup;
    }

  // re-open first file, if we have more than one input file.
  if (argc > 1)
    {
      in = hpgs_new_file_istream(argv[0]);

      if (!in)
        {
          fprintf(stderr,hpgs_i18n("Error: Cannot open input file %s: %s\n"),
                  argv[0],strerror(errno));
          goto cleanup;
        }
      hpgs_reader_attach(reader,in);
    }

  // read in multiple pages.
  for (ifile = 1; ifile < argc; ++ifile)
    {
      if (hpgs_read(reader,HPGS_FALSE))
        {
          fprintf(stderr,hpgs_i18n("Error: Cannot process plot file %s: %s\n"),
                  argv[ifile-1],hpgs_get_error());
          goto cleanup;
        }
      
      in = hpgs_new_file_istream(argv[ifile]);

      if (!in)
        {
          fprintf(stderr,hpgs_i18n("Error: Cannot open input file %s: %s\n"),
                  argv[ifile],strerror(errno));
          goto cleanup;
        }
      
      hpgs_reader_attach(reader,in);
    }

  if (hpgs_read(reader,HPGS_TRUE))
    {
      fprintf(stderr,hpgs_i18n("Error: Cannot process plot file %s: %s\n"),
	      argv[ifile-1],hpgs_get_error());
      goto cleanup;
    }

  if (verbosity >= 2)
    fprintf(stderr,hpgs_i18n("Success.\n"));

  ret = 0;

 cleanup:
  if (reader)
    hpgs_destroy_reader(reader);

  hpgs_cleanup();

  return ret;
}
Beispiel #10
0
static int help (void)
{
  fprintf (stderr,hpgs_i18n(
	   "\n"
	   " hpgs v%s - HPGl Script, a hpgl/2 interpreter/renderer.\n"
	   "\n"
	   " (C) 2004-2009 ev-i Informationstechnologie GmbH (http://www.ev-i.at)\n"
	   "     published under the LGPL (http://www.fsf.org/licenses/lgpl.html).\n"
	   "\n"
	   "usage: hpgs [-i] [-v] [-q] [-d <dev>] [options...] [-o <out>] <in1> <in2>...\n"
	   "       -i ... Ignore plotsize from PS and determine\n"
	   "              the plotsize from the file content.\n"
	   "       --linewidth-size ... Account for linewidths in the plotsize\n"
	   "              calculation for -i (default behaviour).\n"
	   "       --no-linewidth-size ... Ignore linewidths in the plotsize\n"
	   "              calculation for -i.\n"
	   "       -v ... Increase verbosity.\n"
	   "       -q ... Decrease verbosity, be quiet.\n"
	   "       -o <out> ... specifiy the output filename. If not specified, write\n"
	   "                    to stdout.\n"
	   "       -m ... Switch to multipage mode, if a single file is given on the.\n"
	   "              command line. If not specified, only the first page of the input\n"
           "              file is processed.\n"
	   "       -w ... Correct linewidth by given factor (default: 1).\n"
	   "       -d ... Specifiy the output device. The default is the\n"
	   "              native 'eps' device, which writes a simple eps file.\n"
	   "              See section `Supported devices' below.\n"
	   "       -a ... Use antialiasing when rendering to a png image.\n"
	   "       --thin-alpha=<a>\n"
           "              Specifiy the minimal alpha value for thin lines.\n"
	   "              allowed values lie in the interval [0.001,1.0] (default: 0.25).\n"
	   "       -I ... Specifiy image interpolation.\n"
	   "       --rop3 ... Use ROP3 raster operations for rendering on devices\n"
	   "              with ROP3 capabilities (default).\n"
	   "       --no-rop3 ... Suppress usage of ROP3 raster operations.\n"
	   "       -c ... Specifiy the compression level for png writing.\n"
	   "       -r ... Specifiy the device resolution in dpi.\n"
	   "              If no y-resolution is given, the y-resolution\n"
	   "              is set to the same value as the x-resolution.\n"
	   "       -p ... Specifiy the maximum pixel size of the device.\n"
	   "              This is in fact an alternate method to specify the\n"
	   "              resolution of the device. If -p is given, the device\n"
	   "              resolution is caclulated in a way, that the plot fits\n"
	   "              into the given rectangle.\n"
	   "              If no y-size is given, the size y-size\n"
	   "              is set to the same value as the x-size.\n"
	   "       -s<papersize> ... Specifiy the plot size in pt (1/72 inch).\n"
	   "              If -s is not given, the size is calculated from\n"
	   "              the contents of the hpgl file.\n"
           "              The <papersize> may be either one of the standard\n"
           "              paper sizes A0,A1,A2,A3 or A4, their landscape versions\n"
           "              A0l,A1l,A2l,A3l or A4l or a size in the format <width>x<height>\n"
           "              where <width> and <height> specify a physical length in one of the\n"
           "              formats <l>,<l>mm,<l>cm,<l>inch or <l>pt. <l> is a floating point\n"
           "              number, the default unit is PostScript pt (1/72 inch).\n"
	   "       --origin=<origin> ... Specifiy the origin of the displayed content.\n"
	   "              If -s is not given, the origin is calculated from\n"
	   "              the contents of the hpgl file.\n"
           "              The <origin> may be in the format <width>x<height>\n"
           "              as described above for the option -s.\n"
	   "       --paper=<papersize>\n"
           "              Specify a paper size of the output device. All plots\n"
           "              are scaled to this paper size respecting the given border.\n"
           "              If no fixed paper size is given, each page in the output\n"
           "              file has an individual size adapted to the size of the HPGL\n"
           "              content of the page.\n"
           "              The format of <papersize> is decribed above for -s.\n"
	   "       --border=<border>\n"
           "              Specify a border for placing plots on output pages.\n"
	   "       --rotation=<angle>\n"
           "              Specify an angle for placing plots on output pages.\n"
	   "       --stamp=<stamp>\n"
           "              Specify a string, which is printed in the background.\n"
	   "       --stamp-encoding=<enc>\n"
           "              Specify an the name of the encoding of the string, which\n"
	   "              is given in --stamp. Default is iso-8859-1.\n"
	   "       --stamp-size=<pt>\n"
           "              Specify the size of the stamp specified with --stamp\n"
	   "              in point. Default value: 500pt.\n"
	   "       --dump-png=<filename>\n"
           "              Specify a filename for dumping inline PCL images in.\n"
           "              PNG format. The actual filenames written are:\n"
           "                 <filename>0001.png\n"
           "                 <filename>0002.png\n"
           "                  .....\n"
           "              If <filename> contains an extension '.png' the counter\n"
           "              is put between the basename and the '.png' extension.\n"
	   "       --help\n"
           "              Displays this usage information.\n"
	   "       --version\n"
           "              Displays the version information.\n"
	   "\n"
	   "Supported devices (option -d):\n"
	   "\n"
	   "       bbox    ... writes a PostScript BoundingBox to stdout.\n"
	   "       ps      ... writes a multipage PostScript file.\n"
	   "       eps     ... writes an eps files.\n"
	   "       png_256 ... writes an indexed 8bpp png image.\n"
	   "       png_gray... writes a grayscale 8bpp png image.\n"
	   "       png_rgb ... writes a rgb 24bpp png image.\n"
	   "       png_gray_alpha ... writes a grayscale 16bpp png image\n"
	   "                          with an alpha channel.\n"
	   "       png_rgb_alpha ... writes a rgb 32bpp png image\n"
	   "                         with an alpha channel.\n"
	   "       cairo_png ... writes a rgb 32bpp png image using\n"
	   "                     the cairo library (experimental).\n")
	   ,HPGS_VERSION );

  hpgs_cleanup();

  return 0;
}
/*! 
   Sets a clip frame to the given device, which encloses all regions
   of the device, which are cover by the image taking into account
   the given ROP3 transfer function.

   The argument \c data must contain a pointer to a two-dimensional
   array of raw pixels of the size of the image. This array is filled
   with pixel values as if the image has been painted to a white
   destination area using the given ROP3 function.

   Return values:
     \li 0 The clip frame is empty, no operation has been performed on
           the output device.

     \li 1 The clip frame is not empty, the clip path has been
           set to the output device using clipsave/moveto/lineto/clip
           operations.

     \li 2 The clip frame covers the whole image, no operation has been
           performed on the output device.

     \li 3 The clip frame is not empty, the visible pixels have all the same color
           and clip path has been set to the output device using
           moveto/lineto/setrgbcolor/fill operations. The image does not have to be
           transferred by subsequent functions, the rgb color of the device has been
           altered.

     \li -1 An error occured on the output device.

*/
int hpgs_image_rop3_clip(hpgs_device *device,
                         hpgs_palette_color *data,
                         const hpgs_image *img,
                         const hpgs_point *ll, const hpgs_point *lr,
                         const hpgs_point *ur,
                         const hpgs_palette_color *p,
                         hpgs_xrop3_func_t xrop3)
{
  // The upper bound for clip_lines_sz is (w+1)*(h+1)*2.
  // This formula is chosen so, that for w==1 and h==1,
  // this result is achieved. For larger pictures, we
  // use 1/8th of the upper bound, which is pretty conservative.
  // If not doing so, the algorithm easily consumes up to 1GB or more,
  // which is too much for alloca, too. So this estimation combined
  // with the usage of malloc should make the code robust.
  size_t clip_lines_sz = ((img->width+1)*(img->height+1)+31)/4;

  hpgs_img_clip_line *clip_lines = (hpgs_img_clip_line *)
    malloc(sizeof(hpgs_img_clip_line)*clip_lines_sz);

  hpgs_img_clip_seg *segs0 = (hpgs_img_clip_seg *)
    hpgs_alloca(sizeof(hpgs_img_clip_seg)*(img->width+1));

  hpgs_img_clip_seg *segs1 = (hpgs_img_clip_seg *)
    hpgs_alloca(sizeof(hpgs_img_clip_seg)*(img->width+1));

  if (!clip_lines || !segs0 || !segs1)
    return hpgs_set_error(hpgs_i18n("hpgs_image_rop3_clip: Out of memory allocating temporary storage."));

  int n_clip_lines = 0;
  int ret = -1;
  int i_seg0,n_segs0 = 0;
  int i_seg1,n_segs1 = 0;

  hpgs_point ul;
  int i,j;

  hpgs_bool all_visible = HPGS_TRUE;
  hpgs_palette_color *first_visible_pixel = 0;
  hpgs_bool single_color = HPGS_FALSE;

  ul.x = ll->x + (ur->x - lr->x);
  ul.y = ll->y + (ur->y - lr->y);

  // first, accumulate lines.
  for (i=0;i<img->height+1;++i)
    {
      // cut the current raster line
      int t_last = 1;
      n_segs1 = 0;

      // this is here in order to construct all lines
      // for the very last grid line
      if (i<img->height)
        {
          for (j=0;j<img->width;++j)
            {
              int t;
              hpgs_paint_color s;
              unsigned r,g,b;
              
              hpgs_image_get_pixel(img,j,i,&s,0);

              r = xrop3(s.r,p->r);
              g = xrop3(s.g,p->g);
              b = xrop3(s.b,p->b);

              // transparent ?
              t = (r == 0x00ff && g == 0x00ff && b == 0x00ff);

              if (t != t_last) // last pixel different transparency ?
                {
                  segs1[n_segs1].j = j;
                  segs1[n_segs1].i_vert = -1;
                  ++n_segs1;
                }

              t_last = t;

              data->r = (unsigned char)r;
              data->g = (unsigned char)g;
              data->b = (unsigned char)b;

              if (!t)
                {
                  if (!first_visible_pixel)
                    {
                      first_visible_pixel = data;
                      single_color = HPGS_TRUE;
                    }
                  else if (single_color &&
                           (first_visible_pixel->r != data->r ||
                            first_visible_pixel->g != data->g ||
                            first_visible_pixel->b != data->b   ))
                    single_color = HPGS_FALSE;
                }

              ++data;
            }

          if (n_segs1 != 1 || segs1[0].j > 0)
            all_visible = HPGS_FALSE;

          // close trailing visible segment.
          if (t_last == 0)
            {
              segs1[n_segs1].j = j;
              segs1[n_segs1].i_vert = -1;
              ++n_segs1;
            }
        }

      assert(n_segs1 <= (img->width+1));

#ifdef HPGS_IMAGE_ROP_DEBUG
      hpgs_log("i=%d: segs1:",i);

      for (j=0;j<n_segs1;++j)
        hpgs_log("%c%d",j?',':' ',segs1[j].j);
      hpgs_log("\n");

      j=n_clip_lines;
#endif

      // construct lines.
      i_seg0 = 0;
      i_seg1 = 0;
      t_last = -1;

      while (i_seg0 < n_segs0 || i_seg1 < n_segs1)
        {
          if (i_seg1 >= n_segs1 || (i_seg0 < n_segs0 && segs0[i_seg0].j < segs1[i_seg1].j))
            {
              // horizontal line.
              if (t_last >= 0)
                {
                  clip_lines[n_clip_lines].i0 = i; 
                  clip_lines[n_clip_lines].i1 = i; 
                  // check for the orientation.
                  if (i_seg0 & 1)
                    {
                      clip_lines[n_clip_lines].j0 = t_last; 
                      clip_lines[n_clip_lines].j1 = segs0[i_seg0].j;
                    }
                  else
                    {
                      clip_lines[n_clip_lines].j0 = segs0[i_seg0].j;
                      clip_lines[n_clip_lines].j1 = t_last; 
                    }

                  if (++n_clip_lines >= clip_lines_sz &&
                      grow_clip_lines(device,&clip_lines,&clip_lines_sz))
                    goto cleanup;

                  t_last = -1;
                }
              else
                t_last = segs0[i_seg0].j;


              ++i_seg0;
            }
          else if (i_seg0 >= n_segs0 ||  segs1[i_seg1].j < segs0[i_seg0].j)
            {
              // horizontal line.
              if (t_last >= 0)
                {
                  clip_lines[n_clip_lines].i0 = i; 
                  clip_lines[n_clip_lines].i1 = i; 
                  // check for the orientation.
                  if (i_seg1 & 1)
                    {
                      clip_lines[n_clip_lines].j0 = segs1[i_seg1].j; 
                      clip_lines[n_clip_lines].j1 = t_last;
                    }
                  else
                    {
                      clip_lines[n_clip_lines].j0 = t_last; 
                      clip_lines[n_clip_lines].j1 = segs1[i_seg1].j;
                    }
                  if (++n_clip_lines >= clip_lines_sz &&
                      grow_clip_lines(device,&clip_lines,&clip_lines_sz))
                    goto cleanup;
                  t_last = -1;
                }
              else
                t_last = segs1[i_seg1].j;

              // create vertical line.
              clip_lines[n_clip_lines].j0 = segs1[i_seg1].j; 
              clip_lines[n_clip_lines].j1 = segs1[i_seg1].j; 

              // check for the orientation.
              if (i_seg1 & 1)
                {
                  clip_lines[n_clip_lines].i0 = i+1;
                  clip_lines[n_clip_lines].i1 = i;
                }
              else
                {
                  clip_lines[n_clip_lines].i0 = i;
                  clip_lines[n_clip_lines].i1 = i+1;
                }

              segs1[i_seg1].i_vert = n_clip_lines;
              if (++n_clip_lines >= clip_lines_sz &&
                  grow_clip_lines(device,&clip_lines,&clip_lines_sz))
                goto cleanup;

              ++i_seg1;
            }
          else
            {
              assert(segs0[i_seg0].j == segs1[i_seg1].j);
              
              // horizontal line.
              if (t_last >= 0)
                {
                  clip_lines[n_clip_lines].i0 = i; 
                  clip_lines[n_clip_lines].i1 = i; 
                  // check for the orientation.
                  if (i_seg1 & 1)
                    {
                      clip_lines[n_clip_lines].j0 = segs1[i_seg1].j; 
                      clip_lines[n_clip_lines].j1 = t_last;
                    }
                  else
                    {
                      clip_lines[n_clip_lines].j0 = t_last; 
                      clip_lines[n_clip_lines].j1 = segs1[i_seg1].j;
                    }

                  if (++n_clip_lines >= clip_lines_sz &&
                      grow_clip_lines(device,&clip_lines,&clip_lines_sz))
                    goto cleanup;
                }

              if ((i_seg0 & 1) == (i_seg1 & 1))
                {
                  // extend segment
                  int il = segs0[i_seg0].i_vert;
                  if (i_seg1 & 1)
                    clip_lines[il].i0 = i+1;
                  else
                    clip_lines[il].i1= i+1;
                  
                  segs1[i_seg1].i_vert = il;
                  t_last = -1;
                }
              else
                {
                  // create new segment.
                  clip_lines[n_clip_lines].j0 = segs1[i_seg1].j;
                  clip_lines[n_clip_lines].j1 = segs1[i_seg1].j;

                  if (i_seg1 & 1)
                    {
                      clip_lines[n_clip_lines].i0 = i+1;
                      clip_lines[n_clip_lines].i1 = i;
                    }
                  else
                    {
                      clip_lines[n_clip_lines].i0 = i;
                      clip_lines[n_clip_lines].i1 = i+1;
                    }

                  segs1[i_seg1].i_vert = n_clip_lines;

                  if (++n_clip_lines >= clip_lines_sz &&
                      grow_clip_lines(device,&clip_lines,&clip_lines_sz))
                    goto cleanup;

                  t_last = segs1[i_seg1].j;
                }

              ++i_seg0;
              ++i_seg1;
            }
        }

#ifdef HPGS_IMAGE_ROP_DEBUG
      hpgs_log("i=%d: lines: ",i);

      for (;j<n_clip_lines;++j)
        hpgs_log("(%d,%d,%d,%d)",
                clip_lines[j].i0,clip_lines[j].j0,
                clip_lines[j].i1,clip_lines[j].j1);
      hpgs_log("\n");
#endif
      assert (t_last == -1);

      // swap clip segment caches
      {
        hpgs_img_clip_seg *tmp = segs0;
        segs0=segs1;
        segs1=tmp;
      }
      n_segs0 = n_segs1;
    }

#ifdef HPGS_IMAGE_ROP_DEBUG
  hpgs_log("clip_img: n_clip_lines,all_visible = %d,%d.\n",
           n_clip_lines,all_visible);
#endif

  if (n_clip_lines <= 0) { ret = 0; goto cleanup; }
  if (all_visible && !single_color)  { ret = 2; goto cleanup; }

  assert(n_clip_lines <= (img->width+1)*(img->height+1)*2);

  // OK, now create the lookup key of the lines.
  for (i=0;i<n_clip_lines;++i)
    {
      clip_lines[i].key = MK_LINE_KEY(clip_lines[i].i0,clip_lines[i].j0);
      clip_lines[i].usage = 0;
    }

  // sort the table
  qsort(clip_lines,n_clip_lines,sizeof(hpgs_img_clip_line),compare_clip_lines);

  if (!single_color && hpgs_clipsave(device)) goto cleanup;

  // now construct the clip path.
  for (i = 0;i<n_clip_lines;++i)
    {
      hpgs_img_clip_line *line = clip_lines+i;
      int iline = 0;

      if (line->usage) continue;

      do
        {
          hpgs_point p;
          int key,i0,i1;

          p.x = ul.x +
            line->j0 * (lr->x - ll->x) / img->width +
            line->i0 * (lr->x - ur->x) / img->height ;
          
          p.y = ul.y +
            line->j0 * (lr->y - ll->y) / img->width +
            line->i0 * (lr->y - ur->y) / img->height ;
          
          key = MK_LINE_KEY(line->i1,line->j1);

          if (iline)
            {
              if (hpgs_lineto(device,&p))  goto cleanup;
            }
          else
            {
              if (hpgs_moveto(device,&p))  goto cleanup;
            }

#ifdef HPGS_IMAGE_ROP_DEBUG
          hpgs_log("(%d,%d,%d,%d)",
                  line->i0,line->j0,
                  line->i1,line->j1);
#endif
          ++iline;
          line->usage=1;

          // binary search
          i0 = 0;
          i1 = n_clip_lines;

          while (i1>i0)
            {
              int ii = i0+(i1-i0)/2;
              
              if (clip_lines[ii].key < key)
                i0 = ii+1;
              else
                i1 = ii;
            }

          while (clip_lines[i0].usage &&
                 i0 < n_clip_lines-1 &&
                 clip_lines[i0+1].key == key)
            ++i0;

          assert(i0 < n_clip_lines && key == clip_lines[i0].key);

          line = clip_lines+i0;

          assert (line);

          if (line->usage && line < clip_lines + n_clip_lines &&
              line[1].key == key)
            ++line;
        }
      while (!line->usage);

      assert (line->i0 == clip_lines[i].i0 &&
              line->j0 == clip_lines[i].j0   );

#ifdef HPGS_IMAGE_ROP_DEBUG
      hpgs_log("\n");
#endif
      if (hpgs_closepath(device)) goto cleanup;
    }

  if (single_color)
    {
      hpgs_color c;

      c.r = first_visible_pixel->r / 255.0;
      c.g = first_visible_pixel->g / 255.0;
      c.b = first_visible_pixel->b / 255.0;

      if (hpgs_setrgbcolor(device,&c)) goto cleanup;
      if (hpgs_fill(device,HPGS_FALSE)) goto cleanup;
      if (hpgs_newpath(device)) goto cleanup;

      ret = 3;
    }

  else
    {
      if (hpgs_clip(device,HPGS_FALSE)) goto cleanup;
      if (hpgs_newpath(device)) goto cleanup;

      ret = 1;
    }

 cleanup:
  if (clip_lines) free(clip_lines);
  return ret;
}
Beispiel #12
0
/* 
  HPGL command PW (Pen Width)
*/
int hpgs_reader_do_PW (hpgs_reader *reader)
{
  int pen=-1;
  double width=1.0;

  if (!reader->eoc)
    if (hpgs_reader_read_double(reader,&width)) return -1;
  if (!reader->eoc)
    {
      if (hpgs_reader_read_int(reader,&pen)) return -1;

      if (pen < 0 || pen >= reader->npens)
        {
          if (pen >= reader->npens && pen < 256)
            {
              if (hpgs_reader_set_number_of_pens(reader,pen+1))
                return -1;
            }
          else
            {
              if (reader->verbosity)
                hpgs_log(hpgs_i18n("PW: Illegal pen number %d.\n"),pen);
              
              return 0;
            }
        }
    }

  if (reader->verbosity >= 2)
    hpgs_log("PW: pen,width,rel = %d,%g,%d.\n",pen,width,reader->pen_width_relative);

  if (reader->pen_width_relative)
    width *= 10.0;
  else
    width *= MM_TO_PT;

  if (pen < 0)
    {
      int i;
      for (i=0;i<reader->npens;++i)
	reader->pen_widths[i] = width;
    }
  else
    reader->pen_widths[pen] = width;

  if (pen < 0 || pen == reader->current_pen)
    {
      if (hpgs_reader_checkpath(reader)) return -1;

      if (reader->pen_width_relative)
        width *= hypot(reader->P2.x-reader->P1.x,
                       reader->P2.y-reader->P1.y ) * 0.001 * HP_TO_PT;
      else
        width *= HP_TO_PT / reader->world_scale;

      width *= reader->page_scale;

      if (hpgs_setlinewidth(reader->device,width*reader->lw_factor))
	return -1;
    }

  return 0;
}
Beispiel #13
0
/* 
  HPGL command PC (Pen Color)
*/
int hpgs_reader_do_PC (hpgs_reader *reader)
{
  int pen=-1;
  double r=-1.0e20,g=-1.0e20,b=-1.0e20;

  if (!reader->eoc && hpgs_reader_read_int(reader,&pen)) return -1;
  if (!reader->eoc && hpgs_reader_read_double(reader,&r)) return -1;
  if (!reader->eoc && hpgs_reader_read_double(reader,&g)) return -1;
  if (!reader->eoc && hpgs_reader_read_double(reader,&b)) return -1;

  if (pen >= reader->npens)
    {
      if (pen < 256)
        {
          if (hpgs_reader_set_number_of_pens(reader,pen+1))
            return -1;
        }
      else
        {
          if (reader->verbosity)
            hpgs_log(hpgs_i18n("PC: Illegal pen number %d.\n"),pen);

          return 0;
        }
    }

  if (pen < 0)
    {
      hpgs_reader_set_std_pen_colors(reader,0,reader->npens);
      pen = reader->current_pen;
    }
  else
    {
      if (r==-1.0e20 || g==-1.0e20 || b==-1.0e20)
        {
          hpgs_reader_set_std_pen_colors(reader,pen,1);
        }
      else
        {
          reader->pen_colors[pen].r =
            (r - reader->min_color.r) / (reader->max_color.r - reader->min_color.r);
          if (reader->pen_colors[pen].r < 0.0) reader->pen_colors[pen].r = 0.0;
          if (reader->pen_colors[pen].r > 1.0) reader->pen_colors[pen].r = 1.0;

          reader->pen_colors[pen].g =
            (g - reader->min_color.g) / (reader->max_color.g - reader->min_color.g);
          if (reader->pen_colors[pen].g < 0.0) reader->pen_colors[pen].g = 0.0;
          if (reader->pen_colors[pen].g > 1.0) reader->pen_colors[pen].g = 1.0;

          reader->pen_colors[pen].b =
            (b - reader->min_color.b) / (reader->max_color.b - reader->min_color.b);
          if (reader->pen_colors[pen].b < 0.0) reader->pen_colors[pen].b = 0.0;
          if (reader->pen_colors[pen].b > 1.0) reader->pen_colors[pen].b = 1.0;
        }
    }

  if (pen == reader->current_pen)
    if (hpgs_setrgbcolor(reader->device,
			 &reader->pen_colors[pen]))
      return -1;

  return 0;
}