2 |
- |
1 |
/* Copyright (C) 1989, 1990, 1991 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: gdevdjtc.c,v 1.6 2002/06/16 05:48:54 lpd Exp $*/
|
|
|
18 |
/* HP DeskJet 500C driver */
|
|
|
19 |
#include "gdevprn.h"
|
|
|
20 |
#include "gdevpcl.h"
|
|
|
21 |
#include "malloc_.h"
|
|
|
22 |
|
|
|
23 |
/***
|
|
|
24 |
*** Note: this driver was contributed by a user, Alfred Kayser:
|
|
|
25 |
*** please contact AKayser@et.tudelft.nl if you have questions.
|
|
|
26 |
***/
|
|
|
27 |
|
|
|
28 |
#ifndef SHINGLING /* Interlaced, multi-pass printing */
|
|
|
29 |
#define SHINGLING 1 /* 0 = none, 1 = 50%, 2 = 25%, 2 is best & slowest */
|
|
|
30 |
#endif
|
|
|
31 |
|
|
|
32 |
#ifndef DEPLETION /* 'Intelligent' dot-removal */
|
|
|
33 |
#define DEPLETION 1 /* 0 = none, 1 = 25%, 2 = 50%, 1 best for graphics? */
|
|
|
34 |
#endif /* Use 0 for transparencies */
|
|
|
35 |
|
|
|
36 |
#define X_DPI 300
|
|
|
37 |
#define Y_DPI 300
|
|
|
38 |
/* bytes per line for DeskJet Color */
|
|
|
39 |
#define LINE_SIZE ((X_DPI * 85 / 10 + 63) / 64 * 8)
|
|
|
40 |
|
|
|
41 |
/* The device descriptors */
|
|
|
42 |
private dev_proc_print_page(djet500c_print_page);
|
|
|
43 |
|
|
|
44 |
private gx_device_procs djet500c_procs =
|
|
|
45 |
prn_color_procs(gdev_prn_open, gdev_prn_output_page, gdev_prn_close,
|
|
|
46 |
gdev_pcl_3bit_map_rgb_color, gdev_pcl_3bit_map_color_rgb);
|
|
|
47 |
|
|
|
48 |
const gx_device_printer far_data gs_djet500c_device =
|
|
|
49 |
prn_device(djet500c_procs, "djet500c",
|
|
|
50 |
85, /* width_10ths, 8.5" */
|
|
|
51 |
120, /* height_10ths, 12" */
|
|
|
52 |
X_DPI, Y_DPI,
|
|
|
53 |
0.25, 0.25, 0.25, 0.25, /* margins */
|
|
|
54 |
3, djet500c_print_page);
|
|
|
55 |
|
|
|
56 |
/* Forward references */
|
|
|
57 |
private int djet500c_print_page(gx_device_printer *, FILE *);
|
|
|
58 |
|
|
|
59 |
static int mode2compress(byte *row, byte *end_row, byte *compressed);
|
|
|
60 |
|
|
|
61 |
/* The DeskJet 500C uses additive colors in separate planes. */
|
|
|
62 |
/* We only keep one bit of color, with 1 = R, 2 = G, 4 = B. */
|
|
|
63 |
/* Because the buffering routines assume 0 = white, */
|
|
|
64 |
/* we complement all the color components. */
|
|
|
65 |
|
|
|
66 |
/* Send the page to the printer. For speed, compress each scan line, */
|
|
|
67 |
/* since computer-to-printer communication time is often a bottleneck. */
|
|
|
68 |
/* The DeskJet Color can compress (mode 2) */
|
|
|
69 |
|
|
|
70 |
private int
|
|
|
71 |
djet500c_print_page(gx_device_printer *pdev, FILE *fprn)
|
|
|
72 |
{
|
|
|
73 |
byte *bitData=NULL;
|
|
|
74 |
byte *plane1=NULL;
|
|
|
75 |
byte *plane2=NULL;
|
|
|
76 |
byte *plane3=NULL;
|
|
|
77 |
int bitSize=0;
|
|
|
78 |
int planeSize=0;
|
|
|
79 |
|
|
|
80 |
/* select the most compressed mode available & clear tmp storage */
|
|
|
81 |
/* put printer in known state */
|
|
|
82 |
fputs("\033E",fprn);
|
|
|
83 |
|
|
|
84 |
/* ends raster graphics to set raster graphics resolution */
|
|
|
85 |
fputs("\033*rbC", fprn); /* was \033*rB */
|
|
|
86 |
|
|
|
87 |
/* set raster graphics resolution -- 300 dpi */
|
|
|
88 |
fputs("\033*t300R", fprn);
|
|
|
89 |
|
|
|
90 |
/* A4, skip perf, def. paper tray */
|
|
|
91 |
fputs("\033&l26a0l1H", fprn);
|
|
|
92 |
|
|
|
93 |
/* RGB Mode */
|
|
|
94 |
fputs("\033*r3U", fprn);
|
|
|
95 |
|
|
|
96 |
/* set depletion level */
|
|
|
97 |
fprintf(fprn, "\033*o%dD", DEPLETION);
|
|
|
98 |
|
|
|
99 |
/* set shingling level */
|
|
|
100 |
fprintf(fprn, "\033*o%dQ", SHINGLING);
|
|
|
101 |
|
|
|
102 |
/* move to top left of page & set current position */
|
|
|
103 |
fputs("\033*p0x0Y", fprn); /* cursor pos: 0,0 */
|
|
|
104 |
|
|
|
105 |
fputs("\033*b2M", fprn); /* mode 2 compression for now */
|
|
|
106 |
|
|
|
107 |
fputs("\033*r0A", fprn); /* start graf. left */
|
|
|
108 |
|
|
|
109 |
/* Send each scan line in turn */
|
|
|
110 |
{ int lnum;
|
|
|
111 |
int num_blank_lines = 0;
|
|
|
112 |
int lineSize = gdev_mem_bytes_per_scan_line((gx_device *)pdev);
|
|
|
113 |
if (lineSize>bitSize)
|
|
|
114 |
{
|
|
|
115 |
if (bitData) free(bitData);
|
|
|
116 |
bitSize=lineSize;
|
|
|
117 |
bitData=(byte*)malloc(bitSize+16);
|
|
|
118 |
}
|
|
|
119 |
for (lnum=0; lnum<pdev->height; lnum++)
|
|
|
120 |
{
|
|
|
121 |
byte *endData;
|
|
|
122 |
|
|
|
123 |
gdev_prn_copy_scan_lines(pdev, lnum, bitData, lineSize);
|
|
|
124 |
|
|
|
125 |
/* Remove trailing 0s. */
|
|
|
126 |
endData = bitData + lineSize;
|
|
|
127 |
while ( (endData>bitData) && (endData[-1] == 0) )
|
|
|
128 |
endData--;
|
|
|
129 |
if (endData == bitData)
|
|
|
130 |
num_blank_lines++;
|
|
|
131 |
else
|
|
|
132 |
{ int count, k, i, lineLen;
|
|
|
133 |
|
|
|
134 |
/* Pad with 0s to fill out the last */
|
|
|
135 |
/* block of 8 bytes. */
|
|
|
136 |
memset(endData, 0, 7);
|
|
|
137 |
|
|
|
138 |
lineLen=((endData-bitData)+7)/8; /* Round to next 8multiple */
|
|
|
139 |
if (planeSize<lineLen)
|
|
|
140 |
{
|
|
|
141 |
if (plane1) free(plane1);
|
|
|
142 |
if (plane2) free(plane2);
|
|
|
143 |
if (plane3) free(plane3);
|
|
|
144 |
planeSize=lineLen;
|
|
|
145 |
plane1=(byte*)malloc(planeSize+8);
|
|
|
146 |
plane2=(byte*)malloc(planeSize+8);
|
|
|
147 |
plane3=(byte*)malloc(planeSize+8);
|
|
|
148 |
}
|
|
|
149 |
/* Transpose the data to get pixel planes. */
|
|
|
150 |
for (k=i=0; k<lineLen; i+=8, k++)
|
|
|
151 |
{
|
|
|
152 |
register ushort t, c;
|
|
|
153 |
|
|
|
154 |
/* Three smaller loops are better optimizable and use less
|
|
|
155 |
vars, so most of them can be in registers even on pc's */
|
|
|
156 |
for (c=t=0;t<8;t++)
|
|
|
157 |
c = (c<<1) | (bitData[t+i]&4);
|
|
|
158 |
plane3[k] = ~(byte)(c>>2);
|
|
|
159 |
for (c=t=0;t<8;t++)
|
|
|
160 |
c = (c<<1) | (bitData[t+i]&2);
|
|
|
161 |
plane2[k] = ~(byte)(c>>1);
|
|
|
162 |
for (c=t=0;t<8;t++)
|
|
|
163 |
c = (c<<1) | (bitData[t+i]&1);
|
|
|
164 |
plane1[k] = ~(byte)(c);
|
|
|
165 |
}
|
|
|
166 |
|
|
|
167 |
/* Skip blank lines if any */
|
|
|
168 |
if (num_blank_lines > 0)
|
|
|
169 |
{ /* move down from current position */
|
|
|
170 |
fprintf(fprn, "\033*b%dY", num_blank_lines);
|
|
|
171 |
num_blank_lines = 0;
|
|
|
172 |
}
|
|
|
173 |
|
|
|
174 |
/* Transfer raster graphics */
|
|
|
175 |
/* in the order R, G, B. */
|
|
|
176 |
/* lineLen is at least bitSize/8, so bitData can easily be used to store
|
|
|
177 |
lineLen of bytes */
|
|
|
178 |
/* P.s. mode9 compression is akward(??) to use, because the lineLenght's
|
|
|
179 |
are different, so we are stuck with mode 2, which is good enough */
|
|
|
180 |
|
|
|
181 |
/* set the line width */
|
|
|
182 |
fprintf(fprn, "\033*r%dS", lineLen*8);
|
|
|
183 |
|
|
|
184 |
count = mode2compress(plane1, plane1 + lineLen, bitData);
|
|
|
185 |
fprintf(fprn, "\033*b%dV", count);
|
|
|
186 |
fwrite(bitData, sizeof(byte), count, fprn);
|
|
|
187 |
count = mode2compress(plane2, plane2 + lineLen, bitData);
|
|
|
188 |
fprintf(fprn, "\033*b%dV", count);
|
|
|
189 |
fwrite(bitData, sizeof(byte), count, fprn);
|
|
|
190 |
count = mode2compress(plane3, plane3 + lineLen, bitData);
|
|
|
191 |
fprintf(fprn, "\033*b%dW", count);
|
|
|
192 |
fwrite(bitData, sizeof(byte), count, fprn);
|
|
|
193 |
}
|
|
|
194 |
}
|
|
|
195 |
}
|
|
|
196 |
/* end raster graphics */
|
|
|
197 |
fputs("\033*rbC", fprn); /* was \033*rB */
|
|
|
198 |
fputs("\033*r1U", fprn); /* back to 1 plane */
|
|
|
199 |
|
|
|
200 |
/* put printer in known state */
|
|
|
201 |
fputs("\033E",fprn);
|
|
|
202 |
|
|
|
203 |
/* eject page */
|
|
|
204 |
fputs("\033&l0H", fprn);
|
|
|
205 |
|
|
|
206 |
/* release allocated memory */
|
|
|
207 |
if (bitData) free(bitData);
|
|
|
208 |
if (plane1) free(plane1);
|
|
|
209 |
if (plane2) free(plane2);
|
|
|
210 |
if (plane3) free(plane3);
|
|
|
211 |
|
|
|
212 |
return 0;
|
|
|
213 |
}
|
|
|
214 |
|
|
|
215 |
|
|
|
216 |
/*
|
|
|
217 |
* Mode 2 Row compression routine for the HP DeskJet & LaserJet IIp.
|
|
|
218 |
* Compresses data from row up to end_row, storing the result
|
|
|
219 |
* starting at compressed. Returns the number of bytes stored.
|
|
|
220 |
* Runs of K<=127 literal bytes are encoded as K-1 followed by
|
|
|
221 |
* the bytes; runs of 2<=K<=127 identical bytes are encoded as
|
|
|
222 |
* 257-K followed by the byte.
|
|
|
223 |
* In the worst case, the result is N+(N/127)+1 bytes long,
|
|
|
224 |
* where N is the original byte count (end_row - row).
|
|
|
225 |
* I can't use the general pcl version, because it assume even linelength's
|
|
|
226 |
*/
|
|
|
227 |
|
|
|
228 |
static int
|
|
|
229 |
mode2compress(byte *row, byte *end_row, byte *compressed)
|
|
|
230 |
{
|
|
|
231 |
register byte *exam; /* word being examined in the row to compress */
|
|
|
232 |
register byte *cptr = compressed; /* output pointer into compressed bytes */
|
|
|
233 |
int i, count, len;
|
|
|
234 |
byte test;
|
|
|
235 |
|
|
|
236 |
exam = row;
|
|
|
237 |
while (1)
|
|
|
238 |
{
|
|
|
239 |
test = *exam++;
|
|
|
240 |
/* Advance exam until test==*exam or exam==end_row */
|
|
|
241 |
while ((test != *exam) && (exam < end_row))
|
|
|
242 |
test = *exam++;
|
|
|
243 |
/* row points to start of differing bytes,
|
|
|
244 |
exam points to start of consequtive series
|
|
|
245 |
or to end of row */
|
|
|
246 |
if (exam<end_row) exam--;
|
|
|
247 |
len=exam-row;
|
|
|
248 |
while (len>0)
|
|
|
249 |
{
|
|
|
250 |
count=len;
|
|
|
251 |
if (count>127) count=127;
|
|
|
252 |
*cptr++=count-1;
|
|
|
253 |
for (i=0;i<count;i++) *cptr++ = *row++;
|
|
|
254 |
len-=count;
|
|
|
255 |
}
|
|
|
256 |
if (exam>=end_row) break; /* done */
|
|
|
257 |
exam++; /* skip first same byte */
|
|
|
258 |
while ((test == *exam) && (exam < end_row)) /* skip all same bytes */
|
|
|
259 |
exam++;
|
|
|
260 |
/* exam points now first different word or to end of data */
|
|
|
261 |
len = exam-row;
|
|
|
262 |
while (len>0)
|
|
|
263 |
{
|
|
|
264 |
count=len;
|
|
|
265 |
if (count>127) count=127;
|
|
|
266 |
*cptr++=(257-count);
|
|
|
267 |
*cptr++=test;
|
|
|
268 |
len-=count;
|
|
|
269 |
}
|
|
|
270 |
if (exam>=end_row) break; /* end of data */
|
|
|
271 |
row = exam; /* row points to first dissimular byte */
|
|
|
272 |
}
|
|
|
273 |
return (cptr-compressed);
|
|
|
274 |
}
|