1 /* Copyright (C) 1990, 1995, 1997, 2000 Aladdin Enterprises. All rights reserved. 2 3 This file is part of AFPL Ghostscript. 4 5 AFPL Ghostscript is distributed with NO WARRANTY OF ANY KIND. No author or 6 distributor accepts any responsibility for the consequences of using it, or 7 for whether it serves any particular purpose or works at all, unless he or 8 she says so in writing. Refer to the Aladdin Free Public License (the 9 "License") for full details. 10 11 Every copy of AFPL Ghostscript must include a copy of the License, normally 12 in a plain ASCII text file named PUBLIC. The License grants you the right 13 to copy, modify and redistribute AFPL Ghostscript, but only under certain 14 conditions described in the License. Among other things, the License 15 requires that the copyright notice and this notice be preserved on all 16 copies. 17 */ 18 19 /*$Id: gdevbj10.c,v 1.4 2001/08/01 00:48:23 stefan911 Exp $*/ 20 /* Canon Bubble Jet BJ-10e, BJ200, and BJ300 printer driver */ 21 #include "gdevprn.h" 22 23 /* 24 * The following is taken from the BJ200 Programmer's manual. The top 25 * margin is 3mm (0.12"), and the bottom margin is 6.4mm (0.25"). The 26 * left and right margin depend on the type of paper -- US letter or 27 * A4 -- but ultimately rest on a print width of 203.2mm (8"). For letter 28 * paper, the left margin (and hence the right) is 6.4mm (0.25"), while 29 * for A4 paper, both are 3.4mm (0.13"). 30 * 31 * The bottom margin requires a bit of care. The image is printed 32 * as strips, each about 3.4mm wide. We can only attain the bottom 33 * margin if the final strip coincides with it. Note that each strip 34 * is generated using only 48 of the available 64 jets, and the absence 35 * of those bottom 16 jets makes our bottom margin, in effect, about 36 * 1.1mm (0.04") larger. 37 * 38 * The bj200 behaves, in effect, as though the origin were at the first 39 * printable position, rather than the top left corner of the page, so 40 * we add a translation to the initial matrix to compensate for this. 41 * 42 * Except for the details of getting the margins correct, the bj200 is 43 * no different from the bj10e, and uses the same routine to print each 44 * page. 45 * 46 * NOTE: The bj200 has a DIP switch called "Text scale mode" and if 47 * set, it allows the printer to get 66 lines on a letter-sized page 48 * by reducing the line spacing by a factor of 14/15. If this DIP 49 * switch is set, the page image printed by ghostscript will also be 50 * similarly squeezed. Thus text scale mode is something ghostscript 51 * would like to disable. 52 * 53 * According to the bj200 manual, which describes the bj10 commands, 54 * the printer can be reset either to the settings determined by the 55 * DIP switches, or to the factory defaults, and then some of those 56 * settings can be specifically overriden. Unfortunately, the text 57 * scale mode and horizontal print position (for letter vs A4 paper) 58 * can not be overriden. On my bj200, the factory settings are for 59 * no text scaling and letter paper, thus using the factory defaults 60 * also implies letter paper. I don't know if this is necessarily 61 * true for bj200's sold elsewhere, or for other printers that use 62 * the same command set. 63 * 64 * If your factory defaults are in fact the same, you can compile 65 * the driver with USE_FACTORY_DEFAULTS defined, in which case the 66 * printer will be reset to the factory defaults for letter paper, 67 * and reset to the DIP switch settings for A4 paper. In this case, 68 * with letter-sized paper, the text scale mode will be disabled. 69 * Further, by leaving the horizontal print position DIP switch set 70 * for A4 paper, gs will be able to print on either A4 or letter 71 * paper without changing the DIP switch. Since it's not clear that 72 * the factory defaults are universal, the default behaviour is not 73 * to define USE_FACTORY_DEFAULTS, and the printer will always be 74 * reset to the DIP switch defaults. 75 */ 76 77 /* 78 * According to md@duesti.fido.de (Matthias Duesterhoeft): 79 80 It is possible to use the printer Canon BJ-300 (and 330) with Ghostscript if 81 you use the driver for the Canon BJ-200. The Printer has to be set to 82 Proprinter Mode. Although it is possible to set the print quality with a DIP 83 switch, you should add the following to the already existing init-string: 84 1B 5B 64 01 00 80 (all numbers in hex) 85 This sets the print quality to letter quality. 86 87 The minimum margins are the following: 88 89 Portrait: 90 B5/A4: min. left and right margin: 3.4 mm (0.13") 91 Letter: min. left and right margin: 6.4 mm (0.25") 92 93 Landscape: 94 B4: min. left and right margin: 9.3 mm (0.37") 95 A3: min. left and right margin: 37.3 mm (1.47") 96 97 The recommended top margin is 12.7 mm (0.5"), although the printer is capable 98 to start at 0 mm. The recommended bottom margin is 25.4 mm (1"), but 12.7 mm 99 (0.5") are possible, too. If you ask me, don't use the recommended top and 100 bottom margins, use 0" and 0.5". 101 102 */ 103 104 #define BJ200_TOP_MARGIN 0.12 105 #define BJ200_BOTTOM_MARGIN 0.29 106 #define BJ200_LETTER_SIDE_MARGIN 0.25 107 #define BJ200_A4_SIDE_MARGIN 0.13 108 109 private dev_proc_open_device(bj200_open); 110 111 private dev_proc_print_page(bj10e_print_page); 112 113 private gx_device_procs prn_bj200_procs = 114 prn_procs(bj200_open, gdev_prn_output_page, gdev_prn_close); 115 116 const gx_device_printer far_data gs_bj200_device = 117 prn_device(prn_bj200_procs, "bj200", 118 DEFAULT_WIDTH_10THS, 119 DEFAULT_HEIGHT_10THS, 120 360, /* x_dpi */ 121 360, /* y_dpi */ 122 0, 0, 0, 0, /* margins filled in by bj200_open */ 123 1, bj10e_print_page); 124 125 /* 126 * (<simon@pogner.demon.co.uk>, aka <sjwright@cix.compulink.co.uk>): 127 * My bj10ex, which as far as I can tell is just like a bj10e, works 128 * fine with the bj200 setup here. 129 */ 130 131 const gx_device_printer far_data gs_bj10e_device = 132 prn_device(prn_bj200_procs, "bj10e", 133 DEFAULT_WIDTH_10THS, 134 DEFAULT_HEIGHT_10THS, 135 360, /* x_dpi */ 136 360, /* y_dpi */ 137 0,0,0,0, /* margins */ 138 1, bj10e_print_page); 139 140 /* 141 * Notes on the BJ10e/BJ200 command set. 142 * 143 144 According to the BJ200 manual, the "set initial condition" sequence (ESC [ 145 K) has 2 bytes which can override the DIP switches -- these are the last 2 146 bytes. Several bits are listed as "reserved" -- one or more may possibly 147 affect the sheet feeder. The first is referred to as <P1>, with the 148 following meaning: 149 1 0 150 bit 7 ignore/process P1 ignore process 151 bit 6 reserved 152 bit 5 alarm disabled enabled 153 bit 4 automatic CR CR+LF CR 154 bit 3 automatic LF CR+LF LF 155 bit 2 page length 12 inches 11 inches 156 bit 1 style for zero slashed not slashed 157 bit 0 character set set 2 set 1 158 159 The last byte is <P2>, with the following meaning: 160 1 0 161 bit 7 ignore/process P2 ignore process 162 bit 6 code page 850 437 163 bit 5 reserved 164 bit 4 reserved 165 bit 3 reserved 166 bit 2 reserved 167 bit 1 reserved 168 bit 0 reserved 169 170 The automatic CR setting is important to gs, but the rest shouldn't matter 171 (gs doesn't print characters or send LF, and it explicitly sets the page 172 length). The sequence ESC 5 <n> controls automatic CR -- if <n> is 0x00, 173 it is turned off (CR only) and if <n> is 0x01, it is turned on (CR + LF). 174 So we do following: Change the initialization string to so that the last 2 175 of the 9 bytes are \200 rather than \000. Then add 176 |* Turn off automatic carriage return, otherwise we get line feeds. *| 177 fwrite("\0335\000", 1, 3, prn_stream); 178 after the initialization. (Actually, instead of setting the last 2 bytes 179 to \200, we suppress them altogether by changing the byte count from \004 180 to \002 (the byte count is the 4th (low 8 bits) and 5th (high 8 bits) bytes 181 in the initialization sequence).) 182 183 */ 184 185 /* ------ Internal routines ------ */ 186 187 /* Open the printer, and set the margins. */ 188 private int 189 bj200_open(gx_device *pdev) 190 { 191 /* Change the margins according to the paper size. 192 The top and bottom margins don't seem to depend on the 193 page length, but on the paper handling mechanism; 194 The side margins do depend on the paper width, as the 195 printer centres the 8" print line on the page. */ 196 197 static const float a4_margins[4] = 198 { BJ200_A4_SIDE_MARGIN, BJ200_BOTTOM_MARGIN, 199 BJ200_A4_SIDE_MARGIN, BJ200_TOP_MARGIN 200 }; 201 static const float letter_margins[4] = 202 { BJ200_LETTER_SIDE_MARGIN, BJ200_BOTTOM_MARGIN, 203 BJ200_LETTER_SIDE_MARGIN, BJ200_TOP_MARGIN 204 }; 205 206 gx_device_set_margins(pdev, 207 (pdev->width / pdev->x_pixels_per_inch <= 8.4 ? 208 a4_margins : letter_margins), 209 true); 210 return gdev_prn_open(pdev); 211 } 212 213 /* Send the page to the printer. */ 214 private int 215 bj10e_print_page(gx_device_printer *pdev, FILE *prn_stream) 216 { int line_size = gx_device_raster((gx_device *)pdev, 0); 217 int xres = pdev->x_pixels_per_inch; 218 int yres = pdev->y_pixels_per_inch; 219 int mode = (yres == 180 ? 220 (xres == 180 ? 11 : 12) : 221 (xres == 180 ? 14 : 16)); 222 int bytes_per_column = (yres == 180) ? 3 : 6; 223 int bits_per_column = bytes_per_column * 8; 224 int skip_unit = bytes_per_column * 3; 225 byte *in = (byte *)gs_malloc(8, line_size, "bj10e_print_page(in)"); 226 byte *out = (byte *)gs_malloc(bits_per_column, line_size, "bj10e_print_page(out)"); 227 int lnum = 0; 228 int skip = 0; 229 int code = 0; 230 int last_row = dev_print_scan_lines(pdev); 231 int limit = last_row - bits_per_column; 232 233 if ( in == 0 || out == 0 ) 234 { code = gs_note_error(gs_error_VMerror); 235 goto fin; 236 } 237 238 /* Initialize the printer. */ 239 #ifdef USE_FACTORY_DEFAULTS 240 /* Check for U.S. letter vs. A4 paper. */ 241 fwrite(( pdev->width / pdev->x_pixels_per_inch <= 8.4 ? 242 "\033[K\002\000\000\044" /*A4--DIP switch defaults*/ : 243 "\033[K\002\000\004\044" /*letter--factory defaults*/ ), 244 1, 7, prn_stream); 245 #else 246 fwrite("\033[K\002\000\000\044", 1, 7, prn_stream); 247 #endif 248 249 /* Turn off automatic carriage return, otherwise we get line feeds. */ 250 fwrite("\0335\000", 1, 3, prn_stream); 251 252 /* Set vertical spacing. */ 253 fwrite("\033[\\\004\000\000\000", 1, 7, prn_stream); 254 fputc(yres & 0xff, prn_stream); 255 fputc(yres >> 8, prn_stream); 256 257 /* Set the page length. This is the printable length, in inches. */ 258 fwrite("\033C\000", 1, 3, prn_stream); 259 fputc((last_row + yres - 1)/yres, prn_stream); 260 261 /* Transfer pixels to printer. The last row we can print is defined 262 by "last_row". Only the bottom of the print head can print at the 263 bottom margin, and so we align the final printing pass. The print 264 head is kept from moving below "limit", which is exactly one pass 265 above the bottom margin. Once it reaches this limit, we make our 266 final printing pass of a full "bits_per_column" rows. */ 267 while ( lnum < last_row ) 268 { 269 byte *in_data; 270 byte *in_end = in + line_size; 271 byte *out_beg = out; 272 byte *out_end = out + bytes_per_column * pdev->width; 273 byte *outl = out; 274 int bnum; 275 276 /* Copy 1 scan line and test for all zero. */ 277 code = gdev_prn_get_bits(pdev, lnum, in, &in_data); 278 if ( code < 0 ) goto xit; 279 /* The mem... or str... functions should be faster than */ 280 /* the following code, but all systems seem to implement */ 281 /* them so badly that this code is faster. */ 282 { register const long *zip = (const long *)in_data; 283 register int zcnt = line_size; 284 register const byte *zipb; 285 for ( ; zcnt >= 4 * sizeof(long); zip += 4, zcnt -= 4 * sizeof(long) ) 286 { if ( zip[0] | zip[1] | zip[2] | zip[3] ) 287 goto notz; 288 } 289 zipb = (const byte *)zip; 290 while ( --zcnt >= 0 ) 291 { 292 if ( *zipb++ ) 293 goto notz; 294 } 295 /* Line is all zero, skip */ 296 lnum++; 297 skip++; 298 continue; 299 notz: ; 300 } 301 302 /* Vertical tab to the appropriate position. Note here that 303 we make sure we don't move below limit. */ 304 if ( lnum > limit ) 305 { skip -= (lnum - limit); 306 lnum = limit; 307 } 308 while ( skip > 255 ) 309 { fputs("\033J\377", prn_stream); 310 skip -= 255; 311 } 312 if ( skip ) 313 fprintf(prn_stream, "\033J%c", skip); 314 315 /* If we've printed as far as "limit", then reset "limit" 316 to "last_row" for the final printing pass. */ 317 if ( lnum == limit ) 318 limit = last_row; 319 skip = 0; 320 321 /* Transpose in blocks of 8 scan lines. */ 322 for ( bnum = 0; bnum < bits_per_column; bnum += 8 ) 323 { int lcnt = min(8, limit - lnum); 324 byte *inp = in; 325 byte *outp = outl; 326 lcnt = gdev_prn_copy_scan_lines(pdev, 327 lnum, in, lcnt * line_size); 328 if ( lcnt < 0 ) 329 { code = lcnt; 330 goto xit; 331 } 332 if ( lcnt < 8 ) 333 memset(in + lcnt * line_size, 0, 334 (8 - lcnt) * line_size); 335 for ( ; inp < in_end; inp++, outp += bits_per_column ) 336 { gdev_prn_transpose_8x8(inp, line_size, 337 outp, bytes_per_column); 338 } 339 outl++; 340 lnum += lcnt; 341 skip += lcnt; 342 } 343 344 /* Send the bits to the printer. We alternate horizontal 345 skips with the data. The horizontal skips are in units 346 of 1/120 inches, so we look at the data in groups of 347 3 columns, since 3/360 = 1/120, and 3/180 = 2/120. */ 348 outl = out; 349 do 350 { int count; 351 int n; 352 byte *out_ptr; 353 354 /* First look for blank groups of columns. */ 355 while(outl < out_end) 356 { n = count = min(out_end - outl, skip_unit); 357 out_ptr = outl; 358 while ( --count >= 0 ) 359 { if ( *out_ptr++ ) 360 break; 361 } 362 if ( count >= 0 ) 363 break; 364 else 365 outl = out_ptr; 366 } 367 if (outl >= out_end) 368 break; 369 if (outl > out_beg) 370 { count = (outl - out_beg) / skip_unit; 371 if ( xres == 180 ) count <<= 1; 372 fprintf(prn_stream, "\033d%c%c", 373 count & 0xff, count >> 8); 374 } 375 376 /* Next look for non-blank groups of columns. */ 377 out_beg = outl; 378 outl += n; 379 while(outl < out_end) 380 { n = count = min(out_end - outl, skip_unit); 381 out_ptr = outl; 382 while ( --count >= 0 ) 383 { if ( *out_ptr++ ) 384 break; 385 } 386 if ( count < 0 ) 387 break; 388 else 389 outl += n; 390 } 391 count = outl - out_beg + 1; 392 fprintf(prn_stream, "\033[g%c%c%c", 393 count & 0xff, count >> 8, mode); 394 fwrite(out_beg, 1, count - 1, prn_stream); 395 out_beg = outl; 396 outl += n; 397 } 398 while ( out_beg < out_end ); 399 400 fputc('\r', prn_stream); 401 } 402 403 /* Eject the page */ 404 xit: fputc(014, prn_stream); /* form feed */ 405 fflush(prn_stream); 406 fin: if ( out != 0 ) 407 gs_free((char *)out, bits_per_column, line_size, 408 "bj10e_print_page(out)"); 409 if ( in != 0 ) 410 gs_free((char *)in, 8, line_size, "bj10e_print_page(in)"); 411 return code; 412 } 413