Subversion Repositories planix.SVN

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
2 - 1
/* Copyright (C) 1989, 1992, 1995 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: gdevokii.c,v 1.7 2004/08/10 13:02:36 stefan Exp $*/
18
/*
19
 * Okidata IBM compatible dot-matrix printer driver for Ghostscript.
20
 *
21
 * This device is for the Okidata Microline IBM compatible 9 pin dot
22
 * matrix printers.  It is derived from the Epson 9 pin printer driver
23
 * using the standard 1/72" vertical pin spacing and the 60/120/240
24
 * dpi horizontal resolutions.  The vertical feed resolution however
25
 * is 1/144" and the Okidata implements the standard 1/216" requests
26
 * through "scaling":
27
 *
28
 *   (power on)
29
 *   "\033J\001" (vertical feed 1/216")  => Nothing happens
30
 *   "\033J\001" (vertical feed 1/216")  => Advance 1/144"
31
 *   "\033J\001" (vertical feed 1/216")  => Advance 1/144"
32
 *   "\033J\001" (vertical feed 1/216")  => Nothing happens
33
 *   (and so on)
34
 *
35
 * The simple minded accounting used here keep track of when the
36
 * page actually advances assumes the printer starts in a "power on"
37
 * state.
38
 * 
39
 * Supported resolutions are:
40
 *
41
 *    60x72      60x144
42
 *   120x72     120x144
43
 *   240x72     240x144
44
 *
45
 */
46
#include "gdevprn.h"
47
 
48
/*
49
 * Valid values for X_DPI:
50
 *
51
 *     60, 120, 240
52
 *
53
 * The value specified at compile time is the default value used if the
54
 * user does not specify a resolution at runtime.
55
 */
56
 
57
#ifndef X_DPI
58
#  define X_DPI 120
59
#endif
60
 
61
/*
62
 * Valid values for Y_DPI:
63
 *
64
 *     72, 144
65
 *
66
 * The value specified at compile time is the default value used if the
67
 * user does not specify a resolution at runtime.
68
 */
69
 
70
#ifndef Y_DPI
71
#  define Y_DPI 72
72
#endif
73
 
74
/* The device descriptor */
75
private dev_proc_print_page(okiibm_print_page);
76
 
77
/* Okidata IBM device */
78
const gx_device_printer far_data gs_okiibm_device =
79
  prn_device(prn_std_procs, "okiibm",
80
	DEFAULT_WIDTH_10THS, DEFAULT_HEIGHT_10THS,
81
	X_DPI, Y_DPI,
82
	0.25, 0.0, 0.25, 0.0,			/* margins */
83
	1, okiibm_print_page);
84
 
85
/* ------ Internal routines ------ */
86
 
87
/* Forward references */
88
private void okiibm_output_run(byte *, int, int, char, FILE *, int);
89
 
90
/* Send the page to the printer. */
91
private int
92
okiibm_print_page1(gx_device_printer *pdev, FILE *prn_stream, int y_9pin_high,
93
  const char *init_string, int init_length,
94
  const char *end_string, int end_length)
95
{	
96
	static const char graphics_modes_9[5] =
97
	{	
98
	-1, 0 /*60*/, 1 /*120*/, -1, 3 /*240*/
99
	};
100
 
101
	int in_y_mult = (y_9pin_high ? 2 : 1);
102
	int line_size = gdev_mem_bytes_per_scan_line((gx_device *)pdev);
103
	/* Note that in_size is a multiple of 8. */
104
	int in_size = line_size * (8 * in_y_mult);
105
	byte *buf1 = (byte *)gs_malloc(pdev->memory, in_size, 1, "okiibm_print_page(buf1)");
106
	byte *buf2 = (byte *)gs_malloc(pdev->memory, in_size, 1, "okiibm_print_page(buf2)");
107
	byte *in = buf1;
108
	byte *out = buf2;
109
	int out_y_mult = 1;
110
	int x_dpi = pdev->x_pixels_per_inch;
111
	char start_graphics = graphics_modes_9[x_dpi / 60];
112
	int first_pass = (start_graphics == 3 ? 1 : 0);
113
	int last_pass = first_pass * 2;
114
	int y_passes = (y_9pin_high ? 2 : 1);
115
	int skip = 0, lnum = 0, pass, ypass;
116
	int y_step = 0;
117
 
118
	/* Check allocations */
119
	if ( buf1 == 0 || buf2 == 0 )
120
	{	if ( buf1 ) 
121
		  gs_free(pdev->memory, (char *)buf1, in_size, 1, "okiibm_print_page(buf1)");
122
		if ( buf2 ) 
123
		  gs_free(pdev->memory, (char *)buf2, in_size, 1, "okiibm_print_page(buf2)");
124
		return_error(gs_error_VMerror);
125
	}
126
 
127
	/* Initialize the printer. */
128
	fwrite(init_string, 1, init_length, prn_stream);
129
 
130
	/* Print lines of graphics */
131
	while ( lnum < pdev->height )
132
	{	
133
		byte *in_data;
134
		byte *inp;
135
		byte *in_end;
136
		byte *out_end;
137
		int lcnt;
138
 
139
		/* Copy 1 scan line and test for all zero. */
140
		gdev_prn_get_bits(pdev, lnum, in, &in_data);
141
		if ( in_data[0] == 0 &&
142
		     !memcmp((char *)in_data, (char *)in_data + 1, line_size - 1)
143
		   )
144
	    	{	
145
			lnum++;
146
			skip += 2 / in_y_mult;
147
			continue;
148
		}
149
 
150
		/*
151
		 * Vertical tab to the appropriate position.
152
		 * The skip count is in 1/144" steps.  If total
153
		 * vertical request is not a multiple od 1/72"
154
		 * we need to make sure the page is actually
155
		 * going to advance.
156
		 */
157
		if ( skip & 1 )
158
		{
159
			int n = 1 + (y_step == 0 ? 1 : 0);
160
			fprintf(prn_stream, "\033J%c", n);
161
			y_step = (y_step + n) % 3;
162
			skip -= 1;
163
		}
164
		skip = skip / 2 * 3;
165
		while ( skip > 255 )
166
		{	
167
			fputs("\033J\377", prn_stream);
168
			skip -= 255;
169
		}
170
		if ( skip )
171
		{
172
			fprintf(prn_stream, "\033J%c", skip);
173
		}
174
 
175
		/* Copy the the scan lines. */
176
	    	lcnt = gdev_prn_copy_scan_lines(pdev, lnum, in, in_size);
177
		if ( lcnt < 8 * in_y_mult )
178
		{	/* Pad with lines of zeros. */
179
			memset(in + lcnt * line_size, 0,
180
			       in_size - lcnt * line_size);
181
		}
182
 
183
		if ( y_9pin_high )
184
		{	/* Shuffle the scan lines */
185
			byte *p;
186
			int i;
187
			static const char index[] =
188
			{  0, 2, 4, 6, 8, 10, 12, 14,
189
			   1, 3, 5, 7, 9, 11, 13, 15
190
			};
191
			for ( i = 0; i < 16; i++ )
192
			{
193
				memcpy( out + (i * line_size),
194
				        in + (index[i] * line_size),
195
				        line_size);
196
			}
197
			p = in;
198
			in = out;
199
			out = p;
200
		}
201
 
202
	for ( ypass = 0; ypass < y_passes; ypass++ )
203
	{
204
	    for ( pass = first_pass; pass <= last_pass; pass++ )
205
	    {
206
		/* We have to 'transpose' blocks of 8 pixels x 8 lines, */
207
		/* because that's how the printer wants the data. */
208
 
209
	        if ( pass == first_pass )
210
	        {
211
		    out_end = out;
212
		    inp = in;
213
		    in_end = inp + line_size;
214
 
215
    	            for ( ; inp < in_end; inp++, out_end += 8 )
216
    	            { 
217
    		        gdev_prn_transpose_8x8(inp + (ypass * 8 * line_size), 
218
					       line_size, out_end, 1);
219
		    }
220
		    /* Remove trailing 0s. */
221
		    while ( out_end > out && out_end[-1] == 0 )
222
	            {
223
		       	out_end--;
224
		    }
225
		}
226
 
227
		/* Transfer whatever is left and print. */
228
		if ( out_end > out )
229
	        {
230
		    okiibm_output_run(out, (int)(out_end - out),
231
			           out_y_mult, start_graphics,
232
				   prn_stream, pass);
233
	        }
234
	    	fputc('\r', prn_stream);
235
	    }
236
	    if ( ypass < y_passes - 1 )
237
	    {
238
		int n = 1 + (y_step == 0 ? 1 : 0);
239
		fprintf(prn_stream, "\033J%c", n);
240
		y_step = (y_step + n) % 3;
241
	    }
242
	}
243
	skip = 16 - y_passes + 1;		/* no skip on last Y pass */
244
	lnum += 8 * in_y_mult;
245
	}
246
 
247
	/* Reinitialize the printer. */
248
	fwrite(end_string, 1, end_length, prn_stream);
249
	fflush(prn_stream);
250
 
251
	gs_free(pdev->memory, (char *)buf2, in_size, 1, "okiibm_print_page(buf2)");
252
	gs_free(pdev->memory, (char *)buf1, in_size, 1, "okiibm_print_page(buf1)");
253
	return 0;
254
}
255
 
256
/* Output a single graphics command. */
257
/* pass=0 for all columns, 1 for even columns, 2 for odd columns. */
258
private void
259
okiibm_output_run(byte *data, int count, int y_mult,
260
  char start_graphics, FILE *prn_stream, int pass)
261
{	
262
	int xcount = count / y_mult;
263
 
264
	fputc(033, prn_stream);
265
	fputc("KLYZ"[start_graphics], prn_stream);
266
	fputc(xcount & 0xff, prn_stream);
267
	fputc(xcount >> 8, prn_stream);
268
	if ( !pass )
269
	{
270
		fwrite(data, 1, count, prn_stream);
271
	}
272
	else
273
	{	
274
		/* Only write every other column of y_mult bytes. */
275
		int which = pass;
276
		register byte *dp = data;
277
		register int i, j;
278
 
279
		for ( i = 0; i < xcount; i++, which++ )
280
		{
281
			for ( j = 0; j < y_mult; j++, dp++ )
282
			{
283
				putc(((which & 1) ? *dp : 0), prn_stream);
284
			}
285
		}
286
	}
287
}
288
 
289
/* The print_page procedures are here, to avoid a forward reference. */
290
 
291
private const char okiibm_init_string[]	= { 0x18 };
292
private const char okiibm_end_string[]	= { 0x0c };
293
private const char okiibm_one_direct[]	= { 0x1b, 0x55, 0x01 };
294
private const char okiibm_two_direct[]	= { 0x1b, 0x55, 0x00 };
295
 
296
private int
297
okiibm_print_page(gx_device_printer *pdev, FILE *prn_stream)
298
{
299
	char init_string[16], end_string[16];
300
	int init_length, end_length;
301
 
302
	init_length = sizeof(okiibm_init_string);
303
	memcpy(init_string, okiibm_init_string, init_length);
304
 
305
	end_length = sizeof(okiibm_end_string);
306
	memcpy(end_string, okiibm_end_string, end_length);
307
 
308
	if ( pdev->y_pixels_per_inch > 72 &&
309
	     pdev->x_pixels_per_inch > 60 )
310
	{
311
		/* Unidirectional printing for the higher resolutions. */
312
		memcpy( init_string + init_length, okiibm_one_direct,
313
		        sizeof(okiibm_one_direct) );
314
		init_length += sizeof(okiibm_one_direct);
315
 
316
		memcpy( end_string + end_length, okiibm_two_direct,
317
		        sizeof(okiibm_two_direct) );
318
		end_length += sizeof(okiibm_two_direct);
319
	}
320
 
321
	return okiibm_print_page1( pdev, prn_stream, 
322
				   pdev->y_pixels_per_inch > 72 ? 1 : 0,
323
				   init_string, init_length,
324
				   end_string, end_length );
325
}