1
/* Copyright (C) 2001-2006 Artifex Software, Inc.
4
This software is provided AS-IS with no warranty, either express or
7
This software is distributed under license and may not be copied, modified
8
or distributed except as expressly authorized under the terms of that
9
license. Refer to licensing information at http://www.artifex.com/
10
or contact Artifex Software, Inc., 7 Mt. Lassen Drive - Suite A-134,
11
San Rafael, CA 94903, U.S.A., +1(415)492-9861, for further information.
13
/* $Id: gdevokii.c 8250 2007-09-25 13:31:24Z giles $*/
15
* Okidata IBM compatible dot-matrix printer driver for Ghostscript.
17
* This device is for the Okidata Microline IBM compatible 9 pin dot
18
* matrix printers. It is derived from the Epson 9 pin printer driver
19
* using the standard 1/72" vertical pin spacing and the 60/120/240
20
* dpi horizontal resolutions. The vertical feed resolution however
21
* is 1/144" and the Okidata implements the standard 1/216" requests
25
* "\033J\001" (vertical feed 1/216") => Nothing happens
26
* "\033J\001" (vertical feed 1/216") => Advance 1/144"
27
* "\033J\001" (vertical feed 1/216") => Advance 1/144"
28
* "\033J\001" (vertical feed 1/216") => Nothing happens
31
* The simple minded accounting used here keep track of when the
32
* page actually advances assumes the printer starts in a "power on"
35
* Supported resolutions are:
45
* Valid values for X_DPI:
49
* The value specified at compile time is the default value used if the
50
* user does not specify a resolution at runtime.
58
* Valid values for Y_DPI:
62
* The value specified at compile time is the default value used if the
63
* user does not specify a resolution at runtime.
70
/* The device descriptor */
71
static dev_proc_print_page(okiibm_print_page);
73
/* Okidata IBM device */
74
const gx_device_printer far_data gs_okiibm_device =
75
prn_device(prn_std_procs, "okiibm",
76
DEFAULT_WIDTH_10THS, DEFAULT_HEIGHT_10THS,
78
0.25, 0.0, 0.25, 0.0, /* margins */
79
1, okiibm_print_page);
81
/* ------ Internal routines ------ */
83
/* Forward references */
84
static void okiibm_output_run(byte *, int, int, char, FILE *, int);
86
/* Send the page to the printer. */
88
okiibm_print_page1(gx_device_printer *pdev, FILE *prn_stream, int y_9pin_high,
89
const char *init_string, int init_length,
90
const char *end_string, int end_length)
92
static const char graphics_modes_9[5] =
94
-1, 0 /*60*/, 1 /*120*/, -1, 3 /*240*/
97
int in_y_mult = (y_9pin_high ? 2 : 1);
98
int line_size = gdev_mem_bytes_per_scan_line((gx_device *)pdev);
99
/* Note that in_size is a multiple of 8. */
100
int in_size = line_size * (8 * in_y_mult);
101
byte *buf1 = (byte *)gs_malloc(pdev->memory, in_size, 1, "okiibm_print_page(buf1)");
102
byte *buf2 = (byte *)gs_malloc(pdev->memory, in_size, 1, "okiibm_print_page(buf2)");
106
int x_dpi = pdev->x_pixels_per_inch;
107
char start_graphics = graphics_modes_9[x_dpi / 60];
108
int first_pass = (start_graphics == 3 ? 1 : 0);
109
int last_pass = first_pass * 2;
110
int y_passes = (y_9pin_high ? 2 : 1);
111
int skip = 0, lnum = 0, pass, ypass;
114
/* Check allocations */
115
if ( buf1 == 0 || buf2 == 0 )
117
gs_free(pdev->memory, (char *)buf1, in_size, 1, "okiibm_print_page(buf1)");
119
gs_free(pdev->memory, (char *)buf2, in_size, 1, "okiibm_print_page(buf2)");
120
return_error(gs_error_VMerror);
123
/* Initialize the printer. */
124
fwrite(init_string, 1, init_length, prn_stream);
126
/* Print lines of graphics */
127
while ( lnum < pdev->height )
135
/* Copy 1 scan line and test for all zero. */
136
gdev_prn_get_bits(pdev, lnum, in, &in_data);
137
if ( in_data[0] == 0 &&
138
!memcmp((char *)in_data, (char *)in_data + 1, line_size - 1)
142
skip += 2 / in_y_mult;
147
* Vertical tab to the appropriate position.
148
* The skip count is in 1/144" steps. If total
149
* vertical request is not a multiple od 1/72"
150
* we need to make sure the page is actually
155
int n = 1 + (y_step == 0 ? 1 : 0);
156
fprintf(prn_stream, "\033J%c", n);
157
y_step = (y_step + n) % 3;
163
fputs("\033J\377", prn_stream);
168
fprintf(prn_stream, "\033J%c", skip);
171
/* Copy the the scan lines. */
172
lcnt = gdev_prn_copy_scan_lines(pdev, lnum, in, in_size);
173
if ( lcnt < 8 * in_y_mult )
174
{ /* Pad with lines of zeros. */
175
memset(in + lcnt * line_size, 0,
176
in_size - lcnt * line_size);
180
{ /* Shuffle the scan lines */
183
static const char index[] =
184
{ 0, 2, 4, 6, 8, 10, 12, 14,
185
1, 3, 5, 7, 9, 11, 13, 15
187
for ( i = 0; i < 16; i++ )
189
memcpy( out + (i * line_size),
190
in + (index[i] * line_size),
198
for ( ypass = 0; ypass < y_passes; ypass++ )
200
for ( pass = first_pass; pass <= last_pass; pass++ )
202
/* We have to 'transpose' blocks of 8 pixels x 8 lines, */
203
/* because that's how the printer wants the data. */
205
if ( pass == first_pass )
209
in_end = inp + line_size;
211
for ( ; inp < in_end; inp++, out_end += 8 )
213
gdev_prn_transpose_8x8(inp + (ypass * 8 * line_size),
214
line_size, out_end, 1);
216
/* Remove trailing 0s. */
217
while ( out_end > out && out_end[-1] == 0 )
223
/* Transfer whatever is left and print. */
226
okiibm_output_run(out, (int)(out_end - out),
227
out_y_mult, start_graphics,
230
fputc('\r', prn_stream);
232
if ( ypass < y_passes - 1 )
234
int n = 1 + (y_step == 0 ? 1 : 0);
235
fprintf(prn_stream, "\033J%c", n);
236
y_step = (y_step + n) % 3;
239
skip = 16 - y_passes + 1; /* no skip on last Y pass */
240
lnum += 8 * in_y_mult;
243
/* Reinitialize the printer. */
244
fwrite(end_string, 1, end_length, prn_stream);
247
gs_free(pdev->memory, (char *)buf2, in_size, 1, "okiibm_print_page(buf2)");
248
gs_free(pdev->memory, (char *)buf1, in_size, 1, "okiibm_print_page(buf1)");
252
/* Output a single graphics command. */
253
/* pass=0 for all columns, 1 for even columns, 2 for odd columns. */
255
okiibm_output_run(byte *data, int count, int y_mult,
256
char start_graphics, FILE *prn_stream, int pass)
258
int xcount = count / y_mult;
260
fputc(033, prn_stream);
261
fputc("KLYZ"[start_graphics], prn_stream);
262
fputc(xcount & 0xff, prn_stream);
263
fputc(xcount >> 8, prn_stream);
266
fwrite(data, 1, count, prn_stream);
270
/* Only write every other column of y_mult bytes. */
272
register byte *dp = data;
275
for ( i = 0; i < xcount; i++, which++ )
277
for ( j = 0; j < y_mult; j++, dp++ )
279
putc(((which & 1) ? *dp : 0), prn_stream);
285
/* The print_page procedures are here, to avoid a forward reference. */
287
static const char okiibm_init_string[] = { 0x18 };
288
static const char okiibm_end_string[] = { 0x0c };
289
static const char okiibm_one_direct[] = { 0x1b, 0x55, 0x01 };
290
static const char okiibm_two_direct[] = { 0x1b, 0x55, 0x00 };
293
okiibm_print_page(gx_device_printer *pdev, FILE *prn_stream)
295
char init_string[16], end_string[16];
296
int init_length, end_length;
298
init_length = sizeof(okiibm_init_string);
299
memcpy(init_string, okiibm_init_string, init_length);
301
end_length = sizeof(okiibm_end_string);
302
memcpy(end_string, okiibm_end_string, end_length);
304
if ( pdev->y_pixels_per_inch > 72 &&
305
pdev->x_pixels_per_inch > 60 )
307
/* Unidirectional printing for the higher resolutions. */
308
memcpy( init_string + init_length, okiibm_one_direct,
309
sizeof(okiibm_one_direct) );
310
init_length += sizeof(okiibm_one_direct);
312
memcpy( end_string + end_length, okiibm_two_direct,
313
sizeof(okiibm_two_direct) );
314
end_length += sizeof(okiibm_two_direct);
317
return okiibm_print_page1( pdev, prn_stream,
318
pdev->y_pixels_per_inch > 72 ? 1 : 0,
319
init_string, init_length,
320
end_string, end_length );