1 /* Copyright (C) 1991, 1992 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: gdevpjet.c,v 1.7 2004/08/04 23:33:29 stefan Exp $*/
18 /* H-P PaintJet, PaintJet XL, and DEC LJ250 drivers. */
19 /* Thanks to Rob Reiss (rob@moray.berkeley.edu) for the PaintJet XL */
20 /* modifications. */
21 #include "gdevprn.h"
22 #include "gdevpcl.h"
23
24 /* X_DPI and Y_DPI must be the same, and may be either 90 or 180. */
25 #define X_DPI 180
26 #define Y_DPI 180
27
28 /* We round up LINE_SIZE to a multiple of 8 bytes */
29 /* because that's the unit of transposition from pixels to planes. */
30 #define LINE_SIZE ((X_DPI * 85 / 10 + 63) / 64 * 8)
31
32 /* The device descriptors */
33 private dev_proc_print_page(lj250_print_page);
34 private dev_proc_print_page(paintjet_print_page);
35 private dev_proc_print_page(pjetxl_print_page);
36 private int pj_common_print_page(gx_device_printer *, FILE *, int, const char *);
37 private gx_device_procs paintjet_procs =
38 prn_color_procs(gdev_prn_open, gdev_prn_output_page, gdev_prn_close,
39 gdev_pcl_3bit_map_rgb_color, gdev_pcl_3bit_map_color_rgb);
40 const gx_device_printer far_data gs_lj250_device =
41 prn_device(paintjet_procs, "lj250",
42 85, /* width_10ths, 8.5" */
43 110, /* height_10ths, 11" */
44 X_DPI, Y_DPI,
45 0.25, 0, 0.25, 0, /* margins */
46 3, lj250_print_page);
47 const gx_device_printer far_data gs_paintjet_device =
48 prn_device(paintjet_procs, "paintjet",
49 85, /* width_10ths, 8.5" */
50 110, /* height_10ths, 11" */
51 X_DPI, Y_DPI,
52 0.25, 0, 0.25, 0, /* margins */
53 3, paintjet_print_page);
54 private gx_device_procs pjetxl_procs =
55 prn_color_procs(gdev_prn_open, gdev_prn_output_page, gdev_prn_close,
56 gdev_pcl_3bit_map_rgb_color, gdev_pcl_3bit_map_color_rgb);
57 const gx_device_printer far_data gs_pjetxl_device =
58 prn_device(pjetxl_procs, "pjetxl",
59 85, /* width_10ths, 8.5" */
60 110, /* height_10ths, 11" */
61 X_DPI, Y_DPI,
62 0.25, 0, 0, 0, /* margins */
63 3, pjetxl_print_page);
64
65 /* Forward references */
66 private int compress1_row(const byte *, const byte *, byte *);
67
68 /* ------ Internal routines ------ */
69
70 /* Send a page to the LJ250. We need to enter and exit */
71 /* the PaintJet emulation mode. */
72 private int
lj250_print_page(gx_device_printer * pdev,FILE * prn_stream)73 lj250_print_page(gx_device_printer *pdev, FILE *prn_stream)
74 { fputs("\033%8", prn_stream); /* Enter PCL emulation mode */
75 /* ends raster graphics to set raster graphics resolution */
76 fputs("\033*rB", prn_stream);
77 /* Exit PCL emulation mode after printing */
78 return pj_common_print_page(pdev, prn_stream, 0, "\033*r0B\014\033%@");
79 }
80
81 /* Send a page to the PaintJet. */
82 private int
paintjet_print_page(gx_device_printer * pdev,FILE * prn_stream)83 paintjet_print_page(gx_device_printer *pdev, FILE *prn_stream)
84 { /* ends raster graphics to set raster graphics resolution */
85 fputs("\033*rB", prn_stream);
86 return pj_common_print_page(pdev, prn_stream, 0, "\033*r0B\014");
87 }
88
89 /* Send a page to the PaintJet XL. */
90 private int
pjetxl_print_page(gx_device_printer * pdev,FILE * prn_stream)91 pjetxl_print_page(gx_device_printer *pdev, FILE *prn_stream)
92 { /* Initialize PaintJet XL for printing */
93 fputs("\033E", prn_stream);
94 /* The XL has a different vertical origin, who knows why?? */
95 return pj_common_print_page(pdev, prn_stream, -360, "\033*rC");
96 }
97
98 /* Send the page to the printer. Compress each scan line. */
99 private int
pj_common_print_page(gx_device_printer * pdev,FILE * prn_stream,int y_origin,const char * end_page)100 pj_common_print_page(gx_device_printer *pdev, FILE *prn_stream, int y_origin,
101 const char *end_page)
102 {
103 #define DATA_SIZE (LINE_SIZE * 8)
104 byte *data =
105 (byte *)gs_malloc(pdev->memory, DATA_SIZE, 1,
106 "paintjet_print_page(data)");
107 byte *plane_data =
108 (byte *)gs_malloc(pdev->memory, LINE_SIZE * 3, 1,
109 "paintjet_print_page(plane_data)");
110 if ( data == 0 || plane_data == 0 )
111 { if ( data )
112 gs_free(pdev->memory, (char *)data, DATA_SIZE, 1,
113 "paintjet_print_page(data)");
114 if ( plane_data )
115 gs_free(pdev->memory, (char *)plane_data, LINE_SIZE * 3, 1,
116 "paintjet_print_page(plane_data)");
117 return_error(gs_error_VMerror);
118 }
119
120 /* set raster graphics resolution -- 90 or 180 dpi */
121 fprintf(prn_stream, "\033*t%dR", X_DPI);
122
123 /* set the line width */
124 fprintf(prn_stream, "\033*r%dS", DATA_SIZE);
125
126 /* set the number of color planes */
127 fprintf(prn_stream, "\033*r%dU", 3); /* always 3 */
128
129 /* move to top left of page */
130 fprintf(prn_stream, "\033&a0H\033&a%dV", y_origin);
131
132 /* select data compression */
133 fputs("\033*b1M", prn_stream);
134
135 /* start raster graphics */
136 fputs("\033*r1A", prn_stream);
137
138 /* Send each scan line in turn */
139 { int lnum;
140 int line_size = gdev_mem_bytes_per_scan_line((gx_device *)pdev);
141 int num_blank_lines = 0;
142 for ( lnum = 0; lnum < pdev->height; lnum++ )
143 { byte *end_data = data + line_size;
144 gdev_prn_copy_scan_lines(pdev, lnum,
145 (byte *)data, line_size);
146 /* Remove trailing 0s. */
147 while ( end_data > data && end_data[-1] == 0 )
148 end_data--;
149 if ( end_data == data )
150 { /* Blank line */
151 num_blank_lines++;
152 }
153 else
154 { int i;
155 byte *odp;
156 byte *row;
157
158 /* Pad with 0s to fill out the last */
159 /* block of 8 bytes. */
160 memset(end_data, 0, 7);
161
162 /* Transpose the data to get pixel planes. */
163 for ( i = 0, odp = plane_data; i < DATA_SIZE;
164 i += 8, odp++
165 )
166 { /* The following is for 16-bit machines */
167 #define spread3(c)\
168 { 0, c, c*0x100, c*0x101, c*0x10000L, c*0x10001L, c*0x10100L, c*0x10101L }
169 static ulong spr40[8] = spread3(0x40);
170 static ulong spr8[8] = spread3(8);
171 static ulong spr2[8] = spread3(2);
172 register byte *dp = data + i;
173 register ulong pword =
174 (spr40[dp[0]] << 1) +
175 (spr40[dp[1]]) +
176 (spr40[dp[2]] >> 1) +
177 (spr8[dp[3]] << 1) +
178 (spr8[dp[4]]) +
179 (spr8[dp[5]] >> 1) +
180 (spr2[dp[6]]) +
181 (spr2[dp[7]] >> 1);
182 odp[0] = (byte)(pword >> 16);
183 odp[LINE_SIZE] = (byte)(pword >> 8);
184 odp[LINE_SIZE*2] = (byte)(pword);
185 }
186 /* Skip blank lines if any */
187 if ( num_blank_lines > 0 )
188 { /* move down from current position */
189 fprintf(prn_stream, "\033&a+%dV",
190 num_blank_lines * (720 / Y_DPI));
191 num_blank_lines = 0;
192 }
193
194 /* Transfer raster graphics */
195 /* in the order R, G, B. */
196 for ( row = plane_data + LINE_SIZE * 2, i = 0;
197 i < 3; row -= LINE_SIZE, i++
198 )
199 { byte temp[LINE_SIZE * 2];
200 int count = compress1_row(row, row + LINE_SIZE, temp);
201 fprintf(prn_stream, "\033*b%d%c",
202 count, "VVW"[i]);
203 fwrite(temp, sizeof(byte),
204 count, prn_stream);
205 }
206 }
207 }
208 }
209
210 /* end the page */
211 fputs(end_page, prn_stream);
212
213 gs_free(pdev->memory, (char *)data, DATA_SIZE, 1, "paintjet_print_page(data)");
214 gs_free(pdev->memory, (char *)plane_data, LINE_SIZE * 3, 1, "paintjet_print_page(plane_data)");
215
216 return 0;
217 }
218
219 /*
220 * Row compression for the H-P PaintJet.
221 * Compresses data from row up to end_row, storing the result
222 * starting at compressed. Returns the number of bytes stored.
223 * The compressed format consists of a byte N followed by a
224 * data byte that is to be repeated N+1 times.
225 * In the worst case, the `compressed' representation is
226 * twice as large as the input.
227 * We complement the bytes at the same time, because
228 * we accumulated the image in complemented form.
229 */
230 private int
compress1_row(const byte * row,const byte * end_row,byte * compressed)231 compress1_row(const byte *row, const byte *end_row,
232 byte *compressed)
233 { register const byte *in = row;
234 register byte *out = compressed;
235 while ( in < end_row )
236 { byte test = *in++;
237 const byte *run = in;
238 while ( in < end_row && *in == test ) in++;
239 /* Note that in - run + 1 is the repetition count. */
240 while ( in - run > 255 )
241 { *out++ = 255;
242 *out++ = ~test;
243 run += 256;
244 }
245 *out++ = in - run;
246 *out++ = ~test;
247 }
248 return out - compressed;
249 }
250