libgimpprint API Reference: src/main/print-canon.c Source File

Main Page | Modules | Alphabetical List | Data Structures | File List | Data Fields | Globals | Related Pages

# src/main/print-canon.c

Go to the documentation of this file.

    00001 /*
    00002  * "$Id: print-canon_8c-source.html,v 1.1.1.2 2004/12/22 23:49:06 jlovell 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(1.0, single_dotsize),
    00263   SHADE(0.25, 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(1.0, single_dotsize),
    00276   SHADE(0.26, 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(1.0, two_bit_dotsize),
    00306   SHADE(0.33, 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(1.0, three_bit_dotsize),
    00346   SHADE(0.33, 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\n",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\n",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, 384);
    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, 384);
    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, 384);
    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 + COMPBUFWIDTH / 4],  /* 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);
    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);
    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 / pd->bits, 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