1
/* Copyright (C) 2001-2006 Artifex Software, Inc.
4
This software is provided AS-IS with no warranty, either express or
7
This software is distributed under license and may not be copied, modified
8
or distributed except as expressly authorized under the terms of that
9
license. Refer to licensing information at http://www.artifex.com/
10
or contact Artifex Software, Inc., 7 Mt. Lassen Drive - Suite A-134,
11
San Rafael, CA 94903, U.S.A., +1(415)492-9861, for further information.
13
/* $Id: gdevdjtc.c 8250 2007-09-25 13:31:24Z giles $*/
14
/* HP DeskJet 500C driver */
20
*** Note: this driver was contributed by a user, Alfred Kayser:
21
*** please contact AKayser@et.tudelft.nl if you have questions.
24
#ifndef SHINGLING /* Interlaced, multi-pass printing */
25
#define SHINGLING 1 /* 0 = none, 1 = 50%, 2 = 25%, 2 is best & slowest */
28
#ifndef DEPLETION /* 'Intelligent' dot-removal */
29
#define DEPLETION 1 /* 0 = none, 1 = 25%, 2 = 50%, 1 best for graphics? */
30
#endif /* Use 0 for transparencies */
34
/* bytes per line for DeskJet Color */
35
#define LINE_SIZE ((X_DPI * 85 / 10 + 63) / 64 * 8)
37
/* The device descriptors */
38
static dev_proc_print_page(djet500c_print_page);
40
static gx_device_procs djet500c_procs =
41
prn_color_procs(gdev_prn_open, gdev_prn_output_page, gdev_prn_close,
42
gdev_pcl_3bit_map_rgb_color, gdev_pcl_3bit_map_color_rgb);
44
const gx_device_printer far_data gs_djet500c_device =
45
prn_device(djet500c_procs, "djet500c",
46
85, /* width_10ths, 8.5" */
47
120, /* height_10ths, 12" */
49
0.25, 0.25, 0.25, 0.25, /* margins */
50
3, djet500c_print_page);
52
/* Forward references */
53
static int djet500c_print_page(gx_device_printer *, FILE *);
55
static int mode2compress(byte *row, byte *end_row, byte *compressed);
57
/* The DeskJet 500C uses additive colors in separate planes. */
58
/* We only keep one bit of color, with 1 = R, 2 = G, 4 = B. */
59
/* Because the buffering routines assume 0 = white, */
60
/* we complement all the color components. */
62
/* Send the page to the printer. For speed, compress each scan line, */
63
/* since computer-to-printer communication time is often a bottleneck. */
64
/* The DeskJet Color can compress (mode 2) */
67
djet500c_print_page(gx_device_printer *pdev, FILE *fprn)
76
/* select the most compressed mode available & clear tmp storage */
77
/* put printer in known state */
80
/* ends raster graphics to set raster graphics resolution */
81
fputs("\033*rbC", fprn); /* was \033*rB */
83
/* set raster graphics resolution -- 300 dpi */
84
fputs("\033*t300R", fprn);
86
/* A4, skip perf, def. paper tray */
87
fputs("\033&l26a0l1H", fprn);
90
fputs("\033*r3U", fprn);
92
/* set depletion level */
93
fprintf(fprn, "\033*o%dD", DEPLETION);
95
/* set shingling level */
96
fprintf(fprn, "\033*o%dQ", SHINGLING);
98
/* move to top left of page & set current position */
99
fputs("\033*p0x0Y", fprn); /* cursor pos: 0,0 */
101
fputs("\033*b2M", fprn); /* mode 2 compression for now */
103
fputs("\033*r0A", fprn); /* start graf. left */
105
/* Send each scan line in turn */
107
int num_blank_lines = 0;
108
int lineSize = gdev_mem_bytes_per_scan_line((gx_device *)pdev);
109
if (lineSize>bitSize)
111
if (bitData) free(bitData);
113
bitData=(byte*)malloc(bitSize+16);
115
for (lnum=0; lnum<pdev->height; lnum++)
119
gdev_prn_copy_scan_lines(pdev, lnum, bitData, lineSize);
121
/* Remove trailing 0s. */
122
endData = bitData + lineSize;
123
while ( (endData>bitData) && (endData[-1] == 0) )
125
if (endData == bitData)
128
{ int count, k, i, lineLen;
130
/* Pad with 0s to fill out the last */
131
/* block of 8 bytes. */
132
memset(endData, 0, 7);
134
lineLen=((endData-bitData)+7)/8; /* Round to next 8multiple */
135
if (planeSize<lineLen)
137
if (plane1) free(plane1);
138
if (plane2) free(plane2);
139
if (plane3) free(plane3);
141
plane1=(byte*)malloc(planeSize+8);
142
plane2=(byte*)malloc(planeSize+8);
143
plane3=(byte*)malloc(planeSize+8);
145
/* Transpose the data to get pixel planes. */
146
for (k=i=0; k<lineLen; i+=8, k++)
148
register ushort t, c;
150
/* Three smaller loops are better optimizable and use less
151
vars, so most of them can be in registers even on pc's */
153
c = (c<<1) | (bitData[t+i]&4);
154
plane3[k] = ~(byte)(c>>2);
156
c = (c<<1) | (bitData[t+i]&2);
157
plane2[k] = ~(byte)(c>>1);
159
c = (c<<1) | (bitData[t+i]&1);
160
plane1[k] = ~(byte)(c);
163
/* Skip blank lines if any */
164
if (num_blank_lines > 0)
165
{ /* move down from current position */
166
fprintf(fprn, "\033*b%dY", num_blank_lines);
170
/* Transfer raster graphics */
171
/* in the order R, G, B. */
172
/* lineLen is at least bitSize/8, so bitData can easily be used to store
174
/* P.s. mode9 compression is akward(??) to use, because the lineLenght's
175
are different, so we are stuck with mode 2, which is good enough */
177
/* set the line width */
178
fprintf(fprn, "\033*r%dS", lineLen*8);
180
count = mode2compress(plane1, plane1 + lineLen, bitData);
181
fprintf(fprn, "\033*b%dV", count);
182
fwrite(bitData, sizeof(byte), count, fprn);
183
count = mode2compress(plane2, plane2 + lineLen, bitData);
184
fprintf(fprn, "\033*b%dV", count);
185
fwrite(bitData, sizeof(byte), count, fprn);
186
count = mode2compress(plane3, plane3 + lineLen, bitData);
187
fprintf(fprn, "\033*b%dW", count);
188
fwrite(bitData, sizeof(byte), count, fprn);
192
/* end raster graphics */
193
fputs("\033*rbC", fprn); /* was \033*rB */
194
fputs("\033*r1U", fprn); /* back to 1 plane */
196
/* put printer in known state */
200
fputs("\033&l0H", fprn);
202
/* release allocated memory */
203
if (bitData) free(bitData);
204
if (plane1) free(plane1);
205
if (plane2) free(plane2);
206
if (plane3) free(plane3);
213
* Mode 2 Row compression routine for the HP DeskJet & LaserJet IIp.
214
* Compresses data from row up to end_row, storing the result
215
* starting at compressed. Returns the number of bytes stored.
216
* Runs of K<=127 literal bytes are encoded as K-1 followed by
217
* the bytes; runs of 2<=K<=127 identical bytes are encoded as
218
* 257-K followed by the byte.
219
* In the worst case, the result is N+(N/127)+1 bytes long,
220
* where N is the original byte count (end_row - row).
221
* I can't use the general pcl version, because it assume even linelength's
225
mode2compress(byte *row, byte *end_row, byte *compressed)
227
register byte *exam; /* word being examined in the row to compress */
228
register byte *cptr = compressed; /* output pointer into compressed bytes */
236
/* Advance exam until test==*exam or exam==end_row */
237
while ((test != *exam) && (exam < end_row))
239
/* row points to start of differing bytes,
240
exam points to start of consequtive series
242
if (exam<end_row) exam--;
247
if (count>127) count=127;
249
for (i=0;i<count;i++) *cptr++ = *row++;
252
if (exam>=end_row) break; /* done */
253
exam++; /* skip first same byte */
254
while ((test == *exam) && (exam < end_row)) /* skip all same bytes */
256
/* exam points now first different word or to end of data */
261
if (count>127) count=127;
266
if (exam>=end_row) break; /* end of data */
267
row = exam; /* row points to first dissimular byte */
269
return (cptr-compressed);