xref: /plan9/sys/src/cmd/gs/src/gdevlbp8.c (revision 593dc095aefb2a85c828727bbfa9da139a49bdf4)
1 /* Copyright (C) 1991, 1994, 1996, 1997 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: gdevlbp8.c,v 1.6 2002/10/07 08:28:56 ghostgum Exp $*/
18 /* Canon LBP-8II and LIPS III driver */
19 #include "gdevprn.h"
20 
21 /*
22   Modifications:
23     2.2.97  Lauri Paatero
24             Changed CSI command into ESC [. DCS commands may still need to be changed
25             (to ESC P).
26     4.9.96  Lauri Paatero
27 	    Corrected LBP-8II margins again. Real problem was that (0,0) is NOT
28                 in upper left corner.
29 	    Now using relative addressing for vertical addressing. This avoids
30 problems
31                 when printing to paper with wrong size.
32     18.6.96 Lauri Paatero, lauri.paatero@paatero.pp.fi
33             Corrected LBP-8II margins.
34             Added logic to recognize (and optimize away) long strings of 00's in data.
35             For LBP-8II removed use of 8-bit CSI (this does not work if 8-bit character
36                 set has been configured in LBP-8II. (Perhaps this should also be done
37                 for LBP-8III?)
38   Original versions:
39     LBP8 driver: Tom Quinn (trq@prg.oxford.ac.uk)
40     LIPS III driver: Kenji Okamoto (okamoto@okamoto.cias.osakafu-u.ac.jp)
41 */
42 
43 
44 #define X_DPI 300
45 #define Y_DPI 300
46 #define LINE_SIZE ((X_DPI * 85 / 10 + 7) / 8)	/* bytes per line */
47 
48 /* The device descriptors */
49 private dev_proc_print_page(lbp8_print_page);
50 private dev_proc_print_page(lips3_print_page);
51 
52 const gx_device_printer far_data gs_lbp8_device =
53   prn_device(prn_std_procs, "lbp8",
54 	DEFAULT_WIDTH_10THS, DEFAULT_HEIGHT_10THS,
55 	X_DPI, Y_DPI,
56 	0.16, 0.2, 0.32, 0.21,		/* margins: left, bottom, right, top */
57 	1, lbp8_print_page);
58 
59 const gx_device_printer far_data gs_lips3_device =
60   prn_device(prn_std_procs, "lips3",
61 	82,				/* width_10ths, 8.3" */
62 	117,				/* height_10ths, 11.7" */
63 	X_DPI, Y_DPI,
64 	0.16, 0.27, 0.23, 0.27,		/* margins */
65 	1, lips3_print_page);
66 
67 /* ------ Internal routines ------ */
68 
69 #define ESC (char)0x1b
70 #define CSI '\233'
71 #define DCS '\220'
72 #define ST '\234'
73 
74 static const char lbp8_init[] = {
75   ESC, ';', ESC, 'c', ESC, ';', /* reset, ISO */
76   ESC, '[', '2', '&', 'z',	/* fullpaint mode */
77   ESC, '[', '1', '4', 'p',	/* select page type (A4) */
78   ESC, '[', '1', '1', 'h',	/* set mode */
79   ESC, '[', '7', ' ', 'I',	/* select unit size (300dpi)*/
80   ESC, '[', '6', '3', 'k', 	/* Move 63 dots up (to top of printable area) */
81 };
82 
83 static const char *lbp8_end = NULL;
84 
85 static const char lips3_init[] = {
86   ESC, '<', /* soft reset */
87   DCS, '0', 'J', ST, /* JOB END */
88   DCS, '3', '1', ';', '3', '0', '0', ';', '2', 'J', ST, /* 300dpi, LIPS3 JOB START */
89   ESC, '<',  /* soft reset */
90   DCS, '2', 'y', 'P', 'r', 'i', 'n', 't', 'i', 'n', 'g', '(', 'g', 's', ')', ST,  /* Printing (gs) display */
91   ESC, '[', '?', '1', 'l',  /* auto cr-lf disable */
92   ESC, '[', '?', '2', 'h', /* auto ff disable */
93   ESC, '[', '1', '1', 'h', /* set mode */
94   ESC, '[', '7', ' ', 'I', /* select unit size (300dpi)*/
95   ESC, '[', 'f' /* move to home position */
96 };
97 
98 static const char lips3_end[] = {
99   DCS, '0', 'J', ST  /* JOB END */
100 };
101 
102 /* Send the page to the printer.  */
103 private int
can_print_page(gx_device_printer * pdev,FILE * prn_stream,const char * init,int init_size,const char * end,int end_size)104 can_print_page(gx_device_printer *pdev, FILE *prn_stream,
105   const char *init, int init_size, const char *end, int end_size)
106 {
107 	char data[LINE_SIZE*2];
108 	char *out_data;
109 	int last_line_nro = 0;
110 
111 	fwrite(init, init_size, 1, prn_stream);		/* initialize */
112 
113 	/* Send each scan line in turn */
114 	{
115 	    int lnum;
116 	    int line_size = gdev_mem_bytes_per_scan_line((gx_device *)pdev);
117 	    byte rmask = (byte)(0xff << (-pdev->width & 7));
118 
119 	    for ( lnum = 0; lnum < pdev->height; lnum++ ) {
120     		char *end_data = data + LINE_SIZE;
121 		gdev_prn_copy_scan_lines(pdev, lnum,
122 					 (byte *)data, line_size);
123 	   	/* Mask off 1-bits beyond the line width. */
124 		end_data[-1] &= rmask;
125 		/* Remove trailing 0s. */
126 		while ( end_data > data && end_data[-1] == 0 )
127 			end_data--;
128 		if ( end_data != data ) {
129 		    int num_cols = 0;
130 		    int out_count;
131 		    int zero_count;
132 		    out_data = data;
133 
134 		    /* move down */
135 		    fprintf(prn_stream, "%c[%de",
136 			    ESC, lnum-last_line_nro );
137 		    last_line_nro = lnum;
138 
139 		    while (out_data < end_data) {
140 			/* Remove leading 0s*/
141 			while(out_data < end_data && *out_data == 0) {
142 		            num_cols += 8;
143                             out_data++;
144                         }
145 
146 			out_count = end_data - out_data;
147 			zero_count = 0;
148 
149 			/* if there is a lot data, find if there is sequence of zeros */
150 			if (out_count>22) {
151 
152 				out_count = 1;
153 
154 				while(out_data+out_count+zero_count < end_data) {
155 					if (out_data[zero_count+out_count] != 0) {
156 						out_count += 1+zero_count;
157 						zero_count = 0;
158 					}
159 					else {
160 						zero_count++;
161 						if (zero_count>20)
162 							break;
163 					}
164 				}
165 
166 			}
167 
168 			if (out_count==0)
169 				break;
170 
171 			/* move down and across*/
172 			fprintf(prn_stream, "%c[%d`",
173 				ESC, num_cols );
174 			/* transfer raster graphic command */
175 			fprintf(prn_stream, "%c[%d;%d;300;.r",
176 				ESC, out_count, out_count);
177 
178 			/* send the row */
179 			fwrite(out_data, sizeof(char),
180                                out_count, prn_stream);
181 
182 			out_data += out_count+zero_count;
183                	        num_cols += 8*(out_count+zero_count);
184 		    }
185 		}
186 	    }
187 	}
188 
189 	/* eject page */
190 	fprintf(prn_stream, "%c=", ESC);
191 
192 	/* terminate */
193 	if (end != NULL)
194 	    fwrite(end, end_size, 1, prn_stream);
195 
196 	return 0;
197 }
198 
199 /* Print an LBP-8 page. */
200 private int
lbp8_print_page(gx_device_printer * pdev,FILE * prn_stream)201 lbp8_print_page(gx_device_printer *pdev, FILE *prn_stream)
202 {	return can_print_page(pdev, prn_stream, lbp8_init, sizeof(lbp8_init),
203 			      lbp8_end, sizeof(lbp8_end));
204 }
205 
206 /* Print a LIPS III page. */
207 private int
lips3_print_page(gx_device_printer * pdev,FILE * prn_stream)208 lips3_print_page(gx_device_printer *pdev, FILE *prn_stream)
209 {	return can_print_page(pdev, prn_stream, lips3_init, sizeof(lips3_init),
210 			      lips3_end, sizeof(lips3_end));
211 }
212