xref: /plan9-contrib/sys/src/cmd/gs/src/gdevbj10.c (revision d46c239f8612929b7dbade67d0d071633df3a15d)
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