Main Page   Modules   Alphabetical List   Data Structures   File List   Data Fields   Globals  

src/main/print-canon.c

Go to the documentation of this file.
00001 /*
00002  * "$Id: print-canon.c,v 1.147 2004/05/07 19:20:30 rleigh Exp $"
00003  *
00004  *   Print plug-in CANON BJL driver for the GIMP.
00005  *
00006  *   Copyright 1997-2000 Michael Sweet (mike@easysw.com),
00007  *      Robert Krawitz (rlk@alum.mit.edu) and
00008  *      Andy Thaller (thaller@ph.tum.de)
00009  *
00010  *   This program is free software; you can redistribute it and/or modify it
00011  *   under the terms of the GNU General Public License as published by the Free
00012  *   Software Foundation; either version 2 of the License, or (at your option)
00013  *   any later version.
00014  *
00015  *   This program is distributed in the hope that it will be useful, but
00016  *   WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
00017  *   or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
00018  *   for more details.
00019  *
00020  *   You should have received a copy of the GNU General Public License
00021  *   along with this program; if not, write to the Free Software
00022  *   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
00023  */
00024 
00025 /*
00026  * This file must include only standard C header files.  The core code must
00027  * compile on generic platforms that don't support glib, gimp, gtk, etc.
00028  */
00029 
00030 /*
00031  * Large parts of this file (mainly the ink handling) is based on
00032  * print-escp2.c -- refer to README.new-printer on how to adjust the colors
00033  * for a certain model.
00034  */
00035 
00036 /* TODO-LIST
00037  *
00038  *   * adjust the colors of all supported models
00039  *
00040  */
00041 
00042 #ifdef HAVE_CONFIG_H
00043 #include <config.h>
00044 #endif
00045 #include <gimp-print/gimp-print.h>
00046 #include "gimp-print-internal.h"
00047 #include <gimp-print/gimp-print-intl-internal.h>
00048 #include <string.h>
00049 #include <stdio.h>
00050 #if defined(HAVE_VARARGS_H) && !defined(HAVE_STDARG_H)
00051 #include <varargs.h>
00052 #else
00053 #include <stdarg.h>
00054 #endif
00055 #ifdef HAVE_LIMITS_H
00056 #include <limits.h>
00057 #endif
00058 
00059 /* Solaris with gcc has problems because gcc's limits.h doesn't #define */
00060 /* this */
00061 #ifndef CHAR_BIT
00062 #define CHAR_BIT 8
00063 #endif
00064 
00065 #if (0)
00066 #define EXPERIMENTAL_STUFF 0
00067 #endif
00068 
00069 #define MAX_CARRIAGE_WIDTH      13 /* This really needs to go away */
00070 
00071 /*
00072  * We really need to get away from this silly static nonsense...
00073  */
00074 #define MAX_PHYSICAL_BPI 1440
00075 #define MAX_OVERSAMPLED 8
00076 #define MAX_BPP 4
00077 #define COMPBUFWIDTH (MAX_PHYSICAL_BPI * MAX_OVERSAMPLED * MAX_BPP * \
00078         MAX_CARRIAGE_WIDTH / CHAR_BIT)
00079 
00080 #define MIN(a,b) (((a)<(b)) ? (a) : (b))
00081 #define MAX(a, b) ((a) > (b) ? (a) : (b))
00082 
00083 static const int channel_color_map[] =
00084 {
00085   STP_ECOLOR_K, STP_ECOLOR_C, STP_ECOLOR_M, STP_ECOLOR_Y, STP_ECOLOR_C, STP_ECOLOR_M, STP_ECOLOR_Y
00086 };
00087 
00088 static const int subchannel_color_map[] =
00089 {
00090   0, 0, 0, 0, 1, 1, 1
00091 };
00092 
00093 static const double ink_darknesses[] =
00094 {
00095   1.0, 0.31 / .5, 0.61 / .97, 0.08
00096 };
00097 
00098 #define USE_3BIT_FOLD_TYPE 323
00099 
00100 /*
00101  * For each printer, we can select from a variety of dot sizes.
00102  * For single dot size printers, the available sizes are usually 0,
00103  * which is the "default", and some subset of 1-4.  For simple variable
00104  * dot size printers (with only one kind of variable dot size), the
00105  * variable dot size is specified as 0x10.  For newer printers, there
00106  * is a choice of variable dot sizes available, 0x10, 0x11, and 0x12 in
00107  * order of increasing size.
00108  *
00109  * Normally, we want to specify the smallest dot size that lets us achieve
00110  * a density of less than .8 or thereabouts (above that we start to get
00111  * some dither artifacts).  This needs to be tested for each printer and
00112  * resolution.
00113  *
00114  * An entry of -1 in a slot means that this resolution is not available.
00115  *              0                      standard dot sizes are used.
00116  *              1                      drop modulation is used.
00117  */
00118 
00119 /* We know a per-model base resolution (like 180dpi or 150dpi)
00120  * and multipliers for the base resolution in the dotsize-, densities-
00121  * and inklist:
00122  * for 180dpi base resolution we would have
00123  *   s_r11_4 for 4color ink @180dpi
00124  *   s_r22_4 for 4color ink @360dpi
00125  *   s_r33_4 for 4color ink @720dpi
00126  *   s_r43_4 for 4color ink @1440x720dpi
00127  */
00128 
00129 typedef struct canon_dot_sizes
00130 {
00131   int dot_r11;    /*  180x180  or   150x150  */
00132   int dot_r22;    /*  360x360  or   300x300  */
00133   int dot_r33;    /*  720x720  or   600x600  */
00134   int dot_r43;    /* 1440x720  or  1200x600  */
00135   int dot_r44;    /* 1440x1440 or  1200x1200 */
00136   int dot_r55;    /* 2880x2880 or  2400x2400 */
00137 } canon_dot_size_t;
00138 
00139 /*
00140  * Specify the base density for each available resolution.
00141  *
00142  */
00143 
00144 typedef struct canon_densities
00145 {
00146   double d_r11;  /*  180x180  or   150x150  */
00147   double d_r22;  /*  360x360  or   300x300  */
00148   double d_r33;  /*  720x720  or   600x600  */
00149   double d_r43;  /* 1440x720  or  1200x600  */
00150   double d_r44;  /* 1440x1440 or  1200x1200 */
00151   double d_r55;  /* 2880x2880 or  2400x2400 */
00152 } canon_densities_t;
00153 
00154 
00155 
00156 /*
00157  * Definition of the multi-level inks available to a given printer.
00158  * Each printer may use a different kind of ink droplet for variable
00159  * and single drop size for each supported horizontal resolution and
00160  * type of ink (4 or 6 color).
00161  *
00162  * Recall that 6 color ink is treated as simply another kind of
00163  * multi-level ink, but the driver offers the user a choice of 4 and
00164  * 6 color ink, so we need to define appropriate inksets for both
00165  * kinds of ink.
00166  *
00167  * Stuff like the MIS 4 and 6 "color" monochrome inks doesn't fit into
00168  * this model very nicely, so we'll either have to special case it
00169  * or find some way of handling it in here.
00170  */
00171 
00172 typedef struct canon_variable_ink
00173 {
00174   double density;
00175   const stp_shade_t *shades;
00176   int numshades;
00177 } canon_variable_ink_t;
00178 
00179 typedef struct canon_variable_inkset
00180 {
00181   const canon_variable_ink_t *c;
00182   const canon_variable_ink_t *m;
00183   const canon_variable_ink_t *y;
00184   const canon_variable_ink_t *k;
00185 } canon_variable_inkset_t;
00186 
00187 /*
00188  * currenty unaccounted for are the 7color printers and the 3color ones
00189  * (which use CMY only printheads)
00190  *
00191  */
00192 
00193 typedef struct canon_variable_inklist
00194 {
00195   const int bits;
00196   const int colors;
00197   const canon_variable_inkset_t *r11;    /*  180x180  or   150x150  */
00198   const canon_variable_inkset_t *r22;    /*  360x360  or   300x300  */
00199   const canon_variable_inkset_t *r33;    /*  720x720  or   600x600  */
00200   const canon_variable_inkset_t *r43;    /* 1440x720  or  1200x600  */
00201   const canon_variable_inkset_t *r44;    /* 1440x1440 or  1200x1200 */
00202   const canon_variable_inkset_t *r55;    /* 2880x2880 or  2400x2400 */
00203 } canon_variable_inklist_t;
00204 
00205 
00206 #ifdef EXPERIMENTAL_STUFF
00207 /*
00208  * A printmode is defined by its resolution (xdpi x ydpi), the bits per pixel
00209  * and the installed printhead.
00210  *
00211  * For a hereby defined printmode we specify the density and gamma multipliers
00212  * and the ink definition with optional adjustments for lum, hue and sat
00213  *
00214  */
00215 typedef struct canon_variable_printmode
00216 {
00217   const int xdpi;                      /* horizontal resolution */
00218   const int ydpi;                      /* vertical resolution   */
00219   const int bits;                      /* bits per pixel        */
00220   const int printhead;                 /* installed printhead   */
00221   const int quality;                   /* maximum init-quality  */
00222   const double density;                /* density multiplier    */
00223   const double gamma;                  /* gamma multiplier      */
00224   const canon_variable_inkset_t *inks; /* ink definition        */
00225   const char *lum_adjustment;          /* optional lum adj.     */
00226   const char *hue_adjustment;          /* optional hue adj.     */
00227   const char *sat_adjustment;          /* optional sat adj.     */
00228 } canon_variable_printmode_t;
00229 #endif
00230 
00231 /* NOTE  NOTE  NOTE  NOTE  NOTE  NOTE  NOTE  NOTE  NOTE  NOTE  NOTE  NOTE
00232  *
00233  * The following dither ranges were taken from print-escp2.c and do NOT
00234  * represent the requirements of canon inks. Feel free to play with them
00235  * accoring to the escp2 part of doc/README.new-printer and send me a patch
00236  * if you get better results. Please send mail to thaller@ph.tum.de
00237  */
00238 
00239 #define DECLARE_INK(name, density)              \
00240 static const canon_variable_ink_t name##_ink =  \
00241 {                                               \
00242   density,                                      \
00243   name##_shades,                                \
00244   sizeof(name##_shades) / sizeof(stp_shade_t)   \
00245 }
00246 
00247 #define SHADE(density, name)                            \
00248 { density, sizeof(name)/sizeof(stp_dotsize_t), name }
00249 
00250 /*
00251  * Dither ranges specifically for Cyan/LightCyan (see NOTE above)
00252  *
00253  */
00254 
00255 static const stp_dotsize_t single_dotsize[] =
00256 {
00257   { 0x1, 1.0 }
00258 };
00259 
00260 static const stp_shade_t canon_Cc_1bit_shades[] =
00261 {
00262   SHADE(0.25, single_dotsize),
00263   SHADE(1.0, single_dotsize),
00264 };
00265 
00266 DECLARE_INK(canon_Cc_1bit, 0.75);
00267 
00268 /*
00269  * Dither ranges specifically for Magenta/LightMagenta (see NOTE above)
00270  *
00271  */
00272 
00273 static const stp_shade_t canon_Mm_1bit_shades[] =
00274 {
00275   SHADE(0.26, single_dotsize),
00276   SHADE(1.0, single_dotsize),
00277 };
00278 
00279 DECLARE_INK(canon_Mm_1bit, 0.75);
00280 
00281 /*
00282  * Dither ranges specifically for any Color and 2bit/pixel (see NOTE above)
00283  *
00284  */
00285 static const stp_dotsize_t two_bit_dotsize[] =
00286 {
00287   { 0x1, 0.45 },
00288   { 0x2, 0.68 },
00289   { 0x3, 1.0 }
00290 };
00291 
00292 static const stp_shade_t canon_X_2bit_shades[] =
00293 {
00294   SHADE(1.0, two_bit_dotsize)
00295 };
00296 
00297 DECLARE_INK(canon_X_2bit, 1.0);
00298 
00299 /*
00300  * Dither ranges specifically for any Color/LightColor and 2bit/pixel
00301  * (see NOTE above)
00302  */
00303 static const stp_shade_t canon_Xx_2bit_shades[] =
00304 {
00305   SHADE(0.33, two_bit_dotsize),
00306   SHADE(1.0, two_bit_dotsize),
00307 };
00308 
00309 DECLARE_INK(canon_Xx_2bit, 1.0);
00310 
00311 /*
00312  * Dither ranges specifically for any Color and 3bit/pixel
00313  * (see NOTE above)
00314  *
00315  * BIG NOTE: The bjc8200 has this kind of ink. One Byte seems to hold
00316  *           drop sizes for 3 pixels in a 3/2/2 bit fashion.
00317  *           Size values for 3bit-sized pixels range from 1 to 7,
00318  *           size values for 2bit-sized picels from 1 to 3 (kill msb).
00319  *
00320  *
00321  */
00322 static const stp_dotsize_t three_bit_dotsize[] =
00323 {
00324   { 0x1, 0.45 },
00325   { 0x2, 0.55 },
00326   { 0x3, 0.66 },
00327   { 0x4, 0.77 },
00328   { 0x5, 0.88 },
00329   { 0x6, 1.0 }
00330 };
00331 
00332 static const stp_shade_t canon_X_3bit_shades[] =
00333 {
00334   SHADE(1.0, three_bit_dotsize)
00335 };
00336 
00337 DECLARE_INK(canon_X_3bit, 1.0);
00338 
00339 /*
00340  * Dither ranges specifically for any Color/LightColor and 3bit/pixel
00341  * (see NOTE above)
00342  */
00343 static const stp_shade_t canon_Xx_3bit_shades[] =
00344 {
00345   SHADE(0.33, three_bit_dotsize),
00346   SHADE(1.0, three_bit_dotsize),
00347 };
00348 
00349 DECLARE_INK(canon_Xx_3bit, 1.0);
00350 
00351 
00352 /* Inkset for printing in CMY and 1bit/pixel */
00353 static const canon_variable_inkset_t ci_CMY_1 =
00354 {
00355   NULL,
00356   NULL,
00357   NULL,
00358   NULL
00359 };
00360 
00361 /* Inkset for printing in CMY and 2bit/pixel */
00362 static const canon_variable_inkset_t ci_CMY_2 =
00363 {
00364   &canon_X_2bit_ink,
00365   &canon_X_2bit_ink,
00366   &canon_X_2bit_ink,
00367   NULL
00368 };
00369 
00370 /* Inkset for printing in CMYK and 1bit/pixel */
00371 static const canon_variable_inkset_t ci_CMYK_1 =
00372 {
00373   NULL,
00374   NULL,
00375   NULL,
00376   NULL
00377 };
00378 
00379 /* Inkset for printing in CcMmYK and 1bit/pixel */
00380 static const canon_variable_inkset_t ci_CcMmYK_1 =
00381 {
00382   &canon_Cc_1bit_ink,
00383   &canon_Mm_1bit_ink,
00384   NULL,
00385   NULL
00386 };
00387 
00388 /* Inkset for printing in CMYK and 2bit/pixel */
00389 static const canon_variable_inkset_t ci_CMYK_2 =
00390 {
00391   &canon_X_2bit_ink,
00392   &canon_X_2bit_ink,
00393   &canon_X_2bit_ink,
00394   &canon_X_2bit_ink
00395 };
00396 
00397 /* Inkset for printing in CcMmYK and 2bit/pixel */
00398 static const canon_variable_inkset_t ci_CcMmYK_2 =
00399 {
00400   &canon_Xx_2bit_ink,
00401   &canon_Xx_2bit_ink,
00402   &canon_X_2bit_ink,
00403   &canon_X_2bit_ink
00404 };
00405 
00406 /* Inkset for printing in CMYK and 3bit/pixel */
00407 static const canon_variable_inkset_t ci_CMYK_3 =
00408 {
00409   &canon_X_3bit_ink,
00410   &canon_X_3bit_ink,
00411   &canon_X_3bit_ink,
00412   &canon_X_3bit_ink
00413 };
00414 
00415 /* Inkset for printing in CcMmYK and 3bit/pixel */
00416 static const canon_variable_inkset_t ci_CcMmYK_3 =
00417 {
00418   &canon_Xx_3bit_ink,
00419   &canon_Xx_3bit_ink,
00420   &canon_X_3bit_ink,
00421   &canon_X_3bit_ink,
00422 };
00423 
00424 
00425 typedef canon_variable_inklist_t* canon_variable_inklist_p;
00426 
00427 /* Ink set should be applicable for any CMYK based model */
00428 static const canon_variable_inklist_t canon_ink_standard[] =
00429 {
00430   {
00431     1,4,
00432     &ci_CMYK_1, &ci_CMYK_1, &ci_CMYK_1,
00433     &ci_CMYK_1, &ci_CMYK_1, &ci_CMYK_1,
00434   },
00435 };
00436 
00437 /* Ink set for printers using CMY and CMY photo printing, 1 or 2bit/pixel */
00438 static const canon_variable_inklist_t canon_ink_oldphoto[] =
00439 {
00440   {
00441     1,3,
00442     &ci_CMY_1, &ci_CMY_1, &ci_CMY_1,
00443     &ci_CMY_1, &ci_CMY_1, &ci_CMY_1,
00444   },
00445   {
00446     2,3,
00447     &ci_CMY_2, &ci_CMY_2,
00448     &ci_CMY_2, &ci_CMY_2,
00449     &ci_CMY_2, &ci_CMY_2,
00450   },
00451 };
00452 
00453 /* Ink set for printers using CMYK and CcMmYK printing, 1 or 2bit/pixel */
00454 static const canon_variable_inklist_t canon_ink_standardphoto[] =
00455 {
00456   {
00457     1,4,
00458     &ci_CMYK_1, &ci_CMYK_1, &ci_CMYK_1,
00459     &ci_CMYK_1, &ci_CMYK_1, &ci_CMYK_1,
00460   },
00461   {
00462     2,4,
00463     &ci_CMYK_2, &ci_CMYK_2,
00464     &ci_CMYK_2, &ci_CMYK_2,
00465     &ci_CMYK_2, &ci_CMYK_2,
00466   },
00467   {
00468     1,6,
00469     &ci_CcMmYK_1, &ci_CcMmYK_1, &ci_CcMmYK_1,
00470     &ci_CcMmYK_1, &ci_CcMmYK_1, &ci_CcMmYK_1,
00471   },
00472   {
00473     2,6,
00474     &ci_CcMmYK_2, &ci_CcMmYK_2, &ci_CcMmYK_2,
00475     &ci_CcMmYK_2, &ci_CcMmYK_2, &ci_CcMmYK_2,
00476   },
00477 };
00478 
00479 /* Ink set for printers using CMYK and CcMmYK printing, 1 or 3bit/pixel */
00480 static const canon_variable_inklist_t canon_ink_superphoto[] =
00481 {
00482   {
00483     1,4,
00484     &ci_CMYK_1, &ci_CMYK_1, &ci_CMYK_1,
00485     &ci_CMYK_1, &ci_CMYK_1, &ci_CMYK_1,
00486   },
00487   {
00488     3,4,
00489     &ci_CMYK_3, &ci_CMYK_3, &ci_CMYK_3,
00490     &ci_CMYK_3, &ci_CMYK_3, &ci_CMYK_3,
00491   },
00492   {
00493     3,6,
00494     &ci_CcMmYK_3, &ci_CcMmYK_3, &ci_CcMmYK_3,
00495     &ci_CcMmYK_3, &ci_CcMmYK_3, &ci_CcMmYK_3,
00496   },
00497 };
00498 
00499 
00500 static const char standard_sat_adjustment[] =
00501 "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
00502 "<gimp-print>\n"
00503 "<curve wrap=\"wrap\" type=\"linear\" gamma=\"0\">\n"
00504 "<sequence count=\"48\" lower-bound=\"0\" upper-bound=\"4\">\n"
00505 /* C */  "1.00 1.00 1.00 1.00 1.00 1.00 1.00 1.00 "  /* B */
00506 /* B */  "1.00 1.00 1.00 1.00 1.00 1.00 1.00 1.00 "  /* M */
00507 /* M */  "1.00 0.95 0.90 0.90 0.90 0.90 0.90 0.90 "  /* R */
00508 /* R */  "0.90 0.95 0.95 1.00 1.00 1.00 1.00 1.00 "  /* Y */
00509 /* Y */  "1.00 1.00 1.00 1.00 1.00 1.00 1.00 1.00 "  /* G */
00510 /* G */  "1.00 1.00 1.00 1.00 1.00 1.00 1.00 1.00 "  /* C */
00511 "</sequence>\n"
00512 "</curve>\n"
00513 "</gimp-print>\n";
00514 
00515 static const char standard_lum_adjustment[] =
00516 "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
00517 "<gimp-print>\n"
00518 "<curve wrap=\"wrap\" type=\"linear\" gamma=\"0\">\n"
00519 "<sequence count=\"48\" lower-bound=\"0\" upper-bound=\"4\">\n"
00520 /* C */  "0.50 0.52 0.56 0.60 0.66 0.71 0.74 0.77 "  /* B */
00521 /* B */  "0.81 0.79 0.74 0.68 0.70 0.74 0.77 0.82 "  /* M */
00522 /* M */  "0.88 0.93 0.95 0.97 0.97 0.96 0.95 0.95 "  /* R */
00523 /* R */  "0.95 0.96 0.97 0.98 0.99 1.00 1.00 1.00 "  /* Y */
00524 /* Y */  "1.00 0.97 0.94 0.92 0.90 0.88 0.85 0.79 "  /* G */
00525 /* G */  "0.69 0.64 0.58 0.54 0.54 0.54 0.53 0.51 "  /* C */
00526 "</sequence>\n"
00527 "</curve>\n"
00528 "</gimp-print>\n";
00529 
00530 static const char standard_hue_adjustment[] =
00531 "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
00532 "<gimp-print>\n"
00533 "<curve wrap=\"wrap\" type=\"linear\" gamma=\"0\">\n"
00534 "<sequence count=\"48\" lower-bound=\"-6\" upper-bound=\"6\">\n"
00535 /* C */  "0.00 0.06 0.10 0.10 0.06 -.01 -.09 -.17 "  /* B */
00536 /* B */  "-.25 -.33 -.38 -.38 -.36 -.34 -.34 -.34 "  /* M */
00537 /* M */  "-.34 -.34 -.36 -.40 -.50 -.40 -.30 -.20 "  /* R */
00538 /* R */  "-.12 -.07 -.04 -.02 0.00 0.00 0.00 0.00 "  /* Y */
00539 /* Y */  "0.00 0.00 0.00 -.05 -.10 -.15 -.22 -.24 "  /* G */
00540 /* G */  "-.26 -.30 -.33 -.28 -.25 -.20 -.13 -.06 "  /* C */
00541 "</sequence>\n"
00542 "</curve>\n"
00543 "</gimp-print>\n";
00544 
00545 typedef enum {
00546   COLOR_MONOCHROME = 1,
00547   COLOR_CMY = 3,
00548   COLOR_CMYK = 4,
00549   COLOR_CCMMYK= 6,
00550   COLOR_CCMMYYK= 7
00551 } colormode_t;
00552 
00553 typedef struct canon_caps {
00554   int model;          /* model number as used in printers.xml */
00555   int model_id;       /* model ID code for use in commands */
00556   int max_width;      /* maximum printable paper size */
00557   int max_height;
00558   int base_res;       /* base resolution - shall be 150 or 180 */
00559   int max_xdpi;       /* maximum horizontal resolution */
00560   int max_ydpi;       /* maximum vertical resolution */
00561   int max_quality;
00562   int border_left;    /* left margin, points */
00563   int border_right;   /* right margin, points */
00564   int border_top;     /* absolute top margin, points */
00565   int border_bottom;  /* absolute bottom margin, points */
00566   int inks;           /* installable cartridges (CANON_INK_*) */
00567   int slots;          /* available paperslots */
00568   unsigned long features;       /* special bjl settings */
00569 #ifdef EXPERIMENTAL_STUFF
00570   const canon_variable_printmode_t *printmodes;
00571   int printmodes_cnt;
00572 #else
00573   int dummy;
00574   const canon_dot_size_t dot_sizes;   /* Vector of dot sizes for resolutions */
00575   const canon_densities_t densities;   /* List of densities for each printer */
00576   const canon_variable_inklist_t *inxs; /* Choices of inks for this printer */
00577   int inxs_cnt;                         /* number of ink definitions in inxs */
00578 #endif
00579   const char *lum_adjustment;
00580   const char *hue_adjustment;
00581   const char *sat_adjustment;
00582 } canon_cap_t;
00583 
00584 typedef struct
00585 {
00586   const canon_cap_t *caps;
00587   unsigned char *cols[7];
00588   int delay[7];
00589   int delay_max;
00590   int buf_length;
00591   int out_width;
00592   int left;
00593   int emptylines;
00594   int bits;
00595   int ydpi;
00596 } canon_privdata_t;
00597 
00598 static void canon_write_line(stp_vars_t *v);
00599 
00600 
00601 /* Codes for possible ink-tank combinations.
00602  * Each combo is represented by the colors that can be used with
00603  * the installed ink-tank(s)
00604  * Combinations of the codes represent the combinations allowed for a model
00605  * Note that only preferrable combinations should be used
00606  */
00607 #define CANON_INK_K           1
00608 #define CANON_INK_CMY         2
00609 #define CANON_INK_CMYK        4
00610 #define CANON_INK_CcMmYK      8
00611 #define CANON_INK_CcMmYyK    16
00612 
00613 #define CANON_INK_BLACK_MASK (CANON_INK_K|CANON_INK_CMYK|CANON_INK_CcMmYK)
00614 
00615 #define CANON_INK_PHOTO_MASK (CANON_INK_CcMmYK|CANON_INK_CcMmYyK)
00616 
00617 /* document feeding */
00618 #define CANON_SLOT_ASF1    1
00619 #define CANON_SLOT_ASF2    2
00620 #define CANON_SLOT_MAN1    4
00621 #define CANON_SLOT_MAN2    8
00622 
00623 /* model peculiarities */
00624 #define CANON_CAP_DMT       0x01ul    /* Drop Modulation Technology */
00625 #define CANON_CAP_MSB_FIRST 0x02ul    /* how to send data           */
00626 #define CANON_CAP_a         0x04ul
00627 #define CANON_CAP_b         0x08ul
00628 #define CANON_CAP_q         0x10ul
00629 #define CANON_CAP_m         0x20ul
00630 #define CANON_CAP_d         0x40ul
00631 #define CANON_CAP_t         0x80ul
00632 #define CANON_CAP_c         0x100ul
00633 #define CANON_CAP_p         0x200ul
00634 #define CANON_CAP_l         0x400ul
00635 #define CANON_CAP_r         0x800ul
00636 #define CANON_CAP_g         0x1000ul
00637 #define CANON_CAP_ACKSHORT  0x2000ul
00638 
00639 #define CANON_CAP_STD0 (CANON_CAP_b|CANON_CAP_c|CANON_CAP_d|\
00640                         CANON_CAP_l|CANON_CAP_q|CANON_CAP_t)
00641 
00642 #define CANON_CAP_STD1 (CANON_CAP_b|CANON_CAP_c|CANON_CAP_d|CANON_CAP_l|\
00643                         CANON_CAP_m|CANON_CAP_p|CANON_CAP_q|CANON_CAP_t)
00644 
00645 #ifdef EXPERIMENTAL_STUFF
00646 #define CANON_MODES(A) A,sizeof(A)/sizeof(canon_variable_printmode_t*)
00647 #else
00648 #define CANON_MODES(A) 0
00649 #endif
00650 
00651 #define CANON_INK(A) A,sizeof(A)/sizeof(canon_variable_inklist_t*)
00652 
00653 
00654 #ifdef EXPERIMENTAL_STUFF
00655 
00656 #define BC_10   CANON_INK_K       /* b/w   */
00657 #define BC_11   CANON_INK_CMYK    /* color */
00658 #define BC_12   CANON_INK_CMYK    /* photo */
00659 #define BC_20   CANON_INK_K       /* b/w   */
00660 #define BC_21   CANON_INK_CMYK    /* color */
00661 #define BC_22   CANON_INK_CMYK    /* photo */
00662 #define BC_29   0                 /* neon! */
00663 #define BC_3031 CANON_INK_CMYK    /* color */
00664 #define BC_3231 CANON_INK_CcMmYK  /* photo */
00665 
00666 
00667 static const canon_variable_printmode_t canon_nomodes[] =
00668 {
00669   {0,0,0,0,0,0,0,0,0,0}
00670 };
00671 
00672 static const canon_variable_printmode_t canon_modes_30[] = {
00673   {  180, 180, 1, BC_10, 2,  1.0, 1.0, &ci_CMYK_1,   0,0,0 },
00674   {  360, 360, 1, BC_10, 2,  1.0, 1.0, &ci_CMYK_1,   0,0,0 },
00675   {  720, 360, 1, BC_10, 2,  1.0, 1.0, &ci_CMYK_1,   0,0,0 },
00676 };
00677 
00678 static const canon_variable_printmode_t canon_modes_85[] = {
00679   {  360, 360, 1, BC_10, 2,  1.0, 1.0, &ci_CMYK_1,   0,0,0 },
00680   {  360, 360, 1, BC_11, 2,  1.0, 1.0, &ci_CMYK_1,   0,0,0 },
00681   {  360, 360, 2, BC_11, 2,  1.0, 1.0, &ci_CMYK_2,   0,0,0 },
00682   {  360, 360, 1, BC_21, 2,  1.0, 1.0, &ci_CMYK_1,   0,0,0 },
00683   {  360, 360, 2, BC_21, 2,  1.0, 1.0, &ci_CMYK_2,   0,0,0 },
00684 };
00685 
00686 static const canon_variable_printmode_t canon_modes_2x00[] = {
00687   {  360, 360, 1, BC_20, 2,  1.0, 1.0, &ci_CMYK_1,   0,0,0 },
00688   {  360, 360, 1, BC_21, 2,  1.0, 1.0, &ci_CMYK_1,   0,0,0 },
00689   {  360, 360, 1, BC_22, 2,  1.0, 1.0, &ci_CMYK_1,   0,0,0 },
00690 };
00691 
00692 static const canon_variable_printmode_t canon_modes_6x00[] = {
00693   {  360, 360, 1, BC_3031, 2,  1.8, 1.0, &ci_CMYK_1,   0,0,0 },
00694   {  360, 360, 2, BC_3031, 2,  1.8, 1.0, &ci_CMYK_2,   0,0,0 },
00695   {  720, 720, 1, BC_3031, 2,  1.0, 1.0, &ci_CMYK_1,   0,0,0 },
00696   { 1440, 720, 1, BC_3031, 2,  0.5, 1.0, &ci_CMYK_1,   0,0,0 },
00697   {  360, 360, 1, BC_3231, 2,  1.8, 1.0, &ci_CcMmYK_1, 0,0,0 },
00698   {  360, 360, 2, BC_3231, 2,  1.8, 1.0, &ci_CcMmYK_2, 0,0,0 },
00699   {  720, 720, 1, BC_3231, 2,  1.0, 1.0, &ci_CcMmYK_1, 0,0,0 },
00700   { 1440, 720, 1, BC_3231, 2,  0.5, 1.0, &ci_CcMmYK_1, 0,0,0 },
00701 };
00702 #endif
00703 
00704 static const canon_cap_t canon_model_capabilities[] =
00705 {
00706   /* default settings for unknown models */
00707 
00708   {   -1, 17*72/2,842,180,180,20,20,20,20, CANON_INK_K, CANON_SLOT_ASF1, 0 },
00709 
00710   /* ******************************** */
00711   /*                                  */
00712   /* tested and color-adjusted models */
00713   /*                                  */
00714   /* ******************************** */
00715 
00716 
00717 
00718 
00719   /* ************************************ */
00720   /*                                      */
00721   /* tested models w/out color-adjustment */
00722   /*                                      */
00723   /* ************************************ */
00724 
00725 
00726   { /* Canon  BJ 30   *//* heads: BC-10 */
00727     30, 1,
00728     9.5*72, 14*72,
00729     90, 360, 360, 2,
00730     11, 9, 10, 18,
00731     CANON_INK_K,
00732     CANON_SLOT_ASF1,
00733     CANON_CAP_STD0 | CANON_CAP_a,
00734     CANON_MODES(canon_modes_30),
00735 #ifndef EXPERIMENTAL_STUFF
00736     {-1,0,0,0,-1,-1}, /*090x090 180x180 360x360 720x360 720x720 1440x1440*/
00737     {1,1,1,1,1,1},    /*------- 180x180 360x360 720x360 ------- ---------*/
00738     CANON_INK(canon_ink_standard),
00739 #endif
00740     standard_lum_adjustment,
00741     standard_hue_adjustment,
00742     standard_sat_adjustment
00743   },
00744 
00745   { /* Canon  BJC 85  *//* heads: BC-20 BC-21 BC-22 */
00746     85, 1,
00747     9.5*72, 14*72,
00748     90, 720, 360, 2,
00749     11, 9, 10, 18,
00750     CANON_INK_K | CANON_INK_CMYK | CANON_INK_CcMmYK,
00751     CANON_SLOT_ASF1,
00752     CANON_CAP_STD0 | CANON_CAP_a | CANON_CAP_DMT,
00753     CANON_MODES(canon_modes_85),
00754 #ifndef EXPERIMENTAL_STUFF
00755     {-1,-1,1,0,-1,-1},/*090x090 180x180 360x360 720x360 720x720 1440x1440*/
00756     {1,1,1,1,1,1},    /*------- ------- 360x360 720x360 ------- ---------*/
00757     CANON_INK(canon_ink_standard),
00758 #endif
00759     standard_lum_adjustment,
00760     standard_hue_adjustment,
00761     standard_sat_adjustment
00762   },
00763 
00764   { /* Canon BJC 4300 *//* heads: BC-20 BC-21 BC-22 BC-29 */
00765     4300, 1,
00766     618, 936,      /* 8.58" x 13 " */
00767     180, 1440, 720, 2,
00768     11, 9, 10, 18,
00769     CANON_INK_CMYK | CANON_INK_CcMmYK,
00770     CANON_SLOT_ASF1 | CANON_SLOT_MAN1,
00771     CANON_CAP_STD0 | CANON_CAP_DMT,
00772     CANON_MODES(canon_nomodes),
00773 #ifndef EXPERIMENTAL_STUFF
00774     {-1,1,0,0,-1,-1}, /*180x180 360x360 720x720 1440x720 1440x1440 2880x2880*/
00775     {1,1,1,1,1,1},    /*------- 360x360 720x720 1440x720 --------- ---------*/
00776     CANON_INK(canon_ink_standard),
00777 #endif
00778     standard_lum_adjustment,
00779     standard_hue_adjustment,
00780     standard_sat_adjustment
00781   },
00782 
00783   { /* Canon BJC 4400 *//* heads: BC-20 BC-21 BC-22 BC-29 */
00784     4400, 1,
00785     9.5*72, 14*72,
00786     90, 720, 360, 2,
00787     11, 9, 10, 18,
00788     CANON_INK_K | CANON_INK_CMYK | CANON_INK_CcMmYK,
00789     CANON_SLOT_ASF1,
00790     CANON_CAP_STD0 | CANON_CAP_a | CANON_CAP_DMT,
00791     CANON_MODES(canon_nomodes),
00792 #ifndef EXPERIMENTAL_STUFF
00793     {-1,-1,0,0,-1,-1},/*090x090 180x180 360x360 720x360 720x720 1440x1440*/
00794     {1,1,1,1,1,1},    /*------- ------- 360x360 720x360 ------- ---------*/
00795     CANON_INK(canon_ink_standard),
00796 #endif
00797     standard_lum_adjustment,
00798     standard_hue_adjustment,
00799     standard_sat_adjustment
00800   },
00801 
00802   { /* Canon BJC 6000 *//* heads: BC-30/BC-31 BC-32/BC-31 */
00803     6000, 3,
00804     618, 936,      /* 8.58" x 13 " */
00805     180, 1440, 720, 2,
00806     11, 9, 10, 18,
00807     CANON_INK_CMYK | CANON_INK_CcMmYK,
00808     CANON_SLOT_ASF1 | CANON_SLOT_MAN1,
00809     CANON_CAP_STD1 | CANON_CAP_DMT | CANON_CAP_ACKSHORT,
00810     CANON_MODES(canon_modes_6x00),
00811 #ifndef EXPERIMENTAL_STUFF
00812     {-1,1,0,0,-1,-1}, /*180x180 360x360 720x720 1440x720 1440x1440 2880x2880*/
00813     {1,1.8,1,0.5,1,1},/*------- 360x360 720x720 1440x720 --------- ---------*/
00814     CANON_INK(canon_ink_standardphoto),
00815 #endif
00816     standard_lum_adjustment,
00817     standard_hue_adjustment,
00818     standard_sat_adjustment
00819   },
00820 
00821   { /* Canon BJC 6200 *//* heads: BC-30/BC-31 BC-32/BC-31 */
00822     6200, 3,
00823     618, 936,      /* 8.58" x 13 " */
00824     180, 1440, 720, 2,
00825     11, 9, 10, 18,
00826     CANON_INK_CMYK | CANON_INK_CcMmYK,
00827     CANON_SLOT_ASF1 | CANON_SLOT_MAN1,
00828     CANON_CAP_STD1 | CANON_CAP_DMT | CANON_CAP_ACKSHORT,
00829     CANON_MODES(canon_modes_6x00),
00830 #ifndef EXPERIMENTAL_STUFF
00831     {-1,1,0,0,-1,-1}, /*180x180 360x360 720x720 1440x720 1440x1440 2880x2880*/
00832     {0,1.8,1,.5,0,0}, /*------- 360x360 720x720 1440x720 --------- ---------*/
00833     CANON_INK(canon_ink_standardphoto),
00834 #endif
00835     standard_lum_adjustment,
00836     standard_hue_adjustment,
00837     standard_sat_adjustment
00838   },
00839 
00840   { /* Canon BJC 6500 *//* heads: BC-30/BC-31 BC-32/BC-31 */
00841     6500, 3,
00842     842, 17*72,
00843     180, 1440, 720, 2,
00844     11, 9, 10, 18,
00845     CANON_INK_CMYK | CANON_INK_CcMmYK,
00846     CANON_SLOT_ASF1 | CANON_SLOT_MAN1,
00847     CANON_CAP_STD1 | CANON_CAP_DMT,
00848     CANON_MODES(canon_modes_6x00),
00849 #ifndef EXPERIMENTAL_STUFF
00850     {-1,1,0,0,-1,-1}, /*180x180 360x360 720x720 1440x720 1440x1440 2880x2880*/
00851     {0,1.8,1,.5,0,0}, /*------- 360x360 720x720 1440x720 --------- ---------*/
00852     CANON_INK(canon_ink_standardphoto),
00853 #endif
00854     standard_lum_adjustment,
00855     standard_hue_adjustment,
00856     standard_sat_adjustment
00857   },
00858 
00859   { /* Canon BJC 8200 *//* heads: BC-50 */
00860     8200, 3,
00861     842, 17*72,
00862     150, 1200,1200, 4,
00863     11, 9, 10, 18,
00864     CANON_INK_CMYK, /*  | CANON_INK_CcMmYK */
00865     CANON_SLOT_ASF1,
00866     CANON_CAP_STD1 | CANON_CAP_r | CANON_CAP_DMT | CANON_CAP_ACKSHORT,
00867     CANON_MODES(canon_nomodes),
00868 #ifndef EXPERIMENTAL_STUFF
00869     {-1,0,0,-1,0,-1}, /*150x150 300x300 600x600 1200x600 1200x1200 2400x2400*/
00870     {1,1,1,1,1,1},    /*------- 300x300 600x600 -------- 1200x1200 ---------*/
00871     CANON_INK(canon_ink_superphoto),
00872 #endif
00873     standard_lum_adjustment,
00874     standard_hue_adjustment,
00875     standard_sat_adjustment
00876   },
00877 
00878 
00879   /* *************** */
00880   /*                 */
00881   /* untested models */
00882   /*                 */
00883   /* *************** */
00884 
00885 
00886   { /* Canon BJC 210 *//* heads: BC-02 BC-05 BC-06 */
00887     210, 1,
00888     618, 936,      /* 8.58" x 13 " */
00889     90, 720, 360, 2,
00890     11, 9, 10, 18,
00891     CANON_INK_K | CANON_INK_CMY,
00892     CANON_SLOT_ASF1 | CANON_SLOT_MAN1,
00893     CANON_CAP_STD0,
00894     CANON_MODES(canon_nomodes),
00895 #ifndef EXPERIMENTAL_STUFF
00896     {0,0,0,0,-1,-1},/*180x180 360x360 720x720 1440x720 1440x1440 2880x2880*/
00897     {1,1,1,1,1,1},    /*180x180 360x360 ------- -------- --------- ---------*/
00898     CANON_INK(canon_ink_standard),
00899 #endif
00900     standard_lum_adjustment,
00901     standard_hue_adjustment,
00902     standard_sat_adjustment
00903   },
00904   { /* Canon BJC 240 *//* heads: BC-02 BC-05 BC-06 */
00905     240, 1,
00906     618, 936,      /* 8.58" x 13 " */
00907     90, 720, 360, 2,
00908     11, 9, 10, 18,
00909     CANON_INK_K | CANON_INK_CMY,
00910     CANON_SLOT_ASF1 | CANON_SLOT_MAN1,
00911     CANON_CAP_STD0 | CANON_CAP_DMT,
00912     CANON_MODES(canon_nomodes),
00913 #ifndef EXPERIMENTAL_STUFF
00914     {0,0,1,0,-1,-1},/*180x180 360x360 720x720 1440x720 1440x1440 2880x2880*/
00915     {1,1,1,1,1,1},    /*180x180 360x360 ------- -------- --------- ---------*/
00916     CANON_INK(canon_ink_oldphoto),
00917 #endif
00918     standard_lum_adjustment,
00919     standard_hue_adjustment,
00920     standard_sat_adjustment
00921   },
00922   { /* Canon BJC 250 *//* heads: BC-02 BC-05 BC-06 */
00923     250, 1,
00924     618, 936,      /* 8.58" x 13 " */
00925     90, 720, 360, 2,
00926     11, 9, 10, 18,
00927     CANON_INK_K | CANON_INK_CMY,
00928     CANON_SLOT_ASF1 | CANON_SLOT_MAN1,
00929     CANON_CAP_STD0 | CANON_CAP_DMT,
00930     CANON_MODES(canon_nomodes),
00931 #ifndef EXPERIMENTAL_STUFF
00932     {0,0,1,0,-1,-1},/*180x180 360x360 720x720 1440x720 1440x1440 2880x2880*/
00933     {1,1,1,1,1,1},    /*180x180 360x360 ------- -------- --------- ---------*/
00934     CANON_INK(canon_ink_oldphoto),
00935 #endif
00936     standard_lum_adjustment,
00937     standard_hue_adjustment,
00938     standard_sat_adjustment
00939   },
00940   { /* Canon BJC 1000 *//* heads: BC-02 BC-05 BC-06 */
00941     1000, 1,
00942     842, 17*72,
00943     90, 720, 360, 2,
00944     11, 9, 10, 18,
00945     CANON_INK_K | CANON_INK_CMY,
00946     CANON_SLOT_ASF1,
00947     CANON_CAP_STD0 | CANON_CAP_DMT | CANON_CAP_a,
00948     CANON_MODES(canon_nomodes),
00949 #ifndef EXPERIMENTAL_STUFF
00950     {0,0,1,0,-1,-1},  /*180x180 360x360 720x720 1440x720 1440x1440 2880x2880*/
00951     {1,1,1,1,1,1},    /*180x180 360x360 ------- -------- --------- ---------*/
00952     CANON_INK(canon_ink_oldphoto),
00953 #endif
00954     standard_lum_adjustment,
00955     standard_hue_adjustment,
00956     standard_sat_adjustment
00957   },
00958   { /* Canon BJC 2000 *//* heads: BC-20 BC-21 BC-22 BC-29 */
00959     2000, 1,
00960     842, 17*72,
00961     180, 720, 360, 2,
00962     11, 9, 10, 18,
00963     CANON_INK_CMYK,
00964     CANON_SLOT_ASF1,
00965     CANON_CAP_STD0 | CANON_CAP_a,
00966     CANON_MODES(canon_nomodes),
00967 #ifndef EXPERIMENTAL_STUFF
00968     {0,0,-1,-1,-1,-1},/*180x180 360x360 720x720 1440x720 1440x1440 2880x2880*/
00969     {1,1,1,1,1,1},    /*180x180 360x360 ------- -------- --------- ---------*/
00970     CANON_INK(canon_ink_standard),
00971 #endif
00972     standard_lum_adjustment,
00973     standard_hue_adjustment,
00974     standard_sat_adjustment
00975   },
00976   { /* Canon BJC 3000 *//* heads: BC-30 BC-33 BC-34 */
00977     3000, 3,
00978     842, 17*72,
00979     180, 1440, 720, 2,
00980     11, 9, 10, 18,
00981     CANON_INK_CMYK | CANON_INK_CcMmYK,
00982     CANON_SLOT_ASF1,
00983     CANON_CAP_STD0 | CANON_CAP_a | CANON_CAP_DMT, /*FIX? should have _r? */
00984     CANON_MODES(canon_nomodes),
00985 #ifndef EXPERIMENTAL_STUFF
00986     {-1,1,0,0,-1,-1}, /*180x180 360x360 720x720 1440x720 1440x1440 2880x2880*/
00987     {1,1,1,1,1,1},    /*------- 360x360 720x720 1440x720 --------- ---------*/
00988     CANON_INK(canon_ink_standard),
00989 #endif
00990     standard_lum_adjustment,
00991     standard_hue_adjustment,
00992     standard_sat_adjustment
00993   },
00994   { /* Canon BJC 6100 *//* heads: BC-30/BC-31 BC-32/BC-31 */
00995     6100, 3,
00996     842, 17*72,
00997     180, 1440, 720, 2,
00998     11, 9, 10, 18,
00999     CANON_INK_CMYK | CANON_INK_CcMmYK,
01000     CANON_SLOT_ASF1,
01001     CANON_CAP_STD1 | CANON_CAP_a | CANON_CAP_r | CANON_CAP_DMT,
01002     CANON_MODES(canon_modes_6x00),
01003 #ifndef EXPERIMENTAL_STUFF
01004     {-1,1,0,0,-1,-1}, /*180x180 360x360 720x720 1440x720 1440x1440 2880x2880*/
01005     {1,1,1,1,1,1},    /*------- 360x360 720x720 1440x720 --------- ---------*/
01006     CANON_INK(canon_ink_standard),
01007 #endif
01008     standard_lum_adjustment,
01009     standard_hue_adjustment,
01010     standard_sat_adjustment
01011   },
01012   { /* Canon BJC 7000 *//* heads: BC-60/BC-61 BC-60/BC-62   ??????? */
01013     7000, 3,
01014     842, 17*72,
01015     150, 1200, 600, 2,
01016     11, 9, 10, 18,
01017     CANON_INK_CMYK | CANON_INK_CcMmYyK,
01018     CANON_SLOT_ASF1,
01019     CANON_CAP_STD1,
01020     CANON_MODES(canon_nomodes),
01021 #ifndef EXPERIMENTAL_STUFF
01022     {-1,0,0,0,-1,-1}, /*150x150 300x300 600x600 1200x600 1200x1200 2400x2400*/
01023     {1,3.5,1.8,1,1,1},/*------- 300x300 600x600 1200x600 --------- ---------*/
01024     CANON_INK(canon_ink_standard),
01025 #endif
01026     standard_lum_adjustment,
01027     standard_hue_adjustment,
01028     standard_sat_adjustment
01029   },
01030   { /* Canon BJC 7100 *//* heads: BC-60/BC-61 BC-60/BC-62   ??????? */
01031     7100, 3,
01032     842, 17*72,
01033     150, 1200, 600, 2,
01034     11, 9, 10, 18,
01035     CANON_INK_CMYK | CANON_INK_CcMmYyK,
01036     CANON_SLOT_ASF1,
01037     CANON_CAP_STD0,
01038     CANON_MODES(canon_nomodes),
01039 #ifndef EXPERIMENTAL_STUFF
01040     {-1,0,0,0,-1,-1}, /*150x150 300x300 600x600 1200x600 1200x1200 2400x2400*/
01041     {1,1,1,1,1,1},    /*------- 300x300 600x600 1200x600 --------- ---------*/
01042     CANON_INK(canon_ink_standard),
01043 #endif
01044     standard_lum_adjustment,
01045     standard_hue_adjustment,
01046     standard_sat_adjustment
01047   },
01048 
01049   /*****************************/
01050   /*                           */
01051   /*  extremely fuzzy models   */
01052   /* (might never work at all) */
01053   /*                           */
01054   /*****************************/
01055 
01056   { /* Canon BJC 5100 *//* heads: BC-20 BC-21 BC-22 BC-23 BC-29 */
01057     5100, 1,
01058     17*72, 22*72,
01059     180, 1440, 720, 2,
01060     11, 9, 10, 18,
01061     CANON_INK_CMYK | CANON_INK_CcMmYK,
01062     CANON_SLOT_ASF1,
01063     CANON_CAP_STD0 | CANON_CAP_DMT,
01064     CANON_MODES(canon_nomodes),
01065 #ifndef EXPERIMENTAL_STUFF
01066     {-1,1,0,0,-1,-1}, /*180x180 360x360 720x720 1440x720 1440x1440 2880x2880*/
01067     {1,1,1,1,1,1},    /*------- 360x360 720x720 1440x720 --------- ---------*/
01068     CANON_INK(canon_ink_standard),
01069 #endif
01070     standard_lum_adjustment,
01071     standard_hue_adjustment,
01072     standard_sat_adjustment
01073   },
01074   { /* Canon BJC 5500 *//* heads: BC-20 BC-21 BC-29 */
01075     5500, 1,
01076     22*72, 34*72,
01077     180, 720, 360, 2,
01078     11, 9, 10, 18,
01079     CANON_INK_CMYK | CANON_INK_CcMmYK,
01080     CANON_SLOT_ASF1,
01081     CANON_CAP_STD0 | CANON_CAP_a,
01082     CANON_MODES(canon_nomodes),
01083 #ifndef EXPERIMENTAL_STUFF
01084     {0,0,-1,-1,-1,-1},/*180x180 360x360 720x720 1440x720 1440x1440 2880x2880*/
01085     {1,1,1,1,1,1},    /*180x180 360x360 ------- -------- --------- ---------*/
01086     CANON_INK(canon_ink_standard),
01087 #endif
01088     standard_lum_adjustment,
01089     standard_hue_adjustment,
01090     standard_sat_adjustment
01091   },
01092   { /* Canon BJC 6500 *//* heads: BC-30/BC-31 BC-32/BC-31 */
01093     6500, 3,
01094     17*72, 22*72,
01095     180, 1440, 720, 2,
01096     11, 9, 10, 18,
01097     CANON_INK_CMYK | CANON_INK_CcMmYK,
01098     CANON_SLOT_ASF1,
01099     CANON_CAP_STD1 | CANON_CAP_a | CANON_CAP_DMT,
01100     CANON_MODES(canon_nomodes),
01101 #ifndef EXPERIMENTAL_STUFF
01102     {-1,1,0,0,-1,-1}, /*180x180 360x360 720x720 1440x720 1440x1440 2880x2880*/
01103     {1,1,1,1,1,1},    /*------- 360x360 720x720 1440x720 --------- ---------*/
01104     CANON_INK(canon_ink_standard),
01105 #endif
01106     standard_lum_adjustment,
01107     standard_hue_adjustment,
01108     standard_sat_adjustment
01109   },
01110   { /* Canon BJC 8500 *//* heads: BC-80/BC-81 BC-82/BC-81 */
01111     8500, 3,
01112     17*72, 22*72,
01113     150, 1200,1200, 2,
01114     11, 9, 10, 18,
01115     CANON_INK_CMYK | CANON_INK_CcMmYK,
01116     CANON_SLOT_ASF1,
01117     CANON_CAP_STD0,
01118     CANON_MODES(canon_nomodes),
01119 #ifndef EXPERIMENTAL_STUFF
01120     {-1,0,0,-1,0,-1}, /*150x150 300x300 600x600 1200x600 1200x1200 2400x2400*/
01121     {1,1,1,1,1,1},    /*------- 300x300 600x600 -------- 1200x1200 ---------*/
01122     CANON_INK(canon_ink_standard),
01123 #endif
01124     standard_lum_adjustment,
01125     standard_hue_adjustment,
01126     standard_sat_adjustment
01127   },
01128 };
01129 
01130 typedef struct {
01131   int x;
01132   int y;
01133   const char *name;
01134   const char *text;
01135   const char *name_dmt;
01136   const char *text_dmt;
01137 } canon_res_t;
01138 
01139 static const canon_res_t canon_resolutions[] = {
01140   { 90, 90, "90x90dpi", N_("90x90 DPI"), "90x90dmt", N_("90x90 DPI DMT") },
01141   { 180, 180, "180x180dpi", N_("180x180 DPI"), "180x180dmt", N_("180x180 DPI DMT") },
01142   { 360, 360, "360x360dpi", N_("360x360 DPI"), "360x360dmt", N_("360x360 DPI DMT") },
01143   { 720, 360, "720x360dpi", N_("720x360 DPI"), "720x360dmt", N_("720x360 DPI DMT") },
01144   { 720, 720, "720x720dpi", N_("720x720 DPI"), "720x720dmt", N_("720x720 DPI DMT") },
01145   { 1440, 720, "1440x720dpi", N_("1440x720 DPI"), "1440x720dmt", N_("1440x720 DPI DMT") },
01146   { 1440, 1440, "1440x1440dpi", N_("1440x1440 DPI"), "1440x1440dmt", N_("1440x1440 DPI DMT") },
01147   { 2880, 2880, "2880x2880dpi", N_("2880x2880 DPI"), "2880x2880dmt", N_("2880x2880 DPI DMT") },
01148   { 150, 150, "150x150dpi", N_("150x150 DPI"), "150x150dmt", N_("150x150 DPI DMT") },
01149   { 300, 300, "300x300dpi", N_("300x300 DPI"), "300x300dmt", N_("300x300 DPI DMT") },
01150   { 600, 300, "600x300dpi", N_("600x300 DPI"), "600x300dmt", N_("600x300 DPI DMT") },
01151   { 600, 600, "600x600dpi", N_("600x600 DPI"), "600x600dmt", N_("600x600 DPI DMT") },
01152   { 1200, 600, "1200x600dpi", N_("1200x600 DPI"), "1200x600dmt", N_("1200x600 DPI DMT") },
01153   { 1200, 1200, "1200x1200dpi", N_("1200x1200 DPI"), "1200x1200dmt", N_("1200x1200 DPI DMT") },
01154   { 2400, 2400, "2400x2400dpi", N_("2400x2400 DPI"), "2400x2400dmt", N_("2400x2400 DPI DMT") },
01155   { 0, 0, NULL, NULL, NULL, NULL }
01156 };
01157 
01158 static const char plain_paper_lum_adjustment[] =
01159 "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
01160 "<gimp-print>\n"
01161 "<curve wrap=\"wrap\" type=\"linear\" gamma=\"0\">\n"
01162 "<sequence count=\"48\" lower-bound=\"0\" upper-bound=\"4\">\n"
01163 "1.20 1.22 1.28 1.34 1.39 1.42 1.45 1.48 "  /* C */
01164 "1.50 1.40 1.30 1.25 1.20 1.10 1.05 1.05 "  /* B */
01165 "1.05 1.05 1.05 1.05 1.05 1.05 1.05 1.05 "  /* M */
01166 "1.05 1.05 1.05 1.10 1.10 1.10 1.10 1.10 "  /* R */
01167 "1.10 1.15 1.30 1.45 1.60 1.75 1.90 2.00 "  /* Y */
01168 "2.10 2.00 1.80 1.70 1.60 1.50 1.40 1.30 "  /* G */
01169 "</sequence>\n"
01170 "</curve>\n"
01171 "</gimp-print>\n";
01172 
01173 typedef struct {
01174   const char *name;
01175   const char *text;
01176   int media_code;
01177   double base_density;
01178   double k_lower_scale;
01179   double k_upper;
01180   const char *hue_adjustment;
01181   const char *lum_adjustment;
01182   const char *sat_adjustment;
01183 } paper_t;
01184 
01185 typedef struct {
01186   const canon_cap_t *caps;
01187   int printing_color;
01188   const paper_t *pt;
01189   int print_head;
01190   int colormode;
01191   const char *source_str;
01192   int xdpi;
01193   int ydpi;
01194   int page_width;
01195   int page_height;
01196   int top;
01197   int left;
01198   int bits;
01199 } canon_init_t;
01200 
01201 static const paper_t canon_paper_list[] = {
01202   { "Plain",            N_ ("Plain Paper"),                0x00, 0.50, 0.25, 0.500, 0, 0, 0 },
01203   { "Transparency",     N_ ("Transparencies"),             0x02, 1.00, 1.00, 0.900, 0, 0, 0 },
01204   { "BackPrint",        N_ ("Back Print Film"),            0x03, 1.00, 1.00, 0.900, 0, 0, 0 },
01205   { "Fabric",           N_ ("Fabric Sheets"),              0x04, 0.50, 0.25, 0.500, 0, 0, 0 },
01206   { "Envelope",         N_ ("Envelope"),                   0x08, 0.50, 0.25, 0.500, 0, 0, 0 },
01207   { "Coated",           N_ ("High Resolution Paper"),      0x07, 0.78, 0.25, 0.500, 0, 0, 0 },
01208   { "TShirt",           N_ ("T-Shirt Transfers"),          0x03, 0.50, 0.25, 0.500, 0, 0, 0 },
01209   { "GlossyFilm",       N_ ("High Gloss Film"),            0x06, 1.00, 1.00, 0.999, 0, 0, 0 },
01210   { "GlossyPaper",      N_ ("Glossy Photo Paper"),         0x05, 1.00, 1.00, 0.999, 0, 0, 0 },
01211   { "GlossyCard",       N_ ("Glossy Photo Cards"),         0x0a, 1.00, 1.00, 0.999, 0, 0, 0 },
01212   { "GlossyPro",        N_ ("Photo Paper Pro"),            0x09, 1.00, 1.00, 0.999, 0, 0, 0 },
01213   { "Other",            N_ ("Other"),                      0x00, 0.50, 0.25, .5, 0, 0, 0 },
01214 };
01215 
01216 static const int paper_type_count = sizeof(canon_paper_list) / sizeof(paper_t);
01217 
01218 static const stp_parameter_t the_parameters[] =
01219 {
01220   {
01221     "PageSize", N_("Page Size"), N_("Basic Printer Setup"),
01222     N_("Size of the paper being printed to"),
01223     STP_PARAMETER_TYPE_STRING_LIST, STP_PARAMETER_CLASS_CORE,
01224     STP_PARAMETER_LEVEL_BASIC, 1, 1, -1, 1, 0
01225   },
01226   {
01227     "MediaType", N_("Media Type"), N_("Basic Printer Setup"),
01228     N_("Type of media (plain paper, photo paper, etc.)"),
01229     STP_PARAMETER_TYPE_STRING_LIST, STP_PARAMETER_CLASS_FEATURE,
01230     STP_PARAMETER_LEVEL_BASIC, 1, 1, -1, 1, 0
01231   },
01232   {
01233     "InputSlot", N_("Media Source"), N_("Basic Printer Setup"),
01234     N_("Source (input slot) of the media"),
01235     STP_PARAMETER_TYPE_STRING_LIST, STP_PARAMETER_CLASS_FEATURE,
01236     STP_PARAMETER_LEVEL_BASIC, 1, 1, -1, 1, 0
01237   },
01238   {
01239     "Resolution", N_("Resolution"), N_("Basic Printer Setup"),
01240     N_("Resolution and quality of the print"),
01241     STP_PARAMETER_TYPE_STRING_LIST, STP_PARAMETER_CLASS_FEATURE,
01242     STP_PARAMETER_LEVEL_BASIC, 1, 1, -1, 1, 0
01243   },
01244   {
01245     "InkType", N_("Ink Type"), N_("Advanced Printer Setup"),
01246     N_("Type of ink in the printer"),
01247     STP_PARAMETER_TYPE_STRING_LIST, STP_PARAMETER_CLASS_FEATURE,
01248     STP_PARAMETER_LEVEL_BASIC, 1, 1, -1, 1, 0
01249   },
01250   {
01251     "InkChannels", N_("Ink Channels"), N_("Advanced Printer Functionality"),
01252     N_("Ink Channels"),
01253     STP_PARAMETER_TYPE_INT, STP_PARAMETER_CLASS_FEATURE,
01254     STP_PARAMETER_LEVEL_INTERNAL, 0, 0, -1, 0, 0
01255   },
01256   {
01257     "PrintingMode", N_("Printing Mode"), N_("Core Parameter"),
01258     N_("Printing Output Mode"),
01259     STP_PARAMETER_TYPE_STRING_LIST, STP_PARAMETER_CLASS_CORE,
01260     STP_PARAMETER_LEVEL_BASIC, 1, 1, -1, 1, 0
01261   },
01262 };
01263 
01264 static const int the_parameter_count =
01265 sizeof(the_parameters) / sizeof(const stp_parameter_t);
01266 
01267 typedef struct
01268 {
01269   const stp_parameter_t param;
01270   double min;
01271   double max;
01272   double defval;
01273   int color_only;
01274 } float_param_t;
01275 
01276 static const float_param_t float_parameters[] =
01277 {
01278   {
01279     {
01280       "CyanDensity", N_("Cyan Balance"), N_("Output Level Adjustment"),
01281       N_("Adjust the cyan balance"),
01282       STP_PARAMETER_TYPE_DOUBLE, STP_PARAMETER_CLASS_OUTPUT,
01283       STP_PARAMETER_LEVEL_ADVANCED, 0, 1, 1, 1, 0
01284     }, 0.0, 2.0, 1.0, 1
01285   },
01286   {
01287     {
01288       "MagentaDensity", N_("Magenta Balance"), N_("Output Level Adjustment"),
01289       N_("Adjust the magenta balance"),
01290       STP_PARAMETER_TYPE_DOUBLE, STP_PARAMETER_CLASS_OUTPUT,
01291       STP_PARAMETER_LEVEL_ADVANCED, 0, 1, 2, 1, 0
01292     }, 0.0, 2.0, 1.0, 1
01293   },
01294   {
01295     {
01296       "YellowDensity", N_("Yellow Balance"), N_("Output Level Adjustment"),
01297       N_("Adjust the yellow balance"),
01298       STP_PARAMETER_TYPE_DOUBLE, STP_PARAMETER_CLASS_OUTPUT,
01299       STP_PARAMETER_LEVEL_ADVANCED, 0, 1, 3, 1, 0
01300     }, 0.0, 2.0, 1.0, 1
01301   },
01302   {
01303     {
01304       "BlackDensity", N_("Black Balance"), N_("Output Level Adjustment"),
01305       N_("Adjust the black balance"),
01306       STP_PARAMETER_TYPE_DOUBLE, STP_PARAMETER_CLASS_OUTPUT,
01307       STP_PARAMETER_LEVEL_ADVANCED, 0, 1, 0, 1, 0
01308     }, 0.0, 2.0, 1.0, 1
01309   },
01310   {
01311     {
01312       "LightCyanTransition", N_("Light Cyan Transition"), N_("Advanced Ink Adjustment"),
01313       N_("Light Cyan Transition"),
01314       STP_PARAMETER_TYPE_DOUBLE, STP_PARAMETER_CLASS_OUTPUT,
01315       STP_PARAMETER_LEVEL_ADVANCED4, 0, 1, -1, 1, 0
01316     }, 0.0, 5.0, 1.0, 1
01317   },
01318   {
01319     {
01320       "LightMagentaTransition", N_("Light Magenta Transition"), N_("Advanced Ink Adjustment"),
01321       N_("Light Magenta Transition"),
01322       STP_PARAMETER_TYPE_DOUBLE, STP_PARAMETER_CLASS_OUTPUT,
01323       STP_PARAMETER_LEVEL_ADVANCED4, 0, 1, -1, 1, 0
01324     }, 0.0, 5.0, 1.0, 1
01325   },
01326  {
01327     {
01328       "LightYellowTransition", N_("Light Yellow Transition"), N_("Advanced Ink Adjustment"),
01329       N_("Light Yellow Transition"),
01330       STP_PARAMETER_TYPE_DOUBLE, STP_PARAMETER_CLASS_OUTPUT,
01331       STP_PARAMETER_LEVEL_ADVANCED4, 0, 1, -1, 1, 0
01332     }, 0.0, 5.0, 1.0, 1
01333   },
01334 };
01335 
01336 
01337 static const int float_parameter_count =
01338 sizeof(float_parameters) / sizeof(const float_param_t);
01339 
01340 static const paper_t *
01341 get_media_type(const char *name)
01342 {
01343   int i;
01344   if (name)
01345     for (i = 0; i < paper_type_count; i++)
01346       {
01347         /* translate paper_t.name */
01348         if (!strcmp(name, canon_paper_list[i].name))
01349           return &(canon_paper_list[i]);
01350       }
01351   return NULL;
01352 }
01353 
01354 
01355 static const canon_cap_t * canon_get_model_capabilities(int model)
01356 {
01357   int i;
01358   int models= sizeof(canon_model_capabilities) / sizeof(canon_cap_t);
01359   for (i=0; i<models; i++) {
01360     if (canon_model_capabilities[i].model == model) {
01361       return &(canon_model_capabilities[i]);
01362     }
01363   }
01364   stp_deprintf(STP_DBG_CANON,"canon: model %d not found in capabilities list.\n",model);
01365   return &(canon_model_capabilities[0]);
01366 }
01367 
01368 static int
01369 canon_source_type(const char *name, const canon_cap_t * caps)
01370 {
01371   /* used internally: do not translate */
01372   if (name)
01373     {
01374       if (!strcmp(name,"Auto"))    return 4;
01375       if (!strcmp(name,"Manual"))    return 0;
01376       if (!strcmp(name,"ManualNP")) return 1;
01377     }
01378 
01379   stp_deprintf(STP_DBG_CANON,"canon: Unknown source type '%s' - reverting to auto\n",name);
01380   return 4;
01381 }
01382 
01383 static int
01384 canon_printhead_type(const char *name, const canon_cap_t * caps)
01385 {
01386   /* used internally: do not translate */
01387   if (name)
01388     {
01389       if (!strcmp(name,"Gray"))             return 0;
01390       if (!strcmp(name,"RGB"))             return 1;
01391       if (!strcmp(name,"CMYK"))       return 2;
01392       if (!strcmp(name,"PhotoCMY"))       return 3;
01393       if (!strcmp(name,"Photo"))             return 4;
01394       if (!strcmp(name,"PhotoCMYK")) return 5;
01395     }
01396   if (name && *name == 0) {
01397     if (caps->inks & CANON_INK_CMYK) return 2;
01398     if (caps->inks & CANON_INK_CMY)  return 1;
01399     if (caps->inks & CANON_INK_K)    return 0;
01400   }
01401 
01402   stp_deprintf(STP_DBG_CANON,"canon: Unknown head combo '%s' - reverting to black",name);
01403   return 0;
01404 }
01405 
01406 static colormode_t
01407 canon_printhead_colors(const char *name, const canon_cap_t * caps)
01408 {
01409   /* used internally: do not translate */
01410   if (name)
01411     {
01412       if (!strcmp(name,"Gray"))             return COLOR_MONOCHROME;
01413       if (!strcmp(name,"RGB"))             return COLOR_CMY;
01414       if (!strcmp(name,"CMYK"))       return COLOR_CMYK;
01415       if (!strcmp(name,"PhotoCMY"))       return COLOR_CCMMYK;
01416       if (!strcmp(name,"PhotoCMYK")) return COLOR_CCMMYYK;
01417     }
01418 
01419   if (name && *name == 0) {
01420     if (caps->inks & CANON_INK_CMYK) return COLOR_CMYK;
01421     if (caps->inks & CANON_INK_CMY)  return COLOR_CMY;
01422     if (caps->inks & CANON_INK_K)    return COLOR_MONOCHROME;
01423   }
01424 
01425   stp_deprintf(STP_DBG_CANON,"canon: Unknown head combo '%s' - reverting to black",name);
01426   return COLOR_MONOCHROME;
01427 }
01428 
01429 static unsigned char
01430 canon_size_type(const stp_vars_t *v, const canon_cap_t * caps)
01431 {
01432   const stp_papersize_t *pp = stp_get_papersize_by_size(stp_get_page_height(v),
01433                                                         stp_get_page_width(v));
01434   if (pp)
01435     {
01436       const char *name = pp->name;
01437       /* used internally: do not translate */
01438       /* built ins: */
01439       if (!strcmp(name,"A5"))          return 0x01;
01440       if (!strcmp(name,"A4"))          return 0x03;
01441       if (!strcmp(name,"B5"))          return 0x08;
01442       if (!strcmp(name,"Letter"))      return 0x0d;
01443       if (!strcmp(name,"Legal"))       return 0x0f;
01444       if (!strcmp(name,"COM10")) return 0x16;
01445       if (!strcmp(name,"DL")) return 0x17;
01446       if (!strcmp(name,"LetterExtra"))     return 0x2a;
01447       if (!strcmp(name,"A4Extra"))         return 0x2b;
01448       if (!strcmp(name,"w288h144"))   return 0x2d;
01449       /* custom */
01450 
01451       stp_deprintf(STP_DBG_CANON,"canon: Unknown paper size '%s' - using custom\n",name);
01452     } else {
01453       stp_deprintf(STP_DBG_CANON,"canon: Couldn't look up paper size %dx%d - "
01454               "using custom\n",stp_get_page_height(v), stp_get_page_width(v));
01455     }
01456   return 0;
01457 }
01458 
01459 #ifndef EXPERIMENTAL_STUFF
01460 static int canon_res_code(const canon_cap_t * caps, int xdpi, int ydpi)
01461 {
01462   int x, y, res= 0;
01463 
01464   for (x=1; x<6; x++) if ((xdpi/caps->base_res) == (1<<(x-1))) res= (x<<4);
01465   for (y=1; y<6; y++) if ((ydpi/caps->base_res) == (1<<(y-1))) res|= y;
01466 
01467   return res;
01468 }
01469 #else
01470 static const canon_variable_printmode_t *canon_printmode(const canon_cap_t * caps,
01471                                                          int xdpi, int ydpi,
01472                                                          int bpp, int head)
01473 {
01474   const canon_variable_printmode_t *modes;
01475   int modes_cnt;
01476   int i;
01477   if (!caps) return 0;
01478   modes= caps->printmodes;
01479   modes_cnt= caps->printmodes_cnt;
01480   /* search for the right printmode: */
01481   for (i=0; i<modes_cnt; i++) {
01482     if ((modes[i].xdpi== xdpi) && (modes[i].ydpi== ydpi) &&
01483         (modes[i].bits== bpp) && (modes[i].printhead== head))
01484       {
01485         return &(modes[i]);
01486       }
01487   }
01488   /* nothing found -> either return 0 or apply some policy to
01489    * get a fallback printmode
01490    */
01491   if (modes[0].xdpi) return modes;
01492   return 0;
01493 }
01494 #endif
01495 
01496 static int
01497 canon_ink_type(const canon_cap_t * caps, int res_code)
01498 {
01499 #ifndef EXPERIMENTAL_STUFF
01500   switch (res_code)
01501     {
01502     case 0x11: return caps->dot_sizes.dot_r11;
01503     case 0x22: return caps->dot_sizes.dot_r22;
01504     case 0x33: return caps->dot_sizes.dot_r33;
01505     case 0x43: return caps->dot_sizes.dot_r43;
01506     case 0x44: return caps->dot_sizes.dot_r44;
01507     case 0x55: return caps->dot_sizes.dot_r55;
01508     }
01509   return -1;
01510 #else
01511   return -1;
01512 #endif
01513 }
01514 
01515 static const char *
01516 canon_lum_adjustment(int model)
01517 {
01518   const canon_cap_t * caps= canon_get_model_capabilities(model);
01519   return (caps->lum_adjustment);
01520 }
01521 
01522 static const char *
01523 canon_hue_adjustment(int model)
01524 {
01525   const canon_cap_t * caps= canon_get_model_capabilities(model);
01526   return (caps->hue_adjustment);
01527 }
01528 
01529 static const char *
01530 canon_sat_adjustment(int model)
01531 {
01532   const canon_cap_t * caps= canon_get_model_capabilities(model);
01533   return (caps->sat_adjustment);
01534 }
01535 
01536 static double
01537 canon_density(const canon_cap_t * caps, int res_code)
01538 {
01539 #ifndef EXPERIMENTAL_STUFF
01540   switch (res_code)
01541     {
01542     case 0x11: return caps->densities.d_r11;
01543     case 0x22: return caps->densities.d_r22;
01544     case 0x33: return caps->densities.d_r33;
01545     case 0x43: return caps->densities.d_r43;
01546     case 0x44: return caps->densities.d_r44;
01547     case 0x55: return caps->densities.d_r55;
01548     default:
01549       stp_deprintf(STP_DBG_CANON,"no such res_code 0x%x in density of model %d\n",
01550               res_code,caps->model);
01551       return 0.2;
01552     }
01553 #else
01554   return 0.2;
01555 #endif
01556 }
01557 
01558 static const canon_variable_inkset_t *
01559 canon_inks(const canon_cap_t * caps, int res_code, int colors, int bits)
01560 {
01561 #ifndef EXPERIMENTAL_STUFF
01562   const canon_variable_inklist_t *inks = caps->inxs;
01563   int i;
01564 
01565   if (!inks)
01566     return NULL;
01567 
01568   for (i=0; i<caps->inxs_cnt; i++) {
01569       stp_deprintf(STP_DBG_CANON,"hmm, trying ink for resolution code "
01570               "%x, %d bits, %d colors\n",res_code,inks[i].bits,inks[i].colors);
01571     if ((inks[i].bits==bits) && (inks[i].colors==colors)) {
01572       stp_deprintf(STP_DBG_CANON,"wow, found ink for resolution code "
01573               "%x, %d bits, %d colors\n",res_code,bits,colors);
01574       switch (res_code)
01575         {
01576         case 0x11: return inks[i].r11;
01577         case 0x22: return inks[i].r22;
01578         case 0x33: return inks[i].r33;
01579         case 0x43: return inks[i].r43;
01580         case 0x44: return inks[i].r44;
01581         case 0x55: return inks[i].r55;
01582         }
01583     }
01584   }
01585   stp_deprintf(STP_DBG_CANON,"ooo, found no ink for resolution code "
01586           "%x, %d bits, %d colors in all %d defs!\n",
01587           res_code,bits,colors,caps->inxs_cnt);
01588   return NULL;
01589 #else
01590   return NULL;
01591 #endif
01592 }
01593 
01594 static void
01595 canon_describe_resolution(const stp_vars_t *v, int *x, int *y)
01596 {
01597   const char *resolution = stp_get_string_parameter(v, "Resolution");
01598   const canon_res_t *res = canon_resolutions;
01599   while (res->x > 0)
01600     {
01601       if (strcmp(resolution, res->name) == 0 ||
01602           strcmp(resolution, res->name_dmt) == 0)
01603         {
01604           *x = res->x;
01605           *y = res->y;
01606           return;
01607         }
01608       res++;
01609     }
01610   *x = -1;
01611   *y = -1;
01612 }
01613 
01614 static const char *
01615 canon_describe_output(const stp_vars_t *v)
01616 {
01617   int model = stp_get_model_id(v);
01618   const canon_cap_t *caps = canon_get_model_capabilities(model);
01619   const char *print_mode = stp_get_string_parameter(v, "PrintingMode");
01620   const char *ink_type = stp_get_string_parameter(v, "InkType");
01621   colormode_t colormode = canon_printhead_colors(ink_type,caps);
01622   int printhead= canon_printhead_type(ink_type,caps);
01623 
01624   if ((print_mode && strcmp(print_mode, "BW") == 0) ||
01625       printhead == 0 || caps->inks == CANON_INK_K)
01626     colormode = COLOR_MONOCHROME;
01627 
01628   switch (colormode)
01629     {
01630     case COLOR_CMY:
01631       return "CMY";
01632     case COLOR_CMYK:
01633       return "CMYK";
01634     case COLOR_MONOCHROME:
01635     default:
01636       return "Grayscale";
01637     }
01638 }
01639 
01640 static const stp_param_string_t media_sources[] =
01641               {
01642                 { "Auto",       N_ ("Auto Sheet Feeder") },
01643                 { "Manual",     N_ ("Manual with Pause") },
01644                 { "ManualNP",   N_ ("Manual without Pause") }
01645               };
01646 
01647 
01648 /*
01649  * 'canon_parameters()' - Return the parameter values for the given parameter.
01650  */
01651 
01652 static stp_parameter_list_t
01653 canon_list_parameters(const stp_vars_t *v)
01654 {
01655   stp_parameter_list_t *ret = stp_parameter_list_create();
01656   int i;
01657   for (i = 0; i < the_parameter_count; i++)
01658     stp_parameter_list_add_param(ret, &(the_parameters[i]));
01659   for (i = 0; i < float_parameter_count; i++)
01660     stp_parameter_list_add_param(ret, &(float_parameters[i].param));
01661   return ret;
01662 }
01663 
01664 static void
01665 canon_parameters(const stp_vars_t *v, const char *name,
01666                  stp_parameter_t *description)
01667 {
01668   int           i;
01669 
01670   const canon_cap_t * caps=
01671     canon_get_model_capabilities(stp_get_model_id(v));
01672   description->p_type = STP_PARAMETER_TYPE_INVALID;
01673 
01674   if (name == NULL)
01675     return;
01676 
01677   for (i = 0; i < float_parameter_count; i++)
01678     if (strcmp(name, float_parameters[i].param.name) == 0)
01679       {
01680         stp_fill_parameter_settings(description,
01681                                      &(float_parameters[i].param));
01682         description->deflt.dbl = float_parameters[i].defval;
01683         description->bounds.dbl.upper = float_parameters[i].max;
01684         description->bounds.dbl.lower = float_parameters[i].min;
01685         return;
01686       }
01687 
01688   for (i = 0; i < the_parameter_count; i++)
01689     if (strcmp(name, the_parameters[i].name) == 0)
01690       {
01691         stp_fill_parameter_settings(description, &(the_parameters[i]));
01692         break;
01693       }
01694   if (strcmp(name, "PageSize") == 0)
01695   {
01696     int height_limit, width_limit;
01697     int papersizes = stp_known_papersizes();
01698     description->bounds.str = stp_string_list_create();
01699 
01700     width_limit = caps->max_width;
01701     height_limit = caps->max_height;
01702 
01703     for (i = 0; i < papersizes; i++) {
01704       const stp_papersize_t *pt = stp_get_papersize_by_index(i);
01705       if (strlen(pt->name) > 0 &&
01706           pt->width <= width_limit && pt->height <= height_limit)
01707         {
01708           if (stp_string_list_count(description->bounds.str) == 0)
01709             description->deflt.str = pt->name;
01710           stp_string_list_add_string(description->bounds.str,
01711                                      pt->name, pt->text);
01712         }
01713     }
01714   }
01715   else if (strcmp(name, "Resolution") == 0)
01716   {
01717     int x,y;
01718     int t;
01719     description->bounds.str= stp_string_list_create();
01720     description->deflt.str = NULL;
01721 
01722     for (x=1; x<6; x++) {
01723       for (y=x-1; y<x+1; y++) {
01724         if ((t= canon_ink_type(caps,(x<<4)|y)) > -1) {
01725           int xx = (1<<x)/2*caps->base_res;
01726           int yy = (1<<y)/2*caps->base_res;
01727           const canon_res_t *res = canon_resolutions;
01728           while (res->x > 0) {
01729             if (xx == res->x && yy == res->y) {
01730               stp_string_list_add_string(description->bounds.str,
01731                                         res->name, _(res->text));
01732               stp_deprintf(STP_DBG_CANON,"supports mode '%s'\n",
01733                            res->name);
01734               if (xx >= 300 && yy >= 300 && description->deflt.str == NULL)
01735                 description->deflt.str = res->name;
01736               if (t == 1) {
01737                 stp_string_list_add_string(description->bounds.str,
01738                                           res->name_dmt, _(res->text_dmt));
01739                 stp_deprintf(STP_DBG_CANON,"supports mode '%s'\n",
01740                              res->name_dmt);
01741               }
01742               break;
01743             }
01744             res++;
01745           }
01746         }
01747       }
01748     }
01749   }
01750   else if (strcmp(name, "InkType") == 0)
01751   {
01752     description->bounds.str= stp_string_list_create();
01753     /* used internally: do not translate */
01754     if ((caps->inks & CANON_INK_K))
01755       stp_string_list_add_string(description->bounds.str,
01756                                "Gray", _("Black"));
01757     if ((caps->inks & CANON_INK_CMY))
01758       stp_string_list_add_string(description->bounds.str,
01759                                "RGB", _("CMY Color"));
01760     if ((caps->inks & CANON_INK_CMYK))
01761       stp_string_list_add_string(description->bounds.str,
01762                                "CMYK", _("CMYK Color"));
01763     if ((caps->inks & CANON_INK_CcMmYK))
01764       stp_string_list_add_string(description->bounds.str,
01765                                "PhotoCMY", _("Photo CcMmY Color"));
01766     if ((caps->inks & CANON_INK_CcMmYyK))
01767       stp_string_list_add_string(description->bounds.str,
01768                                "PhotoCMYK", _("Photo CcMmYK Color"));
01769     description->deflt.str =
01770       stp_string_list_param(description->bounds.str, 0)->name;
01771   }
01772   else if (strcmp(name, "InkChannels") == 0)
01773     {
01774       if (caps->inks & CANON_INK_CcMmYyK)
01775         description->deflt.integer = 7;
01776       else if (caps->inks & CANON_INK_CcMmYK)
01777         description->deflt.integer = 6;
01778       else if (caps->inks & CANON_INK_CMYK)
01779         description->deflt.integer = 4;
01780       else if (caps->inks & CANON_INK_CMY)
01781         description->deflt.integer = 3;
01782       else
01783         description->deflt.integer = 1;
01784       description->bounds.integer.lower = -1;
01785       description->bounds.integer.upper = -1;
01786     }
01787   else if (strcmp(name, "MediaType") == 0)
01788   {
01789     int count = sizeof(canon_paper_list) / sizeof(canon_paper_list[0]);
01790     description->bounds.str= stp_string_list_create();
01791     description->deflt.str= canon_paper_list[0].name;
01792 
01793     for (i = 0; i < count; i ++)
01794       stp_string_list_add_string(description->bounds.str,
01795                                 canon_paper_list[i].name,
01796                                 _(canon_paper_list[i].text));
01797   }
01798   else if (strcmp(name, "InputSlot") == 0)
01799   {
01800     int count = 3;
01801     description->bounds.str= stp_string_list_create();
01802     description->deflt.str= media_sources[0].name;
01803     for (i = 0; i < count; i ++)
01804       stp_string_list_add_string(description->bounds.str,
01805                                 media_sources[i].name,
01806                                 _(media_sources[i].text));
01807   }
01808   else if (strcmp(name, "PrintingMode") == 0)
01809   {
01810     description->bounds.str = stp_string_list_create();
01811     stp_string_list_add_string
01812       (description->bounds.str, "Color", _("Color"));
01813     stp_string_list_add_string
01814       (description->bounds.str, "BW", _("Black and White"));
01815     description->deflt.str =
01816       stp_string_list_param(description->bounds.str, 0)->name;
01817   }
01818 }
01819 
01820 
01821 /*
01822  * 'canon_imageable_area()' - Return the imageable area of the page.
01823  */
01824 
01825 static void
01826 internal_imageable_area(const stp_vars_t *v,   /* I */
01827                         int  use_paper_margins,
01828                         int  *left,     /* O - Left position in points */
01829                         int  *right,    /* O - Right position in points */
01830                         int  *bottom,   /* O - Bottom position in points */
01831                         int  *top)      /* O - Top position in points */
01832 {
01833   int   width, length;                  /* Size of page */
01834   int left_margin = 0;
01835   int right_margin = 0;
01836   int bottom_margin = 0;
01837   int top_margin = 0;
01838 
01839   const canon_cap_t * caps= canon_get_model_capabilities(stp_get_model_id(v));
01840   const char *media_size = stp_get_string_parameter(v, "PageSize");
01841   const stp_papersize_t *pt = NULL;
01842 
01843   if (media_size && use_paper_margins)
01844     pt = stp_get_papersize_by_name(media_size);
01845 
01846   stp_default_media_size(v, &width, &length);
01847   if (pt)
01848     {
01849       left_margin = pt->left;
01850       right_margin = pt->right;
01851       bottom_margin = pt->bottom;
01852       top_margin = pt->top;
01853     }
01854   left_margin = MAX(left_margin, caps->border_left);
01855   right_margin = MAX(right_margin, caps->border_right);
01856   top_margin = MAX(top_margin, caps->border_top);
01857   bottom_margin = MAX(bottom_margin, caps->border_bottom);
01858 
01859   *left =       left_margin;
01860   *right =      width - right_margin;
01861   *top =        top_margin;
01862   *bottom =     length - bottom_margin;
01863 }
01864 
01865 static void
01866 canon_imageable_area(const stp_vars_t *v,   /* I */
01867                      int  *left,        /* O - Left position in points */
01868                      int  *right,       /* O - Right position in points */
01869                      int  *bottom,      /* O - Bottom position in points */
01870                      int  *top)         /* O - Top position in points */
01871 {
01872   internal_imageable_area(v, 1, left, right, bottom, top);
01873 }
01874 
01875 static void
01876 canon_limit(const stp_vars_t *v,                /* I */
01877             int *width,
01878             int *height,
01879             int *min_width,
01880             int *min_height)
01881 {
01882   const canon_cap_t * caps=
01883     canon_get_model_capabilities(stp_get_model_id(v));
01884   *width =      caps->max_width;
01885   *height =     caps->max_height;
01886   *min_width = 1;
01887   *min_height = 1;
01888 }
01889 
01890 /*
01891  * 'canon_cmd()' - Sends a command with variable args
01892  */
01893 static void
01894 canon_cmd(const stp_vars_t *v, /* I - the printer         */
01895           const char *ini, /* I - 2 bytes start code  */
01896           const char cmd,  /* I - command code        */
01897           int  num,  /* I - number of arguments */
01898           ...        /* I - the args themselves */
01899           )
01900 {
01901   unsigned char *buffer = stp_zalloc(num + 1);
01902   int i;
01903   va_list ap;
01904 
01905   if (num)
01906     {
01907       va_start(ap, num);
01908       for (i=0; i<num; i++)
01909         buffer[i]= (unsigned char) va_arg(ap, int);
01910       va_end(ap);
01911     }
01912 
01913   stp_zfwrite(ini,2,1,v);
01914   if (cmd)
01915     {
01916       stp_putc(cmd,v);
01917       stp_put16_le(num, v);
01918       if (num)
01919         stp_zfwrite((const char *)buffer,num,1,v);
01920     }
01921   stp_free(buffer);
01922 }
01923 
01924 #define PUT(WHAT,VAL,RES) stp_deprintf(STP_DBG_CANON,"canon: "WHAT\
01925 " is %04x =% 5d = %f\" = %f mm\n",(VAL),(VAL),(VAL)/(1.*RES),(VAL)/(RES/25.4))
01926 
01927 #define ESC28 "\033\050"
01928 #define ESC5b "\033\133"
01929 #define ESC40 "\033\100"
01930 
01931 /* ESC [K --  -- reset printer:
01932  */
01933 static void
01934 canon_init_resetPrinter(const stp_vars_t *v, canon_init_t *init)
01935 {
01936   unsigned long f=init->caps->features;
01937   if (f & (CANON_CAP_ACKSHORT))
01938     {
01939       canon_cmd(v,ESC5b,0x4b, 2, 0x00,0x1f);
01940       stp_puts("BJLSTART\nControlMode=Common\n",v);
01941       if (f & CANON_CAP_ACKSHORT) stp_puts("AckTime=Short\n",v);
01942       stp_puts("BJLEND\n",v);
01943     }
01944   canon_cmd(v,ESC5b,0x4b, 2, 0x00,0x0f);
01945 }
01946 
01947 /* ESC (a -- 0x61 -- cmdSetPageMode --:
01948  */
01949 static void
01950 canon_init_setPageMode(const stp_vars_t *v, canon_init_t *init)
01951 {
01952   if (!(init->caps->features & CANON_CAP_a))
01953     return;
01954 
01955   if (init->caps->features & CANON_CAP_a)
01956     canon_cmd(v,ESC28,0x61, 1, 0x01);
01957 }
01958 
01959 /* ESC (b -- 0x62 -- -- set data compression:
01960  */
01961 static void
01962 canon_init_setDataCompression(const stp_vars_t *v, canon_init_t *init)
01963 {
01964   if (!(init->caps->features & CANON_CAP_b))
01965     return;
01966 
01967   canon_cmd(v,ESC28,0x62, 1, 0x01);
01968 }
01969 
01970 /* ESC (c -- 0x63 -- cmdSetColor --:
01971  */
01972 static void
01973 canon_init_setColor(const stp_vars_t *v, canon_init_t *init)
01974 {
01975   unsigned char
01976     arg_63_1, arg_63_2, arg_63_3;
01977 
01978 
01979   if (!(init->caps->features & CANON_CAP_c))
01980     return;
01981 
01982   arg_63_1 = init->caps->model_id << 4;                                         /* MODEL_ID */
01983 
01984   switch ( init->caps->model_id ) {
01985 
01986         case 0:                 /* very old 360 dpi series: BJC-800/820 */
01987                 break;          /*      tbd */
01988 
01989         case 1:                 /* 360 dpi series - BJC-4000, BJC-210, BJC-70 and their descendants */
01990                 if (!init->printing_color)
01991                         arg_63_1|= 0x01;                                        /* PRINT_COLOUR */
01992 
01993                 arg_63_2 = ((init->pt ? init->pt->media_code : 0) << 4)         /* PRINT_MEDIA */
01994                         + 1;    /* hardcode to High quality for now */          /* PRINT_QUALITY */
01995 
01996                 canon_cmd(v,ESC28,0x63, 2, arg_63_1, arg_63_2);
01997                 break;
01998 
01999         case 2:                 /* are any models using this? */
02000                 break;
02001 
02002         case 3:                 /* 720 dpi series - BJC-3000 and descendants */
02003                 if (!init->printing_color)
02004                         arg_63_1|= 0x01;                                        /* colour mode */
02005 
02006                 arg_63_2 = (init->pt) ? init->pt->media_code : 0;               /* print media type */
02007 
02008                 arg_63_3 = 2;   /* hardcode to whatever this means for now */   /* quality, apparently */
02009 
02010                 canon_cmd(v,ESC28,0x63, 3, arg_63_1, arg_63_2, arg_63_3);
02011                 break;
02012         }
02013 
02014   return;
02015 }
02016 
02017 /* ESC (d -- 0x64 -- -- set raster resolution:
02018  */
02019 static void
02020 canon_init_setResolution(const stp_vars_t *v, canon_init_t *init)
02021 {
02022   if (!(init->caps->features & CANON_CAP_d))
02023     return;
02024 
02025   canon_cmd(v,ESC28,0x64, 4,
02026             (init->ydpi >> 8 ), (init->ydpi & 255),
02027             (init->xdpi >> 8 ), (init->xdpi & 255));
02028 }
02029 
02030 /* ESC (g -- 0x67 -- cmdSetPageMargins --:
02031  */
02032 static void
02033 canon_init_setPageMargins(const stp_vars_t *v, canon_init_t *init)
02034 {
02035   /* TOFIX: what exactly is to be sent?
02036    * Is it the printable length or the bottom border?
02037    * Is is the printable width or the right border?
02038    */
02039 
02040   int minlength= 0;
02041   int minwidth= 0;
02042   int length= init->page_height*5/36;
02043   int width= init->page_width*5/36;
02044 
02045   if (!(init->caps->features & CANON_CAP_g))
02046     return;
02047 
02048   if (minlength>length) length= minlength;
02049   if (minwidth>width) width= minwidth;
02050 
02051   canon_cmd(v,ESC28,0x67, 4, 0,
02052             (unsigned char)(length),1,
02053             (unsigned char)(width));
02054 
02055 }
02056 
02057 /* ESC (l -- 0x6c -- cmdSetTray --:
02058  */
02059 static void
02060 canon_init_setTray(const stp_vars_t *v, canon_init_t *init)
02061 {
02062   unsigned char
02063     arg_6c_1 = 0x00,
02064     arg_6c_2 = 0x00; /* plain paper */
02065 
02066   /* int media= canon_media_type(media_str,caps); */
02067   int source= canon_source_type(init->source_str,init->caps);
02068 
02069   if (!(init->caps->features & CANON_CAP_l))
02070     return;
02071 
02072   arg_6c_1 = init->caps->model_id << 4;
02073 
02074   arg_6c_1|= (source & 0x0f);
02075 
02076   if (init->pt) arg_6c_2= init->pt->media_code;
02077 
02078   canon_cmd(v,ESC28,0x6c, 2, arg_6c_1, arg_6c_2);
02079 }
02080 
02081 /* ESC (m -- 0x6d --  -- :
02082  */
02083 static void
02084 canon_init_setPrintMode(const stp_vars_t *v, canon_init_t *init)
02085 {
02086   unsigned char
02087     arg_6d_1 = 0x03, /* color printhead? */
02088     arg_6d_2 = 0x00, /* 00=color  02=b/w */
02089     arg_6d_3 = 0x00, /* only 01 for bjc8200 */
02090     arg_6d_a = 0x03, /* A4 paper */
02091     arg_6d_b = 0x00;
02092 
02093   if (!(init->caps->features & CANON_CAP_m))
02094     return;
02095 
02096   arg_6d_a= canon_size_type(v,init->caps);
02097   if (!arg_6d_a)
02098     arg_6d_b= 1;
02099 
02100   if (init->print_head==0)
02101     arg_6d_1= 0x03;
02102   else if (init->print_head<=2)
02103     arg_6d_1= 0x02;
02104   else if (init->print_head<=4)
02105     arg_6d_1= 0x04;
02106   if (!init->printing_color)
02107     arg_6d_2= 0x02;
02108 
02109   if (init->caps->model==8200)
02110     arg_6d_3= 0x01;
02111 
02112   canon_cmd(v,ESC28,0x6d,12, arg_6d_1,
02113             0xff,0xff,0x00,0x00,0x07,0x00,
02114             arg_6d_a,arg_6d_b,arg_6d_2,0x00,arg_6d_3);
02115 }
02116 
02117 /* ESC (p -- 0x70 -- cmdSetPageMargins2 --:
02118  */
02119 static void
02120 canon_init_setPageMargins2(const stp_vars_t *v, canon_init_t *init)
02121 {
02122   /* TOFIX: what exactly is to be sent?
02123    * Is it the printable length or the bottom border?
02124    * Is is the printable width or the right border?
02125    */
02126 
02127   int printable_width=  init->page_width*5/6;
02128   int printable_length= init->page_height*5/6;
02129 
02130   unsigned char arg_70_1= (printable_length >> 8) & 0xff;
02131   unsigned char arg_70_2= (printable_length) & 0xff;
02132   unsigned char arg_70_3= (printable_width >> 8) & 0xff;
02133   unsigned char arg_70_4= (printable_width) & 0xff;
02134 
02135   if (!(init->caps->features & CANON_CAP_p))
02136     return;
02137 
02138   canon_cmd(v,ESC28,0x70, 8,
02139             arg_70_1, arg_70_2, 0x00, 0x00,
02140             arg_70_3, arg_70_4, 0x00, 0x00);
02141 }
02142 
02143 /* ESC (q -- 0x71 -- setPageID -- :
02144  */
02145 static void
02146 canon_init_setPageID(const stp_vars_t *v, canon_init_t *init)
02147 {
02148   if (!(init->caps->features & CANON_CAP_q))
02149     return;
02150 
02151   canon_cmd(v,ESC28,0x71, 1, 0x01);
02152 }
02153 
02154 /* ESC (r -- 0x72 --  -- :
02155  */
02156 static void
02157 canon_init_setX72(const stp_vars_t *v, canon_init_t *init)
02158 {
02159   if (!(init->caps->features & CANON_CAP_r))
02160     return;
02161 
02162   canon_cmd(v,ESC28,0x72, 1, 0x61); /* whatever for - 8200 needs it */
02163 }
02164 
02165 /* ESC (t -- 0x74 -- cmdSetImage --:
02166  */
02167 static void
02168 canon_init_setImage(const stp_vars_t *v, canon_init_t *init)
02169 {
02170   unsigned char
02171     arg_74_1 = 0x01, /* 1 bit per pixel */
02172     arg_74_2 = 0x00, /*  */
02173     arg_74_3 = 0x01; /* 01 <= 360 dpi    09 >= 720 dpi */
02174 
02175   if (!(init->caps->features & CANON_CAP_t))
02176     return;
02177 
02178   if (init->xdpi==1440) arg_74_2= 0x04;
02179   if (init->ydpi>=720)  arg_74_3= 0x09;
02180 
02181   if (init->bits>1) {
02182     arg_74_1= 0x02;
02183     arg_74_2= 0x80;
02184     arg_74_3= 0x09;
02185     if (init->colormode == COLOR_CMY) arg_74_3= 0x02; /* for BC-06 cartridge!!! */
02186   }
02187 
02188   /* workaround for the bjc8200 in 6color mode - not really understood */
02189   if (init->caps->model==8200) {
02190     if (init->colormode==COLOR_CCMMYK) {
02191       arg_74_1= 0xff;
02192       arg_74_2= 0x90;
02193       arg_74_3= 0x04;
02194       init->bits=3;
02195       if (init->ydpi>600)  arg_74_3= 0x09;
02196     } else {
02197       arg_74_1= 0x01;
02198       arg_74_2= 0x00;
02199       arg_74_3= 0x01;
02200       if (init->ydpi>600)  arg_74_3= 0x09;
02201     }
02202   }
02203 
02204   canon_cmd(v,ESC28,0x74, 3, arg_74_1, arg_74_2, arg_74_3);
02205 }
02206 
02207 static void
02208 canon_init_printer(const stp_vars_t *v, canon_init_t *init)
02209 {
02210   int mytop;
02211   /* init printer */
02212 
02213   canon_init_resetPrinter(v,init);       /* ESC [K */
02214   canon_init_setPageMode(v,init);        /* ESC (a */
02215   canon_init_setDataCompression(v,init); /* ESC (b */
02216   canon_init_setPageID(v,init);          /* ESC (q */
02217   canon_init_setPrintMode(v,init);       /* ESC (m */
02218   canon_init_setResolution(v,init);      /* ESC (d */
02219   canon_init_setImage(v,init);           /* ESC (t */
02220   canon_init_setColor(v,init);           /* ESC (c */
02221   canon_init_setPageMargins(v,init);     /* ESC (g */
02222   canon_init_setPageMargins2(v,init);    /* ESC (p */
02223   canon_init_setTray(v,init);            /* ESC (l */
02224   canon_init_setX72(v,init);             /* ESC (r */
02225 
02226   /* some linefeeds */
02227 
02228   mytop= (init->top*init->ydpi)/72;
02229   canon_cmd(v,ESC28,0x65, 2, (mytop >> 8 ),(mytop & 255));
02230 }
02231 
02232 static void
02233 canon_deinit_printer(const stp_vars_t *v, canon_init_t *init)
02234 {
02235   /* eject page */
02236   stp_putc(0x0c,v);
02237 
02238   /* say goodbye */
02239   canon_cmd(v,ESC28,0x62,1,0);
02240   if (init->caps->features & CANON_CAP_a)
02241     canon_cmd(v,ESC28,0x61, 1, 0);
02242 }
02243 
02244 static int
02245 canon_start_job(const stp_vars_t *v, stp_image_t *image)
02246 {
02247   return 1;
02248 }
02249 
02250 static int
02251 canon_end_job(const stp_vars_t *v, stp_image_t *image)
02252 {
02253   canon_cmd(v,ESC40,0,0);
02254   return 1;
02255 }
02256 
02257 /*
02258  * 'advance_buffer()' - Move (num) lines of length (len) down one line
02259  *                      and sets first line to 0s
02260  *                      accepts NULL pointers as buf
02261  *                  !!! buf must contain more than (num) lines !!!
02262  *                      also sets first line to 0s if num<1
02263  */
02264 static void
02265 canon_advance_buffer(unsigned char *buf, int len, int num)
02266 {
02267   if (!buf || !len) return;
02268   if (num>0) memmove(buf+len,buf,len*num);
02269   memset(buf,0,len);
02270 }
02271 
02272 static void
02273 setup_column(canon_privdata_t *privdata, int col, int buf_length)
02274 {
02275   privdata->cols[col] = stp_zalloc(buf_length * (privdata->delay[col] + 1));
02276 }
02277 
02278 static void
02279 canon_printfunc(stp_vars_t *v)
02280 {
02281   int i;
02282   canon_privdata_t *pd = (canon_privdata_t *) stp_get_component_data(v, "Driver");
02283   canon_write_line(v);
02284   for (i = 0; i < 7; i++)
02285     canon_advance_buffer(pd->cols[i], pd->buf_length, pd->delay[i]);
02286 
02287 }
02288 
02289 static double
02290 get_double_param(stp_vars_t *v, const char *param)
02291 {
02292   if (param && stp_check_float_parameter(v, param, STP_PARAMETER_ACTIVE))
02293     return stp_get_float_parameter(v, param);
02294   else
02295     return 1.0;
02296 }
02297 
02298 static void
02299 set_ink_ranges(stp_vars_t *v, const canon_variable_ink_t *ink, int color,
02300                const char *channel_param, const char *subchannel_param)
02301 {
02302   if (!ink)
02303     return;
02304   stp_dither_set_inks_full(v, color, ink->numshades, ink->shades, 1.0,
02305                            ink_darknesses[color]);
02306   stp_channel_set_density_adjustment
02307     (v, color, 1, (get_double_param(v, channel_param) *
02308                    get_double_param(v, subchannel_param) *
02309                    get_double_param(v, "Density")));
02310 }
02311 
02312 /*
02313  * 'canon_print()' - Print an image to a CANON printer.
02314  */
02315 static int
02316 canon_do_print(stp_vars_t *v, stp_image_t *image)
02317 {
02318   int i;
02319   int           status = 1;
02320   int           model = stp_get_model_id(v);
02321   const char    *resolution = stp_get_string_parameter(v, "Resolution");
02322   const char    *media_source = stp_get_string_parameter(v, "InputSlot");
02323   const char    *print_mode = stp_get_string_parameter(v, "PrintingMode");
02324   int printing_color = 0;
02325   const char    *ink_type = stp_get_string_parameter(v, "InkType");
02326   int           top = stp_get_top(v);
02327   int           left = stp_get_left(v);
02328   int           y;              /* Looping vars */
02329   int           xdpi, ydpi;     /* Resolution */
02330   int           n;              /* Output number */
02331   canon_privdata_t privdata;
02332   int           page_width,     /* Width of page */
02333                 page_height,    /* Length of page */
02334                 page_left,
02335                 page_top,
02336                 page_right,
02337                 page_bottom,
02338                 page_true_height,       /* True length of page */
02339                 out_width,      /* Width of image on page */
02340                 out_height,     /* Length of image on page */
02341                 out_channels,   /* Output bytes per pixel */
02342                 length,         /* Length of raster data */
02343                 errdiv,         /* Error dividend */
02344                 errmod,         /* Error modulus */
02345                 errval,         /* Current error value */
02346                 errline,        /* Current raster line */
02347                 errlast;        /* Last raster line loaded */
02348   unsigned      zero_mask;
02349   int           bits= 1;
02350   int           image_height,
02351                 image_width;
02352   int           res_code;
02353   int           use_6color= 0;
02354   double        k_upper, k_lower;
02355   stp_curve_t *lum_adjustment = NULL;
02356   stp_curve_t *hue_adjustment = NULL;
02357   stp_curve_t *sat_adjustment = NULL;
02358 
02359   canon_init_t  init;
02360   const canon_cap_t * caps= canon_get_model_capabilities(model);
02361   int printhead= canon_printhead_type(ink_type,caps);
02362   colormode_t colormode = canon_printhead_colors(ink_type,caps);
02363   const paper_t *pt;
02364   const canon_variable_inkset_t *inks;
02365   const canon_res_t *res = canon_resolutions;
02366 
02367   if (!stp_verify(v))
02368     {
02369       stp_eprintf(v, "Print options not verified; cannot print.\n");
02370       return 0;
02371     }
02372   if (strcmp(print_mode, "Color") == 0)
02373     printing_color = 1;
02374 
02375   PUT("top        ",top,72);
02376   PUT("left       ",left,72);
02377 
02378   /*
02379   * Setup a read-only pixel region for the entire image...
02380   */
02381 
02382   stp_image_init(image);
02383 
02384   /* force grayscale if image is grayscale
02385    *                 or single black cartridge installed
02386    */
02387 
02388   if (printhead == 0 || caps->inks == CANON_INK_K)
02389     {
02390       printing_color = 0;
02391       stp_set_string_parameter(v, "PrintingMode", "BW");
02392     }
02393 
02394   if (!printing_color)
02395     colormode = COLOR_MONOCHROME;
02396 
02397  /*
02398   * Figure out the output resolution...
02399   */
02400 
02401   xdpi = -1;
02402   ydpi = -1;
02403   while (res->x > 0) {
02404     if (strcmp(resolution, res->name) == 0 ||
02405         strcmp(resolution, res->name_dmt) == 0)
02406       {
02407         xdpi = res->x;
02408         ydpi = res->y;
02409         break;
02410       }
02411     res++;
02412   }
02413 
02414   stp_deprintf(STP_DBG_CANON,"canon: resolution=%dx%d\n",xdpi,ydpi);
02415   stp_deprintf(STP_DBG_CANON,"       rescode   =0x%x\n",canon_res_code(caps,xdpi,ydpi));
02416   res_code= canon_res_code(caps,xdpi,ydpi);
02417 
02418   if (strcmp(resolution, res->name_dmt) == 0 &&
02419       (caps->features & CANON_CAP_DMT)) {
02420     bits= 2;
02421     stp_deprintf(STP_DBG_CANON,"canon: using drop modulation technology\n");
02422   }
02423 
02424  /*
02425   * Compute the output size...
02426   */
02427 
02428   out_width = stp_get_width(v);
02429   out_height = stp_get_height(v);
02430 
02431   internal_imageable_area(v, 0, &page_left, &page_right,
02432                           &page_bottom, &page_top);
02433   left -= page_left;
02434   top -= page_top;
02435   page_width = page_right - page_left;
02436   page_height = page_bottom - page_top;
02437 
02438   image_height = stp_image_height(image);
02439   image_width = stp_image_width(image);
02440 
02441   stp_default_media_size(v, &n, &page_true_height);
02442 
02443   PUT("top        ",top,72);
02444   PUT("left       ",left,72);
02445   PUT("page_true_height",page_true_height,72);
02446   PUT("out_width ", out_width,xdpi);
02447   PUT("out_height", out_height,ydpi);
02448 
02449   PUT("top     ",top,72);
02450   PUT("left    ",left,72);
02451 
02452   pt = get_media_type(stp_get_string_parameter(v, "MediaType"));
02453 
02454   init.caps = caps;
02455   init.printing_color = printing_color;
02456   init.pt = pt;
02457   init.print_head = printhead;
02458   init.colormode = colormode;
02459   init.source_str = media_source;
02460   init.xdpi = xdpi;
02461   init.ydpi = ydpi;
02462   init.page_width = page_width;
02463   init.page_height = page_height;
02464   init.top = top;
02465   init.left = left;
02466   init.bits = bits;
02467 
02468   canon_init_printer(v, &init);
02469 
02470   /* possibly changed during initialitation
02471    * to enforce valid modes of operation:
02472    */
02473   bits= init.bits;
02474   xdpi= init.xdpi;
02475   ydpi= init.ydpi;
02476 
02477  /*
02478   * Convert image size to printer resolution...
02479   */
02480 
02481   out_width  = xdpi * out_width / 72;
02482   out_height = ydpi * out_height / 72;
02483 
02484   PUT("out_width ", out_width,xdpi);
02485   PUT("out_height", out_height,ydpi);
02486 
02487   left = xdpi * left / 72;
02488 
02489   PUT("leftskip",left,xdpi);
02490 
02491   for (i = 0; i < 7; i++)
02492     privdata.cols[i] = NULL;
02493 
02494   if(xdpi==1440){
02495     privdata.delay[0] = 0;
02496     privdata.delay[1] = 112;
02497     privdata.delay[2] = 224;
02498     privdata.delay[3] = 336;
02499     privdata.delay[4] = 112;
02500     privdata.delay[5] = 224;
02501     privdata.delay[6] = 336;
02502     privdata.delay_max = 336;
02503     stp_deprintf(STP_DBG_CANON,"canon: delay on!\n");
02504   } else {
02505     for (i = 0; i < 7; i++)
02506       privdata.delay[i] = 0;
02507     privdata.delay_max = 0;
02508     stp_deprintf(STP_DBG_CANON,"canon: delay off!\n");
02509   }
02510 
02511  /*
02512   * Allocate memory for the raster data...
02513   */
02514 
02515   length = (out_width + 7) / 8;
02516 
02517   privdata.buf_length= length*bits;
02518   privdata.left = left;
02519   privdata.bits = bits;
02520   privdata.out_width = out_width;
02521   privdata.caps = caps;
02522   privdata.ydpi = ydpi;
02523 
02524   stp_deprintf(STP_DBG_CANON,"canon: buflength is %d!\n",privdata.buf_length);
02525 
02526   if (colormode==COLOR_MONOCHROME) {
02527     setup_column(&privdata, 0, privdata.buf_length);
02528   } else {
02529     setup_column(&privdata, 1, privdata.buf_length);
02530     setup_column(&privdata, 2, privdata.buf_length);
02531     setup_column(&privdata, 3, privdata.buf_length);
02532 
02533     if (colormode!=COLOR_CMY)
02534       setup_column(&privdata, 0, privdata.buf_length);
02535 
02536     if (colormode==COLOR_CCMMYK || colormode==COLOR_CCMMYYK) {
02537       use_6color= 1;
02538       setup_column(&privdata, 4, privdata.buf_length);
02539       setup_column(&privdata, 5, privdata.buf_length);
02540       if (colormode==CANON_INK_CcMmYyK)
02541         setup_column(&privdata, 6, privdata.buf_length);
02542     }
02543   }
02544 
02545   if (privdata.cols[0])
02546     {
02547       if (privdata.cols[1])
02548         stp_set_string_parameter(v, "STPIOutputType", "KCMY");
02549       else
02550         stp_set_string_parameter(v, "STPIOutputType", "Grayscale");
02551     }
02552   else
02553     stp_set_string_parameter(v, "STPIOutputType", "CMY");
02554 
02555   stp_deprintf(STP_DBG_CANON,
02556                "canon: driver will use colors %s%s%s%s%s%s%s\n",
02557                privdata.cols[0] ? "K" : "",
02558                privdata.cols[1] ? "C" : "",
02559                privdata.cols[2] ? "M" : "",
02560                privdata.cols[3] ? "Y" : "",
02561                privdata.cols[4] ? "c" : "",
02562                privdata.cols[5] ? "m" : "",
02563                privdata.cols[6] ? "y" : "");
02564 
02565   stp_deprintf(STP_DBG_CANON,"density is %f\n",
02566                stp_get_float_parameter(v, "Density"));
02567 
02568   /*
02569    * Compute the LUT.  For now, it's 8 bit, but that may eventually
02570    * sometimes change.
02571    */
02572 
02573   if (!stp_check_float_parameter(v, "Density", STP_PARAMETER_DEFAULTED))
02574     {
02575       stp_set_float_parameter_active(v, "Density", STP_PARAMETER_ACTIVE);
02576       stp_set_float_parameter(v, "Density", 1.0);
02577     }
02578   if (pt)
02579     stp_scale_float_parameter(v, "Density", pt->base_density);
02580   else                  /* Can't find paper type? Assume plain */
02581     stp_scale_float_parameter(v, "Density", .5);
02582   stp_scale_float_parameter(v, "Density", canon_density(caps, res_code));
02583   if (stp_get_float_parameter(v, "Density") > 1.0)
02584     stp_set_float_parameter(v, "Density", 1.0);
02585   if (colormode == COLOR_MONOCHROME)
02586     stp_scale_float_parameter(v, "Gamma", 1.25);
02587 
02588   stp_deprintf(STP_DBG_CANON,"density is %f\n",
02589                stp_get_float_parameter(v, "Density"));
02590 
02591  /*
02592   * Output the page...
02593   */
02594 
02595 
02596   if (use_6color)
02597     k_lower = .4 / bits + .1;
02598   else
02599     k_lower = .25 / bits;
02600   if (pt)
02601     {
02602       k_lower *= pt->k_lower_scale;
02603       k_upper = pt->k_upper;
02604     }
02605   else
02606     {
02607       k_lower *= .5;
02608       k_upper = .5;
02609     }
02610   if (!stp_check_float_parameter(v, "GCRLower", STP_PARAMETER_ACTIVE))
02611     stp_set_default_float_parameter(v, "GCRLower", k_lower);
02612   if (!stp_check_float_parameter(v, "GCRUpper", STP_PARAMETER_ACTIVE))
02613     stp_set_default_float_parameter(v, "GCRUpper", k_upper);
02614   stp_dither_init(v, image, out_width, xdpi, ydpi);
02615 
02616   for (i = 0; i < 7; i++)
02617     {
02618       if (privdata.cols[i])
02619         stp_dither_add_channel(v, privdata.cols[i], channel_color_map[i],
02620                                subchannel_color_map[i]);
02621     }
02622 
02623   if ((inks = canon_inks(caps, res_code, colormode, bits))!=0)
02624     {
02625       set_ink_ranges(v, inks->c, STP_ECOLOR_C, "MagentaDensity",
02626                      "LightCyanTransition");
02627       set_ink_ranges(v, inks->m, STP_ECOLOR_M, "MagentaDensity",
02628                      "LightMagentaTransition");
02629       set_ink_ranges(v, inks->y, STP_ECOLOR_Y, "YellowDensity",
02630                      "LightYellowTransition");
02631       set_ink_ranges(v, inks->k, STP_ECOLOR_K, "BlackDensity", NULL);
02632     }
02633   stp_channel_set_density_adjustment
02634     (v, STP_ECOLOR_C, 0,
02635      get_double_param(v, "CyanDensity") * get_double_param(v, "Density"));
02636   stp_channel_set_density_adjustment
02637     (v, STP_ECOLOR_M, 0,
02638      get_double_param(v, "MagentaDensity") * get_double_param(v, "Density"));
02639   stp_channel_set_density_adjustment
02640     (v, STP_ECOLOR_Y, 0,
02641      get_double_param(v, "YellowDensity") * get_double_param(v, "Density"));
02642   stp_channel_set_density_adjustment
02643     (v, STP_ECOLOR_K, 0,
02644      get_double_param(v, "BlackDensity") * get_double_param(v, "Density"));
02645 
02646   errdiv  = image_height / out_height;
02647   errmod  = image_height % out_height;
02648   errval  = 0;
02649   errlast = -1;
02650   errline  = 0;
02651 
02652   if (!stp_check_curve_parameter(v, "HueMap", STP_PARAMETER_ACTIVE) &&
02653       pt->hue_adjustment)
02654     {
02655       hue_adjustment = stp_read_and_compose_curves
02656         (canon_hue_adjustment(model),
02657          pt ? pt->hue_adjustment : NULL, STP_CURVE_COMPOSE_ADD);
02658       stp_set_curve_parameter(v, "HueMap", hue_adjustment);
02659       stp_curve_destroy(hue_adjustment);
02660     }
02661   if (!stp_check_curve_parameter(v, "LumMap", STP_PARAMETER_ACTIVE) &&
02662       pt->lum_adjustment)
02663     {
02664       lum_adjustment = stp_read_and_compose_curves
02665         (canon_lum_adjustment(model),
02666          pt ? pt->lum_adjustment : NULL, STP_CURVE_COMPOSE_MULTIPLY);
02667       stp_set_curve_parameter(v, "LumMap", lum_adjustment);
02668       stp_curve_destroy(lum_adjustment);
02669     }
02670   if (!stp_check_curve_parameter(v, "SatMap", STP_PARAMETER_ACTIVE) &&
02671       pt->sat_adjustment)
02672     {
02673       sat_adjustment = stp_read_and_compose_curves
02674         (canon_sat_adjustment(model),
02675          pt ? pt->sat_adjustment : NULL, STP_CURVE_COMPOSE_MULTIPLY);
02676       stp_set_curve_parameter(v, "SatMap", sat_adjustment);
02677       stp_curve_destroy(sat_adjustment);
02678     }
02679 
02680   out_channels = stp_color_init(v, image, 65536);
02681   stp_allocate_component_data(v, "Driver", NULL, NULL, &privdata);
02682 
02683   privdata.emptylines = 0;
02684   for (y = 0; y < out_height; y ++)
02685   {
02686     int duplicate_line = 1;
02687 
02688     if (errline != errlast)
02689     {
02690       errlast = errline;
02691       duplicate_line = 0;
02692       if (stp_color_get_row(v, image, errline, &zero_mask))
02693         {
02694           status = 2;
02695           break;
02696         }
02697     }
02698 
02699     stp_dither(v, y, duplicate_line, zero_mask, NULL);
02700     canon_printfunc(v);
02701     errval += errmod;
02702     errline += errdiv;
02703     if (errval >= out_height)
02704     {
02705       errval -= out_height;
02706       errline ++;
02707     }
02708   }
02709 
02710   /*
02711    * Flush delayed buffers...
02712    */
02713 
02714   if (privdata.delay_max) {
02715     stp_deprintf(STP_DBG_CANON,"\ncanon: flushing %d possibly delayed buffers\n",
02716                  privdata.delay_max);
02717     for (y= 0; y<privdata.delay_max; y++) {
02718 
02719       canon_write_line(v);
02720       for (i = 0; i < 7; i++)
02721         canon_advance_buffer(privdata.cols[i], privdata.buf_length,
02722                              privdata.delay[i]);
02723     }
02724   }
02725 
02726   stp_image_conclude(image);
02727 
02728  /*
02729   * Cleanup...
02730   */
02731 
02732   for (i = 0; i < 7; i++)
02733     if (privdata.cols[i])
02734       stp_free(privdata.cols[i]);
02735 
02736   canon_deinit_printer(v, &init);
02737   return status;
02738 }
02739 
02740 static int
02741 canon_print(const stp_vars_t *v, stp_image_t *image)
02742 {
02743   int status;
02744   stp_vars_t *nv = stp_vars_create_copy(v);
02745   stp_prune_inactive_options(nv);
02746   status = canon_do_print(nv, image);
02747   stp_vars_destroy(nv);
02748   return status;
02749 }
02750 
02751 static const stp_printfuncs_t print_canon_printfuncs =
02752 {
02753   canon_list_parameters,
02754   canon_parameters,
02755   stp_default_media_size,
02756   canon_imageable_area,
02757   canon_limit,
02758   canon_print,
02759   canon_describe_resolution,
02760   canon_describe_output,
02761   stp_verify_printer_params,
02762   canon_start_job,
02763   canon_end_job
02764 };
02765 
02766 /*
02767  * 'canon_fold_lsb_msb()' fold 2 lines in order lsb/msb
02768  */
02769 
02770 static void
02771 canon_fold_2bit(const unsigned char *line,
02772                 int single_length,
02773                 unsigned char *outbuf)
02774 {
02775   int i;
02776   for (i = 0; i < single_length; i++) {
02777     outbuf[0] =
02778       ((line[0] & (1 << 7)) >> 1) |
02779       ((line[0] & (1 << 6)) >> 2) |
02780       ((line[0] & (1 << 5)) >> 3) |
02781       ((line[0] & (1 << 4)) >> 4) |
02782       ((line[single_length] & (1 << 7)) >> 0) |
02783       ((line[single_length] & (1 << 6)) >> 1) |
02784       ((line[single_length] & (1 << 5)) >> 2) |
02785       ((line[single_length] & (1 << 4)) >> 3);
02786     outbuf[1] =
02787       ((line[0] & (1 << 3)) << 3) |
02788       ((line[0] & (1 << 2)) << 2) |
02789       ((line[0] & (1 << 1)) << 1) |
02790       ((line[0] & (1 << 0)) << 0) |
02791       ((line[single_length] & (1 << 3)) << 4) |
02792       ((line[single_length] & (1 << 2)) << 3) |
02793       ((line[single_length] & (1 << 1)) << 2) |
02794       ((line[single_length] & (1 << 0)) << 1);
02795     line++;
02796     outbuf += 2;
02797   }
02798 }
02799 
02800 #ifndef USE_3BIT_FOLD_TYPE
02801 #error YOU MUST CHOOSE A VALUE FOR USE_3BIT_FOLD_TYPE
02802 #endif
02803 
02804 #if USE_3BIT_FOLD_TYPE == 333
02805 
02806 static void
02807 canon_fold_3bit(const unsigned char *line,
02808                 int single_length,
02809                 unsigned char *outbuf)
02810 {
02811   int i;
02812   for (i = 0; i < single_length; i++) {
02813     outbuf[0] =
02814       ((line[0] & (1 << 7)) >> 2) |
02815       ((line[0] & (1 << 6)) >> 4) |
02816       ((line[single_length] & (1 << 7)) >> 1) |
02817       ((line[single_length] & (1 << 6)) >> 3) |
02818       ((line[single_length] & (1 << 5)) >> 5) |
02819       ((line[2*single_length] & (1 << 7)) << 0) |
02820       ((line[2*single_length] & (1 << 6)) >> 2) |
02821       ((line[2*single_length] & (1 << 5)) >> 4);
02822     outbuf[1] =
02823       ((line[0] & (1 << 5)) << 2) |
02824       ((line[0] & (1 << 4)) << 0) |
02825       ((line[0] & (1 << 3)) >> 2) |
02826       ((line[single_length] & (1 << 4)) << 1) |
02827       ((line[single_length] & (1 << 3)) >> 1) |
02828       ((line[2*single_length] & (1 << 4)) << 2) |
02829       ((line[2*single_length] & (1 << 3)) << 0) |
02830       ((line[2*single_length] & (1 << 2)) >> 2);
02831     outbuf[2] =
02832       ((line[0] & (1 << 2)) << 4) |
02833       ((line[0] & (1 << 1)) << 2) |
02834       ((line[0] & (1 << 0)) << 0) |
02835       ((line[single_length] & (1 << 2)) << 5) |
02836       ((line[single_length] & (1 << 1)) << 3) |
02837       ((line[single_length] & (1 << 0)) << 1) |
02838       ((line[2*single_length] & (1 << 1)) << 4) |
02839       ((line[2*single_length] & (1 << 0)) << 2);
02840     line++;
02841     outbuf += 3;
02842   }
02843 }
02844 
02845 #elif USE_3BIT_FOLD_TYPE == 323
02846 
02847 static void
02848 canon_fold_3bit(const unsigned char *line,
02849                 int single_length,
02850                 unsigned char *outbuf)
02851 {
02852   unsigned char A0,A1,A2,B0,B1,B2,C0,C1,C2;
02853   const unsigned char *last= line+single_length;
02854 
02855   for (; line < last; line+=3, outbuf+=8) {
02856 
02857     A0= line[0]; B0= line[single_length]; C0= line[2*single_length];
02858 
02859     if (line<last-2) {
02860       A1= line[1]; B1= line[single_length+1]; C1= line[2*single_length+1];
02861     } else {
02862       A1= 0; B1= 0; C1= 0;
02863     }
02864     if (line<last-1) {
02865       A2= line[2]; B2= line[single_length+2]; C2= line[2*single_length+2];
02866     } else {
02867       A2= 0; B2= 0; C2= 0;
02868     }
02869 
02870     outbuf[0] =
02871       ((C0 & 0x80) >> 0) |
02872       ((B0 & 0x80) >> 1) |
02873       ((A0 & 0x80) >> 2) |
02874       ((B0 & 0x40) >> 2) |
02875       ((A0 & 0x40) >> 3) |
02876       ((C0 & 0x20) >> 3) |
02877       ((B0 & 0x20) >> 4) |
02878       ((A0 & 0x20) >> 5);
02879     outbuf[1] =
02880       ((C0 & 0x10) << 3) |
02881       ((B0 & 0x10) << 2) |
02882       ((A0 & 0x10) << 1) |
02883       ((B0 & 0x08) << 1) |
02884       ((A0 & 0x08) << 0) |
02885       ((C0 & 0x04) >> 0) |
02886       ((B0 & 0x04) >> 1) |
02887       ((A0 & 0x04) >> 2);
02888     outbuf[2] =
02889       ((C0 & 0x02) << 6) |
02890       ((B0 & 0x02) << 5) |
02891       ((A0 & 0x02) << 4) |
02892       ((B0 & 0x01) << 4) |
02893       ((A0 & 0x01) << 3) |
02894       ((C1 & 0x80) >> 5) |
02895       ((B1 & 0x80) >> 6) |
02896       ((A1 & 0x80) >> 7);
02897     outbuf[3] =
02898       ((C1 & 0x40) << 1) |
02899       ((B1 & 0x40) << 0) |
02900       ((A1 & 0x40) >> 1) |
02901       ((B1 & 0x20) >> 1) |
02902       ((A1 & 0x20) >> 2) |
02903       ((C1 & 0x10) >> 2) |
02904       ((B1 & 0x10) >> 3) |
02905       ((A1 & 0x10) >> 4);
02906     outbuf[4] =
02907       ((C1 & 0x08) << 4) |
02908       ((B1 & 0x08) << 3) |
02909       ((A1 & 0x08) << 2) |
02910       ((B1 & 0x04) << 2) |
02911       ((A1 & 0x04) << 1) |
02912       ((C1 & 0x02) << 1) |
02913       ((B1 & 0x02) >> 0) |
02914       ((A1 & 0x02) >> 1);
02915     outbuf[5] =
02916       ((C1 & 0x01) << 7) |
02917       ((B1 & 0x01) << 6) |
02918       ((A1 & 0x01) << 5) |
02919       ((B2 & 0x80) >> 3) |
02920       ((A2 & 0x80) >> 4) |
02921       ((C2 & 0x40) >> 4) |
02922       ((B2 & 0x40) >> 5) |
02923       ((A2 & 0x40) >> 6);
02924     outbuf[6] =
02925       ((C2 & 0x20) << 2) |
02926       ((B2 & 0x20) << 1) |
02927       ((A2 & 0x20) << 0) |
02928       ((B2 & 0x10) >> 0) |
02929       ((A2 & 0x10) >> 1) |
02930       ((C2 & 0x08) >> 1) |
02931       ((B2 & 0x08) >> 2) |
02932       ((A2 & 0x08) >> 3);
02933     outbuf[7] =
02934       ((C2 & 0x04) << 5) |
02935       ((B2 & 0x04) << 4) |
02936       ((A2 & 0x04) << 3) |
02937       ((B2 & 0x02) << 3) |
02938       ((A2 & 0x02) << 2) |
02939       ((C2 & 0x01) << 2) |
02940       ((B2 & 0x01) << 1) |
02941       ((A2 & 0x01) << 0);
02942   }
02943 }
02944 
02945 #else
02946 #error 3BIT FOLD TYPE NOT IMPLEMENTED
02947 #endif
02948 
02949 static void
02950 canon_shift_buffer(unsigned char *line,int length,int bits)
02951 {
02952   int i,j;
02953   for (j=0; j<bits; j++) {
02954     for (i=length-1; i>0; i--) {
02955       line[i]= (line[i] >> 1) | (line[i-1] << 7);
02956     }
02957     line[0] = line[0] >> 1;
02958   }
02959 }
02960 
02961 #if 0
02962 static void
02963 canon_shift_buffer2(unsigned char *line,int length,int bits)
02964 {
02965   int i;
02966   for (i=length-1; i>0; i--) {
02967     line[i]= (line[i] >> bits) | (line[i-1] << (8-bits));
02968   }
02969   line[0] = line[0] >> bits;
02970 }
02971 #endif
02972 
02973 /*
02974  * 'canon_write()' - Send graphics using TIFF packbits compression.
02975  */
02976 
02977 static int
02978 canon_write(stp_vars_t *v,              /* I - Print file or command */
02979             const canon_cap_t *   caps,         /* I - Printer model */
02980             unsigned char *line,        /* I - Output bitmap data */
02981             int           length,       /* I - Length of bitmap data */
02982             int           coloridx,     /* I - Which color */
02983             int           ydpi,         /* I - Vertical resolution */
02984             int           *empty,       /* IO- Preceeding empty lines */
02985             int           width,        /* I - Printed width */
02986             int           offset,       /* I - Offset from left side */
02987             int           bits)
02988 {
02989   unsigned char
02990     comp_buf[COMPBUFWIDTH],             /* Compression buffer */
02991     in_fold[COMPBUFWIDTH],
02992     *in_ptr= line,
02993     *comp_ptr, *comp_data;
02994   int newlength;
02995   int offset2,bitoffset;
02996   unsigned char color;
02997 
02998  /* Don't send blank lines... */
02999 
03000   if (line[0] == 0 && memcmp(line, line + 1, length - 1) == 0)
03001     return 0;
03002 
03003   /* fold lsb/msb pairs if drop modulation is active */
03004 
03005 
03006 
03007   if (bits==2) {
03008     memset(in_fold,0,length*2);
03009     canon_fold_2bit(line,length,in_fold);
03010     in_ptr= in_fold;
03011     length= (length*8/4); /* 4 pixels in 8bit */
03012     offset= (offset*8/4); /* 4 pixels in 8bit  */
03013   }
03014   if (bits==3) {
03015     memset(in_fold,0,length*3);
03016     canon_fold_3bit(line,length,in_fold);
03017     in_ptr= in_fold;
03018     length= (length*8)/3;
03019     offset= (offset/3)*8;
03020 #if 0
03021     switch(offset%3){
03022     case 0: offset= (offset/3)*8;   break;
03023     case 1: offset= (offset/3)*8/*+3 CAREFUL! CANNOT SHIFT _AFTER_ RECODING!!*/; break;
03024     case 2: offset= (offset/3)*8/*+5 CAREFUL! CANNOT SHIFT _AFTER_ RECODING!!*/; break;
03025     }
03026 #endif
03027   }
03028   /* pack left border rounded to multiples of 8 dots */
03029 
03030   comp_data= comp_buf;
03031   offset2= offset/8;
03032   bitoffset= offset%8;
03033   while (offset2>0) {
03034     unsigned char toffset = offset2 > 128 ? 128 : offset2;
03035     comp_data[0] = 1 - toffset;
03036     comp_data[1] = 0;
03037     comp_data += 2;
03038     offset2-= toffset;
03039   }
03040   if (bitoffset) {
03041     if (bitoffset<8)
03042       canon_shift_buffer(in_ptr,length,bitoffset);
03043     else
03044       stp_deprintf(STP_DBG_CANON,"SEVERE BUG IN print-canon.c::canon_write() "
03045               "bitoffset=%d!!\n",bitoffset);
03046   }
03047 
03048   stp_pack_tiff(v, in_ptr, length, comp_data, &comp_ptr, NULL, NULL);
03049   newlength= comp_ptr - comp_buf;
03050 
03051   /* send packed empty lines if any */
03052 
03053   if (*empty) {
03054     stp_zfwrite("\033\050\145\002\000", 5, 1, v);
03055     stp_put16_be(*empty, v);
03056     *empty= 0;
03057   }
03058 
03059  /* Send a line of raster graphics... */
03060 
03061   stp_zfwrite("\033\050\101", 3, 1, v);
03062   stp_put16_le(newlength + 1, v);
03063   color= "CMYKcmy"[coloridx];
03064   if (!color) color= 'K';
03065   stp_putc(color,v);
03066   stp_zfwrite((const char *)comp_buf, newlength, 1, v);
03067   stp_putc('\015', v);
03068   return 1;
03069 }
03070 
03071 
03072 static void
03073 canon_write_line(stp_vars_t *v)
03074 {
03075   canon_privdata_t *pd =
03076     (canon_privdata_t *) stp_get_component_data(v, "Driver");
03077   static const int write_sequence[] = { 0, 3, 2, 1, 6, 5, 4 };
03078   static const int write_number[] = { 3, 2, 1, 0, 6, 5, 4 };
03079   int i;
03080   int written= 0;
03081 
03082   for (i = 0; i < 7; i++)
03083     {
03084       int col = write_sequence[i];
03085       int num = write_number[i];
03086       if (pd->cols[col])
03087         written += canon_write(v, pd->caps,
03088                                pd->cols[col] + pd->delay[col] * pd->buf_length,
03089                                pd->buf_length, num, pd->ydpi,
03090                                &(pd->emptylines), pd->out_width,
03091                                pd->left, pd->bits);
03092     }
03093   if (written)
03094     stp_zfwrite("\033\050\145\002\000\000\001", 7, 1, v);
03095   else
03096     pd->emptylines += 1;
03097 }
03098 
03099 
03100 static stp_family_t print_canon_module_data =
03101   {
03102     &print_canon_printfuncs,
03103     NULL
03104   };
03105 
03106 
03107 static int
03108 print_canon_module_init(void)
03109 {
03110   return stp_family_register(print_canon_module_data.printer_list);
03111 }
03112 
03113 
03114 static int
03115 print_canon_module_exit(void)
03116 {
03117   return stp_family_unregister(print_canon_module_data.printer_list);
03118 }
03119 
03120 
03121 /* Module header */
03122 #define stp_module_version print_canon_LTX_stp_module_version
03123 #define stp_module_data print_canon_LTX_stp_module_data
03124 
03125 stp_module_version_t stp_module_version = {0, 0};
03126 
03127 stp_module_t stp_module_data =
03128   {
03129     "canon",
03130     VERSION,
03131     "Canon family driver",
03132     STP_MODULE_CLASS_FAMILY,
03133     NULL,
03134     print_canon_module_init,
03135     print_canon_module_exit,
03136     (void *) &print_canon_module_data
03137   };
03138 

Generated on Wed May 12 20:21:30 2004 for libgimpprint API Reference by doxygen1.2.17