1 /*
2 *
3 * Print plug-in CANON BJL driver for the GIMP.
4 *
5 * Copyright 1997-2000 Michael Sweet (mike@easysw.com),
6 * Robert Krawitz (rlk@alum.mit.edu) and
7 * Andy Thaller (thaller@ph.tum.de)
8 *
9 * Copyright (c) 2006 - 2007 Sascha Sommer (saschasommer@freenet.de)
10 *
11 * This program is free software; you can redistribute it and/or modify it
12 * under the terms of the GNU General Public License as published by the Free
13 * Software Foundation; either version 2 of the License, or (at your option)
14 * any later version.
15 *
16 * This program is distributed in the hope that it will be useful, but
17 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
18 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
19 * for more details.
20 *
21 * You should have received a copy of the GNU General Public License
22 * along with this program. If not, see <https://www.gnu.org/licenses/>.
23 */
24
25 /*
26 * This file must include only standard C header files. The core code must
27 * compile on generic platforms that don't support glib, gimp, gtk, etc.
28 */
29
30 /*
31 * Large parts of this file (mainly the ink handling) is based on
32 * print-escp2.c -- refer to README.new-printer on how to adjust the colors
33 * for a certain model.
34 */
35
36 /* TODO-LIST
37 *
38 * * adjust the colors of all supported models
39 *
40 */
41 #ifdef HAVE_CONFIG_H
42 #include <config.h>
43 #endif
44 #include <gutenprint/gutenprint.h>
45 #include "gutenprint-internal.h"
46 #include <gutenprint/gutenprint-intl-internal.h>
47 #include <string.h>
48 #include <stdio.h>
49 #if defined(HAVE_VARARGS_H) && !defined(HAVE_STDARG_H)
50 #include <varargs.h>
51 #else
52 #include <stdarg.h>
53 #endif
54 #ifdef HAVE_LIMITS_H
55 #include <limits.h>
56 #endif
57 #include <math.h>
58
59 #include "print-canon.h"
60
61 #ifndef MIN
62 # define MIN(a,b) (((a)<(b)) ? (a) : (b))
63 #endif /* !MIN */
64 #ifndef MAX
65 # define MAX(a, b) ((a) > (b) ? (a) : (b))
66 #endif /* !MAX */
67
68 /* 5 3-level pixels into 1 byte */
69 static int
pack_pixels(unsigned char * buf,int len)70 pack_pixels(unsigned char* buf,int len)
71 {
72 int read_pos = 0;
73 int write_pos = 0;
74 int shift = 6;
75 while(read_pos < len)
76 {
77 /* read 5pixels at 2 bit */
78 unsigned short value = buf[read_pos] << 8;
79 if(read_pos+1 < len)
80 value += buf[read_pos + 1];
81 if(shift) /*6,4,2,0*/
82 value >>= shift;
83 /* write 8bit value representing the 10 bit pixel combination */
84 buf[write_pos] = tentoeight[value & 1023];
85 ++write_pos;
86 if(shift == 0)
87 {
88 shift = 6;
89 read_pos += 2;
90 }
91 else
92 {
93 shift -= 2;
94 ++read_pos;
95 }
96 }
97 return write_pos;
98 }
99
100 /* 3 4-bit-per-pixel 5-level pixels into 1 byte */
101 static int
pack_pixels3_5(unsigned char * buf,int len)102 pack_pixels3_5(unsigned char* buf,int len)
103 {
104 int read_pos = 0;
105 int write_pos = 0;
106 int shift = 4;
107 while(read_pos < len)
108 {
109 /* read 3pixels at 4 bit */
110 unsigned short value = buf[read_pos] << 8;
111 if(read_pos+1 < len)
112 value += buf[read_pos + 1];
113 if(shift) /*4,0*/
114 value >>= shift;
115 /* write 8bit value representing the 12 bit pixel combination */
116 buf[write_pos] = twelve2eight[value & 4095];
117 ++write_pos;
118 if(shift == 0)
119 {
120 shift = 4;
121 read_pos += 2;
122 }
123 else
124 {
125 shift -= 4;
126 ++read_pos;
127 }
128 }
129 return write_pos;
130 }
131
132 /* 3 4-bit-per-pixel 6-level pixels into 1 byte */
133 static int
pack_pixels3_6(unsigned char * buf,int len)134 pack_pixels3_6(unsigned char* buf,int len)
135 {
136 int read_pos = 0;
137 int write_pos = 0;
138 int shift = 4;
139 while(read_pos < len)
140 {
141 /* read 3pixels at 4 bit */
142 unsigned short value = buf[read_pos] << 8;
143 if(read_pos+1 < len)
144 value += buf[read_pos + 1];
145 if(shift) /*4,0*/
146 value >>= shift;
147 /* write 8bit value representing the 12 bit pixel combination */
148 buf[write_pos] = twelve2eight2[value & 4095];
149 ++write_pos;
150 if(shift == 0)
151 {
152 shift = 4;
153 read_pos += 2;
154 }
155 else
156 {
157 shift -= 4;
158 ++read_pos;
159 }
160 }
161 return write_pos;
162 }
163
164 /* model peculiarities */
165 #define CANON_CAP_MSB_FIRST 0x02ul /* how to send data */
166 #define CANON_CAP_a 0x04ul
167 #define CANON_CAP_b 0x08ul
168 #define CANON_CAP_q 0x10ul
169 #define CANON_CAP_m 0x20ul
170 #define CANON_CAP_d 0x40ul
171 #define CANON_CAP_t 0x80ul
172 #define CANON_CAP_c 0x100ul
173 #define CANON_CAP_p 0x200ul
174 #define CANON_CAP_l 0x400ul
175 #define CANON_CAP_r 0x800ul
176 #define CANON_CAP_g 0x1000ul
177 #define CANON_CAP_px 0x2000ul
178 #define CANON_CAP_rr 0x4000ul
179 #define CANON_CAP_I 0x8000ul
180 #define CANON_CAP_T 0x10000ul /* cartridge selection for PIXMA printers with Black and Color carts */
181 #define CANON_CAP_P 0x20000ul /* related to media type selection */
182 #define CANON_CAP_DUPLEX 0x40000ul /* duplex printing */
183 #define CANON_CAP_XML 0x80000ul /* use of XML at start and end of print data */
184 #define CANON_CAP_CARTRIDGE 0x100000ul /* not sure of this yet */
185 #define CANON_CAP_M 0x200000ul /* not sure of this yet */
186 #define CANON_CAP_S 0x400000ul /* not sure of this yet */
187 #define CANON_CAP_cart 0x800000ul /* BJC printers with Color, Black, Photo options */
188 #define CANON_CAP_BORDERLESS 0x1000000ul /* borderless (fullbleed) printing */
189 #define CANON_CAP_NOBLACK 0x2000000ul /* no Black cartridge selection */
190 #define CANON_CAP_v 0x4000000ul /* not sure of this yet */
191 #define CANON_CAP_w 0x8000000ul /* related to media type selection */
192 #define CANON_CAP_s 0x10000000ul /* not sure of this yet: duplex-related? */
193 #define CANON_CAP_u 0x20000000ul /* not sure of this yet: duplex-related? */
194
195 #define CANON_CAP_STD0 (CANON_CAP_b|CANON_CAP_c|CANON_CAP_d|\
196 CANON_CAP_l|CANON_CAP_q|CANON_CAP_t)
197
198 #define CANON_CAP_STD1 (CANON_CAP_b|CANON_CAP_c|CANON_CAP_d|CANON_CAP_l|\
199 CANON_CAP_m|CANON_CAP_p|CANON_CAP_q|CANON_CAP_t)
200
201 #include "canon-inks.h"
202 #include "canon-modes.h"
203 #include "canon-media.h"
204 #include "canon-media-mode.h"
205 #include "canon-printers.h"
206
207 typedef struct {
208 char name;
209 const canon_ink_t* props;
210 unsigned char* buf;
211 unsigned char* comp_buf_offset;
212 unsigned int buf_length;
213 unsigned int delay;
214 } canon_channel_t;
215
216 typedef struct
217 {
218 const canon_mode_t* mode;
219 const canon_slot_t* slot;
220 const canon_paper_t *pt;
221 /* cartridge selection for CANON_CAP_T and CANON_CAP_cart */
222 const char *ink_set;
223 const canon_modeuse_t* modeuse;
224 /* final inks used for output, after selection process completed */
225 unsigned int used_inks;
226 int num_channels;
227 int quality;
228 canon_channel_t* channels;
229 char* channel_order;
230 const canon_cap_t *caps;
231 unsigned char *comp_buf;
232 unsigned char *fold_buf;
233 int delay_max;
234 int buf_length_max;
235 int length;
236 int out_width;
237 int out_height;
238 int page_width;
239 int page_height;
240 int top;
241 int left;
242 int emptylines;
243 int ncolors; /* number of colors to print with */
244 int physical_xdpi, nozzle_ydpi, stepper_ydpi;
245 int nozzles; /* count of inkjets for one pass */
246 int nozzle_separation;
247 int horizontal_passes;
248 int vertical_passes;
249 int vertical_oversample;
250 int *head_offset;
251 int last_pass_offset;
252 int bidirectional; /* tells us if we are allowed to print bidirectional */
253 int direction; /* stores the last direction of the print head */
254 int weave_bits[4];
255 const char *duplex_str;
256 int is_first_page;
257 double cd_inner_radius;
258 double cd_outer_radius;
259 } canon_privdata_t;
260
261 static const canon_modeuse_t* select_media_modes(stp_vars_t *v, const canon_paper_t* media_type,const canon_modeuselist_t* mlist);
262 static int compare_mode_valid(stp_vars_t *v,const canon_mode_t* mode,const canon_modeuse_t* muse, const canon_modeuselist_t* mlist);
263 static const canon_mode_t* suitable_mode_monochrome(stp_vars_t *v,const canon_modeuse_t* muse,const canon_cap_t *caps,int quality,const char *duplex_mode);
264 static const canon_mode_t* find_first_matching_mode_monochrome(stp_vars_t *v,const canon_modeuse_t* muse,const canon_cap_t *caps,const char *duplex_mode);
265 static const canon_mode_t* find_first_matching_mode(stp_vars_t *v,const canon_modeuse_t* muse,const canon_cap_t *caps,const char *duplex_mode);
266 static const canon_mode_t* suitable_mode_color(stp_vars_t *v,const canon_modeuse_t* muse,const canon_cap_t *caps,int quality,const char *duplex_mode);
267 static const canon_mode_t* find_first_matching_mode_color(stp_vars_t *v,const canon_modeuse_t* muse,const canon_cap_t *caps,const char *duplex_mode);
268 static const canon_mode_t* suitable_mode_photo(stp_vars_t *v,const canon_modeuse_t* muse,const canon_cap_t *caps,int quality,const char *duplex_mode);
269 static const canon_mode_t* find_first_matching_mode_photo(stp_vars_t *v,const canon_modeuse_t* muse,const canon_cap_t *caps,const char *duplex_mode);
270 static const canon_mode_t* suitable_mode_general(stp_vars_t *v,const canon_modeuse_t* muse,const canon_cap_t *caps,int quality,const char *duplex_mode);
271 static const char* find_ink_type(stp_vars_t *v,const canon_mode_t* mode,const char *printing_mode);
272 static const canon_mode_t* canon_check_current_mode(stp_vars_t *v);
273
274 static void canon_write_line(stp_vars_t *v);
275
276 static void canon_advance_paper(stp_vars_t *, int);
277 static void canon_flush_pass(stp_vars_t *, int, int);
278 static void canon_write_multiraster(stp_vars_t *v,canon_privdata_t* pd,int y);
279
280 static void fix_papersize(unsigned char arg_ESCP_1, int *paper_width, int *paper_length);
281
282 static const stp_parameter_t the_parameters[] =
283 {
284 {
285 "PageSize", N_("Page Size"), "Color=No,Category=Basic Printer Setup",
286 N_("Size of the paper being printed to"),
287 STP_PARAMETER_TYPE_STRING_LIST, STP_PARAMETER_CLASS_CORE,
288 STP_PARAMETER_LEVEL_BASIC, 1, 1, STP_CHANNEL_NONE, 1, 0
289 },
290 {
291 "MediaType", N_("Media Type"), "Color=Yes,Category=Basic Printer Setup",
292 N_("Type of media (plain paper, photo paper, etc.)"),
293 STP_PARAMETER_TYPE_STRING_LIST, STP_PARAMETER_CLASS_FEATURE,
294 STP_PARAMETER_LEVEL_BASIC, 1, 1, STP_CHANNEL_NONE, 1, 0
295 },
296 {
297 "InputSlot", N_("Media Source"), "Color=No,Category=Basic Printer Setup",
298 N_("Source (input slot) of the media"),
299 STP_PARAMETER_TYPE_STRING_LIST, STP_PARAMETER_CLASS_FEATURE,
300 STP_PARAMETER_LEVEL_BASIC, 1, 1, STP_CHANNEL_NONE, 1, 0
301 },
302 {
303 "CassetteTray", N_("Cassette Tray"), "Color=No,Category=Basic Printer Setup",
304 N_("Tray selection for cassette media source"),
305 STP_PARAMETER_TYPE_STRING_LIST, STP_PARAMETER_CLASS_FEATURE,
306 STP_PARAMETER_LEVEL_BASIC, 1, 1, STP_CHANNEL_NONE, 1, 0
307 },
308 {
309 "CDInnerRadius", N_("CD Hub Size"), "Color=No,Category=Basic Printer Setup",
310 N_("Print only outside of the hub of the CD, or all the way to the hole"),
311 STP_PARAMETER_TYPE_STRING_LIST, STP_PARAMETER_CLASS_FEATURE,
312 STP_PARAMETER_LEVEL_BASIC, 1, 1, STP_CHANNEL_NONE, 1, 0
313 },
314 {
315 "CDOuterDiameter", N_("CD Size (Custom)"), "Color=No,Category=Basic Printer Setup",
316 N_("Variable adjustment for the outer diameter of CD"),
317 STP_PARAMETER_TYPE_DIMENSION, STP_PARAMETER_CLASS_FEATURE,
318 STP_PARAMETER_LEVEL_ADVANCED, 1, 1, STP_CHANNEL_NONE, 1, 0
319 },
320 {
321 "CDInnerDiameter", N_("CD Hub Size (Custom)"), "Color=No,Category=Basic Printer Setup",
322 N_("Variable adjustment to the inner hub of the CD"),
323 STP_PARAMETER_TYPE_DIMENSION, STP_PARAMETER_CLASS_FEATURE,
324 STP_PARAMETER_LEVEL_ADVANCED, 1, 1, STP_CHANNEL_NONE, 1, 0
325 },
326 {
327 "CDXAdjustment", N_("CD Horizontal Fine Adjustment"), "Color=No,Category=Advanced Printer Setup",
328 N_("Fine adjustment to horizontal position for CD printing"),
329 STP_PARAMETER_TYPE_DIMENSION, STP_PARAMETER_CLASS_FEATURE,
330 STP_PARAMETER_LEVEL_ADVANCED, 1, 1, STP_CHANNEL_NONE, 1, 0
331 },
332 {
333 "CDYAdjustment", N_("CD Vertical Fine Adjustment"), "Color=No,Category=Advanced Printer Setup",
334 N_("Fine adjustment to horizontal position for CD printing"),
335 STP_PARAMETER_TYPE_DIMENSION, STP_PARAMETER_CLASS_FEATURE,
336 STP_PARAMETER_LEVEL_ADVANCED, 1, 1, STP_CHANNEL_NONE, 1, 0
337 },
338 {
339 "Resolution", N_("Resolution"), "Color=Yes,Category=Basic Printer Setup",
340 N_("Resolution and quality of the print"),
341 STP_PARAMETER_TYPE_STRING_LIST, STP_PARAMETER_CLASS_FEATURE,
342 STP_PARAMETER_LEVEL_BASIC, 1, 1, STP_CHANNEL_NONE, 1, 0
343 },
344 /*
345 * Don't check this parameter. We may offer different settings for
346 * different ink sets, but we need to be able to handle settings from PPD
347 * files that don't have constraints set up.
348 */
349 {
350 "InkType", N_("Ink Type"), "Color=Yes,Category=Advanced Printer Setup",
351 N_("Type of ink in the printer"),
352 STP_PARAMETER_TYPE_STRING_LIST, STP_PARAMETER_CLASS_FEATURE,
353 STP_PARAMETER_LEVEL_BASIC, 1, 1, STP_CHANNEL_NONE, 0, 0
354 },
355 {
356 "InkChannels", N_("Ink Channels"), "Color=Yes,Category=Advanced Printer Functionality",
357 N_("Ink Channels"),
358 STP_PARAMETER_TYPE_INT, STP_PARAMETER_CLASS_FEATURE,
359 STP_PARAMETER_LEVEL_INTERNAL, 0, 0, STP_CHANNEL_NONE, 0, 0
360 },
361 /*
362 * Don't check this parameter. We may offer different settings for
363 * different ink sets, but we need to be able to handle settings from PPD
364 * files that don't have constraints set up.
365 */
366 {
367 "PrintingMode", N_("Printing Mode"), "Color=Yes,Category=Core Parameter",
368 N_("Printing Output Mode"),
369 STP_PARAMETER_TYPE_STRING_LIST, STP_PARAMETER_CLASS_CORE,
370 STP_PARAMETER_LEVEL_BASIC, 1, 1, STP_CHANNEL_NONE, 0, 0
371 },
372 /*
373 * Don't check this parameter. We may offer different settings for
374 * different ink sets, but we need to be able to handle settings from PPD
375 * files that don't have constraints set up.
376 */
377 {
378 "InkSet", N_("Ink Set"), "Color=Yes,Category=Basic Printer Setup",
379 N_("Type of inkset in the printer"),
380 STP_PARAMETER_TYPE_STRING_LIST, STP_PARAMETER_CLASS_FEATURE,
381 STP_PARAMETER_LEVEL_BASIC, 1, 1, STP_CHANNEL_NONE, 0, 0
382 },
383 {
384 "FullBleed", N_("Borderless"), "Color=No,Category=Basic Printer Setup",
385 N_("Print without borders"),
386 STP_PARAMETER_TYPE_BOOLEAN, STP_PARAMETER_CLASS_FEATURE,
387 STP_PARAMETER_LEVEL_BASIC, 1, 1, STP_CHANNEL_NONE, 1, 0
388 },
389 {
390 "Duplex", N_("Double-Sided Printing"), "Color=No,Category=Basic Printer Setup",
391 N_("Duplex/Tumble Setting"),
392 STP_PARAMETER_TYPE_STRING_LIST, STP_PARAMETER_CLASS_FEATURE,
393 STP_PARAMETER_LEVEL_BASIC, 1, 1, STP_CHANNEL_NONE, 1, 0
394 },
395 {
396 "Quality", N_("Print Quality"), "Color=Yes,Category=Basic Output Adjustment",
397 N_("Print Quality"),
398 STP_PARAMETER_TYPE_STRING_LIST, STP_PARAMETER_CLASS_FEATURE,
399 STP_PARAMETER_LEVEL_BASIC, 1, 1, STP_CHANNEL_NONE, 0, 0
400 },
401 {
402 "Orientation", N_("Orientation"), "Color=No,Category=Basic Printer Setup",
403 N_("Orientation, Portrait, Landscape, Upside Down, Seascape"),
404 STP_PARAMETER_TYPE_STRING_LIST, STP_PARAMETER_CLASS_FEATURE,
405 STP_PARAMETER_LEVEL_BASIC, 1, 1, STP_CHANNEL_NONE, 1, 0,
406 },
407 };
408
409 static const int the_parameter_count =
410 sizeof(the_parameters) / sizeof(const stp_parameter_t);
411
412 typedef struct
413 {
414 const stp_parameter_t param;
415 double min;
416 double max;
417 double defval;
418 int color_only;
419 } float_param_t;
420
421 static const float_param_t float_parameters[] =
422 {
423 {
424 {
425 "CyanDensity", N_("Cyan Density"), "Color=Yes,Category=Output Level Adjustment",
426 N_("Adjust the cyan density"),
427 STP_PARAMETER_TYPE_DOUBLE, STP_PARAMETER_CLASS_OUTPUT,
428 STP_PARAMETER_LEVEL_ADVANCED, 0, 1, 1, 1, 0
429 }, 0.0, 2.0, 1.0, 1
430 },
431 {
432 {
433 "MagentaDensity", N_("Magenta Density"), "Color=Yes,Category=Output Level Adjustment",
434 N_("Adjust the magenta density"),
435 STP_PARAMETER_TYPE_DOUBLE, STP_PARAMETER_CLASS_OUTPUT,
436 STP_PARAMETER_LEVEL_ADVANCED, 0, 1, 2, 1, 0
437 }, 0.0, 2.0, 1.0, 1
438 },
439 {
440 {
441 "YellowDensity", N_("Yellow Density"), "Color=Yes,Category=Output Level Adjustment",
442 N_("Adjust the yellow density"),
443 STP_PARAMETER_TYPE_DOUBLE, STP_PARAMETER_CLASS_OUTPUT,
444 STP_PARAMETER_LEVEL_ADVANCED, 0, 1, 3, 1, 0
445 }, 0.0, 2.0, 1.0, 1
446 },
447 {
448 {
449 "BlackDensity", N_("Black Density"), "Color=Yes,Category=Output Level Adjustment",
450 N_("Adjust the black density"),
451 STP_PARAMETER_TYPE_DOUBLE, STP_PARAMETER_CLASS_OUTPUT,
452 STP_PARAMETER_LEVEL_ADVANCED, 0, 1, 0, 1, 0
453 }, 0.0, 2.0, 1.0, 1
454 },
455 {
456 {
457 "LightCyanTrans", N_("Light Cyan Transition"), "Color=Yes,Category=Advanced Ink Adjustment",
458 N_("Light Cyan Transition"),
459 STP_PARAMETER_TYPE_DOUBLE, STP_PARAMETER_CLASS_OUTPUT,
460 STP_PARAMETER_LEVEL_ADVANCED4, 0, 1, STP_CHANNEL_NONE, 1, 0
461 }, 0.0, 5.0, 1.0, 1
462 },
463 {
464 {
465 "LightMagentaTrans", N_("Light Magenta Transition"), "Color=Yes,Category=Advanced Ink Adjustment",
466 N_("Light Magenta Transition"),
467 STP_PARAMETER_TYPE_DOUBLE, STP_PARAMETER_CLASS_OUTPUT,
468 STP_PARAMETER_LEVEL_ADVANCED4, 0, 1, STP_CHANNEL_NONE, 1, 0
469 }, 0.0, 5.0, 1.0, 1
470 },
471 {
472 {
473 "LightYellowTrans", N_("Light Yellow Transition"), "Color=Yes,Category=Advanced Ink Adjustment",
474 N_("Light Yellow Transition"),
475 STP_PARAMETER_TYPE_DOUBLE, STP_PARAMETER_CLASS_OUTPUT,
476 STP_PARAMETER_LEVEL_ADVANCED4, 0, 1, STP_CHANNEL_NONE, 1, 0
477 }, 0.0, 5.0, 1.0, 1
478 },
479 };
480
481 static const int float_parameter_count =
482 sizeof(float_parameters) / sizeof(const float_param_t);
483
484 /*
485 * Duplex support - modes available
486 * Note that the internal names MUST match those in cups/genppd.c else the
487 * PPD files will not be generated correctly
488 */
489
490 static const stp_param_string_t duplex_types[] =
491 {
492 { "None", N_ ("Off") },
493 { "DuplexNoTumble", N_ ("Long Edge (Standard)") },
494 { "DuplexTumble", N_ ("Short Edge (Flip)") }
495 };
496 #define NUM_DUPLEX (sizeof (duplex_types) / sizeof (stp_param_string_t))
497
498 /*
499 * Orientation support - modes available
500 * Note that the internal names MUST match those in cups/genppd.c else the
501 * PPD files will not be generated correctly
502 */
503
504 static const stp_param_string_t orientation_types[] = {
505 {"Portrait", N_("Portrait")},
506 {"Landscape", N_("Landscape")},
507 {"UpsideDown", N_("Reverse Portrait")},
508 {"Seascape", N_("Reverse Landscape")},
509 };
510 #define NUM_ORIENTATION (sizeof (orientation_types) / sizeof (stp_param_string_t))
511
512 static const canon_paper_t *
get_media_type(const canon_cap_t * caps,const char * name)513 get_media_type(const canon_cap_t* caps,const char *name)
514 {
515 int i;
516 if (name && caps->paperlist)
517 {
518 for (i = 0; i < caps->paperlist->count; i++)
519 {
520 /* translate paper_t.name */
521 if (!strcmp(name, caps->paperlist->papers[i].name))
522 return &(caps->paperlist->papers[i]);
523 }
524 return &(caps->paperlist->papers[0]);
525 }
526 return NULL;
527 }
528
529 static const char* canon_families[] = {
530 "", /* the old BJC printers */
531 "S", /* 1 */
532 "i", /* 2 */
533 "PIXMA iP", /* 3 */
534 "PIXMA iX", /* 4 */
535 "PIXMA MP", /* 5 */
536 "PIXUS", /* 6 */
537 "PIXMA Pro", /* 7 */
538 "PIXMA MG", /* 8 */
539 "PIXMA MX", /* 9 */
540 "SELPHY DS", /* 10 */
541 "PIXMA mini",/* 11 */
542 "PIXMA E", /* 12 */
543 "PIXMA P", /* 13 */
544 "MAXIFY iB", /* 14 */
545 "MAXIFY MB", /* 15 */
546 "PIXMA MPC", /* 16 */
547 "PIXMA G", /* 17 */
548 "PIXMA TS", /* 18 */
549 "PIXMA TR", /* 19 */
550 "PIXMA XK", /* 20 */
551 };
552
553 /* canon model ids look like the following
554 FFMMMMMM
555 FF: family is the offset in the canon_families struct
556 MMMMMM: model nr
557 */
canon_get_printername(const stp_vars_t * v)558 static char* canon_get_printername(const stp_vars_t* v)
559 {
560 unsigned int model = stp_get_model_id(v);
561 unsigned int family = model / 1000000;
562 unsigned int nr = model - family * 1000000;
563 char* name;
564 size_t len;
565 if(family >= sizeof(canon_families) / sizeof(canon_families[0])){
566 stp_eprintf(v,"canon_get_printername: no family %i using default BJC\n", family);
567 family = 0;
568 }
569 len = strlen(canon_families[family]) + 7; /* max model nr. + terminating 0 */
570 name = stp_zalloc(len);
571 snprintf(name,len,"%s%u",canon_families[family],nr);
572 stp_dprintf(STP_DBG_CANON, v,"canon_get_printername: current printer name: %s\n", name);
573 return name;
574 }
575
canon_get_model_capabilities(const stp_vars_t * v)576 static const canon_cap_t * canon_get_model_capabilities(const stp_vars_t*v)
577 {
578 int i;
579 char* name = canon_get_printername(v);
580 int models= sizeof(canon_model_capabilities) / sizeof(canon_cap_t);
581 for (i=0; i<models; i++) {
582 if (!strcmp(canon_model_capabilities[i].name,name)) {
583 stp_free(name);
584 return &(canon_model_capabilities[i]);
585 }
586 }
587 stp_eprintf(v,"canon: model %s not found in capabilities list=> using default\n",name);
588 stp_free(name);
589 return &(canon_model_capabilities[0]);
590 }
591
592 static const canon_slot_t *
canon_source_type(const char * name,const canon_cap_t * caps)593 canon_source_type(const char *name, const canon_cap_t * caps)
594 {
595 if(name){
596 int i;
597 for(i=0; i<caps->slotlist->count; i++){
598 if( !strcmp(name,caps->slotlist->slots[i].name))
599 return &(caps->slotlist->slots[i]);
600 }
601 }
602 return &(caps->slotlist->slots[0]);
603 }
604
605 /* function returns the current set printmode (specified by resolution) */
606 /* if no mode is set the default mode will be returned */
canon_get_current_mode(const stp_vars_t * v)607 static const canon_mode_t* canon_get_current_mode(const stp_vars_t *v){
608 #if 0
609 const char* input_slot = stp_get_string_parameter(v, "InputSlot");
610 const char *quality = stp_get_string_parameter(v, "Quality");
611 #endif
612 const char *resolution = stp_get_string_parameter(v, "Resolution");
613 const canon_cap_t * caps = canon_get_model_capabilities(v);
614 const canon_mode_t* mode = NULL;
615 const char *ink_type = stp_get_string_parameter(v, "InkType");/*debug*/
616 const char *ink_set = stp_get_string_parameter(v, "InkSet");/*debug*/
617 int i;
618
619 stp_dprintf(STP_DBG_CANON, v,"Entered canon_get_current_mode\n");
620
621 if (ink_set)
622 stp_dprintf(STP_DBG_CANON, v,"DEBUG: Gutenprint: InkSet value (high priority): '%s'\n",ink_set);
623 else
624 stp_dprintf(STP_DBG_CANON, v,"DEBUG: Gutenprint: InkSet value is NULL\n");
625
626 if (ink_type)
627 stp_dprintf(STP_DBG_CANON, v,"DEBUG: Gutenprint: InkType value (low priority): '%s'\n",ink_type);
628 else
629 stp_dprintf(STP_DBG_CANON, v,"DEBUG: Gutenprint: InkType value is NULL\n");
630
631 if(resolution){
632 for(i=0;i<caps->modelist->count;i++){
633 if(!strcmp(resolution,caps->modelist->modes[i].name)){
634 mode = &caps->modelist->modes[i];
635 break;
636 }
637 }
638 }
639 #if 0
640 if(!mode)
641 mode = &caps->modelist->modes[caps->modelist->default_mode];
642 #endif
643
644 #if 0
645 if(quality && strcmp(quality, "None") == 0)
646 quality = "Standard";
647
648 if(quality && !strcmp(quality,"Standard")){
649 return &caps->modelist->modes[caps->modelist->default_mode];
650 }
651 #endif
652
653 #if 0
654 /* only some modes can print to cd */
655 if(input_slot && !strcmp(input_slot,"CD") && !(mode->flags & MODE_FLAG_CD)){
656 for(i=0;i<caps->modelist->count;i++){
657 if(caps->modelist->modes[i].flags & MODE_FLAG_CD){
658 mode = &caps->modelist->modes[i];
659 break;
660 }
661 }
662 }
663 #endif
664
665 stp_dprintf(STP_DBG_CANON, v,"DEBUG: Gutenprint: current mode is '%s'\n",resolution);
666
667 return mode;
668 }
669
select_media_modes(stp_vars_t * v,const canon_paper_t * media_type,const canon_modeuselist_t * mlist)670 const canon_modeuse_t* select_media_modes(stp_vars_t *v, const canon_paper_t* media_type,const canon_modeuselist_t* mlist){
671 const canon_modeuse_t* muse = NULL;
672 int i;
673 for(i=0;i<mlist->count;i++){
674 if(!strcmp(media_type->name,mlist->modeuses[i].name)){
675 muse = &mlist->modeuses[i];
676 stp_dprintf(STP_DBG_CANON, v,"DEBUG: Gutenprint: mode searching: assigned media '%s'\n",mlist->name);
677 break;
678 }
679 }
680 return muse;
681 }
682
compare_mode_valid(stp_vars_t * v,const canon_mode_t * mode,const canon_modeuse_t * muse,const canon_modeuselist_t * mlist)683 int compare_mode_valid(stp_vars_t *v,const canon_mode_t* mode,const canon_modeuse_t* muse, const canon_modeuselist_t* mlist){
684 int i=0;
685 int modecheck=1;
686 stp_dprintf(STP_DBG_CANON, v,"DEBUG: Gutenprint: mode searching: assigned mode-media '%s'\n",mlist->name);
687 while (muse->mode_name_list[i]!=NULL){
688 if(!strcmp(mode->name,muse->mode_name_list[i])){
689 modecheck=0;
690 break;
691 }
692 i++;
693 }
694 return modecheck;
695 }
696
suitable_mode_monochrome(stp_vars_t * v,const canon_modeuse_t * muse,const canon_cap_t * caps,int quality,const char * duplex_mode)697 const canon_mode_t* suitable_mode_monochrome(stp_vars_t *v,const canon_modeuse_t* muse,const canon_cap_t *caps,int quality,const char *duplex_mode) {
698 const canon_mode_t* mode=NULL;
699 int i=0;
700 int j;
701 int modefound=0;
702
703 stp_dprintf(STP_DBG_CANON, v,"DEBUG: Entered suitable_mode_monochrome\n");
704
705 while ((muse->mode_name_list[i]!=NULL) && (modefound != 1)){
706 for(j=0;j<caps->modelist->count;j++){
707 if(!strcmp(muse->mode_name_list[i],caps->modelist->modes[j].name)){/* find right place in canon-modes list */
708 if ( (muse->use_flags & INKSET_BLACK_MODEREPL) ) {
709 /* only look at modes with MODE_FLAG_BLACK if INKSET_BLACK_MODEREPL is in force */
710 if ( (caps->modelist->modes[j].quality >= quality) && (caps->modelist->modes[j].flags & MODE_FLAG_BLACK) ){
711 /* keep setting the mode until lowest matching quality is found */
712 if ( (duplex_mode && strncmp(duplex_mode,"Duplex",6)) || !(muse->use_flags & DUPLEX_SUPPORT) || !(caps->modelist->modes[j].flags & MODE_FLAG_NODUPLEX) ) {
713 /* duplex check -- rare for monochrome, cannot remember any such case */
714 mode = &caps->modelist->modes[j];
715 modefound=1;
716 }
717 }
718 break; /* go to next mode in muse list */
719 }
720 else { /* no special replacement modes for black inkset */
721 if ( (caps->modelist->modes[j].quality >= quality) ){
722 /* keep setting the mode until lowest matching quality is found */
723 if ( (duplex_mode && strncmp(duplex_mode,"Duplex",6)) || !(muse->use_flags & DUPLEX_SUPPORT) || !(caps->modelist->modes[j].flags & MODE_FLAG_NODUPLEX) ) {
724 /* duplex check -- rare for monochrome, cannot remember any such case */
725 mode = &caps->modelist->modes[j];
726 modefound=1;
727 }
728 }
729 break; /* go to next mode in muse list */
730 }
731 }
732 }
733 i++;
734 }
735 return mode;
736 }
737
find_first_matching_mode_monochrome(stp_vars_t * v,const canon_modeuse_t * muse,const canon_cap_t * caps,const char * duplex_mode)738 const canon_mode_t* find_first_matching_mode_monochrome(stp_vars_t *v,const canon_modeuse_t* muse,const canon_cap_t *caps,const char *duplex_mode) {
739 const canon_mode_t* mode=NULL;
740 /* only look at modes with MODE_FLAG_BLACK if INKSET_BLACK_MODEREPL is in force */
741 int i=0;
742 int modefound=0;
743 int j;
744
745 stp_dprintf(STP_DBG_CANON, v,"DEBUG: Entered find_first_matching_mode_monochrome\n");
746
747 while ( (muse->mode_name_list[i]!=NULL) && (modefound != 1) ) {
748 /* pick first mode with MODE_FLAG_BLACK */
749 for(j=0;j<caps->modelist->count;j++){
750 if(!strcmp(muse->mode_name_list[i],caps->modelist->modes[j].name)){/* find right place in canon-modes list */
751 /* only look at modes with MODE_FLAG_BLACK if INKSET_BLACK_MODEREPL is in force */
752 if ( (caps->modelist->modes[j].flags & MODE_FLAG_BLACK) ) {
753 if ( (duplex_mode && strncmp(duplex_mode,"Duplex",6)) || !(muse->use_flags & DUPLEX_SUPPORT) || !(caps->modelist->modes[j].flags & MODE_FLAG_NODUPLEX) ) {
754 /* duplex check -- rare for monochrome, cannot remember any such case */
755 mode = &caps->modelist->modes[j];
756 modefound=1;
757 stp_dprintf(STP_DBG_CANON, v,"DEBUG: Gutenprint (find_first_matching_mode_monochrome): picked monochrome mode (%s)\n",mode->name);
758 }
759 }
760 break; /* go to next mode in muse list */
761 }
762 }
763 i++;
764 }
765 return mode;
766 }
767
find_first_matching_mode(stp_vars_t * v,const canon_modeuse_t * muse,const canon_cap_t * caps,const char * duplex_mode)768 const canon_mode_t* find_first_matching_mode(stp_vars_t *v,const canon_modeuse_t* muse,const canon_cap_t *caps,const char *duplex_mode) {
769 const canon_mode_t* mode=NULL;
770 int i=0;
771 int modefound=0;
772 int j;
773
774 stp_dprintf(STP_DBG_CANON, v,"DEBUG: Entered find_first_matching_mode\n");
775
776 while ( (muse->mode_name_list[i]!=NULL) && (modefound != 1) ) {
777 for(j=0;j<caps->modelist->count;j++){
778 if(!strcmp(muse->mode_name_list[i],caps->modelist->modes[j].name)){/* find right place in canon-modes list */
779 if ( (duplex_mode && strncmp(duplex_mode,"Duplex",6)) || !(muse->use_flags & DUPLEX_SUPPORT) || !(caps->modelist->modes[j].flags & MODE_FLAG_NODUPLEX) ) {
780 /* duplex check */
781 mode = &caps->modelist->modes[j];
782 modefound=1;
783 stp_dprintf(STP_DBG_CANON, v,"DEBUG: Gutenprint (find_first_matching_mode): picked mode without inkset limitation (%s)\n",mode->name);
784 }
785 break; /* go to next mode in muse list */
786 }
787 }
788 i++;
789 }
790 return mode;
791 }
792
suitable_mode_color(stp_vars_t * v,const canon_modeuse_t * muse,const canon_cap_t * caps,int quality,const char * duplex_mode)793 const canon_mode_t* suitable_mode_color(stp_vars_t *v,const canon_modeuse_t* muse,const canon_cap_t *caps,int quality,const char *duplex_mode) {
794 const canon_mode_t* mode=NULL;
795 int i=0;
796 int j;
797 int modefound=0;
798
799 stp_dprintf(STP_DBG_CANON, v,"DEBUG: Entered suitable_mode_color\n");
800
801 while ((muse->mode_name_list[i]!=NULL) && (modefound != 1)){
802 for(j=0;j<caps->modelist->count;j++){
803 if(!strcmp(muse->mode_name_list[i],caps->modelist->modes[j].name)){/* find right place in canon-modes list */
804 if ( (muse->use_flags & INKSET_COLOR_MODEREPL) ) {
805 /* only look at modes with MODE_FLAG_COLOR if INKSET_COLOR_MODEREPL is in force */
806 if ( (caps->modelist->modes[j].quality >= quality) && (caps->modelist->modes[j].flags & MODE_FLAG_COLOR) ) {
807 /* keep setting the mode until lowest matching quality is found */
808 if ( (duplex_mode && strncmp(duplex_mode,"Duplex",6)) || !(muse->use_flags & DUPLEX_SUPPORT) || !(caps->modelist->modes[j].flags & MODE_FLAG_NODUPLEX) ) {
809 /* duplex check */
810 mode = &caps->modelist->modes[j];
811 stp_dprintf(STP_DBG_CANON, v,"DEBUG: Gutenprint (suitable_mode_color): picked mode with special replacement inkset (%s)\n",mode->name);
812 modefound=1;
813 }
814 }
815 break; /* go to next mode in muse list */
816 }
817 else { /* no special replacement modes for color inkset */
818 if ( (caps->modelist->modes[j].quality >= quality) ){
819 /* keep setting the mode until lowest matching quality is found */
820 if ( (duplex_mode && strncmp(duplex_mode,"Duplex",6)) || !(muse->use_flags & DUPLEX_SUPPORT) || !(caps->modelist->modes[j].flags & MODE_FLAG_NODUPLEX) ) {
821 /* duplex check */
822 mode = &caps->modelist->modes[j];
823 stp_dprintf(STP_DBG_CANON, v,"DEBUG: Gutenprint (suitable_mode_color): picked mode without any special replacement inkset (%s)\n",mode->name);
824 modefound=1;
825 }
826 }
827 break; /* go to next mode in muse list */
828 }
829 }
830 }
831 i++;
832 }
833 return mode;
834 }
835
find_first_matching_mode_color(stp_vars_t * v,const canon_modeuse_t * muse,const canon_cap_t * caps,const char * duplex_mode)836 const canon_mode_t* find_first_matching_mode_color(stp_vars_t *v,const canon_modeuse_t* muse,const canon_cap_t *caps,const char *duplex_mode) {
837 const canon_mode_t* mode=NULL;
838 /* only look at modes with MODE_FLAG_COLOR if INKSET_COLOR_MODEREPL is in force */
839 int i=0;
840 int modefound=0;
841 int j;
842
843 stp_dprintf(STP_DBG_CANON, v,"DEBUG: Entered find_first_matching_mode_color\n");
844
845 while ( (muse->mode_name_list[i]!=NULL) && (modefound != 1) ) {
846 /* pick first mode with MODE_FLAG_COLOR */
847 for(j=0;j<caps->modelist->count;j++){
848 if(!strcmp(muse->mode_name_list[i],caps->modelist->modes[j].name)){/* find right place in canon-modes list */
849 /* only look at modes with MODE_FLAG_COLOR if INKSET_COLOR_MODEREPL is in force */
850 if ( (caps->modelist->modes[j].flags & MODE_FLAG_COLOR) ) {
851 if ( (duplex_mode && strncmp(duplex_mode,"Duplex",6)) || !(muse->use_flags & DUPLEX_SUPPORT) || !(caps->modelist->modes[j].flags & MODE_FLAG_NODUPLEX) ) {
852 /* duplex check */
853 mode = &caps->modelist->modes[j];
854 stp_dprintf(STP_DBG_CANON, v,"DEBUG: Gutenprint (find_first_matching_mode_color): picked first mode with special replacement inkset (%s)\n",mode->name);
855 modefound=1;
856 }
857 }
858 break; /* go to next mode in muse list */
859 }
860 }
861 i++;
862 }
863 return mode;
864 }
865
suitable_mode_photo(stp_vars_t * v,const canon_modeuse_t * muse,const canon_cap_t * caps,int quality,const char * duplex_mode)866 const canon_mode_t* suitable_mode_photo(stp_vars_t *v,const canon_modeuse_t* muse,const canon_cap_t *caps,int quality,const char *duplex_mode) {
867 const canon_mode_t* mode=NULL;
868 int i=0;
869 int j;
870 int modefound=0;
871
872 stp_dprintf(STP_DBG_CANON, v,"DEBUG: Entered suitable_mode_photo\n");
873
874 while ((muse->mode_name_list[i]!=NULL) && (modefound != 1)){
875 for(j=0;j<caps->modelist->count;j++){
876 if(!strcmp(muse->mode_name_list[i],caps->modelist->modes[j].name)){/* find right place in canon-modes list */
877 if ( (muse->use_flags & INKSET_PHOTO_MODEREPL) ) {
878 /* only look at modes with MODE_FLAG_PHOTO if INKSET_PHOTO_MODEREPL is in force */
879 if ( (caps->modelist->modes[j].quality >= quality) && (caps->modelist->modes[j].flags & MODE_FLAG_PHOTO) ) {
880 /* keep setting the mode until lowest matching quality is found */
881 if ( (duplex_mode && strncmp(duplex_mode,"Duplex",6)) || !(muse->use_flags & DUPLEX_SUPPORT) || !(caps->modelist->modes[j].flags & MODE_FLAG_NODUPLEX) ) {
882 /* duplex check */
883 mode = &caps->modelist->modes[j];
884 stp_dprintf(STP_DBG_CANON, v,"DEBUG: Gutenprint (suitable_mode_photo): picked first mode with special replacement inkset (%s)\n",mode->name);
885 modefound=1;
886 }
887 }
888 break; /* go to next mode in muse list */
889 }
890 else { /* if no special replacement modes for photo inkset */
891 if ( (caps->modelist->modes[j].quality >= quality) ){
892 /* keep setting the mode until lowest matching quality is found */
893 if ( (duplex_mode && strncmp(duplex_mode,"Duplex",6)) || !(muse->use_flags & DUPLEX_SUPPORT) || !(caps->modelist->modes[j].flags & MODE_FLAG_NODUPLEX) ) {
894 /* duplex check */
895 mode = &caps->modelist->modes[j];
896 stp_dprintf(STP_DBG_CANON, v,"DEBUG: Gutenprint (suitable_mode_photo): picked first mode with photo inkset (%s)\n",mode->name);
897 modefound=1;
898 }
899 }
900 break; /* go to next mode in muse list */
901 }
902 }
903 }
904 i++;
905 }
906 return mode;
907 }
908
find_first_matching_mode_photo(stp_vars_t * v,const canon_modeuse_t * muse,const canon_cap_t * caps,const char * duplex_mode)909 const canon_mode_t* find_first_matching_mode_photo(stp_vars_t *v,const canon_modeuse_t* muse,const canon_cap_t *caps,const char *duplex_mode) {
910 const canon_mode_t* mode=NULL;
911 /* only look at modes with MODE_FLAG_PHOTO if INKSET_PHOTO_MODEREPL is in force */
912 int i=0;
913 int modefound=0;
914 int j;
915
916 stp_dprintf(STP_DBG_CANON, v,"DEBUG: Entered find_first_matching_mode_photo\n");
917
918 while ( (muse->mode_name_list[i]!=NULL) && (modefound != 1) ) {
919 /* pick first mode with MODE_FLAG_PHOTO */
920 for(j=0;j<caps->modelist->count;j++){
921 if(!strcmp(muse->mode_name_list[i],caps->modelist->modes[j].name)){/* find right place in canon-modes list */
922 /* only look at modes with MODE_FLAG_PHOTO if INKSET_PHOTO_MODEREPL is in force */
923 if ( (caps->modelist->modes[j].flags & MODE_FLAG_PHOTO) ) {
924 if ( (duplex_mode && strncmp(duplex_mode,"Duplex",6)) || !(muse->use_flags & DUPLEX_SUPPORT) || !(caps->modelist->modes[j].flags & MODE_FLAG_NODUPLEX) ) {
925 /* duplex check */
926 mode = &caps->modelist->modes[j];
927 stp_dprintf(STP_DBG_CANON, v,"DEBUG: Gutenprint (find_first_matching_mode_photo): picked first mode with photo inkset (%s)\n",mode->name);
928 modefound=1;
929 }
930 }
931 break; /* go to next mode in muse list */
932 }
933 }
934 i++;
935 }
936 return mode;
937 }
938
suitable_mode_general(stp_vars_t * v,const canon_modeuse_t * muse,const canon_cap_t * caps,int quality,const char * duplex_mode)939 const canon_mode_t* suitable_mode_general(stp_vars_t *v,const canon_modeuse_t* muse,const canon_cap_t *caps,int quality,const char *duplex_mode) {
940 const canon_mode_t* mode=NULL;
941 int i=0;
942 int j;
943 int modefound=0;
944
945 stp_dprintf(STP_DBG_CANON, v,"DEBUG: Entered suitable_mode_general\n");
946
947
948 while ((muse->mode_name_list[i]!=NULL) && (modefound != 1)){
949 for(j=0;j<caps->modelist->count;j++){
950 if(!strcmp(muse->mode_name_list[i],caps->modelist->modes[j].name)){/* find right place in canon-modes list */
951 if ( (caps->modelist->modes[j].quality >= quality) ) {
952 /* keep setting the mode until lowest matching quality is found */
953 if ( (duplex_mode && strncmp(duplex_mode,"Duplex",6)) || !(muse->use_flags & DUPLEX_SUPPORT) || !(caps->modelist->modes[j].flags & MODE_FLAG_NODUPLEX) ) {
954 /* duplex check */
955 mode = &caps->modelist->modes[j];
956 stp_dprintf(STP_DBG_CANON, v,"DEBUG: Gutenprint (suitable_mode_general): picked first mode with lowest matching quality (%s)\n",mode->name);
957 modefound=1;
958 }
959 }
960 break; /* go to next mode in muse list */
961 }
962 }
963 i++;
964 }
965 return mode;
966 }
967
find_ink_type(stp_vars_t * v,const canon_mode_t * mode,const char * printing_mode)968 const char* find_ink_type(stp_vars_t *v,const canon_mode_t* mode,const char *printing_mode) {
969 int i,inkfound;
970 const char *ink_type = stp_get_string_parameter(v, "InkType");
971
972 stp_dprintf(STP_DBG_CANON, v,"DEBUG: Entered find_ink_type\n");
973
974 /* if InkType does not match that of mode, change InkType to match it */
975 /* choose highest color as default, as there is only one option for Black */
976 /* if InkType does not match that of mode, change InkType to match it */
977 /* choose highest color as default, as there is only one option for Black */
978 if (printing_mode && !strcmp(printing_mode,"BW")) {
979 stp_dprintf(STP_DBG_CANON, v,"DEBUG: Gutenprint (InkSet:Both): InkType changed to %u (%s)\n",CANON_INK_K, "Gray");
980 stp_set_string_parameter(v, "InkType", "Gray");
981 ink_type = stp_get_string_parameter(v, "InkType");
982 } else {
983 inkfound=0;
984 stp_dprintf(STP_DBG_CANON, v,"DEBUG: Gutenprint (InkSet:Both): InkType of mode %s is currently set as %s\n",mode->name,ink_type);
985 for(i=0;i<sizeof(canon_inktypes)/sizeof(canon_inktypes[0]);i++){
986 if (mode->ink_types & canon_inktypes[i].ink_type) { /* a mode can have several ink_types: must compare with ink_type if set */
987 if ( !(strcmp(ink_type,canon_inktypes[i].name))) {
988 inkfound=1;
989 stp_dprintf(STP_DBG_CANON, v,"DEBUG: Gutenprint (InkSet:Both): InkType match found %i(%s)\n",canon_inktypes[i].ink_type,canon_inktypes[i].name);
990 stp_set_string_parameter(v, "InkType", canon_inktypes[i].name);
991 ink_type = stp_get_string_parameter(v, "InkType");
992 break;
993 }
994 }
995 }
996 /* if no match found choose first available inkset */
997 if (inkfound==0) {
998 for(i=0;i<sizeof(canon_inktypes)/sizeof(canon_inktypes[0]);i++){
999 if (mode->ink_types & canon_inktypes[i].ink_type) { /* a mode can have several ink_types: must compare with ink_type if set */
1000 if ((!ink_type) || (strcmp(ink_type,canon_inktypes[i].name))) { /* if InkType does not match selected mode ink type*/
1001 stp_dprintf(STP_DBG_CANON, v,"DEBUG: Gutenprint (InkSet:Both): No match found---InkType changed to %i(%s)\n",canon_inktypes[i].ink_type,canon_inktypes[i].name);
1002 stp_set_string_parameter(v, "InkType", canon_inktypes[i].name);
1003 ink_type = stp_get_string_parameter(v, "InkType");
1004 inkfound=1; /* set */
1005 break;
1006 }
1007 }
1008 }
1009 }
1010 }
1011 return ink_type;
1012 }
1013
1014 /* function checks printmode (specified by resolution) */
1015 /* and substitutes a mode if needed. NULL is returned for now */
canon_check_current_mode(stp_vars_t * v)1016 const canon_mode_t* canon_check_current_mode(stp_vars_t *v){
1017 #if 0
1018 const char* input_slot = stp_get_string_parameter(v, "InputSlot");
1019 const char *quality = stp_get_string_parameter(v, "Quality");
1020 #endif
1021 const char *resolution = stp_get_string_parameter(v, "Resolution");
1022 const char *ink_set = stp_get_string_parameter(v, "InkSet");
1023 const char *duplex_mode = stp_get_string_parameter(v, "Duplex");
1024 const char *ink_type = stp_get_string_parameter(v, "InkType");
1025 const char *printing_mode = stp_get_string_parameter(v, "PrintingMode");
1026 const canon_cap_t * caps = canon_get_model_capabilities(v);
1027 const canon_mode_t* mode = NULL;
1028 const canon_modeuselist_t* mlist = caps->modeuselist;
1029 const canon_modeuse_t* muse = NULL;
1030 const canon_paper_t* media_type = get_media_type(caps,stp_get_string_parameter(v, "MediaType"));
1031 int i,j;
1032 int modecheck, quality, modefound;
1033 #if 0
1034 int inkfound;
1035 #endif
1036
1037 stp_dprintf(STP_DBG_CANON, v,"Entered canon_check_current_mode: got PrintingMode %s\n",printing_mode);
1038
1039 /* Logic: priority of options
1040 1. Media --- always present for final selection.
1041 2. InkSet (cartridge selection) --- optional as only some printers offer this.
1042 3. PrintingMode --- for printers which have K-only monochrome modes can choose BW.
1043 4. Duplex --- for printers that have special duplex modes need to skip non-duplex modes.
1044 5. InkType --- suggestion only, since modes are tied to ink types in most Canon printers.
1045 6. Quality --- suggestion, based on initially-selected mode.
1046 7. Mode --- once chosen, InkType is selected based on quality, inkset, printing mode.
1047 */
1048
1049 /*
1050 canon-mode-media:
1051 INKSET_BLACK_SUPPORT: media type supports black-only cartridge
1052 INKSET_COLOR_SUPPORT: media type supports color-only cartridge
1053 INKSET_BLACK_MODEREPL: media type has special modes for black-only cartridge
1054 INKSET_COLOR_MODEREPL: media type has special modes for black-only cartridge
1055 INKSET_PHOTO_SUPPORT: media type supports special photo cartridge
1056 DUPLEX_MODEREPL: media type has (a) special mode(s) for duplex
1057 canon-modes.h:
1058 MODE_FLAG_BLACK: mode can be used for supporting black-only cartridge
1059 MODE_FLAG_COLOR: mode can be used for supporting color-only cartridge
1060 MODE_FLAG_PHOTO: mode can be used for supporting photo cartridge
1061 MODE_FLAG_NOPDUPLEX: mode cannot be used for duplex, must be skipped
1062 */
1063
1064 if(resolution){
1065 stp_dprintf(STP_DBG_CANON, v,"DEBUG: Gutenprint: check_current_mode --- (Initial) Resolution already known: '%s'\n",resolution);
1066 for(i=0;i<caps->modelist->count;i++){
1067 if(!strcmp(resolution,caps->modelist->modes[i].name)){
1068 mode = &caps->modelist->modes[i];
1069 break;
1070 }
1071 }
1072 }
1073 else {
1074 stp_dprintf(STP_DBG_CANON, v,"DEBUG: Gutenprint: check_current_mode --- (Initial) Resolution not yet known \n");
1075 }
1076
1077 if (ink_set)
1078 stp_dprintf(STP_DBG_CANON, v,"DEBUG: Gutenprint: (Initial) InkSet value (high priority): '%s'\n",ink_set);
1079 else
1080 stp_dprintf(STP_DBG_CANON, v,"DEBUG: Gutenprint: (Initial) InkSet value is NULL\n");
1081
1082 if (ink_type)
1083 stp_dprintf(STP_DBG_CANON, v,"DEBUG: Gutenprint: (Initial) InkType value (low priority): '%s'\n",ink_type);
1084 else
1085 stp_dprintf(STP_DBG_CANON, v,"DEBUG: Gutenprint: (Initial) InkType value is NULL\n");
1086
1087 /* beginning of mode replacement code */
1088 if (media_type && resolution && mode) {
1089 stp_dprintf(STP_DBG_CANON, v,"DEBUG: Gutenprint: check_current_mode --- Resolution, Media, Mode all known \n");
1090 stp_dprintf(STP_DBG_CANON, v,"DEBUG: Gutenprint: media type selected: '%s'\n",media_type->name);
1091 stp_dprintf(STP_DBG_CANON, v,"DEBUG: (Initial) Gutenprint: mode initially active: '%s'\n",mode->name);
1092
1093 /* scroll through modeuse list to find media */
1094 muse = select_media_modes(v,media_type,mlist);
1095
1096 /* now scroll through to find if the mode is in the modeuses list */
1097 modecheck=compare_mode_valid(v,mode,muse,mlist);
1098
1099 stp_dprintf(STP_DBG_CANON, v,"DEBUG: (mode replacement) Gutenprint: modecheck value: '%i'\n",modecheck);
1100
1101 /* if we did not find a valid mode, need to replace it */
1102 if (modecheck!=0) {
1103
1104 stp_dprintf(STP_DBG_CANON, v,"DEBUG: Gutenprint (check_current_mode): no suitable mode exists, need to find a mode\n");
1105
1106 quality = mode->quality;
1107 /* Black InkSet */
1108 if (ink_set && !strcmp(ink_set,"Black")) {
1109 stp_set_string_parameter(v, "PrintingMode","BW");
1110 printing_mode = stp_get_string_parameter(v, "PrintingMode");
1111 if (!(mode->ink_types & CANON_INK_K)) {
1112
1113 /* need a new mode:
1114 loop through modes in muse list searching for a matching inktype, comparing quality
1115 */
1116 mode=suitable_mode_monochrome(v,muse,caps,quality,duplex_mode);
1117 if (!mode)
1118 modefound=0;
1119 else
1120 modefound=1;
1121
1122 if (modefound == 0) { /* still did not find a mode: pick first one for that media matching the InkSet limitation */
1123 if ( (muse->use_flags & INKSET_BLACK_MODEREPL) ) {
1124 mode=find_first_matching_mode_monochrome(v,muse,caps,duplex_mode);
1125 }
1126 else { /* no special replacement modes for black inkset */
1127 mode=find_first_matching_mode(v,muse,caps,duplex_mode);
1128 stp_dprintf(STP_DBG_CANON, v,"Gutenprint (check_current_mode): Ink set is set to CANON_INK_K but did no special conditions, so first match taken: '%s'\n",mode->name);
1129 }
1130 }
1131 if (!mode)
1132 modefound=0;
1133 else
1134 modefound=1;
1135
1136 /* set InkType for the mode found */
1137 for(i=0;i<sizeof(canon_inktypes)/sizeof(canon_inktypes[0]);i++){
1138 if (mode->ink_types & canon_inktypes[i].ink_type) {
1139 if (strcmp(ink_type,canon_inktypes[i].name)) { /* if InkType does not match selected mode ink type*/
1140 stp_dprintf(STP_DBG_CANON, v,"DEBUG: Gutenprint (InkSet:Black): InkType changed to %i(%s)\n",canon_inktypes[i].ink_type,canon_inktypes[i].name);
1141 stp_set_string_parameter(v, "InkType", canon_inktypes[i].name);
1142 ink_type = stp_get_string_parameter(v, "InkType");
1143 break;
1144 }
1145 }
1146 }
1147 }
1148 else {
1149 /* mode is fine */
1150 /* matched expected K inkset, but need to check if Duplex matches, and if not, get a new mode with right inkset */
1151 mode=suitable_mode_monochrome(v,muse,caps,quality,duplex_mode);
1152 stp_dprintf(STP_DBG_CANON, v,"Gutenprint (check_current_mode): Ink set is set to CANON_INK_K and mode already fits (but need to check for duplex condition): '%s'\n",mode->name);
1153 if (!mode)
1154 modefound=0;
1155 else
1156 modefound=1;
1157
1158 if (modefound == 0) { /* still did not find a mode: pick first one for that media matching the InkSet limitation */
1159 if ( (muse->use_flags & INKSET_BLACK_MODEREPL) ) {
1160 mode=find_first_matching_mode_monochrome(v,muse,caps,duplex_mode);
1161 stp_dprintf(STP_DBG_CANON, v,"Gutenprint (check_current_mode): Ink set is set to CANON_INK_K, pick first one matching condition for black mode replacement: '%s'\n",mode->name);
1162 }
1163 else { /* no special replacement modes for black inkset */
1164 mode=find_first_matching_mode(v,muse,caps,duplex_mode);
1165 stp_dprintf(STP_DBG_CANON, v,"Gutenprint (check_current_mode): Ink set is set to CANON_INK_K, pick first one matching condition without mode replacement needed: '%s'\n",mode->name);
1166 }
1167 }
1168
1169 ink_type=find_ink_type(v,mode,printing_mode);
1170 #if 0
1171 /* if InkType does not match that of mode, change InkType to match it */
1172 /* choose highest color as default, as there is only one option for Black */
1173 /* if InkType does not match that of mode, change InkType to match it */
1174 /* choose highest color as default, as there is only one option for Black */
1175 if (printing_mode && !strcmp(printing_mode,"BW")) {
1176 stp_dprintf(STP_DBG_CANON, v,"DEBUG: Gutenprint (InkSet:Black): InkType changed to %u (%s)\n",CANON_INK_K, "Gray");
1177 stp_set_string_parameter(v, "InkType", "Gray");
1178 ink_type = stp_get_string_parameter(v, "InkType");
1179 } else {
1180 inkfound=0;
1181 stp_dprintf(STP_DBG_CANON, v,"DEBUG: Gutenprint (InkSet:Black): InkType of mode %s is currently set as %s\n",mode->name,ink_type);
1182 for(i=0;i<sizeof(canon_inktypes)/sizeof(canon_inktypes[0]);i++){
1183 if (mode->ink_types & canon_inktypes[i].ink_type) { /* a mode can have several ink_types: must compare with ink_type if set */
1184 if ( !(strcmp(ink_type,canon_inktypes[i].name))) {
1185 inkfound=1;
1186 stp_dprintf(STP_DBG_CANON, v,"DEBUG: Gutenprint (InkSet:Black): InkType match found %i(%s)\n",canon_inktypes[i].ink_type,canon_inktypes[i].name);
1187 stp_set_string_parameter(v, "InkType", canon_inktypes[i].name);
1188 ink_type = stp_get_string_parameter(v, "InkType");
1189 break;
1190 }
1191 }
1192 }
1193 /* if no match found choose first available inkset */
1194 if (inkfound==0) {
1195 for(i=0;i<sizeof(canon_inktypes)/sizeof(canon_inktypes[0]);i++){
1196 if (mode->ink_types & canon_inktypes[i].ink_type) { /* a mode can have several ink_types: must compare with ink_type if set */
1197 if ((!ink_type) || (strcmp(ink_type,canon_inktypes[i].name))) { /* if InkType does not match selected mode ink type*/
1198 stp_dprintf(STP_DBG_CANON, v,"DEBUG: Gutenprint (InkSet:Black): No match found---InkType changed to %i(%s)\n",canon_inktypes[i].ink_type,canon_inktypes[i].name);
1199 stp_set_string_parameter(v, "InkType", canon_inktypes[i].name);
1200 ink_type = stp_get_string_parameter(v, "InkType");
1201 inkfound=1; /* set */
1202 break;
1203 }
1204 }
1205 }
1206 }
1207 }
1208 #endif
1209
1210 #if 0
1211 /* set InkType for the mode found */
1212 for(i=0;i<sizeof(canon_inktypes)/sizeof(canon_inktypes[0]);i++){
1213 if (mode->ink_types & canon_inktypes[i].ink_type) {
1214 if (strcmp(ink_type,canon_inktypes[i].name)) { /* if InkType does not match selected mode ink type*/
1215 stp_dprintf(STP_DBG_CANON, v,"DEBUG: Gutenprint (InkSet:Black): InkType changed to %i(%s)\n",canon_inktypes[i].ink_type,canon_inktypes[i].name);
1216 stp_set_string_parameter(v, "InkType", canon_inktypes[i].name);
1217 ink_type = stp_get_string_parameter(v, "InkType");
1218 break;
1219 }
1220 }
1221 }
1222 #endif
1223
1224 }
1225 } /* End of Black Inkset */
1226 /*-------------------------------------------------------------------------------------------------*/
1227 /* Color InkSet */
1228 /* Added limitation: "Color" for BJC corresponds to "Both" on other types */
1229 else if ( (ink_set && !strcmp(ink_set,"Color")) && (caps->features & CANON_CAP_T) ) {
1230 stp_set_string_parameter(v, "PrintingMode","Color");
1231 printing_mode = stp_get_string_parameter(v, "PrintingMode");
1232 if (!(mode->ink_types & CANON_INK_CMY)) {
1233 stp_dprintf(STP_DBG_CANON, v,"DEBUG: Gutenprint (InkSet:Color): inkset incorrect for Color cartridge---need new mode\n");
1234 /* need a new mode
1235 loop through modes in muse list searching for a matching inktype, comparing quality
1236 */
1237 mode=suitable_mode_color(v,muse,caps,quality,duplex_mode);
1238 if (!mode)
1239 modefound=0;
1240 else
1241 modefound=1;
1242
1243 if (modefound == 0) { /* still did not find a mode: pick first one for that media */
1244 if ( (muse->use_flags & INKSET_COLOR_MODEREPL) ) {
1245 mode=find_first_matching_mode_color(v,muse,caps,duplex_mode);
1246 stp_dprintf(STP_DBG_CANON, v,"DEBUG: Gutenprint (InkSet:Color): Decided on first matching mode for color inkset (%s)\n",mode->name);
1247 }
1248 else { /* no special replacement modes for color inkset */
1249 mode=find_first_matching_mode(v,muse,caps,duplex_mode);
1250 stp_dprintf(STP_DBG_CANON, v,"DEBUG: Gutenprint (InkSet:Color): Decided on first matching mode with no special replacement modes for color inkset (%s)\n",mode->name);
1251 }
1252 }
1253 if (!mode)
1254 modefound=0;
1255 else
1256 modefound=1;
1257
1258 ink_type=find_ink_type(v,mode,printing_mode);
1259 #if 0
1260 /* if InkType does not match that of mode, change InkType to match it */
1261 /* choose highest color as default, as there is only one option for Black */
1262 /* if InkType does not match that of mode, change InkType to match it */
1263 /* choose highest color as default, as there is only one option for Black */
1264 if (printing_mode && !strcmp(printing_mode,"BW")) {
1265 stp_dprintf(STP_DBG_CANON, v,"DEBUG: Gutenprint (InkSet:Color): InkType changed to %u (%s)\n",CANON_INK_K, "Gray");
1266 stp_set_string_parameter(v, "InkType", "Gray");
1267 ink_type = stp_get_string_parameter(v, "InkType");
1268 } else {
1269 inkfound=0;
1270 stp_dprintf(STP_DBG_CANON, v,"DEBUG: Gutenprint (InkSet:Color): InkType of mode %s is currently set as %s\n",mode->name,ink_type);
1271 for(i=0;i<sizeof(canon_inktypes)/sizeof(canon_inktypes[0]);i++){
1272 if (mode->ink_types & canon_inktypes[i].ink_type) { /* a mode can have several ink_types: must compare with ink_type if set */
1273 if ( !(strcmp(ink_type,canon_inktypes[i].name))) {
1274 inkfound=1;
1275 stp_dprintf(STP_DBG_CANON, v,"DEBUG: Gutenprint (InkSet:Color): InkType match found %i(%s)\n",canon_inktypes[i].ink_type,canon_inktypes[i].name);
1276 stp_set_string_parameter(v, "InkType", canon_inktypes[i].name);
1277 ink_type = stp_get_string_parameter(v, "InkType");
1278 break;
1279 }
1280 }
1281 }
1282 /* if no match found choose first available inkset */
1283 if (inkfound==0) {
1284 for(i=0;i<sizeof(canon_inktypes)/sizeof(canon_inktypes[0]);i++){
1285 if (mode->ink_types & canon_inktypes[i].ink_type) { /* a mode can have several ink_types: must compare with ink_type if set */
1286 if ((!ink_type) || (strcmp(ink_type,canon_inktypes[i].name))) { /* if InkType does not match selected mode ink type*/
1287 stp_dprintf(STP_DBG_CANON, v,"DEBUG: Gutenprint (InkSet:Both): No match found---InkType changed to %i(%s)\n",canon_inktypes[i].ink_type,canon_inktypes[i].name);
1288 stp_set_string_parameter(v, "InkType", canon_inktypes[i].name);
1289 ink_type = stp_get_string_parameter(v, "InkType");
1290 inkfound=1; /* set */
1291 break;
1292 }
1293 }
1294 }
1295 }
1296 }
1297 #endif
1298 #if 0
1299 /* set InkType for the mode found */
1300 for(i=0;i<sizeof(canon_inktypes)/sizeof(canon_inktypes[0]);i++){
1301 if (mode->ink_types & canon_inktypes[i].ink_type) {
1302 if (strcmp(ink_type,canon_inktypes[i].name)) { /* if InkType does not match selected mode ink type*/
1303 stp_dprintf(STP_DBG_CANON, v,"DEBUG: Gutenprint (InkSet:Color): InkType changed to %i(%s)\n",canon_inktypes[i].ink_type,canon_inktypes[i].name);
1304 stp_set_string_parameter(v, "InkType", canon_inktypes[i].name);
1305 ink_type = stp_get_string_parameter(v, "InkType");
1306 break;
1307 }
1308 }
1309 }
1310 #endif
1311
1312 }
1313 else {
1314 /* mode is fine */
1315 /* matched expected RGB inkset, but need to check if Duplex matches, and if not, get a new mode with right inkset */
1316 stp_dprintf(STP_DBG_CANON, v,"DEBUG: Gutenprint (InkSet:Color): inkset OK but need to check other parameters\n");
1317 mode=suitable_mode_color(v,muse,caps,quality,duplex_mode);
1318 if (!mode)
1319 modefound=0;
1320 else
1321 modefound=1;
1322
1323 if (modefound == 0) { /* still did not find a mode: pick first one for that media */
1324 if ( (muse->use_flags & INKSET_COLOR_MODEREPL) ) {
1325 mode=find_first_matching_mode_color(v,muse,caps,duplex_mode);
1326 stp_dprintf(STP_DBG_CANON, v,"DEBUG: Gutenprint (InkSet:Color): Decided on first matching mode for color inkset (%s)\n",mode->name);
1327 }
1328 else { /* no special replacement modes for color inkset */
1329 mode=find_first_matching_mode(v,muse,caps,duplex_mode);
1330 stp_dprintf(STP_DBG_CANON, v,"DEBUG: Gutenprint (InkSet:Color): Decided on first matching mode with no special replacement modes for color inkset (%s)\n",mode->name);
1331 }
1332 }
1333 if (!mode)
1334 modefound=0;
1335 else
1336 modefound=1;
1337
1338 ink_type=find_ink_type(v,mode,printing_mode);
1339 #if 0
1340 /* if InkType does not match that of mode, change InkType to match it */
1341 /* choose highest color as default, as there is only one option for Black */
1342 /* if InkType does not match that of mode, change InkType to match it */
1343 /* choose highest color as default, as there is only one option for Black */
1344 if (printing_mode && !strcmp(printing_mode,"BW")) {
1345 stp_dprintf(STP_DBG_CANON, v,"DEBUG: Gutenprint (InkSet:Color): InkType changed to %u (%s)\n",CANON_INK_K, "Gray");
1346 stp_set_string_parameter(v, "InkType", "Gray");
1347 ink_type = stp_get_string_parameter(v, "InkType");
1348 } else {
1349 inkfound=0;
1350 stp_dprintf(STP_DBG_CANON, v,"DEBUG: Gutenprint (InkSet:Color): InkType of mode %s is currently set as %s\n",mode->name,ink_type);
1351 for(i=0;i<sizeof(canon_inktypes)/sizeof(canon_inktypes[0]);i++){
1352 if (mode->ink_types & canon_inktypes[i].ink_type) { /* a mode can have several ink_types: must compare with ink_type if set */
1353 if ( !(strcmp(ink_type,canon_inktypes[i].name))) {
1354 inkfound=1;
1355 stp_dprintf(STP_DBG_CANON, v,"DEBUG: Gutenprint (InkSet:Color): InkType match found %i(%s)\n",canon_inktypes[i].ink_type,canon_inktypes[i].name);
1356 stp_set_string_parameter(v, "InkType", canon_inktypes[i].name);
1357 ink_type = stp_get_string_parameter(v, "InkType");
1358 break;
1359 }
1360 }
1361 }
1362 /* if no match found choose first available inkset */
1363 if (inkfound==0) {
1364 for(i=0;i<sizeof(canon_inktypes)/sizeof(canon_inktypes[0]);i++){
1365 if (mode->ink_types & canon_inktypes[i].ink_type) { /* a mode can have several ink_types: must compare with ink_type if set */
1366 if ((!ink_type) || (strcmp(ink_type,canon_inktypes[i].name))) { /* if InkType does not match selected mode ink type*/
1367 stp_dprintf(STP_DBG_CANON, v,"DEBUG: Gutenprint (InkSet:Color): No match found---InkType changed to %i(%s)\n",canon_inktypes[i].ink_type,canon_inktypes[i].name);
1368 stp_set_string_parameter(v, "InkType", canon_inktypes[i].name);
1369 ink_type = stp_get_string_parameter(v, "InkType");
1370 inkfound=1; /* set */
1371 break;
1372 }
1373 }
1374 }
1375 }
1376 }
1377 #endif
1378 #if 0
1379 /* set InkType for the mode found */
1380 for(i=0;i<sizeof(canon_inktypes)/sizeof(canon_inktypes[0]);i++){
1381 if (mode->ink_types & canon_inktypes[i].ink_type) {
1382 if (strcmp(ink_type,canon_inktypes[i].name)) { /* if InkType does not match selected mode ink type*/
1383 stp_dprintf(STP_DBG_CANON, v,"DEBUG: Gutenprint (InkSet:Color): InkType changed to %i(%s)\n",canon_inktypes[i].ink_type,canon_inktypes[i].name);
1384 stp_set_string_parameter(v, "InkType", canon_inktypes[i].name);
1385 ink_type = stp_get_string_parameter(v, "InkType");
1386 break;
1387 }
1388 }
1389 }
1390 #endif
1391
1392 }
1393 } /* end of Color InkSet */
1394 /*-------------------------------------------------------------------------------------------------*/
1395 /* Photo cartridge selection: only use modes that support it */
1396 else if (ink_set && !strcmp(ink_set,"Photo")) {
1397 /* Photo cartridge printing does not seem to have any monochrome option */
1398 stp_set_string_parameter(v, "PrintingMode","Color");
1399 printing_mode = stp_get_string_parameter(v, "PrintingMode");
1400 /* need to match photo cartridge mode flag */
1401 if (!(mode->flags & MODE_FLAG_PHOTO)) {
1402 /* need a new mode
1403 loop through modes in muse list searching for a matching inkset, comparing quality
1404 */
1405 mode=suitable_mode_photo(v,muse,caps,quality,duplex_mode);
1406 if (!mode)
1407 modefound=0;
1408 else
1409 modefound=1;
1410
1411 if (modefound == 0) { /* still did not find a mode: pick first one for that media */
1412 if ( (muse->use_flags & INKSET_PHOTO_MODEREPL) ) {
1413 mode=find_first_matching_mode_photo(v,muse,caps,duplex_mode);
1414 }
1415 else { /* no special replacement modes for photo inkset */
1416 mode=find_first_matching_mode(v,muse,caps,duplex_mode);
1417 }
1418 }
1419 if (!mode)
1420 modefound=0;
1421 else
1422 modefound=1;
1423
1424 ink_type=find_ink_type(v,mode,printing_mode);
1425 #if 0
1426 /* if InkType does not match that of mode, change InkType to match it */
1427 /* choose highest color as default, as there is only one option for Black */
1428 /* if InkType does not match that of mode, change InkType to match it */
1429 /* choose highest color as default, as there is only one option for Black */
1430 if (printing_mode && !strcmp(printing_mode,"BW")) {
1431 stp_dprintf(STP_DBG_CANON, v,"DEBUG: Gutenprint (InkSet:Both): InkType changed to %u (%s)\n",CANON_INK_K, "Gray");
1432 stp_set_string_parameter(v, "InkType", "Gray");
1433 ink_type = stp_get_string_parameter(v, "InkType");
1434 } else {
1435 inkfound=0;
1436 stp_dprintf(STP_DBG_CANON, v,"DEBUG: Gutenprint (InkSet:Both): InkType of mode %s is currently set as %s\n",mode->name,ink_type);
1437 for(i=0;i<sizeof(canon_inktypes)/sizeof(canon_inktypes[0]);i++){
1438 if (mode->ink_types & canon_inktypes[i].ink_type) { /* a mode can have several ink_types: must compare with ink_type if set */
1439 if ( !(strcmp(ink_type,canon_inktypes[i].name))) {
1440 inkfound=1;
1441 stp_dprintf(STP_DBG_CANON, v,"DEBUG: Gutenprint (InkSet:Both): InkType match found %i(%s)\n",canon_inktypes[i].ink_type,canon_inktypes[i].name);
1442 stp_set_string_parameter(v, "InkType", canon_inktypes[i].name);
1443 ink_type = stp_get_string_parameter(v, "InkType");
1444 break;
1445 }
1446 }
1447 }
1448 /* if no match found choose first available inkset */
1449 if (inkfound==0) {
1450 for(i=0;i<sizeof(canon_inktypes)/sizeof(canon_inktypes[0]);i++){
1451 if (mode->ink_types & canon_inktypes[i].ink_type) { /* a mode can have several ink_types: must compare with ink_type if set */
1452 if ((!ink_type) || (strcmp(ink_type,canon_inktypes[i].name))) { /* if InkType does not match selected mode ink type*/
1453 stp_dprintf(STP_DBG_CANON, v,"DEBUG: Gutenprint (InkSet:Both): No match found---InkType changed to %i(%s)\n",canon_inktypes[i].ink_type,canon_inktypes[i].name);
1454 stp_set_string_parameter(v, "InkType", canon_inktypes[i].name);
1455 ink_type = stp_get_string_parameter(v, "InkType");
1456 inkfound=1; /* set */
1457 break;
1458 }
1459 }
1460 }
1461 }
1462 }
1463 #endif
1464 #if 0
1465 /* set InkType for the mode found */
1466 for(i=0;i<sizeof(canon_inktypes)/sizeof(canon_inktypes[0]);i++){
1467 if (mode->ink_types & canon_inktypes[i].ink_type) {
1468 if (strcmp(ink_type,canon_inktypes[i].name)) { /* if InkType does not match selected mode ink type*/
1469 stp_dprintf(STP_DBG_CANON, v,"DEBUG: Gutenprint (InkSet:Color): InkType changed to %i(%s)\n",canon_inktypes[i].ink_type,canon_inktypes[i].name);
1470 stp_set_string_parameter(v, "InkType", canon_inktypes[i].name);
1471 ink_type = stp_get_string_parameter(v, "InkType");
1472 break;
1473 }
1474 }
1475 }
1476 #endif
1477
1478 }
1479 else {
1480 /* mode is fine */
1481 /* matched expected inkset, but need to check if Duplex matches, and if not, get a new mode with right inkset */
1482 mode=suitable_mode_photo(v,muse,caps,quality,duplex_mode);
1483 if (!mode)
1484 modefound=0;
1485 else
1486 modefound=1;
1487
1488 if (modefound == 0) { /* still did not find a mode: pick first one for that media */
1489 if ( (muse->use_flags & INKSET_PHOTO_MODEREPL) ) {
1490 mode=find_first_matching_mode_photo(v,muse,caps,duplex_mode);
1491 }
1492 else { /* no special replacement modes for photo inkset */
1493 mode=find_first_matching_mode(v,muse,caps,duplex_mode);
1494 }
1495 }
1496 if (!mode)
1497 modefound=0;
1498 else
1499 modefound=1;
1500
1501 ink_type=find_ink_type(v,mode,printing_mode);
1502 #if 0
1503 /* if InkType does not match that of mode, change InkType to match it */
1504 /* choose highest color as default, as there is only one option for Black */
1505 /* if InkType does not match that of mode, change InkType to match it */
1506 /* choose highest color as default, as there is only one option for Black */
1507 if (printing_mode && !strcmp(printing_mode,"BW")) {
1508 stp_dprintf(STP_DBG_CANON, v,"DEBUG: Gutenprint (InkSet:Both): InkType changed to %u (%s)\n",CANON_INK_K, "Gray");
1509 stp_set_string_parameter(v, "InkType", "Gray");
1510 ink_type = stp_get_string_parameter(v, "InkType");
1511 } else {
1512 inkfound=0;
1513 stp_dprintf(STP_DBG_CANON, v,"DEBUG: Gutenprint (InkSet:Both): InkType of mode %s is currently set as %s\n",mode->name,ink_type);
1514 for(i=0;i<sizeof(canon_inktypes)/sizeof(canon_inktypes[0]);i++){
1515 if (mode->ink_types & canon_inktypes[i].ink_type) { /* a mode can have several ink_types: must compare with ink_type if set */
1516 if ( !(strcmp(ink_type,canon_inktypes[i].name))) {
1517 inkfound=1;
1518 stp_dprintf(STP_DBG_CANON, v,"DEBUG: Gutenprint (InkSet:Both): InkType match found %i(%s)\n",canon_inktypes[i].ink_type,canon_inktypes[i].name);
1519 stp_set_string_parameter(v, "InkType", canon_inktypes[i].name);
1520 ink_type = stp_get_string_parameter(v, "InkType");
1521 break;
1522 }
1523 }
1524 }
1525 /* if no match found choose first available inkset */
1526 if (inkfound==0) {
1527 for(i=0;i<sizeof(canon_inktypes)/sizeof(canon_inktypes[0]);i++){
1528 if (mode->ink_types & canon_inktypes[i].ink_type) { /* a mode can have several ink_types: must compare with ink_type if set */
1529 if ((!ink_type) || (strcmp(ink_type,canon_inktypes[i].name))) { /* if InkType does not match selected mode ink type*/
1530 stp_dprintf(STP_DBG_CANON, v,"DEBUG: Gutenprint (InkSet:Both): No match found---InkType changed to %i(%s)\n",canon_inktypes[i].ink_type,canon_inktypes[i].name);
1531 stp_set_string_parameter(v, "InkType", canon_inktypes[i].name);
1532 ink_type = stp_get_string_parameter(v, "InkType");
1533 inkfound=1; /* set */
1534 break;
1535 }
1536 }
1537 }
1538 }
1539 }
1540 #endif
1541 #if 0
1542 /* set InkType for the mode found */
1543 for(i=0;i<sizeof(canon_inktypes)/sizeof(canon_inktypes[0]);i++){
1544 if (mode->ink_types & canon_inktypes[i].ink_type) {
1545 if (strcmp(ink_type,canon_inktypes[i].name)) { /* if InkType does not match selected mode ink type*/
1546 stp_dprintf(STP_DBG_CANON, v,"DEBUG: Gutenprint (InkSet:Color): InkType changed to %i(%s)\n",canon_inktypes[i].ink_type,canon_inktypes[i].name);
1547 stp_set_string_parameter(v, "InkType", canon_inktypes[i].name);
1548 ink_type = stp_get_string_parameter(v, "InkType");
1549 break;
1550 }
1551 }
1552 }
1553
1554 #endif
1555
1556 }
1557 } /* end of Photo Inkset */
1558 /*-------------------------------------------------------------------------------------------------*/
1559 /* no restrictions for InkSet "Both" (non-BJC) or "Color" (BJC) or if no InkSet set yet --- do not worry about InkSet at all */
1560 else {
1561 if (printing_mode && !strcmp(printing_mode,"Color")) {
1562 stp_dprintf(STP_DBG_CANON, v,"DEBUG: Gutenprint (InkSet:Both) PrintingMode Color\n");
1563 /* must skip K-only inksets if they exist: they only exist if the option "BW" is also declared but we cannot check if an option exists or not */
1564 i=0;
1565 quality = mode->quality;
1566 modefound=0;
1567 while ( (muse->mode_name_list[i]!=NULL) && (modefound != 1) ) {
1568 for(j=0;j<caps->modelist->count;j++){
1569 if(!strcmp(muse->mode_name_list[i],caps->modelist->modes[j].name)){/* find right place in canon-modes list */
1570 if ( (caps->modelist->modes[j].quality >= quality) ) {
1571 if ( (duplex_mode && strncmp(duplex_mode,"Duplex",6)) || !(muse->use_flags & DUPLEX_SUPPORT) || !(caps->modelist->modes[j].flags & MODE_FLAG_NODUPLEX) ) {
1572 /* duplex check */
1573 if (caps->modelist->modes[j].ink_types > CANON_INK_K) {
1574 mode = &caps->modelist->modes[j];
1575 stp_dprintf(STP_DBG_CANON, v,"DEBUG: Gutenprint (check_current_mode, Both/Color, printmode color): picked first mode with color inkset (%s)\n",mode->name);
1576 modefound=1;
1577 }
1578 }
1579 }
1580 break; /* go to next mode in muse list */
1581 }
1582 }
1583 i++;
1584 }
1585 }
1586 else if (printing_mode && !strcmp(printing_mode,"BW")) {
1587 stp_dprintf(STP_DBG_CANON, v,"DEBUG: Gutenprint (InkSet:Both) PrintingMode BW\n");
1588 /* need to find K-only inksets: they must exist since we declared the printer to have this capability! */
1589 i=0;
1590 quality = mode->quality;
1591 modefound=0;
1592 while ( (muse->mode_name_list[i]!=NULL) && (modefound != 1) ) {
1593 for(j=0;j<caps->modelist->count;j++){
1594 if(!strcmp(muse->mode_name_list[i],caps->modelist->modes[j].name)){/* find right place in canon-modes list */
1595 if ( (caps->modelist->modes[j].quality >= quality) ) {
1596 if ( (duplex_mode && strncmp(duplex_mode,"Duplex",6)) || !(muse->use_flags & DUPLEX_SUPPORT) || !(caps->modelist->modes[j].flags & MODE_FLAG_NODUPLEX) ) {
1597 /* duplex check */
1598 if (caps->modelist->modes[j].ink_types & CANON_INK_K) { /* AND means support for CANON_IN_K is included */
1599 mode = &caps->modelist->modes[j];
1600 stp_dprintf(STP_DBG_CANON, v,"DEBUG: Gutenprint (check_current_mode, Both/Color, printmode BW): picked first mode with mono inkset (%s)\n",mode->name);
1601 modefound=1;
1602 }
1603 }
1604 }
1605 break; /* go to next mode in muse list */
1606 }
1607 }
1608 i++;
1609 }
1610 }
1611 else { /* no restriction from PrintingMode if not set yet */
1612 stp_dprintf(STP_DBG_CANON, v,"DEBUG: Gutenprint (InkSet:Both) PrintingMode not set yet\n");
1613 /* if mode is not a matching duplex mode, need to find a new one */
1614 i=0;
1615 quality = mode->quality;
1616 modefound=0;
1617 while ( (muse->mode_name_list[i]!=NULL) && (modefound != 1) ) {
1618 for(j=0;j<caps->modelist->count;j++){
1619 if(!strcmp(muse->mode_name_list[i],caps->modelist->modes[j].name)){/* find right place in canon-modes list */
1620 if ( (caps->modelist->modes[j].quality >= quality) ) {
1621 if ( !(duplex_mode) || !(muse->use_flags & DUPLEX_SUPPORT) || !(caps->modelist->modes[j].flags & MODE_FLAG_NODUPLEX) ) {
1622 /* duplex check */
1623 mode = &caps->modelist->modes[j];
1624 stp_dprintf(STP_DBG_CANON, v,"DEBUG: Gutenprint (check_current_mode, Both/Color, printmode unset): picked first mode with quality match (%s)\n",mode->name);
1625 modefound=1;
1626 }
1627 }
1628 break; /* go to next mode in muse list */
1629 }
1630 }
1631 i++;
1632 }
1633 }
1634 /* if no mode was found yet, repeat with no restrictions --- since some media may not allow PrintingMode to be what was selected */
1635 if (modefound==0) {
1636 i=0;
1637 quality = mode->quality;
1638 while ( (muse->mode_name_list[i]!=NULL) && (modefound != 1) ) {
1639 for(j=0;j<caps->modelist->count;j++){
1640 if(!strcmp(muse->mode_name_list[i],caps->modelist->modes[j].name)){/* find right place in canon-modes list */
1641 if ( (caps->modelist->modes[j].quality >= quality) ) {
1642 if ( (duplex_mode && strncmp(duplex_mode,"Duplex",6)) || !(muse->use_flags & DUPLEX_SUPPORT) || !(caps->modelist->modes[j].flags & MODE_FLAG_NODUPLEX) ) {
1643 /* duplex check */
1644 mode = &caps->modelist->modes[j];
1645 stp_dprintf(STP_DBG_CANON, v,"DEBUG: Gutenprint (check_current_mode, Both/Color, no printmode): picked first mode with quality match (%s)\n",mode->name);
1646 modefound=1;
1647 /* set PrintingMode to whatever the mode is capable of */
1648 if (caps->modelist->modes[j].ink_types > CANON_INK_K) {
1649 stp_set_string_parameter(v,"PrintingMode","Color");
1650 printing_mode = stp_get_string_parameter(v, "PrintingMode");
1651 stp_dprintf(STP_DBG_CANON, v,"DEBUG: Gutenprint (InkSet:Both) PrintingMode set to Color\n");
1652 } else {
1653 stp_set_string_parameter(v,"PrintingMode","BW");
1654 printing_mode = stp_get_string_parameter(v, "PrintingMode");
1655 stp_dprintf(STP_DBG_CANON, v,"DEBUG: Gutenprint (InkSet:Both) PrintingMode set to BW\n");
1656 }
1657 }
1658 }
1659 break; /* go to next mode in muse list */
1660 }
1661 }
1662 i++;
1663 }
1664 }
1665
1666 ink_type=find_ink_type(v,mode,printing_mode);
1667 #if 0
1668 /* if InkType does not match that of mode, change InkType to match it */
1669 /* choose highest color as default, as there is only one option for Black */
1670 /* if InkType does not match that of mode, change InkType to match it */
1671 /* choose highest color as default, as there is only one option for Black */
1672 if (printing_mode && !strcmp(printing_mode,"BW")) {
1673 stp_dprintf(STP_DBG_CANON, v,"DEBUG: Gutenprint (InkSet:Both): InkType changed to %u (%s)\n",CANON_INK_K, "Gray");
1674 stp_set_string_parameter(v, "InkType", "Gray");
1675 ink_type = stp_get_string_parameter(v, "InkType");
1676 } else {
1677 inkfound=0;
1678 stp_dprintf(STP_DBG_CANON, v,"DEBUG: Gutenprint (InkSet:Both): InkType of mode %s is currently set as %s\n",mode->name,ink_type);
1679 for(i=0;i<sizeof(canon_inktypes)/sizeof(canon_inktypes[0]);i++){
1680 if (mode->ink_types & canon_inktypes[i].ink_type) { /* a mode can have several ink_types: must compare with ink_type if set */
1681 if ( !(strcmp(ink_type,canon_inktypes[i].name))) {
1682 inkfound=1;
1683 stp_dprintf(STP_DBG_CANON, v,"DEBUG: Gutenprint (InkSet:Both): InkType match found %i(%s)\n",canon_inktypes[i].ink_type,canon_inktypes[i].name);
1684 stp_set_string_parameter(v, "InkType", canon_inktypes[i].name);
1685 ink_type = stp_get_string_parameter(v, "InkType");
1686 break;
1687 }
1688 }
1689 }
1690 /* if no match found choose first available inkset */
1691 if (inkfound==0) {
1692 for(i=0;i<sizeof(canon_inktypes)/sizeof(canon_inktypes[0]);i++){
1693 if (mode->ink_types & canon_inktypes[i].ink_type) { /* a mode can have several ink_types: must compare with ink_type if set */
1694 if ((!ink_type) || (strcmp(ink_type,canon_inktypes[i].name))) { /* if InkType does not match selected mode ink type*/
1695 stp_dprintf(STP_DBG_CANON, v,"DEBUG: Gutenprint (InkSet:Both): No match found---choosing first available. InkType changed to %i(%s)\n",canon_inktypes[i].ink_type,canon_inktypes[i].name);
1696 stp_set_string_parameter(v, "InkType", canon_inktypes[i].name);
1697 ink_type = stp_get_string_parameter(v, "InkType");
1698 inkfound=1; /* set */
1699 break;
1700 }
1701 }
1702 }
1703 }
1704 }
1705 #endif
1706
1707 /* end of cartridge option block */
1708
1709 stp_dprintf(STP_DBG_CANON, v,"DEBUG: Gutenprint: mode searching: replaced mode with: '%s'\n",mode->name);
1710
1711 #if 0
1712 /* set InkType for the mode decided upon */
1713 for(i=0;i<sizeof(canon_inktypes)/sizeof(canon_inktypes[0]);i++){
1714 if (mode->ink_types & canon_inktypes[i].ink_type) {
1715 if (strcmp(ink_type,canon_inktypes[i].name)) {
1716 stp_dprintf(STP_DBG_CANON, v,"DEBUG: Gutenprint (Mode found): InkType changed to %i(%s)\n",canon_inktypes[i].ink_type,canon_inktypes[i].name);
1717 stp_set_string_parameter(v, "InkType", canon_inktypes[i].name);
1718 ink_type = stp_get_string_parameter(v, "InkType");
1719 break;
1720 }
1721 }
1722 }
1723 #endif
1724
1725 }
1726 }
1727 /* -------------------------------------- modecheck returned 0 for compare_mode_valid ------------------------------------------*/
1728 else { /* we did find the mode in the list for media, so it should take precedence over other settings, as it is more specific. */
1729
1730 stp_dprintf(STP_DBG_CANON, v,"DEBUG: Gutenprint (check_current_mode): mode exists, need to check for consistency (%s)\n",mode->name);
1731 quality = mode->quality;
1732 /* Black InkSet */
1733 if (ink_set && !strcmp(ink_set,"Black")) {
1734 stp_set_string_parameter(v, "PrintingMode","BW");
1735 printing_mode = stp_get_string_parameter(v, "PrintingMode");
1736 if (!(mode->ink_types & CANON_INK_K)) {
1737 /* need a new mode:
1738 loop through modes in muse list searching for a matching inktype, comparing quality
1739 */
1740 mode=suitable_mode_monochrome(v,muse,caps,quality,duplex_mode);
1741 if (!mode)
1742 modefound=0;
1743 else
1744 modefound=1;
1745
1746 if (modefound == 0) { /* still did not find a mode: pick first one for that media */
1747 if ( (muse->use_flags & INKSET_BLACK_MODEREPL) ) {
1748 mode=find_first_matching_mode_monochrome(v,muse,caps,duplex_mode);
1749 }
1750 else { /* no special replacement modes for black inkset */
1751 mode=find_first_matching_mode(v,muse,caps,duplex_mode);
1752 }
1753 }
1754 if (!mode)
1755 modefound=0;
1756 else
1757 modefound=1;
1758
1759 ink_type=find_ink_type(v,mode,printing_mode);
1760 #if 0
1761 /* if InkType does not match that of mode, change InkType to match it */
1762 /* choose highest color as default, as there is only one option for Black */
1763 /* if InkType does not match that of mode, change InkType to match it */
1764 /* choose highest color as default, as there is only one option for Black */
1765 if (printing_mode && !strcmp(printing_mode,"BW")) {
1766 stp_dprintf(STP_DBG_CANON, v,"DEBUG: Gutenprint (InkSet:Both): InkType changed to %u (%s)\n",CANON_INK_K, "Gray");
1767 stp_set_string_parameter(v, "InkType", "Gray");
1768 ink_type = stp_get_string_parameter(v, "InkType");
1769 } else {
1770 inkfound=0;
1771 stp_dprintf(STP_DBG_CANON, v,"DEBUG: Gutenprint (InkSet:Both): InkType of mode %s is currently set as %s\n",mode->name,ink_type);
1772 for(i=0;i<sizeof(canon_inktypes)/sizeof(canon_inktypes[0]);i++){
1773 if (mode->ink_types & canon_inktypes[i].ink_type) { /* a mode can have several ink_types: must compare with ink_type if set */
1774 if ( !(strcmp(ink_type,canon_inktypes[i].name))) {
1775 inkfound=1;
1776 stp_dprintf(STP_DBG_CANON, v,"DEBUG: Gutenprint (InkSet:Both): InkType match found %i(%s)\n",canon_inktypes[i].ink_type,canon_inktypes[i].name);
1777 stp_set_string_parameter(v, "InkType", canon_inktypes[i].name);
1778 ink_type = stp_get_string_parameter(v, "InkType");
1779 break;
1780 }
1781 }
1782 }
1783 /* if no match found choose first available inkset */
1784 if (inkfound==0) {
1785 for(i=0;i<sizeof(canon_inktypes)/sizeof(canon_inktypes[0]);i++){
1786 if (mode->ink_types & canon_inktypes[i].ink_type) { /* a mode can have several ink_types: must compare with ink_type if set */
1787 if ((!ink_type) || (strcmp(ink_type,canon_inktypes[i].name))) { /* if InkType does not match selected mode ink type*/
1788 stp_dprintf(STP_DBG_CANON, v,"DEBUG: Gutenprint (InkSet:Both): No match found---InkType changed to %i(%s)\n",canon_inktypes[i].ink_type,canon_inktypes[i].name);
1789 stp_set_string_parameter(v, "InkType", canon_inktypes[i].name);
1790 ink_type = stp_get_string_parameter(v, "InkType");
1791 inkfound=1; /* set */
1792 break;
1793 }
1794 }
1795 }
1796 }
1797 }
1798 #endif
1799 #if 0
1800 /* set InkType for the mode found */
1801 for(i=0;i<sizeof(canon_inktypes)/sizeof(canon_inktypes[0]);i++){
1802 if (mode->ink_types & canon_inktypes[i].ink_type) {
1803 if (strcmp(ink_type,canon_inktypes[i].name)) { /* if InkType does not match selected mode ink type*/
1804 stp_dprintf(STP_DBG_CANON, v,"DEBUG: Gutenprint (InkSet:Black): InkType changed to %i(%s)\n",canon_inktypes[i].ink_type,canon_inktypes[i].name);
1805 stp_set_string_parameter(v, "InkType", canon_inktypes[i].name);
1806 ink_type = stp_get_string_parameter(v, "InkType");
1807 break;
1808 }
1809 }
1810 }
1811 #endif
1812
1813 }
1814 else {
1815 /* mode is fine */
1816 /* matched expected K inkset, but need to check if Duplex matches, and if not, get a new mode with right inkset */
1817 mode=suitable_mode_monochrome(v,muse,caps,quality,duplex_mode);
1818 if (!mode)
1819 modefound=0;
1820 else
1821 modefound=1;
1822
1823 if (modefound == 0) { /* still did not find a mode: pick first one for that media */
1824 if ( (muse->use_flags & INKSET_BLACK_MODEREPL) ) {
1825 mode=find_first_matching_mode_monochrome(v,muse,caps,duplex_mode);
1826 }
1827 else { /* no special replacement modes for black inkset */
1828 mode=find_first_matching_mode(v,muse,caps,duplex_mode);
1829 }
1830 }
1831 if (!mode)
1832 modefound=0;
1833 else
1834 modefound=1;
1835
1836 ink_type=find_ink_type(v,mode,printing_mode);
1837 #if 0
1838 /* if InkType does not match that of mode, change InkType to match it */
1839 /* choose highest color as default, as there is only one option for Black */
1840 /* if InkType does not match that of mode, change InkType to match it */
1841 /* choose highest color as default, as there is only one option for Black */
1842 if (printing_mode && !strcmp(printing_mode,"BW")) {
1843 stp_dprintf(STP_DBG_CANON, v,"DEBUG: Gutenprint (InkSet:Both): InkType changed to %u (%s)\n",CANON_INK_K, "Gray");
1844 stp_set_string_parameter(v, "InkType", "Gray");
1845 ink_type = stp_get_string_parameter(v, "InkType");
1846 } else {
1847 inkfound=0;
1848 stp_dprintf(STP_DBG_CANON, v,"DEBUG: Gutenprint (InkSet:Both): InkType of mode %s is currently set as %s\n",mode->name,ink_type);
1849 for(i=0;i<sizeof(canon_inktypes)/sizeof(canon_inktypes[0]);i++){
1850 if (mode->ink_types & canon_inktypes[i].ink_type) { /* a mode can have several ink_types: must compare with ink_type if set */
1851 if ( !(strcmp(ink_type,canon_inktypes[i].name))) {
1852 inkfound=1;
1853 stp_dprintf(STP_DBG_CANON, v,"DEBUG: Gutenprint (InkSet:Both): InkType match found %i(%s)\n",canon_inktypes[i].ink_type,canon_inktypes[i].name);
1854 stp_set_string_parameter(v, "InkType", canon_inktypes[i].name);
1855 ink_type = stp_get_string_parameter(v, "InkType");
1856 break;
1857 }
1858 }
1859 }
1860 /* if no match found choose first available inkset */
1861 if (inkfound==0) {
1862 for(i=0;i<sizeof(canon_inktypes)/sizeof(canon_inktypes[0]);i++){
1863 if (mode->ink_types & canon_inktypes[i].ink_type) { /* a mode can have several ink_types: must compare with ink_type if set */
1864 if ((!ink_type) || (strcmp(ink_type,canon_inktypes[i].name))) { /* if InkType does not match selected mode ink type*/
1865 stp_dprintf(STP_DBG_CANON, v,"DEBUG: Gutenprint (InkSet:Both): No match found---InkType changed to %i(%s)\n",canon_inktypes[i].ink_type,canon_inktypes[i].name);
1866 stp_set_string_parameter(v, "InkType", canon_inktypes[i].name);
1867 ink_type = stp_get_string_parameter(v, "InkType");
1868 inkfound=1; /* set */
1869 break;
1870 }
1871 }
1872 }
1873 }
1874 }
1875 #endif
1876 #if 0
1877 /* set InkType for the mode found */
1878 for(i=0;i<sizeof(canon_inktypes)/sizeof(canon_inktypes[0]);i++){
1879 if (mode->ink_types & canon_inktypes[i].ink_type) {
1880 if (strcmp(ink_type,canon_inktypes[i].name)) { /* if InkType does not match selected mode ink type*/
1881 stp_dprintf(STP_DBG_CANON, v,"DEBUG: Gutenprint (InkSet:Black): InkType changed to %i(%s)\n",canon_inktypes[i].ink_type,canon_inktypes[i].name);
1882 stp_set_string_parameter(v, "InkType", canon_inktypes[i].name);
1883 ink_type = stp_get_string_parameter(v, "InkType");
1884 break;
1885 }
1886 }
1887 }
1888 #endif
1889
1890 }
1891 } /* End of Black Inkset */
1892 /*-------------------------------------------------------------------------------------------------*/
1893 /* InkSet Color */
1894 else if ( (ink_set && !strcmp(ink_set,"Color")) && (caps->features & CANON_CAP_T) ) {
1895 stp_set_string_parameter(v, "PrintingMode","Color");
1896 printing_mode = stp_get_string_parameter(v, "PrintingMode");
1897 if (!(mode->ink_types & CANON_INK_CMY)) { /* Color InkSet */
1898 stp_dprintf(STP_DBG_CANON, v,"DEBUG: Gutenprint (InkSet:Color): inkset incorrect for Color cartridge---need new mode\n");
1899 /* need a new mode
1900 loop through modes in muse list searching for a matching inktype, comparing quality
1901 */
1902 mode=suitable_mode_color(v,muse,caps,quality,duplex_mode);
1903
1904 if (!mode)
1905 modefound=0;
1906 else
1907 modefound=1;
1908
1909 if (modefound == 0) { /* still did not find a mode: pick first one for that media */
1910 if ( (muse->use_flags & INKSET_COLOR_MODEREPL) ) {
1911 mode=find_first_matching_mode_monochrome(v,muse,caps,duplex_mode);
1912 stp_dprintf(STP_DBG_CANON, v,"DEBUG: Gutenprint (InkSet:Color): Decided on first matching mode for color inkset (%s)\n",mode->name);
1913 }
1914 else { /* no special replacement modes for color inkset */
1915 mode=find_first_matching_mode(v,muse,caps,duplex_mode);
1916 stp_dprintf(STP_DBG_CANON, v,"DEBUG: Gutenprint (InkSet:Color): Decided on first matching mode with no special replacement modes for color inkset (%s)\n",mode->name);
1917 }
1918 }
1919 if (!mode)
1920 modefound=0;
1921 else
1922 modefound=1;
1923
1924 ink_type=find_ink_type(v,mode,printing_mode);
1925 #if 0
1926 /* if InkType does not match that of mode, change InkType to match it */
1927 /* choose highest color as default, as there is only one option for Black */
1928 /* if InkType does not match that of mode, change InkType to match it */
1929 /* choose highest color as default, as there is only one option for Black */
1930 if (printing_mode && !strcmp(printing_mode,"BW")) {
1931 stp_dprintf(STP_DBG_CANON, v,"DEBUG: Gutenprint (InkSet:Both): InkType changed to %u (%s)\n",CANON_INK_K, "Gray");
1932 stp_set_string_parameter(v, "InkType", "Gray");
1933 ink_type = stp_get_string_parameter(v, "InkType");
1934 } else {
1935 inkfound=0;
1936 stp_dprintf(STP_DBG_CANON, v,"DEBUG: Gutenprint (InkSet:Both): InkType of mode %s is currently set as %s\n",mode->name,ink_type);
1937 for(i=0;i<sizeof(canon_inktypes)/sizeof(canon_inktypes[0]);i++){
1938 if (mode->ink_types & canon_inktypes[i].ink_type) { /* a mode can have several ink_types: must compare with ink_type if set */
1939 if ( !(strcmp(ink_type,canon_inktypes[i].name))) {
1940 inkfound=1;
1941 stp_dprintf(STP_DBG_CANON, v,"DEBUG: Gutenprint (InkSet:Both): InkType match found %i(%s)\n",canon_inktypes[i].ink_type,canon_inktypes[i].name);
1942 stp_set_string_parameter(v, "InkType", canon_inktypes[i].name);
1943 ink_type = stp_get_string_parameter(v, "InkType");
1944 break;
1945 }
1946 }
1947 }
1948 /* if no match found choose first available inkset */
1949 if (inkfound==0) {
1950 for(i=0;i<sizeof(canon_inktypes)/sizeof(canon_inktypes[0]);i++){
1951 if (mode->ink_types & canon_inktypes[i].ink_type) { /* a mode can have several ink_types: must compare with ink_type if set */
1952 if ((!ink_type) || (strcmp(ink_type,canon_inktypes[i].name))) { /* if InkType does not match selected mode ink type*/
1953 stp_dprintf(STP_DBG_CANON, v,"DEBUG: Gutenprint (InkSet:Both): No match found---InkType changed to %i(%s)\n",canon_inktypes[i].ink_type,canon_inktypes[i].name);
1954 stp_set_string_parameter(v, "InkType", canon_inktypes[i].name);
1955 ink_type = stp_get_string_parameter(v, "InkType");
1956 inkfound=1; /* set */
1957 break;
1958 }
1959 }
1960 }
1961 }
1962 }
1963 #endif
1964 #if 0
1965 /* set InkType for the mode found */
1966 for(i=0;i<sizeof(canon_inktypes)/sizeof(canon_inktypes[0]);i++){
1967 if (mode->ink_types & canon_inktypes[i].ink_type) {
1968 if (strcmp(ink_type,canon_inktypes[i].name)) { /* if InkType does not match selected mode ink type*/
1969 stp_dprintf(STP_DBG_CANON, v,"DEBUG: Gutenprint (InkSet:Color): InkType changed to %i(%s)\n",canon_inktypes[i].ink_type,canon_inktypes[i].name);
1970 stp_set_string_parameter(v, "InkType", canon_inktypes[i].name);
1971 ink_type = stp_get_string_parameter(v, "InkType");
1972 break;
1973 }
1974 }
1975 }
1976 #endif
1977
1978 }
1979 else {
1980 /* mode is fine */
1981 /* matched expected RGB inkset, but need to check if Duplex matches, and if not, get a new mode with right inkset */
1982 stp_dprintf(STP_DBG_CANON, v,"DEBUG: Gutenprint (InkSet:Color): inkset OK but need to check other parameters\n");
1983 mode=suitable_mode_color(v,muse,caps,quality,duplex_mode); /* something wrong here!!! */
1984 stp_dprintf(STP_DBG_CANON, v,"DEBUG: Gutenprint (InkSet:Color): returned mode for color inkset: %s\n",mode->name);
1985 if (!mode)
1986 modefound=0;
1987 else
1988 modefound=1;
1989
1990 if (modefound == 0) { /* still did not find a mode: pick first one for that media */
1991 if ( (muse->use_flags & INKSET_COLOR_MODEREPL) ) {
1992 mode=find_first_matching_mode_monochrome(v,muse,caps,duplex_mode);
1993 stp_dprintf(STP_DBG_CANON, v,"DEBUG: Gutenprint (InkSet:Color): Decided on first matching mode for color inkset (%s)\n",mode->name);
1994 }
1995 else { /* no special replacement modes for color inkset */
1996 mode=find_first_matching_mode(v,muse,caps,duplex_mode);
1997 stp_dprintf(STP_DBG_CANON, v,"DEBUG: Gutenprint (InkSet:Color): Decided on first matching mode with no special replacement modes for color inkset (%s)\n",mode->name);
1998 }
1999 }
2000 if (!mode)
2001 modefound=0;
2002 else
2003 modefound=1;
2004
2005 ink_type=find_ink_type(v,mode,printing_mode);
2006 #if 0
2007 /* if InkType does not match that of mode, change InkType to match it */
2008 /* choose highest color as default, as there is only one option for Black */
2009 /* if InkType does not match that of mode, change InkType to match it */
2010 /* choose highest color as default, as there is only one option for Black */
2011 if (printing_mode && !strcmp(printing_mode,"BW")) {
2012 stp_dprintf(STP_DBG_CANON, v,"DEBUG: Gutenprint (InkSet:Both): InkType changed to %u (%s)\n",CANON_INK_K, "Gray");
2013 stp_set_string_parameter(v, "InkType", "Gray");
2014 ink_type = stp_get_string_parameter(v, "InkType");
2015 } else {
2016 inkfound=0;
2017 stp_dprintf(STP_DBG_CANON, v,"DEBUG: Gutenprint (InkSet:Both): InkType of mode %s is currently set as %s\n",mode->name,ink_type);
2018 for(i=0;i<sizeof(canon_inktypes)/sizeof(canon_inktypes[0]);i++){
2019 if (mode->ink_types & canon_inktypes[i].ink_type) { /* a mode can have several ink_types: must compare with ink_type if set */
2020 if ( !(strcmp(ink_type,canon_inktypes[i].name))) {
2021 inkfound=1;
2022 stp_dprintf(STP_DBG_CANON, v,"DEBUG: Gutenprint (InkSet:Both): InkType match found %i(%s)\n",canon_inktypes[i].ink_type,canon_inktypes[i].name);
2023 stp_set_string_parameter(v, "InkType", canon_inktypes[i].name);
2024 ink_type = stp_get_string_parameter(v, "InkType");
2025 break;
2026 }
2027 }
2028 }
2029 /* if no match found choose first available inkset */
2030 if (inkfound==0) {
2031 for(i=0;i<sizeof(canon_inktypes)/sizeof(canon_inktypes[0]);i++){
2032 if (mode->ink_types & canon_inktypes[i].ink_type) { /* a mode can have several ink_types: must compare with ink_type if set */
2033 if ((!ink_type) || (strcmp(ink_type,canon_inktypes[i].name))) { /* if InkType does not match selected mode ink type*/
2034 stp_dprintf(STP_DBG_CANON, v,"DEBUG: Gutenprint (InkSet:Both): No match found---InkType changed to %i(%s)\n",canon_inktypes[i].ink_type,canon_inktypes[i].name);
2035 stp_set_string_parameter(v, "InkType", canon_inktypes[i].name);
2036 ink_type = stp_get_string_parameter(v, "InkType");
2037 inkfound=1; /* set */
2038 break;
2039 }
2040 }
2041 }
2042 }
2043 }
2044 #endif
2045 #if 0
2046 /* set InkType for the mode found */
2047 for(i=0;i<sizeof(canon_inktypes)/sizeof(canon_inktypes[0]);i++){
2048 if (mode->ink_types & canon_inktypes[i].ink_type) {
2049 if (strcmp(ink_type,canon_inktypes[i].name)) { /* if InkType does not match selected mode ink type*/
2050 stp_dprintf(STP_DBG_CANON, v,"DEBUG: Gutenprint (InkSet:Color): InkType changed to %i(%s)\n",canon_inktypes[i].ink_type,canon_inktypes[i].name);
2051 stp_set_string_parameter(v, "InkType", canon_inktypes[i].name);
2052 ink_type = stp_get_string_parameter(v, "InkType");
2053 break;
2054 }
2055 }
2056 }
2057 #endif
2058
2059 }
2060 } /* End of Color Inkset */
2061 /*-------------------------------------------------------------------------------------------------*/
2062 /* Photo cartridge selection: only use modes that support it */
2063 else if (ink_set && !strcmp(ink_set,"Photo")) {
2064 /* Photo cartridge printing does not seem to have any monochrome option */
2065 stp_set_string_parameter(v, "PrintingMode","Color");
2066 printing_mode = stp_get_string_parameter(v, "PrintingMode");
2067 /* need to match photo cartridge mode flag */
2068 if (!(mode->flags & MODE_FLAG_PHOTO)) {
2069 /* need a new mode
2070 loop through modes in muse list searching for a matching inkset, comparing quality
2071 */
2072 mode=suitable_mode_photo(v,muse,caps,quality,duplex_mode);
2073 if (!mode)
2074 modefound=0;
2075 else
2076 modefound=1;
2077
2078 if (modefound == 0) { /* still did not find a mode: pick first one for that media */
2079 if ( (muse->use_flags & INKSET_PHOTO_MODEREPL) ) {
2080 mode=find_first_matching_mode_photo(v,muse,caps,duplex_mode);
2081 }
2082 else { /* no special replacement modes for photo inkset */
2083 mode=find_first_matching_mode(v,muse,caps,duplex_mode);
2084 }
2085 }
2086 if (!mode)
2087 modefound=0;
2088 else
2089 modefound=1;
2090
2091 ink_type=find_ink_type(v,mode,printing_mode);
2092 #if 0
2093 /* if InkType does not match that of mode, change InkType to match it */
2094 /* choose highest color as default, as there is only one option for Black */
2095 /* if InkType does not match that of mode, change InkType to match it */
2096 /* choose highest color as default, as there is only one option for Black */
2097 if (printing_mode && !strcmp(printing_mode,"BW")) {
2098 stp_dprintf(STP_DBG_CANON, v,"DEBUG: Gutenprint (InkSet:Both): InkType changed to %u (%s)\n",CANON_INK_K, "Gray");
2099 stp_set_string_parameter(v, "InkType", "Gray");
2100 ink_type = stp_get_string_parameter(v, "InkType");
2101 } else {
2102 inkfound=0;
2103 stp_dprintf(STP_DBG_CANON, v,"DEBUG: Gutenprint (InkSet:Both): InkType of mode %s is currently set as %s\n",mode->name,ink_type);
2104 for(i=0;i<sizeof(canon_inktypes)/sizeof(canon_inktypes[0]);i++){
2105 if (mode->ink_types & canon_inktypes[i].ink_type) { /* a mode can have several ink_types: must compare with ink_type if set */
2106 if ( !(strcmp(ink_type,canon_inktypes[i].name))) {
2107 inkfound=1;
2108 stp_dprintf(STP_DBG_CANON, v,"DEBUG: Gutenprint (InkSet:Both): InkType match found %i(%s)\n",canon_inktypes[i].ink_type,canon_inktypes[i].name);
2109 stp_set_string_parameter(v, "InkType", canon_inktypes[i].name);
2110 ink_type = stp_get_string_parameter(v, "InkType");
2111 break;
2112 }
2113 }
2114 }
2115 /* if no match found choose first available inkset */
2116 if (inkfound==0) {
2117 for(i=0;i<sizeof(canon_inktypes)/sizeof(canon_inktypes[0]);i++){
2118 if (mode->ink_types & canon_inktypes[i].ink_type) { /* a mode can have several ink_types: must compare with ink_type if set */
2119 if ((!ink_type) || (strcmp(ink_type,canon_inktypes[i].name))) { /* if InkType does not match selected mode ink type*/
2120 stp_dprintf(STP_DBG_CANON, v,"DEBUG: Gutenprint (InkSet:Both): No match found---InkType changed to %i(%s)\n",canon_inktypes[i].ink_type,canon_inktypes[i].name);
2121 stp_set_string_parameter(v, "InkType", canon_inktypes[i].name);
2122 ink_type = stp_get_string_parameter(v, "InkType");
2123 inkfound=1; /* set */
2124 break;
2125 }
2126 }
2127 }
2128 }
2129 }
2130 #endif
2131 #if 0
2132 /* set InkType for the mode found */
2133 for(i=0;i<sizeof(canon_inktypes)/sizeof(canon_inktypes[0]);i++){
2134 if (mode->ink_types & canon_inktypes[i].ink_type) {
2135 if (strcmp(ink_type,canon_inktypes[i].name)) { /* if InkType does not match selected mode ink type*/
2136 stp_dprintf(STP_DBG_CANON, v,"DEBUG: Gutenprint (InkSet:Color): InkType changed to %i(%s)\n",canon_inktypes[i].ink_type,canon_inktypes[i].name);
2137 stp_set_string_parameter(v, "InkType", canon_inktypes[i].name);
2138 ink_type = stp_get_string_parameter(v, "InkType");
2139 break;
2140 }
2141 }
2142 }
2143 #endif
2144
2145 }
2146 else {
2147 /* mode is fine */
2148 /* matched expected inkset, but need to check if Duplex matches, and if not, get a new mode with right inkset */
2149 mode=suitable_mode_photo(v,muse,caps,quality,duplex_mode);
2150 if (!mode)
2151 modefound=0;
2152 else
2153 modefound=1;
2154
2155 if (modefound == 0) { /* still did not find a mode: pick first one for that media */
2156 if ( (muse->use_flags & INKSET_PHOTO_MODEREPL) ) {
2157 mode=find_first_matching_mode_photo(v,muse,caps,duplex_mode);
2158 }
2159 else { /* no special replacement modes for photo inkset */
2160 mode=find_first_matching_mode(v,muse,caps,duplex_mode);
2161 }
2162 }
2163 if (!mode)
2164 modefound=0;
2165 else
2166 modefound=1;
2167
2168 ink_type=find_ink_type(v,mode,printing_mode);
2169 #if 0
2170 /* if InkType does not match that of mode, change InkType to match it */
2171 /* choose highest color as default, as there is only one option for Black */
2172 /* if InkType does not match that of mode, change InkType to match it */
2173 /* choose highest color as default, as there is only one option for Black */
2174 if (printing_mode && !strcmp(printing_mode,"BW")) {
2175 stp_dprintf(STP_DBG_CANON, v,"DEBUG: Gutenprint (InkSet:Both): InkType changed to %u (%s)\n",CANON_INK_K, "Gray");
2176 stp_set_string_parameter(v, "InkType", "Gray");
2177 ink_type = stp_get_string_parameter(v, "InkType");
2178 } else {
2179 inkfound=0;
2180 stp_dprintf(STP_DBG_CANON, v,"DEBUG: Gutenprint (InkSet:Both): InkType of mode %s is currently set as %s\n",mode->name,ink_type);
2181 for(i=0;i<sizeof(canon_inktypes)/sizeof(canon_inktypes[0]);i++){
2182 if (mode->ink_types & canon_inktypes[i].ink_type) { /* a mode can have several ink_types: must compare with ink_type if set */
2183 if ( !(strcmp(ink_type,canon_inktypes[i].name))) {
2184 inkfound=1;
2185 stp_dprintf(STP_DBG_CANON, v,"DEBUG: Gutenprint (InkSet:Both): InkType match found %i(%s)\n",canon_inktypes[i].ink_type,canon_inktypes[i].name);
2186 stp_set_string_parameter(v, "InkType", canon_inktypes[i].name);
2187 ink_type = stp_get_string_parameter(v, "InkType");
2188 break;
2189 }
2190 }
2191 }
2192 /* if no match found choose first available inkset */
2193 if (inkfound==0) {
2194 for(i=0;i<sizeof(canon_inktypes)/sizeof(canon_inktypes[0]);i++){
2195 if (mode->ink_types & canon_inktypes[i].ink_type) { /* a mode can have several ink_types: must compare with ink_type if set */
2196 if ((!ink_type) || (strcmp(ink_type,canon_inktypes[i].name))) { /* if InkType does not match selected mode ink type*/
2197 stp_dprintf(STP_DBG_CANON, v,"DEBUG: Gutenprint (InkSet:Both): No match found---InkType changed to %i(%s)\n",canon_inktypes[i].ink_type,canon_inktypes[i].name);
2198 stp_set_string_parameter(v, "InkType", canon_inktypes[i].name);
2199 ink_type = stp_get_string_parameter(v, "InkType");
2200 inkfound=1; /* set */
2201 break;
2202 }
2203 }
2204 }
2205 }
2206 }
2207 #endif
2208 #if 0
2209 /* set InkType for the mode found */
2210 for(i=0;i<sizeof(canon_inktypes)/sizeof(canon_inktypes[0]);i++){
2211 if (mode->ink_types & canon_inktypes[i].ink_type) {
2212 if (strcmp(ink_type,canon_inktypes[i].name)) { /* if InkType does not match selected mode ink type*/
2213 stp_dprintf(STP_DBG_CANON, v,"DEBUG: Gutenprint (InkSet:Color): InkType changed to %i(%s)\n",canon_inktypes[i].ink_type,canon_inktypes[i].name);
2214 stp_set_string_parameter(v, "InkType", canon_inktypes[i].name);
2215 ink_type = stp_get_string_parameter(v, "InkType");
2216 break;
2217 }
2218 }
2219 }
2220 #endif
2221
2222 }
2223 } /* end of Photo Inkset */
2224 /*-------------------------------------------------------------------------------------------------*/
2225 /* no restrictions for InkSet "Both" (non-BJC) or "Color" (BJC) or if no InkSet set yet */
2226 else {
2227 if (printing_mode && !strcmp(printing_mode,"Color")) {
2228 stp_dprintf(STP_DBG_CANON, v,"DEBUG: Gutenprint (InkSet:Both) PrintingMode Color\n");
2229 /* must skip K-only inksets if they exist: they only exist if the option "BW" is also declared but we cannot check if an option exists or not */
2230 i=0;
2231 quality = mode->quality;
2232 modefound=0;
2233 while ( (muse->mode_name_list[i]!=NULL) && (modefound != 1) ) {
2234 for(j=0;j<caps->modelist->count;j++){
2235 if(!strcmp(muse->mode_name_list[i],caps->modelist->modes[j].name)){/* find right place in canon-modes list */
2236 if ( (caps->modelist->modes[j].quality >= quality) ) {
2237 if ( (duplex_mode && strncmp(duplex_mode,"Duplex",6)) || !(muse->use_flags & DUPLEX_SUPPORT) || !(caps->modelist->modes[j].flags & MODE_FLAG_NODUPLEX) ) {
2238 /* duplex check */
2239 if (caps->modelist->modes[j].ink_types > CANON_INK_K) {
2240 if (!strcmp(mode->name,caps->modelist->modes[j].name)) {
2241 mode = &caps->modelist->modes[j];
2242 stp_dprintf(STP_DBG_CANON, v,"DEBUG: Gutenprint (InkSet:Both) Color: Decided on mode (%s)\n",mode->name);
2243 modefound=1;
2244 }
2245 }
2246 }
2247 }
2248 break; /* go to next mode in muse list */
2249 }
2250 }
2251 i++;
2252 }
2253 }
2254 else if (printing_mode && !strcmp(printing_mode,"BW")) {
2255 stp_dprintf(STP_DBG_CANON, v,"DEBUG: Gutenprint (InkSet:Both) PrintingMode BW\n");
2256 /* need to find K-only inksets: they must exist since we declared the printer to have this capability! */
2257 i=0;
2258 quality = mode->quality;
2259 modefound=0;
2260 while ( (muse->mode_name_list[i]!=NULL) && (modefound != 1) ) {
2261 for(j=0;j<caps->modelist->count;j++){
2262 if(!strcmp(muse->mode_name_list[i],caps->modelist->modes[j].name)){/* find right place in canon-modes list */
2263 if ( (caps->modelist->modes[j].quality >= quality) ) {
2264 if ( (duplex_mode && strncmp(duplex_mode,"Duplex",6)) || !(muse->use_flags & DUPLEX_SUPPORT) || !(caps->modelist->modes[j].flags & MODE_FLAG_NODUPLEX) ) {
2265 /* duplex check */
2266 if (caps->modelist->modes[j].ink_types & CANON_INK_K) { /* AND means CANON_INK_K is included in the support */
2267 if (!strcmp(mode->name,caps->modelist->modes[j].name)) {
2268 mode = &caps->modelist->modes[j];
2269 stp_dprintf(STP_DBG_CANON, v,"DEBUG: Gutenprint (InkSet:Both) BW: Decided on mode (%s)\n",mode->name);
2270 modefound=1;
2271 }
2272 }
2273 }
2274 }
2275 break; /* go to next mode in muse list */
2276 }
2277 }
2278 i++;
2279 }
2280 }
2281 else { /* no restriction from PrintingMode if not set yet */
2282 stp_dprintf(STP_DBG_CANON, v,"DEBUG: Gutenprint (InkSet:Both) PrintingMode not set yet\n");
2283 i=0;
2284 quality = mode->quality;
2285 modefound=0;
2286 while ( (muse->mode_name_list[i]!=NULL) && (modefound != 1) ) {
2287 for(j=0;j<caps->modelist->count;j++){
2288 if(!strcmp(muse->mode_name_list[i],caps->modelist->modes[j].name)){/* find right place in canon-modes list */
2289 if ( (caps->modelist->modes[j].quality >= quality) ) {
2290 if ( (duplex_mode && strncmp(duplex_mode,"Duplex",6)) || !(muse->use_flags & DUPLEX_SUPPORT) || !(caps->modelist->modes[j].flags & MODE_FLAG_NODUPLEX) ) {
2291 /* duplex check */
2292 if (!strcmp(mode->name,caps->modelist->modes[j].name)) {
2293 mode = &caps->modelist->modes[j];
2294 stp_dprintf(STP_DBG_CANON, v,"DEBUG: Gutenprint (InkSet:Both) PrintingMode not set yet: Decided on first matching mode with quality match (%s)\n",mode->name);
2295 modefound=1;
2296 }
2297 }
2298 }
2299 break; /* go to next mode in muse list */
2300 }
2301 }
2302 i++;
2303 }
2304 }
2305 /* if no mode was found yet, repeat with no restrictions --- since some media may not allow PrintingMode to be what was selected */
2306 if (modefound==0) {
2307 i=0;
2308 quality = mode->quality;
2309 while ( (muse->mode_name_list[i]!=NULL) && (modefound != 1) ) {
2310 for(j=0;j<caps->modelist->count;j++){
2311 if(!strcmp(muse->mode_name_list[i],caps->modelist->modes[j].name)){/* find right place in canon-modes list */
2312 if ( (caps->modelist->modes[j].quality >= quality) ) {
2313 if ( (duplex_mode && strncmp(duplex_mode,"Duplex",6)) || !(muse->use_flags & DUPLEX_SUPPORT) || !(caps->modelist->modes[j].flags & MODE_FLAG_NODUPLEX) ) {
2314 /* duplex check */
2315 mode = &caps->modelist->modes[j];
2316 stp_dprintf(STP_DBG_CANON, v,"DEBUG: Gutenprint (InkSet:Both) No mode previously found---catch-all: Decided on first matching mode (%s)\n",mode->name);
2317 modefound=1;
2318 /* set PrintingMode to whatever the mode is capable of */
2319 if (caps->modelist->modes[j].ink_types > CANON_INK_K){
2320 stp_set_string_parameter(v,"PrintingMode","Color");
2321 printing_mode = stp_get_string_parameter(v, "PrintingMode");
2322 stp_dprintf(STP_DBG_CANON, v,"DEBUG: Gutenprint (InkSet:Both) PrintingMode set to Color\n");
2323 } else {
2324 stp_set_string_parameter(v,"PrintingMode","BW");
2325 printing_mode = stp_get_string_parameter(v, "PrintingMode");
2326 stp_dprintf(STP_DBG_CANON, v,"DEBUG: Gutenprint (InkSet:Both) PrintingMode set to BW\n");
2327 }
2328 }
2329 }
2330 break; /* go to next mode in muse list */
2331 }
2332 }
2333 i++;
2334 }
2335 }
2336
2337 ink_type=find_ink_type(v,mode,printing_mode);
2338 #if 0
2339 /* if InkType does not match that of mode, change InkType to match it */
2340 /* choose highest color as default, as there is only one option for Black */
2341 /* if InkType does not match that of mode, change InkType to match it */
2342 /* choose highest color as default, as there is only one option for Black */
2343 if (printing_mode && !strcmp(printing_mode,"BW")) {
2344 stp_dprintf(STP_DBG_CANON, v,"DEBUG: Gutenprint (InkSet:Both): InkType changed to %u (%s)\n",CANON_INK_K, "Gray");
2345 stp_set_string_parameter(v, "InkType", "Gray");
2346 ink_type = stp_get_string_parameter(v, "InkType");
2347 } else {
2348 inkfound=0;
2349 stp_dprintf(STP_DBG_CANON, v,"DEBUG: Gutenprint (InkSet:Both): InkType of mode %s is currently set as %s\n",mode->name,ink_type);
2350 for(i=0;i<sizeof(canon_inktypes)/sizeof(canon_inktypes[0]);i++){
2351 if (mode->ink_types & canon_inktypes[i].ink_type) { /* a mode can have several ink_types: must compare with ink_type if set */
2352 if ( !(strcmp(ink_type,canon_inktypes[i].name))) {
2353 inkfound=1;
2354 stp_dprintf(STP_DBG_CANON, v,"DEBUG: Gutenprint (InkSet:Both): InkType match found %i(%s)\n",canon_inktypes[i].ink_type,canon_inktypes[i].name);
2355 stp_set_string_parameter(v, "InkType", canon_inktypes[i].name);
2356 ink_type = stp_get_string_parameter(v, "InkType");
2357 break;
2358 }
2359 }
2360 }
2361 /* if no match found choose first available inkset */
2362 if (inkfound==0) {
2363 for(i=0;i<sizeof(canon_inktypes)/sizeof(canon_inktypes[0]);i++){
2364 if (mode->ink_types & canon_inktypes[i].ink_type) { /* a mode can have several ink_types: must compare with ink_type if set */
2365 if ((!ink_type) || (strcmp(ink_type,canon_inktypes[i].name))) { /* if InkType does not match selected mode ink type*/
2366 stp_dprintf(STP_DBG_CANON, v,"DEBUG: Gutenprint (InkSet:Both): No match found---choosing first available. InkType changed to %i(%s)\n",canon_inktypes[i].ink_type,canon_inktypes[i].name);
2367 stp_set_string_parameter(v, "InkType", canon_inktypes[i].name);
2368 ink_type = stp_get_string_parameter(v, "InkType");
2369 inkfound=1; /* set */
2370 break;
2371 }
2372 }
2373 }
2374 }
2375 }
2376 #endif
2377 }
2378 }
2379 }
2380 /* end of mode replacement code */
2381
2382
2383 #if 0
2384 if(quality && strcmp(quality, "None") == 0)
2385 quality = "Standard";
2386
2387 if(quality && !strcmp(quality,"Standard")){
2388 return &caps->modelist->modes[caps->modelist->default_mode];
2389 }
2390 #endif
2391
2392 #if 0
2393 /* only some modes can print to cd */
2394 if(input_slot && !strcmp(input_slot,"CD") && !(mode->flags & MODE_FLAG_CD)){
2395 for(i=0;i<caps->modelist->count;i++){
2396 if(caps->modelist->modes[i].flags & MODE_FLAG_CD){
2397 mode = &caps->modelist->modes[i];
2398 break;
2399 }
2400 }
2401 }
2402 #endif
2403
2404
2405 if (mode) {
2406 stp_set_string_parameter(v, "Resolution",mode->text); /* check_current_mode checks resolution! */
2407 stp_dprintf(STP_DBG_CANON, v,"DEBUG: Gutenprint: check_current_mode --- updated Resolution: '%s'\n",mode->name);
2408 }
2409
2410 if (mode) {
2411 stp_dprintf(STP_DBG_CANON, v,"DEBUG: Gutenprint: check_current_mode --- Final returned mode: '%s'\n",mode->name);
2412 }
2413 else {
2414 stp_dprintf(STP_DBG_CANON, v,"DEBUG: Gutenprint: check_current_mode --- Final returned mode is NULL \n");
2415 }
2416
2417 /* set PrintingMode in case of Inkset precedence */
2418 if (mode) { /* final mode takes precedence */
2419 if (mode->ink_types == CANON_INK_K)
2420 stp_set_string_parameter(v, "PrintingMode", "BW");
2421 else
2422 stp_set_string_parameter(v, "PrintingMode", "Color");
2423 }
2424 else if (ink_type) { /* mode not yet known, but InkType known. InkSet should have been handled together with InkType above */
2425 if (!strcmp(ink_type,"Gray"))
2426 stp_set_string_parameter(v, "PrintingMode", "BW");
2427 else
2428 stp_set_string_parameter(v, "PrintingMode", "Color");
2429 }
2430
2431 if (printing_mode) {
2432 stp_dprintf(STP_DBG_CANON, v,"DEBUG: Gutenprint: Final PrintingMode %s\n",printing_mode);
2433 } else { /* should not happen */
2434 stp_dprintf(STP_DBG_CANON, v,"DEBUG: Gutenprint: Final PrintingMode is NULL\n");
2435 }
2436 if (ink_set) {
2437 stp_dprintf(STP_DBG_CANON, v,"DEBUG: Gutenprint: Final InkSet value (high priority): '%s'\n",ink_set);
2438 } else {
2439 stp_dprintf(STP_DBG_CANON, v,"DEBUG: Gutenprint: Final InkSet value is NULL\n");
2440 }
2441
2442 if (ink_type) {
2443 stp_dprintf(STP_DBG_CANON, v,"DEBUG: Gutenprint: Final InkType value (low priority): '%s'\n",ink_type);
2444 } else {
2445 stp_dprintf(STP_DBG_CANON, v,"DEBUG: Gutenprint: Final InkType value is NULL\n");
2446 }
2447
2448 return mode;
2449 }
2450
2451 /* function returns the best ink_type for the current mode */
2452 static unsigned int
canon_printhead_colors(const stp_vars_t * v)2453 canon_printhead_colors(const stp_vars_t*v)
2454 {
2455 int i,j;
2456 const canon_mode_t* mode;
2457 const canon_cap_t * caps = canon_get_model_capabilities(v);
2458 const char *print_mode = stp_get_string_parameter(v, "PrintingMode");
2459 const char *ink_type = stp_get_string_parameter(v, "InkType");
2460 const char *ink_set = stp_get_string_parameter(v, "InkSet");
2461
2462 stp_dprintf(STP_DBG_CANON, v,"Entered canon_printhead_colors: got PrintingMode %s\n",print_mode);
2463
2464 /* if a mode is available, use it. Else mode is NULL */
2465 stp_dprintf(STP_DBG_CANON, v,"Calling get_current_parameter from canon_printhead_colors\n");
2466 mode = canon_get_current_mode(v);
2467
2468 /* get the printing mode again */
2469 print_mode = stp_get_string_parameter(v, "PrintingMode");
2470
2471 /* if the printing mode was already selected as BW, accept it */
2472 if(print_mode && !strcmp(print_mode, "BW") && !(caps->features & CANON_CAP_NOBLACK) ){ /* workaround in case BW is a default */
2473 stp_dprintf(STP_DBG_CANON, v,"(canon_printhead_colors[BW]) Found InkType %u (CANON_INK_K)\n",CANON_INK_K);
2474 stp_dprintf(STP_DBG_CANON, v,"(canon_printhead_colors[BW]) NOBLACK? %lu\n",(caps->features & CANON_CAP_NOBLACK));
2475 return CANON_INK_K;
2476 }
2477 /* alternatively, if the cartridge selection is in force, and black cartridge is selected, accept it */
2478 if(ink_set && !strcmp(ink_set, "Black")){
2479 stp_dprintf(STP_DBG_CANON, v,"(canon_printhead_colors[BW]) Found InkSet black selection\n");
2480 return CANON_INK_K;
2481 }
2482
2483 /* originally finds selected InkType of form: CANON_INK_<inks> */
2484 /* but this is incorrect, since it does not check media or mode */
2485 /* change: deal with mode set and mode not set cases */
2486
2487 /* if mode was already set, then return the ink types for only that mode */
2488
2489 if (mode) {
2490 /* if an inktype selected check what it is */
2491 if(ink_type){
2492 for(i=0;i<sizeof(canon_inktypes)/sizeof(canon_inktypes[0]);i++){
2493 if (mode->ink_types & canon_inktypes[i].ink_type) {
2494 stp_dprintf(STP_DBG_CANON, v,"(canon_printhead_colors[inktype]) Found InkType %i(%s)\n",canon_inktypes[i].ink_type,canon_inktypes[i].name);
2495 return canon_inktypes[i].ink_type;
2496 }
2497 }
2498 }
2499 else {
2500 /* find the matching inks for the mode: chooses the first one found for a mode! */
2501 /* ink types are arranged in decreasing order so those with more meta inks are discovered first */
2502 for(i=0;i<sizeof(canon_inktypes)/sizeof(canon_inktypes[0]);i++){
2503 if(mode->ink_types & canon_inktypes[i].ink_type) {
2504 stp_dprintf(STP_DBG_CANON, v,"(canon_printhead_colors[mode]) Found InkType %i(%s)\n",canon_inktypes[i].ink_type,canon_inktypes[i].name);
2505 return canon_inktypes[i].ink_type;
2506 }
2507 }
2508 }
2509 }
2510 else { /* mode not yet set */
2511 /* if an inktype selected check what it is */
2512 if(ink_type){
2513 for(i=0;i<sizeof(canon_inktypes)/sizeof(canon_inktypes[0]);i++){
2514 if(ink_type && !strcmp(canon_inktypes[i].name,ink_type)) {
2515 stp_dprintf(STP_DBG_CANON, v,"(canon_printhead_colors[inktype]) Found InkType %i(%s)\n",canon_inktypes[i].ink_type,canon_inktypes[i].name);
2516 return canon_inktypes[i].ink_type;
2517 }
2518 }
2519 }
2520 else { /* no ink type selected yet */
2521 stp_dprintf(STP_DBG_CANON, v,"canon_printhead_colors: no mode and no inktype: we have to choose the highest one to return\n");
2522 /* loop through all modes, and return the highest inktype found */
2523 for(i=0;i<sizeof(canon_inktypes)/sizeof(canon_inktypes[0]);i++){
2524 for(j=0;j<caps->modelist->count;j++){
2525 if(caps->modelist->modes[j].ink_types & canon_inktypes[i].ink_type){
2526 stp_dprintf(STP_DBG_CANON, v," highest inktype found --- %s(%s)\n",canon_inktypes[i].name,canon_inktypes[i].text);
2527 return canon_inktypes[i].ink_type;
2528 }
2529 }
2530 }
2531 }
2532
2533 }
2534
2535 /* originally as fallback choose CANON_INK_K */
2536 /* However, some Canon printers do not have monochrome mode at all, only color meta ink modes, like iP6000 series */
2537 #if 0
2538 stp_dprintf(STP_DBG_CANON, v,"(canon_printhead_colors[fall-through]) Returning InkType %i(CANON_INK_K)\n",CANON_INK_K);
2539 return CANON_INK_K;
2540 #endif
2541 /* new fallback: loop through ink type in reverse order, picking first one found, which if CANON_INK_K is supported will be that, else the lowest amount of color */
2542 for(i=((sizeof(canon_inktypes)/sizeof(canon_inktypes[0]))-1);i>=0;i--){
2543 for(j=0;j<caps->modelist->count;j++){
2544 if(caps->modelist->modes[j].ink_types & canon_inktypes[i].ink_type){
2545 stp_dprintf(STP_DBG_CANON, v," lowest inktype found --- %s(%s)\n",canon_inktypes[i].name,canon_inktypes[i].text);
2546 return canon_inktypes[i].ink_type;
2547 }
2548 }
2549 }
2550
2551 /* if fails until here, return something reasonable in most situations */
2552 return CANON_INK_K;
2553
2554 }
2555
2556 static unsigned char
canon_size_type(const stp_vars_t * v,const canon_cap_t * caps)2557 canon_size_type(const stp_vars_t *v, const canon_cap_t * caps)
2558 {
2559 const stp_papersize_list_t *list = stpi_get_standard_papersize_list();
2560 const stp_papersize_t *pp = stpi_get_papersize_by_size(list,
2561 stp_get_page_height(v),
2562 stp_get_page_width(v));
2563
2564 stp_dprintf(STP_DBG_CANON, v,"canon: entered canon_size_type\n");
2565
2566 if (pp)
2567 {
2568 const char *name = pp->name;
2569 stp_dprintf(STP_DBG_CANON, v,"canon: in canon_size_type is pp->name: '%s'\n",name);
2570 /* used internally: do not translate */
2571 /* built ins: Japanese driver notation */
2572 if (!strcmp(name,"A5")) return 0x01;
2573 if (!strcmp(name,"A4")) return 0x03;
2574 if (!strcmp(name,"A3")) return 0x05;
2575 if (!strcmp(name,"B5")) return 0x08;
2576 if (!strcmp(name,"B4")) return 0x0a;
2577 if (!strcmp(name,"Letter")) return 0x0d;
2578 if (!strcmp(name,"Legal")) return 0x0f;
2579 if (!strcmp(name,"Tabloid")) return 0x11; /* 11x17 inch */
2580 if (!strcmp(name,"w283h420")) return 0x14; /* Hagaki */
2581 /* if (!strcmp(name,"COM10")) return 0x16;*/
2582 /* if (!strcmp(name,"DL")) return 0x17;*/
2583 if (!strcmp(name,"LetterExtra")) return 0x2a; /* Letter navi --- Letter+ */
2584 if (!strcmp(name,"A4Extra")) return 0x2b; /* A4navi --- A4+ */
2585 if (!strcmp(name,"A3plus")) return 0x2c; /* A3navi --- A3+ (13x19 inch) */
2586 if (!strcmp(name,"w288h144")) return 0x2d; /* 4x2 inch labels */
2587 if (!strcmp(name,"COM10")) return 0x2e; /* US Comm #10 Env */
2588 if (!strcmp(name,"DL")) return 0x2f; /* Euro DL Env */
2589 if (!strcmp(name,"w297h666")) return 0x30; /* Western Env #4 (you4) */
2590 if (!strcmp(name,"w277h538")) return 0x31; /* Western Env #6 (you6) */
2591 if (!strcmp(name,"w252h360J")) return 0x32; /* L --- similar to US 3.5x5 inch size */
2592 if (!strcmp(name,"w360h504J")) return 0x33; /* 2L --- similar to US5x7 inch */
2593 if (!strcmp(name,"w288h432J")) return 0x34; /* KG --- same size as US 4x6 inch */
2594 /* if (!strcmp(name,"CD5Inch")) return 0x35; */ /* CD Custom Tray */
2595 if (!strcmp(name,"w155h257")) return 0x36; /* Japanese Business Card 55mm x 91mm */
2596 if (!strcmp(name,"w360h504")) return 0x37; /* US5x7 inch */
2597 if (!strcmp(name,"w420h567")) return 0x39; /* Oufuku Hagaki --- but should be w567h420 */
2598 if (!strcmp(name,"w340h666")) return 0x3a; /* Japanese Long Env #3 (chou3) */
2599 if (!strcmp(name,"w255h581")) return 0x3b; /* Japanese Long Env #4 (chou4) */
2600 /* if (!strcmp(name,"CD5Inch")) return 0x3f; */ /* CD Tray A */
2601 /* if (!strcmp(name,"CD5Inch")) return 0x40; */ /* CD Tray B */
2602 if (!strcmp(name,"w155h244")) return 0x41; /* Business/Credit Card 54mm x 86mm */
2603
2604 /* Fine Art paper codes */
2605 /* iP6700D, iP7100, iP7500, iP8100, iP8600, iP9910 */
2606 /* iX7000 */
2607 /* MG6100, M6200, MG8100, MG8200 */
2608 /* MX7600 */
2609 /* MP950, MP960, MP970, MP980, MP990 */
2610 /* if (!strcmp(name,"A4")) return 0x42; */ /* FineArt A4 35mm border --- iP7100: gap is 18 */
2611 /* if (!strcmp(name,"A3")) return 0x43; */ /* FineArt A3 35mm border */
2612 /* if (!strcmp(name,"A3plus")) return 0x44; */ /* FineArt A3plus 35mm border */
2613 /* if (!strcmp(name,"Letter")) return 0x45; */ /* FineArt Letter 35mm border */
2614
2615 if (!strcmp(name,"w288h576")) return 0x46; /* US4x8 */
2616 if (!strcmp(name,"w1008h1224J")) return 0x47; /* HanKire --- 14in x 17 inch */
2617 if (!strcmp(name,"720h864J")) return 0x48; /* YonKire --- 10in x 12 inch */
2618 if (!strcmp(name,"c8x10J")) return 0x49; /* RokuKire --- same size as 8x10 inch */
2619
2620 /* if (!strcmp(name,"CD5Inch")) return 0x4a; */ /* CD Tray C */
2621 /* if (!strcmp(name,"CD5Inch")) return 0x4b; */ /* CD Tray D */
2622 /* if (!strcmp(name,"CD5Inch")) return 0x4c; */ /* CD Tray E */
2623
2624 /* Fine Art paper codes */
2625 /* Pro series (9000, 9000 Mk.2, 9500, 9500 Mk.2, PRO-1) */
2626 /* if (!strcmp(name,"A4")) return 0x4d; */ /* FineArt A4 35mm border */
2627 /* if (!strcmp(name,"A3")) return 0x4e; */ /* FineArt A3 35mm border */
2628 /* if (!strcmp(name,"Letter")) return 0x4f; */ /* FineArt Letter 35mm border */
2629 /* if (!strcmp(name,"A3plus")) return 0x50; */ /* FineArt A3plus 35mm border */
2630
2631 /* if (!strcmp(name,"CD5Inch")) return 0x51; */ /* CD Tray F */
2632 if (!strcmp(name,"w288h512")) return 0x52; /* Wide 101.6x180.6mm */
2633 /* w283h566 Wide postcard 100mm x 200mm */
2634
2635 /* media size codes for CD (and other media depending on printer model */
2636
2637 if (!strcmp(name,"CD5Inch")) return 0x53; /* CD Tray G --- arbitrary choice here, modify in ESC (P command */
2638 /* if (!strcmp(name,"CD5Inch")) return 0x56; */ /* CD Tray G-late */
2639 /* if (!strcmp(name,"CD5Inch")) return 0x57; */ /* CD Tray H */
2640
2641 /* Fine Art paper codes */
2642 /* MG6300, MG6500, MG6700, MG7100, MG7500 (only A4), MG6900, MG7700 */
2643 /* iP8700, iX6800 (A3 also) */
2644 /* if (!strcmp(name,"A4")) return 0x58; */ /* FineArt A4 35mm border */
2645 /* if (!strcmp(name,"A3")) return 0x59; */ /* FineArt A3 35mm border */
2646 /* if (!strcmp(name,"Letter")) return 0x5a; */ /* FineArt Letter 35mm border */
2647 /* if (!strcmp(name,"A3plus")) return 0x5d; */ /* FineArt A3plus 35mm border */
2648
2649 /* if (!strcmp(name,"CD5Inch")) return 0x5b; */ /* CD Tray J */
2650 /* if (!strcmp(name,"CD5Inch")) return 0x62; */ /* CD Tray L */
2651
2652 if (!strcmp(name,"A6")) return 0x63;
2653
2654 if (!strcmp(name,"LegalIndia")) return 0x8d; /* Legal (India) */
2655 if (!strcmp(name,"Oficio")) return 0x8e; /* Oficio */
2656 if (!strcmp(name,"M-Oficio")) return 0x8f; /* Mexico Oficio */
2657
2658 if (!strcmp(name,"w612h936")) return 0x90; /* (American) Foolscap */
2659 if (!strcmp(name,"Executive")) return 0x91;
2660
2661 if (!strcmp(name,"C5")) return 0x92; /* C5 Env */
2662 if (!strcmp(name,"Monarch")) return 0x93; /* Monarch Env */
2663
2664 if (!strcmp(name,"B-Oficio")) return 0x94; /* Brazil Oficio */
2665
2666 if (!strcmp(name,"w360h360")) return 0xba; /* square 5x5 inch */
2667
2668 /* custom */
2669
2670 stp_dprintf(STP_DBG_CANON, v,"canon: Unknown paper size '%s' - using custom\n",name);
2671 } else {
2672 stp_dprintf(STP_DBG_CANON, v,"canon: Couldn't look up paper size %fx%f - "
2673 "using custom\n",stp_get_page_height(v), stp_get_page_width(v));
2674 }
2675 return 0;
2676 }
2677
2678 /* fix paper_width and paper_length for known papersizes in ESC (p command */
fix_papersize(unsigned char arg_ESCP_1,int * paper_width,int * paper_length)2679 static void fix_papersize(unsigned char arg_ESCP_1, int *paper_width, int *paper_length){
2680
2681 switch(arg_ESCP_1)
2682 {
2683 case 0x63: *paper_width = 2481; *paper_length = 3497; break;; /* A6 */
2684 case 0x01: *paper_width = 3497; *paper_length = 4961; break;; /* A5 */
2685 case 0x03: *paper_width = 4961; *paper_length = 7016; break;; /* A4 */
2686 case 0x05: *paper_width = 7016; *paper_length = 9922; break;; /* A3 */
2687 case 0x08: *paper_width = 4300; *paper_length = 6071; break;; /* B5 */
2688 case 0x0a: *paper_width = 6071; *paper_length = 8599; break;; /* B4 */
2689 case 0x0d: *paper_width = 5100; *paper_length = 6600; break;; /* Letter */
2690 case 0x0f: *paper_width = 5100; *paper_length = 8400; break;; /* Legal */
2691 case 0x8d: *paper_width = 5079; *paper_length = 8150; break;; /* Legal (India) */
2692 case 0x8e: *paper_width = 5100; *paper_length = 7500; break;; /* Oficio */
2693 case 0x94: *paper_width = 5103; *paper_length = 8386; break;; /* Brazil Oficio */
2694 case 0x8f: *paper_width = 5103; *paper_length = 8056; break;; /* Mexico Oficio */
2695 case 0x90: *paper_width = 5100; *paper_length = 7800; break;; /* (American) Foolscap */
2696 case 0x91: *paper_width = 4352; *paper_length = 6300; break;; /* Executive */
2697 case 0x11: *paper_width = 6600; *paper_length = 10200; break;; /* Tabloid : 11x17" */
2698 /* Letter+, A4+ only seem to be available in shrink-to-fit */
2699 /* case 0x2a: paper_width = ( init->page_width + border_left + border_right ) * unit / 72; break;; */ /* LetterExtra : Letter navi, Letter+ */
2700 /* case 0x2b: paper_width = ( init->page_width + border_left + border_right ) * unit / 72; break;; */ /* A4Extra : A4navi, A4+ */
2701 case 0x2c: *paper_width = 7772; *paper_length = 11410; break;; /* A3Extra : A3navi, A3+ (13x19") */
2702 /* case 0x2d: paper_width = ( init->page_width + border_left + border_right ) * unit / 72; break;; */ /* w288h144 : 4x2" labels */
2703 /* Hagaki media */
2704 case 0x14: *paper_width = 2363; *paper_length = 3497; break;; /* w283h420 : Hagaki */
2705 /* Oufuku Hagaki should be swapped: w567h420, same height as Hagaki */
2706 /* case 0x39: paper_width = 4725; l: 3497 */
2707 /* w420h567 : Oufuku Hagaki */
2708 /* case 0x39: paper_width=(init->page_width + border_left + border_right) * unit / 72; break;;*/ /* leave untouched since orientation wrong */
2709 case 0x52: *paper_width = 2400; *paper_length = 4267; break;; /* w288h512 : Wide101.6x180.6mm */
2710 /* Envelope media */
2711 case 0x16: *paper_width = 2475; *paper_length = 5700; break;; /* COM10 : US Commercial #10 */
2712 case 0x17: *paper_width = 2599; *paper_length = 5197; break;; /* DL : Euro DL */
2713 case 0x2e: *paper_width = 2475; *paper_length = 5700; break;; /* COM10 : US Commercial #10 */
2714 case 0x2f: *paper_width = 2599; *paper_length = 5197; break;; /* DL : Euro DL */
2715 case 0x30: *paper_width = 2481; *paper_length = 5552; break;; /* w297xh666 : Western Env #4 (you4) */
2716 case 0x31: *paper_width = 2155; *paper_length = 4489; break;; /* w277xh538 : Western Env #6 (you6) */
2717 case 0x3a: *paper_width = 2835; *paper_length = 5552; break;; /* w340xh666 : Japanese Long Env #3 (chou3) */
2718 case 0x3b: *paper_width = 2126; *paper_length = 4843; break;; /* w255xh581 : Japanese Long Env #4 (chou4) */
2719 case 0x92: *paper_width = 3827; *paper_length = 5410; break;; /* C5 */
2720 case 0x93: *paper_width = 2325; *paper_length = 4500; break;; /* Monarch */
2721 /* Photo media */
2722 case 0x32: *paper_width = 2103; *paper_length = 3000; break;; /* w252h360 : L --- similar to US 3.5x5" */
2723 case 0x33: *paper_width = 3000; *paper_length = 4205; break;; /* w360h504 : 2L --- similar to US 5x7" */
2724 case 0x37: *paper_width = 3000; *paper_length = 4200; break;; /* w360h504 : US 5x7" */
2725 case 0x34: *paper_width = 2400; *paper_length = 3600; break;; /* w288h432J : KG --- same as US 4x6" */
2726 case 0x46: *paper_width = 2400; *paper_length = 4800; break;; /* w288h576 : US 4x8" */
2727 case 0xba: *paper_width = 3000; *paper_length = 3000; break;; /* w360h360 : square 5x5" */
2728 /* CD media */
2729 case 0x35: *paper_width = 3207; *paper_length = 6041; break;; /* CD5Inch : CD Custom Tray */
2730 case 0x3f: *paper_width = 3378; *paper_length = 6206; break;; /* CD5Inch : CD Tray A */
2731 case 0x40: *paper_width = 3095; *paper_length = 5640; break;; /* CD5Inch : CD Tray B */
2732 case 0x4a: *paper_width = 3095; *paper_length = 5640; break;; /* CD5Inch : CD Tray C */
2733 case 0x4b: *paper_width = 3095; *paper_length = 5640; break;; /* CD5Inch : CD Tray D */
2734 case 0x4c: *paper_width = 4063; *paper_length = 6497; break;; /* CD5Inch : CD Tray E */
2735 case 0x51: *paper_width = 3095; *paper_length = 5730; break;; /* CD5Inch : CD Tray F */
2736 case 0x53: *paper_width = 3095; *paper_length = 6008; break;; /* CD5Inch : CD Tray G */
2737 case 0x56: *paper_width = 3095; *paper_length = 6008; break;; /* CD5Inch : CD Tray G late version */
2738 case 0x57: *paper_width = 3572; *paper_length = 8953; break;; /* CD5Inch : CD Tray H */
2739 case 0x5b: *paper_width = 3071; *paper_length = 5311; break;; /* CD5Inch : CD Tray J */
2740 /* no printer using Tray L yet supported */
2741 /* case 0x62: paper_width = ( init->page_width + border_left + border_right ) * unit / 72; break;; */ /* CD5Inch : CD Tray L */
2742 case 0xbc: *paper_width = 3494; *paper_length = 4928; break;; /* CD5Inch : CD Tray M */
2743 /* Business/Credit Card media */
2744 case 0x36: *paper_width = 1300; *paper_length = 2150; break;; /* w155h257 : Japanese Business Card 55x91mm */
2745 case 0x41: *paper_width = 1276; *paper_length = 2032; break;; /* w155h244 : Business/Credit Card 54x86mm */
2746 /* Fine Art media */
2747 case 0x42: *paper_width = 4961; *paper_length = 7016; break;; /* FineArt A4 35mm border */
2748 case 0x43: *paper_width = 7016; *paper_length = 9922; break;; /* FineArt A3 35mm border */
2749 case 0x44: *paper_width = 7772; *paper_length = 11410; break;; /* FineArt A3+ 35mm border */
2750 case 0x45: *paper_width = 5100; *paper_length = 6600; break;; /* FineArt Letter 35mm border */
2751 case 0x4d: *paper_width = 4961; *paper_length = 7016; break;; /* FineArt A4 35mm border */
2752 case 0x4e: *paper_width = 7016; *paper_length = 9922; break;; /* FineArt A3 35mm border */
2753 case 0x4f: *paper_width = 5100; *paper_length = 6600; break;; /* FineArt Letter 35mm border */
2754 case 0x50: *paper_width = 7772; *paper_length = 11410; break;; /* FineArt A3+ 35mm border */
2755 case 0x58: *paper_width = 4961; *paper_length = 7016; break;; /* FineArt A4 35mm border */
2756 case 0x59: *paper_width = 7016; *paper_length = 9922; break;; /* FineArt A3 35mm border */
2757 case 0x5a: *paper_width = 5100; *paper_length = 6600; break;; /* FineArt Letter 35mm border */
2758 case 0x5d: *paper_width = 7772; *paper_length = 11410; break;; /* FineArt A3+ 35mm border */
2759 /* Other media */
2760 case 0x47: *paper_width = 8400; *paper_length = 10200; break;; /* w1008h1224J : HanKire --- 14x17" */
2761 case 0x48: *paper_width = 6000; *paper_length = 7200; break;; /* 720h864J : YonKire --- 10x12" */
2762 case 0x49: *paper_width = 4800; *paper_length = 6000; break;; /* c8x10J : RokuKire --- same as 8x10" */
2763 /* default */
2764 /* default: paper_width=(init->page_width + border_left + border_right) * unit / 72; break;; */ /* custom */
2765 }
2766 }
2767
2768 static void
canon_describe_resolution(const stp_vars_t * v,stp_resolution_t * x,stp_resolution_t * y)2769 canon_describe_resolution(const stp_vars_t *v, stp_resolution_t *x, stp_resolution_t *y)
2770 {
2771 const canon_mode_t* mode = NULL;
2772 const canon_cap_t * caps = canon_get_model_capabilities(v);
2773
2774 /* if mode is not yet set, it remains NULL */
2775 stp_dprintf(STP_DBG_CANON, v,"Calling get_current_parameter from canon_describe_resolution\n");
2776 mode = canon_get_current_mode(v);
2777
2778 if(!mode)
2779 mode = &caps->modelist->modes[caps->modelist->default_mode];
2780
2781 if (mode) {
2782 *x = mode->xdpi;
2783 *y = mode->ydpi;
2784 }
2785 }
2786
2787 static const char *
canon_describe_output(const stp_vars_t * v)2788 canon_describe_output(const stp_vars_t *v)
2789 {
2790 unsigned int ink_type = canon_printhead_colors(v);
2791
2792 if(ink_type & CANON_INK_CMYK_MASK)
2793 return "CMYK";
2794 if(ink_type & CANON_INK_CMY_MASK)
2795 return "CMY";
2796 /* Gernot added */
2797 /*if(ink_type & CANON_INK_cmy_MASK)
2798 return "cmy";*/
2799 return "Grayscale";
2800 }
2801
2802 /*
2803 * 'canon_parameters()' - Return the parameter values for the given parameter.
2804 */
2805
2806 static stp_parameter_list_t
canon_list_parameters(const stp_vars_t * v)2807 canon_list_parameters(const stp_vars_t *v)
2808 {
2809 stp_parameter_list_t *ret = stp_parameter_list_create();
2810 stp_parameter_list_t *tmp_list;
2811
2812 int i;
2813
2814 /* Set up dithering */
2815 tmp_list = stp_dither_list_parameters(v);
2816 stp_parameter_list_append(ret, tmp_list);
2817 stp_parameter_list_destroy(tmp_list);
2818
2819 for (i = 0; i < the_parameter_count; i++)
2820 stp_parameter_list_add_param(ret, &(the_parameters[i]));
2821 for (i = 0; i < float_parameter_count; i++)
2822 stp_parameter_list_add_param(ret, &(float_parameters[i].param));
2823 return ret;
2824 }
2825
2826 static void
canon_parameters(const stp_vars_t * v,const char * name,stp_parameter_t * description)2827 canon_parameters(const stp_vars_t *v, const char *name,
2828 stp_parameter_t *description)
2829 {
2830 int i,j;
2831
2832 const canon_cap_t * caps=
2833 canon_get_model_capabilities(v);
2834 description->p_type = STP_PARAMETER_TYPE_INVALID;
2835
2836 if (name == NULL)
2837 return;
2838
2839 for (i = 0; i < float_parameter_count; i++)
2840 if (strcmp(name, float_parameters[i].param.name) == 0)
2841 {
2842 /* presumably need to return the maximum number of inks the printer can handle */
2843 unsigned int ink_type = canon_printhead_colors(v);
2844
2845 stp_fill_parameter_settings(description,
2846 &(float_parameters[i].param));
2847 description->deflt.dbl = float_parameters[i].defval;
2848 description->bounds.dbl.upper = float_parameters[i].max;
2849 description->bounds.dbl.lower = float_parameters[i].min;
2850 if (ink_type != CANON_INK_K || !float_parameters[i].color_only)
2851 description->is_active = 1;
2852 else
2853 description->is_active = 0;
2854 return;
2855 }
2856
2857 for (i = 0; i < the_parameter_count; i++)
2858 if (strcmp(name, the_parameters[i].name) == 0)
2859 {
2860 stp_fill_parameter_settings(description, &(the_parameters[i]));
2861 break;
2862 }
2863 if (strcmp(name, "PageSize") == 0)
2864 {
2865 const char* input_slot = stp_get_string_parameter(v, "InputSlot");
2866 unsigned int height_limit, width_limit;
2867 description->bounds.str = stp_string_list_create();
2868
2869 width_limit = caps->max_width;
2870 height_limit = caps->max_height;
2871
2872 if(input_slot && !strcmp(input_slot,"CD")){
2873 stp_string_list_add_string
2874 (description->bounds.str, "CD5Inch", _("CD - 5 inch"));
2875 stp_string_list_add_string
2876 (description->bounds.str, "CD3Inch", _("CD - 3 inch"));
2877 stp_string_list_add_string
2878 (description->bounds.str, "CDCustom", _("CD - Custom"));
2879 }else{
2880 const stp_papersize_list_t *paper_sizes =
2881 stpi_get_standard_papersize_list();
2882 const stp_papersize_list_item_t *ptli =
2883 stpi_papersize_list_get_start(paper_sizes);
2884 while (ptli)
2885 {
2886 const stp_papersize_t *pt = stpi_paperlist_item_get_data(ptli);
2887 if (pt->paper_size_type == PAPERSIZE_TYPE_STANDARD ||
2888 pt->paper_size_type == PAPERSIZE_TYPE_ENVELOPE) {
2889 if (strlen(pt->name) > 0 &&
2890 pt->width <= width_limit && pt->height <= height_limit){
2891 stp_string_list_add_string(description->bounds.str,
2892 pt->name, gettext(pt->text));
2893 }
2894 }
2895 ptli = stpi_paperlist_item_next(ptli);
2896 }
2897 }
2898 description->deflt.str =
2899 stp_string_list_param(description->bounds.str, 0)->name;
2900 }
2901 else if (strcmp(name, "CDInnerRadius") == 0 )
2902 {
2903 const char* input_slot = stp_get_string_parameter(v, "InputSlot");
2904 description->bounds.str = stp_string_list_create();
2905 if ( (!input_slot || !strcmp(input_slot,"CD")) &&
2906 (!stp_get_string_parameter(v, "PageSize") ||
2907 strcmp(stp_get_string_parameter(v, "PageSize"), "CDCustom") != 0) )
2908 {
2909 stp_string_list_add_string
2910 (description->bounds.str, "None", _("Normal"));
2911 stp_string_list_add_string
2912 (description->bounds.str, "Small", _("Print To Hub"));
2913 description->deflt.str =
2914 stp_string_list_param(description->bounds.str, 0)->name;
2915 }
2916 else
2917 description->is_active = 0;
2918 }
2919 else if (strcmp(name, "CDInnerDiameter") == 0 )
2920 {
2921 const char* input_slot = stp_get_string_parameter(v, "InputSlot");
2922 description->bounds.dimension.lower = 16 * 10 * 72 / 254;
2923 description->bounds.dimension.upper = 43 * 10 * 72 / 254;
2924 description->deflt.dimension = 43 * 10 * 72 / 254;
2925 if ( (!input_slot || !strcmp(input_slot,"CD")) &&
2926 (!stp_get_string_parameter(v, "PageSize") ||
2927 strcmp(stp_get_string_parameter(v, "PageSize"), "CDCustom") == 0) )
2928 description->is_active = 1;
2929 else
2930 description->is_active = 0;
2931 }
2932 else if (strcmp(name, "CDOuterDiameter") == 0 )
2933 {
2934 const char* input_slot = stp_get_string_parameter(v, "InputSlot");
2935 description->bounds.dimension.lower = 65 * 10 * 72 / 254;
2936 description->bounds.dimension.upper = 120 * 10 * 72 / 254;
2937 description->deflt.dimension = 329;
2938 if ( (!input_slot || !strcmp(input_slot,"CD")) &&
2939 (!stp_get_string_parameter(v, "PageSize") ||
2940 strcmp(stp_get_string_parameter(v, "PageSize"), "CDCustom") == 0) )
2941 description->is_active = 1;
2942 else
2943 description->is_active = 0;
2944 }
2945 else if (strcmp(name, "CDXAdjustment") == 0 ||
2946 strcmp(name, "CDYAdjustment") == 0)
2947 {
2948 const char* input_slot = stp_get_string_parameter(v, "InputSlot");
2949 description->bounds.dimension.lower = -15;
2950 description->bounds.dimension.upper = 15;
2951 description->deflt.dimension = 0;
2952 if (!input_slot || !strcmp(input_slot,"CD"))
2953 description->is_active = 1;
2954 else
2955 description->is_active = 0;
2956 }
2957 else if (strcmp(name, "Resolution") == 0)
2958 {
2959 #if 0
2960 const char* input_slot = stp_get_string_parameter(v, "InputSlot");
2961 #endif
2962 description->bounds.str= stp_string_list_create();
2963 description->deflt.str = NULL;
2964 for(i=0;i<caps->modelist->count;i++){
2965 #if 0
2966 if(!((!input_slot || !strcmp(input_slot,"CD")) && !(caps->modelist->modes[i].flags & MODE_FLAG_CD)))
2967 #endif
2968 stp_string_list_add_string(description->bounds.str,
2969 caps->modelist->modes[i].name, gettext(caps->modelist->modes[i].text));
2970 stp_dprintf(STP_DBG_CANON, v,"supports mode '%s'\n",
2971 caps->modelist->modes[i].name);
2972 if(i == caps->modelist->default_mode)
2973 description->deflt.str=caps->modelist->modes[i].name;
2974 }
2975 }
2976 else if (strcmp(name, "InkType") == 0)
2977 {
2978 const canon_mode_t* mode = NULL;
2979
2980 stp_dprintf(STP_DBG_CANON, v,"Calling get_current_parameter from InkType block in canon_parameters\n");
2981 mode=canon_get_current_mode(v);
2982
2983 description->bounds.str= stp_string_list_create();
2984 if (mode) {
2985 for(i=0;i<sizeof(canon_inktypes)/sizeof(canon_inktypes[0]);i++){
2986 if(mode->ink_types & canon_inktypes[i].ink_type){
2987 stp_string_list_add_string(description->bounds.str,canon_inktypes[i].name,_(canon_inktypes[i].text));
2988 stp_dprintf(STP_DBG_CANON, v," mode known --- Added InkType %s(%s) for mode %s (inktype %u)\n",canon_inktypes[i].name,canon_inktypes[i].text,mode->name,mode->ink_types);
2989 }
2990 }
2991 description->deflt.str = stp_string_list_param(description->bounds.str, 0)->name;
2992 }
2993 /* mode not defined yet --- needed for PPD generation */
2994 else {
2995 for(i=0;i<sizeof(canon_inktypes)/sizeof(canon_inktypes[0]);i++){
2996 for(j=0;j<caps->modelist->count;j++){
2997 if(caps->modelist->modes[j].ink_types & canon_inktypes[i].ink_type){
2998 stp_string_list_add_string(description->bounds.str,canon_inktypes[i].name,_(canon_inktypes[i].text));
2999 stp_dprintf(STP_DBG_CANON, v," no mode --- Added InkType %s(%s) for mode (%s) inktypes %u\n",canon_inktypes[i].name,canon_inktypes[i].text,caps->modelist->modes[j].name,caps->modelist->modes[j].ink_types);
3000 break;
3001 }
3002 }
3003 }
3004 /* default type must be deduced from the default mode */
3005 /* use color if available, so break after first (color) is found, since inkt types ordered with gray last */
3006 for(i=0;i<sizeof(canon_inktypes)/sizeof(canon_inktypes[0]);i++){
3007 if(caps->modelist->modes[caps->modelist->default_mode].ink_types & canon_inktypes[i].ink_type){
3008 description->deflt.str = canon_inktypes[i].name;
3009 break;
3010 }
3011 }
3012 }
3013 /* default type must be deduced from the default mode */
3014 /*description->deflt.str = stp_string_list_param(description->bounds.str, 0)->name;*/
3015 }
3016 else if (strcmp(name, "InkChannels") == 0)
3017 {
3018 unsigned int ink_type = canon_printhead_colors(v);
3019 for(i=0;i<sizeof(canon_inktypes)/sizeof(canon_inktypes[0]);i++){
3020 if(ink_type == canon_inktypes[i].ink_type){
3021 description->deflt.integer = canon_inktypes[i].num_channels;
3022 stp_dprintf(STP_DBG_CANON, v,"Added %d InkChannels\n",canon_inktypes[i].num_channels);
3023 }
3024 }
3025 description->bounds.integer.lower = -1;
3026 description->bounds.integer.upper = -1;
3027 }
3028 else if (strcmp(name, "MediaType") == 0)
3029 {
3030 const canon_paper_t * canon_paper_list = caps->paperlist->papers;
3031 int count = caps->paperlist->count;
3032 description->bounds.str= stp_string_list_create();
3033 description->deflt.str= canon_paper_list[0].name;
3034
3035 for (i = 0; i < count; i ++) {
3036 stp_string_list_add_string(description->bounds.str,
3037 canon_paper_list[i].name,
3038 gettext(canon_paper_list[i].text));
3039
3040 stp_dprintf(STP_DBG_CANON, v,"DEBUG: Gutenprint: Added Media Type: '%s'\n",canon_paper_list[i].name);
3041 }
3042 }
3043 else if (strcmp(name, "InputSlot") == 0)
3044 {
3045 const canon_slot_t * canon_slot_list = caps->slotlist->slots;
3046 int count = caps->slotlist->count;
3047 description->bounds.str= stp_string_list_create();
3048 description->deflt.str= canon_slot_list[0].name;
3049
3050 for (i = 0; i < count; i ++)
3051 stp_string_list_add_string(description->bounds.str,
3052 canon_slot_list[i].name,
3053 gettext(canon_slot_list[i].text));
3054 }
3055 else if (strcmp(name, "CassetteTray") == 0)
3056 {
3057 description->bounds.str= stp_string_list_create();
3058 description->is_active = 0;
3059 if (caps->CassetteTray_Opts) {
3060 const char* input_slot = stp_get_string_parameter(v, "InputSlot");
3061 stp_string_list_add_string
3062 (description->bounds.str, "Default", _("Driver-Controlled"));
3063 stp_string_list_add_string
3064 (description->bounds.str, "Upper", _("Upper Tray/Cassette 1"));
3065 stp_string_list_add_string
3066 (description->bounds.str, "Lower", _("Lower Tray/Cassette 2"));
3067 description->deflt.str =
3068 stp_string_list_param(description->bounds.str, 0)->name;
3069 if (!input_slot || !strcmp(input_slot,"Cassette"))
3070 description->is_active = 1;
3071 }
3072 }
3073 else if (strcmp(name, "PrintingMode") == 0)
3074 {
3075 int found_color, found_mono;
3076 const canon_mode_t* mode = NULL;
3077 /* mode remains NULL if not yet set */
3078
3079 stp_dprintf(STP_DBG_CANON, v,"Calling get_current_mode from PrintingMode block in canon_parameter\n");
3080 mode = canon_get_current_mode(v);
3081
3082 /* If mode is not set need to search ink types for all modes and
3083 see whether we have any color there
3084 */
3085
3086 stp_dprintf(STP_DBG_CANON, v,"PrintingMode---entered enumeration block in canon_printers\n");
3087
3088 description->bounds.str = stp_string_list_create();
3089
3090 stp_dprintf(STP_DBG_CANON, v,"PrintingMode---created list\n");
3091
3092 if (mode) {
3093 stp_dprintf(STP_DBG_CANON, v,"PrintingMode: (mode known) what is the current mode inktype value: %i\n",mode->ink_types);
3094 /* e.g., ink_types is 21 = 16 + 4 + 1 */
3095 if (mode->ink_types > 1) {
3096 stp_string_list_add_string
3097 (description->bounds.str, "Color", _("Color"));
3098 stp_dprintf(STP_DBG_CANON, v,"PrintingMode: (mode known) added Color\n");
3099 }
3100 if (mode->ink_types & CANON_INK_K) {
3101 stp_string_list_add_string
3102 (description->bounds.str, "BW", _("Black and White"));
3103 stp_dprintf(STP_DBG_CANON, v,"PrintingMode: (mode known) added BW\n");
3104 }
3105 }
3106 #if 0
3107 /* original code */
3108 if (mode)
3109 if (mode->ink_types != CANON_INK_K) {
3110 stp_string_list_add_string
3111 (description->bounds.str, "Color", _("Color"));
3112 stp_dprintf(STP_DBG_CANON, v,"PrintingMode: (mode known) added Color\n");
3113 }
3114 #endif
3115
3116 else { /* mode not known yet --- needed for PPD generation */
3117 stp_dprintf(STP_DBG_CANON, v,"PrintingMode: entered mode not known conditional block\n");
3118 /* add code to find color inks */
3119 /* default type must be deduced from the default mode */
3120 /* use color if available, so break after first (color) is found, since ink types ordered with gray last */
3121 found_color=0;
3122 for(i=0;i<sizeof(canon_inktypes)/sizeof(canon_inktypes[0]);i++){
3123 for(j=0;j<caps->modelist->count;j++){
3124 if(caps->modelist->modes[j].ink_types > 1){
3125 stp_string_list_add_string
3126 (description->bounds.str, "Color", _("Color"));
3127 found_color=1;
3128 stp_dprintf(STP_DBG_CANON, v,"PrintingMode: (mode not known) added Color\n");
3129 break;
3130 }
3131 }
3132 if (found_color==1)
3133 break;
3134 }
3135 found_mono=0;
3136 for(i=0;i<sizeof(canon_inktypes)/sizeof(canon_inktypes[0]);i++){
3137 for(j=0;j<caps->modelist->count;j++){
3138 if(caps->modelist->modes[j].ink_types & CANON_INK_K){
3139 stp_string_list_add_string
3140 (description->bounds.str, "BW", _("Black and White"));
3141 found_mono=1;
3142 stp_dprintf(STP_DBG_CANON, v,"PrintingMode: (mode not known) added BW\n");
3143 break;
3144 }
3145 }
3146 if (found_mono==1)
3147 break;
3148 }
3149
3150 #if 0
3151 /* ink types for default mode*/
3152 if(caps->modelist->modes[caps->modelist->default_mode].ink_types > 1){
3153 stp_string_list_add_string
3154 (description->bounds.str, "Color", _("Color"));
3155 stp_dprintf(STP_DBG_CANON, v,"PrintingMode: (mode not known) added Color\n");
3156 }
3157 if(caps->modelist->modes[caps->modelist->default_mode].ink_types & CANON_INK_K){
3158 stp_string_list_add_string
3159 (description->bounds.str, "BW", _("Black and White"));
3160 stp_dprintf(STP_DBG_CANON, v,"PrintingMode: (mode not known) added BW\n");
3161 }
3162 #endif
3163 #if 0
3164 /* original code */
3165 stp_string_list_add_string
3166 (description->bounds.str, "BW", _("Black and White"));
3167 stp_dprintf(STP_DBG_CANON, v,"PrintingMode: added BW\n");
3168 #endif
3169 }
3170
3171 /* original code --- fine as is */
3172 description->deflt.str =
3173 stp_string_list_param(description->bounds.str, 0)->name;
3174 }
3175 else if (strcmp(name, "InkSet") == 0)
3176 {
3177 description->bounds.str= stp_string_list_create();
3178 if (caps->features & CANON_CAP_T) {
3179 stp_string_list_add_string
3180 (description->bounds.str, "Both", _("Both"));
3181 if (!(caps->features & CANON_CAP_NOBLACK)) {
3182 stp_string_list_add_string
3183 (description->bounds.str, "Black", _("Black"));
3184 }
3185 stp_string_list_add_string
3186 (description->bounds.str, "Color", _("Color"));
3187 } /* mutually exclusive */
3188 else if (caps->features & CANON_CAP_cart) {
3189 stp_string_list_add_string
3190 (description->bounds.str, "Color", _("Color"));
3191 stp_string_list_add_string
3192 (description->bounds.str, "Black", _("Black"));
3193 stp_string_list_add_string
3194 (description->bounds.str, "Photo", _("Photo"));
3195 } else {
3196 /* make sure to have at least a default value: no choice */
3197 stp_string_list_add_string
3198 (description->bounds.str, "None", _("None"));
3199 }
3200 description->deflt.str =
3201 stp_string_list_param(description->bounds.str, 0)->name;
3202 }
3203 /* Test implementation of borderless printing */
3204 else if (strcmp(name, "FullBleed") == 0)
3205 {
3206 const char* input_slot = stp_get_string_parameter(v, "InputSlot");
3207 if (input_slot && !strcmp(input_slot,"CD"))
3208 description->is_active = 0;
3209 else if (caps->features & CANON_CAP_BORDERLESS)
3210 description->deflt.boolean = 0;
3211 else
3212 description->is_active = 0;
3213 }
3214 else if (strcmp(name, "Duplex") == 0)
3215 {
3216 int offer_duplex=0;
3217
3218 description->bounds.str = stp_string_list_create();
3219
3220 /*
3221 * Don't offer the Duplex/Tumble options if the JobMode parameter is
3222 * set to "Page" Mode.
3223 * "Page" mode is set by the Gimp Plugin, which only outputs one page at a
3224 * time, so Duplex/Tumble is meaningless.
3225 */
3226
3227 if (stp_get_string_parameter(v, "JobMode"))
3228 offer_duplex = strcmp(stp_get_string_parameter(v, "JobMode"), "Page");
3229 else
3230 offer_duplex=1;
3231
3232 if (offer_duplex && (caps->features & CANON_CAP_DUPLEX))
3233 {
3234 description->deflt.str = duplex_types[0].name;
3235 for (i=0; i < NUM_DUPLEX; i++)
3236 {
3237 stp_string_list_add_string(description->bounds.str,
3238 duplex_types[i].name,gettext(duplex_types[i].text));
3239 }
3240 }
3241 else
3242 description->is_active = 0;
3243 }
3244 else if (strcmp(name, "Orientation") == 0)
3245 {
3246 description->bounds.str = stp_string_list_create();
3247 description->deflt.str = orientation_types[0].name;
3248 for (i=0; i < NUM_ORIENTATION; i++)
3249 {
3250 stp_string_list_add_string(description->bounds.str,
3251 orientation_types[i].name,gettext(orientation_types[i].text));
3252 }
3253 }
3254 else if (strcmp(name, "Quality") == 0)
3255 {
3256 #if 0
3257 int has_standard_quality = 0;
3258 #endif
3259 description->bounds.str = stp_string_list_create();
3260 stp_string_list_add_string(description->bounds.str, "None",
3261 _("Manual Control"));
3262 stp_string_list_add_string(description->bounds.str, "Standard",
3263 _("Standard"));
3264 description->deflt.str = "Standard";
3265 }
3266 /* Cartridge selection for those printers that have it */
3267 else if (strcmp(name, "Cartridge") == 0)
3268 {
3269 #if 0
3270 int offer_cartridge_selection = 0;
3271 #endif
3272 description->bounds.str = stp_string_list_create();
3273 stp_string_list_add_string(description->bounds.str, "Both",
3274 _("Both"));
3275 stp_string_list_add_string(description->bounds.str, "Color",
3276 _("Color"));
3277 stp_string_list_add_string(description->bounds.str, "Black",
3278 _("Black"));
3279
3280 /* description->deflt.str = "Both"; */
3281 /* Note: not necessary set cartridge if Mono mode */
3282
3283 if (caps->features & CANON_CAP_CARTRIDGE)
3284 {
3285 description->deflt.str =
3286 stp_string_list_param(description->bounds.str, 0)->name;
3287 }
3288 else
3289 description->is_active = 0;
3290 }
3291
3292 }
3293
3294
3295 /*
3296 * 'canon_imageable_area()' - Return the imageable area of the page.
3297 */
3298
3299 static void
internal_imageable_area(const stp_vars_t * v,int use_paper_margins,int use_maximum_area,stp_dimension_t * left,stp_dimension_t * right,stp_dimension_t * bottom,stp_dimension_t * top)3300 internal_imageable_area(const stp_vars_t *v, /* I */
3301 int use_paper_margins,
3302 int use_maximum_area,
3303 stp_dimension_t *left, /* O - Left position in points */
3304 stp_dimension_t *right, /* O - Right position in points */
3305 stp_dimension_t *bottom, /* O - Bottom position in points */
3306 stp_dimension_t *top) /* O - Top position in points */
3307 {
3308 stp_dimension_t width, length; /* Size of page */
3309 int cd = 0; /* CD selected */
3310 const char *media_size = stp_get_string_parameter(v, "PageSize");
3311 stp_dimension_t left_margin = 0;
3312 stp_dimension_t right_margin = 0;
3313 stp_dimension_t bottom_margin = 0;
3314 stp_dimension_t top_margin = 0;
3315 const stp_papersize_t *pt = NULL;
3316 const char* input_slot = stp_get_string_parameter(v, "InputSlot");
3317
3318 const canon_cap_t * caps= canon_get_model_capabilities(v);
3319
3320 if (media_size)
3321 pt = stp_describe_papersize(v, media_size);
3322
3323 if(input_slot && !strcmp(input_slot,"CD"))
3324 cd = 1;
3325
3326 stp_default_media_size(v, &width, &length);
3327
3328 if (cd) {
3329 /* ignore printer margins for the cd print, margins get adjusted in do_print for now */
3330 if (pt) {
3331 /* move code from do_print here */
3332 }
3333 else {
3334 /* move code from do_print here */
3335 }
3336 }
3337 /* non-CD media */
3338 else {
3339 if (pt && use_paper_margins) {
3340 left_margin = pt->left;
3341 right_margin = pt->right;
3342 bottom_margin = pt->bottom;
3343 top_margin = pt->top;
3344 }
3345 /* limit to printer capabilities---without fullbleed */
3346 left_margin = MAX(left_margin, caps->border_left);
3347 right_margin = MAX(right_margin, caps->border_right);
3348 top_margin = MAX(top_margin, caps->border_top);
3349 bottom_margin = MAX(bottom_margin, caps->border_bottom);
3350 }
3351
3352 /* temporarily limit to non-CD media until page size code moved here from do_print */
3353 /* Note: written below code to handle CD case as well */
3354 if(!cd){
3355 stp_dprintf(STP_DBG_CANON, v,"internal_imageable_area: about to enter the borderless condition block\n");
3356 stp_dprintf(STP_DBG_CANON, v,"internal_imageable_area: is borderless available? %016lx\n",caps->features & CANON_CAP_BORDERLESS);
3357 stp_dprintf(STP_DBG_CANON, v,"internal_imageable_area: is borderless selected? %d\n",stp_get_boolean_parameter(v, "FullBleed"));
3358
3359 if ( (caps->features & CANON_CAP_BORDERLESS) &&
3360 (use_maximum_area || (!cd && stp_get_boolean_parameter(v, "FullBleed")))) {
3361
3362 stp_dprintf(STP_DBG_CANON, v,"internal_imageable_area: entered borderless condition\n");
3363
3364 if (pt) {
3365
3366 stp_dprintf(STP_DBG_CANON, v,"internal_imageable_area: entered pt condition\n");
3367
3368 if (pt->left <= 0 && pt->right <= 0 && pt->top <= 0 && pt->bottom <= 0) {
3369
3370 stp_dprintf(STP_DBG_CANON, v,"internal_imageable_area: entered margin<=0 condition\n");
3371
3372 if (use_paper_margins) {
3373 unsigned width_limit = caps->max_width;
3374 left_margin = -8;
3375 right_margin = -8;
3376 if (width - right_margin - 3 > width_limit)
3377 right_margin = width - width_limit - 3;
3378 top_margin = -6;
3379 bottom_margin = -15;
3380
3381 stp_dprintf(STP_DBG_CANON, v,"internal_imageable_area: use_paper_margins so set margins all to -7\n");
3382
3383 }
3384 else {
3385 left_margin = 0;
3386 right_margin = 0;
3387 top_margin = 0;
3388 bottom_margin = 0;
3389
3390 stp_dprintf(STP_DBG_CANON, v,"internal_imageable_area: does not use paper margins so set margins all to 0\n");
3391
3392 }
3393 }
3394 }
3395 }
3396 }
3397
3398 stp_dprintf(STP_DBG_CANON, v,"internal_imageable_area: left_margin %f\n",left_margin);
3399 stp_dprintf(STP_DBG_CANON, v,"internal_imageable_area: right_margin %f\n",right_margin);
3400 stp_dprintf(STP_DBG_CANON, v,"internal_imageable_area: top_margin %f\n",top_margin);
3401 stp_dprintf(STP_DBG_CANON, v,"internal_imageable_area: bottom_margin %f\n",bottom_margin);
3402
3403 *left = left_margin;
3404 *right = width - right_margin;
3405 *top = top_margin;
3406 *bottom = length - bottom_margin;
3407
3408 stp_dprintf(STP_DBG_CANON, v,"internal_imageable_area: page_left %f\n",*left);
3409 stp_dprintf(STP_DBG_CANON, v,"internal_imageable_area: page_right %f\n",*right);
3410 stp_dprintf(STP_DBG_CANON, v,"internal_imageable_area: page_top %f\n",*top);
3411 stp_dprintf(STP_DBG_CANON, v,"internal_imageable_area: page_bottom %f\n",*bottom);
3412
3413 }
3414
3415 static void
canon_imageable_area(const stp_vars_t * v,stp_dimension_t * left,stp_dimension_t * right,stp_dimension_t * bottom,stp_dimension_t * top)3416 canon_imageable_area(const stp_vars_t *v, /* I */
3417 stp_dimension_t *left, /* O - Left position in points */
3418 stp_dimension_t *right, /* O - Right position in points */
3419 stp_dimension_t *bottom, /* O - Bottom position in points */
3420 stp_dimension_t *top) /* O - Top position in points */
3421 {
3422 internal_imageable_area(v, 1, 0, left, right, bottom, top);
3423 }
3424
3425 static void
canon_maximum_imageable_area(const stp_vars_t * v,stp_dimension_t * left,stp_dimension_t * right,stp_dimension_t * bottom,stp_dimension_t * top)3426 canon_maximum_imageable_area(const stp_vars_t *v, /* I */
3427 stp_dimension_t *left, /* O - Left position in points */
3428 stp_dimension_t *right, /* O - Right position in points */
3429 stp_dimension_t *bottom, /* O - Bottom position in points */
3430 stp_dimension_t *top) /* O - Top position in points */
3431 {
3432 internal_imageable_area(v, 1, 1, left, right, bottom, top);
3433 }
3434
3435 static void
canon_limit(const stp_vars_t * v,stp_dimension_t * width,stp_dimension_t * height,stp_dimension_t * min_width,stp_dimension_t * min_height)3436 canon_limit(const stp_vars_t *v, /* I */
3437 stp_dimension_t *width,
3438 stp_dimension_t *height,
3439 stp_dimension_t *min_width,
3440 stp_dimension_t *min_height)
3441 {
3442 const canon_cap_t * caps=
3443 canon_get_model_capabilities(v);
3444 *width = caps->max_width;
3445 *height = caps->max_height;
3446 *min_width = 1;
3447 *min_height = 1;
3448 }
3449
3450 /*
3451 * 'canon_cmd()' - Sends a command with variable args
3452 */
3453 static void
canon_cmd(const stp_vars_t * v,const char * ini,const char cmd,int num,...)3454 canon_cmd(const stp_vars_t *v, /* I - the printer */
3455 const char *ini, /* I - 2 bytes start code */
3456 const char cmd, /* I - command code */
3457 int num, /* I - number of arguments */
3458 ... /* I - the args themselves */
3459 )
3460 {
3461 unsigned char *buffer = stp_zalloc(num + 1);
3462 int i;
3463 va_list ap;
3464
3465 if (num)
3466 {
3467 va_start(ap, num);
3468 for (i=0; i<num; i++)
3469 buffer[i]= (unsigned char) va_arg(ap, int);
3470 va_end(ap);
3471 }
3472
3473 stp_zfwrite(ini,2,1,v);
3474 if (cmd)
3475 {
3476 stp_putc(cmd,v);
3477 stp_put16_le(num, v);
3478 if (num)
3479 stp_zfwrite((const char *)buffer,num,1,v);
3480 }
3481 stp_free(buffer);
3482 }
3483
3484 #define PUT(V,WHAT,VAL,RES) stp_dprintf(STP_DBG_CANON,V,"canon: "WHAT \
3485 " is %04x =% 5d = %f\" = %f mm\n",(VAL),(VAL),(VAL)/(1.*RES),(VAL)/(RES/25.4))
3486
3487 #define ESC28 "\033\050"
3488 #define ESC5b "\033\133"
3489 #define ESC40 "\033\100"
3490
canon_control_cmd(const stp_vars_t * v,const char * cmd)3491 static void canon_control_cmd(const stp_vars_t*v,const char* cmd){
3492 canon_cmd(v,ESC5b,0x4b, 2, 0x00,0x1f);
3493 stp_puts("BJLSTART\nControlMode=Common\n",v);
3494 stp_puts(cmd,v);
3495 stp_putc('\n',v);
3496 stp_puts("BJLEND\n",v);
3497 }
3498
3499
3500 /* ESC [K -- -- reset printer:
3501 */
3502 static void
canon_init_resetPrinter(const stp_vars_t * v,const canon_privdata_t * init)3503 canon_init_resetPrinter(const stp_vars_t *v, const canon_privdata_t *init)
3504 {
3505 if ( init->caps->control_cmdlist ){
3506 int i=0;
3507 while(init->caps->control_cmdlist[i]){
3508 canon_control_cmd(v,init->caps->control_cmdlist[i]);
3509 ++i;
3510 }
3511 }
3512 if(!strcmp(init->slot->name,"CD"))
3513 canon_control_cmd(v,"MediaDetection=ON");
3514 canon_cmd(v,ESC5b,0x4b, 2, 0x00,0x0f);
3515 }
3516
3517 /* ESC ($ -- 0x24 -- cmdSetDuplex --:
3518 */
3519 static void
canon_init_setDuplex(const stp_vars_t * v,const canon_privdata_t * init)3520 canon_init_setDuplex(const stp_vars_t *v, const canon_privdata_t *init)
3521 {
3522 if (!(init->caps->features & CANON_CAP_DUPLEX))
3523 return;
3524 if (strncmp(init->duplex_str, "Duplex", 6)) {
3525 if ( !(strcmp(init->caps->name,"i860")) || !(strcmp(init->caps->name,"i865")) || !(strcmp(init->caps->name,"i950")) || !(strcmp(init->caps->name,"i960")) || !(strcmp(init->caps->name,"i990")) ) {
3526 /* i860, i865, i950, i960, i990 use ESC ($ command even for simplex mode */
3527 canon_cmd(v,ESC28,0x24,9,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00);
3528 return;
3529 }
3530 else
3531 return;
3532 }
3533 /* The same command seems to be needed for both Duplex and DuplexTumble
3534 no idea about the meanings of the single bytes */
3535 canon_cmd(v,ESC28,0x24,9,0x01,0x00,0x02,0x00,0x00,0x00,0x00,0x00,0x02);
3536 }
3537
3538 /* ESC (a -- 0x61 -- cmdSetPageMode --:
3539 */
3540 static void
canon_init_setPageMode(const stp_vars_t * v,const canon_privdata_t * init)3541 canon_init_setPageMode(const stp_vars_t *v, const canon_privdata_t *init)
3542 {
3543 if (!(init->caps->features & CANON_CAP_a))
3544 return;
3545
3546 if (init->caps->features & CANON_CAP_a)
3547 canon_cmd(v,ESC28,0x61, 1, 0x01);
3548 }
3549
3550 /* ESC (b -- 0x62 -- -- set data compression:
3551 */
3552 static void
canon_init_setDataCompression(const stp_vars_t * v,const canon_privdata_t * init)3553 canon_init_setDataCompression(const stp_vars_t *v, const canon_privdata_t *init)
3554 {
3555 if (!(init->caps->features & CANON_CAP_b))
3556 return;
3557
3558 canon_cmd(v,ESC28,0x62, 1, 0x01);
3559 }
3560
3561 /* ESC (c -- 0x63 -- cmdSetColor --:
3562 */
3563 static void
canon_init_setColor(const stp_vars_t * v,const canon_privdata_t * init)3564 canon_init_setColor(const stp_vars_t *v, const canon_privdata_t *init)
3565 {
3566 unsigned char
3567 numargs, arg_63[6];
3568
3569 if (!(init->caps->features & CANON_CAP_c))
3570 return;
3571
3572 numargs = 3;
3573 arg_63[0] = init->caps->model_id << 4; /* MODEL_ID */
3574
3575 switch ( init->caps->model_id ) {
3576
3577 case 0: /* very old 360 dpi series: BJC-800/820 */
3578 break; /* tbd */
3579
3580 case 1: /* 360 dpi series - BJC-4000, BJC-210, BJC-70 and their descendants */
3581 if (init->used_inks == CANON_INK_K)
3582 arg_63[0]|= 0x01; /* PRINT_COLOUR */
3583
3584
3585 // if ( (!strcmp(init->caps->name,"85")) || (!strcmp(init->caps->name,"1000")) ) /* BJC-85, BJC-1000 */
3586 // arg_63[1] = (init->pt) ? init->pt->media_code_c : 0; /* print media type */
3587 // else /* original, not sure which models follow this at all */
3588 arg_63[1] = ((init->pt ? init->pt->media_code_c : 0) << 4) /* PRINT_MEDIA */
3589 + 1; /* hardcode to High quality for now */ /* PRINT_QUALITY */
3590
3591 if (!strcmp(init->caps->name,"2100")) { /* BJC-2100: ESC (c command length is 3 */
3592 if (!strcmp(init->mode->name,"720x360dpi"))
3593 arg_63[1] = 0x00;
3594 else if (!strcmp(init->mode->name,"360x360dpi_draft"))
3595 arg_63[1] = 0x00;
3596 else if (!strcmp(init->mode->name,"180x180dpi"))
3597 arg_63[1] = 0x02;
3598 /* else keep at 01 hard-coded as above - logic unknown */
3599 canon_cmd(v,ESC28,0x63, 3, arg_63[0], arg_63[1], 0x00);
3600 } else /* length 2 in legacy code */
3601 canon_cmd(v,ESC28,0x63, 2, arg_63[0], arg_63[1]);
3602 break;
3603
3604 case 2: /* are any models using this? */
3605 break;
3606
3607 case 3: /* 720 dpi series - BJC-3000 and descendants */
3608 if (init->used_inks == CANON_INK_K)
3609 arg_63[0]|= 0x01; /* colour mode */
3610
3611 arg_63[1] = (init->pt) ? init->pt->media_code_c : 0; /* print media type */
3612
3613 if (!strcmp(init->caps->name,"S200")) /* S200 */
3614 {
3615 if ((init->mode->xdpi == 720) && (init->mode->ydpi == 720 ))
3616 arg_63[2] = 1;
3617 else
3618 arg_63[2] = 4; /* hardcoded: quality 3 (may be 0...4) */
3619 /* bidirectional is controlled via quality: 0..2 is bidi, 3 and 4 uni */
3620 /* not every combination works, no idea about the principle */
3621 if ( (init->mode->xdpi > 360) || (init->mode->ydpi > 360) )
3622 {
3623 numargs = 6;
3624 arg_63[3] = 0x10; arg_63[4] = 6; arg_63[5] = 8; /* arg5 makes a vert. offset for K */
3625 if (init->used_inks == CANON_INK_K)
3626 arg_63[4] = 1;
3627 }
3628 }
3629 else if (!strcmp(init->caps->name,"4550")) /* BJC-4550 */
3630 {
3631 numargs = 3;
3632 arg_63[2] = 0; /* not used in Black and Color, no idea about PhotoColor yet */
3633 arg_63[1] = init->quality; /* hardcode to whatever this means for now; quality, apparently */
3634 }
3635 else
3636 arg_63[2] = init->quality; /* hardcode to whatever this means for now; quality, apparently */
3637
3638 stp_zprintf(v, "\033\050\143");
3639 stp_put16_le(numargs, v);
3640 stp_zfwrite((const char *)arg_63, numargs, 1, v);
3641 break;
3642 }
3643
3644 return;
3645 }
3646
3647 /* ESC (d -- 0x64 -- -- set raster resolution:
3648 */
3649 static void
canon_init_setResolution(const stp_vars_t * v,const canon_privdata_t * init)3650 canon_init_setResolution(const stp_vars_t *v, const canon_privdata_t *init)
3651 {
3652 if (!(init->caps->features & CANON_CAP_d))
3653 return;
3654
3655 if (strcmp(init->caps->name,"S200") || (init->mode->xdpi <= 360))
3656 canon_cmd(v,ESC28,0x64, 4,
3657 (init->mode->ydpi >> 8 ), (init->mode->ydpi & 255),
3658 (init->mode->xdpi >> 8 ), (init->mode->xdpi & 255));
3659 else
3660 if (init->mode->xdpi < 2880)
3661 canon_cmd(v,ESC28,0x64, 4,
3662 (720 >> 8), (720 & 255),
3663 (720 >> 8), (720 & 255));
3664 else
3665 canon_cmd(v,ESC28,0x64, 4,
3666 (720 >> 8), (720 & 255),
3667 (2880 >> 8), (2880 & 255));
3668 }
3669
3670 /* ESC (g -- 0x67 -- cmdSetPageMargins --:
3671 */
3672 static void
canon_init_setPageMargins(const stp_vars_t * v,const canon_privdata_t * init)3673 canon_init_setPageMargins(const stp_vars_t *v, const canon_privdata_t *init)
3674 {
3675 /* TOFIX: what exactly is to be sent?
3676 * Is it the printable length or the bottom border?
3677 * Is is the printable width or the right border?
3678 */
3679
3680 int minlength= 0;
3681 int minwidth= 0;
3682 int length= init->page_height*5/36;
3683 int width= init->page_width*5/36;
3684
3685 if (!(init->caps->features & CANON_CAP_g))
3686 return;
3687
3688 if (minlength>length) length= minlength;
3689 if (minwidth>width) width= minwidth;
3690
3691 canon_cmd(v,ESC28,0x67, 4, 0,
3692 (unsigned char)(length),1,
3693 (unsigned char)(width));
3694
3695 }
3696
3697 /* ESC (l -- 0x6c -- cmdSetTray --:
3698 */
3699 static void
canon_init_setTray(const stp_vars_t * v,const canon_privdata_t * init)3700 canon_init_setTray(const stp_vars_t *v, const canon_privdata_t *init)
3701 {
3702 unsigned char
3703 arg_6c_1 = 0x00,
3704 arg_6c_2 = 0x00, /* plain paper */
3705 arg_6c_3 = 0x00; /* special cases like iP7100 to be handled */
3706
3707 if (!(init->caps->features & CANON_CAP_l))
3708 return;
3709
3710 arg_6c_1 = init->caps->model_id << 4;
3711
3712 arg_6c_1|= (init->slot->code & 0x0f);
3713
3714 /* set gap for MP710/740 if thick media selected */
3715 if (!strcmp(init->slot->name,"AutoThick"))
3716 if ( (!strcmp(init->caps->name,"PIXMA MP710")) || (!strcmp(init->caps->name,"PIXMA MP740")) )
3717 arg_6c_3 = 0x10;
3718
3719 switch ( init->caps->model_id ) {
3720 case 0:
3721 break;
3722 case 1:
3723 if (init->pt) arg_6c_2 = ((init->pt ? init->pt->media_code_l : 0) << 4); /* PRINT_MEDIA */
3724 break;
3725 case 2:
3726 break;
3727 case 3:
3728 if (init->pt) arg_6c_2 = init->pt->media_code_l; /* PRINT_MEDIA */
3729 break;
3730 }
3731
3732 /* select between length 2 and 3 byte variations of command */
3733 /*if(init->caps->model_id >= 3)*/
3734 if(init->caps->ESC_l_len == 3)
3735 canon_cmd(v,ESC28,0x6c, 3, arg_6c_1, arg_6c_2, arg_6c_3); /* 3rd arg is "gap" */
3736 else /* else 2 bytes---no other option for now */
3737 canon_cmd(v,ESC28,0x6c, 2, arg_6c_1, arg_6c_2);
3738 }
3739
3740 /* ESC (m -- 0x6d -- -- :
3741 */
3742 static void
canon_init_setPrintMode(const stp_vars_t * v,const canon_privdata_t * init)3743 canon_init_setPrintMode(const stp_vars_t *v, const canon_privdata_t *init)
3744 {
3745 unsigned char
3746 arg_6d_1 = 0x03, /* color printhead? */
3747 arg_6d_2 = 0x00, /* 00=color 02=b/w */
3748 arg_6d_3 = 0x00, /* only 01 for bjc8200 and S200*/
3749 /* S200:for envelope and t-shirt transfer = 03 */
3750 arg_6d_a = 0x03, /* A4 paper */
3751 arg_6d_b = 0x00;
3752
3753 if (!(init->caps->features & CANON_CAP_m))
3754 return;
3755
3756 arg_6d_a= canon_size_type(v,init->caps);
3757 if (!arg_6d_a)
3758 arg_6d_b= 1;
3759
3760 arg_6d_1= 0x04;
3761
3762 if ((!strcmp(init->caps->name,"7000")) && (init->used_inks == CANON_INK_K || init->used_inks == CANON_INK_CcMmYK || init->used_inks == CANON_INK_CcMmYyK))
3763 arg_6d_1= 0x03;
3764
3765 if (((!strcmp(init->caps->name,"8200") || !strcmp(init->caps->name,"S200")) && init->used_inks == CANON_INK_K) || init->used_inks == CANON_INK_CMYK)
3766 arg_6d_1= 0x02;
3767
3768 if(!strcmp(init->caps->name,"S200") && init->used_inks == CANON_INK_CMY)
3769 arg_6d_1= 0x02;
3770
3771 if (init->used_inks == CANON_INK_K)
3772 arg_6d_2= 0x02;
3773
3774 if (!strcmp(init->caps->name,"8200") || !strcmp(init->caps->name,"S200"))
3775 arg_6d_3= 0x01;
3776
3777 canon_cmd(v,ESC28,0x6d,12, arg_6d_1,
3778 0xff,0xff,0x00,0x00,0x07,0x00,
3779 arg_6d_a,arg_6d_b,arg_6d_2,0x00,arg_6d_3);
3780 }
3781
3782 /* ESC (M -- 0x4d -- -- :
3783 */
3784 static void
canon_init_setESC_M(const stp_vars_t * v,const canon_privdata_t * init)3785 canon_init_setESC_M(const stp_vars_t *v, const canon_privdata_t *init)
3786 {
3787 if (!(init->caps->features & CANON_CAP_M))
3788 return;
3789
3790 canon_cmd(v,ESC28,0x4d, 3, 0x00, 0x00, 0x00);
3791 }
3792
3793 /* ESC (p -- 0x70 -- cmdSetPageMargins2 --:
3794 */
3795 static void
canon_init_setPageMargins2(const stp_vars_t * v,canon_privdata_t * init)3796 canon_init_setPageMargins2(const stp_vars_t *v, canon_privdata_t *init)
3797 {
3798 unsigned char arg_70_1,arg_70_2,arg_70_3,arg_70_4;
3799
3800 int border_left,border_right,border_top,border_bottom;
3801 int border_left2,border_top2;
3802 int border_right2;
3803 int border_bottom2;
3804 int area_right,area_top;
3805 int test_cd; /* variable for activating experimental adjustments */
3806 /* CD tray size adjustments for paper dimensions */
3807 int adjust_tray_custom_length, adjust_tray_custom_width;
3808 int adjust_tray_A_length, adjust_tray_A_width;
3809 int adjust_tray_BCD_length, adjust_tray_BCD_width;
3810 int adjust_tray_E_length, adjust_tray_E_width;
3811 int adjust_tray_F_length, adjust_tray_F_width;
3812 int adjust_tray_G_length, adjust_tray_G_width;
3813 int adjust_tray_H_length, adjust_tray_H_width;
3814 int adjust_tray_J_length, adjust_tray_J_width;
3815 int adjust_tray_L_length, adjust_tray_L_width;
3816 /* CD tray border adjustments */
3817 int adjust_tray_custom_left, adjust_tray_custom_right, adjust_tray_custom_top, adjust_tray_custom_bottom;
3818 int adjust_tray_A_left, adjust_tray_A_right, adjust_tray_A_top, adjust_tray_A_bottom;
3819 int adjust_tray_BCD_left, adjust_tray_BCD_right, adjust_tray_BCD_top, adjust_tray_BCD_bottom;
3820 int adjust_tray_E_left, adjust_tray_E_right, adjust_tray_E_top, adjust_tray_E_bottom;
3821 int adjust_tray_F_left, adjust_tray_F_right, adjust_tray_F_top, adjust_tray_F_bottom;
3822 int adjust_tray_G_left, adjust_tray_G_right, adjust_tray_G_top, adjust_tray_G_bottom;
3823 int adjust_tray_H_left, adjust_tray_H_right, adjust_tray_H_top, adjust_tray_H_bottom;
3824 int adjust_tray_J_left, adjust_tray_J_right, adjust_tray_J_top, adjust_tray_J_bottom;
3825 int adjust_tray_L_left, adjust_tray_L_right, adjust_tray_L_top, adjust_tray_L_bottom;
3826 int paper_width, paper_length;
3827
3828 /* Canon printer firmware requires paper_width (and paper_length?)
3829 to be exact matches in units of 1/600 inch.
3830 To this end, papersize code is used to find the papersize for the
3831 printjob, and paper_width and paper_length set to exact values,
3832 rather than calculated.
3833 */
3834 unsigned char arg_ESCP_1 = (init->pt) ? canon_size_type(v,init->caps) : 0x03; /* default size A4 */
3835 stp_dprintf(STP_DBG_CANON, v,"setPageMargins2: arg_ESCP_1 = '%x'\n",arg_ESCP_1);
3836
3837 /* TOFIX: what exactly is to be sent?
3838 * Is it the printable length or the bottom border?
3839 * Is is the printable width or the right border?
3840 */
3841
3842 int unit = 600;
3843 int printable_width = (init->page_width + 1)*5/6;
3844 int printable_length = (init->page_height + 1)*5/6;
3845
3846 const char* input_slot = stp_get_string_parameter(v, "InputSlot");
3847 int print_cd = (input_slot && (!strcmp(input_slot, "CD")));
3848
3849 stp_dprintf(STP_DBG_CANON, v,"setPageMargins2: print_cd = %d\n",print_cd);
3850
3851 test_cd = 1;
3852 /*
3853 Adjustments for different CD trays:
3854 All based on the following settings:
3855 CANON_CD_X = 176
3856 CANON_CD_Y = 405
3857
3858 Custom:
3859 printable_width = init->page_width + 24;
3860 printable_length = init->page_height + 132;
3861
3862 A:
3863 printable_width = init->page_width + 44;
3864 printable_length = init->page_height + 151;
3865
3866 B/C/D:
3867 printable_width = init->page_width + 10;
3868 printable_length = init->page_height + 84;
3869
3870 E:
3871 printable_width = init->page_width + 127;
3872 printable_length = init->page_height + 186;
3873
3874 F:
3875 printable_width = init->page_width + 10;
3876 printable_length = init->page_height + 95;
3877
3878 G:
3879 printable_width = init->page_width + 10;
3880 printable_length = init->page_height + 127;
3881
3882 H:
3883 printable_width = init->page_width + 68;
3884 printable_length = init->page_height + 481;
3885
3886 J:
3887 printable_width = init->page_width + 8;
3888 printable_length = init->page_height + 44;
3889
3890 L:
3891 printable_width = init->page_width + 10;
3892 printable_length = init->page_height + 263;
3893 */
3894
3895 /* adjust paper dimensions for CD in points */
3896 adjust_tray_custom_length = 132;
3897 adjust_tray_custom_width = 24;
3898 adjust_tray_A_length = 151;
3899 adjust_tray_A_width = 44;
3900 adjust_tray_BCD_length = 84;
3901 adjust_tray_BCD_width = 10;
3902 adjust_tray_E_length = 186;
3903 adjust_tray_E_width = 127;
3904 adjust_tray_F_length = 95;
3905 adjust_tray_F_width = 10; /* 10 calculated, but empirically 11 */
3906 adjust_tray_G_length = 127;
3907 adjust_tray_G_width = 10; /* 10 calculated, but empirically 11 */
3908 adjust_tray_H_length = 481;
3909 adjust_tray_H_width = 68;
3910 adjust_tray_J_length = 44;
3911 adjust_tray_J_width = 8;
3912 adjust_tray_L_length = 263;
3913 adjust_tray_L_width = 10;
3914
3915 /* ensure less than or equal to Windows measurements by border adjustments in points */
3916 adjust_tray_custom_left = 0;
3917 adjust_tray_custom_right = 0;
3918 adjust_tray_custom_top = 0;
3919 adjust_tray_custom_bottom = 0;
3920 adjust_tray_A_left = 0;
3921 adjust_tray_A_right = 0;
3922 adjust_tray_A_top = 0;
3923 adjust_tray_A_bottom = 0;
3924 adjust_tray_BCD_left = 0;
3925 adjust_tray_BCD_right = 0;
3926 adjust_tray_BCD_top = 0;
3927 adjust_tray_BCD_bottom = 0;
3928 adjust_tray_E_left = 0;
3929 adjust_tray_E_right = 0;
3930 adjust_tray_E_top = 0;
3931 adjust_tray_E_bottom = 0;
3932 adjust_tray_F_left = 0;
3933 adjust_tray_F_right = 0;
3934 adjust_tray_F_top = 0;
3935 adjust_tray_F_bottom = 0;
3936 adjust_tray_G_left = 0;
3937 adjust_tray_G_right = 0;
3938 adjust_tray_G_top = 0;
3939 adjust_tray_G_bottom = 0;
3940 adjust_tray_H_left = 0;
3941 adjust_tray_H_right = 0;
3942 adjust_tray_H_top = 0;
3943 adjust_tray_H_bottom = 0;
3944 adjust_tray_J_left = 0;
3945 adjust_tray_J_right = 0;
3946 adjust_tray_J_top = 0;
3947 adjust_tray_J_bottom = 0;
3948 adjust_tray_L_left = 0;
3949 adjust_tray_L_right = 0;
3950 adjust_tray_L_top = 0;
3951 adjust_tray_L_bottom = 0;
3952
3953 if ((print_cd) && test_cd) {
3954 /* test all of the parameters for CD */
3955 stp_dprintf(STP_DBG_CANON, v,"==========Start Test Printout=========='\n");
3956
3957 stp_dprintf(STP_DBG_CANON, v, "Tray Custom original init->page_width (pts): '%d'\n",init->page_width);
3958 stp_dprintf(STP_DBG_CANON, v, "Tray Custom original init->page_height (pts): '%d'\n",init->page_height);
3959 stp_dprintf(STP_DBG_CANON, v, "Tray Custom modified init->page_width (pts): '%d'\n",init->page_width + adjust_tray_custom_width);
3960 stp_dprintf(STP_DBG_CANON, v, "Tray Custom modified init->page_height (pts): '%d'\n",init->page_height + adjust_tray_custom_length);
3961 stp_dprintf(STP_DBG_CANON, v, "Tray Custom printable width (pts): '%d'\n",(init->page_width + adjust_tray_custom_width + 1) * 5 / 6);
3962 stp_dprintf(STP_DBG_CANON, v, "Tray Custom printable length (pts): '%d'\n",(init->page_height + adjust_tray_custom_length + 1) * 5 / 6);
3963 stp_dprintf(STP_DBG_CANON, v, "Tray Custom page_width (1/600): '%d'\n",(init->page_width + adjust_tray_custom_width) * unit / 72);
3964 stp_dprintf(STP_DBG_CANON, v, "Tray Custom page_height (1/600): '%d'\n",(init->page_height + adjust_tray_custom_length) * unit / 72);
3965 stp_dprintf(STP_DBG_CANON, v, "Tray Custom paper_width (1/600): '%d'\n",(init->page_width + adjust_tray_custom_width + 20 + adjust_tray_custom_left + adjust_tray_custom_right) * unit / 72);
3966 stp_dprintf(STP_DBG_CANON, v, "Tray Custom paper_height (1/600): '%d'\n",(init->page_height + adjust_tray_custom_length + 24 + adjust_tray_custom_top + adjust_tray_custom_bottom) * unit / 72);
3967
3968 stp_dprintf(STP_DBG_CANON, v, "Tray A original init->page_width (pts): '%d'\n",init->page_width);
3969 stp_dprintf(STP_DBG_CANON, v, "Tray A original init->page_height (pts): '%d'\n",init->page_height);
3970 stp_dprintf(STP_DBG_CANON, v, "Tray A modified init->page_width (pts): '%d'\n",init->page_width + adjust_tray_A_width);
3971 stp_dprintf(STP_DBG_CANON, v, "Tray A modified init->page_height (pts): '%d'\n",init->page_height + adjust_tray_A_length);
3972 stp_dprintf(STP_DBG_CANON, v, "Tray A printable width (pts): '%d'\n",(init->page_width + adjust_tray_A_width + 1) * 5 / 6);
3973 stp_dprintf(STP_DBG_CANON, v, "Tray A printable length (pts): '%d'\n",(init->page_height + adjust_tray_A_length + 1) * 5 / 6);
3974 stp_dprintf(STP_DBG_CANON, v, "Tray A page_width (1/600): '%d'\n",(init->page_width + adjust_tray_A_width) * unit / 72);
3975 stp_dprintf(STP_DBG_CANON, v, "Tray A page_height (1/600): '%d'\n",(init->page_height + adjust_tray_A_length) * unit / 72);
3976 stp_dprintf(STP_DBG_CANON, v, "Tray A paper_width (1/600): '%d'\n",(init->page_width + adjust_tray_A_width + 20 + adjust_tray_A_left + adjust_tray_A_right ) * unit / 72);
3977 stp_dprintf(STP_DBG_CANON, v, "Tray A paper_height (1/600): '%d'\n",(init->page_height + adjust_tray_A_length + 24 + adjust_tray_A_top + adjust_tray_A_bottom) * unit / 72);
3978
3979 stp_dprintf(STP_DBG_CANON, v, "Tray B/C/D original init->page_width (pts): '%d'\n",init->page_width);
3980 stp_dprintf(STP_DBG_CANON, v, "Tray B/C/D original init->page_height (pts): '%d'\n",init->page_height);
3981 stp_dprintf(STP_DBG_CANON, v, "Tray B/C/D modified init->page_width (pts): '%d'\n",init->page_width + adjust_tray_BCD_width);
3982 stp_dprintf(STP_DBG_CANON, v, "Tray B/C/D modified init->page_height (pts): '%d'\n",init->page_height + adjust_tray_BCD_length);
3983 stp_dprintf(STP_DBG_CANON, v, "Tray B/C/D printable width (pts): '%d'\n",(init->page_width + adjust_tray_BCD_width + 1) * 5 / 6);
3984 stp_dprintf(STP_DBG_CANON, v, "Tray B/C/D printable length (pts): '%d'\n",(init->page_height + adjust_tray_BCD_length + 1) * 5 / 6);
3985 stp_dprintf(STP_DBG_CANON, v, "Tray B/C/D page_width (1/600): '%d'\n",(init->page_width + adjust_tray_BCD_width) * unit / 72);
3986 stp_dprintf(STP_DBG_CANON, v, "Tray B/C/D page_height (1/600): '%d'\n",(init->page_height + adjust_tray_BCD_length) * unit / 72);
3987 stp_dprintf(STP_DBG_CANON, v, "Tray B/C/D paper_width (1/600): '%d'\n",(init->page_width + adjust_tray_BCD_width + 20 + adjust_tray_BCD_left + adjust_tray_BCD_right) * unit / 72);
3988 stp_dprintf(STP_DBG_CANON, v, "Tray B/C/D paper_height (1/600): '%d'\n",(init->page_height + adjust_tray_BCD_length + 24 + adjust_tray_BCD_top + adjust_tray_BCD_bottom) * unit / 72);
3989
3990 stp_dprintf(STP_DBG_CANON, v, "Tray E original init->page_width (pts): '%d'\n",init->page_width);
3991 stp_dprintf(STP_DBG_CANON, v, "Tray E original init->page_height (pts): '%d'\n",init->page_height);
3992 stp_dprintf(STP_DBG_CANON, v, "Tray E modified init->page_width (pts): '%d'\n",init->page_width + adjust_tray_E_width);
3993 stp_dprintf(STP_DBG_CANON, v, "Tray E modified init->page_height (pts): '%d'\n",init->page_height + adjust_tray_E_length);
3994 stp_dprintf(STP_DBG_CANON, v, "Tray E printable width (pts): '%d'\n",(init->page_width + adjust_tray_E_width + 1) * 5 / 6);
3995 stp_dprintf(STP_DBG_CANON, v, "Tray E printable length (pts): '%d'\n",(init->page_height + adjust_tray_E_length + 1) * 5 / 6);
3996 stp_dprintf(STP_DBG_CANON, v, "Tray E page_width (1/600): '%d'\n",(init->page_width + adjust_tray_E_width) * unit / 72);
3997 stp_dprintf(STP_DBG_CANON, v, "Tray E page_height (1/600): '%d'\n",(init->page_height + adjust_tray_E_length) * unit / 72);
3998 stp_dprintf(STP_DBG_CANON, v, "Tray E paper_width (1/600): '%d'\n",(init->page_width + adjust_tray_E_width + 20 + adjust_tray_E_left + adjust_tray_E_right) * unit / 72);
3999 stp_dprintf(STP_DBG_CANON, v, "Tray E paper_height (1/600): '%d'\n",(init->page_height + adjust_tray_E_length + 24 + adjust_tray_E_top + adjust_tray_E_bottom) * unit / 72);
4000
4001 stp_dprintf(STP_DBG_CANON, v, "Tray F original init->page_width (pts): '%d'\n",init->page_width);
4002 stp_dprintf(STP_DBG_CANON, v, "Tray F original init->page_height (pts): '%d'\n",init->page_height);
4003 stp_dprintf(STP_DBG_CANON, v, "Tray F modified init->page_width (pts): '%d'\n",init->page_width + adjust_tray_F_width);
4004 stp_dprintf(STP_DBG_CANON, v, "Tray F modified init->page_height (pts): '%d'\n",init->page_height + adjust_tray_F_length);
4005 stp_dprintf(STP_DBG_CANON, v, "Tray F printable width (pts): '%d'\n",(init->page_width + adjust_tray_F_width + 1) * 5 / 6);
4006 stp_dprintf(STP_DBG_CANON, v, "Tray F printable length (pts): '%d'\n",(init->page_height + adjust_tray_F_length + 1) * 5 / 6);
4007 stp_dprintf(STP_DBG_CANON, v, "Tray F page_width (1/600): '%d'\n",(init->page_width + adjust_tray_F_width) * unit / 72);
4008 stp_dprintf(STP_DBG_CANON, v, "Tray F page_height (1/600): '%d'\n",(init->page_height + adjust_tray_F_length) * unit / 72);
4009 stp_dprintf(STP_DBG_CANON, v, "Tray F paper_width (1/600): '%d'\n",(init->page_width + adjust_tray_F_width + 20 + adjust_tray_F_left + adjust_tray_F_right) * unit / 72);
4010 stp_dprintf(STP_DBG_CANON, v, "Tray F paper_height (1/600): '%d'\n",(init->page_height + adjust_tray_F_length + 24 + adjust_tray_F_top + adjust_tray_F_bottom) * unit / 72);
4011
4012 stp_dprintf(STP_DBG_CANON, v, "Tray G original init->page_width (pts): '%d'\n",init->page_width);
4013 stp_dprintf(STP_DBG_CANON, v, "Tray G original init->page_height (pts): '%d'\n",init->page_height);
4014 stp_dprintf(STP_DBG_CANON, v, "Tray G modified init->page_width (pts): '%d'\n",init->page_width + adjust_tray_G_width);
4015 stp_dprintf(STP_DBG_CANON, v, "Tray G modified init->page_height (pts): '%d'\n",init->page_height + adjust_tray_G_length);
4016 stp_dprintf(STP_DBG_CANON, v, "Tray G printable width (pts): '%d'\n",(init->page_width + adjust_tray_G_width + 1) * 5 / 6);
4017 stp_dprintf(STP_DBG_CANON, v, "Tray G printable length (pts): '%d'\n",(init->page_height + adjust_tray_G_length + 1) * 5 / 6);
4018 stp_dprintf(STP_DBG_CANON, v, "Tray G page_width (1/600): '%d'\n",(init->page_width + adjust_tray_G_width) * unit / 72);
4019 stp_dprintf(STP_DBG_CANON, v, "Tray G page_height (1/600): '%d'\n",(init->page_height + adjust_tray_G_length) * unit / 72);
4020 stp_dprintf(STP_DBG_CANON, v, "Tray G paper_width (1/600): '%d'\n",(init->page_width + adjust_tray_G_width + 20 + adjust_tray_G_left + adjust_tray_G_right) * unit / 72);
4021 stp_dprintf(STP_DBG_CANON, v, "Tray G paper_height (1/600): '%d'\n",(init->page_height + adjust_tray_G_length + 24 + adjust_tray_G_top + adjust_tray_G_bottom) * unit / 72);
4022
4023 stp_dprintf(STP_DBG_CANON, v, "Tray H original init->page_width (pts): '%d'\n",init->page_width);
4024 stp_dprintf(STP_DBG_CANON, v, "Tray H original init->page_height (pts): '%d'\n",init->page_height);
4025 stp_dprintf(STP_DBG_CANON, v, "Tray H modified init->page_width (pts): '%d'\n",init->page_width + adjust_tray_H_width);
4026 stp_dprintf(STP_DBG_CANON, v, "Tray H modified init->page_height (pts): '%d'\n",init->page_height + adjust_tray_H_length);
4027 stp_dprintf(STP_DBG_CANON, v, "Tray H printable width (pts): '%d'\n",(init->page_width + adjust_tray_H_width + 1) * 5 / 6);
4028 stp_dprintf(STP_DBG_CANON, v, "Tray H printable length (pts): '%d'\n",(init->page_height + adjust_tray_H_length + 1) * 5 / 6);
4029 stp_dprintf(STP_DBG_CANON, v, "Tray H page_width (1/600): '%d'\n",(init->page_width + adjust_tray_H_width) * unit / 72);
4030 stp_dprintf(STP_DBG_CANON, v, "Tray H page_height (1/600): '%d'\n",(init->page_height + adjust_tray_H_length) * unit / 72);
4031 stp_dprintf(STP_DBG_CANON, v, "Tray H paper_width (1/600): '%d'\n",(init->page_width + adjust_tray_H_width + 20 + adjust_tray_H_left + adjust_tray_H_right) * unit / 72);
4032 stp_dprintf(STP_DBG_CANON, v, "Tray H paper_height (1/600): '%d'\n",(init->page_height + adjust_tray_H_length + 24 + adjust_tray_H_top + adjust_tray_H_bottom) * unit / 72);
4033
4034 stp_dprintf(STP_DBG_CANON, v, "Tray J original init->page_width (pts): '%d'\n",init->page_width);
4035 stp_dprintf(STP_DBG_CANON, v, "Tray J original init->page_height (pts): '%d'\n",init->page_height);
4036 stp_dprintf(STP_DBG_CANON, v, "Tray J modified init->page_width (pts): '%d'\n",init->page_width + adjust_tray_J_width);
4037 stp_dprintf(STP_DBG_CANON, v, "Tray J modified init->page_height (pts): '%d'\n",init->page_height + adjust_tray_J_length);
4038 stp_dprintf(STP_DBG_CANON, v, "Tray J printable width (pts): '%d'\n",(init->page_width + adjust_tray_J_width + 1) * 5 / 6);
4039 stp_dprintf(STP_DBG_CANON, v, "Tray J printable length (pts): '%d'\n",(init->page_height + adjust_tray_J_length + 1) * 5 / 6);
4040 stp_dprintf(STP_DBG_CANON, v, "Tray J page_width (1/600): '%d'\n",(init->page_width + adjust_tray_J_width) * unit / 72);
4041 stp_dprintf(STP_DBG_CANON, v, "Tray J page_height (1/600): '%d'\n",(init->page_height + adjust_tray_J_length) * unit / 72);
4042 stp_dprintf(STP_DBG_CANON, v, "Tray J paper_width (1/600): '%d'\n",(init->page_width + adjust_tray_J_width + 20 + adjust_tray_J_left + adjust_tray_J_right) * unit / 72);
4043 stp_dprintf(STP_DBG_CANON, v, "Tray J paper_height (1/600): '%d'\n",(init->page_height + adjust_tray_J_length + 24 + adjust_tray_J_top + adjust_tray_J_bottom) * unit / 72);
4044
4045 stp_dprintf(STP_DBG_CANON, v, "Tray L original init->page_width (pts): '%d'\n",init->page_width);
4046 stp_dprintf(STP_DBG_CANON, v, "Tray L original init->page_height (pts): '%d'\n",init->page_height);
4047 stp_dprintf(STP_DBG_CANON, v, "Tray L modified init->page_width (pts): '%d'\n",init->page_width + adjust_tray_L_width);
4048 stp_dprintf(STP_DBG_CANON, v, "Tray L modified init->page_height (pts): '%d'\n",init->page_height + adjust_tray_L_length);
4049 stp_dprintf(STP_DBG_CANON, v, "Tray L printable width (pts): '%d'\n",(init->page_width + adjust_tray_L_width + 1) * 5 / 6);
4050 stp_dprintf(STP_DBG_CANON, v, "Tray L printable length (pts): '%d'\n",(init->page_height + adjust_tray_L_length + 1) * 5 / 6);
4051 stp_dprintf(STP_DBG_CANON, v, "Tray L page_width (1/600): '%d'\n",(init->page_width + adjust_tray_L_width) * unit / 72);
4052 stp_dprintf(STP_DBG_CANON, v, "Tray L page_height (1/600): '%d'\n",(init->page_height + adjust_tray_L_length) * unit / 72);
4053 stp_dprintf(STP_DBG_CANON, v, "Tray L paper_width (1/600): '%d'\n",(init->page_width + adjust_tray_L_width + 20 + adjust_tray_L_left + adjust_tray_L_right) * unit / 72);
4054 stp_dprintf(STP_DBG_CANON, v, "Tray L paper_height (1/600): '%d'\n",(init->page_height + adjust_tray_L_length + 24 + adjust_tray_L_top + adjust_tray_L_bottom) * unit / 72);
4055
4056 stp_dprintf(STP_DBG_CANON, v,"==========End Test Printout=========='\n");
4057 }
4058
4059 /* Tray Custom */
4060 if ( (print_cd) && !(strcmp(init->caps->name,"PIXMA MP710")) && (test_cd==1) ) {
4061
4062 init->page_width +=24;
4063 init->page_height +=132;
4064
4065 stp_dprintf(STP_DBG_CANON, v, "Tray Custom modified init->page_width: '%d'\n",init->page_width);
4066 stp_dprintf(STP_DBG_CANON, v, "Tray Custom modified init->page_height: '%d'\n",init->page_height);
4067
4068 printable_width= (init->page_width+ 1)*5/6;
4069 printable_length= (init->page_height + 1)*5/6;
4070
4071 stp_dprintf(STP_DBG_CANON, v, "Tray Custom modified printable_width: '%d'\n",printable_width);
4072 stp_dprintf(STP_DBG_CANON, v, "Tray Custom modified printable_length: '%d'\n",printable_length);
4073
4074 }
4075
4076 /* Tray A */
4077 if ( (print_cd) && !(strcmp(init->caps->name,"PIXMA iP9910")) && (test_cd==1) ) {
4078
4079 init->page_width +=44;
4080 init->page_height +=151;
4081
4082 stp_dprintf(STP_DBG_CANON, v, "Tray A modified init->page_width: '%d'\n",init->page_width);
4083 stp_dprintf(STP_DBG_CANON, v, "Tray A modified init->page_height: '%d'\n",init->page_height);
4084
4085 printable_width= (init->page_width+ 1)*5/6;
4086 printable_length= (init->page_height + 1)*5/6;
4087
4088 stp_dprintf(STP_DBG_CANON, v, "Tray A modified printable_width: '%d'\n",printable_width);
4089 stp_dprintf(STP_DBG_CANON, v, "Tray A modified printable_length: '%d'\n",printable_length);
4090
4091 }
4092
4093 /* Tray B,C,D */
4094 if ( (print_cd) && !(strcmp(init->caps->name,"PIXMA iP3000")) && (test_cd==1) ) {
4095
4096 init->page_width +=10;
4097 init->page_height +=84;
4098
4099 stp_dprintf(STP_DBG_CANON, v, "Tray B/C/D modified init->page_width: '%d'\n",init->page_width);
4100 stp_dprintf(STP_DBG_CANON, v, "Tray B/C/B modified init->page_height: '%d'\n",init->page_height);
4101
4102 printable_width= (init->page_width+ 1)*5/6;
4103 printable_length= (init->page_height + 1)*5/6;
4104
4105 stp_dprintf(STP_DBG_CANON, v, "Tray B/C/D modified printable_width: '%d'\n",printable_width);
4106 stp_dprintf(STP_DBG_CANON, v, "Tray B/C/D modified printable_length: '%d'\n",printable_length);
4107
4108 }
4109
4110 /* Tray E */
4111 if ( (print_cd) && !(strcmp(init->caps->name,"PIXMA Pro9000")) && (test_cd==1) ) {
4112
4113 init->page_width +=127;
4114 init->page_height +=186;
4115
4116 stp_dprintf(STP_DBG_CANON, v, "Tray E modified init->page_width: '%d'\n",init->page_width);
4117 stp_dprintf(STP_DBG_CANON, v, "Tray E modified init->page_height: '%d'\n",init->page_height);
4118
4119 printable_width= (init->page_width+ 1)*5/6;
4120 printable_length= (init->page_height + 1)*5/6;
4121
4122 stp_dprintf(STP_DBG_CANON, v, "Tray E modified printable_width: '%d'\n",printable_width);
4123 stp_dprintf(STP_DBG_CANON, v, "Tray E modified printable_length: '%d'\n",printable_length);
4124
4125 }
4126
4127 /* Tray F */
4128 if ( (print_cd) && !(strcmp(init->caps->name,"PIXMA iP4500")) && (test_cd==1) ) {
4129 stp_dprintf(STP_DBG_CANON, v,"DEBUG: Gutenprint: Tray F init->page_width: '%d'\n",init->page_width);
4130 stp_dprintf(STP_DBG_CANON, v,"DEBUG: Gutenprint: Tray F init->page_height: '%d'\n",init->page_height);
4131
4132 stp_dprintf(STP_DBG_CANON, v, "Tray F init->page_width: '%d'\n",init->page_width);
4133 stp_dprintf(STP_DBG_CANON, v, "Tray F init->page_height: '%d'\n",init->page_height);
4134 stp_dprintf(STP_DBG_CANON, v, "Tray F initial printable_width: '%d'\n",printable_width);
4135 stp_dprintf(STP_DBG_CANON, v, "Tray F initial printable_length: '%d'\n",printable_length);
4136
4137 init->page_width +=10;
4138 init->page_height +=95;
4139
4140 stp_dprintf(STP_DBG_CANON, v, "Tray F modified init->page_width: '%d'\n",init->page_width);
4141 stp_dprintf(STP_DBG_CANON, v, "Tray F modified init->page_height: '%d'\n",init->page_height);
4142
4143 printable_width= (init->page_width+ 1)*5/6;
4144 printable_length= (init->page_height + 1)*5/6;
4145
4146 stp_dprintf(STP_DBG_CANON, v, "Tray F modified printable_width: '%d'\n",printable_width);
4147 stp_dprintf(STP_DBG_CANON, v, "Tray F modified printable_length: '%d'\n",printable_length);
4148
4149 stp_dprintf(STP_DBG_CANON, v,"DEBUG: Gutenprint: Tray F modified printable_width: '%d'\n",printable_width);
4150 stp_dprintf(STP_DBG_CANON, v,"DEBUG: Gutenprint: Tray F modified printable_length: '%d'\n",printable_length);
4151 }
4152
4153 /* Tray G */
4154 if ( (print_cd) && !(strcmp(init->caps->name,"PIXMA iP4700")) && (test_cd==1) ) {
4155
4156 init->page_width +=10;
4157 init->page_height +=127;
4158
4159 stp_dprintf(STP_DBG_CANON, v, "Tray G modified init->page_width: '%d'\n",init->page_width);
4160 stp_dprintf(STP_DBG_CANON, v, "Tray G modified init->page_height: '%d'\n",init->page_height);
4161
4162 printable_width= (init->page_width+ 1)*5/6;
4163 printable_length= (init->page_height + 1)*5/6;
4164
4165 stp_dprintf(STP_DBG_CANON, v, "Tray G modified printable_width: '%d'\n",printable_width);
4166 stp_dprintf(STP_DBG_CANON, v, "Tray G modified printable_length: '%d'\n",printable_length);
4167
4168 }
4169
4170 /* Tray H */
4171 if ( (print_cd) && !(strcmp(init->caps->name,"PIXMA PRO-1")) && (test_cd==1) ) {
4172
4173 init->page_width +=68;
4174 init->page_height +=481;
4175
4176 stp_dprintf(STP_DBG_CANON, v, "Tray H modified init->page_width: '%d'\n",init->page_width);
4177 stp_dprintf(STP_DBG_CANON, v, "Tray H modified init->page_height: '%d'\n",init->page_height);
4178
4179 printable_width= (init->page_width+ 1)*5/6;
4180 printable_length= (init->page_height + 1)*5/6;
4181
4182 stp_dprintf(STP_DBG_CANON, v, "Tray H modified printable_width: '%d'\n",printable_width);
4183 stp_dprintf(STP_DBG_CANON, v, "Tray H modified printable_length: '%d'\n",printable_length);
4184
4185 }
4186
4187 /* Tray J */
4188 if ( (print_cd) && !(strcmp(init->caps->name,"PIXMA iP7200")) && (test_cd==1) ) {
4189
4190 init->page_width +=8;
4191 init->page_height +=44;
4192
4193 stp_dprintf(STP_DBG_CANON, v, "Tray J modified init->page_width: '%d'\n",init->page_width);
4194 stp_dprintf(STP_DBG_CANON, v, "Tray J modified init->page_height: '%d'\n",init->page_height);
4195
4196 printable_width= (init->page_width+ 1)*5/6;
4197 printable_length= (init->page_height + 1)*5/6;
4198
4199 stp_dprintf(STP_DBG_CANON, v, "Tray J modified printable_width: '%d'\n",printable_width);
4200 stp_dprintf(STP_DBG_CANON, v, "Tray J modified printable_length: '%d'\n",printable_length);
4201
4202 }
4203
4204 /* Tray L */
4205 if ( (print_cd) && !(strcmp(init->caps->name,"PIXMA iP8700")) && (test_cd==1) ) {
4206
4207 init->page_width +=10;
4208 init->page_height +=263;
4209
4210 stp_dprintf(STP_DBG_CANON, v, "Tray L modified init->page_width: '%d'\n",init->page_width);
4211 stp_dprintf(STP_DBG_CANON, v, "Tray L modified init->page_height: '%d'\n",init->page_height);
4212
4213 printable_width= (init->page_width+ 1)*5/6;
4214 printable_length= (init->page_height + 1)*5/6;
4215
4216 stp_dprintf(STP_DBG_CANON, v, "Tray L modified printable_width: '%d'\n",printable_width);
4217 stp_dprintf(STP_DBG_CANON, v, "Tray L modified printable_length: '%d'\n",printable_length);
4218
4219 }
4220
4221 /* Tray M - TODO */
4222 /* to add code here */
4223
4224 if ( (init->caps->features & CANON_CAP_BORDERLESS) &&
4225 !(print_cd) && stp_get_boolean_parameter(v, "FullBleed") )
4226 {
4227 stp_dprintf(STP_DBG_CANON, v,"canon_init_setPageMargins2: for borderless set printable length and width to 0\n");
4228 /* set to 0 for borderless */
4229 printable_width = 0;
4230 printable_length = 0;
4231 }
4232
4233 /* arguments for short form of Esc (p command */
4234 arg_70_1= (printable_length >> 8) & 0xff;
4235 arg_70_2= (printable_length) & 0xff;
4236 arg_70_3= (printable_width >> 8) & 0xff;
4237 arg_70_4= (printable_width) & 0xff;
4238
4239
4240 if (!(init->caps->features & CANON_CAP_px) && !(init->caps->features & CANON_CAP_p))
4241 return;
4242
4243 if ((init->caps->features & CANON_CAP_px) ) {
4244 /* workaround for CD writing that uses CANON_CAP_px --- fix with capabilities */
4245 if ( !( input_slot && !(strcmp(input_slot,"CD")) ) || !(strcmp(init->caps->name,"PIXMA iP4500")) || !(strcmp(init->caps->name,"PIXMA iP4600")) || !(strcmp(init->caps->name,"PIXMA iP4700")) || !(strcmp(init->caps->name,"PIXMA iP4800")) || !(strcmp(init->caps->name,"PIXMA iP4900")) || !(strcmp(init->caps->name,"PIXMA iP7200")) || !(strcmp(init->caps->name,"PIXMA MP980")) || !(strcmp(init->caps->name,"PIXMA MP990")) || !(strcmp(init->caps->name,"PIXMA MG5200")) || !(strcmp(init->caps->name,"PIXMA MG5300")) || !(strcmp(init->caps->name,"PIXMA MG6100")) || !(strcmp(init->caps->name,"PIXMA MG6200")) || !(strcmp(init->caps->name,"PIXMA MG6500")) || !(strcmp(init->caps->name,"PIXMA MG6700")) || !(strcmp(init->caps->name,"PIXMA MG7500")) || !(strcmp(init->caps->name,"PIXMA MG7700")) || !(strcmp(init->caps->name,"PIXMA MG8100")) || !(strcmp(init->caps->name,"PIXMA MG8200")) || !(strcmp(init->caps->name,"PIXMA iP9910")) || !(strcmp(init->caps->name,"PIXMA MP710")) || !(strcmp(init->caps->name,"PIXMA iP3000")) || !(strcmp(init->caps->name,"PIXMA Pro9000")) || !(strcmp(init->caps->name,"PIXMA iP8700")) || !(strcmp(init->caps->name,"PIXMA iX6800")) || !(strcmp(init->caps->name,"PIXMA TS8000")) )
4246 /* need to check if iP9910, MP710, iP3000, Pro9000 use Esc (p */
4247 {
4248
4249 /* original borders */
4250 border_left=init->caps->border_left;
4251 border_right=init->caps->border_right;
4252 border_top=init->caps->border_top;
4253 border_bottom=init->caps->border_bottom;
4254
4255 if (print_cd) {
4256 border_top=9;
4257 border_bottom=15; /* was 9 originally */
4258 }
4259
4260 /* modified borders */
4261 border_left2=border_left;
4262 border_top2=border_top;
4263 border_right2=border_right;
4264 border_bottom2=border_bottom;
4265
4266 if ( (print_cd) && !(strcmp(init->caps->name,"PIXMA MP710")) && (test_cd==1) ) {
4267 border_left2 = border_left + adjust_tray_custom_left;
4268 border_right2 = border_right + adjust_tray_custom_right;
4269 border_top2 = border_top + adjust_tray_custom_top;
4270 border_bottom2 = border_bottom + adjust_tray_custom_bottom;
4271 }
4272
4273 if ( (print_cd) && !(strcmp(init->caps->name,"PIXMA iP9910")) && (test_cd==1) ) {
4274 border_left2 = border_left + adjust_tray_A_left;
4275 border_right2 = border_right + adjust_tray_A_right;
4276 border_top2 = border_top + adjust_tray_A_top;
4277 border_bottom2 = border_bottom + adjust_tray_A_bottom;
4278 }
4279
4280 if ( (print_cd) && !(strcmp(init->caps->name,"PIXMA iP3000")) && (test_cd==1) ) {
4281 border_left2 = border_left + adjust_tray_BCD_left;
4282 border_right2 = border_right + adjust_tray_BCD_right;
4283 border_top2 = border_top + adjust_tray_BCD_top;
4284 border_bottom2 = border_bottom + adjust_tray_BCD_bottom;
4285 }
4286
4287 if ( (print_cd) && !(strcmp(init->caps->name,"PIXMA Pro9000")) && (test_cd==1) ) {
4288 border_left2 = border_left + adjust_tray_E_left;
4289 border_right2 = border_right + adjust_tray_E_right;
4290 border_top2 = border_top + adjust_tray_E_top;
4291 border_bottom2 = border_bottom + adjust_tray_E_bottom;
4292 }
4293
4294 if ( (print_cd) && !(strcmp(init->caps->name,"PIXMA iP4500")) && (test_cd==1) ) {
4295 border_left2 = border_left + adjust_tray_F_left;
4296 border_right2 = border_right + adjust_tray_F_right;
4297 border_top2 = border_top + adjust_tray_F_top;
4298 border_bottom2 = border_bottom + adjust_tray_F_bottom;
4299 }
4300
4301 if ( (print_cd) && !(strcmp(init->caps->name,"PIXMA iP4700")) && (test_cd==1) ) {
4302 border_left2 = border_left + adjust_tray_G_left;
4303 border_right2 = border_right + adjust_tray_G_right;
4304 border_top2 = border_top + adjust_tray_G_top;
4305 border_bottom2 = border_bottom + adjust_tray_G_bottom;
4306 }
4307
4308 if ( (print_cd) && !(strcmp(init->caps->name,"PIXMA PRO-1")) && (test_cd==1) ) {
4309 border_left2 = border_left + adjust_tray_H_left;
4310 border_right2 = border_right + adjust_tray_H_right;
4311 border_top2 = border_top + adjust_tray_H_top;
4312 border_bottom2 = border_bottom + adjust_tray_H_bottom;
4313 }
4314
4315 if ( (print_cd) && !(strcmp(init->caps->name,"PIXMA iP7200")) && (test_cd==1) ) {
4316 border_left2 = border_left + adjust_tray_J_left;
4317 border_right2 = border_right + adjust_tray_J_right;
4318 border_top2 = border_top + adjust_tray_J_top;
4319 border_bottom2 = border_bottom + adjust_tray_J_bottom;
4320 }
4321
4322 if ( (print_cd) && !(strcmp(init->caps->name,"PIXMA iP8700")) && (test_cd==1) ) {
4323 border_left2 = border_left + adjust_tray_L_left;
4324 border_right2 = border_right + adjust_tray_L_right;
4325 border_top2 = border_top + adjust_tray_L_top;
4326 border_bottom2 = border_bottom + adjust_tray_L_bottom;
4327 }
4328
4329 /* this does not seem to need adjustment, so use original borders */
4330 area_right = border_left * unit / 72;
4331 area_top = border_top * unit / 72;
4332
4333 if ( (init->caps->features & CANON_CAP_BORDERLESS) &&
4334 !(print_cd) && stp_get_boolean_parameter(v, "FullBleed") ) {
4335 border_left2=-8; /* -8 mini series -6 */
4336 border_right2=-8; /* -8 */
4337 border_top2=-6; /* -6 standard */
4338 border_bottom2=-15; /* -15 standard */
4339 area_right = border_left2 * unit / 72;
4340 area_top = border_top2 * unit / 72;
4341 }
4342
4343 stp_dprintf(STP_DBG_CANON, v,"setPageMargins2: init->page_height = %d\n",init->page_height);
4344 stp_dprintf(STP_DBG_CANON, v,"setPageMargins2: printable_length = %d\n",printable_length);
4345 stp_dprintf(STP_DBG_CANON, v,"setPageMargins2: paper_height = %d\n",(init->page_height + border_top + border_bottom) * unit / 72);
4346
4347
4348 stp_dprintf(STP_DBG_CANON, v, "final init->page_width: '%d'\n",init->page_width);
4349 stp_dprintf(STP_DBG_CANON, v, "final init->page_height: '%d'\n",init->page_height);
4350 stp_dprintf(STP_DBG_CANON, v, "final printable_width: '%d'\n",printable_width);
4351 stp_dprintf(STP_DBG_CANON, v, "final printable_length: '%d'\n",printable_length);
4352
4353 stp_zfwrite(ESC28,2,1,v); /* ESC( */
4354 stp_putc(0x70,v); /* p */
4355 stp_put16_le(46, v); /* len */
4356 /* 0 for borderless, calculated otherwise */
4357 stp_put16_be(printable_length,v); /* printable_length */
4358 stp_put16_be(0,v);
4359 /* 0 for borderless, calculated otherwise */
4360 stp_put16_be(printable_width,v); /* printable_width */
4361 stp_put16_be(0,v);
4362 stp_put32_be(0,v);
4363 stp_put16_be(unit,v);
4364
4365 /* depends on borderless or not: uses modified borders */
4366 stp_put32_be(area_right,v); /* area_right : Windows seems to use 9.6, gutenprint uses 10 */
4367 stp_put32_be(area_top,v); /* area_top : Windows seems to use 8.4, gutenprint uses 15 */
4368
4369 /* calculated depending on borderless or not: uses modified borders */
4370 if ( (init->caps->features & CANON_CAP_BORDERLESS) &&
4371 !(print_cd) && stp_get_boolean_parameter(v, "FullBleed") ) {
4372 /* borderless */
4373 stp_put32_be((init->page_width - border_left2 - border_right2 ) * unit / 72,v); /* area_width */
4374 stp_put32_be((init->page_height - border_top2 - border_bottom2 ) * unit / 72,v); /* area_length */
4375 }
4376 else {
4377 if ( (print_cd) && (test_cd==1) ) { /* bordered for CD */
4378 stp_put32_be(init->page_width * unit / 72,v); /* area_width */
4379 stp_put32_be(init->page_height * unit / 72,v); /* area_length */
4380 }
4381 else { /* bordered non CD media */
4382 stp_put32_be((init->page_width) * unit / 72,v); /* area_width */
4383 stp_put32_be((init->page_height) * unit / 72,v); /* area_length */
4384 }
4385 }
4386
4387 /* 0 under all currently known circumstances */
4388 stp_put32_be(0,v); /* paper_right : Windows also 0 here for all Trays */
4389 stp_put32_be(0,v); /* paper_top : Windows also 0 here for all Trays */
4390
4391 /* standard paper sizes, unchanged for borderless so use
4392 original borders */
4393
4394 /* discovered that paper_width needs to be same as Windows
4395 dimensions for Canon printer firmware to automatically
4396 determine which tray to pull paper from automatically.
4397 */
4398
4399 if ( (init->caps->features & CANON_CAP_BORDERLESS) &&
4400 !(print_cd) && stp_get_boolean_parameter(v, "FullBleed") ) {
4401 /* borderless */
4402 stp_put32_be((init->page_width) * unit / 72,v); /* paper_width */
4403 stp_put32_be((init->page_height) * unit / 72,v); /* paper_length */
4404 }
4405 else {
4406 if ( (print_cd) && (test_cd==1) ) { /* bordered for CD */
4407 paper_width = (init->page_width + border_left2 + border_right2) * unit / 72; /* paper_width */
4408 paper_length = (init->page_height + border_top2 + border_bottom2) * unit / 72; /* paper_length */
4409 fix_papersize(arg_ESCP_1, &paper_width, &paper_length);
4410 stp_put32_be(paper_width,v); /* paper_width */
4411 stp_put32_be(paper_length,v); /* paper_length */
4412 }
4413 else { /* bordered non CD media */
4414 /* set by calculation first, then correct if necessary */
4415 paper_width = (init->page_width + border_left + border_right) * unit / 72; /* paper_width */
4416 paper_length = (init->page_height + border_top + border_bottom) * unit / 72; /* paper_length */
4417 fix_papersize(arg_ESCP_1, &paper_width, &paper_length);
4418 stp_put32_be(paper_width,v); /* paper_width */
4419 stp_put32_be(paper_length,v); /* paper_length */
4420 }
4421 }
4422
4423 return;
4424 }
4425 }
4426 canon_cmd(v,ESC28,0x70, 8,
4427 arg_70_1, arg_70_2, 0x00, 0x00,
4428 arg_70_3, arg_70_4, 0x00, 0x00);
4429 }
4430
4431 /* ESC (P -- 0x50 -- unknown -- :
4432 Seems to set media and page information. Different byte lengths
4433 depending on printer model.
4434 Page rotation option in driver [ESC (v] influences ESC (P command
4435 parameters 5 and 6:
4436 none: 1 0
4437 90 deg: 2 0
4438 180 deg: 1 1
4439 270 deg: 2 1
4440 */
4441 static void
canon_init_setESC_P(const stp_vars_t * v,const canon_privdata_t * init)4442 canon_init_setESC_P(const stp_vars_t *v, const canon_privdata_t *init)
4443 {
4444 unsigned char arg_ESCP_1, arg_ESCP_2, arg_ESCP_5, arg_ESCP_6, arg_ESCP_7, arg_ESCP_9;
4445
4446 stp_dimension_t width, length;
4447 /* const char *media_size = stp_get_string_parameter(v, "PageSize");
4448 const stp_papersize_t *pt = NULL; */
4449 const char* orientation_type = stp_get_string_parameter(v, "Orientation");
4450 const char* input_slot = stp_get_string_parameter(v, "InputSlot");
4451 const char* input_tray = stp_get_string_parameter(v, "CassetteTray");
4452 /* const canon_cap_t * caps= canon_get_model_capabilities(v); */
4453 int print_cd = (input_slot && (!strcmp(input_slot, "CD")));
4454 int tray_upper = (input_tray && (!strcmp(input_tray, "Upper")));
4455 int tray_lower = (input_tray && (!strcmp(input_tray, "Lower")));
4456 int tray_user_select;
4457 unsigned char user_ESCP_9;
4458
4459 if(!(init->caps->features & CANON_CAP_P))
4460 return;
4461
4462 /* if (media_size)
4463 pt = stp_describe_papersize(v, media_size); */
4464 stp_default_media_size(v, &width, &length);
4465 if (tray_upper || tray_lower)
4466 tray_user_select=1;
4467 else
4468 tray_user_select=0;
4469 if (tray_upper)
4470 user_ESCP_9=0x01;
4471 else if (tray_lower)
4472 user_ESCP_9=0x02;
4473 else
4474 user_ESCP_9=0x00; /* fall-through setting, but this value is not used */
4475
4476 arg_ESCP_1 = (init->pt) ? canon_size_type(v,init->caps): 0x03; /* media size: set to A4 size as default */
4477 stp_dprintf(STP_DBG_CANON, v,"canon: ESCP (P code read paper size, resulting arg_ESCP_1: '%x'\n",arg_ESCP_1);
4478 arg_ESCP_2 = (init->pt) ? init->pt->media_code_P: 0x00; /* media type: set to plain as default */
4479 arg_ESCP_5 = 0x01; /* default for portrait orientation */
4480 arg_ESCP_6 = 0x00; /* default for portrait orientation */
4481
4482 arg_ESCP_7 = 0x01; /* default - use unknown, with some printers set
4483 to 0x00 for envelope sizes (and other?)
4484 regardless of media type */
4485
4486 if( orientation_type && !strcmp(orientation_type,"Portrait")) { /* none */
4487 arg_ESCP_5 = 0x01;
4488 arg_ESCP_6 = 0x00;
4489 }
4490 else if( orientation_type && !strcmp(orientation_type,"Landscape")) { /* 90 deg */
4491 arg_ESCP_5 = 0x02;
4492 arg_ESCP_6 = 0x00;
4493 }
4494 else if( orientation_type && !strcmp(orientation_type,"UpsideDown")) { /* 180 deg */
4495 arg_ESCP_5 = 0x01;
4496 arg_ESCP_6 = 0x01;
4497 }
4498 else if( orientation_type && !strcmp(orientation_type,"Seascape")) { /* 270 deg */
4499 arg_ESCP_5 = 0x02;
4500 arg_ESCP_6 = 0x01;
4501 }
4502
4503
4504 /* Code for last argument in 9-byte ESC (P printers with and upper and lower tray included in the cassette input source
4505 The intention appears to be to allow printing of photos and non-photo paper without needing to change trays.
4506 Note, envelopes are printed from the lower tray.
4507
4508 Upper tray specification from MG7700 user manual:
4509 Min width: 3.5 inches / 89.0 mm (L size)
4510 Min height: 5 inches / 127.0 mm (L size)
4511 Max width: 7.87 inches / 200.0 mm (marked up to 5 inches)
4512 Max height: 7.28 inches / 184.9 mm
4513
4514 Lower tray specification:
4515 Min width: 3.54 inches / 90.0 mm (takes business envelopes)
4516 Min height: 7.29 inches / 185.0 mm
4517 Max width: 8.5 inches / 215.9 mm
4518 Max height: 14 inches / 355.6 mm
4519
4520 Conditions:
4521 Init: Upper tray
4522 Media:
4523 Hagaki, Photo media --> upper tray
4524 Envelopes (argESCP_2 == 0x08) --> lower tray
4525 Other --> lower tray
4526 Size: Length:
4527 < 7.29 inches (524 pt = 184.85 mm; 525 pt = 185.2 mm ) --> upper tray
4528 >=7.29 inches (524 pt = 184.85 mm; 525 pt = 185.2 mm ) --> lower tray
4529
4530 Printers with this capability:
4531 Code 0xd for cassette (standard cassette code is 0x8)
4532
4533 MG5400
4534 MG6300
4535 MG6500
4536 MG6700
4537 MG6900 - same as MG7700
4538 MG7500
4539 MG7700
4540 iP7200
4541 MX720
4542 MX920
4543 */
4544
4545
4546 if ( !(strcmp(init->caps->name,"PIXMA iP7200")) || !(strcmp(init->caps->name,"PIXMA MG5400")) || !(strcmp(init->caps->name,"PIXMA MG6300")) || !(strcmp(init->caps->name,"PIXMA MG6500")) || !(strcmp(init->caps->name,"PIXMA MG6700")) || !(strcmp(init->caps->name,"PIXMA MG7500")) || !(strcmp(init->caps->name,"PIXMA MG7700")) || !(strcmp(init->caps->name,"PIXMA MX720")) || !(strcmp(init->caps->name,"PIXMA MX920")) ) {
4547 /* default: use upper tray of cassette with two trays, condition check later */
4548 arg_ESCP_9 = 0x01;
4549 }
4550 else if ( !(strcmp(init->caps->name,"PIXMA E400")) || !(strcmp(init->caps->name,"PIXMA E460")) || !(strcmp(init->caps->name,"PIXMA E470")) || !(strcmp(init->caps->name,"PIXMA E480")) || !(strcmp(init->caps->name,"PIXMA E560")) || !(strcmp(init->caps->name,"PIXMA E3100")) || !(strcmp(init->caps->name,"PIXMA TS5000")) || !(strcmp(init->caps->name,"PIXMA TS6000")) || !(strcmp(init->caps->name,"PIXMA TS8000")) || !(strcmp(init->caps->name,"PIXMA G1000")) || !(strcmp(init->caps->name,"PIXMA G4000")) || !(strcmp(init->caps->name,"PIXMA MG2900")) || !(strcmp(init->caps->name,"PIXMA MG3500")) || !(strcmp(init->caps->name,"PIXMA MG3600")) || !(strcmp(init->caps->name,"PIXMA MG5500")) || !(strcmp(init->caps->name,"PIXMA MG5600")) || !(strcmp(init->caps->name,"PIXMA iP110")) || !(strcmp(init->caps->name,"PIXMA iP2800")) || !(strcmp(init->caps->name,"PIXMA iP8700")) || !(strcmp(init->caps->name,"PIXMA iX6800")) || !(strcmp(init->caps->name,"MAXIFY iB4000")) || !(strcmp(init->caps->name,"MAXIFY iB4100")) || !(strcmp(init->caps->name,"MAXIFY MB2000")) || !(strcmp(init->caps->name,"MAXIFY MB2100")) || !(strcmp(init->caps->name,"MAXIFY MB2300")) || !(strcmp(init->caps->name,"MAXIFY MB2700")) || !(strcmp(init->caps->name,"PIXMA MX470")) || !(strcmp(init->caps->name,"PIXMA MX490")) ) {
4551 arg_ESCP_9 = 0xff;
4552 }
4553
4554 else {
4555 arg_ESCP_9 = 0x00;
4556 }
4557
4558 if ( !(strcmp(init->caps->name,"PIXMA E470")) || !(strcmp(init->caps->name,"PIXMA G4000")) || !(strcmp(init->caps->name,"PIXMA TS5000")) || !(strcmp(init->caps->name,"PIXMA TS6000")) || !(strcmp(init->caps->name,"PIXMA TS8000")) ){
4559 /* all envelope sizes it appears, even if media is not Envelope */
4560 /* currently not sure about custom sizes, thus only specify here the known Canon envelope sizes */
4561 switch(arg_ESCP_2)
4562 {
4563 case 0x2e: arg_ESCP_7=0x00; break;; /* US Comm #10 */
4564 case 0x2f: arg_ESCP_7=0x00; break;; /* Euro DL Env */
4565 case 0x30: arg_ESCP_7=0x00; break;; /* Western Env #4 (you4) */
4566 case 0x31: arg_ESCP_7=0x00; break;; /* Western Env #6 (you6) */
4567 case 0x3a: arg_ESCP_7=0x00; break;; /* Japanese Long Env #3 (chou3) */
4568 case 0x3b: arg_ESCP_7=0x00; break;; /* Japanese Long Env #4 (chou4) */
4569 /* new envelopes for some printers added for completeness */
4570 case 0x92: arg_ESCP_7=0x00; break;; /* C5 */
4571 case 0x93: arg_ESCP_7=0x00; break;; /* Monarch */
4572 }
4573 }
4574
4575 /* workaround for CD media */
4576
4577 if ( (arg_ESCP_2 == 0x1f) || ( arg_ESCP_2 == 0x20) ) {
4578 if ( arg_ESCP_1 == 0x53 ) {
4579 /* Tray G as default */
4580 arg_ESCP_1 = 0x53;
4581 /* Custom CD tray */
4582 if ( !(strcmp(init->caps->name,"i865")) || !(strcmp(init->caps->name,"PIXMA MP710")) || !(strcmp(init->caps->name,"PIXMA MP740")) || !(strcmp(init->caps->name,"PIXMA MP900")) ) {
4583 arg_ESCP_1 = 0x35;
4584 }
4585 /* Tray A */
4586 if ( !(strcmp(init->caps->name,"PIXMA iP9910")) ) {
4587 arg_ESCP_1 = 0x3f;
4588 }
4589 /* Tray B */
4590 if ( !(strcmp(init->caps->name,"PIXMA MP750")) || !(strcmp(init->caps->name,"PIXMA MP760")) || !(strcmp(init->caps->name,"PIXMA MP770")) || !(strcmp(init->caps->name,"PIXMA MP780")) || !(strcmp(init->caps->name,"PIXMA MP790")) || !(strcmp(init->caps->name,"PIXMA iP3000")) || !(strcmp(init->caps->name,"PIXMA iP3100")) || !(strcmp(init->caps->name,"PIXMA iP4000")) || !(strcmp(init->caps->name,"PIXMA iP4100")) || !(strcmp(init->caps->name,"PIXMA iP5000")) || !(strcmp(init->caps->name,"PIXMA iP6000")) || !(strcmp(init->caps->name,"PIXMA iP6100")) || !(strcmp(init->caps->name,"PIXMA iP7100")) || !(strcmp(init->caps->name,"PIXMA iP8100")) || !(strcmp(init->caps->name,"PIXMA iP8500")) || !(strcmp(init->caps->name,"PIXMA iP8600")) ) {
4591 arg_ESCP_1 = 0x40;
4592 }
4593 /* Tray C */
4594 if ( !(strcmp(init->caps->name,"PIXMA MP950")) || !(strcmp(init->caps->name,"PIXMA iP4200")) || !(strcmp(init->caps->name,"PIXMA iP5200")) || !(strcmp(init->caps->name,"PIXMA iP6700")) || !(strcmp(init->caps->name,"PIXMA iP7500")) ) {
4595 arg_ESCP_1 = 0x4a;
4596 }
4597 /* Tray D */
4598 if ( !(strcmp(init->caps->name,"PIXMA MP500")) || !(strcmp(init->caps->name,"PIXMA MP530")) || !(strcmp(init->caps->name,"PIXMA MP800")) || !(strcmp(init->caps->name,"PIXMA MP830")) ) {
4599 arg_ESCP_1 = 0x4b;
4600 }
4601 /* Tray E */
4602 if ( !(strcmp(init->caps->name,"PIXMA Pro9000")) || !(strcmp(init->caps->name,"PIXMA Pro9002")) || !(strcmp(init->caps->name,"PIXMA Pro9500")) || !(strcmp(init->caps->name,"PIXMA Pro95002")) ) {
4603 arg_ESCP_1 = 0x4c;
4604 }
4605 /* Tray F */
4606 if ( !(strcmp(init->caps->name,"PIXMA MP600")) || !(strcmp(init->caps->name,"PIXMA MP610")) || !(strcmp(init->caps->name,"PIXMA MP810")) || !(strcmp(init->caps->name,"PIXMA MP960")) || !(strcmp(init->caps->name,"PIXMA MP970")) || !(strcmp(init->caps->name,"PIXMA MX850")) || !(strcmp(init->caps->name,"PIXMA iP4300")) || !(strcmp(init->caps->name,"PIXMA iP4500")) || !(strcmp(init->caps->name,"PIXMA iP5300")) ) {
4607 arg_ESCP_1 = 0x51;
4608 }
4609 /* Tray G from iP4600 onwards */
4610 if ( !(strcmp(init->caps->name,"PIXMA iP4600")) || !(strcmp(init->caps->name,"PIXMA iP4700")) || !(strcmp(init->caps->name,"PIXMA iP4800")) || !(strcmp(init->caps->name,"PIXMA iP4900")) || !(strcmp(init->caps->name,"PIXMA MG5200")) || !(strcmp(init->caps->name,"PIXMA MG5300")) || !(strcmp(init->caps->name,"PIXMA MG6100")) || !(strcmp(init->caps->name,"PIXMA MG6200")) || !(strcmp(init->caps->name,"PIXMA MG8100")) || !(strcmp(init->caps->name,"PIXMA MG8200")) ) {
4611 arg_ESCP_1 = 0x56;
4612 }
4613 /* Tray J from iP7200 onwards */
4614 if ( !(strcmp(init->caps->name,"PIXMA iP7200")) || !(strcmp(init->caps->name,"PIXMA MG5400")) || !(strcmp(init->caps->name,"PIXMA MG6300")) || !(strcmp(init->caps->name,"PIXMA MG6500")) || !(strcmp(init->caps->name,"PIXMA MG6700")) || !(strcmp(init->caps->name,"PIXMA MG7500")) || !(strcmp(init->caps->name,"PIXMA MG7700")) || !(strcmp(init->caps->name,"PIXMA MX920")) ) {
4615 arg_ESCP_1 = 0x5b;
4616 arg_ESCP_9 = 0x00;
4617 }
4618 /* Tray L from iP8700 onwards */
4619 if ( !(strcmp(init->caps->name,"PIXMA iP8700")) ) {
4620 arg_ESCP_1 = 0x62;
4621 }
4622 /* Tray M from TS8000 onwards */
4623 if ( !(strcmp(init->caps->name,"PIXMA TS8000")) ) {
4624 arg_ESCP_1 = 0xbc;
4625 }
4626
4627 }
4628 }
4629 /* 850i: CD Tray custom: none --- no ESC (P */
4630 /* 865i: CD Tray custom: 0x35 */
4631 /* MP500: CD Tray D : 0x4b */
4632 /* MP530: CD Tray D : 0x4b */
4633 /* MP600: CD Tray F : 0x51 */
4634 /* MP610: CD Tray F : 0x51 */
4635 /* MP630: CD Tray G : 0x53 */
4636 /* MP640: CD Tray G : 0x53 */
4637 /* MP700: CD tray custom: none --- no ESC (P */
4638 /* MP710: CD tray custom: 0x35 */
4639 /* MP730: CD tray custom: none --- no ESC (P */
4640 /* MP740: CD tray custom: 0x35 */
4641 /* MP750: CD Tray B : 0x40 */
4642 /* MP760: CD Tray B : 0x40 */
4643 /* MP770: CD Tray B : 0x40 */
4644 /* MP780: CD Tray B : 0x40 */
4645 /* MP790: CD Tray B : 0x40 */
4646 /* MP800: CD Tray D : 0x4b */
4647 /* MP810: CD Tray F : 0x51 */
4648 /* MP830: CD Tray D : 0x4b */
4649 /* MP900: CD Tray custom: 0x35 */
4650 /* MP950: CD Tray C : 0x4a */
4651 /* MP960: CD Tray F : 0x51 */
4652 /* MP970: CD Tray F : 0x51 */
4653 /* MP980: CD Tray G : 0x53 */
4654 /* MP990: CD Tray G : 0x53 */
4655 /* MX850: CD Tray F : 0x51 */
4656 /* MX920: CD Tray J : 0x5b */
4657 /* iP3000: CD Tray B : 0x40 */
4658 /* iP3100: CD Tray B : 0x40 */
4659 /* iP4000: CD Tray B : 0x40 */
4660 /* iP4100: CD Tray B : 0x40 */
4661 /* iP4200: CD Tray C : 0x4a */
4662 /* iP4300: CD Tray F : 0x51 */
4663 /* iP4500: CD Tray F : 0x51 */
4664 /* iP4600: CD Tray G : 0x53 */
4665 /* iP4700: CD Tray G : 0x53 */
4666 /* iP4800: CD Tray G : 0x56 */
4667 /* iP4900: CD Tray G : 0x56 */
4668 /* iP5000: CD Tray B : 0x40 */
4669 /* iP5200: CD Tray C : 0x4a */
4670 /* iP5300: CD Tray F : 0x51 */
4671 /* iP6000D:CD Tray B : 0x40 */
4672 /* iP6100D:CD Tray B : 0x40 */
4673 /* iP6700D:CD Tray C : 0x4a */
4674 /* iP7100: CD Tray B : 0x40 */
4675 /* iP7200: CD Tray J : 0x5b */
4676 /* iP7500: CD Tray C : 0x4a */
4677 /* iP8100: CD Tray B : 0x40 */
4678 /* iP8500 :CD Tray B : 0x40 */
4679 /* iP8600: CD Tray B : 0x40 */
4680 /* iP8700: CD Tray L : 0x62 */
4681 /* iP9910: CD Tray A : 0x3f */
4682 /* MG5200: CD Tray G : 0x56 */
4683 /* MG5300: CD Tray G : 0x56 */
4684 /* MG5400: CD Tray J : 0x5b */
4685 /* MG6100: CD Tray G : 0x56 */
4686 /* MG6200: CD Tray G : 0x56 */
4687 /* MG6300: CD Tray J : 0x5b */
4688 /* MG6500: CD Tray J : 0x5b */
4689 /* MG6700: CD Tray J : 0x5b */
4690 /* MG6900: CD Tray J : 0x5b */
4691 /* MG7500: CD Tray J : 0x5b */
4692 /* MG7700: CD Tray J : 0x5b */
4693 /* MG8100: CD Tray G : 0x56 */
4694 /* MG8200: CD Tray G : 0x56 */
4695 /* pro9000:CD Tray E : 0x4c */
4696 /* pro9000mk2:CD Tray E : 0x4c */
4697 /* pro9500:CD Tray E : 0x4c */
4698 /* pro9500mk2:CD Tray E : 0x4c */
4699 /* PRO-1: CD Tray H : 0x57 */
4700 /* TS8000: CD Tray M : 0xbc */
4701
4702 /* workaround for FineArt media having same size as non-FineArt media */
4703
4704 /* Fine Art paper codes */
4705 /* iP6700D, iP7100, iP7500, iP8100, iP8600, iP9910 */
4706 /* iX7000 */
4707 /* MG6100, M6200, MG8100, MG8200 */
4708 /* MX7600 */
4709 /* MP950, MP960, MP970, MP980, MP990 */
4710 /* if (!strcmp(name,"A4")) return 0x42; */ /* FineArt A4 35mm border --- iP7100: gap is 18 */
4711 /* if (!strcmp(name,"A3")) return 0x43; */ /* FineArt A3 35mm border */
4712 /* if (!strcmp(name,"A3plus")) return 0x44; */ /* FineArt A3plus 35mm border */
4713 /* if (!strcmp(name,"Letter")) return 0x45; */ /* FineArt Letter 35mm border */
4714
4715 /* Fine Art paper codes */
4716 /* Pro series (9000, 9000 Mk.2, 9500, 9500 Mk.2, PRO-1) */
4717 /* if (!strcmp(name,"A4")) return 0x4d; */ /* FineArt A4 35mm border */
4718 /* if (!strcmp(name,"A3")) return 0x4e; */ /* FineArt A3 35mm border */
4719 /* if (!strcmp(name,"A3plus")) return 0x50; */ /* FineArt A3plus 35mm border */
4720 /* if (!strcmp(name,"Letter")) return 0x4f; */ /* FineArt Letter 35mm border */
4721
4722 /* Fine Art paper codes */
4723 /* MG6300, MG6500, MG6700, MG7100, MG7500 */
4724 /* if (!strcmp(name,"A4")) return 0x58; */ /* FineArt A4 35mm border */
4725 /* if (!strcmp(name,"Letter")) return 0x5a; */ /* FineArt Letter 35mm border */
4726
4727 /* Fine Art paper codes */
4728 /* iP8700, iX6800 */
4729 /* if (!strcmp(name,"A4")) return 0x58; */ /* FineArt A4 35mm border */
4730 /* if (!strcmp(name,"A3")) return 0x59; */ /* FineArt A3 35mm border */
4731 /* if (!strcmp(name,"A3plus")) return 0x5d; */ /* FineArt A3plus 35mm border */
4732 /* if (!strcmp(name,"Letter")) return 0x5a; */ /* FineArt Letter 35mm border */
4733
4734
4735 /* iP7100 is an exception needing yet another papersize code */
4736 if ( (arg_ESCP_2 == 0x28) || ( arg_ESCP_2 == 0x29) || (arg_ESCP_2 == 0x2c) || (arg_ESCP_2 == 0x31) ) {
4737 /* A4 FineArt */
4738 if ( arg_ESCP_1 == 0x03 ) {
4739 if ( !(strcmp(init->caps->name,"PIXMA MP950")) || !(strcmp(init->caps->name,"PIXMA MP960")) || !(strcmp(init->caps->name,"PIXMA MP970")) || !(strcmp(init->caps->name,"PIXMA MP980")) || !(strcmp(init->caps->name,"PIXMA MP990")) || !(strcmp(init->caps->name,"PIXMA MX7600")) || !(strcmp(init->caps->name,"PIXMA iP6700")) || !(strcmp(init->caps->name,"PIXMA iP7100")) || !(strcmp(init->caps->name,"PIXMA iP7500")) || !(strcmp(init->caps->name,"PIXMA iP8100")) || !(strcmp(init->caps->name,"PIXMA iP8600")) || !(strcmp(init->caps->name,"PIXMA iP9910")) || !(strcmp(init->caps->name,"PIXMA iX7000")) || !(strcmp(init->caps->name,"PIXMA MG6100")) || !(strcmp(init->caps->name,"PIXMA MG6200")) || !(strcmp(init->caps->name,"PIXMA MG8200")) || !(strcmp(init->caps->name,"PIXMA MG8100")) || !(strcmp(init->caps->name,"PIXMA MG8200")) ) {
4740 arg_ESCP_1 = 0x42;
4741 }
4742 else if ( !(strcmp(init->caps->name,"PIXMA Pro9000")) || !(strcmp(init->caps->name,"PIXMA Pro9002")) || !(strcmp(init->caps->name,"PIXMA Pro9500")) || !(strcmp(init->caps->name,"PIXMA Pro9502")) ) {
4743 arg_ESCP_1 = 0x4d;
4744 }
4745 else if ( !(strcmp(init->caps->name,"PIXMA MG6300")) || !(strcmp(init->caps->name,"PIXMA MG6500")) || !(strcmp(init->caps->name,"PIXMA MG6700")) || !(strcmp(init->caps->name,"PIXMA MG7500")) || !(strcmp(init->caps->name,"PIXMA iP8700")) || !(strcmp(init->caps->name,"PIXMA iX6800")) || !(strcmp(init->caps->name,"PIXMA TS8000")) ) {
4746 arg_ESCP_1 = 0x58;
4747 }
4748 else {
4749 /* default back to non-FineArt */
4750 arg_ESCP_1 = 0x03;
4751 }
4752 }
4753 /* A3 FineArt */
4754 if ( arg_ESCP_1 == 0x05 ) {
4755 if ( !(strcmp(init->caps->name,"PIXMA MP950")) || !(strcmp(init->caps->name,"PIXMA MP960")) || !(strcmp(init->caps->name,"PIXMA MP970")) || !(strcmp(init->caps->name,"PIXMA MP980")) || !(strcmp(init->caps->name,"PIXMA MP990")) || !(strcmp(init->caps->name,"PIXMA MX7600")) || !(strcmp(init->caps->name,"PIXMA iP6700")) || !(strcmp(init->caps->name,"PIXMA iP7100")) || !(strcmp(init->caps->name,"PIXMA iP7500")) || !(strcmp(init->caps->name,"PIXMA iP8100")) || !(strcmp(init->caps->name,"PIXMA iP8600")) || !(strcmp(init->caps->name,"PIXMA iP9910")) || !(strcmp(init->caps->name,"PIXMA iX7000")) || !(strcmp(init->caps->name,"PIXMA MG6100")) || !(strcmp(init->caps->name,"PIXMA MG6200")) || !(strcmp(init->caps->name,"PIXMA MG8200")) || !(strcmp(init->caps->name,"PIXMA MG8100")) || !(strcmp(init->caps->name,"PIXMA MG8200")) ) {
4756 arg_ESCP_1 = 0x43;
4757 }
4758 else if ( !(strcmp(init->caps->name,"PIXMA Pro9000")) || !(strcmp(init->caps->name,"PIXMA Pro9002")) || !(strcmp(init->caps->name,"PIXMA Pro9500")) || !(strcmp(init->caps->name,"PIXMA Pro9502")) ) {
4759 arg_ESCP_1 = 0x4e;
4760 }
4761 #if 0
4762 /* no known papersize code yet, since these printers do not handle A3 */
4763 else if ( !(strcmp(init->caps->name,"PIXMA MG6300")) || !(strcmp(init->caps->name,"PIXMA MG6500")) || !(strcmp(init->caps->name,"PIXMA MG6700")) || !(strcmp(init->caps->name,"PIXMA MG7500")) || !(strcmp(init->caps->name,"PIXMA iP8700")) || !(strcmp(init->caps->name,"PIXMA iX6800")) ) {
4764 arg_ESCP_1 = 0x59;
4765 }
4766 #endif
4767 else {
4768 /* default back to non-FineArt */
4769 arg_ESCP_1 = 0x05;
4770 }
4771 }
4772 /* Letter FineArt */
4773 if ( arg_ESCP_1 == 0x0d ) {
4774 if ( !(strcmp(init->caps->name,"PIXMA MP950")) || !(strcmp(init->caps->name,"PIXMA MP960")) || !(strcmp(init->caps->name,"PIXMA MP970")) || !(strcmp(init->caps->name,"PIXMA MP980")) || !(strcmp(init->caps->name,"PIXMA MP990")) || !(strcmp(init->caps->name,"PIXMA MX7600")) || !(strcmp(init->caps->name,"PIXMA iP6700")) || !(strcmp(init->caps->name,"PIXMA iP7100")) || !(strcmp(init->caps->name,"PIXMA iP7500")) || !(strcmp(init->caps->name,"PIXMA iP8100")) || !(strcmp(init->caps->name,"PIXMA iP8600")) || !(strcmp(init->caps->name,"PIXMA iP9910")) || !(strcmp(init->caps->name,"PIXMA iX7000")) || !(strcmp(init->caps->name,"PIXMA MG6100")) || !(strcmp(init->caps->name,"PIXMA MG6200")) || !(strcmp(init->caps->name,"PIXMA MG8200")) || !(strcmp(init->caps->name,"PIXMA MG8100")) || !(strcmp(init->caps->name,"PIXMA MG8200")) ) {
4775 arg_ESCP_1 = 0x45;
4776 }
4777 else if ( !(strcmp(init->caps->name,"PIXMA Pro9000")) || !(strcmp(init->caps->name,"PIXMA Pro9002")) || !(strcmp(init->caps->name,"PIXMA Pro9500")) || !(strcmp(init->caps->name,"PIXMA Pro9502")) ) {
4778 arg_ESCP_1 = 0x4f;
4779 }
4780 else if ( !(strcmp(init->caps->name,"PIXMA MG6300")) || !(strcmp(init->caps->name,"PIXMA MG6500")) || !(strcmp(init->caps->name,"PIXMA MG6700")) || !(strcmp(init->caps->name,"PIXMA MG7500")) || !(strcmp(init->caps->name,"PIXMA iP8700")) || !(strcmp(init->caps->name,"PIXMA iX6800")) || !(strcmp(init->caps->name,"PIXMA TS8000")) ) {
4781 arg_ESCP_1 = 0x5a;
4782 }
4783 else {
4784 /* default back to non-FineArt */
4785 arg_ESCP_1 = 0x0d;
4786 }
4787 }
4788 /* A3plus FineArt */
4789 if ( arg_ESCP_1 == 0x2c ) {
4790 if ( !(strcmp(init->caps->name,"PIXMA MP950")) || !(strcmp(init->caps->name,"PIXMA MP960")) || !(strcmp(init->caps->name,"PIXMA MP970")) || !(strcmp(init->caps->name,"PIXMA MP980")) || !(strcmp(init->caps->name,"PIXMA MP990")) || !(strcmp(init->caps->name,"PIXMA MX7600")) || !(strcmp(init->caps->name,"PIXMA iP6700")) || !(strcmp(init->caps->name,"PIXMA iP7100")) || !(strcmp(init->caps->name,"PIXMA iP7500")) || !(strcmp(init->caps->name,"PIXMA iP8100")) || !(strcmp(init->caps->name,"PIXMA iP8600")) || !(strcmp(init->caps->name,"PIXMA iP9910")) || !(strcmp(init->caps->name,"PIXMA iX7000")) || !(strcmp(init->caps->name,"PIXMA MG6100")) || !(strcmp(init->caps->name,"PIXMA MG6200")) || !(strcmp(init->caps->name,"PIXMA MG8200")) || !(strcmp(init->caps->name,"PIXMA MG8100")) || !(strcmp(init->caps->name,"PIXMA MG8200")) ) {
4791 arg_ESCP_1 = 0x44;
4792 }
4793 else if ( !(strcmp(init->caps->name,"PIXMA Pro9000")) || !(strcmp(init->caps->name,"PIXMA Pro9002")) || !(strcmp(init->caps->name,"PIXMA Pro9500")) || !(strcmp(init->caps->name,"PIXMA Pro9502")) ) {
4794 arg_ESCP_1 = 0x50;
4795 }
4796 #if 0
4797 else if ( !(strcmp(init->caps->name,"PIXMA iP8700")) || !(strcmp(init->caps->name,"PIXMA iX6800")) ) {
4798 arg_ESCP_1 = 0x5d;
4799 }
4800 #endif
4801 else {
4802 /* default back to non-FineArt */
4803 arg_ESCP_1 = 0x2c;
4804 }
4805 }
4806 }
4807
4808 /* workaround for media type based differences in 9-parameter ESC (P commands */
4809 /* These printers use 0x02 (lower tray) usually and for envelopes, 0x01 (upper tray) with various Hagaki/Photo media, and 0x00 with CD media */
4810 if ( !(strcmp(init->caps->name,"PIXMA iP7200")) || !(strcmp(init->caps->name,"PIXMA MG5400")) || !(strcmp(init->caps->name,"PIXMA MG6300")) || !(strcmp(init->caps->name,"PIXMA MG6500")) || !(strcmp(init->caps->name,"PIXMA MG6700")) || !(strcmp(init->caps->name,"PIXMA MG7500")) || !(strcmp(init->caps->name,"PIXMA MG7700")) || !(strcmp(init->caps->name,"PIXMA MX720")) || !(strcmp(init->caps->name,"PIXMA MX920")) ) {
4811 if (tray_user_select && !print_cd)
4812 arg_ESCP_9=user_ESCP_9;
4813 else {
4814 switch(arg_ESCP_2)
4815 {
4816 /* Hagaki media */
4817 case 0x07: arg_ESCP_9=0x01; break;;
4818 case 0x14: arg_ESCP_9=0x01; break;; /* not used with any of these models */
4819 case 0x1b: arg_ESCP_9=0x01; break;;
4820 case 0x36: arg_ESCP_9=0x01; break;;
4821 case 0x38: arg_ESCP_9=0x01; break;;
4822 case 0x46: arg_ESCP_9=0x01; break;;
4823 case 0x47: arg_ESCP_9=0x01; break;;
4824 case 0x48: arg_ESCP_9=0x01; break;;
4825 /* Photo media here */
4826 case 0x32: arg_ESCP_9=0x01; break;;
4827 case 0x33: arg_ESCP_9=0x01; break;;
4828 case 0x3f: arg_ESCP_9=0x01; break;;
4829 case 0x2a: arg_ESCP_9=0x01; break;;
4830 case 0x16: arg_ESCP_9=0x01; break;;
4831 case 0x44: arg_ESCP_9=0x01; break;; /* MG6700, MG7500 only, instead of 0x16 */
4832 case 0x1c: arg_ESCP_9=0x01; break;;
4833 case 0x24: arg_ESCP_9=0x01; break;;
4834 /* Envelope media */
4835 case 0x08: arg_ESCP_9=0x02; break;;
4836 /* CD media */
4837 case 0x1f: arg_ESCP_9=0x00; break;;
4838 case 0x20: arg_ESCP_9=0x00; break;;
4839 /* other media default to lower tray */
4840 default: arg_ESCP_9=0x02; break;;
4841 }
4842
4843 /* condition for length to use lower tray: 7.29 in equals 524-525 points */
4844 if ( (arg_ESCP_9 == 0x01) && ( length > 524 ) ) {
4845 arg_ESCP_9=0x02;
4846 }
4847
4848 /* even if user does not select correct CD media type, set appropriately */
4849 if (print_cd)
4850 arg_ESCP_9=0x00;
4851 }
4852 }
4853
4854 /* MG6700, MG7500, TS8000 uses 0xff with CD media tray */
4855 if ( !(strcmp(init->caps->name,"PIXMA MG6700")) || !(strcmp(init->caps->name,"PIXMA MG7500")) || !(strcmp(init->caps->name,"PIXMA TS8000")) ) {
4856 if (tray_user_select && !print_cd)
4857 arg_ESCP_9=user_ESCP_9;
4858 else {
4859 switch(arg_ESCP_2)
4860 {
4861 /* CD media */
4862 case 0x1f: arg_ESCP_9=0xff; break;;
4863 case 0x20: arg_ESCP_9=0xff; break;;
4864 }
4865
4866 /* even if user does not select correct CD media type, set appropriately */
4867 if (print_cd)
4868 arg_ESCP_9=0x00;
4869 }
4870 }
4871
4872 if ( init->caps->ESC_P_len == 9 ) /* support for new devices from October 2012. */
4873 {/* the 4th of the 6 bytes is the media type. 2nd byte is media size. Both read from canon-media array. */
4874
4875 if ( !(strcmp(init->caps->name,"PIXMA MG7700")) ) {
4876 /* output with 3 extra 0s at the end */
4877 canon_cmd( v,ESC28,0x50,12,0x00,arg_ESCP_1,0x00,arg_ESCP_2,arg_ESCP_5,arg_ESCP_6,arg_ESCP_7,0x00,arg_ESCP_9,0x00,0x00,0x00 );
4878 }
4879 else {
4880
4881 /* arg_ESCP_1 = 0x03; */ /* A4 size */
4882 /* arg_ESCP_2 = 0x00; */ /* plain media */
4883 /* size media tray */
4884 canon_cmd( v,ESC28,0x50,9,0x00,arg_ESCP_1,0x00,arg_ESCP_2,arg_ESCP_5,arg_ESCP_6,arg_ESCP_7,0x00,arg_ESCP_9 );
4885
4886 }
4887 }
4888 else if ( init->caps->ESC_P_len == 8 ) /* support for new devices from 2012. */
4889 {/* the 4th of the 6 bytes is the media type. 2nd byte is media size. Both read from canon-media array. */
4890
4891 /* arg_ESCP_1 = 0x03; */ /* A4 size */
4892 /* arg_ESCP_2 = 0x00; */ /* plain media */
4893 /* size media */
4894 canon_cmd( v,ESC28,0x50,8,0x00,arg_ESCP_1,0x00,arg_ESCP_2,arg_ESCP_5,arg_ESCP_6,arg_ESCP_7,0x00 );
4895 }
4896 else if ( init->caps->ESC_P_len == 6 ) /* first devices with XML header and ender */
4897 {/* the 4th of the 6 bytes is the media type. 2nd byte is media size. Both read from canon-media array. */
4898
4899 /* arg_ESCP_1 = 0x03; */ /* A4 size */
4900 /* arg_ESCP_2 = 0x00; */ /* plain media */
4901 /* size media */
4902 canon_cmd( v,ESC28,0x50,6,0x00,arg_ESCP_1,0x00,arg_ESCP_2,arg_ESCP_5,arg_ESCP_6 );
4903 }
4904 else if ( init->caps->ESC_P_len == 4 ) {/* 4 bytes */
4905 /* size media */
4906 canon_cmd( v,ESC28,0x50,4,0x00,arg_ESCP_1,0x00,arg_ESCP_2 );
4907 }
4908 else if ( init->caps->ESC_P_len == 2 ) {
4909 /* 2 bytes only */
4910 canon_cmd( v,ESC28,0x50,2,0x00,arg_ESCP_1 );
4911 }
4912 else /* error in definition */
4913 stp_dprintf(STP_DBG_CANON, v,"SEVERE BUG IN print-canon.c::canon_init_setESC_P() "
4914 "ESC_P_len=%d!!\n",init->caps->ESC_P_len);
4915 }
4916
4917 /* ESC (s -- 0x73 -- :
4918 used in some newer printers for duplex pages except last one.
4919 When capability available, used for non-tumble and tumble (unlike Esc (u which is non-tumble only)
4920 Limitation: outputs on every page */
4921 static void
canon_init_setESC_s(const stp_vars_t * v,const canon_privdata_t * init)4922 canon_init_setESC_s(const stp_vars_t *v, const canon_privdata_t *init)
4923 {
4924 if (!(init->caps->features & CANON_CAP_DUPLEX))
4925 return;
4926 if (!(init->caps->features & CANON_CAP_s))
4927 return;
4928
4929 canon_cmd(v,ESC28,0x73, 1, 0x00);
4930 }
4931
4932 /* ESC (S -- 0x53 -- unknown -- :
4933 Required by iP90/iP90v and iP100 printers.
4934 */
4935 static void
canon_init_setESC_S(const stp_vars_t * v,const canon_privdata_t * init)4936 canon_init_setESC_S(const stp_vars_t *v, const canon_privdata_t *init)
4937 {
4938 unsigned char arg_ESCS_01,arg_ESCS_04,arg_ESCS_09,arg_ESCS_11;
4939
4940 if (!(init->caps->features & CANON_CAP_S))
4941 return;
4942
4943 if (!(init->mode->flags & MODE_FLAG_S))
4944 return;
4945
4946 /* iP90 defaults: based on non-photo media */
4947 arg_ESCS_01 = 0x01;
4948 arg_ESCS_04 = 0xff;
4949 arg_ESCS_09 = 0x1a;
4950 arg_ESCS_11 = 0x68;
4951
4952 /* hard-coded for different media, color and quality settings */
4953 /* iP90 bytes 1,4,9 and 11 vary */
4954 if ( !(strcmp(init->caps->name,"PIXMA iP90")) ) {
4955 if ( !strcmp(init->mode->name,"600x600dpi_high2") || !strcmp(init->mode->name,"600x600dpi_high4") ) {
4956 /* if inkset is color then set special bytes, else leave default.
4957 Note: in this case the mode only has CMYK, mono is a different mode.
4958 */
4959 if (init->used_inks == CANON_INK_CMYK) {
4960 arg_ESCS_01 = 0xc1;
4961 arg_ESCS_04 = 0xf1;
4962 arg_ESCS_09 = 0x50;
4963 arg_ESCS_11 = 0x28;
4964 }
4965 } else if ( !strcmp(init->mode->name,"300x300dpi_draft") ) {
4966 /* set regardless of inkset */
4967 arg_ESCS_09 = 0x02;
4968 arg_ESCS_11 = 0x08;
4969 } else if ( !strcmp(init->mode->name,"600x600dpi_draft2") ) {
4970 /* if inkset is color then set special bytes, else leave default */
4971 if (init->used_inks == CANON_INK_CMYK) {
4972 arg_ESCS_09 = 0x0a;
4973 arg_ESCS_11 = 0x28;
4974 }
4975 } else if ( !strcmp(init->mode->name,"600x600dpi_photohigh") || !strcmp(init->mode->name,"600x600dpi_photo") || !strcmp(init->mode->name,"600x600dpi_photodraft") ) {
4976 /* almost all photo media need (same) changes from defaults */
4977 /* exception: "600x600dpi_photohigh2" no ESC (S command */
4978 /* exception: "600x600dpi_tshirt" no ESC (S command */
4979 arg_ESCS_01 = 0xc1;
4980 arg_ESCS_04 = 0xf0;
4981 arg_ESCS_09 = 0x50;
4982 arg_ESCS_11 = 0x28;
4983 }
4984 }
4985 else if ( !(strcmp(init->caps->name,"PIXMA iP100")) ) {
4986 /* iP100 bytes 9 and 11 vary */
4987 if ( !strcmp(init->mode->name,"300x300dpi_draft") ) {
4988 /* set regardless of inkset */
4989 arg_ESCS_09 = 0x02;
4990 arg_ESCS_11 = 0x08;
4991 } else if ( !strcmp(init->mode->name,"600x600dpi_photohigh2") || !strcmp(init->mode->name,"600x600dpi_photohigh") || !strcmp(init->mode->name,"600x600dpi_photo2") || !strcmp(init->mode->name,"600x600dpi_photo") || !strcmp(init->mode->name,"600x600dpi_tshirt") ) {
4992 /* all photo media need (same) changes from defaults */
4993 arg_ESCS_09 = 0x0a;
4994 arg_ESCS_11 = 0x28;
4995 }
4996 }
4997
4998 canon_cmd(v,ESC28,0x53,54,arg_ESCS_01,0x02,0xff,arg_ESCS_04,0x41,0x02,0x00,0x01,arg_ESCS_09,0x00,arg_ESCS_11,0x00,0x01,0x01,0x03,0x02,0x01,0x01,0x01,0x03,0x02,0x00,0x07,0x06,0x02,0x01,0x02,0x04,0x04,0x04,0x05,0x06,0x08,0x08,0x08,0x0a,0x0a,0x09,0x00,0x03,0x02,0x01,0x01,0x01,0x01,0x01,0x06,0x02,0x02,0x02,0x03,0x04,0x05,0x06);
4999
5000 }
5001
5002 /* ESC (T -- 0x54 -- setCartridge -- :
5003 */
5004 static void
canon_init_setCartridge(const stp_vars_t * v,const canon_privdata_t * init)5005 canon_init_setCartridge(const stp_vars_t *v, const canon_privdata_t *init)
5006 {
5007 const char *ink_set;
5008
5009 if (!(init->caps->features & CANON_CAP_T))
5010 return;
5011
5012 ink_set = stp_get_string_parameter(v, "InkSet");
5013
5014 if (ink_set && !(strcmp(ink_set,"Both"))) {
5015 if ( !(strcmp(init->caps->name,"PIXMA iP90")) || !(strcmp(init->caps->name,"PIXMA iP100")) || !(strcmp(init->caps->name,"PIXMA iP110")) ) {
5016 canon_cmd(v,ESC28,0x54,3,0x02,0x00,0x00); /* default for iP90, iP100, iP110 */
5017 }
5018 else if ( !(strcmp(init->caps->name,"PIXMA iP6210")) ) {
5019 canon_cmd(v,ESC28,0x54,3,0x03,0x06,0x06); /* default for iP6210D, iP6220D, iP6310D */
5020 /* both: 0x3 0x6 0x6 */
5021 /* color: 0x3 0x1 0x1 */
5022 }
5023 else {
5024 canon_cmd(v,ESC28,0x54,3,0x03,0x04,0x04); /* default: both cartridges */
5025 }
5026 }
5027 else if (ink_set && !(strcmp(ink_set,"Black"))) {
5028 if ( !(strcmp(init->caps->name,"PIXMA iP90")) || !(strcmp(init->caps->name,"PIXMA iP100")) || !(strcmp(init->caps->name,"PIXMA iP110")) ) {
5029 canon_cmd(v,ESC28,0x54,3,0x02,0x00,0x00); /* default for iP90, iP100, iP110 */
5030 }
5031 else if ( !(strcmp(init->caps->name,"PIXMA iP6210")) ) {
5032 canon_cmd(v,ESC28,0x54,3,0x03,0x06,0x06); /* default for iP6210D, iP6220D, iP6310D */
5033 /* both: 0x3 0x6 0x6 */
5034 /* color: 0x3 0x1 0x1 */
5035 /* workaround since does not have black option */
5036 }
5037 else {
5038 canon_cmd(v,ESC28,0x54,3,0x03,0x02,0x02); /* default: black cartridge */
5039 }
5040 }
5041 else if (ink_set && !(strcmp(ink_set,"Color"))) {
5042 if ( !(strcmp(init->caps->name,"PIXMA iP90")) || !(strcmp(init->caps->name,"PIXMA iP100")) || !(strcmp(init->caps->name,"PIXMA iP110")) ) {
5043 canon_cmd(v,ESC28,0x54,3,0x02,0x00,0x01); /* composite for iP90, iP100, iP110 */
5044 /* black save : 2 1 0 for selected plain (600dpi std) modes, rest remain 2 0 0 */
5045 /* composite black: 2 0 1 for selected plain (600dpi std & draft) modes, rest remain 2 0 0 */
5046 /* both above set : AND of bytes above */
5047 }
5048 else if ( !(strcmp(init->caps->name,"PIXMA iP6210")) ) {
5049 canon_cmd(v,ESC28,0x54,3,0x03,0x01,0x01); /* default for iP6210D, iP6220D, iP6310D */
5050 /* both: 0x3 0x6 0x6 */
5051 /* color: 0x3 0x1 0x1 */
5052 }
5053 else {
5054 canon_cmd(v,ESC28,0x54,3,0x03,0x01,0x01); /* default: color cartridges */
5055 }
5056 }
5057 else {
5058 canon_cmd(v,ESC28,0x54,3,0x03,0x04,0x04); /* default: both cartridges */
5059 }
5060 }
5061
5062 /* ESC (q -- 0x71 -- setPageID -- :
5063 */
5064 static void
canon_init_setPageID(const stp_vars_t * v,const canon_privdata_t * init)5065 canon_init_setPageID(const stp_vars_t *v, const canon_privdata_t *init)
5066 {
5067 if (!(init->caps->features & CANON_CAP_q))
5068 return;
5069
5070 canon_cmd(v,ESC28,0x71, 1, 0x01);
5071 }
5072
5073 /* ESC (r -- 0x72 -- -- :
5074 */
5075 static void
canon_init_setX72(const stp_vars_t * v,const canon_privdata_t * init)5076 canon_init_setX72(const stp_vars_t *v, const canon_privdata_t *init)
5077 {
5078 if ( !( (init->caps->features & CANON_CAP_r)
5079 || (init->caps->features & CANON_CAP_rr) ) )
5080 return;
5081
5082 if ( (init->caps->features & CANON_CAP_r)
5083 || (init->caps->features & CANON_CAP_rr) )
5084 if (init->caps->ESC_r_arg != 0) /* only output arg if non-zero */
5085 canon_cmd(v,ESC28,0x72, 1, init->caps->ESC_r_arg); /* whatever for - 8200/S200 need it */
5086 if (init->caps->features & CANON_CAP_rr) {
5087 if ( !(strcmp(init->caps->name,"S200")) ) {
5088 canon_cmd(v,ESC28,0x72, 3, 0x63, 1, 0); /* whatever for - S200 needs it */
5089 /* probably to set the print direction of the head */
5090 }
5091 else if ( !(strcmp(init->caps->name,"S820")) || !(strcmp(init->caps->name,"S900")) || !(strcmp(init->caps->name,"S9000")) || !(strcmp(init->caps->name,"i950")) || !(strcmp(init->caps->name,"i960")) || !(strcmp(init->caps->name,"i9100")) || !(strcmp(init->caps->name,"i9900")) || !(strcmp(init->caps->name,"PIXMA iP7100")) || !(strcmp(init->caps->name,"PIXMA iP8100")) || !(strcmp(init->caps->name,"PIXMA iP8500")) || !(strcmp(init->caps->name,"PIXMA iP8600")) || !(strcmp(init->caps->name,"PIXMA iP9910")) || !(strcmp(init->caps->name,"PIXMA MP900")) || !(strcmp(init->caps->name,"PIXMA Pro9000")) || !(strcmp(init->caps->name,"PIXMA Pro9002")) || !(strcmp(init->caps->name,"PIXMA Pro9500")) || !(strcmp(init->caps->name,"PIXMA Pro9502")) ) {
5092 canon_cmd(v,ESC28,0x72, 2, 0x62, 0); /* 2 bytes */
5093 }
5094 /* CD mode only */
5095 else if ( (init->mode->flags & MODE_FLAG_CD) && (!(strcmp(init->caps->name,"PIXMA iP4600")) || !(strcmp(init->caps->name,"PIXMA iP4700")) || !(strcmp(init->caps->name,"PIXMA MP980")) || !(strcmp(init->caps->name,"PIXMA MP990")) ) ) {
5096 canon_cmd(v,ESC28,0x72, 1, 0x65);
5097 }
5098 /* CD mode only */
5099 else if ( (init->mode->flags & MODE_FLAG_CD) && ( !(strcmp(init->caps->name,"PIXMA iP4800")) || !(strcmp(init->caps->name,"PIXMA MG6100")) || !(strcmp(init->caps->name,"PIXMA MG8100")) ) ) {
5100 canon_cmd(v,ESC28,0x72, 1, 0x68);
5101 }
5102 /* CD mode only -- no ESC (r at all otherwise */
5103 else if ( (init->mode->flags & MODE_FLAG_CD) && ( !(strcmp(init->caps->name,"PIXMA iP4900")) || !(strcmp(init->caps->name,"PIXMA MG5200")) || !(strcmp(init->caps->name,"PIXMA MG5300")) || !(strcmp(init->caps->name,"PIXMA MG6200")) || !(strcmp(init->caps->name,"PIXMA MG8200")) || !(strcmp(init->caps->name,"PIXMA TS8000")) ) ) {
5104 canon_cmd(v,ESC28,0x72, 1, 0x68); /* same as above case? */
5105 }
5106 /* other cases here */
5107 }
5108 }
5109
5110 /* ESC (r -- 0x72 -- ??? set direction ??? -- :
5111 only works if quality = 01 (S200) */
5112 static void
canon_set_X72(const stp_vars_t * v,int x72arg)5113 canon_set_X72(const stp_vars_t *v, int x72arg)
5114 {
5115 canon_cmd(v,ESC28,0x72, 3, 0x63, x72arg, 0);
5116 }
5117
5118 /* ESC (t -- 0x74 -- cmdSetImage --:
5119 */
5120 static void
canon_init_setImage(const stp_vars_t * v,const canon_privdata_t * init)5121 canon_init_setImage(const stp_vars_t *v, const canon_privdata_t *init)
5122 {
5123 unsigned char
5124 arg_74_1 = 0x01, /* 1 bit per pixel */
5125 arg_74_2 = 0x00, /* */
5126 arg_74_3 = 0x01; /* 01 <= 360 dpi 09 >= 720 dpi */
5127
5128 if (!(init->caps->features & CANON_CAP_t))
5129 return;
5130
5131 if(init->mode->flags & MODE_FLAG_EXTENDED_T) /*code requires extended mode settings*/
5132 {
5133 int i;
5134 int length = init->mode->num_inks*3 + 3;
5135 unsigned char* buf = stp_zalloc(length);
5136 buf[0]=0x80;
5137 if(init->mode->flags & MODE_FLAG_PRO){
5138 buf[1]=0x90; /* was 0x10, but this should probably be 0x90 */
5139 buf[2]=0x4;
5140 }else if(init->mode->flags & MODE_FLAG_IP8500){
5141 buf[1]=0x00;
5142 buf[2]=0x01;
5143 }else if(init->mode->flags & MODE_FLAG_MP130){
5144 buf[1]=0x04;
5145 buf[2]=0x01;
5146 }else if(init->mode->flags & MODE_FLAG_MP360){
5147 buf[1]=0x84;
5148 buf[2]=0x01;
5149 }else{
5150 buf[1]=0x80;
5151 buf[2]=0x01;
5152 }
5153 for(i=0;i<init->mode->num_inks;i++){
5154 if(init->mode->inks[i].channel != 0){ /* 0 means ink is used in gutenprint for sub-channel setup but not intended for printer */
5155 if(init->mode->inks[i].ink->flags & INK_FLAG_5pixel_in_1byte)
5156 buf[3+i*3+0]=(1<<5)|init->mode->inks[i].ink->bits; /*info*/
5157 /*else if(init->mode->inks[i].ink->flags & INK_FLAG_lowresmode)
5158 {
5159 buf[3+i*3+1]=0x01;
5160 buf[3+i*3+0]=init->mode->inks[i].ink->bits;
5161 }*/
5162 else if(init->mode->inks[i].ink->flags & INK_FLAG_3pixel5level_in_1byte)
5163 buf[3+i*3+0]=(1<<5)|init->mode->inks[i].ink->bits; /*info*/
5164 else if(init->mode->inks[i].ink->flags & INK_FLAG_3pixel6level_in_1byte)
5165 buf[3+i*3+0]=(1<<5)|init->mode->inks[i].ink->bits; /*info*/
5166 else
5167 buf[3+i*3+0]=init->mode->inks[i].ink->bits;
5168
5169 /* workaround for now on the 4-4 inkset and others */
5170 /*if (init->mode->inks[i].ink->bits == 4)
5171 buf[3+i*3+2] = 0x04;*/
5172 /*else if (init->mode->inks[i].ink->bits == 2)
5173 buf[3+i*3+2] = 0x04;*/
5174 /*else if (init->mode->inks[i].ink->bits == 1)
5175 buf[3+i*3+2] = 0x02;*/
5176 /*else*/ /* normal operation */
5177 buf[3+i*3+2]= init->mode->inks[i].ink->numsizes+1;/*level*/
5178 /*else
5179 buf[3+i*3+2] = 0x00;*/
5180 /* this should show that there is an error */
5181 }
5182 }
5183 stp_zfwrite(ESC28,2,1,v);
5184 stp_putc(0x74,v);
5185 stp_put16_le(length,v);
5186 stp_zfwrite((char*)buf,length,1,v);
5187 stp_free(buf);
5188 return;
5189 }
5190
5191 /* other models mostly hardcoded stuff not really understood ;( */
5192 if (!strcmp(init->caps->name,"S200")) /* 1 bit per pixel (arg 4,7,10,13); */
5193 /* 2 level per pixel (arg 6,9,12,15) for each color */
5194 /* though we print only 1bit/pixel - but this is how */
5195 /* the windows driver works */
5196 {
5197 canon_cmd(v,ESC28,0x74, 30, 0x80, 4, 1, 1, 0, 2, 1, 0, 2, 1, 0, 2, 1, 0, 2,\
5198 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
5199 return;
5200 }
5201
5202 if (init->mode->xdpi==1440) arg_74_2= 0x04;
5203 if (init->mode->ydpi>=720) arg_74_3= 0x09;
5204
5205 if (init->mode->inks[0].ink->bits>1) {
5206 arg_74_1= 0x02;
5207 arg_74_2= 0x80;
5208 arg_74_3= 0x09; /* default for most media */
5209 /* FIXME: (Gernot) below must be corrected I think, since CMY is
5210 not a function of the cartridge but of the driver selection of
5211 which logical inks get sent to the printer. So here the
5212 printers that use this should be enumerated, rather than a
5213 generic condition based on CANON_INK_CMY */
5214 if (init->used_inks == CANON_INK_CMY) arg_74_3= 0x02; /* for BC-06 cartridge!!! */
5215 /* example of better way: for BJC-3000 series */
5216 if ( !strcmp(init->caps->name,"3000") || !strcmp(init->caps->name,"4300")) {
5217 /* but if photo cartridge selection, set differently again */
5218 if (init->mode->flags & MODE_FLAG_PHOTO)
5219 arg_74_3= 0x0a;
5220 /* T-Shirt (3), Backprint Film (3) or Transparencies (2) */
5221 else if ((init->pt->media_code_c==2) || (init->pt->media_code_c==3))
5222 arg_74_3= 0x01;
5223 else
5224 /* other media */
5225 arg_74_3= 0x09; /* return to default after broken code above */
5226 }
5227 if ( (!strcmp(init->caps->name,"2000")) || (!strcmp(init->caps->name,"2100")) ) {
5228 /* but if photo cartridge selection, set differently again */
5229 if (init->mode->flags & MODE_FLAG_PHOTO)
5230 arg_74_3= 0x0a;
5231 else
5232 /* other media */
5233 arg_74_3= 0x09; /* return to default after broken code above */
5234 }
5235
5236 }
5237
5238 /* workaround for the bjc8200 in 6color mode - not really understood */
5239 if (!strcmp(init->caps->name,"8200")) {
5240 if (init->used_inks == CANON_INK_CcMmYK) {
5241 arg_74_1= 0xff;
5242 arg_74_2= 0x90;
5243 arg_74_3= 0x04;
5244 if (init->mode->ydpi>600) arg_74_3= 0x09;
5245 } else {
5246 arg_74_1= 0x01;
5247 arg_74_2= 0x00;
5248 arg_74_3= 0x01;
5249 if (init->mode->ydpi>600) arg_74_3= 0x09;
5250 }
5251 }
5252
5253 canon_cmd(v,ESC28,0x74, 3, arg_74_1, arg_74_2, arg_74_3);
5254 }
5255
5256 /* ESC (I (J (L
5257 */
5258 static void
canon_init_setMultiRaster(const stp_vars_t * v,const canon_privdata_t * init)5259 canon_init_setMultiRaster(const stp_vars_t *v, const canon_privdata_t *init){
5260
5261 int i; /* introduced for channel counting */
5262 char* raster_channel_order; /* introduced for channel counting */
5263
5264 if(!(init->caps->features & CANON_CAP_I))
5265 return;
5266
5267 canon_cmd(v,ESC28,0x49, 1, 0x1); /* enable MultiLine Raster? */
5268 /* canon_cmd(v,ESC28,0x4a, 1, init->caps->raster_lines_per_block); */
5269 canon_cmd(v,ESC28,0x4a, 1, init->mode->raster_lines_per_block); /* set number of lines per raster block */
5270
5271 /* set the color sequence */
5272 stp_zfwrite("\033(L", 3, 1, v);
5273 stp_put16_le(init->num_channels, v);
5274 /* add an exception here to add 0x60 of cmy channels for those printers/modes that require it */
5275 /* Note: 2017-06-28 this section needs revision, many printers not entered here, thus modes either not supported or incorrectly output */
5276 raster_channel_order=init->channel_order;
5277 if ( !(strcmp(init->caps->name,"PIXMA E3100")) || !(strcmp(init->caps->name,"PIXMA MP140")) || !(strcmp(init->caps->name,"PIXMA MP150")) || !(strcmp(init->caps->name,"PIXMA MP160")) || !(strcmp(init->caps->name,"PIXMA MP170")) || !(strcmp(init->caps->name,"PIXMA MP180")) || !(strcmp(init->caps->name,"PIXMA MP190")) || !(strcmp(init->caps->name,"PIXMA MP210")) || !(strcmp(init->caps->name,"PIXMA MP220")) || !(strcmp(init->caps->name,"PIXMA MP240")) || !(strcmp(init->caps->name,"PIXMA MP250")) || !(strcmp(init->caps->name,"PIXMA MP270")) || !(strcmp(init->caps->name,"PIXMA MP280")) || !(strcmp(init->caps->name,"PIXMA MP450")) || !(strcmp(init->caps->name,"PIXMA MP460")) || !(strcmp(init->caps->name,"PIXMA MP470")) || !(strcmp(init->caps->name,"PIXMA MP480")) || !(strcmp(init->caps->name,"PIXMA MP490")) || !(strcmp(init->caps->name,"PIXMA MP495")) || !(strcmp(init->caps->name,"PIXMA MX300")) || !(strcmp(init->caps->name,"PIXMA MX310")) || !(strcmp(init->caps->name,"PIXMA MX330")) || !(strcmp(init->caps->name,"PIXMA MX340")) || !(strcmp(init->caps->name,"PIXMA MX350")) || !(strcmp(init->caps->name,"PIXMA MX360")) || !(strcmp(init->caps->name,"PIXMA MX370")) || !(strcmp(init->caps->name,"PIXMA MX410")) || !(strcmp(init->caps->name,"PIXMA MX510")) || !(strcmp(init->caps->name,"PIXMA MX520")) || !(strcmp(init->caps->name,"PIXMA iP2700")) || !(strcmp(init->caps->name,"PIXMA MG2100")) || !(strcmp(init->caps->name,"PIXMA MG2400")) || !(strcmp(init->caps->name,"PIXMA MG2500")) || !(strcmp(init->caps->name,"PIXMA MG3500")) || !(strcmp(init->caps->name,"PIXMA MG3600")) || !(strcmp(init->caps->name,"PIXMA G1000")) || !(strcmp(init->caps->name,"PIXMA G4000")) )
5278 {
5279 /* if cmy there, add 0x60 to each --- all modes using cmy require it */
5280 for(i=0;i<init->num_channels;i++){
5281 switch(init->channel_order[i]){
5282 case 'c':raster_channel_order[i]+=0x60; break;;
5283 case 'm':raster_channel_order[i]+=0x60; break;;
5284 case 'y':raster_channel_order[i]+=0x60; break;;
5285 }
5286 }
5287 /* Gernot: debug */
5288 /* if CMY there, add 0x80 to each to change to cmy+0x60 */
5289 /* for(i=0;i<init->num_channels;i++){
5290 switch(init->channel_order[i]){
5291 case 'C':raster_channel_order[i]+=0x80; break;;
5292 case 'M':raster_channel_order[i]+=0x80; break;;
5293 case 'Y':raster_channel_order[i]+=0x80; break;;
5294 }
5295 }*/
5296 stp_zfwrite((const char *)raster_channel_order,init->num_channels, 1, v);
5297 }
5298 /* note these names are from canon-printers.h, only separate driver strings are required */
5299 else if ( !(strcmp(init->caps->name,"PIXMA iP6210")) ) {
5300 /* if cmy there, add 0x60 to each --- only some modes using cmy require it */
5301 /* case one: all modes with only cmy */
5302 if (init->num_channels==3) {
5303 for(i=0;i<init->num_channels;i++){
5304 switch(init->channel_order[i]){
5305 case 'c':raster_channel_order[i]+=0x60; break;;
5306 case 'm':raster_channel_order[i]+=0x60; break;;
5307 case 'y':raster_channel_order[i]+=0x60; break;;
5308 }
5309 }
5310 }
5311 /* case two: CMYcmy modes, but not CMYkcm modes */
5312 else if ( (init->num_channels==6) && (init->used_inks==CANON_INK_CMY) ) {
5313 for(i=0;i<init->num_channels;i++){
5314 switch(init->channel_order[i]){
5315 case 'c':raster_channel_order[i]+=0x60; break;;
5316 case 'm':raster_channel_order[i]+=0x60; break;;
5317 case 'y':raster_channel_order[i]+=0x60; break;;
5318 }
5319 }
5320 }
5321 /* case three: CMYkm modes with 0x80 to subtract from all inks with 2 or 8 bits */
5322 else if ( (init->num_channels==6) && (init->used_inks==CANON_INK_CcMmYK) && ((init->mode->inks[0].ink->bits==2) || (init->mode->inks[0].ink->bits==8)) ) {
5323 for(i=0;i<init->num_channels;i++){
5324 switch(init->channel_order[i]){
5325 case 'C':raster_channel_order[i]+=0x80; break;;
5326 case 'M':raster_channel_order[i]+=0x80; break;;
5327 case 'Y':raster_channel_order[i]+=0x80; break;;
5328 case 'c':raster_channel_order[i]+=0x80; break;;
5329 case 'm':raster_channel_order[i]+=0x80; break;;
5330 case 'k':raster_channel_order[i]+=0x80; break;;
5331 }
5332 }
5333 }
5334 stp_zfwrite((const char *)raster_channel_order,init->num_channels, 1, v);
5335 }
5336 else
5337 {
5338 stp_zfwrite((const char *)init->channel_order,init->num_channels, 1, v);
5339 }
5340 }
5341
5342 /* ESC (u -- 0x75 -- even pages duplex for long side only -- */
5343 static void
canon_init_setESC_u(const stp_vars_t * v,const canon_privdata_t * init)5344 canon_init_setESC_u(const stp_vars_t *v, const canon_privdata_t *init)
5345 {
5346 if (!(init->caps->features & CANON_CAP_DUPLEX))
5347 return;
5348
5349 canon_cmd( v,ESC28,0x75, 1, 0x01 );
5350 }
5351
5352 /* ESC (v -- 0x76 -- */
5353 /* page rotation in Windows driver settings: */
5354 /* none: 0x0 */
5355 /* 90 deg: 0x1 */
5356 /* 180 deg: 0x2 */
5357 /* 270 deg: 0x3 */
5358 /* also influences ESC (P command parameters 5 and 6 */
5359 /* none: 1 0 */
5360 /* 90 deg: 2 0 */
5361 /* 180 deg: 1 1 */
5362 /* 270 deg: 2 1 */
5363 static void
canon_init_setESC_v(const stp_vars_t * v,const canon_privdata_t * init)5364 canon_init_setESC_v(const stp_vars_t *v, const canon_privdata_t *init)
5365 {
5366 const char *orientation_type =stp_get_string_parameter(v, "Orientation");
5367 unsigned char arg_ESCv_1 = 0x00;
5368
5369 if (!(init->caps->features & CANON_CAP_v))
5370 return;
5371
5372 if( orientation_type && !strcmp(orientation_type,"Portrait")) /* none */
5373 arg_ESCv_1 = 0x00;
5374 else if( orientation_type && !strcmp(orientation_type,"Landscape")) /* 90 deg */
5375 arg_ESCv_1 = 0x01;
5376 else if( orientation_type && !strcmp(orientation_type,"UpsideDown")) /* 180 deg */
5377 arg_ESCv_1 = 0x02;
5378 else if( orientation_type && !strcmp(orientation_type,"Seascape")) /* 270 deg */
5379 arg_ESCv_1 = 0x03;
5380
5381 canon_cmd( v,ESC28,0x76, 1, arg_ESCv_1 );
5382 }
5383
5384 /* ESC (w -- 0x77 -- :
5385 Unknown.
5386 new September 2015, currently only 1 byte.
5387 */
5388 static void
canon_init_setESC_w(const stp_vars_t * v,const canon_privdata_t * init)5389 canon_init_setESC_w(const stp_vars_t *v, const canon_privdata_t *init)
5390 {
5391 unsigned char arg_ESCw_1;
5392 if (!(init->caps->features & CANON_CAP_w))
5393 return;
5394
5395 arg_ESCw_1 = (init->pt) ? init->pt->media_code_w: 0x00;
5396 canon_cmd( v,ESC28,0x77, 1, arg_ESCw_1 );
5397 }
5398
5399 static void
canon_init_printer(const stp_vars_t * v,canon_privdata_t * init)5400 canon_init_printer(const stp_vars_t *v, canon_privdata_t *init)
5401 {
5402 unsigned int mytop;
5403 int page_number = stp_get_int_parameter(v, "PageNumber");
5404 const char *duplex_mode = stp_get_string_parameter(v, "Duplex");
5405 /* init printer */
5406 if (init->is_first_page) {
5407 canon_init_resetPrinter(v,init); /* ESC [K */
5408 canon_init_setESC_M(v,init); /* ESC (M */
5409 canon_init_setDuplex(v,init); /* ESC ($ */
5410 }
5411 canon_init_setPageMode(v,init); /* ESC (a */
5412 canon_init_setDataCompression(v,init); /* ESC (b */
5413 canon_init_setPageID(v,init); /* ESC (q */
5414 canon_init_setPrintMode(v,init); /* ESC (m */
5415 canon_init_setResolution(v,init); /* ESC (d */
5416 canon_init_setImage(v,init); /* ESC (t */
5417 canon_init_setColor(v,init); /* ESC (c */
5418 canon_init_setPageMargins(v,init); /* ESC (g */
5419 canon_init_setPageMargins2(v,init); /* ESC (p */
5420 canon_init_setESC_P(v,init); /* ESC (P */
5421 canon_init_setCartridge(v,init); /* ESC (T */
5422 canon_init_setESC_S(v,init); /* ESC (S */
5423 canon_init_setTray(v,init); /* ESC (l */
5424 canon_init_setX72(v,init); /* ESC (r */
5425 canon_init_setESC_v(v,init); /* ESC (v */
5426 if (init->is_first_page)
5427 canon_init_setESC_w(v,init); /* ESC (w */
5428 if((page_number & 1) && duplex_mode && !strcmp(duplex_mode,"DuplexNoTumble"))
5429 canon_init_setESC_u(v,init); /* ESC (u 0x1 */
5430 if(duplex_mode)
5431 canon_init_setESC_s(v,init); /* ESC (s 0x0 */
5432 canon_init_setMultiRaster(v,init); /* ESC (I (J (L */
5433
5434 /* some linefeeds */
5435
5436 mytop= (init->top*init->mode->ydpi)/72;
5437
5438 if(init->caps->features & CANON_CAP_I)
5439 /* mytop /= init->caps->raster_lines_per_block; */
5440 mytop /= init->mode->raster_lines_per_block;
5441
5442 if(mytop)
5443 canon_cmd(v,ESC28,0x65, 2, (mytop >> 8 ),(mytop & 255));
5444 }
5445
5446 static void
canon_deinit_printer(const stp_vars_t * v,const canon_privdata_t * init)5447 canon_deinit_printer(const stp_vars_t *v, const canon_privdata_t *init)
5448 {
5449 /* eject page */
5450 stp_putc(0x0c,v);
5451
5452 /* say goodbye */
5453 canon_cmd(v,ESC28,0x62,1,0);
5454 if (init->caps->features & CANON_CAP_a)
5455 canon_cmd(v,ESC28,0x61, 1, 0);
5456 }
5457
5458 static int
canon_start_job(const stp_vars_t * v,stp_image_t * image)5459 canon_start_job(const stp_vars_t *v, stp_image_t *image)
5460 {
5461 const canon_cap_t * caps = canon_get_model_capabilities(v);
5462 /* output XML for iP2700 and other devices */
5463 if (caps->features & CANON_CAP_XML) {
5464 int length=strlen(prexml_iP2700); /* 680 */
5465 stp_zfwrite((const char*)prexml_iP2700,length,1,v);
5466 }
5467 return 1;
5468 }
5469
5470 static int
canon_end_job(const stp_vars_t * v,stp_image_t * image)5471 canon_end_job(const stp_vars_t *v, stp_image_t *image)
5472 {
5473 const canon_cap_t * caps = canon_get_model_capabilities(v);
5474 canon_cmd(v,ESC40,0,0);
5475 /* output XML for iP2700 and other devices */
5476 if (caps->features & CANON_CAP_XML) {
5477 int length=strlen(postxml_iP2700); /* 263 */
5478 stp_zfwrite((const char*)postxml_iP2700,length,1,v);
5479 }
5480 return 1;
5481 }
5482
5483 /*
5484 * 'advance_buffer()' - Move (num) lines of length (len) down one line
5485 * and sets first line to 0s
5486 * accepts NULL pointers as buf
5487 * !!! buf must contain more than (num) lines !!!
5488 * also sets first line to 0s if num<1
5489 */
5490 static void
canon_advance_buffer(unsigned char * buf,int len,int num)5491 canon_advance_buffer(unsigned char *buf, int len, int num)
5492 {
5493 if (!buf || !len) return;
5494 if (num>0) memmove(buf+len,buf,len*num);
5495 memset(buf,0,len);
5496 }
5497
5498 static void
canon_printfunc(stp_vars_t * v)5499 canon_printfunc(stp_vars_t *v)
5500 {
5501 int i;
5502 canon_privdata_t *pd = (canon_privdata_t *) stp_get_component_data(v, "Driver");
5503 canon_write_line(v);
5504 for (i = 0; i < pd->num_channels ; i++)
5505 canon_advance_buffer(pd->channels[i].buf, pd->length, pd->channels[i].delay);
5506
5507 }
5508
5509 static double
get_double_param(stp_vars_t * v,const char * param)5510 get_double_param(stp_vars_t *v, const char *param)
5511 {
5512 if (param && stp_check_float_parameter(v, param, STP_PARAMETER_ACTIVE))
5513 return stp_get_float_parameter(v, param);
5514 else
5515 return 1.0;
5516 }
5517
5518
5519
5520 static void
set_mask(unsigned char * cd_mask,int x_center,int scaled_x_where,int limit,int expansion,int invert)5521 set_mask(unsigned char *cd_mask, int x_center, int scaled_x_where,
5522 int limit, int expansion, int invert)
5523 {
5524 int clear_val = invert ? 255 : 0;
5525 int set_val = invert ? 0 : 255;
5526 int bytesize = 8 / expansion;
5527 int byteextra = bytesize - 1;
5528 int first_x_on = x_center - scaled_x_where;
5529 int first_x_off = x_center + scaled_x_where;
5530 if (first_x_on < 0)
5531 first_x_on = 0;
5532 if (first_x_on > limit)
5533 first_x_on = limit;
5534 if (first_x_off < 0)
5535 first_x_off = 0;
5536 if (first_x_off > limit)
5537 first_x_off = limit;
5538 first_x_on += byteextra;
5539 if (first_x_off > (first_x_on - byteextra))
5540 {
5541 int first_x_on_byte = first_x_on / bytesize;
5542 int first_x_on_mod = expansion * (byteextra - (first_x_on % bytesize));
5543 int first_x_on_extra = ((1 << first_x_on_mod) - 1) ^ clear_val;
5544 int first_x_off_byte = first_x_off / bytesize;
5545 int first_x_off_mod = expansion * (byteextra - (first_x_off % bytesize));
5546 int first_x_off_extra = ((1 << 8) - (1 << first_x_off_mod)) ^ clear_val;
5547 if (first_x_off_byte < first_x_on_byte)
5548 {
5549 /* This can happen, if 6 or fewer points are turned on */
5550 cd_mask[first_x_on_byte] = first_x_on_extra & first_x_off_extra;
5551 }
5552 else
5553 {
5554 if (first_x_on_extra != clear_val)
5555
5556 cd_mask[first_x_on_byte - 1] = first_x_on_extra;
5557 if (first_x_off_byte > first_x_on_byte)
5558 memset(cd_mask + first_x_on_byte, set_val,
5559 first_x_off_byte - first_x_on_byte);
5560 if (first_x_off_extra != clear_val)
5561 cd_mask[first_x_off_byte] = first_x_off_extra;
5562 }
5563 }
5564 }
5565
5566
5567 /* get delay settings for the specified color and mode */
canon_get_delay(canon_privdata_t * privdata,char color)5568 static int canon_get_delay(canon_privdata_t* privdata,char color){
5569 int i=0;
5570 int delay = 0;
5571 const canon_delay_t* delaylist = privdata->mode->delay;
5572
5573 while(delaylist && delaylist[i].color){
5574 if(delaylist[i].color == color){
5575 delay = delaylist[i].delay;
5576 break;
5577 }
5578 ++i;
5579 }
5580 if(delay > privdata->delay_max)
5581 privdata->delay_max = delay;
5582 return delay;
5583 }
5584
5585
5586 /* add a single channel to the dither engine */
canon_setup_channel(stp_vars_t * v,canon_privdata_t * privdata,int channel,int subchannel,const canon_inkset_t * ink,stp_shade_t ** shades)5587 static 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){
5588 if(ink->channel && ink->density > 0.0){
5589 int delay = canon_get_delay(privdata,ink->channel);
5590 canon_channel_t* current;
5591 stp_dprintf(STP_DBG_CANON, v, "canon_setup_channel: (start) privdata->num_channels %d\n", privdata->num_channels);
5592 stp_dprintf(STP_DBG_CANON, v, "canon_setup_channel: (start) privdata->channel_order %s\n", privdata->channel_order);
5593
5594 /* create a new channel */
5595 privdata->channels = stp_realloc(privdata->channels,sizeof(canon_channel_t) * (privdata->num_channels + 1));
5596 privdata->channel_order = stp_realloc(privdata->channel_order,privdata->num_channels + 2);
5597 /* update channel order */
5598 privdata->channel_order[privdata->num_channels]=ink->channel;
5599 stp_dprintf(STP_DBG_CANON, v, "canon_setup_channel: ink->channel %c\n", ink->channel);
5600 privdata->channel_order[privdata->num_channels+1]='\0';
5601 stp_dprintf(STP_DBG_CANON, v, "canon_setup_channel: (terminated)privdata->channel_order %s\n", privdata->channel_order);
5602 current = &(privdata->channels[privdata->num_channels]);
5603 ++privdata->num_channels;
5604 /* fill ink properties */
5605 current->name = ink->channel;
5606 stp_dprintf(STP_DBG_CANON, v, "canon_setup_channel: current->name %c\n", current->name);
5607 current->props = ink->ink;
5608 current->delay = delay;
5609 /* calculate buffer length */
5610 current->buf_length = ((privdata->length * current->props->bits)+1)*(delay + 1);
5611 /* update maximum buffer length */
5612 if(current->buf_length > privdata->buf_length_max)
5613 privdata->buf_length_max = current->buf_length;
5614 /* allocate buffer for the raster data */
5615 current->buf = stp_zalloc(current->buf_length + 1);
5616 /* add channel to the dither engine */
5617 stp_dither_add_channel(v, current->buf , channel , subchannel);
5618
5619 /* add shades to the shades array */
5620 *shades = stp_realloc(*shades,(subchannel + 1) * sizeof(stp_shade_t));
5621 /* move previous shades up one position as set_inks_full expects the subchannels first */
5622 if(subchannel)
5623 memmove(*shades + 1,*shades,sizeof(stp_shade_t) * subchannel);
5624 (*shades)[0].value = ink->density;
5625 stp_dprintf(STP_DBG_CANON, v, "canon_setup_channel: ink->density %.3f\n", ink->density);
5626 (*shades)[0].numsizes = ink->ink->numsizes;
5627 /* test for 4-4 inket with 8 levels spaced every 2nd */
5628 /*if (ink->ink->bits == 4)
5629 (*shades)[0].numsizes = 8;*/
5630
5631 (*shades)[0].dot_sizes = ink->ink->dot_sizes;
5632 return 1;
5633 }
5634 return 0;
5635 }
5636
5637
5638
5639
5640
5641 /* setup the dither channels */
canon_setup_channels(stp_vars_t * v,canon_privdata_t * privdata)5642 static void canon_setup_channels(stp_vars_t *v,canon_privdata_t* privdata){
5643 /* (in gutenprint notation) => KCMY, 1230 => CMYK etc. */
5644 const char default_channel_order[STP_NCOLORS] = {0,1,2,3};
5645 /* codes for the primary channels */
5646 const char primary[STP_NCOLORS] = {'K','C','M','Y',};
5647 /* codes for the subchannels */
5648 const char secondary[STP_NCOLORS] = {'k','c','m','y'};
5649 /* names of the density adjustment controls */
5650 const char *primary_density_control[STP_NCOLORS] = {"BlackDensity","CyanDensity","MagentaDensity","YellowDensity"};
5651 const char *secondary_density_control[STP_NCOLORS] = {NULL,"LightCyanTrans","LightMagentaTrans","LightYellowTrans"};
5652 /* ink darkness for every channel */
5653 const double ink_darkness[] = {1.0, 0.31 / .5, 0.61 / .97, 0.08};
5654 const char* channel_order = default_channel_order;
5655
5656
5657
5658 int channel;
5659 int channel_idx;
5660
5661 if(privdata->caps->channel_order)
5662 channel_order = privdata->caps->channel_order;
5663
5664
5665 /* loop through the dither channels */
5666 for(channel_idx = 0; channel_idx < STP_NCOLORS ; channel_idx++){
5667 int i;
5668 unsigned int subchannel = 0;
5669 stp_shade_t* shades = NULL;
5670 int is_black_channel = 0;
5671 channel = channel_order[channel_idx];
5672 stp_dprintf(STP_DBG_CANON, v, "canon_setup_channels: channel %d\n", channel);
5673 if(channel == STP_ECOLOR_K && privdata->used_inks & CANON_INK_K_MASK){ /* black channel */
5674 /* find K and k inks */
5675 for(i=0;i<privdata->mode->num_inks;i++){
5676 const canon_inkset_t* ink = &privdata->mode->inks[i];
5677 if(ink->channel == primary[channel] || ink->channel == secondary[channel]) {
5678 subchannel += canon_setup_channel(v,privdata,channel,subchannel,ink,&shades);
5679 /* Gernot: add */
5680 stp_dprintf(STP_DBG_CANON, v, "canon_setup_channels: got a black channel\n");
5681 }
5682 }
5683 is_black_channel = 1;
5684 /* adding cmy channels */
5685 /*}else if(channel != STP_ECOLOR_K && privdata->used_inks & (CANON_INK_CMY_MASK | CANON_INK_cmy_MASK)){ */ /* color channels */
5686 }else if(channel != STP_ECOLOR_K && privdata->used_inks & CANON_INK_CMY_MASK){ /* color channels */
5687 for(i=0;i<privdata->mode->num_inks;i++){
5688 const canon_inkset_t* ink = &privdata->mode->inks[i];
5689 stp_dprintf(STP_DBG_CANON, v, "canon_setup_channels: loop non-K inks %d\n", i);
5690 /*if(ink->channel == primary[channel] || ((privdata->used_inks & (CANON_INK_CcMmYyKk_MASK | CANON_INK_cmy_MASK)) && (ink->channel == secondary[channel]))) {*/
5691 if(ink->channel == primary[channel] || ((privdata->used_inks & (CANON_INK_CcMmYyKk_MASK|CANON_INK_CMY_MASK)) && (ink->channel == secondary[channel]))) {
5692 /* Gernot: see if this works: use the masks that includes secondary channels */
5693 /* if(ink->channel == primary[channel] || ((privdata->used_inks & CANON_INK_CMYKk_MASK ) && (ink->channel == secondary[channel]))) {*/
5694 subchannel += canon_setup_channel(v,privdata,channel,subchannel,ink,&shades);
5695 stp_dprintf(STP_DBG_CANON, v, "canon_setup_channels: adding subchannel\n");
5696 }
5697 else {
5698 stp_dprintf(STP_DBG_CANON, v, "canon_setup_channels: not creating subchannel\n");
5699 }
5700 }
5701 }
5702
5703 /* set inks and density */
5704 if(shades){
5705 stp_dither_set_inks_full(v,channel, subchannel, shades, 1.0, ink_darkness[channel]);
5706 for(i=0;i<subchannel;i++){
5707 double density = get_double_param(v, primary_density_control[channel]) * get_double_param(v, "Density");
5708 stp_dprintf(STP_DBG_CANON, v, "canon_setup_channels: loop subchannels for shades %d\n", i);
5709 if(i > 0 && secondary_density_control[channel])
5710 density *= get_double_param(v, secondary_density_control[channel]);
5711 stp_channel_set_density_adjustment(v,channel,subchannel,density);
5712 }
5713 if (is_black_channel)
5714 stp_channel_set_black_channel(v, channel);
5715 stp_free(shades);
5716 }
5717 }
5718 }
5719
5720
5721
5722
5723
5724
5725
5726 /* FIXME move this to printercaps, and/or Esc (p command */
5727 #define CANON_CD_X 176
5728 #define CANON_CD_Y 405
5729
setup_page(stp_vars_t * v,canon_privdata_t * privdata)5730 static void setup_page(stp_vars_t* v,canon_privdata_t* privdata){
5731 const char *media_source = stp_get_string_parameter(v, "InputSlot");
5732 const char *cd_type = stp_get_string_parameter(v, "PageSize");
5733 int print_cd = (media_source && (!strcmp(media_source, "CD")));
5734 stp_dimension_t page_left,
5735 page_top,
5736 page_right,
5737 page_bottom;
5738 int hub_size = 0;
5739
5740 #if 0
5741 /* needed in workaround for Oufuku Hagaki */
5742 const stp_papersize_t *pp = stpi_get_papersize_by_size(v,
5743 stp_get_page_height(v),
5744 stp_get_page_width(v));
5745
5746 if (pp)
5747 {
5748 const char *name = pp->name;
5749 if (!strcmp(name,"w420h567")) {
5750 /* workaround for Oufuku Hagaki: wrong orientation */
5751 privdata->page_width = stp_get_width(v);
5752 privdata->page_height = stp_get_height(v);
5753 stp_set_page_width(v, privdata->page_height);
5754 stp_set_page_height(v, privdata->page_width);
5755 }
5756 }
5757 #endif
5758
5759 if (cd_type && (strcmp(cd_type, "CDCustom") == 0 ))
5760 {
5761 int outer_diameter = stp_get_dimension_parameter(v, "CDOuterDiameter");
5762 stp_set_page_width(v, outer_diameter);
5763 stp_set_page_height(v, outer_diameter);
5764 stp_set_width(v, outer_diameter);
5765 stp_set_height(v, outer_diameter);
5766 hub_size = stp_get_dimension_parameter(v, "CDInnerDiameter");
5767 }
5768 else
5769 {
5770 const char *inner_radius_name = stp_get_string_parameter(v, "CDInnerRadius");
5771 hub_size = 43 * 10 * 72 / 254; /* 43 mm standard CD hub */
5772
5773 if (inner_radius_name && strcmp(inner_radius_name, "Small") == 0)
5774 hub_size = 16 * 10 * 72 / 254; /* 15 mm prints to the hole - play it
5775 safe and print 16 mm */
5776 }
5777
5778 privdata->top = stp_get_top(v);
5779 privdata->left = stp_get_left(v);
5780 privdata->out_width = stp_get_width(v); /* check Epson: page_true_width */
5781 privdata->out_height = stp_get_height(v); /* check Epson: page_true_height */
5782
5783 stp_dprintf(STP_DBG_CANON, v,"stp_get_width: privdata->out_width is %i\n",privdata->out_width);
5784 stp_dprintf(STP_DBG_CANON, v,"stp_get_height: privdata->out_height is %i\n",privdata->out_height);
5785
5786 /* Don't use full bleed mode if the paper itself has a margin */
5787 if (privdata->left > 0 || privdata->top > 0)
5788 stp_set_boolean_parameter(v, "FullBleed", 0);
5789
5790 internal_imageable_area(v, 0, 0, &page_left, &page_right,
5791 &page_bottom, &page_top);
5792 if (print_cd) {
5793 privdata->cd_inner_radius = hub_size / 2;
5794 privdata->cd_outer_radius = stp_get_width(v) / 2;
5795 privdata->left = CANON_CD_X - privdata->cd_outer_radius + stp_get_dimension_parameter(v, "CDXAdjustment");;
5796 privdata->top = CANON_CD_Y - privdata->cd_outer_radius + stp_get_dimension_parameter(v, "CDYAdjustment");
5797 privdata->page_width = privdata->left + privdata->out_width;
5798 privdata->page_height = privdata->top + privdata->out_height;
5799 } else {
5800 privdata->left -= page_left;
5801 privdata->top -= page_top; /* checked in Epson: matches */
5802 privdata->page_width = page_right - page_left; /* checked in Epson: matches */
5803 privdata->page_height = page_bottom - page_top; /* checked in Epson: matches */
5804 }
5805
5806 stp_dprintf(STP_DBG_CANON, v, "setup_page page_top = %f\n",page_top);
5807 stp_dprintf(STP_DBG_CANON, v, "setup_page page_bottom = %f\n",page_bottom);
5808 stp_dprintf(STP_DBG_CANON, v, "setup_page page_left = %f\n",page_left);
5809 stp_dprintf(STP_DBG_CANON, v, "setup_page page_right = %f\n",page_right);
5810 stp_dprintf(STP_DBG_CANON, v, "setup_page top = %i\n",privdata->top);
5811 stp_dprintf(STP_DBG_CANON, v, "setup_page left = %i\n",privdata->left);
5812 stp_dprintf(STP_DBG_CANON, v, "setup_page out_height = %i\n",privdata->out_height);
5813 stp_dprintf(STP_DBG_CANON, v, "setup_page page_height = %i\n",privdata->page_height);
5814 stp_dprintf(STP_DBG_CANON, v, "setup_page page_width = %i\n",privdata->page_width);
5815
5816 }
5817
5818
5819 /* combine all curve parameters in s and apply them */
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)5820 static 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){
5821 const char * s[3];
5822 size_t count = sizeof(s) / sizeof(s[0]);
5823 stp_curve_t *ret = NULL;
5824 int curve_count = 0;
5825 int i;
5826 const size_t piecewise_point_count = 384;
5827
5828
5829 /* ignore settings from the printercaps if the user specified his own parameters */
5830 if(stp_check_curve_parameter(v,type, STP_PARAMETER_ACTIVE))
5831 return;
5832
5833 /* init parameter list (FIXME pass array directly???)*/
5834 s[0] = s1;
5835 s[1] = s2;
5836 s[2] = s3;
5837
5838 /* skip empty curves */
5839 for(i=0;i<count;i++){
5840 if(s[i])
5841 s[curve_count++] = s[i];
5842 }
5843
5844 /* combine curves */
5845 if(curve_count){
5846 for(i=0;i<curve_count;i++){
5847 stp_curve_t* t_tmp = stp_curve_create_from_string(s[i]);
5848 if(t_tmp){
5849 if(stp_curve_is_piecewise(t_tmp)){
5850 stp_curve_resample(t_tmp, piecewise_point_count);
5851 }
5852 if(!ret){
5853 ret = t_tmp;
5854 }else{
5855 stp_curve_t* t_comp = NULL;
5856 stp_curve_compose(&t_comp, ret, t_tmp, comp, -1);
5857 if(t_comp){
5858 stp_curve_destroy(ret);
5859 ret = t_comp;
5860 }
5861 stp_curve_destroy(t_tmp);
5862 }
5863 }
5864 }
5865 }
5866
5867 /* apply result */
5868 if(ret){
5869 stp_set_curve_parameter(v, type, ret);
5870 stp_curve_destroy(ret);
5871 }
5872 }
5873
5874 /*
5875 * 'canon_print()' - Print an image to a CANON printer.
5876 */
5877 static int
canon_do_print(stp_vars_t * v,stp_image_t * image)5878 canon_do_print(stp_vars_t *v, stp_image_t *image)
5879 {
5880 int i;
5881 int status = 1;
5882 const char *media_source = stp_get_string_parameter(v, "InputSlot");
5883 const char *ink_type = stp_get_string_parameter(v, "InkType");
5884 const char *duplex_mode = stp_get_string_parameter(v, "Duplex");
5885 int page_number = stp_get_int_parameter(v, "PageNumber");
5886 const canon_cap_t * caps = canon_get_model_capabilities(v);
5887 const canon_modeuselist_t* mlist = caps->modeuselist;
5888 #if 0
5889 const canon_modeuse_t* muse;
5890 #endif
5891 /* int monocheck = 0;
5892 int colcheck = 0; */
5893 int x,y; /* Looping vars */
5894 canon_privdata_t privdata;
5895 int errdiv, /* Error dividend */
5896 errmod, /* Error modulus */
5897 errval, /* Current error value */
5898 errline, /* Current raster line */
5899 errlast; /* Last raster line loaded */
5900 #if 0
5901 out_channels; /* Output bytes per pixel */
5902 #endif
5903 unsigned zero_mask;
5904 int print_cd = (media_source && (!strcmp(media_source, "CD")));
5905 int image_height;
5906 #if 0
5907 int image_width;
5908 #endif
5909 double k_upper, k_lower;
5910 unsigned char *cd_mask = NULL;
5911 double outer_r_sq = 0;
5912 double inner_r_sq = 0;
5913 unsigned char* weave_cols[4] ; /* TODO clean up weaving code to be more generic */
5914
5915 stp_dprintf(STP_DBG_CANON, v, "Entering canon_do_print\n");
5916
5917 if (!stp_verify(v))
5918 {
5919 stp_eprintf(v, "Print options not verified; cannot print.\n");
5920 return 0;
5921 }
5922 /*
5923 * Setup a read-only pixel region for the entire image...
5924 */
5925
5926 stp_image_init(image);
5927
5928
5929 /* rotate even pages for DuplexNoTumble */
5930 if((page_number & 1) && duplex_mode && !strcmp(duplex_mode,"DuplexNoTumble"))
5931 image = stpi_buffer_image(image,BUFFER_FLAG_FLIP_X | BUFFER_FLAG_FLIP_Y);
5932
5933 memset(&privdata,0,sizeof(canon_privdata_t));
5934 privdata.caps = caps;
5935
5936 /* find the wanted media type */
5937 /* - media type has priority
5938 - then we select source
5939 - then inkset (cartridge selection)
5940 - then we select duplex
5941 - after that we compare if mode is compatible with media
5942 - if not, we replace it using closest quality setting
5943 - then we decide on printhead colors based on actual mode to use
5944 */
5945
5946 privdata.pt = get_media_type(caps,stp_get_string_parameter(v, "MediaType"));
5947 privdata.slot = canon_source_type(media_source,caps);
5948
5949 /* --- make adjustment to InkSet based on Media --- */
5950
5951 /* cartridge selection if any: default is Both---but should change to NULL if CANON_CAP_T is not available */
5952 /* check if InkSet chosen is possible for this Media */
5953 /* - if Black, check if modes for selected media have a black flag */
5954 /* else, set InkSet to "Both" for now */
5955
5956 /* scroll through modeuse list to find media */
5957 for(i=0;i<mlist->count;i++){
5958 if(!strcmp(privdata.pt->name,mlist->modeuses[i].name)){
5959 #if 0
5960 muse = &mlist->modeuses[i];
5961 #endif
5962 break;
5963 }
5964 }
5965
5966 if ( !strcmp(stp_get_string_parameter(v, "InkSet"),"Black")) {
5967 /* check if there is any mode for that media with K-only inktype */
5968 /* if not, change it to "Both" */
5969 /* NOTE: User cannot force monochrome printing here, since that would require changing the Color Model */
5970 if (!(mlist->modeuses[i].use_flags & INKSET_BLACK_SUPPORT)) {
5971 stp_set_string_parameter(v, "InkSet", "Both");
5972 }
5973 }
5974 /* Color-only */
5975 else if ( !strcmp(stp_get_string_parameter(v, "InkSet"),"Color") && (caps->features & CANON_CAP_T) ) {
5976 /* check if there is any mode for that media with no K in the inkset at all */
5977 /* if not, change it to "Both" */
5978 if (!(mlist->modeuses[i].use_flags & INKSET_COLOR_SUPPORT)) {
5979 stp_set_string_parameter(v, "InkSet", "Both");
5980 }
5981 }
5982 /* no restriction for "Both" (non-BJC) or "Color" (BJC) or "Photo" yet */
5983
5984 /* get InkSet after adjustment */
5985 privdata.ink_set = stp_get_string_parameter(v, "InkSet");
5986
5987 /* --- no current restrictions for Duplex setting --- */
5988
5989 /* in particular, we do not constrain duplex printing to certain media */
5990 privdata.duplex_str = duplex_mode;
5991
5992 /* --- make adjustment to InkType to comply with InkSet --- */
5993
5994 /* although InSet adjustment is pre-supposed, even if InkSet is not
5995 adjusted, the InkType adjustment will be validated against mode
5996 later */
5997 if (!strcmp(privdata.ink_set,"Black")) {
5998 if (strcmp(ink_type,"Gray")) {/* if ink_type is NOT set to Gray yet */
5999 stp_dprintf(STP_DBG_CANON, v, "canon_do_print: InkSet Black, so InkType set to Gray\n");
6000 stp_set_string_parameter(v, "InkType", "Gray");
6001 }
6002 } /* Color-only */
6003 else if ( !strcmp(privdata.ink_set,"Color") && (caps->features & CANON_CAP_T) ) {
6004 if (strcmp(ink_type,"RGB")) {/* if ink_type is NOT set to RGB (CMY) yet */
6005 stp_dprintf(STP_DBG_CANON, v, "canon_do_print: InkSet Color, so InkType changed to RGB (CMY)\n");
6006 stp_set_string_parameter(v, "InkType", "RGB");
6007 }
6008 } /* no restriction for InkSet set to "Both" or "Photo" */
6009
6010 /* --- make adjustments to mode --- */
6011
6012 /* find the wanted print mode: NULL if not yet set */
6013 stp_dprintf(STP_DBG_CANON, v, "canon_do_print: calling canon_get_current_mode\n");
6014 privdata.mode = canon_get_current_mode(v);
6015
6016 if(!privdata.mode) {
6017 privdata.mode = &caps->modelist->modes[caps->modelist->default_mode];
6018 }
6019
6020 /* then call get_current_mode again to sort out the correct matching of parameters and mode selection */
6021
6022 stp_dprintf(STP_DBG_CANON, v, "canon_do_print: calling canon_check_current_mode\n");
6023
6024 privdata.mode = canon_check_current_mode(v);
6025
6026 /* --- completed all adjustments: options should be consistent --- */
6027
6028 /* set quality */
6029 privdata.quality = privdata.mode->quality;
6030
6031
6032 /* force grayscale if image is grayscale
6033 * or single black cartridge installed
6034 */
6035 privdata.used_inks = canon_printhead_colors(v);
6036 if (privdata.used_inks == CANON_INK_K)
6037 stp_set_string_parameter(v, "PrintingMode", "BW");
6038 else
6039 stp_set_string_parameter(v, "PrintingMode", "Color");
6040
6041 setup_page(v,&privdata);
6042
6043 image_height = stp_image_height(image);
6044
6045 #if 0
6046 image_width = stp_image_width(image);
6047 #endif
6048
6049 privdata.is_first_page = (page_number == 0);
6050
6051 /*
6052 * Convert image size to printer resolution...
6053 */
6054 #if 0
6055 stp_dprintf(STP_DBG_CANON, v,"canon_do_print: unused image_width is %i pts(?)\n",image_width);
6056 #endif
6057 stp_dprintf(STP_DBG_CANON, v,"canon_do_print: privdata.out_width is %i pts\n",privdata.out_width);
6058 stp_dprintf(STP_DBG_CANON, v,"canon_do_print: privdata.out_height is %i pts\n",privdata.out_height);
6059 stp_dprintf(STP_DBG_CANON, v,"canon_do_print: privdata.left is %i pts\n",privdata.left);
6060
6061 privdata.out_width = privdata.mode->xdpi * privdata.out_width / 72;
6062 privdata.out_height = privdata.mode->ydpi * privdata.out_height / 72;
6063 privdata.left = privdata.mode->xdpi * privdata.left / 72;
6064
6065 stp_dprintf(STP_DBG_CANON, v,"canon_do_print: privdata.out_width is %i dots\n",privdata.out_width);
6066 stp_dprintf(STP_DBG_CANON, v,"canon_do_print: privdata.out_height is %i dots\n",privdata.out_height);
6067 stp_dprintf(STP_DBG_CANON, v,"canon_do_print: privdata.left is %i dots\n",privdata.left);
6068
6069 stp_dprintf(STP_DBG_CANON, v,"density is %f\n",
6070 stp_get_float_parameter(v, "Density"));
6071
6072 /*
6073 * Compute the LUT. For now, it's 8 bit, but that may eventually
6074 * sometimes change.
6075 */
6076
6077 if (!stp_check_float_parameter(v, "Density", STP_PARAMETER_DEFAULTED))
6078 {
6079 stp_set_float_parameter_active(v, "Density", STP_PARAMETER_ACTIVE);
6080 stp_set_float_parameter(v, "Density", 1.0);
6081 }
6082
6083 stp_scale_float_parameter(v, "Density", privdata.pt->base_density);
6084 stp_scale_float_parameter(v, "Density",privdata.mode->density);
6085
6086 if (stp_get_float_parameter(v, "Density") > 1.0)
6087 stp_set_float_parameter(v, "Density", 1.0);
6088
6089 if (privdata.used_inks == CANON_INK_K)
6090 stp_scale_float_parameter(v, "Gamma", 1.25);
6091 stp_scale_float_parameter( v, "Gamma", privdata.mode->gamma );
6092
6093 stp_dprintf(STP_DBG_CANON, v,"density is %f\n",
6094 stp_get_float_parameter(v, "Density"));
6095
6096 if(privdata.used_inks & CANON_INK_CMYK_MASK)
6097 stp_set_string_parameter(v, "STPIOutputType", "KCMY");
6098 else if(privdata.used_inks & CANON_INK_CMY_MASK)
6099 stp_set_string_parameter(v, "STPIOutputType", "CMY");
6100 /* Gernot: addition */
6101 /*else if(privdata.used_inks & CANON_INK_cmy_MASK)
6102 stp_set_string_parameter(v, "STPIOutputType", "cmy");*/
6103 else
6104 stp_set_string_parameter(v, "STPIOutputType", "Grayscale");
6105
6106 privdata.length = (privdata.out_width + 7) / 8;
6107
6108 stp_dprintf(STP_DBG_CANON, v,"privdata.length is %i\n",privdata.length);
6109 stp_dprintf(STP_DBG_CANON, v,"canon_do_print: privdata.num_channels is %i\n",privdata.num_channels);
6110
6111 stp_dither_init(v, image, privdata.out_width, privdata.mode->xdpi, privdata.mode->ydpi);
6112
6113
6114 stp_dprintf(STP_DBG_CANON, v,"privdata.out_width is %i (after stp_dither_init)\n",privdata.out_width);
6115 stp_dprintf(STP_DBG_CANON, v,"privdata.length is %i (after stp_dither_init)\n",privdata.length);
6116 stp_dprintf(STP_DBG_CANON, v,"canon_do_print: privdata.num_channels is %i (after stp_dither_init)\n",privdata.num_channels);
6117
6118 canon_setup_channels(v,&privdata);
6119
6120 stp_dprintf(STP_DBG_CANON, v,"privdata.out_width is %i (after canon_setup_channels)\n",privdata.out_width);
6121 stp_dprintf(STP_DBG_CANON, v,"privdata.length is %i (after canon_setup_channels)\n",privdata.length);
6122 stp_dprintf(STP_DBG_CANON, v,"canon_do_print: privdata.num_channels is %i (after canon_setup_channels)\n",privdata.num_channels);
6123
6124 stp_dprintf(STP_DBG_CANON, v,
6125 "canon: driver will use colors %s\n",privdata.channel_order);
6126
6127 /* Allocate compression buffer */
6128 if(caps->features & CANON_CAP_I)
6129 /*privdata.comp_buf = stp_zalloc(privdata.buf_length_max * 2 * caps->raster_lines_per_block * privdata.num_channels); */
6130 privdata.comp_buf = stp_zalloc(stp_compute_tiff_linewidth(v, privdata.buf_length_max * 2 * privdata.mode->raster_lines_per_block * privdata.num_channels)); /* for multiraster we need to buffer 8 lines for every color */
6131 else
6132 privdata.comp_buf = stp_zalloc(stp_compute_tiff_linewidth(v, privdata.buf_length_max * 2));
6133 /* Allocate fold buffer */
6134 privdata.fold_buf = stp_zalloc(stp_compute_tiff_linewidth(v, privdata.buf_length_max));
6135
6136
6137
6138 /*
6139 * Output the page...
6140 */
6141
6142 /* FIXME this is probably broken, kept for backward compatibility */
6143 if(privdata.num_channels > 4){
6144 k_lower = 0.4 / privdata.channels[4].props->bits + .1;
6145 }else
6146 k_lower = 0.25;
6147
6148 k_lower *= privdata.pt->k_lower_scale;
6149 k_upper = privdata.pt->k_upper;
6150
6151 if (!stp_check_float_parameter(v, "GCRLower", STP_PARAMETER_ACTIVE))
6152 stp_set_default_float_parameter(v, "GCRLower", k_lower);
6153 if (!stp_check_float_parameter(v, "GCRUpper", STP_PARAMETER_ACTIVE))
6154 stp_set_default_float_parameter(v, "GCRUpper", k_upper);
6155
6156
6157 /* init the printer */
6158 canon_init_printer(v, &privdata);
6159
6160 /* initialize weaving for S200 for resolutions > 360dpi */
6161 if (privdata.mode->flags & MODE_FLAG_WEAVE)
6162 {
6163 char weave_color_order[] = "KCMY";
6164
6165 privdata.stepper_ydpi = 720;
6166 privdata.nozzle_ydpi = 360;
6167 if (privdata.mode->xdpi == 2880)
6168 privdata.physical_xdpi = 2880;
6169 else
6170 privdata.physical_xdpi = 720;
6171
6172 stp_dprintf(STP_DBG_CANON, v,"canon: adjust leftskip: old=%d,\n", privdata.left);
6173 privdata.left = (int)( (float)privdata.left * (float)privdata.physical_xdpi / (float)privdata.mode->xdpi ); /* adjust left margin */
6174 stp_dprintf(STP_DBG_CANON, v,"canon: adjust leftskip: new=%d,\n", privdata.left);
6175
6176 privdata.ncolors = 4;
6177 privdata.head_offset = stp_zalloc(sizeof(int) * privdata.ncolors);
6178 memset(privdata.head_offset, 0, sizeof(*privdata.head_offset));
6179
6180 if ( privdata.used_inks == CANON_INK_K )
6181 privdata.nozzles = 64; /* black nozzles */
6182 else
6183 privdata.nozzles = 24; /* color nozzles */
6184 if ( privdata.used_inks == CANON_INK_K )
6185 {
6186 privdata.ncolors = 1;
6187 privdata.head_offset[0] = 0; /* K starts at 0 */
6188 privdata.head_offset[1] = 0 ;/* how far C starts after K */
6189 privdata.head_offset[2] = 0;/* how far M starts after K */
6190 privdata.head_offset[3] = 0;/* how far Y starts after K */
6191 privdata.top += 11;
6192 }
6193 else if ( privdata.used_inks == CANON_INK_CMYK )
6194 {
6195 privdata.head_offset[0] = 0; /* K starts at 0 */
6196 privdata.head_offset[1] = 144 ;/* how far C starts after K */
6197 privdata.head_offset[2] = 144 + 64;/* how far M starts after K */
6198 privdata.head_offset[3] = 144 + 64 + 64;/* how far Y starts after K */
6199 privdata.top += 5;
6200 }
6201 else /* colormode == CMY */
6202 {
6203 privdata.ncolors = 3;
6204 privdata.head_offset[0] = 0; /* K starts at 0 */
6205 privdata.head_offset[1] = 0 ;/* how far C starts after K */
6206 privdata.head_offset[2] = 64;/* how far M starts after K */
6207 privdata.head_offset[3] = 128;/* how far Y starts after K */
6208 privdata.top += 18;
6209 }
6210
6211 privdata.nozzle_separation = privdata.stepper_ydpi / privdata.nozzle_ydpi;
6212 privdata.horizontal_passes = privdata.mode->xdpi / privdata.physical_xdpi;
6213 privdata.vertical_passes = 1;
6214 privdata.vertical_oversample = privdata.mode->ydpi / privdata.stepper_ydpi;
6215 privdata.bidirectional = 1; /* 1: bidirectional; 0: unidirectional printing */
6216 privdata.direction = 1;
6217 stp_allocate_component_data(v, "Driver", NULL, NULL, &privdata);
6218 stp_dprintf(STP_DBG_CANON, v,"canon: initializing weaving: nozzles=%d, nozzle_separation=%d,\n"
6219 "horizontal_passes=%d, vertical_passes=%d,vertical_oversample=%d,\n"
6220 "ncolors=%d, out_width=%d, out_height=%d\n"
6221 "weave_top=%d, weave_page_height=%d \n"
6222 "head_offset=[%d,%d,%d,%d] \n",
6223 privdata.nozzles, privdata.nozzle_separation,
6224 privdata.horizontal_passes, privdata.vertical_passes,
6225 privdata.vertical_oversample, privdata.ncolors,
6226 privdata.out_width, privdata.out_height,
6227 privdata.top * privdata.stepper_ydpi / 72, privdata.page_height * privdata.stepper_ydpi / 72,
6228 privdata.head_offset[0],privdata.head_offset[1],
6229 privdata.head_offset[2],privdata.head_offset[3]);
6230
6231 stp_initialize_weave(v, privdata.nozzles, privdata.nozzle_separation,
6232 privdata.horizontal_passes, privdata.vertical_passes,
6233 privdata.vertical_oversample, privdata.ncolors,
6234 1,
6235 privdata.out_width, privdata.out_height,
6236 privdata.top * privdata.stepper_ydpi / 72,
6237 privdata.page_height * privdata.stepper_ydpi / 72,
6238 privdata.head_offset,
6239 STP_WEAVE_ZIGZAG,
6240 canon_flush_pass,
6241 stp_fill_uncompressed,
6242 stp_pack_uncompressed,
6243 stp_compute_tiff_linewidth);
6244 privdata.last_pass_offset = 0;
6245
6246 if (stp_get_debug_level() & STP_DBG_CANON) {
6247 for(x=0;x<4;x++){
6248 stp_dprintf(STP_DBG_CANON, v, "DEBUG print-canon weave: weave_color_order[%d]: %u\n",
6249 x, (unsigned int)weave_color_order[x]);
6250 }
6251 for(x=0;x<privdata.num_channels;x++){
6252 stp_dprintf(STP_DBG_CANON, v, "DEBUG print-canon weave: channel_order[%d]: %u\n",
6253 x, (unsigned int)privdata.channel_order[x]);
6254 }
6255 }
6256
6257 for(i=0;i<4;i++){/* need all 4 channels for weave_cols, but not for privdata.num_channels! */
6258 /* see if it helps to initialize to zero */
6259 weave_cols[i] = 0;
6260 privdata.weave_bits[i] = 0;
6261
6262 for(x=0;x<privdata.num_channels;x++){
6263 if(weave_color_order[i] == privdata.channel_order[x]){
6264 weave_cols[i] = privdata.channels[x].buf;
6265 privdata.weave_bits[i] = privdata.channels[x].props->bits;
6266 stp_dprintf(STP_DBG_CANON, v, "DEBUG print-canon weave: set weave_cols[%d] to privdata.channels[%d].buf\n",
6267 i, x);
6268 }
6269 }
6270 }
6271 }
6272
6273
6274 errdiv = image_height / privdata.out_height;
6275 errmod = image_height % privdata.out_height;
6276 errval = 0;
6277 errlast = -1;
6278 errline = 0;
6279
6280 /* set Hue, Lum and Sat Maps */
6281 canon_set_curve_parameter(v,"HueMap",STP_CURVE_COMPOSE_ADD,caps->hue_adjustment,privdata.pt->hue_adjustment,privdata.mode->hue_adjustment);
6282 canon_set_curve_parameter(v,"LumMap",STP_CURVE_COMPOSE_MULTIPLY,caps->lum_adjustment,privdata.pt->lum_adjustment,privdata.mode->lum_adjustment);
6283 canon_set_curve_parameter(v,"SatMap",STP_CURVE_COMPOSE_MULTIPLY,caps->sat_adjustment,privdata.pt->sat_adjustment,privdata.mode->sat_adjustment);
6284
6285 #if 0
6286 out_channels = stp_color_init(v, image, 65536);
6287 #endif
6288 (void) stp_color_init(v, image, 65536);
6289 stp_allocate_component_data(v, "Driver", NULL, NULL, &privdata);
6290
6291 privdata.emptylines = 0;
6292 if (print_cd) {
6293 cd_mask = stp_malloc(1 + (privdata.out_width + 7) / 8);
6294 outer_r_sq = (double)privdata.cd_outer_radius * (double)privdata.cd_outer_radius;
6295 inner_r_sq = (double)privdata.cd_inner_radius * (double)privdata.cd_inner_radius;
6296 }
6297 for (y = 0; y < privdata.out_height; y ++)
6298 {
6299 int duplicate_line = 1;
6300
6301 if (errline != errlast)
6302 {
6303 errlast = errline;
6304 duplicate_line = 0;
6305 if (stp_color_get_row(v, image, errline, &zero_mask))
6306 {
6307 status = 2;
6308 break;
6309 }
6310 }
6311 if (print_cd)
6312 {
6313 int x_center = privdata.cd_outer_radius * privdata.mode->xdpi / 72;
6314 int y_distance_from_center =
6315 privdata.cd_outer_radius - (y * 72 / privdata.mode->ydpi);
6316 if (y_distance_from_center < 0)
6317 y_distance_from_center = -y_distance_from_center;
6318 memset(cd_mask, 0, (privdata.out_width + 7) / 8);
6319 if (y_distance_from_center < privdata.cd_outer_radius)
6320 {
6321 double y_sq = (double) y_distance_from_center *
6322 (double) y_distance_from_center;
6323 int x_where = sqrt(outer_r_sq - y_sq) + .5;
6324 int scaled_x_where = x_where * privdata.mode->xdpi / 72;
6325 set_mask(cd_mask, x_center, scaled_x_where,
6326 privdata.out_width, 1, 0);
6327 if (y_distance_from_center < privdata.cd_inner_radius)
6328 {
6329 x_where = sqrt(inner_r_sq - y_sq) + .5;
6330 scaled_x_where = x_where * privdata.mode->ydpi / 72;
6331 set_mask(cd_mask, x_center, scaled_x_where,
6332 privdata.out_width, 1, 1);
6333 }
6334 }
6335 }
6336 stp_dither(v, y, duplicate_line, zero_mask, cd_mask);
6337 if ( privdata.mode->flags & MODE_FLAG_WEAVE )
6338 stp_write_weave(v, weave_cols);
6339 else if ( caps->features & CANON_CAP_I)
6340 canon_write_multiraster(v,&privdata,y);
6341 else
6342 canon_printfunc(v);
6343 errval += errmod;
6344 errline += errdiv;
6345 if (errval >= privdata.out_height)
6346 {
6347 errval -= privdata.out_height;
6348 errline ++;
6349 }
6350 }
6351
6352 if ( privdata.mode->flags & MODE_FLAG_WEAVE )
6353 {
6354 stp_flush_all(v);
6355 canon_advance_paper(v, 5);
6356 }
6357 else
6358 {
6359
6360 /*
6361 * Flush delayed buffers...
6362 */
6363
6364 if (privdata.delay_max) {
6365 stp_dprintf(STP_DBG_CANON, v,"\ncanon: flushing %d possibly delayed buffers\n",
6366 privdata.delay_max);
6367 for (y= 0; y<privdata.delay_max; y++) {
6368
6369 canon_write_line(v);
6370 for (i = 0; i < privdata.num_channels; i++)
6371 canon_advance_buffer(privdata.channels[i].buf, privdata.length,
6372 privdata.channels[i].delay);
6373 }
6374 }
6375 }
6376 stp_image_conclude(image);
6377
6378 /*
6379 * Cleanup...
6380 */
6381
6382 stp_free(privdata.fold_buf);
6383 stp_free(privdata.comp_buf);
6384
6385 if(cd_mask)
6386 stp_free(cd_mask);
6387
6388
6389 canon_deinit_printer(v, &privdata);
6390 /* canon_end_job does not get called for jobmode automatically */
6391 if(!stp_get_string_parameter(v, "JobMode") ||
6392 strcmp(stp_get_string_parameter(v, "JobMode"), "Page") == 0){
6393 canon_end_job(v,image);
6394 }
6395
6396 for(i=0;i< privdata.num_channels;i++)
6397 if(privdata.channels[i].buf)
6398 stp_free(privdata.channels[i].buf);
6399 if(privdata.channels)
6400 stp_free(privdata.channels);
6401
6402 stp_free(privdata.channel_order);
6403 if (privdata.head_offset)
6404 stp_free(privdata.head_offset);
6405
6406
6407 return status;
6408 }
6409
6410 static int
canon_print(const stp_vars_t * v,stp_image_t * image)6411 canon_print(const stp_vars_t *v, stp_image_t *image)
6412 {
6413 int status;
6414 stp_vars_t *nv = stp_vars_create_copy(v);
6415 status = canon_do_print(nv, image);
6416 stp_vars_destroy(nv);
6417 return status;
6418 }
6419
6420 static const stp_printfuncs_t print_canon_printfuncs =
6421 {
6422 canon_list_parameters,
6423 canon_parameters,
6424 stp_default_media_size,
6425 canon_imageable_area,
6426 canon_maximum_imageable_area,
6427 canon_limit,
6428 canon_print,
6429 canon_describe_resolution,
6430 canon_describe_output,
6431 stp_verify_printer_params,
6432 canon_start_job,
6433 canon_end_job,
6434 NULL,
6435 stpi_standard_describe_papersize
6436 };
6437
6438 static void
canon_shift_buffer(unsigned char * line,int length,int bits)6439 canon_shift_buffer(unsigned char *line,int length,int bits)
6440 {
6441 int i,j;
6442 for (j=0; j<bits; j++) {
6443 for (i=length-1; i>0; i--) {
6444 line[i]= (line[i] >> 1) | (line[i-1] << 7);
6445 }
6446 line[0] = line[0] >> 1;
6447 }
6448 }
6449
6450
6451 /* fold, apply the necessary compression, pack tiff and return the compressed length */
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)6452 static 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)
6453 {
6454 unsigned char
6455 *in_ptr= line,
6456 *comp_ptr, *comp_data;
6457 int offset2,bitoffset;
6458
6459 /* Don't send blank lines... */
6460
6461 if (line[0] == 0 && memcmp(line, line + 1, (length * bits) - 1) == 0)
6462 return 0;
6463
6464 /* if no modulation: 1 bit per pixel */
6465
6466 offset2 = offset / 8;
6467 bitoffset = offset % 8;
6468
6469 /* fold lsb/msb pairs if drop modulation is active */
6470
6471 if (bits==2) {
6472 int pixels_per_byte = 4;
6473 if(ink_flags & INK_FLAG_5pixel_in_1byte)
6474 pixels_per_byte = 5;
6475
6476 stp_fold(line,length,pd->fold_buf);
6477 in_ptr = pd->fold_buf;
6478 length = (length*8/4); /* 4 pixels in 8bit */
6479 /* calculate the number of compressed bytes that can be sent directly */
6480 offset2 = offset / pixels_per_byte;
6481 /* calculate the number of (uncompressed) bits that have to be added to the raster data */
6482 bitoffset = (offset % pixels_per_byte) * 2;
6483 }
6484 else if (bits==3) {
6485 stp_fold_3bit_323(line,length,pd->fold_buf);
6486 in_ptr = pd->fold_buf;
6487 length = (length*8)/3;
6488 offset2 = offset/3;
6489 #if 0
6490 switch(offset%3){
6491 case 0: offset= (offset/3)*8; break;
6492 case 1: offset= (offset/3)*8/*+3 CAREFUL! CANNOT SHIFT _AFTER_ RECODING!!*/; break;
6493 case 2: offset= (offset/3)*8/*+5 CAREFUL! CANNOT SHIFT _AFTER_ RECODING!!*/; break;
6494 }
6495 #endif
6496 bitoffset= 0;
6497 }
6498 else if (bits==4) {
6499 int pixels_per_byte = 2;
6500 if(ink_flags & INK_FLAG_3pixel5level_in_1byte)
6501 pixels_per_byte = 3;
6502 else if(ink_flags & INK_FLAG_3pixel6level_in_1byte)
6503 pixels_per_byte = 3;
6504
6505 stp_fold_4bit(line,length,pd->fold_buf);
6506 in_ptr = pd->fold_buf;
6507 length = (length*8)/2; /* 2 pixels in 8 bits */
6508 /* calculate the number of compressed bytes that can be sent directly */
6509 offset2 = offset / pixels_per_byte;
6510 /* calculate the number of (uncompressed) bits that have to be added to the raster data */
6511 bitoffset = (offset % pixels_per_byte) * 2; /* not sure what this value means */
6512 }
6513 else if (bits==8) {
6514 stp_fold_8bit(line,length,pd->fold_buf);
6515 in_ptr= pd->fold_buf;
6516 length = length*8; /* 1 pixel per 8 bits */
6517 offset2 = offset;
6518 bitoffset = 0;
6519 }
6520
6521 /* pack left border rounded to multiples of 8 dots */
6522
6523 comp_data= comp_buf;
6524
6525 while (offset2>0) {
6526 unsigned char toffset = offset2 > 127 ? 127 : offset2;
6527 comp_data[0] = 1 - toffset;
6528 comp_data[1] = 0;
6529 comp_data += 2;
6530 offset2-= toffset;
6531 }
6532 if (bitoffset) {
6533 if (bitoffset<8)
6534 {
6535 in_ptr[ length++ ] = 0;
6536 canon_shift_buffer(in_ptr,length,bitoffset);
6537 }
6538 else if (bitoffset == 8)
6539 {
6540 memmove(in_ptr + 1,in_ptr,length++);
6541 in_ptr[0] = 0;
6542 }
6543 else
6544 stp_dprintf(STP_DBG_CANON, v,"SEVERE BUG IN print-canon.c::canon_write() "
6545 "bitoffset=%d!!\n",bitoffset);
6546 }
6547
6548 if(ink_flags & INK_FLAG_5pixel_in_1byte)
6549 length = pack_pixels(in_ptr,length);
6550 else if(ink_flags & INK_FLAG_3pixel5level_in_1byte)
6551 length = pack_pixels3_5(in_ptr,length);
6552 else if(ink_flags & INK_FLAG_3pixel6level_in_1byte)
6553 length = pack_pixels3_6(in_ptr,length);
6554
6555
6556 stp_pack_tiff(v, in_ptr, length, comp_data, &comp_ptr, NULL, NULL);
6557
6558 return comp_ptr - comp_buf;
6559 }
6560
6561 /*
6562 * 'canon_write()' - Send graphics using TIFF packbits compression.
6563 */
6564
6565 static int
canon_write(stp_vars_t * v,canon_privdata_t * pd,const canon_cap_t * caps,unsigned char * line,int length,int coloridx,int * empty,int width,int offset,int bits,int ink_flags)6566 canon_write(stp_vars_t *v, /* I - Print file or command */
6567 canon_privdata_t *pd, /* privdata */
6568 const canon_cap_t * caps, /* I - Printer model */
6569 unsigned char *line, /* I - Output bitmap data */
6570 int length, /* I - Length of bitmap data */
6571 int coloridx, /* I - Which color */
6572 int *empty, /* IO- Preceding empty lines */
6573 int width, /* I - Printed width */
6574 int offset, /* I - Offset from left side */
6575 int bits,
6576 int ink_flags)
6577 {
6578
6579 unsigned char color;
6580 int newlength = canon_compress(v,pd,line,length,offset,pd->comp_buf,bits,ink_flags);
6581 if(!newlength)
6582 return 0;
6583 /* send packed empty lines if any */
6584
6585 if (*empty) {
6586 stp_zfwrite("\033\050\145\002\000", 5, 1, v);
6587 stp_put16_be(*empty, v);
6588 *empty= 0;
6589 }
6590
6591 /* Send a line of raster graphics... */
6592
6593 stp_zfwrite("\033\050\101", 3, 1, v);
6594 stp_put16_le(newlength + 1, v);
6595 color= "CMYKcmyk"[coloridx];
6596 if (!color) color= 'K';
6597 stp_putc(color,v);
6598 stp_zfwrite((const char *)pd->comp_buf, newlength, 1, v);
6599 stp_putc('\015', v);
6600 return 1;
6601 }
6602
6603
6604 static void
canon_write_line(stp_vars_t * v)6605 canon_write_line(stp_vars_t *v)
6606 {
6607 canon_privdata_t *pd =
6608 (canon_privdata_t *) stp_get_component_data(v, "Driver");
6609 char write_sequence[] = "KYMCymck";
6610 static const int write_number[] = { 3, 2, 1, 0, 6, 5, 4, 7 }; /* KYMCymc */
6611 int i;
6612 int written= 0;
6613 for (i = 0; i < strlen(write_sequence) ; i++)
6614 {
6615 int x;
6616 const canon_channel_t* channel=NULL;
6617 int num = write_number[i];
6618
6619 /* TODO optimize => move reorder code to do_print */
6620 for(x=0;x < pd->num_channels; x++){
6621 if(pd->channels[x].name == write_sequence[i]){
6622 channel = &(pd->channels[x]);
6623 break;
6624 }
6625 }
6626 if(channel){
6627 written += canon_write(v, pd, pd->caps,
6628 channel->buf + channel->delay * pd->length /*buf_length[i]*/,
6629 pd->length, num,
6630 &(pd->emptylines), pd->out_width,
6631 pd->left, channel->props->bits, channel->props->flags);
6632 }
6633 }
6634 if (written)
6635 stp_zfwrite("\033\050\145\002\000\000\001", 7, 1, v);
6636 else
6637 pd->emptylines += 1;
6638 }
6639
6640
6641 /* write one multiraster block */
canon_write_block(stp_vars_t * v,canon_privdata_t * pd,unsigned char * start,unsigned char * end)6642 static void canon_write_block(stp_vars_t* v,canon_privdata_t* pd,unsigned char* start, unsigned char* end){
6643 unsigned int length = end - start;
6644 if(!length)
6645 return;
6646 stp_zfwrite("\033(F", 3, 1, v);
6647 stp_put16_le(length, v);
6648 stp_zfwrite((const char *)start, length, 1, v);
6649 }
6650
6651
canon_write_multiraster(stp_vars_t * v,canon_privdata_t * pd,int y)6652 static void canon_write_multiraster(stp_vars_t *v,canon_privdata_t* pd,int y){
6653 int i;
6654 /*int raster_lines_per_block = pd->caps->raster_lines_per_block;*/
6655 int raster_lines_per_block = pd->mode->raster_lines_per_block;
6656 unsigned int max_length = 2*pd->buf_length_max * raster_lines_per_block;
6657 /* a new raster block begins */
6658 if(!(y % raster_lines_per_block)){
6659 if(y != 0){
6660 /* write finished blocks */
6661 for(i=0;i<pd->num_channels;i++)
6662 canon_write_block(v,pd,pd->comp_buf + i * max_length,pd->channels[i].comp_buf_offset);
6663 }
6664 /* reset start offsets */
6665 for(i=0;i<pd->num_channels;i++)
6666 pd->channels[i].comp_buf_offset = pd->comp_buf + i * max_length;
6667 }
6668 /* compress lines and add them to the buffer */
6669 for(i=0;i<pd->num_channels;i++){
6670 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);
6671 *(pd->channels[i].comp_buf_offset) = 0x80; /* terminate the line */
6672 ++pd->channels[i].comp_buf_offset;
6673 }
6674 if(y == pd->out_height - 1){
6675 /* we just compressed our last line */
6676 if(pd->out_height % raster_lines_per_block){
6677 /* but our raster block is not finished yet */
6678 int missing = raster_lines_per_block - (pd->out_height % raster_lines_per_block); /* calculate missing lines */
6679 for(i=0;i<pd->num_channels;i++){
6680 /* add missing empty lines and write blocks */
6681 int x;
6682 for(x=0;x < missing ; x++){
6683 *(pd->channels[i].comp_buf_offset) = 0x80; /* terminate the line */
6684 ++pd->channels[i].comp_buf_offset;
6685 }
6686 canon_write_block(v,pd,pd->comp_buf + i * max_length,pd->channels[i].comp_buf_offset);
6687 }
6688 }
6689 }
6690 }
6691
6692
6693 static void
canon_advance_paper(stp_vars_t * v,int advance)6694 canon_advance_paper(stp_vars_t *v, int advance)
6695 {
6696 if ( advance > 0 )
6697 {
6698 int a0, a1, a2, a3;
6699 stp_dprintf(STP_DBG_CANON, v," --advance paper %d\n", advance);
6700 a0 = advance & 0xff;
6701 a1 = (advance >> 8) & 0xff;
6702 a2 = (advance >> 16) & 0xff;
6703 a3 = (advance >> 24) & 0xff;
6704 stp_zprintf(v, "\033(e%c%c%c%c%c%c", 4, 0, a3, a2, a1, a0);
6705 }
6706 }
6707
6708 static void
canon_flush_pass(stp_vars_t * v,int passno,int vertical_subpass)6709 canon_flush_pass(stp_vars_t *v, int passno, int vertical_subpass)
6710 {
6711 stp_lineoff_t *lineoffs = stp_get_lineoffsets_by_pass(v, passno);
6712 stp_lineactive_t *lineactive = stp_get_lineactive_by_pass(v, passno);
6713 const stp_linebufs_t *bufs = stp_get_linebases_by_pass(v, passno);
6714 stp_pass_t *pass = stp_get_pass_by_pass(v, passno);
6715 stp_linecount_t *linecount = stp_get_linecount_by_pass(v, passno);
6716 canon_privdata_t *pd = (canon_privdata_t *) stp_get_component_data(v, "Driver");
6717 int papershift = (pass->logicalpassstart - pd->last_pass_offset);
6718
6719 int color, line, written = 0, linelength = 0, lines = 0;
6720 int idx[4]={3, 0, 1, 2}; /* color numbering is different between canon_write and weaving */
6721
6722 stp_dprintf(STP_DBG_CANON, v,"canon_flush_pass: ----pass=%d,---- \n", passno);
6723 (pd->emptylines) = 0;
6724
6725 for ( color = 0; color < pd->ncolors; color++ ) /* find max. linecount */
6726 {
6727 if ( linecount[0].v[color] > lines )
6728 lines = linecount[0].v[color];
6729 }
6730
6731 for ( line = 0; line < lines; line++ ) /* go through each nozzle f that pass */
6732 {
6733 stp_dprintf(STP_DBG_CANON, v," --line=%d\n", line);
6734
6735 if ( written > 0 )
6736 canon_cmd(v,ESC28,0x65, 2, 0, 1); /* go to next nozzle*/
6737 /* if there was printed some data */
6738
6739 written = 0;
6740 for ( color = 0; color < pd->ncolors; color++ )
6741 {
6742 if ( line < linecount[0].v[color] ) /* try only existing lines */
6743 {
6744 if ( lineactive[0].v[color] > 0 )
6745 {
6746 linelength = lineoffs[0].v[color] / linecount[0].v[color];
6747 /* stp_dprintf(STP_DBG_CANON, v,"canon_flush_pass: linelength=%d, bufs[0].v[color]=%p,"
6748 "bufs[0].v[color]+line * linelength=%p, empty=%d \n", linelength, bufs[0].v[color],
6749 bufs[0].v[color] + line * linelength, (pd->emptylines));
6750 */
6751 if ( pass->logicalpassstart - pd->last_pass_offset > 0 )
6752 {
6753 canon_advance_paper(v, papershift);
6754 pd->last_pass_offset = pass->logicalpassstart;
6755 if (pd->bidirectional)
6756 {
6757 pd->direction = (pd->direction +1) & 1;
6758 canon_set_X72(v, pd->direction);
6759 stp_dprintf(STP_DBG_CANON, v," --set direction %d\n", pd->direction);
6760 }
6761 }
6762
6763 written += canon_write(v, pd, pd->caps,
6764 (unsigned char *)(bufs[0].v[color] + line * linelength),
6765 linelength, idx[color],
6766 &(pd->emptylines), pd->out_width,
6767 pd->left, pd->weave_bits[color],0);
6768 if (written) stp_dprintf(STP_DBG_CANON, v," --written color %d,\n", color);
6769
6770 }
6771 }
6772 }
6773
6774 if ( written == 0 ) /* count unused nozzles */
6775 (pd->emptylines) += 1;
6776 }
6777
6778 for ( color = 0; color < pd->ncolors; color++ )
6779 {
6780 lineoffs[0].v[color] = 0;
6781 linecount[0].v[color] = 0;
6782 }
6783 stp_dprintf(STP_DBG_CANON, v," --ended-- with empty=%d \n", (pd->emptylines));
6784 }
6785
6786 static stp_family_t print_canon_module_data =
6787 {
6788 &print_canon_printfuncs,
6789 NULL
6790 };
6791
6792
6793 static int
print_canon_module_init(void)6794 print_canon_module_init(void)
6795 {
6796 return stpi_family_register(print_canon_module_data.printer_list);
6797 }
6798
6799
6800 static int
print_canon_module_exit(void)6801 print_canon_module_exit(void)
6802 {
6803 return stpi_family_unregister(print_canon_module_data.printer_list);
6804 }
6805
6806
6807 /* Module header */
6808 #define stp_module_version print_canon_LTX_stp_module_version
6809 #define stp_module_data print_canon_LTX_stp_module_data
6810
6811 stp_module_version_t stp_module_version = {0, 0};
6812
6813 stp_module_t stp_module_data =
6814 {
6815 "canon",
6816 VERSION,
6817 "Canon family driver",
6818 STP_MODULE_CLASS_FAMILY,
6819 NULL,
6820 print_canon_module_init,
6821 print_canon_module_exit,
6822 (void *) &print_canon_module_data
6823 };
6824