/*
*
* Print plug-in EPSON ESC/P2 driver for the GIMP.
*
* Copyright 1997-2000 Michael Sweet (mike@easysw.com) and
* Robert Krawitz (rlk@alum.mit.edu)
*
* 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
#include
#include
#include "print-escp2.h"
#ifdef __GNUC__
#define inline __inline__
#endif
#define OP_JOB_START 1
#define OP_JOB_PRINT 2
#define OP_JOB_END 4
#ifndef MAX
# define MAX(a, b) ((a) > (b) ? (a) : (b))
#endif /* !MAX */
typedef struct
{
unsigned count;
const char *name;
} channel_count_t;
static const channel_count_t escp2_channel_counts[] =
{
{ 1, "1" },
{ 2, "2" },
{ 3, "3" },
{ 4, "4" },
{ 5, "5" },
{ 6, "6" },
{ 7, "7" },
{ 8, "8" },
{ 9, "9" },
{ 10, "10" },
{ 11, "11" },
{ 12, "12" },
{ 13, "13" },
{ 14, "14" },
{ 15, "15" },
{ 16, "16" },
{ 17, "17" },
{ 18, "18" },
{ 19, "19" },
{ 20, "20" },
{ 21, "21" },
{ 22, "22" },
{ 23, "23" },
{ 24, "24" },
{ 25, "25" },
{ 26, "26" },
{ 27, "27" },
{ 28, "28" },
{ 29, "29" },
{ 30, "30" },
{ 31, "31" },
{ 32, "32" },
{ 33, "33" },
{ 34, "34" },
{ 35, "35" },
{ 36, "36" },
{ 37, "37" },
{ 38, "38" },
{ 39, "39" },
{ 40, "40" },
};
static stp_curve_t *hue_curve_bounds = NULL;
static int escp2_channel_counts_count =
sizeof(escp2_channel_counts) / sizeof(channel_count_t);
static const double ink_darknesses[] =
{
1.0, 0.31 / .4, 0.61 / .96, 0.08, 0.31 * 0.33 / .4, 0.61 * 0.33 / .96, 0.33, 1.0
};
#define INCH(x) (72 * x)
#define PARAMETER_INT(s) \
{ \
"escp2_" #s, "escp2_" #s, \
"Color=Yes,Category=Advanced Printer Functionality", NULL, \
STP_PARAMETER_TYPE_INT, STP_PARAMETER_CLASS_FEATURE, \
STP_PARAMETER_LEVEL_INTERNAL, 0, 1, STP_CHANNEL_NONE, 1, 0 \
}
#define PARAMETER_DIMENSION(s) \
{ \
"escp2_" #s, "escp2_" #s, \
"Color=Yes,Category=Advanced Printer Functionality", NULL, \
STP_PARAMETER_TYPE_DIMENSION, STP_PARAMETER_CLASS_FEATURE, \
STP_PARAMETER_LEVEL_INTERNAL, 0, 1, STP_CHANNEL_NONE, 1, 0 \
}
#define PARAMETER_INT_RO(s) \
{ \
"escp2_" #s, "escp2_" #s, \
"Color=Yes,Category=Advanced Printer Functionality", NULL, \
STP_PARAMETER_TYPE_INT, STP_PARAMETER_CLASS_FEATURE, \
STP_PARAMETER_LEVEL_INTERNAL, 0, 1, STP_CHANNEL_NONE, 1, 1 \
}
#define PARAMETER_RAW(s) \
{ \
"escp2_" #s, "escp2_" #s, \
"Color=Yes,Category=Advanced Printer Functionality", NULL, \
STP_PARAMETER_TYPE_RAW, STP_PARAMETER_CLASS_FEATURE, \
STP_PARAMETER_LEVEL_INTERNAL, 0, 1, STP_CHANNEL_NONE, 1, 0 \
}
typedef struct
{
const stp_parameter_t param;
double min;
double max;
double defval;
int color_only;
} float_param_t;
typedef struct
{
const stp_parameter_t param;
int min;
int max;
int defval;
} int_param_t;
static const stp_parameter_t the_parameters[] =
{
#if 0
{
"AutoMode", N_("Automatic Printing Mode"), "Color=Yes,Category=Basic Output Adjustment",
N_("Automatic printing mode"),
STP_PARAMETER_TYPE_STRING_LIST, STP_PARAMETER_CLASS_FEATURE,
STP_PARAMETER_LEVEL_BASIC, 1, 1, STP_CHANNEL_NONE, 1, 0
},
#endif
/*
* Don't check this parameter. We may offer different settings for
* different papers, but we need to be able to handle settings from PPD
* files that don't have constraints set up.
*/
{
"Quality", N_("Print Quality"), "Color=Yes,Category=Basic Output Adjustment",
N_("Print Quality"),
STP_PARAMETER_TYPE_STRING_LIST, STP_PARAMETER_CLASS_FEATURE,
STP_PARAMETER_LEVEL_BASIC, 1, 1, STP_CHANNEL_NONE, 0, 0
},
{
"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
},
{
"MediaType", N_("Media Type"), "Color=Yes,Category=Basic Printer Setup",
N_("Type of media (plain paper, photo paper, etc.)"),
STP_PARAMETER_TYPE_STRING_LIST, STP_PARAMETER_CLASS_FEATURE,
STP_PARAMETER_LEVEL_BASIC, 1, 1, STP_CHANNEL_NONE, 1, 0
},
{
"InputSlot", N_("Media Source"), "Color=No,Category=Basic Printer Setup",
N_("Source (input slot) of the media"),
STP_PARAMETER_TYPE_STRING_LIST, STP_PARAMETER_CLASS_FEATURE,
STP_PARAMETER_LEVEL_BASIC, 1, 1, STP_CHANNEL_NONE, 1, 0
},
{
"Duplex", N_("Double-Sided Printing"), "Color=No,Category=Basic Printer Setup",
N_("Duplex/Tumble Setting"),
STP_PARAMETER_TYPE_STRING_LIST, STP_PARAMETER_CLASS_FEATURE,
STP_PARAMETER_LEVEL_BASIC, 1, 1, STP_CHANNEL_NONE, 1, 0
},
{
"CDInnerRadius", N_("CD Hub Size"), "Color=No,Category=Basic Printer Setup",
N_("Print only outside of the hub of the CD, or all the way to the hole"),
STP_PARAMETER_TYPE_STRING_LIST, STP_PARAMETER_CLASS_FEATURE,
STP_PARAMETER_LEVEL_BASIC, 1, 1, STP_CHANNEL_NONE, 1, 0
},
{
"CDOuterDiameter", N_("CD Size (Custom)"), "Color=No,Category=Basic Printer Setup",
N_("Variable adjustment for the outer diameter of CD"),
STP_PARAMETER_TYPE_DIMENSION, STP_PARAMETER_CLASS_FEATURE,
STP_PARAMETER_LEVEL_ADVANCED, 1, 1, STP_CHANNEL_NONE, 1, 0
},
{
"CDInnerDiameter", N_("CD Hub Size (Custom)"), "Color=No,Category=Basic Printer Setup",
N_("Variable adjustment to the inner hub of the CD"),
STP_PARAMETER_TYPE_DIMENSION, STP_PARAMETER_CLASS_FEATURE,
STP_PARAMETER_LEVEL_ADVANCED, 1, 1, STP_CHANNEL_NONE, 1, 0
},
{
"CDXAdjustment", N_("CD Horizontal Fine Adjustment"), "Color=No,Category=Advanced Printer Setup",
N_("Fine adjustment to horizontal position for CD printing"),
STP_PARAMETER_TYPE_DIMENSION, STP_PARAMETER_CLASS_FEATURE,
STP_PARAMETER_LEVEL_ADVANCED, 1, 1, STP_CHANNEL_NONE, 1, 0
},
{
"CDYAdjustment", N_("CD Vertical Fine Adjustment"), "Color=No,Category=Advanced Printer Setup",
N_("Fine adjustment to horizontal position for CD printing"),
STP_PARAMETER_TYPE_DIMENSION, STP_PARAMETER_CLASS_FEATURE,
STP_PARAMETER_LEVEL_ADVANCED, 1, 1, STP_CHANNEL_NONE, 1, 0
},
{
"CDAllowOtherMedia", N_("CD Allow Other Media Sizes"), "Color=No,Category=Advanced Printer Setup",
N_("Allow non-CD media sizes when printing to CD"),
STP_PARAMETER_TYPE_BOOLEAN, STP_PARAMETER_CLASS_FEATURE,
STP_PARAMETER_LEVEL_ADVANCED, 1, 1, STP_CHANNEL_NONE, 1, 0
},
{
"Resolution", N_("Resolution"), "Color=Yes,Category=Basic Printer Setup",
N_("Resolution of the print"),
STP_PARAMETER_TYPE_STRING_LIST, STP_PARAMETER_CLASS_FEATURE,
STP_PARAMETER_LEVEL_ADVANCED, 1, 1, STP_CHANNEL_NONE, 1, 0
},
/*
* Don't check this parameter. We may offer different settings for
* different ink sets, but we need to be able to handle settings from PPD
* files that don't have constraints set up.
*/
{
"InkType", N_("Ink Type"), "Color=Yes,Category=Advanced Printer Setup",
N_("Type of ink in the printer"),
STP_PARAMETER_TYPE_STRING_LIST, STP_PARAMETER_CLASS_FEATURE,
STP_PARAMETER_LEVEL_ADVANCED2, 1, 1, STP_CHANNEL_NONE, 0, 0
},
{
"UseGloss", N_("Enhanced Gloss"), "Color=Yes,Category=Basic Printer Setup",
N_("Add gloss enhancement"),
STP_PARAMETER_TYPE_BOOLEAN, STP_PARAMETER_CLASS_FEATURE,
STP_PARAMETER_LEVEL_BASIC, 1, 1, STP_CHANNEL_NONE, 0, 0
},
{
"InkSet", N_("Ink Set"), "Color=Yes,Category=Basic Printer Setup",
N_("Type of ink in the printer"),
STP_PARAMETER_TYPE_STRING_LIST, STP_PARAMETER_CLASS_FEATURE,
STP_PARAMETER_LEVEL_BASIC, 1, 1, STP_CHANNEL_NONE, 1, 0
},
{
"PrintingDirection", N_("Printing Direction"), "Color=Yes,Category=Advanced Output Adjustment",
N_("Printing direction (unidirectional is higher quality, but slower)"),
STP_PARAMETER_TYPE_STRING_LIST, STP_PARAMETER_CLASS_FEATURE,
STP_PARAMETER_LEVEL_ADVANCED1, 1, 1, STP_CHANNEL_NONE, 1, 0
},
{
"FullBleed", N_("Borderless"), "Color=No,Category=Basic Printer Setup",
N_("Print without borders"),
STP_PARAMETER_TYPE_BOOLEAN, STP_PARAMETER_CLASS_FEATURE,
STP_PARAMETER_LEVEL_BASIC, 1, 1, STP_CHANNEL_NONE, 1, 0
},
{
"Weave", N_("Interleave Method"), "Color=Yes,Category=Advanced Output Adjustment",
N_("Interleave pattern to use"),
STP_PARAMETER_TYPE_STRING_LIST, STP_PARAMETER_CLASS_FEATURE,
STP_PARAMETER_LEVEL_ADVANCED1, 1, 1, STP_CHANNEL_NONE, 1, 0
},
{
"OutputOrder", N_("Output Order"), "Color=No,Category=Basic Printer Setup",
N_("Output Order"),
STP_PARAMETER_TYPE_STRING_LIST, STP_PARAMETER_CLASS_FEATURE,
STP_PARAMETER_LEVEL_BASIC, 0, 0, STP_CHANNEL_NONE, 0, 0
},
{
"AlignmentPasses", N_("Alignment Passes"), "Color=No,Category=Advanced Printer Functionality",
N_("Alignment Passes"),
STP_PARAMETER_TYPE_INT, STP_PARAMETER_CLASS_FEATURE,
STP_PARAMETER_LEVEL_INTERNAL, 0, 0, STP_CHANNEL_NONE, 0, 0
},
{
"AlignmentChoices", N_("Alignment Choices"), "Color=No,Category=Advanced Printer Functionality",
N_("Alignment Choices"),
STP_PARAMETER_TYPE_INT, STP_PARAMETER_CLASS_FEATURE,
STP_PARAMETER_LEVEL_INTERNAL, 0, 0, STP_CHANNEL_NONE, 0, 0
},
{
"InkChange", N_("Ink change command"), "Color=No,Category=Advanced Printer Functionality",
N_("Ink change command"),
STP_PARAMETER_TYPE_INT, STP_PARAMETER_CLASS_FEATURE,
STP_PARAMETER_LEVEL_INTERNAL, 0, 0, STP_CHANNEL_NONE, 0, 0
},
{
"AlternateAlignmentPasses", N_("Alternate Alignment Passes"), "Color=No,Category=Advanced Printer Functionality",
N_("Alternate Alignment Passes"),
STP_PARAMETER_TYPE_INT, STP_PARAMETER_CLASS_FEATURE,
STP_PARAMETER_LEVEL_INTERNAL, 0, 0, STP_CHANNEL_NONE, 0, 0
},
{
"AlternateAlignmentChoices", N_("Alternate Alignment Choices"), "Color=No,Category=Advanced Printer Functionality",
N_("Alternate Alignment Choices"),
STP_PARAMETER_TYPE_INT, STP_PARAMETER_CLASS_FEATURE,
STP_PARAMETER_LEVEL_INTERNAL, 0, 0, STP_CHANNEL_NONE, 0, 0
},
{
"SupportsPacketMode", N_("Supports Packet Mode"), "Color=No,Category=Advanced Printer Functionality",
N_("Supports D4 Packet Mode"),
STP_PARAMETER_TYPE_BOOLEAN, STP_PARAMETER_CLASS_FEATURE,
STP_PARAMETER_LEVEL_INTERNAL, 0, 0, STP_CHANNEL_NONE, 0, 0
},
{
"InterchangeableInk", N_("Has Interchangeable Ink Cartridges"), "Color=No,Category=Advanced Printer Functionality",
N_("Has multiple choices of ink cartridges"),
STP_PARAMETER_TYPE_BOOLEAN, STP_PARAMETER_CLASS_FEATURE,
STP_PARAMETER_LEVEL_INTERNAL, 0, 0, STP_CHANNEL_NONE, 0, 0
},
{
"InkChannels", N_("Ink Channels"), "Color=No,Category=Advanced Printer Functionality",
N_("Ink Channels"),
STP_PARAMETER_TYPE_INT, STP_PARAMETER_CLASS_FEATURE,
STP_PARAMETER_LEVEL_INTERNAL, 0, 0, STP_CHANNEL_NONE, 0, 0
},
{
"RawChannelNames", N_("Raw Channel Names"), "Color=No,Category=Advanced Printer Functionality",
N_("Raw Channel Names"),
STP_PARAMETER_TYPE_STRING_LIST, STP_PARAMETER_CLASS_FEATURE,
STP_PARAMETER_LEVEL_INTERNAL, 0, 0, STP_CHANNEL_NONE, 0, 0
},
{
"ChannelNames", N_("Channel Names"), "Color=No,Category=Advanced Printer Functionality",
N_("Channel Names"),
STP_PARAMETER_TYPE_STRING_LIST, STP_PARAMETER_CLASS_FEATURE,
STP_PARAMETER_LEVEL_INTERNAL, 0, 0, STP_CHANNEL_NONE, 0, 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
},
{
"RawChannels", N_("Raw Channels"), "Color=Yes,Category=Core Parameter",
N_("Raw Channel Count"),
STP_PARAMETER_TYPE_STRING_LIST, STP_PARAMETER_CLASS_CORE,
STP_PARAMETER_LEVEL_BASIC, 0, 1, STP_CHANNEL_NONE, 1, 0
},
{
"CyanHueCurve", N_("Cyan Map"), "Color=Yes,Category=Advanced Output Control",
N_("Adjust the cyan map"),
STP_PARAMETER_TYPE_CURVE, STP_PARAMETER_CLASS_OUTPUT,
STP_PARAMETER_LEVEL_ADVANCED4, 0, 1, 1, 1, 0
},
{
"MagentaHueCurve", N_("Magenta Map"), "Color=Yes,Category=Advanced Output Control",
N_("Adjust the magenta map"),
STP_PARAMETER_TYPE_CURVE, STP_PARAMETER_CLASS_OUTPUT,
STP_PARAMETER_LEVEL_ADVANCED4, 0, 1, 2, 1, 0
},
{
"YellowHueCurve", N_("Yellow Map"), "Color=Yes,Category=Advanced Output Control",
N_("Adjust the yellow map"),
STP_PARAMETER_TYPE_CURVE, STP_PARAMETER_CLASS_OUTPUT,
STP_PARAMETER_LEVEL_ADVANCED4, 0, 1, 3, 1, 0
},
{
"BlueHueCurve", N_("Blue Map"), "Color=Yes,Category=Advanced Output Control",
N_("Adjust the blue map"),
STP_PARAMETER_TYPE_CURVE, STP_PARAMETER_CLASS_OUTPUT,
STP_PARAMETER_LEVEL_ADVANCED4, 0, 1, 4, 1, 0
},
{
"OrangeHueCurve", N_("Orange Map"), "Color=Yes,Category=Advanced Output Control",
N_("Adjust the orange map"),
STP_PARAMETER_TYPE_CURVE, STP_PARAMETER_CLASS_OUTPUT,
STP_PARAMETER_LEVEL_ADVANCED4, 0, 1, 4, 1, 0
},
{
"RedHueCurve", N_("Red Map"), "Color=Yes,Category=Advanced Output Control",
N_("Adjust the red map"),
STP_PARAMETER_TYPE_CURVE, STP_PARAMETER_CLASS_OUTPUT,
STP_PARAMETER_LEVEL_ADVANCED4, 0, 1, 5, 1, 0
},
{
"GreenHueCurve", N_("Green Map"), "Color=Yes,Category=Advanced Output Control",
N_("Adjust the green map"),
STP_PARAMETER_TYPE_CURVE, STP_PARAMETER_CLASS_OUTPUT,
STP_PARAMETER_LEVEL_ADVANCED4, 0, 1, 5, 1, 0
},
PARAMETER_INT(max_hres),
PARAMETER_INT(max_vres),
PARAMETER_INT(min_hres),
PARAMETER_INT(min_vres),
PARAMETER_INT(nozzles),
PARAMETER_INT(black_nozzles),
PARAMETER_INT(fast_nozzles),
PARAMETER_INT(min_nozzles),
PARAMETER_INT(min_black_nozzles),
PARAMETER_INT(min_fast_nozzles),
PARAMETER_INT(nozzle_start),
PARAMETER_INT(black_nozzle_start),
PARAMETER_INT(fast_nozzle_start),
PARAMETER_INT(nozzle_separation),
PARAMETER_INT(black_nozzle_separation),
PARAMETER_INT(fast_nozzle_separation),
PARAMETER_INT(separation_rows),
PARAMETER_DIMENSION(max_paper_width),
PARAMETER_DIMENSION(max_paper_height),
PARAMETER_DIMENSION(min_paper_width),
PARAMETER_DIMENSION(min_paper_height),
PARAMETER_DIMENSION(max_imageable_width),
PARAMETER_DIMENSION(max_imageable_height),
PARAMETER_INT(extra_feed),
PARAMETER_INT(pseudo_separation_rows),
PARAMETER_INT(base_separation),
PARAMETER_INT(resolution_scale),
PARAMETER_INT(initial_vertical_offset),
PARAMETER_INT(black_initial_vertical_offset),
PARAMETER_INT(max_black_resolution),
PARAMETER_INT(zero_margin_offset),
PARAMETER_INT(extra_720dpi_separation),
PARAMETER_INT(micro_left_margin),
PARAMETER_INT(min_horizontal_position_alignment),
PARAMETER_INT(base_horizontal_position_alignment),
PARAMETER_INT(bidirectional_upper_limit),
PARAMETER_INT(physical_channels),
PARAMETER_DIMENSION(left_margin),
PARAMETER_DIMENSION(right_margin),
PARAMETER_DIMENSION(top_margin),
PARAMETER_DIMENSION(bottom_margin),
PARAMETER_INT(ink_type),
PARAMETER_INT(bits),
PARAMETER_INT(base_res),
PARAMETER_INT_RO(alignment_passes),
PARAMETER_INT_RO(alignment_choices),
PARAMETER_INT_RO(alternate_alignment_passes),
PARAMETER_INT_RO(alternate_alignment_choices),
PARAMETER_DIMENSION(cd_page_width),
PARAMETER_DIMENSION(cd_page_height),
PARAMETER_DIMENSION(cd_x_offset),
PARAMETER_DIMENSION(cd_y_offset),
PARAMETER_INT(paper_extra_bottom),
PARAMETER_RAW(preinit_sequence),
PARAMETER_RAW(preinit_remote_sequence),
PARAMETER_RAW(postinit_remote_sequence),
PARAMETER_RAW(vertical_borderless_sequence)
};
static const int the_parameter_count =
sizeof(the_parameters) / sizeof(const stp_parameter_t);
static const float_param_t float_parameters[] =
{
{
{
"CyanDensity", N_("Cyan Density"), "Color=Yes,Category=Output Level Adjustment",
N_("Adjust the cyan density"),
STP_PARAMETER_TYPE_DOUBLE, STP_PARAMETER_CLASS_OUTPUT,
STP_PARAMETER_LEVEL_ADVANCED, 0, 1, 1, 1, 0
}, 0.0, 2.0, 1.0, 1
},
{
{
"MagentaDensity", N_("Magenta Density"), "Color=Yes,Category=Output Level Adjustment",
N_("Adjust the magenta density"),
STP_PARAMETER_TYPE_DOUBLE, STP_PARAMETER_CLASS_OUTPUT,
STP_PARAMETER_LEVEL_ADVANCED, 0, 1, 2, 1, 0
}, 0.0, 2.0, 1.0, 1
},
{
{
"YellowDensity", N_("Yellow Density"), "Color=Yes,Category=Output Level Adjustment",
N_("Adjust the yellow density"),
STP_PARAMETER_TYPE_DOUBLE, STP_PARAMETER_CLASS_OUTPUT,
STP_PARAMETER_LEVEL_ADVANCED, 0, 1, 3, 1, 0
}, 0.0, 2.0, 1.0, 1
},
{
{
"BlackDensity", N_("Black Density"), "Color=Yes,Category=Output Level Adjustment",
N_("Adjust the black density"),
STP_PARAMETER_TYPE_DOUBLE, STP_PARAMETER_CLASS_OUTPUT,
STP_PARAMETER_LEVEL_ADVANCED, 0, 1, 0, 1, 0
}, 0.0, 2.0, 1.0, 1
},
{
{
"BlueDensity", N_("Blue Density"), "Color=Yes,Category=Output Level Adjustment",
N_("Adjust the blue density"),
STP_PARAMETER_TYPE_DOUBLE, STP_PARAMETER_CLASS_OUTPUT,
STP_PARAMETER_LEVEL_ADVANCED, 0, 1, 4, 1, 0
}, 0.0, 2.0, 1.0, 1
},
{
{
"OrangeDensity", N_("Orange Density"), "Color=Yes,Category=Output Level Adjustment",
N_("Adjust the orange density"),
STP_PARAMETER_TYPE_DOUBLE, STP_PARAMETER_CLASS_OUTPUT,
STP_PARAMETER_LEVEL_ADVANCED, 0, 1, 4, 1, 0
}, 0.0, 2.0, 1.0, 1
},
{
{
"RedDensity", N_("Red Density"), "Color=Yes,Category=Output Level Adjustment",
N_("Adjust the red density"),
STP_PARAMETER_TYPE_DOUBLE, STP_PARAMETER_CLASS_OUTPUT,
STP_PARAMETER_LEVEL_ADVANCED, 0, 1, 5, 1, 0
}, 0.0, 2.0, 1.0, 1
},
{
{
"GreenDensity", N_("Green Density"), "Color=Yes,Category=Output Level Adjustment",
N_("Adjust the green density"),
STP_PARAMETER_TYPE_DOUBLE, STP_PARAMETER_CLASS_OUTPUT,
STP_PARAMETER_LEVEL_ADVANCED, 0, 1, 5, 1, 0
}, 0.0, 2.0, 1.0, 1
},
{
{
"GlossLimit", N_("Gloss Level"), "Color=Yes,Category=Output Level Adjustment",
N_("Adjust the gloss level"),
STP_PARAMETER_TYPE_DOUBLE, STP_PARAMETER_CLASS_OUTPUT,
STP_PARAMETER_LEVEL_ADVANCED, 0, 1, 6, 1, 0
}, 0.0, 2.0, 1.0, 1
},
{
{
"DropSize1", N_("Drop Size Small"), "Color=Yes,Category=Advanced Ink Adjustment",
N_("Drop Size 1 (small)"),
STP_PARAMETER_TYPE_DOUBLE, STP_PARAMETER_CLASS_OUTPUT,
STP_PARAMETER_LEVEL_ADVANCED4, 0, 1, STP_CHANNEL_NONE, 1, 0
}, 0.0, 1.0, 1.0, 1
},
{
{
"DropSize2", N_("Drop Size Medium"), "Color=Yes,Category=Advanced Ink Adjustment",
N_("Drop Size 2 (medium)"),
STP_PARAMETER_TYPE_DOUBLE, STP_PARAMETER_CLASS_OUTPUT,
STP_PARAMETER_LEVEL_ADVANCED4, 0, 1, STP_CHANNEL_NONE, 1, 0
}, 0.0, 1.0, 0.0, 1
},
{
{
"DropSize3", N_("Drop Size Large"), "Color=Yes,Category=Advanced Ink Adjustment",
N_("Drop Size 3 (large)"),
STP_PARAMETER_TYPE_DOUBLE, STP_PARAMETER_CLASS_OUTPUT,
STP_PARAMETER_LEVEL_ADVANCED4, 0, 1, STP_CHANNEL_NONE, 1, 0
}, 0.0, 1.0, 0.0, 1
},
{
{
"LightCyanValue", N_("Light Cyan Value"), "Color=Yes,Category=Advanced Ink Adjustment",
N_("Light Cyan Value"),
STP_PARAMETER_TYPE_DOUBLE, STP_PARAMETER_CLASS_OUTPUT,
STP_PARAMETER_LEVEL_ADVANCED4, 0, 1, STP_CHANNEL_NONE, 1, 0
}, 0.0, 5.0, 1.0, 1
},
{
{
"LightCyanTrans", N_("Light Cyan Transition"), "Color=Yes,Category=Advanced Ink Adjustment",
N_("Light Cyan Transition"),
STP_PARAMETER_TYPE_DOUBLE, STP_PARAMETER_CLASS_OUTPUT,
STP_PARAMETER_LEVEL_ADVANCED4, 0, 1, STP_CHANNEL_NONE, 1, 0
}, 0.0, 5.0, 1.0, 1
},
{
{
"LightCyanScale", N_("Light Cyan Density Scale"), "Color=Yes,Category=Advanced Ink Adjustment",
N_("Light Cyan Density Scale"),
STP_PARAMETER_TYPE_DOUBLE, STP_PARAMETER_CLASS_OUTPUT,
STP_PARAMETER_LEVEL_ADVANCED4, 0, 1, STP_CHANNEL_NONE, 1, 0
}, 0.0, 5.0, 1.0, 1
},
{
{
"LightMagentaValue", N_("Light Magenta Value"), "Color=Yes,Category=Advanced Ink Adjustment",
N_("Light Magenta Value"),
STP_PARAMETER_TYPE_DOUBLE, STP_PARAMETER_CLASS_OUTPUT,
STP_PARAMETER_LEVEL_ADVANCED4, 0, 1, STP_CHANNEL_NONE, 1, 0
}, 0.0, 5.0, 1.0, 1
},
{
{
"LightMagentaScale", N_("Light Magenta Density Scale"), "Color=Yes,Category=Advanced Ink Adjustment",
N_("Light Magenta Density Scale"),
STP_PARAMETER_TYPE_DOUBLE, STP_PARAMETER_CLASS_OUTPUT,
STP_PARAMETER_LEVEL_ADVANCED4, 0, 1, STP_CHANNEL_NONE, 1, 0
}, 0.0, 5.0, 1.0, 1
},
{
{
"LightMagentaTrans", N_("Light Magenta Transition"), "Color=Yes,Category=Advanced Ink Adjustment",
N_("Light Magenta Transition"),
STP_PARAMETER_TYPE_DOUBLE, STP_PARAMETER_CLASS_OUTPUT,
STP_PARAMETER_LEVEL_ADVANCED4, 0, 1, STP_CHANNEL_NONE, 1, 0
}, 0.0, 5.0, 1.0, 1
},
{
{
"DarkYellowValue", N_("Dark Yellow Value"), "Color=Yes,Category=Advanced Ink Adjustment",
N_("Dark Yellow Value"),
STP_PARAMETER_TYPE_DOUBLE, STP_PARAMETER_CLASS_OUTPUT,
STP_PARAMETER_LEVEL_ADVANCED4, 0, 1, STP_CHANNEL_NONE, 1, 0
}, 0.0, 5.0, 1.0, 1
},
{
{
"DarkYellowTrans", N_("Dark Yellow Transition"), "Color=Yes,Category=Advanced Ink Adjustment",
N_("Dark Yellow Transition"),
STP_PARAMETER_TYPE_DOUBLE, STP_PARAMETER_CLASS_OUTPUT,
STP_PARAMETER_LEVEL_ADVANCED4, 0, 1, STP_CHANNEL_NONE, 1, 0
}, 0.0, 5.0, 1.0, 1
},
{
{
"DarkYellowScale", N_("Dark Yellow Density Scale"), "Color=Yes,Category=Advanced Ink Adjustment",
N_("Dark Yellow Density Scale"),
STP_PARAMETER_TYPE_DOUBLE, STP_PARAMETER_CLASS_OUTPUT,
STP_PARAMETER_LEVEL_ADVANCED4, 0, 1, STP_CHANNEL_NONE, 1, 0
}, 0.0, 5.0, 1.0, 1
},
{
{
"GrayValue", N_("Gray Value"), "Color=Yes,Category=Advanced Ink Adjustment",
N_("Gray Value"),
STP_PARAMETER_TYPE_DOUBLE, STP_PARAMETER_CLASS_OUTPUT,
STP_PARAMETER_LEVEL_ADVANCED4, 0, 1, STP_CHANNEL_NONE, 1, 0
}, 0.0, 5.0, 1.0, 1
},
{
{
"GrayTrans", N_("Gray Transition"), "Color=Yes,Category=Advanced Ink Adjustment",
N_("Gray Transition"),
STP_PARAMETER_TYPE_DOUBLE, STP_PARAMETER_CLASS_OUTPUT,
STP_PARAMETER_LEVEL_ADVANCED4, 0, 1, STP_CHANNEL_NONE, 1, 0
}, 0.0, 5.0, 1.0, 1
},
{
{
"GrayScale", N_("Gray Density Scale"), "Color=Yes,Category=Advanced Ink Adjustment",
N_("Gray Density Scale"),
STP_PARAMETER_TYPE_DOUBLE, STP_PARAMETER_CLASS_OUTPUT,
STP_PARAMETER_LEVEL_ADVANCED4, 0, 1, STP_CHANNEL_NONE, 1, 0
}, 0.0, 5.0, 1.0, 1
},
{
{
"DarkGrayValue", N_("Gray Value"), "Color=Yes,Category=Advanced Ink Adjustment",
N_("Gray Value"),
STP_PARAMETER_TYPE_DOUBLE, STP_PARAMETER_CLASS_OUTPUT,
STP_PARAMETER_LEVEL_ADVANCED4, 0, 1, STP_CHANNEL_NONE, 1, 0
}, 0.0, 5.0, 1.0, 1
},
{
{
"DarkGrayTrans", N_("Gray Transition"), "Color=Yes,Category=Advanced Ink Adjustment",
N_("Gray Transition"),
STP_PARAMETER_TYPE_DOUBLE, STP_PARAMETER_CLASS_OUTPUT,
STP_PARAMETER_LEVEL_ADVANCED4, 0, 1, STP_CHANNEL_NONE, 1, 0
}, 0.0, 5.0, 1.0, 1
},
{
{
"DarkGrayScale", N_("Gray Density Scale"), "Color=Yes,Category=Advanced Ink Adjustment",
N_("Gray Density Scale"),
STP_PARAMETER_TYPE_DOUBLE, STP_PARAMETER_CLASS_OUTPUT,
STP_PARAMETER_LEVEL_ADVANCED4, 0, 1, STP_CHANNEL_NONE, 1, 0
}, 0.0, 5.0, 1.0, 1
},
{
{
"LightGrayValue", N_("Light Gray Value"), "Color=Yes,Category=Advanced Ink Adjustment",
N_("Light Gray Value"),
STP_PARAMETER_TYPE_DOUBLE, STP_PARAMETER_CLASS_OUTPUT,
STP_PARAMETER_LEVEL_ADVANCED4, 0, 1, STP_CHANNEL_NONE, 1, 0
}, 0.0, 5.0, 1.0, 1
},
{
{
"LightGrayTrans", N_("Light Gray Transition"), "Color=Yes,Category=Advanced Ink Adjustment",
N_("Light Gray Transition"),
STP_PARAMETER_TYPE_DOUBLE, STP_PARAMETER_CLASS_OUTPUT,
STP_PARAMETER_LEVEL_ADVANCED4, 0, 1, STP_CHANNEL_NONE, 1, 0
}, 0.0, 5.0, 1.0, 1
},
{
{
"LightGrayScale", N_("Light Gray Density Scale"), "Color=Yes,Category=Advanced Ink Adjustment",
N_("Light Gray Density Scale"),
STP_PARAMETER_TYPE_DOUBLE, STP_PARAMETER_CLASS_OUTPUT,
STP_PARAMETER_LEVEL_ADVANCED4, 0, 1, STP_CHANNEL_NONE, 1, 0
}, 0.0, 5.0, 1.0, 1
},
{
{
"Gray3Value", N_("Dark Gray Value"), "Color=Yes,Category=Advanced Ink Adjustment",
N_("Dark Gray Value"),
STP_PARAMETER_TYPE_DOUBLE, STP_PARAMETER_CLASS_OUTPUT,
STP_PARAMETER_LEVEL_ADVANCED4, 0, 1, STP_CHANNEL_NONE, 1, 0
}, 0.0, 5.0, 1.0, 1
},
{
{
"Gray3Trans", N_("Dark Gray Transition"), "Color=Yes,Category=Advanced Ink Adjustment",
N_("Dark Gray Transition"),
STP_PARAMETER_TYPE_DOUBLE, STP_PARAMETER_CLASS_OUTPUT,
STP_PARAMETER_LEVEL_ADVANCED4, 0, 1, STP_CHANNEL_NONE, 1, 0
}, 0.0, 5.0, 1.0, 1
},
{
{
"Gray3Scale", N_("Dark Gray Density Scale"), "Color=Yes,Category=Advanced Ink Adjustment",
N_("Dark Gray Density Scale"),
STP_PARAMETER_TYPE_DOUBLE, STP_PARAMETER_CLASS_OUTPUT,
STP_PARAMETER_LEVEL_ADVANCED4, 0, 1, STP_CHANNEL_NONE, 1, 0
}, 0.0, 5.0, 1.0, 1
},
{
{
"Gray2Value", N_("Mid Gray Value"), "Color=Yes,Category=Advanced Ink Adjustment",
N_("Medium Gray Value"),
STP_PARAMETER_TYPE_DOUBLE, STP_PARAMETER_CLASS_OUTPUT,
STP_PARAMETER_LEVEL_ADVANCED4, 0, 1, STP_CHANNEL_NONE, 1, 0
}, 0.0, 5.0, 1.0, 1
},
{
{
"Gray2Trans", N_("Mid Gray Transition"), "Color=Yes,Category=Advanced Ink Adjustment",
N_("Medium Gray Transition"),
STP_PARAMETER_TYPE_DOUBLE, STP_PARAMETER_CLASS_OUTPUT,
STP_PARAMETER_LEVEL_ADVANCED4, 0, 1, STP_CHANNEL_NONE, 1, 0
}, 0.0, 5.0, 1.0, 1
},
{
{
"Gray2Scale", N_("Mid Gray Density Scale"), "Color=Yes,Category=Advanced Ink Adjustment",
N_("Medium Gray Density Scale"),
STP_PARAMETER_TYPE_DOUBLE, STP_PARAMETER_CLASS_OUTPUT,
STP_PARAMETER_LEVEL_ADVANCED4, 0, 1, STP_CHANNEL_NONE, 1, 0
}, 0.0, 5.0, 1.0, 1
},
{
{
"Gray1Value", N_("Light Gray Value"), "Color=Yes,Category=Advanced Ink Adjustment",
N_("Light Gray Value"),
STP_PARAMETER_TYPE_DOUBLE, STP_PARAMETER_CLASS_OUTPUT,
STP_PARAMETER_LEVEL_ADVANCED4, 0, 1, STP_CHANNEL_NONE, 1, 0
}, 0.0, 5.0, 1.0, 1
},
{
{
"Gray1Trans", N_("Light Gray Transition"), "Color=Yes,Category=Advanced Ink Adjustment",
N_("Light Gray Transition"),
STP_PARAMETER_TYPE_DOUBLE, STP_PARAMETER_CLASS_OUTPUT,
STP_PARAMETER_LEVEL_ADVANCED4, 0, 1, STP_CHANNEL_NONE, 1, 0
}, 0.0, 5.0, 1.0, 1
},
{
{
"Gray1Scale", N_("Light Gray Density Scale"), "Color=Yes,Category=Advanced Ink Adjustment",
N_("Light Gray Density Scale"),
STP_PARAMETER_TYPE_DOUBLE, STP_PARAMETER_CLASS_OUTPUT,
STP_PARAMETER_LEVEL_ADVANCED4, 0, 1, STP_CHANNEL_NONE, 1, 0
}, 0.0, 5.0, 1.0, 1
},
{
{
"HGray5Value", N_("Hextone Gray 5 Value"), "Color=Yes,Category=Advanced Ink Adjustment",
N_("Hextone Gray 5 (Darkest) Value"),
STP_PARAMETER_TYPE_DOUBLE, STP_PARAMETER_CLASS_OUTPUT,
STP_PARAMETER_LEVEL_ADVANCED4, 0, 1, STP_CHANNEL_NONE, 1, 0
}, 0.0, 5.0, 1.0, 1
},
{
{
"HGray5Trans", N_("Hextone Gray 5 Transition"), "Color=Yes,Category=Advanced Ink Adjustment",
N_("Hextone Gray 5 (Darkest) Transition"),
STP_PARAMETER_TYPE_DOUBLE, STP_PARAMETER_CLASS_OUTPUT,
STP_PARAMETER_LEVEL_ADVANCED4, 0, 1, STP_CHANNEL_NONE, 1, 0
}, 0.0, 5.0, 1.0, 1
},
{
{
"HGray5Scale", N_("Hextone Gray 5 Density Scale"), "Color=Yes,Category=Advanced Ink Adjustment",
N_("Hextone Gray 5 (Darkest) Density Scale"),
STP_PARAMETER_TYPE_DOUBLE, STP_PARAMETER_CLASS_OUTPUT,
STP_PARAMETER_LEVEL_ADVANCED4, 0, 1, STP_CHANNEL_NONE, 1, 0
}, 0.0, 5.0, 1.0, 1
},
{
{
"HGray4Value", N_("Hextone Gray 4 Value"), "Color=Yes,Category=Advanced Ink Adjustment",
N_("Hextone Gray 4 Value"),
STP_PARAMETER_TYPE_DOUBLE, STP_PARAMETER_CLASS_OUTPUT,
STP_PARAMETER_LEVEL_ADVANCED4, 0, 1, STP_CHANNEL_NONE, 1, 0
}, 0.0, 5.0, 1.0, 1
},
{
{
"HGray4Trans", N_("Hextone Gray 4 Transition"), "Color=Yes,Category=Advanced Ink Adjustment",
N_("Hextone Gray 4 Transition"),
STP_PARAMETER_TYPE_DOUBLE, STP_PARAMETER_CLASS_OUTPUT,
STP_PARAMETER_LEVEL_ADVANCED4, 0, 1, STP_CHANNEL_NONE, 1, 0
}, 0.0, 5.0, 1.0, 1
},
{
{
"HGray4Scale", N_("Hextone Gray 4 Density Scale"), "Color=Yes,Category=Advanced Ink Adjustment",
N_("Hextone Gray 4 Density Scale"),
STP_PARAMETER_TYPE_DOUBLE, STP_PARAMETER_CLASS_OUTPUT,
STP_PARAMETER_LEVEL_ADVANCED4, 0, 1, STP_CHANNEL_NONE, 1, 0
}, 0.0, 5.0, 1.0, 1
},
{
{
"HGray3Value", N_("Hextone Gray 3 Value"), "Color=Yes,Category=Advanced Ink Adjustment",
N_("Hextone Gray 3 Value"),
STP_PARAMETER_TYPE_DOUBLE, STP_PARAMETER_CLASS_OUTPUT,
STP_PARAMETER_LEVEL_ADVANCED4, 0, 1, STP_CHANNEL_NONE, 1, 0
}, 0.0, 5.0, 1.0, 1
},
{
{
"HGray3Trans", N_("Hextone Gray 3 Transition"), "Color=Yes,Category=Advanced Ink Adjustment",
N_("Hextone Gray 3 Transition"),
STP_PARAMETER_TYPE_DOUBLE, STP_PARAMETER_CLASS_OUTPUT,
STP_PARAMETER_LEVEL_ADVANCED4, 0, 1, STP_CHANNEL_NONE, 1, 0
}, 0.0, 5.0, 1.0, 1
},
{
{
"HGray3Scale", N_("Hextone Gray 3 Density Scale"), "Color=Yes,Category=Advanced Ink Adjustment",
N_("Hextone Gray 3 Density Scale"),
STP_PARAMETER_TYPE_DOUBLE, STP_PARAMETER_CLASS_OUTPUT,
STP_PARAMETER_LEVEL_ADVANCED4, 0, 1, STP_CHANNEL_NONE, 1, 0
}, 0.0, 5.0, 1.0, 1
},
{
{
"HGray2Value", N_("Hextone Gray 2 Value"), "Color=Yes,Category=Advanced Ink Adjustment",
N_("Hextone Gray 2 Value"),
STP_PARAMETER_TYPE_DOUBLE, STP_PARAMETER_CLASS_OUTPUT,
STP_PARAMETER_LEVEL_ADVANCED4, 0, 1, STP_CHANNEL_NONE, 1, 0
}, 0.0, 5.0, 1.0, 1
},
{
{
"HGray2Trans", N_("Hextone Gray 2 Transition"), "Color=Yes,Category=Advanced Ink Adjustment",
N_("Hextone Gray 2 Transition"),
STP_PARAMETER_TYPE_DOUBLE, STP_PARAMETER_CLASS_OUTPUT,
STP_PARAMETER_LEVEL_ADVANCED4, 0, 1, STP_CHANNEL_NONE, 1, 0
}, 0.0, 5.0, 1.0, 1
},
{
{
"HGray2Scale", N_("Hextone Gray 2 Density Scale"), "Color=Yes,Category=Advanced Ink Adjustment",
N_("Hextone Gray 2 Density Scale"),
STP_PARAMETER_TYPE_DOUBLE, STP_PARAMETER_CLASS_OUTPUT,
STP_PARAMETER_LEVEL_ADVANCED4, 0, 1, STP_CHANNEL_NONE, 1, 0
}, 0.0, 5.0, 1.0, 1
},
{
{
"HGray1Value", N_("Hextone Gray 1 Value"), "Color=Yes,Category=Advanced Ink Adjustment",
N_("Hextone Gray 1 (Lightest) Value"),
STP_PARAMETER_TYPE_DOUBLE, STP_PARAMETER_CLASS_OUTPUT,
STP_PARAMETER_LEVEL_ADVANCED4, 0, 1, STP_CHANNEL_NONE, 1, 0
}, 0.0, 5.0, 1.0, 1
},
{
{
"HGray1Trans", N_("Hextone Gray 1 Transition"), "Color=Yes,Category=Advanced Ink Adjustment",
N_("Hextone Gray 1 (Lightest) Transition"),
STP_PARAMETER_TYPE_DOUBLE, STP_PARAMETER_CLASS_OUTPUT,
STP_PARAMETER_LEVEL_ADVANCED4, 0, 1, STP_CHANNEL_NONE, 1, 0
}, 0.0, 5.0, 1.0, 1
},
{
{
"HGray1Scale", N_("Hextone Gray 1 Density Scale"), "Color=Yes,Category=Advanced Ink Adjustment",
N_("Hextone Gray 1 (Lightest) Density Scale"),
STP_PARAMETER_TYPE_DOUBLE, STP_PARAMETER_CLASS_OUTPUT,
STP_PARAMETER_LEVEL_ADVANCED4, 0, 1, STP_CHANNEL_NONE, 1, 0
}, 0.0, 5.0, 1.0, 1
},
{
{
"BlackTrans", N_("GCR Transition"), "Color=Yes,Category=Advanced Output Control",
N_("Adjust the gray component transition rate"),
STP_PARAMETER_TYPE_DOUBLE, STP_PARAMETER_CLASS_OUTPUT,
STP_PARAMETER_LEVEL_ADVANCED4, 0, 1, 0, 1, 0
}, 0.0, 1.0, 1.0, 1
},
{
{
"GCRLower", N_("GCR Lower Bound"), "Color=Yes,Category=Advanced Output Control",
N_("Lower bound of gray component reduction"),
STP_PARAMETER_TYPE_DOUBLE, STP_PARAMETER_CLASS_OUTPUT,
STP_PARAMETER_LEVEL_ADVANCED4, 0, 1, 0, 1, 0
}, 0.0, 1.0, 0.2, 1
},
{
{
"GCRUpper", N_("GCR Upper Bound"), "Color=Yes,Category=Advanced Output Control",
N_("Upper bound of gray component reduction"),
STP_PARAMETER_TYPE_DOUBLE, STP_PARAMETER_CLASS_OUTPUT,
STP_PARAMETER_LEVEL_ADVANCED4, 0, 1, 0, 1, 0
}, 0.0, 5.0, 0.5, 1
},
{
{
"SubchannelCutoff", N_("Subchannel Cutoff"), "Color=Yes,Category=Advanced Output Control",
N_("Upper limit for using light ink"),
STP_PARAMETER_TYPE_DOUBLE, STP_PARAMETER_CLASS_OUTPUT,
STP_PARAMETER_LEVEL_ADVANCED4, 0, 1, 0, 1, 0
}, 0.0, 1.0, 1.0, 1
},
{
{
"PageDryTime", N_("Drying Time Per Page"), "Color=No,Category=Advanced Printer Functionality",
N_("Set drying time per page"),
STP_PARAMETER_TYPE_DOUBLE, STP_PARAMETER_CLASS_FEATURE,
STP_PARAMETER_LEVEL_ADVANCED3, 0, 1, STP_CHANNEL_NONE, 1, 0
}, 0, 60.0, 0.0, 1
},
{
{
"ScanDryTime", N_("Drying Time Per Scan"), "Color=No,Category=Advanced Printer Functionality",
N_("Set drying time per scan"),
STP_PARAMETER_TYPE_DOUBLE, STP_PARAMETER_CLASS_FEATURE,
STP_PARAMETER_LEVEL_ADVANCED3, 0, 1, STP_CHANNEL_NONE, 1, 0
}, 0, 10.0, 0.0, 1
},
{
{
"ScanMinDryTime", N_("Minimum Drying Time Per Scan"), "Color=No,Category=Advanced Printer Functionality",
N_("Set minimum drying time per scan"),
STP_PARAMETER_TYPE_DOUBLE, STP_PARAMETER_CLASS_FEATURE,
STP_PARAMETER_LEVEL_ADVANCED3, 0, 1, STP_CHANNEL_NONE, 1, 0
}, 0, 10.0, 0.0, 1
},
};
static const int float_parameter_count =
sizeof(float_parameters) / sizeof(const float_param_t);
static const int_param_t int_parameters[] =
{
{
{
"BandEnhancement", N_("Quality Enhancement"), "Color=No,Category=Advanced Printer Functionality",
N_("Enhance print quality by additional passes"),
STP_PARAMETER_TYPE_INT, STP_PARAMETER_CLASS_FEATURE,
STP_PARAMETER_LEVEL_ADVANCED2, 0, 1, STP_CHANNEL_NONE, 1, 0
}, 0, 4, 0
},
{
{
"PaperThickness", N_("Paper Thickness"), "Color=No,Category=Advanced Printer Functionality",
N_("Set printer paper thickness"),
STP_PARAMETER_TYPE_INT, STP_PARAMETER_CLASS_FEATURE,
STP_PARAMETER_LEVEL_ADVANCED3, 0, 1, STP_CHANNEL_NONE, 1, 0
}, 0, 255, 0
},
{
{
"VacuumIntensity", N_("Vacuum Intensity"), "Color=No,Category=Advanced Printer Functionality",
N_("Set vacuum intensity (printer-specific)"),
STP_PARAMETER_TYPE_INT, STP_PARAMETER_CLASS_FEATURE,
STP_PARAMETER_LEVEL_ADVANCED3, 0, 1, STP_CHANNEL_NONE, 1, 0
}, 0, 255, 0
},
{
{
"FeedSequence", N_("Feed Sequence"), "Color=No,Category=Advanced Printer Functionality",
N_("Set paper feed sequence (printer-specific)"),
STP_PARAMETER_TYPE_INT, STP_PARAMETER_CLASS_FEATURE,
STP_PARAMETER_LEVEL_ADVANCED3, 0, 1, STP_CHANNEL_NONE, 1, 0
}, 0, 255, 0
},
{
{
"PrintMethod", N_("Print Method"), "Color=No,Category=Advanced Printer Functionality",
N_("Set print method (printer-specific)"),
STP_PARAMETER_TYPE_INT, STP_PARAMETER_CLASS_FEATURE,
STP_PARAMETER_LEVEL_ADVANCED3, 0, 1, STP_CHANNEL_NONE, 1, 0
}, 0, 255, 0
},
{
{
"PlatenGap", N_("Platen Gap"), "Color=No,Category=Advanced Printer Functionality",
N_("Set platen gap (printer-specific)"),
STP_PARAMETER_TYPE_INT, STP_PARAMETER_CLASS_FEATURE,
STP_PARAMETER_LEVEL_ADVANCED3, 0, 1, STP_CHANNEL_NONE, 1, 0
}, 0, 255, 0
},
{
{
"FeedAdjustment", N_("Feed Adjustment"), "Color=No,Category=Advanced Printer Functionality",
/* xgettext:no-c-format */
N_("Set paper feed adjustment (0.01% units)"),
STP_PARAMETER_TYPE_INT, STP_PARAMETER_CLASS_FEATURE,
STP_PARAMETER_LEVEL_ADVANCED3, 0, 1, STP_CHANNEL_NONE, 1, 0
}, 0, 255, 0
},
};
static const int int_parameter_count =
sizeof(int_parameters) / sizeof(const int_param_t);
static escp2_privdata_t *
get_privdata(stp_vars_t *v)
{
return (escp2_privdata_t *) stp_get_component_data(v, "Driver");
}
#define DEF_SIMPLE_ACCESSOR(f, t) \
static t \
escp2_##f(const stp_vars_t *v) \
{ \
if (stp_check_int_parameter(v, "escp2_" #f, STP_PARAMETER_ACTIVE)) \
return stp_get_int_parameter(v, "escp2_" #f); \
else \
{ \
stpi_escp2_printer_t *printdef = stpi_escp2_get_printer(v); \
return printdef->f; \
} \
}
#define DEF_DIMENSION_ACCESSOR(f) \
static stp_dimension_t \
escp2_##f(const stp_vars_t *v) \
{ \
if (stp_check_dimension_parameter(v, "escp2_" #f, STP_PARAMETER_ACTIVE)) \
return stp_get_dimension_parameter(v, "escp2_" #f); \
else \
{ \
stpi_escp2_printer_t *printdef = stpi_escp2_get_printer(v); \
return (stp_dimension_t) printdef->f; \
} \
}
#define DEF_RAW_ACCESSOR(f, t) \
static t \
escp2_##f(const stp_vars_t *v) \
{ \
if (stp_check_raw_parameter(v, "escp2_" #f, STP_PARAMETER_ACTIVE)) \
return stp_get_raw_parameter(v, "escp2_" #f); \
else \
{ \
stpi_escp2_printer_t *printdef = stpi_escp2_get_printer(v); \
return printdef->f; \
} \
}
#define DEF_ROLL_ACCESSOR(f) \
static stp_dimension_t \
escp2_##f(const stp_vars_t *v, int rollfeed) \
{ \
if (stp_check_dimension_parameter(v, "escp2_" #f, STP_PARAMETER_ACTIVE)) \
return stp_get_dimension_parameter(v, "escp2_" #f); \
else \
{ \
stpi_escp2_printer_t *printdef = stpi_escp2_get_printer(v); \
const res_t *res = stpi_escp2_find_resolution(v); \
if (res && res->command) \
{ \
if (rollfeed) \
return (printdef->m_roll_##f); \
else \
return (printdef->m_##f); \
} \
else \
{ \
if (rollfeed) \
return (printdef->roll_##f); \
else \
return (printdef->f); \
} \
} \
}
DEF_SIMPLE_ACCESSOR(max_hres, int)
DEF_SIMPLE_ACCESSOR(max_vres, int)
DEF_SIMPLE_ACCESSOR(min_hres, int)
DEF_SIMPLE_ACCESSOR(min_vres, int)
DEF_SIMPLE_ACCESSOR(nozzles, unsigned)
DEF_SIMPLE_ACCESSOR(black_nozzles, unsigned)
DEF_SIMPLE_ACCESSOR(fast_nozzles, unsigned)
DEF_SIMPLE_ACCESSOR(min_nozzles, unsigned)
DEF_SIMPLE_ACCESSOR(min_black_nozzles, unsigned)
DEF_SIMPLE_ACCESSOR(min_fast_nozzles, unsigned)
DEF_SIMPLE_ACCESSOR(nozzle_start, int)
DEF_SIMPLE_ACCESSOR(black_nozzle_start, int)
DEF_SIMPLE_ACCESSOR(fast_nozzle_start, int)
DEF_SIMPLE_ACCESSOR(nozzle_separation, unsigned)
DEF_SIMPLE_ACCESSOR(black_nozzle_separation, unsigned)
DEF_SIMPLE_ACCESSOR(fast_nozzle_separation, unsigned)
DEF_SIMPLE_ACCESSOR(separation_rows, unsigned)
DEF_SIMPLE_ACCESSOR(paper_extra_bottom, int)
DEF_SIMPLE_ACCESSOR(extra_feed, unsigned)
DEF_SIMPLE_ACCESSOR(pseudo_separation_rows, int)
DEF_SIMPLE_ACCESSOR(base_separation, int)
DEF_SIMPLE_ACCESSOR(resolution_scale, int)
DEF_SIMPLE_ACCESSOR(initial_vertical_offset, int)
DEF_SIMPLE_ACCESSOR(black_initial_vertical_offset, int)
DEF_SIMPLE_ACCESSOR(max_black_resolution, int)
DEF_SIMPLE_ACCESSOR(zero_margin_offset, int)
DEF_SIMPLE_ACCESSOR(extra_720dpi_separation, int)
DEF_SIMPLE_ACCESSOR(micro_left_margin, int)
DEF_SIMPLE_ACCESSOR(min_horizontal_position_alignment, unsigned)
DEF_SIMPLE_ACCESSOR(base_horizontal_position_alignment, unsigned)
DEF_SIMPLE_ACCESSOR(bidirectional_upper_limit, int)
DEF_SIMPLE_ACCESSOR(physical_channels, int)
DEF_SIMPLE_ACCESSOR(alignment_passes, int)
DEF_SIMPLE_ACCESSOR(alignment_choices, int)
DEF_SIMPLE_ACCESSOR(alternate_alignment_passes, int)
DEF_SIMPLE_ACCESSOR(alternate_alignment_choices, int)
DEF_DIMENSION_ACCESSOR(max_paper_width)
DEF_DIMENSION_ACCESSOR(max_paper_height)
DEF_DIMENSION_ACCESSOR(min_paper_width)
DEF_DIMENSION_ACCESSOR(min_paper_height)
DEF_DIMENSION_ACCESSOR(max_imageable_width)
DEF_DIMENSION_ACCESSOR(max_imageable_height)
DEF_DIMENSION_ACCESSOR(cd_page_width)
DEF_DIMENSION_ACCESSOR(cd_page_height)
DEF_DIMENSION_ACCESSOR(cd_x_offset)
DEF_DIMENSION_ACCESSOR(cd_y_offset)
DEF_ROLL_ACCESSOR(left_margin)
DEF_ROLL_ACCESSOR(right_margin)
DEF_ROLL_ACCESSOR(top_margin)
DEF_ROLL_ACCESSOR(bottom_margin)
DEF_RAW_ACCESSOR(preinit_sequence, const stp_raw_t *)
DEF_RAW_ACCESSOR(preinit_remote_sequence, const stp_raw_t *)
DEF_RAW_ACCESSOR(postinit_remote_sequence, const stp_raw_t *)
DEF_RAW_ACCESSOR(vertical_borderless_sequence, const stp_raw_t *)
/* froundto( 500.5 points, 180 dpi, 72 points/inch) */
static double
froundto(double value, double numerator, double denominator)
{
double multiplier = (double) ((int) ((numerator + (denominator / 2)) / denominator));
return ((double) ((int) ((value * multiplier) + .5))) / multiplier;
}
static const resolution_list_t *
escp2_reslist(const stp_vars_t *v)
{
stpi_escp2_printer_t *printdef = stpi_escp2_get_printer(v);
return printdef->resolutions;
}
static inline const printer_weave_list_t *
escp2_printer_weaves(const stp_vars_t *v)
{
stpi_escp2_printer_t *printdef = stpi_escp2_get_printer(v);
return printdef->printer_weaves;
}
static inline const stp_string_list_t *
escp2_channel_names(const stp_vars_t *v)
{
stpi_escp2_printer_t *printdef = stpi_escp2_get_printer(v);
return (printdef->channel_names);
}
static inline const inkgroup_t *
escp2_inkgroup(const stp_vars_t *v)
{
stpi_escp2_printer_t *printdef = stpi_escp2_get_printer(v);
return (printdef->inkgroup);
}
static inline const quality_list_t *
escp2_quality_list(const stp_vars_t *v)
{
stpi_escp2_printer_t *printdef = stpi_escp2_get_printer(v);
return printdef->quality_list;
}
static short
escp2_duplex_left_margin(const stp_vars_t *v)
{
stpi_escp2_printer_t *printdef = stpi_escp2_get_printer(v);
return printdef->duplex_left_margin;
}
static short
escp2_duplex_right_margin(const stp_vars_t *v)
{
stpi_escp2_printer_t *printdef = stpi_escp2_get_printer(v);
return printdef->duplex_right_margin;
}
static short
escp2_duplex_top_margin(const stp_vars_t *v)
{
stpi_escp2_printer_t *printdef = stpi_escp2_get_printer(v);
return printdef->duplex_top_margin;
}
static short
escp2_duplex_bottom_margin(const stp_vars_t *v)
{
stpi_escp2_printer_t *printdef = stpi_escp2_get_printer(v);
return printdef->duplex_bottom_margin;
}
static const channel_count_t *
get_channel_count_by_name(const char *name)
{
int i;
for (i = 0; i < escp2_channel_counts_count; i++)
if (strcmp(name, escp2_channel_counts[i].name) == 0)
return &(escp2_channel_counts[i]);
return NULL;
}
static const channel_count_t *
get_channel_count_by_number(unsigned count)
{
int i;
for (i = 0; i < escp2_channel_counts_count; i++)
if (count == escp2_channel_counts[i].count)
return &(escp2_channel_counts[i]);
return NULL;
}
static int
escp2_res_param(const stp_vars_t *v, const char *param, const res_t *res)
{
if (res)
{
if (res->v &&
stp_check_int_parameter(res->v, param, STP_PARAMETER_ACTIVE))
return stp_get_int_parameter(res->v, param);
else
return -1;
}
if (stp_check_int_parameter(v, param, STP_PARAMETER_ACTIVE))
return stp_get_int_parameter(v, param);
else
{
const res_t *res1 = stpi_escp2_find_resolution(v);
if (res1->v &&
stp_check_int_parameter(res1->v, param, STP_PARAMETER_ACTIVE))
return stp_get_int_parameter(res1->v, param);
}
return -1;
}
static int
escp2_ink_type(const stp_vars_t *v)
{
return escp2_res_param(v, "escp2_ink_type", NULL);
}
static double
escp2_density(const stp_vars_t *v)
{
if (stp_check_float_parameter(v, "escp2_density", STP_PARAMETER_ACTIVE))
return stp_get_float_parameter(v, "escp2_density");
else
{
const res_t *res1 = stpi_escp2_find_resolution(v);
if (res1->v &&
stp_check_float_parameter(res1->v, "escp2_density", STP_PARAMETER_ACTIVE))
return stp_get_float_parameter(res1->v, "escp2_density");
}
return 0;
}
static inline int
escp2_bits(const stp_vars_t *v)
{
return escp2_res_param(v, "escp2_bits", NULL);
}
static inline int
escp2_base_res(const stp_vars_t *v)
{
return escp2_res_param(v, "escp2_base_res", NULL);
}
static inline int
escp2_ink_type_by_res(const stp_vars_t *v, const res_t *res)
{
return escp2_res_param(v, "escp2_ink_type", res);
}
static inline double
escp2_density_by_res(const stp_vars_t *v, const res_t *res)
{
if (res)
{
if (res->v &&
stp_check_float_parameter(res->v, "escp2_density", STP_PARAMETER_ACTIVE))
return stp_get_float_parameter(res->v, "escp2_density");
}
return 0.0;
}
static inline int
escp2_bits_by_res(const stp_vars_t *v, const res_t *res)
{
return escp2_res_param(v, "escp2_bits", res);
}
static inline int
escp2_base_res_by_res(const stp_vars_t *v, const res_t *res)
{
return escp2_res_param(v, "escp2_base_res", res);
}
static escp2_dropsize_t *
escp2_copy_dropsizes(const stp_vars_t *v)
{
const res_t *res = stpi_escp2_find_resolution(v);
escp2_dropsize_t *ndrops;
if (!res || !(res->v))
return NULL;
ndrops = stp_zalloc(sizeof(escp2_dropsize_t));
if (! ndrops)
return NULL;
if (stp_check_float_parameter(res->v, "DropSize1", STP_PARAMETER_ACTIVE))
{
ndrops->numdropsizes = 1;
ndrops->dropsizes[0] = stp_get_float_parameter(res->v, "DropSize1");
}
if (stp_check_float_parameter(res->v, "DropSize2", STP_PARAMETER_ACTIVE))
{
ndrops->numdropsizes = 2;
ndrops->dropsizes[1] = stp_get_float_parameter(res->v, "DropSize2");
}
if (stp_check_float_parameter(res->v, "DropSize3", STP_PARAMETER_ACTIVE))
{
ndrops->numdropsizes = 3;
ndrops->dropsizes[2] = stp_get_float_parameter(res->v, "DropSize3");
}
return ndrops;
}
static void
escp2_free_dropsizes(escp2_dropsize_t *drops)
{
if (drops)
stp_free(drops);
}
const inklist_t *
stpi_escp2_inklist(const stp_vars_t *v)
{
int i;
const char *ink_list_name = NULL;
const inkgroup_t *inkgroup = escp2_inkgroup(v);
if (stp_check_string_parameter(v, "InkSet", STP_PARAMETER_ACTIVE))
ink_list_name = stp_get_string_parameter(v, "InkSet");
if (ink_list_name)
{
for (i = 0; i < inkgroup->n_inklists; i++)
{
if (strcmp(ink_list_name, inkgroup->inklists[i].name) == 0)
return &(inkgroup->inklists[i]);
}
}
STPI_ASSERT(inkgroup, v);
return &(inkgroup->inklists[0]);
}
static const shade_t *
escp2_shades(const stp_vars_t *v, int channel)
{
const inklist_t *inklist = stpi_escp2_inklist(v);
return &(inklist->shades[channel]);
}
static shade_t *
escp2_copy_shades(const stp_vars_t *v, int channel)
{
int i;
shade_t *nshades;
const inklist_t *inklist = stpi_escp2_inklist(v);
if (!inklist)
return NULL;
nshades = stp_zalloc(sizeof(shade_t));
nshades->n_shades = inklist->shades[channel].n_shades;
nshades->shades = stp_zalloc(sizeof(double) * inklist->shades[channel].n_shades);
for (i = 0; i < inklist->shades[channel].n_shades; i++)
nshades->shades[i] = inklist->shades[channel].shades[i];
return nshades;
}
static void
escp2_free_shades(shade_t *shades)
{
if (shades)
{
if (shades->shades)
stp_free(shades->shades);
stp_free(shades);
}
}
static const stp_string_list_t *
escp2_paperlist(const stp_vars_t *v)
{
stpi_escp2_printer_t *printdef = stpi_escp2_get_printer(v);
return printdef->papers;
}
static const stp_string_list_t *
escp2_slotlist(const stp_vars_t *v)
{
stpi_escp2_printer_t *printdef = stpi_escp2_get_printer(v);
return printdef->input_slots;
}
static int
supports_borderless(const stp_vars_t *v)
{
return (stpi_escp2_has_cap(v, MODEL_ZEROMARGIN, MODEL_ZEROMARGIN_YES) ||
stpi_escp2_has_cap(v, MODEL_ZEROMARGIN, MODEL_ZEROMARGIN_FULL) ||
stpi_escp2_has_cap(v, MODEL_ZEROMARGIN, MODEL_ZEROMARGIN_H_ONLY) ||
stpi_escp2_has_cap(v, MODEL_ZEROMARGIN, MODEL_ZEROMARGIN_RESTR));
}
static int
max_nozzle_span(const stp_vars_t *v)
{
int nozzle_count = escp2_nozzles(v);
int nozzle_separation = escp2_nozzle_separation(v);
int black_nozzle_count = escp2_black_nozzles(v);
int black_nozzle_separation = escp2_black_nozzle_separation(v);
int nozzle_span = nozzle_count * nozzle_separation;
int black_nozzle_span = black_nozzle_count * black_nozzle_separation;
if (black_nozzle_span > nozzle_span)
return black_nozzle_span;
else
return nozzle_span;
}
static const stp_raw_t *
get_printer_weave(const stp_vars_t *v)
{
int i;
const res_t *res = stpi_escp2_find_resolution(v);
const printer_weave_list_t *p = escp2_printer_weaves(v);
if (p)
{
const char *name = stp_get_string_parameter(v, "Weave");
int printer_weave_count = p->n_printer_weaves;
if (name)
{
for (i = 0; i < printer_weave_count; i++)
{
if (!strcmp(name, p->printer_weaves[i].name))
return p->printer_weaves[i].command;
}
}
}
if (res)
return res->command;
return NULL;
}
static int
use_printer_weave(const stp_vars_t *v)
{
const res_t *res = stpi_escp2_find_resolution(v);
return (!res || res->command);
}
static void
get_resolution_bounds_by_paper_type(const stp_vars_t *v,
unsigned *max_x, unsigned *max_y,
unsigned *min_x, unsigned *min_y)
{
const paper_t *paper = stpi_escp2_get_media_type(v, 1);
*min_x = 0;
*min_y = 0;
*max_x = 0;
*max_y = 0;
if (paper)
{
switch (paper->paper_class)
{
case PAPER_PLAIN:
*min_x = 0;
*min_y = 0;
*max_x = escp2_base_separation(v) * 4;
*max_y = escp2_base_separation(v) * 2;
break;
case PAPER_GOOD:
*min_x = escp2_base_separation(v);
*min_y = escp2_base_separation(v);
*max_x = escp2_base_separation(v) * 4;
*max_y = escp2_base_separation(v) * 4;
break;
case PAPER_PHOTO:
*min_x = escp2_base_separation(v) * 2;
*min_y = escp2_base_separation(v);
*max_x = 2880;
*max_y = escp2_base_separation(v) * 4;
if (*min_x >= escp2_max_hres(v))
*min_x = escp2_max_hres(v);
break;
case PAPER_PREMIUM_PHOTO:
*min_x = escp2_base_separation(v) * 2;
*min_y = escp2_base_separation(v) * 2;
*max_x = 0;
*max_y = 0;
if (*min_x >= escp2_max_hres(v))
*min_x = escp2_max_hres(v);
break;
case PAPER_TRANSPARENCY:
*min_x = escp2_base_separation(v);
*min_y = escp2_base_separation(v);
*max_x = escp2_base_separation(v) * 2;
*max_y = escp2_base_separation(v) * 2;
break;
}
stp_dprintf(STP_DBG_ESCP2, v,
"Paper %s class %d: min_x %d min_y %d max_x %d max_y %d\n",
paper->text, paper->paper_class, *min_x, *min_y,
*max_x, *max_y);
}
}
static int
verify_resolution_by_paper_type(const stp_vars_t *v, const res_t *res)
{
unsigned min_x = 0;
unsigned min_y = 0;
unsigned max_x = 0;
unsigned max_y = 0;
get_resolution_bounds_by_paper_type(v, &max_x, &max_y, &min_x, &min_y);
if ((max_x == 0 || res->printed_hres <= max_x) &&
(max_y == 0 || res->printed_vres <= max_y) &&
(min_x == 0 || res->printed_hres >= min_x) &&
(min_y == 0 || res->printed_vres >= min_y))
{
stp_dprintf(STP_DBG_ESCP2, v,
"Resolution %s (%d, %d) GOOD (%d, %d, %d, %d)\n",
res->name, res->printed_hres, res->printed_vres,
min_x, min_y, max_x, max_y);
return 1;
}
else
{
stp_dprintf(STP_DBG_ESCP2, v,
"Resolution %s (%d, %d) BAD (%d, %d, %d, %d)\n",
res->name, res->printed_hres, res->printed_vres,
min_x, min_y, max_x, max_y);
return 0;
}
}
static int
verify_resolution(const stp_vars_t *v, const res_t *res)
{
int nozzle_width =
(escp2_base_separation(v) / escp2_nozzle_separation(v));
int nozzles = escp2_nozzles(v);
if (escp2_ink_type_by_res(v, res) != -1 &&
res->vres <= escp2_max_vres(v) &&
res->hres <= escp2_max_hres(v) &&
res->vres >= escp2_min_vres(v) &&
res->hres >= escp2_min_hres(v) &&
(nozzles == 1 ||
((res->vres / nozzle_width) * nozzle_width) == res->vres))
{
int xdpi = res->hres;
int physical_xdpi = escp2_base_res_by_res(v, res);
int horizontal_passes, oversample;
if (physical_xdpi > xdpi)
physical_xdpi = xdpi;
horizontal_passes = xdpi / physical_xdpi;
oversample = horizontal_passes * res->vertical_passes;
if (horizontal_passes < 1)
horizontal_passes = 1;
if (oversample < 1)
oversample = 1;
if (((horizontal_passes * res->vertical_passes) <= STP_MAX_WEAVE) &&
(res->command || (nozzles > 1 && nozzles > oversample)))
return 1;
}
return 0;
}
static void
get_printer_resolution_bounds(const stp_vars_t *v,
unsigned *max_x, unsigned *max_y,
unsigned *min_x, unsigned *min_y)
{
int i = 0;
const resolution_list_t *resolutions = escp2_reslist(v);
*max_x = 0;
*max_y = 0;
*min_x = 0;
*min_y = 0;
for (i = 0; i < resolutions->n_resolutions; i++)
{
res_t *res = &(resolutions->resolutions[i]);
if (verify_resolution(v, res))
{
if (res->printed_hres * res->vertical_passes > *max_x)
*max_x = res->printed_hres * res->vertical_passes;
if (res->printed_vres > *max_y)
*max_y = res->printed_vres;
if (*min_x == 0 ||
res->printed_hres * res->vertical_passes < *min_x)
*min_x = res->printed_hres * res->vertical_passes;
if (*min_y == 0 || res->printed_vres < *min_y)
*min_y = res->printed_vres;
}
}
stp_dprintf(STP_DBG_ESCP2, v,
"Printer bounds: %d %d %d %d\n", *min_x, *min_y, *max_x, *max_y);
}
static int
verify_papersize(const stp_vars_t *v, const stp_papersize_t *pt)
{
stp_dimension_t height_limit, width_limit;
stp_dimension_t min_height_limit, min_width_limit;
unsigned int envelope_landscape =
stpi_escp2_has_cap(v, MODEL_ENVELOPE_LANDSCAPE, MODEL_ENVELOPE_LANDSCAPE_YES);
width_limit = escp2_max_paper_width(v);
height_limit = escp2_max_paper_height(v);
min_width_limit = escp2_min_paper_width(v);
min_height_limit = escp2_min_paper_height(v);
if (pt->paper_size_type != PAPERSIZE_TYPE_STANDARD &&
pt->paper_size_type != PAPERSIZE_TYPE_ENVELOPE)
return 0;
if (strlen(pt->name) > 0 &&
(pt->paper_size_type != PAPERSIZE_TYPE_ENVELOPE ||
envelope_landscape || pt->height > pt->width) &&
pt->width <= width_limit && pt->height <= height_limit &&
(pt->height >= min_height_limit || pt->height == 0) &&
(pt->width >= min_width_limit || pt->width == 0) &&
(pt->width == 0 || pt->height > 0 ||
stpi_escp2_printer_supports_rollfeed(v)))
return 1;
else
return 0;
}
static int
verify_inktype(const stp_vars_t *v, const inkname_t *inks)
{
if (inks->inkset == INKSET_EXTENDED)
return 0;
else
return 1;
}
static const char *
get_default_inktype(const stp_vars_t *v)
{
const inklist_t *ink_list = stpi_escp2_inklist(v);
const paper_t *paper_type;
if (!ink_list)
return NULL;
paper_type = stpi_escp2_get_media_type(v, 0);
if (!paper_type)
paper_type = stpi_escp2_get_default_media_type(v);
if (paper_type && paper_type->preferred_ink_type)
return paper_type->preferred_ink_type;
else if (stpi_escp2_has_cap(v, MODEL_FAST_360, MODEL_FAST_360_YES) &&
stp_check_string_parameter(v, "Resolution", STP_PARAMETER_ACTIVE))
{
const res_t *res = stpi_escp2_find_resolution(v);
if (res)
{
/* Hard-coded value for old printers */
if (res->vres == 360 && res->hres == escp2_base_res(v))
{
int i;
for (i = 0; i < ink_list->n_inks; i++)
if (strcmp(ink_list->inknames[i].name, "CMYK") == 0)
return ink_list->inknames[i].name;
}
}
}
return ink_list->inknames[0].name;
}
static const inkname_t *
get_inktype(const stp_vars_t *v)
{
const char *ink_type = stp_get_string_parameter(v, "InkType");
const inklist_t *ink_list = stpi_escp2_inklist(v);
int i;
if (!ink_type || strcmp(ink_type, "None") == 0 ||
(ink_list && ink_list->n_inks == 1))
ink_type = get_default_inktype(v);
if (ink_type && ink_list)
{
for (i = 0; i < ink_list->n_inks; i++)
{
if (strcmp(ink_type, ink_list->inknames[i].name) == 0)
return &(ink_list->inknames[i]);
}
}
/*
* If we couldn't find anything, try again with the default ink type.
* This may mean duplicate work, but that's cheap enough.
*/
ink_type = get_default_inktype(v);
if (ink_type && ink_list)
{
for (i = 0; i < ink_list->n_inks; i++)
{
if (strcmp(ink_type, ink_list->inknames[i].name) == 0)
return &(ink_list->inknames[i]);
}
}
/*
* If even *that* doesn't work, try using the first ink type on the list.
*/
return (ink_list) ? &(ink_list->inknames[0]) : NULL;
}
static const inkname_t *
get_inktype_only(const stp_vars_t *v)
{
const char *ink_type = stp_get_string_parameter(v, "InkType");
if (!ink_type)
return NULL;
else
return get_inktype(v);
}
static int
printer_supports_inkset(const stp_vars_t *v, inkset_id_t inkset)
{
const inkgroup_t *ink_group = escp2_inkgroup(v);
int i;
for (i = 0; i < ink_group->n_inklists; i++)
{
const inklist_t *ink_list = &(ink_group->inklists[i]);
if (ink_list)
{
int j;
for (j = 0; j < ink_list->n_inks; j++)
{
if (ink_list->inknames[j].inkset == inkset)
{
return 1;
}
}
}
}
return 0;
}
static const stp_vars_t *
get_media_adjustment(const stp_vars_t *v)
{
const paper_t *pt = stpi_escp2_get_media_type(v, 0);
if (pt)
return pt->v;
else
return NULL;
}
/*
* 'escp2_parameters()' - Return the parameter values for the given parameter.
*/
static stp_parameter_list_t
escp2_list_parameters(const stp_vars_t *v)
{
stp_parameter_list_t *ret = stp_parameter_list_create();
stp_parameter_list_t *tmp_list;
int i;
/* Set up dithering */
tmp_list = stp_dither_list_parameters(v);
stp_parameter_list_append(ret, tmp_list);
stp_parameter_list_destroy(tmp_list);
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));
for (i = 0; i < int_parameter_count; i++)
stp_parameter_list_add_param(ret, &(int_parameters[i].param));
return ret;
}
static void
set_density_parameter(const stp_vars_t *v,
stp_parameter_t *description,
const char *name)
{
const inkname_t *ink_name = get_inktype(v);
description->is_active = 0;
if (ink_name && stp_get_string_parameter(v, "PrintingMode") &&
strcmp(stp_get_string_parameter(v, "PrintingMode"), "BW") != 0)
{
int i, j;
for (i = 0; i < ink_name->channel_count; i++)
{
ink_channel_t *ich = &(ink_name->channels[i]);
if (ich)
{
for (j = 0; j < ich->n_subchannels; j++)
{
physical_subchannel_t *sch = &(ich->subchannels[j]);
if (sch && sch->channel_density &&
!strcmp(name, sch->channel_density))
{
description->is_active = 1;
description->bounds.dbl.lower = 0;
description->bounds.dbl.upper = 2.0;
description->deflt.dbl = 1.0;
}
}
}
}
}
}
static void
set_hue_map_parameter(const stp_vars_t *v,
stp_parameter_t *description,
const char *name)
{
const inkname_t *ink_name = get_inktype(v);
description->is_active = 0;
description->deflt.curve = hue_curve_bounds;
description->bounds.curve = stp_curve_create_copy(hue_curve_bounds);
if (ink_name && stp_get_string_parameter(v, "PrintingMode") &&
strcmp(stp_get_string_parameter(v, "PrintingMode"), "BW") != 0)
{
int i;
for (i = 0; i < ink_name->channel_count; i++)
{
ink_channel_t *ich = &(ink_name->channels[i]);
if (ich && ich->hue_curve && !strcmp(name, ich->hue_curve_name))
{
description->deflt.curve = ich->hue_curve;
description->is_active = 1;
}
}
}
}
static void
fill_value_parameters(const stp_vars_t *v,
stp_parameter_t *description,
int color)
{
const shade_t *shades = escp2_shades(v, color);
const inkname_t *ink_name = get_inktype(v);
description->is_active = 1;
description->bounds.dbl.lower = 0;
description->bounds.dbl.upper = 1.0;
description->deflt.dbl = 1.0;
if (shades && ink_name)
{
const ink_channel_t *channel = &(ink_name->channels[color]);
int i;
for (i = 0; i < channel->n_subchannels; i++)
{
if (channel->subchannels[i].subchannel_value &&
strcmp(description->name,
channel->subchannels[i].subchannel_value) == 0)
{
description->deflt.dbl = shades->shades[i];
return;
}
}
}
}
static void
set_color_value_parameter(const stp_vars_t *v,
stp_parameter_t *description,
int color)
{
description->is_active = 0;
if (stp_get_string_parameter(v, "PrintingMode") &&
strcmp(stp_get_string_parameter(v, "PrintingMode"), "BW") != 0)
{
const inkname_t *ink_name = get_inktype(v);
if (ink_name &&
ink_name->channel_count == 4 &&
ink_name->channels[color].n_subchannels == 2)
fill_value_parameters(v, description, color);
}
}
static void
set_gray_value_parameter(const stp_vars_t *v,
stp_parameter_t *description,
int expected_channels)
{
const inkname_t *ink_name = get_inktype_only(v);
description->is_active = 0;
if (!ink_name &&
((expected_channels == 4 && printer_supports_inkset(v, INKSET_QUADTONE)) ||
(expected_channels == 6 && printer_supports_inkset(v, INKSET_HEXTONE))))
fill_value_parameters(v, description, STP_ECOLOR_K);
else if (ink_name &&
(ink_name->channels[STP_ECOLOR_K].n_subchannels ==
expected_channels))
fill_value_parameters(v, description, STP_ECOLOR_K);
else
set_color_value_parameter(v, description, STP_ECOLOR_K);
}
static void
fill_transition_parameters(const stp_vars_t *v,
stp_parameter_t *description,
int color)
{
const stp_vars_t *paper_adj = get_media_adjustment(v);
description->is_active = 1;
description->bounds.dbl.lower = 0;
description->bounds.dbl.upper = 1.0;
if (paper_adj && stp_check_float_parameter(paper_adj, "SubchannelCutoff", STP_PARAMETER_ACTIVE))
description->deflt.dbl = stp_get_float_parameter(paper_adj, "SubchannelCutoff");
else
description->deflt.dbl = 1.0;
}
static void
set_color_transition_parameter(const stp_vars_t *v,
stp_parameter_t *description,
int color)
{
description->is_active = 0;
if (stp_get_string_parameter(v, "PrintingMode") &&
strcmp(stp_get_string_parameter(v, "PrintingMode"), "BW") != 0)
{
const inkname_t *ink_name = get_inktype(v);
if (ink_name &&
ink_name->channel_count == 4 &&
ink_name->channels[color].n_subchannels == 2)
fill_transition_parameters(v, description, color);
}
}
static void
set_gray_transition_parameter(const stp_vars_t *v,
stp_parameter_t *description,
int expected_channels)
{
const inkname_t *ink_name = get_inktype_only(v);
description->is_active = 0;
if (!ink_name &&
((expected_channels == 4 && printer_supports_inkset(v, INKSET_QUADTONE)) ||
(expected_channels == 6 && printer_supports_inkset(v, INKSET_HEXTONE))))
fill_transition_parameters(v, description, STP_ECOLOR_K);
if (ink_name &&
(ink_name->channels[STP_ECOLOR_K].n_subchannels ==
expected_channels))
fill_transition_parameters(v, description, STP_ECOLOR_K);
else
set_color_transition_parameter(v, description, STP_ECOLOR_K);
}
static void
fill_scale_parameters(stp_parameter_t *description)
{
description->is_active = 1;
description->bounds.dbl.lower = 0;
description->bounds.dbl.upper = 5.0;
description->deflt.dbl = 1.0;
}
static void
set_color_scale_parameter(const stp_vars_t *v,
stp_parameter_t *description,
int color)
{
description->is_active = 0;
if (stp_get_string_parameter(v, "PrintingMode") &&
strcmp(stp_get_string_parameter(v, "PrintingMode"), "BW") != 0)
{
const inkname_t *ink_name = get_inktype(v);
if (ink_name &&
ink_name->channel_count == 4 &&
ink_name->channels[color].n_subchannels == 2)
fill_scale_parameters(description);
}
}
static void
set_gray_scale_parameter(const stp_vars_t *v,
stp_parameter_t *description,
int expected_channels)
{
const inkname_t *ink_name = get_inktype_only(v);
description->is_active = 0;
if (!ink_name &&
((expected_channels == 4 && printer_supports_inkset(v, INKSET_QUADTONE)) ||
(expected_channels == 6 && printer_supports_inkset(v, INKSET_HEXTONE))))
fill_transition_parameters(v, description, STP_ECOLOR_K);
if (ink_name &&
(ink_name->channels[STP_ECOLOR_K].n_subchannels ==
expected_channels))
fill_scale_parameters(description);
else
set_color_scale_parameter(v, description, STP_ECOLOR_K);
}
static const res_t *
find_default_resolution(const stp_vars_t *v, const quality_t *q, int strict)
{
const resolution_list_t *resolutions = escp2_reslist(v);
int i = 0;
stp_dprintf(STP_DBG_ESCP2, v, "Quality %s: min %d %d max %d %d, des %d %d\n",
q->name, q->min_hres, q->min_vres, q->max_hres, q->max_vres,
q->desired_hres, q->desired_vres);
if (q->desired_hres < 0 || q->desired_vres < 0)
{
for (i = resolutions->n_resolutions - 1; i >= 0; i--)
{
const res_t *res = &(resolutions->resolutions[i]);
stp_dprintf(STP_DBG_ESCP2, v, " Checking resolution %s %d...\n",
res->name, i);
if ((q->max_hres <= 0 || res->printed_hres <= q->max_hres) &&
(q->max_vres <= 0 || res->printed_vres <= q->max_vres) &&
q->min_hres <= res->printed_hres &&
q->min_vres <= res->printed_vres &&
verify_resolution(v, res) &&
verify_resolution_by_paper_type(v, res))
return res;
}
}
if (!strict)
{
unsigned max_x, max_y, min_x, min_y;
unsigned desired_hres = q->desired_hres;
unsigned desired_vres = q->desired_vres;
get_resolution_bounds_by_paper_type(v, &max_x, &max_y, &min_x, &min_y);
stp_dprintf(STP_DBG_ESCP2, v, " Comparing hres %d to %d, %d\n",
desired_hres, min_x, max_x);
stp_dprintf(STP_DBG_ESCP2, v, " Comparing vres %d to %d, %d\n",
desired_vres, min_y, max_y);
if (max_x > 0 && desired_hres > max_x)
{
stp_dprintf(STP_DBG_ESCP2, v, " Decreasing hres from %d to %d\n",
desired_hres, max_x);
desired_hres = max_x;
}
else if (desired_hres < min_x)
{
stp_dprintf(STP_DBG_ESCP2, v, " Increasing hres from %d to %d\n",
desired_hres, min_x);
desired_hres = min_x;
}
if (max_y > 0 && desired_vres > max_y)
{
stp_dprintf(STP_DBG_ESCP2, v, " Decreasing vres from %d to %d\n",
desired_vres, max_y);
desired_vres = max_y;
}
else if (desired_vres < min_y)
{
stp_dprintf(STP_DBG_ESCP2, v, " Increasing vres from %d to %d\n",
desired_vres, min_y);
desired_vres = min_y;
}
for (i = 0; i < resolutions->n_resolutions; i++)
{
res_t *res = &(resolutions->resolutions[i]);
if (verify_resolution(v, res) &&
res->printed_vres == desired_vres &&
res->printed_hres == desired_hres)
{
stp_dprintf(STP_DBG_ESCP2, v,
" Found desired resolution w/o oversample: %s %d: %d * %d, %d\n",
res->name, i, res->printed_hres,
res->vertical_passes, res->printed_vres);
return res;
}
}
for (i = 0; i < resolutions->n_resolutions; i++)
{
res_t *res = &(resolutions->resolutions[i]);
if (verify_resolution(v, res) &&
res->printed_vres == desired_vres &&
res->printed_hres * res->vertical_passes == desired_hres)
{
stp_dprintf(STP_DBG_ESCP2, v,
" Found desired resolution: %s %d: %d * %d, %d\n",
res->name, i, res->printed_hres,
res->vertical_passes, res->printed_vres);
return res;
}
}
for (i = 0; i < resolutions->n_resolutions; i++)
{
res_t *res = &(resolutions->resolutions[i]);
if (verify_resolution(v, res) &&
(q->min_vres == 0 || res->printed_vres >= q->min_vres) &&
(q->max_vres == 0 || res->printed_vres <= q->max_vres) &&
(q->min_hres == 0 ||
res->printed_hres * res->vertical_passes >=q->min_hres) &&
(q->max_hres == 0 ||
res->printed_hres * res->vertical_passes <= q->max_hres))
{
stp_dprintf(STP_DBG_ESCP2, v,
" Found acceptable resolution: %s %d: %d * %d, %d\n",
res->name, i, res->printed_hres,
res->vertical_passes, res->printed_vres);
return res;
}
}
}
#if 0
if (!strict) /* Try again to find a match */
{
for (i = 0; i < resolutions->n_resolutions; i++)
{
res_t *res = &(resolutions->resolutions[i]);
if (verify_resolution(v, res) &&
res->printed_vres >= desired_vres &&
res->printed_hres * res->vertical_passes >= desired_hres &&
res->printed_vres <= 2 * desired_vres &&
res->printed_hres * res->vertical_passes <= 2 * desired_hres)
return res;
}
}
#endif
return NULL;
}
static int
verify_quality(const stp_vars_t *v, const quality_t *q)
{
unsigned max_x, max_y, min_x, min_y;
get_printer_resolution_bounds(v, &max_x, &max_y, &min_x, &min_y);
if ((q->max_vres == 0 || min_y <= q->max_vres) &&
(q->min_vres == 0 || max_y >= q->min_vres) &&
(q->max_hres == 0 || min_x <= q->max_hres) &&
(q->min_hres == 0 || max_x >= q->min_hres))
{
stp_dprintf(STP_DBG_ESCP2, v, "Quality %s OK: %d %d %d %d\n",
q->text, q->min_hres, q->min_vres, q->max_hres, q->max_vres);
return 1;
}
else
{
stp_dprintf(STP_DBG_ESCP2, v, "Quality %s not OK: %d %d %d %d\n",
q->text, q->min_hres, q->min_vres, q->max_hres, q->max_vres);
return 0;
}
}
static const res_t *
find_resolution_from_quality(const stp_vars_t *v, const char *quality,
int strict)
{
int i;
const quality_list_t *quals = escp2_quality_list(v);
/* This is a rather gross hack... */
if (strcmp(quality, "None") == 0)
quality = "Standard";
for (i = 0; i < quals->n_quals; i++)
{
const quality_t *q = &(quals->qualities[i]);
if (strcmp(quality, q->name) == 0 && verify_quality(v, q))
return find_default_resolution(v, q, strict);
}
return NULL;
}
static const inkname_t *
get_raw_inktype(const stp_vars_t *v)
{
if (strcmp(stp_get_string_parameter(v, "InputImageType"), "Raw") == 0)
{
const inklist_t *inks = stpi_escp2_inklist(v);
int ninktypes = inks->n_inks;
int i;
const char *channel_name = stp_get_string_parameter(v, "RawChannels");
const channel_count_t *count;
if (!channel_name)
goto none;
count = get_channel_count_by_name(channel_name);
if (!count)
goto none;
for (i = 0; i < ninktypes; i++)
if (inks->inknames[i].inkset == INKSET_EXTENDED &&
(inks->inknames[i].channel_count == count->count))
return &(inks->inknames[i]);
}
none:
return get_inktype(v);
}
static void
escp2_parameters(const stp_vars_t *v, const char *name,
stp_parameter_t *description)
{
int i;
description->p_type = STP_PARAMETER_TYPE_INVALID;
int found = 0;
if (name == NULL)
return;
memset(&description->deflt, 0, sizeof(description->deflt));
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;
found = 1;
break;
}
if (!found)
{
for (i = 0; i < int_parameter_count; i++)
if (strcmp(name, int_parameters[i].param.name) == 0)
{
stp_fill_parameter_settings(description,
&(int_parameters[i].param));
description->deflt.integer = int_parameters[i].defval;
description->bounds.integer.upper = int_parameters[i].max;
description->bounds.integer.lower = int_parameters[i].min;
found = 1;
break;
}
}
if (!found)
{
for (i = 0; i < the_parameter_count; i++)
if (strcmp(name, the_parameters[i].name) == 0)
{
stp_fill_parameter_settings(description, &(the_parameters[i]));
if (description->p_type == STP_PARAMETER_TYPE_INT)
{
description->deflt.integer = 0;
description->bounds.integer.upper = INT_MAX;
description->bounds.integer.lower = INT_MIN;
}
break;
}
}
if (strcmp(name, "AutoMode") == 0)
{
description->bounds.str = stp_string_list_create();
stp_string_list_add_string(description->bounds.str, "None",
_("Full Manual Control"));
stp_string_list_add_string(description->bounds.str, "Auto",
_("Automatic Setting Control"));
description->deflt.str = "None"; /* so CUPS doesn't break */
}
else if (strcmp(name, "PageSize") == 0)
{
const input_slot_t *slot = stpi_escp2_get_input_slot(v);
description->bounds.str = stp_string_list_create();
if (slot && slot->is_cd &&
!stp_get_boolean_parameter(v, "CDAllowOtherMedia"))
{
stp_string_list_add_string
(description->bounds.str, "CD5Inch", _("CD - 5 inch"));
stp_string_list_add_string
(description->bounds.str, "CD3Inch", _("CD - 3 inch"));
stp_string_list_add_string
(description->bounds.str, "CDCustom", _("CD - Custom"));
}
else
{
const stp_papersize_list_t *paper_sizes =
stpi_get_standard_papersize_list();
const stp_papersize_list_item_t *ptli =
stpi_papersize_list_get_start(paper_sizes);
while (ptli)
{
const stp_papersize_t *pt = stpi_paperlist_item_get_data(ptli);
if (verify_papersize(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, "CDAllowOtherMedia") == 0)
{
const input_slot_t *slot = stpi_escp2_get_input_slot(v);
if (stpi_escp2_printer_supports_print_to_cd(v) &&
(!slot || slot->is_cd))
description->is_active = 1;
else
description->is_active = 0;
}
else if (strcmp(name, "CDInnerRadius") == 0 )
{
const input_slot_t *slot = stpi_escp2_get_input_slot(v);
description->bounds.str = stp_string_list_create();
if (stpi_escp2_printer_supports_print_to_cd(v) &&
(!slot || slot->is_cd) &&
(!stp_get_string_parameter(v, "PageSize") ||
strcmp(stp_get_string_parameter(v, "PageSize"), "CDCustom") != 0))
{
stp_string_list_add_string
(description->bounds.str, "None", _("Normal"));
stp_string_list_add_string
(description->bounds.str, "Small", _("Print To Hub"));
description->deflt.str =
stp_string_list_param(description->bounds.str, 0)->name;
}
else
description->is_active = 0;
}
else if (strcmp(name, "CDInnerDiameter") == 0 )
{
const input_slot_t *slot = stpi_escp2_get_input_slot(v);
description->bounds.dimension.lower = 16 * 10 * 72 / 254;
description->bounds.dimension.upper = 43 * 10 * 72 / 254;
description->deflt.dimension = 43 * 10 * 72 / 254;
if (stpi_escp2_printer_supports_print_to_cd(v) &&
(!slot || slot->is_cd) &&
(!stp_get_string_parameter(v, "PageSize") ||
strcmp(stp_get_string_parameter(v, "PageSize"), "CDCustom") == 0))
description->is_active = 1;
else
description->is_active = 0;
}
else if (strcmp(name, "CDOuterDiameter") == 0 )
{
const input_slot_t *slot = stpi_escp2_get_input_slot(v);
description->bounds.dimension.lower = 65 * 10 * 72 / 254;
description->bounds.dimension.upper = 120 * 10 * 72 / 254;
description->deflt.dimension = 329;
if (stpi_escp2_printer_supports_print_to_cd(v) &&
(!slot || slot->is_cd) &&
(!stp_get_string_parameter(v, "PageSize") ||
strcmp(stp_get_string_parameter(v, "PageSize"), "CDCustom") == 0))
description->is_active = 1;
else
description->is_active = 0;
}
else if (strcmp(name, "CDXAdjustment") == 0 ||
strcmp(name, "CDYAdjustment") == 0)
{
const input_slot_t *slot = stpi_escp2_get_input_slot(v);
description->bounds.dimension.lower = -30;
description->bounds.dimension.upper = 30;
description->deflt.dimension = 0;
if (stpi_escp2_printer_supports_print_to_cd(v) && (!slot || slot->is_cd))
description->is_active = 1;
else
description->is_active = 0;
}
else if (strcmp(name, "Quality") == 0)
{
const quality_list_t *quals = escp2_quality_list(v);
int has_standard_quality = 0;
description->bounds.str = stp_string_list_create();
stp_string_list_add_string(description->bounds.str, "None",
_("Manual Control"));
for (i = 0; i < quals->n_quals; i++)
{
const quality_t *q = &(quals->qualities[i]);
if (verify_quality(v, q))
stp_string_list_add_string(description->bounds.str, q->name,
gettext(q->text));
if (strcmp(q->name, "Standard") == 0)
has_standard_quality = 1;
}
if (has_standard_quality)
description->deflt.str = "Standard";
else
description->deflt.str = "None";
}
else if (strcmp(name, "Resolution") == 0)
{
const resolution_list_t *resolutions = escp2_reslist(v);
description->bounds.str = stp_string_list_create();
stp_string_list_add_string(description->bounds.str, "None",
_("Default"));
description->deflt.str = "None";
for (i = 0; i < resolutions->n_resolutions; i++)
{
res_t *res = &(resolutions->resolutions[i]);
if (verify_resolution(v, res))
stp_string_list_add_string(description->bounds.str,
res->name, gettext(res->text));
}
}
else if (strcmp(name, "InkType") == 0)
{
const inklist_t *inks = stpi_escp2_inklist(v);
int ninktypes = inks->n_inks;
int verified_inktypes = 0;
for (i = 0; i < ninktypes; i++)
if (verify_inktype(v, &(inks->inknames[i])))
verified_inktypes++;
description->bounds.str = stp_string_list_create();
if (verified_inktypes > 1)
{
stp_string_list_add_string(description->bounds.str, "None",
_("Standard"));
for (i = 0; i < ninktypes; i++)
if (verify_inktype(v, &(inks->inknames[i])))
stp_string_list_add_string(description->bounds.str,
inks->inknames[i].name,
gettext(inks->inknames[i].text));
description->deflt.str = "None";
}
else
description->is_active = 0;
}
else if (strcmp(name, "InkSet") == 0)
{
const inkgroup_t *inks = escp2_inkgroup(v);
int ninklists = inks->n_inklists;
description->bounds.str = stp_string_list_create();
if (ninklists > 1)
{
for (i = 0; i < ninklists; i++)
{
stp_string_list_add_string(description->bounds.str,
inks->inklists[i].name,
gettext(inks->inklists[i].text));
}
description->deflt.str =
stp_string_list_param(description->bounds.str, 0)->name;
}
else
description->is_active = 0;
}
else if (strcmp(name, "MediaType") == 0)
{
const stp_string_list_t *p = escp2_paperlist(v);
description->is_active = 0;
if (p)
{
int nmediatypes = stp_string_list_count(p);
description->bounds.str = stp_string_list_create();
if (nmediatypes)
{
description->is_active = 1;
for (i = 0; i < nmediatypes; i++)
stp_string_list_add_string(description->bounds.str,
stp_string_list_param(p, i)->name,
gettext(stp_string_list_param(p, i)->text));
description->deflt.str =
stp_string_list_param(description->bounds.str, 0)->name;
}
}
}
else if (strcmp(name, "InputSlot") == 0)
{
const stp_string_list_t *p = escp2_slotlist(v);
description->is_active = 0;
if (p)
{
int nslots = stp_string_list_count(p);
description->bounds.str = stp_string_list_create();
if (nslots)
{
description->is_active = 1;
for (i = 0; i < nslots; i++)
stp_string_list_add_string(description->bounds.str,
stp_string_list_param(p, i)->name,
gettext(stp_string_list_param(p, i)->text));
description->deflt.str =
stp_string_list_param(description->bounds.str, 0)->name;
}
}
}
else if (strcmp(name, "PrintingDirection") == 0)
{
description->bounds.str = stp_string_list_create();
stp_string_list_add_string
(description->bounds.str, "None", _("Automatic"));
stp_string_list_add_string
(description->bounds.str, "Bidirectional", _("Bidirectional"));
stp_string_list_add_string
(description->bounds.str, "Unidirectional", _("Unidirectional"));
description->deflt.str =
stp_string_list_param(description->bounds.str, 0)->name;
}
else if (strcmp(name, "Weave") == 0)
{
description->bounds.str = stp_string_list_create();
if (stpi_escp2_has_cap(v, MODEL_COMMAND, MODEL_COMMAND_PRO))
{
const res_t *res = stpi_escp2_find_resolution(v);
const printer_weave_list_t *printer_weaves = escp2_printer_weaves(v);
int nprinter_weaves = 0;
if (printer_weaves && use_printer_weave(v) && (!res || res->command))
nprinter_weaves = printer_weaves->n_printer_weaves;
if (nprinter_weaves)
{
stp_string_list_add_string(description->bounds.str, "None",
_("Standard"));
for (i = 0; i < nprinter_weaves; i++)
stp_string_list_add_string(description->bounds.str,
printer_weaves->printer_weaves[i].name,
gettext(printer_weaves->printer_weaves[i].text));
}
else
description->is_active = 0;
}
else
{
stp_string_list_add_string
(description->bounds.str, "None", _("Standard"));
stp_string_list_add_string
(description->bounds.str, "Alternate", _("Alternate Fill"));
stp_string_list_add_string
(description->bounds.str, "Ascending", _("Ascending Fill"));
stp_string_list_add_string
(description->bounds.str, "Descending", _("Descending Fill"));
stp_string_list_add_string
(description->bounds.str, "Ascending2X", _("Ascending Double"));
stp_string_list_add_string
(description->bounds.str, "Staggered", _("Nearest Neighbor Avoidance"));
}
if (description->is_active)
description->deflt.str =
stp_string_list_param(description->bounds.str, 0)->name;
}
else if (strcmp(name, "OutputOrder") == 0)
{
description->bounds.str = stp_string_list_create();
description->deflt.str = "Reverse";
}
else if (strcmp(name, "FullBleed") == 0)
{
const input_slot_t *slot = stpi_escp2_get_input_slot(v);
if (slot && slot->is_cd)
description->is_active = 0;
else if (supports_borderless(v))
description->deflt.boolean = 0;
else
description->is_active = 0;
}
else if (strcmp(name, "Duplex") == 0)
{
if (stpi_escp2_printer_supports_duplex(v))
{
const input_slot_t *slot = stpi_escp2_get_input_slot(v);
if (slot && !slot->duplex)
description->is_active = 0;
else
{
description->bounds.str = stp_string_list_create();
stp_string_list_add_string
(description->bounds.str, "None", _("Off"));
stp_string_list_add_string
(description->bounds.str, "DuplexNoTumble", _("Long Edge (Standard)"));
stp_string_list_add_string
(description->bounds.str, "DuplexTumble", _("Short Edge(Flip)"));
description->deflt.str = "None";
}
}
else
description->is_active = 0;
}
else if (strcmp(name, "CyanDensity") == 0 ||
strcmp(name, "MagentaDensity") == 0 ||
strcmp(name, "YellowDensity") == 0 ||
strcmp(name, "BlackDensity") == 0 ||
strcmp(name, "RedDensity") == 0 ||
strcmp(name, "BlueDensity") == 0 ||
strcmp(name, "GreenDensity") == 0 ||
strcmp(name, "OrangeDensity") == 0)
set_density_parameter(v, description, name);
else if (strcmp(name, "CyanHueCurve") == 0 ||
strcmp(name, "MagentaHueCurve") == 0 ||
strcmp(name, "YellowHueCurve") == 0 ||
strcmp(name, "RedHueCurve") == 0 ||
strcmp(name, "BlueHueCurve") == 0 ||
strcmp(name, "GreenHueCurve") == 0 ||
strcmp(name, "OrangeHueCurve") == 0)
set_hue_map_parameter(v, description, name);
else if (strcmp(name, "UseGloss") == 0)
{
const inkname_t *ink_name = get_inktype(v);
if (ink_name && ink_name->aux_channel_count > 0)
description->is_active = 1;
else
description->is_active = 0;
}
else if (strcmp(name, "GlossLimit") == 0)
{
const inkname_t *ink_name = get_inktype(v);
if (ink_name && ink_name->aux_channel_count > 0)
description->is_active = 1;
else
description->is_active = 0;
}
else if (strcmp(name, "DropSize1") == 0 ||
strcmp(name, "DropSize2") == 0 ||
strcmp(name, "DropSize3") == 0)
{
if (stpi_escp2_has_cap(v, MODEL_VARIABLE_DOT, MODEL_VARIABLE_YES))
{
const res_t *res = stpi_escp2_find_resolution(v);
if (res && res->v &&
stp_check_float_parameter(v, name, STP_PARAMETER_ACTIVE))
description->deflt.dbl = stp_get_float_parameter(v, name);
description->is_active = 1;
}
else
description->is_active = 0;
}
else if (strcmp(name, "BlackTrans") == 0 ||
strcmp(name, "GCRLower") == 0 ||
strcmp(name, "GCRUpper") == 0)
{
const stp_vars_t *paper_adj = get_media_adjustment(v);
if (paper_adj &&
stp_get_string_parameter(v, "PrintingMode") &&
strcmp(stp_get_string_parameter(v, "PrintingMode"), "BW") != 0)
{
if (paper_adj && stp_check_float_parameter(paper_adj, name, STP_PARAMETER_ACTIVE))
description->deflt.dbl = stp_get_float_parameter(paper_adj, name);
else
description->p_type = STP_PARAMETER_TYPE_INVALID;
}
else
description->p_type = STP_PARAMETER_TYPE_INVALID;
}
else if (strcmp(name, "GrayValue") == 0)
set_gray_value_parameter(v, description, 2);
else if (strcmp(name, "DarkGrayValue") == 0 ||
strcmp(name, "LightGrayValue") == 0)
set_gray_value_parameter(v, description, 3);
else if (strcmp(name, "Gray1Value") == 0 ||
strcmp(name, "Gray2Value") == 0 ||
strcmp(name, "Gray3Value") == 0)
set_gray_value_parameter(v, description, 4);
else if (strcmp(name, "LightCyanValue") == 0)
set_color_value_parameter(v, description, STP_ECOLOR_C);
else if (strcmp(name, "LightMagentaValue") == 0)
set_color_value_parameter(v, description, STP_ECOLOR_M);
else if (strcmp(name, "DarkYellowValue") == 0)
set_color_value_parameter(v, description, STP_ECOLOR_Y);
else if (strcmp(name, "GrayTrans") == 0)
set_gray_transition_parameter(v, description, 2);
else if (strcmp(name, "DarkGrayTrans") == 0 ||
strcmp(name, "LightGrayTrans") == 0)
set_gray_transition_parameter(v, description, 3);
else if (strcmp(name, "Gray1Trans") == 0 ||
strcmp(name, "Gray2Trans") == 0 ||
strcmp(name, "Gray3Trans") == 0)
set_gray_transition_parameter(v, description, 4);
else if (strcmp(name, "LightCyanTrans") == 0)
set_color_transition_parameter(v, description, STP_ECOLOR_C);
else if (strcmp(name, "LightMagentaTrans") == 0)
set_color_transition_parameter(v, description, STP_ECOLOR_M);
else if (strcmp(name, "DarkYellowTrans") == 0)
set_color_transition_parameter(v, description, STP_ECOLOR_Y);
else if (strcmp(name, "GrayScale") == 0)
set_gray_scale_parameter(v, description, 2);
else if (strcmp(name, "DarkGrayScale") == 0 ||
strcmp(name, "LightGrayScale") == 0)
set_gray_scale_parameter(v, description, 3);
else if (strcmp(name, "Gray1Scale") == 0 ||
strcmp(name, "Gray2Scale") == 0 ||
strcmp(name, "Gray3Scale") == 0)
set_gray_scale_parameter(v, description, 4);
else if (strcmp(name, "LightCyanScale") == 0)
set_color_scale_parameter(v, description, STP_ECOLOR_C);
else if (strcmp(name, "LightMagentaScale") == 0)
set_color_scale_parameter(v, description, STP_ECOLOR_M);
else if (strcmp(name, "DarkYellowScale") == 0)
set_color_scale_parameter(v, description, STP_ECOLOR_Y);
else if (strcmp(name, "AlignmentPasses") == 0)
{
description->deflt.integer = escp2_alignment_passes(v);
}
else if (strcmp(name, "AlignmentChoices") == 0)
{
description->deflt.integer = escp2_alignment_choices(v);
}
else if (strcmp(name, "SupportsInkChange") == 0)
{
description->deflt.integer =
stpi_escp2_has_cap(v, MODEL_SUPPORTS_INK_CHANGE,
MODEL_SUPPORTS_INK_CHANGE_YES);
}
else if (strcmp(name, "AlternateAlignmentPasses") == 0)
{
description->deflt.integer = escp2_alternate_alignment_passes(v);
}
else if (strcmp(name, "AlternateAlignmentChoices") == 0)
{
description->deflt.integer = escp2_alternate_alignment_choices(v);
}
else if (strcmp(name, "InkChannels") == 0)
{
description->deflt.integer = escp2_physical_channels(v);
}
else if (strcmp(name, "ChannelNames") == 0)
{
const stp_string_list_t *channel_names = escp2_channel_names(v);
if (channel_names)
{
description->bounds.str = stp_string_list_create_copy(channel_names);
description->deflt.str =
stp_string_list_param(description->bounds.str, 0)->name;
}
else
description->p_type = STP_PARAMETER_TYPE_INVALID;
}
else if (strcmp(name, "SupportsPacketMode") == 0)
{
description->deflt.boolean =
stpi_escp2_has_cap(v, MODEL_PACKET_MODE, MODEL_PACKET_MODE_YES);
}
else if (strcmp(name, "PrintingMode") == 0)
{
description->bounds.str = stp_string_list_create();
stp_string_list_add_string
(description->bounds.str, "Color", _("Color"));
stp_string_list_add_string
(description->bounds.str, "BW", _("Black and White"));
description->deflt.str =
stp_string_list_param(description->bounds.str, 0)->name;
}
else if (strcmp(name, "RawChannels") == 0)
{
const inklist_t *inks = stpi_escp2_inklist(v);
int ninktypes = inks->n_inks;
description->bounds.str = stp_string_list_create();
if (ninktypes >= 1)
{
stp_string_list_add_string(description->bounds.str, "None", "None");
for (i = 0; i < ninktypes; i++)
if (inks->inknames[i].inkset == INKSET_EXTENDED)
{
const channel_count_t *ch =
(get_channel_count_by_number
(inks->inknames[i].channel_count));
stp_string_list_add_string(description->bounds.str,
ch->name, ch->name);
}
description->deflt.str =
stp_string_list_param(description->bounds.str, 0)->name;
}
else
description->is_active = 0;
}
else if (strcmp(name, "RawChannelNames") == 0)
{
const inkname_t *ink_name = get_raw_inktype(v);
if (ink_name)
{
description->bounds.str = stp_string_list_create();
for (i = 0; i < ink_name->channel_count; i++)
{
int j;
const ink_channel_t *ic = &(ink_name->channels[i]);
if (ic)
for (j = 0; j < ic->n_subchannels; j++)
if (ic->subchannels[j].name)
stp_string_list_add_string(description->bounds.str,
ic->subchannels[j].name,
gettext(ic->subchannels[j].text));
}
for (i = 0; i < ink_name->aux_channel_count; i++)
{
int j;
const ink_channel_t *ic = &(ink_name->aux_channels[i]);
if (ic)
for (j = 0; j < ic->n_subchannels; j++)
if (ic->subchannels[j].name)
stp_string_list_add_string(description->bounds.str,
ic->subchannels[j].name,
gettext(ic->subchannels[j].text));
}
description->deflt.str =
stp_string_list_param(description->bounds.str, 0)->name;
}
}
else if (strcmp(name, "MultiChannelLimit") == 0)
{
description->is_active = 0;
if (stp_get_string_parameter(v, "PrintingMode") &&
strcmp(stp_get_string_parameter(v, "PrintingMode"), "BW") != 0)
{
const inkname_t *ink_name = get_inktype(v);
if (ink_name && ink_name->inkset == INKSET_OTHER)
description->is_active = 1;
}
}
else if (strcmp(name, "PageDryTime") == 0 ||
strcmp(name, "ScanDryTime") == 0 ||
strcmp(name, "ScanMinDryTime") == 0 ||
strcmp(name, "FeedAdjustment") == 0 ||
strcmp(name, "PaperThickness") == 0 ||
strcmp(name, "VacuumIntensity") == 0 ||
strcmp(name, "FeedSequence") == 0 ||
strcmp(name, "PrintMethod") == 0 ||
strcmp(name, "PaperMedia") == 0 ||
strcmp(name, "PaperMediaSize") == 0 ||
strcmp(name, "PlatenGap") == 0)
{
description->is_active = stpi_escp2_has_media_feature(v, name);
}
else if (strcmp(name, "BandEnhancement") == 0)
{
description->is_active = 1;
}
}
const res_t *
stpi_escp2_find_resolution(const stp_vars_t *v)
{
const char *resolution = stp_get_string_parameter(v, "Resolution");
if (resolution)
{
const resolution_list_t *resolutions = escp2_reslist(v);
int i;
for (i = 0; i < resolutions->n_resolutions; i++)
{
const res_t *res = &(resolutions->resolutions[i]);
if (!strcmp(resolution, res->name))
return res;
else if (!strcmp(res->name, ""))
return NULL;
}
}
if (stp_check_string_parameter(v, "Quality", STP_PARAMETER_ACTIVE))
{
const res_t *default_res =
find_resolution_from_quality(v, stp_get_string_parameter(v, "Quality"),
0);
if (default_res)
{
stp_dprintf(STP_DBG_ESCP2, v,
"Setting resolution to %s from quality %s\n",
default_res->name,
stp_get_string_parameter(v, "Quality"));
return default_res;
}
else
stp_dprintf(STP_DBG_ESCP2, v, "Unable to map quality %s\n",
stp_get_string_parameter(v, "Quality"));
}
return NULL;
}
static inline int
smax(stp_dimension_t a, stp_dimension_t b)
{
if (a > b)
return a;
else
return b;
}
static void
escp2_media_size(const stp_vars_t *v, /* I */
stp_dimension_t *width, /* O - Width in points */
stp_dimension_t *height) /* O - Height in points */
{
if (stp_get_page_width(v) > 0 && stp_get_page_height(v) > 0)
{
*width = stp_get_page_width(v);
*height = stp_get_page_height(v);
}
else
{
const char *page_size = stp_get_string_parameter(v, "PageSize");
const stp_papersize_t *papersize = NULL;
if (page_size)
papersize = stp_describe_papersize(v, page_size);
if (!papersize)
{
*width = 1;
*height = 1;
}
else
{
*width = papersize->width;
*height = papersize->height;
}
if (*width == 0 || *height == 0)
{
const input_slot_t *slot = stpi_escp2_get_input_slot(v);
if (slot && slot->is_cd)
{
papersize = stp_describe_papersize(v, "CDCustom");
if (papersize)
{
if (*width == 0)
*width = papersize->width;
if (*height == 0)
*height = papersize->height;
}
}
else
{
const stp_papersize_list_t *paper_sizes =
stpi_get_standard_papersize_list();
const stp_papersize_list_item_t *ptli =
stpi_papersize_list_get_start(paper_sizes);
while (ptli)
{
papersize = stpi_paperlist_item_get_data(ptli);
if (verify_papersize(v, papersize))
{
if (*width == 0)
*width = papersize->width;
if (*height == 0)
*height = papersize->height;
break;
}
ptli = stpi_paperlist_item_next(ptli);
}
}
}
/* FIXME When we support A4/letter */
if (*width == 0)
*width = 612;
if (*height == 0)
*height = 792;
}
}
static void
internal_imageable_area(const stp_vars_t *v, int use_paper_margins,
int use_maximum_area,
stp_dimension_t *left, stp_dimension_t *right,
stp_dimension_t *bottom, stp_dimension_t *top)
{
stp_dimension_t width, height; /* Size of page */
int rollfeed = 0; /* Roll feed selected */
int cd = 0; /* CD selected */
const char *media_size = stp_get_string_parameter(v, "PageSize");
const char *duplex = stp_get_string_parameter(v, "Duplex");
stp_dimension_t left_margin = 0;
stp_dimension_t right_margin = 0;
stp_dimension_t bottom_margin = 0;
stp_dimension_t top_margin = 0;
const stp_papersize_t *pt = NULL;
const input_slot_t *input_slot = NULL;
if (media_size)
pt = stp_describe_papersize(v, media_size);
input_slot = stpi_escp2_get_input_slot(v);
if (input_slot)
{
cd = input_slot->is_cd;
rollfeed = input_slot->is_roll_feed;
}
escp2_media_size(v, &width, &height);
if (cd)
{
if (pt)
{
left_margin = pt->left;
right_margin = pt->right;
bottom_margin = pt->bottom;
top_margin = pt->top;
}
else
{
left_margin = 0;
right_margin = 0;
bottom_margin = 0;
top_margin = 0;
}
}
else
{
if (pt && use_paper_margins)
{
left_margin = pt->left;
right_margin = pt->right;
bottom_margin = pt->bottom;
top_margin = pt->top;
}
left_margin = smax(left_margin, escp2_left_margin(v, rollfeed));
right_margin = smax(right_margin, escp2_right_margin(v, rollfeed));
bottom_margin = smax(bottom_margin, escp2_bottom_margin(v, rollfeed));
top_margin = smax(top_margin, escp2_top_margin(v, rollfeed));
}
if (supports_borderless(v) &&
(use_maximum_area ||
(!cd && stp_get_boolean_parameter(v, "FullBleed"))))
{
if (pt)
{
if (pt->left <= 0 && pt->right <= 0 && pt->top <= 0 &&
pt->bottom <= 0)
{
if (use_paper_margins)
{
stp_dimension_t width_limit = escp2_max_paper_width(v);
stp_dimension_t offset = escp2_zero_margin_offset(v);
stp_dimension_t margin = escp2_micro_left_margin(v);
stp_dimension_t sep = escp2_base_separation(v);
stp_dimension_t delta = -((offset - margin) * 72.0 / sep);
left_margin = delta; /* Allow some overlap if paper isn't */
right_margin = delta; /* positioned correctly */
if (width - right_margin - 3 > width_limit)
right_margin = width - width_limit - 3;
if (! stpi_escp2_has_cap(v, MODEL_ZEROMARGIN,
MODEL_ZEROMARGIN_H_ONLY))
{
top_margin = -7;
bottom_margin = -7;
}
}
else
{
left_margin = 0;
right_margin = 0;
if (! stpi_escp2_has_cap(v, MODEL_ZEROMARGIN,
MODEL_ZEROMARGIN_H_ONLY))
{
top_margin = 0;
bottom_margin = 0;
}
}
}
}
}
if (!use_maximum_area && duplex && strcmp(duplex, "None") != 0)
{
left_margin = smax(left_margin, escp2_duplex_left_margin(v));
right_margin = smax(right_margin, escp2_duplex_right_margin(v));
bottom_margin = smax(bottom_margin, escp2_duplex_bottom_margin(v));
top_margin = smax(top_margin, escp2_duplex_top_margin(v));
}
if (width > escp2_max_imageable_width(v))
width = escp2_max_imageable_width(v);
if (height > escp2_max_imageable_height(v))
height = escp2_max_imageable_height(v);
*left = left_margin;
*right = width - right_margin;
*top = top_margin;
*bottom = height - bottom_margin;
}
/*
* 'escp2_imageable_area()' - Return the imageable area of the page.
*/
static void
escp2_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, 1, 0, left, right, bottom, top);
}
static void
escp2_maximum_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, 1, 1, left, right, bottom, top);
}
static void
escp2_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)
{
*width = escp2_max_paper_width(v);
*height = escp2_max_paper_height(v);
*min_width = escp2_min_paper_width(v);
*min_height = escp2_min_paper_height(v);
}
static void
escp2_describe_resolution(const stp_vars_t *v, stp_resolution_t *x, stp_resolution_t *y)
{
const res_t *res = stpi_escp2_find_resolution(v);
if (res && verify_resolution(v, res))
{
*x = res->printed_hres;
*y = res->printed_vres;
return;
}
*x = -1;
*y = -1;
}
static const char *
escp2_describe_output(const stp_vars_t *v)
{
const char *printing_mode = stp_get_string_parameter(v, "PrintingMode");
const char *input_image_type = stp_get_string_parameter(v, "InputImageType");
if (input_image_type && strcmp(input_image_type, "Raw") == 0)
return "Raw";
else if (printing_mode && strcmp(printing_mode, "BW") == 0)
return "Grayscale";
else
{
const inkname_t *ink_type = get_inktype(v);
if (ink_type)
{
switch (ink_type->inkset)
{
case INKSET_QUADTONE:
case INKSET_HEXTONE:
return "Grayscale";
case INKSET_OTHER:
case INKSET_CMYK:
case INKSET_CcMmYK:
case INKSET_CcMmYyK:
case INKSET_CcMmYKk:
default:
if (ink_type->channels[0].n_subchannels > 0)
return "KCMY";
else
return "CMY";
break;
}
}
else
return "CMYK";
}
}
static int
escp2_has_advanced_command_set(const stp_vars_t *v)
{
return (stpi_escp2_has_cap(v, MODEL_COMMAND, MODEL_COMMAND_PRO) ||
stpi_escp2_has_cap(v, MODEL_COMMAND, MODEL_COMMAND_1999) ||
stpi_escp2_has_cap(v, MODEL_COMMAND, MODEL_COMMAND_2000));
}
static int
escp2_use_extended_commands(const stp_vars_t *v, int use_softweave)
{
return (stpi_escp2_has_cap(v, MODEL_COMMAND, MODEL_COMMAND_PRO) ||
(stpi_escp2_has_cap(v, MODEL_VARIABLE_DOT, MODEL_VARIABLE_YES) &&
use_softweave));
}
static int
set_raw_ink_type(stp_vars_t *v)
{
const inklist_t *inks = stpi_escp2_inklist(v);
int ninktypes = inks->n_inks;
int i;
const char *channel_name = stp_get_string_parameter(v, "RawChannels");
const channel_count_t *count;
if (!channel_name)
return 0;
count = get_channel_count_by_name(channel_name);
if (!count)
return 0;
/*
* If we're using raw printer output, we dummy up the appropriate inkset.
*/
for (i = 0; i < ninktypes; i++)
if (inks->inknames[i].inkset == INKSET_EXTENDED &&
(inks->inknames[i].channel_count == count->count))
{
stp_dprintf(STP_DBG_INK, v, "Changing ink type from %s to %s\n",
stp_get_string_parameter(v, "InkType") ?
stp_get_string_parameter(v, "InkType") : "NULL",
inks->inknames[i].name);
stp_set_string_parameter(v, "InkType", inks->inknames[i].name);
stp_set_int_parameter(v, "STPIRawChannels", count->count);
return 1;
}
stp_eprintf
(v, _("This printer does not support raw printer output at depth %d\n"),
count->count);
return 0;
}
static void
adjust_density_and_ink_type(stp_vars_t *v)
{
escp2_privdata_t *pd = get_privdata(v);
const stp_vars_t *pv = pd->paper_type->v;
double paper_density = .8;
if (pv && stp_check_float_parameter(pv, "Density", STP_PARAMETER_ACTIVE))
paper_density = stp_get_float_parameter(pv, "Density");
if (!stp_check_float_parameter(v, "Density", STP_PARAMETER_DEFAULTED))
{
stp_set_float_parameter_active(v, "Density", STP_PARAMETER_ACTIVE);
stp_set_float_parameter(v, "Density", 1.0);
}
stp_scale_float_parameter(v, "Density", paper_density * escp2_density(v));
pd->drop_size = escp2_ink_type(v);
if (stp_get_float_parameter(v, "Density") > 1.0)
stp_set_float_parameter(v, "Density", 1.0);
}
static void
adjust_print_quality(stp_vars_t *v)
{
escp2_privdata_t *pd = get_privdata(v);
const stp_vars_t *pv = pd->paper_type->v;
double k_upper = 1.0;
double k_lower = 0;
double k_transition = 1.0;
/*
* Compute the LUT. For now, it's 8 bit, but that may eventually
* sometimes change.
*/
if (pv)
{
int i;
stp_string_list_t *slist;
stp_set_default_float_parameter(v, "BlackDensity", 1.0);
stp_set_default_float_parameter(v, "Saturation", 1.0);
stp_set_default_float_parameter(v, "Gamma", 1.0);
slist = stp_list_parameters(pv, STP_PARAMETER_TYPE_STRING_LIST);
if (slist)
{
int len = stp_string_list_count(slist);
for (i = 0; i < len; i++)
{
const char *name = stp_string_list_param(slist, i)->name;
if (!stp_check_string_parameter(v, name, STP_PARAMETER_ACTIVE))
stp_set_string_parameter(v, name,
stp_get_string_parameter(pv, name));
}
stp_string_list_destroy(slist);
}
slist = stp_list_parameters(pv, STP_PARAMETER_TYPE_FILE);
if (slist)
{
int len = stp_string_list_count(slist);
for (i = 0; i < len; i++)
{
const char *name = stp_string_list_param(slist, i)->name;
if (!stp_check_file_parameter(v, name, STP_PARAMETER_ACTIVE))
stp_set_file_parameter(v, name,
stp_get_file_parameter(pv, name));
}
stp_string_list_destroy(slist);
}
slist = stp_list_parameters(pv, STP_PARAMETER_TYPE_INT);
if (slist)
{
int len = stp_string_list_count(slist);
for (i = 0; i < len; i++)
{
const char *name = stp_string_list_param(slist, i)->name;
if (!stp_check_int_parameter(v, name, STP_PARAMETER_ACTIVE))
stp_set_int_parameter(v, name,
stp_get_int_parameter(pv, name));
}
stp_string_list_destroy(slist);
}
slist = stp_list_parameters(pv, STP_PARAMETER_TYPE_DIMENSION);
if (slist)
{
int len = stp_string_list_count(slist);
for (i = 0; i < len; i++)
{
const char *name = stp_string_list_param(slist, i)->name;
if (!stp_check_dimension_parameter(v, name, STP_PARAMETER_ACTIVE))
stp_set_dimension_parameter(v, name,
stp_get_dimension_parameter(pv, name));
}
stp_string_list_destroy(slist);
}
slist = stp_list_parameters(pv, STP_PARAMETER_TYPE_BOOLEAN);
if (slist)
{
int len = stp_string_list_count(slist);
for (i = 0; i < len; i++)
{
const char *name = stp_string_list_param(slist, i)->name;
if (!stp_check_boolean_parameter(v, name, STP_PARAMETER_ACTIVE))
stp_set_boolean_parameter(v, name,
stp_get_boolean_parameter(pv, name));
}
stp_string_list_destroy(slist);
}
slist = stp_list_parameters(pv, STP_PARAMETER_TYPE_CURVE);
if (slist)
{
int len = stp_string_list_count(slist);
for (i = 0; i < len; i++)
{
const char *name = stp_string_list_param(slist, i)->name;
if (!stp_check_curve_parameter(v, name, STP_PARAMETER_ACTIVE))
stp_set_curve_parameter(v, name,
stp_get_curve_parameter(pv, name));
}
stp_string_list_destroy(slist);
}
slist = stp_list_parameters(pv, STP_PARAMETER_TYPE_ARRAY);
if (slist)
{
int len = stp_string_list_count(slist);
for (i = 0; i < len; i++)
{
const char *name = stp_string_list_param(slist, i)->name;
if (!stp_check_array_parameter(v, name, STP_PARAMETER_ACTIVE))
stp_set_array_parameter(v, name,
stp_get_array_parameter(pv, name));
}
stp_string_list_destroy(slist);
}
slist = stp_list_parameters(pv, STP_PARAMETER_TYPE_RAW);
if (slist)
{
int len = stp_string_list_count(slist);
for (i = 0; i < len; i++)
{
const char *name = stp_string_list_param(slist, i)->name;
if (!stp_check_raw_parameter(v, name, STP_PARAMETER_ACTIVE))
{
const stp_raw_t *r = stp_get_raw_parameter(pv, name);
stp_set_raw_parameter(v, name, r->data, r->bytes);
}
}
stp_string_list_destroy(slist);
}
slist = stp_list_parameters(pv, STP_PARAMETER_TYPE_DOUBLE);
if (slist)
{
int len = stp_string_list_count(slist);
for (i = 0; i < len; i++)
{
const char *name = stp_string_list_param(slist, i)->name;
if (strcmp(name, "BlackDensity") == 0 ||
strcmp(name, "Saturation") == 0 ||
strcmp(name, "Gamma") == 0)
stp_scale_float_parameter(v, name,
stp_get_float_parameter(pv, name));
else if (strcmp(name, "GCRLower") == 0)
k_lower = stp_get_float_parameter(pv, "GCRLower");
else if (strcmp(name, "GCRUpper") == 0)
k_upper = stp_get_float_parameter(pv, "GCRUpper");
else if (strcmp(name, "BlackTrans") == 0)
k_transition = stp_get_float_parameter(pv, "BlackTrans");
else if (!stp_check_float_parameter(v, name, STP_PARAMETER_ACTIVE))
stp_set_float_parameter(v, name,
stp_get_float_parameter(pv, name));
}
stp_string_list_destroy(slist);
}
}
if (!stp_check_float_parameter(v, "GCRLower", STP_PARAMETER_ACTIVE))
stp_set_default_float_parameter(v, "GCRLower", k_lower);
if (!stp_check_float_parameter(v, "GCRUpper", STP_PARAMETER_ACTIVE))
stp_set_default_float_parameter(v, "GCRUpper", k_upper);
if (!stp_check_float_parameter(v, "BlackTrans", STP_PARAMETER_ACTIVE))
stp_set_default_float_parameter(v, "BlackTrans", k_transition);
}
static int
count_channels(const inkname_t *inks, int use_aux_channels)
{
int answer = 0;
int i;
for (i = 0; i < inks->channel_count; i++)
if (inks->channels[i].n_subchannels > 0)
answer += inks->channels[i].n_subchannels;
if (use_aux_channels)
for (i = 0; i < inks->aux_channel_count; i++)
if (inks->aux_channels[i].n_subchannels > 0)
answer += inks->aux_channels[i].n_subchannels;
return answer;
}
static int
compute_channel_count(const inkname_t *ink_type, int channel_limit,
int use_aux_channels)
{
int i;
int physical_channels = 0;
for (i = 0; i < channel_limit; i++)
{
const ink_channel_t *channel = &(ink_type->channels[i]);
if (channel)
physical_channels += channel->n_subchannels;
}
if (use_aux_channels)
for (i = 0; i < ink_type->aux_channel_count; i++)
if (ink_type->aux_channels[i].n_subchannels > 0)
physical_channels += ink_type->aux_channels[i].n_subchannels;
return physical_channels;
}
static double
get_double_param(const 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 void
setup_inks(stp_vars_t *v)
{
escp2_privdata_t *pd = get_privdata(v);
int i, j;
escp2_dropsize_t *drops;
const inkname_t *ink_type = pd->inkname;
const stp_vars_t *pv = pd->paper_type->v;
double gloss_scale = get_double_param(v, "Density");
drops = escp2_copy_dropsizes(v);
stp_init_debug_messages(v);
if (stp_check_float_parameter(v, "DropSize1", STP_PARAMETER_ACTIVE))
{
drops->dropsizes[0] = stp_get_float_parameter(v, "DropSize1");
if (drops->dropsizes[0] > 0 && drops->numdropsizes < 1)
drops->numdropsizes = 1;
}
if (stp_check_float_parameter(v, "DropSize2", STP_PARAMETER_ACTIVE))
{
drops->dropsizes[1] = stp_get_float_parameter(v, "DropSize2");
if (drops->dropsizes[1] > 0 && drops->numdropsizes < 2)
drops->numdropsizes = 2;
}
if (stp_check_float_parameter(v, "DropSize3", STP_PARAMETER_ACTIVE))
{
drops->dropsizes[2] = stp_get_float_parameter(v, "DropSize3");
if (drops->dropsizes[2] > 0 && drops->numdropsizes < 3)
drops->numdropsizes = 3;
}
STPI_ASSERT(drops->numdropsizes < (1 << escp2_bits(v)), v);
for (i = drops->numdropsizes - 1; i >= 0; i--)
{
if (drops->dropsizes[i] > 0)
break;
drops->numdropsizes--;
}
for (i = 0; i < pd->logical_channels; i++)
{
const ink_channel_t *channel = &(ink_type->channels[i]);
if (channel && channel->n_subchannels > 0)
{
int hue_curve_found = 0;
const char *param = channel->subchannels[0].channel_density;
shade_t *shades = escp2_copy_shades(v, i);
double userval = get_double_param(v, param);
STPI_ASSERT(shades->n_shades >= channel->n_subchannels, v);
if (ink_type->inkset != INKSET_EXTENDED)
{
if (strcmp(param, "BlackDensity") == 0)
stp_channel_set_black_channel(v, i);
else if (strcmp(param, "GlossDensity") == 0)
{
gloss_scale *= get_double_param(v, param);
}
}
for (j = 0; j < channel->n_subchannels; j++)
{
const char *subparam =
channel->subchannels[j].subchannel_value;
if (subparam &&
stp_check_float_parameter(v, subparam, STP_PARAMETER_ACTIVE))
shades->shades[j] = stp_get_float_parameter(v, subparam);
}
stp_dither_set_inks(v, i, 1.0, ink_darknesses[i % 8],
channel->n_subchannels, shades->shades,
drops->numdropsizes, drops->dropsizes);
for (j = 0; j < channel->n_subchannels; j++)
{
const char *subparam =
channel->subchannels[j].subchannel_scale;
double scale = userval * get_double_param(v, subparam);
scale *= get_double_param(v, "Density");
stp_channel_set_density_adjustment(v, i, j, scale);
subparam =
channel->subchannels[j].subchannel_transition;
if (subparam &&
stp_check_float_parameter(v, subparam, STP_PARAMETER_ACTIVE))
stp_channel_set_cutoff_adjustment
(v, i, j, stp_get_float_parameter(v, subparam));
else if (pv)
{
if (subparam &&
stp_check_float_parameter(pv, subparam, STP_PARAMETER_ACTIVE))
stp_channel_set_cutoff_adjustment
(v, i, j, stp_get_float_parameter(pv, subparam));
else if (stp_check_float_parameter(pv, "SubchannelCutoff", STP_PARAMETER_ACTIVE))
stp_channel_set_cutoff_adjustment
(v, i, j, stp_get_float_parameter(pv, "SubchannelCutoff"));
}
}
if (ink_type->inkset != INKSET_EXTENDED)
{
if (channel->hue_curve_name)
{
const stp_curve_t *curve = NULL;
curve = stp_get_curve_parameter(v, channel->hue_curve_name);
if (curve)
{
stp_channel_set_curve(v, i, curve);
hue_curve_found = 1;
}
}
if (channel->hue_curve && !hue_curve_found)
stp_channel_set_curve(v, i, channel->hue_curve);
}
escp2_free_shades(shades);
}
}
if (pd->use_aux_channels)
{
int base_count = pd->logical_channels;
for (i = 0; i < ink_type->aux_channel_count; i++)
{
const ink_channel_t *channel = &(ink_type->aux_channels[i]);
if (channel && channel->n_subchannels > 0)
{
int ch = i + base_count;
const char *param = channel->subchannels[0].channel_density;
shade_t *shades = escp2_copy_shades(v, ch);
double userval = get_double_param(v, param);
STPI_ASSERT(shades->n_shades >= channel->n_subchannels, v);
if (strcmp(param, "GlossDensity") == 0)
{
gloss_scale *= get_double_param(v, param);
stp_channel_set_gloss_channel(v, ch);
stp_channel_set_gloss_limit(v, gloss_scale);
}
for (j = 0; j < channel->n_subchannels; j++)
{
const char *subparam =
channel->subchannels[j].subchannel_value;
if (subparam &&
stp_check_float_parameter(v, subparam, STP_PARAMETER_ACTIVE))
shades->shades[j] = stp_get_float_parameter(v, subparam);
}
stp_dither_set_inks(v, ch, 1.0, ink_darknesses[ch % 8],
channel->n_subchannels, shades->shades,
drops->numdropsizes, drops->dropsizes);
for (j = 0; j < channel->n_subchannels; j++)
{
const char *subparam =
channel->subchannels[j].subchannel_scale;
double scale = userval * get_double_param(v, subparam);
scale *= get_double_param(v, "Density");
stp_channel_set_density_adjustment(v, ch, j, scale);
subparam =
channel->subchannels[j].subchannel_transition;
if (subparam &&
stp_check_float_parameter(v, subparam, STP_PARAMETER_ACTIVE))
stp_channel_set_cutoff_adjustment
(v, ch, j, stp_get_float_parameter(v, subparam));
else if (pv)
{
if (subparam &&
stp_check_float_parameter(pv, subparam, STP_PARAMETER_ACTIVE))
stp_channel_set_cutoff_adjustment
(v, ch, j, stp_get_float_parameter(pv, subparam));
else if (stp_check_float_parameter(pv, "SubchannelCutoff", STP_PARAMETER_ACTIVE))
stp_channel_set_cutoff_adjustment
(v, ch, j, stp_get_float_parameter(pv, "SubchannelCutoff"));
}
}
if (channel->hue_curve)
{
stp_curve_t *curve_tmp =
stp_curve_create_copy(channel->hue_curve);
(void) stp_curve_rescale(curve_tmp,
sqrt(1.0 / stp_get_float_parameter(v, "Gamma")),
STP_CURVE_COMPOSE_EXPONENTIATE,
STP_CURVE_BOUNDS_RESCALE);
stp_channel_set_curve(v, ch, curve_tmp);
stp_curve_destroy(curve_tmp);
}
escp2_free_shades(shades);
}
}
}
escp2_free_dropsizes(drops);
stp_flush_debug_messages(v);
}
static void
setup_head_offset(stp_vars_t *v)
{
escp2_privdata_t *pd = get_privdata(v);
int i;
int channel_id = 0;
int channel_limit = pd->logical_channels;
const inkname_t *ink_type = pd->inkname;
if (pd->channels_in_use > pd->logical_channels)
channel_limit = pd->channels_in_use;
pd->head_offset = stp_zalloc(sizeof(int) * channel_limit);
for (i = 0; i < pd->logical_channels; i++)
{
const ink_channel_t *channel = &(ink_type->channels[i]);
if (channel)
{
int j;
for (j = 0; j < channel->n_subchannels; j++)
{
pd->head_offset[channel_id] =
channel->subchannels[j].head_offset;
channel_id++;
}
}
}
if (pd->use_aux_channels)
{
for (i = 0; i < ink_type->aux_channel_count; i++)
{
const ink_channel_t *channel = &(ink_type->aux_channels[i]);
if (channel)
{
int j;
for (j = 0; j < channel->n_subchannels; j++)
{
pd->head_offset[channel_id] =
channel->subchannels[j].head_offset;
channel_id++;
}
}
}
}
if (pd->physical_channels == 1)
pd->head_offset[0] = 0;
pd->max_head_offset = 0;
if (pd->physical_channels > 1)
for (i = 0; i < pd->channels_in_use; i++)
{
pd->head_offset[i] = pd->head_offset[i] * pd->res->vres /
escp2_base_separation(v);
if (pd->head_offset[i] > pd->max_head_offset)
pd->max_head_offset = pd->head_offset[i];
}
}
static int
supports_split_channels(stp_vars_t *v)
{
escp2_privdata_t *pd = get_privdata(v);
int i;
int split_channel_count = -1;
for (i = 0; i < pd->logical_channels; i++)
{
int j;
if (pd->inkname->channels[i].n_subchannels > 0)
{
for (j = 0; j < pd->inkname->channels[i].n_subchannels; j++)
{
int split_count = pd->inkname->channels[i].subchannels[j].split_channel_count;
if (split_count == 0)
return 0;
else if (split_channel_count >= 0 && split_count != split_channel_count)
return 0;
else
split_channel_count = split_count;
}
}
}
if (split_channel_count > 0)
return split_channel_count;
else
return 0;
}
static void
setup_split_channels(stp_vars_t *v)
{
escp2_privdata_t *pd = get_privdata(v);
/*
* Set up the output channels
*/
pd->split_channel_count = supports_split_channels(v);
if (pd->split_channel_count)
{
if (pd->res->vres <
(escp2_base_separation(v) / escp2_black_nozzle_separation(v)))
{
int incr =
(escp2_base_separation(v) / escp2_black_nozzle_separation(v)) /
pd->res->vres;
pd->split_channel_count /= incr;
pd->nozzle_separation *= incr;
pd->nozzles /= incr;
pd->min_nozzles /= incr;
}
}
}
static void
setup_basic(stp_vars_t *v)
{
escp2_privdata_t *pd = get_privdata(v);
pd->advanced_command_set = escp2_has_advanced_command_set(v);
pd->command_set = stpi_escp2_get_cap(v, MODEL_COMMAND);
pd->variable_dots = stpi_escp2_has_cap(v, MODEL_VARIABLE_DOT, MODEL_VARIABLE_YES);
pd->has_graymode = stpi_escp2_has_cap(v, MODEL_GRAYMODE, MODEL_GRAYMODE_YES);
pd->preinit_sequence = escp2_preinit_sequence(v);
pd->preinit_remote_sequence = escp2_preinit_remote_sequence(v);
pd->deinit_remote_sequence = escp2_postinit_remote_sequence(v);
pd->borderless_sequence = escp2_vertical_borderless_sequence(v);
pd->base_separation = escp2_base_separation(v);
pd->resolution_scale = escp2_resolution_scale(v);
}
static void
setup_misc(stp_vars_t *v)
{
escp2_privdata_t *pd = get_privdata(v);
pd->input_slot = stpi_escp2_get_input_slot(v);
pd->paper_type = stpi_escp2_get_media_type(v, 0);
pd->ink_group = escp2_inkgroup(v);
pd->media_settings = stp_vars_create_copy(pd->paper_type->v);
stpi_escp2_set_media_size(pd->media_settings, v);
if (stp_check_float_parameter(v, "PageDryTime", STP_PARAMETER_ACTIVE))
stp_set_float_parameter(pd->media_settings, "PageDryTime",
stp_get_float_parameter(v, "PageDryTime"));
if (stp_check_float_parameter(v, "ScanDryTime", STP_PARAMETER_ACTIVE))
stp_set_float_parameter(pd->media_settings, "ScanDryTime",
stp_get_float_parameter(v, "ScanDryTime"));
if (stp_check_float_parameter(v, "ScanMinDryTime", STP_PARAMETER_ACTIVE))
stp_set_float_parameter(pd->media_settings, "ScanMinDryTime",
stp_get_float_parameter(v, "ScanMinDryTime"));
if (stp_check_int_parameter(v, "FeedAdjustment", STP_PARAMETER_ACTIVE))
stp_set_int_parameter(pd->media_settings, "FeedAdjustment",
stp_get_int_parameter(v, "FeedAdjustment"));
if (stp_check_int_parameter(v, "PaperThickness", STP_PARAMETER_ACTIVE))
stp_set_int_parameter(pd->media_settings, "PaperThickness",
stp_get_int_parameter(v, "PaperThickness"));
if (stp_check_int_parameter(v, "VacuumIntensity", STP_PARAMETER_ACTIVE))
stp_set_int_parameter(pd->media_settings, "VacuumIntensity",
stp_get_int_parameter(v, "VacuumIntensity"));
if (stp_check_int_parameter(v, "FeedSequence", STP_PARAMETER_ACTIVE))
stp_set_int_parameter(pd->media_settings, "FeedSequence",
stp_get_int_parameter(v, "FeedSequence"));
if (stp_check_int_parameter(v, "PrintMethod", STP_PARAMETER_ACTIVE))
stp_set_int_parameter(pd->media_settings, "PrintMethod",
stp_get_int_parameter(v, "PrintMethod"));
if (stp_check_int_parameter(v, "PlatenGap", STP_PARAMETER_ACTIVE))
stp_set_int_parameter(pd->media_settings, "PlatenGap",
stp_get_int_parameter(v, "PlatenGap"));
}
static void
allocate_channels(stp_vars_t *v, int line_length)
{
escp2_privdata_t *pd = get_privdata(v);
const inkname_t *ink_type = pd->inkname;
int i, j, k;
int channel_id = 0;
int split_id = 0;
pd->cols = stp_zalloc(sizeof(unsigned char *) * pd->channels_in_use);
pd->channels =
stp_zalloc(sizeof(physical_subchannel_t *) * pd->channels_in_use);
if (pd->split_channel_count)
pd->split_channels = stp_zalloc(sizeof(short) * pd->channels_in_use *
pd->split_channel_count);
for (i = 0; i < pd->logical_channels; i++)
{
const ink_channel_t *channel = &(ink_type->channels[i]);
if (channel)
{
for (j = 0; j < channel->n_subchannels; j++)
{
const physical_subchannel_t *sc = &(channel->subchannels[j]);
pd->cols[channel_id] = stp_zalloc(line_length);
pd->channels[channel_id] = sc;
stp_dither_add_channel(v, pd->cols[channel_id], i, j);
if (pd->split_channel_count)
{
for (k = 0; k < pd->split_channel_count; k++)
pd->split_channels[split_id++] = sc->split_channels[k];
}
channel_id++;
}
}
}
if (pd->use_aux_channels && ink_type->aux_channel_count > 0)
{
for (i = 0; i < ink_type->aux_channel_count; i++)
{
const ink_channel_t *channel = &(ink_type->aux_channels[i]);
for (j = 0; j < channel->n_subchannels; j++)
{
const physical_subchannel_t *sc = &(channel->subchannels[j]);
pd->cols[channel_id] = stp_zalloc(line_length);
pd->channels[channel_id] = sc;
stp_dither_add_channel(v, pd->cols[channel_id],
i + pd->logical_channels, j);
if (pd->split_channel_count)
{
for (k = 0; k < pd->split_channel_count; k++)
pd->split_channels[split_id++] = sc->split_channels[k];
}
channel_id++;
}
}
}
stp_set_string_parameter(v, "STPIOutputType", escp2_describe_output(v));
}
static unsigned
gcd(unsigned a, unsigned b)
{
unsigned tmp;
if (b > a)
{
tmp = a;
a = b;
b = tmp;
}
while (1)
{
tmp = a % b;
if (tmp == 0)
return b;
a = b;
b = tmp;
}
}
static unsigned
lcm(unsigned a, unsigned b)
{
if (a == b)
return a;
else
return a * b / gcd(a, b);
}
/* XXX -- How do we handle 300 DPI base? */
static int
adjusted_vertical_resolution(const stp_vars_t *v, const res_t *res)
{
if (res->vres >= escp2_base_separation(v) * 2)
return res->vres;
else if (res->hres >= escp2_base_separation(v) * 2) /* Special case 720x360 */
return escp2_base_separation(v) * 2;
else if (res->vres % 90 == 0)
return res->vres;
else
return lcm(res->hres, res->vres); /* E. g. 360x240 => 720 */
}
static int
adjusted_horizontal_resolution(const stp_vars_t *v, const res_t *res)
{
/* XXX -- How do we handle 300 DPI base? */
if (res->vres % 90 == 0)
return res->hres;
else
return lcm(res->hres, res->vres); /* E. g. 360x240 => 720 */
}
static void
setup_resolution(stp_vars_t *v)
{
escp2_privdata_t *pd = get_privdata(v);
const res_t *res = stpi_escp2_find_resolution(v);
int vertical = adjusted_vertical_resolution(v, res);
int horizontal = adjusted_horizontal_resolution(v, res);
pd->res = res;
pd->use_extended_commands =
escp2_use_extended_commands(v, !(pd->res->command));
pd->physical_xdpi = escp2_base_res(v);
if (pd->physical_xdpi > pd->res->hres)
pd->physical_xdpi = pd->res->hres;
if (pd->use_extended_commands)
{
pd->unit_scale = MAX(escp2_max_hres(v), escp2_max_vres(v));
pd->horizontal_units = horizontal;
pd->micro_units = horizontal;
}
else
{
/* Hard-coded values for older printers */
pd->unit_scale = 3600;
if (pd->res->hres <= 720)
pd->micro_units = vertical;
else
pd->micro_units = horizontal;
pd->horizontal_units = vertical;
}
/* Note hard-coded 1440 -- from Epson manuals */
if (stpi_escp2_has_cap(v, MODEL_COMMAND, MODEL_COMMAND_1999) &&
stpi_escp2_has_cap(v, MODEL_VARIABLE_DOT, MODEL_VARIABLE_NO))
pd->micro_units = 1440;
pd->vertical_units = vertical;
pd->page_management_units = vertical;
}
static void
setup_softweave_parameters(stp_vars_t *v)
{
escp2_privdata_t *pd = get_privdata(v);
pd->horizontal_passes = pd->res->printed_hres / pd->physical_xdpi;
if (pd->physical_channels == 1 &&
(pd->inkname->channels[0].subchannels->split_channel_count > 1 ||
(pd->res->vres >=
(escp2_base_separation(v) / escp2_black_nozzle_separation(v)))) &&
(escp2_max_black_resolution(v) < 0 ||
pd->res->vres <= escp2_max_black_resolution(v)) &&
escp2_black_nozzles(v))
pd->use_black_parameters = 1;
else
pd->use_black_parameters = 0;
if (pd->use_fast_360)
{
pd->nozzles = escp2_fast_nozzles(v);
pd->nozzle_separation = escp2_fast_nozzle_separation(v);
pd->nozzle_start = escp2_fast_nozzle_start(v);
pd->min_nozzles = escp2_min_fast_nozzles(v);
}
else if (pd->use_black_parameters)
{
pd->nozzles = escp2_black_nozzles(v);
pd->nozzle_separation = escp2_black_nozzle_separation(v);
pd->nozzle_start = escp2_black_nozzle_start(v);
pd->min_nozzles = escp2_min_black_nozzles(v);
}
else
{
pd->nozzles = escp2_nozzles(v);
pd->nozzle_separation = escp2_nozzle_separation(v);
pd->nozzle_start = escp2_nozzle_start(v);
pd->min_nozzles = escp2_min_nozzles(v);
}
}
static void
setup_printer_weave_parameters(stp_vars_t *v)
{
escp2_privdata_t *pd = get_privdata(v);
pd->horizontal_passes = 1;
pd->nozzles = 1;
pd->nozzle_separation = 1;
pd->nozzle_start = 0;
pd->min_nozzles = 1;
if (pd->physical_channels == 1)
pd->use_black_parameters = 1;
else
pd->use_black_parameters = 0;
pd->extra_vertical_passes = 1;
}
static void
setup_head_parameters(stp_vars_t *v)
{
escp2_privdata_t *pd = get_privdata(v);
/*
* Set up the output channels
*/
if (strcmp(stp_get_string_parameter(v, "PrintingMode"), "BW") == 0)
pd->logical_channels = 1;
else
pd->logical_channels = pd->inkname->channel_count;
pd->physical_channels =
compute_channel_count(pd->inkname, pd->logical_channels,
pd->use_aux_channels);
if (pd->physical_channels == 0)
{
pd->inkname = stpi_escp2_get_default_black_inkset();
pd->physical_channels =
compute_channel_count(pd->inkname, pd->logical_channels,
pd->use_aux_channels);
}
pd->printer_weave = get_printer_weave(v);
pd->extra_vertical_passes = 1;
if (stp_check_int_parameter(v, "BandEnhancement", STP_PARAMETER_ACTIVE))
pd->extra_vertical_passes =
1 << stp_get_int_parameter(v, "BandEnhancement");
if (stpi_escp2_has_cap(v, MODEL_FAST_360, MODEL_FAST_360_YES) &&
(pd->inkname->inkset == INKSET_CMYK || pd->physical_channels == 1) &&
pd->res->hres == pd->physical_xdpi && pd->res->vres == 360)
pd->use_fast_360 = 1;
else
pd->use_fast_360 = 0;
/*
* Set up the printer-specific parameters (weaving)
*/
pd->use_printer_weave = use_printer_weave(v);
if (pd->use_printer_weave)
setup_printer_weave_parameters(v);
else
setup_softweave_parameters(v);
pd->separation_rows = escp2_separation_rows(v);
pd->pseudo_separation_rows = escp2_pseudo_separation_rows(v);
pd->extra_720dpi_separation = escp2_extra_720dpi_separation(v);
pd->bidirectional_upper_limit = escp2_bidirectional_upper_limit(v);
if (pd->horizontal_passes == 0)
pd->horizontal_passes = 1;
setup_head_offset(v);
setup_split_channels(v);
if (stp_check_string_parameter(v, "Duplex", STP_PARAMETER_ACTIVE))
{
const char *duplex = stp_get_string_parameter(v, "Duplex");
if (strcmp(duplex, "DuplexTumble") == 0)
pd->duplex = DUPLEX_TUMBLE;
else if (strcmp(duplex, "DuplexNoTumble") == 0)
pd->duplex = DUPLEX_NO_TUMBLE;
else
pd->duplex = 0;
}
if (pd->duplex)
pd->extra_vertical_feed = 0;
else
pd->extra_vertical_feed = escp2_extra_feed(v);
if (strcmp(stp_get_string_parameter(v, "PrintingMode"), "BW") == 0 &&
pd->physical_channels == 1)
{
if (pd->use_black_parameters)
pd->initial_vertical_offset =
(escp2_black_initial_vertical_offset(v) -
(escp2_black_nozzle_start(v) * (int) escp2_black_nozzle_separation(v))) *
pd->page_management_units /
escp2_base_separation(v);
else
pd->initial_vertical_offset = pd->head_offset[0] +
((escp2_initial_vertical_offset(v) -
(escp2_nozzle_start(v) * (int) escp2_nozzle_separation(v))) *
pd->page_management_units / escp2_base_separation(v));
}
else
pd->initial_vertical_offset =
(escp2_initial_vertical_offset(v) -
(escp2_nozzle_start(v) * (int) escp2_nozzle_separation(v))) *
pd->page_management_units /
escp2_base_separation(v);
pd->printing_initial_vertical_offset = 0;
pd->bitwidth = escp2_bits(v);
}
static void
setup_page(stp_vars_t *v)
{
escp2_privdata_t *pd = get_privdata(v);
const input_slot_t *input_slot = stpi_escp2_get_input_slot(v);
stp_dimension_t extra_left = 0;
stp_dimension_t extra_top = 0;
stp_dimension_t hub_size = 0;
int min_horizontal_alignment = escp2_min_horizontal_position_alignment(v);
int base_horizontal_alignment =
pd->res->hres / escp2_base_horizontal_position_alignment(v);
int required_horizontal_alignment =
MAX(min_horizontal_alignment, base_horizontal_alignment);
const char *cd_type = stp_get_string_parameter(v, "PageSize");
if (cd_type && (strcmp(cd_type, "CDCustom") == 0 ))
{
stp_dimension_t outer_diameter =
stp_get_dimension_parameter(v, "CDOuterDiameter");
stp_set_page_width(v, outer_diameter);
stp_set_page_height(v, outer_diameter);
stp_set_width(v, outer_diameter);
stp_set_height(v, outer_diameter);
hub_size = stp_get_dimension_parameter(v, "CDInnerDiameter");
}
else
{
const char *inner_radius_name = stp_get_string_parameter(v, "CDInnerRadius");
hub_size = 43.0 * 10.0 * 72.0 / 254.0; /* 43 mm standard CD hub */
if (inner_radius_name && strcmp(inner_radius_name, "Small") == 0)
hub_size = 16.0 * 10.0 * 72.0 / 254.0; /* 15 mm prints to the hole -
play safe and print 16 mm */
}
escp2_media_size(v, &(pd->page_true_width), &(pd->page_true_height));
/* Don't use full bleed mode if the paper itself has a margin */
if (pd->page_left > 0 || pd->page_top > 0)
stp_set_boolean_parameter(v, "FullBleed", 0);
if (stpi_escp2_has_cap(v, MODEL_ZEROMARGIN, MODEL_ZEROMARGIN_FULL) &&
((!input_slot || !(input_slot->is_cd))))
{
pd->page_extra_height =
max_nozzle_span(v) * pd->page_management_units /
escp2_base_separation(v);
if (stp_get_boolean_parameter(v, "FullBleed"))
pd->paper_extra_bottom = 0;
else
pd->paper_extra_bottom = escp2_paper_extra_bottom(v);
}
else if (stpi_escp2_has_cap(v, MODEL_ZEROMARGIN, MODEL_ZEROMARGIN_YES) &&
(stp_get_boolean_parameter(v, "FullBleed")) &&
((!input_slot || !(input_slot->is_cd))))
{
pd->paper_extra_bottom = 0;
pd->page_extra_height =
escp2_zero_margin_offset(v) * pd->page_management_units /
escp2_base_separation(v);
}
else if (stpi_escp2_has_cap(v, MODEL_ZEROMARGIN, MODEL_ZEROMARGIN_RESTR) &&
(stp_get_boolean_parameter(v, "FullBleed")) &&
((!input_slot || !(input_slot->is_cd))))
{
pd->paper_extra_bottom = 0;
pd->page_extra_height = 0;
}
else if (stpi_escp2_printer_supports_duplex(v) && !pd->duplex)
{
pd->paper_extra_bottom = escp2_paper_extra_bottom(v);
pd->page_extra_height =
max_nozzle_span(v) * pd->page_management_units /
escp2_base_separation(v);
}
else
{
if (input_slot)
pd->page_extra_height = input_slot->extra_height *
pd->page_management_units / escp2_base_separation(v);
else
pd->page_extra_height = 0;
if (pd->duplex)
pd->paper_extra_bottom = 0;
else
pd->paper_extra_bottom = escp2_paper_extra_bottom(v);
}
internal_imageable_area(v, 0, 0, &pd->page_left, &pd->page_right,
&pd->page_bottom, &pd->page_top);
stp_set_left(v, froundto(stp_get_left(v), pd->res->hres, 72));
stp_set_width(v, froundto(stp_get_width(v), pd->res->hres, 72));
stp_set_top(v, froundto(stp_get_top(v), pd->res->hres, 72));
stp_set_height(v, froundto(stp_get_height(v), pd->res->hres, 72));
if (input_slot && input_slot->is_cd && escp2_cd_x_offset(v) > 0)
{
stp_dimension_t left_center = escp2_cd_x_offset(v) +
stp_get_dimension_parameter(v, "CDXAdjustment");
stp_dimension_t top_center = escp2_cd_y_offset(v) +
stp_get_dimension_parameter(v, "CDYAdjustment");
pd->page_true_height = pd->page_bottom - pd->page_top;
pd->page_true_width = pd->page_right - pd->page_left;
pd->paper_extra_bottom = 0;
pd->page_extra_height = 0;
stp_set_left(v, stp_get_left(v) - pd->page_left);
stp_set_top(v, stp_get_top(v) - pd->page_top);
pd->page_right -= pd->page_left;
pd->page_bottom -= pd->page_top;
pd->page_top = 0;
pd->page_left = 0;
extra_top = top_center - (pd->page_bottom / 2.0);
extra_left = left_center - (pd->page_right / 2.0);
pd->cd_inner_radius = hub_size * pd->micro_units / 72.0 / 2.0;
pd->cd_outer_radius = pd->page_right * pd->micro_units / 72.0 / 2.0;
pd->cd_x_offset =
((pd->page_right / 2.0) - stp_get_left(v)) * pd->micro_units / 72.0;
pd->cd_y_offset = stp_get_top(v) * pd->res->printed_vres / 72.0;
if (escp2_cd_page_height(v))
{
pd->page_right = escp2_cd_page_width(v);
pd->page_bottom = escp2_cd_page_height(v);
pd->page_true_height = escp2_cd_page_height(v);
pd->page_true_width = escp2_cd_page_width(v);
}
}
pd->page_right += extra_left + 1;
pd->page_width = pd->page_right - pd->page_left;
pd->image_left = stp_get_left(v) - pd->page_left + extra_left;
pd->image_width = stp_get_width(v);
pd->image_scaled_width = pd->image_width * pd->res->hres / 72;
pd->image_printed_width = pd->image_width * pd->res->printed_hres / 72;
if (pd->split_channel_count >= 1)
{
pd->split_channel_width =
((pd->image_printed_width + pd->horizontal_passes - 1) /
pd->horizontal_passes);
pd->split_channel_width = (pd->split_channel_width + 7) / 8;
pd->split_channel_width *= pd->bitwidth;
if (!(stp_get_debug_level() & STP_DBG_NO_COMPRESSION))
{
pd->comp_buf =
stp_malloc(stp_compute_tiff_linewidth(v, pd->split_channel_width));
}
}
pd->image_left_position = pd->image_left * pd->micro_units / 72;
pd->zero_margin_offset = escp2_zero_margin_offset(v);
if (supports_borderless(v) &&
pd->advanced_command_set &&
((!input_slot || !(input_slot->is_cd)) &&
stp_get_boolean_parameter(v, "FullBleed")))
{
int margin = escp2_micro_left_margin(v);
int sep = escp2_base_separation(v);
pd->image_left_position +=
(pd->zero_margin_offset - margin) * pd->micro_units / sep;
}
/*
* Many printers print extremely slowly if the starting position
* is not aligned to 1/180"
*/
if (required_horizontal_alignment > 1)
pd->image_left_position =
(pd->image_left_position / required_horizontal_alignment) *
required_horizontal_alignment;
pd->page_bottom += extra_top + 1;
pd->page_height = pd->page_bottom - pd->page_top;
pd->image_top = stp_get_top(v) - pd->page_top + extra_top;
pd->image_height = stp_get_height(v);
pd->image_scaled_height = pd->image_height * pd->res->vres / 72;
pd->image_printed_height = pd->image_height * pd->res->printed_vres / 72;
if (input_slot && input_slot->roll_feed_cut_flags)
{
pd->page_true_height += 4; /* Empirically-determined constants */
pd->page_top += 2;
pd->page_bottom += 2;
pd->image_top += 2;
pd->page_height += 2;
}
}
static void
set_mask(unsigned char *cd_mask, int x_center, int scaled_x_where,
int limit, int expansion, int invert)
{
int clear_val = invert ? 255 : 0;
int set_val = invert ? 0 : 255;
int bytesize = 8 / expansion;
int byteextra = bytesize - 1;
int first_x_on = x_center - scaled_x_where;
int first_x_off = x_center + scaled_x_where;
if (first_x_on < 0)
first_x_on = 0;
if (first_x_on > limit)
first_x_on = limit;
if (first_x_off < 0)
first_x_off = 0;
if (first_x_off > limit)
first_x_off = limit;
first_x_on += byteextra;
if (first_x_off > (first_x_on - byteextra))
{
int first_x_on_byte = first_x_on / bytesize;
int first_x_on_mod = expansion * (byteextra - (first_x_on % bytesize));
int first_x_on_extra = ((1 << first_x_on_mod) - 1) ^ clear_val;
int first_x_off_byte = first_x_off / bytesize;
int first_x_off_mod = expansion * (byteextra - (first_x_off % bytesize));
int first_x_off_extra = ((1 << 8) - (1 << first_x_off_mod)) ^ clear_val;
if (first_x_off_byte < first_x_on_byte)
{
/* This can happen, if 6 or fewer points are turned on */
cd_mask[first_x_on_byte] = first_x_on_extra & first_x_off_extra;
}
else
{
if (first_x_on_extra != clear_val)
cd_mask[first_x_on_byte - 1] = first_x_on_extra;
if (first_x_off_byte > first_x_on_byte)
memset(cd_mask + first_x_on_byte, set_val,
first_x_off_byte - first_x_on_byte);
if (first_x_off_extra != clear_val)
cd_mask[first_x_off_byte] = first_x_off_extra;
}
}
}
static int
escp2_print_data(stp_vars_t *v, stp_image_t *image)
{
escp2_privdata_t *pd = get_privdata(v);
int errdiv = stp_image_height(image) / pd->image_printed_height;
int errmod = stp_image_height(image) % pd->image_printed_height;
int errval = 0;
int errlast = -1;
int errline = 0;
int y;
stp_dimension_t outer_r_sq = 0;
stp_dimension_t inner_r_sq = 0;
int x_center = pd->cd_x_offset * pd->res->printed_hres / pd->micro_units;
unsigned char *cd_mask = NULL;
if (pd->cd_outer_radius > 0)
{
cd_mask = stp_malloc(1 + (pd->image_printed_width + 7) / 8);
outer_r_sq = pd->cd_outer_radius * pd->cd_outer_radius;
inner_r_sq = pd->cd_inner_radius * pd->cd_inner_radius;
}
for (y = 0; y < pd->image_printed_height; y ++)
{
int duplicate_line = 1;
unsigned zero_mask;
if (errline != errlast)
{
errlast = errline;
duplicate_line = 0;
if (stp_color_get_row(v, image, errline, &zero_mask))
return 2;
}
if (cd_mask)
{
stp_dimension_t y_distance_from_center =
pd->cd_outer_radius -
((y + pd->cd_y_offset) * pd->micro_units / pd->res->printed_vres);
if (y_distance_from_center < 0)
y_distance_from_center = -y_distance_from_center;
memset(cd_mask, 0, (pd->image_printed_width + 7) / 8);
if (y_distance_from_center < pd->cd_outer_radius)
{
stp_dimension_t y_sq = y_distance_from_center * y_distance_from_center;
stp_dimension_t x_where = sqrt(outer_r_sq - y_sq);
int scaled_x_where = x_where * pd->res->printed_hres / pd->micro_units;
set_mask(cd_mask, x_center, scaled_x_where,
pd->image_printed_width, 1, 0);
if (y_distance_from_center < pd->cd_inner_radius)
{
x_where = sqrt(inner_r_sq - y_sq);
scaled_x_where = x_where * pd->res->printed_hres / pd->micro_units;
set_mask(cd_mask, x_center, scaled_x_where,
pd->image_printed_width, 1, 1);
}
}
}
stp_dither(v, y, duplicate_line, zero_mask, cd_mask);
stp_write_weave(v, pd->cols);
errval += errmod;
errline += errdiv;
if (errval >= pd->image_printed_height)
{
errval -= pd->image_printed_height;
errline ++;
}
}
if (cd_mask)
stp_free(cd_mask);
return 1;
}
static int
escp2_print_page(stp_vars_t *v, stp_image_t *image)
{
int status;
escp2_privdata_t *pd = get_privdata(v);
int line_width = (pd->image_printed_width + 7) / 8 * pd->bitwidth;
int weave_pattern = STP_WEAVE_ZIGZAG;
if (stp_check_string_parameter(v, "Weave", STP_PARAMETER_ACTIVE))
{
const char *weave = stp_get_string_parameter(v, "Weave");
if (strcmp(weave, "Alternate") == 0)
weave_pattern = STP_WEAVE_ZIGZAG;
else if (strcmp(weave, "Ascending") == 0)
weave_pattern = STP_WEAVE_ASCENDING;
else if (strcmp(weave, "Descending") == 0)
weave_pattern = STP_WEAVE_DESCENDING;
else if (strcmp(weave, "Ascending2X") == 0)
weave_pattern = STP_WEAVE_ASCENDING_2X;
else if (strcmp(weave, "Staggered") == 0)
weave_pattern = STP_WEAVE_STAGGERED;
}
stp_initialize_weave
(v,
pd->nozzles,
pd->nozzle_separation * pd->res->vres / escp2_base_separation(v),
pd->horizontal_passes,
pd->res->vertical_passes * pd->extra_vertical_passes,
1,
pd->channels_in_use,
pd->bitwidth,
pd->image_printed_width,
pd->image_printed_height,
((pd->page_extra_height * pd->res->vres / pd->vertical_units) +
(pd->image_top * pd->res->vres / 72)),
(pd->page_extra_height +
(pd->page_height + pd->extra_vertical_feed) * pd->res->vres / 72),
pd->head_offset,
weave_pattern,
stpi_escp2_flush_pass,
(((stp_get_debug_level() & STP_DBG_NO_COMPRESSION) ||
pd->split_channel_count > 0) ?
stp_fill_uncompressed : stp_fill_tiff),
(((stp_get_debug_level() & STP_DBG_NO_COMPRESSION) ||
pd->split_channel_count > 0) ?
stp_pack_uncompressed : stp_pack_tiff),
(((stp_get_debug_level() & STP_DBG_NO_COMPRESSION) ||
pd->split_channel_count > 0) ?
stp_compute_uncompressed_linewidth : stp_compute_tiff_linewidth));
stp_dither_init(v, image, pd->image_printed_width, pd->res->printed_hres,
pd->res->printed_vres);
allocate_channels(v, line_width);
adjust_print_quality(v);
(void) stp_color_init(v, image, 65536);
/* stpi_dither_set_expansion(v, pd->res->hres / pd->res->printed_hres); */
setup_inks(v);
status = escp2_print_data(v, image);
stp_flush_all(v);
stpi_escp2_terminate_page(v);
return status;
}
/*
* 'escp2_print()' - Print an image to an EPSON printer.
*/
static int
escp2_do_print(stp_vars_t *v, stp_image_t *image, int print_op)
{
int status = 1;
int i;
escp2_privdata_t *pd;
if (strcmp(stp_get_string_parameter(v, "PrintingMode"), "BW") == 0 &&
(stp_get_string_parameter(v, "InkType") &&
(strcmp(stp_get_string_parameter(v, "InkType"), "RGB") == 0 ||
strcmp(stp_get_string_parameter(v, "InkType"), "CMY") == 0 ||
strcmp(stp_get_string_parameter(v, "InkType"), "CMYRB") == 0 ||
strcmp(stp_get_string_parameter(v, "InkType"), "CMYRBG") == 0 ||
strcmp(stp_get_string_parameter(v, "InkType"), "CMYRO") == 0 ||
strcmp(stp_get_string_parameter(v, "InkType"), "CMYROG") == 0 ||
strcmp(stp_get_string_parameter(v, "InkType"), "PhotoCMY") == 0 ||
strcmp(stp_get_string_parameter(v, "InkType"), "RGBG") == 0)))
{
stp_eprintf(v, "Warning: Inkset %s not available in BW\n",
stp_get_string_parameter(v, "InkType"));
stp_set_string_parameter(v, "InkType", "CMYK");
}
if (!stp_verify(v))
{
stp_eprintf(v, _("Print options not verified; cannot print.\n"));
return 0;
}
if (strcmp(stp_get_string_parameter(v, "InputImageType"), "Raw") == 0 &&
!set_raw_ink_type(v))
return 0;
int page_number = stp_get_int_parameter(v, "PageNumber");
pd = (escp2_privdata_t *) stp_zalloc(sizeof(escp2_privdata_t));
pd->printed_something = 0;
pd->last_color = -1;
pd->last_pass_offset = 0;
pd->last_pass = -1;
pd->send_zero_pass_advance =
stpi_escp2_has_cap(v, MODEL_SEND_ZERO_ADVANCE, MODEL_SEND_ZERO_ADVANCE_YES);
stp_allocate_component_data(v, "Driver", NULL, NULL, pd);
pd->inkname = get_inktype(v);
if (pd->inkname && pd->inkname->inkset != INKSET_EXTENDED &&
stp_check_boolean_parameter(v, "UseGloss", STP_PARAMETER_ACTIVE) &&
stp_get_boolean_parameter(v, "UseGloss"))
pd->use_aux_channels = 1;
else
pd->use_aux_channels = 0;
if (pd->inkname && pd->inkname->inkset == INKSET_QUADTONE &&
strcmp(stp_get_string_parameter(v, "PrintingMode"), "BW") != 0)
{
stp_eprintf(v, "Warning: Quadtone inkset only available in MONO\n");
stp_set_string_parameter(v, "PrintingMode", "BW");
}
if (pd->inkname && pd->inkname->inkset == INKSET_HEXTONE &&
strcmp(stp_get_string_parameter(v, "PrintingMode"), "BW") != 0)
{
stp_eprintf(v, "Warning: Hextone inkset only available in MONO\n");
stp_set_string_parameter(v, "PrintingMode", "BW");
}
pd->channels_in_use = count_channels(pd->inkname, pd->use_aux_channels);
setup_basic(v);
setup_resolution(v);
setup_head_parameters(v);
setup_page(v);
setup_misc(v);
adjust_density_and_ink_type(v);
if (print_op & OP_JOB_START)
stpi_escp2_init_printer(v);
if (print_op & OP_JOB_PRINT)
{
stp_image_init(image);
if ((page_number & 1) && pd->duplex &&
((pd->duplex & pd->input_slot->duplex) == 0))
/* If the hardware can't do the duplex operation, we need to
emulate it in software */
image = stpi_buffer_image(image, BUFFER_FLAG_FLIP_X | BUFFER_FLAG_FLIP_Y);
status = escp2_print_page(v, image);
stp_image_conclude(image);
}
if (print_op & OP_JOB_END)
stpi_escp2_deinit_printer(v);
if (pd->head_offset)
stp_free(pd->head_offset);
/*
* Cleanup...
*/
if (pd->cols)
{
for (i = 0; i < pd->channels_in_use; i++)
if (pd->cols[i])
stp_free(pd->cols[i]);
stp_free(pd->cols);
}
if (pd->media_settings)
stp_vars_destroy(pd->media_settings);
if (pd->channels)
stp_free(pd->channels);
if (pd->split_channels)
stp_free(pd->split_channels);
if (pd->comp_buf)
stp_free(pd->comp_buf);
stp_free(pd);
return status;
}
static int
escp2_print(const stp_vars_t *v, stp_image_t *image)
{
stp_vars_t *nv = stp_vars_create_copy(v);
int op = OP_JOB_PRINT;
int status;
if (!stp_get_string_parameter(v, "JobMode") ||
strcmp(stp_get_string_parameter(v, "JobMode"), "Page") == 0)
op = OP_JOB_START | OP_JOB_PRINT | OP_JOB_END;
status = escp2_do_print(nv, image, op);
stp_vars_destroy(nv);
return status;
}
static int
escp2_job_start(const stp_vars_t *v, stp_image_t *image)
{
stp_vars_t *nv = stp_vars_create_copy(v);
int status;
status = escp2_do_print(nv, image, OP_JOB_START);
stp_vars_destroy(nv);
return status;
}
static int
escp2_job_end(const stp_vars_t *v, stp_image_t *image)
{
stp_vars_t *nv = stp_vars_create_copy(v);
int status;
status = escp2_do_print(nv, image, OP_JOB_END);
stp_vars_destroy(nv);
return status;
}
static const stp_printfuncs_t print_escp2_printfuncs =
{
escp2_list_parameters,
escp2_parameters,
escp2_media_size,
escp2_imageable_area,
escp2_maximum_imageable_area,
escp2_limit,
escp2_print,
escp2_describe_resolution,
escp2_describe_output,
stp_verify_printer_params,
escp2_job_start,
escp2_job_end,
NULL,
stpi_standard_describe_papersize
};
static stp_family_t print_escp2_module_data =
{
&print_escp2_printfuncs,
NULL
};
static int
print_escp2_module_init(void)
{
hue_curve_bounds = stp_curve_create_from_string
("\n"
"\n"
"\n"
"\n"
"1 1\n"
"\n"
"\n"
"");
return stpi_family_register(print_escp2_module_data.printer_list);
}
static int
print_escp2_module_exit(void)
{
return stpi_family_unregister(print_escp2_module_data.printer_list);
}
/* Module header */
#define stp_module_version print_escp2_LTX_stp_module_version
#define stp_module_data print_escp2_LTX_stp_module_data
stp_module_version_t stp_module_version = {0, 0};
stp_module_t stp_module_data =
{
"escp2",
VERSION,
"Epson family driver",
STP_MODULE_CLASS_FAMILY,
NULL,
print_escp2_module_init,
print_escp2_module_exit,
(void *) &print_escp2_module_data
};