Warning: Attempt to read property "date" on null in /usr/local/www/websvn.planix.org/blame.php on line 247

Warning: Attempt to read property "msg" on null in /usr/local/www/websvn.planix.org/blame.php on line 247
WebSVN – planix.SVN – Blame – /os/branches/feature_tlsv12/sys/src/cmd/gs/src/gdevepsn.c – Rev 2

Subversion Repositories planix.SVN

Rev

Go to most recent revision | Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
2 - 1
/* Copyright (C) 1989-1994, 1998 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: gdevepsn.c,v 1.9 2004/08/04 19:36:12 stefan Exp $*/
18
/*
19
 * Epson (and similar) dot-matrix printer driver for Ghostscript.
20
 *
21
 * Four devices are defined here: 'epson', 'eps9mid', 'eps9high', and 'ibmpro'.
22
 * The 'epson' device is the generic device, for 9-pin and 24-pin printers.
23
 * 'eps9high' is a special mode for 9-pin printers where scan lines are
24
 * interleaved in multiple passes to produce high vertical resolution at
25
 * the expense of several passes of the print head.  'eps9mid' is a special
26
 * mode for 9 pin printers too, scan lines are interleaved but with next
27
 * vertical line. 'ibmpro' is for the IBM ProPrinter, which has slightly 
28
 * (but only slightly) different control codes.
29
 *
30
 * Thanks to:
31
 *	David Wexelblat (dwex@mtgzfs3.att.com) for the 'eps9high' code;
32
 *	Guenther Thomsen (thomsen@cs.tu-berlin.de) for the 'eps9mid' code;
33
 *	James W. Birdsall (jwbirdsa@picarefy.picarefy.com) for the
34
 *	  'ibmpro' modifications;
35
 *	Russell J. Lang (rjl@aladdin.com) for the 180x60 and 240x180 dpi
36
 *	  enhancements.
37
 */
38
#include "gdevprn.h"
39
 
40
/*
41
 * Define whether the printer is archaic -- so old that it doesn't
42
 * support settable tabs, pitch, or left margin.  (This should be a
43
 * run-time property....)  Note: the IBM ProPrinter is archaic.
44
 */
45
/*#define ARCHAIC 1*/
46
 
47
/*
48
 * Define whether the printer is a Panasonic 9-pin printer,
49
 * which sometimes doesn't recognize a horizontal tab command
50
 * when a line contains a lot of graphics commands,
51
 * requiring a "backspace, space" sequence before a tab.
52
 */
53
/*#define TAB_HICCUP 1*/
54
 
55
/*
56
 * Define the minimum distance for which it's worth converting white space
57
 * into a tab.  This can be specified in pixels (to save transmission time),
58
 * in tenths of an inch (for printers where tabs provoke actual head motion),
59
 * or both.  The distance must meet BOTH criteria for the driver to tab,
60
 * so an irrelevant criterion should be set to 0 rather than infinite.
61
 */
62
#define MIN_TAB_PIXELS 10
63
#define MIN_TAB_10THS 15
64
 
65
/*
66
 * Valid values for X_DPI:
67
 *
68
 *    For 9-pin printers: 60, 120, 240
69
 *    For 24-pin printers: 60, 120, 180, 240, 360
70
 *
71
 * The value specified at compile time is the default value used if the
72
 * user does not specify a resolution at runtime.
73
 */
74
#ifndef X_DPI
75
#  define X_DPI 240
76
#endif
77
 
78
/*
79
 * For Y_DPI, a given printer will support a base resolution of 60 or 72;
80
 * check the printer manual.  The Y_DPI value must be a multiple of this
81
 * base resolution.  Valid values for Y_DPI:
82
 *
83
 *    For 9-pin printers: 1*base_res
84
 *    For 24-pin printers: 1*base_res, 3*base_res
85
 *
86
 * The value specified at compile time is the default value used if the
87
 * user does not specify a resolution at runtime.
88
 */
89
 
90
#ifndef Y_BASERES
91
#  define Y_BASERES 72
92
#endif
93
#ifndef Y_DPI
94
#  define Y_DPI (1*Y_BASERES)
95
#endif
96
 
97
/* The device descriptors */
98
private dev_proc_print_page(epson_print_page);
99
private dev_proc_print_page(eps9mid_print_page); 
100
private dev_proc_print_page(eps9high_print_page);
101
private dev_proc_print_page(ibmpro_print_page);
102
 
103
/* Standard Epson device */
104
const gx_device_printer far_data gs_epson_device =
105
  prn_device(prn_std_procs, "epson",
106
	DEFAULT_WIDTH_10THS, DEFAULT_HEIGHT_10THS,
107
	X_DPI, Y_DPI,
108
	0.2, 0.0, 0.0, 0.0,			/* margins */
109
	1, epson_print_page);
110
 
111
/* Mid-res (interleaved, 1 pass per line) 9-pin device */
112
const gx_device_printer far_data gs_eps9mid_device = 
113
  prn_device(prn_std_procs, "eps9mid",
114
	DEFAULT_WIDTH_10THS, DEFAULT_HEIGHT_10THS,
115
	X_DPI, 3*Y_BASERES,
116
	0.2, 0.0, 0, 0.0,			/* margins */
117
	1, eps9mid_print_page);
118
 
119
 
120
/* High-res (interleaved) 9-pin device */
121
const gx_device_printer far_data gs_eps9high_device = 
122
  prn_device(prn_std_procs, "eps9high",
123
	DEFAULT_WIDTH_10THS, DEFAULT_HEIGHT_10THS,
124
	X_DPI, 3*Y_BASERES,
125
	0.2, 0.0, 0.0, 0.0,			/* margins */
126
	1, eps9high_print_page);
127
 
128
/* IBM ProPrinter device */
129
const gx_device_printer far_data gs_ibmpro_device =
130
  prn_device(prn_std_procs, "ibmpro",
131
	DEFAULT_WIDTH_10THS, DEFAULT_HEIGHT_10THS,
132
	X_DPI, Y_DPI,
133
	0.2, 0.0, 0.0, 0.0,			/* margins */
134
	1, ibmpro_print_page);
135
 
136
/* ------ Driver procedures ------ */
137
 
138
/* Forward references */
139
private void eps_output_run(byte *, int, int, char, FILE *, int);
140
 
141
/* Send the page to the printer. */
142
#define DD 0x40				/* double density flag */
143
private int
144
eps_print_page(gx_device_printer *pdev, FILE *prn_stream, int y_9pin_high,
145
  const char *init_string, int init_length, const char *end_string,
146
  int archaic, int tab_hiccup)
147
{	
148
	static const char graphics_modes_9[5] =
149
	{	
150
	-1, 0 /*60*/, 1	/*120*/, 7 /*180*/, DD+3 /*240*/
151
	};
152
 
153
	static const char graphics_modes_24[7] =
154
	{	
155
    	-1, 32 /*60*/, 33 /*120*/, 39 /*180*/,
156
	DD+35 /*240*/, -1, DD+40 /*360*/
157
	};
158
 
159
	int y_24pin = (y_9pin_high ? 0 : pdev->y_pixels_per_inch > 72);
160
	int in_y_mult = ((y_24pin | y_9pin_high) ? 3 : 1);
161
	int line_size = gdev_mem_bytes_per_scan_line((gx_device *)pdev);
162
	/* Note that in_size is a multiple of 8. */
163
	int in_size = line_size * (8 * in_y_mult);
164
	byte *buf1 = (byte *)gs_malloc(pdev->memory, in_size, 1, "eps_print_page(buf1)");
165
	byte *buf2 = (byte *)gs_malloc(pdev->memory, in_size, 1, "eps_print_page(buf2)");
166
	byte *in = buf1;
167
	byte *out = buf2;
168
	int out_y_mult = (y_24pin ? 3 : 1);
169
	int x_dpi = (int)pdev->x_pixels_per_inch;
170
	char start_graphics =
171
		(y_24pin ? graphics_modes_24 : graphics_modes_9)[x_dpi / 60];
172
	int first_pass = (start_graphics & DD ? 1 : 0);
173
	int last_pass = first_pass * (y_9pin_high == 2 ? 1 : 2); 
174
	int y_passes = (y_9pin_high ? 3 : 1);
175
	int dots_per_space = x_dpi / 10;	/* pica space = 1/10" */
176
	int bytes_per_space = dots_per_space * out_y_mult;
177
	int tab_min_pixels = x_dpi * MIN_TAB_10THS / 10;
178
	int skip = 0, lnum = 0, pass, ypass;
179
 
180
	/* Check allocations */
181
	if ( buf1 == 0 || buf2 == 0 )
182
	{	if ( buf1 ) 
183
		  gs_free(pdev->memory, (char *)buf1, in_size, 1, "eps_print_page(buf1)");
184
		if ( buf2 ) 
185
		  gs_free(pdev->memory, (char *)buf2, in_size, 1, "eps_print_page(buf2)");
186
		return_error(gs_error_VMerror);
187
	}
188
 
189
	/* Initialize the printer and reset the margins. */
190
	fwrite(init_string, 1, init_length, prn_stream);
191
	if ( init_string[init_length - 1] == 'Q' )
192
		fputc((int)(pdev->width / pdev->x_pixels_per_inch * 10) + 2,
193
		      prn_stream);
194
 
195
	/* Calculate the minimum tab distance. */
196
	if ( tab_min_pixels < max(MIN_TAB_PIXELS, 3) )
197
		tab_min_pixels = max(MIN_TAB_PIXELS, 3);
198
	tab_min_pixels -= tab_min_pixels % 3;	/* simplify life */
199
 
200
	/* Print lines of graphics */
201
	while ( lnum < pdev->height )
202
	{	
203
		byte *in_data;
204
		byte *inp;
205
		byte *in_end;
206
		byte *out_end;
207
		byte *out_blk;
208
		register byte *outp;
209
		int lcnt;
210
 
211
		/* Copy 1 scan line and test for all zero. */
212
		gdev_prn_get_bits(pdev, lnum, in, &in_data);
213
		if ( in_data[0] == 0 &&
214
		     !memcmp((char *)in_data, (char *)in_data + 1, line_size - 1)
215
		   )
216
	    	{	
217
			lnum++;
218
			skip += 3 / in_y_mult;
219
			continue;
220
		}
221
 
222
		/* Vertical tab to the appropriate position. */
223
		while ( skip > 255 )
224
		{	
225
			fputs("\033J\377", prn_stream);
226
			skip -= 255;
227
		}
228
		if ( skip )
229
		{
230
			fprintf(prn_stream, "\033J%c", skip);
231
		}
232
 
233
		/* Copy the the scan lines. */
234
	    	lcnt = gdev_prn_copy_scan_lines(pdev, lnum, in, in_size);
235
		if ( lcnt < 8 * in_y_mult )
236
		{	/* Pad with lines of zeros. */
237
			memset(in + lcnt * line_size, 0,
238
			       in_size - lcnt * line_size);
239
		}
240
 
241
		if ( y_9pin_high == 2 ) 
242
		{	/* Force printing of every dot in one pass */
243
			/* by reducing vertical resolution */
244
		        /* (ORing with the next line of data). */
245
		        /* This is necessary because some Epson compatibles */
246
			/* can't print neighboring dots. */
247
			int i;
248
			for ( i = 0; i < line_size * in_y_mult; ++i )
249
				in_data[i] |= in_data[i + line_size];
250
		}
251
 
252
		if ( y_9pin_high )
253
		{	/* Shuffle the scan lines */
254
			byte *p;
255
			int i;
256
			static const char index[] =
257
			{  0,  8, 16,  1,  9, 17,  
258
			   2, 10, 18,  3, 11, 19,
259
			   4, 12, 20,  5, 13, 21,
260
			   6, 14, 22,  7, 15, 23
261
			};
262
 
263
			for ( i = 0; i < 24; i++ )
264
			{
265
				memcpy(out+(index[i]*line_size),
266
				       in+(i*line_size), line_size);
267
			}
268
			p = in;
269
			in = out;
270
			out = p;
271
		}
272
 
273
	for ( ypass = 0; ypass < y_passes; ypass++ )
274
	{
275
	    for ( pass = first_pass; pass <= last_pass; pass++ )
276
	    {
277
		/* We have to 'transpose' blocks of 8 pixels x 8 lines, */
278
		/* because that's how the printer wants the data. */
279
		/* If we are in a 24-pin mode, we have to transpose */
280
		/* groups of 3 lines at a time. */
281
 
282
		if ( pass == first_pass )
283
		{
284
		    out_end = out;
285
		    inp = in;
286
		    in_end = inp + line_size;
287
 
288
		    if ( y_24pin )
289
    	            { 
290
    			for ( ; inp < in_end; inp++, out_end += 24 )
291
    			{ 
292
    	    	            gdev_prn_transpose_8x8(inp, line_size, out_end, 3);
293
    	                    gdev_prn_transpose_8x8(inp + line_size * 8, 
294
					           line_size, out_end + 1, 3);
295
    	                    gdev_prn_transpose_8x8(inp + line_size * 16, 
296
					           line_size, out_end + 2, 3);
297
			}
298
			/* Remove trailing 0s. */
299
			while ( out_end > out && out_end[-1] == 0 &&
300
    	   			out_end[-2] == 0 && out_end[-3] == 0)
301
			{
302
		             out_end -= 3;
303
			}
304
    	            }
305
		    else
306
    	            { 
307
    			for ( ; inp < in_end; inp++, out_end += 8 )
308
    			{ 
309
    		            gdev_prn_transpose_8x8(inp + (ypass * 8*line_size), 
310
					           line_size, out_end, 1);
311
		    	}
312
			/* Remove trailing 0s. */
313
			while ( out_end > out && out_end[-1] == 0 )
314
	        	{
315
		       	    out_end--;
316
			}
317
    	    	    }
318
		}
319
 
320
		for ( out_blk = outp = out; outp < out_end; )
321
    		{ 
322
    	 	    /* Skip a run of leading 0s.  At least */
323
    	            /* tab_min_pixels are needed to make tabbing */
324
    		    /* worth it.  We do everything by 3's to */
325
    		    /* avoid having to make different cases */
326
    		    /* for 9- and 24-pin. */
327
		   if ( !archaic &&
328
			*outp == 0 && out_end - outp >= tab_min_pixels &&
329
			(outp[1] | outp[2]) == 0 &&
330
			!memcmp((char *)outp, (char *)outp + 3,
331
				tab_min_pixels - 3)
332
		      )
333
    	    	    {
334
    			byte *zp = outp;
335
			int tpos;
336
			byte *newp;
337
 
338
			outp += tab_min_pixels;
339
    			while ( outp + 3 <= out_end && 
340
    		     		*outp == 0 &&
341
    				outp[1] == 0 && outp[2] == 0 )
342
    			{
343
			    outp += 3;
344
    			}
345
			tpos = (outp - out) / bytes_per_space;
346
			newp = out + tpos * bytes_per_space;
347
			if ( newp > zp + 10 )
348
    			{ 
349
    			    /* Output preceding bit data.*/
350
    		   	    if ( zp > out_blk )	
351
    			    {
352
    				/* only false at beginning of line */
353
			     	eps_output_run(out_blk, (int)(zp - out_blk),
354
    				    	       out_y_mult, start_graphics, 
355
					       prn_stream,
356
					       (y_9pin_high == 2 ?
357
					        (1 + ypass) & 1 : pass));
358
			    }
359
			    /* Tab over to the appropriate position. */
360
			    if ( tab_hiccup )
361
			      fputs("\010 ", prn_stream); /* bksp, space */
362
			    /* The following statement is broken up */
363
			    /* to work around a bug in emx/gcc. */
364
			    fprintf(prn_stream, "\033D%c", tpos);
365
			    fputc(0, prn_stream);
366
			    fputc('\t', prn_stream);
367
			    out_blk = outp = newp;
368
			}
369
		    }
370
		    else
371
		    {
372
    			outp += out_y_mult;
373
		    }
374
    		}
375
		if ( outp > out_blk )
376
		{
377
		    eps_output_run(out_blk, (int)(outp - out_blk),
378
			           out_y_mult, start_graphics,
379
				   prn_stream,
380
				   (y_9pin_high == 2 ? (1 + ypass) & 1 : pass));
381
		}
382
 
383
		fputc('\r', prn_stream);
384
	    }
385
	    if ( ypass < y_passes - 1 )
386
		fputs("\033J\001", prn_stream);
387
	}
388
	skip = 24 - y_passes + 1;		/* no skip on last Y pass */
389
	lnum += 8 * in_y_mult;
390
	}
391
 
392
	/* Eject the page and reinitialize the printer */
393
	fputs(end_string, prn_stream);
394
	fflush(prn_stream);
395
 
396
	gs_free(pdev->memory, (char *)buf2, in_size, 1, "eps_print_page(buf2)");
397
	gs_free(pdev->memory, (char *)buf1, in_size, 1, "eps_print_page(buf1)");
398
	return 0;
399
}
400
 
401
/* Output a single graphics command. */
402
/* pass=0 for all columns, 1 for even columns, 2 for odd columns. */
403
private void
404
eps_output_run(byte *data, int count, int y_mult,
405
  char start_graphics, FILE *prn_stream, int pass)
406
{	
407
	int xcount = count / y_mult;
408
 
409
	fputc(033, prn_stream);
410
	if ( !(start_graphics & ~3) )
411
	{	
412
		fputc("KLYZ"[(int)start_graphics], prn_stream);
413
	}
414
	else
415
	{	
416
		fputc('*', prn_stream);
417
		fputc(start_graphics & ~DD, prn_stream);
418
	}
419
	fputc(xcount & 0xff, prn_stream);
420
	fputc(xcount >> 8, prn_stream);
421
	if ( !pass )
422
	{
423
		fwrite(data, 1, count, prn_stream);
424
	}
425
	else
426
	{	
427
		/* Only write every other column of y_mult bytes. */
428
		int which = pass;
429
		register byte *dp = data;
430
		register int i, j;
431
 
432
		for ( i = 0; i < xcount; i++, which++ )
433
		{
434
			for ( j = 0; j < y_mult; j++, dp++ )
435
			{
436
				putc(((which & 1) ? *dp : 0), prn_stream);
437
			}
438
		}
439
	}
440
}
441
 
442
/* The print_page procedures are here, to avoid a forward reference. */
443
#ifndef ARCHAIC
444
#  define ARCHAIC 0
445
#endif
446
#ifndef TAB_HICCUP
447
#  define TAB_HICCUP 0
448
#endif
449
 
450
#define ESC 0x1b
451
private const char eps_init_string[] = {
452
#if ARCHAIC
453
	ESC, '@', 022 /*^R*/, ESC, 'Q'
454
#else
455
	ESC, '@', ESC, 'P', ESC, 'l', 0, '\r', ESC, 'Q'
456
#endif
457
};
458
 
459
private int
460
epson_print_page(gx_device_printer *pdev, FILE *prn_stream)
461
{
462
	return eps_print_page(pdev, prn_stream, 0, eps_init_string,
463
			      sizeof(eps_init_string), "\f\033@",
464
			      ARCHAIC, TAB_HICCUP);
465
}
466
 
467
private int
468
eps9high_print_page(gx_device_printer *pdev, FILE *prn_stream)
469
{
470
	return eps_print_page(pdev, prn_stream, 1, eps_init_string,
471
			      sizeof(eps_init_string), "\f\033@",
472
			      ARCHAIC, TAB_HICCUP);
473
}
474
 
475
private int
476
eps9mid_print_page(gx_device_printer *pdev, FILE *prn_stream)
477
{
478
	return eps_print_page(pdev, prn_stream, 2, eps_init_string,
479
			      sizeof(eps_init_string), "\f\033@", 
480
			      ARCHAIC, TAB_HICCUP);
481
}
482
 
483
private int
484
ibmpro_print_page(gx_device_printer *pdev, FILE *prn_stream)
485
{
486
    /*
487
     * IBM Proprinter Guide to Operations, p. 4-5: "DC1: Select Printer: Sets
488
     * the printer to accept data from your computer."  Prevents printer from
489
     * interpreting first characters as literal text.
490
     */
491
#define DC1 0x11
492
	static const char ibmpro_init_string[] = {
493
		DC1, ESC, '3', 0x30
494
	};
495
#undef DC1
496
	return eps_print_page(pdev, prn_stream, 0, ibmpro_init_string,
497
			      sizeof(ibmpro_init_string), "\f", 1, 0);
498
}