Subversion Repositories planix.SVN

Rev

Rev 2 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
2 - 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
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 *
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
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
}