2 |
- |
1 |
/* Copyright (C) 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: gdevl31s.c,v 1.5 2004/09/02 21:30:53 giles Exp $ */
|
|
|
18 |
/*
|
|
|
19 |
* H-P LaserJet 3100 driver
|
|
|
20 |
*
|
|
|
21 |
* This is a driver for use with the H-P LaserJet 3100 Software.
|
|
|
22 |
* It requires installed H-P LaserJet 3100 Software to print.
|
|
|
23 |
* It can be used with smbclient to print from an UNIX box
|
|
|
24 |
* to a LaserJet 3100 printer attached to a MS-Windows box.
|
|
|
25 |
*
|
|
|
26 |
* Written by Ulrich Schmid, uschmid@mail.hh.provi.de.
|
|
|
27 |
*/
|
|
|
28 |
|
|
|
29 |
#include "gdevprn.h"
|
|
|
30 |
#include "gdevmeds.h"
|
|
|
31 |
|
|
|
32 |
#define XCORRECTION 0.11
|
|
|
33 |
#define YCORRECTION 0.12
|
|
|
34 |
|
|
|
35 |
/* order matters! 0 1 2 3 4 5 6 7 8 */
|
|
|
36 |
const char *media[10] = {"a4", "letter", "legal", "com10", "c5", "dl", "b5", "monarch", "executive", 0};
|
|
|
37 |
const int height[2][10] = {{3447, 3240, 4140, 5587, 2644, 5083, 2975, 4387, 3090, 0},
|
|
|
38 |
{6894, 6480, 8280, 11167, 5288, 10159, 5950, 8767, 6180, 0}};
|
|
|
39 |
const int width[2] = {2528,
|
|
|
40 |
5056};
|
|
|
41 |
#define LARGEST_MEDIUM 2 /* legal */
|
|
|
42 |
|
|
|
43 |
/* These codes correspond to sequences of pixels with the same color.
|
|
|
44 |
* After the code for a sequence < 64 pixels the color changes.
|
|
|
45 |
* After the code for a sequence with 64 pixels the previous color continues. */
|
|
|
46 |
private struct {
|
|
|
47 |
uint bits;
|
|
|
48 |
uint length; /* number of valid bits */
|
|
|
49 |
} code[2][65] =
|
|
|
50 |
/* White */
|
|
|
51 |
{{{0x0ac, 8}, {0x038, 6}, {0x00e, 4}, {0x001, 4}, {0x00d, 4}, {0x003, 4}, {0x007, 4}, {0x00f, 4},
|
|
|
52 |
{0x019, 5}, {0x005, 5}, {0x01c, 5}, {0x002, 5}, {0x004, 6}, {0x030, 6}, {0x00b, 6}, {0x02b, 6},
|
|
|
53 |
{0x015, 6}, {0x035, 6}, {0x072, 7}, {0x018, 7}, {0x008, 7}, {0x074, 7}, {0x060, 7}, {0x010, 7},
|
|
|
54 |
{0x00a, 7}, {0x06a, 7}, {0x064, 7}, {0x012, 7}, {0x00c, 7}, {0x040, 8}, {0x0c0, 8}, {0x058, 8},
|
|
|
55 |
{0x0d8, 8}, {0x048, 8}, {0x0c8, 8}, {0x028, 8}, {0x0a8, 8}, {0x068, 8}, {0x0e8, 8}, {0x014, 8},
|
|
|
56 |
{0x094, 8}, {0x054, 8}, {0x0d4, 8}, {0x034, 8}, {0x0b4, 8}, {0x020, 8}, {0x0a0, 8}, {0x050, 8},
|
|
|
57 |
{0x0d0, 8}, {0x04a, 8}, {0x0ca, 8}, {0x02a, 8}, {0x0aa, 8}, {0x024, 8}, {0x0a4, 8}, {0x01a, 8},
|
|
|
58 |
{0x09a, 8}, {0x05a, 8}, {0x0da, 8}, {0x052, 8}, {0x0d2, 8}, {0x04c, 8}, {0x0cc, 8}, {0x02c, 8},
|
|
|
59 |
{0x01b, 5}},
|
|
|
60 |
/* Black */
|
|
|
61 |
{{0x3b0, 10}, {0x002, 3}, {0x003, 2}, {0x001, 2}, {0x006, 3}, {0x00c, 4}, {0x004, 4}, {0x018, 5},
|
|
|
62 |
{0x028, 6}, {0x008, 6}, {0x010, 7}, {0x050, 7}, {0x070, 7}, {0x020, 8}, {0x0e0, 8}, {0x030, 9},
|
|
|
63 |
{0x3a0, 10}, {0x060, 10}, {0x040, 10}, {0x730, 11}, {0x0b0, 11}, {0x1b0, 11}, {0x760, 11}, {0x0a0, 11},
|
|
|
64 |
{0x740, 11}, {0x0c0, 11}, {0x530, 12}, {0xd30, 12}, {0x330, 12}, {0xb30, 12}, {0x160, 12}, {0x960, 12},
|
|
|
65 |
{0x560, 12}, {0xd60, 12}, {0x4b0, 12}, {0xcb0, 12}, {0x2b0, 12}, {0xab0, 12}, {0x6b0, 12}, {0xeb0, 12},
|
|
|
66 |
{0x360, 12}, {0xb60, 12}, {0x5b0, 12}, {0xdb0, 12}, {0x2a0, 12}, {0xaa0, 12}, {0x6a0, 12}, {0xea0, 12},
|
|
|
67 |
{0x260, 12}, {0xa60, 12}, {0x4a0, 12}, {0xca0, 12}, {0x240, 12}, {0xec0, 12}, {0x1c0, 12}, {0xe40, 12},
|
|
|
68 |
{0x140, 12}, {0x1a0, 12}, {0x9a0, 12}, {0xd40, 12}, {0x340, 12}, {0x5a0, 12}, {0x660, 12}, {0xe60, 12},
|
|
|
69 |
{0x3c0, 10}}};
|
|
|
70 |
|
|
|
71 |
/* Define the default, maximum resolutions. */
|
|
|
72 |
#ifndef X_DPI
|
|
|
73 |
# define X_DPI 600
|
|
|
74 |
#endif
|
|
|
75 |
#ifndef Y_DPI
|
|
|
76 |
# define Y_DPI 600
|
|
|
77 |
#endif
|
|
|
78 |
|
|
|
79 |
/* The device descriptors */
|
|
|
80 |
private dev_proc_print_page_copies(lj3100sw_print_page_copies);
|
|
|
81 |
private dev_proc_close_device(lj3100sw_close);
|
|
|
82 |
|
|
|
83 |
private gx_device_procs prn_lj3100sw_procs =
|
|
|
84 |
prn_params_procs(gdev_prn_open, gdev_prn_output_page, lj3100sw_close,
|
|
|
85 |
gdev_prn_get_params, gdev_prn_put_params);
|
|
|
86 |
|
|
|
87 |
/* workaround to emulate the missing prn_device_margins_copies macro */
|
|
|
88 |
#define gx_default_print_page_copies lj3100sw_print_page_copies
|
|
|
89 |
gx_device_printer far_data gs_lj3100sw_device =
|
|
|
90 |
prn_device_margins/*_copies*/(prn_lj3100sw_procs, "lj3100sw",
|
|
|
91 |
DEFAULT_WIDTH_10THS, DEFAULT_HEIGHT_10THS,
|
|
|
92 |
X_DPI, Y_DPI,
|
|
|
93 |
XCORRECTION, YCORRECTION,
|
|
|
94 |
0.25, 0.2, 0.25, 0.2,
|
|
|
95 |
1, 0 /* lj3100sw_print_page_copies */);
|
|
|
96 |
#undef gx_default_print_page_copies
|
|
|
97 |
|
|
|
98 |
#define ppdev ((gx_device_printer *)pdev)
|
|
|
99 |
|
|
|
100 |
#define BUFFERSIZE 0x1000
|
|
|
101 |
|
|
|
102 |
private void
|
|
|
103 |
lj3100sw_output_section_header(FILE *prn_stream, int type, int arg1, int arg2)
|
|
|
104 |
{
|
|
|
105 |
fputc(type & 0xff, prn_stream);
|
|
|
106 |
fputc(type >> 8 & 0xff, prn_stream);
|
|
|
107 |
fputc(arg1 & 0xff, prn_stream);
|
|
|
108 |
fputc(arg1 >> 8 & 0xff, prn_stream);
|
|
|
109 |
fputc(arg2 & 0xff, prn_stream);
|
|
|
110 |
fputc(arg2 >> 8 & 0xff, prn_stream);
|
|
|
111 |
}
|
|
|
112 |
|
|
|
113 |
private void
|
|
|
114 |
lj3100sw_flush_buffer(FILE *prn_stream, char *buffer, char **pptr)
|
|
|
115 |
{
|
|
|
116 |
int size = *pptr - buffer;
|
|
|
117 |
if (size) {
|
|
|
118 |
lj3100sw_output_section_header(prn_stream, 0, size, 0);
|
|
|
119 |
fwrite(buffer, 1, size, prn_stream);
|
|
|
120 |
*pptr = buffer;
|
|
|
121 |
}
|
|
|
122 |
}
|
|
|
123 |
|
|
|
124 |
private void
|
|
|
125 |
lj3100sw_output_data_byte(FILE *prn_stream, char *buffer, char **pptr, int val)
|
|
|
126 |
{
|
|
|
127 |
if (*pptr >= buffer + BUFFERSIZE)
|
|
|
128 |
lj3100sw_flush_buffer(prn_stream, buffer, pptr);
|
|
|
129 |
*(*pptr)++ = val;
|
|
|
130 |
}
|
|
|
131 |
|
|
|
132 |
private void
|
|
|
133 |
lj3100sw_output_repeated_data_bytes(FILE *prn_stream, char *buffer, char **pptr, int val, int num)
|
|
|
134 |
{
|
|
|
135 |
int size;
|
|
|
136 |
while (num) {
|
|
|
137 |
if (*pptr >= buffer + BUFFERSIZE)
|
|
|
138 |
lj3100sw_flush_buffer(prn_stream, buffer, pptr);
|
|
|
139 |
size = min(num, buffer + BUFFERSIZE - *pptr);
|
|
|
140 |
memset(*pptr, val, size);
|
|
|
141 |
*pptr += size;
|
|
|
142 |
num -= size;
|
|
|
143 |
}
|
|
|
144 |
}
|
|
|
145 |
|
|
|
146 |
private void
|
|
|
147 |
lj3100sw_output_newline(FILE *prn_stream, char *buffer, char **pptr)
|
|
|
148 |
{
|
|
|
149 |
lj3100sw_output_data_byte(prn_stream, buffer, pptr, 0);
|
|
|
150 |
lj3100sw_output_data_byte(prn_stream, buffer, pptr, 0);
|
|
|
151 |
lj3100sw_output_data_byte(prn_stream, buffer, pptr, 0x80);
|
|
|
152 |
}
|
|
|
153 |
|
|
|
154 |
private void
|
|
|
155 |
lj3100sw_output_empty_line(FILE *prn_stream, char *buffer, char **pptr, bool high_resolution)
|
|
|
156 |
{
|
|
|
157 |
if (high_resolution) {
|
|
|
158 |
lj3100sw_output_data_byte(prn_stream, buffer, pptr, 0x80);
|
|
|
159 |
lj3100sw_output_data_byte(prn_stream, buffer, pptr, 0x0f);
|
|
|
160 |
lj3100sw_output_data_byte(prn_stream, buffer, pptr, 0x78);
|
|
|
161 |
lj3100sw_output_data_byte(prn_stream, buffer, pptr, 0xac);
|
|
|
162 |
} else {
|
|
|
163 |
lj3100sw_output_data_byte(prn_stream, buffer, pptr, 0x80);
|
|
|
164 |
lj3100sw_output_data_byte(prn_stream, buffer, pptr, 0x87);
|
|
|
165 |
lj3100sw_output_data_byte(prn_stream, buffer, pptr, 0x0d);
|
|
|
166 |
}
|
|
|
167 |
}
|
|
|
168 |
|
|
|
169 |
private int
|
|
|
170 |
lj3100sw_print_page_copies(gx_device_printer *pdev, FILE *prn_stream, int num_copies /* ignored */)
|
|
|
171 |
{
|
|
|
172 |
int i, j;
|
|
|
173 |
char buffer[BUFFERSIZE], *ptr = buffer;
|
|
|
174 |
int medium_index = select_medium(pdev, media, LARGEST_MEDIUM);
|
|
|
175 |
bool high_resolution = (pdev->x_pixels_per_inch > 300);
|
|
|
176 |
int printer_height = height[high_resolution ? 1 : 0][medium_index];
|
|
|
177 |
int printer_width = width[high_resolution ? 1 : 0];
|
|
|
178 |
int paper_height = pdev->height;
|
|
|
179 |
int paper_width = pdev->width;
|
|
|
180 |
int line_size = gdev_prn_raster(pdev);
|
|
|
181 |
gs_memory_t *mem = pdev->memory;
|
|
|
182 |
byte *in = (byte *)gs_malloc(mem, line_size, 1, "lj3100sw_print_page");
|
|
|
183 |
byte *data;
|
|
|
184 |
if (in == 0)
|
|
|
185 |
return_error(gs_error_VMerror);
|
|
|
186 |
if (gdev_prn_file_is_new(pdev)) {
|
|
|
187 |
lj3100sw_output_section_header(prn_stream, 1, 0, 0);
|
|
|
188 |
lj3100sw_output_repeated_data_bytes(prn_stream, buffer, &ptr, 0x1b, 12);
|
|
|
189 |
ptr += sprintf(ptr, "\r\nBD");
|
|
|
190 |
lj3100sw_output_repeated_data_bytes(prn_stream, buffer, &ptr, 0, 5520);
|
|
|
191 |
ptr += sprintf(ptr, "%s\r\n%s %d\r\n%s %d\r\n%s %d\r\n%s %d\r\n%s %d\r\n%s %d\r\n",
|
|
|
192 |
"NJ",
|
|
|
193 |
"PQ", -1,
|
|
|
194 |
"RE", high_resolution ? 6 : 2,
|
|
|
195 |
"SL", printer_width,
|
|
|
196 |
"LM", 0,
|
|
|
197 |
"PS", medium_index,
|
|
|
198 |
"PC", 0);
|
|
|
199 |
lj3100sw_flush_buffer(prn_stream, buffer, &ptr);
|
|
|
200 |
}
|
|
|
201 |
|
|
|
202 |
lj3100sw_output_section_header(prn_stream, 3, ppdev->NumCopies, 0);
|
|
|
203 |
ptr += sprintf(ptr, "%s %d\r\n%s\r\n",
|
|
|
204 |
"CM", 1,
|
|
|
205 |
"PD");
|
|
|
206 |
*ptr++ = 0;
|
|
|
207 |
lj3100sw_output_newline(prn_stream, buffer, &ptr);
|
|
|
208 |
|
|
|
209 |
for (i = 0; i < printer_height; i++) {
|
|
|
210 |
if (i < paper_height) {
|
|
|
211 |
int color = 0; /* white */
|
|
|
212 |
int count = 0;
|
|
|
213 |
int bit_index = 0;
|
|
|
214 |
uint tmp = 0;
|
|
|
215 |
gdev_prn_get_bits(pdev, i, in, &data);
|
|
|
216 |
for (j = 0; j <= printer_width; j++) {
|
|
|
217 |
int xoffset = (printer_width - paper_width) / 2;
|
|
|
218 |
int newcolor = 0;
|
|
|
219 |
if (j >= xoffset && j < xoffset + paper_width)
|
|
|
220 |
newcolor = (data[(j - xoffset) / 8] >> (7 - (j - xoffset) % 8)) & 1;
|
|
|
221 |
if (j == printer_width)
|
|
|
222 |
newcolor = !color; /* force output */
|
|
|
223 |
if (newcolor == color)
|
|
|
224 |
count++;
|
|
|
225 |
else if (count == printer_width && color == 0) /* implies j == printer_width */
|
|
|
226 |
lj3100sw_output_empty_line(prn_stream, buffer, &ptr, high_resolution);
|
|
|
227 |
else /* print a sequence of pixels with a uniform color */
|
|
|
228 |
while (newcolor != color) {
|
|
|
229 |
int size = min(count, 64);
|
|
|
230 |
tmp |= code[color][size].bits << bit_index;
|
|
|
231 |
bit_index += code[color][size].length;
|
|
|
232 |
while (bit_index >= 8) {
|
|
|
233 |
lj3100sw_output_data_byte(prn_stream, buffer, &ptr, tmp & 0xff);
|
|
|
234 |
tmp >>= 8;
|
|
|
235 |
bit_index -= 8;
|
|
|
236 |
}
|
|
|
237 |
if (size == 64)
|
|
|
238 |
count -= 64;
|
|
|
239 |
else {
|
|
|
240 |
color = newcolor;
|
|
|
241 |
count = 1;
|
|
|
242 |
}
|
|
|
243 |
}
|
|
|
244 |
}
|
|
|
245 |
if (bit_index)
|
|
|
246 |
lj3100sw_output_data_byte(prn_stream, buffer, &ptr, tmp & 0xff);
|
|
|
247 |
}
|
|
|
248 |
else
|
|
|
249 |
lj3100sw_output_empty_line(prn_stream, buffer, &ptr, high_resolution);
|
|
|
250 |
lj3100sw_output_newline(prn_stream, buffer, &ptr);
|
|
|
251 |
}
|
|
|
252 |
|
|
|
253 |
for (i = 0; i < 3; i++ ) {
|
|
|
254 |
lj3100sw_output_data_byte(prn_stream, buffer, &ptr, 0x00);
|
|
|
255 |
lj3100sw_output_data_byte(prn_stream, buffer, &ptr, 0x08);
|
|
|
256 |
lj3100sw_output_data_byte(prn_stream, buffer, &ptr, 0x80);
|
|
|
257 |
}
|
|
|
258 |
lj3100sw_output_repeated_data_bytes(prn_stream, buffer, &ptr, 0, 520);
|
|
|
259 |
lj3100sw_flush_buffer(prn_stream, buffer, &ptr);
|
|
|
260 |
|
|
|
261 |
lj3100sw_output_section_header(prn_stream, 4, 0, 0);
|
|
|
262 |
for (i = 0; i < 4 * ppdev->NumCopies; i++)
|
|
|
263 |
lj3100sw_output_section_header(prn_stream, 54, 0, 0);
|
|
|
264 |
|
|
|
265 |
gs_free(mem, (char *)in, line_size, 1, "lj3100sw_print_page");
|
|
|
266 |
return 0;
|
|
|
267 |
}
|
|
|
268 |
|
|
|
269 |
private int
|
|
|
270 |
lj3100sw_close(gx_device *pdev)
|
|
|
271 |
{
|
|
|
272 |
int i;
|
|
|
273 |
FILE *prn_stream = ((gx_device_printer *)pdev)->file;
|
|
|
274 |
|
|
|
275 |
lj3100sw_output_section_header(prn_stream, 0, 4, 0);
|
|
|
276 |
fputs("XX\r\n", prn_stream);
|
|
|
277 |
for (i = 0; i < 4 * ppdev->NumCopies; i++)
|
|
|
278 |
lj3100sw_output_section_header(prn_stream, 54, 0, 0);
|
|
|
279 |
lj3100sw_output_section_header(prn_stream, 2, 0, 0);
|
|
|
280 |
|
|
|
281 |
return gdev_prn_close(pdev);
|
|
|
282 |
}
|