/* * * Print plug-in Datamax-O'Neil DPL driver for Gutenprint. * * Copyright 1997-2000 Michael Sweet (mike@easysw.com), * Robert Krawitz (rlk@alum.mit.edu) and * Dave Hill (dave@minnie.demon.co.uk) * * Copyright 2016 Steve Letter (sletter1@yahoo.com) * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the Free * Software Foundation; either version 2 of the License, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ /* * This file must include only standard C header files. The core code must * compile on generic platforms that don't support glib, gimp, gtk, etc. */ #ifdef HAVE_CONFIG_H #include #endif #include #include #include "gutenprint-internal.h" #include "dither-impl.h" #include #include #define DEBUG #define DPL_DEBUG_DISABLE_BLANKLINE_REMOVAL /* * Local functions... */ static void dpl_pcx (stp_vars_t *, unsigned char *, int, int); static int dpl_get_multiplier (const stp_vars_t * v); #ifndef MAX #define MAX(a, b) ((a) > (b) ? (a) : (b)) #endif /* !MAX */ typedef struct { int height; int orientation; int label_separator; unsigned int h_offset; unsigned int v_offset; int darkness; int speed; int present; } dpl_privdata_t; /* * Generic define for a name/value set */ typedef struct { const char *dpl_name; const char *dpl_text; int dpl_code; int p0; int p1; } dpl_t; #define DPL_RES_150_150 1 #define DPL_RES_203_203 2 #define DPL_RES_300_300 4 #define DPL_RES_400_400 8 #define DPL_RES_600_600 16 static const dpl_t dpl_resolutions[] = { {"600dpi", N_("600x600 DPI"), DPL_RES_600_600, 600, 600}, {"400dpi", N_("400x400 DPI"), DPL_RES_400_400, 400, 400}, {"300dpi", N_("300x300 DPI"), DPL_RES_300_300, 300, 300}, {"203dpi", N_("203x203 DPI"), DPL_RES_203_203, 203, 203}, {"150dpi", N_("150x150 DPI"), DPL_RES_150_150, 150, 150}, }; #define NUM_RESOLUTIONS (sizeof(dpl_resolutions) / sizeof (dpl_t)) static const dpl_t dpl_speeds[] = { {"A", N_("1.0 IPS"), 'A'}, {"B", N_("1.5 IPS"), 'B'}, {"C", N_("2.0 IPS"), 'C'}, {"D", N_("2.5 IPS"), 'D'}, {"E", N_("3.0 IPS"), 'E'}, {"F", N_("3.5 IPS"), 'F'}, {"G", N_("4.0 IPS"), 'G'}, {"H", N_("4.5 IPS"), 'H'}, {"I", N_("5.0 IPS"), 'I'}, {"J", N_("5.5 IPS"), 'J'}, {"K", N_("6.0 IPS"), 'K'}, {"L", N_("6.5 IPS"), 'L'}, {"M", N_("7.0 IPS"), 'M'}, {"N", N_("7.5 IPS"), 'N'}, {"O", N_("8.0 IPS"), 'O'}, {"P", N_("8.5 IPS"), 'P'}, {"Q", N_("9.0 IPS"), 'Q'}, {"R", N_("9.5 IPS"), 'R'}, {"S", N_("10.0 IPS"), 'S'}, {"T", N_("10.5 IPS"), 'T'}, {"U", N_("11.0 IPS"), 'U'}, {"V", N_("11.5 IPS"), 'V'}, {"W", N_("12.0 IPS"), 'W'}, }; #define NUM_SPEEDS (sizeof(dpl_speeds) / sizeof (dpl_t)) /* * Printer capability data */ typedef struct { int model; int custom_max_width; int custom_max_height; int custom_min_width; int custom_min_height; int resolutions; int max_resolution; int resolution_adjust; char max_speed; char min_speed; char default_speed; } dpl_cap_t; static const dpl_cap_t dpl_model_capabilities[] = { /* Datamax-O'Neil Thermal DPL printers */ {10017, /* I Class Mark II 203 DPI */ 4 * 72, 99 * 72, /* Max paper size */ 1, 1, /* Min paper size */ DPL_RES_203_203, DPL_RES_203_203, DPL_RES_203_203, 'W', 'C', 'O', }, /* Datamax-O'Neil Thermal DPL printers */ {10018, /* I Class Mark II 300 DPI */ 4 * 72, 99 * 72, /* Max paper size */ 1, 1, /* Min paper size */ DPL_RES_150_150 | DPL_RES_300_300, /* Resolutions */ DPL_RES_300_300, DPL_RES_203_203, 'S', 'C', 'O', }, /* Datamax-O'Neil Thermal DPL printers */ {10020, /* I Class Mark II 600 DPI */ 4 * 72, 99 * 72, /* Max paper size */ 1, 1, /* Min paper size */ /* for future use DPL_RES_150_150 | DPL_RES_203_203 | DPL_RES_300_300 | DPL_RES_600_600, */ DPL_RES_300_300 | DPL_RES_600_600, /* Resolutions */ DPL_RES_600_600, DPL_RES_300_300, 'K', 'C', 'G', }, /* Datamax-O'Neil Thermal DPL printers */ {10021, /* E Class Mark III Basic 203 DPI*/ 4 * 72, 99 * 72, /* Max paper size */ 1, 1, /* Min paper size */ DPL_RES_203_203, /* Resolutions */ DPL_RES_203_203, DPL_RES_203_203, 'G', 'C', 'E', }, /* Datamax-O'Neil Thermal DPL printers */ {10022, /* E Class Mark III Basic 300 DPI*/ 4 * 72, 99 * 72, /* Max paper size */ 1, 1, /* Min paper size */ DPL_RES_300_300, /* Resolutions */ DPL_RES_300_300, DPL_RES_300_300, 'G', 'C', 'E', }, /* Datamax-O'Neil Thermal DPL printers */ {10023, /* E Class Mark III Advanced 203 DPI*/ 4 * 72, 99 * 72, /* Max paper size */ 1, 1, /* Min paper size */ DPL_RES_203_203, /* Resolutions */ DPL_RES_203_203, DPL_RES_203_203, 'I', 'C', 'E', }, /* Datamax-O'Neil Thermal DPL printers */ {10024, /* E Class Mark III Advanced 300 DPI*/ 4 * 72, 99 * 72, /* Max paper size */ 1, 1, /* Min paper size */ DPL_RES_300_300, /* Resolutions */ DPL_RES_300_300, DPL_RES_300_300, 'I', 'C', 'G', }, /* Datamax-O'Neil Thermal DPL printers */ {10025, /* E Class Mark III Pro 203 DPI*/ 4 * 72, 99 * 72, /* Max paper size */ 1, 1, /* Min paper size */ DPL_RES_203_203, /* Resolutions */ DPL_RES_203_203, DPL_RES_203_203, 'K', 'C', 'G', }, /* Datamax-O'Neil Thermal DPL printers */ {10026, /* E Class Mark III Pro 300 DPI*/ 4 * 72, 99 * 72, /* Max paper size */ 1, 1, /* Min paper size */ DPL_RES_300_300, /* Resolutions */ DPL_RES_300_300, DPL_RES_300_300, 'I', 'C', 'G', }, /* Datamax-O'Neil Thermal DPL printers */ {10027, /* E Class Mark III ProPlus 203 DPI*/ 4 * 72, 99 * 72, /* Max paper size */ 1, 1, /* Min paper size */ DPL_RES_203_203, /* Resolutions */ DPL_RES_203_203, DPL_RES_203_203, 'K', 'C', 'G', }, /* Datamax-O'Neil Thermal DPL printers */ {10028, /* E Class Mark III ProPlus 300 DPI*/ 4 * 72, 99 * 72, /* Max paper size */ 1, 1, /* Min paper size */ DPL_RES_300_300, /* Resolutions */ DPL_RES_300_300, DPL_RES_300_300, 'I', 'C', 'G', }, /* Datamax-O'Neil Thermal DPL printers */ {10029, /* RL3e */ 3 * 72, 99 * 72, /* Max paper size */ 1, 1, /* Min paper size */ DPL_RES_203_203, /* Resolutions */ DPL_RES_203_203, DPL_RES_203_203, 'G', 'A', 'E', }, /* Datamax-O'Neil Thermal DPL printers */ {10030, /* RL4e */ 4 * 72, 99 * 72, /* Max paper size */ 1, 1, /* Min paper size */ DPL_RES_203_203, /* Resolutions */ DPL_RES_203_203, DPL_RES_203_203, 'G', 'A', 'E', }, /* Datamax-O'Neil Thermal DPL printers */ {10031, /* H4212 */ 4 * 72, 99 * 72, /* Max paper size */ 1, 1, /* Min paper size */ DPL_RES_203_203, /* Resolutions */ DPL_RES_203_203, /* Max Resolution */ DPL_RES_203_203, /* Resolution Adjust */ 'W', /* Maximum IPS */ 'C', /* Minimum IPS */ 'O', /* Default IPS */ }, /* Datamax-O'Neil Thermal DPL printers */ {10032, /* H4212X */ 4 * 72, 99 * 72, /* Max paper size */ 1, 1, /* Min paper size */ DPL_RES_203_203, /* Resolutions */ DPL_RES_203_203, /* Max Resolution */ DPL_RES_203_203, /* Resolution Adjust */ 'W', /* Maximum IPS */ 'C', /* Minimum IPS */ 'O', /* Default IPS */ }, /* Datamax-O'Neil Thermal DPL printers */ {10033, /* H4310 */ 4 * 72, 99 * 72, /* Max paper size */ 1, 1, /* Min paper size */ DPL_RES_150_150 | DPL_RES_300_300, /* Resolutions */ DPL_RES_300_300, /* Max Resolution */ DPL_RES_203_203, /* Resolution Adjust */ 'S', /* Maximum IPS */ 'C', /* Minimum IPS */ 'O', /* Default IPS */ }, /* Datamax-O'Neil Thermal DPL printers */ {10034, /* H4310X */ 4 * 72, 99 * 72, /* Max paper size */ 1, 1, /* Min paper size */ DPL_RES_150_150 | DPL_RES_300_300, /* Resolutions */ DPL_RES_300_300, /* Max Resolution */ DPL_RES_203_203, /* Resolution Adjust */ 'S', /* Maximum IPS */ 'C', /* Minimum IPS */ 'O', /* Default IPS */ }, /* Datamax-O'Neil Thermal DPL printers */ {10035, /* H4408 */ 4 * 72, 99 * 72, /* Max paper size */ 1, 1, /* Min paper size */ DPL_RES_400_400 | DPL_RES_203_203, /* Resolutions */ DPL_RES_203_203, /* Max Resolution */ DPL_RES_203_203, /* Resolution Adjust */ 'O', /* Maximum IPS */ 'C', /* Minimum IPS */ 'G', /* Default IPS */ }, /* Datamax-O'Neil Thermal DPL printers */ {10036, /* H4606 */ 4 * 72, 99 * 72, /* Max paper size */ 1, 1, /* Min paper size */ DPL_RES_300_300 | DPL_RES_600_600, /* Resolutions */ DPL_RES_600_600, /* Max Resolution */ DPL_RES_300_300, /* Resolution Adjust */ 'K', /* Maximum IPS */ 'C', /* Minimum IPS */ 'G', /* Default IPS */ }, /* Datamax-O'Neil Thermal DPL printers */ {10037, /* H4606X */ 4 * 72, 99 * 72, /* Max paper size */ 1, 1, /* Min paper size */ DPL_RES_300_300 | DPL_RES_600_600, /* Resolutions */ DPL_RES_600_600, /* Max Resolution */ DPL_RES_300_300, /* Resolution Adjust */ 'K', /* Maximum IPS */ 'C', /* Minimum IPS */ 'G', /* Default IPS */ }, /* Datamax-O'Neil Thermal DPL printers */ {10038, /* H6210 */ 6 * 72, 99 * 72, /* Max paper size */ 1, 1, /* Min paper size */ DPL_RES_203_203, /* Resolutions */ DPL_RES_203_203, /* Max Resolution */ DPL_RES_203_203, /* Resolution Adjust */ 'S', /* Maximum IPS */ 'C', /* Minimum IPS */ 'O', /* Default IPS */ }, /* Datamax-O'Neil Thermal DPL printers */ {10039, /* H6210X */ 6 * 72, 99 * 72, /* Max paper size */ 1, 1, /* Min paper size */ DPL_RES_203_203, /* Resolutions */ DPL_RES_203_203, /* Max Resolution */ DPL_RES_203_203, /* Resolution Adjust */ 'S', /* Maximum IPS */ 'C', /* Minimum IPS */ 'O', /* Default IPS */ }, /* Datamax-O'Neil Thermal DPL printers */ {10040, /* H6212 */ 6 * 72, 99 * 72, /* Max paper size */ 1, 1, /* Min paper size */ DPL_RES_203_203, /* Resolutions */ DPL_RES_203_203, /* Max Resolution */ DPL_RES_203_203, /* Resolution Adjust */ 'W', /* Maximum IPS */ 'C', /* Minimum IPS */ 'O', /* Default IPS */ }, /* Datamax-O'Neil Thermal DPL printers */ {10041, /* H6212X */ 6 * 72, 99 * 72, /* Max paper size */ 1, 1, /* Min paper size */ DPL_RES_203_203, /* Resolutions */ DPL_RES_203_203, /* Max Resolution */ DPL_RES_203_203, /* Resolution Adjust */ 'W', /* Maximum IPS */ 'C', /* Minimum IPS */ 'O', /* Default IPS */ }, /* Datamax-O'Neil Thermal DPL printers */ {10042, /* H6308 */ 6 * 72, 99 * 72, /* Max paper size */ 1, 1, /* Min paper size */ DPL_RES_150_150 | DPL_RES_300_300, /* Resolutions */ DPL_RES_300_300, /* Max Resolution */ DPL_RES_203_203, /* Resolution Adjust */ 'O', /* Maximum IPS */ 'C', /* Minimum IPS */ 'G', /* Default IPS */ }, /* Datamax-O'Neil Thermal DPL printers */ {10043, /* H6310X */ 6 * 72, 99 * 72, /* Max paper size */ 1, 1, /* Min paper size */ DPL_RES_150_150 | DPL_RES_300_300, /* Resolutions */ DPL_RES_300_300, /* Max Resolution */ DPL_RES_203_203, /* Resolution Adjust */ 'S', /* Maximum IPS */ 'C', /* Minimum IPS */ 'O', /* Default IPS */ }, /* Datamax-O'Neil Thermal DPL printers */ {10044, /* H8308 */ 8.5 * 72, 99 * 72, /* Max paper size */ 1, 1, /* Min paper size */ DPL_RES_150_150 | DPL_RES_300_300, /* Resolutions */ DPL_RES_300_300, /* Max Resolution */ DPL_RES_203_203, /* Resolution Adjust */ 'O', /* Maximum IPS */ 'C', /* Minimum IPS */ 'G', /* Default IPS */ }, /* Datamax-O'Neil Thermal DPL printers */ {10045, /* H8308X */ 8.5 * 72, 99 * 72, /* Max paper size */ 1, 1, /* Min paper size */ DPL_RES_150_150 | DPL_RES_300_300, /* Resolutions */ DPL_RES_300_300, /* Max Resolution */ DPL_RES_203_203, /* Resolution Adjust */ 'O', /* Maximum IPS */ 'C', /* Minimum IPS */ 'G', /* Default IPS */ }, /* Honeywell Thermal DPL printers */ {10046, /* RP2 */ 2 * 72, 99 * 72, /* Max paper size */ 1, 1, /* Min paper size */ DPL_RES_203_203, /* Resolutions */ DPL_RES_203_203, DPL_RES_203_203, 'I', 'A', 'E', }, /* Honeywell Thermal DPL printers */ {10047, /* RP4 */ 4 * 72, 99 * 72, /* Max paper size */ 1, 1, /* Min paper size */ DPL_RES_203_203, /* Resolutions */ DPL_RES_203_203, DPL_RES_203_203, 'I', 'A', 'E', }, }; static const stp_parameter_t the_parameters[] = { { "PageSize", N_("Page Size"), "Color=No,Category=Basic Printer Setup", N_("Size of the paper being printed to"), STP_PARAMETER_TYPE_STRING_LIST, STP_PARAMETER_CLASS_CORE, STP_PARAMETER_LEVEL_BASIC, 1, 1, STP_CHANNEL_NONE, 1, 0}, { "Resolution", N_("Resolution"), "Color=No,Category=Basic Printer Setup", N_("Resolution of the print"), STP_PARAMETER_TYPE_STRING_LIST, STP_PARAMETER_CLASS_FEATURE, STP_PARAMETER_LEVEL_BASIC, 1, 1, STP_CHANNEL_NONE, 1, 0}, { "PrintingMode", N_("Printing Mode"), "Color=Yes,Category=Core Parameter", N_("Printing Output Mode"), STP_PARAMETER_TYPE_STRING_LIST, STP_PARAMETER_CLASS_CORE, STP_PARAMETER_LEVEL_BASIC, 1, 1, STP_CHANNEL_NONE, 1, 0 }, #ifdef FIXME /* Orientation not available for graphics, need * rotation routine in this driver */ { "Orientation", N_("Orientation"), "Color=No,Category=Basic Printer Setup", N_("Orientation, Portrait, Landscape, Upside Down, Seascape"), STP_PARAMETER_TYPE_STRING_LIST, STP_PARAMETER_CLASS_FEATURE, STP_PARAMETER_LEVEL_BASIC, 1, 1, STP_CHANNEL_NONE, 1, 0 }, #endif { "LabelSeparator", N_("Media Index Type"), "Color=No,Category=Basic Printer Setup", N_("Gap, Notch, Hole, Black Mark, Continuous"), STP_PARAMETER_TYPE_STRING_LIST, STP_PARAMETER_CLASS_FEATURE, STP_PARAMETER_LEVEL_BASIC, 1, 1, STP_CHANNEL_NONE, 1, 0, }, { "Darkness", N_("Darkness"), "Color=No,Category=Basic Printer Setup", N_("Darkness Adjust, from 0 to 30"), STP_PARAMETER_TYPE_INT, STP_PARAMETER_CLASS_FEATURE, STP_PARAMETER_LEVEL_BASIC, 0, 1, STP_CHANNEL_NONE, 1, 0}, { "Speed", N_("Print Speed"), "Color=No,Category=Basic Printer Setup", N_("Speed Adjust"), STP_PARAMETER_TYPE_STRING_LIST, STP_PARAMETER_CLASS_FEATURE, STP_PARAMETER_LEVEL_BASIC, 1, 1, STP_CHANNEL_NONE, 0, 0}, }; static const int the_parameter_count = sizeof (the_parameters) / sizeof (const stp_parameter_t); typedef struct { const stp_parameter_t param; double min; double max; double defval; int color_only; } float_param_t; static const float_param_t float_parameters[] = { { { "HorizOffset", N_("Horizontal Offset"), "Color=No,Category=Basic Output Adjustment", N_("Adjust horizontal position"), STP_PARAMETER_TYPE_DOUBLE, STP_PARAMETER_CLASS_OUTPUT, STP_PARAMETER_LEVEL_ADVANCED3, 1, 1, STP_CHANNEL_NONE, 1, 0, }, 0.0, 4.0, 0.0, 0}, { { "VertOffset", N_("Vertical Offset"), "Color=No,Category=Basic Output Adjustment", N_("Adjust vertical position"), STP_PARAMETER_TYPE_DOUBLE, STP_PARAMETER_CLASS_OUTPUT, STP_PARAMETER_LEVEL_ADVANCED3, 1, 1, STP_CHANNEL_NONE, 1, 0, }, 0.0, 10.0, 0.0, 0}, { { "Present", N_("Present Distance"), "Color=No,Category=Basic Output Adjustment", N_("Presnt Distance, 0.0 advances the default."), STP_PARAMETER_TYPE_DOUBLE, STP_PARAMETER_CLASS_FEATURE, STP_PARAMETER_LEVEL_BASIC, 1, 1, STP_CHANNEL_NONE, 1, 0, }, 0.0, 10.0, 0.0, 0}, }; static const int float_parameter_count = sizeof (float_parameters) / sizeof (const float_param_t); /* * Convert a value into it's option name */ static const char * dpl_val_to_string (const stp_vars_t *v, int code, /* I: Code */ const dpl_t * options, /* I: Options */ int num_options) /* I: Num options */ { int i; const char *string = NULL; /* * Look up the code in the table and convert to the string. */ for (i = 0; i < num_options; i++) { if (code == options[i].dpl_code) { string = options[i].dpl_name; break; } } stp_dprintf (STP_DBG_DPL, v, "Code: %d, String: %s\n", code, string); return (string); } static const char * dpl_val_to_text (const stp_vars_t *v, int code, /* I: Code */ const dpl_t * options, /* I: Options */ int num_options) /* I: Num options */ { int i; const char *string = NULL; /* * Look up the code in the table and convert to the string. */ for (i = 0; i < num_options; i++) { if (code == options[i].dpl_code) { string = gettext (options[i].dpl_text); break; } } stp_dprintf (STP_DBG_DPL, v, "Code: %d, String: %s\n", code, string); return (string); } /* * dpl_get_model_capabilities() - Return struct of model capabilities */ static const dpl_cap_t * /* O: Capabilities */ dpl_get_model_capabilities (const stp_vars_t *v) /* I: Model */ { int i; int model = stp_get_model_id(v); int models = sizeof (dpl_model_capabilities) / sizeof (dpl_cap_t); for (i = 0; i < models; i++) { if (dpl_model_capabilities[i].model == model) { return &(dpl_model_capabilities[i]); } } stp_eprintf (v, "dpl: model %d not found in capabilities list.\n", model); return &(dpl_model_capabilities[0]); } /* * Determine the current resolution */ static void dpl_describe_resolution (const stp_vars_t * v, stp_resolution_t *x, stp_resolution_t *y) { int i; const char *resolution = stp_get_string_parameter (v, "Resolution"); *x = -1; *y = -1; if (resolution) { for (i = 0; i < NUM_RESOLUTIONS; i++) { if (!strcmp (resolution, dpl_resolutions[i].dpl_name)) { *x = dpl_resolutions[i].p0; *y = dpl_resolutions[i].p1; } } } if (*x != *y) { if (*x > *y) { *y = *x; } else { *x = *y; } } } int dpl_get_multiplier (const stp_vars_t * v) { stp_resolution_t x, y; int multiplier; int i; int max_dpi; const dpl_cap_t *caps = dpl_get_model_capabilities (v); for (i = 0; i < NUM_RESOLUTIONS; i++) { if (caps->max_resolution == dpl_resolutions[i].dpl_code) { max_dpi = dpl_resolutions[i].p0; } } dpl_describe_resolution (v, &x, &y); if (x == max_dpi) multiplier = 1; else multiplier = 2; return multiplier; } #ifdef FIXME /* * Orientation support - modes available * Note that the internal names MUST match those in cups/genppd.c else the * PPD files will not be generated correctly */ static const stp_param_string_t orientation_types[] = { {"Portrait", N_("Portrait")}, {"Landscape", N_("Landscape")}, {"UpsideDown", N_("Reverse Portrait")}, {"Seascape", N_("Reverse Landscape")}, }; #define NUM_ORIENTATION (sizeof (orientation_types) / sizeof (stp_param_string_t)) #endif /* * Label Separator Support for D-O printers, modes available */ static const stp_param_string_t label_separator_types[] = { {"IGNORE", N_("Printer Setting")}, {"GAP", N_("Gap")}, {"NOTCH", N_("Notch")}, {"HOLE", N_("Hole")}, {"MARK", N_("Black Mark")}, {"CONTINUOUS", N_("Continuous")}, }; #define NUM_LABEL_SEPARATOR (sizeof (label_separator_types) / sizeof (stp_param_string_t)) /* * 'dpl_papersize_valid()' - Is the paper size valid for this printer. */ static int dpl_papersize_valid (const stp_vars_t *v, const stp_papersize_t * pt) { const dpl_cap_t *caps = dpl_get_model_capabilities (v); unsigned int pwidth = pt->width; unsigned int pheight = pt->height; /* * Is it a valid name? */ if (strlen (pt->name) <= 0) return (0); /* * We are allowed custom paper sizes. Check that the size is within * limits. Check that the name contains d-o if this is the * Datamax O'Neil label printer and not custom paper */ if (pwidth <= caps->custom_max_width && pheight <= caps->custom_max_height && (pheight >= caps->custom_min_height || pheight == 0) && (pwidth >= caps->custom_min_width || pwidth == 0)) { if (strcmp (pt->name, "Custom")) { if (NULL != strstr (pt->name, "d-o")) { return (1); } else { return (0); } } } return (0); } /* * 'dpl_parameters()' - Return the parameter values for the given parameter. */ static stp_parameter_list_t dpl_list_parameters (const stp_vars_t * v) { stp_parameter_list_t *ret; int i; ret = stp_parameter_list_create (); for (i = 0; i < the_parameter_count; i++) stp_parameter_list_add_param (ret, &(the_parameters[i])); for (i = 0; i < float_parameter_count; i++) stp_parameter_list_add_param (ret, &(float_parameters[i].param)); return ret; } static void dpl_parameters (const stp_vars_t * v, const char *name, stp_parameter_t * description) { int model = stp_get_model_id (v); int i; const dpl_cap_t *caps; description->p_type = STP_PARAMETER_TYPE_INVALID; if (name == NULL) return; stp_dprintf (STP_DBG_DPL, v, "dpl_parameters(): Name = %s\n", name); caps = dpl_get_model_capabilities (v); stp_dprintf (STP_DBG_DPL, v, "Printer model = %d\n", model); stp_dprintf (STP_DBG_DPL, v, "PageWidth = %d, PageHeight = %d\n", caps->custom_max_width, caps->custom_max_height); stp_dprintf (STP_DBG_DPL, v, "MinPageWidth = %d, MinPageHeight = %d\n", caps->custom_min_width, caps->custom_min_height); stp_dprintf (STP_DBG_DPL, v, "Resolutions: %d\n", caps->resolutions); for (i = 0; i < the_parameter_count; i++) if (strcmp (name, the_parameters[i].name) == 0) { stp_fill_parameter_settings (description, &(the_parameters[i])); break; } description->deflt.str = NULL; for (i = 0; i < float_parameter_count; i++) if (strcmp (name, float_parameters[i].param.name) == 0) { stp_fill_parameter_settings (description, &(float_parameters[i].param)); description->deflt.dbl = float_parameters[i].defval; description->bounds.dbl.upper = float_parameters[i].max; description->bounds.dbl.lower = float_parameters[i].min; break; } if (strcmp (name, "PageSize") == 0) { const stp_papersize_list_t *paper_sizes = stpi_get_papersize_list_named("labels", ""); const stp_papersize_list_item_t *ptli = stpi_papersize_list_get_start(paper_sizes); description->bounds.str = stp_string_list_create (); while (ptli) { const stp_papersize_t *pt = stpi_paperlist_item_get_data(ptli); if (strlen (pt->name) > 0 && dpl_papersize_valid (v, pt)) stp_string_list_add_string(description->bounds.str, pt->name, gettext(pt->text)); ptli = stpi_paperlist_item_next(ptli); } description->deflt.str = stp_string_list_param (description->bounds.str, 0)->name; } else if (strcmp (name, "Resolution") == 0) { description->bounds.str = stp_string_list_create (); description->deflt.str = dpl_val_to_string (v, caps->max_resolution, dpl_resolutions, NUM_RESOLUTIONS); for (i = 0; i < NUM_RESOLUTIONS; i++) if (caps->resolutions & dpl_resolutions[i].dpl_code) { stp_string_list_add_string (description->bounds.str, dpl_val_to_string (v, dpl_resolutions[i].dpl_code, dpl_resolutions, NUM_RESOLUTIONS), dpl_val_to_text (v, dpl_resolutions[i].dpl_code, dpl_resolutions, NUM_RESOLUTIONS)); } } else if (strcmp(name, "PrintingMode") == 0) { description->bounds.str = stp_string_list_create(); stp_string_list_add_string (description->bounds.str, "BW", _("Black and White")); description->deflt.str = stp_string_list_param(description->bounds.str, 0)->name; } #ifdef FIXME else if (strcmp (name, "Orientation") == 0) { description->bounds.str = stp_string_list_create (); description->deflt.str = orientation_types[0].name; for (i = 0; i < NUM_ORIENTATION; i++) { stp_string_list_add_string (description->bounds.str, orientation_types[i].name, gettext (orientation_types[i].text)); } } #endif else if (strcmp (name, "LabelSeparator") == 0) { description->bounds.str = stp_string_list_create (); description->deflt.str = label_separator_types[0].name; for (i = 0; i < NUM_LABEL_SEPARATOR; i++) { stp_string_list_add_string (description->bounds.str, label_separator_types[i].name, gettext (label_separator_types[i]. text)); } } else if (strcmp (name, "Darkness") == 0) { description->deflt.integer = -1; description->bounds.integer.lower = 0; description->bounds.integer.upper = 30; } else if (strcmp (name, "Speed") == 0) { description->bounds.str = stp_string_list_create (); stp_string_list_add_string (description->bounds.str, "None", _("Use Current Setting")); stp_string_list_add_string (description->bounds.str, "Default", _("Use Default Setting")); description->deflt.str = "None"; for (i = 0; i < NUM_SPEEDS; i++) { stp_string_list_add_string (description->bounds.str, dpl_speeds[i].dpl_name, gettext (dpl_speeds[i]. dpl_text)); } } else if (strcmp (name, "HorizOffset") == 0 || strcmp (name, "VertOffset") == 0 || strcmp (name, "Present") == 0) { description->is_active = 1; } } /* * 'dpl_imageable_area()' - Return the imageable area of the page. */ static void internal_imageable_area (const stp_vars_t * v, /* I */ stp_dimension_t *left, /* O - Left position in points */ stp_dimension_t *right, /* O - Right position in points */ stp_dimension_t *bottom, /* O - Bottom position in points */ stp_dimension_t *top) /* O - Top position in points */ { stp_dimension_t width, height; /* Size of page */ stp_default_media_size (v, &width, &height); *left = 0; *right = width; *top = 0; *bottom = height; } static void dpl_imageable_area (const stp_vars_t * v, /* I */ stp_dimension_t *left, /* O - Left position in points */ stp_dimension_t *right, /* O - Right position in points */ stp_dimension_t *bottom, /* O - Bottom position in points */ stp_dimension_t *top) /* O - Top position in points */ { internal_imageable_area (v, left, right, bottom, top); } static void dpl_limit (const stp_vars_t * v, /* I */ stp_dimension_t *width, stp_dimension_t *height, stp_dimension_t *min_width, stp_dimension_t *min_height) { const dpl_cap_t *caps = dpl_get_model_capabilities (v); *width = caps->custom_max_width; *height = caps->custom_max_height; *min_width = caps->custom_min_width; *min_height = caps->custom_min_height; } static const char * dpl_describe_output (const stp_vars_t * v) { return "Grayscale"; } static const stp_papersize_t * dpl_describe_papersize(const stp_vars_t *v, const char *name) { return stpi_get_listed_papersize(name, "labels"); } static void pcx_header (stp_vars_t * v, stp_image_t * image) { unsigned short height; unsigned short right; unsigned short top; /* y = 0 is at bottom */ unsigned short bytes; short xdpi; stp_resolution_t r_xdpi; stp_resolution_t *xdpi_p = (&r_xdpi); short ydpi; stp_resolution_t r_ydpi; stp_resolution_t *ydpi_p = (&r_ydpi); int n; const short zero = 0; stp_putc (10, v); /* Signature */ stp_putc (5, v); /* Version */ stp_putc (1, v); /* RLE encoding */ stp_putc (1, v); /* bits per pixel */ /* Get resolutions */ dpl_describe_resolution (v, xdpi_p, ydpi_p); xdpi = (short) r_xdpi; ydpi = (short) r_ydpi; bytes = (xdpi * 4 + 7 ) / 8; /* must be an even number */ if (bytes != (bytes & 0xfffe)) bytes++; height = stp_image_height (image); /* * Convert image size to printer resolution and setup the page for printing... */ right = 4 * xdpi - 1; top = height - 1; /* send image start and end positions */ stp_zfwrite ((const char *) &zero, 2, 1, v); stp_zfwrite ((const char *) &zero, 2, 1, v); stp_zfwrite ((const char *) &right, 2, 1, v); stp_zfwrite ((const char *) &top, 2, 1, v); /* send resolutions */ stp_zfwrite ((const char *) &xdpi, 2, 1, v); stp_zfwrite ((const char *) &ydpi, 2, 1, v); /* send palette and reserved byte */ for (n = 0; n < 3; n++) stp_putc (0, v); for (n = 0; n < 45; n++) stp_putc (0xff, v); stp_putc (0, v); stp_putc (1, v); /* number of planes, monochrome */ stp_zfwrite ((const char *) &bytes, 2, 1, v); stp_putc (1, v); /* monochrome */ stp_putc (0, v); stp_putc (0, v); /* imagee size */ stp_putc (0, v); stp_putc (0, v); stp_putc (0, v); for (n = 0; n < 54; n++) stp_putc (0, v); /* padding */ } /* * 'dpl_print()' - Print an image to an HP printer. */ static void dpl_printfunc (stp_vars_t * v, int height) { unsigned char *black = stp_dither_get_channel (v, STP_ECOLOR_K, 0); dpl_pcx (v, black, (height + 7) / 8, 1); } static double get_double_param (stp_vars_t * v, const char *param) { if (param && stp_check_float_parameter (v, param, STP_PARAMETER_ACTIVE)) return stp_get_float_parameter (v, param); else return 1.0; } static int dpl_do_print (stp_vars_t * v, stp_image_t * image) { dpl_privdata_t privdata; int status = 1; #ifdef FIXME const char *orientation_mode = stp_get_string_parameter (v, "Orientation"); #endif const char *label_separator_mode = stp_get_string_parameter (v, "LabelSeparator"); double h_offset = get_double_param (v, "HorizOffset"); double v_offset = get_double_param (v, "VertOffset"); double present = get_double_param (v, "Present"); int y; /* Looping vars */ stp_resolution_t xdpi, ydpi; /* Resolution */ int multiplier; unsigned char *black; /* Black bitmap data */ unsigned zero_mask; int image_height; int image_width; const dpl_cap_t *caps = dpl_get_model_capabilities (v); const char *speed = stp_get_string_parameter(v, "Speed"); if (!stp_verify (v)) { stp_eprintf (v, "Print options not verified; cannot print.\n"); return 0; } /* * Setup a read-only pixel region for the entire image... */ stp_image_init (image); stp_set_string_parameter (v, "ColorCorrection", "None"); #ifdef TESTING stp_set_float_parameter (v, "Brightness", 1.0); stp_set_float_parameter (v, "Contrast", 1.0); stp_set_float_parameter (v, "Gamma", 1.0); #endif /* * Figure out the output resolution... */ dpl_describe_resolution (v, &xdpi, &ydpi); stp_dprintf (STP_DBG_DPL, v, "dpl: resolution=%dx%d\n", (int) xdpi, (int) ydpi); if (xdpi <= 0 || ydpi <= 0) { stp_eprintf (v, "No resolution found; cannot print.\n"); return 0; } image_height = stp_image_height (image); image_width = stp_image_width (image); #ifdef FIXME privdata.orientation = 0; if ((strncmp (orientation_mode, "Landscape", 9) == 0)) privdata.orientation = 1; else if ((strncmp (orientation_mode, "UpsideDown", 10) == 0)) privdata.orientation = 2; else if ((strncmp (orientation_mode, "Seascape", 8) == 0)) privdata.orientation = 3; #endif /* * Label Separator mode */ privdata.label_separator = 0; if ((strncmp (label_separator_mode, "GAP", 3) == 0)) privdata.label_separator = 1; else if ((strncmp (label_separator_mode, "NOTCH", 5) == 0)) privdata.label_separator = 1; else if ((strncmp (label_separator_mode, "HOLE", 4) == 0)) privdata.label_separator = 1; else if ((strncmp (label_separator_mode, "MARK", 4) == 0)) privdata.label_separator = 2; else if ((strncmp (label_separator_mode, "CONTINUOUS", 10) == 0)) privdata.label_separator = 3; /* * Print Offsets */ privdata.h_offset = (int) (h_offset * 100); /* in 0.01 of an inch */ privdata.v_offset = (int) (v_offset * 100); /* in 0.01 of an inch */ privdata.present = (int) (present * 100.0); /* in 0.01 of an inch */ /* * Darkness Mode */ if (-1 != (privdata.darkness = stp_get_int_parameter (v, "Darkness"))) { if (0 == privdata.darkness) { privdata.darkness = 10; /* default */ } } /* * Speed Mode */ privdata.speed = 0; if (0 != strcmp("None", speed)) { if (0 == strcmp("Default", speed)) { privdata.speed = (int) caps->default_speed; } else { int i; for (i = 0; i < NUM_SPEEDS; i++) { if (0 == strcmp(dpl_speeds[i].dpl_name, speed)) { privdata.speed = dpl_speeds[i].dpl_code; break; } } if (caps->min_speed > (char) (privdata.speed)) { privdata.speed = caps->min_speed; } else { if (caps->max_speed < (char) (privdata.speed)) { privdata.speed = caps->max_speed; } } } } /* workaround for printer bug */ for (y=0; y<64; y++) stp_putc (0, v); /* * Send DPL initialization commands... */ stp_puts ("\002n\r", v); /* set Imperial units */ /* Max page length */ if (image_height / ydpi > 4) { stp_zprintf (v, "\002M%04i\r", 300 * image_height / ((int) ydpi) + (3 * privdata.v_offset)); } else { stp_zprintf (v, "\002M%04i\r", 1200 + (3 * privdata.v_offset)); } /* set Label Width */ stp_zprintf (v, "\002KcLW%04i\r", 100 * image_width / ((int) xdpi) + privdata.h_offset); if (0 != privdata.label_separator) { if (1 == privdata.label_separator) { stp_puts ("\002e\r", v); /* edge mode */ } else if (2 == privdata.label_separator) { stp_puts ("\002r\r", v); /* Mark mode */ } else { stp_zprintf (v, "\002c%04i\r", 100 * /* Continuous mode */ image_height / ((int) ydpi) + privdata.v_offset); } } if (privdata.darkness > -1) { stp_zprintf (v, "\002KZH%02i\r", privdata.darkness); } if (privdata.speed > 0) { stp_zprintf (v, "\002KZP%c\r", privdata.speed); } stp_zprintf (v, "\002Kf%04i\r", privdata.present); stp_puts ("\002IDPcups0\r", v); /* Save PCX file */ pcx_header (v, image); stp_dprintf (STP_DBG_DPL, v, "Normal init\n"); /* * Allocate memory for the raster data... */ black = stp_malloc ((image_width + 7) / 8); stp_set_string_parameter (v, "STPIOutputType", "Grayscale"); /* set up for very fast dithering as default */ stp_set_string_parameter (v, "DitherAlgorithm", "VeryFast"); stp_dither_init (v, image, image_width, xdpi, ydpi); stp_dither_add_channel (v, black, STP_ECOLOR_K, 0); stp_channel_set_black_channel (v, STP_ECOLOR_K); stp_channel_set_density_adjustment (v, STP_ECOLOR_K, 0, get_double_param (v, "BlackDensity") * 1); (void) stp_color_init (v, image, 65536); stp_allocate_component_data (v, "Driver", NULL, NULL, &privdata); for (y = 0; y < image_height; y++) { if (stp_color_get_row (v, image, y, &zero_mask)) { status = 2; break; } stp_dither (v, y, 0, 0, NULL); dpl_printfunc (v, image_width); } stp_puts ("\r\002L\r", v); /* enter Label Formatting mode */ multiplier = dpl_get_multiplier (v); /* dot multiplier */ stp_zprintf (v, "D%1i%1i\r", multiplier, multiplier); stp_puts ("R0000\r", v); /* 0 offset, offset handled below */ stp_puts ("A2\r", v); /* transparent mode */ /* load graphic */ stp_zprintf (v, "1Y11000%04i%04icups0\r", privdata.v_offset, privdata.h_offset); stp_puts ("Q0001\r", v); /* one label */ stp_puts ("E\r", v); /* print now */ stp_puts ("\002xDGcups0\r", v); /* delete graphic */ #if 0 stp_puts ("\002zD\r", v); /* reclaim space */ #endif stp_image_conclude (image); /* * Cleanup... */ if (black != NULL) stp_free (black); return status; } static int dpl_print (const stp_vars_t * v, stp_image_t * image) { int status; stp_vars_t *nv = stp_vars_create_copy (v); stp_prune_inactive_options (nv); status = dpl_do_print (nv, image); stp_vars_destroy (nv); return status; } static const stp_printfuncs_t print_dpl_printfuncs = { dpl_list_parameters, dpl_parameters, stp_default_media_size, dpl_imageable_area, dpl_imageable_area, dpl_limit, dpl_print, dpl_describe_resolution, dpl_describe_output, stp_verify_printer_params, NULL, NULL, NULL, dpl_describe_papersize }; static void dpl_pcx (stp_vars_t * v, /* I - Print file or command */ unsigned char *short_line, /* I - Output bitmap data */ int height, /* I - Height of bitmap data */ int last_plane) /* I - True if this is the last plane */ { unsigned char *line; unsigned char *data; unsigned char stored; int add_bytes = 0; int count = 0; int in = 0; int out = 0; stp_resolution_t xdpi, ydpi; const dpl_cap_t *caps = dpl_get_model_capabilities (v); int i; int max_dpi; int dpi_adjust; /* Each line has to be 4 inches long */ dpl_describe_resolution (v, &xdpi, &ydpi); for (i = 0; i < NUM_RESOLUTIONS; i++) { if (caps->max_resolution == dpl_resolutions[i].dpl_code) { max_dpi = dpl_resolutions[i].p0; } if (caps->resolution_adjust == dpl_resolutions[i].dpl_code) { dpi_adjust = dpl_resolutions[i].p0; } } if (xdpi == max_dpi) { add_bytes = ((xdpi * 4) + 7) / 8 - height; } else { add_bytes = ((dpi_adjust * 4) + 7) / 8 - height; } /* allocate 4 inch input buffer */ line = (unsigned char *) stp_malloc (height + add_bytes); /* allocate output buffer, worst case */ data = (unsigned char *) stp_malloc ((height + add_bytes) * 2); /* invert data, cups makes white 1 and black 0, printer wants the opposite */ for (in = 0; in < height; in++) { line[in] = 0xff ^ short_line[in]; } /* pad to 4 inches */ for (in = height; in < (height + add_bytes); in++) { line[in] = 0xff; } in = 0; while (in < (height + add_bytes)) { stored = line[in]; /* save the value */ for (count = 1; in + count < (height + add_bytes) && line[in + count] == stored && count < 63; count++); /* count the run */ /* test to see if we need to make a run of one because the data value has the two top bits set and see if we actually have a run */ if (stored > 191 || count > 1) { data[out++] = count | 0xc0; /* mask to indicate a run */ data[out++] = stored; /* output the value */ } else /* not a run */ { data[out++] = stored; /* output the value */ } in += count; } stp_zfwrite ((const char *) data, out, 1, v); stp_free (line); stp_free (data); } static stp_family_t print_dpl_module_data = { &print_dpl_printfuncs, NULL }; static int print_dpl_module_init (void) { return stpi_family_register (print_dpl_module_data.printer_list); } static int print_dpl_module_exit (void) { return stpi_family_unregister (print_dpl_module_data.printer_list); } /* Module header */ #define stp_module_version print_dpl_LTX_stp_module_version #define stp_module_data print_dpl_LTX_stp_module_data stp_module_version_t stp_module_version = { 0, 0 }; stp_module_t stp_module_data = { "dpl", VERSION, "DPL family driver", STP_MODULE_CLASS_FAMILY, NULL, print_dpl_module_init, print_dpl_module_exit, (void *) &print_dpl_module_data };