summaryrefslogtreecommitdiff
path: root/src/main/print-canon.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/main/print-canon.c')
-rw-r--r--src/main/print-canon.c3103
1 files changed, 3103 insertions, 0 deletions
diff --git a/src/main/print-canon.c b/src/main/print-canon.c
new file mode 100644
index 0000000..fc5425e
--- /dev/null
+++ b/src/main/print-canon.c
@@ -0,0 +1,3103 @@
+/*
+ * "$Id: print-canon.c,v 1.71 2001/10/27 17:16:39 rlk Exp $"
+ *
+ * Print plug-in CANON BJL driver for the GIMP.
+ *
+ * Copyright 1997-2000 Michael Sweet (mike@easysw.com),
+ * Robert Krawitz (rlk@alum.mit.edu) and
+ * Andy Thaller (thaller@ph.tum.de)
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+/*
+ * This file must include only standard C header files. The core code must
+ * compile on generic platforms that don't support glib, gimp, gtk, etc.
+ */
+
+/*
+ * Large parts of this file (mainly the ink handling) is based on
+ * print-escp2.c -- refer to README.new-printer on how to adjust the colors
+ * for a certain model.
+ */
+
+/* TODO-LIST
+ *
+ * * adjust the colors of all supported models
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+#include <gimp-print/gimp-print.h>
+#include "gimp-print-internal.h"
+#include <gimp-print/gimp-print-intl-internal.h>
+#include <string.h>
+#include <stdio.h>
+#if defined(HAVE_VARARGS_H) && !defined(HAVE_STDARG_H)
+#include <varargs.h>
+#else
+#include <stdarg.h>
+#endif
+
+#if (0)
+#define EXPERIMENTAL_STUFF 0
+#endif
+
+#define MAX_CARRIAGE_WIDTH 13 /* This really needs to go away */
+
+/*
+ * We really need to get away from this silly static nonsense...
+ */
+#define MAX_PHYSICAL_BPI 1440
+#define MAX_OVERSAMPLED 8
+#define MAX_BPP 4
+#define BITS_PER_BYTE 8
+#define COMPBUFWIDTH (MAX_PHYSICAL_BPI * MAX_OVERSAMPLED * MAX_BPP * \
+ MAX_CARRIAGE_WIDTH / BITS_PER_BYTE)
+
+#define USE_3BIT_FOLD_TYPE 323
+
+/*
+ * For each printer, we can select from a variety of dot sizes.
+ * For single dot size printers, the available sizes are usually 0,
+ * which is the "default", and some subset of 1-4. For simple variable
+ * dot size printers (with only one kind of variable dot size), the
+ * variable dot size is specified as 0x10. For newer printers, there
+ * is a choice of variable dot sizes available, 0x10, 0x11, and 0x12 in
+ * order of increasing size.
+ *
+ * Normally, we want to specify the smallest dot size that lets us achieve
+ * a density of less than .8 or thereabouts (above that we start to get
+ * some dither artifacts). This needs to be tested for each printer and
+ * resolution.
+ *
+ * An entry of -1 in a slot means that this resolution is not available.
+ * 0 standard dot sizes are used.
+ * 1 drop modulation is used.
+ */
+
+/* We know a per-model base resolution (like 180dpi or 150dpi)
+ * and multipliers for the base resolution in the dotsize-, densities-
+ * and inklist:
+ * for 180dpi base resolution we would have
+ * s_r11_4 for 4color ink @180dpi
+ * s_r22_4 for 4color ink @360dpi
+ * s_r33_4 for 4color ink @720dpi
+ * s_r43_4 for 4color ink @1440x720dpi
+ */
+
+typedef struct canon_dot_sizes
+{
+ int dot_r11; /* 180x180 or 150x150 */
+ int dot_r22; /* 360x360 or 300x300 */
+ int dot_r33; /* 720x720 or 600x600 */
+ int dot_r43; /* 1440x720 or 1200x600 */
+ int dot_r44; /* 1440x1440 or 1200x1200 */
+ int dot_r55; /* 2880x2880 or 2400x2400 */
+} canon_dot_size_t;
+
+/*
+ * Specify the base density for each available resolution.
+ *
+ */
+
+typedef struct canon_densities
+{
+ double d_r11; /* 180x180 or 150x150 */
+ double d_r22; /* 360x360 or 300x300 */
+ double d_r33; /* 720x720 or 600x600 */
+ double d_r43; /* 1440x720 or 1200x600 */
+ double d_r44; /* 1440x1440 or 1200x1200 */
+ double d_r55; /* 2880x2880 or 2400x2400 */
+} canon_densities_t;
+
+
+
+/*
+ * Definition of the multi-level inks available to a given printer.
+ * Each printer may use a different kind of ink droplet for variable
+ * and single drop size for each supported horizontal resolution and
+ * type of ink (4 or 6 color).
+ *
+ * Recall that 6 color ink is treated as simply another kind of
+ * multi-level ink, but the driver offers the user a choice of 4 and
+ * 6 color ink, so we need to define appropriate inksets for both
+ * kinds of ink.
+ *
+ * Stuff like the MIS 4 and 6 "color" monochrome inks doesn't fit into
+ * this model very nicely, so we'll either have to special case it
+ * or find some way of handling it in here.
+ */
+
+typedef struct canon_variable_ink
+{
+ const stp_simple_dither_range_t *range;
+ int count;
+ double density;
+} canon_variable_ink_t;
+
+typedef struct canon_variable_inkset
+{
+ const canon_variable_ink_t *c;
+ const canon_variable_ink_t *m;
+ const canon_variable_ink_t *y;
+ const canon_variable_ink_t *k;
+} canon_variable_inkset_t;
+
+/*
+ * currenty unaccounted for are the 7color printers and the 3color ones
+ * (which use CMY only printheads)
+ *
+ */
+
+typedef struct canon_variable_inklist
+{
+ const int bits;
+ const int colors;
+ const canon_variable_inkset_t *r11; /* 180x180 or 150x150 */
+ const canon_variable_inkset_t *r22; /* 360x360 or 300x300 */
+ const canon_variable_inkset_t *r33; /* 720x720 or 600x600 */
+ const canon_variable_inkset_t *r43; /* 1440x720 or 1200x600 */
+ const canon_variable_inkset_t *r44; /* 1440x1440 or 1200x1200 */
+ const canon_variable_inkset_t *r55; /* 2880x2880 or 2400x2400 */
+} canon_variable_inklist_t;
+
+
+#ifdef EXPERIMENTAL_STUFF
+/*
+ * A printmode is defined by its resolution (xdpi x ydpi), the bits per pixel
+ * and the installed printhead.
+ *
+ * For a hereby defined printmode we specify the density and gamma multipliers
+ * and the ink definition with optional adjustments for lum, hue and sat
+ *
+ */
+typedef struct canon_variable_printmode
+{
+ const int xdpi; /* horizontal resolution */
+ const int ydpi; /* vertical resolution */
+ const int bits; /* bits per pixel */
+ const int printhead; /* installed printhead */
+ const int quality; /* maximum init-quality */
+ const double density; /* density multiplier */
+ const double gamma; /* gamma multiplier */
+ const canon_variable_inkset_t *inks; /* ink definition */
+ const double *lum_adjustment; /* optional lum adj. */
+ const double *hue_adjustment; /* optional hue adj. */
+ const double *sat_adjustment; /* optional sat adj. */
+} canon_variable_printmode_t;
+#endif
+
+/* NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE
+ *
+ * The following dither ranges were taken from print-escp2.c and do NOT
+ * represent the requirements of canon inks. Feel free to play with them
+ * accoring to the escp2 part of doc/README.new-printer and send me a patch
+ * if you get better results. Please send mail to thaller@ph.tum.de
+ */
+
+/*
+ * Dither ranges specifically for Cyan/LightCyan (see NOTE above)
+ *
+ */
+static const stp_simple_dither_range_t canon_dither_ranges_Cc_1bit[] =
+{
+ { 0.25, 0x1, 0, 1 },
+ { 1.0, 0x1, 1, 1 }
+};
+
+static const canon_variable_ink_t canon_ink_Cc_1bit =
+{
+ canon_dither_ranges_Cc_1bit,
+ sizeof(canon_dither_ranges_Cc_1bit) / sizeof(stp_simple_dither_range_t),
+ .75
+};
+
+/*
+ * Dither ranges specifically for Magenta/LightMagenta (see NOTE above)
+ *
+ */
+static const stp_simple_dither_range_t canon_dither_ranges_Mm_1bit[] =
+{
+ { 0.26, 0x1, 0, 1 },
+ { 1.0, 0x1, 1, 1 }
+};
+
+static const canon_variable_ink_t canon_ink_Mm_1bit =
+{
+ canon_dither_ranges_Mm_1bit,
+ sizeof(canon_dither_ranges_Mm_1bit) / sizeof(stp_simple_dither_range_t),
+ .75
+};
+
+
+/*
+ * Dither ranges specifically for any Color and 2bit/pixel (see NOTE above)
+ *
+ */
+static const stp_simple_dither_range_t canon_dither_ranges_X_2bit[] =
+{
+ { 0.45, 0x1, 1, 1 },
+ { 0.68, 0x2, 1, 2 },
+ { 1.0, 0x3, 1, 3 }
+};
+
+static const canon_variable_ink_t canon_ink_X_2bit =
+{
+ canon_dither_ranges_X_2bit,
+ sizeof(canon_dither_ranges_X_2bit) / sizeof(stp_simple_dither_range_t),
+ 1.0
+};
+
+/*
+ * Dither ranges specifically for any Color/LightColor and 2bit/pixel
+ * (see NOTE above)
+ */
+static const stp_simple_dither_range_t canon_dither_ranges_Xx_2bit[] =
+{
+ { 0.15, 0x1, 0, 1 },
+ { 0.227, 0x2, 0, 2 },
+/* { 0.333, 0x3, 0, 3 }, */
+ { 0.45, 0x1, 1, 1 },
+ { 0.68, 0x2, 1, 2 },
+ { 1.0, 0x3, 1, 3 }
+};
+
+static const canon_variable_ink_t canon_ink_Xx_2bit =
+{
+ canon_dither_ranges_Xx_2bit,
+ sizeof(canon_dither_ranges_Xx_2bit) / sizeof(stp_simple_dither_range_t),
+ 1.0
+};
+
+/*
+ * Dither ranges specifically for any Color and 3bit/pixel
+ * (see NOTE above)
+ *
+ * BIG NOTE: The bjc8200 has this kind of ink. One Byte seems to hold
+ * drop sizes for 3 pixels in a 3/2/2 bit fashion.
+ * Size values for 3bit-sized pixels range from 1 to 7,
+ * size values for 2bit-sized picels from 1 to 3 (kill msb).
+ *
+ *
+ */
+static const stp_simple_dither_range_t canon_dither_ranges_X_3bit[] =
+{
+ { 0.45, 0x1, 1, 1 },
+ { 0.55, 0x2, 1, 2 },
+ { 0.66, 0x3, 1, 3 },
+ { 0.77, 0x4, 1, 4 },
+ { 0.88, 0x5, 1, 5 },
+ { 1.0, 0x6, 1, 6 }
+};
+
+static const canon_variable_ink_t canon_ink_X_3bit =
+{
+ canon_dither_ranges_X_3bit,
+ sizeof(canon_dither_ranges_X_3bit) / sizeof(stp_simple_dither_range_t),
+ 1.0
+};
+
+/*
+ * Dither ranges specifically for any Color/LightColor and 3bit/pixel
+ * (see NOTE above)
+ */
+static const stp_simple_dither_range_t canon_dither_ranges_Xx_3bit[] =
+{
+ { 0.15, 0x1, 0, 1 },
+ { 0.227, 0x2, 0, 2 },
+ { 0.333, 0x3, 0, 3 },
+/* { 0.333, 0x3, 0, 3 }, */
+ { 0.45, 0x1, 1, 1 },
+ { 0.55, 0x2, 1, 2 },
+ { 0.66, 0x3, 1, 3 },
+ { 0.77, 0x4, 1, 4 },
+ { 0.88, 0x5, 1, 5 },
+ { 1.0, 0x6, 1, 6 }
+};
+
+static const canon_variable_ink_t canon_ink_Xx_3bit =
+{
+ canon_dither_ranges_Xx_3bit,
+ sizeof(canon_dither_ranges_Xx_3bit) / sizeof(stp_simple_dither_range_t),
+ 1.0
+};
+
+
+/* Inkset for printing in CMY and 1bit/pixel */
+static const canon_variable_inkset_t ci_CMY_1 =
+{
+ NULL,
+ NULL,
+ NULL,
+ NULL
+};
+
+/* Inkset for printing in CMY and 2bit/pixel */
+static const canon_variable_inkset_t ci_CMY_2 =
+{
+ &canon_ink_X_2bit,
+ &canon_ink_X_2bit,
+ &canon_ink_X_2bit,
+ NULL
+};
+
+/* Inkset for printing in CMYK and 1bit/pixel */
+static const canon_variable_inkset_t ci_CMYK_1 =
+{
+ NULL,
+ NULL,
+ NULL,
+ NULL
+};
+
+/* Inkset for printing in CcMmYK and 1bit/pixel */
+static const canon_variable_inkset_t ci_CcMmYK_1 =
+{
+ &canon_ink_Cc_1bit,
+ &canon_ink_Mm_1bit,
+ NULL,
+ NULL
+};
+
+/* Inkset for printing in CMYK and 2bit/pixel */
+static const canon_variable_inkset_t ci_CMYK_2 =
+{
+ &canon_ink_X_2bit,
+ &canon_ink_X_2bit,
+ &canon_ink_X_2bit,
+ &canon_ink_X_2bit
+};
+
+/* Inkset for printing in CcMmYK and 2bit/pixel */
+static const canon_variable_inkset_t ci_CcMmYK_2 =
+{
+ &canon_ink_Xx_2bit,
+ &canon_ink_Xx_2bit,
+ &canon_ink_X_2bit,
+ &canon_ink_X_2bit
+};
+
+/* Inkset for printing in CMYK and 3bit/pixel */
+static const canon_variable_inkset_t ci_CMYK_3 =
+{
+ &canon_ink_X_3bit,
+ &canon_ink_X_3bit,
+ &canon_ink_X_3bit,
+ &canon_ink_X_3bit
+};
+
+/* Inkset for printing in CcMmYK and 3bit/pixel */
+static const canon_variable_inkset_t ci_CcMmYK_3 =
+{
+ &canon_ink_Xx_3bit,
+ &canon_ink_Xx_3bit,
+ &canon_ink_X_3bit,
+ &canon_ink_X_3bit,
+};
+
+
+typedef canon_variable_inklist_t* canon_variable_inklist_p;
+
+/* Ink set should be applicable for any CMYK based model */
+static const canon_variable_inklist_t canon_ink_standard[] =
+{
+ {
+ 1,4,
+ &ci_CMYK_1, &ci_CMYK_1, &ci_CMYK_1,
+ &ci_CMYK_1, &ci_CMYK_1, &ci_CMYK_1,
+ },
+};
+
+/* Ink set for printers using CMY and CMY photo printing, 1 or 2bit/pixel */
+static const canon_variable_inklist_t canon_ink_oldphoto[] =
+{
+ {
+ 1,3,
+ &ci_CMY_1, &ci_CMY_1, &ci_CMY_1,
+ &ci_CMY_1, &ci_CMY_1, &ci_CMY_1,
+ },
+ {
+ 2,3,
+ &ci_CMY_2, &ci_CMY_2,
+ &ci_CMY_2, &ci_CMY_2,
+ &ci_CMY_2, &ci_CMY_2,
+ },
+};
+
+/* Ink set for printers using CMYK and CcMmYK printing, 1 or 2bit/pixel */
+static const canon_variable_inklist_t canon_ink_standardphoto[] =
+{
+ {
+ 1,4,
+ &ci_CMYK_1, &ci_CMYK_1, &ci_CMYK_1,
+ &ci_CMYK_1, &ci_CMYK_1, &ci_CMYK_1,
+ },
+ {
+ 2,4,
+ &ci_CMYK_2, &ci_CMYK_2,
+ &ci_CMYK_2, &ci_CMYK_2,
+ &ci_CMYK_2, &ci_CMYK_2,
+ },
+ {
+ 1,6,
+ &ci_CcMmYK_1, &ci_CcMmYK_1, &ci_CcMmYK_1,
+ &ci_CcMmYK_1, &ci_CcMmYK_1, &ci_CcMmYK_1,
+ },
+ {
+ 2,6,
+ &ci_CcMmYK_2, &ci_CcMmYK_2, &ci_CcMmYK_2,
+ &ci_CcMmYK_2, &ci_CcMmYK_2, &ci_CcMmYK_2,
+ },
+};
+
+/* Ink set for printers using CMYK and CcMmYK printing, 1 or 3bit/pixel */
+static const canon_variable_inklist_t canon_ink_superphoto[] =
+{
+ {
+ 1,4,
+ &ci_CMYK_1, &ci_CMYK_1, &ci_CMYK_1,
+ &ci_CMYK_1, &ci_CMYK_1, &ci_CMYK_1,
+ },
+ {
+ 3,4,
+ &ci_CMYK_3, &ci_CMYK_3, &ci_CMYK_3,
+ &ci_CMYK_3, &ci_CMYK_3, &ci_CMYK_3,
+ },
+ {
+ 3,6,
+ &ci_CcMmYK_3, &ci_CcMmYK_3, &ci_CcMmYK_3,
+ &ci_CcMmYK_3, &ci_CcMmYK_3, &ci_CcMmYK_3,
+ },
+};
+
+
+static const double standard_sat_adjustment[49] =
+{
+ 1.0, /* C */
+ 1.1,
+ 1.2,
+ 1.3,
+ 1.4,
+ 1.5,
+ 1.6,
+ 1.7,
+ 1.8, /* B */
+ 1.9,
+ 1.9,
+ 1.9,
+ 1.7,
+ 1.5,
+ 1.3,
+ 1.1,
+ 1.0, /* M */
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0, /* R */
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0, /* Y */
+ 1.0,
+ 1.0,
+ 1.1,
+ 1.2,
+ 1.3,
+ 1.4,
+ 1.5,
+ 1.5, /* G */
+ 1.4,
+ 1.3,
+ 1.2,
+ 1.1,
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0 /* C */
+};
+
+static const double standard_lum_adjustment[49] =
+{
+ 0.50, /* C */
+ 0.6,
+ 0.7,
+ 0.8,
+ 0.9,
+ 0.86,
+ 0.82,
+ 0.79,
+ 0.78, /* B */
+ 0.8,
+ 0.83,
+ 0.87,
+ 0.9,
+ 0.95,
+ 1.05,
+ 1.15,
+ 1.3, /* M */
+ 1.25,
+ 1.2,
+ 1.15,
+ 1.12,
+ 1.09,
+ 1.06,
+ 1.03,
+ 1.0, /* R */
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0, /* Y */
+ 0.9,
+ 0.8,
+ 0.7,
+ 0.65,
+ 0.6,
+ 0.55,
+ 0.52,
+ 0.48, /* G */
+ 0.47,
+ 0.47,
+ 0.49,
+ 0.49,
+ 0.49,
+ 0.52,
+ 0.51,
+ 0.50 /* C */
+};
+
+static const double standard_hue_adjustment[49] =
+{
+ 0.00, /* C */
+ 0.05,
+ 0.04,
+ 0.01,
+ -0.03,
+ -0.10,
+ -0.18,
+ -0.26,
+ -0.35, /* B */
+ -0.43,
+ -0.40,
+ -0.32,
+ -0.25,
+ -0.18,
+ -0.10,
+ -0.07,
+ 0.00, /* M */
+ -0.04,
+ -0.09,
+ -0.13,
+ -0.18,
+ -0.23,
+ -0.27,
+ -0.31,
+ -0.35, /* R */
+ -0.38,
+ -0.30,
+ -0.23,
+ -0.15,
+ -0.08,
+ 0.00,
+ -0.02,
+ 0.00, /* Y */
+ 0.08,
+ 0.10,
+ 0.08,
+ 0.05,
+ 0.03,
+ -0.03,
+ -0.12,
+ -0.20, /* G */
+ -0.17,
+ -0.20,
+ -0.17,
+ -0.15,
+ -0.12,
+ -0.10,
+ -0.08,
+ 0.00, /* C */
+};
+
+typedef enum {
+ COLOR_MONOCHROME = 1,
+ COLOR_CMY = 3,
+ COLOR_CMYK = 4,
+ COLOR_CCMMYK= 6,
+ COLOR_CCMMYYK= 7
+} colormode_t;
+
+typedef struct canon_caps {
+ int model; /* model number as used in printers.xml */
+ int model_id; /* model ID code for use in commands */
+ int max_width; /* maximum printable paper size */
+ int max_height;
+ int base_res; /* base resolution - shall be 150 or 180 */
+ int max_xdpi; /* maximum horizontal resolution */
+ int max_ydpi; /* maximum vertical resolution */
+ int max_quality;
+ int border_left; /* left margin, points */
+ int border_right; /* right margin, points */
+ int border_top; /* absolute top margin, points */
+ int border_bottom; /* absolute bottom margin, points */
+ int inks; /* installable cartridges (CANON_INK_*) */
+ int slots; /* available paperslots */
+ unsigned long features; /* special bjl settings */
+#ifdef EXPERIMENTAL_STUFF
+ const canon_variable_printmode_t *printmodes;
+ int printmodes_cnt;
+#else
+ int dummy;
+ const canon_dot_size_t dot_sizes; /* Vector of dot sizes for resolutions */
+ const canon_densities_t densities; /* List of densities for each printer */
+ const canon_variable_inklist_t *inxs; /* Choices of inks for this printer */
+ int inxs_cnt; /* number of ink definitions in inxs */
+#endif
+ const double *lum_adjustment;
+ const double *hue_adjustment;
+ const double *sat_adjustment;
+} canon_cap_t;
+
+static void canon_write_line(const stp_vars_t, const canon_cap_t *, int,
+ unsigned char *, int,
+ unsigned char *, int,
+ unsigned char *, int,
+ unsigned char *, int,
+ unsigned char *, int,
+ unsigned char *, int,
+ unsigned char *, int,
+ int, int, int, int *,int);
+
+
+/* Codes for possible ink-tank combinations.
+ * Each combo is represented by the colors that can be used with
+ * the installed ink-tank(s)
+ * Combinations of the codes represent the combinations allowed for a model
+ * Note that only preferrable combinations should be used
+ */
+#define CANON_INK_K 1
+#define CANON_INK_CMY 2
+#define CANON_INK_CMYK 4
+#define CANON_INK_CcMmYK 8
+#define CANON_INK_CcMmYyK 16
+
+#define CANON_INK_BLACK_MASK (CANON_INK_K|CANON_INK_CMYK|CANON_INK_CcMmYK)
+
+#define CANON_INK_PHOTO_MASK (CANON_INK_CcMmYK|CANON_INK_CcMmYyK)
+
+/* document feeding */
+#define CANON_SLOT_ASF1 1
+#define CANON_SLOT_ASF2 2
+#define CANON_SLOT_MAN1 4
+#define CANON_SLOT_MAN2 8
+
+/* model peculiarities */
+#define CANON_CAP_DMT 0x01ul /* Drop Modulation Technology */
+#define CANON_CAP_MSB_FIRST 0x02ul /* how to send data */
+#define CANON_CAP_a 0x04ul
+#define CANON_CAP_b 0x08ul
+#define CANON_CAP_q 0x10ul
+#define CANON_CAP_m 0x20ul
+#define CANON_CAP_d 0x40ul
+#define CANON_CAP_t 0x80ul
+#define CANON_CAP_c 0x100ul
+#define CANON_CAP_p 0x200ul
+#define CANON_CAP_l 0x400ul
+#define CANON_CAP_r 0x800ul
+#define CANON_CAP_g 0x1000ul
+#define CANON_CAP_ACKSHORT 0x2000ul
+
+#define CANON_CAP_STD0 (CANON_CAP_b|CANON_CAP_c|CANON_CAP_d|\
+ CANON_CAP_l|CANON_CAP_q|CANON_CAP_t)
+
+#define CANON_CAP_STD1 (CANON_CAP_b|CANON_CAP_c|CANON_CAP_d|CANON_CAP_l|\
+ CANON_CAP_m|CANON_CAP_p|CANON_CAP_q|CANON_CAP_t)
+
+#ifdef EXPERIMENTAL_STUFF
+#define CANON_MODES(A) A,sizeof(A)/sizeof(canon_variable_printmode_t*)
+#else
+#define CANON_MODES(A) 0
+#endif
+
+#define CANON_INK(A) A,sizeof(A)/sizeof(canon_variable_inklist_t*)
+
+
+#ifdef EXPERIMENTAL_STUFF
+
+#define BC_10 CANON_INK_K /* b/w */
+#define BC_11 CANON_INK_CMYK /* color */
+#define BC_12 CANON_INK_CMYK /* photo */
+#define BC_20 CANON_INK_K /* b/w */
+#define BC_21 CANON_INK_CMYK /* color */
+#define BC_22 CANON_INK_CMYK /* photo */
+#define BC_29 0 /* neon! */
+#define BC_3031 CANON_INK_CMYK /* color */
+#define BC_3231 CANON_INK_CcMmYK /* photo */
+
+
+static const canon_variable_printmode_t canon_nomodes[] =
+{
+ {0,0,0,0,0,0,0,0,0,0}
+};
+
+static const canon_variable_printmode_t canon_modes_30[] = {
+ { 180, 180, 1, BC_10, 2, 1.0, 1.0, &ci_CMYK_1, 0,0,0 },
+ { 360, 360, 1, BC_10, 2, 1.0, 1.0, &ci_CMYK_1, 0,0,0 },
+ { 720, 360, 1, BC_10, 2, 1.0, 1.0, &ci_CMYK_1, 0,0,0 },
+};
+
+static const canon_variable_printmode_t canon_modes_85[] = {
+ { 360, 360, 1, BC_10, 2, 1.0, 1.0, &ci_CMYK_1, 0,0,0 },
+ { 360, 360, 1, BC_11, 2, 1.0, 1.0, &ci_CMYK_1, 0,0,0 },
+ { 360, 360, 2, BC_11, 2, 1.0, 1.0, &ci_CMYK_2, 0,0,0 },
+ { 360, 360, 1, BC_21, 2, 1.0, 1.0, &ci_CMYK_1, 0,0,0 },
+ { 360, 360, 2, BC_21, 2, 1.0, 1.0, &ci_CMYK_2, 0,0,0 },
+};
+
+static const canon_variable_printmode_t canon_modes_2x00[] = {
+ { 360, 360, 1, BC_20, 2, 1.0, 1.0, &ci_CMYK_1, 0,0,0 },
+ { 360, 360, 1, BC_21, 2, 1.0, 1.0, &ci_CMYK_1, 0,0,0 },
+ { 360, 360, 1, BC_22, 2, 1.0, 1.0, &ci_CMYK_1, 0,0,0 },
+};
+
+static const canon_variable_printmode_t canon_modes_6x00[] = {
+ { 360, 360, 1, BC_3031, 2, 1.8, 1.0, &ci_CMYK_1, 0,0,0 },
+ { 360, 360, 2, BC_3031, 2, 1.8, 1.0, &ci_CMYK_2, 0,0,0 },
+ { 720, 720, 1, BC_3031, 2, 1.0, 1.0, &ci_CMYK_1, 0,0,0 },
+ { 1440, 720, 1, BC_3031, 2, 0.5, 1.0, &ci_CMYK_1, 0,0,0 },
+ { 360, 360, 1, BC_3231, 2, 1.8, 1.0, &ci_CcMmYK_1, 0,0,0 },
+ { 360, 360, 2, BC_3231, 2, 1.8, 1.0, &ci_CcMmYK_2, 0,0,0 },
+ { 720, 720, 1, BC_3231, 2, 1.0, 1.0, &ci_CcMmYK_1, 0,0,0 },
+ { 1440, 720, 1, BC_3231, 2, 0.5, 1.0, &ci_CcMmYK_1, 0,0,0 },
+};
+#endif
+
+static const canon_cap_t canon_model_capabilities[] =
+{
+ /* default settings for unkown models */
+
+ { -1, 8*72,11*72,180,180,20,20,20,20, CANON_INK_K, CANON_SLOT_ASF1, 0 },
+
+ /* ******************************** */
+ /* */
+ /* tested and color-adjusted models */
+ /* */
+ /* ******************************** */
+
+
+
+
+ /* ************************************ */
+ /* */
+ /* tested models w/out color-adjustment */
+ /* */
+ /* ************************************ */
+
+
+ { /* Canon BJ 30 *//* heads: BC-10 */
+ 30, 1,
+ 9.5*72, 14*72,
+ 90, 360, 360, 2,
+ 11, 9, 10, 18,
+ CANON_INK_K,
+ CANON_SLOT_ASF1,
+ CANON_CAP_STD0 | CANON_CAP_a,
+ CANON_MODES(canon_modes_30),
+#ifndef EXPERIMENTAL_STUFF
+ {-1,0,0,0,-1,-1}, /*090x090 180x180 360x360 720x360 720x720 1440x1440*/
+ {1,1,1,1,1,1}, /*------- 180x180 360x360 720x360 ------- ---------*/
+ CANON_INK(canon_ink_standard),
+#endif
+ standard_lum_adjustment,
+ standard_hue_adjustment,
+ standard_sat_adjustment
+ },
+
+ { /* Canon BJC 85 *//* heads: BC-20 BC-21 BC-22 */
+ 85, 1,
+ 9.5*72, 14*72,
+ 90, 720, 360, 2,
+ 11, 9, 10, 18,
+ CANON_INK_K | CANON_INK_CMYK | CANON_INK_CcMmYK,
+ CANON_SLOT_ASF1,
+ CANON_CAP_STD0 | CANON_CAP_a | CANON_CAP_DMT,
+ CANON_MODES(canon_modes_85),
+#ifndef EXPERIMENTAL_STUFF
+ {-1,-1,1,0,-1,-1},/*090x090 180x180 360x360 720x360 720x720 1440x1440*/
+ {1,1,1,1,1,1}, /*------- ------- 360x360 720x360 ------- ---------*/
+ CANON_INK(canon_ink_standard),
+#endif
+ standard_lum_adjustment,
+ standard_hue_adjustment,
+ standard_sat_adjustment
+ },
+
+ { /* Canon BJC 4300 *//* heads: BC-20 BC-21 BC-22 BC-29 */
+ 4300, 1,
+ 618, 936, /* 8.58" x 13 " */
+ 180, 1440, 720, 2,
+ 11, 9, 10, 18,
+ CANON_INK_CMYK | CANON_INK_CcMmYK,
+ CANON_SLOT_ASF1 | CANON_SLOT_MAN1,
+ CANON_CAP_STD0 | CANON_CAP_DMT,
+ CANON_MODES(canon_nomodes),
+#ifndef EXPERIMENTAL_STUFF
+ {-1,1,0,0,-1,-1}, /*180x180 360x360 720x720 1440x720 1440x1440 2880x2880*/
+ {1,1,1,1,1,1}, /*------- 360x360 720x720 1440x720 --------- ---------*/
+ CANON_INK(canon_ink_standard),
+#endif
+ standard_lum_adjustment,
+ standard_hue_adjustment,
+ standard_sat_adjustment
+ },
+
+ { /* Canon BJC 4400 *//* heads: BC-20 BC-21 BC-22 BC-29 */
+ 4400, 1,
+ 9.5*72, 14*72,
+ 90, 720, 360, 2,
+ 11, 9, 10, 18,
+ CANON_INK_K | CANON_INK_CMYK | CANON_INK_CcMmYK,
+ CANON_SLOT_ASF1,
+ CANON_CAP_STD0 | CANON_CAP_a | CANON_CAP_DMT,
+ CANON_MODES(canon_nomodes),
+#ifndef EXPERIMENTAL_STUFF
+ {-1,-1,0,0,-1,-1},/*090x090 180x180 360x360 720x360 720x720 1440x1440*/
+ {1,1,1,1,1,1}, /*------- ------- 360x360 720x360 ------- ---------*/
+ CANON_INK(canon_ink_standard),
+#endif
+ standard_lum_adjustment,
+ standard_hue_adjustment,
+ standard_sat_adjustment
+ },
+
+ { /* Canon BJC 6000 *//* heads: BC-30/BC-31 BC-32/BC-31 */
+ 6000, 3,
+ 618, 936, /* 8.58" x 13 " */
+ 180, 1440, 720, 2,
+ 11, 9, 10, 18,
+ CANON_INK_CMYK | CANON_INK_CcMmYK,
+ CANON_SLOT_ASF1 | CANON_SLOT_MAN1,
+ CANON_CAP_STD1 | CANON_CAP_DMT | CANON_CAP_ACKSHORT,
+ CANON_MODES(canon_modes_6x00),
+#ifndef EXPERIMENTAL_STUFF
+ {-1,1,0,0,-1,-1}, /*180x180 360x360 720x720 1440x720 1440x1440 2880x2880*/
+ {1,1.8,1,0.5,1,1},/*------- 360x360 720x720 1440x720 --------- ---------*/
+ CANON_INK(canon_ink_standardphoto),
+#endif
+ standard_lum_adjustment,
+ standard_hue_adjustment,
+ standard_sat_adjustment
+ },
+
+ { /* Canon BJC 6200 *//* heads: BC-30/BC-31 BC-32/BC-31 */
+ 6200, 3,
+ 618, 936, /* 8.58" x 13 " */
+ 180, 1440, 720, 2,
+ 11, 9, 10, 18,
+ CANON_INK_CMYK | CANON_INK_CcMmYK,
+ CANON_SLOT_ASF1 | CANON_SLOT_MAN1,
+ CANON_CAP_STD1 | CANON_CAP_DMT | CANON_CAP_ACKSHORT,
+ CANON_MODES(canon_modes_6x00),
+#ifndef EXPERIMENTAL_STUFF
+ {-1,1,0,0,-1,-1}, /*180x180 360x360 720x720 1440x720 1440x1440 2880x2880*/
+ {0,1.8,1,.5,0,0}, /*------- 360x360 720x720 1440x720 --------- ---------*/
+ CANON_INK(canon_ink_standardphoto),
+#endif
+ standard_lum_adjustment,
+ standard_hue_adjustment,
+ standard_sat_adjustment
+ },
+
+ { /* Canon BJC 6500 *//* heads: BC-30/BC-31 BC-32/BC-31 */
+ 6500, 3,
+ 11*72, 17*72,
+ 180, 1440, 720, 2,
+ 11, 9, 10, 18,
+ CANON_INK_CMYK | CANON_INK_CcMmYK,
+ CANON_SLOT_ASF1 | CANON_SLOT_MAN1,
+ CANON_CAP_STD1 | CANON_CAP_DMT,
+ CANON_MODES(canon_modes_6x00),
+#ifndef EXPERIMENTAL_STUFF
+ {-1,1,0,0,-1,-1}, /*180x180 360x360 720x720 1440x720 1440x1440 2880x2880*/
+ {0,1.8,1,.5,0,0}, /*------- 360x360 720x720 1440x720 --------- ---------*/
+ CANON_INK(canon_ink_standardphoto),
+#endif
+ standard_lum_adjustment,
+ standard_hue_adjustment,
+ standard_sat_adjustment
+ },
+
+ { /* Canon BJC 8200 *//* heads: BC-50 */
+ 8200, 3,
+ 11*72, 17*72,
+ 150, 1200,1200, 4,
+ 11, 9, 10, 18,
+ CANON_INK_CMYK, /* | CANON_INK_CcMmYK */
+ CANON_SLOT_ASF1,
+ CANON_CAP_STD1 | CANON_CAP_r | CANON_CAP_DMT | CANON_CAP_ACKSHORT,
+ CANON_MODES(canon_nomodes),
+#ifndef EXPERIMENTAL_STUFF
+ {-1,0,0,-1,0,-1}, /*150x150 300x300 600x600 1200x600 1200x1200 2400x2400*/
+ {1,1,1,1,1,1}, /*------- 300x300 600x600 -------- 1200x1200 ---------*/
+ CANON_INK(canon_ink_superphoto),
+#endif
+ standard_lum_adjustment,
+ standard_hue_adjustment,
+ standard_sat_adjustment
+ },
+
+
+ /* *************** */
+ /* */
+ /* untested models */
+ /* */
+ /* *************** */
+
+
+ { /* Canon BJC 210 *//* heads: BC-02 BC-05 BC-06 */
+ 210, 1,
+ 11*72, 17*72,
+ 90, 720, 360, 2,
+ 11, 9, 10, 18,
+ CANON_INK_K | CANON_INK_CMY,
+ CANON_SLOT_ASF1 | CANON_SLOT_MAN1,
+ CANON_CAP_STD0,
+ CANON_MODES(canon_nomodes),
+#ifndef EXPERIMENTAL_STUFF
+ {0,0,0,0,-1,-1},/*180x180 360x360 720x720 1440x720 1440x1440 2880x2880*/
+ {1,1,1,1,1,1}, /*180x180 360x360 ------- -------- --------- ---------*/
+ CANON_INK(canon_ink_standard),
+#endif
+ standard_lum_adjustment,
+ standard_hue_adjustment,
+ standard_sat_adjustment
+ },
+ { /* Canon BJC 240 *//* heads: BC-02 BC-05 BC-06 */
+ 240, 1,
+ 11*72, 17*72,
+ 90, 720, 360, 2,
+ 11, 9, 10, 18,
+ CANON_INK_K | CANON_INK_CMY,
+ CANON_SLOT_ASF1 | CANON_SLOT_MAN1,
+ CANON_CAP_STD0 | CANON_CAP_DMT,
+ CANON_MODES(canon_nomodes),
+#ifndef EXPERIMENTAL_STUFF
+ {0,0,1,0,-1,-1},/*180x180 360x360 720x720 1440x720 1440x1440 2880x2880*/
+ {1,1,1,1,1,1}, /*180x180 360x360 ------- -------- --------- ---------*/
+ CANON_INK(canon_ink_oldphoto),
+#endif
+ standard_lum_adjustment,
+ standard_hue_adjustment,
+ standard_sat_adjustment
+ },
+ { /* Canon BJC 250 *//* heads: BC-02 BC-05 BC-06 */
+ 250, 1,
+ 11*72, 17*72,
+ 90, 720, 360, 2,
+ 11, 9, 10, 18,
+ CANON_INK_K | CANON_INK_CMY,
+ CANON_SLOT_ASF1 | CANON_SLOT_MAN1,
+ CANON_CAP_STD0 | CANON_CAP_DMT,
+ CANON_MODES(canon_nomodes),
+#ifndef EXPERIMENTAL_STUFF
+ {0,0,1,0,-1,-1},/*180x180 360x360 720x720 1440x720 1440x1440 2880x2880*/
+ {1,1,1,1,1,1}, /*180x180 360x360 ------- -------- --------- ---------*/
+ CANON_INK(canon_ink_oldphoto),
+#endif
+ standard_lum_adjustment,
+ standard_hue_adjustment,
+ standard_sat_adjustment
+ },
+ { /* Canon BJC 1000 *//* heads: BC-02 BC-05 BC-06 */
+ 1000, 1,
+ 11*72, 17*72,
+ 90, 720, 360, 2,
+ 11, 9, 10, 18,
+ CANON_INK_K | CANON_INK_CMY,
+ CANON_SLOT_ASF1,
+ CANON_CAP_STD0 | CANON_CAP_DMT | CANON_CAP_a,
+ CANON_MODES(canon_nomodes),
+#ifndef EXPERIMENTAL_STUFF
+ {0,0,1,0,-1,-1}, /*180x180 360x360 720x720 1440x720 1440x1440 2880x2880*/
+ {1,1,1,1,1,1}, /*180x180 360x360 ------- -------- --------- ---------*/
+ CANON_INK(canon_ink_oldphoto),
+#endif
+ standard_lum_adjustment,
+ standard_hue_adjustment,
+ standard_sat_adjustment
+ },
+ { /* Canon BJC 2000 *//* heads: BC-20 BC-21 BC-22 BC-29 */
+ 2000, 1,
+ 11*72, 17*72,
+ 180, 720, 360, 2,
+ 11, 9, 10, 18,
+ CANON_INK_CMYK,
+ CANON_SLOT_ASF1,
+ CANON_CAP_STD0 | CANON_CAP_a,
+ CANON_MODES(canon_nomodes),
+#ifndef EXPERIMENTAL_STUFF
+ {0,0,-1,-1,-1,-1},/*180x180 360x360 720x720 1440x720 1440x1440 2880x2880*/
+ {1,1,1,1,1,1}, /*180x180 360x360 ------- -------- --------- ---------*/
+ CANON_INK(canon_ink_standard),
+#endif
+ standard_lum_adjustment,
+ standard_hue_adjustment,
+ standard_sat_adjustment
+ },
+ { /* Canon BJC 3000 *//* heads: BC-30 BC-33 BC-34 */
+ 3000, 3,
+ 11*72, 17*72,
+ 180, 1440, 720, 2,
+ 11, 9, 10, 18,
+ CANON_INK_CMYK | CANON_INK_CcMmYK,
+ CANON_SLOT_ASF1,
+ CANON_CAP_STD0 | CANON_CAP_a | CANON_CAP_DMT, /*FIX? should have _r? */
+ CANON_MODES(canon_nomodes),
+#ifndef EXPERIMENTAL_STUFF
+ {-1,1,0,0,-1,-1}, /*180x180 360x360 720x720 1440x720 1440x1440 2880x2880*/
+ {1,1,1,1,1,1}, /*------- 360x360 720x720 1440x720 --------- ---------*/
+ CANON_INK(canon_ink_standard),
+#endif
+ standard_lum_adjustment,
+ standard_hue_adjustment,
+ standard_sat_adjustment
+ },
+ { /* Canon BJC 6100 *//* heads: BC-30/BC-31 BC-32/BC-31 */
+ 6100, 3,
+ 11*72, 17*72,
+ 180, 1440, 720, 2,
+ 11, 9, 10, 18,
+ CANON_INK_CMYK | CANON_INK_CcMmYK,
+ CANON_SLOT_ASF1,
+ CANON_CAP_STD1 | CANON_CAP_a | CANON_CAP_r | CANON_CAP_DMT,
+ CANON_MODES(canon_modes_6x00),
+#ifndef EXPERIMENTAL_STUFF
+ {-1,1,0,0,-1,-1}, /*180x180 360x360 720x720 1440x720 1440x1440 2880x2880*/
+ {1,1,1,1,1,1}, /*------- 360x360 720x720 1440x720 --------- ---------*/
+ CANON_INK(canon_ink_standard),
+#endif
+ standard_lum_adjustment,
+ standard_hue_adjustment,
+ standard_sat_adjustment
+ },
+ { /* Canon BJC 7000 *//* heads: BC-60/BC-61 BC-60/BC-62 ??????? */
+ 7000, 3,
+ 11*72, 17*72,
+ 150, 1200, 600, 2,
+ 11, 9, 10, 18,
+ CANON_INK_CMYK | CANON_INK_CcMmYyK,
+ CANON_SLOT_ASF1,
+ CANON_CAP_STD1,
+ CANON_MODES(canon_nomodes),
+#ifndef EXPERIMENTAL_STUFF
+ {-1,0,0,0,-1,-1}, /*150x150 300x300 600x600 1200x600 1200x1200 2400x2400*/
+ {1,3.5,1.8,1,1,1},/*------- 300x300 600x600 1200x600 --------- ---------*/
+ CANON_INK(canon_ink_standard),
+#endif
+ standard_lum_adjustment,
+ standard_hue_adjustment,
+ standard_sat_adjustment
+ },
+ { /* Canon BJC 7100 *//* heads: BC-60/BC-61 BC-60/BC-62 ??????? */
+ 7100, 3,
+ 11*72, 17*72,
+ 150, 1200, 600, 2,
+ 11, 9, 10, 18,
+ CANON_INK_CMYK | CANON_INK_CcMmYyK,
+ CANON_SLOT_ASF1,
+ CANON_CAP_STD0,
+ CANON_MODES(canon_nomodes),
+#ifndef EXPERIMENTAL_STUFF
+ {-1,0,0,0,-1,-1}, /*150x150 300x300 600x600 1200x600 1200x1200 2400x2400*/
+ {1,1,1,1,1,1}, /*------- 300x300 600x600 1200x600 --------- ---------*/
+ CANON_INK(canon_ink_standard),
+#endif
+ standard_lum_adjustment,
+ standard_hue_adjustment,
+ standard_sat_adjustment
+ },
+
+ /*****************************/
+ /* */
+ /* extremely fuzzy models */
+ /* (might never work at all) */
+ /* */
+ /*****************************/
+
+ { /* Canon BJC 5100 *//* heads: BC-20 BC-21 BC-22 BC-23 BC-29 */
+ 5100, 1,
+ 17*72, 22*72,
+ 180, 1440, 720, 2,
+ 11, 9, 10, 18,
+ CANON_INK_CMYK | CANON_INK_CcMmYK,
+ CANON_SLOT_ASF1,
+ CANON_CAP_STD0 | CANON_CAP_DMT,
+ CANON_MODES(canon_nomodes),
+#ifndef EXPERIMENTAL_STUFF
+ {-1,1,0,0,-1,-1}, /*180x180 360x360 720x720 1440x720 1440x1440 2880x2880*/
+ {1,1,1,1,1,1}, /*------- 360x360 720x720 1440x720 --------- ---------*/
+ CANON_INK(canon_ink_standard),
+#endif
+ standard_lum_adjustment,
+ standard_hue_adjustment,
+ standard_sat_adjustment
+ },
+ { /* Canon BJC 5500 *//* heads: BC-20 BC-21 BC-29 */
+ 5500, 1,
+ 22*72, 34*72,
+ 180, 720, 360, 2,
+ 11, 9, 10, 18,
+ CANON_INK_CMYK | CANON_INK_CcMmYK,
+ CANON_SLOT_ASF1,
+ CANON_CAP_STD0 | CANON_CAP_a,
+ CANON_MODES(canon_nomodes),
+#ifndef EXPERIMENTAL_STUFF
+ {0,0,-1,-1,-1,-1},/*180x180 360x360 720x720 1440x720 1440x1440 2880x2880*/
+ {1,1,1,1,1,1}, /*180x180 360x360 ------- -------- --------- ---------*/
+ CANON_INK(canon_ink_standard),
+#endif
+ standard_lum_adjustment,
+ standard_hue_adjustment,
+ standard_sat_adjustment
+ },
+ { /* Canon BJC 6500 *//* heads: BC-30/BC-31 BC-32/BC-31 */
+ 6500, 3,
+ 17*72, 22*72,
+ 180, 1440, 720, 2,
+ 11, 9, 10, 18,
+ CANON_INK_CMYK | CANON_INK_CcMmYK,
+ CANON_SLOT_ASF1,
+ CANON_CAP_STD1 | CANON_CAP_a | CANON_CAP_DMT,
+ CANON_MODES(canon_nomodes),
+#ifndef EXPERIMENTAL_STUFF
+ {-1,1,0,0,-1,-1}, /*180x180 360x360 720x720 1440x720 1440x1440 2880x2880*/
+ {1,1,1,1,1,1}, /*------- 360x360 720x720 1440x720 --------- ---------*/
+ CANON_INK(canon_ink_standard),
+#endif
+ standard_lum_adjustment,
+ standard_hue_adjustment,
+ standard_sat_adjustment
+ },
+ { /* Canon BJC 8500 *//* heads: BC-80/BC-81 BC-82/BC-81 */
+ 8500, 3,
+ 17*72, 22*72,
+ 150, 1200,1200, 2,
+ 11, 9, 10, 18,
+ CANON_INK_CMYK | CANON_INK_CcMmYK,
+ CANON_SLOT_ASF1,
+ CANON_CAP_STD0,
+ CANON_MODES(canon_nomodes),
+#ifndef EXPERIMENTAL_STUFF
+ {-1,0,0,-1,0,-1}, /*150x150 300x300 600x600 1200x600 1200x1200 2400x2400*/
+ {1,1,1,1,1,1}, /*------- 300x300 600x600 -------- 1200x1200 ---------*/
+ CANON_INK(canon_ink_standard),
+#endif
+ standard_lum_adjustment,
+ standard_hue_adjustment,
+ standard_sat_adjustment
+ },
+};
+
+
+static const double plain_paper_lum_adjustment[49] =
+{
+ 1.2, /* C */
+ 1.22,
+ 1.28,
+ 1.34,
+ 1.39,
+ 1.42,
+ 1.45,
+ 1.48,
+ 1.5, /* B */
+ 1.4,
+ 1.3,
+ 1.25,
+ 1.2,
+ 1.1,
+ 1.05,
+ 1.05,
+ 1.05, /* M */
+ 1.05,
+ 1.05,
+ 1.05,
+ 1.05,
+ 1.05,
+ 1.05,
+ 1.05,
+ 1.05, /* R */
+ 1.05,
+ 1.05,
+ 1.1,
+ 1.1,
+ 1.1,
+ 1.1,
+ 1.1,
+ 1.1, /* Y */
+ 1.15,
+ 1.3,
+ 1.45,
+ 1.6,
+ 1.75,
+ 1.9,
+ 2.0,
+ 2.1, /* G */
+ 2.0,
+ 1.8,
+ 1.7,
+ 1.6,
+ 1.5,
+ 1.4,
+ 1.3,
+ 1.2 /* C */
+};
+
+typedef struct {
+ const char *name;
+ const char *text;
+ int media_code;
+ double base_density;
+ double k_lower_scale;
+ double k_upper;
+ const double *hue_adjustment;
+ const double *lum_adjustment;
+ const double *sat_adjustment;
+} paper_t;
+
+typedef struct {
+ const canon_cap_t *caps;
+ int output_type;
+ const paper_t *pt;
+ int print_head;
+ int colormode;
+ const char *source_str;
+ int xdpi;
+ int ydpi;
+ int page_width;
+ int page_height;
+ int top;
+ int left;
+ int bits;
+} canon_init_t;
+
+static const paper_t canon_paper_list[] = {
+ { "Plain", N_ ("Plain Paper"), 0x00, 0.50, 0.25, 0.500, 0, 0, 0 },
+ { "Transparency", N_ ("Transparencies"), 0x02, 1.00, 1.00, 0.900, 0, 0, 0 },
+ { "BackPrint", N_ ("Back Print Film"), 0x03, 1.00, 1.00, 0.900, 0, 0, 0 },
+ { "Fabric", N_ ("Fabric Sheets"), 0x04, 0.50, 0.25, 0.500, 0, 0, 0 },
+ { "Envelope", N_ ("Envelope"), 0x08, 0.50, 0.25, 0.500, 0, 0, 0 },
+ { "Coated", N_ ("High Resolution Paper"), 0x07, 0.78, 0.25, 0.500, 0, 0, 0 },
+ { "TShirt", N_ ("T-Shirt Transfers"), 0x03, 0.50, 0.25, 0.500, 0, 0, 0 },
+ { "GlossyFilm", N_ ("High Gloss Film"), 0x06, 1.00, 1.00, 0.999, 0, 0, 0 },
+ { "GlossyPaper", N_ ("Glossy Photo Paper"), 0x05, 1.00, 1.00, 0.999, 0, 0, 0 },
+ { "GlossyCard", N_ ("Glossy Photo Cards"), 0x0a, 1.00, 1.00, 0.999, 0, 0, 0 },
+ { "GlossyPro", N_ ("Photo Paper Pro"), 0x09, 1.00, 1.00, 0.999, 0, 0, 0 },
+ { "Other", N_ ("Other"), 0x00, 0.50, 0.25, .5, 0, 0, 0 },
+};
+
+static const int paper_type_count = sizeof(canon_paper_list) / sizeof(paper_t);
+
+static const paper_t *
+get_media_type(const char *name)
+{
+ int i;
+ for (i = 0; i < paper_type_count; i++)
+ {
+ /* translate paper_t.name */
+ if (!strcmp(name, canon_paper_list[i].name))
+ return &(canon_paper_list[i]);
+ }
+ return NULL;
+}
+
+
+static const canon_cap_t * canon_get_model_capabilities(int model)
+{
+ int i;
+ int models= sizeof(canon_model_capabilities) / sizeof(canon_cap_t);
+ for (i=0; i<models; i++) {
+ if (canon_model_capabilities[i].model == model) {
+ return &(canon_model_capabilities[i]);
+ }
+ }
+ stp_deprintf(STP_DBG_CANON,"canon: model %d not found in capabilities list.\n",model);
+ return &(canon_model_capabilities[0]);
+}
+
+static int
+canon_source_type(const char *name, const canon_cap_t * caps)
+{
+ /* used internally: do not translate */
+ if (!strcmp(name,"Auto")) return 4;
+ if (!strcmp(name,"Manual")) return 0;
+ if (!strcmp(name,"ManualNP")) return 1;
+
+ stp_deprintf(STP_DBG_CANON,"canon: Unknown source type '%s' - reverting to auto\n",name);
+ return 4;
+}
+
+static int
+canon_printhead_type(const char *name, const canon_cap_t * caps)
+{
+ /* used internally: do not translate */
+ if (!strcmp(name,"Gray")) return 0;
+ if (!strcmp(name,"RGB")) return 1;
+ if (!strcmp(name,"CMYK")) return 2;
+ if (!strcmp(name,"PhotoCMY")) return 3;
+ if (!strcmp(name,"Photo")) return 4;
+ if (!strcmp(name,"PhotoCMYK")) return 5;
+
+ if (*name == 0) {
+ if (caps->inks & CANON_INK_CMYK) return 2;
+ if (caps->inks & CANON_INK_CMY) return 1;
+ if (caps->inks & CANON_INK_K) return 0;
+ }
+
+ stp_deprintf(STP_DBG_CANON,"canon: Unknown head combo '%s' - reverting to black",name);
+ return 0;
+}
+
+static colormode_t
+canon_printhead_colors(const char *name, const canon_cap_t * caps)
+{
+ /* used internally: do not translate */
+ if (!strcmp(name,"Gray")) return COLOR_MONOCHROME;
+ if (!strcmp(name,"RGB")) return COLOR_CMY;
+ if (!strcmp(name,"CMYK")) return COLOR_CMYK;
+ if (!strcmp(name,"PhotoCMY")) return COLOR_CCMMYK;
+ if (!strcmp(name,"PhotoCMYK")) return COLOR_CCMMYYK;
+
+ if (*name == 0) {
+ if (caps->inks & CANON_INK_CMYK) return COLOR_CMYK;
+ if (caps->inks & CANON_INK_CMY) return COLOR_CMY;
+ if (caps->inks & CANON_INK_K) return COLOR_MONOCHROME;
+ }
+
+ stp_deprintf(STP_DBG_CANON,"canon: Unknown head combo '%s' - reverting to black",name);
+ return COLOR_MONOCHROME;
+}
+
+static unsigned char
+canon_size_type(const stp_vars_t v, const canon_cap_t * caps)
+{
+ const stp_papersize_t pp = stp_get_papersize_by_size(stp_get_page_height(v),
+ stp_get_page_width(v));
+ if (pp)
+ {
+ const char *name = stp_papersize_get_name(pp);
+ /* used internally: do not translate */
+ /* built ins: */
+ if (!strcmp(name,"A5")) return 0x01;
+ if (!strcmp(name,"A4")) return 0x03;
+ if (!strcmp(name,"B5")) return 0x08;
+ if (!strcmp(name,"Letter")) return 0x0d;
+ if (!strcmp(name,"Legal")) return 0x0f;
+ if (!strcmp(name,"COM10")) return 0x16;
+ if (!strcmp(name,"DL")) return 0x17;
+ if (!strcmp(name,"LetterExtra")) return 0x2a;
+ if (!strcmp(name,"A4Extra")) return 0x2b;
+ if (!strcmp(name,"w288h144")) return 0x2d;
+ /* custom */
+
+ stp_deprintf(STP_DBG_CANON,"canon: Unknown paper size '%s' - using custom\n",name);
+ } else {
+ stp_deprintf(STP_DBG_CANON,"canon: Couldn't look up paper size %dx%d - "
+ "using custom\n",stp_get_page_height(v), stp_get_page_width(v));
+ }
+ return 0;
+}
+
+static char *
+c_strdup(const char *s)
+{
+ char *ret = stp_malloc(strlen(s) + 1);
+ strcpy(ret, s);
+ return ret;
+}
+
+#ifndef EXPERIMENTAL_STUFF
+static int canon_res_code(const canon_cap_t * caps, int xdpi, int ydpi)
+{
+ int x, y, res= 0;
+
+ for (x=1; x<6; x++) if ((xdpi/caps->base_res) == (1<<(x-1))) res= (x<<4);
+ for (y=1; y<6; y++) if ((ydpi/caps->base_res) == (1<<(y-1))) res|= y;
+
+ return res;
+}
+#else
+static const canon_variable_printmode_t *canon_printmode(const canon_cap_t * caps,
+ int xdpi, int ydpi,
+ int bpp, int head)
+{
+ const canon_variable_printmode_t *modes;
+ int modes_cnt;
+ int i;
+ if (!caps) return 0;
+ modes= caps->printmodes;
+ modes_cnt= caps->printmodes_cnt;
+ /* search for the right printmode: */
+ for (i=0; i<modes_cnt; i++) {
+ if ((modes[i].xdpi== xdpi) && (modes[i].ydpi== ydpi) &&
+ (modes[i].bits== bpp) && (modes[i].printhead== head))
+ {
+ return &(modes[i]);
+ }
+ }
+ /* nothing found -> either return 0 or apply some policy to
+ * get a fallback printmode
+ */
+ if (modes[0].xdpi) return modes;
+ return 0;
+}
+#endif
+
+static int
+canon_ink_type(const canon_cap_t * caps, int res_code)
+{
+#ifndef EXPERIMENTAL_STUFF
+ switch (res_code)
+ {
+ case 0x11: return caps->dot_sizes.dot_r11;
+ case 0x22: return caps->dot_sizes.dot_r22;
+ case 0x33: return caps->dot_sizes.dot_r33;
+ case 0x43: return caps->dot_sizes.dot_r43;
+ case 0x44: return caps->dot_sizes.dot_r44;
+ case 0x55: return caps->dot_sizes.dot_r55;
+ }
+ return -1;
+#else
+ return -1;
+#endif
+}
+
+static const double *
+canon_lum_adjustment(const stp_printer_t printer)
+{
+ const canon_cap_t * caps=
+ canon_get_model_capabilities(stp_printer_get_model(printer));
+ return (caps->lum_adjustment);
+}
+
+static const double *
+canon_hue_adjustment(const stp_printer_t printer)
+{
+ const canon_cap_t * caps=
+ canon_get_model_capabilities(stp_printer_get_model(printer));
+ return (caps->hue_adjustment);
+}
+
+static const double *
+canon_sat_adjustment(const stp_printer_t printer)
+{
+ const canon_cap_t * caps=
+ canon_get_model_capabilities(stp_printer_get_model(printer));
+ return (caps->sat_adjustment);
+}
+
+static double
+canon_density(const canon_cap_t * caps, int res_code)
+{
+#ifndef EXPERIMENTAL_STUFF
+ switch (res_code)
+ {
+ case 0x11: return caps->densities.d_r11;
+ case 0x22: return caps->densities.d_r22;
+ case 0x33: return caps->densities.d_r33;
+ case 0x43: return caps->densities.d_r43;
+ case 0x44: return caps->densities.d_r44;
+ case 0x55: return caps->densities.d_r55;
+ default:
+ stp_deprintf(STP_DBG_CANON,"no such res_code 0x%x in density of model %d\n",
+ res_code,caps->model);
+ return 0.2;
+ }
+#else
+ return 0.2;
+#endif
+}
+
+static const canon_variable_inkset_t *
+canon_inks(const canon_cap_t * caps, int res_code, int colors, int bits)
+{
+#ifndef EXPERIMENTAL_STUFF
+ const canon_variable_inklist_t *inks = caps->inxs;
+ int i;
+
+ if (!inks)
+ return NULL;
+
+ for (i=0; i<caps->inxs_cnt; i++) {
+ stp_deprintf(STP_DBG_CANON,"hmm, trying ink for resolution code "
+ "%x, %d bits, %d colors\n",res_code,inks[i].bits,inks[i].colors);
+ if ((inks[i].bits==bits) && (inks[i].colors==colors)) {
+ stp_deprintf(STP_DBG_CANON,"wow, found ink for resolution code "
+ "%x, %d bits, %d colors\n",res_code,bits,colors);
+ switch (res_code)
+ {
+ case 0x11: return inks[i].r11;
+ case 0x22: return inks[i].r22;
+ case 0x33: return inks[i].r33;
+ case 0x43: return inks[i].r43;
+ case 0x44: return inks[i].r44;
+ case 0x55: return inks[i].r55;
+ }
+ }
+ }
+ stp_deprintf(STP_DBG_CANON,"ooo, found no ink for resolution code "
+ "%x, %d bits, %d colors in all %d defs!\n",
+ res_code,bits,colors,caps->inxs_cnt);
+ return NULL;
+#else
+ return NULL;
+#endif
+}
+
+static void
+canon_describe_resolution(const stp_printer_t printer,
+ const char *resolution, int *x, int *y)
+{
+ *x = -1;
+ *y = -1;
+ sscanf(resolution, "%dx%d", x, y);
+ return;
+}
+
+static stp_param_t media_sources[] =
+ {
+ { "Auto", N_ ("Auto Sheet Feeder") },
+ { "Manual", N_ ("Manual with Pause") },
+ { "ManualNP", N_ ("Manual without Pause") }
+ };
+
+
+/*
+ * 'canon_parameters()' - Return the parameter values for the given parameter.
+ */
+
+static stp_param_t * /* O - Parameter values */
+canon_parameters(const stp_printer_t printer, /* I - Printer model */
+ const char *ppd_file, /* I - PPD file (not used) */
+ const char *name, /* I - Name of parameter */
+ int *count) /* O - Number of values */
+{
+ int i;
+ stp_param_t *p= 0;
+ stp_param_t *valptrs= 0;
+
+ const canon_cap_t * caps=
+ canon_get_model_capabilities(stp_printer_get_model(printer));
+
+ if (count == NULL)
+ return (NULL);
+
+ *count = 0;
+
+ if (name == NULL)
+ return (NULL);
+
+ if (strcmp(name, "PageSize") == 0)
+ {
+ int height_limit, width_limit;
+ int papersizes = stp_known_papersizes();
+ valptrs = stp_malloc(sizeof(stp_param_t) * papersizes);
+ *count = 0;
+
+ width_limit = caps->max_width;
+ height_limit = caps->max_height;
+
+ for (i = 0; i < papersizes; i++) {
+ const stp_papersize_t pt = stp_get_papersize_by_index(i);
+ if (strlen(stp_papersize_get_name(pt)) > 0 &&
+ stp_papersize_get_width(pt) <= width_limit &&
+ stp_papersize_get_height(pt) <= height_limit)
+ {
+ valptrs[*count].name = c_strdup(stp_papersize_get_name(pt));
+ valptrs[*count].text = c_strdup(stp_papersize_get_text(pt));
+ (*count)++;
+ }
+ }
+ }
+ else if (strcmp(name, "Resolution") == 0)
+ {
+ char tmp[100];
+ int x,y;
+ int c= 0;
+ int t;
+ valptrs = stp_malloc(sizeof(stp_param_t) * 10);
+
+ for (x=1; x<6; x++) {
+ for (y=x-1; y<x+1; y++) {
+ if ((t= canon_ink_type(caps,(x<<4)|y)) > -1) {
+ sprintf(tmp,"%dx%ddpi",
+ (1<<x)/2*caps->base_res,(1<<y)/2*caps->base_res);
+ valptrs[c].name= c_strdup(tmp);
+
+ sprintf(tmp,"%dx%d DPI",
+ (1<<x)/2*caps->base_res,(1<<y)/2*caps->base_res);
+ stp_deprintf(STP_DBG_CANON,"supports mode '%s'\n",tmp);
+ valptrs[c++].text= c_strdup(tmp);
+
+ if (t==1) {
+ sprintf(tmp,"%dx%ddmt",
+ (1<<x)/2*caps->base_res,(1<<y)/2*caps->base_res);
+ valptrs[c].name= c_strdup(tmp);
+ sprintf(tmp,"%dx%d DPI DMT",
+ (1<<x)/2*caps->base_res,(1<<y)/2*caps->base_res);
+ stp_deprintf(STP_DBG_CANON,"supports mode '%s'\n",tmp);
+ valptrs[c++].text = c_strdup(tmp);
+ }
+ }
+ }
+ }
+ *count= c;
+ }
+ else if (strcmp(name, "InkType") == 0)
+ {
+ int c= 0;
+ valptrs = stp_malloc(sizeof(stp_param_t) * 5);
+ /* used internally: do not translate */
+ if ((caps->inks & CANON_INK_K))
+ {
+ valptrs[c].name = c_strdup("Gray");
+ valptrs[c++].text = c_strdup(_("Black"));
+ }
+ if ((caps->inks & CANON_INK_CMY))
+ {
+ valptrs[c].name = c_strdup("RGB");
+ valptrs[c++].text = c_strdup(_("CMY Color"));
+ }
+ if ((caps->inks & CANON_INK_CMYK))
+ {
+ valptrs[c].name = c_strdup("CMYK");
+ valptrs[c++].text = c_strdup(_("CMYK Color"));
+ }
+ if ((caps->inks & CANON_INK_CcMmYK))
+ {
+ valptrs[c].name = c_strdup("PhotoCMY");
+ valptrs[c++].text = c_strdup(_("Photo CcMmY Color"));
+ }
+ if ((caps->inks & CANON_INK_CcMmYyK))
+ {
+ valptrs[c].name = c_strdup("PhotoCMYK");
+ valptrs[c++].text = c_strdup(_("Photo CcMmYK Color"));
+ }
+
+ *count = c;
+ }
+ else if (strcmp(name, "MediaType") == 0)
+ {
+ *count = sizeof(canon_paper_list) / sizeof(canon_paper_list[0]);
+
+ valptrs = stp_malloc(*count * sizeof(stp_param_t));
+
+ for (i = 0; i < *count; i ++)
+ {
+ valptrs[i].name = c_strdup(canon_paper_list[i].name);
+ valptrs[i].text = c_strdup(_(canon_paper_list[i].text));
+ }
+ }
+ else if (strcmp(name, "InputSlot") == 0)
+ {
+ *count = 3;
+ p = media_sources;
+
+ valptrs = stp_malloc(*count * sizeof(stp_param_t));
+ for (i = 0; i < *count; i ++)
+ {
+ /* translate media_sources */
+ valptrs[i].name = c_strdup(p[i].name);
+ valptrs[i].text = c_strdup(_(p[i].text));
+ }
+ }
+ else
+ return (NULL);
+
+ return (valptrs);
+}
+
+static const char *
+canon_default_parameters(const stp_printer_t printer,
+ const char *ppd_file,
+ const char *name)
+{
+ int i;
+ const canon_cap_t * caps=
+ canon_get_model_capabilities(stp_printer_get_model(printer));
+
+ if (name == NULL)
+ return (NULL);
+
+ if (strcmp(name, "PageSize") == 0)
+ {
+ int height_limit, width_limit;
+ int papersizes = stp_known_papersizes();
+
+ width_limit = caps->max_width;
+ height_limit = caps->max_height;
+
+ for (i = 0; i < papersizes; i++) {
+ const stp_papersize_t pt = stp_get_papersize_by_index(i);
+ if (strlen(stp_papersize_get_name(pt)) > 0 &&
+ stp_papersize_get_width(pt) <= width_limit &&
+ stp_papersize_get_height(pt) <= height_limit)
+ return (stp_papersize_get_name(pt));
+ }
+ return NULL;
+ }
+ else if (strcmp(name, "Resolution") == 0)
+ {
+ char tmp[100];
+ int x,y;
+ int t;
+ int min_res = caps->base_res;
+ while (min_res < 300)
+ min_res *= 2;
+
+ for (x=1; x<6; x++)
+ {
+ for (y=x-1; y<x+1; y++)
+ {
+ if ((t= canon_ink_type(caps,(x<<4)|y)) > -1)
+ {
+ if (t == 1)
+ sprintf(tmp, "%dx%ddmt", min_res, min_res);
+ else
+ sprintf(tmp,"%dx%ddpi", min_res, min_res);
+
+ stp_deprintf(STP_DBG_CANON,"supports mode '%s'\n",tmp);
+ return (c_strdup(tmp));
+ }
+ }
+ }
+ return NULL;
+ }
+ else if (strcmp(name, "InkType") == 0)
+ {
+ /* used internally: do not translate */
+ if ((caps->inks & CANON_INK_K))
+ return ("Gray");
+ if ((caps->inks & CANON_INK_CMY))
+ return ("RGB");
+ if ((caps->inks & CANON_INK_CMYK))
+ return ("CMYK");
+ if ((caps->inks & CANON_INK_CcMmYK))
+ return ("PhotoCMY");
+ if ((caps->inks & CANON_INK_CcMmYyK))
+ return ("PhotoCMYK");
+ return NULL;
+ }
+ else if (strcmp(name, "MediaType") == 0)
+ {
+ return (canon_paper_list[0].name);
+ }
+ else if (strcmp(name, "InputSlot") == 0)
+ {
+ return (media_sources[0].name);
+ }
+ else
+ return (NULL);
+}
+
+
+/*
+ * 'canon_imageable_area()' - Return the imageable area of the page.
+ */
+
+static void
+canon_imageable_area(const stp_printer_t printer, /* I - Printer model */
+ const stp_vars_t v, /* I */
+ int *left, /* O - Left position in points */
+ int *right, /* O - Right position in points */
+ int *bottom, /* O - Bottom position in points */
+ int *top) /* O - Top position in points */
+{
+ int width, length; /* Size of page */
+
+ const canon_cap_t * caps=
+ canon_get_model_capabilities(stp_printer_get_model(printer));
+
+ stp_default_media_size(printer, v, &width, &length);
+
+ *left = caps->border_left;
+ *right = width - caps->border_right;
+ *top = length - caps->border_top;
+ *bottom = caps->border_bottom;
+}
+
+static void
+canon_limit(const stp_printer_t printer, /* I - Printer model */
+ const stp_vars_t v, /* I */
+ int *width,
+ int *height,
+ int *min_width,
+ int *min_height)
+{
+ const canon_cap_t * caps=
+ canon_get_model_capabilities(stp_printer_get_model(printer));
+ *width = caps->max_width;
+ *height = caps->max_height;
+ *min_width = 1;
+ *min_height = 1;
+}
+
+/*
+ * 'canon_cmd()' - Sends a command with variable args
+ */
+static void
+canon_cmd(const stp_vars_t v, /* I - the printer */
+ const char *ini, /* I - 2 bytes start code */
+ const char cmd, /* I - command code */
+ int num, /* I - number of arguments */
+ ... /* I - the args themselves */
+ )
+{
+ unsigned char *buffer = stp_malloc(num + 1);
+ int i;
+ va_list ap;
+
+ if (num)
+ {
+ va_start(ap, num);
+ for (i=0; i<num; i++)
+ buffer[i]= (unsigned char) va_arg(ap, int);
+ va_end(ap);
+ }
+
+ stp_zfwrite(ini,2,1,v);
+ if (cmd)
+ {
+ stp_putc(cmd,v);
+ stp_putc((num & 255),v);
+ stp_putc((num >> 8 ),v);
+ if (num)
+ stp_zfwrite((const char *)buffer,num,1,v);
+ }
+ stp_free(buffer);
+}
+
+#define PUT(WHAT,VAL,RES) stp_deprintf(STP_DBG_CANON,"canon: "WHAT\
+" is %04x =% 5d = %f\" = %f mm\n",(VAL),(VAL),(VAL)/(1.*RES),(VAL)/(RES/25.4))
+
+#define ESC28 "\033\050"
+#define ESC5b "\033\133"
+#define ESC40 "\033\100"
+
+#define MIN(a,b) (((a)<(b)) ? (a) : (b))
+#define MAX(a,b) (((a)>(b)) ? (a) : (b))
+
+/* ESC [K -- -- reset printer:
+ */
+static void
+canon_init_resetPrinter(const stp_vars_t v, canon_init_t *init)
+{
+ unsigned long f=init->caps->features;
+ if (f & (CANON_CAP_ACKSHORT))
+ {
+ canon_cmd(v,ESC5b,0x4b, 2, 0x00,0x1f);
+ stp_puts("BJLSTART\nControlMode=Common\n",v);
+ if (f & CANON_CAP_ACKSHORT) stp_puts("AckTime=Short\n",v);
+ stp_puts("BJLEND\n",v);
+ }
+ canon_cmd(v,ESC5b,0x4b, 2, 0x00,0x0f);
+}
+
+/* ESC (a -- 0x61 -- cmdSetPageMode --:
+ */
+static void
+canon_init_setPageMode(const stp_vars_t v, canon_init_t *init)
+{
+ if (!(init->caps->features & CANON_CAP_a))
+ return;
+
+ if (init->caps->features & CANON_CAP_a)
+ canon_cmd(v,ESC28,0x61, 1, 0x01);
+}
+
+/* ESC (b -- 0x62 -- -- set data compression:
+ */
+static void
+canon_init_setDataCompression(const stp_vars_t v, canon_init_t *init)
+{
+ if (!(init->caps->features & CANON_CAP_b))
+ return;
+
+ canon_cmd(v,ESC28,0x62, 1, 0x01);
+}
+
+/* ESC (c -- 0x63 -- cmdSetColor --:
+ */
+static void
+canon_init_setColor(const stp_vars_t v, canon_init_t *init)
+{
+ unsigned char
+ arg_63_1 = 0x00,
+ arg_63_2 = 0x00, /* plain paper */
+ arg_63_3 = 0x00; /* output quality, hardcoded to Normal for now */
+
+ if (!(init->caps->features & CANON_CAP_c))
+ return;
+
+ arg_63_1 = init->caps->model_id << 4;
+
+ if (init->output_type==OUTPUT_GRAY || init->output_type == OUTPUT_MONOCHROME)
+ arg_63_1|= 0x01;
+
+ if (init->pt) arg_63_2= init->pt->media_code;
+
+ canon_cmd(v,ESC28,0x63, 3, arg_63_1, arg_63_2, arg_63_3);
+}
+
+/* ESC (d -- 0x64 -- -- set raster resolution:
+ */
+static void
+canon_init_setResolution(const stp_vars_t v, canon_init_t *init)
+{
+ if (!(init->caps->features & CANON_CAP_d))
+ return;
+
+ canon_cmd(v,ESC28,0x64, 4,
+ (init->ydpi >> 8 ), (init->ydpi & 255),
+ (init->xdpi >> 8 ), (init->xdpi & 255));
+}
+
+/* ESC (g -- 0x67 -- cmdSetPageMargins --:
+ */
+static void
+canon_init_setPageMargins(const stp_vars_t v, canon_init_t *init)
+{
+ /* TOFIX: what exactly is to be sent?
+ * Is it the printable length or the bottom border?
+ * Is is the printable width or the right border?
+ */
+
+ int minlength= 0;
+ int minwidth= 0;
+ int length= init->page_height*5/36;
+ int width= init->page_width*5/36;
+
+ if (!(init->caps->features & CANON_CAP_g))
+ return;
+
+ if (minlength>length) length= minlength;
+ if (minwidth>width) width= minwidth;
+
+ canon_cmd(v,ESC28,0x67, 4, 0,
+ (unsigned char)(length),1,
+ (unsigned char)(width));
+
+}
+
+/* ESC (l -- 0x6c -- cmdSetTray --:
+ */
+static void
+canon_init_setTray(const stp_vars_t v, canon_init_t *init)
+{
+ unsigned char
+ arg_6c_1 = 0x00,
+ arg_6c_2 = 0x00; /* plain paper */
+
+ /* int media= canon_media_type(media_str,caps); */
+ int source= canon_source_type(init->source_str,init->caps);
+
+ if (!(init->caps->features & CANON_CAP_l))
+ return;
+
+ arg_6c_1 = init->caps->model_id << 4;
+
+ arg_6c_1|= (source & 0x0f);
+
+ if (init->pt) arg_6c_2= init->pt->media_code;
+
+ canon_cmd(v,ESC28,0x6c, 2, arg_6c_1, arg_6c_2);
+}
+
+/* ESC (m -- 0x6d -- -- :
+ */
+static void
+canon_init_setPrintMode(const stp_vars_t v, canon_init_t *init)
+{
+ unsigned char
+ arg_6d_1 = 0x03, /* color printhead? */
+ arg_6d_2 = 0x00, /* 00=color 02=b/w */
+ arg_6d_3 = 0x00, /* only 01 for bjc8200 */
+ arg_6d_a = 0x03, /* A4 paper */
+ arg_6d_b = 0x00;
+
+ if (!(init->caps->features & CANON_CAP_m))
+ return;
+
+ arg_6d_a= canon_size_type(v,init->caps);
+ if (!arg_6d_a)
+ arg_6d_b= 1;
+
+ if (init->print_head==0)
+ arg_6d_1= 0x03;
+ else if (init->print_head<=2)
+ arg_6d_1= 0x02;
+ else if (init->print_head<=4)
+ arg_6d_1= 0x04;
+ if (init->output_type==OUTPUT_GRAY || init->output_type == OUTPUT_MONOCHROME)
+ arg_6d_2= 0x02;
+
+ if (init->caps->model==8200)
+ arg_6d_3= 0x01;
+
+ canon_cmd(v,ESC28,0x6d,12, arg_6d_1,
+ 0xff,0xff,0x00,0x00,0x07,0x00,
+ arg_6d_a,arg_6d_b,arg_6d_2,0x00,arg_6d_3);
+}
+
+/* ESC (p -- 0x70 -- cmdSetPageMargins2 --:
+ */
+static void
+canon_init_setPageMargins2(const stp_vars_t v, canon_init_t *init)
+{
+ /* TOFIX: what exactly is to be sent?
+ * Is it the printable length or the bottom border?
+ * Is is the printable width or the right border?
+ */
+
+ int printable_width= init->page_width*5/6;
+ int printable_length= init->page_height*5/6;
+
+ unsigned char arg_70_1= (printable_length >> 8) & 0xff;
+ unsigned char arg_70_2= (printable_length) & 0xff;
+ unsigned char arg_70_3= (printable_width >> 8) & 0xff;
+ unsigned char arg_70_4= (printable_width) & 0xff;
+
+ if (!(init->caps->features & CANON_CAP_p))
+ return;
+
+ canon_cmd(v,ESC28,0x70, 8,
+ arg_70_1, arg_70_2, 0x00, 0x00,
+ arg_70_3, arg_70_4, 0x00, 0x00);
+}
+
+/* ESC (q -- 0x71 -- setPageID -- :
+ */
+static void
+canon_init_setPageID(const stp_vars_t v, canon_init_t *init)
+{
+ if (!(init->caps->features & CANON_CAP_q))
+ return;
+
+ canon_cmd(v,ESC28,0x71, 1, 0x01);
+}
+
+/* ESC (r -- 0x72 -- -- :
+ */
+static void
+canon_init_setX72(const stp_vars_t v, canon_init_t *init)
+{
+ if (!(init->caps->features & CANON_CAP_r))
+ return;
+
+ canon_cmd(v,ESC28,0x72, 1, 0x61); /* whatever for - 8200 needs it */
+}
+
+/* ESC (t -- 0x74 -- cmdSetImage --:
+ */
+static void
+canon_init_setImage(const stp_vars_t v, canon_init_t *init)
+{
+ unsigned char
+ arg_74_1 = 0x01, /* 1 bit per pixel */
+ arg_74_2 = 0x00, /* */
+ arg_74_3 = 0x01; /* 01 <= 360 dpi 09 >= 720 dpi */
+
+ if (!(init->caps->features & CANON_CAP_t))
+ return;
+
+ if (init->xdpi==1440) arg_74_2= 0x04;
+ if (init->ydpi>=720) arg_74_3= 0x09;
+
+ if (init->bits>1) {
+ arg_74_1= 0x02;
+ arg_74_2= 0x80;
+ arg_74_3= 0x09;
+ if (init->colormode == COLOR_CMY) arg_74_3= 0x02; /* for BC-06 cartridge!!! */
+ }
+
+ /* workaround for the bjc8200 in 6color mode - not really understood */
+ if (init->caps->model==8200) {
+ if (init->colormode==COLOR_CCMMYK) {
+ arg_74_1= 0xff;
+ arg_74_2= 0x90;
+ arg_74_3= 0x04;
+ init->bits=3;
+ if (init->ydpi>600) arg_74_3= 0x09;
+ } else {
+ arg_74_1= 0x01;
+ arg_74_2= 0x00;
+ arg_74_3= 0x01;
+ if (init->ydpi>600) arg_74_3= 0x09;
+ }
+ }
+
+ canon_cmd(v,ESC28,0x74, 3, arg_74_1, arg_74_2, arg_74_3);
+}
+
+static void
+canon_init_printer(const stp_vars_t v, canon_init_t *init)
+{
+ int mytop;
+ /* init printer */
+
+ canon_init_resetPrinter(v,init); /* ESC [K */
+ canon_init_setPageMode(v,init); /* ESC (a */
+ canon_init_setDataCompression(v,init); /* ESC (b */
+ canon_init_setPageID(v,init); /* ESC (q */
+ canon_init_setPrintMode(v,init); /* ESC (m */
+ canon_init_setResolution(v,init); /* ESC (d */
+ canon_init_setImage(v,init); /* ESC (t */
+ canon_init_setColor(v,init); /* ESC (c */
+ canon_init_setPageMargins(v,init); /* ESC (g */
+ canon_init_setPageMargins2(v,init); /* ESC (p */
+ canon_init_setTray(v,init); /* ESC (l */
+ canon_init_setX72(v,init); /* ESC (r */
+
+ /* some linefeeds */
+
+ mytop= (init->top*init->ydpi)/72;
+ canon_cmd(v,ESC28,0x65, 2, (mytop >> 8 ),(mytop & 255));
+}
+
+static void
+canon_deinit_printer(const stp_vars_t v, canon_init_t *init)
+{
+ /* eject page */
+ stp_putc(0x0c,v);
+
+ /* say goodbye */
+ canon_cmd(v,ESC28,0x62,1,0);
+ if (init->caps->features & CANON_CAP_a)
+ canon_cmd(v,ESC28,0x61, 1, 0);
+ canon_cmd(v,ESC40,0,0);
+}
+
+
+/*
+ * 'alloc_buffer()' allocates buffer and fills it with 0
+ */
+static unsigned char *
+canon_alloc_buffer(int size)
+{
+ unsigned char *buf= stp_malloc(size);
+ if (buf)
+ memset(buf,0,size);
+ return buf;
+}
+
+/*
+ * 'advance_buffer()' - Move (num) lines of length (len) down one line
+ * and sets first line to 0s
+ * accepts NULL pointers as buf
+ * !!! buf must contain more than (num) lines !!!
+ * also sets first line to 0s if num<1
+ */
+static void
+canon_advance_buffer(unsigned char *buf, int len, int num)
+{
+ if (!buf || !len) return;
+ if (num>0) memmove(buf+len,buf,len*num);
+ memset(buf,0,len);
+}
+
+/*
+ * 'canon_print()' - Print an image to a CANON printer.
+ */
+static void
+canon_print(const stp_printer_t printer, /* I - Model */
+ stp_image_t *image, /* I - Image to print */
+ const stp_vars_t v)
+{
+ int i;
+ const unsigned char *cmap = stp_get_cmap(v);
+ int model = stp_printer_get_model(printer);
+ const char *resolution = stp_get_resolution(v);
+ const char *media_source = stp_get_media_source(v);
+ int output_type = stp_get_output_type(v);
+ int orientation = stp_get_orientation(v);
+ const char *ink_type = stp_get_ink_type(v);
+ double scaling = stp_get_scaling(v);
+ int top = stp_get_top(v);
+ int left = stp_get_left(v);
+ int y; /* Looping vars */
+ int xdpi, ydpi; /* Resolution */
+ int n; /* Output number */
+ unsigned short *out; /* Output pixels (16-bit) */
+ unsigned char *in, /* Input pixels */
+ *black, /* Black bitmap data */
+ *cyan, /* Cyan bitmap data */
+ *magenta, /* Magenta bitmap data */
+ *yellow, /* Yellow bitmap data */
+ *lcyan, /* Light cyan bitmap data */
+ *lmagenta, /* Light magenta bitmap data */
+ *lyellow; /* Light yellow bitmap data */
+ int delay_k,
+ delay_c,
+ delay_m,
+ delay_y,
+ delay_lc,
+ delay_lm,
+ delay_ly,
+ delay_max;
+ int page_left, /* Left margin of page */
+ page_right, /* Right margin of page */
+ page_top, /* Top of page */
+ page_bottom, /* Bottom of page */
+ page_width, /* Width of page */
+ page_height, /* Length of page */
+ page_true_height, /* True length of page */
+ out_width, /* Width of image on page */
+ out_length, /* Length of image on page */
+ out_bpp, /* Output bytes per pixel */
+ length, /* Length of raster data */
+ buf_length, /* Length of raster data buffer (dmt) */
+ errdiv, /* Error dividend */
+ errmod, /* Error modulus */
+ errval, /* Current error value */
+ errline, /* Current raster line */
+ errlast; /* Last raster line loaded */
+ stp_convert_t colorfunc = 0; /* Color conversion function... */
+ int zero_mask;
+ int bits= 1;
+ int image_height,
+ image_width,
+ image_bpp;
+ int ink_spread;
+ void * dither;
+ int res_code;
+ int use_6color= 0;
+ double k_upper, k_lower;
+ int emptylines= 0;
+ stp_vars_t nv = stp_allocate_copy(v);
+ double lum_adjustment[49], sat_adjustment[49], hue_adjustment[49];
+ int have_lum_adjustment= 0;
+ int have_sat_adjustment= 0;
+ int have_hue_adjustment= 0;
+ canon_init_t init;
+ const canon_cap_t * caps= canon_get_model_capabilities(model);
+ int printhead= canon_printhead_type(ink_type,caps);
+ colormode_t colormode = canon_printhead_colors(ink_type,caps);
+ const paper_t *pt;
+ const canon_variable_inkset_t *inks;
+
+ if (!stp_get_verified(nv))
+ {
+ stp_eprintf(nv, "Print options not verified; cannot print.\n");
+ return;
+ }
+
+ PUT("top ",top,72);
+ PUT("left ",left,72);
+
+ /*
+ * Setup a read-only pixel region for the entire image...
+ */
+
+ image->init(image);
+ image_height = image->height(image);
+ image_width = image->width(image);
+ image_bpp = image->bpp(image);
+
+ /* force grayscale if image is grayscale
+ * or single black cartridge installed
+ */
+
+ if ((printhead == 0 || caps->inks == CANON_INK_K) &&
+ output_type != OUTPUT_MONOCHROME)
+ {
+ output_type = OUTPUT_GRAY;
+ stp_set_output_type(nv, output_type);
+ }
+
+ if (output_type == OUTPUT_GRAY || output_type == OUTPUT_MONOCHROME)
+ colormode = COLOR_MONOCHROME;
+ stp_set_output_color_model(nv, COLOR_MODEL_CMY);
+
+ /*
+ * Choose the correct color conversion function...
+ */
+
+ colorfunc = stp_choose_colorfunc(output_type, image_bpp, cmap, &out_bpp, nv);
+
+ /*
+ * Figure out the output resolution...
+ */
+
+ switch (sscanf(resolution,"%dx%d",&xdpi,&ydpi)) {
+ case 1: ydpi= xdpi; if (ydpi>caps->max_ydpi) ydpi/= 2; break;
+ case 0: xdpi= caps->max_xdpi; ydpi= caps->max_ydpi; break;
+ }
+
+ stp_deprintf(STP_DBG_CANON,"canon: resolution=%dx%d\n",xdpi,ydpi);
+ stp_deprintf(STP_DBG_CANON," rescode =0x%x\n",canon_res_code(caps,xdpi,ydpi));
+ res_code= canon_res_code(caps,xdpi,ydpi);
+
+ if (((!strcmp(resolution+(strlen(resolution)-3),"DMT")) ||
+ (!strcmp(resolution+(strlen(resolution)-3),"dmt"))) &&
+ (caps->features & CANON_CAP_DMT) &&
+ output_type != OUTPUT_MONOCHROME) {
+ bits= 2;
+ stp_deprintf(STP_DBG_CANON,"canon: using drop modulation technology\n");
+ }
+
+ /*
+ * Compute the output size...
+ */
+
+ canon_imageable_area(printer, nv, &page_left, &page_right,
+ &page_bottom, &page_top);
+
+ stp_compute_page_parameters(page_right, page_left, page_top, page_bottom,
+ scaling, image_width, image_height, image,
+ &orientation, &page_width, &page_height,
+ &out_width, &out_length, &left, &top);
+
+ /*
+ * Recompute the image length and width. If the image has been
+ * rotated, these will change from previously.
+ */
+ image_height = image->height(image);
+ image_width = image->width(image);
+
+ stp_default_media_size(printer, nv, &n, &page_true_height);
+
+ PUT("top ",top,72);
+ PUT("left ",left,72);
+ PUT("page_top ",page_top,72);
+ PUT("page_bottom",page_bottom,72);
+ PUT("page_left ",page_left,72);
+ PUT("page_right ",page_right,72);
+ PUT("page_width ",page_width,72);
+ PUT("page_height",page_height,72);
+ PUT("page_true_height",page_true_height,72);
+ PUT("out_width ", out_width,xdpi);
+ PUT("out_length", out_length,ydpi);
+
+ image->progress_init(image);
+
+ PUT("top ",top,72);
+ PUT("left ",left,72);
+
+ pt = get_media_type(stp_get_media_type(nv));
+
+ init.caps = caps;
+ init.output_type = output_type;
+ init.pt = pt;
+ init.print_head = printhead;
+ init.colormode = colormode;
+ init.source_str = media_source;
+ init.xdpi = xdpi;
+ init.ydpi = ydpi;
+ init.page_width = page_width;
+ init.page_height = page_height;
+ init.top = top;
+ init.left = left;
+ init.bits = bits;
+
+ canon_init_printer(nv, &init);
+
+ /* possibly changed during initialitation
+ * to enforce valid modes of operation:
+ */
+ bits= init.bits;
+ xdpi= init.xdpi;
+ ydpi= init.ydpi;
+
+ /*
+ * Convert image size to printer resolution...
+ */
+
+ out_width = xdpi * out_width / 72;
+ out_length = ydpi * out_length / 72;
+
+ PUT("out_width ", out_width,xdpi);
+ PUT("out_length", out_length,ydpi);
+
+ left = xdpi * left / 72;
+
+ PUT("leftskip",left,xdpi);
+
+ if(xdpi==1440){
+ delay_k= 0;
+ delay_c= 112;
+ delay_m= 224;
+ delay_y= 336;
+ delay_lc= 112;
+ delay_lm= 224;
+ delay_ly= 336;
+ delay_max= 336;
+ stp_deprintf(STP_DBG_CANON,"canon: delay on!\n");
+ } else {
+ delay_k= delay_c= delay_m= delay_y= delay_lc= delay_lm= delay_ly=0;
+ delay_max=0;
+ stp_deprintf(STP_DBG_CANON,"canon: delay off!\n");
+ }
+
+ /*
+ * Allocate memory for the raster data...
+ */
+
+ length = (out_width + 7) / 8;
+
+ buf_length= length*bits;
+
+ stp_deprintf(STP_DBG_CANON,"canon: buflength is %d!\n",buf_length);
+
+ if (colormode==COLOR_MONOCHROME) {
+ black = canon_alloc_buffer(buf_length*(delay_k+1));
+ cyan = NULL;
+ magenta = NULL;
+ lcyan = NULL;
+ lmagenta= NULL;
+ yellow = NULL;
+ lyellow = NULL;
+ } else {
+ cyan = canon_alloc_buffer(buf_length*(delay_c+1));
+ magenta = canon_alloc_buffer(buf_length*(delay_m+1));
+ yellow = canon_alloc_buffer(buf_length*(delay_y+1));
+
+ if (colormode!=COLOR_CMY)
+ black = canon_alloc_buffer(buf_length*(delay_k+1));
+ else
+ black = NULL;
+
+ if (colormode==COLOR_CCMMYK || colormode==COLOR_CCMMYYK) {
+ use_6color= 1;
+ lcyan = canon_alloc_buffer(buf_length*(delay_lc+1));
+ lmagenta = canon_alloc_buffer(buf_length*(delay_lm+1));
+ if (colormode==CANON_INK_CcMmYyK)
+ lyellow = canon_alloc_buffer(buf_length*(delay_lc+1));
+ else
+ lyellow = NULL;
+ } else {
+ lcyan = NULL;
+ lmagenta = NULL;
+ lyellow = NULL;
+ }
+ }
+
+ stp_deprintf(STP_DBG_CANON,"canon: driver will use colors %s%s%s%s%s%s\n",
+ cyan ? "C" : "", lcyan ? "c" : "", magenta ? "M" : "",
+ lmagenta ? "m" : "", yellow ? "Y" : "", black ? "K" : "");
+
+ stp_deprintf(STP_DBG_CANON,"density is %f\n",stp_get_density(nv));
+
+ /*
+ * Compute the LUT. For now, it's 8 bit, but that may eventually
+ * sometimes change.
+ */
+ if (pt)
+ stp_set_density(nv, stp_get_density(nv) * pt->base_density);
+ else /* Can't find paper type? Assume plain */
+ stp_set_density(nv, stp_get_density(nv) * .5);
+ stp_set_density(nv, stp_get_density(nv) * canon_density(caps, res_code));
+ if (stp_get_density(nv) > 1.0)
+ stp_set_density(nv, 1.0);
+ if (colormode == COLOR_MONOCHROME)
+ stp_set_gamma(nv, stp_get_gamma(nv) / .8);
+ stp_compute_lut(nv, 256);
+
+ stp_deprintf(STP_DBG_CANON,"density is %f\n",stp_get_density(nv));
+
+ /*
+ * Output the page...
+ */
+
+ if (xdpi > ydpi)
+ dither = stp_init_dither(image_width, out_width, 1, xdpi / ydpi, nv);
+ else
+ dither = stp_init_dither(image_width, out_width, ydpi / xdpi, 1, nv);
+
+ for (i = 0; i <= NCOLORS; i++)
+ stp_dither_set_black_level(dither, i, 1.0);
+
+ if (use_6color)
+ k_lower = .4 / bits + .1;
+ else
+ k_lower = .25 / bits;
+ if (pt)
+ {
+ k_lower *= pt->k_lower_scale;
+ k_upper = pt->k_upper;
+ }
+ else
+ {
+ k_lower *= .5;
+ k_upper = .5;
+ }
+ stp_dither_set_black_lower(dither, k_lower);
+ stp_dither_set_black_upper(dither, k_upper);
+ stp_dither_set_adaptive_limit(dither, .75);
+
+ if ((inks = canon_inks(caps, res_code, colormode, bits))!=0)
+ {
+ if (inks->c)
+ stp_dither_set_ranges(dither, ECOLOR_C, inks->c->count, inks->c->range,
+ inks->c->density * stp_get_density(nv));
+ if (inks->m)
+ stp_dither_set_ranges(dither, ECOLOR_M, inks->m->count, inks->m->range,
+ inks->m->density * stp_get_density(nv));
+ if (inks->y)
+ stp_dither_set_ranges(dither, ECOLOR_Y, inks->y->count, inks->y->range,
+ inks->y->density * stp_get_density(nv));
+ if (inks->k)
+ stp_dither_set_ranges(dither, ECOLOR_K, inks->k->count, inks->k->range,
+ inks->k->density * stp_get_density(nv));
+ }
+
+ switch (stp_get_image_type(nv))
+ {
+ case IMAGE_LINE_ART:
+ stp_dither_set_ink_spread(dither, 19);
+ break;
+ case IMAGE_SOLID_TONE:
+ stp_dither_set_ink_spread(dither, 15);
+ break;
+ case IMAGE_CONTINUOUS:
+ ink_spread = 13;
+ /*
+ if (ydpi > canon_max_vres(model))
+ ink_spread++;
+ */
+ if (bits > 1)
+ ink_spread++;
+ stp_dither_set_ink_spread(dither, ink_spread);
+ break;
+ }
+ stp_dither_set_density(dither, stp_get_density(nv));
+
+ in = stp_malloc(image_width * image_bpp);
+ out = stp_malloc(image_width * out_bpp * 2);
+
+ errdiv = image_height / out_length;
+ errmod = image_height % out_length;
+ errval = 0;
+ errlast = -1;
+ errline = 0;
+ if (canon_lum_adjustment(printer)) {
+ int k;
+ for (k = 0; k < 49; k++) {
+ have_lum_adjustment= 1;
+ lum_adjustment[k] = canon_lum_adjustment(printer)[k];
+ if(pt)
+ if (pt->lum_adjustment)
+ lum_adjustment[k] *= pt->lum_adjustment[k];
+ }
+ }
+ if (canon_sat_adjustment(printer)) {
+ int k;
+ for (k = 0; k < 49; k++) {
+ have_sat_adjustment= 1;
+ sat_adjustment[k] = canon_sat_adjustment(printer)[k];
+ if(pt)
+ if (pt->sat_adjustment)
+ sat_adjustment[k] *= pt->sat_adjustment[k];
+ }
+ }
+ if (canon_hue_adjustment(printer)) {
+ int k;
+ for (k = 0; k < 49; k++) {
+ have_hue_adjustment= 1;
+ hue_adjustment[k] = canon_hue_adjustment(printer)[k];
+ if(pt)
+ if (pt->hue_adjustment)
+ hue_adjustment[k] += pt->hue_adjustment[k];
+ }
+ }
+
+
+ for (y = 0; y < out_length; y ++)
+ {
+ int duplicate_line = 1;
+ if ((y & 63) == 0)
+ image->note_progress(image, y, out_length);
+
+ if (errline != errlast)
+ {
+ errlast = errline;
+ duplicate_line = 0;
+ if (image->get_row(image, in, errline) != STP_IMAGE_OK)
+ break;
+ (*colorfunc)(nv, in, out, &zero_mask, image_width, image_bpp, cmap,
+ have_hue_adjustment ? hue_adjustment : NULL,
+ have_lum_adjustment ? lum_adjustment : NULL,
+ have_sat_adjustment ? sat_adjustment : NULL);
+ }
+
+ stp_dither(out, y, dither, cyan, lcyan, magenta, lmagenta,
+ yellow, 0, black, duplicate_line, zero_mask);
+
+ canon_write_line(nv, caps, ydpi,
+ black, delay_k,
+ cyan, delay_c,
+ magenta, delay_m,
+ yellow, delay_y,
+ lcyan, delay_lc,
+ lmagenta, delay_lm,
+ lyellow, delay_ly,
+ length, out_width, left, &emptylines, bits);
+
+ canon_advance_buffer(black, buf_length,delay_k);
+ canon_advance_buffer(cyan, buf_length,delay_c);
+ canon_advance_buffer(magenta, buf_length,delay_m);
+ canon_advance_buffer(yellow, buf_length,delay_y);
+ canon_advance_buffer(lcyan, buf_length,delay_lc);
+ canon_advance_buffer(lmagenta,buf_length,delay_lm);
+ canon_advance_buffer(lyellow, buf_length,delay_ly);
+
+ errval += errmod;
+ errline += errdiv;
+ if (errval >= out_length)
+ {
+ errval -= out_length;
+ errline ++;
+ }
+ }
+ image->progress_conclude(image);
+
+ stp_free_dither(dither);
+
+ /*
+ * Flush delayed buffers...
+ */
+
+ if (delay_max) {
+ stp_deprintf(STP_DBG_CANON,"\ncanon: flushing %d possibly delayed buffers\n",
+ delay_max);
+ for (y= 0; y<delay_max; y++) {
+
+ canon_write_line(nv, caps, ydpi,
+ black, delay_k,
+ cyan, delay_c,
+ magenta, delay_m,
+ yellow, delay_y,
+ lcyan, delay_lc,
+ lmagenta, delay_lm,
+ lyellow, delay_ly,
+ length, out_width, left, &emptylines, bits);
+
+ canon_advance_buffer(black, buf_length,delay_k);
+ canon_advance_buffer(cyan, buf_length,delay_c);
+ canon_advance_buffer(magenta, buf_length,delay_m);
+ canon_advance_buffer(yellow, buf_length,delay_y);
+ canon_advance_buffer(lcyan, buf_length,delay_lc);
+ canon_advance_buffer(lmagenta,buf_length,delay_lm);
+ canon_advance_buffer(lyellow, buf_length,delay_ly);
+ }
+ }
+
+ /*
+ * Cleanup...
+ */
+
+ stp_free_lut(nv);
+ stp_free(in);
+ stp_free(out);
+
+ if (black != NULL) stp_free(black);
+ if (cyan != NULL) stp_free(cyan);
+ if (magenta != NULL) stp_free(magenta);
+ if (yellow != NULL) stp_free(yellow);
+ if (lcyan != NULL) stp_free(lcyan);
+ if (lmagenta != NULL) stp_free(lmagenta);
+ if (lyellow != NULL) stp_free(lyellow);
+
+ canon_deinit_printer(nv, &init);
+ stp_free_vars(nv);
+}
+
+const stp_printfuncs_t stp_canon_printfuncs =
+{
+ canon_parameters,
+ stp_default_media_size,
+ canon_imageable_area,
+ canon_limit,
+ canon_print,
+ canon_default_parameters,
+ canon_describe_resolution,
+ stp_verify_printer_params
+};
+
+/*
+ * 'canon_fold_lsb_msb()' fold 2 lines in order lsb/msb
+ */
+
+static void
+canon_fold_2bit(const unsigned char *line,
+ int single_length,
+ unsigned char *outbuf)
+{
+ int i;
+ for (i = 0; i < single_length; i++) {
+ outbuf[0] =
+ ((line[0] & (1 << 7)) >> 1) |
+ ((line[0] & (1 << 6)) >> 2) |
+ ((line[0] & (1 << 5)) >> 3) |
+ ((line[0] & (1 << 4)) >> 4) |
+ ((line[single_length] & (1 << 7)) >> 0) |
+ ((line[single_length] & (1 << 6)) >> 1) |
+ ((line[single_length] & (1 << 5)) >> 2) |
+ ((line[single_length] & (1 << 4)) >> 3);
+ outbuf[1] =
+ ((line[0] & (1 << 3)) << 3) |
+ ((line[0] & (1 << 2)) << 2) |
+ ((line[0] & (1 << 1)) << 1) |
+ ((line[0] & (1 << 0)) << 0) |
+ ((line[single_length] & (1 << 3)) << 4) |
+ ((line[single_length] & (1 << 2)) << 3) |
+ ((line[single_length] & (1 << 1)) << 2) |
+ ((line[single_length] & (1 << 0)) << 1);
+ line++;
+ outbuf += 2;
+ }
+}
+
+#ifndef USE_3BIT_FOLD_TYPE
+#error YOU MUST CHOOSE A VALUE FOR USE_3BIT_FOLD_TYPE
+#endif
+
+#if USE_3BIT_FOLD_TYPE == 333
+
+static void
+canon_fold_3bit(const unsigned char *line,
+ int single_length,
+ unsigned char *outbuf)
+{
+ int i;
+ for (i = 0; i < single_length; i++) {
+ outbuf[0] =
+ ((line[0] & (1 << 7)) >> 2) |
+ ((line[0] & (1 << 6)) >> 4) |
+ ((line[single_length] & (1 << 7)) >> 1) |
+ ((line[single_length] & (1 << 6)) >> 3) |
+ ((line[single_length] & (1 << 5)) >> 5) |
+ ((line[2*single_length] & (1 << 7)) << 0) |
+ ((line[2*single_length] & (1 << 6)) >> 2) |
+ ((line[2*single_length] & (1 << 5)) >> 4);
+ outbuf[1] =
+ ((line[0] & (1 << 5)) << 2) |
+ ((line[0] & (1 << 4)) << 0) |
+ ((line[0] & (1 << 3)) >> 2) |
+ ((line[single_length] & (1 << 4)) << 1) |
+ ((line[single_length] & (1 << 3)) >> 1) |
+ ((line[2*single_length] & (1 << 4)) << 2) |
+ ((line[2*single_length] & (1 << 3)) << 0) |
+ ((line[2*single_length] & (1 << 2)) >> 2);
+ outbuf[2] =
+ ((line[0] & (1 << 2)) << 4) |
+ ((line[0] & (1 << 1)) << 2) |
+ ((line[0] & (1 << 0)) << 0) |
+ ((line[single_length] & (1 << 2)) << 5) |
+ ((line[single_length] & (1 << 1)) << 3) |
+ ((line[single_length] & (1 << 0)) << 1) |
+ ((line[2*single_length] & (1 << 1)) << 4) |
+ ((line[2*single_length] & (1 << 0)) << 2);
+ line++;
+ outbuf += 3;
+ }
+}
+
+#elif USE_3BIT_FOLD_TYPE == 323
+
+static void
+canon_fold_3bit(const unsigned char *line,
+ int single_length,
+ unsigned char *outbuf)
+{
+ unsigned char A0,A1,A2,B0,B1,B2,C0,C1,C2;
+ const unsigned char *last= line+single_length;
+
+ for (; line < last; line+=3, outbuf+=8) {
+
+ A0= line[0]; B0= line[single_length]; C0= line[2*single_length];
+
+ if (line<last-2) {
+ A1= line[1]; B1= line[single_length+1]; C1= line[2*single_length+1];
+ } else {
+ A1= 0; B1= 0; C1= 0;
+ }
+ if (line<last-1) {
+ A2= line[2]; B2= line[single_length+2]; C2= line[2*single_length+2];
+ } else {
+ A2= 0; B2= 0; C2= 0;
+ }
+
+ outbuf[0] =
+ ((C0 & 0x80) >> 0) |
+ ((B0 & 0x80) >> 1) |
+ ((A0 & 0x80) >> 2) |
+ ((B0 & 0x40) >> 2) |
+ ((A0 & 0x40) >> 3) |
+ ((C0 & 0x20) >> 3) |
+ ((B0 & 0x20) >> 4) |
+ ((A0 & 0x20) >> 5);
+ outbuf[1] =
+ ((C0 & 0x10) << 3) |
+ ((B0 & 0x10) << 2) |
+ ((A0 & 0x10) << 1) |
+ ((B0 & 0x08) << 1) |
+ ((A0 & 0x08) << 0) |
+ ((C0 & 0x04) >> 0) |
+ ((B0 & 0x04) >> 1) |
+ ((A0 & 0x04) >> 2);
+ outbuf[2] =
+ ((C0 & 0x02) << 6) |
+ ((B0 & 0x02) << 5) |
+ ((A0 & 0x02) << 4) |
+ ((B0 & 0x01) << 4) |
+ ((A0 & 0x01) << 3) |
+ ((C1 & 0x80) >> 5) |
+ ((B1 & 0x80) >> 6) |
+ ((A1 & 0x80) >> 7);
+ outbuf[3] =
+ ((C1 & 0x40) << 1) |
+ ((B1 & 0x40) << 0) |
+ ((A1 & 0x40) >> 1) |
+ ((B1 & 0x20) >> 1) |
+ ((A1 & 0x20) >> 2) |
+ ((C1 & 0x10) >> 2) |
+ ((B1 & 0x10) >> 3) |
+ ((A1 & 0x10) >> 4);
+ outbuf[4] =
+ ((C1 & 0x08) << 4) |
+ ((B1 & 0x08) << 3) |
+ ((A1 & 0x08) << 2) |
+ ((B1 & 0x04) << 2) |
+ ((A1 & 0x04) << 1) |
+ ((C1 & 0x02) << 1) |
+ ((B1 & 0x02) >> 0) |
+ ((A1 & 0x02) >> 1);
+ outbuf[5] =
+ ((C1 & 0x01) << 7) |
+ ((B1 & 0x01) << 6) |
+ ((A1 & 0x01) << 5) |
+ ((B2 & 0x80) >> 3) |
+ ((A2 & 0x80) >> 4) |
+ ((C2 & 0x40) >> 4) |
+ ((B2 & 0x40) >> 5) |
+ ((A2 & 0x40) >> 6);
+ outbuf[6] =
+ ((C2 & 0x20) << 2) |
+ ((B2 & 0x20) << 1) |
+ ((A2 & 0x20) << 0) |
+ ((B2 & 0x10) >> 0) |
+ ((A2 & 0x10) >> 1) |
+ ((C2 & 0x08) >> 1) |
+ ((B2 & 0x08) >> 2) |
+ ((A2 & 0x08) >> 3);
+ outbuf[7] =
+ ((C2 & 0x04) << 5) |
+ ((B2 & 0x04) << 4) |
+ ((A2 & 0x04) << 3) |
+ ((B2 & 0x02) << 3) |
+ ((A2 & 0x02) << 2) |
+ ((C2 & 0x01) << 2) |
+ ((B2 & 0x01) << 1) |
+ ((A2 & 0x01) << 0);
+ }
+}
+
+#else
+#error 3BIT FOLD TYPE NOT IMPLEMENTED
+#endif
+
+static void
+canon_shift_buffer(unsigned char *line,int length,int bits)
+{
+ int i,j;
+ for (j=0; j<bits; j++) {
+ for (i=length-1; i>0; i--) {
+ line[i]= (line[i] >> 1) | (line[i-1] << 7);
+ }
+ line[0] = line[0] >> 1;
+ }
+}
+
+static void
+canon_shift_buffer2(unsigned char *line,int length,int bits)
+{
+ int i;
+ for (i=length-1; i>0; i--) {
+ line[i]= (line[i] >> bits) | (line[i-1] << (8-bits));
+ }
+ line[0] = line[0] >> bits;
+}
+
+
+/*
+ * 'canon_write()' - Send graphics using TIFF packbits compression.
+ */
+
+static int
+canon_write(const stp_vars_t v, /* I - Print file or command */
+ const canon_cap_t * caps, /* I - Printer model */
+ unsigned char *line, /* I - Output bitmap data */
+ int length, /* I - Length of bitmap data */
+ int coloridx, /* I - Which color */
+ int ydpi, /* I - Vertical resolution */
+ int *empty, /* IO- Preceeding empty lines */
+ int width, /* I - Printed width */
+ int offset, /* I - Offset from left side */
+ int bits)
+{
+ unsigned char
+ comp_buf[COMPBUFWIDTH], /* Compression buffer */
+ in_fold[COMPBUFWIDTH],
+ *in_ptr= line,
+ *comp_ptr, *comp_data;
+ int newlength;
+ int offset2,bitoffset;
+ unsigned char color;
+
+ /* Don't send blank lines... */
+
+ if (line[0] == 0 && memcmp(line, line + 1, length - 1) == 0)
+ return 0;
+
+ /* fold lsb/msb pairs if drop modulation is active */
+
+
+
+ if (bits==2) {
+ memset(in_fold,0,length*2);
+ canon_fold_2bit(line,length,in_fold);
+ in_ptr= in_fold;
+ length= (length*8/4); /* 4 pixels in 8bit */
+ offset= (offset*8/4); /* 4 pixels in 8bit */
+ }
+ if (bits==3) {
+ memset(in_fold,0,length*3);
+ canon_fold_3bit(line,length,in_fold);
+ in_ptr= in_fold;
+ length= (length*8)/3;
+ offset= (offset/3)*8;
+#if 0
+ switch(offset%3){
+ case 0: offset= (offset/3)*8; break;
+ case 1: offset= (offset/3)*8/*+3 CAREFUL! CANNOT SHIFT _AFTER_ RECODING!!*/; break;
+ case 2: offset= (offset/3)*8/*+5 CAREFUL! CANNOT SHIFT _AFTER_ RECODING!!*/; break;
+ }
+#endif
+ }
+ /* pack left border rounded to multiples of 8 dots */
+
+ comp_data= comp_buf;
+ offset2= offset/8;
+ bitoffset= offset%8;
+ while (offset2>0) {
+ unsigned char toffset = offset2 > 128 ? 128 : offset2;
+ comp_data[0] = 1 - toffset;
+ comp_data[1] = 0;
+ comp_data += 2;
+ offset2-= toffset;
+ }
+ if (bitoffset) {
+ if (bitoffset<8)
+ canon_shift_buffer(in_ptr,length,bitoffset);
+ else
+ stp_deprintf(STP_DBG_CANON,"SEVERE BUG IN print-canon.c::canon_write() "
+ "bitoffset=%d!!\n",bitoffset);
+ }
+
+ stp_pack_tiff(in_ptr, length, comp_data, &comp_ptr);
+ newlength= comp_ptr - comp_buf;
+
+ /* send packed empty lines if any */
+
+ if (*empty) {
+ stp_zfwrite("\033\050\145\002\000", 5, 1, v);
+ stp_putc((*empty) >> 8 , v);
+ stp_putc((*empty) & 255, v);
+ *empty= 0;
+ }
+
+ /* Send a line of raster graphics... */
+
+ stp_zfwrite("\033\050\101", 3, 1, v);
+ stp_putc((newlength+1) & 255, v);
+ stp_putc((newlength+1) >> 8, v);
+ color= "CMYKcmy"[coloridx];
+ if (!color) color= 'K';
+ stp_putc(color,v);
+ stp_zfwrite((const char *)comp_buf, newlength, 1, v);
+ stp_putc('\015', v);
+ return 1;
+}
+
+
+static void
+canon_write_line(const stp_vars_t v, /* I - Print file or command */
+ const canon_cap_t * caps, /* I - Printer model */
+ int ydpi, /* I - Vertical resolution */
+ unsigned char *k, /* I - Output bitmap data */
+ int dk, /* I - */
+ unsigned char *c, /* I - Output bitmap data */
+ int dc, /* I - */
+ unsigned char *m, /* I - Output bitmap data */
+ int dm, /* I - */
+ unsigned char *y, /* I - Output bitmap data */
+ int dy, /* I - */
+ unsigned char *lc, /* I - Output bitmap data */
+ int dlc, /* I - */
+ unsigned char *lm, /* I - Output bitmap data */
+ int dlm, /* I - */
+ unsigned char *ly, /* I - Output bitmap data */
+ int dly, /* I - */
+ int l, /* I - Length of bitmap data */
+ int width, /* I - Printed width */
+ int offset, /* I - horizontal offset */
+ int *empty, /* IO- unflushed empty lines */
+ int bits)
+{
+ int written= 0;
+
+ if (k) written+=
+ canon_write(v, caps, k+ dk*l, l, 3, ydpi, empty, width, offset, bits);
+ if (y) written+=
+ canon_write(v, caps, y+ dy*l, l, 2, ydpi, empty, width, offset, bits);
+ if (m) written+=
+ canon_write(v, caps, m+ dm*l, l, 1, ydpi, empty, width, offset, bits);
+ if (c) written+=
+ canon_write(v, caps, c+ dc*l, l, 0, ydpi, empty, width, offset, bits);
+ if (ly) written+=
+ canon_write(v, caps, ly+dly*l, l, 6, ydpi, empty, width, offset, bits);
+ if (lm) written+=
+ canon_write(v, caps, lm+dlm*l, l, 5, ydpi, empty, width, offset, bits);
+ if (lc) written+=
+ canon_write(v, caps, lc+dlc*l, l, 4, ydpi, empty, width, offset, bits);
+
+ if (written||(empty==0))
+ stp_zfwrite("\033\050\145\002\000\000\001", 7, 1, v);
+ else
+ (*empty)+= 1;
+}