home *** CD-ROM | disk | FTP | other *** search
- /*
- * "$Id: print-canon.c,v 1.6 2000/11/07 23:23:02 mitch Exp $"
- *
- * Print plug-in CANON BJL driver for the GIMP.
- *
- * Copyright 1997-2000 Michael Sweet (mike@easysw.com) and
- * Robert Krawitz (rlk@alum.mit.edu)
- *
- * 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.
- */
-
-
- /* TODO-LIST
- *
- * * implement the left border
- *
- */
-
- #include <stdarg.h>
- #include "print.h"
-
- /*
- * Local functions...
- */
-
- typedef struct {
- int model;
- int max_width; /* maximum printable paper size */
- int max_height;
- int max_xdpi;
- int max_ydpi;
- int max_quality;
- int border_left;
- int border_right;
- int border_top;
- int border_bottom;
- int inks; /* installable cartridges (CANON_INK_*) */
- int slots; /* available paperslots */
- int features; /* special bjl settings */
- } canon_cap_t;
-
- static void canon_write_line(FILE *, 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);
-
- #define PHYSICAL_BPI 1440
- #define MAX_OVERSAMPLED 4
- #define MAX_BPP 2
- #define BITS_PER_BYTE 8
- #define COMPBUFWIDTH (PHYSICAL_BPI * MAX_OVERSAMPLED * MAX_BPP * \
- MAX_CARRIAGE_WIDTH / BITS_PER_BYTE)
-
-
- /* 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_CcMmYy 16
- #define CANON_INK_CcMmYyK 32
-
- #define CANON_INK_BLACK_MASK (CANON_INK_K|CANON_INK_CMYK|\
- CANON_INK_CcMmYK|CANON_INK_CcMmYyK)
-
- #define CANON_INK_PHOTO_MASK (CANON_INK_CcMmYy|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 1<<0 /* Drop Modulation Technology */
- #define CANON_CAP_MSB_FIRST 1<<1 /* how to send data */
- #define CANON_CAP_CMD61 1<<2 /* uses command #0x61 */
- #define CANON_CAP_CMD6d 1<<3 /* uses command #0x6d */
- #define CANON_CAP_CMD70 1<<4 /* uses command #0x70 */
- #define CANON_CAP_CMD72 1<<5 /* uses command #0x72 */
-
-
- static 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 models */
-
- { /* Canon BJC 4300 */
- 4300,
- 618, 936, /* 8.58" x 13 " */
- 1440, 720, 2,
- 11, 9, 10, 18,
- CANON_INK_CMYK | CANON_INK_CcMmYK,
- CANON_SLOT_ASF1 | CANON_SLOT_MAN1,
- CANON_CAP_DMT
- },
-
- { /* Canon BJC 4400 */
- 4400,
- 9.5*72, 14*72,
- 720, 360, 2,
- 11, 9, 10, 18,
- CANON_INK_K | CANON_INK_CMYK | CANON_INK_CcMmYK,
- CANON_SLOT_ASF1,
- CANON_CAP_CMD61 | CANON_CAP_DMT
- },
-
- { /* Canon BJC 6000 */
- 6000,
- 618, 936, /* 8.58" x 13 " */
- 1440, 720, 2,
- 11, 9, 10, 18,
- CANON_INK_CMYK | CANON_INK_CcMmYK,
- CANON_SLOT_ASF1 | CANON_SLOT_MAN1,
- CANON_CAP_DMT
- },
-
- { /* Canon BJC 8200 */
- 8200,
- 11*72, 17*72,
- 1200,1200, 4,
- 11, 9, 10, 18,
- CANON_INK_CMYK | CANON_INK_CcMmYK,
- CANON_SLOT_ASF1,
- CANON_CAP_DMT | CANON_CAP_CMD72
- },
-
- /* untested models */
-
- { /* Canon BJC 1000 */
- 1000,
- 11*72, 17*72,
- 360, 360, 2,
- 11, 9, 10, 18,
- CANON_INK_K | CANON_INK_CMY,
- CANON_SLOT_ASF1,
- CANON_CAP_CMD61
- },
- { /* Canon BJC 2000 */
- 2000,
- 11*72, 17*72,
- 720, 360, 2,
- 11, 9, 10, 18,
- CANON_INK_CMYK,
- CANON_SLOT_ASF1,
- CANON_CAP_CMD61
- },
- { /* Canon BJC 3000 */
- 3000,
- 11*72, 17*72,
- 1440, 720, 2,
- 11, 9, 10, 18,
- CANON_INK_CMYK | CANON_INK_CcMmYK,
- CANON_SLOT_ASF1,
- CANON_CAP_CMD61 | CANON_CAP_DMT
- },
- { /* Canon BJC 6100 */
- 6100,
- 11*72, 17*72,
- 1440, 720, 2,
- 11, 9, 10, 18,
- CANON_INK_CMYK | CANON_INK_CcMmYK,
- CANON_SLOT_ASF1,
- CANON_CAP_CMD61
- },
- { /* Canon BJC 7000 */
- 7000,
- 11*72, 17*72,
- 1200, 600, 2,
- 11, 9, 10, 18,
- CANON_INK_CMYK | CANON_INK_CcMmYyK,
- CANON_SLOT_ASF1,
- 0
- },
- { /* Canon BJC 7100 */
- 7100,
- 11*72, 17*72,
- 1200, 600, 2,
- 11, 9, 10, 18,
- CANON_INK_CMYK | CANON_INK_CcMmYyK,
- CANON_SLOT_ASF1,
- 0
- },
-
- /* extremely fuzzy models */
-
- { /* Canon BJC 5100 */
- 5100,
- 17*72, 22*72,
- 1440, 720, 2,
- 11, 9, 10, 18,
- CANON_INK_CMYK | CANON_INK_CcMmYK,
- CANON_SLOT_ASF1,
- CANON_CAP_DMT
- },
- { /* Canon BJC 5500 */
- 5500,
- 22*72, 34*72,
- 720, 360, 2,
- 11, 9, 10, 18,
- CANON_INK_CMYK | CANON_INK_CcMmYK,
- CANON_SLOT_ASF1,
- CANON_CAP_CMD61
- },
- { /* Canon BJC 6500 */
- 6500,
- 17*72, 22*72,
- 1440, 720, 2,
- 11, 9, 10, 18,
- CANON_INK_CMYK | CANON_INK_CcMmYK,
- CANON_SLOT_ASF1,
- CANON_CAP_CMD61 | CANON_CAP_DMT
- },
- { /* Canon BJC 8500 */
- 8500,
- 17*72, 22*72,
- 1200,1200, 2,
- 11, 9, 10, 18,
- CANON_INK_CMYK | CANON_INK_CcMmYK,
- CANON_SLOT_ASF1,
- 0
- },
- };
-
-
-
-
- static 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];
- }
- }
- #ifdef DEBUG
- fprintf(stderr,"canon: model %d not found in capabilities list.\n",model);
- #endif
- return canon_model_capabilities[0];
- }
-
- static int
- canon_media_type(const char *name, canon_cap_t caps)
- {
- if (!strcmp(name,"Plain Paper")) return 1;
- if (!strcmp(name,"Transparencies")) return 2;
- if (!strcmp(name,"Back Print Film")) return 3;
- if (!strcmp(name,"Fabric Sheets")) return 4;
- if (!strcmp(name,"Envelope")) return 5;
- if (!strcmp(name,"High Resolution Paper")) return 6;
- if (!strcmp(name,"T-Shirt Transfers")) return 7;
- if (!strcmp(name,"High Gloss Film")) return 8;
- if (!strcmp(name,"Glossy Photo Paper")) return 9;
- if (!strcmp(name,"Glossy Photo Cards")) return 10;
- if (!strcmp(name,"Photo Paper Pro")) return 11;
-
- #ifdef DEBUG
- fprintf(stderr,"canon: Unknown media type '%s' - reverting to plain\n",name);
- #endif
- return 1;
- }
-
- static int
- canon_source_type(const char *name, canon_cap_t caps)
- {
- if (!strcmp(name,"Auto Sheet Feeder")) return 4;
- if (!strcmp(name,"Manual with Pause")) return 0;
- if (!strcmp(name,"Manual without Pause")) return 1;
-
- #ifdef DEBUG
- fprintf(stderr,"canon: Unknown source type '%s' - reverting to auto\n",name);
- #endif
- return 4;
- }
-
- static int
- canon_printhead_type(const char *name, canon_cap_t caps)
- {
- if (!strcmp(name,"Black")) return 0;
- if (!strcmp(name,"Color")) return 1;
- if (!strcmp(name,"Black/Color")) return 2;
- if (!strcmp(name,"Photo/Color")) return 3;
- if (!strcmp(name,"Photo")) return 4;
- if (!strcmp(name,"Black/Photo Color")) 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;
- }
-
- #ifdef DEBUG
- fprintf(stderr,"canon: Unknown head combo '%s' - reverting to black\n",name);
- #endif
- return 0;
- }
-
- static unsigned char
- canon_size_type(const vars_t *v, canon_cap_t caps)
- {
- const papersize_t *pp = get_papersize_by_size(v->page_height, v->page_width);
- if (pp)
- {
- const char *name = pp->name;
- /* 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,"Envelope 10")) return 0x16;
- if (!strcmp(name,"Envelope DL")) return 0x17;
- if (!strcmp(name,"Letter+")) return 0x2a;
- if (!strcmp(name,"A4+")) return 0x2b;
- if (!strcmp(name,"Canon 4x2")) return 0x2d;
- /* custom */
-
- #ifdef DEBUG
- fprintf(stderr,"canon: Unknown paper size '%s' - using custom\n",name);
- } else {
- fprintf(stderr,"canon: Couldn't look up paper size %dx%d - "
- "using custom\n",v->page_height, v->page_width);
- #endif
- }
- return 0;
- }
-
- static char *
- c_strdup(const char *s)
- {
- char *ret = malloc(strlen(s) + 1);
- strcpy(ret, s);
- return ret;
- }
-
- const char *
- canon_default_resolution(const printer_t *printer)
- {
- canon_cap_t caps= canon_get_model_capabilities(printer->model);
- if (!(caps.max_xdpi%300))
- return "300x300 DPI";
- else
- return "180x180 DPI";
- }
-
- /*
- * 'canon_parameters()' - Return the parameter values for the given parameter.
- */
-
- char ** /* O - Parameter values */
- canon_parameters(const printer_t *printer, /* I - Printer model */
- char *ppd_file, /* I - PPD file (not used) */
- char *name, /* I - Name of parameter */
- int *count) /* O - Number of values */
- {
- int i;
- char **p= 0,
- **valptrs= 0;
-
- static char *media_types[] =
- {
- ("Plain Paper"),
- ("Transparencies"),
- ("Back Print Film"),
- ("Fabric Sheets"),
- ("Envelope"),
- ("High Resolution Paper"),
- ("T-Shirt Transfers"),
- ("High Gloss Film"),
- ("Glossy Photo Paper"),
- ("Glossy Photo Cards"),
- ("Photo Paper Pro")
- };
- static char *media_sources[] =
- {
- ("Auto Sheet Feeder"),
- ("Manual with Pause"),
- ("Manual without Pause"),
- };
-
- canon_cap_t caps= canon_get_model_capabilities(printer->model);
-
- if (count == NULL)
- return (NULL);
-
- *count = 0;
-
- if (name == NULL)
- return (NULL);
-
- if (strcmp(name, "PageSize") == 0) {
- int length_limit, width_limit;
- const papersize_t *papersizes = get_papersizes();
- valptrs = malloc(sizeof(char *) * known_papersizes());
- *count = 0;
-
- width_limit = caps.max_width;
- length_limit = caps.max_height;
-
- for (i = 0; i < known_papersizes(); i++) {
- if (strlen(papersizes[i].name) > 0 &&
- papersizes[i].width <= width_limit &&
- papersizes[i].length <= length_limit) {
- valptrs[*count] = malloc(strlen(papersizes[i].name) + 1);
- strcpy(valptrs[*count], papersizes[i].name);
- (*count)++;
- }
- }
- return (valptrs);
- }
- else if (strcmp(name, "Resolution") == 0)
- {
- int x= caps.max_xdpi, y= caps.max_ydpi;
- int c= 0;
- valptrs = malloc(sizeof(char *) * 10);
- if (!(caps.max_xdpi%300)) {
-
- if ( 300<=x && 300<=y)
- valptrs[c++]= c_strdup("300x300 DPI");
- if ( 300<=x && 300<=y && (caps.features&CANON_CAP_DMT))
- valptrs[c++]= c_strdup("300x300 DPI DMT");
- if ( 600<=x && 600<=y)
- valptrs[c++]= c_strdup("600x600 DPI");
- if ( 600<=x && 600<=y && (caps.features&CANON_CAP_DMT))
- valptrs[c++]= c_strdup("600x600 DPI DMT");
- if (1200==x && 600==y)
- valptrs[c++]= c_strdup("1200x600 DPI");
- if (1200<=x && 1200<=y)
- valptrs[c++]= c_strdup("1200x1200 DPI");
-
- } else if (!(caps.max_xdpi%180)) {
-
- if ( 180<=x && 180<=y)
- valptrs[c++]= c_strdup("180x180 DPI");
- if ( 360<=x && 360<=y)
- valptrs[c++]= c_strdup("360x360 DPI");
- if ( 360<=x && 360<=y && (caps.features&CANON_CAP_DMT))
- valptrs[c++]= c_strdup("360x360 DPI DMT");
- if ( 720==x && 360==y)
- valptrs[c++]= c_strdup("720x360 DPI");
- if ( 720<=x && 720<=y)
- valptrs[c++]= c_strdup("720x720 DPI");
- if (1440==x && 720==y)
- valptrs[c++]= c_strdup("1440x720 DPI");
- if (1440<=x &&1440<=y)
- valptrs[c++]= c_strdup("1440x1440 DPI");
-
- } else {
- #ifdef DEBUG
- fprintf(stderr,"canon: unknown resolution multiplier for model %d\n",
- caps.model);
- #endif
- return 0;
- }
- *count= c;
- p= valptrs;
- }
- else if (strcmp(name, "InkType") == 0)
- {
- int c= 0;
- valptrs = malloc(sizeof(char *) * 5);
- if ((caps.inks & CANON_INK_K))
- valptrs[c++]= c_strdup("Black");
- if ((caps.inks & CANON_INK_CMY))
- valptrs[c++]= c_strdup("Color");
- if ((caps.inks & CANON_INK_CMYK))
- valptrs[c++]= c_strdup("Black/Color");
- if ((caps.inks & CANON_INK_CcMmYK))
- valptrs[c++]= c_strdup("Photo/Color");
- if ((caps.inks & CANON_INK_CcMmYy))
- valptrs[c++]= c_strdup("Photo");
- if ((caps.inks & CANON_INK_CcMmYyK))
- valptrs[c++]= c_strdup("Black/Photo Color");
- *count = c;
- p = valptrs;
- }
- else if (strcmp(name, "MediaType") == 0)
- {
- *count = 11;
- p = media_types;
- }
- else if (strcmp(name, "InputSlot") == 0)
- {
- *count = 3;
- p = media_sources;
- }
- else
- return (NULL);
-
- valptrs = malloc(*count * sizeof(char *));
- for (i = 0; i < *count; i ++)
- valptrs[i] = c_strdup(p[i]);
-
- return (valptrs);
- }
-
-
- /*
- * 'canon_imageable_area()' - Return the imageable area of the page.
- */
-
- void
- canon_imageable_area(const printer_t *printer, /* I - Printer model */
- const 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 */
-
- canon_cap_t caps= canon_get_model_capabilities(printer->model);
-
- 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;
- }
-
- void
- canon_limit(const printer_t *printer, /* I - Printer model */
- const vars_t *v, /* I */
- int *width, /* O - Left position in points */
- int *length) /* O - Top position in points */
- {
- canon_cap_t caps= canon_get_model_capabilities(printer->model);
- *width = caps.max_width;
- *length = caps.max_height;
- }
-
- /*
- * 'canon_cmd()' - Sends a command with variable args
- */
- static void
- canon_cmd(FILE *prn, /* I - the printer */
- char *ini, /* I - 2 bytes start code */
- char cmd, /* I - command code */
- int num, /* I - number of arguments */
- ... /* I - the args themselves */
- )
- {
- static int bufsize= 0;
- static unsigned char *buffer;
- int i;
- va_list ap;
-
- if (!buffer || (num > bufsize)) {
- if (buffer)
- free(buffer);
- buffer = malloc(num);
- bufsize= num;
- if (!buffer) {
- #ifdef DEBUG
- fprintf(stderr,"\ncanon: *** buffer allocation failed...\n");
- fprintf(stderr,"canon: *** command 0x%02x with %d args dropped\n\n",
- cmd,num);
- #endif
- return;
- }
- }
- if (num) {
- va_start(ap, num);
- for (i=0; i<num; i++)
- buffer[i]= (unsigned char) va_arg(ap, int);
- va_end(ap);
- }
-
- fwrite(ini,2,1,prn);
- if (cmd) {
- fputc(cmd,prn);
- fputc((num & 255),prn);
- fputc((num >> 8 ),prn);
- fwrite(buffer,num,1,prn);
- }
- }
-
- #ifdef DEBUG
- #define PUT(WHAT,VAL,RES) fprintf(stderr,"canon: "WHAT" is %04x =% 5d = %f\" = %f mm\n",(VAL),(VAL),(VAL)/(1.*RES),(VAL)/(RES/25.4))
- #else
- #define PUT(WHAT,VAL,RES) do {} while (0)
- #endif
-
- static void
- canon_init_printer(FILE *prn, canon_cap_t caps,
- int output_type, const char *media_str,
- const vars_t *v, int print_head,
- const char *source_str,
- int xdpi, int ydpi,
- int page_width, int page_height,
- int top, int left,
- int use_dmt)
- {
- #define MEDIACODES 11
- static unsigned char mediacode_63[] = {
- 0x00,0x00,0x02,0x03,0x04,0x08,0x07,0x03,0x06,0x05,0x05,0x09
- };
- static unsigned char mediacode_6c[] = {
- 0x00,0x00,0x02,0x03,0x04,0x08,0x07,0x03,0x06,0x05,0x0a,0x09
- };
-
- #define ESC28 "\x1b\x28"
- #define ESC5b "\x1b\x5b"
- #define ESC40 "\x1b\x40"
-
- unsigned char
- arg_63_1 = 0x00,
- arg_63_2 = 0x00, /* plain paper */
- arg_63_3 = caps.max_quality, /* output quality */
- arg_6c_1 = 0x00,
- arg_6c_2 = 0x01, /* plain paper */
- 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,
- arg_70_1 = 0x02, /* A4 printable area */
- arg_70_2 = 0xa6,
- arg_70_3 = 0x01,
- arg_70_4 = 0xe0,
- arg_74_1 = 0x01, /* 1 bit per pixel */
- arg_74_2 = 0x00, /* */
- arg_74_3 = 0x01; /* 01 <= 360 dpi 09 >= 720 dpi */
-
- int media= canon_media_type(media_str,caps);
- int source= canon_source_type(source_str,caps);
-
- int printable_width= page_width*10/12;
- int printable_height= page_height*10/12;
-
- arg_6d_a= canon_size_type(v,caps);
- if (!arg_6d_a) arg_6d_b= 1;
-
- if (caps.model<3000)
- arg_63_1= arg_6c_1= 0x10;
- else
- arg_63_1= arg_6c_1= 0x30;
-
- if (output_type==OUTPUT_GRAY) arg_63_1|= 0x01;
- arg_6c_1|= (source & 0x0f);
-
- if (print_head==0) arg_6d_1= 0x03;
- else if (print_head<=2) arg_6d_1= 0x02;
- else if (print_head<=4) arg_6d_1= 0x04;
- if (output_type==OUTPUT_GRAY) arg_6d_2= 0x02;
-
- if (caps.model==8200) arg_6d_3= 0x01;
-
- arg_70_1= (printable_height >> 8) & 0xff;
- arg_70_2= (printable_height) & 0xff;
- arg_70_3= (printable_width >> 8) & 0xff;
- arg_70_4= (printable_width) & 0xff;
-
- if (xdpi==1440) arg_74_2= 0x04;
- if (ydpi>=720) arg_74_3= 0x09;
-
- if (media<MEDIACODES) {
- arg_63_2= mediacode_63[media];
- arg_6c_2= mediacode_6c[media];
- }
-
- if (use_dmt) {
- arg_74_1= 0x02;
- arg_74_2= 0x80;
- arg_74_3= 0x09;
- }
-
- /* workaround for the bjc8200 - not really understood */
- if (caps.model==8200 && use_dmt) {
- arg_74_1= 0xff;
- arg_74_2= 0x90;
- arg_74_3= 0x04;
- }
-
- /*
- #ifdef DEBUG
- fprintf(stderr,"canon: printable size = %dx%d (%dx%d) %02x%02x %02x%02x\n",
- page_width,page_height,printable_width,printable_height,
- arg_70_1,arg_70_2,arg_70_3,arg_70_4);
- #endif
- */
-
- /* init printer */
-
- canon_cmd(prn,ESC5b,0x4b, 2, 0x00,0x0f);
- if (caps.features & CANON_CAP_CMD61)
- canon_cmd(prn,ESC28,0x61, 1, 0x01);
- canon_cmd(prn,ESC28,0x62, 1, 0x01);
- canon_cmd(prn,ESC28,0x71, 1, 0x01);
-
- if (caps.features & CANON_CAP_CMD6d)
- canon_cmd(prn,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);
-
- /* set resolution */
-
- canon_cmd(prn,ESC28,0x64, 4, (ydpi >> 8 ), (ydpi & 255),
- (xdpi >> 8 ), (xdpi & 255));
-
- canon_cmd(prn,ESC28,0x74, 3, arg_74_1, arg_74_2, arg_74_3);
-
- canon_cmd(prn,ESC28,0x63, 3, arg_63_1, arg_63_2, arg_63_3);
-
- if (caps.features & CANON_CAP_CMD70)
- canon_cmd(prn,ESC28,0x70, 8, arg_70_1, arg_70_2, 0x00, 0x00,
- arg_70_3, arg_70_4, 0x00, 0x00);
-
- canon_cmd(prn,ESC28,0x6c, 2, arg_6c_1, arg_6c_2);
-
- if (caps.features & CANON_CAP_CMD72)
- canon_cmd(prn,ESC28,0x72, 1, 0x61); /* whatever for - 8200 might need it */
-
- /* some linefeeds */
-
- top= (top*ydpi)/72;
- PUT("topskip ",top,ydpi);
- canon_cmd(prn,ESC28,0x65, 2, (top >> 8 ),(top & 255));
- }
-
- void canon_deinit_printer(FILE *prn, canon_cap_t caps)
- {
- /* eject page */
- fputc(0x0c,prn);
-
- /* say goodbye */
- canon_cmd(prn,ESC28,0x62,1,0);
- if (caps.features & CANON_CAP_CMD61)
- canon_cmd(prn,ESC28,0x61, 1, 0x00);
- canon_cmd(prn,ESC40,0,0);
- fflush(prn);
- }
-
-
- /*
- * 'alloc_buffer()' allocates buffer and fills it with 0
- */
- static unsigned char *canon_alloc_buffer(int size)
- {
- unsigned char *buf= 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.
- */
- void
- canon_print(const printer_t *printer, /* I - Model */
- int copies, /* I - Number of copies */
- FILE *prn, /* I - File to print to */
- Image image, /* I - Image to print */
- const vars_t *v)
- {
- unsigned char *cmap = v->cmap;
- int model = printer->model;
- const char *resolution = v->resolution;
- const char *media_type = v->media_type;
- const char *media_source = v->media_source;
- int output_type = v->output_type;
- int orientation = v->orientation;
- const char *ink_type = v->ink_type;
- double scaling = v->scaling;
- int top = v->top;
- int left = v->left;
- 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, /* Height of page */
- page_length, /* True length of page */
- out_width, /* Width of image on page */
- out_height, /* Height 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 */
- convert_t colorfunc = 0; /* Color conversion function... */
- int image_height,
- image_width,
- image_bpp;
- int use_dmt = 0;
- void * dither;
- double the_levels[] = { 0.5, 0.75, 1.0 };
- vars_t nv;
-
- canon_cap_t caps= canon_get_model_capabilities(model);
- int printhead= canon_printhead_type(ink_type,caps);
-
- memcpy(&nv, v, sizeof(vars_t));
- /*
- 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 (nv.image_type == IMAGE_MONOCHROME)
- {
- output_type = OUTPUT_GRAY;
- }
-
- if (printhead == 0 || caps.inks == CANON_INK_K)
- output_type = OUTPUT_GRAY;
-
- /*
- * Choose the correct color conversion function...
- */
-
- colorfunc = choose_colorfunc(output_type, image_bpp, cmap, &out_bpp, &nv);
-
- /*
- * Figure out the output resolution...
- */
-
- sscanf(resolution,"%dx%d",&xdpi,&ydpi);
- #ifdef DEBUG
- fprintf(stderr,"canon: resolution=%dx%d\n",xdpi,ydpi);
- #endif
-
- if (!strcmp(resolution+(strlen(resolution)-3),"DMT") &&
- (caps.features & CANON_CAP_DMT) &&
- nv.image_type != IMAGE_MONOCHROME) {
- use_dmt= 1;
- #ifdef DEBUG
- fprintf(stderr,"canon: using drop modulation technology\n");
- #endif
- }
-
- /*
- * Compute the output size...
- */
-
- canon_imageable_area(printer, &nv, &page_left, &page_right,
- &page_bottom, &page_top);
-
- 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_height, &left, &top);
-
- /*
- * Recompute the image height and width. If the image has been
- * rotated, these will change from previously.
- */
- image_height = Image_height(image);
- image_width = Image_width(image);
-
- default_media_size(printer, &nv, &n, &page_length);
-
- /*
- 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_length",page_length,72);
- PUT("out_width ", out_width,xdpi);
- PUT("out_height", out_height,ydpi);
- */
-
- Image_progress_init(image);
-
- PUT("top ",top,72);
- PUT("left ",left,72);
-
- canon_init_printer(prn, caps, output_type, media_type,
- &nv, printhead, media_source,
- xdpi, ydpi, page_width, page_height,
- top,left,use_dmt);
-
- /*
- * Convert image size to printer resolution...
- */
-
- out_width = xdpi * out_width / 72;
- out_height = ydpi * out_height / 72;
-
- /*
- PUT("out_width ", out_width,xdpi);
- PUT("out_height", out_height,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= 0;
- delay_max= 336;
- #ifdef DEBUG
- fprintf(stderr,"canon: delay on!\n");
- #endif
- } else {
- delay_k= delay_c= delay_m= delay_y= delay_lc= delay_lm= delay_ly=0;
- delay_max=0;
- #ifdef DEBUG
- fprintf(stderr,"canon: delay off!\n");
- #endif
- }
-
- /*
- * Allocate memory for the raster data...
- */
-
- length = (out_width + 7) / 8;
-
- if (use_dmt) {
- buf_length= length*2;
- } else {
- buf_length= length;
- }
-
- #ifdef DEBUG
- fprintf(stderr,"canon: buflength is %d!\n",buf_length);
- #endif
-
- if (output_type == OUTPUT_GRAY) {
- 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 ((caps.inks & CANON_INK_BLACK_MASK))
- black = canon_alloc_buffer(buf_length*(delay_k+1));
- else
- black = NULL;
-
- if (printhead==3 && (caps.inks & (CANON_INK_PHOTO_MASK))) {
- lcyan = canon_alloc_buffer(buf_length*(delay_lc+1));
- lmagenta = canon_alloc_buffer(buf_length*(delay_lm+1));
- if ((caps.inks & CANON_INK_CcMmYy) ||
- (caps.inks & CANON_INK_CcMmYyK))
- lyellow = canon_alloc_buffer(buf_length*(delay_lc+1));
- else
- lyellow = NULL;
- } else {
- lcyan = NULL;
- lmagenta = NULL;
- lyellow = NULL;
- }
- }
-
- #ifdef DEBUG
- fprintf(stderr,"canon: driver will use colors ");
- if (cyan) fputc('C',stderr);
- if (lcyan) fputc('c',stderr);
- if (magenta) fputc('M',stderr);
- if (lmagenta) fputc('m',stderr);
- if (yellow) fputc('Y',stderr);
- if (lyellow) fputc('y',stderr);
- if (black) fputc('K',stderr);
- fprintf(stderr,"\n");
- #endif
-
- #ifdef DEBUG
- fprintf(stderr,"density is %f\n",nv.density);
- #endif
-
- nv.density = (nv.density * ydpi) / (xdpi * 1.0);
- if (nv.density > 1.0)
- nv.density = 1.0;
- compute_lut(256, &nv);
-
- #ifdef DEBUG
- fprintf(stderr,"density is %f\n",nv.density);
- #endif
-
- if (xdpi > ydpi)
- dither = init_dither(image_width, out_width, 1, xdpi / ydpi, &nv);
- else
- dither = init_dither(image_width, out_width, ydpi / xdpi, 1, &nv);
-
- dither_set_black_levels(dither, 1.0, 1.0, 1.0);
- dither_set_black_lower(dither, .8 / ((1 << (use_dmt+1)) - 1));
- /*
- if (use_glossy_film)
- */
- dither_set_black_upper(dither, .999);
- /*
- else
- dither_set_black_upper(dither, .999);
- */
-
- if (!use_dmt) {
- dither_set_light_inks(dither,
- (lcyan) ? (0.3333) : (0.0),
- (lmagenta)? (0.3333) : (0.0),
- (lyellow) ? (0.3333) : (0.0), nv.density);
- }
-
- switch (nv.image_type)
- {
- case IMAGE_LINE_ART:
- dither_set_ink_spread(dither, 19);
- break;
- case IMAGE_SOLID_TONE:
- dither_set_ink_spread(dither, 15);
- break;
- case IMAGE_CONTINUOUS:
- dither_set_ink_spread(dither, 14);
- break;
- }
- dither_set_density(dither, nv.density);
-
- if (use_dmt)
- {
- dither_set_c_ranges_simple(dither, 3, the_levels, nv.density);
- dither_set_m_ranges_simple(dither, 3, the_levels, nv.density);
- dither_set_y_ranges_simple(dither, 3, the_levels, nv.density);
- dither_set_k_ranges_simple(dither, 3, the_levels, nv.density);
- }
- /*
- * Output the page...
- */
-
- in = malloc(image_width * image_bpp);
- out = malloc(image_width * out_bpp * 2);
-
- errdiv = image_height / out_height;
- errmod = image_height % out_height;
- errval = 0;
- errlast = -1;
- errline = 0;
-
- for (y = 0; y < out_height; y ++)
- {
- int duplicate_line = 1;
- if ((y & 63) == 0)
- Image_note_progress(image, y, out_height);
-
- if (errline != errlast)
- {
- errlast = errline;
- duplicate_line = 0;
- Image_get_row(image, in, errline);
- (*colorfunc)(in, out, image_width, image_bpp, cmap, &nv);
- }
-
- if (nv.image_type == IMAGE_MONOCHROME)
- dither_monochrome(out, y, dither, black, duplicate_line);
- else if (output_type == OUTPUT_GRAY)
- dither_black(out, y, dither, black, duplicate_line);
- else
- dither_cmyk(out, y, dither, cyan, lcyan, magenta, lmagenta,
- yellow, 0, black, duplicate_line);
-
- #ifdef DEBUG
- /* fprintf(stderr,","); */
- #endif
-
- canon_write_line(prn, 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, use_dmt);
-
- #ifdef DEBUG
- /* fprintf(stderr,"!"); */
- #endif
-
- 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_height)
- {
- errval -= out_height;
- errline ++;
- }
- }
- Image_progress_conclude(image);
-
- free_dither(dither);
-
- /*
- * Flush delayed buffers...
- */
-
- if (delay_max) {
- #ifdef DEBUG
- fprintf(stderr,"\ncanon: flushing %d possibly delayed buffers\n",
- delay_max);
- #endif
- for (y= 0; y<delay_max; y++) {
-
- canon_write_line(prn, 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, use_dmt);
-
- #ifdef DEBUG
- /* fprintf(stderr,"-"); */
- #endif
-
- 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...
- */
-
- free_lut(&nv);
- free(in);
- free(out);
-
- if (black != NULL) free(black);
- if (cyan != NULL) free(cyan);
- if (magenta != NULL) free(magenta);
- if (yellow != NULL) free(yellow);
- if (lcyan != NULL) free(lcyan);
- if (lmagenta != NULL) free(lmagenta);
- if (lyellow != NULL) free(lyellow);
-
- canon_deinit_printer(prn, caps);
- }
-
- /*
- * 'canon_fold_lsb_msb()' fold 2 lines in order lsb/msb
- */
-
- static void
- canon_fold_lsb_msb(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;
- }
- }
-
- /*
- * 'canon_fold_msb_lsb()' fold 2 lines in order msb/lsb
- */
-
- static void
- canon_fold_msb_lsb(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)) >> 0) |
- ((line[0] & (1 << 6)) >> 1) |
- ((line[0] & (1 << 5)) >> 2) |
- ((line[0] & (1 << 4)) >> 3) |
- ((line[single_length] & (1 << 7)) >> 1) |
- ((line[single_length] & (1 << 6)) >> 2) |
- ((line[single_length] & (1 << 5)) >> 3) |
- ((line[single_length] & (1 << 4)) >> 4);
- outbuf[1] =
- ((line[0] & (1 << 3)) << 4) |
- ((line[0] & (1 << 2)) << 3) |
- ((line[0] & (1 << 1)) << 2) |
- ((line[0] & (1 << 0)) << 1) |
- ((line[single_length] & (1 << 3)) << 3) |
- ((line[single_length] & (1 << 2)) << 2) |
- ((line[single_length] & (1 << 1)) << 1) |
- ((line[single_length] & (1 << 0)) << 0);
- line++;
- outbuf += 2;
- }
- }
-
- static void
- canon_pack(unsigned char *line,
- int length,
- unsigned char *comp_buf,
- unsigned char **comp_ptr)
- {
- unsigned char *start; /* Start of compressed data */
- unsigned char repeat; /* Repeating char */
- int count; /* Count of compressed bytes */
- int tcount; /* Temporary count < 128 */
-
- /*
- * Compress using TIFF "packbits" run-length encoding...
- */
-
- (*comp_ptr) = comp_buf;
-
- while (length > 0)
- {
- /*
- * Get a run of non-repeated chars...
- */
-
- start = line;
- line += 2;
- length -= 2;
-
- while (length > 0 && (line[-2] != line[-1] || line[-1] != line[0]))
- {
- line ++;
- length --;
- }
-
- line -= 2;
- length += 2;
-
- /*
- * Output the non-repeated sequences (max 128 at a time).
- */
-
- count = line - start;
- while (count > 0)
- {
- tcount = count > 128 ? 128 : count;
-
- (*comp_ptr)[0] = tcount - 1;
- memcpy((*comp_ptr) + 1, start, tcount);
-
- (*comp_ptr) += tcount + 1;
- start += tcount;
- count -= tcount;
- }
-
- if (length <= 0)
- break;
-
- /*
- * Find the repeated sequences...
- */
-
- start = line;
- repeat = line[0];
-
- line ++;
- length --;
-
- while (length > 0 && *line == repeat)
- {
- line ++;
- length --;
- }
-
- /*
- * Output the repeated sequences (max 128 at a time).
- */
-
- count = line - start;
- while (count > 0)
- {
- tcount = count > 128 ? 128 : count;
-
- (*comp_ptr)[0] = 1 - tcount;
- (*comp_ptr)[1] = repeat;
-
- (*comp_ptr) += 2;
- count -= tcount;
- }
- }
- }
-
-
- /*
- * 'canon_write()' - Send graphics using TIFF packbits compression.
- */
-
- static int
- canon_write(FILE *prn, /* I - Print file or command */
- 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 dmt)
- {
- unsigned char
- comp_buf[COMPBUFWIDTH], /* Compression buffer */
- in_fold[COMPBUFWIDTH],
- *in_ptr= line,
- *comp_ptr, *comp_data;
- int newlength;
- 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 (dmt) {
- if (1) {
- if (caps.features & CANON_CAP_MSB_FIRST)
- canon_fold_msb_lsb(line,length,in_fold);
- else
- canon_fold_lsb_msb(line,length,in_fold);
- in_ptr= in_fold;
- }
- length*= 2;
- offset*= 2;
- }
-
- /* pack left border rounded to multiples of 8 dots */
-
- comp_data= comp_buf;
- if (offset) {
- int offset2= (offset+4)/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;
- }
- }
-
- canon_pack(in_ptr, length, comp_data, &comp_ptr);
- newlength= comp_ptr - comp_buf;
-
- /* send packed empty lines if any */
-
- if (*empty) {
- #ifdef DEBUG
- /* fprintf(stderr,"<%d%c>",*empty,("CMYKcmy"[coloridx])); */
- #endif
- fwrite("\x1b\x28\x65\x02\x00", 5, 1, prn);
- fputc((*empty) >> 8 , prn);
- fputc((*empty) & 255, prn);
- *empty= 0;
- }
-
- /* Send a line of raster graphics... */
-
- fwrite("\x1b\x28\x41", 3, 1, prn);
- putc((newlength+1) & 255, prn);
- putc((newlength+1) >> 8, prn);
- color= "CMYKcmy"[coloridx];
- if (!color) color= 'K';
- putc(color,prn);
- fwrite(comp_buf, newlength, 1, prn);
- putc('\x0d', prn);
- return 1;
- }
-
-
- static void
- canon_write_line(FILE *prn, /* I - Print file or command */
- 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 dmt)
- {
- static int empty= 0;
- int written= 0;
-
- if (k) written+=
- canon_write(prn, caps, k+ dk*l, l, 3, ydpi, &empty, width, offset, dmt);
- if (y) written+=
- canon_write(prn, caps, y+ dy*l, l, 2, ydpi, &empty, width, offset, dmt);
- if (m) written+=
- canon_write(prn, caps, m+ dm*l, l, 1, ydpi, &empty, width, offset, dmt);
- if (c) written+=
- canon_write(prn, caps, c+ dc*l, l, 0, ydpi, &empty, width, offset, dmt);
- if (ly) written+=
- canon_write(prn, caps, ly+dly*l, l, 6, ydpi, &empty, width, offset, dmt);
- if (lm) written+=
- canon_write(prn, caps, lm+dlm*l, l, 5, ydpi, &empty, width, offset, dmt);
- if (lc) written+=
- canon_write(prn, caps, lc+dlc*l, l, 4, ydpi, &empty, width, offset, dmt);
-
- if (written)
- fwrite("\x1b\x28\x65\x02\x00\x00\x01", 7, 1, prn);
- else
- empty++;
- }
-