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