1 /* Copyright (C) 1991, 1994, 1996, 1997 artofcode LLC.  All rights reserved.
2 
3   This program is free software; you can redistribute it and/or modify it
4   under the terms of the GNU General Public License as published by the
5   Free Software Foundation; either version 2 of the License, or (at your
6   option) any later version.
7 
8   This program is distributed in the hope that it will be useful, but
9   WITHOUT ANY WARRANTY; without even the implied warranty of
10   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
11   General Public License for more details.
12 
13   You should have received a copy of the GNU General Public License along
14   with this program; if not, write to the Free Software Foundation, Inc.,
15   59 Temple Place, Suite 330, Boston, MA, 02111-1307.
16 
17 */
18 
19 /*$Id: gdevlbp8.c,v 1.3.2.1.2.1 2003/01/17 00:49:00 giles Exp $*/
20 /* Canon LBP-8II and LIPS III driver */
21 #include "gdevprn.h"
22 
23 /*
24   Modifications:
25     3.10.00 Johnny Lam
26             Removed LIPS III code, as it's obsoleted by gdevlips driver.
27     2.2.97  Lauri Paatero
28             Changed CSI command into ESC [. DCS commands may still need to be changed
29             (to ESC P).
30     4.9.96  Lauri Paatero
31 	    Corrected LBP-8II margins again. Real problem was that (0,0) is NOT
32                 in upper left corner.
33 	    Now using relative addressing for vertical addressing. This avoids
34 problems
35                 when printing to paper with wrong size.
36     18.6.96 Lauri Paatero, lauri.paatero@paatero.pp.fi
37             Corrected LBP-8II margins.
38             Added logic to recognize (and optimize away) long strings of 00's in data.
39             For LBP-8II removed use of 8-bit CSI (this does not work if 8-bit character
40                 set has been configured in LBP-8II. (Perhaps this should also be done
41                 for LBP-8III?)
42   Original versions:
43     LBP8 driver: Tom Quinn (trq@prg.oxford.ac.uk)
44     LIPS III driver: Kenji Okamoto (okamoto@okamoto.cias.osakafu-u.ac.jp)
45 */
46 
47 
48 #define X_DPI 300
49 #define Y_DPI 300
50 #define LINE_SIZE ((X_DPI * 85 / 10 + 7) / 8)	/* bytes per line */
51 
52 /* The device descriptors */
53 private dev_proc_print_page(lbp8_print_page);
54 
55 const gx_device_printer far_data gs_lbp8_device =
56   prn_device(prn_std_procs, "lbp8",
57 	DEFAULT_WIDTH_10THS, DEFAULT_HEIGHT_10THS,
58 	X_DPI, Y_DPI,
59 	0.16, 0.2, 0.32, 0.21,		/* margins: left, bottom, right, top */
60 	1, lbp8_print_page);
61 
62 /* ------ Internal routines ------ */
63 
64 #define ESC 0x1b
65 #define CSI 0233
66 #define DCS 0220
67 #define ST 0234
68 
69 static const char lbp8_init[] = {
70   ESC, ';', ESC, 'c', ESC, ';', /* reset, ISO */
71   ESC, '[', '2', '&', 'z',	/* fullpaint mode */
72   ESC, '[', '1', '4', 'p',	/* select page type (A4) */
73   ESC, '[', '1', '1', 'h',	/* set mode */
74   ESC, '[', '7', ' ', 'I',	/* select unit size (300dpi)*/
75   ESC, '[', '6', '3', 'k', 	/* Move 63 dots up (to top of printable area) */
76 };
77 
78 static const char *lbp8_end = NULL;
79 
80 /* Send the page to the printer.  */
81 private int
can_print_page(gx_device_printer * pdev,FILE * prn_stream,const char * init,int init_size,const char * end,int end_size)82 can_print_page(gx_device_printer *pdev, FILE *prn_stream,
83   const char *init, int init_size, const char *end, int end_size)
84 {
85 	char data[LINE_SIZE*2];
86 	char *out_data;
87 	int last_line_nro = 0;
88 
89 	fwrite(init, init_size, 1, prn_stream);		/* initialize */
90 
91 	/* Send each scan line in turn */
92 	{
93 	    int lnum;
94 	    int line_size = gdev_mem_bytes_per_scan_line((gx_device *)pdev);
95 	    byte rmask = (byte)(0xff << (-pdev->width & 7));
96 
97 	    for ( lnum = 0; lnum < pdev->height; lnum++ ) {
98     		char *end_data = data + LINE_SIZE;
99 		gdev_prn_copy_scan_lines(pdev, lnum,
100 					 (byte *)data, line_size);
101 	   	/* Mask off 1-bits beyond the line width. */
102 		end_data[-1] &= rmask;
103 		/* Remove trailing 0s. */
104 		while ( end_data > data && end_data[-1] == 0 )
105 			end_data--;
106 		if ( end_data != data ) {
107 		    int num_cols = 0;
108 		    int out_count;
109 		    int zero_count;
110 		    out_data = data;
111 
112 		    /* move down */
113 		    fprintf(prn_stream, "%c[%de",
114 			    ESC, lnum-last_line_nro );
115 		    last_line_nro = lnum;
116 
117 		    while (out_data < end_data) {
118 			/* Remove leading 0s*/
119 			while(out_data < end_data && *out_data == 0) {
120 		            num_cols += 8;
121                             out_data++;
122                         }
123 
124 			out_count = end_data - out_data;
125 			zero_count = 0;
126 
127 			/* if there is a lot data, find if there is sequence of zeros */
128 			if (out_count>22) {
129 
130 				out_count = 1;
131 
132 				while(out_data+out_count+zero_count < end_data) {
133 					if (out_data[zero_count+out_count] != 0) {
134 						out_count += 1+zero_count;
135 						zero_count = 0;
136 					}
137 					else {
138 						zero_count++;
139 						if (zero_count>20)
140 							break;
141 					}
142 				}
143 
144 			}
145 
146 			if (out_count==0)
147 				break;
148 
149 			/* move down and across*/
150 			fprintf(prn_stream, "%c[%d`",
151 				ESC, num_cols );
152 			/* transfer raster graphic command */
153 			fprintf(prn_stream, "%c[%d;%d;300;.r",
154 				ESC, out_count, out_count);
155 
156 			/* send the row */
157 			fwrite(out_data, sizeof(char),
158                                out_count, prn_stream);
159 
160 			out_data += out_count+zero_count;
161                	        num_cols += 8*(out_count+zero_count);
162 		    }
163 		}
164 	    }
165 	}
166 
167 	/* eject page */
168 	fprintf(prn_stream, "%c=", ESC);
169 
170 	/* terminate */
171 	if (end != NULL)
172 	    fwrite(end, end_size, 1, prn_stream);
173 
174 	return 0;
175 }
176 
177 /* Print an LBP-8 page. */
178 private int
lbp8_print_page(gx_device_printer * pdev,FILE * prn_stream)179 lbp8_print_page(gx_device_printer *pdev, FILE *prn_stream)
180 {	return can_print_page(pdev, prn_stream, lbp8_init, sizeof(lbp8_init),
181 			      lbp8_end, sizeof(lbp8_end));
182 }
183