1/* 2 * "$Id: print-canon.c,v 1.249 2011/05/01 07:40:55 gernot2270 Exp $" 3 * 4 * Print plug-in CANON BJL driver for the GIMP. 5 * 6 * Copyright 1997-2000 Michael Sweet (mike@easysw.com), 7 * Robert Krawitz (rlk@alum.mit.edu) and 8 * Andy Thaller (thaller@ph.tum.de) 9 * 10 * Copyright (c) 2006 - 2007 Sascha Sommer (saschasommer@freenet.de) 11 * 12 * This program is free software; you can redistribute it and/or modify it 13 * under the terms of the GNU General Public License as published by the Free 14 * Software Foundation; either version 2 of the License, or (at your option) 15 * any later version. 16 * 17 * This program is distributed in the hope that it will be useful, but 18 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 19 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 20 * for more details. 21 * 22 * You should have received a copy of the GNU General Public License 23 * along with this program; if not, write to the Free Software 24 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 25 */ 26 27/* 28 * This file must include only standard C header files. The core code must 29 * compile on generic platforms that don't support glib, gimp, gtk, etc. 30 */ 31 32/* 33 * Large parts of this file (mainly the ink handling) is based on 34 * print-escp2.c -- refer to README.new-printer on how to adjust the colors 35 * for a certain model. 36 */ 37 38/* TODO-LIST 39 * 40 * * adjust the colors of all supported models 41 * 42 */ 43#ifdef HAVE_CONFIG_H 44#include <config.h> 45#endif 46#include <gutenprint/gutenprint.h> 47#include "gutenprint-internal.h" 48#include <gutenprint/gutenprint-intl-internal.h> 49#include <string.h> 50#include <stdio.h> 51#if defined(HAVE_VARARGS_H) && !defined(HAVE_STDARG_H) 52#include <varargs.h> 53#else 54#include <stdarg.h> 55#endif 56#ifdef HAVE_LIMITS_H 57#include <limits.h> 58#endif 59#include <math.h> 60 61#include "print-canon.h" 62 63#ifndef MIN 64# define MIN(a,b) (((a)<(b)) ? (a) : (b)) 65#endif /* !MIN */ 66#ifndef MAX 67# define MAX(a, b) ((a) > (b) ? (a) : (b)) 68#endif /* !MAX */ 69 70 71 72 73 74 75 76static int 77pack_pixels(unsigned char* buf,int len) 78{ 79 int read_pos = 0; 80 int write_pos = 0; 81 int shift = 6; 82 while(read_pos < len) 83 { 84 /* read 5pixels a 2 bit */ 85 unsigned short value = buf[read_pos] << 8; 86 if(read_pos+1 < len) 87 value += buf[read_pos + 1]; 88 if(shift) /*6,4,2,0*/ 89 value >>= shift; 90 /* write 8bit value representing the 10 bit pixel combination */ 91 buf[write_pos] = tentoeight[value & 1023]; 92 ++write_pos; 93 if(shift == 0) 94 { 95 shift = 6; 96 read_pos += 2; 97 } 98 else 99 { 100 shift -= 2; 101 ++read_pos; 102 } 103 } 104 return write_pos; 105} 106 107/* model peculiarities */ 108#define CANON_CAP_MSB_FIRST 0x02ul /* how to send data */ 109#define CANON_CAP_a 0x04ul 110#define CANON_CAP_b 0x08ul 111#define CANON_CAP_q 0x10ul 112#define CANON_CAP_m 0x20ul 113#define CANON_CAP_d 0x40ul 114#define CANON_CAP_t 0x80ul 115#define CANON_CAP_c 0x100ul 116#define CANON_CAP_p 0x200ul 117#define CANON_CAP_l 0x400ul 118#define CANON_CAP_r 0x800ul 119#define CANON_CAP_g 0x1000ul 120#define CANON_CAP_px 0x2000ul 121#define CANON_CAP_rr 0x4000ul 122#define CANON_CAP_I 0x8000ul 123#define CANON_CAP_T 0x10000ul /* not sure of this yet! */ 124#define CANON_CAP_P 0x20000ul 125#define CANON_CAP_DUPLEX 0x40000ul 126#define CANON_CAP_XML 0x80000ul /* not sure of this yet */ 127#define CANON_CAP_CARTRIDGE 0x100000ul /* not sure of this yet */ 128 129#define CANON_CAP_STD0 (CANON_CAP_b|CANON_CAP_c|CANON_CAP_d|\ 130 CANON_CAP_l|CANON_CAP_q|CANON_CAP_t) 131 132#define CANON_CAP_STD1 (CANON_CAP_b|CANON_CAP_c|CANON_CAP_d|CANON_CAP_l|\ 133 CANON_CAP_m|CANON_CAP_p|CANON_CAP_q|CANON_CAP_t) 134 135#include "canon-inks.h" 136#include "canon-modes.h" 137#include "canon-media.h" 138#include "canon-printers.h" 139 140 141typedef struct { 142 char name; 143 const canon_ink_t* props; 144 unsigned char* buf; 145 unsigned char* comp_buf_offset; 146 unsigned int buf_length; 147 unsigned int delay; 148} canon_channel_t; 149 150 151 152typedef struct 153{ 154 const canon_mode_t* mode; 155 const canon_slot_t* slot; 156 const canon_paper_t *pt; 157 unsigned int used_inks; 158 int num_channels; 159 int quality; 160 canon_channel_t* channels; 161 char* channel_order; 162 const canon_cap_t *caps; 163 unsigned char *comp_buf; 164 unsigned char *fold_buf; 165 int delay_max; 166 int buf_length_max; 167 int length; 168 int out_width; 169 int out_height; 170 int page_width; 171 int page_height; 172 int top; 173 int left; 174 int emptylines; 175 int ncolors; /* number of colors to print with */ 176 int physical_xdpi, nozzle_ydpi, stepper_ydpi; 177 int nozzles; /* count of inkjets for one pass */ 178 int nozzle_separation; 179 int horizontal_passes; 180 int vertical_passes; 181 int vertical_oversample; 182 int *head_offset; 183 int last_pass_offset; 184 int bidirectional; /* tells us if we are allowed to print bidirectional */ 185 int direction; /* stores the last direction of the print head */ 186 int weave_bits[4]; 187 const char *duplex_str; 188 int is_first_page; 189 double cd_inner_radius; 190 double cd_outer_radius; 191} canon_privdata_t; 192 193static void canon_write_line(stp_vars_t *v); 194 195static void canon_advance_paper(stp_vars_t *, int); 196static void canon_flush_pass(stp_vars_t *, int, int); 197static void canon_write_multiraster(stp_vars_t *v,canon_privdata_t* pd,int y); 198 199static const stp_parameter_t the_parameters[] = 200{ 201 { 202 "PageSize", N_("Page Size"), "Color=No,Category=Basic Printer Setup", 203 N_("Size of the paper being printed to"), 204 STP_PARAMETER_TYPE_STRING_LIST, STP_PARAMETER_CLASS_CORE, 205 STP_PARAMETER_LEVEL_BASIC, 1, 1, STP_CHANNEL_NONE, 1, 0 206 }, 207 { 208 "MediaType", N_("Media Type"), "Color=Yes,Category=Basic Printer Setup", 209 N_("Type of media (plain paper, photo paper, etc.)"), 210 STP_PARAMETER_TYPE_STRING_LIST, STP_PARAMETER_CLASS_FEATURE, 211 STP_PARAMETER_LEVEL_BASIC, 1, 1, STP_CHANNEL_NONE, 1, 0 212 }, 213 { 214 "InputSlot", N_("Media Source"), "Color=No,Category=Basic Printer Setup", 215 N_("Source (input slot) of the media"), 216 STP_PARAMETER_TYPE_STRING_LIST, STP_PARAMETER_CLASS_FEATURE, 217 STP_PARAMETER_LEVEL_BASIC, 1, 1, STP_CHANNEL_NONE, 1, 0 218 }, 219 { 220 "CDInnerRadius", N_("CD Hub Size"), "Color=No,Category=Basic Printer Setup", 221 N_("Print only outside of the hub of the CD, or all the way to the hole"), 222 STP_PARAMETER_TYPE_STRING_LIST, STP_PARAMETER_CLASS_FEATURE, 223 STP_PARAMETER_LEVEL_BASIC, 1, 1, STP_CHANNEL_NONE, 1, 0 224 }, 225 { 226 "CDOuterDiameter", N_("CD Size (Custom)"), "Color=No,Category=Basic Printer Setup", 227 N_("Variable adjustment for the outer diameter of CD"), 228 STP_PARAMETER_TYPE_DIMENSION, STP_PARAMETER_CLASS_FEATURE, 229 STP_PARAMETER_LEVEL_ADVANCED, 1, 1, STP_CHANNEL_NONE, 1, 0 230 }, 231 { 232 "CDInnerDiameter", N_("CD Hub Size (Custom)"), "Color=No,Category=Basic Printer Setup", 233 N_("Variable adjustment to the inner hub of the CD"), 234 STP_PARAMETER_TYPE_DIMENSION, STP_PARAMETER_CLASS_FEATURE, 235 STP_PARAMETER_LEVEL_ADVANCED, 1, 1, STP_CHANNEL_NONE, 1, 0 236 }, 237 { 238 "CDXAdjustment", N_("CD Horizontal Fine Adjustment"), "Color=No,Category=Advanced Printer Setup", 239 N_("Fine adjustment to horizontal position for CD printing"), 240 STP_PARAMETER_TYPE_DIMENSION, STP_PARAMETER_CLASS_FEATURE, 241 STP_PARAMETER_LEVEL_ADVANCED, 1, 1, STP_CHANNEL_NONE, 1, 0 242 }, 243 { 244 "CDYAdjustment", N_("CD Vertical Fine Adjustment"), "Color=No,Category=Advanced Printer Setup", 245 N_("Fine adjustment to horizontal position for CD printing"), 246 STP_PARAMETER_TYPE_DIMENSION, STP_PARAMETER_CLASS_FEATURE, 247 STP_PARAMETER_LEVEL_ADVANCED, 1, 1, STP_CHANNEL_NONE, 1, 0 248 }, 249 { 250 "Resolution", N_("Resolution"), "Color=Yes,Category=Basic Printer Setup", 251 N_("Resolution and quality of the print"), 252 STP_PARAMETER_TYPE_STRING_LIST, STP_PARAMETER_CLASS_FEATURE, 253 STP_PARAMETER_LEVEL_BASIC, 1, 1, STP_CHANNEL_NONE, 1, 0 254 }, 255 { 256 "InkType", N_("Ink Type"), "Color=Yes,Category=Advanced Printer Setup", 257 N_("Type of ink in the printer"), 258 STP_PARAMETER_TYPE_STRING_LIST, STP_PARAMETER_CLASS_FEATURE, 259 STP_PARAMETER_LEVEL_BASIC, 1, 1, STP_CHANNEL_NONE, 1, 0 260 }, 261 { 262 "InkChannels", N_("Ink Channels"), "Color=Yes,Category=Advanced Printer Functionality", 263 N_("Ink Channels"), 264 STP_PARAMETER_TYPE_INT, STP_PARAMETER_CLASS_FEATURE, 265 STP_PARAMETER_LEVEL_INTERNAL, 0, 0, STP_CHANNEL_NONE, 0, 0 266 }, 267 { 268 "PrintingMode", N_("Printing Mode"), "Color=Yes,Category=Core Parameter", 269 N_("Printing Output Mode"), 270 STP_PARAMETER_TYPE_STRING_LIST, STP_PARAMETER_CLASS_CORE, 271 STP_PARAMETER_LEVEL_BASIC, 1, 1, STP_CHANNEL_NONE, 1, 0 272 }, 273 { 274 "Duplex", N_("Double-Sided Printing"), "Color=No,Category=Basic Printer Setup", 275 N_("Duplex/Tumble Setting"), 276 STP_PARAMETER_TYPE_STRING_LIST, STP_PARAMETER_CLASS_FEATURE, 277 STP_PARAMETER_LEVEL_BASIC, 1, 1, STP_CHANNEL_NONE, 1, 0 278 }, 279 { 280 "Quality", N_("Print Quality"), "Color=Yes,Category=Basic Output Adjustment", 281 N_("Print Quality"), 282 STP_PARAMETER_TYPE_STRING_LIST, STP_PARAMETER_CLASS_FEATURE, 283 STP_PARAMETER_LEVEL_BASIC, 1, 1, STP_CHANNEL_NONE, 0, 0 284 }, 285}; 286 287static const int the_parameter_count = 288sizeof(the_parameters) / sizeof(const stp_parameter_t); 289 290typedef struct 291{ 292 const stp_parameter_t param; 293 double min; 294 double max; 295 double defval; 296 int color_only; 297} float_param_t; 298 299static const float_param_t float_parameters[] = 300{ 301 { 302 { 303 "CyanDensity", N_("Cyan Density"), "Color=Yes,Category=Output Level Adjustment", 304 N_("Adjust the cyan density"), 305 STP_PARAMETER_TYPE_DOUBLE, STP_PARAMETER_CLASS_OUTPUT, 306 STP_PARAMETER_LEVEL_ADVANCED, 0, 1, 1, 1, 0 307 }, 0.0, 2.0, 1.0, 1 308 }, 309 { 310 { 311 "MagentaDensity", N_("Magenta Density"), "Color=Yes,Category=Output Level Adjustment", 312 N_("Adjust the magenta density"), 313 STP_PARAMETER_TYPE_DOUBLE, STP_PARAMETER_CLASS_OUTPUT, 314 STP_PARAMETER_LEVEL_ADVANCED, 0, 1, 2, 1, 0 315 }, 0.0, 2.0, 1.0, 1 316 }, 317 { 318 { 319 "YellowDensity", N_("Yellow Density"), "Color=Yes,Category=Output Level Adjustment", 320 N_("Adjust the yellow density"), 321 STP_PARAMETER_TYPE_DOUBLE, STP_PARAMETER_CLASS_OUTPUT, 322 STP_PARAMETER_LEVEL_ADVANCED, 0, 1, 3, 1, 0 323 }, 0.0, 2.0, 1.0, 1 324 }, 325 { 326 { 327 "BlackDensity", N_("Black Density"), "Color=Yes,Category=Output Level Adjustment", 328 N_("Adjust the black density"), 329 STP_PARAMETER_TYPE_DOUBLE, STP_PARAMETER_CLASS_OUTPUT, 330 STP_PARAMETER_LEVEL_ADVANCED, 0, 1, 0, 1, 0 331 }, 0.0, 2.0, 1.0, 1 332 }, 333 { 334 { 335 "LightCyanTrans", N_("Light Cyan Transition"), "Color=Yes,Category=Advanced Ink Adjustment", 336 N_("Light Cyan Transition"), 337 STP_PARAMETER_TYPE_DOUBLE, STP_PARAMETER_CLASS_OUTPUT, 338 STP_PARAMETER_LEVEL_ADVANCED4, 0, 1, STP_CHANNEL_NONE, 1, 0 339 }, 0.0, 5.0, 1.0, 1 340 }, 341 { 342 { 343 "LightMagentaTrans", N_("Light Magenta Transition"), "Color=Yes,Category=Advanced Ink Adjustment", 344 N_("Light Magenta Transition"), 345 STP_PARAMETER_TYPE_DOUBLE, STP_PARAMETER_CLASS_OUTPUT, 346 STP_PARAMETER_LEVEL_ADVANCED4, 0, 1, STP_CHANNEL_NONE, 1, 0 347 }, 0.0, 5.0, 1.0, 1 348 }, 349 { 350 { 351 "LightYellowTrans", N_("Light Yellow Transition"), "Color=Yes,Category=Advanced Ink Adjustment", 352 N_("Light Yellow Transition"), 353 STP_PARAMETER_TYPE_DOUBLE, STP_PARAMETER_CLASS_OUTPUT, 354 STP_PARAMETER_LEVEL_ADVANCED4, 0, 1, STP_CHANNEL_NONE, 1, 0 355 }, 0.0, 5.0, 1.0, 1 356 }, 357}; 358 359 360static const int float_parameter_count = 361sizeof(float_parameters) / sizeof(const float_param_t); 362 363/* 364 * Duplex support - modes available 365 * Note that the internal names MUST match those in cups/genppd.c else the 366 * PPD files will not be generated correctly 367 */ 368 369static const stp_param_string_t duplex_types[] = 370{ 371 { "None", N_ ("Off") }, 372 { "DuplexNoTumble", N_ ("Long Edge (Standard)") }, 373 { "DuplexTumble", N_ ("Short Edge (Flip)") } 374}; 375#define NUM_DUPLEX (sizeof (duplex_types) / sizeof (stp_param_string_t)) 376 377 378 379static const canon_paper_t * 380get_media_type(const canon_cap_t* caps,const char *name) 381{ 382 int i; 383 if (name && caps->paperlist) 384 for (i = 0; i < caps->paperlist->count; i++) 385 { 386 /* translate paper_t.name */ 387 if (!strcmp(name, caps->paperlist->papers[i].name)) 388 return &(caps->paperlist->papers[i]); 389 } 390 return &(caps->paperlist->papers[0]); 391} 392 393 394static const char* canon_families[] = { 395 "", /* the old BJC printers */ 396 "S", 397 "i", 398 "PIXMA iP", 399 "PIXMA iX", 400 "PIXMA MP", 401 "PIXUS", 402 "PIXMA Pro", 403 "PIXMA MG", 404 "PIXMA MX", 405}; 406 407/* canon model ids look like the following 408 FFMMMMMM 409 FF: family is the offset in the canon_families struct 410 MMMMMM: model nr 411*/ 412static char* canon_get_printername(const stp_vars_t* v) 413{ 414 unsigned int model = stp_get_model_id(v); 415 unsigned int family = model / 1000000; 416 unsigned int nr = model - family * 1000000; 417 char* name; 418 size_t len; 419 if(family >= sizeof(canon_families) / sizeof(canon_families[0])){ 420 stp_erprintf("canon_get_printername: no family %i using default BJC\n", family); 421 family = 0; 422 } 423 len = strlen(canon_families[family]) + 7; /* max model nr. + terminating 0 */ 424 name = stp_zalloc(len); 425 snprintf(name,len,"%s%u",canon_families[family],nr); 426 return name; 427} 428 429 430 431 432static const canon_cap_t * canon_get_model_capabilities(const stp_vars_t*v) 433{ 434 int i; 435 char* name = canon_get_printername(v); 436 int models= sizeof(canon_model_capabilities) / sizeof(canon_cap_t); 437 for (i=0; i<models; i++) { 438 if (!strcmp(canon_model_capabilities[i].name,name)) { 439 stp_free(name); 440 return &(canon_model_capabilities[i]); 441 } 442 } 443 stp_erprintf("canon: model %s not found in capabilities list=> using default\n",name); 444 stp_free(name); 445 return &(canon_model_capabilities[0]); 446} 447 448static const canon_slot_t * 449canon_source_type(const char *name, const canon_cap_t * caps) 450{ 451 if(name){ 452 int i; 453 for(i=0; i<caps->slotlist->count; i++){ 454 if( !strcmp(name,caps->slotlist->slots[i].name)) 455 return &(caps->slotlist->slots[i]); 456 } 457 } 458 return &(caps->slotlist->slots[0]); 459} 460 461 462/* function returns the current set printmode (specified by resolution) */ 463/* if no mode is set the default mode will be returned */ 464static const canon_mode_t* canon_get_current_mode(const stp_vars_t *v){ 465 const char* input_slot = stp_get_string_parameter(v, "InputSlot"); 466 const char *resolution = stp_get_string_parameter(v, "Resolution"); 467 const char *quality = stp_get_string_parameter(v, "Quality"); 468 const canon_cap_t * caps = canon_get_model_capabilities(v); 469 const canon_mode_t* mode = NULL; 470 int i; 471 472 if(resolution){ 473 for(i=0;i<caps->modelist->count;i++){ 474 if(!strcmp(resolution,caps->modelist->modes[i].name)){ 475 mode = &caps->modelist->modes[i]; 476 break; 477 } 478 } 479 } 480 481 if(!mode) 482 mode = &caps->modelist->modes[caps->modelist->default_mode]; 483 484#if 0 485 if(quality && strcmp(quality, "None") == 0) 486 quality = "Standard"; 487 488 if(quality && !strcmp(quality,"Standard")){ 489 return &caps->modelist->modes[caps->modelist->default_mode]; 490 } 491#endif 492 493#if 0 494 /* only some modes can print to cd */ 495 if(input_slot && !strcmp(input_slot,"CD") && !(mode->flags & MODE_FLAG_CD)){ 496 for(i=0;i<caps->modelist->count;i++){ 497 if(caps->modelist->modes[i].flags & MODE_FLAG_CD){ 498 mode = &caps->modelist->modes[i]; 499 break; 500 } 501 } 502 } 503#endif 504 505 506 507 508 509 return mode; 510} 511 512/* function returns the best ink_type for the current mode */ 513static unsigned int 514canon_printhead_colors(const stp_vars_t*v) 515{ 516 int i; 517 const canon_mode_t* mode; 518 const char *print_mode = stp_get_string_parameter(v, "PrintingMode"); 519 const char *ink_type = stp_get_string_parameter(v, "InkType"); 520 if(print_mode && strcmp(print_mode, "BW") == 0) 521 return CANON_INK_K; 522 523 if(ink_type){ 524 for(i=0;i<sizeof(canon_inktypes)/sizeof(canon_inktypes[0]);i++){ 525 if(ink_type && !strcmp(canon_inktypes[i].name,ink_type)) 526 return canon_inktypes[i].ink_type; 527 } 528 } 529 mode = canon_get_current_mode(v); 530 for(i=0;i<sizeof(canon_inktypes)/sizeof(canon_inktypes[0]);i++){ 531 if(mode->ink_types & canon_inktypes[i].ink_type) 532 return canon_inktypes[i].ink_type; 533 } 534 return CANON_INK_K; 535} 536 537static unsigned char 538canon_size_type(const stp_vars_t *v, const canon_cap_t * caps) 539{ 540 const stp_papersize_t *pp = stp_get_papersize_by_size(stp_get_page_height(v), 541 stp_get_page_width(v)); 542 if (pp) 543 { 544 const char *name = pp->name; 545 /* used internally: do not translate */ 546 /* built ins: Japanese driver notation */ 547 if (!strcmp(name,"A5")) return 0x01; 548 if (!strcmp(name,"A4")) return 0x03; 549 if (!strcmp(name,"A3")) return 0x05; 550 if (!strcmp(name,"B5")) return 0x08; 551 if (!strcmp(name,"B4")) return 0x0a; 552 if (!strcmp(name,"Letter")) return 0x0d; 553 if (!strcmp(name,"Legal")) return 0x0f; 554 if (!strcmp(name,"Tabloid")) return 0x11; /* 11x17 */ 555 if (!strcmp(name,"w283h420")) return 0x14; /* Hagaki */ 556 if (!strcmp(name,"COM10")) return 0x16; 557 if (!strcmp(name,"DL")) return 0x17; 558 if (!strcmp(name,"LetterExtra")) return 0x2a; 559 if (!strcmp(name,"A4Extra")) return 0x2b; 560 if (!strcmp(name,"A3plus")) return 0x2c; /* A3navi --- A3+ */ 561 if (!strcmp(name,"w288h144")) return 0x2d; 562 if (!strcmp(name,"w252h360J")) return 0x32; /* L --- similar to US 3.5x5 size */ 563 if (!strcmp(name,"w360h504J")) return 0x33; /* 2L --- similar to US5x7 */ 564 if (!strcmp(name,"w288h432J")) return 0x34; /* KG --- same size as US 4x6 */ 565 if (!strcmp(name,"w360h504")) return 0x37; /* US5x7 */ 566 if (!strcmp(name,"w420h567")) return 0x39; /* Ofuku Hagaki */ 567 if (!strcmp(name,"w288h576")) return 0x46; /* US4x8 */ 568 if (!strcmp(name,"w1008h1224J")) return 0x47; /* HanKire --- 14in x 17in */ 569 if (!strcmp(name,"720h864J")) return 0x48; /* YonKire --- 10in x 12 in*/ 570 if (!strcmp(name,"c8x10J")) return 0x49; /* RokuKire --- same size as 8x10 */ 571 if (!strcmp(name,"w288h512")) return 0x52; /* Wide101.6x180.6 */ 572 /* custom */ 573 574 stp_deprintf(STP_DBG_CANON,"canon: Unknown paper size '%s' - using custom\n",name); 575 } else { 576 stp_deprintf(STP_DBG_CANON,"canon: Couldn't look up paper size %dx%d - " 577 "using custom\n",stp_get_page_height(v), stp_get_page_width(v)); 578 } 579 return 0; 580} 581 582static void 583canon_describe_resolution(const stp_vars_t *v, int *x, int *y) 584{ 585 const canon_mode_t* mode = canon_get_current_mode(v); 586 *x = mode->xdpi; 587 *y = mode->ydpi; 588} 589 590static const char * 591canon_describe_output(const stp_vars_t *v) 592{ 593 unsigned int ink_type = canon_printhead_colors(v); 594 595 if(ink_type & CANON_INK_CMYK_MASK) 596 return "CMYK"; 597 if(ink_type & CANON_INK_CMY_MASK) 598 return "CMY"; 599 return "Grayscale"; 600} 601 602/* 603 * 'canon_parameters()' - Return the parameter values for the given parameter. 604 */ 605 606static stp_parameter_list_t 607canon_list_parameters(const stp_vars_t *v) 608{ 609 stp_parameter_list_t *ret = stp_parameter_list_create(); 610 int i; 611 for (i = 0; i < the_parameter_count; i++) 612 stp_parameter_list_add_param(ret, &(the_parameters[i])); 613 for (i = 0; i < float_parameter_count; i++) 614 stp_parameter_list_add_param(ret, &(float_parameters[i].param)); 615 return ret; 616} 617 618static void 619canon_parameters(const stp_vars_t *v, const char *name, 620 stp_parameter_t *description) 621{ 622 int i; 623 624 const canon_cap_t * caps= 625 canon_get_model_capabilities(v); 626 description->p_type = STP_PARAMETER_TYPE_INVALID; 627 628 if (name == NULL) 629 return; 630 631 for (i = 0; i < float_parameter_count; i++) 632 if (strcmp(name, float_parameters[i].param.name) == 0) 633 { 634 unsigned int ink_type = canon_printhead_colors(v); 635 636 stp_fill_parameter_settings(description, 637 &(float_parameters[i].param)); 638 description->deflt.dbl = float_parameters[i].defval; 639 description->bounds.dbl.upper = float_parameters[i].max; 640 description->bounds.dbl.lower = float_parameters[i].min; 641 if (ink_type != CANON_INK_K || !float_parameters[i].color_only) 642 description->is_active = 1; 643 else 644 description->is_active = 0; 645 return; 646 } 647 648 for (i = 0; i < the_parameter_count; i++) 649 if (strcmp(name, the_parameters[i].name) == 0) 650 { 651 stp_fill_parameter_settings(description, &(the_parameters[i])); 652 break; 653 } 654 if (strcmp(name, "PageSize") == 0) 655 { 656 const char* input_slot = stp_get_string_parameter(v, "InputSlot"); 657 int height_limit, width_limit; 658 int papersizes = stp_known_papersizes(); 659 description->bounds.str = stp_string_list_create(); 660 661 width_limit = caps->max_width; 662 height_limit = caps->max_height; 663 664 if(input_slot && !strcmp(input_slot,"CD")){ 665 stp_string_list_add_string 666 (description->bounds.str, "CD5Inch", _("CD - 5 inch")); 667 stp_string_list_add_string 668 (description->bounds.str, "CD3Inch", _("CD - 3 inch")); 669 stp_string_list_add_string 670 (description->bounds.str, "CDCustom", _("CD - Custom")); 671 }else{ 672 for (i = 0; i < papersizes; i++) { 673 const stp_papersize_t *pt = stp_get_papersize_by_index(i); 674 if (strlen(pt->name) > 0 && 675 pt->width <= width_limit && pt->height <= height_limit){ 676 stp_string_list_add_string(description->bounds.str, 677 pt->name, gettext(pt->text)); 678 } 679 } 680 } 681 description->deflt.str = 682 stp_string_list_param(description->bounds.str, 0)->name; 683 } 684 else if (strcmp(name, "CDInnerRadius") == 0 ) 685 { 686 const char* input_slot = stp_get_string_parameter(v, "InputSlot"); 687 description->bounds.str = stp_string_list_create(); 688 if (input_slot && !strcmp(input_slot,"CD") && 689 (!stp_get_string_parameter(v, "PageSize") || 690 strcmp(stp_get_string_parameter(v, "PageSize"), "CDCustom") != 0)) 691 { 692 stp_string_list_add_string 693 (description->bounds.str, "None", _("Normal")); 694 stp_string_list_add_string 695 (description->bounds.str, "Small", _("Print To Hub")); 696 description->deflt.str = 697 stp_string_list_param(description->bounds.str, 0)->name; 698 } 699 else 700 description->is_active = 0; 701 } 702 else if (strcmp(name, "CDInnerDiameter") == 0 ) 703 { 704 const char* input_slot = stp_get_string_parameter(v, "InputSlot"); 705 description->bounds.dimension.lower = 16 * 10 * 72 / 254; 706 description->bounds.dimension.upper = 43 * 10 * 72 / 254; 707 description->deflt.dimension = 43 * 10 * 72 / 254; 708 if (input_slot && !strcmp(input_slot,"CD") && 709 (!stp_get_string_parameter(v, "PageSize") || 710 strcmp(stp_get_string_parameter(v, "PageSize"), "CDCustom") == 0)) 711 description->is_active = 1; 712 else 713 description->is_active = 0; 714 } 715 else if (strcmp(name, "CDOuterDiameter") == 0 ) 716 { 717 const char* input_slot = stp_get_string_parameter(v, "InputSlot"); 718 description->bounds.dimension.lower = 65 * 10 * 72 / 254; 719 description->bounds.dimension.upper = 120 * 10 * 72 / 254; 720 description->deflt.dimension = 329; 721 if (input_slot && !strcmp(input_slot,"CD") && 722 (!stp_get_string_parameter(v, "PageSize") || 723 strcmp(stp_get_string_parameter(v, "PageSize"), "CDCustom") == 0)) 724 description->is_active = 1; 725 else 726 description->is_active = 0; 727 } 728 else if (strcmp(name, "CDXAdjustment") == 0 || 729 strcmp(name, "CDYAdjustment") == 0) 730 { 731 const char* input_slot = stp_get_string_parameter(v, "InputSlot"); 732 description->bounds.dimension.lower = -15; 733 description->bounds.dimension.upper = 15; 734 description->deflt.dimension = 0; 735 if (input_slot && !strcmp(input_slot,"CD")) 736 description->is_active = 1; 737 else 738 description->is_active = 0; 739 } 740 else if (strcmp(name, "Resolution") == 0) 741 { 742 const char* input_slot = stp_get_string_parameter(v, "InputSlot"); 743 description->bounds.str= stp_string_list_create(); 744 description->deflt.str = NULL; 745 for(i=0;i<caps->modelist->count;i++){ 746#if 0 747 if(!(input_slot && !strcmp(input_slot,"CD") && !(caps->modelist->modes[i].flags & MODE_FLAG_CD))) 748#endif 749 stp_string_list_add_string(description->bounds.str, 750 caps->modelist->modes[i].name, gettext(caps->modelist->modes[i].text)); 751 stp_deprintf(STP_DBG_CANON,"supports mode '%s'\n", 752 caps->modelist->modes[i].name); 753 if(i == caps->modelist->default_mode) 754 description->deflt.str=caps->modelist->modes[i].name; 755 756 757 } 758 } 759 else if (strcmp(name, "InkType") == 0) 760 { 761 const canon_mode_t* mode = canon_get_current_mode(v); 762 description->bounds.str= stp_string_list_create(); 763 for(i=0;i<sizeof(canon_inktypes)/sizeof(canon_inktypes[0]);i++){ 764 if(mode->ink_types & canon_inktypes[i].ink_type){ 765 stp_string_list_add_string(description->bounds.str,canon_inktypes[i].name,_(canon_inktypes[i].text)); 766 } 767 } 768 description->deflt.str = stp_string_list_param(description->bounds.str, 0)->name; 769 } 770 else if (strcmp(name, "InkChannels") == 0) 771 { 772 unsigned int ink_type = canon_printhead_colors(v); 773 for(i=0;i<sizeof(canon_inktypes)/sizeof(canon_inktypes[0]);i++){ 774 if(ink_type == canon_inktypes[i].ink_type) 775 description->deflt.integer = canon_inktypes[i].num_channels; 776 } 777 description->bounds.integer.lower = -1; 778 description->bounds.integer.upper = -1; 779 } 780 else if (strcmp(name, "MediaType") == 0) 781 { 782 const canon_paper_t * canon_paper_list = caps->paperlist->papers; 783 int count = caps->paperlist->count; 784 description->bounds.str= stp_string_list_create(); 785 description->deflt.str= canon_paper_list[0].name; 786 787 for (i = 0; i < count; i ++) 788 stp_string_list_add_string(description->bounds.str, 789 canon_paper_list[i].name, 790 gettext(canon_paper_list[i].text)); 791 } 792 else if (strcmp(name, "InputSlot") == 0) 793 { 794 const canon_slot_t * canon_slot_list = caps->slotlist->slots; 795 int count = caps->slotlist->count; 796 description->bounds.str= stp_string_list_create(); 797 description->deflt.str= canon_slot_list[0].name; 798 799 for (i = 0; i < count; i ++) 800 stp_string_list_add_string(description->bounds.str, 801 canon_slot_list[i].name, 802 gettext(canon_slot_list[i].text)); 803 } 804 else if (strcmp(name, "PrintingMode") == 0) 805 { 806 const canon_mode_t* mode = canon_get_current_mode(v); 807 description->bounds.str = stp_string_list_create(); 808 if (mode->ink_types != CANON_INK_K) 809 stp_string_list_add_string 810 (description->bounds.str, "Color", _("Color")); 811 stp_string_list_add_string 812 (description->bounds.str, "BW", _("Black and White")); 813 description->deflt.str = 814 stp_string_list_param(description->bounds.str, 0)->name; 815 } 816 else if (strcmp(name, "Duplex") == 0) 817 { 818 int offer_duplex=0; 819 820 description->bounds.str = stp_string_list_create(); 821 822/* 823 * Don't offer the Duplex/Tumble options if the JobMode parameter is 824 * set to "Page" Mode. 825 * "Page" mode is set by the Gimp Plugin, which only outputs one page at a 826 * time, so Duplex/Tumble is meaningless. 827 */ 828 829 if (stp_get_string_parameter(v, "JobMode")) 830 offer_duplex = strcmp(stp_get_string_parameter(v, "JobMode"), "Page"); 831 else 832 offer_duplex=1; 833 834 if (offer_duplex && (caps->features & CANON_CAP_DUPLEX)) 835 { 836 description->deflt.str = duplex_types[0].name; 837 for (i=0; i < NUM_DUPLEX; i++) 838 { 839 stp_string_list_add_string(description->bounds.str, 840 duplex_types[i].name,gettext(duplex_types[i].text)); 841 } 842 } 843 else 844 description->is_active = 0; 845 } 846 else if (strcmp(name, "Quality") == 0) 847 { 848 int has_standard_quality = 0; 849 description->bounds.str = stp_string_list_create(); 850 stp_string_list_add_string(description->bounds.str, "None", 851 _("Manual Control")); 852 stp_string_list_add_string(description->bounds.str, "Standard", 853 _("Standard")); 854 description->deflt.str = "Standard"; 855 } 856 /* Cartridge selection for those printers that have it */ 857 else if (strcmp(name, "Cartridge") == 0) 858 { 859 int offer_cartridge_selection = 0; 860 description->bounds.str = stp_string_list_create(); 861 stp_string_list_add_string(description->bounds.str, "Both", 862 _("Both")); 863 stp_string_list_add_string(description->bounds.str, "Color", 864 _("Color")); 865 stp_string_list_add_string(description->bounds.str, "Black", 866 _("Black")); 867 868 /* description->deflt.str = "Both"; */ 869 /* Note: not necessary set cartridge if Mono mode */ 870 871 if (caps->features & CANON_CAP_CARTRIDGE) 872 { 873 description->deflt.str = 874 stp_string_list_param(description->bounds.str, 0)->name; 875 } 876 else 877 description->is_active = 0; 878 } 879 880} 881 882 883/* 884 * 'canon_imageable_area()' - Return the imageable area of the page. 885 */ 886 887static void 888internal_imageable_area(const stp_vars_t *v, /* I */ 889 int use_paper_margins, 890 int *left, /* O - Left position in points */ 891 int *right, /* O - Right position in points */ 892 int *bottom, /* O - Bottom position in points */ 893 int *top) /* O - Top position in points */ 894{ 895 int width, length; /* Size of page */ 896 int left_margin = 0; 897 int right_margin = 0; 898 int bottom_margin = 0; 899 int top_margin = 0; 900 int cd = 0; 901 902 const canon_cap_t * caps= canon_get_model_capabilities(v); 903 const char *media_size = stp_get_string_parameter(v, "PageSize"); 904 const stp_papersize_t *pt = NULL; 905 const char* input_slot = stp_get_string_parameter(v, "InputSlot"); 906 907 if(input_slot && !strcmp(input_slot,"CD")) 908 cd = 1; 909 910 if (media_size && use_paper_margins) 911 pt = stp_get_papersize_by_name(media_size); 912 913 stp_default_media_size(v, &width, &length); 914 if (pt) 915 { 916 left_margin = pt->left; 917 right_margin = pt->right; 918 bottom_margin = pt->bottom; 919 top_margin = pt->top; 920 } 921 /* ignore printer margins for the cd print, margins get adjusted in do_print */ 922 if(!cd){ 923 left_margin = MAX(left_margin, caps->border_left); 924 right_margin = MAX(right_margin, caps->border_right); 925 top_margin = MAX(top_margin, caps->border_top); 926 bottom_margin = MAX(bottom_margin, caps->border_bottom); 927 } 928 929 *left = left_margin; 930 *right = width - right_margin; 931 *top = top_margin; 932 *bottom = length - bottom_margin; 933} 934 935static void 936canon_imageable_area(const stp_vars_t *v, /* I */ 937 int *left, /* O - Left position in points */ 938 int *right, /* O - Right position in points */ 939 int *bottom, /* O - Bottom position in points */ 940 int *top) /* O - Top position in points */ 941{ 942 internal_imageable_area(v, 1, left, right, bottom, top); 943} 944 945static void 946canon_limit(const stp_vars_t *v, /* I */ 947 int *width, 948 int *height, 949 int *min_width, 950 int *min_height) 951{ 952 const canon_cap_t * caps= 953 canon_get_model_capabilities(v); 954 *width = caps->max_width; 955 *height = caps->max_height; 956 *min_width = 1; 957 *min_height = 1; 958} 959 960/* 961 * 'canon_cmd()' - Sends a command with variable args 962 */ 963static void 964canon_cmd(const stp_vars_t *v, /* I - the printer */ 965 const char *ini, /* I - 2 bytes start code */ 966 const char cmd, /* I - command code */ 967 int num, /* I - number of arguments */ 968 ... /* I - the args themselves */ 969 ) 970{ 971 unsigned char *buffer = stp_zalloc(num + 1); 972 int i; 973 va_list ap; 974 975 if (num) 976 { 977 va_start(ap, num); 978 for (i=0; i<num; i++) 979 buffer[i]= (unsigned char) va_arg(ap, int); 980 va_end(ap); 981 } 982 983 stp_zfwrite(ini,2,1,v); 984 if (cmd) 985 { 986 stp_putc(cmd,v); 987 stp_put16_le(num, v); 988 if (num) 989 stp_zfwrite((const char *)buffer,num,1,v); 990 } 991 stp_free(buffer); 992} 993 994#define PUT(WHAT,VAL,RES) stp_deprintf(STP_DBG_CANON,"canon: "WHAT\ 995" is %04x =% 5d = %f\" = %f mm\n",(VAL),(VAL),(VAL)/(1.*RES),(VAL)/(RES/25.4)) 996 997#define ESC28 "\033\050" 998#define ESC5b "\033\133" 999#define ESC40 "\033\100" 1000 1001static void canon_control_cmd(const stp_vars_t*v,const char* cmd){ 1002 canon_cmd(v,ESC5b,0x4b, 2, 0x00,0x1f); 1003 stp_puts("BJLSTART\nControlMode=Common\n",v); 1004 stp_puts(cmd,v); 1005 stp_putc('\n',v); 1006 stp_puts("BJLEND\n",v); 1007} 1008 1009 1010/* ESC [K -- -- reset printer: 1011 */ 1012static void 1013canon_init_resetPrinter(const stp_vars_t *v, const canon_privdata_t *init) 1014{ 1015 if ( init->caps->control_cmdlist ){ 1016 int i=0; 1017 while(init->caps->control_cmdlist[i]){ 1018 canon_control_cmd(v,init->caps->control_cmdlist[i]); 1019 ++i; 1020 } 1021 } 1022 if(!strcmp(init->slot->name,"CD")) 1023 canon_control_cmd(v,"MediaDetection=ON"); 1024 canon_cmd(v,ESC5b,0x4b, 2, 0x00,0x0f); 1025} 1026 1027/* ESC ($ -- 0x24 -- cmdSetDuplex --: 1028 */ 1029static void 1030canon_init_setDuplex(const stp_vars_t *v, const canon_privdata_t *init) 1031{ 1032 if (!(init->caps->features & CANON_CAP_DUPLEX)) 1033 return; 1034 if (strncmp(init->duplex_str, "Duplex", 6)) 1035 return; 1036 /* The same command seems to be needed for both Duplex and DuplexTumble 1037 no idea about the meanings of the single bytes */ 1038 canon_cmd(v,ESC28,0x24,9,0x01,0x00,0x02,0x00,0x00,0x00,0x00,0x00,0x02); 1039} 1040 1041/* ESC (a -- 0x61 -- cmdSetPageMode --: 1042 */ 1043static void 1044canon_init_setPageMode(const stp_vars_t *v, const canon_privdata_t *init) 1045{ 1046 if (!(init->caps->features & CANON_CAP_a)) 1047 return; 1048 1049 if (init->caps->features & CANON_CAP_a) 1050 canon_cmd(v,ESC28,0x61, 1, 0x01); 1051} 1052 1053/* ESC (b -- 0x62 -- -- set data compression: 1054 */ 1055static void 1056canon_init_setDataCompression(const stp_vars_t *v, const canon_privdata_t *init) 1057{ 1058 if (!(init->caps->features & CANON_CAP_b)) 1059 return; 1060 1061 canon_cmd(v,ESC28,0x62, 1, 0x01); 1062} 1063 1064/* ESC (c -- 0x63 -- cmdSetColor --: 1065 */ 1066static void 1067canon_init_setColor(const stp_vars_t *v, const canon_privdata_t *init) 1068{ 1069 unsigned char 1070 numargs, arg_63[6]; 1071 1072 if (!(init->caps->features & CANON_CAP_c)) 1073 return; 1074 1075 numargs = 3; 1076 arg_63[0] = init->caps->model_id << 4; /* MODEL_ID */ 1077 1078 switch ( init->caps->model_id ) { 1079 1080 case 0: /* very old 360 dpi series: BJC-800/820 */ 1081 break; /* tbd */ 1082 1083 case 1: /* 360 dpi series - BJC-4000, BJC-210, BJC-70 and their descendants */ 1084 if (init->used_inks == CANON_INK_K) 1085 arg_63[0]|= 0x01; /* PRINT_COLOUR */ 1086 1087 arg_63[1] = ((init->pt ? init->pt->media_code_c : 0) << 4) /* PRINT_MEDIA */ 1088 + 1; /* hardcode to High quality for now */ /* PRINT_QUALITY */ 1089 1090 canon_cmd(v,ESC28,0x63, 2, arg_63[0], arg_63[1]); 1091 break; 1092 1093 case 2: /* are any models using this? */ 1094 break; 1095 1096 case 3: /* 720 dpi series - BJC-3000 and descendants */ 1097 if (init->used_inks == CANON_INK_K) 1098 arg_63[0]|= 0x01; /* colour mode */ 1099 1100 arg_63[1] = (init->pt) ? init->pt->media_code_c : 0; /* print media type */ 1101 1102 if (!strcmp(init->caps->name,"S200")) /* S200 */ 1103 { 1104 if ((init->mode->xdpi == 720) && (init->mode->ydpi == 720 )) 1105 arg_63[2] = 1; 1106 else 1107 arg_63[2] = 4; /* hardcoded: quality 3 (may be 0...4) */ 1108 /* bidirectional is controlled via quality: 0..2 is bidi, 3 and 4 uni */ 1109 /* not every combination works, no idea about the principle */ 1110 if ( (init->mode->xdpi > 360) || (init->mode->ydpi > 360) ) 1111 { 1112 numargs = 6; 1113 arg_63[3] = 0x10; arg_63[4] = 6; arg_63[5] = 8; /* arg5 makes a vert. offset for K */ 1114 if (init->used_inks == CANON_INK_K) 1115 arg_63[4] = 1; 1116 } 1117 } 1118 else 1119 arg_63[2] = init->quality; /* hardcode to whatever this means for now; quality, apparently */ 1120 1121 stp_zprintf(v, "\033\050\143"); 1122 stp_put16_le(numargs, v); 1123 stp_zfwrite((const char *)arg_63, numargs, 1, v); 1124 break; 1125 } 1126 1127 return; 1128} 1129 1130/* ESC (d -- 0x64 -- -- set raster resolution: 1131 */ 1132static void 1133canon_init_setResolution(const stp_vars_t *v, const canon_privdata_t *init) 1134{ 1135 if (!(init->caps->features & CANON_CAP_d)) 1136 return; 1137 1138 if (strcmp(init->caps->name,"S200") || (init->mode->xdpi <= 360)) 1139 canon_cmd(v,ESC28,0x64, 4, 1140 (init->mode->ydpi >> 8 ), (init->mode->ydpi & 255), 1141 (init->mode->xdpi >> 8 ), (init->mode->xdpi & 255)); 1142 else 1143 if (init->mode->xdpi < 2880) 1144 canon_cmd(v,ESC28,0x64, 4, 1145 (720 >> 8), (720 & 255), 1146 (720 >> 8), (720 & 255)); 1147 else 1148 canon_cmd(v,ESC28,0x64, 4, 1149 (720 >> 8), (720 & 255), 1150 (2880 >> 8), (2880 & 255)); 1151 } 1152 1153/* ESC (g -- 0x67 -- cmdSetPageMargins --: 1154 */ 1155static void 1156canon_init_setPageMargins(const stp_vars_t *v, const canon_privdata_t *init) 1157{ 1158 /* TOFIX: what exactly is to be sent? 1159 * Is it the printable length or the bottom border? 1160 * Is is the printable width or the right border? 1161 */ 1162 1163 int minlength= 0; 1164 int minwidth= 0; 1165 int length= init->page_height*5/36; 1166 int width= init->page_width*5/36; 1167 1168 if (!(init->caps->features & CANON_CAP_g)) 1169 return; 1170 1171 if (minlength>length) length= minlength; 1172 if (minwidth>width) width= minwidth; 1173 1174 canon_cmd(v,ESC28,0x67, 4, 0, 1175 (unsigned char)(length),1, 1176 (unsigned char)(width)); 1177 1178} 1179 1180/* ESC (l -- 0x6c -- cmdSetTray --: 1181 */ 1182static void 1183canon_init_setTray(const stp_vars_t *v, const canon_privdata_t *init) 1184{ 1185 unsigned char 1186 arg_6c_1 = 0x00, 1187 arg_6c_2 = 0x00; /* plain paper */ 1188 1189 if (!(init->caps->features & CANON_CAP_l)) 1190 return; 1191 1192 arg_6c_1 = init->caps->model_id << 4; 1193 1194 arg_6c_1|= (init->slot->code & 0x0f); 1195 1196 if (init->pt) arg_6c_2= init->pt->media_code_l; 1197 if(init->caps->model_id >= 3) 1198 canon_cmd(v,ESC28,0x6c, 3, arg_6c_1, arg_6c_2, 0); 1199 else 1200 canon_cmd(v,ESC28,0x6c, 2, arg_6c_1, arg_6c_2); 1201} 1202 1203/* ESC (m -- 0x6d -- -- : 1204 */ 1205static void 1206canon_init_setPrintMode(const stp_vars_t *v, const canon_privdata_t *init) 1207{ 1208 unsigned char 1209 arg_6d_1 = 0x03, /* color printhead? */ 1210 arg_6d_2 = 0x00, /* 00=color 02=b/w */ 1211 arg_6d_3 = 0x00, /* only 01 for bjc8200 and S200*/ 1212 /* S200:for envelope and t-shirt transfer = 03 */ 1213 arg_6d_a = 0x03, /* A4 paper */ 1214 arg_6d_b = 0x00; 1215 1216 if (!(init->caps->features & CANON_CAP_m)) 1217 return; 1218 1219 arg_6d_a= canon_size_type(v,init->caps); 1220 if (!arg_6d_a) 1221 arg_6d_b= 1; 1222 1223 arg_6d_1= 0x04; 1224 if ((!strcmp(init->caps->name,"7000")) && (init->used_inks == CANON_INK_K || init->used_inks == CANON_INK_CcMmYK || init->used_inks == CANON_INK_CcMmYyK)) 1225 arg_6d_1= 0x03; 1226 1227 if (((!strcmp(init->caps->name,"8200") || !strcmp(init->caps->name,"S200")) && init->used_inks == CANON_INK_K) || init->used_inks == CANON_INK_CMYK) 1228 arg_6d_1= 0x02; 1229 1230 if(!strcmp(init->caps->name,"S200") && init->used_inks == CANON_INK_CMY) 1231 arg_6d_1= 0x02; 1232 1233 if (init->used_inks == CANON_INK_K) 1234 arg_6d_2= 0x02; 1235 1236 if (!strcmp(init->caps->name,"8200") || !strcmp(init->caps->name,"S200")) 1237 arg_6d_3= 0x01; 1238 1239 canon_cmd(v,ESC28,0x6d,12, arg_6d_1, 1240 0xff,0xff,0x00,0x00,0x07,0x00, 1241 arg_6d_a,arg_6d_b,arg_6d_2,0x00,arg_6d_3); 1242} 1243 1244/* ESC (p -- 0x70 -- cmdSetPageMargins2 --: 1245 */ 1246static void 1247canon_init_setPageMargins2(const stp_vars_t *v, const canon_privdata_t *init) 1248{ 1249 /* TOFIX: what exactly is to be sent? 1250 * Is it the printable length or the bottom border? 1251 * Is is the printable width or the right border? 1252 */ 1253 int printable_width= (init->page_width + 1)*5/6; 1254 int printable_length= (init->page_height + 1)*5/6; 1255 1256 unsigned char arg_70_1= (printable_length >> 8) & 0xff; 1257 unsigned char arg_70_2= (printable_length) & 0xff; 1258 unsigned char arg_70_3= (printable_width >> 8) & 0xff; 1259 unsigned char arg_70_4= (printable_width) & 0xff; 1260 const char* input_slot = stp_get_string_parameter(v, "InputSlot"); 1261 1262 if (!(init->caps->features & CANON_CAP_px) && !(init->caps->features & CANON_CAP_p)) 1263 return; 1264 1265 if ((init->caps->features & CANON_CAP_px) && !(input_slot && !strcmp(input_slot,"CD"))) 1266 { 1267 unsigned int unit = 600; 1268 stp_zfwrite(ESC28,2,1,v); /* ESC( */ 1269 stp_putc(0x70,v); /* p */ 1270 stp_put16_le(46, v); /* len */ 1271 stp_put16_be(printable_length,v); 1272 stp_put16_be(0,v); 1273 stp_put16_be(printable_width,v); 1274 stp_put16_be(0,v); 1275 stp_put32_be(0,v); 1276 stp_put16_be(unit,v); 1277 1278 stp_put32_be(init->caps->border_left * unit / 72,v); /* area_right */ 1279 stp_put32_be(init->caps->border_top * unit / 72,v); /* area_top */ 1280 stp_put32_be(init->page_width * unit / 72,v); /* area_width */ 1281 stp_put32_be(init->page_height * unit / 72,v); /* area_length */ 1282 stp_put32_be(0,v); /* paper_right */ 1283 stp_put32_be(0,v); /* paper_top */ 1284 stp_put32_be((init->page_width + init->caps->border_left + init->caps->border_right) * unit / 72,v); /* paper_width */ 1285 stp_put32_be((init->page_height + init->caps->border_top + init->caps->border_bottom) * unit / 72,v); /* paper_height */ 1286 return; 1287 } 1288 1289 canon_cmd(v,ESC28,0x70, 8, 1290 arg_70_1, arg_70_2, 0x00, 0x00, 1291 arg_70_3, arg_70_4, 0x00, 0x00); 1292} 1293 1294/* ESC (P -- 0x50 -- unknown -- : 1295 seems to set media and page information. Different byte lengths depending on printer model. */ 1296static void 1297canon_init_setESC_P(const stp_vars_t *v, const canon_privdata_t *init) 1298{ 1299 unsigned char arg_ESCP_2; 1300 if(!(init->caps->features & CANON_CAP_P)) 1301 return; 1302 1303 arg_ESCP_2 = (init->pt) ? init->pt->media_code_P: 0x00; 1304 1305 /* models that add two more bytes "1 0" to the end of the usual 4-byte sequence: */ 1306 /* iP2700 */ 1307 /* MX340 */ 1308 /* MX350 --- same driver as MX340 */ 1309 /* MX360 */ 1310 /* MX410 --- same driver as MX360 */ 1311 /* MX420 */ 1312 /* MX870 */ 1313 /* MX880 */ 1314 /* MP493 */ 1315 /* MP550 */ 1316 /* MP640 */ 1317 /* iX6500 */ 1318 /* iX7000 */ 1319 if ( (!strcmp(init->caps->name,"iP2700")) || (!strcmp(init->caps->name,"MX340")) || (!strcmp(init->caps->name,"MX360")) || (!strcmp(init->caps->name,"MX410")) || (!strcmp(init->caps->name,"MX420")) || (!strcmp(init->caps->name,"MX870")) || (!strcmp(init->caps->name,"MX880")) || (!strcmp(init->caps->name,"MP550")) || (!strcmp(init->caps->name,"MP493")) || (!strcmp(init->caps->name,"MP640")) || (!strcmp(init->caps->name,"iX6500")) || (!strcmp(init->caps->name,"iX7000")) || (!strcmp(init->caps->name,"iP4700")) || (!strcmp(init->caps->name,"iP4800")) ) 1320 /* add a lot more here: try if(init->caps->model_id >= 3) how to guess for 4 bytes or more */ 1321 {/* the 4th of the 6 bytes is the media type. 2nd byte is media size. Both read from canon-media array. */ 1322 1323 /* arg_ESCP_1 = 0x03; */ /* A4 size */ 1324 /* arg_ESCP_2 = 0x00; */ /* plain media */ 1325 /* size media */ 1326 canon_cmd( v,ESC28,0x50,6,0x00,0x03,0x00,arg_ESCP_2,0x01,0x00); 1327 } 1328 else 1329 /* size media */ 1330 canon_cmd( v,ESC28,0x50,4,0x00,0x03,0x00,arg_ESCP_2 ); 1331} 1332 1333/* ESC (T -- 0x54 -- setCartridge -- : 1334 */ 1335static void 1336canon_init_setCartridge(const stp_vars_t *v, const canon_privdata_t *init) 1337{ 1338 if (!(init->caps->features & CANON_CAP_T)) 1339 return; 1340 1341 canon_cmd(v,ESC28,0x54,3,0x03,0x04,0x04); /* default: both cartridges */ 1342} 1343 1344/* ESC (q -- 0x71 -- setPageID -- : 1345 */ 1346static void 1347canon_init_setPageID(const stp_vars_t *v, const canon_privdata_t *init) 1348{ 1349 if (!(init->caps->features & CANON_CAP_q)) 1350 return; 1351 1352 canon_cmd(v,ESC28,0x71, 1, 0x01); 1353} 1354 1355/* ESC (r -- 0x72 -- -- : 1356 */ 1357static void 1358canon_init_setX72(const stp_vars_t *v, const canon_privdata_t *init) 1359{ 1360 if ( !( (init->caps->features & CANON_CAP_r) 1361 || (init->caps->features & CANON_CAP_rr) ) ) 1362 return; 1363 1364 if ( (init->caps->features & CANON_CAP_r) 1365 || (init->caps->features & CANON_CAP_rr) ) 1366 canon_cmd(v,ESC28,0x72, 1, init->caps->ESC_r_arg); /* whatever for - 8200/S200 need it */ 1367 if (init->caps->features & CANON_CAP_rr) 1368 canon_cmd(v,ESC28,0x72, 3, 0x63, 1, 0); /* whatever for - S200 needs it */ 1369 /* probably to set the print direction of the head */ 1370} 1371 1372/* ESC (r -- 0x72 -- ??? set direction ??? -- : 1373 only works if quality = 01 (S200) */ 1374static void 1375canon_set_X72(const stp_vars_t *v, int x72arg) 1376{ 1377 canon_cmd(v,ESC28,0x72, 3, 0x63, x72arg, 0); 1378} 1379 1380/* ESC (t -- 0x74 -- cmdSetImage --: 1381 */ 1382static void 1383canon_init_setImage(const stp_vars_t *v, const canon_privdata_t *init) 1384{ 1385 unsigned char 1386 arg_74_1 = 0x01, /* 1 bit per pixel */ 1387 arg_74_2 = 0x00, /* */ 1388 arg_74_3 = 0x01; /* 01 <= 360 dpi 09 >= 720 dpi */ 1389 1390 if (!(init->caps->features & CANON_CAP_t)) 1391 return; 1392 1393 if(init->mode->flags & MODE_FLAG_EXTENDED_T) /*code requires extended mode settings*/ 1394 { 1395 int i; 1396 int length = init->mode->num_inks*3 + 3; 1397 unsigned char* buf = stp_zalloc(length); 1398 buf[0]=0x80; 1399 if(init->mode->flags & MODE_FLAG_PRO){ 1400 buf[1]=0x90; /* was 0x10, but this should probably be 0x90 */ 1401 buf[2]=0x4; 1402 }else if(init->mode->flags & MODE_FLAG_IP8500){ 1403 buf[1]=0x00; 1404 buf[2]=0x01; 1405 }else{ 1406 buf[1]=0x80; 1407 buf[2]=0x01; 1408 } 1409 for(i=0;i<init->mode->num_inks;i++){ 1410 if(init->mode->inks[i].ink){ 1411 if(init->mode->inks[i].ink->flags & INK_FLAG_5pixel_in_1byte) 1412 buf[3+i*3+0]=(1<<5)|init->mode->inks[i].ink->bits; /*info*/ 1413 /*else if(init->mode->inks[i].ink->flags & INK_FLAG_lowresmode) 1414 { 1415 buf[3+i*3+1]=0x01; 1416 buf[3+i*3+0]=init->mode->inks[i].ink->bits; 1417 }*/ 1418 else 1419 buf[3+i*3+0]=init->mode->inks[i].ink->bits; 1420 1421 /* workaround for now on the 4-4 inkset and others */ 1422 /*if (init->mode->inks[i].ink->bits == 4) 1423 buf[3+i*3+2] = 0x04;*/ 1424 /*else if (init->mode->inks[i].ink->bits == 2) 1425 buf[3+i*3+2] = 0x04;*/ 1426 /*else if (init->mode->inks[i].ink->bits == 1) 1427 buf[3+i*3+2] = 0x02;*/ 1428 buf[3+i*3+2]= init->mode->inks[i].ink->numsizes+1;/*level*/ 1429 /*else 1430 buf[3+i*3+2] = 0x00;*/ 1431 /* this should show that there is an error */ 1432 } 1433 } 1434 stp_zfwrite(ESC28,2,1,v); 1435 stp_putc(0x74,v); 1436 stp_put16_le(length,v); 1437 stp_zfwrite((char*)buf,length,1,v); 1438 stp_free(buf); 1439 return; 1440 } 1441 1442 /* other models mostly hardcoded stuff not really understood ;( */ 1443 if (!strcmp(init->caps->name,"S200")) /* 1 bit per pixel (arg 4,7,10,13); */ 1444 /* 2 level per pixel (arg 6,9,12,15) for each color */ 1445 /* though we print only 1bit/pixel - but this is how */ 1446 /* the windows driver works */ 1447 { 1448 canon_cmd(v,ESC28,0x74, 30, 0x80, 4, 1, 1, 0, 2, 1, 0, 2, 1, 0, 2, 1, 0, 2,\ 1449 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); 1450 return; 1451 } 1452 1453 if (init->mode->xdpi==1440) arg_74_2= 0x04; 1454 if (init->mode->ydpi>=720) arg_74_3= 0x09; 1455 1456 if (init->mode->inks[0].ink->bits>1) { 1457 arg_74_1= 0x02; 1458 arg_74_2= 0x80; 1459 arg_74_3= 0x09; 1460 if (init->used_inks == CANON_INK_CMY) arg_74_3= 0x02; /* for BC-06 cartridge!!! */ 1461 } 1462 1463 /* workaround for the bjc8200 in 6color mode - not really understood */ 1464 if (!strcmp(init->caps->name,"8200")) { 1465 if (init->used_inks == CANON_INK_CcMmYK) { 1466 arg_74_1= 0xff; 1467 arg_74_2= 0x90; 1468 arg_74_3= 0x04; 1469 if (init->mode->ydpi>600) arg_74_3= 0x09; 1470 } else { 1471 arg_74_1= 0x01; 1472 arg_74_2= 0x00; 1473 arg_74_3= 0x01; 1474 if (init->mode->ydpi>600) arg_74_3= 0x09; 1475 } 1476 } 1477 1478 canon_cmd(v,ESC28,0x74, 3, arg_74_1, arg_74_2, arg_74_3); 1479} 1480 1481/* ESC (I (J (L 1482 */ 1483static void 1484canon_init_setMultiRaster(const stp_vars_t *v, const canon_privdata_t *init){ 1485 1486 int i; /* introduced for channel counting */ 1487 char* raster_channel_order; /* introduced for channel counting */ 1488 1489 if(!(init->caps->features & CANON_CAP_I)) 1490 return; 1491 1492 canon_cmd(v,ESC28,0x49, 1, 0x1); /* enable MultiLine Raster? */ 1493 canon_cmd(v,ESC28,0x4a, 1, init->caps->raster_lines_per_block); /* set number of lines per raster block */ 1494 1495 /* set the color sequence */ 1496 stp_zfwrite("\033(L", 3, 1, v); 1497 stp_put16_le(init->num_channels, v); 1498 /* add an exception here to add 0x60 of cmy channels for those printers/modes that require it */ 1499 raster_channel_order=init->channel_order; 1500 /* if (!strcmp(init->caps->name,"MP450"))*/ 1501 { 1502 /* if cmy there, add 0x60 to each --- this is not yet correct, some modes do not require it! */ 1503 /* if (init->num_channels==7) {*/ 1504 for(i=0;i<init->num_channels;i++){ 1505 switch(init->channel_order[i]){ 1506 /* case 'c':raster_channel_order[i]+=0x60; break;;*/ 1507 /* case 'm':raster_channel_order[i]+=0x60; break;;*/ 1508 /* case 'y':raster_channel_order[i]+=0x60; break;;*/ 1509 } 1510 } 1511 /*}*/ 1512 stp_zfwrite((const char *)raster_channel_order,init->num_channels, 1, v); 1513 } 1514 /* else 1515 { 1516 stp_zfwrite((const char *)init->channel_order,init->num_channels, 1, v); 1517 }*/ 1518} 1519 1520 1521 1522 1523static void 1524canon_init_printer(const stp_vars_t *v, const canon_privdata_t *init) 1525{ 1526 unsigned int mytop; 1527 /* init printer */ 1528 if (init->is_first_page) { 1529 canon_init_resetPrinter(v,init); /* ESC [K */ 1530 canon_init_setDuplex(v,init); /* ESC ($ */ 1531 } 1532 canon_init_setPageMode(v,init); /* ESC (a */ 1533 canon_init_setDataCompression(v,init); /* ESC (b */ 1534 canon_init_setPageID(v,init); /* ESC (q */ 1535 canon_init_setPrintMode(v,init); /* ESC (m */ 1536 canon_init_setResolution(v,init); /* ESC (d */ 1537 canon_init_setImage(v,init); /* ESC (t */ 1538 canon_init_setColor(v,init); /* ESC (c */ 1539 canon_init_setPageMargins(v,init); /* ESC (g */ 1540 canon_init_setPageMargins2(v,init); /* ESC (p */ 1541 canon_init_setESC_P(v,init); /* ESC (P */ 1542 canon_init_setCartridge(v,init); /* ESC (T */ 1543 canon_init_setTray(v,init); /* ESC (l */ 1544 canon_init_setX72(v,init); /* ESC (r */ 1545 canon_init_setMultiRaster(v,init); /* ESC (I (J (L */ 1546 1547 /* some linefeeds */ 1548 1549 mytop= (init->top*init->mode->ydpi)/72; 1550 1551 if(init->caps->features & CANON_CAP_I) 1552 mytop /= init->caps->raster_lines_per_block; 1553 1554 if(mytop) 1555 canon_cmd(v,ESC28,0x65, 2, (mytop >> 8 ),(mytop & 255)); 1556} 1557 1558static void 1559canon_deinit_printer(const stp_vars_t *v, const canon_privdata_t *init) 1560{ 1561 /* eject page */ 1562 stp_putc(0x0c,v); 1563 1564 /* say goodbye */ 1565 canon_cmd(v,ESC28,0x62,1,0); 1566 if (init->caps->features & CANON_CAP_a) 1567 canon_cmd(v,ESC28,0x61, 1, 0); 1568} 1569 1570static int 1571canon_start_job(const stp_vars_t *v, stp_image_t *image) 1572{ 1573 const canon_cap_t * caps = canon_get_model_capabilities(v); 1574 /* output XML for iP2700 and other devices */ 1575 if (caps->features & CANON_CAP_XML) { 1576 int length=strlen(prexml_iP2700); /* 680 */ 1577 stp_zfwrite((const char*)prexml_iP2700,length,1,v); 1578 } 1579 return 1; 1580} 1581 1582static int 1583canon_end_job(const stp_vars_t *v, stp_image_t *image) 1584{ 1585 const canon_cap_t * caps = canon_get_model_capabilities(v); 1586 canon_cmd(v,ESC40,0,0); 1587 /* output XML for iP2700 and other devices */ 1588 if (caps->features & CANON_CAP_XML) { 1589 int length=strlen(postxml_iP2700); /* 263 */ 1590 stp_zfwrite((const char*)postxml_iP2700,length,1,v); 1591 } 1592 return 1; 1593} 1594 1595/* 1596 * 'advance_buffer()' - Move (num) lines of length (len) down one line 1597 * and sets first line to 0s 1598 * accepts NULL pointers as buf 1599 * !!! buf must contain more than (num) lines !!! 1600 * also sets first line to 0s if num<1 1601 */ 1602static void 1603canon_advance_buffer(unsigned char *buf, int len, int num) 1604{ 1605 if (!buf || !len) return; 1606 if (num>0) memmove(buf+len,buf,len*num); 1607 memset(buf,0,len); 1608} 1609 1610static void 1611canon_printfunc(stp_vars_t *v) 1612{ 1613 int i; 1614 canon_privdata_t *pd = (canon_privdata_t *) stp_get_component_data(v, "Driver"); 1615 canon_write_line(v); 1616 for (i = 0; i < pd->num_channels ; i++) 1617 canon_advance_buffer(pd->channels[i].buf, pd->length, pd->channels[i].delay); 1618 1619} 1620 1621static double 1622get_double_param(stp_vars_t *v, const char *param) 1623{ 1624 if (param && stp_check_float_parameter(v, param, STP_PARAMETER_ACTIVE)) 1625 return stp_get_float_parameter(v, param); 1626 else 1627 return 1.0; 1628} 1629 1630 1631 1632static void 1633set_mask(unsigned char *cd_mask, int x_center, int scaled_x_where, 1634 int limit, int expansion, int invert) 1635{ 1636 int clear_val = invert ? 255 : 0; 1637 int set_val = invert ? 0 : 255; 1638 int bytesize = 8 / expansion; 1639 int byteextra = bytesize - 1; 1640 int first_x_on = x_center - scaled_x_where; 1641 int first_x_off = x_center + scaled_x_where; 1642 if (first_x_on < 0) 1643 first_x_on = 0; 1644 if (first_x_on > limit) 1645 first_x_on = limit; 1646 if (first_x_off < 0) 1647 first_x_off = 0; 1648 if (first_x_off > limit) 1649 first_x_off = limit; 1650 first_x_on += byteextra; 1651 if (first_x_off > (first_x_on - byteextra)) 1652 { 1653 int first_x_on_byte = first_x_on / bytesize; 1654 int first_x_on_mod = expansion * (byteextra - (first_x_on % bytesize)); 1655 int first_x_on_extra = ((1 << first_x_on_mod) - 1) ^ clear_val; 1656 int first_x_off_byte = first_x_off / bytesize; 1657 int first_x_off_mod = expansion * (byteextra - (first_x_off % bytesize)); 1658 int first_x_off_extra = ((1 << 8) - (1 << first_x_off_mod)) ^ clear_val; 1659 if (first_x_off_byte < first_x_on_byte) 1660 { 1661 /* This can happen, if 6 or fewer points are turned on */ 1662 cd_mask[first_x_on_byte] = first_x_on_extra & first_x_off_extra; 1663 } 1664 else 1665 { 1666 if (first_x_on_extra != clear_val) 1667 1668 cd_mask[first_x_on_byte - 1] = first_x_on_extra; 1669 if (first_x_off_byte > first_x_on_byte) 1670 memset(cd_mask + first_x_on_byte, set_val, 1671 first_x_off_byte - first_x_on_byte); 1672 if (first_x_off_extra != clear_val) 1673 cd_mask[first_x_off_byte] = first_x_off_extra; 1674 } 1675 } 1676} 1677 1678 1679/* get delay settings for the specified color and mode */ 1680static int canon_get_delay(canon_privdata_t* privdata,char color){ 1681 int i=0; 1682 int delay = 0; 1683 const canon_delay_t* delaylist = privdata->mode->delay; 1684 1685 while(delaylist && delaylist[i].color){ 1686 if(delaylist[i].color == color){ 1687 delay = delaylist[i].delay; 1688 break; 1689 } 1690 ++i; 1691 } 1692 if(delay > privdata->delay_max) 1693 privdata->delay_max = delay; 1694 return delay; 1695} 1696 1697 1698/* add a single channel to the dither engine */ 1699static int canon_setup_channel(stp_vars_t *v,canon_privdata_t* privdata,int channel,int subchannel,const canon_inkset_t* ink,stp_shade_t** shades){ 1700 if(ink->channel && ink->density > 0.0){ 1701 int delay = canon_get_delay(privdata,ink->channel); 1702 canon_channel_t* current; 1703 /* create a new channel */ 1704 privdata->channels = stp_realloc(privdata->channels,sizeof(canon_channel_t) * (privdata->num_channels + 1)); 1705 privdata->channel_order = stp_realloc(privdata->channel_order,privdata->num_channels + 2); 1706 /* update channel order */ 1707 privdata->channel_order[privdata->num_channels]=ink->channel; 1708 privdata->channel_order[privdata->num_channels+1]='\0'; 1709 current = &(privdata->channels[privdata->num_channels]); 1710 ++privdata->num_channels; 1711 /* fill ink properties */ 1712 current->name = ink->channel; 1713 current->props = ink->ink; 1714 current->delay = delay; 1715 /* calculate buffer length */ 1716 current->buf_length = ((privdata->length * current->props->bits)+1)*(delay + 1); 1717 /* update maximum buffer length */ 1718 if(current->buf_length > privdata->buf_length_max) 1719 privdata->buf_length_max = current->buf_length; 1720 /* allocate buffer for the raster data */ 1721 current->buf = stp_zalloc(current->buf_length + 1); 1722 /* add channel to the dither engine */ 1723 stp_dither_add_channel(v, current->buf , channel , subchannel); 1724 1725 /* add shades to the shades array */ 1726 *shades = stp_realloc(*shades,(subchannel + 1) * sizeof(stp_shade_t)); 1727 /* move previous shades up one position as set_inks_full expects the subchannels first */ 1728 if(subchannel) 1729 memcpy(*shades + 1,*shades,sizeof(stp_shade_t) * subchannel); 1730 (*shades)[0].value = ink->density; 1731 (*shades)[0].numsizes = ink->ink->numsizes; 1732 (*shades)[0].dot_sizes = ink->ink->dot_sizes; 1733 return 1; 1734 } 1735 return 0; 1736} 1737 1738 1739 1740 1741 1742/* setup the dither channels */ 1743static void canon_setup_channels(stp_vars_t *v,canon_privdata_t* privdata){ 1744 /* (in gutenprint notation) => KCMY, 1230 => CMYK etc. */ 1745 const char default_channel_order[STP_NCOLORS] = {0,1,2,3}; 1746 /* codes for the primary channels */ 1747 const char primary[STP_NCOLORS] = {'K','C','M','Y',}; 1748 /* codes for the subchannels */ 1749 const char secondary[STP_NCOLORS] = {'k','c','m','y'}; 1750 /* names of the density adjustment controls */ 1751 const char *primary_density_control[STP_NCOLORS] = {"BlackDensity","CyanDensity","MagentaDensity","YellowDensity"}; 1752 const char *secondary_density_control[STP_NCOLORS] = {NULL,"LightCyanTrans","LightMagentaTrans","LightYellowTrans"}; 1753 /* ink darkness for every channel */ 1754 const double ink_darkness[] = {1.0, 0.31 / .5, 0.61 / .97, 0.08}; 1755 const char* channel_order = default_channel_order; 1756 1757 1758 1759 int channel; 1760 int channel_idx; 1761 1762 if(privdata->caps->channel_order) 1763 channel_order = privdata->caps->channel_order; 1764 1765 1766 /* loop through the dither channels */ 1767 for(channel_idx = 0; channel_idx < STP_NCOLORS ; channel_idx++){ 1768 int i; 1769 unsigned int subchannel = 0; 1770 stp_shade_t* shades = NULL; 1771 int is_black_channel = 0; 1772 channel = channel_order[channel_idx]; 1773 if(channel == STP_ECOLOR_K && privdata->used_inks & CANON_INK_K_MASK){ /* black channel */ 1774 /* find K and k inks */ 1775 for(i=0;i<privdata->mode->num_inks;i++){ 1776 const canon_inkset_t* ink = &privdata->mode->inks[i]; 1777 if(ink->channel == primary[channel] || ink->channel == secondary[channel]) 1778 subchannel += canon_setup_channel(v,privdata,channel,subchannel,ink,&shades); 1779 } 1780 is_black_channel = 1; 1781 }else if(channel != STP_ECOLOR_K && privdata->used_inks & CANON_INK_CMY_MASK){ /* color channels */ 1782 for(i=0;i<privdata->mode->num_inks;i++){ 1783 const canon_inkset_t* ink = &privdata->mode->inks[i]; 1784 if(ink->channel == primary[channel] || ((privdata->used_inks & CANON_INK_CcMmYyKk_MASK) && (ink->channel == secondary[channel]))) 1785 subchannel += canon_setup_channel(v,privdata,channel,subchannel,ink,&shades); 1786 } 1787 } 1788 1789 /* set inks and density */ 1790 if(shades){ 1791 stp_dither_set_inks_full(v,channel, subchannel, shades, 1.0, ink_darkness[channel]); 1792 for(i=0;i<subchannel;i++){ 1793 double density = get_double_param(v, primary_density_control[channel]) * get_double_param(v, "Density"); 1794 if(i > 0 && secondary_density_control[channel]) 1795 density *= get_double_param(v, secondary_density_control[channel]); 1796 stp_channel_set_density_adjustment(v,channel,subchannel,density); 1797 } 1798 if (is_black_channel) 1799 stp_channel_set_black_channel(v, channel); 1800 stp_free(shades); 1801 } 1802 } 1803} 1804 1805 1806 1807 1808 1809 1810 1811/* FIXME move this to printercaps */ 1812#define CANON_CD_X 176 1813#define CANON_CD_Y 405 1814 1815static void setup_page(stp_vars_t* v,canon_privdata_t* privdata){ 1816 const char *media_source = stp_get_string_parameter(v, "InputSlot"); 1817 const char *cd_type = stp_get_string_parameter(v, "PageSize"); 1818 int print_cd= (media_source && (!strcmp(media_source, "CD"))); 1819 int page_left, 1820 page_top, 1821 page_right, 1822 page_bottom; 1823 int hub_size = 0; 1824 1825 1826 if (cd_type && (strcmp(cd_type, "CDCustom") == 0 )) 1827 { 1828 int outer_diameter = stp_get_dimension_parameter(v, "CDOuterDiameter"); 1829 stp_set_page_width(v, outer_diameter); 1830 stp_set_page_height(v, outer_diameter); 1831 stp_set_width(v, outer_diameter); 1832 stp_set_height(v, outer_diameter); 1833 hub_size = stp_get_dimension_parameter(v, "CDInnerDiameter"); 1834 } 1835 else 1836 { 1837 const char *inner_radius_name = stp_get_string_parameter(v, "CDInnerRadius"); 1838 hub_size = 43 * 10 * 72 / 254; /* 43 mm standard CD hub */ 1839 1840 if (inner_radius_name && strcmp(inner_radius_name, "Small") == 0) 1841 hub_size = 16 * 10 * 72 / 254; /* 15 mm prints to the hole - play it 1842 safe and print 16 mm */ 1843 } 1844 1845 privdata->top = stp_get_top(v); 1846 privdata->left = stp_get_left(v); 1847 privdata->out_width = stp_get_width(v); 1848 privdata->out_height = stp_get_height(v); 1849 1850 internal_imageable_area(v, 0, &page_left, &page_right, 1851 &page_bottom, &page_top); 1852 if (print_cd) { 1853 privdata->cd_inner_radius = hub_size / 2; 1854 privdata->cd_outer_radius = stp_get_width(v) / 2; 1855 privdata->left = CANON_CD_X - privdata->cd_outer_radius + stp_get_dimension_parameter(v, "CDXAdjustment");; 1856 privdata->top = CANON_CD_Y - privdata->cd_outer_radius + stp_get_dimension_parameter(v, "CDYAdjustment"); 1857 privdata->page_width = privdata->left + privdata->out_width; 1858 privdata->page_height = privdata->top + privdata->out_height; 1859 } else { 1860 privdata->left -= page_left; 1861 privdata->top -= page_top; 1862 privdata->page_width = page_right - page_left; 1863 privdata->page_height = page_bottom - page_top; 1864 } 1865 1866} 1867 1868 1869/* combine all curve parameters in s and apply them */ 1870static void canon_set_curve_parameter(stp_vars_t *v,const char* type,stp_curve_compose_t comp,const char* s1,const char* s2,const char* s3){ 1871 const char * s[3]; 1872 size_t count = sizeof(s) / sizeof(s[0]); 1873 stp_curve_t *ret = NULL; 1874 int curve_count = 0; 1875 int i; 1876 const size_t piecewise_point_count = 384; 1877 1878 1879 /* ignore settings from the printercaps if the user specified his own parameters */ 1880 if(stp_check_curve_parameter(v,type, STP_PARAMETER_ACTIVE)) 1881 return; 1882 1883 /* init parameter list (FIXME pass array directly???)*/ 1884 s[0] = s1; 1885 s[1] = s2; 1886 s[2] = s3; 1887 1888 /* skip empty curves */ 1889 for(i=0;i<count;i++){ 1890 if(s[i]) 1891 s[curve_count++] = s[i]; 1892 } 1893 1894 /* combine curves */ 1895 if(curve_count){ 1896 for(i=0;i<curve_count;i++){ 1897 stp_curve_t* t_tmp = stp_curve_create_from_string(s[i]); 1898 if(t_tmp){ 1899 if(stp_curve_is_piecewise(t_tmp)){ 1900 stp_curve_resample(t_tmp, piecewise_point_count); 1901 } 1902 if(!ret){ 1903 ret = t_tmp; 1904 }else{ 1905 stp_curve_t* t_comp = NULL; 1906 stp_curve_compose(&t_comp, ret, t_tmp, comp, -1); 1907 if(t_comp){ 1908 stp_curve_destroy(ret); 1909 ret = t_comp; 1910 } 1911 stp_curve_destroy(t_tmp); 1912 } 1913 } 1914 } 1915 } 1916 1917 /* apply result */ 1918 if(ret){ 1919 stp_set_curve_parameter(v, type, ret); 1920 stp_curve_destroy(ret); 1921 } 1922} 1923 1924/* 1925 * 'canon_print()' - Print an image to a CANON printer. 1926 */ 1927static int 1928canon_do_print(stp_vars_t *v, stp_image_t *image) 1929{ 1930 int i; 1931 int status = 1; 1932 const char *media_source = stp_get_string_parameter(v, "InputSlot"); 1933 const char *duplex_mode =stp_get_string_parameter(v, "Duplex"); 1934 int page_number = stp_get_int_parameter(v, "PageNumber"); 1935 const canon_cap_t * caps= canon_get_model_capabilities(v); 1936 int y; /* Looping vars */ 1937 canon_privdata_t privdata; 1938 int errdiv, /* Error dividend */ 1939 errmod, /* Error modulus */ 1940 errval, /* Current error value */ 1941 errline, /* Current raster line */ 1942 errlast, /* Last raster line loaded */ 1943 out_channels; /* Output bytes per pixel */ 1944 unsigned zero_mask; 1945 int print_cd= (media_source && (!strcmp(media_source, "CD"))); 1946 int image_height, 1947 image_width; 1948 double k_upper, k_lower; 1949 unsigned char *cd_mask = NULL; 1950 double outer_r_sq = 0; 1951 double inner_r_sq = 0; 1952 unsigned char* weave_cols[4] ; /* TODO clean up weaving code to be more generic */ 1953 1954 if (!stp_verify(v)) 1955 { 1956 stp_eprintf(v, "Print options not verified; cannot print.\n"); 1957 return 0; 1958 } 1959 /* 1960 * Setup a read-only pixel region for the entire image... 1961 */ 1962 1963 stp_image_init(image); 1964 1965 1966 /* rotate even pages for DuplexNoTumble */ 1967 if((page_number & 1) && duplex_mode && !strcmp(duplex_mode,"DuplexNoTumble")) 1968 image = stpi_buffer_image(image,BUFFER_FLAG_FLIP_X | BUFFER_FLAG_FLIP_Y); 1969 1970 memset(&privdata,0,sizeof(canon_privdata_t)); 1971 privdata.caps = caps; 1972 1973 /* find the wanted print mode */ 1974 privdata.mode = canon_get_current_mode(v); 1975 1976 /* set quality */ 1977 privdata.quality = privdata.mode->quality; 1978 1979 /* force grayscale if image is grayscale 1980 * or single black cartridge installed 1981 */ 1982 privdata.used_inks = canon_printhead_colors(v); 1983 if (privdata.used_inks == CANON_INK_K) 1984 stp_set_string_parameter(v, "PrintingMode", "BW"); 1985 1986 setup_page(v,&privdata); 1987 1988 image_height = stp_image_height(image); 1989 image_width = stp_image_width(image); 1990 1991 privdata.pt = get_media_type(caps,stp_get_string_parameter(v, "MediaType")); 1992 privdata.slot = canon_source_type(media_source,caps); 1993 privdata.duplex_str = duplex_mode; 1994 privdata.is_first_page = (page_number == 0); 1995 1996 /* 1997 * Convert image size to printer resolution... 1998 */ 1999 2000 privdata.out_width = privdata.mode->xdpi * privdata.out_width / 72; 2001 privdata.out_height = privdata.mode->ydpi * privdata.out_height / 72; 2002 2003 privdata.left = privdata.mode->xdpi * privdata.left / 72; 2004 2005 stp_deprintf(STP_DBG_CANON,"density is %f\n", 2006 stp_get_float_parameter(v, "Density")); 2007 2008 /* 2009 * Compute the LUT. For now, it's 8 bit, but that may eventually 2010 * sometimes change. 2011 */ 2012 2013 if (!stp_check_float_parameter(v, "Density", STP_PARAMETER_DEFAULTED)) 2014 { 2015 stp_set_float_parameter_active(v, "Density", STP_PARAMETER_ACTIVE); 2016 stp_set_float_parameter(v, "Density", 1.0); 2017 } 2018 2019 stp_scale_float_parameter(v, "Density", privdata.pt->base_density); 2020 stp_scale_float_parameter(v, "Density",privdata.mode->density); 2021 2022 if (stp_get_float_parameter(v, "Density") > 1.0) 2023 stp_set_float_parameter(v, "Density", 1.0); 2024 2025 if (privdata.used_inks == CANON_INK_K) 2026 stp_scale_float_parameter(v, "Gamma", 1.25); 2027 stp_scale_float_parameter( v, "Gamma", privdata.mode->gamma ); 2028 2029 stp_deprintf(STP_DBG_CANON,"density is %f\n", 2030 stp_get_float_parameter(v, "Density")); 2031 2032 if(privdata.used_inks & CANON_INK_CMYK_MASK) 2033 stp_set_string_parameter(v, "STPIOutputType", "KCMY"); 2034 else if(privdata.used_inks & CANON_INK_CMY_MASK) 2035 stp_set_string_parameter(v, "STPIOutputType", "CMY"); 2036 else 2037 stp_set_string_parameter(v, "STPIOutputType", "Grayscale"); 2038 2039 privdata.length = (privdata.out_width + 7) / 8; 2040 2041 stp_dither_init(v, image, privdata.out_width, privdata.mode->xdpi, privdata.mode->ydpi); 2042 2043 canon_setup_channels(v,&privdata); 2044 2045 2046 stp_deprintf(STP_DBG_CANON, 2047 "canon: driver will use colors %s\n",privdata.channel_order); 2048 2049 /* Allocate compression buffer */ 2050 if(caps->features & CANON_CAP_I) 2051 privdata.comp_buf = stp_zalloc(privdata.buf_length_max * 2 * caps->raster_lines_per_block * privdata.num_channels); /* for multiraster we need to buffer 8 lines for every color */ 2052 else 2053 privdata.comp_buf = stp_zalloc(privdata.buf_length_max * 2); 2054 /* Allocate fold buffer */ 2055 privdata.fold_buf = stp_zalloc(privdata.buf_length_max); 2056 2057 2058 2059 /* 2060 * Output the page... 2061 */ 2062 2063 /* FIXME this is probably broken, kept for backward compatibility */ 2064 if(privdata.num_channels > 4){ 2065 k_lower = 0.4 / privdata.channels[4].props->bits + .1; 2066 }else 2067 k_lower = 0.25; 2068 2069 k_lower *= privdata.pt->k_lower_scale; 2070 k_upper = privdata.pt->k_upper; 2071 2072 if (!stp_check_float_parameter(v, "GCRLower", STP_PARAMETER_ACTIVE)) 2073 stp_set_default_float_parameter(v, "GCRLower", k_lower); 2074 if (!stp_check_float_parameter(v, "GCRUpper", STP_PARAMETER_ACTIVE)) 2075 stp_set_default_float_parameter(v, "GCRUpper", k_upper); 2076 2077 2078 /* init the printer */ 2079 canon_init_printer(v, &privdata); 2080 2081 /* initialize weaving for S200 for resolutions > 360dpi */ 2082 if (privdata.mode->flags & MODE_FLAG_WEAVE) 2083 { 2084 char weave_color_order[] = "KCMY"; 2085 2086 privdata.stepper_ydpi = 720; 2087 privdata.nozzle_ydpi = 360; 2088 if (privdata.mode->xdpi == 2880) 2089 privdata.physical_xdpi = 2880; 2090 else 2091 privdata.physical_xdpi = 720; 2092 2093 stp_deprintf(STP_DBG_CANON,"canon: adjust leftskip: old=%d,\n", privdata.left); 2094 privdata.left = (int)( (float)privdata.left * (float)privdata.physical_xdpi / (float)privdata.mode->xdpi ); /* adjust left margin */ 2095 stp_deprintf(STP_DBG_CANON,"canon: adjust leftskip: new=%d,\n", privdata.left); 2096 2097 privdata.ncolors = 4; 2098 privdata.head_offset = stp_zalloc(sizeof(int) * privdata.ncolors); 2099 memset(privdata.head_offset, 0, sizeof(privdata.head_offset)); 2100 2101 if ( privdata.used_inks == CANON_INK_K ) 2102 privdata.nozzles = 64; /* black nozzles */ 2103 else 2104 privdata.nozzles = 24; /* color nozzles */ 2105 if ( privdata.used_inks == CANON_INK_K ) 2106 { 2107 privdata.ncolors = 1; 2108 privdata.head_offset[0] = 0; /* K starts at 0 */ 2109 privdata.head_offset[1] = 0 ;/* how far C starts after K */ 2110 privdata.head_offset[2] = 0;/* how far M starts after K */ 2111 privdata.head_offset[3] = 0;/* how far Y starts after K */ 2112 privdata.top += 11; 2113 } 2114 else if ( privdata.used_inks == CANON_INK_CMYK ) 2115 { 2116 privdata.head_offset[0] = 0; /* K starts at 0 */ 2117 privdata.head_offset[1] = 144 ;/* how far C starts after K */ 2118 privdata.head_offset[2] = 144 + 64;/* how far M starts after K */ 2119 privdata.head_offset[3] = 144 + 64 + 64;/* how far Y starts after K */ 2120 privdata.top += 5; 2121 } 2122 else /* colormode == CMY */ 2123 { 2124 privdata.head_offset[0] = 0; /* K starts at 0 */ 2125 privdata.head_offset[1] = 0 ;/* how far C starts after K */ 2126 privdata.head_offset[2] = 64;/* how far M starts after K */ 2127 privdata.head_offset[3] = 128;/* how far Y starts after K */ 2128 privdata.top += 18; 2129 } 2130 2131 privdata.nozzle_separation = privdata.stepper_ydpi / privdata.nozzle_ydpi; 2132 privdata.horizontal_passes = privdata.mode->xdpi / privdata.physical_xdpi; 2133 privdata.vertical_passes = 1; 2134 privdata.vertical_oversample = privdata.mode->ydpi / privdata.stepper_ydpi; 2135 privdata.bidirectional = 1; /* 1: bidirectional; 0: unidirectional printing */ 2136 privdata.direction = 1; 2137 stp_allocate_component_data(v, "Driver", NULL, NULL, &privdata); 2138 stp_deprintf(STP_DBG_CANON,"canon: initializing weaving: nozzles=%d, nozzle_separation=%d,\n" 2139 "horizontal_passes=%d, vertical_passes=%d,vertical_oversample=%d,\n" 2140 "ncolors=%d, out_width=%d, out_height=%d\n" 2141 "weave_top=%d, weave_page_height=%d \n" 2142 "head_offset=[%d,%d,%d,%d] \n", 2143 privdata.nozzles, privdata.nozzle_separation, 2144 privdata.horizontal_passes, privdata.vertical_passes, 2145 privdata.vertical_oversample, privdata.ncolors, 2146 privdata.out_width, privdata.out_height, 2147 privdata.top * privdata.stepper_ydpi / 72, privdata.page_height * privdata.stepper_ydpi / 72, 2148 privdata.head_offset[0],privdata.head_offset[1], 2149 privdata.head_offset[2],privdata.head_offset[3]); 2150 2151 stp_initialize_weave(v, privdata.nozzles, privdata.nozzle_separation, 2152 privdata.horizontal_passes, privdata.vertical_passes, 2153 privdata.vertical_oversample, privdata.ncolors, 2154 1, 2155 privdata.out_width, privdata.out_height, 2156 privdata.top * privdata.stepper_ydpi / 72, 2157 privdata.page_height * privdata.stepper_ydpi / 72, 2158 privdata.head_offset, 2159 STP_WEAVE_ZIGZAG, 2160 canon_flush_pass, 2161 stp_fill_uncompressed, 2162 stp_pack_uncompressed, 2163 stp_compute_uncompressed_linewidth); 2164 privdata.last_pass_offset = 0; 2165 2166 2167 for(i=0;i<4;i++){ 2168 int x; 2169 for(x=0;x<privdata.num_channels;x++){ 2170 if(weave_color_order[i] == privdata.channel_order[x]) 2171 weave_cols[i] = privdata.channels[x].buf; 2172 privdata.weave_bits[i] = privdata.channels[x].props->bits; 2173 } 2174 } 2175 } 2176 2177 2178 errdiv = image_height / privdata.out_height; 2179 errmod = image_height % privdata.out_height; 2180 errval = 0; 2181 errlast = -1; 2182 errline = 0; 2183 2184 /* set Hue, Lum and Sat Maps */ 2185 canon_set_curve_parameter(v,"HueMap",STP_CURVE_COMPOSE_ADD,caps->hue_adjustment,privdata.pt->hue_adjustment,privdata.mode->hue_adjustment); 2186 canon_set_curve_parameter(v,"LumMap",STP_CURVE_COMPOSE_MULTIPLY,caps->lum_adjustment,privdata.pt->lum_adjustment,privdata.mode->lum_adjustment); 2187 canon_set_curve_parameter(v,"SatMap",STP_CURVE_COMPOSE_MULTIPLY,caps->sat_adjustment,privdata.pt->sat_adjustment,privdata.mode->sat_adjustment); 2188 2189 out_channels = stp_color_init(v, image, 65536); 2190 stp_allocate_component_data(v, "Driver", NULL, NULL, &privdata); 2191 2192 privdata.emptylines = 0; 2193 if (print_cd) { 2194 cd_mask = stp_malloc(1 + (privdata.out_width + 7) / 8); 2195 outer_r_sq = (double)privdata.cd_outer_radius * (double)privdata.cd_outer_radius; 2196 inner_r_sq = (double)privdata.cd_inner_radius * (double)privdata.cd_inner_radius; 2197 } 2198 for (y = 0; y < privdata.out_height; y ++) 2199 { 2200 int duplicate_line = 1; 2201 2202 if (errline != errlast) 2203 { 2204 errlast = errline; 2205 duplicate_line = 0; 2206 if (stp_color_get_row(v, image, errline, &zero_mask)) 2207 { 2208 status = 2; 2209 break; 2210 } 2211 } 2212 if (print_cd) 2213 { 2214 int x_center = privdata.cd_outer_radius * privdata.mode->xdpi / 72; 2215 int y_distance_from_center = 2216 privdata.cd_outer_radius - (y * 72 / privdata.mode->ydpi); 2217 if (y_distance_from_center < 0) 2218 y_distance_from_center = -y_distance_from_center; 2219 memset(cd_mask, 0, (privdata.out_width + 7) / 8); 2220 if (y_distance_from_center < privdata.cd_outer_radius) 2221 { 2222 double y_sq = (double) y_distance_from_center * 2223 (double) y_distance_from_center; 2224 int x_where = sqrt(outer_r_sq - y_sq) + .5; 2225 int scaled_x_where = x_where * privdata.mode->xdpi / 72; 2226 set_mask(cd_mask, x_center, scaled_x_where, 2227 privdata.out_width, 1, 0); 2228 if (y_distance_from_center < privdata.cd_inner_radius) 2229 { 2230 x_where = sqrt(inner_r_sq - y_sq) + .5; 2231 scaled_x_where = x_where * privdata.mode->ydpi / 72; 2232 set_mask(cd_mask, x_center, scaled_x_where, 2233 privdata.out_width, 1, 1); 2234 } 2235 } 2236 } 2237 stp_dither(v, y, duplicate_line, zero_mask, cd_mask); 2238 if ( privdata.mode->flags & MODE_FLAG_WEAVE ) 2239 stp_write_weave(v, weave_cols); 2240 else if ( caps->features & CANON_CAP_I) 2241 canon_write_multiraster(v,&privdata,y); 2242 else 2243 canon_printfunc(v); 2244 errval += errmod; 2245 errline += errdiv; 2246 if (errval >= privdata.out_height) 2247 { 2248 errval -= privdata.out_height; 2249 errline ++; 2250 } 2251 } 2252 2253 if ( privdata.mode->flags & MODE_FLAG_WEAVE ) 2254 { 2255 stp_flush_all(v); 2256 canon_advance_paper(v, 5); 2257 } 2258 else 2259 { 2260 2261 /* 2262 * Flush delayed buffers... 2263 */ 2264 2265 if (privdata.delay_max) { 2266 stp_deprintf(STP_DBG_CANON,"\ncanon: flushing %d possibly delayed buffers\n", 2267 privdata.delay_max); 2268 for (y= 0; y<privdata.delay_max; y++) { 2269 2270 canon_write_line(v); 2271 for (i = 0; i < privdata.num_channels; i++) 2272 canon_advance_buffer(privdata.channels[i].buf, privdata.length, 2273 privdata.channels[i].delay); 2274 } 2275 } 2276 } 2277 stp_image_conclude(image); 2278 2279 /* 2280 * Cleanup... 2281 */ 2282 2283 stp_free(privdata.fold_buf); 2284 stp_free(privdata.comp_buf); 2285 2286 if(cd_mask) 2287 stp_free(cd_mask); 2288 2289 2290 canon_deinit_printer(v, &privdata); 2291 /* canon_end_job does not get called for jobmode automatically */ 2292 if(!stp_get_string_parameter(v, "JobMode") || 2293 strcmp(stp_get_string_parameter(v, "JobMode"), "Page") == 0){ 2294 canon_end_job(v,image); 2295 } 2296 2297 for(i=0;i< privdata.num_channels;i++) 2298 if(privdata.channels[i].buf) 2299 stp_free(privdata.channels[i].buf); 2300 if(privdata.channels) 2301 stp_free(privdata.channels); 2302 2303 stp_free(privdata.channel_order); 2304 if (privdata.head_offset) 2305 stp_free(privdata.head_offset); 2306 2307 2308 return status; 2309} 2310 2311static int 2312canon_print(const stp_vars_t *v, stp_image_t *image) 2313{ 2314 int status; 2315 stp_vars_t *nv = stp_vars_create_copy(v); 2316 stp_prune_inactive_options(nv); 2317 status = canon_do_print(nv, image); 2318 stp_vars_destroy(nv); 2319 return status; 2320} 2321 2322static const stp_printfuncs_t print_canon_printfuncs = 2323{ 2324 canon_list_parameters, 2325 canon_parameters, 2326 stp_default_media_size, 2327 canon_imageable_area, 2328 canon_imageable_area, 2329 canon_limit, 2330 canon_print, 2331 canon_describe_resolution, 2332 canon_describe_output, 2333 stp_verify_printer_params, 2334 canon_start_job, 2335 canon_end_job, 2336 NULL 2337}; 2338 2339static void 2340canon_shift_buffer(unsigned char *line,int length,int bits) 2341{ 2342 int i,j; 2343 for (j=0; j<bits; j++) { 2344 for (i=length-1; i>0; i--) { 2345 line[i]= (line[i] >> 1) | (line[i-1] << 7); 2346 } 2347 line[0] = line[0] >> 1; 2348 } 2349} 2350 2351 2352/* fold, apply 5 pixel in 1 byte compression, pack tiff and return the compressed length */ 2353static int canon_compress(stp_vars_t *v, canon_privdata_t *pd, unsigned char* line,int length,int offset,unsigned char* comp_buf,int bits, int ink_flags) 2354{ 2355 unsigned char 2356 *in_ptr= line, 2357 *comp_ptr, *comp_data; 2358 int offset2,bitoffset; 2359 2360 /* Don't send blank lines... */ 2361 2362 if (line[0] == 0 && memcmp(line, line + 1, (length * bits) - 1) == 0) 2363 return 0; 2364 2365 offset2 = offset / 8; 2366 bitoffset = offset % 8; 2367 2368 /* fold lsb/msb pairs if drop modulation is active */ 2369 2370 2371 if (bits==2) { 2372 int pixels_per_byte = 4; 2373 if(ink_flags & INK_FLAG_5pixel_in_1byte) 2374 pixels_per_byte = 5; 2375 2376 stp_fold(line,length,pd->fold_buf); 2377 in_ptr= pd->fold_buf; 2378 length= (length*8/4); /* 4 pixels in 8bit */ 2379 /* calculate the number of compressed bytes that can be sent directly */ 2380 offset2 = offset / pixels_per_byte; 2381 /* calculate the number of (uncompressed) bits that have to be added to the raster data */ 2382 bitoffset = (offset % pixels_per_byte) * 2; 2383 } 2384 else if (bits==3) { 2385 stp_fold_3bit_323(line,length,pd->fold_buf); 2386 in_ptr= pd->fold_buf; 2387 length= (length*8)/3; 2388 offset2 = offset/3; 2389#if 0 2390 switch(offset%3){ 2391 case 0: offset= (offset/3)*8; break; 2392 case 1: offset= (offset/3)*8/*+3 CAREFUL! CANNOT SHIFT _AFTER_ RECODING!!*/; break; 2393 case 2: offset= (offset/3)*8/*+5 CAREFUL! CANNOT SHIFT _AFTER_ RECODING!!*/; break; 2394 } 2395#endif 2396 bitoffset= 0; 2397 } 2398 else if (bits==4) { 2399 stp_fold_4bit(line,length,pd->fold_buf); 2400 in_ptr= pd->fold_buf; 2401 length= (length*8)/2; 2402 offset2 = offset / 2; 2403 bitoffset= offset % 2; 2404 } 2405 2406 /* pack left border rounded to multiples of 8 dots */ 2407 2408 comp_data= comp_buf; 2409 while (offset2>0) { 2410 unsigned char toffset = offset2 > 127 ? 127 : offset2; 2411 comp_data[0] = 1 - toffset; 2412 comp_data[1] = 0; 2413 comp_data += 2; 2414 offset2-= toffset; 2415 } 2416 if (bitoffset) { 2417 if (bitoffset<8) 2418 { 2419 in_ptr[ length++ ] = 0; 2420 canon_shift_buffer(in_ptr,length,bitoffset); 2421 } 2422 else if (bitoffset == 8) 2423 { 2424 memmove(in_ptr + 1,in_ptr,length++); 2425 in_ptr[0] = 0; 2426 } 2427 else 2428 stp_deprintf(STP_DBG_CANON,"SEVERE BUG IN print-canon.c::canon_write() " 2429 "bitoffset=%d!!\n",bitoffset); 2430 } 2431 2432 if(ink_flags & INK_FLAG_5pixel_in_1byte) 2433 length = pack_pixels(in_ptr,length); 2434 2435 stp_pack_tiff(v, in_ptr, length, comp_data, &comp_ptr, NULL, NULL); 2436 2437 return comp_ptr - comp_buf; 2438} 2439 2440/* 2441 * 'canon_write()' - Send graphics using TIFF packbits compression. 2442 */ 2443 2444static int 2445canon_write(stp_vars_t *v, /* I - Print file or command */ 2446 canon_privdata_t *pd, /* privdata */ 2447 const canon_cap_t * caps, /* I - Printer model */ 2448 unsigned char *line, /* I - Output bitmap data */ 2449 int length, /* I - Length of bitmap data */ 2450 int coloridx, /* I - Which color */ 2451 int *empty, /* IO- Preceeding empty lines */ 2452 int width, /* I - Printed width */ 2453 int offset, /* I - Offset from left side */ 2454 int bits, 2455 int ink_flags) 2456{ 2457 2458 unsigned char color; 2459 int newlength = canon_compress(v,pd,line,length,offset,pd->comp_buf,bits,ink_flags); 2460 if(!newlength) 2461 return 0; 2462 /* send packed empty lines if any */ 2463 2464 if (*empty) { 2465 stp_zfwrite("\033\050\145\002\000", 5, 1, v); 2466 stp_put16_be(*empty, v); 2467 *empty= 0; 2468 } 2469 2470 /* Send a line of raster graphics... */ 2471 2472 stp_zfwrite("\033\050\101", 3, 1, v); 2473 stp_put16_le(newlength + 1, v); 2474 color= "CMYKcmyk"[coloridx]; 2475 if (!color) color= 'K'; 2476 stp_putc(color,v); 2477 stp_zfwrite((const char *)pd->comp_buf, newlength, 1, v); 2478 stp_putc('\015', v); 2479 return 1; 2480} 2481 2482 2483static void 2484canon_write_line(stp_vars_t *v) 2485{ 2486 canon_privdata_t *pd = 2487 (canon_privdata_t *) stp_get_component_data(v, "Driver"); 2488 char write_sequence[] = "KYMCymck"; 2489 static const int write_number[] = { 3, 2, 1, 0, 6, 5, 4, 7 }; /* KYMCymc */ 2490 int i; 2491 int written= 0; 2492 for (i = 0; i < strlen(write_sequence) ; i++) 2493 { 2494 int x; 2495 const canon_channel_t* channel=NULL; 2496 int num = write_number[i]; 2497 2498 /* TODO optimize => move reorder code to do_print */ 2499 for(x=0;x < pd->num_channels; x++){ 2500 if(pd->channels[x].name == write_sequence[i]){ 2501 channel = &(pd->channels[x]); 2502 break; 2503 } 2504 } 2505 if(channel){ 2506 written += canon_write(v, pd, pd->caps, 2507 channel->buf + channel->delay * pd->length /*buf_length[i]*/, 2508 pd->length, num, 2509 &(pd->emptylines), pd->out_width, 2510 pd->left, channel->props->bits, channel->props->flags); 2511 } 2512 } 2513 if (written) 2514 stp_zfwrite("\033\050\145\002\000\000\001", 7, 1, v); 2515 else 2516 pd->emptylines += 1; 2517} 2518 2519 2520/* write one multiraster block */ 2521static void canon_write_block(stp_vars_t* v,canon_privdata_t* pd,unsigned char* start, unsigned char* end){ 2522 unsigned int length = end - start; 2523 if(!length) 2524 return; 2525 stp_zfwrite("\033(F", 3, 1, v); 2526 stp_put16_le(length, v); 2527 stp_zfwrite((const char *)start, length, 1, v); 2528} 2529 2530 2531static void canon_write_multiraster(stp_vars_t *v,canon_privdata_t* pd,int y){ 2532 int i; 2533 int raster_lines_per_block = pd->caps->raster_lines_per_block; 2534 unsigned int max_length = 2*pd->buf_length_max * raster_lines_per_block; 2535 /* a new raster block begins */ 2536 if(!(y % raster_lines_per_block)){ 2537 if(y != 0){ 2538 /* write finished blocks */ 2539 for(i=0;i<pd->num_channels;i++) 2540 canon_write_block(v,pd,pd->comp_buf + i * max_length,pd->channels[i].comp_buf_offset); 2541 } 2542 /* reset start offsets */ 2543 for(i=0;i<pd->num_channels;i++) 2544 pd->channels[i].comp_buf_offset = pd->comp_buf + i * max_length; 2545 } 2546 /* compress lines and add them to the buffer */ 2547 for(i=0;i<pd->num_channels;i++){ 2548 pd->channels[i].comp_buf_offset += canon_compress(v,pd, pd->channels[i].buf,pd->length,pd->left,pd->channels[i].comp_buf_offset,pd->channels[i].props->bits, pd->channels[i].props->flags); 2549 *(pd->channels[i].comp_buf_offset) = 0x80; /* terminate the line */ 2550 ++pd->channels[i].comp_buf_offset; 2551 } 2552 if(y == pd->out_height - 1){ 2553 /* we just compressed our last line */ 2554 if(pd->out_height % raster_lines_per_block){ 2555 /* but our raster block is not finished yet */ 2556 int missing = raster_lines_per_block - (pd->out_height % raster_lines_per_block); /* calculate missing lines */ 2557 for(i=0;i<pd->num_channels;i++){ 2558 /* add missing empty lines and write blocks */ 2559 int x; 2560 for(x=0;x < missing ; x++){ 2561 *(pd->channels[i].comp_buf_offset) = 0x80; /* terminate the line */ 2562 ++pd->channels[i].comp_buf_offset; 2563 } 2564 canon_write_block(v,pd,pd->comp_buf + i * max_length,pd->channels[i].comp_buf_offset); 2565 } 2566 } 2567 } 2568} 2569 2570 2571static void 2572canon_advance_paper(stp_vars_t *v, int advance) 2573{ 2574 if ( advance > 0 ) 2575 { 2576 int a0, a1, a2, a3; 2577 stp_deprintf(STP_DBG_CANON," --advance paper %d\n", advance); 2578 a0 = advance & 0xff; 2579 a1 = (advance >> 8) & 0xff; 2580 a2 = (advance >> 16) & 0xff; 2581 a3 = (advance >> 24) & 0xff; 2582 stp_zprintf(v, "\033(e%c%c%c%c%c%c", 4, 0, a3, a2, a1, a0); 2583 } 2584} 2585 2586static void 2587canon_flush_pass(stp_vars_t *v, int passno, int vertical_subpass) 2588{ 2589 stp_lineoff_t *lineoffs = stp_get_lineoffsets_by_pass(v, passno); 2590 stp_lineactive_t *lineactive = stp_get_lineactive_by_pass(v, passno); 2591 const stp_linebufs_t *bufs = stp_get_linebases_by_pass(v, passno); 2592 stp_pass_t *pass = stp_get_pass_by_pass(v, passno); 2593 stp_linecount_t *linecount = stp_get_linecount_by_pass(v, passno); 2594 canon_privdata_t *pd = (canon_privdata_t *) stp_get_component_data(v, "Driver"); 2595 int papershift = (pass->logicalpassstart - pd->last_pass_offset); 2596 2597 int color, line, written = 0, linelength = 0, lines = 0; 2598 int idx[4]={3, 0, 1, 2}; /* color numbering is different between canon_write and weaving */ 2599 2600 stp_deprintf(STP_DBG_CANON,"canon_flush_pass: ----pass=%d,---- \n", passno); 2601 (pd->emptylines) = 0; 2602 2603 for ( color = 0; color < pd->ncolors; color++ ) /* find max. linecount */ 2604 { 2605 if ( linecount[0].v[color] > lines ) 2606 lines = linecount[0].v[color]; 2607 } 2608 2609 for ( line = 0; line < lines; line++ ) /* go through each nozzle f that pass */ 2610 { 2611 stp_deprintf(STP_DBG_CANON," --line=%d\n", line); 2612 2613 if ( written > 0 ) 2614 canon_cmd(v,ESC28,0x65, 2, 0, 1); /* go to next nozzle*/ 2615 /* if there was printed some data */ 2616 2617 written = 0; 2618 for ( color = 0; color < pd->ncolors; color++ ) 2619 { 2620 if ( line < linecount[0].v[color] ) /* try only existing lines */ 2621 { 2622 if ( lineactive[0].v[color] > 0 ) 2623 { 2624 linelength = lineoffs[0].v[color] / linecount[0].v[color]; 2625/* stp_deprintf(STP_DBG_CANON,"canon_flush_pass: linelength=%d, bufs[0].v[color]=%p," 2626 "bufs[0].v[color]+line * linelength=%p, empty=%d \n", linelength, bufs[0].v[color], 2627 bufs[0].v[color] + line * linelength, (pd->emptylines)); 2628*/ 2629 if ( pass->logicalpassstart - pd->last_pass_offset > 0 ) 2630 { 2631 canon_advance_paper(v, papershift); 2632 pd->last_pass_offset = pass->logicalpassstart; 2633 if (pd->bidirectional) 2634 { 2635 pd->direction = (pd->direction +1) & 1; 2636 canon_set_X72(v, pd->direction); 2637 stp_deprintf(STP_DBG_CANON," --set direction %d\n", pd->direction); 2638 } 2639 } 2640 2641 written += canon_write(v, pd, pd->caps, 2642 (unsigned char *)(bufs[0].v[color] + line * linelength), 2643 linelength, idx[color], 2644 &(pd->emptylines), pd->out_width, 2645 pd->left, pd->weave_bits[color],0); 2646 if (written) stp_deprintf(STP_DBG_CANON," --written color %d,\n", color); 2647 2648 } 2649 } 2650 } 2651 2652 if ( written == 0 ) /* count unused nozzles */ 2653 (pd->emptylines) += 1; 2654 } 2655 2656 for ( color = 0; color < pd->ncolors; color++ ) 2657 { 2658 lineoffs[0].v[color] = 0; 2659 linecount[0].v[color] = 0; 2660 } 2661 stp_deprintf(STP_DBG_CANON," --ended-- with empty=%d \n", (pd->emptylines)); 2662} 2663 2664static stp_family_t print_canon_module_data = 2665 { 2666 &print_canon_printfuncs, 2667 NULL 2668 }; 2669 2670 2671static int 2672print_canon_module_init(void) 2673{ 2674 return stp_family_register(print_canon_module_data.printer_list); 2675} 2676 2677 2678static int 2679print_canon_module_exit(void) 2680{ 2681 return stp_family_unregister(print_canon_module_data.printer_list); 2682} 2683 2684 2685/* Module header */ 2686#define stp_module_version print_canon_LTX_stp_module_version 2687#define stp_module_data print_canon_LTX_stp_module_data 2688 2689stp_module_version_t stp_module_version = {0, 0}; 2690 2691stp_module_t stp_module_data = 2692 { 2693 "canon", 2694 VERSION, 2695 "Canon family driver", 2696 STP_MODULE_CLASS_FAMILY, 2697 NULL, 2698 print_canon_module_init, 2699 print_canon_module_exit, 2700 (void *) &print_canon_module_data 2701 }; 2702 2703