diff options
Diffstat (limited to 'src/cups/rastertoprinter.c')
-rw-r--r-- | src/cups/rastertoprinter.c | 1231 |
1 files changed, 723 insertions, 508 deletions
diff --git a/src/cups/rastertoprinter.c b/src/cups/rastertoprinter.c index c88a0be..b9da368 100644 --- a/src/cups/rastertoprinter.c +++ b/src/cups/rastertoprinter.c @@ -1,7 +1,7 @@ /* - * "$Id: rastertoprinter.c,v 1.19.4.15 2004/03/26 03:29:39 rlk Exp $" + * "$Id: rastertoprinter.c,v 1.96 2005/04/23 00:26:07 rlk Exp $" * - * GIMP-print based raster filter for the Common UNIX Printing System. + * Gutenprint based raster filter for the Common UNIX Printing System. * * Copyright 1993-2003 by Easy Software Products. * @@ -32,16 +32,11 @@ * main() - Main entry and processing of driver. * cups_writefunc() - Write data to a file... * cancel_job() - Cancel the current job... - * Image_bpp() - Return the bytes-per-pixel of an image. * Image_get_appname() - Get the application we are running. * Image_get_row() - Get one row of the image. * Image_height() - Return the height of an image. * Image_init() - Initialize an image. - * Image_note_progress() - Notify the user of our progress. - * Image_progress_conclude() - Close the progress display. - * Image_progress_init() - Initialize progress display. - * Image_rotate_ccw() - Rotate the image counter-clockwise - * (unsupported). + * Image_conclude() - Close the progress display. * Image_width() - Return the width of an image. */ @@ -49,6 +44,9 @@ * Include necessary headers... */ +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif #include <cups/cups.h> #include <cups/ppd.h> #include <cups/raster.h> @@ -57,15 +55,11 @@ #include <stdlib.h> #include <unistd.h> #include <fcntl.h> +#include <sys/times.h> #ifdef HAVE_LIMITS_H #include <limits.h> #endif -#ifdef INCLUDE_GIMP_PRINT_H -#include INCLUDE_GIMP_PRINT_H -#else -#include <gimp-print/gimp-print.h> -#endif -#include "../../lib/libprintut.h" +#include <gutenprint/gutenprint.h> /* Solaris with gcc has problems because gcc's limits.h doesn't #define */ /* this */ @@ -88,49 +82,480 @@ typedef struct int top; int width; int height; + int adjusted_width; + int adjusted_height; + int last_percent; cups_page_header_t header; /* Page header from file */ } cups_image_t; static void cups_writefunc(void *file, const char *buf, size_t bytes); +static void cups_errfunc(void *file, const char *buf, size_t bytes); static void cancel_job(int sig); static const char *Image_get_appname(stp_image_t *image); -static void Image_progress_conclude(stp_image_t *image); -static void Image_note_progress(stp_image_t *image, - double current, double total); -static void Image_progress_init(stp_image_t *image); static stp_image_status_t Image_get_row(stp_image_t *image, - unsigned char *data, int row); + unsigned char *data, + size_t byte_limit, int row); static int Image_height(stp_image_t *image); static int Image_width(stp_image_t *image); -static int Image_bpp(stp_image_t *image); -static void Image_rotate_180(stp_image_t *image); -static void Image_rotate_cw(stp_image_t *image); -static void Image_rotate_ccw(stp_image_t *image); +static void Image_conclude(stp_image_t *image); static void Image_init(stp_image_t *image); static stp_image_t theImage = { Image_init, NULL, /* reset */ - NULL, /* transpose */ - NULL, /* hflip */ - NULL, /* vflip */ - NULL, /* crop */ - Image_rotate_ccw, - Image_rotate_cw, - Image_rotate_180, - Image_bpp, Image_width, Image_height, Image_get_row, Image_get_appname, - Image_progress_init, - Image_note_progress, - Image_progress_conclude, + Image_conclude, NULL }; -static volatile stp_image_status_t Image_status; +static volatile stp_image_status_t Image_status = STP_IMAGE_STATUS_OK; +static double total_bytes_printed = 0; +static int print_messages_as_errors = 0; + +static void +set_string_parameter(stp_vars_t *v, const char *name, const char *val) +{ + fprintf(stderr, "DEBUG: Gutenprint set string %s to %s\n", name, val); + stp_set_string_parameter(v, name, val); +} + + +static void +set_special_parameter(stp_vars_t *v, const char *name, int choice) +{ + stp_parameter_t desc; + stp_describe_parameter(v, name, &desc); + if (desc.p_type == STP_PARAMETER_TYPE_STRING_LIST) + { + if (choice >= stp_string_list_count(desc.bounds.str)) + fprintf(stderr, "ERROR: Gutenprint unable to set %s!\n", name); + else + { + stp_set_string_parameter + (v, name, stp_string_list_param(desc.bounds.str, choice)->name); + fprintf(stderr, "DEBUG: Gutenprint set special parameter %s to choice %d (%s)\n", + name, choice, + stp_string_list_param(desc.bounds.str, choice)->name); + } + } + else + fprintf(stderr, "DEBUG: Gutenprint unable to set special %s: not a string\n", + name); + stp_parameter_description_destroy(&desc); +} + +static void +print_debug_block(const stp_vars_t *v, const cups_image_t *cups) +{ + stp_parameter_list_t params; + int nparams; + int i; + fprintf(stderr, "DEBUG: Gutenprint StartPage...\n"); + fprintf(stderr, "DEBUG: Gutenprint MediaClass = \"%s\"\n", cups->header.MediaClass); + fprintf(stderr, "DEBUG: Gutenprint MediaColor = \"%s\"\n", cups->header.MediaColor); + fprintf(stderr, "DEBUG: Gutenprint MediaType = \"%s\"\n", cups->header.MediaType); + fprintf(stderr, "DEBUG: Gutenprint OutputType = \"%s\"\n", cups->header.OutputType); + + fprintf(stderr, "DEBUG: Gutenprint AdvanceDistance = %d\n", cups->header.AdvanceDistance); + fprintf(stderr, "DEBUG: Gutenprint AdvanceMedia = %d\n", cups->header.AdvanceMedia); + fprintf(stderr, "DEBUG: Gutenprint Collate = %d\n", cups->header.Collate); + fprintf(stderr, "DEBUG: Gutenprint CutMedia = %d\n", cups->header.CutMedia); + fprintf(stderr, "DEBUG: Gutenprint Duplex = %d\n", cups->header.Duplex); + fprintf(stderr, "DEBUG: Gutenprint HWResolution = [ %d %d ]\n", cups->header.HWResolution[0], + cups->header.HWResolution[1]); + fprintf(stderr, "DEBUG: Gutenprint ImagingBoundingBox = [ %d %d %d %d ]\n", + cups->header.ImagingBoundingBox[0], cups->header.ImagingBoundingBox[1], + cups->header.ImagingBoundingBox[2], cups->header.ImagingBoundingBox[3]); + fprintf(stderr, "DEBUG: Gutenprint InsertSheet = %d\n", cups->header.InsertSheet); + fprintf(stderr, "DEBUG: Gutenprint Jog = %d\n", cups->header.Jog); + fprintf(stderr, "DEBUG: Gutenprint LeadingEdge = %d\n", cups->header.LeadingEdge); + fprintf(stderr, "DEBUG: Gutenprint Margins = [ %d %d ]\n", cups->header.Margins[0], + cups->header.Margins[1]); + fprintf(stderr, "DEBUG: Gutenprint ManualFeed = %d\n", cups->header.ManualFeed); + fprintf(stderr, "DEBUG: Gutenprint MediaPosition = %d\n", cups->header.MediaPosition); + fprintf(stderr, "DEBUG: Gutenprint MediaWeight = %d\n", cups->header.MediaWeight); + fprintf(stderr, "DEBUG: Gutenprint MirrorPrint = %d\n", cups->header.MirrorPrint); + fprintf(stderr, "DEBUG: Gutenprint NegativePrint = %d\n", cups->header.NegativePrint); + fprintf(stderr, "DEBUG: Gutenprint NumCopies = %d\n", cups->header.NumCopies); + fprintf(stderr, "DEBUG: Gutenprint Orientation = %d\n", cups->header.Orientation); + fprintf(stderr, "DEBUG: Gutenprint OutputFaceUp = %d\n", cups->header.OutputFaceUp); + fprintf(stderr, "DEBUG: Gutenprint PageSize = [ %d %d ]\n", cups->header.PageSize[0], + cups->header.PageSize[1]); + fprintf(stderr, "DEBUG: Gutenprint Separations = %d\n", cups->header.Separations); + fprintf(stderr, "DEBUG: Gutenprint TraySwitch = %d\n", cups->header.TraySwitch); + fprintf(stderr, "DEBUG: Gutenprint Tumble = %d\n", cups->header.Tumble); + fprintf(stderr, "DEBUG: Gutenprint cupsWidth = %d\n", cups->header.cupsWidth); + fprintf(stderr, "DEBUG: Gutenprint cupsHeight = %d\n", cups->header.cupsHeight); + fprintf(stderr, "DEBUG: Gutenprint cups->width = %d\n", cups->width); + fprintf(stderr, "DEBUG: Gutenprint cups->height = %d\n", cups->height); + fprintf(stderr, "DEBUG: Gutenprint cups->adjusted_width = %d\n", cups->adjusted_width); + fprintf(stderr, "DEBUG: Gutenprint cups->adjusted_height = %d\n", cups->adjusted_height); + fprintf(stderr, "DEBUG: Gutenprint cupsMediaType = %d\n", cups->header.cupsMediaType); + fprintf(stderr, "DEBUG: Gutenprint cupsBitsPerColor = %d\n", cups->header.cupsBitsPerColor); + fprintf(stderr, "DEBUG: Gutenprint cupsBitsPerPixel = %d\n", cups->header.cupsBitsPerPixel); + fprintf(stderr, "DEBUG: Gutenprint cupsBytesPerLine = %d\n", cups->header.cupsBytesPerLine); + fprintf(stderr, "DEBUG: Gutenprint cupsColorOrder = %d\n", cups->header.cupsColorOrder); + fprintf(stderr, "DEBUG: Gutenprint cupsColorSpace = %d\n", cups->header.cupsColorSpace); + fprintf(stderr, "DEBUG: Gutenprint cupsCompression = %d\n", cups->header.cupsCompression); + fprintf(stderr, "DEBUG: Gutenprint cupsRowCount = %d\n", cups->header.cupsRowCount); + fprintf(stderr, "DEBUG: Gutenprint cupsRowFeed = %d\n", cups->header.cupsRowFeed); + fprintf(stderr, "DEBUG: Gutenprint cupsRowStep = %d\n", cups->header.cupsRowStep); + fprintf(stderr, "DEBUG: Gutenprint stp_get_driver(v) |%s|\n", stp_get_driver(v)); + fprintf(stderr, "DEBUG: Gutenprint stp_get_left(v) |%d|\n", stp_get_left(v)); + fprintf(stderr, "DEBUG: Gutenprint stp_get_top(v) |%d|\n", stp_get_top(v)); + fprintf(stderr, "DEBUG: Gutenprint stp_get_page_width(v) |%d|\n", stp_get_page_width(v)); + fprintf(stderr, "DEBUG: Gutenprint stp_get_page_height(v) |%d|\n", stp_get_page_height(v)); + params = stp_get_parameter_list(v); + nparams = stp_parameter_list_count(params); + for (i = 0; i < nparams; i++) + { + const stp_parameter_t *p = stp_parameter_list_param(params, i); + switch (p->p_type) + { + case STP_PARAMETER_TYPE_STRING_LIST: + fprintf(stderr, "DEBUG: Gutenprint stp_get_string %s(v) |%s| %d\n", + p->name, stp_get_string_parameter(v, p->name) ? + stp_get_string_parameter(v, p->name) : "NULL", + stp_get_string_parameter_active(v, p->name)); + break; + case STP_PARAMETER_TYPE_DOUBLE: + fprintf(stderr, "DEBUG: Gutenprint stp_get_float %s(v) |%.3f| %d\n", + p->name, stp_get_float_parameter(v, p->name), + stp_get_float_parameter_active(v, p->name)); + break; + case STP_PARAMETER_TYPE_DIMENSION: + fprintf(stderr, "DEBUG: Gutenprint stp_get_dimension %s(v) |%d| %d\n", + p->name, stp_get_dimension_parameter(v, p->name), + stp_get_dimension_parameter_active(v, p->name)); + break; + case STP_PARAMETER_TYPE_INT: + fprintf(stderr, "DEBUG: Gutenprint stp_get_int %s(v) |%d| %d\n", + p->name, stp_get_int_parameter(v, p->name), + stp_get_int_parameter_active(v, p->name)); + break; + case STP_PARAMETER_TYPE_BOOLEAN: + fprintf(stderr, "DEBUG: Gutenprint stp_get_boolean %s(v) |%d| %d\n", + p->name, stp_get_boolean_parameter(v, p->name), + stp_get_boolean_parameter_active(v, p->name)); + break; + /* + * We don't handle raw, curve, or filename arguments. + */ + default: + break; + } + } + stp_parameter_list_destroy(params); +} + +static int +printer_supports_bw(const stp_vars_t *v) +{ + stp_parameter_t desc; + int status = 0; + stp_describe_parameter(v, "PrintingMode", &desc); + if (stp_string_list_is_present(desc.bounds.str, "BW")) + status = 1; + stp_parameter_description_destroy(&desc); + return status; +} + +static void +validate_options(stp_vars_t *v, cups_image_t *cups) +{ + stp_parameter_list_t params = stp_get_parameter_list(v); + int nparams = stp_parameter_list_count(params); + int i; + for (i = 0; i < nparams; i++) + { + const stp_parameter_t *param = stp_parameter_list_param(params, i); + stp_parameter_t desc; + stp_describe_parameter(v, param->name, &desc); + if (desc.p_type == STP_PARAMETER_TYPE_STRING_LIST) + { + if (!stp_string_list_is_present + (desc.bounds.str, stp_get_string_parameter(v, desc.name))) + { + fprintf(stderr, "DEBUG: Gutenprint clearing string %s (%s)\n", + desc.name, stp_get_string_parameter(v, desc.name)); + stp_clear_string_parameter(v, desc.name); + if (desc.is_mandatory) + { + fprintf(stderr, "DEBUG: Gutenprint setting default string %s to %s\n", + desc.name, desc.deflt.str); + stp_set_string_parameter(v, desc.name, desc.deflt.str); + if (strcmp(desc.name, "PageSize") == 0) + { + const stp_papersize_t *ps = + stp_get_papersize_by_name(desc.deflt.str); + if (ps->width > 0) + { + fprintf(stderr, "DEBUG: Gutenprint setting page width to %d\n", + ps->width); + if (ps->width < stp_get_page_width(v)) + stp_set_page_width(v, ps->width); + } + if (ps->height > 0) + { + fprintf(stderr, "DEBUG: Gutenprint setting page height to %d\n", + ps->height); + if (ps->height < stp_get_page_height(v)) + stp_set_page_height(v, ps->height); + } + } + } + } + } + stp_parameter_description_destroy(&desc); + } + stp_parameter_list_destroy(params); +} + +static stp_vars_t * +initialize_page(cups_image_t *cups, const stp_vars_t *default_settings) +{ + const stp_papersize_t *size; /* Paper size */ + stp_vars_t *v = stp_vars_create_copy(default_settings); + + stp_set_page_width(v, cups->header.PageSize[0]); + stp_set_page_height(v, cups->header.PageSize[1]); + stp_set_outfunc(v, cups_writefunc); + stp_set_errfunc(v, cups_errfunc); + stp_set_outdata(v, stdout); + stp_set_errdata(v, stderr); + + if (cups->header.cupsBitsPerColor == 16) + set_string_parameter(v, "ChannelBitDepth", "16"); + else + set_string_parameter(v, "ChannelBitDepth", "8"); + switch (cups->header.cupsColorSpace) + { + case CUPS_CSPACE_W : + /* Olympus photo printers don't support black & white ink! */ + if (printer_supports_bw(v)) + set_string_parameter(v, "PrintingMode", "BW"); + set_string_parameter(v, "InputImageType", "Whitescale"); + break; + case CUPS_CSPACE_K : + /* Olympus photo printers don't support black & white ink! */ + if (printer_supports_bw(v)) + set_string_parameter(v, "PrintingMode", "BW"); + set_string_parameter(v, "InputImageType", "Grayscale"); + break; + case CUPS_CSPACE_RGB : + set_string_parameter(v, "PrintingMode", "Color"); + set_string_parameter(v, "InputImageType", "RGB"); + break; + case CUPS_CSPACE_CMY : + set_string_parameter(v, "PrintingMode", "Color"); + set_string_parameter(v, "InputImageType", "CMY"); + break; + case CUPS_CSPACE_CMYK : + set_string_parameter(v, "PrintingMode", "Color"); + set_string_parameter(v, "InputImageType", "CMYK"); + break; + case CUPS_CSPACE_KCMY : + set_string_parameter(v, "PrintingMode", "Color"); + set_string_parameter(v, "InputImageType", "KCMY"); + break; + default : + fprintf(stderr, "ERROR: Gutenprint Bad colorspace %d!\n", + cups->header.cupsColorSpace); + break; + } + + if (cups->header.cupsCompression >= 0) + set_special_parameter(v, "Resolution", cups->header.cupsCompression); + + if (cups->header.MediaClass && strlen(cups->header.MediaClass) > 0) + set_string_parameter(v, "InputSlot", cups->header.MediaClass); + + if (cups->header.MediaType && strlen(cups->header.MediaType) > 0) + set_string_parameter(v, "MediaType", cups->header.MediaType); + + fprintf(stderr, "DEBUG: Gutenprint PageSize = %dx%d\n", cups->header.PageSize[0], + cups->header.PageSize[1]); + + if ((size = stp_get_papersize_by_size(cups->header.PageSize[1], + cups->header.PageSize[0])) != NULL) + set_string_parameter(v, "PageSize", size->name); + else + fprintf(stderr, "DEBUG: Gutenprint Unable to get media size for (%d, %d)\n", + cups->header.PageSize[1], cups->header.PageSize[0]); + + /* + * Duplex + * Note that the names MUST match those in the printer driver(s) + */ + + if (cups->header.Duplex != 0) + { + if (cups->header.Tumble != 0) + set_string_parameter(v, "Duplex", "DuplexTumble"); + else + set_string_parameter(v, "Duplex", "DuplexNoTumble"); + } + + set_string_parameter(v, "JobMode", "Job"); + validate_options(v, cups); + stp_get_media_size(v, &(cups->width), &(cups->height)); + stp_get_imageable_area(v, &(cups->left), &(cups->right), + &(cups->bottom), &(cups->top)); + fprintf(stderr, "DEBUG: Gutenprint limits w %d l %d r %d h %d t %d b %d\n", + cups->width, cups->left, cups->right, cups->height, cups->top, cups->bottom); + stp_set_width(v, cups->right - cups->left); + stp_set_height(v, cups->bottom - cups->top); + stp_set_left(v, cups->left); + stp_set_top(v, cups->top); + cups->right = cups->width - cups->right; + cups->width = cups->width - cups->left - cups->right; + cups->width = cups->header.HWResolution[0] * cups->width / 72; + cups->left = cups->header.HWResolution[0] * cups->left / 72; + cups->right = cups->header.HWResolution[0] * cups->right / 72; + cups->adjusted_width = cups->width; + if (cups->adjusted_width > cups->header.cupsWidth) + cups->adjusted_width = cups->header.cupsWidth; + + cups->bottom = cups->height - cups->bottom; + cups->height = cups->height - cups->top - cups->bottom; + cups->height = cups->header.HWResolution[1] * cups->height / 72; + cups->top = cups->header.HWResolution[1] * cups->top / 72; + cups->bottom = cups->header.HWResolution[1] * cups->bottom / 72; + cups->adjusted_height = cups->height; + if (cups->adjusted_height > cups->header.cupsHeight) + cups->adjusted_height = cups->header.cupsHeight; + fprintf(stderr, "DEBUG: Gutenprint CUPS settings w %d %d l %d r %d h %d %d t %d b %d\n", + cups->width, cups->adjusted_width, cups->left, cups->right, + cups->height, cups->adjusted_height, cups->top, cups->bottom); + + return v; +} + +static void +purge_excess_data(cups_image_t *cups) +{ + char *buffer = stp_malloc(cups->header.cupsBytesPerLine); + if (buffer) + { + fprintf(stderr, "DEBUG: Gutenprint purging %d rows\n", + cups->header.cupsHeight - cups->row); + while (cups->row < cups->header.cupsHeight) + { + cupsRasterReadPixels(cups->ras, (unsigned char *)buffer, + cups->header.cupsBytesPerLine); + cups->row ++; + } + } + stp_free(buffer); +} + +static void +set_all_options(stp_vars_t *v, cups_option_t *options, int num_options, + ppd_file_t *ppd) +{ + stp_parameter_list_t params = stp_get_parameter_list(v); + int nparams = stp_parameter_list_count(params); + int i; + for (i = 0; i < nparams; i++) + { + const stp_parameter_t *param = stp_parameter_list_param(params, i); + stp_parameter_t desc; + char *ppd_option_name = stp_malloc(strlen(param->name) + 8); /* StpFineFOO\0 */ + + const char *val; /* CUPS option value */ + ppd_option_t *ppd_option; + stp_describe_parameter(v, param->name, &desc); + if (desc.p_type == STP_PARAMETER_TYPE_DOUBLE) + { + sprintf(ppd_option_name, "Stp%s", desc.name); + val = cupsGetOption(ppd_option_name, num_options, options); + if (!val) + { + ppd_option = ppdFindOption(ppd, ppd_option_name); + if (ppd_option) + val = ppd_option->defchoice; + } + if (val && strlen(val) > 0 && strcmp(val, "None") != 0) + { + double coarse_val = atof(val) * 0.001; + double fine_val = 0; + sprintf(ppd_option_name, "StpFine%s", desc.name); + val = cupsGetOption(ppd_option_name, num_options, options); + if (!val) + { + ppd_option = ppdFindOption(ppd, ppd_option_name); + if (ppd_option) + val = ppd_option->defchoice; + } + if (val && strlen(val) > 0 && strcmp(val, "None") != 0) + fine_val = atof(val) * 0.001; + fprintf(stderr, "DEBUG: Gutenprint set float %s to %f + %f\n", + desc.name, coarse_val, fine_val); + fine_val += coarse_val; + if (fine_val > desc.bounds.dbl.upper) + fine_val = desc.bounds.dbl.upper; + stp_set_float_parameter(v, desc.name, fine_val); + } + } + else + { + sprintf(ppd_option_name, "Stp%s", desc.name); + val = cupsGetOption(ppd_option_name, num_options, options); + if (!val) + { + ppd_option = ppdFindOption(ppd, ppd_option_name); + if (ppd_option) + val = ppd_option->defchoice; + } + if (val && ((strlen(val) > 0 && strcmp(val, "None") != 0) || + (desc.p_type == STP_PARAMETER_TYPE_STRING_LIST))) + { + switch (desc.p_type) + { + case STP_PARAMETER_TYPE_STRING_LIST: + fprintf(stderr, "DEBUG: Gutenprint set string %s to %s\n", + desc.name, val); + set_string_parameter(v, desc.name, val); + break; + case STP_PARAMETER_TYPE_INT: + fprintf(stderr, "DEBUG: Gutenprint set int %s to %s\n", + desc.name, val); + stp_set_int_parameter(v, desc.name, atoi(val)); + break; + case STP_PARAMETER_TYPE_DIMENSION: + fprintf(stderr, "DEBUG: Gutenprint set dimension %s to %s\n", + desc.name, val); + stp_set_dimension_parameter(v, desc.name, atoi(val)); + break; + case STP_PARAMETER_TYPE_BOOLEAN: + fprintf(stderr, "DEBUG: Gutenprint set bool %s to %s\n", + desc.name, val); + stp_set_boolean_parameter + (v, desc.name, strcmp(val, "True") == 0 ? 1 : 0); + break; + case STP_PARAMETER_TYPE_CURVE: /* figure this out later... */ + case STP_PARAMETER_TYPE_FILE: /* Probably not, security hole */ + case STP_PARAMETER_TYPE_RAW: /* figure this out later, too */ + fprintf(stderr, "DEBUG: Gutenprint ignoring option %s %s type %d\n", + desc.name, val, desc.p_type); + break; + default: + break; + } + } + else + fprintf(stderr, "DEBUG: Gutenprint NOT setting %s to %s\n", + desc.name, val); + } + stp_parameter_description_destroy(&desc); + stp_free(ppd_option_name); + } + stp_parameter_list_destroy(params); +} /* * 'main()' - Main entry and processing of driver. @@ -144,37 +569,35 @@ main(int argc, /* I - Number of command-line arguments */ cups_image_t cups; /* CUPS image */ const char *ppdfile; /* PPD environment variable */ ppd_file_t *ppd; /* PPD file */ - ppd_option_t *option; /* PPD option */ - stp_printer_t printer; /* Printer driver */ - stp_vars_t v; /* Printer driver variables */ - stp_papersize_t size; /* Paper size */ - char *buffer; /* Overflow buffer */ + const stp_printer_t *printer; /* Printer driver */ int num_options; /* Number of CUPS options */ cups_option_t *options; /* CUPS options */ - const char *val; /* CUPS option value */ - int num_res; /* Number of printer resolutions */ - stp_param_t *res; /* Printer resolutions */ - float stp_gamma, /* STP options */ - stp_brightness, - stp_cyan, - stp_magenta, - stp_yellow, - stp_contrast, - stp_saturation, - stp_density; - + stp_vars_t *v = NULL; + stp_vars_t *default_settings; + int initialized_job = 0; + const char *version_id; + const char *release_version_id; + struct tms tms; + clock_t clk; + long clocks_per_sec; + struct timeval t1, t2; + struct timezone tz; /* - * Initialise libgimpprint + * Initialise libgutenprint */ theImage.rep = ∪︀ + (void) gettimeofday(&t1, &tz); stp_init(); - + version_id = stp_get_version(); + release_version_id = stp_get_release_version(); + default_settings = stp_vars_create(); /* * Check for valid arguments... */ + fprintf(stderr, "DEBUG: Gutenprint %s Starting\n", version_id); if (argc < 6 || argc > 7) { @@ -183,36 +606,73 @@ main(int argc, /* I - Number of command-line arguments */ * and return. */ - fputs("ERROR: rastertoprinter job-id user title copies options [file]\n", stderr); + fputs("ERROR: Gutenprint rastertoprinter job-id user title copies options [file]\n", stderr); return (1); } - Image_status = STP_IMAGE_OK; - /* * Get the PPD file... */ if ((ppdfile = getenv("PPD")) == NULL) { - fputs("ERROR: Fatal error: PPD environment variable not set!\n", stderr); + fputs("ERROR: Gutenprint Fatal error: PPD environment variable not set!\n", stderr); return (1); } + fprintf(stderr, "DEBUG: Gutenprint using PPD file %s\n", ppdfile); if ((ppd = ppdOpenFile(ppdfile)) == NULL) { - fprintf(stderr, "ERROR: Fatal error: Unable to load PPD file \"%s\"!\n", + fprintf(stderr, "ERROR: Gutenprint Fatal error: Unable to load PPD file \"%s\"!\n", ppdfile); return (1); } if (ppd->modelname == NULL) { - fprintf(stderr, "ERROR: Fatal error: No ModelName attribute in PPD file \"%s\"!\n", + fprintf(stderr, "ERROR: Gutenprint Fatal error: No ModelName attribute in PPD file \"%s\"!\n", + ppdfile); + ppdClose(ppd); + return (1); + } + + if (ppd->nickname == NULL) + { + fprintf(stderr, "ERROR: Gutenprint Fatal error: No NickName attribute in PPD file \"%s\"!\n", + ppdfile); + ppdClose(ppd); + return (1); + } + else if (strlen(ppd->nickname) < + strlen(ppd->modelname) + strlen(CUPS_PPD_NICKNAME_STRING) + 3) + { + fprintf(stderr, "ERROR: Gutenprint Fatal error: Corrupted NickName attribute in PPD file \"%s\"!\n", ppdfile); ppdClose(ppd); return (1); } + else if (strcmp(ppd->nickname + strlen(ppd->modelname) + + strlen(CUPS_PPD_NICKNAME_STRING), version_id) != 0) + { + fprintf(stderr, "ERROR: Gutenprint: The version of Gutenprint software installed (%s) does not match the PPD file (%s).\n", + version_id, + ppd->nickname+strlen(ppd->modelname)+strlen(CUPS_PPD_NICKNAME_STRING)); + fprintf(stderr, "ERROR: Gutenprint: If you have upgraded your version of Gutenprint\n"); + fprintf(stderr, "ERROR: Gutenprint: recently, you must reinstall all printer queues.\n"); + fprintf(stderr, "ERROR: Gutenprint: If the previous installed version of Gutenprint\n"); + fprintf(stderr, "ERROR: Gutenprint: was 4.3.19 or higher, you can use the `cups-genppdupdate.%s'\n", release_version_id); + fprintf(stderr, "ERROR: Gutenprint: program to do this; if the previous installed version\n"); + fprintf(stderr, "ERROR: Gutenprint: was older, you can use the Modify Printer command via\n"); + fprintf(stderr, "ERROR: Gutenprint: the CUPS web interface: http://localhost:631/printers.\n"); + /* + * Repeat the first line of the message so that CUPS will display it + */ + fprintf(stderr, "ERROR: Gutenprint: The version of Gutenprint software installed (%s) does not match the PPD file (%s).\n", + version_id, + ppd->nickname+strlen(ppd->modelname)+strlen(CUPS_PPD_NICKNAME_STRING)); + ppdClose(ppd); + return 1; + } /* * Get the STP options, if any... @@ -220,83 +680,33 @@ main(int argc, /* I - Number of command-line arguments */ num_options = cupsParseOptions(argv[5], 0, &options); - if ((val = cupsGetOption("stpGamma", num_options, options)) != NULL) - stp_gamma = atof(val) * 0.001; - else if ((option = ppdFindOption(ppd, "stpGamma")) != NULL) - stp_gamma = atof(option->defchoice) * 0.001; - else - stp_gamma = 1.0; - - if ((val = cupsGetOption("stpBrightness", num_options, options)) != NULL) - stp_brightness = atof(val) * 0.001; - else if ((option = ppdFindOption(ppd, "stpBrightness")) != NULL) - stp_brightness = atof(option->defchoice) * 0.001; - else - stp_brightness = 1.0; - - if ((val = cupsGetOption("stpCyan", num_options, options)) != NULL) - stp_cyan = atof(val) * 0.001; - else if ((option = ppdFindOption(ppd, "stpCyan")) != NULL) - stp_cyan = atof(option->defchoice) * 0.001; - else - stp_cyan = 1.0; - - if ((val = cupsGetOption("stpMagenta", num_options, options)) != NULL) - stp_magenta = atof(val) * 0.001; - else if ((option = ppdFindOption(ppd, "stpMagenta")) != NULL) - stp_magenta = atof(option->defchoice) * 0.001; - else - stp_magenta = 1.0; - - if ((val = cupsGetOption("stpYellow", num_options, options)) != NULL) - stp_yellow = atof(val) * 0.001; - else if ((option = ppdFindOption(ppd, "stpYellow")) != NULL) - stp_yellow = atof(option->defchoice) * 0.001; - else - stp_yellow = 1.0; - - if ((val = cupsGetOption("stpContrast", num_options, options)) != NULL) - stp_contrast = atof(val) * 0.001; - else if ((option = ppdFindOption(ppd, "stpContrast")) != NULL) - stp_contrast = atof(option->defchoice) * 0.001; - else - stp_contrast = 1.0; - - if ((val = cupsGetOption("stpSaturation", num_options, options)) != NULL) - stp_saturation = atof(val) * 0.001; - else if ((option = ppdFindOption(ppd, "stpSaturation")) != NULL) - stp_saturation = atof(option->defchoice) * 0.001; - else - stp_saturation = 1.0; + fprintf(stderr, "DEBUG: Gutenprint CUPS option count is %d (%d bytes)\n", + num_options, strlen(argv[5])); - if ((val = cupsGetOption("stpDensity", num_options, options)) != NULL) - stp_density = atof(val) * 0.001; - else if ((option = ppdFindOption(ppd, "stpDensity")) != NULL) - stp_density = atof(option->defchoice) * 0.001; - else - stp_density = 1.0; + if (num_options > 0) + { + int i; + for (i = 0; i < num_options; i++) + fprintf(stderr, "DEBUG: Gutenprint CUPS option %d %s = %s\n", + i, options[i].name, options[i].value); + } /* * Figure out which driver to use... */ - if ((printer = stp_get_printer_by_long_name(ppd->modelname)) == NULL) - if ((printer = stp_get_printer_by_driver(ppd->modelname)) == NULL) + printer = stp_get_printer_by_driver(ppd->modelname); + if (!printer) + printer = stp_get_printer_by_long_name(ppd->modelname); + + if (printer == NULL) { - fprintf(stderr, "ERROR: Fatal error: Unable to find driver named \"%s\"!\n", + fprintf(stderr, "ERROR: Gutenprint Fatal error: Unable to find driver named \"%s\"!\n", ppd->modelname); ppdClose(ppd); return (1); } - - ppdClose(ppd); - - /* - * Get the resolution options... - */ - - res = stp_printer_get_printfuncs(printer)->parameters(printer, NULL, - "Resolution", &num_res); + fprintf(stderr, "DEBUG: Gutenprint driver %s\n", ppd->modelname); /* * Open the page stream... @@ -306,32 +716,22 @@ main(int argc, /* I - Number of command-line arguments */ { if ((fd = open(argv[6], O_RDONLY)) == -1) { - perror("ERROR: Unable to open raster file - "); + perror("ERROR: Gutenprint Unable to open raster file - "); sleep(1); return (1); } } else fd = 0; + fprintf(stderr, "DEBUG: Gutenprint using fd %d\n", fd); - cups.ras = cupsRasterOpen(fd, CUPS_RASTER_READ); - - /* - * Setup default print variables... - */ - - v = stp_allocate_copy(stp_printer_get_printvars(printer)); + stp_set_printer_defaults(default_settings, printer); + stp_set_float_parameter(default_settings, "AppGamma", 1.0); + set_all_options(default_settings, options, num_options, ppd); + stp_merge_printvars(default_settings, stp_printer_get_defaults(printer)); + ppdClose(ppd); - stp_set_scaling(v, 0); /* No scaling */ - stp_set_cmap(v, NULL); - stp_set_left(v, 0); - stp_set_top(v, 0); - stp_set_orientation(v, ORIENT_PORTRAIT); - stp_set_outfunc(v, cups_writefunc); - stp_set_errfunc(v, cups_writefunc); - stp_set_outdata(v, stdout); - stp_set_errdata(v, stderr); - stp_set_job_mode(v, STP_JOB_MODE_JOB); + cups.ras = cupsRasterOpen(fd, CUPS_RASTER_READ); /* * Process pages as needed... @@ -339,244 +739,108 @@ main(int argc, /* I - Number of command-line arguments */ cups.page = 0; + fprintf(stderr, "DEBUG: Gutenprint about to start printing loop.\n"); + /* + * Read the first page header, which we need in order to set up + * the page. + */ + signal(SIGTERM, cancel_job); while (cupsRasterReadHeader(cups.ras, &cups.header)) - { - /* - * Update the current page... - */ - - cups.row = 0; - - fprintf(stderr, "PAGE: %d 1\n", cups.page + 1); - /* use 1-based page logging */ - - /* - * Debugging info... - */ - - fprintf(stderr, "DEBUG: StartPage...\n"); - fprintf(stderr, "DEBUG: MediaClass = \"%s\"\n", cups.header.MediaClass); - fprintf(stderr, "DEBUG: MediaColor = \"%s\"\n", cups.header.MediaColor); - fprintf(stderr, "DEBUG: MediaType = \"%s\"\n", cups.header.MediaType); - fprintf(stderr, "DEBUG: OutputType = \"%s\"\n", cups.header.OutputType); - - fprintf(stderr, "DEBUG: AdvanceDistance = %d\n", cups.header.AdvanceDistance); - fprintf(stderr, "DEBUG: AdvanceMedia = %d\n", cups.header.AdvanceMedia); - fprintf(stderr, "DEBUG: Collate = %d\n", cups.header.Collate); - fprintf(stderr, "DEBUG: CutMedia = %d\n", cups.header.CutMedia); - fprintf(stderr, "DEBUG: Duplex = %d\n", cups.header.Duplex); - fprintf(stderr, "DEBUG: HWResolution = [ %d %d ]\n", cups.header.HWResolution[0], - cups.header.HWResolution[1]); - fprintf(stderr, "DEBUG: ImagingBoundingBox = [ %d %d %d %d ]\n", - cups.header.ImagingBoundingBox[0], cups.header.ImagingBoundingBox[1], - cups.header.ImagingBoundingBox[2], cups.header.ImagingBoundingBox[3]); - fprintf(stderr, "DEBUG: InsertSheet = %d\n", cups.header.InsertSheet); - fprintf(stderr, "DEBUG: Jog = %d\n", cups.header.Jog); - fprintf(stderr, "DEBUG: LeadingEdge = %d\n", cups.header.LeadingEdge); - fprintf(stderr, "DEBUG: Margins = [ %d %d ]\n", cups.header.Margins[0], - cups.header.Margins[1]); - fprintf(stderr, "DEBUG: ManualFeed = %d\n", cups.header.ManualFeed); - fprintf(stderr, "DEBUG: MediaPosition = %d\n", cups.header.MediaPosition); - fprintf(stderr, "DEBUG: MediaWeight = %d\n", cups.header.MediaWeight); - fprintf(stderr, "DEBUG: MirrorPrint = %d\n", cups.header.MirrorPrint); - fprintf(stderr, "DEBUG: NegativePrint = %d\n", cups.header.NegativePrint); - fprintf(stderr, "DEBUG: NumCopies = %d\n", cups.header.NumCopies); - fprintf(stderr, "DEBUG: Orientation = %d\n", cups.header.Orientation); - fprintf(stderr, "DEBUG: OutputFaceUp = %d\n", cups.header.OutputFaceUp); - fprintf(stderr, "DEBUG: PageSize = [ %d %d ]\n", cups.header.PageSize[0], - cups.header.PageSize[1]); - fprintf(stderr, "DEBUG: Separations = %d\n", cups.header.Separations); - fprintf(stderr, "DEBUG: TraySwitch = %d\n", cups.header.TraySwitch); - fprintf(stderr, "DEBUG: Tumble = %d\n", cups.header.Tumble); - fprintf(stderr, "DEBUG: cupsWidth = %d\n", cups.header.cupsWidth); - fprintf(stderr, "DEBUG: cupsHeight = %d\n", cups.header.cupsHeight); - fprintf(stderr, "DEBUG: cupsMediaType = %d\n", cups.header.cupsMediaType); - fprintf(stderr, "DEBUG: cupsBitsPerColor = %d\n", cups.header.cupsBitsPerColor); - fprintf(stderr, "DEBUG: cupsBitsPerPixel = %d\n", cups.header.cupsBitsPerPixel); - fprintf(stderr, "DEBUG: cupsBytesPerLine = %d\n", cups.header.cupsBytesPerLine); - fprintf(stderr, "DEBUG: cupsColorOrder = %d\n", cups.header.cupsColorOrder); - fprintf(stderr, "DEBUG: cupsColorSpace = %d\n", cups.header.cupsColorSpace); - fprintf(stderr, "DEBUG: cupsCompression = %d\n", cups.header.cupsCompression); - fprintf(stderr, "DEBUG: cupsRowCount = %d\n", cups.header.cupsRowCount); - fprintf(stderr, "DEBUG: cupsRowFeed = %d\n", cups.header.cupsRowFeed); - fprintf(stderr, "DEBUG: cupsRowStep = %d\n", cups.header.cupsRowStep); - - /* - * Setup printer driver variables... - */ - - stp_set_page_width(v, cups.header.PageSize[0]); - stp_set_page_height(v, cups.header.PageSize[1]); - stp_set_image_type(v, cups.header.cupsRowCount); - - switch (cups.header.cupsColorSpace) { - case CUPS_CSPACE_W : - stp_set_output_type(v, OUTPUT_GRAY); - break; - case CUPS_CSPACE_K : - stp_set_output_type(v, OUTPUT_MONOCHROME); - break; - case CUPS_CSPACE_RGB : - stp_set_output_type(v, OUTPUT_COLOR); - break; - case CUPS_CSPACE_CMYK : - stp_set_output_type(v, OUTPUT_RAW_CMYK); - break; - default : - fprintf(stderr, "ERROR: Bad colorspace %d!", - cups.header.cupsColorSpace); - break; - } + /* + * We don't know how many pages we're going to print, and + * we need to call stp_end_job at the completion of the job. + * Therefore, we need to keep v in scope after the termination + * of the loop to permit calling stp_end_job then. Therefore, + * we have to free the previous page's stp_vars_t at the start + * of the loop. + */ + if (v) + stp_vars_destroy(v); + + /* + * Setup printer driver variables... + */ + v = initialize_page(&cups, default_settings); + stp_set_int_parameter(v, "PageNumber", cups.page); + cups.row = 0; + fprintf(stderr, "DEBUG: Gutenprint printing page %d\n", cups.page + 1); + fprintf(stderr, "PAGE: %d 1\n", cups.page + 1); + print_debug_block(v, &cups); + print_messages_as_errors = 1; + if (!stp_verify(v)) + { + fprintf(stderr, "ERROR: Gutenprint: options failed to verify.\n"); + fprintf(stderr, "ERROR: Gutenprint: Make sure that you are using ESP Ghostscript rather\n"); + fprintf(stderr, "ERROR: Gutenprint: than GNU or AFPL Ghostscript with CUPS.\n"); + fprintf(stderr, "ERROR: Gutenprint: If this is not the cause, set LogLevel to debug2 to identify the problem.\n"); + goto cups_abort; + } - if (cups.header.cupsRowStep >= stp_dither_algorithm_count()) - fprintf(stderr, "ERROR: Unable to set dither algorithm!\n"); - else - stp_set_dither_algorithm(v, - stp_dither_algorithm_name(cups.header.cupsRowStep)); - - if (cups.header.MediaClass && strlen(cups.header.MediaClass) > 0) - stp_set_media_source(v, cups.header.MediaClass); - if (cups.header.MediaType && strlen(cups.header.MediaType) > 0) - stp_set_media_type(v, cups.header.MediaType); - if (cups.header.OutputType && strlen(cups.header.OutputType) > 0) - stp_set_ink_type(v, cups.header.OutputType); - - fprintf(stderr, "DEBUG: PageSize = %dx%d\n", cups.header.PageSize[0], - cups.header.PageSize[1]); - - if ((size = stp_get_papersize_by_size(cups.header.PageSize[1], - cups.header.PageSize[0])) != NULL) - stp_set_media_size(v, stp_papersize_get_name(size)); - else - fprintf(stderr, "ERROR: Unable to get media size!\n"); - - if (cups.header.cupsCompression >= num_res) - fprintf(stderr, "ERROR: Unable to set printer resolution!\n"); - else - stp_set_resolution(v, res[cups.header.cupsCompression].name); - - stp_set_app_gamma(v, 1.0); - stp_set_brightness(v, stp_brightness); - stp_set_contrast(v, stp_contrast); - stp_set_cyan(v, stp_cyan); - stp_set_magenta(v, stp_magenta); - stp_set_yellow(v, stp_yellow); - stp_set_saturation(v, stp_saturation); - stp_set_density(v, stp_density); - stp_set_gamma(v, stp_gamma); - stp_merge_printvars(v, stp_printer_get_printvars(printer)); - - fprintf(stderr, "DEBUG: stp_get_output_to(v) |%s|\n", stp_get_output_to(v)); - fprintf(stderr, "DEBUG: stp_get_driver(v) |%s|\n", stp_get_driver(v)); - fprintf(stderr, "DEBUG: stp_get_ppd_file(v) |%s|\n", stp_get_ppd_file(v)); - fprintf(stderr, "DEBUG: stp_get_resolution(v) |%s|\n", stp_get_resolution(v)); - fprintf(stderr, "DEBUG: stp_get_media_size(v) |%s|\n", stp_get_media_size(v)); - fprintf(stderr, "DEBUG: stp_get_media_type(v) |%s|\n", stp_get_media_type(v)); - fprintf(stderr, "DEBUG: stp_get_media_source(v) |%s|\n", stp_get_media_source(v)); - fprintf(stderr, "DEBUG: stp_get_ink_type(v) |%s|\n", stp_get_ink_type(v)); - fprintf(stderr, "DEBUG: stp_get_dither_algorithm(v) |%s|\n", stp_get_dither_algorithm(v)); - fprintf(stderr, "DEBUG: stp_get_output_type(v) |%d|\n", stp_get_output_type(v)); - fprintf(stderr, "DEBUG: stp_get_orientation(v) |%d|\n", stp_get_orientation(v)); - fprintf(stderr, "DEBUG: stp_get_left(v) |%d|\n", stp_get_left(v)); - fprintf(stderr, "DEBUG: stp_get_top(v) |%d|\n", stp_get_top(v)); - fprintf(stderr, "DEBUG: stp_get_image_type(v) |%d|\n", stp_get_image_type(v)); - fprintf(stderr, "DEBUG: stp_get_unit(v) |%d|\n", stp_get_unit(v)); - fprintf(stderr, "DEBUG: stp_get_page_width(v) |%d|\n", stp_get_page_width(v)); - fprintf(stderr, "DEBUG: stp_get_page_height(v) |%d|\n", stp_get_page_height(v)); - fprintf(stderr, "DEBUG: stp_get_input_color_model(v) |%d|\n", stp_get_input_color_model(v)); - fprintf(stderr, "DEBUG: stp_get_output_color_model(v) |%d|\n", stp_get_output_color_model(v)); - fprintf(stderr, "DEBUG: stp_get_brightness(v) |%.3f|\n", stp_get_brightness(v)); - fprintf(stderr, "DEBUG: stp_get_scaling(v) |%.3f|\n", stp_get_scaling(v)); - fprintf(stderr, "DEBUG: stp_get_gamma(v) |%.3f|\n", stp_get_gamma(v)); - fprintf(stderr, "DEBUG: stp_get_contrast(v) |%.3f|\n", stp_get_contrast(v)); - fprintf(stderr, "DEBUG: stp_get_cyan(v) |%.3f|\n", stp_get_cyan(v)); - fprintf(stderr, "DEBUG: stp_get_magenta(v) |%.3f|\n", stp_get_magenta(v)); - fprintf(stderr, "DEBUG: stp_get_yellow(v) |%.3f|\n", stp_get_yellow(v)); - fprintf(stderr, "DEBUG: stp_get_saturation(v) |%.3f|\n", stp_get_saturation(v)); - fprintf(stderr, "DEBUG: stp_get_density(v) |%.3f|\n", stp_get_density(v)); - fprintf(stderr, "DEBUG: stp_get_app_gamma(v) |%.3f|\n", stp_get_app_gamma(v)); - - stp_set_page_number(v, cups.page); - - (*stp_printer_get_printfuncs(printer)->media_size) - (printer, v, &(cups.width), &(cups.height)); - (*stp_printer_get_printfuncs(printer)->imageable_area) - (printer, v, &(cups.left), &(cups.right), &(cups.bottom), &(cups.top)); - fprintf(stderr, "DEBUG: GIMP-PRINT %d %d %d %d %d %d\n", - cups.width, cups.left, cups.right, cups.height, cups.top, cups.bottom); - cups.right = cups.width - cups.right; - cups.width = cups.width - cups.left - cups.right; - cups.width = cups.header.HWResolution[0] * cups.width / 72; - cups.left = cups.header.HWResolution[0] * cups.left / 72; - cups.right = cups.header.HWResolution[0] * cups.right / 72; - - cups.top = cups.height - cups.top; - cups.height = cups.height - cups.top - cups.bottom; - cups.height = cups.header.HWResolution[1] * cups.height / 72; - cups.top = cups.header.HWResolution[1] * cups.top / 72; - cups.bottom = cups.header.HWResolution[1] * cups.bottom / 72; - fprintf(stderr, "DEBUG: GIMP-PRINT %d %d %d %d %d %d\n", - cups.width, cups.left, cups.right, cups.height, cups.top, cups.bottom); + if (!initialized_job) + { + stp_start_job(v, &theImage); + initialized_job = 1; + } - /* - * Print the page... - */ + if (!stp_print(v, &theImage)) + { + fprintf(stderr, "ERROR: Gutenprint failed to print, set LogLevel to debug2 to identify why\n"); + goto cups_abort; + } + print_messages_as_errors = 0; - if (stp_printer_get_printfuncs(printer)->verify(printer, v)) - { - signal(SIGTERM, cancel_job); - if (cups.page == 0) - stp_printer_get_printfuncs(printer)->start_job(printer, &theImage, v); - stp_printer_get_printfuncs(printer)->print(printer, &theImage, v); fflush(stdout); - } - else - fputs("ERROR: Invalid printer settings!\n", stderr); - /* - * Purge any remaining bitmap data... - */ - - if (cups.row < cups.header.cupsHeight) + /* + * Purge any remaining bitmap data... + */ + if (cups.row < cups.header.cupsHeight) + purge_excess_data(&cups); + cups.page ++; + } + if (v) { - if ((buffer = xmalloc(cups.header.cupsBytesPerLine)) == NULL) - break; - - while (cups.row < cups.header.cupsHeight) - { - cupsRasterReadPixels(cups.ras, (unsigned char *)buffer, - cups.header.cupsBytesPerLine); - cups.row ++; - } + fprintf(stderr, "DEBUG: Gutenprint ending job\n"); + stp_end_job(v, &theImage); + stp_vars_destroy(v); } - cups.page ++; - } - - if (cups.page > 0) - stp_printer_get_printfuncs(printer)->end_job(printer, &theImage, v); - - stp_free_vars(v); - - /* - * Close the raster stream... - */ - cupsRasterClose(cups.ras); + clk = times(&tms); + (void) gettimeofday(&t2, &tz); + clocks_per_sec = sysconf(_SC_CLK_TCK); + fprintf(stderr, "DEBUG: Gutenprint printed total %.0f bytes\n", + total_bytes_printed); + fprintf(stderr, "DEBUG: Gutenprint used %.3f seconds user, %.3f seconds system, %.3f seconds elapsed\n", + (double) tms.tms_utime / clocks_per_sec, + (double) tms.tms_stime / clocks_per_sec, + (double) (t2.tv_sec - t1.tv_sec) + + ((double) (t2.tv_usec - t1.tv_usec)) / 1000000.0); + fputs("INFO: Gutenprint Ready to print.\n", stderr); if (fd != 0) close(fd); - - /* - * If no pages were printed, send an error message... - */ - - if (cups.page == 0) - fputs("ERROR: No pages found!\n", stderr); - else - fputs("INFO: Ready to print.\n", stderr); - - return (cups.page == 0); + return 0; + +cups_abort: + clk = times(&tms); + (void) gettimeofday(&t2, &tz); + clocks_per_sec = sysconf(_SC_CLK_TCK); + fprintf(stderr, "DEBUG: Gutenprint printed total %.0f bytes\n", + total_bytes_printed); + fprintf(stderr, "DEBUG: Gutenprint used %.3f seconds user, %.3f seconds system, %.3f seconds elapsed\n", + (double) tms.tms_utime / clocks_per_sec, + (double) tms.tms_stime / clocks_per_sec, + (double) (t2.tv_sec - t1.tv_sec) + + ((double) (t2.tv_usec - t1.tv_usec)) / 1000000.0); + fputs("ERROR: Gutenprint No pages found!\n", stderr); + fputs("ERROR: Gutenprint Invalid printer settings!\n", stderr); + stp_end_job(v, &theImage); + stp_vars_destroy(v); + cupsRasterClose(cups.ras); + if (fd != 0) + close(fd); + return 1; } @@ -588,9 +852,32 @@ static void cups_writefunc(void *file, const char *buf, size_t bytes) { FILE *prn = (FILE *)file; + total_bytes_printed += bytes; fwrite(buf, 1, bytes, prn); } +static void +cups_errfunc(void *file, const char *buf, size_t bytes) +{ + size_t next_nl = 0; + size_t where = 0; + FILE *prn = (FILE *)file; + while (where < bytes) + { + if (print_messages_as_errors) + fputs("ERROR: Gutenprint: ", prn); + else + fputs("DEBUG: Gutenprint internal: ", prn); + while (next_nl < bytes) + { + if (buf[next_nl++] == '\n') + break; + } + fwrite(buf + where, 1, next_nl - where, prn); + where = next_nl; + } +} + /* * 'cancel_job()' - Cancel the current job... @@ -600,41 +887,9 @@ void cancel_job(int sig) /* I - Signal */ { (void)sig; - - Image_status = STP_IMAGE_ABORT; -} - - -/* - * 'Image_bpp()' - Return the bytes-per-pixel of an image. - */ - -static int /* O - Bytes per pixel */ -Image_bpp(stp_image_t *image) /* I - Image */ -{ - cups_image_t *cups; /* CUPS image */ - - - if ((cups = (cups_image_t *)(image->rep)) == NULL) - return (0); - - /* - * For now, we only support RGB and grayscale input from the - * raster filters. - */ - - switch (cups->header.cupsColorSpace) - { - default : - return (1); - case CUPS_CSPACE_RGB : - return (3); - case CUPS_CSPACE_CMYK : - return (4); - } + Image_status = STP_IMAGE_STATUS_ABORT; } - /* * 'Image_get_appname()' - Get the application we are running. */ @@ -644,7 +899,7 @@ Image_get_appname(stp_image_t *image) /* I - Image */ { (void)image; - return ("CUPS 1.1.x driver based on GIMP-print"); + return ("CUPS 1.1.x driver based on Gutenprint"); } @@ -670,50 +925,68 @@ throwaway_data(int amount, cups_image_t *cups) stp_image_status_t Image_get_row(stp_image_t *image, /* I - Image */ unsigned char *data, /* O - Row */ + size_t byte_limit, /* I - how many bytes in data */ int row) /* I - Row number (unused) */ { cups_image_t *cups; /* CUPS image */ int i; /* Looping var */ int bytes_per_line; int margin; - unsigned char *orig = data; - static int warned = 0; - + stp_image_status_t tmp_image_status = Image_status; + unsigned char *orig = data; /* Temporary pointer */ + static int warned = 0; /* Error warning printed? */ + int new_percent; if ((cups = (cups_image_t *)(image->rep)) == NULL) - return STP_IMAGE_ABORT; - bytes_per_line = cups->width * cups->header.cupsBitsPerPixel / CHAR_BIT; + { + fprintf(stderr, "ERROR: Gutenprint image is null! Please report this bug to gimp-print-devel@lists.sourceforge.net\n"); + return STP_IMAGE_STATUS_ABORT; + } + bytes_per_line = + ((cups->adjusted_width * cups->header.cupsBitsPerPixel) + CHAR_BIT - 1) / + CHAR_BIT; margin = cups->header.cupsBytesPerLine - bytes_per_line; if (cups->row < cups->header.cupsHeight) { - fprintf(stderr, "DEBUG: GIMP-PRINT reading %d %d\n", + fprintf(stderr, "DEBUG2: Gutenprint reading %d %d\n", bytes_per_line, cups->row); - cupsRasterReadPixels(cups->ras, data, bytes_per_line); - cups->row ++; - fprintf(stderr, "DEBUG: GIMP-PRINT tossing right %d\n", margin); - if (margin) - throwaway_data(margin, cups); - - /* - * Invert black data for monochrome output... - */ - - if (cups->header.cupsColorSpace == CUPS_CSPACE_K) - for (i = bytes_per_line; i > 0; i --, data ++) - *data = ((1 << CHAR_BIT) - 1) - *data; + while (cups->row <= row && cups->row < cups->header.cupsHeight) + { + cupsRasterReadPixels(cups->ras, data, bytes_per_line); + cups->row ++; + if (margin > 0) + { + fprintf(stderr, "DEBUG2: Gutenprint tossing right %d\n", margin); + throwaway_data(margin, cups); + } + } } else { - if (cups->header.cupsColorSpace == CUPS_CSPACE_CMYK) - memset(data, 0, bytes_per_line); - else - memset(data, ((1 << CHAR_BIT) - 1), bytes_per_line); + switch (cups->header.cupsColorSpace) + { + case CUPS_CSPACE_K: + case CUPS_CSPACE_CMYK: + case CUPS_CSPACE_KCMY: + case CUPS_CSPACE_CMY: + memset(data, 0, bytes_per_line); + break; + case CUPS_CSPACE_RGB: + case CUPS_CSPACE_W: + memset(data, ((1 << CHAR_BIT) - 1), bytes_per_line); + break; + default: + fprintf(stderr, "ERROR: Gutenprint Unknown colorspace %d!\n", + cups->header.cupsColorSpace); + return STP_IMAGE_STATUS_ABORT; + } } /* * This exists to print non-ADSC input which has messed up the job - * input, such as that generated by psnup. + * input, such as that generated by psnup. The output is barely + * legible, but it's better than the garbage output otherwise. */ data = orig; if (cups->header.cupsBitsPerPixel == 1) @@ -721,11 +994,11 @@ Image_get_row(stp_image_t *image, /* I - Image */ if (warned == 0) { fprintf(stderr, - "WARNING: GIMP-PRINT detected broken job options. " + "WARNING: Gutenprint detected broken job options. " "Output quality is degraded. Are you using psnup or non-ADSC PostScript?\n"); warned = 1; } - for (i = cups->width - 1; i >= 0; i--) + for (i = cups->adjusted_width - 1; i >= 0; i--) { if ( (data[i/8] >> (7 - i%8)) &0x1) data[i]=255; @@ -734,7 +1007,17 @@ Image_get_row(stp_image_t *image, /* I - Image */ } } - return Image_status; + new_percent = (int) (100.0 * cups->row / cups->header.cupsHeight); + if (new_percent > cups->last_percent) + { + fprintf(stderr, "INFO: Gutenprint Printing page %d, %d%%\n", + cups->page + 1, new_percent); + cups->last_percent = new_percent; + } + + if (tmp_image_status != STP_IMAGE_STATUS_OK) + fprintf(stderr, "DEBUG: Gutenprint image status %d\n", tmp_image_status); + return tmp_image_status; } @@ -751,8 +1034,8 @@ Image_height(stp_image_t *image) /* I - Image */ if ((cups = (cups_image_t *)(image->rep)) == NULL) return (0); - fprintf(stderr, "DEBUG: GIMP-PRINT: Image_height %d\n", cups->height); - return (cups->height); + fprintf(stderr, "DEBUG: Gutenprint: Image_height %d\n", cups->adjusted_height); + return (cups->adjusted_height); } @@ -763,55 +1046,22 @@ Image_height(stp_image_t *image) /* I - Image */ static void Image_init(stp_image_t *image) /* I - Image */ { - (void)image; -} - - -/* - * 'Image_note_progress()' - Notify the user of our progress. - */ - -void -Image_note_progress(stp_image_t *image, /* I - Image */ - double current, /* I - Current progress */ - double total) /* I - Maximum progress */ -{ cups_image_t *cups; /* CUPS image */ - if ((cups = (cups_image_t *)(image->rep)) == NULL) return; + cups->last_percent = 0; - fprintf(stderr, "INFO: Printing page %d, %.0f%%\n", - cups->page +1, 100.0 * current / total); - /* cups->page + 1 because users expect 1-based counting */ -} - - -/* - * 'Image_progress_conclude()' - Close the progress display. - */ - -static void -Image_progress_conclude(stp_image_t *image) /* I - Image */ -{ - cups_image_t *cups; /* CUPS image */ - - - if ((cups = (cups_image_t *)(image->rep)) == NULL) - return; - - fprintf(stderr, "INFO: Finished page %d...\n", cups->page + 1); + fprintf(stderr, "INFO: Starting page %d...\n", cups->page + 1); /* cups->page + 1 because users expect 1-based counting */ } - /* - * 'Image_progress_init()' - Initialize progress display. + * 'Image_progress_conclude()' - Close the progress display. */ static void -Image_progress_init(stp_image_t *image)/* I - Image */ +Image_conclude(stp_image_t *image) /* I - Image */ { cups_image_t *cups; /* CUPS image */ @@ -819,44 +1069,9 @@ Image_progress_init(stp_image_t *image)/* I - Image */ if ((cups = (cups_image_t *)(image->rep)) == NULL) return; - fprintf(stderr, "INFO: Starting page %d...\n", cups->page + 1); - /* cups->page + 1 because users expect 1-based counting */ + fprintf(stderr, "INFO: Gutenprint Finished page %d...\n", cups->page + 1); } - -/* - * 'Image_rotate_180()' - Rotate the image 180 degrees (unsupported). - */ - -static void -Image_rotate_180(stp_image_t *image) /* I - Image */ -{ - (void)image; -} - - -/* - * 'Image_rotate_ccw()' - Rotate the image counter-clockwise (unsupported). - */ - -static void -Image_rotate_ccw(stp_image_t *image) /* I - Image */ -{ - (void)image; -} - - -/* - * 'Image_rotate_cw()' - Rotate the image clockwise (unsupported). - */ - -static void -Image_rotate_cw(stp_image_t *image) /* I - Image */ -{ - (void)image; -} - - /* * 'Image_width()' - Return the width of an image. */ @@ -870,11 +1085,11 @@ Image_width(stp_image_t *image) /* I - Image */ if ((cups = (cups_image_t *)(image->rep)) == NULL) return (0); - fprintf(stderr, "DEBUG: GIMP-PRINT: Image_width %d\n", cups->width); - return (cups->width); + fprintf(stderr, "DEBUG: Gutenprint: Image_width %d\n", cups->adjusted_width); + return (cups->adjusted_width); } /* - * End of "$Id: rastertoprinter.c,v 1.19.4.15 2004/03/26 03:29:39 rlk Exp $". + * End of "$Id: rastertoprinter.c,v 1.96 2005/04/23 00:26:07 rlk Exp $". */ |