Example #1
0
static void
initialize_global_parameters(void)
{
  int i;
  for (i = 0; i < STP_CHANNEL_LIMIT; i++)
    {
      global_levels[i] = 1.0;
      global_gammas[i] = 1.0;
    }
  global_gamma = 1.0;
  global_steps = 256;
  global_ink_limit = 1.0;
  global_noblackline = 0;
  global_printer_width = 0;
  global_printer_height = 0;
  global_band_height = 0;
  global_n_testpatterns = -1;
  if (global_printer)
    free(global_printer); /* Allocated with strdup() */
  global_printer = NULL;
  global_density = 1.0;
  global_xtop = 0;
  global_xleft = 0;
  global_hsize = 1.0;
  global_vsize = 1.0;
  global_bit_depth = 16;
  global_channel_depth = 0;
  global_image_type = "CMYK";
  global_use_raw_cmyk = 0;
  global_did_something = 0;
  global_invert_data = 0;
  if (static_testpatterns)
    stp_free(static_testpatterns);
  static_testpatterns = NULL;
  if (global_vars)
    stp_vars_destroy(global_vars);
  global_vars = NULL;
  if (global_printer)
    free(global_printer); /* Allocated with strdup() */
  global_printer = NULL;
  start_job = 0;
  end_job = 0;
}
Example #2
0
int
main(int argc, char **argv) {
  int i, k;
  int use_all_page_sizes = 1;
  if (argc > 1 && !strcmp(argv[1], "-s"))
    use_all_page_sizes = 0;

  stp_init();
  for (i = 0; i < stp_printer_model_count(); i++) {
    const stp_printer_t *p = stp_get_printer_by_index(i);
    const char *driver = stp_printer_get_driver(p);
    const char *family = stp_printer_get_family(p);
    stp_vars_t *pv = 
      stp_vars_create_copy(stp_printer_get_defaults(p));
    stp_parameter_t desc;
    int num_opts;
    int printer_is_color = 0;
    const stp_param_string_t *opt;
    int width, height, bottom, left, top, right;
    if (strcmp(family, "ps") == 0 || strcmp(family, "raw") == 0)
      continue;
    stp_describe_parameter(pv, "PrintingMode", &desc);
    if (stp_string_list_is_present(desc.bounds.str, "Color"))
      printer_is_color = 1;
    stp_parameter_description_destroy(&desc);
    if (printer_is_color)
      stp_set_string_parameter(pv, "PrintingMode", "Color");
    else
      stp_set_string_parameter(pv, "PrintingMode", "BW");
    stp_set_string_parameter(pv, "ChannelBitDepth", "8");
    printf("# Printer model %s, long name `%s'\n", driver,
	   stp_printer_get_long_name(p));
    stp_describe_parameter(pv, "PageSize", &desc);
    printf("$defaults{'%s'}{'PageSize'} = '%s';\n",
	   driver, desc.deflt.str);
    num_opts = stp_string_list_count(desc.bounds.str);
    
    for (k = 0; k < num_opts; k++) {
      const stp_papersize_t *papersize;
      opt = stp_string_list_param(desc.bounds.str, k);
      papersize = stp_get_papersize_by_name(opt->name);
      
      if (!papersize) {
	printf("Unable to lookup size %s!\n", opt->name);
	continue;
      }
      if (!use_all_page_sizes && num_opts >= 10 &&
	  (papersize->paper_unit == PAPERSIZE_ENGLISH_EXTENDED ||
	   papersize->paper_unit == PAPERSIZE_METRIC_EXTENDED))
	continue;
      
      width  = papersize->width;
      height = papersize->height;
      
      stp_set_string_parameter(pv, "PageSize", opt->name);
      
      stp_get_media_size(pv, &width, &height);
      stp_get_maximum_imageable_area(pv, &left, &right, &bottom, &top);

      if (left < 0)
	left = 0;
      if (right > width)
	right = width;
      if (bottom > height)
	bottom = height;
      if (top < 0)
	top = 0;
      
      bottom = height - bottom;
      top    = height - top;

      if (strcmp(opt->name, "Custom") == 0) {
	/* Use relative values for the custom size */
	right = width - right;
	top = height - top;
	width = 0;
	height = 0;
      }

      printf("$stpdata{'%s'}{'PageSize'}{'%s'} = '%s';",
	     driver, opt->name, opt->text);
      printf("$imageableareas{'%s'}{'%s'} = {",
	     driver, opt->name);
      printf("'left'=>'%d',", left);
      printf("'right'=>'%d',", right);
      printf("'top'=>'%d',", top);
      printf("'bottom'=>'%d',", bottom);
      printf("'width'=>'%d',", width);
      printf("'height'=>'%d'", height);
      printf("};\n");
    }
    stp_parameter_description_destroy(&desc);
    stp_vars_destroy(pv);
  }
  return 0;
}
int
main(int argc, char **argv)
{
  int i, j, k;
  int first_arg = 1;
  stp_string_list_t *printer_list = NULL;
  stp_parameter_level_t max_level = STP_PARAMETER_LEVEL_ADVANCED4;
  if (argc > 1 && !strcmp(argv[1], "-s"))
    {
      max_level = STP_PARAMETER_LEVEL_BASIC;
      first_arg++;
    }

  stp_init();
  
  if (argc > first_arg)
    {
      printer_list = stp_string_list_create();
      for (i = 1; i < argc; i++)
	stp_string_list_add_string(printer_list, argv[i], argv[i]);
    }
  for (i = 0; i < stp_printer_model_count(); i++)
    {
      stp_parameter_list_t params;
      int nparams;
      stp_parameter_t desc;
      const stp_printer_t *printer = stp_get_printer_by_index(i);
      const char *driver = stp_printer_get_driver(printer);
      const char *family = stp_printer_get_family(printer);
      stp_vars_t *pv = stp_vars_create_copy(stp_printer_get_defaults(printer));
      int tcount = 0;
      size_t count;
      int printer_is_color = 0;
      if (strcmp(family, "ps") == 0 || strcmp(family, "raw") == 0)
	continue;
      if (printer_list && !stp_string_list_is_present(printer_list, driver))
	continue;

      /* Set Job Mode to "Job" as this enables the Duplex option */
      stp_set_string_parameter(pv, "JobMode", "Job");

      stp_describe_parameter(pv, "PrintingMode", &desc);
      if (stp_string_list_is_present(desc.bounds.str, "Color"))
	printer_is_color = 1;
      stp_parameter_description_destroy(&desc);
      if (printer_is_color)
	stp_set_string_parameter(pv, "PrintingMode", "Color");
      else
	stp_set_string_parameter(pv, "PrintingMode", "BW");
      stp_set_string_parameter(pv, "ChannelBitDepth", "8");

      printf("# Printer model %s, long name `%s'\n", driver,
	     stp_printer_get_long_name(printer));

      printf("$families{'%s'} = '%s';\n", driver, family);
      printf("$models{'%s'} = '%d';\n", driver, stp_get_model_id(pv));

      params = stp_get_parameter_list(pv);
      nparams = stp_parameter_list_count(params);

      for (k = 0; k < nparams; k++)
	{
	  const stp_parameter_t *p = stp_parameter_list_param(params, k);
	  if (p->read_only ||
	      (p->p_level > max_level && strcmp(p->name, "Resolution") != 0) ||
	      (p->p_class != STP_PARAMETER_CLASS_OUTPUT &&
	       p->p_class != STP_PARAMETER_CLASS_CORE &&
	       p->p_class != STP_PARAMETER_CLASS_FEATURE))
	    continue;
	  count = 0;
	  stp_describe_parameter(pv, p->name, &desc);
	  if (desc.is_active)
	    {
	      printf("$longnames{'%s'}{'%s'} = '%s';\n",
		     driver, desc.name, desc.text);
	      printf("$param_classes{'%s'}{'%s'} = %d;\n",
		     driver, desc.name, desc.p_class);
	      printf("$param_types{'%s'}{'%s'} = %d;\n",
		     driver, desc.name, desc.p_type);
	      printf("$param_levels{'%s'}{'%s'} = %d;\n",
		     driver, desc.name, desc.p_level);
	      if (desc.p_type == STP_PARAMETER_TYPE_STRING_LIST)
		{
		  count = stp_string_list_count(desc.bounds.str);
		  if (count > 0)
		    {
		      if (desc.is_mandatory)
			{
			  printf("$defaults{'%s'}{'%s'} = '%s';\n",
				 driver, desc.name, desc.deflt.str);
			}
		      else
			{
			  printf("$defaults{'%s'}{'%s'} = '%s';\n",
				 driver, desc.name, "None");
			  printf("$stpdata{'%s'}{'%s'}{'%s'} = '%s';\n",
				 driver, desc.name, "None", "None");
			}
		      for (j = 0; j < count; j++)
			{
			  const stp_param_string_t *param =
			    stp_string_list_param(desc.bounds.str, j);
			  printf("$stpdata{'%s'}{'%s'}{'%s'} = '%s';\n",
				 driver, desc.name, param->name, param->text);
			  if (strcmp(desc.name, "Resolution") == 0)
			    {
			      int x, y;
			      stp_set_string_parameter(pv, "Resolution",
						       param->name);
			      stp_describe_resolution(pv, &x, &y);
			      if (x > 0 && y > 0)
				{
				  printf("$stpdata{'%s'}{'%s'}{'%s'} = '%d';\n",
					 driver, "x_resolution", param->name, x);
				  printf("$stpdata{'%s'}{'%s'}{'%s'} = '%d';\n",
					 driver, "y_resolution", param->name, y);
				}
			    }
			}
		    }
		}
	      else if (desc.p_type == STP_PARAMETER_TYPE_BOOLEAN)
		{
		  if (desc.is_mandatory)
		    {
		      printf("$defaults{'%s'}{'%s'} = '%d';\n",
			     driver, desc.name, desc.deflt.boolean);
		    }
		  else
		    {
		      printf("$defaults{'%s'}{'%s'} = '%s';\n",
			     driver, desc.name, "None");
		      printf("$stpdata{'%s'}{'%s'}{'%s'} = '%s';\n",
			     driver, desc.name, "None", "None");
		    }
		    
		  printf("$stpdata{'%s'}{'%s'}{'False'} = 'False';\n",
			 driver, desc.name);
		  printf("$stpdata{'%s'}{'%s'}{'True'} = 'True';\n",
			 driver, desc.name);
		}
	      else if (desc.p_type == STP_PARAMETER_TYPE_DOUBLE)
		{
		  if (desc.bounds.dbl.lower <= desc.deflt.dbl &&
		      desc.bounds.dbl.upper >= desc.deflt.dbl)
		    {
		      printf("$stp_float_values{'%s'}{'MINVAL'}{'%s'} = %.3f;\n",
			     driver, desc.name, desc.bounds.dbl.lower);
		      printf("$stp_float_values{'%s'}{'MAXVAL'}{'%s'} = %.3f;\n",
			     driver, desc.name, desc.bounds.dbl.upper);
		      printf("$stp_float_values{'%s'}{'DEFVAL'}{'%s'} = %.3f;\n",
			     driver, desc.name, desc.deflt.dbl);
		      /* printf("$stp_float_values{'%s'}{'LONG_NAME'}{'%s'} = '%s';\n",
			 driver, desc.name, gettext(desc.text)); */
		      printf("$stp_float_values{'%s'}{'CATEGORY'}{'%s'} = '%s';\n",
			     driver, desc.name, gettext(desc.category));
		      printf("$stp_float_values{'%s'}{'HELP'}{'%s'} = q(%s);\n",
			     driver, desc.name, (desc.help ? gettext(desc.help) : "''"));
		      printf("$stp_float_values{'%s'}{'MANDATORY'}{'%s'} = q(%d);\n",
			     driver, desc.name, desc.is_mandatory);
		    }
		}
	      else if (desc.p_type == STP_PARAMETER_TYPE_INT)
		{
		  if (desc.bounds.integer.lower <= desc.deflt.integer &&
		      desc.bounds.integer.upper >= desc.deflt.integer)
		    {
		      printf("$stp_int_values{'%s'}{'MINVAL'}{'%s'} = %d;\n",
			     driver, desc.name, desc.bounds.integer.lower);
		      printf("$stp_int_values{'%s'}{'MAXVAL'}{'%s'} = %d;\n",
			     driver, desc.name, desc.bounds.integer.upper);
		      printf("$stp_int_values{'%s'}{'DEFVAL'}{'%s'} = %d;\n",
			     driver, desc.name, desc.deflt.integer);
		      /* printf("$stp_int_values{'%s'}{'LONG_NAME'}{'%s'} = '%s';\n",
			 driver, desc.name, gettext(desc.text)); */
		      printf("$stp_int_values{'%s'}{'CATEGORY'}{'%s'} = '%s';\n",
			     driver, desc.name, gettext(desc.category));
		      printf("$stp_int_values{'%s'}{'HELP'}{'%s'} = q(%s);\n",
			     driver, desc.name, (desc.help ? gettext(desc.help) : "''"));
		      printf("$stp_int_values{'%s'}{'MANDATORY'}{'%s'} = q(%d);\n",
			     driver, desc.name, desc.is_mandatory);
		    }
		}
	      else if (desc.p_type == STP_PARAMETER_TYPE_DIMENSION)
		{
		  if (desc.bounds.dimension.lower <= desc.deflt.dimension &&
		      desc.bounds.dimension.upper >= desc.deflt.dimension)
		    {
		      printf("$stp_dimension_values{'%s'}{'MINVAL'}{'%s'} = %d;\n",
			     driver, desc.name, desc.bounds.dimension.lower);
		      printf("$stp_dimension_values{'%s'}{'MAXVAL'}{'%s'} = %d;\n",
			     driver, desc.name, desc.bounds.dimension.upper);
		      printf("$stp_dimension_values{'%s'}{'DEFVAL'}{'%s'} = %d;\n",
			     driver, desc.name, desc.deflt.dimension);
		      /* printf("$stp_dimension_values{'%s'}{'LONG_NAME'}{'%s'} = '%s';\n",
			 driver, desc.name, gettext(desc.text)); */
		      printf("$stp_dimension_values{'%s'}{'CATEGORY'}{'%s'} = '%s';\n",
			     driver, desc.name, gettext(desc.category));
		      printf("$stp_dimension_values{'%s'}{'HELP'}{'%s'} = q(%s);\n",
			     driver, desc.name, (desc.help ? gettext(desc.help) : "''"));
		      printf("$stp_dimension_values{'%s'}{'MANDATORY'}{'%s'} = q(%d);\n",
			     driver, desc.name, desc.is_mandatory);
		    }
		}
	      tcount += count;
	    }
	  stp_parameter_description_destroy(&desc);
	}
      stp_parameter_list_destroy(params);
      if (tcount > 0)
	{
	  if (printer_is_color)
	    {
	      printf("$defaults{'%s'}{'%s'} = '%s';\n",
		     driver, "Color", "Color");
	      printf("$stpdata{'%s'}{'%s'}{'%s'} = '%s';\n",
		     driver, "Color", "Color", "Color");
	      printf("$stpdata{'%s'}{'%s'}{'%s'} = '%s';\n",
		     driver, "Color", "RawCMYK", "Raw CMYK");
	    }
	  else
	    printf("$defaults{'%s'}{'%s'} = '%s';\n",
		   driver, "Color", "Grayscale");
	  printf("$stpdata{'%s'}{'%s'}{'%s'} = '%s';\n",
		 driver, "Color", "Grayscale", "Gray Scale");
	  printf("$stpdata{'%s'}{'%s'}{'%s'} = '%s';\n",
		 driver, "Color", "BlackAndWhite", "Black and White");
	}
      stp_vars_destroy(pv);
    }
  return 0;
}
Example #4
0
/*
 * 'escp2_print()' - Print an image to an EPSON printer.
 */
static int
raw_print(const stp_vars_t *v, stp_image_t *image)
{
  int		model = stp_get_model_id(v);
  int width = stp_get_page_width(v);
  int height = stp_get_page_height(v);
  int		i, j;
  int		y;		/* Looping vars */
  stp_vars_t	*nv = stp_vars_create_copy(v);
  int out_channels;
  unsigned short *final_out = NULL;
  int		status = 1;
  int bytes_per_channel = raw_model_capabilities[model].output_bits / 8;
  int ink_channels = 1;
  int rotate_output = 0;
  const char *ink_type = stp_get_string_parameter(nv, "InkType");
  stp_image_init(image);

  stp_prune_inactive_options(nv);
  if (!stp_verify(nv))
    {
      stp_eprintf(nv, _("Print options not verified; cannot print.\n"));
      stp_vars_destroy(nv);
      stp_image_conclude(image);
      return 0;
    }
  if (width != stp_image_width(image) || height != stp_image_height(image))
    {
      stp_eprintf(nv, _("Image dimensions must match paper dimensions"));
      stp_vars_destroy(nv);
      stp_image_conclude(image);
      return 0;
    }
  if (ink_type)
    {
      for (i = 0; i < ink_count; i++)
	if (strcmp(ink_type, inks[i].name) == 0)
	  {
	    stp_set_string_parameter(nv, "STPIOutputType", inks[i].output_type);
	    ink_channels = inks[i].output_channels;
	    rotate_output = inks[i].rotate_channels;
	    break;
	  }
    }

  stp_set_float_parameter(nv, "Density", 1.0);
  stp_set_boolean_parameter(nv, "SimpleGamma", 1);
  stp_channel_reset(nv);
  for (i = 0; i < ink_channels; i++)
    stp_channel_add(nv, i, 0, 1.0);

  if (bytes_per_channel == 1)
    out_channels = stp_color_init(nv, image, 256);
  else
    out_channels = stp_color_init(nv, image, 65536);

  if (out_channels != ink_channels && out_channels != 1 && ink_channels != 1)
    {
      stp_eprintf(nv, "Internal error!  Output channels or input channels must be 1\n");
      stp_vars_destroy(nv);
      stp_image_conclude(image);
      return 0;
    }

  if (out_channels != ink_channels)
    final_out = stp_malloc(width * ink_channels * 2);

  for (y = 0; y < height; y++)
    {
      unsigned short *out;
      unsigned short *real_out;
      unsigned zero_mask;
      if (stp_color_get_row(nv, image, y, &zero_mask))
	{
	  status = 2;
	  break;
	}
      out = stp_channel_get_input(nv);
      real_out = out;
      if (rotate_output)
	{
	  unsigned short *tmp_out = real_out;
	  for (i = 0; i < width; i++)
	    {
	      unsigned short tmp = tmp_out[0];
	      for (j = 0; j < ink_channels - 1; j++)
		tmp_out[j] = tmp_out[j + 1];
	      tmp_out[ink_channels - 1] = tmp;
	      tmp_out += ink_channels;
	    }
	}
      if (out_channels != ink_channels)
	{
	  real_out = final_out;
	  if (out_channels < ink_channels)
	    {
	      for (i = 0; i < width; i++)
		{
		  for (j = 0; j < ink_channels; j++)
		    final_out[i * ink_channels + j] = out[i];
		}
	    }
	  else
	    {
	      for (i = 0; i < width; i++)
		{
		  int avg = 0;
		  for (j = 0; j < out_channels; j++)
		    avg += out[i * out_channels + j];
		  final_out[i] = avg / out_channels;
		}
	    }
	}
      if (bytes_per_channel == 1)
	{
	  unsigned char *char_out = (unsigned char *) real_out;
	  for (i = 0; i < width * ink_channels; i++)
	    char_out[i] = real_out[i] / 257;
	}
      stp_zfwrite((char *) real_out,
		  width * ink_channels * bytes_per_channel, 1, nv);
    }
  stp_image_conclude(image);
  if (final_out)
    stp_free(final_out);
  stp_vars_destroy(nv);
  return status;
}
Example #5
0
static int
do_print(void)
{
  int status = 0;
  stp_vars_t *v;
  const stp_printer_t *the_printer;
  int left, right, top, bottom;
  int x, y;
  int width, height;
  int retval;
  stp_parameter_list_t params;
  int count;
  int i;
  char tmp[32];

  initialize_global_parameters();
  global_vars = stp_vars_create();
  stp_set_outfunc(global_vars, writefunc);
  stp_set_errfunc(global_vars, writefunc);
  stp_set_outdata(global_vars, stdout);
  stp_set_errdata(global_vars, stderr);

  setlocale(LC_ALL, "C");
  retval = yyparse();
  setlocale(LC_ALL, "");
  if (retval)
    return retval + 1;

  if (!global_did_something)
    return 1;

  v = stp_vars_create();
  the_printer = stp_get_printer_by_driver(global_printer);
  if (!the_printer)
    {
      int j;
      fprintf(stderr, "Unknown printer %s\nValid printers are:\n",
	      global_printer);
      for (j = 0; j < stp_printer_model_count(); j++)
	{
	  the_printer = stp_get_printer_by_index(j);
	  fprintf(stderr, "%-16s%s\n", stp_printer_get_driver(the_printer),
		  stp_printer_get_long_name(the_printer));
	}
      return 2;
    }
  bytes_written = 0;
  if (global_output)
    {
      if (strcmp(global_output, "-") == 0)
	output = stdout;
      else if (strcmp(global_output, "") == 0)
	output = NULL;
      else if (global_output[0] == '|')
	{
	  close_output();
	  write_to_process = 1;
	  output = popen(global_output+1, "w");
	  if (! output)
	    {
	      fprintf(stderr, "popen '%s' failed: %s\n", global_output, strerror(errno));
	      output = NULL;
	    }
	  free(global_output);
	  global_output = NULL;
	}
      else
	{
	  close_output();
	  output = fopen(global_output, "wb");
	  if (! output)
	    {
	      fprintf(stderr, "Create %s failed: %s\n", global_output, strerror(errno));
	      output = NULL;
	    }
	  free(global_output);
	  global_output = NULL;
	}
    }
  stp_set_printer_defaults(v, the_printer);
  stp_set_outfunc(v, writefunc);
  stp_set_errfunc(v, writefunc);
  stp_set_outdata(v, output);
  stp_set_errdata(v, stderr);
  stp_set_string_parameter(v, "InputImageType", global_image_type);
  sprintf(tmp, "%d", global_bit_depth);
  stp_set_string_parameter(v, "ChannelBitDepth", tmp);
  if (strcmp(global_image_type, "Raw") == 0)
    {
      sprintf(tmp, "%d", global_channel_depth);
      stp_set_string_parameter(v, "RawChannels", tmp);
    }
  stp_set_float_parameter(v, "Density", global_density);
  stp_set_string_parameter(v, "Quality", "None");
  stp_set_string_parameter(v, "ImageType", "None");

  params = stp_get_parameter_list(v);
  count = stp_parameter_list_count(params);
  for (i = 0; i < count; i++)
    {
      const stp_parameter_t *p = stp_parameter_list_param(params, i);
      if (p->p_type == STP_PARAMETER_TYPE_STRING_LIST)
	{
	  const char *val = stp_get_string_parameter(global_vars, p->name);
	  if (val && strlen(val) > 0)
	    {
	      stp_set_string_parameter(v, p->name, val);
	    }
	}
      else if (p->p_type == STP_PARAMETER_TYPE_INT &&
	       stp_check_int_parameter(global_vars, p->name, STP_PARAMETER_ACTIVE))
	{
	  int val = stp_get_int_parameter(global_vars, p->name);
	  stp_set_int_parameter(v, p->name, val);
	}
      else if (p->p_type == STP_PARAMETER_TYPE_BOOLEAN &&
	       stp_check_boolean_parameter(global_vars, p->name, STP_PARAMETER_ACTIVE))
	{
	  int val = stp_get_boolean_parameter(global_vars, p->name);
	  stp_set_boolean_parameter(v, p->name, val);
	}
      else if (p->p_type == STP_PARAMETER_TYPE_CURVE &&
	       stp_check_curve_parameter(global_vars, p->name, STP_PARAMETER_ACTIVE))
	{
	  const stp_curve_t *val = stp_get_curve_parameter(global_vars, p->name);
	  stp_set_curve_parameter(v, p->name, val);
	}
      else if (p->p_type == STP_PARAMETER_TYPE_DOUBLE &&
	       stp_check_float_parameter(global_vars, p->name, STP_PARAMETER_ACTIVE))
	{
	  double val = stp_get_float_parameter(global_vars, p->name);
	  stp_set_float_parameter(v, p->name, val);
	}
    }
  stp_set_page_width(v, stp_get_page_width(global_vars));
  stp_set_page_height(v, stp_get_page_height(global_vars));
  stp_parameter_list_destroy(params);
  if (stp_check_string_parameter(v, "PageSize", STP_PARAMETER_ACTIVE) &&
      !strcmp(stp_get_string_parameter(v, "PageSize"), "Auto"))
    {
      stp_parameter_t desc;
      stp_describe_parameter(v, "PageSize", &desc);
      if (desc.p_type == STP_PARAMETER_TYPE_STRING_LIST)
	stp_set_string_parameter(v, "PageSize", desc.deflt.str);
      stp_parameter_description_destroy(&desc);
    }
  stp_set_printer_defaults_soft(v, the_printer);

  stp_get_imageable_area(v, &left, &right, &bottom, &top);
  stp_describe_resolution(v, &x, &y);
  if (x < 0)
    x = 300;
  if (y < 0)
    y = 300;

  width = right - left;
  height = bottom - top;

  switch (global_size_mode)
    {
    case SIZE_PT:
      top += (int) (global_xtop + .5);
      left += (int) (global_xleft + .5);
      width = (int) (global_hsize + .5);
      height = (int) (global_vsize + .5);
      break;
    case SIZE_IN:
      top += (int) ((global_xtop * 72) + .5);
      left += (int) ((global_xleft * 72) + .5);
      width = (int) ((global_hsize * 72) + .5);
      height = (int) ((global_vsize * 72) + .5);
      break;
    case SIZE_MM:
      top += (int) ((global_xtop * 72 / 25.4) + .5);
      left += (int) ((global_xleft * 72 / 25.4) + .5);
      width = (int) ((global_hsize * 72 / 25.4) + .5);
      height = (int) ((global_vsize * 72 / 25.4) + .5);
      break;
    case SIZE_RELATIVE:
    default:
      top += height * global_xtop;
      left += width * global_xleft;
      width *= global_hsize;
      height *= global_vsize;
      break;
    }
  stp_set_width(v, width);
  stp_set_height(v, height);
#if 0
  width = (width / global_steps) * global_steps;
  height = (height / global_n_testpatterns) * global_n_testpatterns;
#endif
  if (global_steps > width)
    global_steps = width;

  global_printer_width = width * x / 72;
  global_printer_height = height * y / 72;

  global_band_height = global_printer_height / global_n_testpatterns;
  if (global_band_height == 0)
    global_band_height = 1;
  stp_set_left(v, left);
  stp_set_top(v, top);

  stp_merge_printvars(v, stp_printer_get_defaults(the_printer));
  if (stp_verify(v))
    {
      bytes_written = 0;
      if (start_job)
	{
	  stp_start_job(v, &theImage);
	  start_job = 0;
	}
      if (stp_print(v, &theImage) != 1)
	{
	  if (!global_quiet)
	    fputs("FAILED", stderr);
	  failures++;
	  status = 2;
	  if (global_halt_on_error)
	    return status;
	}
      else if (bytes_written == 0)
	{
	  if (!global_quiet)
	    fputs("FAILED: No output", stderr);
	  failures++;
	  status = 2;
	  if (global_halt_on_error)
	    return status;
	}
      else
	passes++;
      if (end_job)
	{
	  stp_end_job(v, &theImage);
	  end_job = 0;
	}
    }
  else
    {
      if (! global_fail_verify_ok)
	{
	  if (!global_quiet)
	    fputs("FAILED", stderr);
	  failures++;
	  status = 2;
	  if (global_halt_on_error)
	    return status;
	}
      else
	{
	  if (!global_quiet)
	    fputs("(skipped)", stderr);
	  skipped++;
	}
    }
  if (!global_quiet)
    fputc('\n', stderr);
  stp_vars_destroy(v);
  stp_free(static_testpatterns);
  static_testpatterns = NULL;
  return status;
}
static int
run_one_weavetest(int physjets, int physsep, int hpasses, int vpasses,
                  int subpasses, int nrows, int first_line, int phys_lines,
                  int color_jet_arrangement, int strategy, int quiet)
{
    int i;
    int j;
    stp_weave_t w;
    stp_vars_t *v;
    int errors[26];
    char errcodes[26];
    int total_errors = 0;
    int lastpass = -1;
    int newestpass = -1;
    int *passstarts;
    int *logpassstarts;
    int *passends;
    int *passcounts;
    signed char *physpassstuff;
    signed char *rowdetail;
    int *current_slot;
    int vmod;
    int head_offset[8];
    int last_good_pass;

    v = stp_vars_create();
    stp_set_outfunc(v, writefunc);
    stp_set_errfunc(v, writefunc);
    stp_set_outdata(v, stdout);
    stp_set_errdata(v, stdout);

    memset(errors, 0, sizeof(int) * 26);
#if 0
    if (physjets < hpasses * vpasses * subpasses)
    {
        return 0;
    }
#endif

    for(i=0; i<8; i++)
        head_offset[i] = 0;

    switch (color_jet_arrangement)
    {
    case 1:			/* C80-type */
        head_offset[0] = (physjets+1)*physsep;
        head_offset[1] = (physjets+1)*physsep;
        head_offset[2] = 2*(physjets+1)*physsep;
        phys_lines += 2*(physjets+1)*physsep;
        break;
    case 2:			/* Offset by 1 (f360) */
        if (physsep % 2 == 0)
        {
            head_offset[1] = physsep / 2;
            head_offset[2] = physsep / 2;
            phys_lines += physsep / 2;
        }
        break;
    case 3:			/* Offset by 1 or 2 (cx3650-type) */
        if (physsep % 3 == 0)
        {
            head_offset[1] = physsep * 2 / 3;
            head_offset[2] = physsep / 3;
            phys_lines += physsep * 2 / 3;
        }
        break;
    default:			/* Normal */
        break;
    }


    stp_initialize_weave(v, physjets, physsep, hpasses, vpasses, subpasses,
                         7, 1, 128, nrows, first_line,
                         phys_lines, head_offset, strategy, flush_pass,
                         stp_fill_tiff, stp_pack_tiff,
                         stp_compute_tiff_linewidth);

    passstarts = stp_malloc(sizeof(int) * (nrows + physsep));
    logpassstarts = stp_malloc(sizeof(int) * (nrows + physsep));
    passends = stp_malloc(sizeof(int) * (nrows + physsep));
    passcounts = stp_malloc(sizeof(int) * (nrows + physsep));
    passes_flushed = stp_malloc(sizeof(int) * (nrows + physsep));
    vmod = 2 * physsep * hpasses * vpasses * subpasses;
    if (vmod == 0)
        vmod = 1;
    current_slot = stp_malloc(sizeof(int) * vmod);
    physpassstuff = stp_malloc((nrows + physsep));
    rowdetail = stp_malloc((nrows + physsep) * physjets);
    memset(rowdetail, 0, (nrows + physsep) * physjets);
    memset(physpassstuff, -1, (nrows + physsep));
    memset(current_slot, 0, (sizeof(int) * vmod));
    if (!quiet)
    {
        print_header();
        printf("%15s %5s %5s %5s %10s %10s %10s %10s\n", "", "row", "pass",
               "jet", "missing", "logical", "physstart", "physend");
    }
    for (i = 0; i < vmod; i++)
        current_slot[i] = -1;
    for (i = 0; i < (nrows + physsep); i++)
    {
        passes_flushed[i] = 0;
        logpassstarts[i] = INT_MIN;
        passstarts[i] = -1;
        passends[i] = -1;
    }
    memset(errcodes, ' ', 26);
    for (i = 0; i < nrows; i++)
    {
        for (j = 0; j < hpasses * vpasses * subpasses; j++)
        {
            int physrow;
            stp_weave_parameters_by_row(v, i+first_line, j, &w);
            physrow = w.logicalpassstart + physsep * w.jet;

            errcodes[0] = (w.pass < 0 ? (errors[0]++, 'A') : ' ');
            errcodes[1] = (w.jet < 0 || w.jet > physjets - 1 ?
                           (errors[1]++, 'B') : ' ');
            errcodes[2] = (w.physpassstart > w.row ? (errors[2]++, 'C') : ' ');
            errcodes[3] = (w.physpassend < w.row ? (errors[3]++, 'D') : ' ');
#if 0
            errcodes[4] = (w.physpassend == w.row && lastpass + 1 != w.pass ?
                           (errors[4]++, 'E') : ' ');
#endif
            errcodes[5] = (w.pass >= 0 && w.pass < nrows &&
                           passstarts[w.pass] != -1 &&
                           passstarts[w.pass] != w.physpassstart ?
                           (errors[5]++, 'F') : ' ');
            errcodes[6] = (w.pass >= 0 && w.pass < nrows &&
                           passends[w.pass] != -1 &&
                           passends[w.pass] != w.physpassend ?
                           (errors[6]++, 'G') : ' ');
            errcodes[7] = (w.row != physrow ? (errors[7]++, 'H') : ' ');
            errcodes[8] = (w.missingstartrows < 0 ||
                           w.missingstartrows > physjets - 1 ?
                           (errors[8]++, 'I') : ' ');
            errcodes[9] = (w.physpassstart < 0 ? (errors[9]++, 'J') : ' ');
            errcodes[10] = (w.missingstartrows > w.jet ?
                            (errors[10]++, 'K') : ' ');
            errcodes[11] = (w.pass >= 0 && w.pass < nrows &&
                            physpassstuff[w.pass] >= 0 &&
                            physpassstuff[w.pass] != j ?
                            (errors[11]++, 'L') : ' ');
            errcodes[12] = (w.pass >= 0 && w.pass < nrows && w.jet >= 0 &&
                            w.jet < physjets &&
                            rowdetail[w.pass * physjets + w.jet] == 1 ?
                            (errors[12]++, 'M') : ' ');
            errcodes[13] = (current_slot[w.pass % vmod] != -1 &&
                            current_slot[w.pass % vmod] != w.pass ?
                            (errors[13]++, 'N') : ' ');
            errcodes[14] = (w.physpassstart == w.row &&
                            w.jet != w.missingstartrows ?
                            (errors[14]++, 'O') : ' ');
            errcodes[15] = ((w.logicalpassstart < 0) ||
                            (w.logicalpassstart + physsep * (physjets - 1) >=
                             phys_lines) ?
                            (errors[15]++, 'P') : ' ');
            errcodes[16] = '\0';

            if (!quiet)
            {
                printf("%15s%5d %5d %5d %10d %10d %10d %10d\n",
                       errcodes, w.row, w.pass, w.jet, w.missingstartrows,
                       w.logicalpassstart, w.physpassstart, w.physpassend);
                fflush(stdout);
            }
            if (w.pass >= 0 && w.pass < (nrows + physsep))
            {
                if (w.physpassend == w.row)
                {
                    lastpass = w.pass;
                    passends[w.pass] = -2;
                    current_slot[w.pass % vmod] = -1;
                }
                else
                {
                    passends[w.pass] = w.physpassend;
                    current_slot[w.pass % vmod] = w.pass;
                }
                passstarts[w.pass] = w.physpassstart;
                logpassstarts[w.pass] = w.logicalpassstart;
                if (w.jet >= 0 && w.jet < physjets)
                    rowdetail[w.pass * physjets + w.jet] = 1;
                if (physpassstuff[w.pass] == -1)
                    physpassstuff[w.pass] = j;
                if (w.pass > newestpass)
                    newestpass = w.pass;
            }
        }
    }
    if (!quiet)
        printf("Unterminated passes:\n");
    for (i = 0; i <= newestpass; i++)
        if (passends[i] >= -1 && passends[i] < nrows && logpassstarts[i] != INT_MIN)
        {
            if (!quiet)
                printf("%d %d\n", i, passends[i]);
            errors[16]++;
        }
    if (!quiet)
    {
        printf("Last terminated pass: %d\n", lastpass);
        printf("Pass starts:\n");
    }
    last_good_pass = 0;
    errcodes[3] = '\0';
    for (i = 0; i <= newestpass; i++)
    {
        if (logpassstarts[i] != INT_MIN)
        {
            if (i > 0)
                errcodes[0] = logpassstarts[i] < logpassstarts[last_good_pass] ?
                              (errors[17]++, 'Q') : ' ';
            errcodes[1] = passes_flushed[i] ? (errors[18]++, 'R') : ' ';
            errcodes[2] = ' ';
            if (!quiet)
                printf("%s %d %d\n", errcodes, i, logpassstarts[i]);
            last_good_pass = i;
        }
        else if (!quiet)
        {
            errcodes[0] = ' ';
            errcodes[1] = ' ';
            errcodes[2] = '*';
            printf("%s %d\n", errcodes, i);
        }
    }
    for (i = 0; i < 26; i++)
        total_errors += errors[i];
    stp_free(rowdetail);
    stp_free(physpassstuff);
    stp_free(current_slot);
    stp_free(passcounts);
    stp_free(passends);
    stp_free(logpassstarts);
    stp_free(passstarts);
    stp_free(passes_flushed);
    if (!quiet || (quiet == 1 && total_errors > 0))
        printf("%d total error%s\n", total_errors, total_errors == 1 ? "" : "s");
    stp_vars_destroy(v);
    return total_errors;
}