1 /* Copyright (C) 2001-2006 Artifex Software, Inc.
2    All Rights Reserved.
3 
4    This software is provided AS-IS with no warranty, either express or
5    implied.
6 
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.
12 */
13 /* $Id: gdevlj56.c 8250 2007-09-25 13:31:24Z giles $ */
14 /* H-P LaserJet 5 & 6 drivers for Ghostscript */
15 #include "gdevprn.h"
16 #include "stream.h"
17 #include "gdevpcl.h"
18 #include "gdevpxat.h"
19 #include "gdevpxen.h"
20 #include "gdevpxop.h"
21 #include "gdevpxut.h"
22 
23 /* Define the default resolution. */
24 #ifndef X_DPI
25 #  define X_DPI 600
26 #endif
27 #ifndef Y_DPI
28 #  define Y_DPI 600
29 #endif
30 
31 /* Define the number of blank lines that make it worthwhile to */
32 /* start a new image. */
33 #define MIN_SKIP_LINES 2
34 
35 /* We round up the LINE_SIZE to a multiple of a ulong for faster scanning. */
36 #define W sizeof(word)
37 
38 static dev_proc_open_device(ljet5_open);
39 static dev_proc_close_device(ljet5_close);
40 static dev_proc_print_page(ljet5_print_page);
41 
42 static const gx_device_procs ljet5_procs =
43 prn_procs(ljet5_open, gdev_prn_output_page, ljet5_close);
44 
45 const gx_device_printer gs_lj5mono_device =
46 prn_device(ljet5_procs, "lj5mono",
47 	   DEFAULT_WIDTH_10THS, DEFAULT_HEIGHT_10THS,
48 	   X_DPI, Y_DPI,
49 	   0, 0, 0, 0,
50 	   1, ljet5_print_page);
51 
52 static const gx_device_procs lj5gray_procs =
53 prn_color_procs(ljet5_open, gdev_prn_output_page, ljet5_close,
54 		gx_default_gray_map_rgb_color,
55 		gx_default_gray_map_color_rgb);
56 
57 const gx_device_printer gs_lj5gray_device = {
58     prn_device_body(gx_device_printer, lj5gray_procs, "lj5gray",
59 		    DEFAULT_WIDTH_10THS, DEFAULT_HEIGHT_10THS,
60 		    X_DPI, Y_DPI,
61 		    0, 0, 0, 0,
62 		    1, 8, 255, 0, 256, 1, ljet5_print_page)
63 };
64 
65 /* Open the printer, writing the stream header. */
66 static int
ljet5_open(gx_device * pdev)67 ljet5_open(gx_device * pdev)
68 {
69     int code = gdev_prn_open(pdev);
70 
71     if (code < 0)
72 	return code;
73     code = gdev_prn_open_printer(pdev, true);
74     if (code < 0)
75 	return code;
76     {
77 	gx_device_printer *const ppdev = (gx_device_printer *)pdev;
78 	stream fs;
79 	stream *const s = &fs;
80 	byte buf[50];		/* arbitrary */
81 
82 	s_init(s, pdev->memory);
83 	swrite_file(s, ppdev->file, buf, sizeof(buf));
84 	px_write_file_header(s, pdev);
85 	sflush(s);		/* don't close */
86     }
87     return 0;
88 }
89 
90 /* Close the printer, writing the stream trailer. */
91 static int
ljet5_close(gx_device * pdev)92 ljet5_close(gx_device * pdev)
93 {
94     gx_device_printer *const ppdev = (gx_device_printer *)pdev;
95     int code = gdev_prn_open_printer(pdev, true);
96 
97     if (code < 0)
98 	return code;
99     px_write_file_trailer(ppdev->file);
100     return gdev_prn_close(pdev);
101 }
102 
103 /* Send the page to the printer.  For now, just send the whole image. */
104 static int
ljet5_print_page(gx_device_printer * pdev,FILE * prn_stream)105 ljet5_print_page(gx_device_printer * pdev, FILE * prn_stream)
106 {
107     gs_memory_t *mem = pdev->memory;
108     uint line_size = gdev_mem_bytes_per_scan_line((gx_device *) pdev);
109     uint line_size_words = (line_size + W - 1) / W;
110     uint out_size = line_size + (line_size / 127) + 1;
111     word *line = (word *)gs_alloc_byte_array(mem, line_size_words, W, "ljet5(line)");
112     byte *out = gs_alloc_bytes(mem, out_size, "ljet5(out)");
113     int code = 0;
114     int lnum;
115     stream fs;
116     stream *const s = &fs;
117     byte buf[200];		/* arbitrary */
118 
119     if (line == 0 || out == 0) {
120 	code = gs_note_error(gs_error_VMerror);
121 	goto done;
122     }
123     s_init(s, mem);
124     swrite_file(s, prn_stream, buf, sizeof(buf));
125 
126     /* Write the page header. */
127     {
128 	static const byte page_header[] = {
129 	    pxtBeginPage,
130 	    DUSP(0, 0), DA(pxaPoint),
131 	    pxtSetCursor
132 	};
133 	static const byte mono_header[] = {
134 	    DUB(eGray), DA(pxaColorSpace),
135 	    DUB(e8Bit), DA(pxaPaletteDepth),
136 	    pxt_ubyte_array, pxt_ubyte, 2, 0xff, 0x00, DA(pxaPaletteData),
137 	    pxtSetColorSpace
138 	};
139 	static const byte gray_header[] = {
140 	    DUB(eGray), DA(pxaColorSpace),
141 	    pxtSetColorSpace
142 	};
143 
144 	px_write_page_header(s, (gx_device *)pdev);
145 	px_write_select_media(s, (gx_device *)pdev, NULL, NULL, 0, false, false);
146 	PX_PUT_LIT(s, page_header);
147 	if (pdev->color_info.depth == 1)
148 	    PX_PUT_LIT(s, mono_header);
149 	else
150 	    PX_PUT_LIT(s, gray_header);
151     }
152 
153     /* Write the image header. */
154     {
155 	static const byte mono_image_header[] = {
156 	    DA(pxaDestinationSize),
157 	    DUB(eIndexedPixel), DA(pxaColorMapping),
158 	    DUB(e1Bit), DA(pxaColorDepth),
159 	    pxtBeginImage
160 	};
161 	static const byte gray_image_header[] = {
162 	    DA(pxaDestinationSize),
163 	    DUB(eDirectPixel), DA(pxaColorMapping),
164 	    DUB(e8Bit), DA(pxaColorDepth),
165 	    pxtBeginImage
166 	};
167 
168 	px_put_us(s, pdev->width);
169 	px_put_a(s, pxaSourceWidth);
170 	px_put_us(s, pdev->height);
171 	px_put_a(s, pxaSourceHeight);
172 	px_put_usp(s, pdev->width, pdev->height);
173 	if (pdev->color_info.depth == 1)
174 	    PX_PUT_LIT(s, mono_image_header);
175 	else
176 	    PX_PUT_LIT(s, gray_image_header);
177     }
178 
179     /* Write the image data, compressing each line. */
180     for (lnum = 0; lnum < pdev->height; ++lnum) {
181 	int ncompr;
182 	static const byte line_header[] = {
183 	    DA(pxaStartLine),
184 	    DUS(1), DA(pxaBlockHeight),
185 	    DUB(eRLECompression), DA(pxaCompressMode),
186 	    pxtReadImage
187 	};
188 
189 	code = gdev_prn_copy_scan_lines(pdev, lnum, (byte *) line, line_size);
190 	if (code < 0)
191 	    goto fin;
192 	px_put_us(s, lnum);
193 	PX_PUT_LIT(s, line_header);
194 	ncompr = gdev_pcl_mode2compress_padded(line, line + line_size_words,
195 					       out, true);
196 	px_put_data_length(s, ncompr);
197 	px_put_bytes(s, out, ncompr);
198     }
199 
200     /* Finish up. */
201   fin:
202     spputc(s, pxtEndImage);
203     spputc(s, pxtEndPage);
204     sflush(s);
205   done:
206     gs_free_object(mem, out, "ljet5(out)");
207     gs_free_object(mem, line, "ljet5(line)");
208     return code;
209 }
210