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