1/* 2 * "$Id: print-escp2.c,v 1.433 2010/12/11 22:04:07 rlk Exp $" 3 * 4 * Print plug-in EPSON ESC/P2 driver for the GIMP. 5 * 6 * Copyright 1997-2000 Michael Sweet (mike@easysw.com) and 7 * Robert Krawitz (rlk@alum.mit.edu) 8 * 9 * This program is free software; you can redistribute it and/or modify it 10 * under the terms of the GNU General Public License as published by the Free 11 * Software Foundation; either version 2 of the License, or (at your option) 12 * any later version. 13 * 14 * This program is distributed in the hope that it will be useful, but 15 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 16 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 17 * for more details. 18 * 19 * You should have received a copy of the GNU General Public License 20 * along with this program; if not, write to the Free Software 21 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 22 */ 23 24/* 25 * This file must include only standard C header files. The core code must 26 * compile on generic platforms that don't support glib, gimp, gtk, etc. 27 */ 28 29#ifdef HAVE_CONFIG_H 30#include <config.h> 31#endif 32#include <gutenprint/gutenprint.h> 33#include <gutenprint/gutenprint-intl-internal.h> 34#include "gutenprint-internal.h" 35#include <string.h> 36#include <math.h> 37#include <limits.h> 38#include "print-escp2.h" 39 40#ifdef __GNUC__ 41#define inline __inline__ 42#endif 43 44#define OP_JOB_START 1 45#define OP_JOB_PRINT 2 46#define OP_JOB_END 4 47 48#ifndef MAX 49# define MAX(a, b) ((a) > (b) ? (a) : (b)) 50#endif /* !MAX */ 51 52typedef struct 53{ 54 unsigned count; 55 const char *name; 56} channel_count_t; 57 58static const channel_count_t escp2_channel_counts[] = 59{ 60 { 1, "1" }, 61 { 2, "2" }, 62 { 3, "3" }, 63 { 4, "4" }, 64 { 5, "5" }, 65 { 6, "6" }, 66 { 7, "7" }, 67 { 8, "8" }, 68 { 9, "9" }, 69 { 10, "10" }, 70 { 11, "11" }, 71 { 12, "12" }, 72 { 13, "13" }, 73 { 14, "14" }, 74 { 15, "15" }, 75 { 16, "16" }, 76 { 17, "17" }, 77 { 18, "18" }, 78 { 19, "19" }, 79 { 20, "20" }, 80 { 21, "21" }, 81 { 22, "22" }, 82 { 23, "23" }, 83 { 24, "24" }, 84 { 25, "25" }, 85 { 26, "26" }, 86 { 27, "27" }, 87 { 28, "28" }, 88 { 29, "29" }, 89 { 30, "30" }, 90 { 31, "31" }, 91 { 32, "32" }, 92}; 93 94static stp_curve_t *hue_curve_bounds = NULL; 95static int escp2_channel_counts_count = 96sizeof(escp2_channel_counts) / sizeof(channel_count_t); 97 98static const double ink_darknesses[] = 99{ 100 1.0, 0.31 / .4, 0.61 / .96, 0.08, 0.31 * 0.33 / .4, 0.61 * 0.33 / .96, 0.33, 1.0 101}; 102 103#define INCH(x) (72 * x) 104 105#define PARAMETER_INT(s) \ 106{ \ 107 "escp2_" #s, "escp2_" #s, \ 108 "Color=Yes,Category=Advanced Printer Functionality", NULL, \ 109 STP_PARAMETER_TYPE_INT, STP_PARAMETER_CLASS_FEATURE, \ 110 STP_PARAMETER_LEVEL_INTERNAL, 0, 1, STP_CHANNEL_NONE, 1, 0 \ 111} 112 113#define PARAMETER_INT_RO(s) \ 114{ \ 115 "escp2_" #s, "escp2_" #s, \ 116 "Color=Yes,Category=Advanced Printer Functionality", NULL, \ 117 STP_PARAMETER_TYPE_INT, STP_PARAMETER_CLASS_FEATURE, \ 118 STP_PARAMETER_LEVEL_INTERNAL, 0, 1, STP_CHANNEL_NONE, 1, 1 \ 119} 120 121#define PARAMETER_RAW(s) \ 122{ \ 123 "escp2_" #s, "escp2_" #s, \ 124 "Color=Yes,Category=Advanced Printer Functionality", NULL, \ 125 STP_PARAMETER_TYPE_RAW, STP_PARAMETER_CLASS_FEATURE, \ 126 STP_PARAMETER_LEVEL_INTERNAL, 0, 1, STP_CHANNEL_NONE, 1, 0 \ 127} 128 129typedef struct 130{ 131 const stp_parameter_t param; 132 double min; 133 double max; 134 double defval; 135 int color_only; 136} float_param_t; 137 138typedef struct 139{ 140 const stp_parameter_t param; 141 int min; 142 int max; 143 int defval; 144} int_param_t; 145 146static const stp_parameter_t the_parameters[] = 147{ 148#if 0 149 { 150 "AutoMode", N_("Automatic Printing Mode"), "Color=Yes,Category=Basic Output Adjustment", 151 N_("Automatic printing mode"), 152 STP_PARAMETER_TYPE_STRING_LIST, STP_PARAMETER_CLASS_FEATURE, 153 STP_PARAMETER_LEVEL_BASIC, 1, 1, STP_CHANNEL_NONE, 1, 0 154 }, 155#endif 156 /* 157 * Don't check this parameter. We may offer different settings for 158 * different papers, but we need to be able to handle settings from PPD 159 * files that don't have constraints set up. 160 */ 161 { 162 "Quality", N_("Print Quality"), "Color=Yes,Category=Basic Output Adjustment", 163 N_("Print Quality"), 164 STP_PARAMETER_TYPE_STRING_LIST, STP_PARAMETER_CLASS_FEATURE, 165 STP_PARAMETER_LEVEL_BASIC, 1, 1, STP_CHANNEL_NONE, 0, 0 166 }, 167 { 168 "PageSize", N_("Page Size"), "Color=No,Category=Basic Printer Setup", 169 N_("Size of the paper being printed to"), 170 STP_PARAMETER_TYPE_STRING_LIST, STP_PARAMETER_CLASS_CORE, 171 STP_PARAMETER_LEVEL_BASIC, 1, 1, STP_CHANNEL_NONE, 1, 0 172 }, 173 { 174 "MediaType", N_("Media Type"), "Color=Yes,Category=Basic Printer Setup", 175 N_("Type of media (plain paper, photo paper, etc.)"), 176 STP_PARAMETER_TYPE_STRING_LIST, STP_PARAMETER_CLASS_FEATURE, 177 STP_PARAMETER_LEVEL_BASIC, 1, 1, STP_CHANNEL_NONE, 1, 0 178 }, 179 { 180 "InputSlot", N_("Media Source"), "Color=No,Category=Basic Printer Setup", 181 N_("Source (input slot) of the media"), 182 STP_PARAMETER_TYPE_STRING_LIST, STP_PARAMETER_CLASS_FEATURE, 183 STP_PARAMETER_LEVEL_BASIC, 1, 1, STP_CHANNEL_NONE, 1, 0 184 }, 185 { 186 "Duplex", N_("Double-Sided Printing"), "Color=No,Category=Basic Printer Setup", 187 N_("Duplex/Tumble Setting"), 188 STP_PARAMETER_TYPE_STRING_LIST, STP_PARAMETER_CLASS_FEATURE, 189 STP_PARAMETER_LEVEL_BASIC, 1, 1, STP_CHANNEL_NONE, 1, 0 190 }, 191 { 192 "CDInnerRadius", N_("CD Hub Size"), "Color=No,Category=Basic Printer Setup", 193 N_("Print only outside of the hub of the CD, or all the way to the hole"), 194 STP_PARAMETER_TYPE_STRING_LIST, STP_PARAMETER_CLASS_FEATURE, 195 STP_PARAMETER_LEVEL_BASIC, 1, 1, STP_CHANNEL_NONE, 1, 0 196 }, 197 { 198 "CDOuterDiameter", N_("CD Size (Custom)"), "Color=No,Category=Basic Printer Setup", 199 N_("Variable adjustment for the outer diameter of CD"), 200 STP_PARAMETER_TYPE_DIMENSION, STP_PARAMETER_CLASS_FEATURE, 201 STP_PARAMETER_LEVEL_ADVANCED, 1, 1, STP_CHANNEL_NONE, 1, 0 202 }, 203 { 204 "CDInnerDiameter", N_("CD Hub Size (Custom)"), "Color=No,Category=Basic Printer Setup", 205 N_("Variable adjustment to the inner hub of the CD"), 206 STP_PARAMETER_TYPE_DIMENSION, STP_PARAMETER_CLASS_FEATURE, 207 STP_PARAMETER_LEVEL_ADVANCED, 1, 1, STP_CHANNEL_NONE, 1, 0 208 }, 209 { 210 "CDXAdjustment", N_("CD Horizontal Fine Adjustment"), "Color=No,Category=Advanced Printer Setup", 211 N_("Fine adjustment to horizontal position for CD printing"), 212 STP_PARAMETER_TYPE_DIMENSION, STP_PARAMETER_CLASS_FEATURE, 213 STP_PARAMETER_LEVEL_ADVANCED, 1, 1, STP_CHANNEL_NONE, 1, 0 214 }, 215 { 216 "CDYAdjustment", N_("CD Vertical Fine Adjustment"), "Color=No,Category=Advanced Printer Setup", 217 N_("Fine adjustment to horizontal position for CD printing"), 218 STP_PARAMETER_TYPE_DIMENSION, STP_PARAMETER_CLASS_FEATURE, 219 STP_PARAMETER_LEVEL_ADVANCED, 1, 1, STP_CHANNEL_NONE, 1, 0 220 }, 221 { 222 "CDAllowOtherMedia", N_("CD Allow Other Media Sizes"), "Color=No,Category=Advanced Printer Setup", 223 N_("Allow non-CD media sizes when printing to CD"), 224 STP_PARAMETER_TYPE_BOOLEAN, STP_PARAMETER_CLASS_FEATURE, 225 STP_PARAMETER_LEVEL_ADVANCED, 1, 1, STP_CHANNEL_NONE, 1, 0 226 }, 227 { 228 "Resolution", N_("Resolution"), "Color=Yes,Category=Basic Printer Setup", 229 N_("Resolution of the print"), 230 STP_PARAMETER_TYPE_STRING_LIST, STP_PARAMETER_CLASS_FEATURE, 231 STP_PARAMETER_LEVEL_ADVANCED, 1, 1, STP_CHANNEL_NONE, 1, 0 232 }, 233 /* 234 * Don't check this parameter. We may offer different settings for 235 * different ink sets, but we need to be able to handle settings from PPD 236 * files that don't have constraints set up. 237 */ 238 { 239 "InkType", N_("Ink Type"), "Color=Yes,Category=Advanced Printer Setup", 240 N_("Type of ink in the printer"), 241 STP_PARAMETER_TYPE_STRING_LIST, STP_PARAMETER_CLASS_FEATURE, 242 STP_PARAMETER_LEVEL_ADVANCED2, 1, 1, STP_CHANNEL_NONE, 0, 0 243 }, 244 { 245 "UseGloss", N_("Enhanced Gloss"), "Color=Yes,Category=Basic Printer Setup", 246 N_("Add gloss enhancement"), 247 STP_PARAMETER_TYPE_BOOLEAN, STP_PARAMETER_CLASS_FEATURE, 248 STP_PARAMETER_LEVEL_BASIC, 1, 1, STP_CHANNEL_NONE, 0, 0 249 }, 250 { 251 "InkSet", N_("Ink Set"), "Color=Yes,Category=Basic Printer Setup", 252 N_("Type of ink in the printer"), 253 STP_PARAMETER_TYPE_STRING_LIST, STP_PARAMETER_CLASS_FEATURE, 254 STP_PARAMETER_LEVEL_BASIC, 1, 1, STP_CHANNEL_NONE, 1, 0 255 }, 256 { 257 "PrintingDirection", N_("Printing Direction"), "Color=Yes,Category=Advanced Output Adjustment", 258 N_("Printing direction (unidirectional is higher quality, but slower)"), 259 STP_PARAMETER_TYPE_STRING_LIST, STP_PARAMETER_CLASS_FEATURE, 260 STP_PARAMETER_LEVEL_ADVANCED1, 1, 1, STP_CHANNEL_NONE, 1, 0 261 }, 262 { 263 "FullBleed", N_("Borderless"), "Color=No,Category=Basic Printer Setup", 264 N_("Print without borders"), 265 STP_PARAMETER_TYPE_BOOLEAN, STP_PARAMETER_CLASS_FEATURE, 266 STP_PARAMETER_LEVEL_BASIC, 1, 1, STP_CHANNEL_NONE, 1, 0 267 }, 268 { 269 "Weave", N_("Interleave Method"), "Color=Yes,Category=Advanced Output Adjustment", 270 N_("Interleave pattern to use"), 271 STP_PARAMETER_TYPE_STRING_LIST, STP_PARAMETER_CLASS_FEATURE, 272 STP_PARAMETER_LEVEL_ADVANCED1, 1, 1, STP_CHANNEL_NONE, 1, 0 273 }, 274 { 275 "OutputOrder", N_("Output Order"), "Color=No,Category=Basic Printer Setup", 276 N_("Output Order"), 277 STP_PARAMETER_TYPE_STRING_LIST, STP_PARAMETER_CLASS_FEATURE, 278 STP_PARAMETER_LEVEL_BASIC, 0, 0, STP_CHANNEL_NONE, 0, 0 279 }, 280 { 281 "AlignmentPasses", N_("Alignment Passes"), "Color=No,Category=Advanced Printer Functionality", 282 N_("Alignment Passes"), 283 STP_PARAMETER_TYPE_INT, STP_PARAMETER_CLASS_FEATURE, 284 STP_PARAMETER_LEVEL_INTERNAL, 0, 0, STP_CHANNEL_NONE, 0, 0 285 }, 286 { 287 "AlignmentChoices", N_("Alignment Choices"), "Color=No,Category=Advanced Printer Functionality", 288 N_("Alignment Choices"), 289 STP_PARAMETER_TYPE_INT, STP_PARAMETER_CLASS_FEATURE, 290 STP_PARAMETER_LEVEL_INTERNAL, 0, 0, STP_CHANNEL_NONE, 0, 0 291 }, 292 { 293 "InkChange", N_("Ink change command"), "Color=No,Category=Advanced Printer Functionality", 294 N_("Ink change command"), 295 STP_PARAMETER_TYPE_INT, STP_PARAMETER_CLASS_FEATURE, 296 STP_PARAMETER_LEVEL_INTERNAL, 0, 0, STP_CHANNEL_NONE, 0, 0 297 }, 298 { 299 "AlternateAlignmentPasses", N_("Alternate Alignment Passes"), "Color=No,Category=Advanced Printer Functionality", 300 N_("Alternate Alignment Passes"), 301 STP_PARAMETER_TYPE_INT, STP_PARAMETER_CLASS_FEATURE, 302 STP_PARAMETER_LEVEL_INTERNAL, 0, 0, STP_CHANNEL_NONE, 0, 0 303 }, 304 { 305 "AlternateAlignmentChoices", N_("Alternate Alignment Choices"), "Color=No,Category=Advanced Printer Functionality", 306 N_("Alternate Alignment Choices"), 307 STP_PARAMETER_TYPE_INT, STP_PARAMETER_CLASS_FEATURE, 308 STP_PARAMETER_LEVEL_INTERNAL, 0, 0, STP_CHANNEL_NONE, 0, 0 309 }, 310 { 311 "SupportsPacketMode", N_("Supports Packet Mode"), "Color=No,Category=Advanced Printer Functionality", 312 N_("Supports D4 Packet Mode"), 313 STP_PARAMETER_TYPE_BOOLEAN, STP_PARAMETER_CLASS_FEATURE, 314 STP_PARAMETER_LEVEL_INTERNAL, 0, 0, STP_CHANNEL_NONE, 0, 0 315 }, 316 { 317 "InterchangeableInk", N_("Has Interchangeable Ink Cartridges"), "Color=No,Category=Advanced Printer Functionality", 318 N_("Has multiple choices of ink cartridges"), 319 STP_PARAMETER_TYPE_BOOLEAN, STP_PARAMETER_CLASS_FEATURE, 320 STP_PARAMETER_LEVEL_INTERNAL, 0, 0, STP_CHANNEL_NONE, 0, 0 321 }, 322 { 323 "InkChannels", N_("Ink Channels"), "Color=No,Category=Advanced Printer Functionality", 324 N_("Ink Channels"), 325 STP_PARAMETER_TYPE_INT, STP_PARAMETER_CLASS_FEATURE, 326 STP_PARAMETER_LEVEL_INTERNAL, 0, 0, STP_CHANNEL_NONE, 0, 0 327 }, 328 { 329 "RawChannelNames", N_("Raw Channel Names"), "Color=No,Category=Advanced Printer Functionality", 330 N_("Raw Channel Names"), 331 STP_PARAMETER_TYPE_STRING_LIST, STP_PARAMETER_CLASS_FEATURE, 332 STP_PARAMETER_LEVEL_INTERNAL, 0, 0, STP_CHANNEL_NONE, 0, 0 333 }, 334 { 335 "ChannelNames", N_("Channel Names"), "Color=No,Category=Advanced Printer Functionality", 336 N_("Channel Names"), 337 STP_PARAMETER_TYPE_STRING_LIST, STP_PARAMETER_CLASS_FEATURE, 338 STP_PARAMETER_LEVEL_INTERNAL, 0, 0, STP_CHANNEL_NONE, 0, 0 339 }, 340 { 341 "PrintingMode", N_("Printing Mode"), "Color=Yes,Category=Core Parameter", 342 N_("Printing Output Mode"), 343 STP_PARAMETER_TYPE_STRING_LIST, STP_PARAMETER_CLASS_CORE, 344 STP_PARAMETER_LEVEL_BASIC, 1, 1, STP_CHANNEL_NONE, 1, 0 345 }, 346 { 347 "RawChannels", N_("Raw Channels"), "Color=Yes,Category=Core Parameter", 348 N_("Raw Channel Count"), 349 STP_PARAMETER_TYPE_STRING_LIST, STP_PARAMETER_CLASS_CORE, 350 STP_PARAMETER_LEVEL_BASIC, 0, 1, STP_CHANNEL_NONE, 1, 0 351 }, 352 { 353 "CyanHueCurve", N_("Cyan Map"), "Color=Yes,Category=Advanced Output Control", 354 N_("Adjust the cyan map"), 355 STP_PARAMETER_TYPE_CURVE, STP_PARAMETER_CLASS_OUTPUT, 356 STP_PARAMETER_LEVEL_ADVANCED4, 0, 1, 1, 1, 0 357 }, 358 { 359 "MagentaHueCurve", N_("Magenta Map"), "Color=Yes,Category=Advanced Output Control", 360 N_("Adjust the magenta map"), 361 STP_PARAMETER_TYPE_CURVE, STP_PARAMETER_CLASS_OUTPUT, 362 STP_PARAMETER_LEVEL_ADVANCED4, 0, 1, 2, 1, 0 363 }, 364 { 365 "YellowHueCurve", N_("Yellow Map"), "Color=Yes,Category=Advanced Output Control", 366 N_("Adjust the yellow map"), 367 STP_PARAMETER_TYPE_CURVE, STP_PARAMETER_CLASS_OUTPUT, 368 STP_PARAMETER_LEVEL_ADVANCED4, 0, 1, 3, 1, 0 369 }, 370 { 371 "BlueHueCurve", N_("Blue Map"), "Color=Yes,Category=Advanced Output Control", 372 N_("Adjust the blue map"), 373 STP_PARAMETER_TYPE_CURVE, STP_PARAMETER_CLASS_OUTPUT, 374 STP_PARAMETER_LEVEL_ADVANCED4, 0, 1, 4, 1, 0 375 }, 376 { 377 "OrangeHueCurve", N_("Orange Map"), "Color=Yes,Category=Advanced Output Control", 378 N_("Adjust the orange map"), 379 STP_PARAMETER_TYPE_CURVE, STP_PARAMETER_CLASS_OUTPUT, 380 STP_PARAMETER_LEVEL_ADVANCED4, 0, 1, 4, 1, 0 381 }, 382 { 383 "RedHueCurve", N_("Red Map"), "Color=Yes,Category=Advanced Output Control", 384 N_("Adjust the red map"), 385 STP_PARAMETER_TYPE_CURVE, STP_PARAMETER_CLASS_OUTPUT, 386 STP_PARAMETER_LEVEL_ADVANCED4, 0, 1, 5, 1, 0 387 }, 388 PARAMETER_INT(max_hres), 389 PARAMETER_INT(max_vres), 390 PARAMETER_INT(min_hres), 391 PARAMETER_INT(min_vres), 392 PARAMETER_INT(nozzles), 393 PARAMETER_INT(black_nozzles), 394 PARAMETER_INT(fast_nozzles), 395 PARAMETER_INT(min_nozzles), 396 PARAMETER_INT(min_black_nozzles), 397 PARAMETER_INT(min_fast_nozzles), 398 PARAMETER_INT(nozzle_start), 399 PARAMETER_INT(black_nozzle_start), 400 PARAMETER_INT(fast_nozzle_start), 401 PARAMETER_INT(nozzle_separation), 402 PARAMETER_INT(black_nozzle_separation), 403 PARAMETER_INT(fast_nozzle_separation), 404 PARAMETER_INT(separation_rows), 405 PARAMETER_INT(max_paper_width), 406 PARAMETER_INT(max_paper_height), 407 PARAMETER_INT(min_paper_width), 408 PARAMETER_INT(min_paper_height), 409 PARAMETER_INT(max_imageable_width), 410 PARAMETER_INT(max_imageable_height), 411 PARAMETER_INT(extra_feed), 412 PARAMETER_INT(pseudo_separation_rows), 413 PARAMETER_INT(base_separation), 414 PARAMETER_INT(resolution_scale), 415 PARAMETER_INT(initial_vertical_offset), 416 PARAMETER_INT(black_initial_vertical_offset), 417 PARAMETER_INT(max_black_resolution), 418 PARAMETER_INT(zero_margin_offset), 419 PARAMETER_INT(extra_720dpi_separation), 420 PARAMETER_INT(micro_left_margin), 421 PARAMETER_INT(min_horizontal_position_alignment), 422 PARAMETER_INT(base_horizontal_position_alignment), 423 PARAMETER_INT(bidirectional_upper_limit), 424 PARAMETER_INT(physical_channels), 425 PARAMETER_INT(left_margin), 426 PARAMETER_INT(right_margin), 427 PARAMETER_INT(top_margin), 428 PARAMETER_INT(bottom_margin), 429 PARAMETER_INT(ink_type), 430 PARAMETER_INT(bits), 431 PARAMETER_INT(base_res), 432 PARAMETER_INT_RO(alignment_passes), 433 PARAMETER_INT_RO(alignment_choices), 434 PARAMETER_INT_RO(alternate_alignment_passes), 435 PARAMETER_INT_RO(alternate_alignment_choices), 436 PARAMETER_INT(cd_x_offset), 437 PARAMETER_INT(cd_y_offset), 438 PARAMETER_INT(cd_page_width), 439 PARAMETER_INT(cd_page_height), 440 PARAMETER_INT(paper_extra_bottom), 441 PARAMETER_RAW(preinit_sequence), 442 PARAMETER_RAW(preinit_remote_sequence), 443 PARAMETER_RAW(postinit_remote_sequence), 444 PARAMETER_RAW(vertical_borderless_sequence) 445}; 446 447static const int the_parameter_count = 448sizeof(the_parameters) / sizeof(const stp_parameter_t); 449 450static const float_param_t float_parameters[] = 451{ 452 { 453 { 454 "CyanDensity", N_("Cyan Density"), "Color=Yes,Category=Output Level Adjustment", 455 N_("Adjust the cyan density"), 456 STP_PARAMETER_TYPE_DOUBLE, STP_PARAMETER_CLASS_OUTPUT, 457 STP_PARAMETER_LEVEL_ADVANCED, 0, 1, 1, 1, 0 458 }, 0.0, 2.0, 1.0, 1 459 }, 460 { 461 { 462 "MagentaDensity", N_("Magenta Density"), "Color=Yes,Category=Output Level Adjustment", 463 N_("Adjust the magenta density"), 464 STP_PARAMETER_TYPE_DOUBLE, STP_PARAMETER_CLASS_OUTPUT, 465 STP_PARAMETER_LEVEL_ADVANCED, 0, 1, 2, 1, 0 466 }, 0.0, 2.0, 1.0, 1 467 }, 468 { 469 { 470 "YellowDensity", N_("Yellow Density"), "Color=Yes,Category=Output Level Adjustment", 471 N_("Adjust the yellow density"), 472 STP_PARAMETER_TYPE_DOUBLE, STP_PARAMETER_CLASS_OUTPUT, 473 STP_PARAMETER_LEVEL_ADVANCED, 0, 1, 3, 1, 0 474 }, 0.0, 2.0, 1.0, 1 475 }, 476 { 477 { 478 "BlackDensity", N_("Black Density"), "Color=Yes,Category=Output Level Adjustment", 479 N_("Adjust the black density"), 480 STP_PARAMETER_TYPE_DOUBLE, STP_PARAMETER_CLASS_OUTPUT, 481 STP_PARAMETER_LEVEL_ADVANCED, 0, 1, 0, 1, 0 482 }, 0.0, 2.0, 1.0, 1 483 }, 484 { 485 { 486 "RedDensity", N_("Red Density"), "Color=Yes,Category=Output Level Adjustment", 487 N_("Adjust the red density"), 488 STP_PARAMETER_TYPE_DOUBLE, STP_PARAMETER_CLASS_OUTPUT, 489 STP_PARAMETER_LEVEL_ADVANCED, 0, 1, 4, 1, 0 490 }, 0.0, 2.0, 1.0, 1 491 }, 492 { 493 { 494 "BlueDensity", N_("Blue Density"), "Color=Yes,Category=Output Level Adjustment", 495 N_("Adjust the blue density"), 496 STP_PARAMETER_TYPE_DOUBLE, STP_PARAMETER_CLASS_OUTPUT, 497 STP_PARAMETER_LEVEL_ADVANCED, 0, 1, 5, 1, 0 498 }, 0.0, 2.0, 1.0, 1 499 }, 500 { 501 { 502 "OrangeDensity", N_("Orange Density"), "Color=Yes,Category=Output Level Adjustment", 503 N_("Adjust the orange density"), 504 STP_PARAMETER_TYPE_DOUBLE, STP_PARAMETER_CLASS_OUTPUT, 505 STP_PARAMETER_LEVEL_ADVANCED, 0, 1, 5, 1, 0 506 }, 0.0, 2.0, 1.0, 1 507 }, 508 { 509 { 510 "GlossLimit", N_("Gloss Level"), "Color=Yes,Category=Output Level Adjustment", 511 N_("Adjust the gloss level"), 512 STP_PARAMETER_TYPE_DOUBLE, STP_PARAMETER_CLASS_OUTPUT, 513 STP_PARAMETER_LEVEL_ADVANCED, 0, 1, 6, 1, 0 514 }, 0.0, 2.0, 1.0, 1 515 }, 516 { 517 { 518 "DropSize1", N_("Drop Size Small"), "Color=Yes,Category=Advanced Ink Adjustment", 519 N_("Drop Size 1 (small)"), 520 STP_PARAMETER_TYPE_DOUBLE, STP_PARAMETER_CLASS_OUTPUT, 521 STP_PARAMETER_LEVEL_ADVANCED4, 0, 1, STP_CHANNEL_NONE, 1, 0 522 }, 0.0, 1.0, 1.0, 1 523 }, 524 { 525 { 526 "DropSize2", N_("Drop Size Medium"), "Color=Yes,Category=Advanced Ink Adjustment", 527 N_("Drop Size 2 (medium)"), 528 STP_PARAMETER_TYPE_DOUBLE, STP_PARAMETER_CLASS_OUTPUT, 529 STP_PARAMETER_LEVEL_ADVANCED4, 0, 1, STP_CHANNEL_NONE, 1, 0 530 }, 0.0, 1.0, 0.0, 1 531 }, 532 { 533 { 534 "DropSize3", N_("Drop Size Large"), "Color=Yes,Category=Advanced Ink Adjustment", 535 N_("Drop Size 3 (large)"), 536 STP_PARAMETER_TYPE_DOUBLE, STP_PARAMETER_CLASS_OUTPUT, 537 STP_PARAMETER_LEVEL_ADVANCED4, 0, 1, STP_CHANNEL_NONE, 1, 0 538 }, 0.0, 1.0, 0.0, 1 539 }, 540 { 541 { 542 "LightCyanValue", N_("Light Cyan Value"), "Color=Yes,Category=Advanced Ink Adjustment", 543 N_("Light Cyan Value"), 544 STP_PARAMETER_TYPE_DOUBLE, STP_PARAMETER_CLASS_OUTPUT, 545 STP_PARAMETER_LEVEL_ADVANCED4, 0, 1, STP_CHANNEL_NONE, 1, 0 546 }, 0.0, 5.0, 1.0, 1 547 }, 548 { 549 { 550 "LightCyanTrans", N_("Light Cyan Transition"), "Color=Yes,Category=Advanced Ink Adjustment", 551 N_("Light Cyan Transition"), 552 STP_PARAMETER_TYPE_DOUBLE, STP_PARAMETER_CLASS_OUTPUT, 553 STP_PARAMETER_LEVEL_ADVANCED4, 0, 1, STP_CHANNEL_NONE, 1, 0 554 }, 0.0, 5.0, 1.0, 1 555 }, 556 { 557 { 558 "LightCyanScale", N_("Light Cyan Density Scale"), "Color=Yes,Category=Advanced Ink Adjustment", 559 N_("Light Cyan Density Scale"), 560 STP_PARAMETER_TYPE_DOUBLE, STP_PARAMETER_CLASS_OUTPUT, 561 STP_PARAMETER_LEVEL_ADVANCED4, 0, 1, STP_CHANNEL_NONE, 1, 0 562 }, 0.0, 5.0, 1.0, 1 563 }, 564 { 565 { 566 "LightMagentaValue", N_("Light Magenta Value"), "Color=Yes,Category=Advanced Ink Adjustment", 567 N_("Light Magenta Value"), 568 STP_PARAMETER_TYPE_DOUBLE, STP_PARAMETER_CLASS_OUTPUT, 569 STP_PARAMETER_LEVEL_ADVANCED4, 0, 1, STP_CHANNEL_NONE, 1, 0 570 }, 0.0, 5.0, 1.0, 1 571 }, 572 { 573 { 574 "LightMagentaScale", N_("Light Magenta Density Scale"), "Color=Yes,Category=Advanced Ink Adjustment", 575 N_("Light Magenta Density Scale"), 576 STP_PARAMETER_TYPE_DOUBLE, STP_PARAMETER_CLASS_OUTPUT, 577 STP_PARAMETER_LEVEL_ADVANCED4, 0, 1, STP_CHANNEL_NONE, 1, 0 578 }, 0.0, 5.0, 1.0, 1 579 }, 580 { 581 { 582 "LightMagentaTrans", N_("Light Magenta Transition"), "Color=Yes,Category=Advanced Ink Adjustment", 583 N_("Light Magenta Transition"), 584 STP_PARAMETER_TYPE_DOUBLE, STP_PARAMETER_CLASS_OUTPUT, 585 STP_PARAMETER_LEVEL_ADVANCED4, 0, 1, STP_CHANNEL_NONE, 1, 0 586 }, 0.0, 5.0, 1.0, 1 587 }, 588 { 589 { 590 "DarkYellowValue", N_("Dark Yellow Value"), "Color=Yes,Category=Advanced Ink Adjustment", 591 N_("Dark Yellow Value"), 592 STP_PARAMETER_TYPE_DOUBLE, STP_PARAMETER_CLASS_OUTPUT, 593 STP_PARAMETER_LEVEL_ADVANCED4, 0, 1, STP_CHANNEL_NONE, 1, 0 594 }, 0.0, 5.0, 1.0, 1 595 }, 596 { 597 { 598 "DarkYellowTrans", N_("Dark Yellow Transition"), "Color=Yes,Category=Advanced Ink Adjustment", 599 N_("Dark Yellow Transition"), 600 STP_PARAMETER_TYPE_DOUBLE, STP_PARAMETER_CLASS_OUTPUT, 601 STP_PARAMETER_LEVEL_ADVANCED4, 0, 1, STP_CHANNEL_NONE, 1, 0 602 }, 0.0, 5.0, 1.0, 1 603 }, 604 { 605 { 606 "DarkYellowScale", N_("Dark Yellow Density Scale"), "Color=Yes,Category=Advanced Ink Adjustment", 607 N_("Dark Yellow Density Scale"), 608 STP_PARAMETER_TYPE_DOUBLE, STP_PARAMETER_CLASS_OUTPUT, 609 STP_PARAMETER_LEVEL_ADVANCED4, 0, 1, STP_CHANNEL_NONE, 1, 0 610 }, 0.0, 5.0, 1.0, 1 611 }, 612 { 613 { 614 "GrayValue", N_("Gray Value"), "Color=Yes,Category=Advanced Ink Adjustment", 615 N_("Gray Value"), 616 STP_PARAMETER_TYPE_DOUBLE, STP_PARAMETER_CLASS_OUTPUT, 617 STP_PARAMETER_LEVEL_ADVANCED4, 0, 1, STP_CHANNEL_NONE, 1, 0 618 }, 0.0, 5.0, 1.0, 1 619 }, 620 { 621 { 622 "GrayTrans", N_("Gray Transition"), "Color=Yes,Category=Advanced Ink Adjustment", 623 N_("Gray Transition"), 624 STP_PARAMETER_TYPE_DOUBLE, STP_PARAMETER_CLASS_OUTPUT, 625 STP_PARAMETER_LEVEL_ADVANCED4, 0, 1, STP_CHANNEL_NONE, 1, 0 626 }, 0.0, 5.0, 1.0, 1 627 }, 628 { 629 { 630 "GrayScale", N_("Gray Density Scale"), "Color=Yes,Category=Advanced Ink Adjustment", 631 N_("Gray Density Scale"), 632 STP_PARAMETER_TYPE_DOUBLE, STP_PARAMETER_CLASS_OUTPUT, 633 STP_PARAMETER_LEVEL_ADVANCED4, 0, 1, STP_CHANNEL_NONE, 1, 0 634 }, 0.0, 5.0, 1.0, 1 635 }, 636 { 637 { 638 "DarkGrayValue", N_("Gray Value"), "Color=Yes,Category=Advanced Ink Adjustment", 639 N_("Gray Value"), 640 STP_PARAMETER_TYPE_DOUBLE, STP_PARAMETER_CLASS_OUTPUT, 641 STP_PARAMETER_LEVEL_ADVANCED4, 0, 1, STP_CHANNEL_NONE, 1, 0 642 }, 0.0, 5.0, 1.0, 1 643 }, 644 { 645 { 646 "DarkGrayTrans", N_("Gray Transition"), "Color=Yes,Category=Advanced Ink Adjustment", 647 N_("Gray Transition"), 648 STP_PARAMETER_TYPE_DOUBLE, STP_PARAMETER_CLASS_OUTPUT, 649 STP_PARAMETER_LEVEL_ADVANCED4, 0, 1, STP_CHANNEL_NONE, 1, 0 650 }, 0.0, 5.0, 1.0, 1 651 }, 652 { 653 { 654 "DarkGrayScale", N_("Gray Density Scale"), "Color=Yes,Category=Advanced Ink Adjustment", 655 N_("Gray Density Scale"), 656 STP_PARAMETER_TYPE_DOUBLE, STP_PARAMETER_CLASS_OUTPUT, 657 STP_PARAMETER_LEVEL_ADVANCED4, 0, 1, STP_CHANNEL_NONE, 1, 0 658 }, 0.0, 5.0, 1.0, 1 659 }, 660 { 661 { 662 "LightGrayValue", N_("Light Gray Value"), "Color=Yes,Category=Advanced Ink Adjustment", 663 N_("Light Gray Value"), 664 STP_PARAMETER_TYPE_DOUBLE, STP_PARAMETER_CLASS_OUTPUT, 665 STP_PARAMETER_LEVEL_ADVANCED4, 0, 1, STP_CHANNEL_NONE, 1, 0 666 }, 0.0, 5.0, 1.0, 1 667 }, 668 { 669 { 670 "LightGrayTrans", N_("Light Gray Transition"), "Color=Yes,Category=Advanced Ink Adjustment", 671 N_("Light Gray Transition"), 672 STP_PARAMETER_TYPE_DOUBLE, STP_PARAMETER_CLASS_OUTPUT, 673 STP_PARAMETER_LEVEL_ADVANCED4, 0, 1, STP_CHANNEL_NONE, 1, 0 674 }, 0.0, 5.0, 1.0, 1 675 }, 676 { 677 { 678 "LightGrayScale", N_("Light Gray Density Scale"), "Color=Yes,Category=Advanced Ink Adjustment", 679 N_("Light Gray Density Scale"), 680 STP_PARAMETER_TYPE_DOUBLE, STP_PARAMETER_CLASS_OUTPUT, 681 STP_PARAMETER_LEVEL_ADVANCED4, 0, 1, STP_CHANNEL_NONE, 1, 0 682 }, 0.0, 5.0, 1.0, 1 683 }, 684 { 685 { 686 "Gray3Value", N_("Dark Gray Value"), "Color=Yes,Category=Advanced Ink Adjustment", 687 N_("Dark Gray Value"), 688 STP_PARAMETER_TYPE_DOUBLE, STP_PARAMETER_CLASS_OUTPUT, 689 STP_PARAMETER_LEVEL_ADVANCED4, 0, 1, STP_CHANNEL_NONE, 1, 0 690 }, 0.0, 5.0, 1.0, 1 691 }, 692 { 693 { 694 "Gray3Trans", N_("Dark Gray Transition"), "Color=Yes,Category=Advanced Ink Adjustment", 695 N_("Dark Gray Transition"), 696 STP_PARAMETER_TYPE_DOUBLE, STP_PARAMETER_CLASS_OUTPUT, 697 STP_PARAMETER_LEVEL_ADVANCED4, 0, 1, STP_CHANNEL_NONE, 1, 0 698 }, 0.0, 5.0, 1.0, 1 699 }, 700 { 701 { 702 "Gray3Scale", N_("Dark Gray Density Scale"), "Color=Yes,Category=Advanced Ink Adjustment", 703 N_("Dark Gray Density Scale"), 704 STP_PARAMETER_TYPE_DOUBLE, STP_PARAMETER_CLASS_OUTPUT, 705 STP_PARAMETER_LEVEL_ADVANCED4, 0, 1, STP_CHANNEL_NONE, 1, 0 706 }, 0.0, 5.0, 1.0, 1 707 }, 708 { 709 { 710 "Gray2Value", N_("Mid Gray Value"), "Color=Yes,Category=Advanced Ink Adjustment", 711 N_("Medium Gray Value"), 712 STP_PARAMETER_TYPE_DOUBLE, STP_PARAMETER_CLASS_OUTPUT, 713 STP_PARAMETER_LEVEL_ADVANCED4, 0, 1, STP_CHANNEL_NONE, 1, 0 714 }, 0.0, 5.0, 1.0, 1 715 }, 716 { 717 { 718 "Gray2Trans", N_("Mid Gray Transition"), "Color=Yes,Category=Advanced Ink Adjustment", 719 N_("Medium Gray Transition"), 720 STP_PARAMETER_TYPE_DOUBLE, STP_PARAMETER_CLASS_OUTPUT, 721 STP_PARAMETER_LEVEL_ADVANCED4, 0, 1, STP_CHANNEL_NONE, 1, 0 722 }, 0.0, 5.0, 1.0, 1 723 }, 724 { 725 { 726 "Gray2Scale", N_("Mid Gray Density Scale"), "Color=Yes,Category=Advanced Ink Adjustment", 727 N_("Medium Gray Density Scale"), 728 STP_PARAMETER_TYPE_DOUBLE, STP_PARAMETER_CLASS_OUTPUT, 729 STP_PARAMETER_LEVEL_ADVANCED4, 0, 1, STP_CHANNEL_NONE, 1, 0 730 }, 0.0, 5.0, 1.0, 1 731 }, 732 { 733 { 734 "Gray1Value", N_("Light Gray Value"), "Color=Yes,Category=Advanced Ink Adjustment", 735 N_("Light Gray Value"), 736 STP_PARAMETER_TYPE_DOUBLE, STP_PARAMETER_CLASS_OUTPUT, 737 STP_PARAMETER_LEVEL_ADVANCED4, 0, 1, STP_CHANNEL_NONE, 1, 0 738 }, 0.0, 5.0, 1.0, 1 739 }, 740 { 741 { 742 "Gray1Trans", N_("Light Gray Transition"), "Color=Yes,Category=Advanced Ink Adjustment", 743 N_("Light Gray Transition"), 744 STP_PARAMETER_TYPE_DOUBLE, STP_PARAMETER_CLASS_OUTPUT, 745 STP_PARAMETER_LEVEL_ADVANCED4, 0, 1, STP_CHANNEL_NONE, 1, 0 746 }, 0.0, 5.0, 1.0, 1 747 }, 748 { 749 { 750 "Gray1Scale", N_("Light Gray Density Scale"), "Color=Yes,Category=Advanced Ink Adjustment", 751 N_("Light Gray Density Scale"), 752 STP_PARAMETER_TYPE_DOUBLE, STP_PARAMETER_CLASS_OUTPUT, 753 STP_PARAMETER_LEVEL_ADVANCED4, 0, 1, STP_CHANNEL_NONE, 1, 0 754 }, 0.0, 5.0, 1.0, 1 755 }, 756 { 757 { 758 "HGray5Value", N_("Hextone Gray 5 Value"), "Color=Yes,Category=Advanced Ink Adjustment", 759 N_("Hextone Gray 5 (Darkest) Value"), 760 STP_PARAMETER_TYPE_DOUBLE, STP_PARAMETER_CLASS_OUTPUT, 761 STP_PARAMETER_LEVEL_ADVANCED4, 0, 1, STP_CHANNEL_NONE, 1, 0 762 }, 0.0, 5.0, 1.0, 1 763 }, 764 { 765 { 766 "HGray5Trans", N_("Hextone Gray 5 Transition"), "Color=Yes,Category=Advanced Ink Adjustment", 767 N_("Hextone Gray 5 (Darkest) Transition"), 768 STP_PARAMETER_TYPE_DOUBLE, STP_PARAMETER_CLASS_OUTPUT, 769 STP_PARAMETER_LEVEL_ADVANCED4, 0, 1, STP_CHANNEL_NONE, 1, 0 770 }, 0.0, 5.0, 1.0, 1 771 }, 772 { 773 { 774 "HGray5Scale", N_("Hextone Gray 5 Density Scale"), "Color=Yes,Category=Advanced Ink Adjustment", 775 N_("Hextone Gray 5 (Darkest) Density Scale"), 776 STP_PARAMETER_TYPE_DOUBLE, STP_PARAMETER_CLASS_OUTPUT, 777 STP_PARAMETER_LEVEL_ADVANCED4, 0, 1, STP_CHANNEL_NONE, 1, 0 778 }, 0.0, 5.0, 1.0, 1 779 }, 780 { 781 { 782 "HGray4Value", N_("Hextone Gray 4 Value"), "Color=Yes,Category=Advanced Ink Adjustment", 783 N_("Hextone Gray 4 Value"), 784 STP_PARAMETER_TYPE_DOUBLE, STP_PARAMETER_CLASS_OUTPUT, 785 STP_PARAMETER_LEVEL_ADVANCED4, 0, 1, STP_CHANNEL_NONE, 1, 0 786 }, 0.0, 5.0, 1.0, 1 787 }, 788 { 789 { 790 "HGray4Trans", N_("Hextone Gray 4 Transition"), "Color=Yes,Category=Advanced Ink Adjustment", 791 N_("Hextone Gray 4 Transition"), 792 STP_PARAMETER_TYPE_DOUBLE, STP_PARAMETER_CLASS_OUTPUT, 793 STP_PARAMETER_LEVEL_ADVANCED4, 0, 1, STP_CHANNEL_NONE, 1, 0 794 }, 0.0, 5.0, 1.0, 1 795 }, 796 { 797 { 798 "HGray4Scale", N_("Hextone Gray 4 Density Scale"), "Color=Yes,Category=Advanced Ink Adjustment", 799 N_("Hextone Gray 4 Density Scale"), 800 STP_PARAMETER_TYPE_DOUBLE, STP_PARAMETER_CLASS_OUTPUT, 801 STP_PARAMETER_LEVEL_ADVANCED4, 0, 1, STP_CHANNEL_NONE, 1, 0 802 }, 0.0, 5.0, 1.0, 1 803 }, 804 { 805 { 806 "HGray3Value", N_("Hextone Gray 3 Value"), "Color=Yes,Category=Advanced Ink Adjustment", 807 N_("Hextone Gray 3 Value"), 808 STP_PARAMETER_TYPE_DOUBLE, STP_PARAMETER_CLASS_OUTPUT, 809 STP_PARAMETER_LEVEL_ADVANCED4, 0, 1, STP_CHANNEL_NONE, 1, 0 810 }, 0.0, 5.0, 1.0, 1 811 }, 812 { 813 { 814 "HGray3Trans", N_("Hextone Gray 3 Transition"), "Color=Yes,Category=Advanced Ink Adjustment", 815 N_("Hextone Gray 3 Transition"), 816 STP_PARAMETER_TYPE_DOUBLE, STP_PARAMETER_CLASS_OUTPUT, 817 STP_PARAMETER_LEVEL_ADVANCED4, 0, 1, STP_CHANNEL_NONE, 1, 0 818 }, 0.0, 5.0, 1.0, 1 819 }, 820 { 821 { 822 "HGray3Scale", N_("Hextone Gray 3 Density Scale"), "Color=Yes,Category=Advanced Ink Adjustment", 823 N_("Hextone Gray 3 Density Scale"), 824 STP_PARAMETER_TYPE_DOUBLE, STP_PARAMETER_CLASS_OUTPUT, 825 STP_PARAMETER_LEVEL_ADVANCED4, 0, 1, STP_CHANNEL_NONE, 1, 0 826 }, 0.0, 5.0, 1.0, 1 827 }, 828 { 829 { 830 "HGray2Value", N_("Hextone Gray 2 Value"), "Color=Yes,Category=Advanced Ink Adjustment", 831 N_("Hextone Gray 2 Value"), 832 STP_PARAMETER_TYPE_DOUBLE, STP_PARAMETER_CLASS_OUTPUT, 833 STP_PARAMETER_LEVEL_ADVANCED4, 0, 1, STP_CHANNEL_NONE, 1, 0 834 }, 0.0, 5.0, 1.0, 1 835 }, 836 { 837 { 838 "HGray2Trans", N_("Hextone Gray 2 Transition"), "Color=Yes,Category=Advanced Ink Adjustment", 839 N_("Hextone Gray 2 Transition"), 840 STP_PARAMETER_TYPE_DOUBLE, STP_PARAMETER_CLASS_OUTPUT, 841 STP_PARAMETER_LEVEL_ADVANCED4, 0, 1, STP_CHANNEL_NONE, 1, 0 842 }, 0.0, 5.0, 1.0, 1 843 }, 844 { 845 { 846 "HGray2Scale", N_("Hextone Gray 2 Density Scale"), "Color=Yes,Category=Advanced Ink Adjustment", 847 N_("Hextone Gray 2 Density Scale"), 848 STP_PARAMETER_TYPE_DOUBLE, STP_PARAMETER_CLASS_OUTPUT, 849 STP_PARAMETER_LEVEL_ADVANCED4, 0, 1, STP_CHANNEL_NONE, 1, 0 850 }, 0.0, 5.0, 1.0, 1 851 }, 852 { 853 { 854 "HGray1Value", N_("Hextone Gray 1 Value"), "Color=Yes,Category=Advanced Ink Adjustment", 855 N_("Hextone Gray 1 (Lightest) Value"), 856 STP_PARAMETER_TYPE_DOUBLE, STP_PARAMETER_CLASS_OUTPUT, 857 STP_PARAMETER_LEVEL_ADVANCED4, 0, 1, STP_CHANNEL_NONE, 1, 0 858 }, 0.0, 5.0, 1.0, 1 859 }, 860 { 861 { 862 "HGray1Trans", N_("Hextone Gray 1 Transition"), "Color=Yes,Category=Advanced Ink Adjustment", 863 N_("Hextone Gray 1 (Lightest) Transition"), 864 STP_PARAMETER_TYPE_DOUBLE, STP_PARAMETER_CLASS_OUTPUT, 865 STP_PARAMETER_LEVEL_ADVANCED4, 0, 1, STP_CHANNEL_NONE, 1, 0 866 }, 0.0, 5.0, 1.0, 1 867 }, 868 { 869 { 870 "HGray1Scale", N_("Hextone Gray 1 Density Scale"), "Color=Yes,Category=Advanced Ink Adjustment", 871 N_("Hextone Gray 1 (Lightest) Density Scale"), 872 STP_PARAMETER_TYPE_DOUBLE, STP_PARAMETER_CLASS_OUTPUT, 873 STP_PARAMETER_LEVEL_ADVANCED4, 0, 1, STP_CHANNEL_NONE, 1, 0 874 }, 0.0, 5.0, 1.0, 1 875 }, 876 { 877 { 878 "BlackTrans", N_("GCR Transition"), "Color=Yes,Category=Advanced Output Control", 879 N_("Adjust the gray component transition rate"), 880 STP_PARAMETER_TYPE_DOUBLE, STP_PARAMETER_CLASS_OUTPUT, 881 STP_PARAMETER_LEVEL_ADVANCED4, 0, 1, 0, 1, 0 882 }, 0.0, 1.0, 1.0, 1 883 }, 884 { 885 { 886 "GCRLower", N_("GCR Lower Bound"), "Color=Yes,Category=Advanced Output Control", 887 N_("Lower bound of gray component reduction"), 888 STP_PARAMETER_TYPE_DOUBLE, STP_PARAMETER_CLASS_OUTPUT, 889 STP_PARAMETER_LEVEL_ADVANCED4, 0, 1, 0, 1, 0 890 }, 0.0, 1.0, 0.2, 1 891 }, 892 { 893 { 894 "GCRUpper", N_("GCR Upper Bound"), "Color=Yes,Category=Advanced Output Control", 895 N_("Upper bound of gray component reduction"), 896 STP_PARAMETER_TYPE_DOUBLE, STP_PARAMETER_CLASS_OUTPUT, 897 STP_PARAMETER_LEVEL_ADVANCED4, 0, 1, 0, 1, 0 898 }, 0.0, 5.0, 0.5, 1 899 }, 900 { 901 { 902 "PageDryTime", N_("Drying Time Per Page"), "Color=No,Category=Advanced Printer Functionality", 903 N_("Set drying time per page"), 904 STP_PARAMETER_TYPE_DOUBLE, STP_PARAMETER_CLASS_FEATURE, 905 STP_PARAMETER_LEVEL_ADVANCED3, 0, 1, STP_CHANNEL_NONE, 1, 0 906 }, 0, 60.0, 0.0, 1 907 }, 908 { 909 { 910 "ScanDryTime", N_("Drying Time Per Scan"), "Color=No,Category=Advanced Printer Functionality", 911 N_("Set drying time per scan"), 912 STP_PARAMETER_TYPE_DOUBLE, STP_PARAMETER_CLASS_FEATURE, 913 STP_PARAMETER_LEVEL_ADVANCED3, 0, 1, STP_CHANNEL_NONE, 1, 0 914 }, 0, 10.0, 0.0, 1 915 }, 916 { 917 { 918 "ScanMinDryTime", N_("Minimum Drying Time Per Scan"), "Color=No,Category=Advanced Printer Functionality", 919 N_("Set minimum drying time per scan"), 920 STP_PARAMETER_TYPE_DOUBLE, STP_PARAMETER_CLASS_FEATURE, 921 STP_PARAMETER_LEVEL_ADVANCED3, 0, 1, STP_CHANNEL_NONE, 1, 0 922 }, 0, 10.0, 0.0, 1 923 }, 924}; 925 926static const int float_parameter_count = 927sizeof(float_parameters) / sizeof(const float_param_t); 928 929 930static const int_param_t int_parameters[] = 931{ 932 { 933 { 934 "BandEnhancement", N_("Quality Enhancement"), "Color=No,Category=Advanced Printer Functionality", 935 N_("Enhance print quality by additional passes"), 936 STP_PARAMETER_TYPE_INT, STP_PARAMETER_CLASS_FEATURE, 937 STP_PARAMETER_LEVEL_ADVANCED2, 0, 1, STP_CHANNEL_NONE, 1, 0 938 }, 0, 4, 0 939 }, 940 { 941 { 942 "PaperThickness", N_("Paper Thickness"), "Color=No,Category=Advanced Printer Functionality", 943 N_("Set printer paper thickness"), 944 STP_PARAMETER_TYPE_INT, STP_PARAMETER_CLASS_FEATURE, 945 STP_PARAMETER_LEVEL_ADVANCED3, 0, 1, STP_CHANNEL_NONE, 1, 0 946 }, 0, 255, 0 947 }, 948 { 949 { 950 "VacuumIntensity", N_("Vacuum Intensity"), "Color=No,Category=Advanced Printer Functionality", 951 N_("Set vacuum intensity (printer-specific)"), 952 STP_PARAMETER_TYPE_INT, STP_PARAMETER_CLASS_FEATURE, 953 STP_PARAMETER_LEVEL_ADVANCED3, 0, 1, STP_CHANNEL_NONE, 1, 0 954 }, 0, 255, 0 955 }, 956 { 957 { 958 "FeedSequence", N_("Feed Sequence"), "Color=No,Category=Advanced Printer Functionality", 959 N_("Set paper feed sequence (printer-specific)"), 960 STP_PARAMETER_TYPE_INT, STP_PARAMETER_CLASS_FEATURE, 961 STP_PARAMETER_LEVEL_ADVANCED3, 0, 1, STP_CHANNEL_NONE, 1, 0 962 }, 0, 255, 0 963 }, 964 { 965 { 966 "PrintMethod", N_("Print Method"), "Color=No,Category=Advanced Printer Functionality", 967 N_("Set print method (printer-specific)"), 968 STP_PARAMETER_TYPE_INT, STP_PARAMETER_CLASS_FEATURE, 969 STP_PARAMETER_LEVEL_ADVANCED3, 0, 1, STP_CHANNEL_NONE, 1, 0 970 }, 0, 255, 0 971 }, 972 { 973 { 974 "PlatenGap", N_("Platen Gap"), "Color=No,Category=Advanced Printer Functionality", 975 N_("Set platen gap (printer-specific)"), 976 STP_PARAMETER_TYPE_INT, STP_PARAMETER_CLASS_FEATURE, 977 STP_PARAMETER_LEVEL_ADVANCED3, 0, 1, STP_CHANNEL_NONE, 1, 0 978 }, 0, 255, 0 979 }, 980 { 981 { 982 "FeedAdjustment", N_("Feed Adjustment"), "Color=No,Category=Advanced Printer Functionality", 983 /* xgettext:no-c-format */ 984 N_("Set paper feed adjustment (0.01% units)"), 985 STP_PARAMETER_TYPE_INT, STP_PARAMETER_CLASS_FEATURE, 986 STP_PARAMETER_LEVEL_ADVANCED3, 0, 1, STP_CHANNEL_NONE, 1, 0 987 }, 0, 255, 0 988 }, 989}; 990 991static const int int_parameter_count = 992sizeof(int_parameters) / sizeof(const int_param_t); 993 994 995static escp2_privdata_t * 996get_privdata(stp_vars_t *v) 997{ 998 return (escp2_privdata_t *) stp_get_component_data(v, "Driver"); 999} 1000 1001#define DEF_SIMPLE_ACCESSOR(f, t) \ 1002static inline t \ 1003escp2_##f(const stp_vars_t *v) \ 1004{ \ 1005 if (stp_check_int_parameter(v, "escp2_" #f, STP_PARAMETER_ACTIVE)) \ 1006 return stp_get_int_parameter(v, "escp2_" #f); \ 1007 else \ 1008 { \ 1009 stpi_escp2_printer_t *printdef = stp_escp2_get_printer(v); \ 1010 return printdef->f; \ 1011 } \ 1012} 1013 1014#define DEF_RAW_ACCESSOR(f, t) \ 1015static inline t \ 1016escp2_##f(const stp_vars_t *v) \ 1017{ \ 1018 if (stp_check_raw_parameter(v, "escp2_" #f, STP_PARAMETER_ACTIVE)) \ 1019 return stp_get_raw_parameter(v, "escp2_" #f); \ 1020 else \ 1021 { \ 1022 stpi_escp2_printer_t *printdef = stp_escp2_get_printer(v); \ 1023 return printdef->f; \ 1024 } \ 1025} 1026 1027#define DEF_ROLL_ACCESSOR(f, t) \ 1028static inline t \ 1029escp2_##f(const stp_vars_t *v, int rollfeed) \ 1030{ \ 1031 if (stp_check_int_parameter(v, "escp2_" #f, STP_PARAMETER_ACTIVE)) \ 1032 return stp_get_int_parameter(v, "escp2_" #f); \ 1033 else \ 1034 { \ 1035 stpi_escp2_printer_t *printdef = stp_escp2_get_printer(v); \ 1036 const res_t *res = stp_escp2_find_resolution(v); \ 1037 if (res && res->command) \ 1038 { \ 1039 if (rollfeed) \ 1040 return (printdef->m_roll_##f); \ 1041 else \ 1042 return (printdef->m_##f); \ 1043 } \ 1044 else \ 1045 { \ 1046 if (rollfeed) \ 1047 return (printdef->roll_##f); \ 1048 else \ 1049 return (printdef->f); \ 1050 } \ 1051 } \ 1052} 1053 1054DEF_SIMPLE_ACCESSOR(max_hres, int) 1055DEF_SIMPLE_ACCESSOR(max_vres, int) 1056DEF_SIMPLE_ACCESSOR(min_hres, int) 1057DEF_SIMPLE_ACCESSOR(min_vres, int) 1058DEF_SIMPLE_ACCESSOR(nozzles, unsigned) 1059DEF_SIMPLE_ACCESSOR(black_nozzles, unsigned) 1060DEF_SIMPLE_ACCESSOR(fast_nozzles, unsigned) 1061DEF_SIMPLE_ACCESSOR(min_nozzles, unsigned) 1062DEF_SIMPLE_ACCESSOR(min_black_nozzles, unsigned) 1063DEF_SIMPLE_ACCESSOR(min_fast_nozzles, unsigned) 1064DEF_SIMPLE_ACCESSOR(nozzle_start, int) 1065DEF_SIMPLE_ACCESSOR(black_nozzle_start, int) 1066DEF_SIMPLE_ACCESSOR(fast_nozzle_start, int) 1067DEF_SIMPLE_ACCESSOR(nozzle_separation, unsigned) 1068DEF_SIMPLE_ACCESSOR(black_nozzle_separation, unsigned) 1069DEF_SIMPLE_ACCESSOR(fast_nozzle_separation, unsigned) 1070DEF_SIMPLE_ACCESSOR(separation_rows, unsigned) 1071DEF_SIMPLE_ACCESSOR(max_paper_width, unsigned) 1072DEF_SIMPLE_ACCESSOR(max_paper_height, unsigned) 1073DEF_SIMPLE_ACCESSOR(min_paper_width, unsigned) 1074DEF_SIMPLE_ACCESSOR(min_paper_height, unsigned) 1075DEF_SIMPLE_ACCESSOR(max_imageable_width, unsigned) 1076DEF_SIMPLE_ACCESSOR(max_imageable_height, unsigned) 1077DEF_SIMPLE_ACCESSOR(cd_x_offset, int) 1078DEF_SIMPLE_ACCESSOR(cd_y_offset, int) 1079DEF_SIMPLE_ACCESSOR(cd_page_width, int) 1080DEF_SIMPLE_ACCESSOR(cd_page_height, int) 1081DEF_SIMPLE_ACCESSOR(paper_extra_bottom, int) 1082DEF_SIMPLE_ACCESSOR(extra_feed, unsigned) 1083DEF_SIMPLE_ACCESSOR(pseudo_separation_rows, int) 1084DEF_SIMPLE_ACCESSOR(base_separation, int) 1085DEF_SIMPLE_ACCESSOR(resolution_scale, int) 1086DEF_SIMPLE_ACCESSOR(initial_vertical_offset, int) 1087DEF_SIMPLE_ACCESSOR(black_initial_vertical_offset, int) 1088DEF_SIMPLE_ACCESSOR(max_black_resolution, int) 1089DEF_SIMPLE_ACCESSOR(zero_margin_offset, int) 1090DEF_SIMPLE_ACCESSOR(extra_720dpi_separation, int) 1091DEF_SIMPLE_ACCESSOR(micro_left_margin, int) 1092DEF_SIMPLE_ACCESSOR(min_horizontal_position_alignment, unsigned) 1093DEF_SIMPLE_ACCESSOR(base_horizontal_position_alignment, unsigned) 1094DEF_SIMPLE_ACCESSOR(bidirectional_upper_limit, int) 1095DEF_SIMPLE_ACCESSOR(physical_channels, int) 1096DEF_SIMPLE_ACCESSOR(alignment_passes, int) 1097DEF_SIMPLE_ACCESSOR(alignment_choices, int) 1098DEF_SIMPLE_ACCESSOR(alternate_alignment_passes, int) 1099DEF_SIMPLE_ACCESSOR(alternate_alignment_choices, int) 1100 1101DEF_ROLL_ACCESSOR(left_margin, unsigned) 1102DEF_ROLL_ACCESSOR(right_margin, unsigned) 1103DEF_ROLL_ACCESSOR(top_margin, unsigned) 1104DEF_ROLL_ACCESSOR(bottom_margin, unsigned) 1105 1106DEF_RAW_ACCESSOR(preinit_sequence, const stp_raw_t *) 1107DEF_RAW_ACCESSOR(preinit_remote_sequence, const stp_raw_t *) 1108DEF_RAW_ACCESSOR(postinit_remote_sequence, const stp_raw_t *) 1109 1110DEF_RAW_ACCESSOR(vertical_borderless_sequence, const stp_raw_t *) 1111 1112static const resolution_list_t * 1113escp2_reslist(const stp_vars_t *v) 1114{ 1115 stpi_escp2_printer_t *printdef = stp_escp2_get_printer(v); 1116 return printdef->resolutions; 1117} 1118 1119static inline const printer_weave_list_t * 1120escp2_printer_weaves(const stp_vars_t *v) 1121{ 1122 stpi_escp2_printer_t *printdef = stp_escp2_get_printer(v); 1123 return printdef->printer_weaves; 1124} 1125 1126static inline const stp_string_list_t * 1127escp2_channel_names(const stp_vars_t *v) 1128{ 1129 stpi_escp2_printer_t *printdef = stp_escp2_get_printer(v); 1130 return (printdef->channel_names); 1131} 1132 1133static inline const inkgroup_t * 1134escp2_inkgroup(const stp_vars_t *v) 1135{ 1136 stpi_escp2_printer_t *printdef = stp_escp2_get_printer(v); 1137 return (printdef->inkgroup); 1138} 1139 1140static inline const quality_list_t * 1141escp2_quality_list(const stp_vars_t *v) 1142{ 1143 stpi_escp2_printer_t *printdef = stp_escp2_get_printer(v); 1144 return printdef->quality_list; 1145} 1146 1147static short 1148escp2_duplex_left_margin(const stp_vars_t *v) 1149{ 1150 stpi_escp2_printer_t *printdef = stp_escp2_get_printer(v); 1151 return printdef->duplex_left_margin; 1152} 1153 1154static short 1155escp2_duplex_right_margin(const stp_vars_t *v) 1156{ 1157 stpi_escp2_printer_t *printdef = stp_escp2_get_printer(v); 1158 return printdef->duplex_right_margin; 1159} 1160 1161static short 1162escp2_duplex_top_margin(const stp_vars_t *v) 1163{ 1164 stpi_escp2_printer_t *printdef = stp_escp2_get_printer(v); 1165 return printdef->duplex_top_margin; 1166} 1167 1168static short 1169escp2_duplex_bottom_margin(const stp_vars_t *v) 1170{ 1171 stpi_escp2_printer_t *printdef = stp_escp2_get_printer(v); 1172 return printdef->duplex_bottom_margin; 1173} 1174 1175static const channel_count_t * 1176get_channel_count_by_name(const char *name) 1177{ 1178 int i; 1179 for (i = 0; i < escp2_channel_counts_count; i++) 1180 if (strcmp(name, escp2_channel_counts[i].name) == 0) 1181 return &(escp2_channel_counts[i]); 1182 return NULL; 1183} 1184 1185static const channel_count_t * 1186get_channel_count_by_number(unsigned count) 1187{ 1188 int i; 1189 for (i = 0; i < escp2_channel_counts_count; i++) 1190 if (count == escp2_channel_counts[i].count) 1191 return &(escp2_channel_counts[i]); 1192 return NULL; 1193} 1194 1195static int 1196escp2_res_param(const stp_vars_t *v, const char *param, const res_t *res) 1197{ 1198 if (res) 1199 { 1200 if (res->v && 1201 stp_check_int_parameter(res->v, param, STP_PARAMETER_ACTIVE)) 1202 return stp_get_int_parameter(res->v, param); 1203 else 1204 return -1; 1205 } 1206 if (stp_check_int_parameter(v, param, STP_PARAMETER_ACTIVE)) 1207 return stp_get_int_parameter(v, param); 1208 else 1209 { 1210 const res_t *res1 = stp_escp2_find_resolution(v); 1211 if (res1->v && 1212 stp_check_int_parameter(res1->v, param, STP_PARAMETER_ACTIVE)) 1213 return stp_get_int_parameter(res1->v, param); 1214 } 1215 return -1; 1216} 1217 1218static int 1219escp2_ink_type(const stp_vars_t *v) 1220{ 1221 return escp2_res_param(v, "escp2_ink_type", NULL); 1222} 1223 1224static double 1225escp2_density(const stp_vars_t *v) 1226{ 1227 if (stp_check_float_parameter(v, "escp2_density", STP_PARAMETER_ACTIVE)) 1228 return stp_get_float_parameter(v, "escp2_density"); 1229 else 1230 { 1231 const res_t *res1 = stp_escp2_find_resolution(v); 1232 if (res1->v && 1233 stp_check_float_parameter(res1->v, "escp2_density", STP_PARAMETER_ACTIVE)) 1234 return stp_get_float_parameter(res1->v, "escp2_density"); 1235 } 1236 return 0; 1237} 1238 1239static int 1240escp2_bits(const stp_vars_t *v) 1241{ 1242 return escp2_res_param(v, "escp2_bits", NULL); 1243} 1244 1245static int 1246escp2_base_res(const stp_vars_t *v) 1247{ 1248 return escp2_res_param(v, "escp2_base_res", NULL); 1249} 1250 1251static int 1252escp2_ink_type_by_res(const stp_vars_t *v, const res_t *res) 1253{ 1254 return escp2_res_param(v, "escp2_ink_type", res); 1255} 1256 1257static double 1258escp2_density_by_res(const stp_vars_t *v, const res_t *res) 1259{ 1260 if (res) 1261 { 1262 if (res->v && 1263 stp_check_float_parameter(res->v, "escp2_density", STP_PARAMETER_ACTIVE)) 1264 return stp_get_float_parameter(res->v, "escp2_density"); 1265 } 1266 return 0.0; 1267} 1268 1269static int 1270escp2_bits_by_res(const stp_vars_t *v, const res_t *res) 1271{ 1272 return escp2_res_param(v, "escp2_bits", res); 1273} 1274 1275static int 1276escp2_base_res_by_res(const stp_vars_t *v, const res_t *res) 1277{ 1278 return escp2_res_param(v, "escp2_base_res", res); 1279} 1280 1281static escp2_dropsize_t * 1282escp2_copy_dropsizes(const stp_vars_t *v) 1283{ 1284 const res_t *res = stp_escp2_find_resolution(v); 1285 escp2_dropsize_t *ndrops; 1286 if (!res || !(res->v)) 1287 return NULL; 1288 ndrops = stp_zalloc(sizeof(escp2_dropsize_t)); 1289 if (! ndrops) 1290 return NULL; 1291 if (stp_check_float_parameter(res->v, "DropSize1", STP_PARAMETER_ACTIVE)) 1292 { 1293 ndrops->numdropsizes = 1; 1294 ndrops->dropsizes[0] = stp_get_float_parameter(res->v, "DropSize1"); 1295 } 1296 if (stp_check_float_parameter(res->v, "DropSize2", STP_PARAMETER_ACTIVE)) 1297 { 1298 ndrops->numdropsizes = 2; 1299 ndrops->dropsizes[1] = stp_get_float_parameter(res->v, "DropSize2"); 1300 } 1301 if (stp_check_float_parameter(res->v, "DropSize3", STP_PARAMETER_ACTIVE)) 1302 { 1303 ndrops->numdropsizes = 3; 1304 ndrops->dropsizes[2] = stp_get_float_parameter(res->v, "DropSize3"); 1305 } 1306 return ndrops; 1307} 1308 1309static void 1310escp2_free_dropsizes(escp2_dropsize_t *drops) 1311{ 1312 if (drops) 1313 stp_free(drops); 1314} 1315 1316const inklist_t * 1317stp_escp2_inklist(const stp_vars_t *v) 1318{ 1319 int i; 1320 const char *ink_list_name = NULL; 1321 const inkgroup_t *inkgroup = escp2_inkgroup(v); 1322 1323 if (stp_check_string_parameter(v, "InkSet", STP_PARAMETER_ACTIVE)) 1324 ink_list_name = stp_get_string_parameter(v, "InkSet"); 1325 if (ink_list_name) 1326 { 1327 for (i = 0; i < inkgroup->n_inklists; i++) 1328 { 1329 if (strcmp(ink_list_name, inkgroup->inklists[i].name) == 0) 1330 return &(inkgroup->inklists[i]); 1331 } 1332 } 1333 STPI_ASSERT(inkgroup, v); 1334 return &(inkgroup->inklists[0]); 1335} 1336 1337static const shade_t * 1338escp2_shades(const stp_vars_t *v, int channel) 1339{ 1340 const inklist_t *inklist = stp_escp2_inklist(v); 1341 return &(inklist->shades[channel]); 1342} 1343 1344static shade_t * 1345escp2_copy_shades(const stp_vars_t *v, int channel) 1346{ 1347 int i; 1348 shade_t *nshades; 1349 const inklist_t *inklist = stp_escp2_inklist(v); 1350 if (!inklist) 1351 return NULL; 1352 nshades = stp_zalloc(sizeof(shade_t)); 1353 nshades->n_shades = inklist->shades[channel].n_shades; 1354 nshades->shades = stp_zalloc(sizeof(double) * inklist->shades[channel].n_shades); 1355 for (i = 0; i < inklist->shades[channel].n_shades; i++) 1356 nshades->shades[i] = inklist->shades[channel].shades[i]; 1357 return nshades; 1358} 1359 1360static void 1361escp2_free_shades(shade_t *shades) 1362{ 1363 if (shades) 1364 { 1365 if (shades->shades) 1366 stp_free(shades->shades); 1367 stp_free(shades); 1368 } 1369} 1370 1371static const stp_string_list_t * 1372escp2_paperlist(const stp_vars_t *v) 1373{ 1374 stpi_escp2_printer_t *printdef = stp_escp2_get_printer(v); 1375 return printdef->papers; 1376} 1377 1378static const stp_string_list_t * 1379escp2_slotlist(const stp_vars_t *v) 1380{ 1381 stpi_escp2_printer_t *printdef = stp_escp2_get_printer(v); 1382 return printdef->input_slots; 1383} 1384 1385static int 1386supports_borderless(const stp_vars_t *v) 1387{ 1388 return (stp_escp2_has_cap(v, MODEL_ZEROMARGIN, MODEL_ZEROMARGIN_YES) || 1389 stp_escp2_has_cap(v, MODEL_ZEROMARGIN, MODEL_ZEROMARGIN_FULL) || 1390 stp_escp2_has_cap(v, MODEL_ZEROMARGIN, MODEL_ZEROMARGIN_H_ONLY) || 1391 stp_escp2_has_cap(v, MODEL_ZEROMARGIN, MODEL_ZEROMARGIN_RESTR)); 1392} 1393 1394static int 1395max_nozzle_span(const stp_vars_t *v) 1396{ 1397 int nozzle_count = escp2_nozzles(v); 1398 int nozzle_separation = escp2_nozzle_separation(v); 1399 int black_nozzle_count = escp2_black_nozzles(v); 1400 int black_nozzle_separation = escp2_black_nozzle_separation(v); 1401 int nozzle_span = nozzle_count * nozzle_separation; 1402 int black_nozzle_span = black_nozzle_count * black_nozzle_separation; 1403 if (black_nozzle_span > nozzle_span) 1404 return black_nozzle_span; 1405 else 1406 return nozzle_span; 1407} 1408 1409static const stp_raw_t * 1410get_printer_weave(const stp_vars_t *v) 1411{ 1412 int i; 1413 const res_t *res = stp_escp2_find_resolution(v); 1414 const printer_weave_list_t *p = escp2_printer_weaves(v); 1415 if (p) 1416 { 1417 const char *name = stp_get_string_parameter(v, "Weave"); 1418 int printer_weave_count = p->n_printer_weaves; 1419 if (name) 1420 { 1421 for (i = 0; i < printer_weave_count; i++) 1422 { 1423 if (!strcmp(name, p->printer_weaves[i].name)) 1424 return p->printer_weaves[i].command; 1425 } 1426 } 1427 } 1428 if (res) 1429 return res->command; 1430 return NULL; 1431} 1432 1433static int 1434use_printer_weave(const stp_vars_t *v) 1435{ 1436 const res_t *res = stp_escp2_find_resolution(v); 1437 return (!res || res->command); 1438} 1439 1440static void 1441get_resolution_bounds_by_paper_type(const stp_vars_t *v, 1442 unsigned *max_x, unsigned *max_y, 1443 unsigned *min_x, unsigned *min_y) 1444{ 1445 const paper_t *paper = stp_escp2_get_media_type(v, 1); 1446 *min_x = 0; 1447 *min_y = 0; 1448 *max_x = 0; 1449 *max_y = 0; 1450 if (paper) 1451 { 1452 switch (paper->paper_class) 1453 { 1454 case PAPER_PLAIN: 1455 *min_x = 0; 1456 *min_y = 0; 1457 *max_x = 1440; 1458 *max_y = 720; 1459 break; 1460 case PAPER_GOOD: 1461 *min_x = 360; 1462 *min_y = 360; 1463 *max_x = 1440; 1464 *max_y = 1440; 1465 break; 1466 case PAPER_PHOTO: 1467 *min_x = 720; 1468 *min_y = 360; 1469 *max_x = 2880; 1470 *max_y = 1440; 1471 if (*min_x >= escp2_max_hres(v)) 1472 *min_x = escp2_max_hres(v); 1473 break; 1474 case PAPER_PREMIUM_PHOTO: 1475 *min_x = 720; 1476 *min_y = 720; 1477 *max_x = 0; 1478 *max_y = 0; 1479 if (*min_x >= escp2_max_hres(v)) 1480 *min_x = escp2_max_hres(v); 1481 break; 1482 case PAPER_TRANSPARENCY: 1483 *min_x = 360; 1484 *min_y = 360; 1485 *max_x = 720; 1486 *max_y = 720; 1487 break; 1488 } 1489 stp_dprintf(STP_DBG_ESCP2, v, 1490 "Paper %s class %d: min_x %d min_y %d max_x %d max_y %d\n", 1491 paper->text, paper->paper_class, *min_x, *min_y, 1492 *max_x, *max_y); 1493 } 1494} 1495 1496static int 1497verify_resolution_by_paper_type(const stp_vars_t *v, const res_t *res) 1498{ 1499 unsigned min_x = 0; 1500 unsigned min_y = 0; 1501 unsigned max_x = 0; 1502 unsigned max_y = 0; 1503 get_resolution_bounds_by_paper_type(v, &max_x, &max_y, &min_x, &min_y); 1504 if ((max_x == 0 || res->printed_hres <= max_x) && 1505 (max_y == 0 || res->printed_vres <= max_y) && 1506 (min_x == 0 || res->printed_hres >= min_x) && 1507 (min_y == 0 || res->printed_vres >= min_y)) 1508 { 1509 stp_dprintf(STP_DBG_ESCP2, v, 1510 "Resolution %s (%d, %d) GOOD (%d, %d, %d, %d)\n", 1511 res->name, res->printed_hres, res->printed_vres, 1512 min_x, min_y, max_x, max_y); 1513 return 1; 1514 } 1515 else 1516 { 1517 stp_dprintf(STP_DBG_ESCP2, v, 1518 "Resolution %s (%d, %d) BAD (%d, %d, %d, %d)\n", 1519 res->name, res->printed_hres, res->printed_vres, 1520 min_x, min_y, max_x, max_y); 1521 return 0; 1522 } 1523} 1524 1525static int 1526verify_resolution(const stp_vars_t *v, const res_t *res) 1527{ 1528 int nozzle_width = 1529 (escp2_base_separation(v) / escp2_nozzle_separation(v)); 1530 int nozzles = escp2_nozzles(v); 1531 if (escp2_ink_type_by_res(v, res) != -1 && 1532 res->vres <= escp2_max_vres(v) && 1533 res->hres <= escp2_max_hres(v) && 1534 res->vres >= escp2_min_vres(v) && 1535 res->hres >= escp2_min_hres(v) && 1536 (nozzles == 1 || 1537 ((res->vres / nozzle_width) * nozzle_width) == res->vres)) 1538 { 1539 int xdpi = res->hres; 1540 int physical_xdpi = escp2_base_res_by_res(v, res); 1541 int horizontal_passes, oversample; 1542 if (physical_xdpi > xdpi) 1543 physical_xdpi = xdpi; 1544 horizontal_passes = xdpi / physical_xdpi; 1545 oversample = horizontal_passes * res->vertical_passes; 1546 if (horizontal_passes < 1) 1547 horizontal_passes = 1; 1548 if (oversample < 1) 1549 oversample = 1; 1550 if (((horizontal_passes * res->vertical_passes) <= STP_MAX_WEAVE) && 1551 (res->command || (nozzles > 1 && nozzles > oversample))) 1552 return 1; 1553 } 1554 return 0; 1555} 1556 1557static void 1558get_printer_resolution_bounds(const stp_vars_t *v, 1559 unsigned *max_x, unsigned *max_y, 1560 unsigned *min_x, unsigned *min_y) 1561{ 1562 int i = 0; 1563 const resolution_list_t *resolutions = escp2_reslist(v); 1564 *max_x = 0; 1565 *max_y = 0; 1566 *min_x = 0; 1567 *min_y = 0; 1568 for (i = 0; i < resolutions->n_resolutions; i++) 1569 { 1570 res_t *res = &(resolutions->resolutions[i]); 1571 if (verify_resolution(v, res)) 1572 { 1573 if (res->printed_hres * res->vertical_passes > *max_x) 1574 *max_x = res->printed_hres * res->vertical_passes; 1575 if (res->printed_vres > *max_y) 1576 *max_y = res->printed_vres; 1577 if (*min_x == 0 || 1578 res->printed_hres * res->vertical_passes < *min_x) 1579 *min_x = res->printed_hres * res->vertical_passes; 1580 if (*min_y == 0 || res->printed_vres < *min_y) 1581 *min_y = res->printed_vres; 1582 } 1583 } 1584 stp_dprintf(STP_DBG_ESCP2, v, 1585 "Printer bounds: %d %d %d %d\n", *min_x, *min_y, *max_x, *max_y); 1586} 1587 1588static int 1589verify_papersize(const stp_vars_t *v, const stp_papersize_t *pt) 1590{ 1591 unsigned int height_limit, width_limit; 1592 unsigned int min_height_limit, min_width_limit; 1593 unsigned int envelope_landscape = 1594 stp_escp2_has_cap(v, MODEL_ENVELOPE_LANDSCAPE, MODEL_ENVELOPE_LANDSCAPE_YES); 1595 width_limit = escp2_max_paper_width(v); 1596 height_limit = escp2_max_paper_height(v); 1597 min_width_limit = escp2_min_paper_width(v); 1598 min_height_limit = escp2_min_paper_height(v); 1599 if (strlen(pt->name) > 0 && 1600 (pt->paper_size_type != PAPERSIZE_TYPE_ENVELOPE || 1601 envelope_landscape || pt->height > pt->width) && 1602 pt->width <= width_limit && pt->height <= height_limit && 1603 (pt->height >= min_height_limit || pt->height == 0) && 1604 (pt->width >= min_width_limit || pt->width == 0) && 1605 (pt->width == 0 || pt->height > 0 || 1606 stp_escp2_printer_supports_rollfeed(v))) 1607 return 1; 1608 else 1609 return 0; 1610} 1611 1612static int 1613verify_inktype(const stp_vars_t *v, const inkname_t *inks) 1614{ 1615 if (inks->inkset == INKSET_EXTENDED) 1616 return 0; 1617 else 1618 return 1; 1619} 1620 1621static const char * 1622get_default_inktype(const stp_vars_t *v) 1623{ 1624 const inklist_t *ink_list = stp_escp2_inklist(v); 1625 const paper_t *paper_type; 1626 if (!ink_list) 1627 return NULL; 1628 paper_type = stp_escp2_get_media_type(v, 0); 1629 if (!paper_type) 1630 paper_type = stp_escp2_get_default_media_type(v); 1631 if (paper_type && paper_type->preferred_ink_type) 1632 return paper_type->preferred_ink_type; 1633 else if (stp_escp2_has_cap(v, MODEL_FAST_360, MODEL_FAST_360_YES) && 1634 stp_check_string_parameter(v, "Resolution", STP_PARAMETER_ACTIVE)) 1635 { 1636 const res_t *res = stp_escp2_find_resolution(v); 1637 if (res) 1638 { 1639 if (res->vres == 360 && res->hres == escp2_base_res(v)) 1640 { 1641 int i; 1642 for (i = 0; i < ink_list->n_inks; i++) 1643 if (strcmp(ink_list->inknames[i].name, "CMYK") == 0) 1644 return ink_list->inknames[i].name; 1645 } 1646 } 1647 } 1648 return ink_list->inknames[0].name; 1649} 1650 1651 1652static const inkname_t * 1653get_inktype(const stp_vars_t *v) 1654{ 1655 const char *ink_type = stp_get_string_parameter(v, "InkType"); 1656 const inklist_t *ink_list = stp_escp2_inklist(v); 1657 int i; 1658 1659 if (!ink_type || strcmp(ink_type, "None") == 0 || 1660 (ink_list && ink_list->n_inks == 1)) 1661 ink_type = get_default_inktype(v); 1662 1663 if (ink_type && ink_list) 1664 { 1665 for (i = 0; i < ink_list->n_inks; i++) 1666 { 1667 if (strcmp(ink_type, ink_list->inknames[i].name) == 0) 1668 return &(ink_list->inknames[i]); 1669 } 1670 } 1671 /* 1672 * If we couldn't find anything, try again with the default ink type. 1673 * This may mean duplicate work, but that's cheap enough. 1674 */ 1675 ink_type = get_default_inktype(v); 1676 for (i = 0; i < ink_list->n_inks; i++) 1677 { 1678 if (strcmp(ink_type, ink_list->inknames[i].name) == 0) 1679 return &(ink_list->inknames[i]); 1680 } 1681 /* 1682 * If even *that* doesn't work, try using the first ink type on the list. 1683 */ 1684 return &(ink_list->inknames[0]); 1685} 1686 1687static const inkname_t * 1688get_inktype_only(const stp_vars_t *v) 1689{ 1690 const char *ink_type = stp_get_string_parameter(v, "InkType"); 1691 1692 if (!ink_type) 1693 return NULL; 1694 else 1695 return get_inktype(v); 1696} 1697 1698static int 1699printer_supports_inkset(const stp_vars_t *v, inkset_id_t inkset) 1700{ 1701 const inkgroup_t *ink_group = escp2_inkgroup(v); 1702 int i; 1703 for (i = 0; i < ink_group->n_inklists; i++) 1704 { 1705 const inklist_t *ink_list = &(ink_group->inklists[i]); 1706 if (ink_list) 1707 { 1708 int j; 1709 for (j = 0; j < ink_list->n_inks; j++) 1710 { 1711 if (ink_list->inknames[j].inkset == inkset) 1712 { 1713 return 1; 1714 } 1715 } 1716 } 1717 } 1718 return 0; 1719} 1720 1721static const stp_vars_t * 1722get_media_adjustment(const stp_vars_t *v) 1723{ 1724 const paper_t *pt = stp_escp2_get_media_type(v, 0); 1725 if (pt) 1726 return pt->v; 1727 else 1728 return NULL; 1729} 1730 1731/* 1732 * 'escp2_parameters()' - Return the parameter values for the given parameter. 1733 */ 1734 1735static stp_parameter_list_t 1736escp2_list_parameters(const stp_vars_t *v) 1737{ 1738 stp_parameter_list_t *ret = stp_parameter_list_create(); 1739 int i; 1740 for (i = 0; i < the_parameter_count; i++) 1741 stp_parameter_list_add_param(ret, &(the_parameters[i])); 1742 for (i = 0; i < float_parameter_count; i++) 1743 stp_parameter_list_add_param(ret, &(float_parameters[i].param)); 1744 for (i = 0; i < int_parameter_count; i++) 1745 stp_parameter_list_add_param(ret, &(int_parameters[i].param)); 1746 return ret; 1747} 1748 1749static void 1750set_density_parameter(const stp_vars_t *v, 1751 stp_parameter_t *description, 1752 const char *name) 1753{ 1754 const inkname_t *ink_name = get_inktype(v); 1755 description->is_active = 0; 1756 if (ink_name && stp_get_string_parameter(v, "PrintingMode") && 1757 strcmp(stp_get_string_parameter(v, "PrintingMode"), "BW") != 0) 1758 { 1759 int i, j; 1760 for (i = 0; i < ink_name->channel_count; i++) 1761 { 1762 ink_channel_t *ich = &(ink_name->channels[i]); 1763 if (ich) 1764 { 1765 for (j = 0; j < ich->n_subchannels; j++) 1766 { 1767 physical_subchannel_t *sch = &(ich->subchannels[j]); 1768 if (sch && sch->channel_density && 1769 !strcmp(name, sch->channel_density)) 1770 { 1771 description->is_active = 1; 1772 description->bounds.dbl.lower = 0; 1773 description->bounds.dbl.upper = 2.0; 1774 description->deflt.dbl = 1.0; 1775 } 1776 } 1777 } 1778 } 1779 } 1780} 1781 1782static void 1783set_hue_map_parameter(const stp_vars_t *v, 1784 stp_parameter_t *description, 1785 const char *name) 1786{ 1787 const inkname_t *ink_name = get_inktype(v); 1788 description->is_active = 0; 1789 description->deflt.curve = hue_curve_bounds; 1790 description->bounds.curve = stp_curve_create_copy(hue_curve_bounds); 1791 if (ink_name && stp_get_string_parameter(v, "PrintingMode") && 1792 strcmp(stp_get_string_parameter(v, "PrintingMode"), "BW") != 0) 1793 { 1794 int i; 1795 for (i = 0; i < ink_name->channel_count; i++) 1796 { 1797 ink_channel_t *ich = &(ink_name->channels[i]); 1798 if (ich && ich->hue_curve && !strcmp(name, ich->hue_curve_name)) 1799 { 1800 description->deflt.curve = ich->hue_curve; 1801 description->is_active = 1; 1802 } 1803 } 1804 } 1805} 1806 1807static void 1808fill_value_parameters(const stp_vars_t *v, 1809 stp_parameter_t *description, 1810 int color) 1811{ 1812 const shade_t *shades = escp2_shades(v, color); 1813 const inkname_t *ink_name = get_inktype(v); 1814 description->is_active = 1; 1815 description->bounds.dbl.lower = 0; 1816 description->bounds.dbl.upper = 1.0; 1817 description->deflt.dbl = 1.0; 1818 if (shades && ink_name) 1819 { 1820 const ink_channel_t *channel = &(ink_name->channels[color]); 1821 int i; 1822 for (i = 0; i < channel->n_subchannels; i++) 1823 { 1824 if (channel->subchannels[i].subchannel_value && 1825 strcmp(description->name, 1826 channel->subchannels[i].subchannel_value) == 0) 1827 { 1828 description->deflt.dbl = shades->shades[i]; 1829 return; 1830 } 1831 } 1832 } 1833} 1834 1835static void 1836set_color_value_parameter(const stp_vars_t *v, 1837 stp_parameter_t *description, 1838 int color) 1839{ 1840 description->is_active = 0; 1841 if (stp_get_string_parameter(v, "PrintingMode") && 1842 strcmp(stp_get_string_parameter(v, "PrintingMode"), "BW") != 0) 1843 { 1844 const inkname_t *ink_name = get_inktype(v); 1845 if (ink_name && 1846 ink_name->channel_count == 4 && 1847 ink_name->channels[color].n_subchannels == 2) 1848 fill_value_parameters(v, description, color); 1849 } 1850} 1851 1852static void 1853set_gray_value_parameter(const stp_vars_t *v, 1854 stp_parameter_t *description, 1855 int expected_channels) 1856{ 1857 const inkname_t *ink_name = get_inktype_only(v); 1858 description->is_active = 0; 1859 if (!ink_name && 1860 ((expected_channels == 4 && printer_supports_inkset(v, INKSET_QUADTONE)) || 1861 (expected_channels == 6 && printer_supports_inkset(v, INKSET_HEXTONE)))) 1862 fill_value_parameters(v, description, STP_ECOLOR_K); 1863 else if (ink_name && 1864 (ink_name->channels[STP_ECOLOR_K].n_subchannels == 1865 expected_channels)) 1866 fill_value_parameters(v, description, STP_ECOLOR_K); 1867 else 1868 set_color_value_parameter(v, description, STP_ECOLOR_K); 1869} 1870 1871static void 1872fill_transition_parameters(const stp_vars_t *v, 1873 stp_parameter_t *description, 1874 int color) 1875{ 1876 const stp_vars_t *paper_adj = get_media_adjustment(v); 1877 description->is_active = 1; 1878 description->bounds.dbl.lower = 0; 1879 description->bounds.dbl.upper = 1.0; 1880 if (paper_adj && stp_check_float_parameter(paper_adj, "SubchannelCutoff", STP_PARAMETER_ACTIVE)) 1881 description->deflt.dbl = stp_get_float_parameter(paper_adj, "SubchannelCutoff"); 1882 else 1883 description->deflt.dbl = 1.0; 1884} 1885 1886static void 1887set_color_transition_parameter(const stp_vars_t *v, 1888 stp_parameter_t *description, 1889 int color) 1890{ 1891 description->is_active = 0; 1892 if (stp_get_string_parameter(v, "PrintingMode") && 1893 strcmp(stp_get_string_parameter(v, "PrintingMode"), "BW") != 0) 1894 { 1895 const inkname_t *ink_name = get_inktype(v); 1896 if (ink_name && 1897 ink_name->channel_count == 4 && 1898 ink_name->channels[color].n_subchannels == 2) 1899 fill_transition_parameters(v, description, color); 1900 } 1901} 1902 1903static void 1904set_gray_transition_parameter(const stp_vars_t *v, 1905 stp_parameter_t *description, 1906 int expected_channels) 1907{ 1908 const inkname_t *ink_name = get_inktype_only(v); 1909 description->is_active = 0; 1910 if (!ink_name && 1911 ((expected_channels == 4 && printer_supports_inkset(v, INKSET_QUADTONE)) || 1912 (expected_channels == 6 && printer_supports_inkset(v, INKSET_HEXTONE)))) 1913 fill_transition_parameters(v, description, STP_ECOLOR_K); 1914 if (ink_name && 1915 (ink_name->channels[STP_ECOLOR_K].n_subchannels == 1916 expected_channels)) 1917 fill_transition_parameters(v, description, STP_ECOLOR_K); 1918 else 1919 set_color_transition_parameter(v, description, STP_ECOLOR_K); 1920} 1921 1922static void 1923fill_scale_parameters(stp_parameter_t *description) 1924{ 1925 description->is_active = 1; 1926 description->bounds.dbl.lower = 0; 1927 description->bounds.dbl.upper = 5.0; 1928 description->deflt.dbl = 1.0; 1929} 1930 1931static void 1932set_color_scale_parameter(const stp_vars_t *v, 1933 stp_parameter_t *description, 1934 int color) 1935{ 1936 description->is_active = 0; 1937 if (stp_get_string_parameter(v, "PrintingMode") && 1938 strcmp(stp_get_string_parameter(v, "PrintingMode"), "BW") != 0) 1939 { 1940 const inkname_t *ink_name = get_inktype(v); 1941 if (ink_name && 1942 ink_name->channel_count == 4 && 1943 ink_name->channels[color].n_subchannels == 2) 1944 fill_scale_parameters(description); 1945 } 1946} 1947 1948static void 1949set_gray_scale_parameter(const stp_vars_t *v, 1950 stp_parameter_t *description, 1951 int expected_channels) 1952{ 1953 const inkname_t *ink_name = get_inktype_only(v); 1954 description->is_active = 0; 1955 if (!ink_name && 1956 ((expected_channels == 4 && printer_supports_inkset(v, INKSET_QUADTONE)) || 1957 (expected_channels == 6 && printer_supports_inkset(v, INKSET_HEXTONE)))) 1958 fill_transition_parameters(v, description, STP_ECOLOR_K); 1959 if (ink_name && 1960 (ink_name->channels[STP_ECOLOR_K].n_subchannels == 1961 expected_channels)) 1962 fill_scale_parameters(description); 1963 else 1964 set_color_scale_parameter(v, description, STP_ECOLOR_K); 1965} 1966 1967static const res_t * 1968find_default_resolution(const stp_vars_t *v, const quality_t *q, int strict) 1969{ 1970 const resolution_list_t *resolutions = escp2_reslist(v); 1971 int i = 0; 1972 stp_dprintf(STP_DBG_ESCP2, v, "Quality %s: min %d %d max %d %d, des %d %d\n", 1973 q->name, q->min_hres, q->min_vres, q->max_hres, q->max_vres, 1974 q->desired_hres, q->desired_vres); 1975 if (q->desired_hres < 0 || q->desired_vres < 0) 1976 { 1977 for (i = resolutions->n_resolutions - 1; i >= 0; i--) 1978 { 1979 const res_t *res = &(resolutions->resolutions[i]); 1980 stp_dprintf(STP_DBG_ESCP2, v, " Checking resolution %s %d...\n", 1981 res->name, i); 1982 if ((q->max_hres <= 0 || res->printed_hres <= q->max_hres) && 1983 (q->max_vres <= 0 || res->printed_vres <= q->max_vres) && 1984 q->min_hres <= res->printed_hres && 1985 q->min_vres <= res->printed_vres && 1986 verify_resolution(v, res) && 1987 verify_resolution_by_paper_type(v, res)) 1988 return res; 1989 } 1990 } 1991 if (!strict) 1992 { 1993 unsigned max_x, max_y, min_x, min_y; 1994 unsigned desired_hres = q->desired_hres; 1995 unsigned desired_vres = q->desired_vres; 1996 get_resolution_bounds_by_paper_type(v, &max_x, &max_y, &min_x, &min_y); 1997 stp_dprintf(STP_DBG_ESCP2, v, " Comparing hres %d to %d, %d\n", 1998 desired_hres, min_x, max_x); 1999 stp_dprintf(STP_DBG_ESCP2, v, " Comparing vres %d to %d, %d\n", 2000 desired_vres, min_y, max_y); 2001 if (max_x > 0 && desired_hres > max_x) 2002 { 2003 stp_dprintf(STP_DBG_ESCP2, v, " Decreasing hres from %d to %d\n", 2004 desired_hres, max_x); 2005 desired_hres = max_x; 2006 } 2007 else if (desired_hres < min_x) 2008 { 2009 stp_dprintf(STP_DBG_ESCP2, v, " Increasing hres from %d to %d\n", 2010 desired_hres, min_x); 2011 desired_hres = min_x; 2012 } 2013 if (max_y > 0 && desired_vres > max_y) 2014 { 2015 stp_dprintf(STP_DBG_ESCP2, v, " Decreasing vres from %d to %d\n", 2016 desired_vres, max_y); 2017 desired_vres = max_y; 2018 } 2019 else if (desired_vres < min_y) 2020 { 2021 stp_dprintf(STP_DBG_ESCP2, v, " Increasing vres from %d to %d\n", 2022 desired_vres, min_y); 2023 desired_vres = min_y; 2024 } 2025 for (i = 0; i < resolutions->n_resolutions; i++) 2026 { 2027 res_t *res = &(resolutions->resolutions[i]); 2028 if (verify_resolution(v, res) && 2029 res->printed_vres == desired_vres && 2030 res->printed_hres == desired_hres) 2031 { 2032 stp_dprintf(STP_DBG_ESCP2, v, 2033 " Found desired resolution w/o oversample: %s %d: %d * %d, %d\n", 2034 res->name, i, res->printed_hres, 2035 res->vertical_passes, res->printed_vres); 2036 return res; 2037 } 2038 } 2039 for (i = 0; i < resolutions->n_resolutions; i++) 2040 { 2041 res_t *res = &(resolutions->resolutions[i]); 2042 if (verify_resolution(v, res) && 2043 res->printed_vres == desired_vres && 2044 res->printed_hres * res->vertical_passes == desired_hres) 2045 { 2046 stp_dprintf(STP_DBG_ESCP2, v, 2047 " Found desired resolution: %s %d: %d * %d, %d\n", 2048 res->name, i, res->printed_hres, 2049 res->vertical_passes, res->printed_vres); 2050 return res; 2051 } 2052 } 2053 for (i = 0; i < resolutions->n_resolutions; i++) 2054 { 2055 res_t *res = &(resolutions->resolutions[i]); 2056 if (verify_resolution(v, res) && 2057 (q->min_vres == 0 || res->printed_vres >= q->min_vres) && 2058 (q->max_vres == 0 || res->printed_vres <= q->max_vres) && 2059 (q->min_hres == 0 || 2060 res->printed_hres * res->vertical_passes >=q->min_hres) && 2061 (q->max_hres == 0 || 2062 res->printed_hres * res->vertical_passes <= q->max_hres)) 2063 { 2064 stp_dprintf(STP_DBG_ESCP2, v, 2065 " Found acceptable resolution: %s %d: %d * %d, %d\n", 2066 res->name, i, res->printed_hres, 2067 res->vertical_passes, res->printed_vres); 2068 return res; 2069 } 2070 } 2071 } 2072#if 0 2073 if (!strict) /* Try again to find a match */ 2074 { 2075 for (i = 0; i < resolutions->n_resolutions; i++) 2076 { 2077 res_t *res = &(resolutions->resolutions[i]); 2078 if (verify_resolution(v, res) && 2079 res->printed_vres >= desired_vres && 2080 res->printed_hres * res->vertical_passes >= desired_hres && 2081 res->printed_vres <= 2 * desired_vres && 2082 res->printed_hres * res->vertical_passes <= 2 * desired_hres) 2083 return res; 2084 } 2085 } 2086#endif 2087 return NULL; 2088} 2089 2090static int 2091verify_quality(const stp_vars_t *v, const quality_t *q) 2092{ 2093 unsigned max_x, max_y, min_x, min_y; 2094 get_printer_resolution_bounds(v, &max_x, &max_y, &min_x, &min_y); 2095 if ((q->max_vres == 0 || min_y <= q->max_vres) && 2096 (q->min_vres == 0 || max_y >= q->min_vres) && 2097 (q->max_hres == 0 || min_x <= q->max_hres) && 2098 (q->min_hres == 0 || max_x >= q->min_hres)) 2099 { 2100 stp_dprintf(STP_DBG_ESCP2, v, "Quality %s OK: %d %d %d %d\n", 2101 q->text, q->min_hres, q->min_vres, q->max_hres, q->max_vres); 2102 return 1; 2103 } 2104 else 2105 { 2106 stp_dprintf(STP_DBG_ESCP2, v, "Quality %s not OK: %d %d %d %d\n", 2107 q->text, q->min_hres, q->min_vres, q->max_hres, q->max_vres); 2108 return 0; 2109 } 2110} 2111 2112static const res_t * 2113find_resolution_from_quality(const stp_vars_t *v, const char *quality, 2114 int strict) 2115{ 2116 int i; 2117 const quality_list_t *quals = escp2_quality_list(v); 2118 /* This is a rather gross hack... */ 2119 if (strcmp(quality, "None") == 0) 2120 quality = "Standard"; 2121 for (i = 0; i < quals->n_quals; i++) 2122 { 2123 const quality_t *q = &(quals->qualities[i]); 2124 if (strcmp(quality, q->name) == 0 && verify_quality(v, q)) 2125 return find_default_resolution(v, q, strict); 2126 } 2127 return NULL; 2128} 2129 2130static const inkname_t * 2131get_raw_inktype(const stp_vars_t *v) 2132{ 2133 if (strcmp(stp_get_string_parameter(v, "InputImageType"), "Raw") == 0) 2134 { 2135 const inklist_t *inks = stp_escp2_inklist(v); 2136 int ninktypes = inks->n_inks; 2137 int i; 2138 const char *channel_name = stp_get_string_parameter(v, "RawChannels"); 2139 const channel_count_t *count; 2140 if (!channel_name) 2141 goto none; 2142 count = get_channel_count_by_name(channel_name); 2143 if (!count) 2144 goto none; 2145 for (i = 0; i < ninktypes; i++) 2146 if (inks->inknames[i].inkset == INKSET_EXTENDED && 2147 (inks->inknames[i].channel_count == count->count)) 2148 return &(inks->inknames[i]); 2149 } 2150 none: 2151 return get_inktype(v); 2152} 2153 2154static void 2155escp2_parameters(const stp_vars_t *v, const char *name, 2156 stp_parameter_t *description) 2157{ 2158 int i; 2159 description->p_type = STP_PARAMETER_TYPE_INVALID; 2160 if (name == NULL) 2161 return; 2162 2163 for (i = 0; i < float_parameter_count; i++) 2164 if (strcmp(name, float_parameters[i].param.name) == 0) 2165 { 2166 stp_fill_parameter_settings(description, 2167 &(float_parameters[i].param)); 2168 description->deflt.dbl = float_parameters[i].defval; 2169 description->bounds.dbl.upper = float_parameters[i].max; 2170 description->bounds.dbl.lower = float_parameters[i].min; 2171 break; 2172 } 2173 for (i = 0; i < int_parameter_count; i++) 2174 if (strcmp(name, int_parameters[i].param.name) == 0) 2175 { 2176 stp_fill_parameter_settings(description, 2177 &(int_parameters[i].param)); 2178 description->deflt.integer = int_parameters[i].defval; 2179 description->bounds.integer.upper = int_parameters[i].max; 2180 description->bounds.integer.lower = int_parameters[i].min; 2181 break; 2182 } 2183 2184 for (i = 0; i < the_parameter_count; i++) 2185 if (strcmp(name, the_parameters[i].name) == 0) 2186 { 2187 stp_fill_parameter_settings(description, &(the_parameters[i])); 2188 if (description->p_type == STP_PARAMETER_TYPE_INT) 2189 { 2190 description->deflt.integer = 0; 2191 description->bounds.integer.upper = INT_MAX; 2192 description->bounds.integer.lower = INT_MIN; 2193 } 2194 break; 2195 } 2196 2197 description->deflt.str = NULL; 2198 if (strcmp(name, "AutoMode") == 0) 2199 { 2200 description->bounds.str = stp_string_list_create(); 2201 stp_string_list_add_string(description->bounds.str, "None", 2202 _("Full Manual Control")); 2203 stp_string_list_add_string(description->bounds.str, "Auto", 2204 _("Automatic Setting Control")); 2205 description->deflt.str = "None"; /* so CUPS and Foomatic don't break */ 2206 } 2207 else if (strcmp(name, "PageSize") == 0) 2208 { 2209 int papersizes = stp_known_papersizes(); 2210 const input_slot_t *slot = stp_escp2_get_input_slot(v); 2211 description->bounds.str = stp_string_list_create(); 2212 if (slot && slot->is_cd && 2213 !stp_get_boolean_parameter(v, "CDAllowOtherMedia")) 2214 { 2215 stp_string_list_add_string 2216 (description->bounds.str, "CD5Inch", _("CD - 5 inch")); 2217 stp_string_list_add_string 2218 (description->bounds.str, "CD3Inch", _("CD - 3 inch")); 2219 stp_string_list_add_string 2220 (description->bounds.str, "CDCustom", _("CD - Custom")); 2221 } 2222 else 2223 { 2224 for (i = 0; i < papersizes; i++) 2225 { 2226 const stp_papersize_t *pt = stp_get_papersize_by_index(i); 2227 if (verify_papersize(v, pt)) 2228 stp_string_list_add_string(description->bounds.str, 2229 pt->name, gettext(pt->text)); 2230 } 2231 } 2232 description->deflt.str = 2233 stp_string_list_param(description->bounds.str, 0)->name; 2234 } 2235 else if (strcmp(name, "CDAllowOtherMedia") == 0) 2236 { 2237 const input_slot_t *slot = stp_escp2_get_input_slot(v); 2238 if (stp_escp2_printer_supports_print_to_cd(v) && 2239 (!slot || slot->is_cd)) 2240 description->is_active = 1; 2241 else 2242 description->is_active = 0; 2243 } 2244 else if (strcmp(name, "CDInnerRadius") == 0 ) 2245 { 2246 const input_slot_t *slot = stp_escp2_get_input_slot(v); 2247 description->bounds.str = stp_string_list_create(); 2248 if (stp_escp2_printer_supports_print_to_cd(v) && 2249 (!slot || slot->is_cd) && 2250 (!stp_get_string_parameter(v, "PageSize") || 2251 strcmp(stp_get_string_parameter(v, "PageSize"), "CDCustom") != 0)) 2252 { 2253 stp_string_list_add_string 2254 (description->bounds.str, "None", _("Normal")); 2255 stp_string_list_add_string 2256 (description->bounds.str, "Small", _("Print To Hub")); 2257 description->deflt.str = 2258 stp_string_list_param(description->bounds.str, 0)->name; 2259 } 2260 else 2261 description->is_active = 0; 2262 } 2263 else if (strcmp(name, "CDInnerDiameter") == 0 ) 2264 { 2265 const input_slot_t *slot = stp_escp2_get_input_slot(v); 2266 description->bounds.dimension.lower = 16 * 10 * 72 / 254; 2267 description->bounds.dimension.upper = 43 * 10 * 72 / 254; 2268 description->deflt.dimension = 43 * 10 * 72 / 254; 2269 if (stp_escp2_printer_supports_print_to_cd(v) && 2270 (!slot || slot->is_cd) && 2271 (!stp_get_string_parameter(v, "PageSize") || 2272 strcmp(stp_get_string_parameter(v, "PageSize"), "CDCustom") == 0)) 2273 description->is_active = 1; 2274 else 2275 description->is_active = 0; 2276 } 2277 else if (strcmp(name, "CDOuterDiameter") == 0 ) 2278 { 2279 const input_slot_t *slot = stp_escp2_get_input_slot(v); 2280 description->bounds.dimension.lower = 65 * 10 * 72 / 254; 2281 description->bounds.dimension.upper = 120 * 10 * 72 / 254; 2282 description->deflt.dimension = 329; 2283 if (stp_escp2_printer_supports_print_to_cd(v) && 2284 (!slot || slot->is_cd) && 2285 (!stp_get_string_parameter(v, "PageSize") || 2286 strcmp(stp_get_string_parameter(v, "PageSize"), "CDCustom") == 0)) 2287 description->is_active = 1; 2288 else 2289 description->is_active = 0; 2290 } 2291 else if (strcmp(name, "CDXAdjustment") == 0 || 2292 strcmp(name, "CDYAdjustment") == 0) 2293 { 2294 const input_slot_t *slot = stp_escp2_get_input_slot(v); 2295 description->bounds.dimension.lower = -15; 2296 description->bounds.dimension.upper = 15; 2297 description->deflt.dimension = 0; 2298 if (stp_escp2_printer_supports_print_to_cd(v) && (!slot || slot->is_cd)) 2299 description->is_active = 1; 2300 else 2301 description->is_active = 0; 2302 } 2303 else if (strcmp(name, "Quality") == 0) 2304 { 2305 const quality_list_t *quals = escp2_quality_list(v); 2306 int has_standard_quality = 0; 2307 description->bounds.str = stp_string_list_create(); 2308 stp_string_list_add_string(description->bounds.str, "None", 2309 _("Manual Control")); 2310 for (i = 0; i < quals->n_quals; i++) 2311 { 2312 const quality_t *q = &(quals->qualities[i]); 2313 if (verify_quality(v, q)) 2314 stp_string_list_add_string(description->bounds.str, q->name, 2315 gettext(q->text)); 2316 if (strcmp(q->name, "Standard") == 0) 2317 has_standard_quality = 1; 2318 } 2319 if (has_standard_quality) 2320 description->deflt.str = "Standard"; 2321 else 2322 description->deflt.str = "None"; 2323 } 2324 else if (strcmp(name, "Resolution") == 0) 2325 { 2326 const resolution_list_t *resolutions = escp2_reslist(v); 2327 description->bounds.str = stp_string_list_create(); 2328 stp_string_list_add_string(description->bounds.str, "None", 2329 _("Default")); 2330 description->deflt.str = "None"; 2331 for (i = 0; i < resolutions->n_resolutions; i++) 2332 { 2333 res_t *res = &(resolutions->resolutions[i]); 2334 if (verify_resolution(v, res)) 2335 stp_string_list_add_string(description->bounds.str, 2336 res->name, gettext(res->text)); 2337 } 2338 } 2339 else if (strcmp(name, "InkType") == 0) 2340 { 2341 const inklist_t *inks = stp_escp2_inklist(v); 2342 int ninktypes = inks->n_inks; 2343 int verified_inktypes = 0; 2344 for (i = 0; i < ninktypes; i++) 2345 if (verify_inktype(v, &(inks->inknames[i]))) 2346 verified_inktypes++; 2347 description->bounds.str = stp_string_list_create(); 2348 if (verified_inktypes > 1) 2349 { 2350 stp_string_list_add_string(description->bounds.str, "None", 2351 _("Standard")); 2352 for (i = 0; i < ninktypes; i++) 2353 if (verify_inktype(v, &(inks->inknames[i]))) 2354 stp_string_list_add_string(description->bounds.str, 2355 inks->inknames[i].name, 2356 gettext(inks->inknames[i].text)); 2357 description->deflt.str = "None"; 2358 } 2359 else 2360 description->is_active = 0; 2361 } 2362 else if (strcmp(name, "InkSet") == 0) 2363 { 2364 const inkgroup_t *inks = escp2_inkgroup(v); 2365 int ninklists = inks->n_inklists; 2366 description->bounds.str = stp_string_list_create(); 2367 if (ninklists > 1) 2368 { 2369 int has_default_choice = 0; 2370 for (i = 0; i < ninklists; i++) 2371 { 2372 stp_string_list_add_string(description->bounds.str, 2373 inks->inklists[i].name, 2374 gettext(inks->inklists[i].text)); 2375 if (strcmp(inks->inklists[i].name, "None") == 0) 2376 has_default_choice = 1; 2377 } 2378 description->deflt.str = 2379 stp_string_list_param(description->bounds.str, 0)->name; 2380 } 2381 else 2382 description->is_active = 0; 2383 } 2384 else if (strcmp(name, "MediaType") == 0) 2385 { 2386 const stp_string_list_t *p = escp2_paperlist(v); 2387 description->is_active = 0; 2388 if (p) 2389 { 2390 int nmediatypes = stp_string_list_count(p); 2391 description->bounds.str = stp_string_list_create(); 2392 if (nmediatypes) 2393 { 2394 description->is_active = 1; 2395 for (i = 0; i < nmediatypes; i++) 2396 stp_string_list_add_string(description->bounds.str, 2397 stp_string_list_param(p, i)->name, 2398 gettext(stp_string_list_param(p, i)->text)); 2399 description->deflt.str = 2400 stp_string_list_param(description->bounds.str, 0)->name; 2401 } 2402 } 2403 } 2404 else if (strcmp(name, "InputSlot") == 0) 2405 { 2406 const stp_string_list_t *p = escp2_slotlist(v); 2407 description->is_active = 0; 2408 if (p) 2409 { 2410 int nslots = stp_string_list_count(p); 2411 description->bounds.str = stp_string_list_create(); 2412 if (nslots) 2413 { 2414 description->is_active = 1; 2415 for (i = 0; i < nslots; i++) 2416 stp_string_list_add_string(description->bounds.str, 2417 stp_string_list_param(p, i)->name, 2418 gettext(stp_string_list_param(p, i)->text)); 2419 description->deflt.str = 2420 stp_string_list_param(description->bounds.str, 0)->name; 2421 } 2422 } 2423 } 2424 else if (strcmp(name, "PrintingDirection") == 0) 2425 { 2426 description->bounds.str = stp_string_list_create(); 2427 stp_string_list_add_string 2428 (description->bounds.str, "None", _("Automatic")); 2429 stp_string_list_add_string 2430 (description->bounds.str, "Bidirectional", _("Bidirectional")); 2431 stp_string_list_add_string 2432 (description->bounds.str, "Unidirectional", _("Unidirectional")); 2433 description->deflt.str = 2434 stp_string_list_param(description->bounds.str, 0)->name; 2435 } 2436 else if (strcmp(name, "Weave") == 0) 2437 { 2438 description->bounds.str = stp_string_list_create(); 2439 if (stp_escp2_has_cap(v, MODEL_COMMAND, MODEL_COMMAND_PRO)) 2440 { 2441 const res_t *res = stp_escp2_find_resolution(v); 2442 const printer_weave_list_t *printer_weaves = escp2_printer_weaves(v); 2443 int nprinter_weaves = 0; 2444 if (printer_weaves && use_printer_weave(v) && (!res || res->command)) 2445 nprinter_weaves = printer_weaves->n_printer_weaves; 2446 if (nprinter_weaves) 2447 { 2448 stp_string_list_add_string(description->bounds.str, "None", 2449 _("Standard")); 2450 for (i = 0; i < nprinter_weaves; i++) 2451 stp_string_list_add_string(description->bounds.str, 2452 printer_weaves->printer_weaves[i].name, 2453 gettext(printer_weaves->printer_weaves[i].text)); 2454 } 2455 else 2456 description->is_active = 0; 2457 } 2458 else 2459 { 2460 stp_string_list_add_string 2461 (description->bounds.str, "None", _("Standard")); 2462 stp_string_list_add_string 2463 (description->bounds.str, "Alternate", _("Alternate Fill")); 2464 stp_string_list_add_string 2465 (description->bounds.str, "Ascending", _("Ascending Fill")); 2466 stp_string_list_add_string 2467 (description->bounds.str, "Descending", _("Descending Fill")); 2468 stp_string_list_add_string 2469 (description->bounds.str, "Ascending2X", _("Ascending Double")); 2470 stp_string_list_add_string 2471 (description->bounds.str, "Staggered", _("Nearest Neighbor Avoidance")); 2472 } 2473 if (description->is_active) 2474 description->deflt.str = 2475 stp_string_list_param(description->bounds.str, 0)->name; 2476 } 2477 else if (strcmp(name, "OutputOrder") == 0) 2478 { 2479 description->bounds.str = stp_string_list_create(); 2480 description->deflt.str = "Reverse"; 2481 } 2482 else if (strcmp(name, "FullBleed") == 0) 2483 { 2484 const input_slot_t *slot = stp_escp2_get_input_slot(v); 2485 if (slot && slot->is_cd) 2486 description->is_active = 0; 2487 else if (supports_borderless(v)) 2488 description->deflt.boolean = 0; 2489 else 2490 description->is_active = 0; 2491 } 2492 else if (strcmp(name, "Duplex") == 0) 2493 { 2494 if (stp_escp2_printer_supports_duplex(v)) 2495 { 2496 const input_slot_t *slot = stp_escp2_get_input_slot(v); 2497 if (slot && !slot->duplex) 2498 description->is_active = 0; 2499 else 2500 { 2501 description->bounds.str = stp_string_list_create(); 2502 stp_string_list_add_string 2503 (description->bounds.str, "None", _("Off")); 2504 stp_string_list_add_string 2505 (description->bounds.str, "DuplexNoTumble", _("Long Edge (Standard)")); 2506 stp_string_list_add_string 2507 (description->bounds.str, "DuplexTumble", _("Short Edge(Flip)")); 2508 description->deflt.str = "None"; 2509 } 2510 } 2511 else 2512 description->is_active = 0; 2513 } 2514 else if (strcmp(name, "CyanDensity") == 0 || 2515 strcmp(name, "MagentaDensity") == 0 || 2516 strcmp(name, "YellowDensity") == 0 || 2517 strcmp(name, "BlackDensity") == 0 || 2518 strcmp(name, "RedDensity") == 0 || 2519 strcmp(name, "BlueDensity") == 0 || 2520 strcmp(name, "OrangeDensity") == 0) 2521 set_density_parameter(v, description, name); 2522 else if (strcmp(name, "CyanHueCurve") == 0 || 2523 strcmp(name, "MagentaHueCurve") == 0 || 2524 strcmp(name, "YellowHueCurve") == 0 || 2525 strcmp(name, "RedHueCurve") == 0 || 2526 strcmp(name, "BlueHueCurve") == 0 || 2527 strcmp(name, "OrangeHueCurve") == 0) 2528 set_hue_map_parameter(v, description, name); 2529 else if (strcmp(name, "UseGloss") == 0) 2530 { 2531 const inkname_t *ink_name = get_inktype(v); 2532 if (ink_name && ink_name->aux_channel_count > 0) 2533 description->is_active = 1; 2534 else 2535 description->is_active = 0; 2536 } 2537 else if (strcmp(name, "GlossLimit") == 0) 2538 { 2539 const inkname_t *ink_name = get_inktype(v); 2540 if (ink_name && ink_name->aux_channel_count > 0) 2541 description->is_active = 1; 2542 else 2543 description->is_active = 0; 2544 } 2545 else if (strcmp(name, "DropSize1") == 0 || 2546 strcmp(name, "DropSize2") == 0 || 2547 strcmp(name, "DropSize3") == 0) 2548 { 2549 if (stp_escp2_has_cap(v, MODEL_VARIABLE_DOT, MODEL_VARIABLE_YES)) 2550 { 2551 const res_t *res = stp_escp2_find_resolution(v); 2552 if (res && res->v && 2553 stp_check_float_parameter(v, name, STP_PARAMETER_ACTIVE)) 2554 description->deflt.dbl = stp_get_float_parameter(v, name); 2555 description->is_active = 1; 2556 } 2557 else 2558 description->is_active = 0; 2559 } 2560 else if (strcmp(name, "BlackTrans") == 0 || 2561 strcmp(name, "GCRLower") == 0 || 2562 strcmp(name, "GCRUpper") == 0) 2563 { 2564 const stp_vars_t *paper_adj = get_media_adjustment(v); 2565 if (paper_adj && 2566 stp_get_string_parameter(v, "PrintingMode") && 2567 strcmp(stp_get_string_parameter(v, "PrintingMode"), "BW") != 0) 2568 { 2569 if (paper_adj && stp_check_float_parameter(paper_adj, name, STP_PARAMETER_ACTIVE)) 2570 description->deflt.dbl = stp_get_float_parameter(paper_adj, name); 2571 else 2572 description->p_type = STP_PARAMETER_TYPE_INVALID; 2573 } 2574 else 2575 description->p_type = STP_PARAMETER_TYPE_INVALID; 2576 } 2577 else if (strcmp(name, "GrayValue") == 0) 2578 set_gray_value_parameter(v, description, 2); 2579 else if (strcmp(name, "DarkGrayValue") == 0 || 2580 strcmp(name, "LightGrayValue") == 0) 2581 set_gray_value_parameter(v, description, 3); 2582 else if (strcmp(name, "Gray1Value") == 0 || 2583 strcmp(name, "Gray2Value") == 0 || 2584 strcmp(name, "Gray3Value") == 0) 2585 set_gray_value_parameter(v, description, 4); 2586 else if (strcmp(name, "LightCyanValue") == 0) 2587 set_color_value_parameter(v, description, STP_ECOLOR_C); 2588 else if (strcmp(name, "LightMagentaValue") == 0) 2589 set_color_value_parameter(v, description, STP_ECOLOR_M); 2590 else if (strcmp(name, "DarkYellowValue") == 0) 2591 set_color_value_parameter(v, description, STP_ECOLOR_Y); 2592 else if (strcmp(name, "GrayTrans") == 0) 2593 set_gray_transition_parameter(v, description, 2); 2594 else if (strcmp(name, "DarkGrayTrans") == 0 || 2595 strcmp(name, "LightGrayTrans") == 0) 2596 set_gray_transition_parameter(v, description, 3); 2597 else if (strcmp(name, "Gray1Trans") == 0 || 2598 strcmp(name, "Gray2Trans") == 0 || 2599 strcmp(name, "Gray3Trans") == 0) 2600 set_gray_transition_parameter(v, description, 4); 2601 else if (strcmp(name, "LightCyanTrans") == 0) 2602 set_color_transition_parameter(v, description, STP_ECOLOR_C); 2603 else if (strcmp(name, "LightMagentaTrans") == 0) 2604 set_color_transition_parameter(v, description, STP_ECOLOR_M); 2605 else if (strcmp(name, "DarkYellowTrans") == 0) 2606 set_color_transition_parameter(v, description, STP_ECOLOR_Y); 2607 else if (strcmp(name, "GrayScale") == 0) 2608 set_gray_scale_parameter(v, description, 2); 2609 else if (strcmp(name, "DarkGrayScale") == 0 || 2610 strcmp(name, "LightGrayScale") == 0) 2611 set_gray_scale_parameter(v, description, 3); 2612 else if (strcmp(name, "Gray1Scale") == 0 || 2613 strcmp(name, "Gray2Scale") == 0 || 2614 strcmp(name, "Gray3Scale") == 0) 2615 set_gray_scale_parameter(v, description, 4); 2616 else if (strcmp(name, "LightCyanScale") == 0) 2617 set_color_scale_parameter(v, description, STP_ECOLOR_C); 2618 else if (strcmp(name, "LightMagentaScale") == 0) 2619 set_color_scale_parameter(v, description, STP_ECOLOR_M); 2620 else if (strcmp(name, "DarkYellowScale") == 0) 2621 set_color_scale_parameter(v, description, STP_ECOLOR_Y); 2622 else if (strcmp(name, "AlignmentPasses") == 0) 2623 { 2624 description->deflt.integer = escp2_alignment_passes(v); 2625 } 2626 else if (strcmp(name, "AlignmentChoices") == 0) 2627 { 2628 description->deflt.integer = escp2_alignment_choices(v); 2629 } 2630 else if (strcmp(name, "SupportsInkChange") == 0) 2631 { 2632 description->deflt.integer = 2633 stp_escp2_has_cap(v, MODEL_SUPPORTS_INK_CHANGE, 2634 MODEL_SUPPORTS_INK_CHANGE_YES); 2635 } 2636 else if (strcmp(name, "AlternateAlignmentPasses") == 0) 2637 { 2638 description->deflt.integer = escp2_alternate_alignment_passes(v); 2639 } 2640 else if (strcmp(name, "AlternateAlignmentChoices") == 0) 2641 { 2642 description->deflt.integer = escp2_alternate_alignment_choices(v); 2643 } 2644 else if (strcmp(name, "InkChannels") == 0) 2645 { 2646 description->deflt.integer = escp2_physical_channels(v); 2647 } 2648 else if (strcmp(name, "ChannelNames") == 0) 2649 { 2650 const stp_string_list_t *channel_names = escp2_channel_names(v); 2651 if (channel_names) 2652 { 2653 description->bounds.str = stp_string_list_create_copy(channel_names); 2654 description->deflt.str = 2655 stp_string_list_param(description->bounds.str, 0)->name; 2656 } 2657 else 2658 description->p_type = STP_PARAMETER_TYPE_INVALID; 2659 } 2660 else if (strcmp(name, "SupportsPacketMode") == 0) 2661 { 2662 description->deflt.boolean = 2663 stp_escp2_has_cap(v, MODEL_PACKET_MODE, MODEL_PACKET_MODE_YES); 2664 } 2665 else if (strcmp(name, "PrintingMode") == 0) 2666 { 2667 description->bounds.str = stp_string_list_create(); 2668 stp_string_list_add_string 2669 (description->bounds.str, "Color", _("Color")); 2670 stp_string_list_add_string 2671 (description->bounds.str, "BW", _("Black and White")); 2672 description->deflt.str = 2673 stp_string_list_param(description->bounds.str, 0)->name; 2674 } 2675 else if (strcmp(name, "RawChannels") == 0) 2676 { 2677 const inklist_t *inks = stp_escp2_inklist(v); 2678 int ninktypes = inks->n_inks; 2679 description->bounds.str = stp_string_list_create(); 2680 if (ninktypes >= 1) 2681 { 2682 stp_string_list_add_string(description->bounds.str, "None", "None"); 2683 for (i = 0; i < ninktypes; i++) 2684 if (inks->inknames[i].inkset == INKSET_EXTENDED) 2685 { 2686 const channel_count_t *ch = 2687 (get_channel_count_by_number 2688 (inks->inknames[i].channel_count)); 2689 stp_string_list_add_string(description->bounds.str, 2690 ch->name, ch->name); 2691 } 2692 description->deflt.str = 2693 stp_string_list_param(description->bounds.str, 0)->name; 2694 } 2695 else 2696 description->is_active = 0; 2697 } 2698 else if (strcmp(name, "RawChannelNames") == 0) 2699 { 2700 const inkname_t *ink_name = get_raw_inktype(v); 2701 if (ink_name) 2702 { 2703 description->bounds.str = stp_string_list_create(); 2704 for (i = 0; i < ink_name->channel_count; i++) 2705 { 2706 int j; 2707 const ink_channel_t *ic = &(ink_name->channels[i]); 2708 if (ic) 2709 for (j = 0; j < ic->n_subchannels; j++) 2710 if (ic->subchannels[j].name) 2711 stp_string_list_add_string(description->bounds.str, 2712 ic->subchannels[j].name, 2713 gettext(ic->subchannels[j].text)); 2714 } 2715 for (i = 0; i < ink_name->aux_channel_count; i++) 2716 { 2717 int j; 2718 const ink_channel_t *ic = &(ink_name->aux_channels[i]); 2719 if (ic) 2720 for (j = 0; j < ic->n_subchannels; j++) 2721 if (ic->subchannels[j].name) 2722 stp_string_list_add_string(description->bounds.str, 2723 ic->subchannels[j].name, 2724 gettext(ic->subchannels[j].text)); 2725 } 2726 description->deflt.str = 2727 stp_string_list_param(description->bounds.str, 0)->name; 2728 } 2729 } 2730 else if (strcmp(name, "MultiChannelLimit") == 0) 2731 { 2732 description->is_active = 0; 2733 if (stp_get_string_parameter(v, "PrintingMode") && 2734 strcmp(stp_get_string_parameter(v, "PrintingMode"), "BW") != 0) 2735 { 2736 const inkname_t *ink_name = get_inktype(v); 2737 if (ink_name && ink_name->inkset == INKSET_OTHER) 2738 description->is_active = 1; 2739 } 2740 } 2741 else if (strcmp(name, "PageDryTime") == 0 || 2742 strcmp(name, "ScanDryTime") == 0 || 2743 strcmp(name, "ScanMinDryTime") == 0 || 2744 strcmp(name, "FeedAdjustment") == 0 || 2745 strcmp(name, "PaperThickness") == 0 || 2746 strcmp(name, "VacuumIntensity") == 0 || 2747 strcmp(name, "FeedSequence") == 0 || 2748 strcmp(name, "PrintMethod") == 0 || 2749 strcmp(name, "PaperMedia") == 0 || 2750 strcmp(name, "PaperMediaSize") == 0 || 2751 strcmp(name, "PlatenGap") == 0) 2752 { 2753 description->is_active = 0; 2754 if (stp_escp2_has_media_feature(v, name)) 2755 description->is_active = 1; 2756 } 2757 else if (strcmp(name, "BandEnhancement") == 0) 2758 { 2759 description->is_active = 1; 2760 } 2761} 2762 2763const res_t * 2764stp_escp2_find_resolution(const stp_vars_t *v) 2765{ 2766 const char *resolution = stp_get_string_parameter(v, "Resolution"); 2767 if (resolution) 2768 { 2769 const resolution_list_t *resolutions = escp2_reslist(v); 2770 int i; 2771 for (i = 0; i < resolutions->n_resolutions; i++) 2772 { 2773 const res_t *res = &(resolutions->resolutions[i]); 2774 if (!strcmp(resolution, res->name)) 2775 return res; 2776 else if (!strcmp(res->name, "")) 2777 return NULL; 2778 } 2779 } 2780 if (stp_check_string_parameter(v, "Quality", STP_PARAMETER_ACTIVE)) 2781 { 2782 const res_t *default_res = 2783 find_resolution_from_quality(v, stp_get_string_parameter(v, "Quality"), 2784 0); 2785 if (default_res) 2786 { 2787 stp_dprintf(STP_DBG_ESCP2, v, 2788 "Setting resolution to %s from quality %s\n", 2789 default_res->name, 2790 stp_get_string_parameter(v, "Quality")); 2791 return default_res; 2792 } 2793 else 2794 stp_dprintf(STP_DBG_ESCP2, v, "Unable to map quality %s\n", 2795 stp_get_string_parameter(v, "Quality")); 2796 } 2797 return NULL; 2798} 2799 2800static inline int 2801imax(int a, int b) 2802{ 2803 if (a > b) 2804 return a; 2805 else 2806 return b; 2807} 2808 2809static void 2810escp2_media_size(const stp_vars_t *v, /* I */ 2811 int *width, /* O - Width in points */ 2812 int *height) /* O - Height in points */ 2813{ 2814 if (stp_get_page_width(v) > 0 && stp_get_page_height(v) > 0) 2815 { 2816 *width = stp_get_page_width(v); 2817 *height = stp_get_page_height(v); 2818 } 2819 else 2820 { 2821 const char *page_size = stp_get_string_parameter(v, "PageSize"); 2822 const stp_papersize_t *papersize = NULL; 2823 if (page_size) 2824 papersize = stp_get_papersize_by_name(page_size); 2825 if (!papersize) 2826 { 2827 *width = 1; 2828 *height = 1; 2829 } 2830 else 2831 { 2832 *width = papersize->width; 2833 *height = papersize->height; 2834 } 2835 if (*width == 0 || *height == 0) 2836 { 2837 const input_slot_t *slot = stp_escp2_get_input_slot(v); 2838 if (slot && slot->is_cd) 2839 { 2840 papersize = stp_get_papersize_by_name("CDCustom"); 2841 if (papersize) 2842 { 2843 if (*width == 0) 2844 *width = papersize->width; 2845 if (*height == 0) 2846 *height = papersize->height; 2847 } 2848 } 2849 else 2850 { 2851 int papersizes = stp_known_papersizes(); 2852 int i; 2853 for (i = 0; i < papersizes; i++) 2854 { 2855 papersize = stp_get_papersize_by_index(i); 2856 if (verify_papersize(v, papersize)) 2857 { 2858 if (*width == 0) 2859 *width = papersize->width; 2860 if (*height == 0) 2861 *height = papersize->height; 2862 break; 2863 } 2864 } 2865 } 2866 } 2867 if (*width == 0) 2868 *width = 612; 2869 if (*height == 0) 2870 *height = 792; 2871 } 2872} 2873 2874static void 2875internal_imageable_area(const stp_vars_t *v, int use_paper_margins, 2876 int use_maximum_area, 2877 int *left, int *right, int *bottom, int *top) 2878{ 2879 int width, height; /* Size of page */ 2880 int rollfeed = 0; /* Roll feed selected */ 2881 int cd = 0; /* CD selected */ 2882 const char *media_size = stp_get_string_parameter(v, "PageSize"); 2883 const char *duplex = stp_get_string_parameter(v, "Duplex"); 2884 int left_margin = 0; 2885 int right_margin = 0; 2886 int bottom_margin = 0; 2887 int top_margin = 0; 2888 const stp_papersize_t *pt = NULL; 2889 const input_slot_t *input_slot = NULL; 2890 2891 if (media_size) 2892 pt = stp_get_papersize_by_name(media_size); 2893 2894 input_slot = stp_escp2_get_input_slot(v); 2895 if (input_slot) 2896 { 2897 cd = input_slot->is_cd; 2898 rollfeed = input_slot->is_roll_feed; 2899 } 2900 2901 escp2_media_size(v, &width, &height); 2902 if (cd) 2903 { 2904 if (pt) 2905 { 2906 left_margin = pt->left; 2907 right_margin = pt->right; 2908 bottom_margin = pt->bottom; 2909 top_margin = pt->top; 2910 } 2911 else 2912 { 2913 left_margin = 0; 2914 right_margin = 0; 2915 bottom_margin = 0; 2916 top_margin = 0; 2917 } 2918 } 2919 else 2920 { 2921 if (pt && use_paper_margins) 2922 { 2923 left_margin = pt->left; 2924 right_margin = pt->right; 2925 bottom_margin = pt->bottom; 2926 top_margin = pt->top; 2927 } 2928 2929 left_margin = imax(left_margin, escp2_left_margin(v, rollfeed)); 2930 right_margin = imax(right_margin, escp2_right_margin(v, rollfeed)); 2931 bottom_margin = imax(bottom_margin, escp2_bottom_margin(v, rollfeed)); 2932 top_margin = imax(top_margin, escp2_top_margin(v, rollfeed)); 2933 } 2934 if (supports_borderless(v) && 2935 (use_maximum_area || 2936 (!cd && stp_get_boolean_parameter(v, "FullBleed")))) 2937 { 2938 if (pt) 2939 { 2940 if (pt->left <= 0 && pt->right <= 0 && pt->top <= 0 && 2941 pt->bottom <= 0) 2942 { 2943 if (use_paper_margins) 2944 { 2945 unsigned width_limit = escp2_max_paper_width(v); 2946 int offset = escp2_zero_margin_offset(v); 2947 int margin = escp2_micro_left_margin(v); 2948 int sep = escp2_base_separation(v); 2949 int delta = -((offset - margin) * 72 / sep); 2950 left_margin = delta; /* Allow some overlap if paper isn't */ 2951 right_margin = delta; /* positioned correctly */ 2952 if (width - right_margin - 3 > width_limit) 2953 right_margin = width - width_limit - 3; 2954 if (! stp_escp2_has_cap(v, MODEL_ZEROMARGIN, 2955 MODEL_ZEROMARGIN_H_ONLY)) 2956 { 2957 top_margin = -7; 2958 bottom_margin = -7; 2959 } 2960 } 2961 else 2962 { 2963 left_margin = 0; 2964 right_margin = 0; 2965 if (! stp_escp2_has_cap(v, MODEL_ZEROMARGIN, 2966 MODEL_ZEROMARGIN_H_ONLY)) 2967 { 2968 top_margin = 0; 2969 bottom_margin = 0; 2970 } 2971 } 2972 } 2973 } 2974 } 2975 if (!use_maximum_area && duplex && strcmp(duplex, "None") != 0) 2976 { 2977 left_margin = imax(left_margin, escp2_duplex_left_margin(v)); 2978 right_margin = imax(right_margin, escp2_duplex_right_margin(v)); 2979 bottom_margin = imax(bottom_margin, escp2_duplex_bottom_margin(v)); 2980 top_margin = imax(top_margin, escp2_duplex_top_margin(v)); 2981 } 2982 2983 if (width > escp2_max_imageable_width(v)) 2984 width = escp2_max_imageable_width(v); 2985 if (height > escp2_max_imageable_height(v)) 2986 height = escp2_max_imageable_height(v); 2987 *left = left_margin; 2988 *right = width - right_margin; 2989 *top = top_margin; 2990 *bottom = height - bottom_margin; 2991} 2992 2993/* 2994 * 'escp2_imageable_area()' - Return the imageable area of the page. 2995 */ 2996 2997static void 2998escp2_imageable_area(const stp_vars_t *v, /* I */ 2999 int *left, /* O - Left position in points */ 3000 int *right, /* O - Right position in points */ 3001 int *bottom, /* O - Bottom position in points */ 3002 int *top) /* O - Top position in points */ 3003{ 3004 internal_imageable_area(v, 1, 0, left, right, bottom, top); 3005} 3006 3007static void 3008escp2_maximum_imageable_area(const stp_vars_t *v, /* I */ 3009 int *left, /* O - Left position in points */ 3010 int *right, /* O - Right position in points */ 3011 int *bottom, /* O - Bottom position in points */ 3012 int *top) /* O - Top position in points */ 3013{ 3014 internal_imageable_area(v, 1, 1, left, right, bottom, top); 3015} 3016 3017static void 3018escp2_limit(const stp_vars_t *v, /* I */ 3019 int *width, int *height, 3020 int *min_width, int *min_height) 3021{ 3022 *width = escp2_max_paper_width(v); 3023 *height = escp2_max_paper_height(v); 3024 *min_width = escp2_min_paper_width(v); 3025 *min_height = escp2_min_paper_height(v); 3026} 3027 3028static void 3029escp2_describe_resolution(const stp_vars_t *v, int *x, int *y) 3030{ 3031 const res_t *res = stp_escp2_find_resolution(v); 3032 if (res && verify_resolution(v, res)) 3033 { 3034 *x = res->printed_hres; 3035 *y = res->printed_vres; 3036 return; 3037 } 3038 *x = -1; 3039 *y = -1; 3040} 3041 3042static const char * 3043escp2_describe_output(const stp_vars_t *v) 3044{ 3045 const char *printing_mode = stp_get_string_parameter(v, "PrintingMode"); 3046 const char *input_image_type = stp_get_string_parameter(v, "InputImageType"); 3047 if (input_image_type && strcmp(input_image_type, "Raw") == 0) 3048 return "Raw"; 3049 else if (printing_mode && strcmp(printing_mode, "BW") == 0) 3050 return "Grayscale"; 3051 else 3052 { 3053 const inkname_t *ink_type = get_inktype(v); 3054 if (ink_type) 3055 { 3056 switch (ink_type->inkset) 3057 { 3058 case INKSET_QUADTONE: 3059 case INKSET_HEXTONE: 3060 return "Grayscale"; 3061 case INKSET_OTHER: 3062 case INKSET_CMYK: 3063 case INKSET_CcMmYK: 3064 case INKSET_CcMmYyK: 3065 case INKSET_CcMmYKk: 3066 default: 3067 if (ink_type->channels[0].n_subchannels > 0) 3068 return "KCMY"; 3069 else 3070 return "CMY"; 3071 break; 3072 } 3073 } 3074 else 3075 return "CMYK"; 3076 } 3077} 3078 3079static int 3080escp2_has_advanced_command_set(const stp_vars_t *v) 3081{ 3082 return (stp_escp2_has_cap(v, MODEL_COMMAND, MODEL_COMMAND_PRO) || 3083 stp_escp2_has_cap(v, MODEL_COMMAND, MODEL_COMMAND_1999) || 3084 stp_escp2_has_cap(v, MODEL_COMMAND, MODEL_COMMAND_2000)); 3085} 3086 3087static int 3088escp2_use_extended_commands(const stp_vars_t *v, int use_softweave) 3089{ 3090 return (stp_escp2_has_cap(v, MODEL_COMMAND, MODEL_COMMAND_PRO) || 3091 (stp_escp2_has_cap(v, MODEL_VARIABLE_DOT, MODEL_VARIABLE_YES) && 3092 use_softweave)); 3093} 3094 3095static int 3096set_raw_ink_type(stp_vars_t *v) 3097{ 3098 const inklist_t *inks = stp_escp2_inklist(v); 3099 int ninktypes = inks->n_inks; 3100 int i; 3101 const char *channel_name = stp_get_string_parameter(v, "RawChannels"); 3102 const channel_count_t *count; 3103 if (!channel_name) 3104 return 0; 3105 count = get_channel_count_by_name(channel_name); 3106 if (!count) 3107 return 0; 3108 3109 /* 3110 * If we're using raw printer output, we dummy up the appropriate inkset. 3111 */ 3112 for (i = 0; i < ninktypes; i++) 3113 if (inks->inknames[i].inkset == INKSET_EXTENDED && 3114 (inks->inknames[i].channel_count == count->count)) 3115 { 3116 stp_dprintf(STP_DBG_INK, v, "Changing ink type from %s to %s\n", 3117 stp_get_string_parameter(v, "InkType") ? 3118 stp_get_string_parameter(v, "InkType") : "NULL", 3119 inks->inknames[i].name); 3120 stp_set_string_parameter(v, "InkType", inks->inknames[i].name); 3121 stp_set_int_parameter(v, "STPIRawChannels", count->count); 3122 return 1; 3123 } 3124 stp_eprintf 3125 (v, _("This printer does not support raw printer output at depth %d\n"), 3126 count->count); 3127 return 0; 3128} 3129 3130static void 3131adjust_density_and_ink_type(stp_vars_t *v) 3132{ 3133 escp2_privdata_t *pd = get_privdata(v); 3134 const stp_vars_t *pv = pd->paper_type->v; 3135 double paper_density = .8; 3136 3137 if (pv && stp_check_float_parameter(pv, "Density", STP_PARAMETER_ACTIVE)) 3138 paper_density = stp_get_float_parameter(pv, "Density"); 3139 3140 if (!stp_check_float_parameter(v, "Density", STP_PARAMETER_DEFAULTED)) 3141 { 3142 stp_set_float_parameter_active(v, "Density", STP_PARAMETER_ACTIVE); 3143 stp_set_float_parameter(v, "Density", 1.0); 3144 } 3145 stp_scale_float_parameter(v, "Density", paper_density * escp2_density(v)); 3146 pd->drop_size = escp2_ink_type(v); 3147 3148 if (stp_get_float_parameter(v, "Density") > 1.0) 3149 stp_set_float_parameter(v, "Density", 1.0); 3150} 3151 3152static void 3153adjust_print_quality(stp_vars_t *v) 3154{ 3155 escp2_privdata_t *pd = get_privdata(v); 3156 const stp_vars_t *pv = pd->paper_type->v; 3157 double k_upper = 1.0; 3158 double k_lower = 0; 3159 double k_transition = 1.0; 3160 3161 /* 3162 * Compute the LUT. For now, it's 8 bit, but that may eventually 3163 * sometimes change. 3164 */ 3165 3166 if (pv) 3167 { 3168 int i; 3169 stp_string_list_t *slist; 3170 stp_set_default_float_parameter(v, "BlackDensity", 1.0); 3171 stp_set_default_float_parameter(v, "Saturation", 1.0); 3172 stp_set_default_float_parameter(v, "Gamma", 1.0); 3173 slist = stp_list_parameters(pv, STP_PARAMETER_TYPE_STRING_LIST); 3174 if (slist) 3175 { 3176 int len = stp_string_list_count(slist); 3177 for (i = 0; i < len; i++) 3178 { 3179 const char *name = stp_string_list_param(slist, i)->name; 3180 if (!stp_check_string_parameter(v, name, STP_PARAMETER_ACTIVE)) 3181 stp_set_string_parameter(v, name, 3182 stp_get_string_parameter(pv, name)); 3183 } 3184 stp_string_list_destroy(slist); 3185 } 3186 slist = stp_list_parameters(pv, STP_PARAMETER_TYPE_FILE); 3187 if (slist) 3188 { 3189 int len = stp_string_list_count(slist); 3190 for (i = 0; i < len; i++) 3191 { 3192 const char *name = stp_string_list_param(slist, i)->name; 3193 if (!stp_check_file_parameter(v, name, STP_PARAMETER_ACTIVE)) 3194 stp_set_file_parameter(v, name, 3195 stp_get_file_parameter(pv, name)); 3196 } 3197 stp_string_list_destroy(slist); 3198 } 3199 slist = stp_list_parameters(pv, STP_PARAMETER_TYPE_INT); 3200 if (slist) 3201 { 3202 int len = stp_string_list_count(slist); 3203 for (i = 0; i < len; i++) 3204 { 3205 const char *name = stp_string_list_param(slist, i)->name; 3206 if (!stp_check_int_parameter(v, name, STP_PARAMETER_ACTIVE)) 3207 stp_set_int_parameter(v, name, 3208 stp_get_int_parameter(pv, name)); 3209 } 3210 stp_string_list_destroy(slist); 3211 } 3212 slist = stp_list_parameters(pv, STP_PARAMETER_TYPE_DIMENSION); 3213 if (slist) 3214 { 3215 int len = stp_string_list_count(slist); 3216 for (i = 0; i < len; i++) 3217 { 3218 const char *name = stp_string_list_param(slist, i)->name; 3219 if (!stp_check_dimension_parameter(v, name, STP_PARAMETER_ACTIVE)) 3220 stp_set_dimension_parameter(v, name, 3221 stp_get_dimension_parameter(pv, name)); 3222 } 3223 stp_string_list_destroy(slist); 3224 } 3225 slist = stp_list_parameters(pv, STP_PARAMETER_TYPE_BOOLEAN); 3226 if (slist) 3227 { 3228 int len = stp_string_list_count(slist); 3229 for (i = 0; i < len; i++) 3230 { 3231 const char *name = stp_string_list_param(slist, i)->name; 3232 if (!stp_check_boolean_parameter(v, name, STP_PARAMETER_ACTIVE)) 3233 stp_set_boolean_parameter(v, name, 3234 stp_get_boolean_parameter(pv, name)); 3235 } 3236 stp_string_list_destroy(slist); 3237 } 3238 slist = stp_list_parameters(pv, STP_PARAMETER_TYPE_CURVE); 3239 if (slist) 3240 { 3241 int len = stp_string_list_count(slist); 3242 for (i = 0; i < len; i++) 3243 { 3244 const char *name = stp_string_list_param(slist, i)->name; 3245 if (!stp_check_curve_parameter(v, name, STP_PARAMETER_ACTIVE)) 3246 stp_set_curve_parameter(v, name, 3247 stp_get_curve_parameter(pv, name)); 3248 } 3249 stp_string_list_destroy(slist); 3250 } 3251 slist = stp_list_parameters(pv, STP_PARAMETER_TYPE_ARRAY); 3252 if (slist) 3253 { 3254 int len = stp_string_list_count(slist); 3255 for (i = 0; i < len; i++) 3256 { 3257 const char *name = stp_string_list_param(slist, i)->name; 3258 if (!stp_check_array_parameter(v, name, STP_PARAMETER_ACTIVE)) 3259 stp_set_array_parameter(v, name, 3260 stp_get_array_parameter(pv, name)); 3261 } 3262 stp_string_list_destroy(slist); 3263 } 3264 slist = stp_list_parameters(pv, STP_PARAMETER_TYPE_RAW); 3265 if (slist) 3266 { 3267 int len = stp_string_list_count(slist); 3268 for (i = 0; i < len; i++) 3269 { 3270 const char *name = stp_string_list_param(slist, i)->name; 3271 if (!stp_check_raw_parameter(v, name, STP_PARAMETER_ACTIVE)) 3272 { 3273 const stp_raw_t *r = stp_get_raw_parameter(pv, name); 3274 stp_set_raw_parameter(v, name, r->data, r->bytes); 3275 } 3276 } 3277 stp_string_list_destroy(slist); 3278 } 3279 slist = stp_list_parameters(pv, STP_PARAMETER_TYPE_DOUBLE); 3280 if (slist) 3281 { 3282 int len = stp_string_list_count(slist); 3283 for (i = 0; i < len; i++) 3284 { 3285 const char *name = stp_string_list_param(slist, i)->name; 3286 if (strcmp(name, "BlackDensity") == 0 || 3287 strcmp(name, "Saturation") == 0 || 3288 strcmp(name, "Gamma") == 0) 3289 stp_scale_float_parameter(v, name, 3290 stp_get_float_parameter(pv, name)); 3291 else if (strcmp(name, "GCRLower") == 0) 3292 k_lower = stp_get_float_parameter(pv, "GCRLower"); 3293 else if (strcmp(name, "GCRUpper") == 0) 3294 k_upper = stp_get_float_parameter(pv, "GCRUpper"); 3295 else if (strcmp(name, "BlackTrans") == 0) 3296 k_transition = stp_get_float_parameter(pv, "BlackTrans"); 3297 else if (!stp_check_float_parameter(v, name, STP_PARAMETER_ACTIVE)) 3298 stp_set_float_parameter(v, name, 3299 stp_get_float_parameter(pv, name)); 3300 } 3301 stp_string_list_destroy(slist); 3302 } 3303 } 3304 3305 if (!stp_check_float_parameter(v, "GCRLower", STP_PARAMETER_ACTIVE)) 3306 stp_set_default_float_parameter(v, "GCRLower", k_lower); 3307 if (!stp_check_float_parameter(v, "GCRUpper", STP_PARAMETER_ACTIVE)) 3308 stp_set_default_float_parameter(v, "GCRUpper", k_upper); 3309 if (!stp_check_float_parameter(v, "BlackTrans", STP_PARAMETER_ACTIVE)) 3310 stp_set_default_float_parameter(v, "BlackTrans", k_transition); 3311 3312 3313} 3314 3315static int 3316count_channels(const inkname_t *inks, int use_aux_channels) 3317{ 3318 int answer = 0; 3319 int i; 3320 for (i = 0; i < inks->channel_count; i++) 3321 if (inks->channels[i].n_subchannels > 0) 3322 answer += inks->channels[i].n_subchannels; 3323 if (use_aux_channels) 3324 for (i = 0; i < inks->aux_channel_count; i++) 3325 if (inks->aux_channels[i].n_subchannels > 0) 3326 answer += inks->aux_channels[i].n_subchannels; 3327 return answer; 3328} 3329 3330static int 3331compute_channel_count(const inkname_t *ink_type, int channel_limit, 3332 int use_aux_channels) 3333{ 3334 int i; 3335 int physical_channels = 0; 3336 for (i = 0; i < channel_limit; i++) 3337 { 3338 const ink_channel_t *channel = &(ink_type->channels[i]); 3339 if (channel) 3340 physical_channels += channel->n_subchannels; 3341 } 3342 if (use_aux_channels) 3343 for (i = 0; i < ink_type->aux_channel_count; i++) 3344 if (ink_type->aux_channels[i].n_subchannels > 0) 3345 physical_channels += ink_type->aux_channels[i].n_subchannels; 3346 return physical_channels; 3347} 3348 3349static double 3350get_double_param(const stp_vars_t *v, const char *param) 3351{ 3352 if (param && stp_check_float_parameter(v, param, STP_PARAMETER_ACTIVE)) 3353 return stp_get_float_parameter(v, param); 3354 else 3355 return 1.0; 3356} 3357 3358static void 3359setup_inks(stp_vars_t *v) 3360{ 3361 escp2_privdata_t *pd = get_privdata(v); 3362 int i, j; 3363 escp2_dropsize_t *drops; 3364 const inkname_t *ink_type = pd->inkname; 3365 const stp_vars_t *pv = pd->paper_type->v; 3366 int gloss_channel = -1; 3367 double gloss_scale = get_double_param(v, "Density"); 3368 3369 drops = escp2_copy_dropsizes(v); 3370 stp_init_debug_messages(v); 3371 if (stp_check_float_parameter(v, "DropSize1", STP_PARAMETER_ACTIVE)) 3372 { 3373 drops->dropsizes[0] = stp_get_float_parameter(v, "DropSize1"); 3374 if (drops->dropsizes[0] > 0 && drops->numdropsizes < 1) 3375 drops->numdropsizes = 1; 3376 } 3377 if (stp_check_float_parameter(v, "DropSize2", STP_PARAMETER_ACTIVE)) 3378 { 3379 drops->dropsizes[1] = stp_get_float_parameter(v, "DropSize2"); 3380 if (drops->dropsizes[1] > 0 && drops->numdropsizes < 2) 3381 drops->numdropsizes = 2; 3382 } 3383 if (stp_check_float_parameter(v, "DropSize3", STP_PARAMETER_ACTIVE)) 3384 { 3385 drops->dropsizes[2] = stp_get_float_parameter(v, "DropSize3"); 3386 if (drops->dropsizes[2] > 0 && drops->numdropsizes < 3) 3387 drops->numdropsizes = 3; 3388 } 3389 for (i = drops->numdropsizes - 1; i >= 0; i--) 3390 { 3391 if (drops->dropsizes[i] > 0) 3392 break; 3393 drops->numdropsizes--; 3394 } 3395 for (i = 0; i < pd->logical_channels; i++) 3396 { 3397 const ink_channel_t *channel = &(ink_type->channels[i]); 3398 if (channel && channel->n_subchannels > 0) 3399 { 3400 int hue_curve_found = 0; 3401 const char *param = channel->subchannels[0].channel_density; 3402 shade_t *shades = escp2_copy_shades(v, i); 3403 double userval = get_double_param(v, param); 3404 STPI_ASSERT(shades->n_shades >= channel->n_subchannels, v); 3405 if (ink_type->inkset != INKSET_EXTENDED) 3406 { 3407 if (strcmp(param, "BlackDensity") == 0) 3408 stp_channel_set_black_channel(v, i); 3409 else if (strcmp(param, "GlossDensity") == 0) 3410 { 3411 gloss_scale *= get_double_param(v, param); 3412 gloss_channel = i; 3413 } 3414 } 3415 for (j = 0; j < channel->n_subchannels; j++) 3416 { 3417 const char *subparam = 3418 channel->subchannels[j].subchannel_value; 3419 if (subparam && 3420 stp_check_float_parameter(v, subparam, STP_PARAMETER_ACTIVE)) 3421 shades->shades[j] = stp_get_float_parameter(v, subparam); 3422 } 3423 stp_dither_set_inks(v, i, 1.0, ink_darknesses[i % 8], 3424 channel->n_subchannels, shades->shades, 3425 drops->numdropsizes, drops->dropsizes); 3426 for (j = 0; j < channel->n_subchannels; j++) 3427 { 3428 const char *subparam = 3429 channel->subchannels[j].subchannel_scale; 3430 double scale = userval * get_double_param(v, subparam); 3431 scale *= get_double_param(v, "Density"); 3432 stp_channel_set_density_adjustment(v, i, j, scale); 3433 subparam = 3434 channel->subchannels[j].subchannel_transition; 3435 if (subparam && 3436 stp_check_float_parameter(v, subparam, STP_PARAMETER_ACTIVE)) 3437 stp_channel_set_cutoff_adjustment 3438 (v, i, j, stp_get_float_parameter(v, subparam)); 3439 else if (pv) 3440 { 3441 if (subparam && 3442 stp_check_float_parameter(pv, subparam, STP_PARAMETER_ACTIVE)) 3443 stp_channel_set_cutoff_adjustment 3444 (v, i, j, stp_get_float_parameter(pv, subparam)); 3445 else if (stp_check_float_parameter(pv, "SubchannelCutoff", STP_PARAMETER_ACTIVE)) 3446 stp_channel_set_cutoff_adjustment 3447 (v, i, j, stp_get_float_parameter(pv, "SubchannelCutoff")); 3448 } 3449 } 3450 if (ink_type->inkset != INKSET_EXTENDED) 3451 { 3452 if (channel->hue_curve_name) 3453 { 3454 const stp_curve_t *curve = NULL; 3455 curve = stp_get_curve_parameter(v, channel->hue_curve_name); 3456 if (curve) 3457 { 3458 stp_channel_set_curve(v, i, curve); 3459 hue_curve_found = 1; 3460 } 3461 } 3462 if (channel->hue_curve && !hue_curve_found) 3463 stp_channel_set_curve(v, i, channel->hue_curve); 3464 } 3465 escp2_free_shades(shades); 3466 } 3467 } 3468 if (pd->use_aux_channels) 3469 { 3470 int base_count = pd->logical_channels; 3471 for (i = 0; i < ink_type->aux_channel_count; i++) 3472 { 3473 const ink_channel_t *channel = &(ink_type->aux_channels[i]); 3474 if (channel && channel->n_subchannels > 0) 3475 { 3476 int ch = i + base_count; 3477 const char *param = channel->subchannels[0].channel_density; 3478 shade_t *shades = escp2_copy_shades(v, ch); 3479 double userval = get_double_param(v, param); 3480 STPI_ASSERT(shades->n_shades >= channel->n_subchannels, v); 3481 if (strcmp(param, "GlossDensity") == 0) 3482 { 3483 gloss_scale *= get_double_param(v, param); 3484 stp_channel_set_gloss_channel(v, ch); 3485 stp_channel_set_gloss_limit(v, gloss_scale); 3486 } 3487 for (j = 0; j < channel->n_subchannels; j++) 3488 { 3489 const char *subparam = 3490 channel->subchannels[j].subchannel_value; 3491 if (subparam && 3492 stp_check_float_parameter(v, subparam, STP_PARAMETER_ACTIVE)) 3493 shades->shades[j] = stp_get_float_parameter(v, subparam); 3494 } 3495 stp_dither_set_inks(v, ch, 1.0, ink_darknesses[ch % 8], 3496 channel->n_subchannels, shades->shades, 3497 drops->numdropsizes, drops->dropsizes); 3498 for (j = 0; j < channel->n_subchannels; j++) 3499 { 3500 const char *subparam = 3501 channel->subchannels[j].subchannel_scale; 3502 double scale = userval * get_double_param(v, subparam); 3503 scale *= get_double_param(v, "Density"); 3504 stp_channel_set_density_adjustment(v, ch, j, scale); 3505 subparam = 3506 channel->subchannels[j].subchannel_transition; 3507 if (subparam && 3508 stp_check_float_parameter(v, subparam, STP_PARAMETER_ACTIVE)) 3509 stp_channel_set_cutoff_adjustment 3510 (v, ch, j, stp_get_float_parameter(v, subparam)); 3511 else if (pv) 3512 { 3513 if (subparam && 3514 stp_check_float_parameter(pv, subparam, STP_PARAMETER_ACTIVE)) 3515 stp_channel_set_cutoff_adjustment 3516 (v, ch, j, stp_get_float_parameter(pv, subparam)); 3517 else if (stp_check_float_parameter(pv, "SubchannelCutoff", STP_PARAMETER_ACTIVE)) 3518 stp_channel_set_cutoff_adjustment 3519 (v, ch, j, stp_get_float_parameter(pv, "SubchannelCutoff")); 3520 } 3521 } 3522 if (channel->hue_curve) 3523 { 3524 stp_curve_t *curve_tmp = 3525 stp_curve_create_copy(channel->hue_curve); 3526 (void) stp_curve_rescale(curve_tmp, 3527 sqrt(1.0 / stp_get_float_parameter(v, "Gamma")), 3528 STP_CURVE_COMPOSE_EXPONENTIATE, 3529 STP_CURVE_BOUNDS_RESCALE); 3530 stp_channel_set_curve(v, ch, curve_tmp); 3531 stp_curve_destroy(curve_tmp); 3532 } 3533 escp2_free_shades(shades); 3534 } 3535 } 3536 } 3537 escp2_free_dropsizes(drops); 3538 stp_flush_debug_messages(v); 3539} 3540 3541static void 3542setup_head_offset(stp_vars_t *v) 3543{ 3544 escp2_privdata_t *pd = get_privdata(v); 3545 int i; 3546 int channel_id = 0; 3547 int channel_limit = pd->logical_channels; 3548 const inkname_t *ink_type = pd->inkname; 3549 if (pd->channels_in_use > pd->logical_channels) 3550 channel_limit = pd->channels_in_use; 3551 pd->head_offset = stp_zalloc(sizeof(int) * channel_limit); 3552 for (i = 0; i < pd->logical_channels; i++) 3553 { 3554 const ink_channel_t *channel = &(ink_type->channels[i]); 3555 if (channel) 3556 { 3557 int j; 3558 for (j = 0; j < channel->n_subchannels; j++) 3559 { 3560 pd->head_offset[channel_id] = 3561 channel->subchannels[j].head_offset; 3562 channel_id++; 3563 } 3564 } 3565 } 3566 if (pd->use_aux_channels) 3567 { 3568 for (i = 0; i < ink_type->aux_channel_count; i++) 3569 { 3570 const ink_channel_t *channel = &(ink_type->aux_channels[i]); 3571 if (channel) 3572 { 3573 int j; 3574 for (j = 0; j < channel->n_subchannels; j++) 3575 { 3576 pd->head_offset[channel_id] = 3577 channel->subchannels[j].head_offset; 3578 channel_id++; 3579 } 3580 } 3581 } 3582 } 3583 if (pd->physical_channels == 1) 3584 pd->head_offset[0] = 0; 3585 pd->max_head_offset = 0; 3586 if (pd->physical_channels > 1) 3587 for (i = 0; i < pd->channels_in_use; i++) 3588 { 3589 pd->head_offset[i] = pd->head_offset[i] * pd->res->vres / 3590 escp2_base_separation(v); 3591 if (pd->head_offset[i] > pd->max_head_offset) 3592 pd->max_head_offset = pd->head_offset[i]; 3593 } 3594} 3595 3596static int 3597supports_split_channels(stp_vars_t *v) 3598{ 3599 escp2_privdata_t *pd = get_privdata(v); 3600 int i; 3601 int split_channel_count = -1; 3602 for (i = 0; i < pd->logical_channels; i++) 3603 { 3604 int j; 3605 if (pd->inkname->channels[i].n_subchannels > 0) 3606 { 3607 for (j = 0; j < pd->inkname->channels[i].n_subchannels; j++) 3608 { 3609 int split_count = pd->inkname->channels[i].subchannels[j].split_channel_count; 3610 if (split_count == 0) 3611 return 0; 3612 else if (split_channel_count >= 0 && split_count != split_channel_count) 3613 return 0; 3614 else 3615 split_channel_count = split_count; 3616 } 3617 } 3618 } 3619 if (split_channel_count > 0) 3620 return split_channel_count; 3621 else 3622 return 0; 3623} 3624 3625 3626static void 3627setup_split_channels(stp_vars_t *v) 3628{ 3629 escp2_privdata_t *pd = get_privdata(v); 3630 /* 3631 * Set up the output channels 3632 */ 3633 pd->split_channel_count = supports_split_channels(v); 3634 if (pd->split_channel_count) 3635 { 3636 if (pd->res->vres < 3637 (escp2_base_separation(v) / escp2_black_nozzle_separation(v))) 3638 { 3639 int incr = 3640 (escp2_base_separation(v) / escp2_black_nozzle_separation(v)) / 3641 pd->res->vres; 3642 pd->split_channel_count /= incr; 3643 pd->nozzle_separation *= incr; 3644 pd->nozzles /= incr; 3645 pd->min_nozzles /= incr; 3646 } 3647 } 3648} 3649 3650static void 3651setup_basic(stp_vars_t *v) 3652{ 3653 escp2_privdata_t *pd = get_privdata(v); 3654 pd->advanced_command_set = escp2_has_advanced_command_set(v); 3655 pd->command_set = stp_escp2_get_cap(v, MODEL_COMMAND); 3656 pd->variable_dots = stp_escp2_has_cap(v, MODEL_VARIABLE_DOT, MODEL_VARIABLE_YES); 3657 pd->has_graymode = stp_escp2_has_cap(v, MODEL_GRAYMODE, MODEL_GRAYMODE_YES); 3658 pd->preinit_sequence = escp2_preinit_sequence(v); 3659 pd->preinit_remote_sequence = escp2_preinit_remote_sequence(v); 3660 pd->deinit_remote_sequence = escp2_postinit_remote_sequence(v); 3661 pd->borderless_sequence = escp2_vertical_borderless_sequence(v); 3662 pd->base_separation = escp2_base_separation(v); 3663 pd->resolution_scale = escp2_resolution_scale(v); 3664} 3665 3666static void 3667setup_misc(stp_vars_t *v) 3668{ 3669 escp2_privdata_t *pd = get_privdata(v); 3670 pd->input_slot = stp_escp2_get_input_slot(v); 3671 pd->paper_type = stp_escp2_get_media_type(v, 0); 3672 pd->ink_group = escp2_inkgroup(v); 3673 pd->media_settings = stp_vars_create_copy(pd->paper_type->v); 3674 stp_escp2_set_media_size(pd->media_settings, v); 3675 if (stp_check_float_parameter(v, "PageDryTime", STP_PARAMETER_ACTIVE)) 3676 stp_set_float_parameter(pd->media_settings, "PageDryTime", 3677 stp_get_float_parameter(v, "PageDryTime")); 3678 if (stp_check_float_parameter(v, "ScanDryTime", STP_PARAMETER_ACTIVE)) 3679 stp_set_float_parameter(pd->media_settings, "ScanDryTime", 3680 stp_get_float_parameter(v, "ScanDryTime")); 3681 if (stp_check_float_parameter(v, "ScanMinDryTime", STP_PARAMETER_ACTIVE)) 3682 stp_set_float_parameter(pd->media_settings, "ScanMinDryTime", 3683 stp_get_float_parameter(v, "ScanMinDryTime")); 3684 if (stp_check_int_parameter(v, "FeedAdjustment", STP_PARAMETER_ACTIVE)) 3685 stp_set_int_parameter(pd->media_settings, "FeedAdjustment", 3686 stp_get_int_parameter(v, "FeedAdjustment")); 3687 if (stp_check_int_parameter(v, "PaperThickness", STP_PARAMETER_ACTIVE)) 3688 stp_set_int_parameter(pd->media_settings, "PaperThickness", 3689 stp_get_int_parameter(v, "PaperThickness")); 3690 if (stp_check_int_parameter(v, "VacuumIntensity", STP_PARAMETER_ACTIVE)) 3691 stp_set_int_parameter(pd->media_settings, "VacuumIntensity", 3692 stp_get_int_parameter(v, "VacuumIntensity")); 3693 if (stp_check_int_parameter(v, "FeedSequence", STP_PARAMETER_ACTIVE)) 3694 stp_set_int_parameter(pd->media_settings, "FeedSequence", 3695 stp_get_int_parameter(v, "FeedSequence")); 3696 if (stp_check_int_parameter(v, "PrintMethod", STP_PARAMETER_ACTIVE)) 3697 stp_set_int_parameter(pd->media_settings, "PrintMethod", 3698 stp_get_int_parameter(v, "PrintMethod")); 3699 if (stp_check_int_parameter(v, "PlatenGap", STP_PARAMETER_ACTIVE)) 3700 stp_set_int_parameter(pd->media_settings, "PlatenGap", 3701 stp_get_int_parameter(v, "PlatenGap")); 3702} 3703 3704static void 3705allocate_channels(stp_vars_t *v, int line_length) 3706{ 3707 escp2_privdata_t *pd = get_privdata(v); 3708 const inkname_t *ink_type = pd->inkname; 3709 int i, j, k; 3710 int channel_id = 0; 3711 int split_id = 0; 3712 3713 pd->cols = stp_zalloc(sizeof(unsigned char *) * pd->channels_in_use); 3714 pd->channels = 3715 stp_zalloc(sizeof(physical_subchannel_t *) * pd->channels_in_use); 3716 if (pd->split_channel_count) 3717 pd->split_channels = stp_zalloc(sizeof(short) * pd->channels_in_use * 3718 pd->split_channel_count); 3719 3720 for (i = 0; i < pd->logical_channels; i++) 3721 { 3722 const ink_channel_t *channel = &(ink_type->channels[i]); 3723 if (channel) 3724 { 3725 for (j = 0; j < channel->n_subchannels; j++) 3726 { 3727 const physical_subchannel_t *sc = &(channel->subchannels[j]); 3728 pd->cols[channel_id] = stp_zalloc(line_length); 3729 pd->channels[channel_id] = sc; 3730 stp_dither_add_channel(v, pd->cols[channel_id], i, j); 3731 if (pd->split_channel_count) 3732 { 3733 for (k = 0; k < pd->split_channel_count; k++) 3734 pd->split_channels[split_id++] = sc->split_channels[k]; 3735 } 3736 channel_id++; 3737 } 3738 } 3739 } 3740 if (pd->use_aux_channels && ink_type->aux_channel_count > 0) 3741 { 3742 for (i = 0; i < ink_type->aux_channel_count; i++) 3743 { 3744 const ink_channel_t *channel = &(ink_type->aux_channels[i]); 3745 for (j = 0; j < channel->n_subchannels; j++) 3746 { 3747 const physical_subchannel_t *sc = &(channel->subchannels[j]); 3748 pd->cols[channel_id] = stp_zalloc(line_length); 3749 pd->channels[channel_id] = sc; 3750 stp_dither_add_channel(v, pd->cols[channel_id], 3751 i + pd->logical_channels, j); 3752 if (pd->split_channel_count) 3753 { 3754 for (k = 0; k < pd->split_channel_count; k++) 3755 pd->split_channels[split_id++] = sc->split_channels[k]; 3756 } 3757 channel_id++; 3758 } 3759 } 3760 } 3761 stp_set_string_parameter(v, "STPIOutputType", escp2_describe_output(v)); 3762} 3763 3764static unsigned 3765gcd(unsigned a, unsigned b) 3766{ 3767 unsigned tmp; 3768 if (b > a) 3769 { 3770 tmp = a; 3771 a = b; 3772 b = tmp; 3773 } 3774 while (1) 3775 { 3776 tmp = a % b; 3777 if (tmp == 0) 3778 return b; 3779 a = b; 3780 b = tmp; 3781 } 3782} 3783 3784static unsigned 3785lcm(unsigned a, unsigned b) 3786{ 3787 if (a == b) 3788 return a; 3789 else 3790 return a * b / gcd(a, b); 3791} 3792 3793static int 3794adjusted_vertical_resolution(const res_t *res) 3795{ 3796 if (res->vres >= 720) 3797 return res->vres; 3798 else if (res->hres >= 720) /* Special case 720x360 */ 3799 return 720; 3800 else if (res->vres % 90 == 0) 3801 return res->vres; 3802 else 3803 return lcm(res->hres, res->vres); 3804} 3805 3806static int 3807adjusted_horizontal_resolution(const res_t *res) 3808{ 3809 if (res->vres % 90 == 0) 3810 return res->hres; 3811 else 3812 return lcm(res->hres, res->vres); 3813} 3814 3815static void 3816setup_resolution(stp_vars_t *v) 3817{ 3818 escp2_privdata_t *pd = get_privdata(v); 3819 const res_t *res = stp_escp2_find_resolution(v); 3820 3821 int vertical = adjusted_vertical_resolution(res); 3822 int horizontal = adjusted_horizontal_resolution(res); 3823 3824 pd->res = res; 3825 pd->use_extended_commands = 3826 escp2_use_extended_commands(v, !(pd->res->command)); 3827 pd->physical_xdpi = escp2_base_res(v); 3828 if (pd->physical_xdpi > pd->res->hres) 3829 pd->physical_xdpi = pd->res->hres; 3830 3831 if (pd->use_extended_commands) 3832 { 3833 pd->unit_scale = MAX(escp2_max_hres(v), escp2_max_vres(v)); 3834 pd->horizontal_units = horizontal; 3835 pd->micro_units = horizontal; 3836 } 3837 else 3838 { 3839 pd->unit_scale = 3600; 3840 if (pd->res->hres <= 720) 3841 pd->micro_units = vertical; 3842 else 3843 pd->micro_units = horizontal; 3844 pd->horizontal_units = vertical; 3845 } 3846 /* Note hard-coded 1440 -- from Epson manuals */ 3847 if (stp_escp2_has_cap(v, MODEL_COMMAND, MODEL_COMMAND_1999) && 3848 stp_escp2_has_cap(v, MODEL_VARIABLE_DOT, MODEL_VARIABLE_NO)) 3849 pd->micro_units = 1440; 3850 pd->vertical_units = vertical; 3851 pd->page_management_units = vertical; 3852} 3853 3854static void 3855setup_softweave_parameters(stp_vars_t *v) 3856{ 3857 escp2_privdata_t *pd = get_privdata(v); 3858 pd->horizontal_passes = pd->res->printed_hres / pd->physical_xdpi; 3859 if (pd->physical_channels == 1 && 3860 (pd->inkname->channels[0].subchannels->split_channel_count > 1 || 3861 (pd->res->vres >= 3862 (escp2_base_separation(v) / escp2_black_nozzle_separation(v)))) && 3863 (escp2_max_black_resolution(v) < 0 || 3864 pd->res->vres <= escp2_max_black_resolution(v)) && 3865 escp2_black_nozzles(v)) 3866 pd->use_black_parameters = 1; 3867 else 3868 pd->use_black_parameters = 0; 3869 if (pd->use_fast_360) 3870 { 3871 pd->nozzles = escp2_fast_nozzles(v); 3872 pd->nozzle_separation = escp2_fast_nozzle_separation(v); 3873 pd->nozzle_start = escp2_fast_nozzle_start(v); 3874 pd->min_nozzles = escp2_min_fast_nozzles(v); 3875 } 3876 else if (pd->use_black_parameters) 3877 { 3878 pd->nozzles = escp2_black_nozzles(v); 3879 pd->nozzle_separation = escp2_black_nozzle_separation(v); 3880 pd->nozzle_start = escp2_black_nozzle_start(v); 3881 pd->min_nozzles = escp2_min_black_nozzles(v); 3882 } 3883 else 3884 { 3885 pd->nozzles = escp2_nozzles(v); 3886 pd->nozzle_separation = escp2_nozzle_separation(v); 3887 pd->nozzle_start = escp2_nozzle_start(v); 3888 pd->min_nozzles = escp2_min_nozzles(v); 3889 } 3890} 3891 3892static void 3893setup_printer_weave_parameters(stp_vars_t *v) 3894{ 3895 escp2_privdata_t *pd = get_privdata(v); 3896 pd->horizontal_passes = 1; 3897 pd->nozzles = 1; 3898 pd->nozzle_separation = 1; 3899 pd->nozzle_start = 0; 3900 pd->min_nozzles = 1; 3901 if (pd->physical_channels == 1) 3902 pd->use_black_parameters = 1; 3903 else 3904 pd->use_black_parameters = 0; 3905 pd->extra_vertical_passes = 1; 3906} 3907 3908static void 3909setup_head_parameters(stp_vars_t *v) 3910{ 3911 escp2_privdata_t *pd = get_privdata(v); 3912 /* 3913 * Set up the output channels 3914 */ 3915 if (strcmp(stp_get_string_parameter(v, "PrintingMode"), "BW") == 0) 3916 pd->logical_channels = 1; 3917 else 3918 pd->logical_channels = pd->inkname->channel_count; 3919 3920 pd->physical_channels = 3921 compute_channel_count(pd->inkname, pd->logical_channels, 3922 pd->use_aux_channels); 3923 if (pd->physical_channels == 0) 3924 { 3925 pd->inkname = stpi_escp2_get_default_black_inkset(); 3926 pd->physical_channels = 3927 compute_channel_count(pd->inkname, pd->logical_channels, 3928 pd->use_aux_channels); 3929 } 3930 3931 pd->printer_weave = get_printer_weave(v); 3932 3933 pd->extra_vertical_passes = 1; 3934 if (stp_check_int_parameter(v, "BandEnhancement", STP_PARAMETER_ACTIVE)) 3935 pd->extra_vertical_passes = 3936 1 << stp_get_int_parameter(v, "BandEnhancement"); 3937 if (stp_escp2_has_cap(v, MODEL_FAST_360, MODEL_FAST_360_YES) && 3938 (pd->inkname->inkset == INKSET_CMYK || pd->physical_channels == 1) && 3939 pd->res->hres == pd->physical_xdpi && pd->res->vres == 360) 3940 pd->use_fast_360 = 1; 3941 else 3942 pd->use_fast_360 = 0; 3943 3944 /* 3945 * Set up the printer-specific parameters (weaving) 3946 */ 3947 pd->use_printer_weave = use_printer_weave(v); 3948 if (pd->use_printer_weave) 3949 setup_printer_weave_parameters(v); 3950 else 3951 setup_softweave_parameters(v); 3952 pd->separation_rows = escp2_separation_rows(v); 3953 pd->pseudo_separation_rows = escp2_pseudo_separation_rows(v); 3954 pd->extra_720dpi_separation = escp2_extra_720dpi_separation(v); 3955 pd->bidirectional_upper_limit = escp2_bidirectional_upper_limit(v); 3956 3957 if (pd->horizontal_passes == 0) 3958 pd->horizontal_passes = 1; 3959 3960 setup_head_offset(v); 3961 setup_split_channels(v); 3962 3963 if (stp_check_string_parameter(v, "Duplex", STP_PARAMETER_ACTIVE)) 3964 { 3965 const char *duplex = stp_get_string_parameter(v, "Duplex"); 3966 if (strcmp(duplex, "DuplexTumble") == 0) 3967 pd->duplex = DUPLEX_TUMBLE; 3968 else if (strcmp(duplex, "DuplexNoTumble") == 0) 3969 pd->duplex = DUPLEX_NO_TUMBLE; 3970 else 3971 pd->duplex = 0; 3972 } 3973 if (pd->duplex) 3974 pd->extra_vertical_feed = 0; 3975 else 3976 pd->extra_vertical_feed = escp2_extra_feed(v); 3977 3978 if (strcmp(stp_get_string_parameter(v, "PrintingMode"), "BW") == 0 && 3979 pd->physical_channels == 1) 3980 { 3981 if (pd->use_black_parameters) 3982 pd->initial_vertical_offset = 3983 (escp2_black_initial_vertical_offset(v) - 3984 (escp2_black_nozzle_start(v) * (int) escp2_black_nozzle_separation(v))) * 3985 pd->page_management_units / 3986 escp2_base_separation(v); 3987 else 3988 pd->initial_vertical_offset = pd->head_offset[0] + 3989 ((escp2_initial_vertical_offset(v) - 3990 (escp2_nozzle_start(v) * (int) escp2_nozzle_separation(v))) * 3991 pd->page_management_units / escp2_base_separation(v)); 3992 } 3993 else 3994 pd->initial_vertical_offset = 3995 (escp2_initial_vertical_offset(v) - 3996 (escp2_nozzle_start(v) * (int) escp2_nozzle_separation(v))) * 3997 pd->page_management_units / 3998 escp2_base_separation(v); 3999 4000 pd->printing_initial_vertical_offset = 0; 4001 pd->bitwidth = escp2_bits(v); 4002} 4003 4004static void 4005setup_page(stp_vars_t *v) 4006{ 4007 escp2_privdata_t *pd = get_privdata(v); 4008 const input_slot_t *input_slot = stp_escp2_get_input_slot(v); 4009 int extra_left = 0; 4010 int extra_top = 0; 4011 int hub_size = 0; 4012 int min_horizontal_alignment = escp2_min_horizontal_position_alignment(v); 4013 int base_horizontal_alignment = 4014 pd->res->hres / escp2_base_horizontal_position_alignment(v); 4015 int required_horizontal_alignment = 4016 MAX(min_horizontal_alignment, base_horizontal_alignment); 4017 4018 const char *cd_type = stp_get_string_parameter(v, "PageSize"); 4019 if (cd_type && (strcmp(cd_type, "CDCustom") == 0 )) 4020 { 4021 int outer_diameter = stp_get_dimension_parameter(v, "CDOuterDiameter"); 4022 stp_set_page_width(v, outer_diameter); 4023 stp_set_page_height(v, outer_diameter); 4024 stp_set_width(v, outer_diameter); 4025 stp_set_height(v, outer_diameter); 4026 hub_size = stp_get_dimension_parameter(v, "CDInnerDiameter"); 4027 } 4028 else 4029 { 4030 const char *inner_radius_name = stp_get_string_parameter(v, "CDInnerRadius"); 4031 hub_size = 43 * 10 * 72 / 254; /* 43 mm standard CD hub */ 4032 4033 if (inner_radius_name && strcmp(inner_radius_name, "Small") == 0) 4034 hub_size = 16 * 10 * 72 / 254; /* 15 mm prints to the hole - play it 4035 safe and print 16 mm */ 4036 } 4037 4038 escp2_media_size(v, &(pd->page_true_width), &(pd->page_true_height)); 4039 /* Don't use full bleed mode if the paper itself has a margin */ 4040 if (pd->page_left > 0 || pd->page_top > 0) 4041 stp_set_boolean_parameter(v, "FullBleed", 0); 4042 if (stp_escp2_has_cap(v, MODEL_ZEROMARGIN, MODEL_ZEROMARGIN_FULL) && 4043 ((!input_slot || !(input_slot->is_cd)))) 4044 { 4045 pd->page_extra_height = 4046 max_nozzle_span(v) * pd->page_management_units / 4047 escp2_base_separation(v); 4048 if (stp_get_boolean_parameter(v, "FullBleed")) 4049 pd->paper_extra_bottom = 0; 4050 else 4051 pd->paper_extra_bottom = escp2_paper_extra_bottom(v); 4052 } 4053 else if (stp_escp2_has_cap(v, MODEL_ZEROMARGIN, MODEL_ZEROMARGIN_YES) && 4054 (stp_get_boolean_parameter(v, "FullBleed")) && 4055 ((!input_slot || !(input_slot->is_cd)))) 4056 { 4057 pd->paper_extra_bottom = 0; 4058 pd->page_extra_height = 4059 escp2_zero_margin_offset(v) * pd->page_management_units / 4060 escp2_base_separation(v); 4061 } 4062 else if (stp_escp2_has_cap(v, MODEL_ZEROMARGIN, MODEL_ZEROMARGIN_RESTR) && 4063 (stp_get_boolean_parameter(v, "FullBleed")) && 4064 ((!input_slot || !(input_slot->is_cd)))) 4065 { 4066 pd->paper_extra_bottom = 0; 4067 pd->page_extra_height = 0; 4068 } 4069 else if (stp_escp2_printer_supports_duplex(v) && !pd->duplex) 4070 { 4071 pd->paper_extra_bottom = escp2_paper_extra_bottom(v); 4072 pd->page_extra_height = 4073 max_nozzle_span(v) * pd->page_management_units / 4074 escp2_base_separation(v); 4075 } 4076 else 4077 { 4078 if (input_slot) 4079 pd->page_extra_height = input_slot->extra_height * 4080 pd->page_management_units / escp2_base_separation(v); 4081 else 4082 pd->page_extra_height = 0; 4083 pd->paper_extra_bottom = escp2_paper_extra_bottom(v); 4084 } 4085 internal_imageable_area(v, 0, 0, &pd->page_left, &pd->page_right, 4086 &pd->page_bottom, &pd->page_top); 4087 4088 if (input_slot && input_slot->is_cd && escp2_cd_x_offset(v) > 0) 4089 { 4090 int left_center = escp2_cd_x_offset(v) + 4091 stp_get_dimension_parameter(v, "CDXAdjustment"); 4092 int top_center = escp2_cd_y_offset(v) + 4093 stp_get_dimension_parameter(v, "CDYAdjustment"); 4094 pd->page_true_height = pd->page_bottom - pd->page_top; 4095 pd->page_true_width = pd->page_right - pd->page_left; 4096 pd->paper_extra_bottom = 0; 4097 pd->page_extra_height = 0; 4098 stp_set_left(v, stp_get_left(v) - pd->page_left); 4099 stp_set_top(v, stp_get_top(v) - pd->page_top); 4100 pd->page_right -= pd->page_left; 4101 pd->page_bottom -= pd->page_top; 4102 pd->page_top = 0; 4103 pd->page_left = 0; 4104 extra_top = top_center - (pd->page_bottom / 2); 4105 extra_left = left_center - (pd->page_right / 2); 4106 pd->cd_inner_radius = hub_size * pd->micro_units / 72 / 2; 4107 pd->cd_outer_radius = pd->page_right * pd->micro_units / 72 / 2; 4108 pd->cd_x_offset = 4109 ((pd->page_right / 2) - stp_get_left(v)) * pd->micro_units / 72; 4110 pd->cd_y_offset = stp_get_top(v) * pd->res->printed_vres / 72; 4111 if (escp2_cd_page_height(v)) 4112 { 4113 pd->page_right = escp2_cd_page_width(v); 4114 pd->page_bottom = escp2_cd_page_height(v); 4115 pd->page_true_height = escp2_cd_page_height(v); 4116 pd->page_true_width = escp2_cd_page_width(v); 4117 } 4118 } 4119 4120 pd->page_right += extra_left + 1; 4121 pd->page_width = pd->page_right - pd->page_left; 4122 pd->image_left = stp_get_left(v) - pd->page_left + extra_left; 4123 pd->image_width = stp_get_width(v); 4124 pd->image_scaled_width = pd->image_width * pd->res->hres / 72; 4125 pd->image_printed_width = pd->image_width * pd->res->printed_hres / 72; 4126 if (pd->split_channel_count >= 1) 4127 { 4128 pd->split_channel_width = 4129 ((pd->image_printed_width + pd->horizontal_passes - 1) / 4130 pd->horizontal_passes); 4131 pd->split_channel_width = (pd->split_channel_width + 7) / 8; 4132 pd->split_channel_width *= pd->bitwidth; 4133 if (!(stp_get_debug_level() & STP_DBG_NO_COMPRESSION)) 4134 { 4135 pd->comp_buf = 4136 stp_malloc(stp_compute_tiff_linewidth(v, pd->split_channel_width)); 4137 } 4138 } 4139 pd->image_left_position = pd->image_left * pd->micro_units / 72; 4140 pd->zero_margin_offset = escp2_zero_margin_offset(v); 4141 if (supports_borderless(v) && 4142 pd->advanced_command_set && 4143 ((!input_slot || !(input_slot->is_cd)) && 4144 stp_get_boolean_parameter(v, "FullBleed"))) 4145 { 4146 int margin = escp2_micro_left_margin(v); 4147 int sep = escp2_base_separation(v); 4148 pd->image_left_position += 4149 (pd->zero_margin_offset - margin) * pd->micro_units / sep; 4150 } 4151 /* 4152 * Many printers print extremely slowly if the starting position 4153 * is not aligned to 1/180" 4154 */ 4155 if (required_horizontal_alignment > 1) 4156 pd->image_left_position = 4157 (pd->image_left_position / required_horizontal_alignment) * 4158 required_horizontal_alignment; 4159 4160 4161 pd->page_bottom += extra_top + 1; 4162 pd->page_height = pd->page_bottom - pd->page_top; 4163 pd->image_top = stp_get_top(v) - pd->page_top + extra_top; 4164 pd->image_height = stp_get_height(v); 4165 pd->image_scaled_height = pd->image_height * pd->res->vres / 72; 4166 pd->image_printed_height = pd->image_height * pd->res->printed_vres / 72; 4167 4168 if (input_slot && input_slot->roll_feed_cut_flags) 4169 { 4170 pd->page_true_height += 4; /* Empirically-determined constants */ 4171 pd->page_top += 2; 4172 pd->page_bottom += 2; 4173 pd->image_top += 2; 4174 pd->page_height += 2; 4175 } 4176} 4177 4178static void 4179set_mask(unsigned char *cd_mask, int x_center, int scaled_x_where, 4180 int limit, int expansion, int invert) 4181{ 4182 int clear_val = invert ? 255 : 0; 4183 int set_val = invert ? 0 : 255; 4184 int bytesize = 8 / expansion; 4185 int byteextra = bytesize - 1; 4186 int first_x_on = x_center - scaled_x_where; 4187 int first_x_off = x_center + scaled_x_where; 4188 if (first_x_on < 0) 4189 first_x_on = 0; 4190 if (first_x_on > limit) 4191 first_x_on = limit; 4192 if (first_x_off < 0) 4193 first_x_off = 0; 4194 if (first_x_off > limit) 4195 first_x_off = limit; 4196 first_x_on += byteextra; 4197 if (first_x_off > (first_x_on - byteextra)) 4198 { 4199 int first_x_on_byte = first_x_on / bytesize; 4200 int first_x_on_mod = expansion * (byteextra - (first_x_on % bytesize)); 4201 int first_x_on_extra = ((1 << first_x_on_mod) - 1) ^ clear_val; 4202 int first_x_off_byte = first_x_off / bytesize; 4203 int first_x_off_mod = expansion * (byteextra - (first_x_off % bytesize)); 4204 int first_x_off_extra = ((1 << 8) - (1 << first_x_off_mod)) ^ clear_val; 4205 if (first_x_off_byte < first_x_on_byte) 4206 { 4207 /* This can happen, if 6 or fewer points are turned on */ 4208 cd_mask[first_x_on_byte] = first_x_on_extra & first_x_off_extra; 4209 } 4210 else 4211 { 4212 if (first_x_on_extra != clear_val) 4213 cd_mask[first_x_on_byte - 1] = first_x_on_extra; 4214 if (first_x_off_byte > first_x_on_byte) 4215 memset(cd_mask + first_x_on_byte, set_val, 4216 first_x_off_byte - first_x_on_byte); 4217 if (first_x_off_extra != clear_val) 4218 cd_mask[first_x_off_byte] = first_x_off_extra; 4219 } 4220 } 4221} 4222 4223static int 4224escp2_print_data(stp_vars_t *v, stp_image_t *image) 4225{ 4226 escp2_privdata_t *pd = get_privdata(v); 4227 int errdiv = stp_image_height(image) / pd->image_printed_height; 4228 int errmod = stp_image_height(image) % pd->image_printed_height; 4229 int errval = 0; 4230 int errlast = -1; 4231 int errline = 0; 4232 int y; 4233 double outer_r_sq = 0; 4234 double inner_r_sq = 0; 4235 int x_center = pd->cd_x_offset * pd->res->printed_hres / pd->micro_units; 4236 unsigned char *cd_mask = NULL; 4237 if (pd->cd_outer_radius > 0) 4238 { 4239 cd_mask = stp_malloc(1 + (pd->image_printed_width + 7) / 8); 4240 outer_r_sq = (double) pd->cd_outer_radius * (double) pd->cd_outer_radius; 4241 inner_r_sq = (double) pd->cd_inner_radius * (double) pd->cd_inner_radius; 4242 } 4243 4244 for (y = 0; y < pd->image_printed_height; y ++) 4245 { 4246 int duplicate_line = 1; 4247 unsigned zero_mask; 4248 4249 if (errline != errlast) 4250 { 4251 errlast = errline; 4252 duplicate_line = 0; 4253 if (stp_color_get_row(v, image, errline, &zero_mask)) 4254 return 2; 4255 } 4256 4257 if (cd_mask) 4258 { 4259 int y_distance_from_center = 4260 pd->cd_outer_radius - 4261 ((y + pd->cd_y_offset) * pd->micro_units / pd->res->printed_vres); 4262 if (y_distance_from_center < 0) 4263 y_distance_from_center = -y_distance_from_center; 4264 memset(cd_mask, 0, (pd->image_printed_width + 7) / 8); 4265 if (y_distance_from_center < pd->cd_outer_radius) 4266 { 4267 double y_sq = (double) y_distance_from_center * 4268 (double) y_distance_from_center; 4269 int x_where = sqrt(outer_r_sq - y_sq) + .5; 4270 int scaled_x_where = x_where * pd->res->printed_hres / pd->micro_units; 4271 set_mask(cd_mask, x_center, scaled_x_where, 4272 pd->image_printed_width, 1, 0); 4273 if (y_distance_from_center < pd->cd_inner_radius) 4274 { 4275 x_where = sqrt(inner_r_sq - y_sq) + .5; 4276 scaled_x_where = x_where * pd->res->printed_hres / pd->micro_units; 4277 set_mask(cd_mask, x_center, scaled_x_where, 4278 pd->image_printed_width, 1, 1); 4279 } 4280 } 4281 } 4282 4283 stp_dither(v, y, duplicate_line, zero_mask, cd_mask); 4284 4285 stp_write_weave(v, pd->cols); 4286 errval += errmod; 4287 errline += errdiv; 4288 if (errval >= pd->image_printed_height) 4289 { 4290 errval -= pd->image_printed_height; 4291 errline ++; 4292 } 4293 } 4294 if (cd_mask) 4295 stp_free(cd_mask); 4296 return 1; 4297} 4298 4299static int 4300escp2_print_page(stp_vars_t *v, stp_image_t *image) 4301{ 4302 int status; 4303 escp2_privdata_t *pd = get_privdata(v); 4304 int out_channels; /* Output bytes per pixel */ 4305 int line_width = (pd->image_printed_width + 7) / 8 * pd->bitwidth; 4306 int weave_pattern = STP_WEAVE_ZIGZAG; 4307 if (stp_check_string_parameter(v, "Weave", STP_PARAMETER_ACTIVE)) 4308 { 4309 const char *weave = stp_get_string_parameter(v, "Weave"); 4310 if (strcmp(weave, "Alternate") == 0) 4311 weave_pattern = STP_WEAVE_ZIGZAG; 4312 else if (strcmp(weave, "Ascending") == 0) 4313 weave_pattern = STP_WEAVE_ASCENDING; 4314 else if (strcmp(weave, "Descending") == 0) 4315 weave_pattern = STP_WEAVE_DESCENDING; 4316 else if (strcmp(weave, "Ascending2X") == 0) 4317 weave_pattern = STP_WEAVE_ASCENDING_2X; 4318 else if (strcmp(weave, "Staggered") == 0) 4319 weave_pattern = STP_WEAVE_STAGGERED; 4320 } 4321 4322 stp_initialize_weave 4323 (v, 4324 pd->nozzles, 4325 pd->nozzle_separation * pd->res->vres / escp2_base_separation(v), 4326 pd->horizontal_passes, 4327 pd->res->vertical_passes * pd->extra_vertical_passes, 4328 1, 4329 pd->channels_in_use, 4330 pd->bitwidth, 4331 pd->image_printed_width, 4332 pd->image_printed_height, 4333 ((pd->page_extra_height * pd->res->vres / pd->vertical_units) + 4334 (pd->image_top * pd->res->vres / 72)), 4335 (pd->page_extra_height + 4336 (pd->page_height + pd->extra_vertical_feed) * pd->res->vres / 72), 4337 pd->head_offset, 4338 weave_pattern, 4339 stpi_escp2_flush_pass, 4340 (((stp_get_debug_level() & STP_DBG_NO_COMPRESSION) || 4341 pd->split_channel_count > 0) ? 4342 stp_fill_uncompressed : stp_fill_tiff), 4343 (((stp_get_debug_level() & STP_DBG_NO_COMPRESSION) || 4344 pd->split_channel_count > 0) ? 4345 stp_pack_uncompressed : stp_pack_tiff), 4346 (((stp_get_debug_level() & STP_DBG_NO_COMPRESSION) || 4347 pd->split_channel_count > 0) ? 4348 stp_compute_uncompressed_linewidth : stp_compute_tiff_linewidth)); 4349 4350 stp_dither_init(v, image, pd->image_printed_width, pd->res->printed_hres, 4351 pd->res->printed_vres); 4352 allocate_channels(v, line_width); 4353 adjust_print_quality(v); 4354 out_channels = stp_color_init(v, image, 65536); 4355 4356/* stpi_dither_set_expansion(v, pd->res->hres / pd->res->printed_hres); */ 4357 4358 setup_inks(v); 4359 4360 status = escp2_print_data(v, image); 4361 stp_flush_all(v); 4362 stpi_escp2_terminate_page(v); 4363 return status; 4364} 4365 4366/* 4367 * 'escp2_print()' - Print an image to an EPSON printer. 4368 */ 4369static int 4370escp2_do_print(stp_vars_t *v, stp_image_t *image, int print_op) 4371{ 4372 int status = 1; 4373 int i; 4374 4375 escp2_privdata_t *pd; 4376 int page_number = stp_get_int_parameter(v, "PageNumber"); 4377 4378 if (!stp_verify(v)) 4379 { 4380 stp_eprintf(v, _("Print options not verified; cannot print.\n")); 4381 return 0; 4382 } 4383 4384 if (strcmp(stp_get_string_parameter(v, "InputImageType"), "Raw") == 0 && 4385 !set_raw_ink_type(v)) 4386 return 0; 4387 4388 pd = (escp2_privdata_t *) stp_zalloc(sizeof(escp2_privdata_t)); 4389 4390 pd->printed_something = 0; 4391 pd->last_color = -1; 4392 pd->last_pass_offset = 0; 4393 pd->last_pass = -1; 4394 pd->send_zero_pass_advance = 4395 stp_escp2_has_cap(v, MODEL_SEND_ZERO_ADVANCE, MODEL_SEND_ZERO_ADVANCE_YES); 4396 stp_allocate_component_data(v, "Driver", NULL, NULL, pd); 4397 4398 pd->inkname = get_inktype(v); 4399 if (pd->inkname->inkset != INKSET_EXTENDED && 4400 stp_check_boolean_parameter(v, "UseGloss", STP_PARAMETER_ACTIVE) && 4401 stp_get_boolean_parameter(v, "UseGloss")) 4402 pd->use_aux_channels = 1; 4403 else 4404 pd->use_aux_channels = 0; 4405 if (pd->inkname && pd->inkname->inkset == INKSET_QUADTONE && 4406 strcmp(stp_get_string_parameter(v, "PrintingMode"), "BW") != 0) 4407 { 4408 stp_eprintf(v, "Warning: Quadtone inkset only available in MONO\n"); 4409 stp_set_string_parameter(v, "PrintingMode", "BW"); 4410 } 4411 if (pd->inkname && pd->inkname->inkset == INKSET_HEXTONE && 4412 strcmp(stp_get_string_parameter(v, "PrintingMode"), "BW") != 0) 4413 { 4414 stp_eprintf(v, "Warning: Hextone inkset only available in MONO\n"); 4415 stp_set_string_parameter(v, "PrintingMode", "BW"); 4416 } 4417 pd->channels_in_use = count_channels(pd->inkname, pd->use_aux_channels); 4418 4419 setup_basic(v); 4420 setup_resolution(v); 4421 setup_head_parameters(v); 4422 setup_page(v); 4423 setup_misc(v); 4424 4425 adjust_density_and_ink_type(v); 4426 if (print_op & OP_JOB_START) 4427 stpi_escp2_init_printer(v); 4428 if (print_op & OP_JOB_PRINT) 4429 { 4430 stp_image_init(image); 4431 if ((page_number & 1) && pd->duplex && 4432 ((pd->duplex & pd->input_slot->duplex) == 0)) 4433 /* If the hardware can't do the duplex operation, we need to 4434 emulate it in software */ 4435 image = stpi_buffer_image(image, BUFFER_FLAG_FLIP_X | BUFFER_FLAG_FLIP_Y); 4436 status = escp2_print_page(v, image); 4437 stp_image_conclude(image); 4438 } 4439 if (print_op & OP_JOB_END) 4440 stpi_escp2_deinit_printer(v); 4441 4442 if (pd->head_offset) 4443 stp_free(pd->head_offset); 4444 4445 /* 4446 * Cleanup... 4447 */ 4448 if (pd->cols) 4449 { 4450 for (i = 0; i < pd->channels_in_use; i++) 4451 if (pd->cols[i]) 4452 stp_free(pd->cols[i]); 4453 stp_free(pd->cols); 4454 } 4455 if (pd->media_settings) 4456 stp_vars_destroy(pd->media_settings); 4457 if (pd->channels) 4458 stp_free(pd->channels); 4459 if (pd->split_channels) 4460 stp_free(pd->split_channels); 4461 if (pd->comp_buf) 4462 stp_free(pd->comp_buf); 4463 stp_free(pd); 4464 4465 return status; 4466} 4467 4468static int 4469escp2_print(const stp_vars_t *v, stp_image_t *image) 4470{ 4471 stp_vars_t *nv = stp_vars_create_copy(v); 4472 int op = OP_JOB_PRINT; 4473 int status; 4474 if (!stp_get_string_parameter(v, "JobMode") || 4475 strcmp(stp_get_string_parameter(v, "JobMode"), "Page") == 0) 4476 op = OP_JOB_START | OP_JOB_PRINT | OP_JOB_END; 4477 stp_prune_inactive_options(nv); 4478 status = escp2_do_print(nv, image, op); 4479 stp_vars_destroy(nv); 4480 return status; 4481} 4482 4483static int 4484escp2_job_start(const stp_vars_t *v, stp_image_t *image) 4485{ 4486 stp_vars_t *nv = stp_vars_create_copy(v); 4487 int status; 4488 stp_prune_inactive_options(nv); 4489 status = escp2_do_print(nv, image, OP_JOB_START); 4490 stp_vars_destroy(nv); 4491 return status; 4492} 4493 4494static int 4495escp2_job_end(const stp_vars_t *v, stp_image_t *image) 4496{ 4497 stp_vars_t *nv = stp_vars_create_copy(v); 4498 int status; 4499 stp_prune_inactive_options(nv); 4500 status = escp2_do_print(nv, image, OP_JOB_END); 4501 stp_vars_destroy(nv); 4502 return status; 4503} 4504 4505static const stp_printfuncs_t print_escp2_printfuncs = 4506{ 4507 escp2_list_parameters, 4508 escp2_parameters, 4509 escp2_media_size, 4510 escp2_imageable_area, 4511 escp2_maximum_imageable_area, 4512 escp2_limit, 4513 escp2_print, 4514 escp2_describe_resolution, 4515 escp2_describe_output, 4516 stp_verify_printer_params, 4517 escp2_job_start, 4518 escp2_job_end, 4519 NULL 4520}; 4521 4522static stp_family_t print_escp2_module_data = 4523 { 4524 &print_escp2_printfuncs, 4525 NULL 4526 }; 4527 4528 4529static int 4530print_escp2_module_init(void) 4531{ 4532 hue_curve_bounds = stp_curve_create_from_string 4533 ("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" 4534 "<gutenprint>\n" 4535 "<curve wrap=\"wrap\" type=\"linear\" gamma=\"0\">\n" 4536 "<sequence count=\"2\" lower-bound=\"0\" upper-bound=\"1\">\n" 4537 "1 1\n" 4538 "</sequence>\n" 4539 "</curve>\n" 4540 "</gutenprint>"); 4541 return stp_family_register(print_escp2_module_data.printer_list); 4542} 4543 4544 4545static int 4546print_escp2_module_exit(void) 4547{ 4548 return stp_family_unregister(print_escp2_module_data.printer_list); 4549} 4550 4551 4552/* Module header */ 4553#define stp_module_version print_escp2_LTX_stp_module_version 4554#define stp_module_data print_escp2_LTX_stp_module_data 4555 4556stp_module_version_t stp_module_version = {0, 0}; 4557 4558stp_module_t stp_module_data = 4559 { 4560 "escp2", 4561 VERSION, 4562 "Epson family driver", 4563 STP_MODULE_CLASS_FAMILY, 4564 NULL, 4565 print_escp2_module_init, 4566 print_escp2_module_exit, 4567 (void *) &print_escp2_module_data 4568 }; 4569 4570