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
djet500c_print_page(gx_device_printer * pdev,FILE * fprn)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
mode2compress(byte * row,byte * end_row,byte * compressed)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 }
275