#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
#include <ctype.h>
#if (0)
#define EXPERIMENTAL_STUFF 0
#endif
#define MAX_CARRIAGE_WIDTH 13
#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
typedef struct canon_dot_sizes
{
int dot_r11;
int dot_r22;
int dot_r33;
int dot_r43;
int dot_r44;
int dot_r55;
} canon_dot_size_t;
typedef struct canon_densities
{
double d_r11;
double d_r22;
double d_r33;
double d_r43;
double d_r44;
double d_r55;
} canon_densities_t;
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;
typedef struct canon_variable_inklist
{
const int bits;
const int colors;
const canon_variable_inkset_t *r11;
const canon_variable_inkset_t *r22;
const canon_variable_inkset_t *r33;
const canon_variable_inkset_t *r43;
const canon_variable_inkset_t *r44;
const canon_variable_inkset_t *r55;
} canon_variable_inklist_t;
#ifdef EXPERIMENTAL_STUFF
typedef struct canon_variable_printmode
{
const int xdpi;
const int ydpi;
const int bits;
const int printhead;
const int quality;
const double density;
const double gamma;
const canon_variable_inkset_t *inks;
const double *lum_adjustment;
const double *hue_adjustment;
const double *sat_adjustment;
} canon_variable_printmode_t;
#endif
static const stp_simple_dither_range_t canon_dither_ranges_Cc_1bit[] =
{
{ 0.25, 0x1, 1, 1 },
{ 1.0, 0x1, 0, 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
};
static const stp_simple_dither_range_t canon_dither_ranges_Mm_1bit[] =
{
{ 0.26, 0x1, 1, 1 },
{ 1.0, 0x1, 0, 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
};
static const stp_simple_dither_range_t canon_dither_ranges_X_2bit[] =
{
{ 0.45, 0x1, 0, 1 },
{ 0.68, 0x2, 0, 2 },
{ 1.0, 0x3, 0, 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
};
static const stp_simple_dither_range_t canon_dither_ranges_Xx_2bit[] =
{
{ 0.15, 0x1, 1, 1 },
{ 0.227, 0x2, 1, 2 },
{ 0.45, 0x1, 0, 1 },
{ 0.68, 0x2, 0, 2 },
{ 1.0, 0x3, 0, 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
};
static const stp_simple_dither_range_t canon_dither_ranges_X_3bit[] =
{
{ 0.45, 0x1, 0, 1 },
{ 0.55, 0x2, 0, 2 },
{ 0.66, 0x3, 0, 3 },
{ 0.77, 0x4, 0, 4 },
{ 0.88, 0x5, 0, 5 },
{ 1.0, 0x6, 0, 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
};
static const stp_simple_dither_range_t canon_dither_ranges_Xx_3bit[] =
{
{ 0.15, 0x1, 1, 1 },
{ 0.227, 0x2, 1, 2 },
{ 0.333, 0x3, 1, 3 },
{ 0.45, 0x1, 0, 1 },
{ 0.55, 0x2, 0, 2 },
{ 0.66, 0x3, 0, 3 },
{ 0.77, 0x4, 0, 4 },
{ 0.88, 0x5, 0, 5 },
{ 1.0, 0x6, 0, 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
};
static const canon_variable_inkset_t ci_CMY_1 =
{
NULL,
NULL,
NULL,
NULL
};
static const canon_variable_inkset_t ci_CMY_2 =
{
&canon_ink_X_2bit,
&canon_ink_X_2bit,
&canon_ink_X_2bit,
NULL
};
static const canon_variable_inkset_t ci_CMYK_1 =
{
NULL,
NULL,
NULL,
NULL
};
static const canon_variable_inkset_t ci_CcMmYK_1 =
{
&canon_ink_Cc_1bit,
&canon_ink_Mm_1bit,
NULL,
NULL
};
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
};
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
};
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
};
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;
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,
},
};
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,
},
};
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,
},
};
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, 1.1, 1.2, 1.3, 1.4, 1.5, 1.6, 1.7,
1.8, 1.9, 1.9, 1.9, 1.7, 1.5, 1.3, 1.1,
1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0,
1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0,
1.0, 1.0, 1.0, 1.1, 1.2, 1.3, 1.4, 1.5,
1.5, 1.4, 1.3, 1.2, 1.1, 1.0, 1.0, 1.0,
1.0
};
static const double standard_lum_adjustment[49] =
{
0.50, 0.6, 0.7, 0.8, 0.9, 0.86, 0.82, 0.79,
0.78, 0.8, 0.83, 0.87, 0.9, 0.95, 1.05, 1.15,
1.3, 1.25, 1.2, 1.15, 1.12, 1.09, 1.06, 1.03,
1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0,
1.0, 0.9, 0.8, 0.7, 0.65, 0.6, 0.55, 0.52,
0.48, 0.47, 0.47, 0.49, 0.49, 0.49, 0.52, 0.51,
0.50
};
static const double standard_hue_adjustment[49] =
{
0.00, 0.05, 0.04, 0.01, -.03, -.10, -.18, -.26,
-.35, -.43, -.40, -.32, -.25, -.18, -.10, -.07,
0.00, -.04, -.09, -.13, -.18, -.23, -.27, -.31,
-.35, -.38, -.30, -.23, -.15, -.08, 0.00, -.02,
0.00, 0.08, 0.10, 0.08, 0.05, 0.03, -.03, -.12,
-.20, 0.17, -.20, -.17, -.15, -.12, -.10, -.08,
0.00,
};
static const double plain_paper_lum_adjustment[49] =
{
1.2, 1.22, 1.28, 1.34, 1.39, 1.42, 1.45, 1.48,
1.5, 1.4, 1.3, 1.25, 1.2, 1.1, 1.05, 1.05,
1.05, 1.05, 1.05, 1.05, 1.05, 1.05, 1.05, 1.05,
1.05, 1.05, 1.05, 1.1, 1.1, 1.1, 1.1, 1.1,
1.1, 1.15, 1.3, 1.45, 1.6, 1.75, 1.9, 2.0,
2.1, 2.0, 1.8, 1.7, 1.6, 1.5, 1.4, 1.3,
1.2
};
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;
int model_id;
int max_width;
int max_height;
int base_res;
int max_xdpi;
int max_ydpi;
int max_quality;
int border_left;
int border_right;
int border_top;
int border_bottom;
int inks;
int slots;
unsigned long features;
#ifdef EXPERIMENTAL_STUFF
const canon_variable_printmode_t *printmodes;
int printmodes_cnt;
#else
int dummy;
const canon_dot_size_t dot_sizes;
const canon_densities_t densities;
const canon_variable_inklist_t *inxs;
int inxs_cnt;
#endif
const double *lum_adjustment;
const double *hue_adjustment;
const double *sat_adjustment;
} canon_cap_t;
typedef struct canon_privdata_weave {
int bidirectional;
int direction;
} canon_privdata_weave;
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);
#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)
#define CANON_SLOT_ASF1 1
#define CANON_SLOT_ASF2 2
#define CANON_SLOT_MAN1 4
#define CANON_SLOT_MAN2 8
#define CANON_CAP_DMT 0x01ul
#define CANON_CAP_MSB_FIRST 0x02ul
#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_rr 0x4000ul
#define CANON_CAP_WEAVE 0x8000ul
#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
#define BC_11 CANON_INK_CMYK
#define BC_12 CANON_INK_CMYK
#define BC_20 CANON_INK_K
#define BC_21 CANON_INK_CMYK
#define BC_22 CANON_INK_CMYK
#define BC_29 0
#define BC_3031 CANON_INK_CMYK
#define BC_3231 CANON_INK_CcMmYK
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[] =
{
{ -1, 8*72,11*72,180,180,20,20,20,20, CANON_INK_K, CANON_SLOT_ASF1, 0 },
{
4202, 3,
618, 936,
180, 2880, 2880, 4,
10, 10, 9, 20,
CANON_INK_CMYK | CANON_INK_CMY | CANON_INK_K,
CANON_SLOT_ASF1,
CANON_CAP_STD1 | CANON_CAP_rr | CANON_CAP_WEAVE,
CANON_MODES(canon_nomodes),
#ifndef EXPERIMENTAL_STUFF
{-1, 0, 0, 0, 0, -1},
{ 1, 2, 1, 0.5, 0.3, 0.2},
CANON_INK(canon_ink_standard),
#endif
standard_lum_adjustment,
standard_hue_adjustment,
standard_sat_adjustment
},
{
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},
{1,1,1,1,1,1},
CANON_INK(canon_ink_standard),
#endif
standard_lum_adjustment,
standard_hue_adjustment,
standard_sat_adjustment
},
{
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},
{1,1,1,1,1,1},
CANON_INK(canon_ink_standard),
#endif
standard_lum_adjustment,
standard_hue_adjustment,
standard_sat_adjustment
},
{
4300, 1,
618, 936,
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},
{1,1,1,1,1,1},
CANON_INK(canon_ink_standard),
#endif
standard_lum_adjustment,
standard_hue_adjustment,
standard_sat_adjustment
},
{
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},
{1,1,1,1,1,1},
CANON_INK(canon_ink_standard),
#endif
standard_lum_adjustment,
standard_hue_adjustment,
standard_sat_adjustment
},
{
6000, 3,
618, 936,
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},
{1,1.8,1,0.5,1,1},
CANON_INK(canon_ink_standardphoto),
#endif
standard_lum_adjustment,
standard_hue_adjustment,
standard_sat_adjustment
},
{
6200, 3,
618, 936,
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},
{0,1.8,1,.5,0,0},
CANON_INK(canon_ink_standardphoto),
#endif
standard_lum_adjustment,
standard_hue_adjustment,
standard_sat_adjustment
},
{
6500, 3,
842, 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},
{0,1.8,1,.5,0,0},
CANON_INK(canon_ink_standardphoto),
#endif
standard_lum_adjustment,
standard_hue_adjustment,
standard_sat_adjustment
},
{
8200, 3,
842, 17*72,
150, 1200,1200, 4,
11, 9, 10, 18,
CANON_INK_CMYK,
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},
{1,1,1,1,1,1},
CANON_INK(canon_ink_superphoto),
#endif
standard_lum_adjustment,
standard_hue_adjustment,
standard_sat_adjustment
},
{
210, 1,
618, 936,
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},
{1,1,1,1,1,1},
CANON_INK(canon_ink_standard),
#endif
standard_lum_adjustment,
standard_hue_adjustment,
standard_sat_adjustment
},
{
240, 1,
618, 936,
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},
{1,1,1,1,1,1},
CANON_INK(canon_ink_oldphoto),
#endif
standard_lum_adjustment,
standard_hue_adjustment,
standard_sat_adjustment
},
{
250, 1,
618, 936,
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},
{1,1,1,1,1,1},
CANON_INK(canon_ink_oldphoto),
#endif
standard_lum_adjustment,
standard_hue_adjustment,
standard_sat_adjustment
},
{
1000, 1,
842, 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},
{1,1,1,1,1,1},
CANON_INK(canon_ink_oldphoto),
#endif
standard_lum_adjustment,
standard_hue_adjustment,
standard_sat_adjustment
},
{
2000, 1,
842, 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},
{1,1,1,1,1,1},
CANON_INK(canon_ink_standard),
#endif
standard_lum_adjustment,
standard_hue_adjustment,
standard_sat_adjustment
},
{
3000, 3,
842, 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,
CANON_MODES(canon_nomodes),
#ifndef EXPERIMENTAL_STUFF
{-1,1,0,0,-1,-1},
{1,1,1,1,1,1},
CANON_INK(canon_ink_standard),
#endif
standard_lum_adjustment,
standard_hue_adjustment,
standard_sat_adjustment
},
{
6100, 3,
842, 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},
{1,1,1,1,1,1},
CANON_INK(canon_ink_standard),
#endif
standard_lum_adjustment,
standard_hue_adjustment,
standard_sat_adjustment
},
{
7000, 3,
842, 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},
{1,3.5,1.8,1,1,1},
CANON_INK(canon_ink_standard),
#endif
standard_lum_adjustment,
standard_hue_adjustment,
standard_sat_adjustment
},
{
7100, 3,
842, 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},
{1,1,1,1,1,1},
CANON_INK(canon_ink_standard),
#endif
standard_lum_adjustment,
standard_hue_adjustment,
standard_sat_adjustment
},
{
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},
{1,1,1,1,1,1},
CANON_INK(canon_ink_standard),
#endif
standard_lum_adjustment,
standard_hue_adjustment,
standard_sat_adjustment
},
{
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},
{1,1,1,1,1,1},
CANON_INK(canon_ink_standard),
#endif
standard_lum_adjustment,
standard_hue_adjustment,
standard_sat_adjustment
},
{
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},
{1,1,1,1,1,1},
CANON_INK(canon_ink_standard),
#endif
standard_lum_adjustment,
standard_hue_adjustment,
standard_sat_adjustment
},
{
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},
{1,1,1,1,1,1},
CANON_INK(canon_ink_standard),
#endif
standard_lum_adjustment,
standard_hue_adjustment,
standard_sat_adjustment
},
};
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 void canon_advance_paper(stp_vars_t, int);
static const int paper_type_count = sizeof(canon_paper_list) / sizeof(paper_t);
static void canon_flush_pass(stp_softweave_t *sw, int passno, int model, int width,
int hoffset, int ydpi, int xdpi, int physical_xdpi,
int vertical_subpass);
static const paper_t *
get_media_type(const char *name)
{
int i;
for (i = 0; i < paper_type_count; i++)
{
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)
{
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)
{
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)
{
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);
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;
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;
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]);
}
}
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 const stp_param_t media_sources[] =
{
{ "Auto", N_ ("Auto Sheet Feeder") },
{ "Manual", N_ ("Manual with Pause") },
{ "ManualNP", N_ ("Manual without Pause") }
};
static stp_param_t *
canon_parameters(const stp_printer_t printer,
const char *ppd_file,
const char *name,
int *count)
{
int i;
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_zalloc(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_zalloc(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_zalloc(sizeof(stp_param_t) * 5);
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_zalloc(*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 = sizeof(media_sources) / sizeof(media_sources[0]);
valptrs = stp_zalloc(*count * sizeof(stp_param_t));
for (i = 0; i < *count; i ++)
{
valptrs[i].name = c_strdup(media_sources[i].name);
valptrs[i].text = c_strdup(_(media_sources[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)
{
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);
}
static void
canon_imageable_area(const stp_printer_t printer,
const stp_vars_t v,
int *left,
int *right,
int *bottom,
int *top)
{
int width, length;
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,
const stp_vars_t v,
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;
}
static void
canon_cmd(const stp_vars_t v,
const char *ini,
const char cmd,
int num,
...
)
{
unsigned char *buffer = stp_zalloc(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))
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);
}
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);
}
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);
}
static void
canon_init_setColor(const stp_vars_t v, canon_init_t *init)
{
unsigned char
numargs, arg_63[6];
if (!(init->caps->features & CANON_CAP_c))
return;
numargs = 3;
arg_63[0] = init->caps->model_id << 4;
switch ( init->caps->model_id ) {
case 0:
break;
case 1:
if (init->output_type==OUTPUT_GRAY || init->output_type == OUTPUT_MONOCHROME)
arg_63[0]|= 0x01;
arg_63[1] = ((init->pt ? init->pt->media_code : 0) << 4)
+ 1;
canon_cmd(v,ESC28,0x63, 2, arg_63[0], arg_63[1]);
break;
case 2:
break;
case 3:
if (init->output_type==OUTPUT_GRAY || init->output_type == OUTPUT_MONOCHROME)
arg_63[0]|= 0x01;
arg_63[1] = (init->pt) ? init->pt->media_code : 0;
if (init->caps->model == 4202)
{
if ((init->xdpi == 720) && (init->ydpi == 720 ))
arg_63[2] = 1;
else
arg_63[2] = 4;
if ( (init->xdpi > 360) || (init->ydpi > 360) )
{
numargs = 6;
arg_63[3] = 0x10; arg_63[4] = 6; arg_63[5] = 8;
if (init->output_type==OUTPUT_GRAY || init->output_type == OUTPUT_MONOCHROME)
arg_63[4] = 1;
}
}
else
arg_63[2] = 2;
stp_zprintf(v, "\033\050\143");
stp_putc((numargs & 255),v);
stp_putc((numargs >> 8 ),v);
stp_zfwrite((const char *)arg_63, numargs, 1, v);
break;
}
return;
}
static void
canon_init_setResolution(const stp_vars_t v, canon_init_t *init)
{
if (!(init->caps->features & CANON_CAP_d))
return;
if (init->caps->model != 4202 || (init->xdpi < 360))
canon_cmd(v,ESC28,0x64, 4,
(init->ydpi >> 8 ), (init->ydpi & 255),
(init->xdpi >> 8 ), (init->xdpi & 255));
else
if (init->xdpi < 2880)
canon_cmd(v,ESC28,0x64, 4,
(720 >> 8), (720 & 255),
(720 >> 8), (720 & 255));
else
canon_cmd(v,ESC28,0x64, 4,
(720 >> 8), (720 & 255),
(2880 >> 8), (2880 & 255));
}
static void
canon_init_setPageMargins(const stp_vars_t v, canon_init_t *init)
{
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));
}
static void
canon_init_setTray(const stp_vars_t v, canon_init_t *init)
{
unsigned char
arg_6c_1 = 0x00,
arg_6c_2 = 0x00;
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);
}
static void
canon_init_setPrintMode(const stp_vars_t v, canon_init_t *init)
{
unsigned char
arg_6d_1 = 0x03,
arg_6d_2 = 0x00,
arg_6d_3 = 0x00,
arg_6d_a = 0x03,
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 || init->caps->model==4202)
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);
}
static void
canon_init_setPageMargins2(const stp_vars_t v, canon_init_t *init)
{
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);
}
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);
}
static void
canon_init_setX72(const stp_vars_t v, canon_init_t *init)
{
if ( !( (init->caps->features & CANON_CAP_r)
|| (init->caps->features & CANON_CAP_rr) ) )
return;
if ( (init->caps->features & CANON_CAP_r)
|| (init->caps->features & CANON_CAP_rr) )
canon_cmd(v,ESC28,0x72, 1, 0x61);
if (init->caps->features & CANON_CAP_rr)
canon_cmd(v,ESC28,0x72, 3, 0x63, 1, 0);
}
static void
canon_set_X72(const stp_vars_t v, int x72arg)
{
canon_cmd(v,ESC28,0x72, 3, 0x63, x72arg, 0);
}
static void
canon_init_setImage(const stp_vars_t v, canon_init_t *init)
{
unsigned char
arg_74_1 = 0x01,
arg_74_2 = 0x00,
arg_74_3 = 0x01;
if (!(init->caps->features & CANON_CAP_t))
return;
if (init->caps->model==4202)
{
canon_cmd(v,ESC28,0x74, 30, 0x80, 4, 1, 1, 0, 2, 1, 0, 2, 1, 0, 2, 1, 0, 2,\
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
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;
}
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;
canon_init_resetPrinter(v,init);
canon_init_setPageMode(v,init);
canon_init_setDataCompression(v,init);
canon_init_setPageID(v,init);
canon_init_setPrintMode(v,init);
canon_init_setResolution(v,init);
canon_init_setImage(v,init);
canon_init_setColor(v,init);
canon_init_setPageMargins(v,init);
canon_init_setPageMargins2(v,init);
canon_init_setTray(v,init);
canon_init_setX72(v,init);
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)
{
stp_putc(0x0c,v);
canon_cmd(v,ESC28,0x62,1,0);
if (init->caps->features & CANON_CAP_a)
canon_cmd(v,ESC28,0x61, 1, 0);
}
static int
canon_end_job(const stp_printer_t printer,
stp_image_t *image,
const stp_vars_t v)
{
if (!stp_get_verified(v))
return 0;
if (stp_get_job_mode(v) != STP_JOB_MODE_JOB)
return 0;
canon_cmd(v,ESC40,0,0);
return 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);
}
static void
canon_print(const stp_printer_t printer,
stp_image_t *image,
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;
int xdpi, ydpi;
int n;
unsigned short *out;
unsigned char *in;
unsigned char *cols[7];
int delay_k,
delay_c,
delay_m,
delay_y,
delay_lc,
delay_lm,
delay_ly,
delay_max;
int page_left,
page_right,
page_top,
page_bottom,
page_width,
page_height,
page_true_height,
out_width,
out_length,
out_bpp,
length,
buf_length,
errdiv,
errmod,
errval,
errline,
errlast;
stp_convert_t colorfunc = 0;
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;
stp_dither_data_t *dt;
void * weave = NULL;
int total_channels;
int physical_xdpi = 720, nozzle_ydpi = 360, stepper_ydpi = 720;
int nozzles = 24;
int nozzle_separation, horizontal_passes;
int vertical_passes, vertical_oversample;
int * head_offset = NULL;
canon_privdata_weave privdata;
if (!stp_get_verified(nv))
{
stp_eprintf(nv, "Print options not verified; cannot print.\n");
return;
}
PUT("top ",top,72);
PUT("left ",left,72);
image->init(image);
image_height = image->height(image);
image_width = image->width(image);
image_bpp = image->bpp(image);
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);
colorfunc = stp_choose_colorfunc(output_type, image_bpp, cmap, &out_bpp, nv);
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);
#ifndef EXPERIMENTAL_STUFF
stp_deprintf(STP_DBG_CANON," rescode =0x%x\n",canon_res_code(caps,xdpi,ydpi));
res_code= canon_res_code(caps,xdpi,ydpi);
#endif
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");
}
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);
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);
bits= init.bits;
xdpi= init.xdpi;
ydpi= init.ydpi;
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) && (model != 4202)){
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 if (model ==4202 ){
delay_k= 0;
delay_c= 0x30;
delay_m= 0x50;
delay_y= 0x70;
delay_lc= 0;
delay_lm= 0;
delay_ly= 0;
delay_max= 0x70;
stp_deprintf(STP_DBG_CANON,"canon: delay for S200 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");
}
length = (out_width + 7) / 8;
buf_length= length*bits;
stp_deprintf(STP_DBG_CANON,"canon: buflength is %d!\n",buf_length);
for (i=0; i<=6; i++)
cols[i] = NULL;
if (colormode==COLOR_MONOCHROME)
cols[0] = stp_zalloc(buf_length*(delay_k+1));
else {
cols[1] = stp_zalloc(buf_length*(delay_c+1));
cols[2] = stp_zalloc(buf_length*(delay_m+1));
cols[3] = stp_zalloc(buf_length*(delay_y+1));
if (colormode!=COLOR_CMY)
cols[0] = stp_zalloc(buf_length*(delay_k+1));
if (colormode==COLOR_CCMMYK || colormode==COLOR_CCMMYYK) {
use_6color= 1;
cols[4] = stp_zalloc(buf_length*(delay_lc+1));
cols[5] = stp_zalloc(buf_length*(delay_lm+1));
if (colormode==CANON_INK_CcMmYyK)
cols[6] = stp_zalloc(buf_length*(delay_lc+1));
}
}
stp_deprintf(STP_DBG_CANON,"canon: driver will use colors %s%s%s%s%s%s\n",
cols[1] ? "C" : "", cols[4] ? "c" : "", cols[2] ? "M" : "",
cols[5] ? "m" : "", cols[3] ? "Y" : "", cols[0] ? "K" : "");
stp_deprintf(STP_DBG_CANON,"density is %f\n",stp_get_density(nv));
if (pt)
stp_set_density(nv, stp_get_density(nv) * pt->base_density);
else
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));
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);
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 (bits > 1)
ink_spread++;
stp_dither_set_ink_spread(dither, ink_spread);
break;
}
stp_dither_set_density(dither, stp_get_density(nv));
if (init.caps->features & CANON_CAP_WEAVE && xdpi > 360)
{
stepper_ydpi = 720;
nozzle_ydpi = 360;
if (xdpi == 2880)
physical_xdpi = 2880;
else
physical_xdpi = 720;
total_channels = 4;
head_offset = stp_zalloc(sizeof(int) * total_channels);
memset(head_offset, 0, sizeof(head_offset));
if ( colormode == COLOR_MONOCHROME )
nozzles = 64;
else
nozzles = 24;
if (colormode == COLOR_MONOCHROME)
{
head_offset[0] = 0;
head_offset[1] = 144 ;
head_offset[2] = 144 + 64;
head_offset[3] = 144 + 64 + 64;
top += 11;
}
else if (colormode == COLOR_CMYK)
{
head_offset[0] = 0;
head_offset[1] = 144 ;
head_offset[2] = 144 + 64;
head_offset[3] = 144 + 64 + 64;
top += 5;
}
else
{
head_offset[0] = 0;
head_offset[1] = 0 ;
head_offset[2] = 64;
head_offset[3] = 128;
top += 18;
}
nozzle_separation = stepper_ydpi / nozzle_ydpi;
horizontal_passes = xdpi / physical_xdpi;
vertical_passes = 1;
vertical_oversample = ydpi / stepper_ydpi;
privdata.bidirectional = 1;
privdata.direction = 1;
stp_set_driver_data(nv, &privdata);
stp_deprintf(STP_DBG_CANON,"canon: initializing weaving: nozzles=%d, nozzle_separation=%d, "
"horizontal_passes=%d, vertical_passes=%d,vertical_oversample=%d, total_channels=%d \n",
nozzles, nozzle_separation,
horizontal_passes, vertical_passes,
vertical_oversample, total_channels);
weave = stp_initialize_weave(nozzles, nozzle_separation,
horizontal_passes, vertical_passes,
vertical_oversample, total_channels,
1,
out_width, out_length,
top * stepper_ydpi / 72,
page_height * stepper_ydpi / 72,
1, head_offset, nv,
canon_flush_pass,
stp_fill_uncompressed,
stp_pack_uncompressed,
stp_compute_uncompressed_linewidth);
}
in = stp_zalloc(image_width * image_bpp);
out = stp_zalloc(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];
}
}
dt = stp_create_dither_data();
stp_add_channel(dt, cols[0], ECOLOR_K, 0);
stp_add_channel(dt, cols[1], ECOLOR_C, 0);
stp_add_channel(dt, cols[4], ECOLOR_C, 1);
stp_add_channel(dt, cols[2], ECOLOR_M, 0);
stp_add_channel(dt, cols[5], ECOLOR_M, 1);
stp_add_channel(dt, cols[3], ECOLOR_Y, 0);
stp_add_channel(dt, cols[6], ECOLOR_Y, 1);
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, dt, duplicate_line, zero_mask);
#if 0
stp_deprintf(STP_DBG_CANON,"dithering done, length=%d, out_width=%d \n"
"black=%p; cyan=%p; magenta=%p; yellow=%p \n",
length, out_width, cols[0], cols[1], cols[2], cols[3]);
dump_area(cols[0], length, "black:");
dump_area(cols[1], length, "cyan:");
dump_area(cols[2], length, "magenta:");
dump_area(cols[3], length, "yellow:");
#endif
if (init.caps->features & CANON_CAP_WEAVE && xdpi > 360)
{
stp_write_weave(weave, length, stepper_ydpi, model, out_width,
left * physical_xdpi / xdpi,
xdpi, physical_xdpi, cols);
}
else
{
canon_write_line(nv, caps, ydpi, cols[0], delay_k,
cols[1], delay_c,
cols[2], delay_m,
cols[3], delay_y,
cols[4], delay_lc,
cols[5], delay_lm,
cols[6], delay_ly,
length, out_width, left, &emptylines, bits);
canon_advance_buffer(cols[0], buf_length,delay_k);
canon_advance_buffer(cols[1], buf_length,delay_c);
canon_advance_buffer(cols[2], buf_length,delay_m);
canon_advance_buffer(cols[3], buf_length,delay_y);
canon_advance_buffer(cols[4], buf_length,delay_lc);
canon_advance_buffer(cols[5], buf_length,delay_lm);
canon_advance_buffer(cols[6], buf_length,delay_ly);
}
errval += errmod;
errline += errdiv;
if (errval >= out_length)
{
errval -= out_length;
errline ++;
}
}
if (init.caps->features & CANON_CAP_WEAVE && xdpi > 360)
{
stp_flush_all(weave, model, out_width,
left * physical_xdpi / xdpi,
ydpi, xdpi, physical_xdpi);
canon_advance_paper(nv, 5);
}
else
{
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, cols[0], delay_k,
cols[1], delay_c,
cols[2], delay_m,
cols[3], delay_y,
cols[4], delay_lc,
cols[5], delay_lm,
cols[6], delay_ly,
length, out_width, left, &emptylines, bits);
canon_advance_buffer(cols[0], buf_length,delay_k);
canon_advance_buffer(cols[1], buf_length,delay_c);
canon_advance_buffer(cols[2], buf_length,delay_m);
canon_advance_buffer(cols[3], buf_length,delay_y);
canon_advance_buffer(cols[4], buf_length,delay_lc);
canon_advance_buffer(cols[5], buf_length,delay_lm);
canon_advance_buffer(cols[6], buf_length,delay_ly);
}
}
}
image->progress_conclude(image);
stp_free_dither_data(dt);
stp_free_dither(dither);
stp_free_lut(nv);
stp_free(in);
stp_free(out);
if (weave != NULL) stp_destroy_weave(weave);
for (y = 0; y < 6; y++)
if ( cols[y] != NULL ) stp_free(cols[y]);
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,
stp_start_job,
canon_end_job
};
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 int
canon_write(const stp_vars_t v,
const canon_cap_t *caps,
unsigned char *line,
int length,
int coloridx,
int ydpi,
int *empty,
int width,
int offset,
int bits)
{
unsigned char
comp_buf[COMPBUFWIDTH],
in_fold[COMPBUFWIDTH],
*in_ptr= line,
*comp_ptr, *comp_data;
int newlength;
int offset2,bitoffset;
unsigned char color;
if (line[0] == 0 && memcmp(line, line + 1, length - 1) == 0)
return 0;
if (bits==2) {
memset(in_fold,0,length*2);
canon_fold_2bit(line,length,in_fold);
in_ptr= in_fold;
length= (length*8/4);
offset= (offset*8/4);
}
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; break;
case 2: offset= (offset/3)*8; break;
}
#endif
}
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;
if (*empty) {
stp_zfwrite("\033\050\145\002\000", 5, 1, v);
stp_putc((*empty) >> 8 , v);
stp_putc((*empty) & 255, v);
*empty= 0;
}
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,
const canon_cap_t * caps,
int ydpi,
unsigned char *k,
int dk,
unsigned char *c,
int dc,
unsigned char *m,
int dm,
unsigned char *y,
int dy,
unsigned char *lc,
int dlc,
unsigned char *lm,
int dlm,
unsigned char *ly,
int dly,
int l,
int width,
int offset,
int *empty,
int bits)
{
int written= 0;
stp_deprintf(STP_DBG_CANON,"canon_write_line: length=%d, width=%d, (hor.)offset=%d\n",
l, width, offset);
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;
}
static void
canon_advance_paper(stp_vars_t v, int advance)
{
if ( advance > 0 )
{
int a0, a1, a2, a3;
stp_deprintf(STP_DBG_CANON,"canon_advance_paper: advance= %d\n", advance);
a0 = advance & 0xff;
a1 = (advance >> 8) & 0xff;
a2 = (advance >> 16) & 0xff;
a3 = (advance >> 24) & 0xff;
stp_zprintf(v, "\033(e%c%c%c%c%c%c", 4, 0, a3, a2, a1, a0);
}
}
static void
canon_flush_pass(stp_softweave_t *sw, int passno, int model, int width,
int hoffset, int ydpi, int xdpi, int physical_xdpi,
int vertical_subpass)
{
const stp_vars_t nv = (sw->v);
stp_lineoff_t *lineoffs = stp_get_lineoffsets_by_pass(sw, passno);
stp_lineactive_t *lineactive = stp_get_lineactive_by_pass(sw, passno);
const stp_linebufs_t *bufs = stp_get_linebases_by_pass(sw, passno);
stp_pass_t *pass = stp_get_pass_by_pass(sw, passno);
stp_linecount_t *linecount = stp_get_linecount_by_pass(sw, passno);
canon_privdata_weave *privdata_weave = stp_get_driver_data(nv);
int papershift = (pass->logicalpassstart - sw->last_pass_offset);
int color, line, empty = 0, written = 0, linelength = 0, lines = 0;
int idx[4]={3, 0, 1, 2};
stp_deprintf(STP_DBG_CANON,"canon_flush_pass: pass=%d, papershift=%d\n", passno, papershift);
for ( color = 0; color < sw->ncolors; color++ )
{
if ( linecount[0].v[color] > lines ) lines = linecount[0].v[color];
}
for ( line = 0; line < lines; line++ )
{
stp_deprintf(STP_DBG_CANON,"canon_flush_pass: line=%d, written=%d, empty=%d \n",
line, written, empty);
if ( written > 0 )
canon_cmd(nv,ESC28,0x65, 2, 0, 1);
written = 0;
for ( color = 0; color < sw->ncolors; color++ )
{
if ( line < linecount[0].v[color] )
{
if ( lineactive[0].v[color] > 0 )
{
linelength = lineoffs[0].v[color] / linecount[0].v[color];
if ( pass->logicalpassstart > sw->last_pass_offset)
{
canon_advance_paper(nv, papershift);
sw->last_pass_offset = pass->logicalpassstart;
if (privdata_weave->bidirectional)
{
privdata_weave->direction = (privdata_weave->direction +1) & 1;
canon_set_X72(nv, privdata_weave->direction);
}
}
written += canon_write(nv, NULL,
(unsigned char *)(bufs[0].v[color] + line * linelength),
linelength, idx[color], 0, &empty, 0, hoffset, sw->bitwidth);
}
}
}
if ( written == 0 )
empty += 1;
}
for ( color = 0; color < sw->ncolors; color++ )
{
lineoffs[0].v[color] = 0;
linecount[0].v[color] = 0;
}
sw->last_pass = pass->pass;
pass->pass = -1;
}