1 /* Copyright (C) 2001-2019 Artifex Software, Inc.
2 All Rights Reserved.
3
4 This software is provided AS-IS with no warranty, either express or
5 implied.
6
7 This software is distributed under license and may not be copied,
8 modified or distributed except as expressly authorized under the terms
9 of the license contained in the file LICENSE in this distribution.
10
11 Refer to licensing information at http://www.artifex.com or contact
12 Artifex Software, Inc., 1305 Grant Avenue - Suite 200, Novato,
13 CA 94945, U.S.A., +1(415)492-9861, for further information.
14 */
15
16 /* Canon LBP-8II and LIPS III driver */
17 #include "gdevprn.h"
18
19 /*
20 Modifications:
21 2.2.97 Lauri Paatero
22 Changed CSI command into ESC [. DCS commands may still need to be changed
23 (to ESC P).
24 4.9.96 Lauri Paatero
25 Corrected LBP-8II margins again. Real problem was that (0,0) is NOT
26 in upper left corner.
27 Now using relative addressing for vertical addressing. This avoids
28 problems
29 when printing to paper with wrong size.
30 18.6.96 Lauri Paatero, lauri.paatero@paatero.pp.fi
31 Corrected LBP-8II margins.
32 Added logic to recognize (and optimize away) long strings of 00's in data.
33 For LBP-8II removed use of 8-bit CSI (this does not work if 8-bit character
34 set has been configured in LBP-8II. (Perhaps this should also be done
35 for LBP-8III?)
36 Original versions:
37 LBP8 driver: Tom Quinn (trq@prg.oxford.ac.uk)
38 LIPS III driver: Kenji Okamoto (okamoto@okamoto.cias.osakafu-u.ac.jp)
39 */
40
41 #define X_DPI 300
42 #define Y_DPI 300
43
44 /* The device descriptors */
45 static dev_proc_print_page(lbp8_print_page);
46 #ifdef NOCONTRIB
47 static dev_proc_print_page(lips3_print_page);
48 #endif
49
50 const gx_device_printer far_data gs_lbp8_device =
51 prn_device(prn_bg_procs, "lbp8", /* The print_page proc is compatible with allowing bg printing */
52 DEFAULT_WIDTH_10THS, DEFAULT_HEIGHT_10THS,
53 X_DPI, Y_DPI,
54 0.16, 0.2, 0.32, 0.21, /* margins: left, bottom, right, top */
55 1, lbp8_print_page);
56
57 #ifdef NOCONTRIB
58 const gx_device_printer far_data gs_lips3_device =
59 prn_device(prn_bg_procs, "lips3", /* The print_page proc is compatible with allowing bg printing */
60 82, /* width_10ths, 8.3" */
61 117, /* height_10ths, 11.7" */
62 X_DPI, Y_DPI,
63 0.16, 0.27, 0.23, 0.27, /* margins */
64 1, lips3_print_page);
65 #endif
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 #ifdef NOCONTRIB
84 static const char lips3_init[] = {
85 ESC, '<', /* soft reset */
86 DCS, '0', 'J', ST, /* JOB END */
87 DCS, '3', '1', ';', '3', '0', '0', ';', '2', 'J', ST, /* 300dpi, LIPS3 JOB START */
88 ESC, '<', /* soft reset */
89 DCS, '2', 'y', 'P', 'r', 'i', 'n', 't', 'i', 'n', 'g', '(', 'g', 's', ')', ST, /* Printing (gs) display */
90 ESC, '[', '?', '1', 'l', /* auto cr-lf disable */
91 ESC, '[', '?', '2', 'h', /* auto ff disable */
92 ESC, '[', '1', '1', 'h', /* set mode */
93 ESC, '[', '7', ' ', 'I', /* select unit size (300dpi)*/
94 ESC, '[', 'f' /* move to home position */
95 };
96
97 static const char lips3_end[] = {
98 DCS, '0', 'J', ST /* JOB END */
99 };
100 #endif
101
102 /* Send the page to the printer. */
103 static int
can_print_page(gx_device_printer * pdev,gp_file * prn_stream,const char * init,int init_size,const char * end,int end_size)104 can_print_page(gx_device_printer *pdev, gp_file *prn_stream,
105 const char *init, int init_size, const char *end, int end_size)
106 {
107 char *data;
108 char *out_data;
109 int last_line_nro = 0;
110 int line_size = gdev_mem_bytes_per_scan_line((gx_device *)pdev);
111 int code = 0;
112
113 data = (char *)gs_alloc_bytes(pdev->memory,
114 line_size*2,
115 "lbp8_line_buffer");
116 if (data == NULL)
117 return_error(gs_error_VMerror);
118
119 gp_fwrite(init, init_size, 1, prn_stream); /* initialize */
120
121 /* Send each scan line in turn */
122 {
123 int lnum;
124 byte rmask = (byte)(0xff << (-pdev->width & 7));
125
126 for ( lnum = 0; lnum < pdev->height; lnum++ ) {
127 char *end_data = data + line_size;
128 code = gdev_prn_copy_scan_lines(pdev, lnum,
129 (byte *)data, line_size);
130 if (code < 0)
131 goto xit;
132 /* Mask off 1-bits beyond the line width. */
133 end_data[-1] &= rmask;
134 /* Remove trailing 0s. */
135 while ( end_data > data && end_data[-1] == 0 )
136 end_data--;
137 if ( end_data != data ) {
138 int num_cols = 0;
139 int out_count;
140 int zero_count;
141 out_data = data;
142
143 /* move down */
144 gp_fprintf(prn_stream, "%c[%de",
145 ESC, lnum-last_line_nro );
146 last_line_nro = lnum;
147
148 while (out_data < end_data) {
149 /* Remove leading 0s*/
150 while(out_data < end_data && *out_data == 0) {
151 num_cols += 8;
152 out_data++;
153 }
154
155 out_count = end_data - out_data;
156 zero_count = 0;
157
158 /* if there is a lot data, find if there is sequence of zeros */
159 if (out_count>22) {
160
161 out_count = 1;
162
163 while(out_data+out_count+zero_count < end_data) {
164 if (out_data[zero_count+out_count] != 0) {
165 out_count += 1+zero_count;
166 zero_count = 0;
167 }
168 else {
169 zero_count++;
170 if (zero_count>20)
171 break;
172 }
173 }
174
175 }
176
177 if (out_count==0)
178 break;
179
180 /* move down and across*/
181 gp_fprintf(prn_stream, "%c[%d`",
182 ESC, num_cols );
183 /* transfer raster graphic command */
184 gp_fprintf(prn_stream, "%c[%d;%d;300;.r",
185 ESC, out_count, out_count);
186
187 /* send the row */
188 gp_fwrite(out_data, sizeof(char),
189 out_count, prn_stream);
190
191 out_data += out_count+zero_count;
192 num_cols += 8*(out_count+zero_count);
193 }
194 }
195 }
196 }
197
198 /* eject page */
199 gp_fprintf(prn_stream, "%c=", ESC);
200
201 /* terminate */
202 if (end != NULL)
203 (void)gp_fwrite(end, end_size, 1, prn_stream);
204
205 xit:
206 gs_free_object(pdev->memory, data, "lbp8_line_buffer");
207
208 return code;
209 }
210
211 /* Print an LBP-8 page. */
212 static int
lbp8_print_page(gx_device_printer * pdev,gp_file * prn_stream)213 lbp8_print_page(gx_device_printer *pdev, gp_file *prn_stream)
214 {
215 return can_print_page(pdev, prn_stream, lbp8_init, sizeof(lbp8_init),
216 NULL, 0);
217 }
218
219 #ifdef NOCONTRIB
220 /* Print a LIPS III page. */
221 static int
lips3_print_page(gx_device_printer * pdev,gp_file * prn_stream)222 lips3_print_page(gx_device_printer *pdev, gp_file *prn_stream)
223 { return can_print_page(pdev, prn_stream, lips3_init, sizeof(lips3_init),
224 lips3_end, sizeof(lips3_end));
225 }
226 #endif
227