1 /* Copyright (C) 1993, 1996 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: gdevo182.c,v 1.6 2004/08/10 13:02:36 stefan Exp $*/
18 /* Okidata Microline 182 printer driver */
19
20 /* Contributed by Maarten Koning (smeg@bnr.ca) April 4, 1993 */
21
22 /****************************************************************
23
24 I use this driver from Unix with the following aliases:
25
26 alias psp "gs -q -sDEVICE=oki182 -sOutputFile=\|lpr - <\!*"
27 alias psphigh "gs -q -sDEVICE=oki182 -r144 -sOutputFile=\|lpr - <\!*"
28
29 ps. I have my printer DIP switches set to the following (as viewed
30 while standing in front of your printer looking down into the
31 config access hatch located at the top of your printer
32 in the centre back).
33
34 Upper Upper Bottom
35 Left Right (at right)
36
37 x x x
38 x x x
39 x x x
40 x x x
41 x x x
42 x x x
43 x x x
44 x x x
45
46 The upper DIP switches are on a SuperSpeed Serial
47 card that will do 19200 baud. I have it set at 9600
48 baud since that seems sufficient to keep the printer
49 busy.
50
51 The important thing is to be in 8-bit mode so that
52 the graphics data can't match any Okidata commands
53 (This driver sets the high bit of graphics data to 1).
54
55 ****************************************************************/
56
57 #include "gdevprn.h"
58
59 /*
60 * Available resolutions are 72x72 or 144x144;
61 * (144x72) would be possible to do also, but I didn't bother)
62 */
63
64 /* The device descriptor */
65
66 private dev_proc_print_page(oki_print_page);
67
68 const gx_device_printer far_data gs_oki182_device =
69 prn_device(prn_std_procs, "oki182",
70 80, /* width_10ths, 8.0" */
71 110, /* height_10ths, 11" */
72 72, /* x_dpi */
73 72, /* y_dpi */
74 0, 0, 0, 0, /* margins */
75 1, oki_print_page);
76
77 /* ------ internal routines ------ */
78
79 /* out is a pointer to an array of 7 scan lines,
80 lineSize is the number of bytes between a pixel and
81 the pixel directly beneath it.
82 scanBits is the number of bits in each scan line
83 out is a pointer to an array of column data, which
84 is how the Okidata wants the graphics image.
85
86 each column of graphics data is 7 bits high and
87 is encoded in a byte - highest pixel in the column
88 is the lowest bit in the byte. The upper bit of the
89 byte is set so that the okidata doesn't mistake
90 graphic image data for graphic commands.
91 */
92
93 private void
oki_transpose(byte * in,byte * out,int scanBits,register int lineSize)94 oki_transpose(byte *in, byte *out, int scanBits, register int lineSize)
95 {
96 register bitMask = 0x80;
97 register byte *inPtr;
98 register byte outByte;
99
100 while (scanBits-- > 0) {
101
102 inPtr = in;
103
104 if (*inPtr & bitMask)
105 outByte = 0x81;
106 else
107 outByte = 0x80;
108 if (*(inPtr += lineSize) & bitMask)
109 outByte += 0x02;
110 if (*(inPtr += lineSize) & bitMask)
111 outByte += 0x04;
112 if (*(inPtr += lineSize) & bitMask)
113 outByte += 0x08;
114 if (*(inPtr += lineSize) & bitMask)
115 outByte += 0x10;
116 if (*(inPtr += lineSize) & bitMask)
117 outByte += 0x20;
118 if (*(inPtr += lineSize) & bitMask)
119 outByte += 0x40;
120
121 *out++ = outByte;
122
123 if ((bitMask >>= 1) == 0) {
124 bitMask = 0x80;
125 in ++;
126 }
127 }
128 }
129
130 /* This routine tries to compress a sequence of okidata
131 graphic bytes by trimming off leading and trailing
132 zeros. Trailing zeros can be thrown away and leading
133 zeros can be replaced with a much smaller number of spaces.
134
135 'in' is a pointer to the graphic bytes to be compressed.
136 origWidth is the number of bytes pointed to by 'in'.
137 highRes is non-zero when 144x144 mode is being used.
138
139 numSpaces is set to the number of spaces that should
140 be printed before the compressed image. newWidth is
141 the new number of bytes that the return value of this
142 function points to.
143
144 xxx - A future enhancement would be to replace long sequences
145 of embedded zeros with exit.graphics-<n> spaces-enter.graphics
146 */
147 private byte *
oki_compress(byte * in,int origWidth,int highRes,int * numSpaces,int * newWidth)148 oki_compress(byte *in, int origWidth, int highRes,
149 int *numSpaces, int *newWidth)
150 {
151 int spaces = 0;
152 int columns_per_space = 6;
153
154 byte *in_end = in + origWidth;
155
156 /* remove trailing zeros (which are realy 0x80's) */
157 while (in_end > in && in_end[-1] == 0x80)
158 in_end --;
159
160 if (highRes)
161 columns_per_space = 12;
162
163 /* remove leading zeros that can be replaced by spaces */
164 while(in < in_end && in[0] == 0x80 && memcmp((char *)in,
165 (char *)in + 1, columns_per_space - 1) == 0) {
166 spaces++;
167 in += columns_per_space;
168 }
169
170 *numSpaces = spaces;
171
172 /* just in case we compressed this line out of existance */
173 if (in_end > in)
174 *newWidth = in_end - in;
175 else
176 *newWidth = 0;
177
178 return(in);
179 }
180
181 /* Send the page to the printer. */
182
183 private int
oki_print_page(gx_device_printer * pdev,FILE * prn_stream)184 oki_print_page(gx_device_printer *pdev, FILE *prn_stream)
185 {
186 int highRes = pdev->y_pixels_per_inch > 100;
187 int bits_per_column = 7;
188 int i, spaces, width;
189 int lcnt;
190
191 int line_size = gdev_prn_raster((gx_device_printer *)pdev);
192
193 byte *in = (byte *)gs_malloc(pdev->memory, 16, line_size, "oki_print_page(in)");
194
195 byte *out1 = (byte *)gs_malloc(pdev->memory, 8, line_size, "oki_print_page(out1)");
196 byte *out2 = (byte *)gs_malloc(pdev->memory, 8, line_size, "oki_print_page(out2)");
197
198 byte *out3;
199
200 int lnum = 0;
201 int skip = 0;
202 int code = 0;
203
204 if ( in == 0 || out1 == 0 || out2 == 0)
205 { code = gs_error_VMerror;
206 gs_note_error(code);
207 goto bail;
208 }
209
210 /* Initialize the printer. */
211 /* CAN; 72x72; left margin = 001; disable skip over perforation */
212 fwrite("\030\034\033%C001\033%S0", 1, 12, prn_stream);
213
214 if (highRes) {
215 fwrite("\033R", 1, 2, prn_stream);
216 bits_per_column = 14;
217 }
218
219 /* Transfer pixels to printer */
220 while ( lnum < pdev->height ) {
221
222 /* Copy 1 scan line and test for all zero. */
223 code = gdev_prn_copy_scan_lines(pdev, lnum, in, line_size);
224 if ( code < 0 )
225 goto xit;
226
227 /* if line is all zero, skip */
228 if ( in[0] == 0 && !memcmp((char *)in, (char *)in + 1,
229 line_size - 1)) {
230 lnum++;
231 if (highRes)
232 skip++;
233 else
234 skip += 2;
235 continue;
236 }
237
238 /* use fine line feed to get to the appropriate position. */
239 while ( skip > 127 ) {
240 fputs("\033%5\177", prn_stream);
241 skip -= 127;
242 }
243 if ( skip )
244 fprintf(prn_stream, "\033%%5%c",
245 (char) (skip & 0xff));
246 skip = 0;
247
248 /* get the rest of the scan lines */
249 code = gdev_prn_copy_scan_lines(pdev, lnum + 1,
250 in + line_size, (bits_per_column - 1) * line_size);
251
252 if ( code < 0 )
253 goto xit;
254
255 lcnt = code + 1; /* since we already grabbed one line */
256
257 if ( lcnt < bits_per_column )
258 memset(in + lcnt * line_size, 0,
259 (bits_per_column - lcnt) * line_size);
260
261 if (highRes) {
262 oki_transpose(in, out1, pdev->width, 2 * line_size);
263 oki_transpose(in + line_size, out2,
264 pdev->width, 2 * line_size);
265 } else
266 oki_transpose(in, out1, pdev->width, line_size);
267
268 out3 = oki_compress(out1, pdev->width, highRes,
269 &spaces, &width);
270
271 for (i=0; i < spaces; i++)
272 putc(' ', prn_stream);
273
274 fwrite("\003", 1, 1, prn_stream);
275 fwrite(out3, 1, width, prn_stream);
276
277 if (highRes) {
278 /* exit graphics; carriage return; 1 bit line feed */
279 fprintf(prn_stream, "\003\002\015\033%%5%c", (char) 1);
280 out3 = oki_compress(out2, pdev->width, highRes,
281 &spaces, &width);
282 for (i=0; i < spaces; i++)
283 putc(' ', prn_stream);
284 fwrite("\003", 1, 1, prn_stream);
285 fwrite(out3, 1, width, prn_stream);
286 fprintf(prn_stream, "\003\002\015\033%%5%c", (char) 13);
287 } else
288 fwrite("\003\016\003\002", 1, 4, prn_stream);
289
290 lnum += bits_per_column;
291 }
292
293 /* Eject the page */
294 xit:
295 fputc(014, prn_stream); /* form feed */
296 fflush(prn_stream);
297
298 bail:
299 if ( out1 != 0 )
300 gs_free(pdev->memory, (char *)out1, 8, line_size, "oki_print_page(out1)");
301
302 if ( out2 != 0 )
303 gs_free(pdev->memory, (char *)out2, 8, line_size, "oki_print_page(out2)");
304
305 if ( in != 0 )
306 gs_free(pdev->memory, (char *)in, 16, line_size, "oki_print_page(in)");
307
308 return code;
309 }
310