2 |
- |
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
|
|
|
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
|
|
|
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
|
|
|
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
|
|
|
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
|
|
|
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 |
}
|