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