00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029 #ifdef HAVE_CONFIG_H
00030 #include <config.h>
00031 #endif
00032 #include <gimp-print/gimp-print.h>
00033 #include <gimp-print/gimp-print-intl-internal.h>
00034 #include "gimp-print-internal.h"
00035 #include <string.h>
00036 #include <assert.h>
00037 #include <math.h>
00038 #include "print-escp2.h"
00039
00040 #ifdef __GNUC__
00041 #define inline __inline__
00042 #endif
00043
00044 #define OP_JOB_START 1
00045 #define OP_JOB_PRINT 2
00046 #define OP_JOB_END 4
00047
00048 #define MAX(a, b) ((a) > (b) ? (a) : (b))
00049
00050 typedef struct
00051 {
00052 const char *attr_name;
00053 short bit_shift;
00054 short bit_width;
00055 } escp2_printer_attr_t;
00056
00057 static const escp2_printer_attr_t escp2_printer_attrs[] =
00058 {
00059 { "command_mode", 0, 4 },
00060 { "horizontal_zero_margin", 4, 1 },
00061 { "rollfeed", 5, 1 },
00062 { "variable_mode", 6, 1 },
00063 { "graymode", 7, 1 },
00064 { "vacuum", 8, 1 },
00065 { "fast_360", 9, 1 },
00066 { "send_zero_advance", 10, 1 },
00067 { "supports_ink_change", 11, 1 },
00068 };
00069
00070 typedef struct
00071 {
00072 unsigned count;
00073 const char *name;
00074 } channel_count_t;
00075
00076 static const channel_count_t escp2_channel_counts[] =
00077 {
00078 { 1, "1" },
00079 { 2, "2" },
00080 { 3, "3" },
00081 { 4, "4" },
00082 { 5, "5" },
00083 { 6, "6" },
00084 { 7, "7" },
00085 { 8, "8" },
00086 { 9, "9" },
00087 { 10, "10" },
00088 { 11, "11" },
00089 { 12, "12" },
00090 { 13, "13" },
00091 { 14, "14" },
00092 { 15, "15" },
00093 { 16, "16" },
00094 { 17, "17" },
00095 { 18, "18" },
00096 { 19, "19" },
00097 { 20, "20" },
00098 { 21, "21" },
00099 { 22, "22" },
00100 { 23, "23" },
00101 { 24, "24" },
00102 { 25, "25" },
00103 { 26, "26" },
00104 { 27, "27" },
00105 { 28, "28" },
00106 { 29, "29" },
00107 { 30, "30" },
00108 { 31, "31" },
00109 { 32, "32" },
00110 };
00111
00112 static int escp2_channel_counts_count =
00113 sizeof(escp2_channel_counts) / sizeof(channel_count_t);
00114
00115 static const double ink_darknesses[] =
00116 {
00117 1.0, 0.31 / .4, 0.61 / .96, 0.08, 0.31 * 0.33 / .4, 0.61 * 0.33 / .96, 0.33, 1.0
00118 };
00119
00120 #define INCH(x) (72 * x)
00121
00122 static const res_t *escp2_find_resolution(const stp_vars_t *v);
00123
00124 #define PARAMETER_INT(s) \
00125 { \
00126 "escp2_" #s, "escp2_" #s, N_("Advanced Printer Functionality"), NULL, \
00127 STP_PARAMETER_TYPE_INT, STP_PARAMETER_CLASS_FEATURE, \
00128 STP_PARAMETER_LEVEL_INTERNAL, 0, 1, -1, 1, 0 \
00129 }
00130
00131 #define PARAMETER_INT_RO(s) \
00132 { \
00133 "escp2_" #s, "escp2_" #s, N_("Advanced Printer Functionality"), NULL, \
00134 STP_PARAMETER_TYPE_INT, STP_PARAMETER_CLASS_FEATURE, \
00135 STP_PARAMETER_LEVEL_INTERNAL, 0, 1, -1, 1, 1 \
00136 }
00137
00138 #define PARAMETER_RAW(s) \
00139 { \
00140 "escp2_" #s, "escp2_" #s, N_("Advanced Printer Functionality"), NULL, \
00141 STP_PARAMETER_TYPE_RAW, STP_PARAMETER_CLASS_FEATURE, \
00142 STP_PARAMETER_LEVEL_INTERNAL, 0, 1, -1, 1, 0 \
00143 }
00144
00145 typedef struct
00146 {
00147 const stp_parameter_t param;
00148 double min;
00149 double max;
00150 double defval;
00151 int color_only;
00152 } float_param_t;
00153
00154 static const stp_parameter_t the_parameters[] =
00155 {
00156 #if 0
00157 {
00158 "AutoMode", N_("Automatic Printing Mode"), N_("Basic Output Adjustment"),
00159 N_("Automatic printing mode"),
00160 STP_PARAMETER_TYPE_STRING_LIST, STP_PARAMETER_CLASS_FEATURE,
00161 STP_PARAMETER_LEVEL_BASIC, 1, 1, -1, 1, 0
00162 },
00163 #endif
00164
00165
00166
00167
00168
00169 {
00170 "Quality", N_("Print Quality"), N_("Basic Output Adjustment"),
00171 N_("Print Quality"),
00172 STP_PARAMETER_TYPE_STRING_LIST, STP_PARAMETER_CLASS_FEATURE,
00173 STP_PARAMETER_LEVEL_BASIC, 1, 1, -1, 0, 0
00174 },
00175 {
00176 "PageSize", N_("Page Size"), N_("Basic Printer Setup"),
00177 N_("Size of the paper being printed to"),
00178 STP_PARAMETER_TYPE_STRING_LIST, STP_PARAMETER_CLASS_CORE,
00179 STP_PARAMETER_LEVEL_BASIC, 1, 1, -1, 1, 0
00180 },
00181 {
00182 "MediaType", N_("Media Type"), N_("Basic Printer Setup"),
00183 N_("Type of media (plain paper, photo paper, etc.)"),
00184 STP_PARAMETER_TYPE_STRING_LIST, STP_PARAMETER_CLASS_FEATURE,
00185 STP_PARAMETER_LEVEL_BASIC, 1, 1, -1, 1, 0
00186 },
00187 {
00188 "InputSlot", N_("Media Source"), N_("Basic Printer Setup"),
00189 N_("Source (input slot) of the media"),
00190 STP_PARAMETER_TYPE_STRING_LIST, STP_PARAMETER_CLASS_FEATURE,
00191 STP_PARAMETER_LEVEL_BASIC, 1, 1, -1, 1, 0
00192 },
00193 {
00194 "Resolution", N_("Resolution"), N_("Basic Printer Setup"),
00195 N_("Resolution of the print"),
00196 STP_PARAMETER_TYPE_STRING_LIST, STP_PARAMETER_CLASS_FEATURE,
00197 STP_PARAMETER_LEVEL_ADVANCED, 1, 1, -1, 1, 0
00198 },
00199
00200
00201
00202
00203
00204 {
00205 "InkType", N_("Ink Type"), N_("Advanced Printer Setup"),
00206 N_("Type of ink in the printer"),
00207 STP_PARAMETER_TYPE_STRING_LIST, STP_PARAMETER_CLASS_FEATURE,
00208 STP_PARAMETER_LEVEL_ADVANCED2, 1, 1, -1, 0, 0
00209 },
00210 {
00211 "InkSet", N_("Ink Set"), N_("Advanced Printer Setup"),
00212 N_("Type of ink in the printer"),
00213 STP_PARAMETER_TYPE_STRING_LIST, STP_PARAMETER_CLASS_FEATURE,
00214 STP_PARAMETER_LEVEL_BASIC, 1, 1, -1, 1, 0
00215 },
00216 {
00217 "PrintingDirection", N_("Printing Direction"), N_("Advanced Output Adjustment"),
00218 N_("Printing direction (unidirectional is higher quality, but slower)"),
00219 STP_PARAMETER_TYPE_STRING_LIST, STP_PARAMETER_CLASS_FEATURE,
00220 STP_PARAMETER_LEVEL_ADVANCED1, 1, 1, -1, 1, 0
00221 },
00222 {
00223 "FullBleed", N_("Borderless"), N_("Basic Printer Setup"),
00224 N_("Print without borders"),
00225 STP_PARAMETER_TYPE_BOOLEAN, STP_PARAMETER_CLASS_FEATURE,
00226 STP_PARAMETER_LEVEL_BASIC, 1, 1, -1, 1, 0
00227 },
00228 {
00229 "Weave", N_("Interleave Method"), N_("Advanced Output Adjustment"),
00230 N_("Interleave pattern to use"),
00231 STP_PARAMETER_TYPE_STRING_LIST, STP_PARAMETER_CLASS_FEATURE,
00232 STP_PARAMETER_LEVEL_ADVANCED1, 1, 1, -1, 1, 0
00233 },
00234 {
00235 "AdjustDotsize", N_("Adjust dot size as necessary"), N_("Advanced Printer Setup"),
00236 N_("Adjust dot size as necessary to achieve desired density"),
00237 STP_PARAMETER_TYPE_BOOLEAN, STP_PARAMETER_CLASS_FEATURE,
00238 STP_PARAMETER_LEVEL_ADVANCED4, 1, 1, -1, 1, 0
00239 },
00240 {
00241 "OutputOrder", N_("Output Order"), N_("Basic Printer Setup"),
00242 N_("Output Order"),
00243 STP_PARAMETER_TYPE_STRING_LIST, STP_PARAMETER_CLASS_FEATURE,
00244 STP_PARAMETER_LEVEL_BASIC, 0, 0, -1, 0, 0
00245 },
00246 {
00247 "AlignmentPasses", N_("Alignment Passes"), N_("Advanced Printer Functionality"),
00248 N_("Alignment Passes"),
00249 STP_PARAMETER_TYPE_INT, STP_PARAMETER_CLASS_FEATURE,
00250 STP_PARAMETER_LEVEL_INTERNAL, 0, 0, -1, 0, 0
00251 },
00252 {
00253 "AlignmentChoices", N_("Alignment Choices"), N_("Advanced Printer Functionality"),
00254 N_("Alignment Choices"),
00255 STP_PARAMETER_TYPE_INT, STP_PARAMETER_CLASS_FEATURE,
00256 STP_PARAMETER_LEVEL_INTERNAL, 0, 0, -1, 0, 0
00257 },
00258 {
00259 "InkChange", N_("Ink change command"), N_("Advanced Printer Functionality"),
00260 N_("Ink change command"),
00261 STP_PARAMETER_TYPE_INT, STP_PARAMETER_CLASS_FEATURE,
00262 STP_PARAMETER_LEVEL_INTERNAL, 0, 0, -1, 0, 0
00263 },
00264 {
00265 "AlternateAlignmentPasses", N_("Alternate Alignment Passes"), N_("Advanced Printer Functionality"),
00266 N_("Alternate Alignment Passes"),
00267 STP_PARAMETER_TYPE_INT, STP_PARAMETER_CLASS_FEATURE,
00268 STP_PARAMETER_LEVEL_INTERNAL, 0, 0, -1, 0, 0
00269 },
00270 {
00271 "AlternateAlignmentChoices", N_("Alternate Alignment Choices"), N_("Advanced Printer Functionality"),
00272 N_("Alternate Alignment Choices"),
00273 STP_PARAMETER_TYPE_INT, STP_PARAMETER_CLASS_FEATURE,
00274 STP_PARAMETER_LEVEL_INTERNAL, 0, 0, -1, 0, 0
00275 },
00276 {
00277 "InkChannels", N_("Ink Channels"), N_("Advanced Printer Functionality"),
00278 N_("Ink Channels"),
00279 STP_PARAMETER_TYPE_INT, STP_PARAMETER_CLASS_FEATURE,
00280 STP_PARAMETER_LEVEL_INTERNAL, 0, 0, -1, 0, 0
00281 },
00282 {
00283 "PrintingMode", N_("Printing Mode"), N_("Core Parameter"),
00284 N_("Printing Output Mode"),
00285 STP_PARAMETER_TYPE_STRING_LIST, STP_PARAMETER_CLASS_CORE,
00286 STP_PARAMETER_LEVEL_BASIC, 1, 1, -1, 1, 0
00287 },
00288 {
00289 "RawChannels", N_("Raw Channels"), N_("Core Parameter"),
00290 N_("Raw Channel Count"),
00291 STP_PARAMETER_TYPE_STRING_LIST, STP_PARAMETER_CLASS_CORE,
00292 STP_PARAMETER_LEVEL_BASIC, 0, 1, -1, 1, 0
00293 },
00294 PARAMETER_INT(max_hres),
00295 PARAMETER_INT(max_vres),
00296 PARAMETER_INT(min_hres),
00297 PARAMETER_INT(min_vres),
00298 PARAMETER_INT(nozzles),
00299 PARAMETER_INT(black_nozzles),
00300 PARAMETER_INT(fast_nozzles),
00301 PARAMETER_INT(min_nozzles),
00302 PARAMETER_INT(min_black_nozzles),
00303 PARAMETER_INT(min_fast_nozzles),
00304 PARAMETER_INT(nozzle_separation),
00305 PARAMETER_INT(black_nozzle_separation),
00306 PARAMETER_INT(fast_nozzle_separation),
00307 PARAMETER_INT(separation_rows),
00308 PARAMETER_INT(max_paper_width),
00309 PARAMETER_INT(max_paper_height),
00310 PARAMETER_INT(min_paper_width),
00311 PARAMETER_INT(min_paper_height),
00312 PARAMETER_INT(extra_feed),
00313 PARAMETER_INT(pseudo_separation_rows),
00314 PARAMETER_INT(base_separation),
00315 PARAMETER_INT(resolution_scale),
00316 PARAMETER_INT(initial_vertical_offset),
00317 PARAMETER_INT(black_initial_vertical_offset),
00318 PARAMETER_INT(max_black_resolution),
00319 PARAMETER_INT(zero_margin_offset),
00320 PARAMETER_INT(extra_720dpi_separation),
00321 PARAMETER_INT(physical_channels),
00322 PARAMETER_INT(left_margin),
00323 PARAMETER_INT(right_margin),
00324 PARAMETER_INT(top_margin),
00325 PARAMETER_INT(bottom_margin),
00326 PARAMETER_INT_RO(alignment_passes),
00327 PARAMETER_INT_RO(alignment_choices),
00328 PARAMETER_INT_RO(alternate_alignment_passes),
00329 PARAMETER_INT_RO(alternate_alignment_choices),
00330 PARAMETER_INT(cd_x_offset),
00331 PARAMETER_INT(cd_y_offset),
00332 PARAMETER_INT(cd_page_width),
00333 PARAMETER_INT(cd_page_height),
00334 PARAMETER_RAW(preinit_sequence),
00335 PARAMETER_RAW(postinit_remote_sequence)
00336 };
00337
00338 static const int the_parameter_count =
00339 sizeof(the_parameters) / sizeof(const stp_parameter_t);
00340
00341 static const float_param_t float_parameters[] =
00342 {
00343 {
00344 {
00345 "CyanDensity", N_("Cyan Balance"), N_("Output Level Adjustment"),
00346 N_("Adjust the cyan balance"),
00347 STP_PARAMETER_TYPE_DOUBLE, STP_PARAMETER_CLASS_OUTPUT,
00348 STP_PARAMETER_LEVEL_ADVANCED, 0, 1, 1, 1, 0
00349 }, 0.0, 2.0, 1.0, 1
00350 },
00351 {
00352 {
00353 "MagentaDensity", N_("Magenta Balance"), N_("Output Level Adjustment"),
00354 N_("Adjust the magenta balance"),
00355 STP_PARAMETER_TYPE_DOUBLE, STP_PARAMETER_CLASS_OUTPUT,
00356 STP_PARAMETER_LEVEL_ADVANCED, 0, 1, 2, 1, 0
00357 }, 0.0, 2.0, 1.0, 1
00358 },
00359 {
00360 {
00361 "YellowDensity", N_("Yellow Balance"), N_("Output Level Adjustment"),
00362 N_("Adjust the yellow balance"),
00363 STP_PARAMETER_TYPE_DOUBLE, STP_PARAMETER_CLASS_OUTPUT,
00364 STP_PARAMETER_LEVEL_ADVANCED, 0, 1, 3, 1, 0
00365 }, 0.0, 2.0, 1.0, 1
00366 },
00367 {
00368 {
00369 "BlackDensity", N_("Black Balance"), N_("Output Level Adjustment"),
00370 N_("Adjust the black balance"),
00371 STP_PARAMETER_TYPE_DOUBLE, STP_PARAMETER_CLASS_OUTPUT,
00372 STP_PARAMETER_LEVEL_ADVANCED, 0, 1, 0, 1, 0
00373 }, 0.0, 2.0, 1.0, 1
00374 },
00375 {
00376 {
00377 "RedDensity", N_("Red Balance"), N_("Output Level Adjustment"),
00378 N_("Adjust the red balance"),
00379 STP_PARAMETER_TYPE_DOUBLE, STP_PARAMETER_CLASS_OUTPUT,
00380 STP_PARAMETER_LEVEL_ADVANCED, 0, 1, 4, 1, 0
00381 }, 0.0, 2.0, 1.0, 1
00382 },
00383 {
00384 {
00385 "BlueDensity", N_("Blue Balance"), N_("Output Level Adjustment"),
00386 N_("Adjust the blue balance"),
00387 STP_PARAMETER_TYPE_DOUBLE, STP_PARAMETER_CLASS_OUTPUT,
00388 STP_PARAMETER_LEVEL_ADVANCED, 0, 1, 5, 1, 0
00389 }, 0.0, 2.0, 1.0, 1
00390 },
00391 {
00392 {
00393 "GlossDensity", N_("Gloss Balance"), N_("Output Level Adjustment"),
00394 N_("Adjust the gloss balance"),
00395 STP_PARAMETER_TYPE_DOUBLE, STP_PARAMETER_CLASS_OUTPUT,
00396 STP_PARAMETER_LEVEL_ADVANCED, 0, 1, 6, 1, 0
00397 }, 0.0, 2.0, 1.0, 1
00398 },
00399 {
00400 {
00401 "LightCyanTransition", N_("Light Cyan Transition"), N_("Advanced Ink Adjustment"),
00402 N_("Light Cyan Transition"),
00403 STP_PARAMETER_TYPE_DOUBLE, STP_PARAMETER_CLASS_OUTPUT,
00404 STP_PARAMETER_LEVEL_ADVANCED4, 0, 1, -1, 1, 0
00405 }, 0.0, 5.0, 1.0, 1
00406 },
00407 {
00408 {
00409 "LightMagentaTransition", N_("Light Magenta Transition"), N_("Advanced Ink Adjustment"),
00410 N_("Light Magenta Transition"),
00411 STP_PARAMETER_TYPE_DOUBLE, STP_PARAMETER_CLASS_OUTPUT,
00412 STP_PARAMETER_LEVEL_ADVANCED4, 0, 1, -1, 1, 0
00413 }, 0.0, 5.0, 1.0, 1
00414 },
00415 {
00416 {
00417 "DarkYellowTransition", N_("Dark Yellow Transition"), N_("Advanced Ink Adjustment"),
00418 N_("Dark Yellow Transition"),
00419 STP_PARAMETER_TYPE_DOUBLE, STP_PARAMETER_CLASS_OUTPUT,
00420 STP_PARAMETER_LEVEL_ADVANCED4, 0, 1, -1, 1, 0
00421 }, 0.0, 5.0, 1.0, 1
00422 },
00423 {
00424 {
00425 "GrayTransition", N_("Gray Transition"), N_("Advanced Ink Adjustment"),
00426 N_("Gray Transition"),
00427 STP_PARAMETER_TYPE_DOUBLE, STP_PARAMETER_CLASS_OUTPUT,
00428 STP_PARAMETER_LEVEL_ADVANCED4, 0, 1, -1, 1, 0
00429 }, 0.0, 5.0, 1.0, 1
00430 },
00431 {
00432 {
00433 "Gray3Transition", N_("Dark Gray Transition"), N_("Advanced Ink Adjustment"),
00434 N_("Dark Gray Transition"),
00435 STP_PARAMETER_TYPE_DOUBLE, STP_PARAMETER_CLASS_OUTPUT,
00436 STP_PARAMETER_LEVEL_ADVANCED4, 0, 1, -1, 1, 0
00437 }, 0.0, 5.0, 1.0, 1
00438 },
00439 {
00440 {
00441 "Gray2Transition", N_("Mid Gray Transition"), N_("Advanced Ink Adjustment"),
00442 N_("Medium Gray Transition"),
00443 STP_PARAMETER_TYPE_DOUBLE, STP_PARAMETER_CLASS_OUTPUT,
00444 STP_PARAMETER_LEVEL_ADVANCED4, 0, 1, -1, 1, 0
00445 }, 0.0, 5.0, 1.0, 1
00446 },
00447 {
00448 {
00449 "Gray1Transition", N_("Light Gray Transition"), N_("Advanced Ink Adjustment"),
00450 N_("Light Gray Transition"),
00451 STP_PARAMETER_TYPE_DOUBLE, STP_PARAMETER_CLASS_OUTPUT,
00452 STP_PARAMETER_LEVEL_ADVANCED4, 0, 1, -1, 1, 0
00453 }, 0.0, 5.0, 1.0, 1
00454 },
00455 };
00456
00457 static const int float_parameter_count =
00458 sizeof(float_parameters) / sizeof(const float_param_t);
00459
00460
00461 static escp2_privdata_t *
00462 get_privdata(stp_vars_t *v)
00463 {
00464 return (escp2_privdata_t *) stp_get_component_data(v, "Driver");
00465 }
00466
00467 static model_featureset_t
00468 escp2_get_cap(const stp_vars_t *v, escp2_model_option_t feature)
00469 {
00470 int model = stp_get_model_id(v);
00471 if (feature < 0 || feature >= MODEL_LIMIT)
00472 return (model_featureset_t) -1;
00473 else
00474 {
00475 model_featureset_t featureset =
00476 (((1ul << escp2_printer_attrs[feature].bit_width) - 1ul) <<
00477 escp2_printer_attrs[feature].bit_shift);
00478 return stpi_escp2_model_capabilities[model].flags & featureset;
00479 }
00480 }
00481
00482 static int
00483 escp2_has_cap(const stp_vars_t *v, escp2_model_option_t feature,
00484 model_featureset_t class)
00485 {
00486 int model = stp_get_model_id(v);
00487 if (feature < 0 || feature >= MODEL_LIMIT)
00488 return -1;
00489 else
00490 {
00491 model_featureset_t featureset =
00492 (((1ul << escp2_printer_attrs[feature].bit_width) - 1ul) <<
00493 escp2_printer_attrs[feature].bit_shift);
00494 if ((stpi_escp2_model_capabilities[model].flags & featureset) == class)
00495 return 1;
00496 else
00497 return 0;
00498 }
00499 }
00500
00501 #define DEF_SIMPLE_ACCESSOR(f, t) \
00502 static inline t \
00503 escp2_##f(const stp_vars_t *v) \
00504 { \
00505 if (stp_check_int_parameter(v, "escp2_" #f, STP_PARAMETER_ACTIVE)) \
00506 return stp_get_int_parameter(v, "escp2_" #f); \
00507 else \
00508 { \
00509 int model = stp_get_model_id(v); \
00510 return (stpi_escp2_model_capabilities[model].f); \
00511 } \
00512 }
00513
00514 #define DEF_RAW_ACCESSOR(f, t) \
00515 static inline t \
00516 escp2_##f(const stp_vars_t *v) \
00517 { \
00518 if (stp_check_raw_parameter(v, "escp2_" #f, STP_PARAMETER_ACTIVE)) \
00519 return stp_get_raw_parameter(v, "escp2_" #f); \
00520 else \
00521 { \
00522 int model = stp_get_model_id(v); \
00523 return (stpi_escp2_model_capabilities[model].f); \
00524 } \
00525 }
00526
00527 #define DEF_COMPOSITE_ACCESSOR(f, t) \
00528 static inline t \
00529 escp2_##f(const stp_vars_t *v) \
00530 { \
00531 int model = stp_get_model_id(v); \
00532 return (stpi_escp2_model_capabilities[model].f); \
00533 }
00534
00535 #define DEF_ROLL_ACCESSOR(f, t) \
00536 static inline t \
00537 escp2_##f(const stp_vars_t *v, int rollfeed) \
00538 { \
00539 if (stp_check_int_parameter(v, "escp2_" #f, STP_PARAMETER_ACTIVE)) \
00540 return stp_get_int_parameter(v, "escp2_" #f); \
00541 else \
00542 { \
00543 int model = stp_get_model_id(v); \
00544 const res_t *res = escp2_find_resolution(v); \
00545 if (res && !(res->softweave)) \
00546 { \
00547 if (rollfeed) \
00548 return (stpi_escp2_model_capabilities[model].m_roll_##f); \
00549 else \
00550 return (stpi_escp2_model_capabilities[model].m_##f); \
00551 } \
00552 else \
00553 { \
00554 if (rollfeed) \
00555 return (stpi_escp2_model_capabilities[model].roll_##f); \
00556 else \
00557 return (stpi_escp2_model_capabilities[model].f); \
00558 } \
00559 } \
00560 }
00561
00562 DEF_SIMPLE_ACCESSOR(max_hres, int)
00563 DEF_SIMPLE_ACCESSOR(max_vres, int)
00564 DEF_SIMPLE_ACCESSOR(min_hres, int)
00565 DEF_SIMPLE_ACCESSOR(min_vres, int)
00566 DEF_SIMPLE_ACCESSOR(nozzles, unsigned)
00567 DEF_SIMPLE_ACCESSOR(black_nozzles, unsigned)
00568 DEF_SIMPLE_ACCESSOR(fast_nozzles, unsigned)
00569 DEF_SIMPLE_ACCESSOR(min_nozzles, unsigned)
00570 DEF_SIMPLE_ACCESSOR(min_black_nozzles, unsigned)
00571 DEF_SIMPLE_ACCESSOR(min_fast_nozzles, unsigned)
00572 DEF_SIMPLE_ACCESSOR(nozzle_separation, unsigned)
00573 DEF_SIMPLE_ACCESSOR(black_nozzle_separation, unsigned)
00574 DEF_SIMPLE_ACCESSOR(fast_nozzle_separation, unsigned)
00575 DEF_SIMPLE_ACCESSOR(separation_rows, unsigned)
00576 DEF_SIMPLE_ACCESSOR(max_paper_width, unsigned)
00577 DEF_SIMPLE_ACCESSOR(max_paper_height, unsigned)
00578 DEF_SIMPLE_ACCESSOR(min_paper_width, unsigned)
00579 DEF_SIMPLE_ACCESSOR(min_paper_height, unsigned)
00580 DEF_SIMPLE_ACCESSOR(cd_x_offset, int)
00581 DEF_SIMPLE_ACCESSOR(cd_y_offset, int)
00582 DEF_SIMPLE_ACCESSOR(cd_page_width, int)
00583 DEF_SIMPLE_ACCESSOR(cd_page_height, int)
00584 DEF_SIMPLE_ACCESSOR(extra_feed, unsigned)
00585 DEF_SIMPLE_ACCESSOR(pseudo_separation_rows, int)
00586 DEF_SIMPLE_ACCESSOR(base_separation, int)
00587 DEF_SIMPLE_ACCESSOR(resolution_scale, int)
00588 DEF_SIMPLE_ACCESSOR(initial_vertical_offset, int)
00589 DEF_SIMPLE_ACCESSOR(black_initial_vertical_offset, int)
00590 DEF_SIMPLE_ACCESSOR(max_black_resolution, int)
00591 DEF_SIMPLE_ACCESSOR(zero_margin_offset, int)
00592 DEF_SIMPLE_ACCESSOR(extra_720dpi_separation, int)
00593 DEF_SIMPLE_ACCESSOR(physical_channels, int)
00594 DEF_SIMPLE_ACCESSOR(alignment_passes, int)
00595 DEF_SIMPLE_ACCESSOR(alignment_choices, int)
00596 DEF_SIMPLE_ACCESSOR(alternate_alignment_passes, int)
00597 DEF_SIMPLE_ACCESSOR(alternate_alignment_choices, int)
00598 DEF_COMPOSITE_ACCESSOR(printer_weaves, const printer_weave_list_t *)
00599
00600 DEF_ROLL_ACCESSOR(left_margin, unsigned)
00601 DEF_ROLL_ACCESSOR(right_margin, unsigned)
00602 DEF_ROLL_ACCESSOR(top_margin, unsigned)
00603 DEF_ROLL_ACCESSOR(bottom_margin, unsigned)
00604
00605 DEF_RAW_ACCESSOR(preinit_sequence, const stp_raw_t *)
00606 DEF_RAW_ACCESSOR(postinit_remote_sequence, const stp_raw_t *)
00607
00608 DEF_COMPOSITE_ACCESSOR(reslist, const res_t *const *)
00609 DEF_COMPOSITE_ACCESSOR(inkgroup, const inkgroup_t *)
00610 DEF_COMPOSITE_ACCESSOR(input_slots, const input_slot_list_t *)
00611 DEF_COMPOSITE_ACCESSOR(quality_list, const quality_list_t *)
00612
00613 static const channel_count_t *
00614 get_channel_count_by_name(const char *name)
00615 {
00616 int i;
00617 for (i = 0; i < escp2_channel_counts_count; i++)
00618 if (strcmp(name, escp2_channel_counts[i].name) == 0)
00619 return &(escp2_channel_counts[i]);
00620 return NULL;
00621 }
00622
00623 static const channel_count_t *
00624 get_channel_count_by_number(unsigned count)
00625 {
00626 int i;
00627 for (i = 0; i < escp2_channel_counts_count; i++)
00628 if (count == escp2_channel_counts[i].count)
00629 return &(escp2_channel_counts[i]);
00630 return NULL;
00631 }
00632
00633 static int
00634 escp2_ink_type(const stp_vars_t *v, int resid)
00635 {
00636 if (stp_check_int_parameter(v, "escp2_ink_type", STP_PARAMETER_ACTIVE))
00637 return stp_get_int_parameter(v, "escp2_ink_type");
00638 else
00639 {
00640 int model = stp_get_model_id(v);
00641 return stpi_escp2_model_capabilities[model].dot_sizes[resid];
00642 }
00643 }
00644
00645 static double
00646 escp2_density(const stp_vars_t *v, int resid)
00647 {
00648 if (stp_check_float_parameter(v, "escp2_density", STP_PARAMETER_ACTIVE))
00649 return stp_get_float_parameter(v, "escp2_density");
00650 else
00651 {
00652 int model = stp_get_model_id(v);
00653 return stpi_escp2_model_capabilities[model].densities[resid];
00654 }
00655 }
00656
00657 static int
00658 escp2_bits(const stp_vars_t *v, int resid)
00659 {
00660 if (stp_check_int_parameter(v, "escp2_bits", STP_PARAMETER_ACTIVE))
00661 return stp_get_int_parameter(v, "escp2_bits");
00662 else
00663 {
00664 int model = stp_get_model_id(v);
00665 return stpi_escp2_model_capabilities[model].bits[resid];
00666 }
00667 }
00668
00669 static double
00670 escp2_base_res(const stp_vars_t *v, int resid)
00671 {
00672 if (stp_check_float_parameter(v, "escp2_base_res", STP_PARAMETER_ACTIVE))
00673 return stp_get_float_parameter(v, "escp2_base_res");
00674 else
00675 {
00676 int model = stp_get_model_id(v);
00677 return stpi_escp2_model_capabilities[model].base_resolutions[resid];
00678 }
00679 }
00680
00681 static const escp2_dropsize_t *
00682 escp2_dropsizes(const stp_vars_t *v, int resid)
00683 {
00684 int model = stp_get_model_id(v);
00685 const escp2_drop_list_t *drops = stpi_escp2_model_capabilities[model].drops;
00686 return (*drops)[resid];
00687 }
00688
00689 static const inklist_t *
00690 escp2_inklist(const stp_vars_t *v)
00691 {
00692 int model = stp_get_model_id(v);
00693 int i;
00694 const char *ink_list_name = NULL;
00695 const inkgroup_t *inkgroup = stpi_escp2_model_capabilities[model].inkgroup;
00696
00697 if (stp_check_string_parameter(v, "InkSet", STP_PARAMETER_ACTIVE))
00698 ink_list_name = stp_get_string_parameter(v, "InkSet");
00699 if (ink_list_name)
00700 {
00701 for (i = 0; i < inkgroup->n_inklists; i++)
00702 {
00703 if (strcmp(ink_list_name, inkgroup->inklists[i]->name) == 0)
00704 return inkgroup->inklists[i];
00705 }
00706 }
00707 return inkgroup->inklists[0];
00708 }
00709
00710 static const shade_t *
00711 escp2_shades(const stp_vars_t *v, int channel)
00712 {
00713 const inklist_t *inklist = escp2_inklist(v);
00714 return &((*inklist->shades)[channel]);
00715 }
00716
00717 static const paperlist_t *
00718 escp2_paperlist(const stp_vars_t *v)
00719 {
00720 const inklist_t *inklist = escp2_inklist(v);
00721 if (inklist)
00722 return inklist->papers;
00723 else
00724 return NULL;
00725 }
00726
00727 static int
00728 using_automatic_settings(const stp_vars_t *v, auto_mode_t mode)
00729 {
00730 int is_raw = 0;
00731 if (stp_get_string_parameter(v, "InputImageType") &&
00732 strcmp(stp_get_string_parameter(v, "InputImageType"), "Raw") == 0)
00733 is_raw = 1;
00734 switch (mode)
00735 {
00736 case AUTO_MODE_QUALITY:
00737 if (stp_check_string_parameter(v, "Quality", STP_PARAMETER_ACTIVE) &&
00738 strcmp(stp_get_string_parameter(v, "Quality"), "None") != 0 &&
00739 !is_raw)
00740 return 1;
00741 else
00742 return 0;
00743 #if 0
00744 case AUTO_MODE_FULL_AUTO:
00745 if (stp_check_string_parameter(v, "AutoMode", STP_PARAMETER_ACTIVE) &&
00746 strcmp(stp_get_string_parameter(v, "AutoMode"), "None") != 0 &&
00747 !is_raw)
00748 return 1;
00749 else
00750 return 0;
00751 #endif
00752 case AUTO_MODE_MANUAL:
00753 if (!stp_check_string_parameter(v, "Quality", STP_PARAMETER_ACTIVE) ||
00754 strcmp(stp_get_string_parameter(v, "Quality"), "None") == 0 ||
00755 is_raw)
00756 return 1;
00757 else
00758 return 0;
00759 }
00760 return 0;
00761 }
00762
00763 static int
00764 compute_internal_resid(int hres, int vres)
00765 {
00766 static const int resolutions[RES_N] =
00767 {
00768 0,
00769 360 * 360,
00770 720 * 360,
00771 720 * 720,
00772 1440 * 720,
00773 1440 * 1440,
00774 2880 * 1440,
00775 2880 * 2880,
00776 };
00777 int total_resolution = hres * vres;
00778 int i;
00779 for (i = 0; i < RES_N; i++)
00780 {
00781 if (total_resolution < resolutions[i])
00782 return i - 1;
00783 }
00784 return RES_N - 1;
00785 }
00786
00787 static int
00788 compute_resid(const res_t *res)
00789 {
00790 return compute_internal_resid(res->hres, res->vres);
00791 }
00792
00793 static int
00794 compute_printed_resid(const res_t *res)
00795 {
00796 return compute_internal_resid(res->printed_hres, res->printed_vres);
00797 }
00798
00799
00800 static const input_slot_t *
00801 get_input_slot(const stp_vars_t *v)
00802 {
00803 int i;
00804 const char *input_slot = stp_get_string_parameter(v, "InputSlot");
00805 if (input_slot && strlen(input_slot) > 0)
00806 {
00807 const input_slot_list_t *slots = escp2_input_slots(v);
00808 if (slots)
00809 {
00810 for (i = 0; i < slots->n_input_slots; i++)
00811 {
00812 if (slots->slots[i].name &&
00813 strcmp(input_slot, slots->slots[i].name) == 0)
00814 {
00815 return &(slots->slots[i]);
00816 break;
00817 }
00818 }
00819 }
00820 }
00821 return NULL;
00822 }
00823
00824 static const printer_weave_t *
00825 get_printer_weave(const stp_vars_t *v)
00826 {
00827 int i;
00828 const printer_weave_list_t *p = escp2_printer_weaves(v);
00829 if (p)
00830 {
00831 const char *name = stp_get_string_parameter(v, "Weave");
00832 int printer_weave_count = p->n_printer_weaves;
00833 if (name)
00834 {
00835 for (i = 0; i < printer_weave_count; i++)
00836 {
00837 if (!strcmp(name, p->printer_weaves[i].name))
00838 return &(p->printer_weaves[i]);
00839 }
00840 }
00841 }
00842 return NULL;
00843 }
00844
00845 static int
00846 use_printer_weave(const stp_vars_t *v)
00847 {
00848 const res_t *res = escp2_find_resolution(v);
00849 if (!res)
00850 return 1;
00851 else if (!(res->softweave))
00852 return 1;
00853 else if (res->printer_weave)
00854 return 1;
00855 else
00856 return 0;
00857 }
00858
00859
00860 static const paper_t *
00861 get_media_type(const stp_vars_t *v)
00862 {
00863 int i;
00864 const paperlist_t *p = escp2_paperlist(v);
00865 if (p)
00866 {
00867 const char *name = stp_get_string_parameter(v, "MediaType");
00868 int paper_type_count = p->paper_count;
00869 if (name)
00870 {
00871 for (i = 0; i < paper_type_count; i++)
00872 {
00873 if (!strcmp(name, p->papers[i].name))
00874 return &(p->papers[i]);
00875 }
00876 }
00877 }
00878 return NULL;
00879 }
00880
00881 static int
00882 verify_resolution_by_paper_type(const stp_vars_t *v, const res_t *res)
00883 {
00884 const paper_t *paper = get_media_type(v);
00885 if (paper)
00886 {
00887 switch (paper->paper_class)
00888 {
00889 case PAPER_PLAIN:
00890 if (res->printed_vres > 720 || res->hres > 720)
00891 return 0;
00892 break;
00893 case PAPER_GOOD:
00894 if (res->printed_vres < 180 || res->hres < 360 ||
00895 res->printed_vres > 720 || res->hres > 1440)
00896 return 0;
00897 break;
00898 case PAPER_PHOTO:
00899 if (res->printed_vres < 360 ||
00900 (res->hres < 720 && res->hres < escp2_max_hres(v)))
00901 return 0;
00902 break;
00903 case PAPER_PREMIUM_PHOTO:
00904 if (res->printed_vres < 720 ||
00905 (res->hres < 720 && res->hres < escp2_max_hres(v)))
00906 return 0;
00907 break;
00908 case PAPER_TRANSPARENCY:
00909 if (res->printed_vres < 360 || res->hres < 360 ||
00910 res->printed_vres > 720 || res->hres > 720)
00911 return 0;
00912 break;
00913 }
00914 }
00915 return 1;
00916 }
00917
00918 static int
00919 verify_resolution(const stp_vars_t *v, const res_t *res)
00920 {
00921 int nozzle_width =
00922 (escp2_base_separation(v) / escp2_nozzle_separation(v));
00923 int nozzles = escp2_nozzles(v);
00924 if (escp2_ink_type(v, compute_printed_resid(res)) != -1 &&
00925 res->vres <= escp2_max_vres(v) &&
00926 res->hres <= escp2_max_hres(v) &&
00927 res->vres >= escp2_min_vres(v) &&
00928 res->hres >= escp2_min_hres(v) &&
00929 (nozzles == 1 ||
00930 ((res->vres / nozzle_width) * nozzle_width) == res->vres))
00931 {
00932 int xdpi = res->hres;
00933 int physical_xdpi = escp2_base_res(v, compute_resid(res));
00934 int horizontal_passes, oversample;
00935 if (physical_xdpi > xdpi)
00936 physical_xdpi = xdpi;
00937 horizontal_passes = xdpi / physical_xdpi;
00938 oversample = horizontal_passes * res->vertical_passes;
00939 if (horizontal_passes < 1)
00940 horizontal_passes = 1;
00941 if (oversample < 1)
00942 oversample = 1;
00943 if (((horizontal_passes * res->vertical_passes) <= 8) &&
00944 (! res->softweave || (nozzles > 1 && nozzles > oversample)))
00945 return 1;
00946 }
00947 return 0;
00948 }
00949
00950 static int
00951 verify_papersize(const stp_vars_t *v, const stp_papersize_t *pt)
00952 {
00953 unsigned int height_limit, width_limit;
00954 unsigned int min_height_limit, min_width_limit;
00955 width_limit = escp2_max_paper_width(v);
00956 height_limit = escp2_max_paper_height(v);
00957 min_width_limit = escp2_min_paper_width(v);
00958 min_height_limit = escp2_min_paper_height(v);
00959 if (strlen(pt->name) > 0 &&
00960 pt->width <= width_limit && pt->height <= height_limit &&
00961 (pt->height >= min_height_limit || pt->height == 0) &&
00962 (pt->width >= min_width_limit || pt->width == 0) &&
00963 (pt->width == 0 || pt->height > 0 ||
00964 escp2_has_cap(v, MODEL_ROLLFEED, MODEL_ROLLFEED_YES)))
00965 return 1;
00966 else
00967 return 0;
00968 }
00969
00970 static int
00971 verify_inktype(const stp_vars_t *v, const escp2_inkname_t *inks)
00972 {
00973 if (inks->inkset == INKSET_EXTENDED)
00974 return 0;
00975 else
00976 return 1;
00977 }
00978
00979 static const char *
00980 get_default_inktype(const stp_vars_t *v)
00981 {
00982 const inklist_t *ink_list = escp2_inklist(v);
00983 const paper_t *paper_type = get_media_type(v);
00984 if (!ink_list)
00985 return NULL;
00986 if (!paper_type)
00987 {
00988 const paperlist_t *p = escp2_paperlist(v);
00989 if (p)
00990 paper_type = &(p->papers[0]);
00991 }
00992 if (paper_type && paper_type->preferred_ink_type)
00993 return paper_type->preferred_ink_type;
00994 else if (escp2_has_cap(v, MODEL_FAST_360, MODEL_FAST_360_YES) &&
00995 stp_check_string_parameter(v, "Resolution", STP_PARAMETER_ACTIVE))
00996 {
00997 const res_t *res = escp2_find_resolution(v);
00998 if (res)
00999 {
01000 int resid = compute_printed_resid(res);
01001 if (res->vres == 360 && res->hres == escp2_base_res(v, resid))
01002 {
01003 int i;
01004 for (i = 0; i < ink_list->n_inks; i++)
01005 if (strcmp(ink_list->inknames[i]->name, "CMYK") == 0)
01006 return ink_list->inknames[i]->name;
01007 }
01008 }
01009 }
01010 return ink_list->inknames[0]->name;
01011 }
01012
01013
01014 static const escp2_inkname_t *
01015 get_inktype(const stp_vars_t *v)
01016 {
01017 const char *ink_type = stp_get_string_parameter(v, "InkType");
01018 const inklist_t *ink_list = escp2_inklist(v);
01019 int i;
01020
01021 if (!ink_type || strcmp(ink_type, "None") == 0 ||
01022 (ink_list && ink_list->n_inks == 1) ||
01023 !using_automatic_settings(v, AUTO_MODE_MANUAL))
01024 ink_type = get_default_inktype(v);
01025
01026 if (ink_type && ink_list)
01027 {
01028 for (i = 0; i < ink_list->n_inks; i++)
01029 {
01030 if (strcmp(ink_type, ink_list->inknames[i]->name) == 0)
01031 return ink_list->inknames[i];
01032 }
01033 }
01034
01035
01036
01037
01038 ink_type = get_default_inktype(v);
01039 for (i = 0; i < ink_list->n_inks; i++)
01040 {
01041 if (strcmp(ink_type, ink_list->inknames[i]->name) == 0)
01042 return ink_list->inknames[i];
01043 }
01044 return NULL;
01045 }
01046
01047 static const paper_adjustment_t *
01048 get_media_adjustment(const stp_vars_t *v)
01049 {
01050 const paper_t *pt = get_media_type(v);
01051 const inklist_t *ink_list = escp2_inklist(v);
01052 if (pt && ink_list && ink_list->paper_adjustments)
01053 {
01054 const paper_adjustment_list_t *adjlist = ink_list->paper_adjustments;
01055 const char *paper_name = pt->name;
01056 int i;
01057 for (i = 0; i < adjlist->paper_count; i++)
01058 {
01059 if (strcmp(paper_name, adjlist->papers[i].name) == 0)
01060 return &(adjlist->papers[i]);
01061 }
01062 }
01063 return NULL;
01064 }
01065
01066
01067
01068
01069
01070
01071 static stp_parameter_list_t
01072 escp2_list_parameters(const stp_vars_t *v)
01073 {
01074 stp_parameter_list_t *ret = stp_parameter_list_create();
01075 int i;
01076 for (i = 0; i < the_parameter_count; i++)
01077 stp_parameter_list_add_param(ret, &(the_parameters[i]));
01078 for (i = 0; i < float_parameter_count; i++)
01079 stp_parameter_list_add_param(ret, &(float_parameters[i].param));
01080 return ret;
01081 }
01082
01083 static void
01084 fill_transition_parameters(stp_parameter_t *description)
01085 {
01086 description->is_active = 1;
01087 description->bounds.dbl.lower = 0;
01088 description->bounds.dbl.upper = 5.0;
01089 description->deflt.dbl = 1.0;
01090 }
01091
01092 static void
01093 set_density_parameter(const stp_vars_t *v,
01094 stp_parameter_t *description,
01095 int color)
01096 {
01097 description->is_active = 0;
01098 if (stp_get_string_parameter(v, "PrintingMode") &&
01099 strcmp(stp_get_string_parameter(v, "PrintingMode"), "BW") != 0 &&
01100 using_automatic_settings(v, AUTO_MODE_MANUAL))
01101 {
01102 const escp2_inkname_t *ink_name = get_inktype(v);
01103 if (ink_name &&
01104 ink_name->channel_set->channel_count > color &&
01105 ink_name->channel_set->channels[color])
01106 description->is_active = 1;
01107 }
01108 }
01109
01110 static void
01111 set_gray_transition_parameter(const stp_vars_t *v,
01112 stp_parameter_t *description,
01113 int expected_channels)
01114 {
01115 const escp2_inkname_t *ink_name = get_inktype(v);
01116 description->is_active = 0;
01117 if (ink_name && ink_name->channel_set->channels[STP_ECOLOR_K] &&
01118 (ink_name->channel_set->channels[STP_ECOLOR_K]->n_subchannels ==
01119 expected_channels) &&
01120 using_automatic_settings(v, AUTO_MODE_MANUAL))
01121 fill_transition_parameters(description);
01122 }
01123
01124 static void
01125 set_color_transition_parameter(const stp_vars_t *v,
01126 stp_parameter_t *description,
01127 int color)
01128 {
01129 description->is_active = 0;
01130 if (stp_get_string_parameter(v, "PrintingMode") &&
01131 strcmp(stp_get_string_parameter(v, "PrintingMode"), "BW") != 0 &&
01132 using_automatic_settings(v, AUTO_MODE_MANUAL))
01133 {
01134 const escp2_inkname_t *ink_name = get_inktype(v);
01135 if (ink_name &&
01136 ink_name->channel_set->channel_count == 4 &&
01137 ink_name->channel_set->channels[color] &&
01138 ink_name->channel_set->channels[color]->n_subchannels == 2)
01139 fill_transition_parameters(description);
01140 }
01141 }
01142
01143 static const res_t *
01144 find_default_resolution(const stp_vars_t *v, int desired_hres, int desired_vres,
01145 int strict)
01146 {
01147 const res_t *const *res = escp2_reslist(v);
01148 int i = 0;
01149 if (desired_hres < 0)
01150 {
01151 while (res[i])
01152 i++;
01153 i--;
01154 while (i >= 0)
01155 {
01156 if (verify_resolution(v, res[i]) &&
01157 verify_resolution_by_paper_type(v, res[i]))
01158 return res[i];
01159 i--;
01160 }
01161 }
01162 i = 0;
01163 while (res[i])
01164 {
01165 if (verify_resolution(v, res[i]) &&
01166 verify_resolution_by_paper_type(v, res[i]) &&
01167 res[i]->vres >= desired_vres && res[i]->hres >= desired_hres &&
01168 res[i]->vres <= 2 * desired_vres && res[i]->hres <= 2 * desired_hres)
01169 return res[i];
01170 i++;
01171 }
01172 #if 0
01173 if (!strict)
01174 {
01175 i = 0;
01176 while (res[i])
01177 {
01178 if (verify_resolution(v, res[i]) &&
01179 res[i]->vres >= desired_vres &&
01180 res[i]->hres >= desired_hres &&
01181 res[i]->vres <= 2 * desired_vres &&
01182 res[i]->hres <= 2 * desired_hres)
01183 return res[i];
01184 i++;
01185 }
01186 }
01187 #endif
01188 return NULL;
01189 }
01190
01191 static const res_t *
01192 find_resolution_from_quality(const stp_vars_t *v, const char *quality,
01193 int strict)
01194 {
01195 int i;
01196 const quality_list_t *quals = escp2_quality_list(v);
01197 for (i = 0; i < quals->n_quals; i++)
01198 {
01199 const quality_t *q = &(quals->qualities[i]);
01200 if (strcmp(quality, q->name) == 0 &&
01201 (q->min_vres == 0 || escp2_min_vres(v) <= q->min_vres) &&
01202 (q->min_hres == 0 || escp2_min_hres(v) <= q->min_hres) &&
01203 (q->max_vres == 0 || escp2_max_vres(v) >= q->max_vres) &&
01204 (q->max_hres == 0 || escp2_max_hres(v) >= q->max_hres))
01205 {
01206 return find_default_resolution(v, q->desired_hres, q->desired_vres,
01207 strict);
01208 }
01209 }
01210 return NULL;
01211 }
01212
01213 static void
01214 escp2_parameters(const stp_vars_t *v, const char *name,
01215 stp_parameter_t *description)
01216 {
01217 int i;
01218 description->p_type = STP_PARAMETER_TYPE_INVALID;
01219 if (name == NULL)
01220 return;
01221
01222 for (i = 0; i < float_parameter_count; i++)
01223 if (strcmp(name, float_parameters[i].param.name) == 0)
01224 {
01225 stp_fill_parameter_settings(description,
01226 &(float_parameters[i].param));
01227 description->deflt.dbl = float_parameters[i].defval;
01228 description->bounds.dbl.upper = float_parameters[i].max;
01229 description->bounds.dbl.lower = float_parameters[i].min;
01230 break;
01231 }
01232
01233 for (i = 0; i < the_parameter_count; i++)
01234 if (strcmp(name, the_parameters[i].name) == 0)
01235 {
01236 stp_fill_parameter_settings(description, &(the_parameters[i]));
01237 break;
01238 }
01239
01240 description->deflt.str = NULL;
01241 if (strcmp(name, "AutoMode") == 0)
01242 {
01243 description->bounds.str = stp_string_list_create();
01244 stp_string_list_add_string(description->bounds.str, "None",
01245 _("Full Manual Control"));
01246 stp_string_list_add_string(description->bounds.str, "Auto",
01247 _("Automatic Setting Control"));
01248 description->deflt.str = "None";
01249 }
01250 else if (strcmp(name, "PageSize") == 0)
01251 {
01252 int papersizes = stp_known_papersizes();
01253 const input_slot_t *slot = get_input_slot(v);
01254 description->bounds.str = stp_string_list_create();
01255 if (slot && slot->is_cd)
01256 {
01257 stp_string_list_add_string
01258 (description->bounds.str, "CD5Inch", "CD - 5 inch");
01259 stp_string_list_add_string
01260 (description->bounds.str, "CD3Inch", "CD - 3 inch");
01261 }
01262 else
01263 {
01264 for (i = 0; i < papersizes; i++)
01265 {
01266 const stp_papersize_t *pt = stp_get_papersize_by_index(i);
01267 if (verify_papersize(v, pt))
01268 stp_string_list_add_string(description->bounds.str,
01269 pt->name, pt->text);
01270 }
01271 }
01272 description->deflt.str =
01273 stp_string_list_param(description->bounds.str, 0)->name;
01274 }
01275 else if (strcmp(name, "Quality") == 0)
01276 {
01277 const quality_list_t *quals = escp2_quality_list(v);
01278 int has_standard_quality = 0;
01279 description->bounds.str = stp_string_list_create();
01280 stp_string_list_add_string(description->bounds.str, "None",
01281 _("Manual Control"));
01282 for (i = 0; i < quals->n_quals; i++)
01283 {
01284 const quality_t *q = &(quals->qualities[i]);
01285 if (((q->min_vres == 0 || escp2_min_vres(v) <= q->min_vres) &&
01286 (q->min_hres == 0 || escp2_min_hres(v) <= q->min_hres) &&
01287 (q->max_vres == 0 || escp2_max_vres(v) >= q->max_vres) &&
01288 (q->max_hres == 0 || escp2_max_hres(v) >= q->max_hres)) &&
01289 (find_resolution_from_quality(v, q->name, 1) ||
01290 (!stp_check_string_parameter(v, "MediaType",
01291 STP_PARAMETER_ACTIVE))))
01292 stp_string_list_add_string(description->bounds.str, q->name,
01293 q->text);
01294 if (strcmp(q->name, "Standard") == 0)
01295 has_standard_quality = 1;
01296 }
01297 if (has_standard_quality)
01298 description->deflt.str = "Standard";
01299 else
01300 description->deflt.str = "None";
01301 }
01302 else if (strcmp(name, "Resolution") == 0)
01303 {
01304 const res_t *const *res = escp2_reslist(v);
01305 const res_t *defval = find_default_resolution(v, 720, 360, 0);
01306 description->bounds.str = stp_string_list_create();
01307 i = 0;
01308 while (res[i])
01309 {
01310 if (verify_resolution(v, res[i]) &&
01311 (using_automatic_settings(v, AUTO_MODE_MANUAL) ||
01312 !stp_check_string_parameter(v, "MediaType",
01313 STP_PARAMETER_ACTIVE) ||
01314 verify_resolution_by_paper_type(v, res[i])))
01315 stp_string_list_add_string(description->bounds.str,
01316 res[i]->name, _(res[i]->text));
01317 i++;
01318 }
01319 if (defval)
01320 description->deflt.str = defval->name;
01321 else
01322 description->deflt.str = res[0]->name;
01323 if (!using_automatic_settings(v, AUTO_MODE_MANUAL))
01324 description->is_active = 0;
01325 }
01326 else if (strcmp(name, "InkType") == 0)
01327 {
01328 const inklist_t *inks = escp2_inklist(v);
01329 int ninktypes = inks->n_inks;
01330 description->bounds.str = stp_string_list_create();
01331 if (ninktypes > 1)
01332 {
01333 stp_string_list_add_string(description->bounds.str, "None",
01334 _("Standard"));
01335 for (i = 0; i < ninktypes; i++)
01336 if (verify_inktype(v, inks->inknames[i]))
01337 stp_string_list_add_string(description->bounds.str,
01338 inks->inknames[i]->name,
01339 _(inks->inknames[i]->text));
01340 description->deflt.str = "None";
01341 }
01342 if (ninktypes <= 1 || !using_automatic_settings(v, AUTO_MODE_MANUAL))
01343 description->is_active = 0;
01344 }
01345 else if (strcmp(name, "InkSet") == 0)
01346 {
01347 const inkgroup_t *inks = escp2_inkgroup(v);
01348 int ninklists = inks->n_inklists;
01349 description->bounds.str = stp_string_list_create();
01350 if (ninklists > 1)
01351 {
01352 int has_default_choice = 0;
01353 for (i = 0; i < ninklists; i++)
01354 {
01355 stp_string_list_add_string(description->bounds.str,
01356 inks->inklists[i]->name,
01357 _(inks->inklists[i]->text));
01358 if (strcmp(inks->inklists[i]->name, "None") == 0)
01359 has_default_choice = 1;
01360 }
01361 description->deflt.str =
01362 stp_string_list_param(description->bounds.str, 0)->name;
01363 if (!using_automatic_settings(v, AUTO_MODE_MANUAL) &&
01364 has_default_choice)
01365 description->is_active = 0;
01366 }
01367 else
01368 description->is_active = 0;
01369 }
01370 else if (strcmp(name, "MediaType") == 0)
01371 {
01372 const paperlist_t *p = escp2_paperlist(v);
01373 int nmediatypes = p->paper_count;
01374 description->bounds.str = stp_string_list_create();
01375 if (nmediatypes)
01376 {
01377 for (i = 0; i < nmediatypes; i++)
01378 stp_string_list_add_string(description->bounds.str,
01379 p->papers[i].name,
01380 _(p->papers[i].text));
01381 description->deflt.str =
01382 stp_string_list_param(description->bounds.str, 0)->name;
01383 }
01384 else
01385 description->is_active = 0;
01386 }
01387 else if (strcmp(name, "InputSlot") == 0)
01388 {
01389 const input_slot_list_t *slots = escp2_input_slots(v);
01390 int ninputslots = slots->n_input_slots;
01391 description->bounds.str = stp_string_list_create();
01392 if (ninputslots)
01393 {
01394 for (i = 0; i < ninputslots; i++)
01395 stp_string_list_add_string(description->bounds.str,
01396 slots->slots[i].name,
01397 _(slots->slots[i].text));
01398 description->deflt.str =
01399 stp_string_list_param(description->bounds.str, 0)->name;
01400 }
01401 else
01402 description->is_active = 0;
01403 }
01404 else if (strcmp(name, "PrintingDirection") == 0)
01405 {
01406 description->bounds.str = stp_string_list_create();
01407 stp_string_list_add_string
01408 (description->bounds.str, "None", _("Automatic"));
01409 stp_string_list_add_string
01410 (description->bounds.str, "Bidirectional", _("Bidirectional"));
01411 stp_string_list_add_string
01412 (description->bounds.str, "Unidirectional", _("Unidirectional"));
01413 description->deflt.str =
01414 stp_string_list_param(description->bounds.str, 0)->name;
01415 if (!using_automatic_settings(v, AUTO_MODE_MANUAL))
01416 description->is_active = 0;
01417 }
01418 else if (strcmp(name, "Weave") == 0)
01419 {
01420 description->bounds.str = stp_string_list_create();
01421 if (escp2_has_cap(v, MODEL_COMMAND, MODEL_COMMAND_PRO))
01422 {
01423 const res_t *res = escp2_find_resolution(v);
01424 const printer_weave_list_t *printer_weaves = escp2_printer_weaves(v);
01425 int nprinter_weaves = 0;
01426 if (use_printer_weave(v) && (!res || res->printer_weave))
01427 nprinter_weaves = printer_weaves->n_printer_weaves;
01428 if (nprinter_weaves)
01429 {
01430 stp_string_list_add_string(description->bounds.str, "None",
01431 _("Standard"));
01432 for (i = 0; i < nprinter_weaves; i++)
01433 stp_string_list_add_string(description->bounds.str,
01434 printer_weaves->printer_weaves[i].name,
01435 _(printer_weaves->printer_weaves[i].text));
01436 }
01437 else
01438 description->is_active = 0;
01439 }
01440 else
01441 {
01442 stp_string_list_add_string
01443 (description->bounds.str, "None", _("Standard"));
01444 stp_string_list_add_string
01445 (description->bounds.str, "Alternate", _("Alternate Fill"));
01446 stp_string_list_add_string
01447 (description->bounds.str, "Ascending", _("Ascending Fill"));
01448 stp_string_list_add_string
01449 (description->bounds.str, "Descending", _("Descending Fill"));
01450 stp_string_list_add_string
01451 (description->bounds.str, "Ascending2X", _("Ascending Double"));
01452 stp_string_list_add_string
01453 (description->bounds.str, "Staggered", _("Nearest Neighbor Avoidance"));
01454 }
01455 if (description->is_active)
01456 description->deflt.str =
01457 stp_string_list_param(description->bounds.str, 0)->name;
01458 if (!using_automatic_settings(v, AUTO_MODE_MANUAL))
01459 description->is_active = 0;
01460 }
01461 else if (strcmp(name, "OutputOrder") == 0)
01462 {
01463 description->bounds.str = stp_string_list_create();
01464 description->deflt.str = "Reverse";
01465 }
01466 else if (strcmp(name, "FullBleed") == 0)
01467 {
01468 if (escp2_has_cap(v, MODEL_XZEROMARGIN, MODEL_XZEROMARGIN_YES))
01469 description->deflt.boolean = 0;
01470 else
01471 description->is_active = 0;
01472 }
01473 else if (strcmp(name, "AdjustDotsize") == 0)
01474 {
01475 description->deflt.boolean = 0;
01476 if (!using_automatic_settings(v, AUTO_MODE_MANUAL))
01477 description->is_active = 0;
01478 }
01479 else if (strcmp(name, "CyanDensity") == 0)
01480 set_density_parameter(v, description, STP_ECOLOR_C);
01481 else if (strcmp(name, "MagentaDensity") == 0)
01482 set_density_parameter(v, description, STP_ECOLOR_M);
01483 else if (strcmp(name, "YellowDensity") == 0)
01484 set_density_parameter(v, description, STP_ECOLOR_Y);
01485 else if (strcmp(name, "BlackDensity") == 0)
01486 set_density_parameter(v, description, STP_ECOLOR_K);
01487 else if (strcmp(name, "RedDensity") == 0)
01488 set_density_parameter(v, description, XCOLOR_R);
01489 else if (strcmp(name, "BlueDensity") == 0)
01490 set_density_parameter(v, description, XCOLOR_B);
01491 else if (strcmp(name, "GlossDensity") == 0)
01492 set_density_parameter(v, description, XCOLOR_GLOSS);
01493 else if (strcmp(name, "GrayTransition") == 0)
01494 set_gray_transition_parameter(v, description, 2);
01495 else if (strcmp(name, "Gray1Transition") == 0 ||
01496 strcmp(name, "Gray2Transition") == 0 ||
01497 strcmp(name, "Gray3Transition") == 0)
01498 set_gray_transition_parameter(v, description, 4);
01499 else if (strcmp(name, "LightCyanTransition") == 0)
01500 set_color_transition_parameter(v, description, STP_ECOLOR_C);
01501 else if (strcmp(name, "LightMagentaTransition") == 0)
01502 set_color_transition_parameter(v, description, STP_ECOLOR_M);
01503 else if (strcmp(name, "DarkYellowTransition") == 0)
01504 set_color_transition_parameter(v, description, STP_ECOLOR_Y);
01505 else if (strcmp(name, "AlignmentPasses") == 0)
01506 {
01507 description->deflt.integer = escp2_alignment_passes(v);
01508 }
01509 else if (strcmp(name, "AlignmentChoices") == 0)
01510 {
01511 description->deflt.integer = escp2_alignment_choices(v);
01512 }
01513 else if (strcmp(name, "SupportsInkChange") == 0)
01514 {
01515 description->deflt.integer =
01516 escp2_has_cap(v, MODEL_SUPPORTS_INK_CHANGE,
01517 MODEL_SUPPORTS_INK_CHANGE_YES);
01518 }
01519 else if (strcmp(name, "AlternateAlignmentPasses") == 0)
01520 {
01521 description->deflt.integer = escp2_alternate_alignment_passes(v);
01522 }
01523 else if (strcmp(name, "AlternateAlignmentChoices") == 0)
01524 {
01525 description->deflt.integer = escp2_alternate_alignment_choices(v);
01526 }
01527 else if (strcmp(name, "InkChannels") == 0)
01528 {
01529 description->deflt.integer = escp2_physical_channels(v);
01530 }
01531 else if (strcmp(name, "PrintingMode") == 0)
01532 {
01533 description->bounds.str = stp_string_list_create();
01534 stp_string_list_add_string
01535 (description->bounds.str, "Color", _("Color"));
01536 stp_string_list_add_string
01537 (description->bounds.str, "BW", _("Black and White"));
01538 description->deflt.str =
01539 stp_string_list_param(description->bounds.str, 0)->name;
01540 }
01541 else if (strcmp(name, "RawChannels") == 0)
01542 {
01543 const inklist_t *inks = escp2_inklist(v);
01544 int ninktypes = inks->n_inks;
01545 description->bounds.str = stp_string_list_create();
01546 if (ninktypes > 1)
01547 {
01548 stp_string_list_add_string(description->bounds.str, "None", "None");
01549 for (i = 0; i < ninktypes; i++)
01550 if (inks->inknames[i]->inkset == INKSET_EXTENDED)
01551 {
01552 const channel_count_t *ch =
01553 (get_channel_count_by_number
01554 (inks->inknames[i]->channel_set->channel_count));
01555 stp_string_list_add_string(description->bounds.str,
01556 ch->name, ch->name);
01557 }
01558 description->deflt.str =
01559 stp_string_list_param(description->bounds.str, 0)->name;
01560 }
01561 if (ninktypes <= 1)
01562 description->is_active = 0;
01563 }
01564 }
01565
01566 static const res_t *
01567 escp2_find_resolution(const stp_vars_t *v)
01568 {
01569 const char *resolution;
01570 if (stp_check_string_parameter(v, "Quality", STP_PARAMETER_ACTIVE))
01571 {
01572 const res_t *default_res =
01573 find_resolution_from_quality(v, stp_get_string_parameter(v, "Quality"),
01574 0);
01575 if (default_res)
01576 {
01577 stp_dprintf(STP_DBG_ESCP2, v,
01578 "Setting resolution to %s from quality %s\n",
01579 default_res->name,
01580 stp_get_string_parameter(v, "Quality"));
01581 return default_res;
01582 }
01583 else
01584 stp_dprintf(STP_DBG_ESCP2, v, "Unable to map quality %s\n",
01585 stp_get_string_parameter(v, "Quality"));
01586 }
01587 resolution = stp_get_string_parameter(v, "Resolution");
01588 if (resolution)
01589 {
01590 const res_t *const *res = escp2_reslist(v);
01591 int i = 0;
01592 while (res[i])
01593 {
01594 if (!strcmp(resolution, res[i]->name))
01595 return res[i];
01596 else if (!strcmp(res[i]->name, ""))
01597 return NULL;
01598 i++;
01599 }
01600 }
01601 return NULL;
01602 }
01603
01604 static inline int
01605 imax(int a, int b)
01606 {
01607 if (a > b)
01608 return a;
01609 else
01610 return b;
01611 }
01612
01613 static void
01614 internal_imageable_area(const stp_vars_t *v, int use_paper_margins,
01615 int *left, int *right, int *bottom, int *top)
01616 {
01617 int width, height;
01618 int rollfeed = 0;
01619 int cd = 0;
01620 const char *media_size = stp_get_string_parameter(v, "PageSize");
01621 int left_margin = 0;
01622 int right_margin = 0;
01623 int bottom_margin = 0;
01624 int top_margin = 0;
01625 const stp_papersize_t *pt = NULL;
01626 const input_slot_t *input_slot = NULL;
01627
01628 if (media_size && use_paper_margins)
01629 pt = stp_get_papersize_by_name(media_size);
01630
01631 input_slot = get_input_slot(v);
01632 if (input_slot)
01633 {
01634 cd = input_slot->is_cd;
01635 rollfeed = input_slot->is_roll_feed;
01636 }
01637
01638 stp_default_media_size(v, &width, &height);
01639 if (cd)
01640 {
01641 left_margin = 0;
01642 right_margin = 0;
01643 bottom_margin = 0;
01644 top_margin = 0;
01645 }
01646 else
01647 {
01648 if (pt)
01649 {
01650 left_margin = pt->left;
01651 right_margin = pt->right;
01652 bottom_margin = pt->bottom;
01653 top_margin = pt->top;
01654 }
01655
01656 left_margin = imax(left_margin, escp2_left_margin(v, rollfeed));
01657 right_margin = imax(right_margin, escp2_right_margin(v, rollfeed));
01658 bottom_margin = imax(bottom_margin, escp2_bottom_margin(v, rollfeed));
01659 top_margin = imax(top_margin, escp2_top_margin(v, rollfeed));
01660 }
01661 *left = left_margin;
01662 *right = width - right_margin;
01663 *top = top_margin;
01664 *bottom = height - bottom_margin;
01665 if (!cd &&
01666 escp2_has_cap(v, MODEL_XZEROMARGIN, MODEL_XZEROMARGIN_YES) &&
01667 stp_get_boolean_parameter(v, "FullBleed"))
01668 {
01669 *left -= 80 / (360 / 72);
01670 *right += 80 / (360 / 72);
01671 *bottom += escp2_nozzles(v) * escp2_nozzle_separation(v) * 72 /
01672 escp2_base_separation(v);
01673 }
01674 }
01675
01676
01677
01678
01679
01680 static void
01681 escp2_imageable_area(const stp_vars_t *v,
01682 int *left,
01683 int *right,
01684 int *bottom,
01685 int *top)
01686 {
01687 internal_imageable_area(v, 1, left, right, bottom, top);
01688 }
01689
01690 static void
01691 escp2_limit(const stp_vars_t *v,
01692 int *width, int *height,
01693 int *min_width, int *min_height)
01694 {
01695 *width = escp2_max_paper_width(v);
01696 *height = escp2_max_paper_height(v);
01697 *min_width = escp2_min_paper_width(v);
01698 *min_height = escp2_min_paper_height(v);
01699 }
01700
01701 static void
01702 escp2_describe_resolution(const stp_vars_t *v, int *x, int *y)
01703 {
01704 const res_t *res = escp2_find_resolution(v);
01705 if (res && verify_resolution(v, res))
01706 {
01707 *x = res->printed_hres;
01708 *y = res->printed_vres;
01709 return;
01710 }
01711 *x = -1;
01712 *y = -1;
01713 }
01714
01715 static const char *
01716 escp2_describe_output(const stp_vars_t *v)
01717 {
01718 const char *printing_mode = stp_get_string_parameter(v, "PrintingMode");
01719 const char *input_image_type = stp_get_string_parameter(v, "InputImageType");
01720 if (input_image_type && strcmp(input_image_type, "Raw") == 0)
01721 return "Raw";
01722 else if (printing_mode && strcmp(printing_mode, "BW") == 0)
01723 return "Grayscale";
01724 else
01725 {
01726 const escp2_inkname_t *ink_type = get_inktype(v);
01727 if (ink_type)
01728 {
01729 switch (ink_type->inkset)
01730 {
01731 case INKSET_CMYKRB:
01732 return "CMYKRB";
01733 case INKSET_CMYK:
01734 case INKSET_CcMmYK:
01735 case INKSET_CcMmYyK:
01736 case INKSET_CcMmYKk:
01737 default:
01738 if (ink_type->channel_set->channels[0])
01739 return "KCMY";
01740 else
01741 return "CMY";
01742 break;
01743 }
01744 }
01745 else
01746 return "CMYK";
01747 }
01748 }
01749
01750 static int
01751 escp2_has_advanced_command_set(const stp_vars_t *v)
01752 {
01753 return (escp2_has_cap(v, MODEL_COMMAND, MODEL_COMMAND_PRO) ||
01754 escp2_has_cap(v, MODEL_COMMAND, MODEL_COMMAND_1999) ||
01755 escp2_has_cap(v, MODEL_COMMAND, MODEL_COMMAND_2000));
01756 }
01757
01758 static int
01759 escp2_use_extended_commands(const stp_vars_t *v, int use_softweave)
01760 {
01761 return (escp2_has_cap(v, MODEL_COMMAND, MODEL_COMMAND_PRO) ||
01762 (escp2_has_cap(v, MODEL_VARIABLE_DOT, MODEL_VARIABLE_YES) &&
01763 use_softweave));
01764 }
01765
01766 static int
01767 set_raw_ink_type(stp_vars_t *v)
01768 {
01769 const inklist_t *inks = escp2_inklist(v);
01770 int ninktypes = inks->n_inks;
01771 int i;
01772 const char *channel_name = stp_get_string_parameter(v, "RawChannels");
01773 const channel_count_t *count;
01774 if (!channel_name)
01775 return 0;
01776 count = get_channel_count_by_name(channel_name);
01777 if (!count)
01778 return 0;
01779
01780
01781
01782
01783 for (i = 0; i < ninktypes; i++)
01784 if (inks->inknames[i]->inkset == INKSET_EXTENDED &&
01785 (inks->inknames[i]->channel_set->channel_count == count->count))
01786 {
01787 stp_dprintf(STP_DBG_INK, v, "Changing ink type from %s to %s\n",
01788 stp_get_string_parameter(v, "InkType") ?
01789 stp_get_string_parameter(v, "InkType") : "NULL",
01790 inks->inknames[i]->name);
01791 stp_set_string_parameter(v, "InkType", inks->inknames[i]->name);
01792 stp_set_int_parameter(v, "STPIRawChannels", count->count);
01793 return 1;
01794 }
01795 stp_eprintf
01796 (v, _("This printer does not support raw printer output at depth %d\n"),
01797 count->count);
01798 return 0;
01799 }
01800
01801 static void
01802 adjust_density_and_ink_type(stp_vars_t *v, stp_image_t *image)
01803 {
01804 escp2_privdata_t *pd = get_privdata(v);
01805 const paper_adjustment_t *pt = pd->paper_adjustment;
01806 double paper_density = .8;
01807 int o_resid = compute_printed_resid(pd->res);
01808
01809 if (pt)
01810 paper_density = pt->base_density;
01811
01812 if (!stp_check_float_parameter(v, "Density", STP_PARAMETER_DEFAULTED))
01813 {
01814 stp_set_float_parameter_active(v, "Density", STP_PARAMETER_ACTIVE);
01815 stp_set_float_parameter(v, "Density", 1.0);
01816 }
01817
01818 stp_scale_float_parameter
01819 (v, "Density", paper_density * escp2_density(v, o_resid));
01820 pd->drop_size = escp2_ink_type(v, o_resid);
01821 pd->ink_resid = o_resid;
01822
01823
01824
01825
01826
01827
01828 if (stp_get_float_parameter(v, "Density") > 1.0)
01829 {
01830 if (stp_check_int_parameter(v, "escp2_ink_type", STP_PARAMETER_ACTIVE) ||
01831 stp_check_int_parameter(v, "escp2_density", STP_PARAMETER_ACTIVE) ||
01832 stp_check_int_parameter(v, "escp2_bits", STP_PARAMETER_ACTIVE) ||
01833 (stp_check_boolean_parameter(v, "AdjustDotsize",
01834 STP_PARAMETER_ACTIVE) &&
01835 ! stp_get_boolean_parameter(v, "AdjustDotsize")))
01836 {
01837 stp_set_float_parameter(v, "Density", 1.0);
01838 }
01839 else
01840 {
01841 double density = stp_get_float_parameter(v, "Density");
01842 int resid = o_resid;
01843 int xresid = resid;
01844 double xdensity = density;
01845 while (density > 1.0 && resid >= RES_360)
01846 {
01847 int tresid = xresid - 1;
01848 int bits_now = escp2_bits(v, resid);
01849 double density_now = escp2_density(v, resid);
01850 int bits_then = escp2_bits(v, tresid);
01851 double density_then = escp2_density(v, tresid);
01852 int drop_size_then = escp2_ink_type(v, tresid);
01853
01854
01855
01856
01857
01858
01859
01860 if (bits_now != bits_then || density_then <= 0.0 ||
01861 drop_size_then == -1)
01862 break;
01863 xdensity = density * density_then / density_now / 2;
01864 xresid = tresid;
01865
01866
01867
01868
01869
01870 if (density / xdensity > 1.001)
01871 {
01872 density = xdensity;
01873 resid = tresid;
01874 }
01875 }
01876 pd->drop_size = escp2_ink_type(v, resid);
01877 pd->ink_resid = resid;
01878 if (density > 1.0)
01879 density = 1.0;
01880 stp_set_float_parameter(v, "Density", density);
01881 }
01882 }
01883 }
01884
01885 static void
01886 adjust_print_quality(stp_vars_t *v, stp_image_t *image)
01887 {
01888 escp2_privdata_t *pd = get_privdata(v);
01889 stp_curve_t *adjustment = NULL;
01890 const paper_adjustment_t *pt;
01891 double k_upper = 1.0;
01892 double k_lower = 0;
01893 double k_transition = 1.0;
01894
01895
01896
01897
01898
01899
01900 pt = pd->paper_adjustment;
01901 if (pt)
01902 {
01903 k_lower = pt->k_lower;
01904 k_upper = pt->k_upper;
01905 k_transition = pt->k_transition;
01906 stp_set_default_float_parameter(v, "CyanDensity", 1.0);
01907 stp_scale_float_parameter(v, "CyanDensity", pt->cyan);
01908 stp_set_default_float_parameter(v, "MagentaDensity", 1.0);
01909 stp_scale_float_parameter(v, "MagentaDensity", pt->magenta);
01910 stp_set_default_float_parameter(v, "YellowDensity", 1.0);
01911 stp_scale_float_parameter(v, "YellowDensity", pt->yellow);
01912 stp_set_default_float_parameter(v, "BlackDensity", 1.0);
01913 stp_scale_float_parameter(v, "BlackDensity", pt->black);
01914 stp_set_default_float_parameter(v, "Saturation", 1.0);
01915 stp_scale_float_parameter(v, "Saturation", pt->saturation);
01916 stp_set_default_float_parameter(v, "Gamma", 1.0);
01917 stp_scale_float_parameter(v, "Gamma", pt->gamma);
01918 }
01919
01920
01921 if (!stp_check_float_parameter(v, "GCRLower", STP_PARAMETER_ACTIVE))
01922 stp_set_default_float_parameter(v, "GCRLower", k_lower);
01923 if (!stp_check_float_parameter(v, "GCRUpper", STP_PARAMETER_ACTIVE))
01924 stp_set_default_float_parameter(v, "GCRUpper", k_upper);
01925 if (!stp_check_float_parameter(v, "BlackGamma", STP_PARAMETER_ACTIVE))
01926 stp_set_default_float_parameter(v, "BlackGamma", k_transition);
01927
01928
01929 if (!stp_check_curve_parameter(v, "HueMap", STP_PARAMETER_ACTIVE) &&
01930 pt->hue_adjustment)
01931 {
01932 adjustment = stp_curve_create_from_string(pt->hue_adjustment);
01933 stp_set_curve_parameter(v, "HueMap", adjustment);
01934 stp_set_curve_parameter_active(v, "HueMap", STP_PARAMETER_ACTIVE);
01935 stp_curve_destroy(adjustment);
01936 }
01937 if (!stp_check_curve_parameter(v, "SatMap", STP_PARAMETER_ACTIVE) &&
01938 pt->sat_adjustment)
01939 {
01940 adjustment = stp_curve_create_from_string(pt->sat_adjustment);
01941 stp_set_curve_parameter(v, "SatMap", adjustment);
01942 stp_set_curve_parameter_active(v, "SatMap", STP_PARAMETER_ACTIVE);
01943 stp_curve_destroy(adjustment);
01944 }
01945 if (!stp_check_curve_parameter(v, "LumMap", STP_PARAMETER_ACTIVE) &&
01946 pt->lum_adjustment)
01947 {
01948 adjustment = stp_curve_create_from_string(pt->lum_adjustment);
01949 stp_set_curve_parameter(v, "LumMap", adjustment);
01950 stp_set_curve_parameter_active(v, "LumMap", STP_PARAMETER_ACTIVE);
01951 stp_curve_destroy(adjustment);
01952 }
01953 }
01954
01955 static int
01956 count_channels(const escp2_inkname_t *inks)
01957 {
01958 int answer = 0;
01959 int i;
01960 for (i = 0; i < inks->channel_set->channel_count; i++)
01961 if (inks->channel_set->channels[i])
01962 answer += inks->channel_set->channels[i]->n_subchannels;
01963 return answer;
01964 }
01965
01966 static int
01967 compute_channel_count(const escp2_inkname_t *ink_type, int channel_limit)
01968 {
01969 int i;
01970 int physical_channels = 0;
01971 for (i = 0; i < channel_limit; i++)
01972 {
01973 const ink_channel_t *channel = ink_type->channel_set->channels[i];
01974 if (channel)
01975 physical_channels += channel->n_subchannels;
01976 }
01977 return physical_channels;
01978 }
01979
01980 static double
01981 get_double_param(const stp_vars_t *v, const char *param)
01982 {
01983 if (param && stp_check_float_parameter(v, param, STP_PARAMETER_ACTIVE))
01984 return stp_get_float_parameter(v, param);
01985 else
01986 return 1.0;
01987 }
01988
01989 static void
01990 setup_inks(stp_vars_t *v)
01991 {
01992 escp2_privdata_t *pd = get_privdata(v);
01993 int i, j;
01994 const escp2_dropsize_t *drops;
01995 const escp2_inkname_t *ink_type = pd->inkname;
01996 const paper_adjustment_t *paper = pd->paper_adjustment;
01997
01998 drops = escp2_dropsizes(v, pd->ink_resid);
01999 stp_init_debug_messages(v);
02000 for (i = 0; i < pd->logical_channels; i++)
02001 {
02002 const ink_channel_t *channel = ink_type->channel_set->channels[i];
02003 if (channel && channel->n_subchannels > 0)
02004 {
02005 const char *param = channel->subchannels[0].channel_density;
02006 const shade_t *shades = escp2_shades(v, i);
02007 double userval = get_double_param(v, param);
02008 if (shades->n_shades < channel->n_subchannels)
02009 {
02010 stp_erprintf("Not enough shades!\n");
02011 }
02012 if (strcmp(param, "BlackDensity") == 0)
02013 stp_channel_set_black_channel(v, i);
02014 stp_dither_set_inks(v, i, 1.0, ink_darknesses[i % 8],
02015 channel->n_subchannels, shades->shades,
02016 drops->numdropsizes, drops->dropsizes);
02017 for (j = 0; j < channel->n_subchannels; j++)
02018 {
02019 const char *subparam =
02020 channel->subchannels[j].subchannel_scale;
02021 double scale = userval * get_double_param(v, subparam);
02022 scale *= get_double_param(v, "Density");
02023 stp_channel_set_density_adjustment(v, i, j, scale);
02024 if (paper)
02025 stp_channel_set_cutoff_adjustment(v, i, j,
02026 paper->subchannel_cutoff);
02027 }
02028 }
02029 }
02030 stp_flush_debug_messages(v);
02031 }
02032
02033 static void
02034 setup_head_offset(stp_vars_t *v)
02035 {
02036 escp2_privdata_t *pd = get_privdata(v);
02037 int i;
02038 int channel_id = 0;
02039 int channel_limit = pd->logical_channels;
02040 const escp2_inkname_t *ink_type = pd->inkname;
02041 if (pd->channels_in_use > pd->logical_channels)
02042 channel_limit = pd->channels_in_use;
02043 pd->head_offset = stp_zalloc(sizeof(int) * channel_limit);
02044 for (i = 0; i < pd->logical_channels; i++)
02045 {
02046 const ink_channel_t *channel = ink_type->channel_set->channels[i];
02047 if (channel)
02048 {
02049 int j;
02050 for (j = 0; j < channel->n_subchannels; j++)
02051 {
02052 pd->head_offset[channel_id] =
02053 channel->subchannels[j].head_offset;
02054 channel_id++;
02055 }
02056 }
02057 }
02058 if (pd->physical_channels == 1)
02059 pd->head_offset[0] = 0;
02060 pd->max_head_offset = 0;
02061 if (pd->physical_channels > 1)
02062 for (i = 0; i < pd->channels_in_use; i++)
02063 {
02064 pd->head_offset[i] = pd->head_offset[i] * pd->res->vres /
02065 escp2_base_separation(v);
02066 if (pd->head_offset[i] > pd->max_head_offset)
02067 pd->max_head_offset = pd->head_offset[i];
02068 }
02069 }
02070
02071 static void
02072 setup_misc(stp_vars_t *v)
02073 {
02074 escp2_privdata_t *pd = get_privdata(v);
02075 pd->input_slot = get_input_slot(v);
02076 pd->paper_type = get_media_type(v);
02077 pd->paper_adjustment = get_media_adjustment(v);
02078 pd->ink_group = escp2_inkgroup(v);
02079 pd->init_sequence = escp2_preinit_sequence(v);
02080 pd->deinit_sequence = escp2_postinit_remote_sequence(v);
02081 pd->advanced_command_set = escp2_has_advanced_command_set(v);
02082 pd->command_set = escp2_get_cap(v, MODEL_COMMAND);
02083 pd->variable_dots = escp2_has_cap(v, MODEL_VARIABLE_DOT, MODEL_VARIABLE_YES);
02084 pd->has_vacuum = escp2_has_cap(v, MODEL_VACUUM, MODEL_VACUUM_YES);
02085 pd->has_graymode = escp2_has_cap(v, MODEL_GRAYMODE, MODEL_GRAYMODE_YES);
02086 pd->base_separation = escp2_base_separation(v);
02087 pd->resolution_scale = escp2_resolution_scale(v);
02088 pd->use_extended_commands =
02089 escp2_use_extended_commands(v, pd->res->softweave);
02090 }
02091
02092 static void
02093 allocate_channels(stp_vars_t *v, int line_length)
02094 {
02095 escp2_privdata_t *pd = get_privdata(v);
02096 const escp2_inkname_t *ink_type = pd->inkname;
02097 int i;
02098 int channel_id = 0;
02099
02100 pd->cols = stp_zalloc(sizeof(unsigned char *) * pd->channels_in_use);
02101 pd->channels =
02102 stp_zalloc(sizeof(physical_subchannel_t *) * pd->channels_in_use);
02103
02104 for (i = 0; i < pd->logical_channels; i++)
02105 {
02106 const ink_channel_t *channel = ink_type->channel_set->channels[i];
02107 if (channel)
02108 {
02109 int j;
02110 for (j = 0; j < channel->n_subchannels; j++)
02111 {
02112 pd->cols[channel_id] = stp_zalloc(line_length);
02113 pd->channels[channel_id] = &(channel->subchannels[j]);
02114 stp_dither_add_channel(v, pd->cols[channel_id], i, j);
02115 channel_id++;
02116 }
02117 }
02118 }
02119 stp_set_string_parameter(v, "STPIOutputType", escp2_describe_output(v));
02120 }
02121
02122 static unsigned
02123 gcd(unsigned a, unsigned b)
02124 {
02125 unsigned tmp;
02126 if (b > a)
02127 {
02128 tmp = a;
02129 a = b;
02130 b = tmp;
02131 }
02132 while (1)
02133 {
02134 tmp = a % b;
02135 if (tmp == 0)
02136 return b;
02137 a = b;
02138 b = tmp;
02139 }
02140 }
02141
02142 static unsigned
02143 lcm(unsigned a, unsigned b)
02144 {
02145 if (a == b)
02146 return a;
02147 else
02148 return a * b / gcd(a, b);
02149 }
02150
02151 static int
02152 adjusted_vertical_resolution(const res_t *res)
02153 {
02154 if (res->vres >= 720)
02155 return res->vres;
02156 else if (res->hres >= 720)
02157 return 720;
02158 else if (res->vres % 90 == 0)
02159 return res->vres;
02160 else
02161 return lcm(res->hres, res->vres);
02162 }
02163
02164 static int
02165 adjusted_horizontal_resolution(const res_t *res)
02166 {
02167 if (res->vres % 90 == 0)
02168 return res->hres;
02169 else
02170 return lcm(res->hres, res->vres);
02171 }
02172
02173 static void
02174 setup_resolution(stp_vars_t *v)
02175 {
02176 escp2_privdata_t *pd = get_privdata(v);
02177 const res_t *res = escp2_find_resolution(v);
02178 int resid = compute_resid(res);
02179
02180 int vertical = adjusted_vertical_resolution(res);
02181 int horizontal = adjusted_horizontal_resolution(res);
02182
02183 pd->res = res;
02184 pd->physical_xdpi = escp2_base_res(v, resid);
02185 if (pd->physical_xdpi > pd->res->hres)
02186 pd->physical_xdpi = pd->res->hres;
02187
02188 if (escp2_use_extended_commands(v, pd->res->softweave))
02189 {
02190 pd->unit_scale = escp2_max_hres(v);
02191 pd->horizontal_units = horizontal;
02192 pd->micro_units = horizontal;
02193 }
02194 else
02195 {
02196 pd->unit_scale = 3600;
02197 if (pd->res->hres <= 720)
02198 pd->micro_units = vertical;
02199 else
02200 pd->micro_units = horizontal;
02201 pd->horizontal_units = vertical;
02202 }
02203 if (escp2_has_cap(v, MODEL_COMMAND, MODEL_COMMAND_1999) &&
02204 escp2_has_cap(v, MODEL_VARIABLE_DOT, MODEL_VARIABLE_NO))
02205 pd->micro_units = 1440;
02206 pd->vertical_units = vertical;
02207 pd->page_management_units = vertical;
02208 pd->printing_resolution = escp2_base_res(v, resid);
02209 }
02210
02211 static void
02212 setup_softweave_parameters(stp_vars_t *v)
02213 {
02214 escp2_privdata_t *pd = get_privdata(v);
02215 pd->horizontal_passes = pd->res->printed_hres / pd->physical_xdpi;
02216 if (pd->physical_channels == 1 &&
02217 (pd->res->vres >=
02218 (escp2_base_separation(v) / escp2_black_nozzle_separation(v))) &&
02219 (escp2_max_black_resolution(v) < 0 ||
02220 pd->res->vres <= escp2_max_black_resolution(v)) &&
02221 escp2_black_nozzles(v))
02222 pd->use_black_parameters = 1;
02223 else
02224 pd->use_black_parameters = 0;
02225 if (pd->use_fast_360)
02226 {
02227 pd->nozzles = escp2_fast_nozzles(v);
02228 pd->nozzle_separation = escp2_fast_nozzle_separation(v);
02229 pd->min_nozzles = escp2_min_fast_nozzles(v);
02230 }
02231 else if (pd->use_black_parameters)
02232 {
02233 pd->nozzles = escp2_black_nozzles(v);
02234 pd->nozzle_separation = escp2_black_nozzle_separation(v);
02235 pd->min_nozzles = escp2_min_black_nozzles(v);
02236 }
02237 else
02238 {
02239 pd->nozzles = escp2_nozzles(v);
02240 pd->nozzle_separation = escp2_nozzle_separation(v);
02241 pd->min_nozzles = escp2_min_nozzles(v);
02242 }
02243 }
02244
02245 static void
02246 setup_printer_weave_parameters(stp_vars_t *v)
02247 {
02248 escp2_privdata_t *pd = get_privdata(v);
02249 pd->horizontal_passes = 1;
02250 pd->nozzles = 1;
02251 pd->nozzle_separation = 1;
02252 pd->min_nozzles = 1;
02253 pd->use_black_parameters = 0;
02254 }
02255
02256 static void
02257 setup_head_parameters(stp_vars_t *v)
02258 {
02259 escp2_privdata_t *pd = get_privdata(v);
02260
02261
02262
02263 if (strcmp(stp_get_string_parameter(v, "PrintingMode"), "BW") == 0)
02264 pd->logical_channels = 1;
02265 else
02266 pd->logical_channels = pd->inkname->channel_set->channel_count;
02267
02268 pd->physical_channels =
02269 compute_channel_count(pd->inkname, pd->logical_channels);
02270 if (pd->physical_channels == 0)
02271 {
02272 pd->inkname = &stpi_escp2_default_black_inkset;
02273 pd->physical_channels =
02274 compute_channel_count(pd->inkname, pd->logical_channels);
02275 }
02276
02277 pd->use_printer_weave = use_printer_weave(v);
02278 if (pd->use_printer_weave)
02279 {
02280 pd->printer_weave = get_printer_weave(v);
02281 if (pd->res->softweave && pd->printer_weave && pd->printer_weave->value == 0)
02282 pd->printer_weave = NULL;
02283 }
02284
02285
02286 if (escp2_has_cap(v, MODEL_FAST_360, MODEL_FAST_360_YES) &&
02287 (pd->inkname->inkset == INKSET_CMYK || pd->physical_channels == 1) &&
02288 pd->res->hres == pd->physical_xdpi && pd->res->vres == 360)
02289 pd->use_fast_360 = 1;
02290 else
02291 pd->use_fast_360 = 0;
02292
02293
02294
02295
02296 if (pd->use_printer_weave)
02297 setup_printer_weave_parameters(v);
02298 else
02299 setup_softweave_parameters(v);
02300 pd->separation_rows = escp2_separation_rows(v);
02301 pd->pseudo_separation_rows = escp2_pseudo_separation_rows(v);
02302 pd->extra_720dpi_separation = escp2_extra_720dpi_separation(v);
02303
02304 if (pd->horizontal_passes == 0)
02305 pd->horizontal_passes = 1;
02306
02307 setup_head_offset(v);
02308
02309 if (strcmp(stp_get_string_parameter(v, "PrintingMode"), "BW") == 0 &&
02310 pd->physical_channels == 1)
02311 {
02312 if (pd->use_black_parameters)
02313 pd->initial_vertical_offset =
02314 escp2_black_initial_vertical_offset(v) * pd->page_management_units /
02315 escp2_base_separation(v);
02316 else
02317 pd->initial_vertical_offset = pd->head_offset[0] +
02318 (escp2_initial_vertical_offset(v) *
02319 pd->page_management_units / escp2_base_separation(v));
02320 }
02321 else
02322 pd->initial_vertical_offset =
02323 escp2_initial_vertical_offset(v) * pd->page_management_units /
02324 escp2_base_separation(v);
02325
02326 pd->printing_initial_vertical_offset = 0;
02327 pd->bitwidth = escp2_bits(v, compute_printed_resid(pd->res));
02328 }
02329
02330 static void
02331 setup_page(stp_vars_t *v)
02332 {
02333 int n;
02334 escp2_privdata_t *pd = get_privdata(v);
02335 const input_slot_t *input_slot = get_input_slot(v);
02336 int extra_left = 0;
02337 int extra_top = 0;
02338
02339 stp_default_media_size(v, &n, &(pd->page_true_height));
02340 internal_imageable_area(v, 0, &pd->page_left, &pd->page_right,
02341 &pd->page_bottom, &pd->page_top);
02342
02343 if (input_slot && input_slot->is_cd && escp2_cd_x_offset(v) > 0)
02344 {
02345 int left_center = escp2_cd_x_offset(v);
02346 int top_center = escp2_cd_y_offset(v);
02347 if (escp2_cd_page_width(v))
02348 pd->page_right = escp2_cd_page_width(v);
02349 else
02350 extra_left = left_center - (pd->page_right / 2);
02351 if (escp2_cd_page_height(v))
02352 {
02353 pd->page_bottom = escp2_cd_page_height(v);
02354 pd->page_true_height = escp2_cd_page_height(v);
02355 }
02356 else
02357 extra_top = top_center - (pd->page_bottom / 2);
02358 pd->cd_inner_radius = 43 * pd->micro_units * 10 / 254 / 2;
02359 pd->cd_outer_radius = pd->page_right * pd->micro_units / 72 / 2;
02360 pd->cd_x_offset =
02361 ((pd->page_right / 2) - stp_get_left(v)) * pd->micro_units / 72;
02362 pd->cd_y_offset =
02363 ((pd->page_bottom / 2) - stp_get_top(v)) * pd->micro_units / 72;
02364 }
02365
02366 pd->page_right += extra_left + 1;
02367 pd->page_width = pd->page_right - pd->page_left;
02368 pd->image_left = stp_get_left(v) - pd->page_left + extra_left;
02369 pd->image_width = stp_get_width(v);
02370 pd->image_scaled_width = pd->image_width * pd->res->hres / 72;
02371 pd->image_printed_width = pd->image_width * pd->res->printed_hres / 72;
02372 pd->image_left_position = pd->image_left * pd->micro_units / 72;
02373
02374
02375 pd->page_bottom += extra_top + 1;
02376 pd->page_true_height += extra_top + 1;
02377 pd->page_height = pd->page_bottom - pd->page_top;
02378 pd->image_top = stp_get_top(v) - pd->page_top + extra_top;
02379 pd->image_height = stp_get_height(v);
02380 pd->image_scaled_height = pd->image_height * pd->res->vres / 72;
02381 pd->image_printed_height = pd->image_height * pd->res->printed_vres / 72;
02382
02383 if (input_slot && input_slot->roll_feed_cut_flags)
02384 {
02385 pd->page_true_height += 4;
02386 pd->page_top += 2;
02387 pd->page_bottom += 2;
02388 pd->image_top += 2;
02389 pd->page_height += 2;
02390 }
02391 }
02392
02393 static void
02394 set_mask(unsigned char *cd_mask, int x_center, int scaled_x_where,
02395 int limit, int expansion, int invert)
02396 {
02397 int clear_val = invert ? 255 : 0;
02398 int set_val = invert ? 0 : 255;
02399 int bytesize = 8 / expansion;
02400 int byteextra = bytesize - 1;
02401 int first_x_on = x_center - scaled_x_where;
02402 int first_x_off = x_center + scaled_x_where;
02403 if (first_x_on < 0)
02404 first_x_on = 0;
02405 if (first_x_on > limit)
02406 first_x_on = limit;
02407 if (first_x_off < 0)
02408 first_x_off = 0;
02409 if (first_x_off > limit)
02410 first_x_off = limit;
02411 first_x_on += byteextra;
02412 if (first_x_off > (first_x_on - byteextra))
02413 {
02414 int first_x_on_byte = first_x_on / bytesize;
02415 int first_x_on_mod = expansion * (byteextra - (first_x_on % bytesize));
02416 int first_x_on_extra = ((1 << first_x_on_mod) - 1) ^ clear_val;
02417 int first_x_off_byte = first_x_off / bytesize;
02418 int first_x_off_mod = expansion * (byteextra - (first_x_off % bytesize));
02419 int first_x_off_extra = ((1 << 8) - (1 << first_x_off_mod)) ^ clear_val;
02420 if (first_x_off_byte < first_x_on_byte)
02421 {
02422
02423 cd_mask[first_x_on_byte] = first_x_on_extra & first_x_off_extra;
02424 }
02425 else
02426 {
02427 if (first_x_on_extra != clear_val)
02428 cd_mask[first_x_on_byte - 1] = first_x_on_extra;
02429 if (first_x_off_byte > first_x_on_byte)
02430 memset(cd_mask + first_x_on_byte, set_val,
02431 first_x_off_byte - first_x_on_byte);
02432 if (first_x_off_extra != clear_val)
02433 cd_mask[first_x_off_byte] = first_x_off_extra;
02434 }
02435 }
02436 }
02437
02438 static int
02439 escp2_print_data(stp_vars_t *v, stp_image_t *image)
02440 {
02441 escp2_privdata_t *pd = get_privdata(v);
02442 int errdiv = stp_image_height(image) / pd->image_printed_height;
02443 int errmod = stp_image_height(image) % pd->image_printed_height;
02444 int errval = 0;
02445 int errlast = -1;
02446 int errline = 0;
02447 int y;
02448 double outer_r_sq = 0;
02449 double inner_r_sq = 0;
02450 int x_center = pd->cd_x_offset * pd->res->printed_hres / pd->micro_units;
02451 unsigned char *cd_mask = NULL;
02452 if (pd->cd_outer_radius > 0)
02453 {
02454 cd_mask = stp_malloc(1 + (pd->image_printed_width + 7) / 8);
02455 outer_r_sq = (double) pd->cd_outer_radius * (double) pd->cd_outer_radius;
02456 inner_r_sq = (double) pd->cd_inner_radius * (double) pd->cd_inner_radius;
02457 }
02458
02459 for (y = 0; y < pd->image_printed_height; y ++)
02460 {
02461 int duplicate_line = 1;
02462 unsigned zero_mask;
02463
02464 if (errline != errlast)
02465 {
02466 errlast = errline;
02467 duplicate_line = 0;
02468 if (stp_color_get_row(v, image, errline, &zero_mask))
02469 return 2;
02470 }
02471
02472 if (cd_mask)
02473 {
02474 int y_distance_from_center =
02475 pd->cd_y_offset - (y * pd->micro_units / pd->res->printed_vres);
02476 if (y_distance_from_center < 0)
02477 y_distance_from_center = -y_distance_from_center;
02478 memset(cd_mask, 0, (pd->image_printed_width + 7) / 8);
02479 if (y_distance_from_center < pd->cd_outer_radius)
02480 {
02481 double y_sq = (double) y_distance_from_center *
02482 (double) y_distance_from_center;
02483 int x_where = sqrt(outer_r_sq - y_sq) + .5;
02484 int scaled_x_where = x_where * pd->res->printed_hres / pd->micro_units;
02485 set_mask(cd_mask, x_center, scaled_x_where,
02486 pd->image_printed_width, 1, 0);
02487 if (y_distance_from_center < pd->cd_inner_radius)
02488 {
02489 x_where = sqrt(inner_r_sq - y_sq) + .5;
02490 scaled_x_where = x_where * pd->res->printed_hres / pd->micro_units;
02491 set_mask(cd_mask, x_center, scaled_x_where,
02492 pd->image_printed_width, 1, 1);
02493 }
02494 }
02495 }
02496
02497 stp_dither(v, y, duplicate_line, zero_mask, cd_mask);
02498
02499 stp_write_weave(v, pd->cols);
02500 errval += errmod;
02501 errline += errdiv;
02502 if (errval >= pd->image_printed_height)
02503 {
02504 errval -= pd->image_printed_height;
02505 errline ++;
02506 }
02507 }
02508 if (cd_mask)
02509 stp_free(cd_mask);
02510 return 1;
02511 }
02512
02513 static int
02514 escp2_print_page(stp_vars_t *v, stp_image_t *image)
02515 {
02516 int status;
02517 int i;
02518 escp2_privdata_t *pd = get_privdata(v);
02519 int out_channels;
02520 int line_width = (pd->image_printed_width + 7) / 8 * pd->bitwidth;
02521 int weave_pattern = STP_WEAVE_ZIGZAG;
02522 if (stp_check_string_parameter(v, "Weave", STP_PARAMETER_ACTIVE))
02523 {
02524 const char *weave = stp_get_string_parameter(v, "Weave");
02525 if (strcmp(weave, "Alternate") == 0)
02526 weave_pattern = STP_WEAVE_ZIGZAG;
02527 else if (strcmp(weave, "Ascending") == 0)
02528 weave_pattern = STP_WEAVE_ASCENDING;
02529 else if (strcmp(weave, "Descending") == 0)
02530 weave_pattern = STP_WEAVE_DESCENDING;
02531 else if (strcmp(weave, "Ascending2X") == 0)
02532 weave_pattern = STP_WEAVE_ASCENDING_2X;
02533 else if (strcmp(weave, "Staggered") == 0)
02534 weave_pattern = STP_WEAVE_STAGGERED;
02535 }
02536
02537 stp_initialize_weave
02538 (v,
02539 pd->nozzles,
02540 pd->nozzle_separation * pd->res->vres / escp2_base_separation(v),
02541 pd->horizontal_passes,
02542 pd->res->vertical_passes,
02543 1,
02544 pd->channels_in_use,
02545 pd->bitwidth,
02546 pd->image_printed_width,
02547 pd->image_printed_height,
02548 pd->image_top * pd->res->vres / 72,
02549 (pd->page_height + escp2_extra_feed(v)) * pd->res->vres / 72,
02550 pd->head_offset,
02551 weave_pattern,
02552 stpi_escp2_flush_pass,
02553 FILLFUNC,
02554 PACKFUNC,
02555 COMPUTEFUNC);
02556
02557 stp_dither_init(v, image, pd->image_printed_width, pd->res->printed_hres,
02558 pd->res->printed_vres);
02559 allocate_channels(v, line_width);
02560 adjust_print_quality(v, image);
02561 out_channels = stp_color_init(v, image, 65536);
02562
02563
02564
02565 setup_inks(v);
02566
02567 status = escp2_print_data(v, image);
02568 stp_image_conclude(image);
02569 stp_flush_all(v);
02570 stpi_escp2_terminate_page(v);
02571
02572
02573
02574
02575 for (i = 0; i < pd->channels_in_use; i++)
02576 if (pd->cols[i])
02577 stp_free(pd->cols[i]);
02578 stp_free(pd->cols);
02579 stp_free(pd->channels);
02580 return status;
02581 }
02582
02583
02584
02585
02586 static int
02587 escp2_do_print(stp_vars_t *v, stp_image_t *image, int print_op)
02588 {
02589 int status = 1;
02590
02591 escp2_privdata_t *pd;
02592
02593 if (!stp_verify(v))
02594 {
02595 stp_eprintf(v, _("Print options not verified; cannot print.\n"));
02596 return 0;
02597 }
02598 stp_image_init(image);
02599
02600 if (strcmp(stp_get_string_parameter(v, "InputImageType"), "Raw") == 0 &&
02601 !set_raw_ink_type(v))
02602 return 0;
02603
02604 pd = (escp2_privdata_t *) stp_zalloc(sizeof(escp2_privdata_t));
02605 pd->printed_something = 0;
02606 pd->last_color = -1;
02607 pd->last_pass_offset = 0;
02608 pd->last_pass = -1;
02609 pd->send_zero_pass_advance =
02610 escp2_has_cap(v, MODEL_SEND_ZERO_ADVANCE, MODEL_SEND_ZERO_ADVANCE_YES);
02611 stp_allocate_component_data(v, "Driver", NULL, NULL, pd);
02612
02613 pd->inkname = get_inktype(v);
02614 pd->channels_in_use = count_channels(pd->inkname);
02615
02616 setup_resolution(v);
02617 setup_head_parameters(v);
02618 setup_page(v);
02619 setup_misc(v);
02620
02621 adjust_density_and_ink_type(v, image);
02622 if (print_op & OP_JOB_START)
02623 stpi_escp2_init_printer(v);
02624 if (print_op & OP_JOB_PRINT)
02625 status = escp2_print_page(v, image);
02626 if (print_op & OP_JOB_END)
02627 stpi_escp2_deinit_printer(v);
02628
02629 stp_free(pd->head_offset);
02630 stp_free(pd);
02631
02632 return status;
02633 }
02634
02635 static int
02636 escp2_print(const stp_vars_t *v, stp_image_t *image)
02637 {
02638 stp_vars_t *nv = stp_vars_create_copy(v);
02639 int op = OP_JOB_PRINT;
02640 int status;
02641 if (!stp_get_string_parameter(v, "JobMode") ||
02642 strcmp(stp_get_string_parameter(v, "JobMode"), "Page") == 0)
02643 op = OP_JOB_START | OP_JOB_PRINT | OP_JOB_END;
02644 stp_prune_inactive_options(nv);
02645 status = escp2_do_print(nv, image, op);
02646 stp_vars_destroy(nv);
02647 return status;
02648 }
02649
02650 static int
02651 escp2_job_start(const stp_vars_t *v, stp_image_t *image)
02652 {
02653 stp_vars_t *nv = stp_vars_create_copy(v);
02654 int status;
02655 stp_prune_inactive_options(nv);
02656 status = escp2_do_print(nv, image, OP_JOB_START);
02657 stp_vars_destroy(nv);
02658 return status;
02659 }
02660
02661 static int
02662 escp2_job_end(const stp_vars_t *v, stp_image_t *image)
02663 {
02664 stp_vars_t *nv = stp_vars_create_copy(v);
02665 int status;
02666 stp_prune_inactive_options(nv);
02667 status = escp2_do_print(nv, image, OP_JOB_END);
02668 stp_vars_destroy(nv);
02669 return status;
02670 }
02671
02672 static const stp_printfuncs_t print_escp2_printfuncs =
02673 {
02674 escp2_list_parameters,
02675 escp2_parameters,
02676 stp_default_media_size,
02677 escp2_imageable_area,
02678 escp2_limit,
02679 escp2_print,
02680 escp2_describe_resolution,
02681 escp2_describe_output,
02682 stp_verify_printer_params,
02683 escp2_job_start,
02684 escp2_job_end
02685 };
02686
02687 static stp_family_t print_escp2_module_data =
02688 {
02689 &print_escp2_printfuncs,
02690 NULL
02691 };
02692
02693
02694 static int
02695 print_escp2_module_init(void)
02696 {
02697 return stp_family_register(print_escp2_module_data.printer_list);
02698 }
02699
02700
02701 static int
02702 print_escp2_module_exit(void)
02703 {
02704 return stp_family_unregister(print_escp2_module_data.printer_list);
02705 }
02706
02707
02708
02709 #define stp_module_version print_escp2_LTX_stp_module_version
02710 #define stp_module_data print_escp2_LTX_stp_module_data
02711
02712 stp_module_version_t stp_module_version = {0, 0};
02713
02714 stp_module_t stp_module_data =
02715 {
02716 "escp2",
02717 VERSION,
02718 "Epson family driver",
02719 STP_MODULE_CLASS_FAMILY,
02720 NULL,
02721 print_escp2_module_init,
02722 print_escp2_module_exit,
02723 (void *) &print_escp2_module_data
02724 };
02725