1 /*
2 Copyright (C) 2000 Hewlett-Packard Company
3 Portions Copyright (C) 1996-1998 <Uli Wortmann uliw@erdw.ethz.ch>.
4 Portions Copyright (C) 1999 Aladdin Enterprises. All rights reserved.
5
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
10
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19
20 This program may also be distributed as part of Aladdin Ghostscript,
21 under the terms of the Aladdin Free Public License (the "License").
22
23 Every copy of Aladdin Ghostscript must include a copy of the
24 License, normally in a plain ASCII text file named PUBLIC. The
25 License grants you the right to copy, modify and redistribute
26 Aladdin Ghostscript, but only under certain conditions described in
27 the License. Among other things, the License requires that the
28 copyright notice and this notice be preserved on all copies.
29 */
30
31 /* $Id: gdevcd8.c,v 1.5 2002/07/30 18:53:21 easysw Exp $ */
32
33 /*----------------------------------------------------------------
34
35 A printer driver for the HP670, HP690, HP850, HP855
36 HP870, HP890, HP1100, HP1600 and HP2200 color printers.
37 Also work with HP DesignJet 500 large-format color printer.
38 To be used with the Ghostscript printing system.
39
40 CREDITS: Much of the driver is based on ideas derived
41 from the cdj550 driver of George Cameron.
42
43 The support for the hp670, hp690, hp890
44 and hp1600 was added by Martin Gerbershagen.
45
46 The support for the hp2200 was added by Siow-Kiat Tan.
47
48 The support for the dnj500 was added by Timur Maximov.
49
50 -------------------------------------------------------------------*/
51
52 /* Note: Depending on how you transfered the files,
53 you might need to remove some CR-codes used on intel-based machines:
54
55 simply type: unzip -a hp850.zip
56
57 to compile with gs5.x, simply add
58
59 DEVICE_DEVS4=cdj850.dev cdj670.dev cdj890.dev cdj1600.dev
60
61 to your makefile.
62
63 BTW, it is always a good idea to read Make.htm found in the
64 gs-distrib before attempting to recompile.....
65
66 */
67
68 /* 1999-01-07 edited by L. Peter Deutsch <ghost@aladdin.com> to eliminate
69 non-const statics and otherwise bring up to date with Ghostscript coding
70 style guidelines. */
71
72 /* 01.06.98 Version 1.3 Due to the most welcome contribution
73 of Martin Gerbershagen (ger@ulm.temic.de),
74 support for the hp670, hp690 and hp890
75 and hp1600 has been added. Martin has also
76 resolved all known bugs.
77
78 Problems : Dark colors are still pale.
79
80
81 The driver no longer needs special switches to be invoked
82 except -sDEVICE=cdj850, or -sDEVICE=CDJ890, or sDEVICE=CDJ670
83 or -sDEVICE=CDJ1600
84
85 The hp690 is supported through the hp670 device, the hp855, hp870
86 and the hp1100 through the hp850 device.
87
88 The driver implements the following switches:
89
90 -dPapertype= 0 plain paper [default]
91 1 bond paper
92 2 special paper
93 3 glossy film
94 4 transparency film
95
96 Note, currently the lookuptables are not suited
97 for printing on special paper or transperencies.
98 Please revert to the gamma functions in this case.
99
100 -dQuality= -1 draft
101 0 normal [default]
102 1 presentation
103
104 -dRetStatus= 0 C-RET off
105 1 C-RET on [default]
106
107 -dMasterGamma= 3.0 [default = 1.0]
108 __Note__: To take advantage of the calibrated color-transfer
109 functions, be sure not to have any Gamma-Statements
110 left! If you need to (i.e. overhead sheets),
111 you still can use the gamma-functions, but they will
112 override the built-in calibration. To use gamma in the
113 traditional way, set MasterGamma to any value greater
114 1.0 and less 10.0. To adjust individual gamma-values,
115 you have to additionally set MasterGamma to a value
116 greater 1.0 and less 10.0
117
118 With the next release, gamma functions will be dropped.
119
120 When using the driver, be aware that printing in 600dpi involves
121 processing of large amounts of data (> 188MB !). Therefore, the
122 driver is not what you would expect to be a fast driver ;-)
123 This is no problem when printing a full sized color page (because
124 printing itself is slow), but it's really annoying if yoy print only
125 text pages. Maybe I can optimize the code for text-only pages in a
126 later release. Right now, it is recommended to use the highest
127 possible optimisation level your compiler offers....
128 For the time beeing, use the cdj550 device with -sBitsPerPixel=3
129 for fast proof-prints. If you simply want to print 600dpi b/w data,
130 use the cdj550 device with -sBitsPerPixel=8 (or 1).
131
132 Since the printer itself is slow, it may help to set the
133 process-priority of the gs-process to regular or even less. On a
134 486/100MHZ this is still sufficient to maintain a continuos
135 data-flow.
136 Note to OS/2 users: Simply put the gs-window into the background,
137 or minimize it. Also make sure, that print01.sys is invoked without
138 the /irq switch (great speed improvement under warp4).
139
140 The printer default settings compensate for dot-gain by a
141 calibrated color-transfer function. If this appears to be to light
142 for your business-graphs, or for overhead-sheets, feel free to set
143 -dMasterGamma=1.7.
144
145 Furthermore, you may tweak the gammavalues independently by setting
146 -dGammaValC, -dGammaValM, -dGammaValY or -dGammaValK (if not set,
147 the values default to MasterGamma). This will only work, when
148 -dMasterGamma is set to a value greater than 1.0.
149
150 If you want to learn more about gamma, see:
151
152 http://www.erdw.ethz.ch/~bonk/ftp/misc/gammafaq.pdf
153 http://www.erdw.ethz.ch/~bonk/ftp/misc/colorfaq.pdf
154
155 Further information, bugs, tips etc, can be found
156 at my website.
157
158 Have fun!
159
160 Uli
161
162 http://www.erdw.ethz.ch/~bonk/bonk.html
163
164 */
165
166 /* 25.08.97 Version 1.2. Resolved all but one of the
167 known bugs, introduced a couple
168 of perfomance improvements. Complete
169 new color-transfer-function handling.
170 (see gamma). */
171
172 /* 04.05.97 Version 1.1. For added features, */
173 /* resolved bugs and so forth, please see */
174 /* http://bonk.ethz.ch */
175
176 /* 11.11.96. Initial release of the driver */
177
178 #include "math_.h"
179 #include <stdlib.h> /* for rand() */
180 #include "assert_.h"
181 #include "gdevprn.h"
182 #include "gdevpcl.h"
183 #include "gsparam.h"
184
185 #include "gdebug.h"
186 #include <string.h>
187
188 /* Conversion stuff. */
189 #include "gxlum.h"
190
191 #define near
192
193 /* This holds the initialisation data of the hp850. These are sent to
194 * the printer with the Config Raster command (Esc * g # W ...) during
195 * printer initialization. See the functions cdj850_start_raster_mode(),
196 * cdj880_start_raster_mode(), and cdj1600_start_raster_mode().
197 */
198 typedef struct hp850_cmyk_init_s {
199 byte a[26];
200 } hp850_cmyk_init_t;
201 static const hp850_cmyk_init_t hp850_cmyk_init =
202 {
203 {
204 0x02, /* format */
205 0x04, /* number of components */
206 /* black */
207 0x01, /* MSB x resolution */
208 0x2c, /* LSB x resolution */
209 0x01, /* MSB y resolution */
210 0x2c, /* LSB y resolution */
211 0x00, /* MSB intensity levels */
212 0x02, /* LSB intensity levels */
213
214 /* cyan */
215 0x01, /* MSB x resolution */
216 0x2c, /* LSB x resolution */
217 0x01, /* MSB y resolution */
218 0x2c, /* LSB y resolution */
219 0x00, /* MSB intensity levels */
220 0x02, /* LSB intensity levels */
221
222 /* magenta */
223 0x01, /* MSB x resolution */
224 0x2c, /* LSB x resolution */
225 0x01, /* MSB y resolution */
226 0x2c, /* LSB y resolution */
227 0x00, /* MSB intensity levels */
228 0x02, /* LSB intensity levels */
229
230 /* yellow */
231 0x01, /* MSB x resolution */
232 0x2c, /* LSB x resolution */
233 0x01, /* MSB y resolution */
234 0x2c, /* LSB y resolution */
235 0x00, /* MSB intensity levels */
236 0x02 /* LSB intensity levels */
237 }
238 };
239
240 /* this holds the color lookuptable data of the hp850 */
241 typedef struct {
242 byte c[256]; /* Lookuptable for cyan */
243 byte m[256]; /* dito for magenta */
244 byte y[256]; /* dito for yellow */
245 byte k[256]; /* dito for black */
246 int correct[256]; /* potential undercolor black correction */
247 } Gamma;
248
249 static const Gamma gammat850 =
250 {
251 /* Lookup values for cyan */
252 {0, 0, 0, 2, 2, 2, 3, 3, 3, 5, 5, 5, 7, 7, 6, 7, 7, 6, 7, 7, 7, 8, 8,
253 8, 8, 8, 8, 9, 9, 9, 9, 9, 10, 10, 10, 10, 10, 10, 11, 11, 12, 12, 12,
254 12, 12, 12, 13, 13, 14, 14, 14, 15, 15, 16, 16, 15, 16, 16, 17, 17,
255 17, 17, 17, 18, 18, 18, 19, 19, 20, 20, 20, 20, 20, 21, 21, 21, 22,
256 22, 23, 23, 23, 23, 23, 24, 24, 25, 25, 26, 26, 26, 26, 26, 27, 27,
257 27, 27, 28, 28, 29, 28, 28, 29, 29, 30, 30, 31, 31, 32, 32, 33, 34,
258 35, 35, 36, 36, 37, 37, 38, 38, 39, 39, 40, 40, 41, 41, 42, 42, 42,
259 43, 43, 43, 44, 45, 45, 46, 46, 47, 47, 48, 48, 49, 50, 50, 51, 51,
260 52, 52, 53, 54, 54, 54, 55, 55, 56, 57, 58, 58, 59, 60, 60, 61, 62,
261 62, 63, 65, 65, 66, 67, 67, 68, 69, 69, 70, 72, 73, 73, 74, 75, 75,
262 76, 77, 79, 79, 80, 81, 82, 83, 83, 84, 86, 87, 88, 88, 89, 90, 91,
263 92, 93, 94, 95, 96, 97, 97, 99, 100, 101, 102, 103, 104, 105, 106,
264 108, 109, 110, 111, 112, 114, 115, 117, 119, 120, 122, 124, 125, 127,
265 129, 131, 132, 135, 136, 138, 140, 142, 144, 146, 147, 150, 152, 154,
266 157, 159, 162, 164, 166, 168, 171, 174, 176, 180, 182, 187, 192, 197,
267 204, 215, 255},
268 /* Lookup values for magenta */
269 {0, 0, 0, 1, 1, 1, 3, 3, 3, 4, 4, 4, 5, 5, 5, 6, 6, 6, 7, 7, 7, 7, 7,
270 7, 8, 8, 8, 9, 9, 10, 10, 9, 10, 10, 10, 11, 11, 11, 11, 11, 12, 12,
271 12, 13, 13, 13, 14, 14, 15, 15, 15, 16, 16, 16, 16, 16, 17, 17, 17,
272 17, 17, 18, 18, 19, 19, 19, 19, 19, 20, 20, 20, 21, 21, 22, 22, 22,
273 23, 23, 24, 24, 25, 25, 25, 26, 26, 27, 27, 28, 29, 29, 29, 29, 30,
274 30, 31, 30, 31, 31, 32, 31, 31, 32, 32, 33, 33, 34, 34, 35, 35, 36,
275 36, 37, 37, 38, 38, 39, 39, 40, 40, 41, 41, 42, 42, 43, 43, 44, 44,
276 45, 45, 46, 46, 47, 48, 48, 49, 49, 50, 50, 51, 51, 52, 53, 53, 54,
277 54, 55, 55, 56, 57, 57, 58, 58, 59, 60, 60, 61, 61, 62, 63, 64, 65,
278 66, 66, 67, 68, 68, 70, 71, 71, 72, 73, 73, 74, 76, 77, 77, 78, 79,
279 79, 80, 81, 82, 83, 84, 85, 86, 87, 87, 88, 89, 90, 91, 91, 92, 93,
280 94, 95, 96, 97, 98, 99, 100, 100, 101, 102, 103, 105, 106, 107, 108,
281 109, 112, 113, 114, 115, 116, 118, 119, 121, 123, 124, 125, 128, 129,
282 130, 133, 134, 135, 138, 139, 142, 144, 145, 148, 150, 152, 154, 157,
283 159, 162, 164, 168, 169, 170, 172, 175, 177, 179, 182, 185, 189, 193,
284 198, 204, 215, 255},
285 /* Lookup values for yellow */
286 {0, 0, 0, 2, 2, 2, 3, 3, 3, 5, 5, 5, 7, 7, 6, 7, 7, 6, 7, 7, 7, 8, 8,
287 8, 8, 8, 8, 9, 9, 9, 9, 9, 10, 9, 9, 10, 10, 10, 10, 10, 11, 11, 11,
288 12, 12, 13, 13, 14, 14, 15, 15, 16, 16, 16, 16, 16, 17, 17, 18, 18,
289 18, 19, 18, 19, 19, 19, 20, 20, 21, 21, 21, 22, 22, 22, 22, 22, 23,
290 23, 24, 24, 25, 25, 25, 26, 27, 28, 28, 29, 29, 29, 30, 30, 30, 30,
291 31, 31, 32, 32, 33, 33, 32, 33, 33, 34, 34, 35, 35, 36, 36, 37, 37,
292 38, 38, 39, 39, 40, 40, 41, 41, 42, 42, 43, 43, 44, 44, 45, 45, 45,
293 45, 46, 46, 47, 48, 48, 49, 49, 50, 50, 51, 51, 52, 53, 53, 54, 54,
294 55, 55, 56, 57, 58, 59, 59, 60, 61, 61, 62, 62, 63, 64, 65, 66, 67,
295 67, 68, 69, 69, 70, 71, 72, 73, 74, 74, 75, 76, 77, 77, 78, 79, 79,
296 80, 81, 82, 83, 84, 85, 86, 87, 87, 88, 89, 90, 91, 91, 93, 94, 95,
297 96, 97, 98, 100, 101, 102, 102, 103, 104, 106, 107, 108, 109, 110,
298 111, 113, 114, 115, 116, 117, 118, 119, 121, 123, 124, 126, 128, 130,
299 131, 134, 135, 137, 139, 140, 143, 145, 146, 148, 150, 152, 154, 156,
300 158, 160, 163, 166, 167, 169, 171, 173, 176, 178, 181, 184, 188, 192,
301 198, 204, 215, 255},
302 /* Lookup values for black */
303 {0, 0, 0, 1, 1, 1, 1, 1, 1, 3, 3, 3, 3, 3, 2, 4, 3, 3, 3, 3, 3, 4, 4,
304 4, 5, 5, 5, 5, 5, 6, 6, 6, 6, 6, 6, 7, 7, 7, 7, 7, 8, 8, 8, 9, 9, 8,
305 8, 8, 9, 9, 9, 10, 10, 10, 10, 10, 11, 11, 11, 11, 12, 12, 12, 13, 13,
306 12, 12, 12, 13, 13, 13, 13, 13, 14, 14, 14, 14, 14, 15, 15, 16, 16,
307 16, 17, 17, 17, 17, 18, 18, 18, 19, 19, 20, 20, 20, 20, 20, 21, 21,
308 21, 21, 22, 22, 22, 22, 23, 22, 23, 23, 24, 24, 24, 24, 25, 25, 26,
309 26, 26, 26, 27, 27, 28, 28, 28, 28, 29, 29, 30, 30, 31, 31, 31, 32,
310 32, 33, 33, 34, 34, 35, 36, 36, 36, 37, 37, 37, 38, 38, 40, 40, 40,
311 41, 41, 42, 43, 43, 43, 43, 44, 45, 45, 46, 47, 47, 48, 49, 49, 50,
312 52, 52, 53, 54, 54, 56, 56, 57, 58, 59, 60, 60, 61, 62, 63, 63, 64,
313 65, 66, 67, 68, 69, 70, 71, 72, 72, 73, 75, 75, 76, 77, 78, 80, 81,
314 82, 82, 83, 84, 85, 86, 88, 89, 90, 91, 94, 95, 96, 98, 99, 100, 101,
315 103, 105, 106, 107, 110, 111, 112, 115, 116, 118, 120, 121, 124, 126,
316 127, 131, 133, 134, 138, 140, 141, 146, 148, 151, 154, 156, 160, 163,
317 166, 169, 174, 177, 182, 187, 194, 203, 215, 255}
318 };
319
320
321 static const Gamma gammat890 =
322 {
323 /* Lookup values for cyan */
324 {0, 2, 3, 5, 7, 8, 10, 12, 13, 15, 16, 18, 20, 21, 23, 25, 26, 28, 29,
325 31, 32, 34, 36, 37, 39, 40, 42, 43, 45, 46, 48, 50, 51, 53, 54, 56, 57,
326 59, 60, 62, 63, 65, 66, 68, 69, 70, 72, 73, 75, 76, 78, 79, 81, 82, 83,
327 85, 86, 88, 89, 91, 92, 93, 95, 96, 97, 99, 100, 102, 103, 104, 106,
328 107, 108, 110, 111, 112, 114, 115, 116, 118, 119, 120, 121, 123, 124,
329 125, 127, 128, 129, 130, 132, 133, 134, 135, 137, 138, 139, 140, 141,
330 143, 144, 145, 146, 147, 149, 150, 151, 152, 153, 154, 155, 157, 158,
331 159, 160, 161, 162, 163, 164, 166, 167, 168, 169, 170, 171, 172, 173,
332 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187,
333 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 200, 201,
334 201, 202, 203, 204, 205, 206, 207, 208, 208, 209, 210, 211, 212, 213,
335 213, 214, 215, 216, 217, 217, 218, 219, 220, 220, 221, 222, 223, 223,
336 224, 225, 225, 226, 227, 228, 228, 229, 230, 230, 231, 231, 232, 233,
337 233, 234, 235, 235, 236, 236, 237, 238, 238, 239, 239, 240, 240, 241,
338 241, 242, 242, 243, 243, 244, 244, 245, 245, 246, 246, 247, 247, 247,
339 248, 248, 249, 249, 249, 250, 250, 250, 251, 251, 251, 252, 252, 252,
340 252, 253, 253, 253, 253, 254, 254, 254, 254, 254, 255, 255, 255, 255,
341 255, 255, 255},
342
343 /* Lookup values for magenta */ /* gamma 0.6 */ /* 0.8 */
344
345 {0, 1, 2, 3, 4, 5, 6, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20,
346 21, 22, 23, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39,
347 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 52, 53, 54, 55, 56, 57, 58,
348 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76,
349 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 86, 87, 88, 89, 90, 91, 92, 93,
350 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108,
351 109, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121,
352 122, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 132, 133,
353 134, 135, 136, 137, 138, 139, 140, 140, 141, 142, 143, 144, 145, 146,
354 147, 147, 148, 149, 150, 151, 152, 153, 153, 154, 155, 156, 157, 158,
355 158, 159, 160, 161, 162, 163, 163, 164, 165, 166, 167, 168, 168, 169,
356 170, 171, 172, 172, 173, 174, 175, 176, 176, 177, 178, 179, 179, 180,
357 181, 182, 182, 183, 184, 185, 185, 186, 187, 188, 188, 189, 190, 191,
358 191, 192, 193, 193, 194, 195, 196, 196, 197, 198, 198, 199, 200, 200,
359 201, 202, 202, 203, 204, 204, 205, 205, 206, 207, 207, 208, 209, 209,
360 210, 210, 211, 211, 212, 213, 213, 214, 214, 215, 215, 216, 216, 217,
361 217, 218, 218, 218, 219, 219, 219, 220, 220},
362
363 /* Lookup values for yellow */
364 /* gamma 0.7 */
365
366 {0, 1, 3, 4, 6, 7, 9, 10, 11, 13, 14, 16, 17, 18, 20, 21, 23, 24, 25,
367 27, 28, 29, 31, 32, 34, 35, 36, 38, 39, 40, 42, 43, 44, 46, 47, 48, 50,
368 51, 52, 54, 55, 56, 58, 59, 60, 62, 63, 64, 66, 67, 68, 70, 71, 72, 73,
369 75, 76, 77, 79, 80, 81, 82, 84, 85, 86, 88, 89, 90, 91, 93, 94, 95, 96,
370 97, 99, 100, 101, 102, 104, 105, 106, 107, 109, 110, 111, 112, 113, 115,
371 116, 117, 118, 119, 120, 122, 123, 124, 125, 126, 127, 129, 130, 131,
372 132, 133, 134, 136, 137, 138, 139, 140, 141, 142, 143, 145, 146, 147,
373 148, 149, 150, 151, 152, 153, 154, 155, 157, 158, 159, 160, 161, 162,
374 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176,
375 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190,
376 191, 192, 193, 194, 195, 196, 196, 197, 198, 199, 200, 201, 202, 203,
377 204, 205, 205, 206, 207, 208, 209, 210, 211, 211, 212, 213, 214, 215,
378 216, 216, 217, 218, 219, 220, 220, 221, 222, 223, 223, 224, 225, 226,
379 226, 227, 228, 229, 229, 230, 231, 232, 232, 233, 234, 234, 235, 236,
380 236, 237, 238, 238, 239, 239, 240, 241, 241, 242, 242, 243, 244, 244,
381 245, 245, 246, 246, 247, 247, 248, 248, 249, 249, 250, 250, 251, 251,
382 251, 252, 252, 253, 253, 253, 254, 254, 254, 254, 255, 255, 255, 255},
383
384 /* Lookup values for black */
385 /* gamma 3.3 */
386
387 {0, 0, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 4, 4, 4, 5, 5, 5, 6, 6, 6, 7, 7, 7,
388 8, 8, 8, 9, 9, 9, 9, 10, 10, 10, 11, 11, 11, 12, 12, 13, 13, 13, 14, 14,
389 14, 15, 15, 15, 16, 16, 16, 17, 17, 17, 18, 18, 18, 19, 19, 20, 20, 20,
390 21, 21, 21, 22, 22, 22, 23, 23, 24, 24, 24, 25, 25, 26, 26, 26, 27, 27,
391 27, 28, 28, 29, 29, 29, 30, 30, 31, 31, 32, 32, 32, 33, 33, 34, 34, 34,
392 35, 35, 36, 36, 37, 37, 37, 38, 38, 39, 39, 40, 40, 41, 41, 41, 42, 42,
393 43, 43, 44, 44, 45, 45, 46, 46, 47, 47, 48, 48, 49, 49, 50, 50, 51, 51,
394 52, 52, 53, 53, 54, 54, 55, 55, 56, 56, 57, 57, 58, 58, 59, 60, 60, 61,
395 61, 62, 62, 63, 64, 64, 65, 65, 66, 67, 67, 68, 68, 69, 70, 70, 71, 72,
396 72, 73, 74, 74, 75, 76, 76, 77, 78, 78, 79, 80, 80, 81, 82, 83, 83, 84,
397 85, 86, 86, 87, 88, 89, 90, 91, 91, 92, 93, 94, 95, 96, 97, 97, 98, 99,
398 100, 101, 102, 103, 104, 105, 106, 107, 108, 110, 111, 112, 113, 114,
399 115, 117, 118, 119, 120, 122, 123, 124, 126, 127, 129, 130, 132, 134,
400 135, 137, 139, 141, 143, 145, 147, 149, 152, 154, 157, 159, 162, 166,
401 169, 173, 178, 183, 189, 196, 207, 255},
402 };
403
404 static const Gamma * const gammat[] =
405 {
406 &gammat850, /* CDJ670 */
407 &gammat850, /* CDJ850 */
408 &gammat850, /* CDJ880 */
409 &gammat890, /* CDJ890 */
410 &gammat850 /* CDJ1600 */
411 };
412
413 static int
414 rescale_byte_wise1x1(int bytecount, const byte * inbytea,
415 const byte * inbyteb, byte * outbyte);
416 static int
417 rescale_byte_wise2x1(int bytecount, const byte * inbytea,
418 const byte * inbyteb, byte * outbyte);
419 static int
420 rescale_byte_wise1x2(int bytecount, const byte * inbytea,
421 const byte * inbyteb, byte * outbyte);
422 static int
423 rescale_byte_wise2x2(int bytecount, const byte * inbytea,
424 const byte * inbyteb, byte * outbyte);
425
426 static int (* const rescale_color_plane[2][2]) (int, const byte *, const byte *, byte *) = {
427 {
428 rescale_byte_wise1x1, rescale_byte_wise1x2
429 },
430 {
431 rescale_byte_wise2x1, rescale_byte_wise2x2
432 }
433 };
434
435 /*
436 * Drivers stuff.
437 *
438 */
439 #define DESKJET_PRINT_LIMIT 0.04 /* 'real' top margin? */
440 /* Margins are left, bottom, right, top. */
441 #define DESKJET_MARGINS_LETTER 0.25, 0.50, 0.25, 0.167
442 #define DESKJET_MARGINS_A4 0.13, 0.46, 0.13, 0.04
443 /* Define bits-per-pixel - default is 32-bit cmyk-mode */
444 #ifndef BITSPERPIXEL
445 # define BITSPERPIXEL 32
446 #endif
447 #define DOFFSET (dev_t_margin(pdev) - DESKJET_PRINT_LIMIT) /* Print position */
448
449
450 #define W sizeof(word)
451 #define I sizeof(int)
452
453 /* paper types */
454 typedef enum {
455 PLAIN_PAPER, BOND_PAPER, SPECIAL_PAPER, GLOSSY_FILM, TRANSPARENCY_FILM
456 } cdj_paper_type_t;
457
458 /* quality */
459 typedef enum {
460 DRAFT = -1, NORMAL = 0, PRESENTATION = 1
461 } cdj_quality_t;
462
463 /* Printer types */
464 typedef enum {
465 DJ670C, DJ850C, DJ880C, DJ890C, DJ1600C, HP2200C, DNJ500C
466 } cdj_printer_type_t;
467
468
469 /* No. of ink jets (used to minimise head movements)
470 * NOTE: These don't appear to actually be used anywhere. Can they
471 * be removed?
472 */
473 #define HEAD_ROWS_MONO 50
474 #define HEAD_ROWS_COLOUR 16
475
476
477 /*
478 * Colour mapping procedures
479 */
480 static dev_proc_map_cmyk_color(gdev_cmyk_map_cmyk_color);
481 static dev_proc_map_rgb_color(gdev_cmyk_map_rgb_color);
482 static dev_proc_map_color_rgb(gdev_cmyk_map_color_rgb);
483
484 static dev_proc_map_rgb_color(gdev_pcl_map_rgb_color);
485 static dev_proc_map_color_rgb(gdev_pcl_map_color_rgb);
486
487
488 /*
489 * Print-page, parameters and miscellaneous procedures
490 */
491 static dev_proc_open_device(hp_colour_open);
492
493 static dev_proc_get_params(cdj850_get_params);
494 static dev_proc_put_params(cdj850_put_params);
495
496 static dev_proc_print_page(cdj850_print_page);
497 static dev_proc_print_page(chp2200_print_page);
498 static dev_proc_print_page(cdnj500_print_page);
499
500 /* The device descriptors */
501
502 /* The basic structure for all printers. Note the presence of the cmyk, depth
503 and correct fields even if some are not used by all printers. */
504
505 #define prn_colour_device_body(dtype, procs, dname, w10, h10, xdpi, ydpi, lm, bm, rm, tm, ncomp, depth, mg, mc, dg, dc, print_page, cmyk, correct)\
506 prn_device_body(dtype, procs, dname, w10, h10, xdpi, ydpi, lm, bm, rm, tm, ncomp, depth, mg, mc, dg, dc, print_page), cmyk, depth /* default */, correct
507
508
509
510 #define gx_prn_colour_device_common \
511 gx_prn_device_common; \
512 int cmyk; /* 0: not CMYK-capable, > 0: printing CMYK, */ \
513 /* < 0 : CMYK-capable, not printing CMYK */ \
514 uint default_depth; /* Used only for CMYK-capable printers now. */ \
515 uint correction
516
517
518 /* some definitions needed later */
519 struct error_val_field {
520 int c; /* Current value of Cyan error during dithering */
521 int m; /* Current value of Magenta error during dithering */
522 int y; /* Current value of Yellow error during dithering */
523 int k; /* Current value of Black error during dithering */
524 };
525
526 /* this structure holds all the pointers to the different values
527 in all those data fields */
528 /*
529 * The principal data pointers are stored as pairs of values, with
530 * the selection being made by the 'scan' variable. The function of the
531 * scan variable is overloaded, as it controls both the alternating
532 * raster scan direction used in the Floyd-Steinberg dithering and also
533 * the buffer alternation required for line-difference compression.
534 *
535 * Thus, the number of pointers required is as follows:
536 */
537
538 struct ptr_arrays {
539 byte *data[4]; /* 4 600dpi data, scan direction and alternating buffers */
540 byte *data_c[4]; /* 4 300dpi data, as above, */
541 byte *plane_data[4][4]; /*4 b/w-planes, scan direction and alternating buffers */
542 byte *plane_data_c[4][8]; /* as above, but for 8 planes */
543 byte *out_data; /* output buffer for the b/w data, one 600dpi plane */
544 byte *test_data[4]; /* holds a copy of the last plane */
545 int *errors[2]; /* 2 b/w dithering erros (scan direction only) */
546 int *errors_c[2]; /* 2 color dithering errors (scan direction only) */
547 word *storage; /* pointer to the beginning of the b/w-buffer */
548 word *storage_start; /* used for debugging */
549 word *storage_end; /* used for debugging */
550 word *storage_size; /* used for debugging */
551 };
552
553 /* Some miscellaneous variables */
554 struct misc_struct {
555 int line_size; /* size of scan_line */
556 int line_size_c; /* size of rescaled scan_line */
557 int line_size_words; /* size of scan_line in words */
558 int paper_size; /* size of paper */
559 int num_comps; /* number of color components (1 - 4) */
560 int bits_per_pixel; /* bits per pixel 1,4,8,16,24,32 */
561 int storage_bpp; /* = bits_per_pixel */
562 int expanded_bpp; /* = bits_per_pixel */
563 int plane_size; /* size of b/w bit plane */
564 int plane_size_c; /* size of color bit plane */
565 int databuff_size; /* size of databuffer for b/w data */
566 int databuff_size_c; /* size of databuffer for color data */
567 int errbuff_size; /* size of error buffer b/w -data */
568 int errbuff_size_c; /* size of error buffer color -data */
569 int outbuff_size; /* size of output buffer for b/w data */
570 int scan; /* scan-line variable [0,1] */
571 int cscan; /* dito for the color-planes */
572 int is_two_pass; /* checks if b/w data has already been printed */
573 int zero_row_count; /* How many empty lines */
574 uint storage_size_words; /* size of storage in words for b/w data */
575 uint storage_size_words_c; /* size of storage in words for c-data */
576 int is_color_data; /* indicates whether there is color data */
577 };
578
579 /* function pointer typedefs for device driver struct */
580 typedef void (*StartRasterMode) (gx_device_printer * pdev, int paper_size,
581 FILE * prn_stream);
582 typedef void (*PrintNonBlankLines) (gx_device_printer * pdev,
583 struct ptr_arrays *data_ptrs,
584 struct misc_struct *misc_vars,
585 struct error_val_field *error_values,
586 const Gamma *gamma,
587 FILE * prn_stream);
588
589 typedef void (*TerminatePage) (gx_device_printer * pdev, FILE * prn_stream);
590
591 typedef struct gx_device_cdj850_s {
592 gx_device_common;
593 gx_prn_colour_device_common;
594 int /*cdj_quality_t*/ quality; /* -1 draft, 0 normal, 1 best */
595 int /*cdj_paper_type_t*/ papertype; /* papertype [0,4] */
596 int intensities; /* intensity values per pixel [2,4] */
597 int xscal; /* boolean to indicate x scaling by 2 */
598 int yscal; /* boolean to indicate y scaling by 2 */
599 int /*cdj_printer_type_t*/ ptype; /* printer type, one of DJ670C, DJ850C, DJ890C, DJ1600C */
600 int compression; /* compression level */
601 float mastergamma; /* Gammavalue applied to all colors */
602 float gammavalc; /* range to which gamma-correction is
603 applied to bw values */
604 float gammavalm; /* amount of gamma correction for bw */
605 float gammavaly; /* range to which gamma-correction i
606 applied to color values */
607 float gammavalk; /* amount of gamma correction for color */
608 float blackcorrect; /* amount of gamma correction for color */
609 StartRasterMode start_raster_mode; /* output function to start raster mode */
610 PrintNonBlankLines print_non_blank_lines; /* output function to print a non blank line */
611 TerminatePage terminate_page; /* page termination output function */
612 } gx_device_cdj850;
613
614 typedef struct {
615 gx_device_common;
616 gx_prn_colour_device_common;
617 } gx_device_colour_prn;
618
619
620 /* Use the cprn_device macro to access generic fields (like cmyk,
621 default_depth and correction), and specific macros for specific
622 devices. */
623
624 #define cprn_device ((gx_device_colour_prn*) pdev)
625 #define cdj850 ((gx_device_cdj850 *)pdev)
626
627 #define prn_cmyk_colour_device(dtype, procs, dev_name, x_dpi, y_dpi, bpp, print_page, correct)\
628 prn_colour_device_body(dtype, procs, dev_name,\
629 DEFAULT_WIDTH_10THS, DEFAULT_HEIGHT_10THS, x_dpi, y_dpi, 0, 0, 0, 0,\
630 ((bpp == 1 || bpp == 4) ? 1 : 4), bpp,\
631 (bpp > 8 ? 255 : 1), (1 << (bpp >> 2)) - 1, /* max_gray, max_color */\
632 (bpp > 8 ? 5 : 2), (bpp > 8 ? 5 : bpp > 1 ? 2 : 0),\
633 print_page, 1 /* cmyk */, correct)
634
635 #define prn_cmy_colour_device(dtype, procs, dev_name, x_dpi, y_dpi, bpp, print_page, correct)\
636 prn_colour_device_body(dtype, procs, dev_name,\
637 DEFAULT_WIDTH_10THS, DEFAULT_HEIGHT_10THS, x_dpi, y_dpi, 0, 0, 0, 0,\
638 ((bpp == 1 || bpp == 4) ? 1 : 3), bpp,\
639 (bpp > 8 ? 255 : 1), (bpp > 8 ? 255 : 1), /* max_gray, max_color */\
640 (bpp > 8 ? 5 : 2), (bpp > 8 ? 5 : bpp > 1 ? 2 : 0),\
641 print_page, -1 /* cmyk */, correct)
642
643 /* The prn_rgb_color_device is used by the HP2200 and DNJ500 */
644 #define prn_rgb_colour_device(dtype, procs, dev_name, x_dpi, y_dpi, bpp, print_page, correct)\
645 prn_colour_device_body(dtype, procs, dev_name,\
646 DEFAULT_WIDTH_10THS, DEFAULT_HEIGHT_10THS, x_dpi, y_dpi, 0, 0, 0, 0,\
647 3 /*3=rgb*/, bpp,\
648 255, 255, /* max_gray, max_color */\
649 256, 256,\
650 print_page, 0 /* no cmyk */, correct)
651
652 #define cdj_850_device(procs, dev_name, x_dpi, y_dpi, bpp, print_page, correction, quality, papertype, intensities,ptype,compression,mastergamma,gammavalc,gammavalm,gammavaly,gammavalk,blackcorrect,start_raster_mode,print_non_blank_line,terminate_page)\
653 { prn_cmyk_colour_device(gx_device_cdj850, procs, dev_name, x_dpi, y_dpi, bpp, print_page, correction),\
654 quality,\
655 papertype,\
656 intensities,\
657 0, 0, /* xscal, yscal */\
658 ptype,\
659 compression,\
660 mastergamma,\
661 gammavalc,\
662 gammavalm,\
663 gammavaly,\
664 gammavalk,\
665 blackcorrect,\
666 start_raster_mode,\
667 print_non_blank_line,\
668 terminate_page\
669 }
670
671 #define cdj_1600_device(procs, dev_name, x_dpi, y_dpi, bpp, print_page, correction, quality, papertype, intensities,ptype,compression,mastergamma,gammavalc,gammavalm,gammavaly,gammavalk,blackcorrect,start_raster_mode,print_non_blank_line,terminate_page)\
672 { prn_cmy_colour_device(gx_device_cdj850, procs, dev_name, x_dpi, y_dpi, bpp, print_page, correction),\
673 quality,\
674 papertype,\
675 intensities,\
676 0, 0, /* xscal, yscal */\
677 ptype,\
678 compression,\
679 mastergamma,\
680 gammavalc,\
681 gammavalm,\
682 gammavaly,\
683 gammavalk,\
684 blackcorrect,\
685 start_raster_mode,\
686 print_non_blank_line,\
687 terminate_page\
688 }
689
690 /* HP2200 and DNJ500 is a RGB printer */
691 #define chp_2200_device(procs, dev_name, x_dpi, y_dpi, bpp, print_page, correction, quality, papertype, intensities,ptype,compression,mastergamma,gammavalc,gammavalm,gammavaly,gammavalk,blackcorrect,start_raster_mode,print_non_blank_line,terminate_page)\
692 { prn_rgb_colour_device(gx_device_cdj850, procs, dev_name, x_dpi, y_dpi, bpp, print_page, correction),\
693 quality,\
694 papertype,\
695 intensities,\
696 0, 0, /* xscal, yscal */\
697 ptype,\
698 compression,\
699 mastergamma,\
700 gammavalc,\
701 gammavalm,\
702 gammavaly,\
703 gammavalk,\
704 blackcorrect,\
705 start_raster_mode,\
706 print_non_blank_line,\
707 terminate_page\
708 }
709
710 #define cmyk_colour_procs(proc_colour_open, proc_get_params, proc_put_params, \
711 map_rgb_color, map_color_rgb, map_cmyk_color)\
712 { proc_colour_open,\
713 gx_default_get_initial_matrix,\
714 gx_default_sync_output,\
715 gdev_prn_output_page,\
716 gdev_prn_close,\
717 map_rgb_color,\
718 map_color_rgb,\
719 NULL /* fill_rectangle */,\
720 NULL /* tile_rectangle */,\
721 NULL /* copy_mono */,\
722 NULL /* copy_color */,\
723 NULL /* draw_line */,\
724 gx_default_get_bits,\
725 proc_get_params,\
726 proc_put_params,\
727 map_cmyk_color\
728 }
729
730
731 /* Printer-specific functions. Most printers are handled by the cdj850_xx()
732 * functions.
733 */
734 static void
735 cdj850_start_raster_mode(gx_device_printer * pdev,
736 int papersize, FILE * prn_stream);
737
738 static void
739 cdj850_print_non_blank_lines(gx_device_printer * pdev,
740 struct ptr_arrays *data_ptrs,
741 struct misc_struct *misc_vars,
742 struct error_val_field *error_values,
743 const Gamma *gamma,
744 FILE * prn_stream);
745
746 static void
747 cdj850_terminate_page(gx_device_printer * pdev, FILE * prn_stream);
748
749 /* The 880C and siblings need a separate set of functions because they seem
750 * to require a somewhat different version of PCL3+.
751 */
752 static void
753 cdj880_start_raster_mode(gx_device_printer * pdev,
754 int papersize, FILE * prn_stream);
755
756 static void
757 cdj880_print_non_blank_lines(gx_device_printer * pdev,
758 struct ptr_arrays *data_ptrs,
759 struct misc_struct *misc_vars,
760 struct error_val_field *error_values,
761 const Gamma *gamma,
762 FILE * prn_stream);
763
764 static void
765 cdj880_terminate_page(gx_device_printer * pdev, FILE * prn_stream);
766
767 /* Functions for the 1600C.
768 */
769 static void
770 cdj1600_start_raster_mode(gx_device_printer * pdev,
771 int papersize, FILE * prn_stream);
772 static void
773 cdj1600_print_non_blank_lines(gx_device_printer * pdev,
774 struct ptr_arrays *data_ptrs,
775 struct misc_struct *misc_vars,
776 struct error_val_field *error_values,
777 const Gamma *gamma,
778 FILE * prn_stream);
779 static void
780 cdj1600_terminate_page(gx_device_printer * pdev, FILE * prn_stream);
781
782 /* Functions for the HP2200C */
783 static void
784 chp2200_start_raster_mode(gx_device_printer * pdev,
785 int papersize, FILE * prn_stream);
786
787 static void
788 chp2200_terminate_page(gx_device_printer * pdev, FILE * prn_stream);
789
790 /* Functions for the DNJ500C */
791 static void
792 cdnj500_start_raster_mode(gx_device_printer * pdev,
793 int papersize, FILE * prn_stream);
794
795 static void
796 cdnj500_terminate_page(gx_device_printer * pdev, FILE * prn_stream);
797
798
799 static const gx_device_procs cdj670_procs =
800 cmyk_colour_procs(hp_colour_open, cdj850_get_params, cdj850_put_params,
801 NULL, gdev_cmyk_map_color_rgb, gdev_cmyk_map_cmyk_color);
802
803 static const gx_device_procs cdj850_procs =
804 cmyk_colour_procs(hp_colour_open, cdj850_get_params, cdj850_put_params,
805 NULL, gdev_cmyk_map_color_rgb, gdev_cmyk_map_cmyk_color);
806
807 static const gx_device_procs cdj880_procs =
808 cmyk_colour_procs(hp_colour_open, cdj850_get_params, cdj850_put_params,
809 NULL, gdev_cmyk_map_color_rgb, gdev_cmyk_map_cmyk_color);
810
811 static const gx_device_procs cdj890_procs =
812 cmyk_colour_procs(hp_colour_open, cdj850_get_params, cdj850_put_params,
813 NULL, gdev_cmyk_map_color_rgb, gdev_cmyk_map_cmyk_color);
814
815 static const gx_device_procs cdj1600_procs =
816 cmyk_colour_procs(hp_colour_open, cdj850_get_params, cdj850_put_params,
817 gdev_pcl_map_rgb_color, gdev_pcl_map_color_rgb, NULL);
818
819 /* HP2200 and DNJ500 is a RGB printer */
820 static const gx_device_procs chp2200_procs =
821 cmyk_colour_procs(hp_colour_open, cdj850_get_params, cdj850_put_params,
822 gx_default_rgb_map_rgb_color, gx_default_rgb_map_color_rgb, NULL);
823
824
825 const gx_device_cdj850 gs_cdj670_device =
826 cdj_850_device(cdj670_procs, "cdj670", 600, 600, 32, cdj850_print_page, 0,
827 PRESENTATION, PLAIN_PAPER, 2, DJ670C, 9,
828 1.0, 0.0, 0.0, 0.0, 0.0, 1.0,
829 cdj850_start_raster_mode, cdj850_print_non_blank_lines,
830 cdj850_terminate_page);
831
832 const gx_device_cdj850 gs_cdj850_device =
833 cdj_850_device(cdj850_procs, "cdj850", 600, 600, 32, cdj850_print_page, 0,
834 PRESENTATION, PLAIN_PAPER, 4, DJ850C, 9,
835 1.0, 0.0, 0.0, 0.0, 0.0, 1.0,
836 cdj850_start_raster_mode, cdj850_print_non_blank_lines,
837 cdj850_terminate_page);
838
839 const gx_device_cdj850 gs_cdj880_device =
840 cdj_850_device(cdj880_procs, "cdj880", 600, 600, 32, cdj850_print_page, 0,
841 PRESENTATION, PLAIN_PAPER, 4, DJ880C, 2,
842 1.0, 0.0, 0.0, 0.0, 0.0, 1.0,
843 cdj880_start_raster_mode, cdj880_print_non_blank_lines,
844 cdj880_terminate_page);
845
846 const gx_device_cdj850 gs_cdj890_device =
847 cdj_850_device(cdj890_procs, "cdj890", 600, 600, 32, cdj850_print_page, 0,
848 PRESENTATION, PLAIN_PAPER, 4, DJ890C, 9,
849 1.0, 0.0, 0.0, 0.0, 0.0, 1.0,
850 cdj850_start_raster_mode, cdj850_print_non_blank_lines,
851 cdj850_terminate_page);
852
853 const gx_device_cdj850 gs_cdj1600_device =
854 cdj_1600_device(cdj1600_procs, "cdj1600", 300, 300, 24, cdj850_print_page, 0,
855 PRESENTATION, PLAIN_PAPER, 2, DJ1600C, 3,
856 1.0, 0.0, 0.0, 0.0, 0.0, 1.0,
857 cdj1600_start_raster_mode, cdj1600_print_non_blank_lines,
858 cdj1600_terminate_page);
859
860 /* HP2200 does not need color matching and halftoning parameters */
861 const gx_device_cdj850 gs_chp2200_device =
862 chp_2200_device(chp2200_procs, "chp2200", 300, 300, 24, chp2200_print_page, 0,
863 NORMAL, PLAIN_PAPER, 0 /*unused*/, HP2200C, 10,
864 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, /*all unused*/
865 chp2200_start_raster_mode, NULL /*unused*/,
866 chp2200_terminate_page);
867
868 /* DNJ500 does not need color matching and halftoning parameters */
869 const gx_device_cdj850 gs_cdnj500_device =
870 chp_2200_device(chp2200_procs, "cdnj500", 300, 300, 24, cdnj500_print_page, 0,
871 NORMAL, PLAIN_PAPER, 0 /*unused*/, DNJ500C, 10,
872 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, /*all unused*/
873 cdnj500_start_raster_mode, NULL /*unused*/,
874 cdnj500_terminate_page);
875
876 /* Forward references */
877 static int cdj_put_param_int(gs_param_list *, gs_param_name,
878 int *, int, int, int);
879 static int cdj_put_param_float(gs_param_list *, gs_param_name, float
880 *, float, float, int);
881 static int cdj_put_param_bpp(gx_device *, gs_param_list *, int, int, int);
882 static int cdj_set_bpp(gx_device *, int, int);
883
884
885 /* hp_colour_open()
886 *
887 * Open the printer and set up the margins. Also, set parameters for
888 * the printer depending on document type and print settings.
889 *
890 * Inputs: gx_device ptr to the device
891 */
892 static int
hp_colour_open(gx_device * pdev)893 hp_colour_open(gx_device * pdev)
894 { /* Change the margins if necessary. */
895 static const float dj_a4[4] = {
896 DESKJET_MARGINS_A4
897 };
898 static const float dj_letter[4] = {
899 DESKJET_MARGINS_LETTER
900 };
901
902 /* margins for DJ1600C from manual */
903 static const float m_cdj1600[4] = {
904 0.25, 0.5, 0.25, 0.5
905 };
906
907 /* margins for HP2200C */
908 static const float chp2200_a4[4] = {
909 0.13, 0.46, 0.13, 0.08
910 };
911 static const float chp2200_letter[4] = {
912 0.25, 0.46, 0.25, 0.08
913 };
914
915 /* margins for DNJ500C */
916 static const float cdnj500[4] = {
917 0.00, 0.00, 0.00, 0.00
918 };
919
920 const float *m = (float *)0;
921
922 /* Set up colour params if put_params has not already done so */
923 if (pdev->color_info.num_components == 0) {
924 int code = cdj_set_bpp(pdev, pdev->color_info.depth,
925 pdev->color_info.num_components);
926
927 if (code < 0)
928 return code;
929 }
930 /* assign printer type and set resolution dependent on printer type */
931 switch (cdj850->ptype) {
932 case DJ670C:
933 if (cdj850->papertype <= SPECIAL_PAPER) { /* paper */
934 if (cdj850->quality == DRAFT) {
935 gx_device_set_resolution(pdev, 300.0, 300.0);
936 cdj850->xscal = 0;
937 cdj850->yscal = 0;
938 } else if (cdj850->quality == NORMAL) {
939 gx_device_set_resolution(pdev, 600.0, 300.0);
940 cdj850->xscal = 1;
941 cdj850->yscal = 0;
942 } else { /* quality == PRESENTATION */
943 gx_device_set_resolution(pdev, 600.0, 600.0);
944 cdj850->xscal = 1;
945 cdj850->yscal = 1;
946 }
947 } else { /* film */
948 gx_device_set_resolution(pdev, 600.0, 300.0);
949 cdj850->xscal = 1;
950 cdj850->yscal = 0;
951 }
952 m = (gdev_pcl_paper_size(pdev) == PAPER_SIZE_A4 ? dj_a4 : dj_letter);
953 break;
954 case DJ850C:
955 if (cdj850->quality == DRAFT) {
956 gx_device_set_resolution(pdev, 300.0, 300.0);
957 cdj850->xscal = 0;
958 cdj850->yscal = 0;
959 cdj850->intensities = 2;
960 } else if (cdj850->quality == NORMAL) {
961 gx_device_set_resolution(pdev, 600.0, 600.0);
962 cdj850->xscal = 1;
963 cdj850->yscal = 1;
964 /* only 3 intensities for normal paper */
965 if (cdj850->papertype <= PLAIN_PAPER) {
966 cdj850->intensities = 3;
967 } /* else cdj850->intensities = 4 from initialization */
968 } else { /* quality == PRESENTATION */
969 gx_device_set_resolution(pdev, 600.0, 600.0);
970 cdj850->xscal = 1;
971 cdj850->yscal = 1;
972 /* intensities = 4 from initialization */
973 }
974 m = (gdev_pcl_paper_size(pdev) == PAPER_SIZE_A4 ? dj_a4 : dj_letter);
975 break;
976 case DJ880C:
977 if (cdj850->quality == DRAFT) {
978 gx_device_set_resolution(pdev, 300.0, 300.0);
979 cdj850->xscal = 0;
980 cdj850->yscal = 0;
981 cdj850->intensities = 2;
982 } else if (cdj850->quality == NORMAL) {
983 gx_device_set_resolution(pdev, 600.0, 300.0);
984 cdj850->xscal = 1;
985 cdj850->yscal = 0;
986 /* only 3 intensities for normal paper */
987 if (cdj850->papertype <= PLAIN_PAPER) {
988 cdj850->intensities = 4;
989 } /* else cdj850->intensities = 4 from initialization */
990 } else { /* quality == PRESENTATION */
991 gx_device_set_resolution(pdev, 600.0, 600.0);
992 cdj850->xscal = 0; /* color is also 600dpi in PRESENTATION mode */
993 cdj850->yscal = 0;
994 cdj850->intensities = 4;
995 }
996 m = (gdev_pcl_paper_size(pdev) == PAPER_SIZE_A4 ? dj_a4 : dj_letter);
997 break;
998 case DJ890C:
999 if (cdj850->quality == DRAFT) {
1000 gx_device_set_resolution(pdev, 300.0, 300.0);
1001 cdj850->xscal = 0;
1002 cdj850->yscal = 0;
1003 cdj850->intensities = 2;
1004 } else if (cdj850->quality == NORMAL) {
1005 gx_device_set_resolution(pdev, 600.0, 300.0);
1006 cdj850->xscal = 1;
1007 cdj850->yscal = 0;
1008 /* only 3 intensities for normal paper */
1009 if (cdj850->papertype <= PLAIN_PAPER) {
1010 cdj850->intensities = 3;
1011 } /* else cdj850->intensities = 4 from initialization */
1012 } else { /* quality == PRESENTATION */
1013 gx_device_set_resolution(pdev, 600.0, 600.0);
1014 cdj850->xscal = 1;
1015 cdj850->yscal = 1;
1016 /* intensities = 4 from initialization */
1017 }
1018 m = (gdev_pcl_paper_size(pdev) == PAPER_SIZE_A4 ? dj_a4 : dj_letter);
1019 break;
1020 case DJ1600C:
1021 gx_device_set_resolution(pdev, 300.0, 300.0);
1022 m = m_cdj1600;
1023 break;
1024 /* HP2200 supports 300dpi draft/normal and 600dpi normal/best
1025 for all media types. For normal, we are only using 300dpi here*/
1026 case HP2200C:
1027 cdj850->xscal = 0; /* unused */
1028 cdj850->yscal = 0; /* unused */
1029 cdj850->intensities = 0; /* unused */
1030 if (cdj850->quality == DRAFT) {
1031 gx_device_set_resolution(pdev, 300.0, 300.0);
1032 } else if (cdj850->quality == NORMAL) {
1033 gx_device_set_resolution(pdev, 300.0, 300.0);
1034 } else { /* quality == PRESENTATION */
1035 gx_device_set_resolution(pdev, 600.0, 600.0);
1036 }
1037 m = (gdev_pcl_paper_size(pdev) == PAPER_SIZE_A4 ? chp2200_a4 : chp2200_letter);
1038 break;
1039 /* DNJ500 supports 300dpi and 600dpi with any combinations */
1040 case DNJ500C:
1041 cdj850->xscal = 0; /* unused */
1042 cdj850->yscal = 0; /* unused */
1043 cdj850->intensities = 0; /* unused */
1044 if (cdj850->quality == DRAFT) {
1045 gx_device_set_resolution(pdev, 300.0, 300.0);
1046 } else if (cdj850->quality == NORMAL) {
1047 gx_device_set_resolution(pdev, 600.0, 600.0);
1048 } else { /* quality == PRESENTATION */
1049 gx_device_set_resolution(pdev, 600.0, 600.0);
1050 }
1051 m = cdnj500;
1052 break;
1053 default:
1054 assert(0);
1055 }
1056 gx_device_set_margins(pdev, m, true);
1057 return gdev_prn_open(pdev);
1058 }
1059
1060 /* Added parameters for DeskJet 850C */
1061 static int
cdj850_get_params(gx_device * pdev,gs_param_list * plist)1062 cdj850_get_params(gx_device * pdev, gs_param_list * plist)
1063 {
1064 int code = gdev_prn_get_params(pdev, plist);
1065
1066 if (code < 0 ||
1067 (code = param_write_int(plist, "Quality", &cdj850->quality)) < 0 ||
1068 (code = param_write_int(plist, "Papertype", &cdj850->papertype)) < 0 ||
1069 (code = param_write_float(plist, "MasterGamma", &cdj850->gammavalc))
1070 < 0 ||
1071 (code = param_write_float(plist, "GammaValC", &cdj850->gammavalc)) <
1072 0 ||
1073 (code = param_write_float(plist, "GammaValM", &cdj850->gammavalm)) <
1074 0 ||
1075 (code = param_write_float(plist, "GammaValY", &cdj850->gammavaly)) <
1076 0 ||
1077 (code = param_write_float(plist, "GammaValK", &cdj850->gammavalk)) <
1078 0 ||
1079 (code = param_write_float(plist, "BlackCorrect",
1080 &cdj850->blackcorrect)) < 0
1081 )
1082 return code;
1083
1084 return code;
1085 }
1086
1087 static int
cdj850_put_params(gx_device * pdev,gs_param_list * plist)1088 cdj850_put_params(gx_device * pdev, gs_param_list * plist)
1089 {
1090 int quality = cdj850->quality;
1091 int papertype = cdj850->papertype;
1092 float mastergamma = cdj850->mastergamma;
1093 float gammavalc = cdj850->gammavalc;
1094 float gammavalm = cdj850->gammavalm;
1095 float gammavaly = cdj850->gammavaly;
1096 float gammavalk = cdj850->gammavalk;
1097 float blackcorrect = cdj850->blackcorrect;
1098 int bpp = 0;
1099 int code = 0;
1100
1101 code = cdj_put_param_int(plist, "BitsPerPixel", &bpp, 1, 32, code);
1102 code = cdj_put_param_int(plist, "Quality", &quality, 0, 2, code);
1103 code = cdj_put_param_int(plist, "Papertype", &papertype, 0, 4, code);
1104 code = cdj_put_param_float(plist, "MasterGamma", &mastergamma, 0.1, 9.0, code);
1105 code = cdj_put_param_float(plist, "GammaValC", &gammavalc, 0.0, 9.0, code);
1106 code = cdj_put_param_float(plist, "GammaValM", &gammavalm, 0.0, 9.0, code);
1107 code = cdj_put_param_float(plist, "GammaValY", &gammavaly, 0.0, 9.0, code);
1108 code = cdj_put_param_float(plist, "GammaValK", &gammavalk, 0.0, 9.0, code);
1109 code = cdj_put_param_float(plist, "BlackCorrect", &blackcorrect, 0.0,
1110 9.0, code);
1111
1112
1113 if (code < 0)
1114 return code;
1115 code = cdj_put_param_bpp(pdev, plist, bpp, bpp, 0);
1116 if (code < 0)
1117 return code;
1118
1119 cdj850->quality = quality;
1120 cdj850->papertype = papertype;
1121 cdj850->mastergamma = mastergamma;
1122 cdj850->gammavalc = gammavalc;
1123 cdj850->gammavalm = gammavalm;
1124 cdj850->gammavaly = gammavaly;
1125 cdj850->gammavalk = gammavalk;
1126 cdj850->blackcorrect = blackcorrect;
1127 return 0;
1128 }
1129
1130 /* ------ Internal routines ------ */
1131 /* The DeskJet850C can compress (mode 9) */
1132
1133
1134 /* Some convenient shorthand .. */
1135 #define x_dpi (pdev->x_pixels_per_inch)
1136 #define y_dpi (pdev->y_pixels_per_inch)
1137
1138 /* To calculate buffer size as next greater multiple of both parameter and W */
1139 #define calc_buffsize(a, b) (((((a) + ((b) * W) - 1) / ((b) * W))) * W)
1140
1141 /* internal functions */
1142 static void
1143 FSDlinebw(int scan, int plane_size,
1144 struct error_val_field *error_values,
1145 byte * kP,
1146 int n, int *ep, byte * dp);
1147 static void
1148 FSDlinec2(int scan, int plane_size,
1149 struct error_val_field *error_values,
1150 byte * cPa, byte * mPa, byte * yPa, int n,
1151 byte * dp, int *ep);
1152 static void
1153 FSDlinec3(int scan, int plane_size,
1154 struct error_val_field *error_values,
1155 byte * cPa, byte * mPa, byte * yPa,
1156 byte * cPb, byte * mPb, byte * yPb,
1157 int n, byte * dp, int *ep);
1158 static void
1159 FSDlinec4(int scan, int plane_size,
1160 struct error_val_field *error_values,
1161 byte * cPa, byte * mPa, byte * yPa,
1162 byte * cPb, byte * mPb, byte * yPb,
1163 int n, byte * dp, int *ep);
1164 static void
1165 init_error_buffer(struct misc_struct *misc_vars,
1166 struct ptr_arrays *data_ptrs);
1167 static void
1168 do_floyd_steinberg(int scan, int cscan, int plane_size,
1169 int plane_size_c, int n,
1170 struct ptr_arrays *data_ptrs,
1171 gx_device_printer * pdev,
1172 struct error_val_field *error_values);
1173 static int
1174 do_gcr(int bytecount, byte * inbyte, const byte * kvalues,
1175 const byte * cvalues, const byte * mvalues,
1176 const byte * yvalues, const int *kcorrect,
1177 word * inword);
1178
1179 /* UNUSED
1180 *static int
1181 *test_scan (P4(int size,
1182 * byte * current,
1183 * byte * last,
1184 * byte * control));
1185 *static void
1186 *save_color_data(P3(int size,
1187 * byte * current,
1188 * byte * saved));
1189 *
1190 */
1191 static void
1192 send_scan_lines(gx_device_printer * pdev,
1193 struct ptr_arrays *data_ptrs,
1194 struct misc_struct *misc_vars,
1195 struct error_val_field *error_values,
1196 const Gamma *gamma,
1197 FILE * prn_stream);
1198 static void
1199 do_gamma(float mastergamma, float gammaval, byte * values);
1200 static void
1201 do_black_correction(float kvalue, int *kcorrect);
1202
1203 static void
1204 init_data_structure(gx_device_printer * pdev,
1205 struct ptr_arrays *data_ptrs,
1206 struct misc_struct *misc_vars);
1207 static void
1208 calculate_memory_size(gx_device_printer * pdev,
1209 struct misc_struct *misc_vars);
1210
1211
1212 static void
assign_dpi(int dpi,byte * msb)1213 assign_dpi(int dpi, byte * msb)
1214 {
1215 if (dpi == 600) {
1216 msb[0] = 0x02;
1217 msb[1] = 0x58;
1218 } else {
1219 msb[0] = 0x01;
1220 msb[1] = 0x2c;
1221 }
1222 }
1223
1224 static void
cdj850_terminate_page(gx_device_printer * pdev,FILE * prn_stream)1225 cdj850_terminate_page(gx_device_printer * pdev, FILE * prn_stream)
1226 {
1227 fputs("0M", prn_stream); /* Reset compression */
1228 fputs("\033*rC\033E", prn_stream); /* End Graphics, Reset */
1229 fputs("\033&l0H", prn_stream); /* eject page */
1230 }
1231
1232 static void
cdj880_terminate_page(gx_device_printer * pdev,FILE * prn_stream)1233 cdj880_terminate_page(gx_device_printer * pdev, FILE * prn_stream)
1234 {
1235 fputs("\033*rC\f\033E", prn_stream); /* End graphics, FF, Reset */
1236 fputs("\033%-12345X", prn_stream);
1237 }
1238
1239 /* HP2200 terminate page routine */
1240 static void
chp2200_terminate_page(gx_device_printer * pdev,FILE * prn_stream)1241 chp2200_terminate_page(gx_device_printer * pdev, FILE * prn_stream)
1242 {
1243 fputs("\033*rC\f\033E", prn_stream); /* End graphics, FF, Reset */
1244 fputs("\033%-12345X@PJL EOJ\012\033%-12345X", prn_stream); /* Send the PJL EOJ */
1245 }
1246
1247 /* DNJ500 terminate page routine */
1248 static void
cdnj500_terminate_page(gx_device_printer * pdev,FILE * prn_stream)1249 cdnj500_terminate_page(gx_device_printer * pdev, FILE * prn_stream)
1250 {
1251 fputs("\033*rC", prn_stream); /* End graphics */
1252 fputs("\033%-12345X@PJL EOJ \n", prn_stream); /* Send the PJL EOJ */
1253 }
1254
1255 /* Here comes the hp850 output routine -------------------- */
1256 static int
cdj850_print_page(gx_device_printer * pdev,FILE * prn_stream)1257 cdj850_print_page(gx_device_printer * pdev, FILE * prn_stream)
1258 {
1259
1260 struct error_val_field error_values;
1261 struct ptr_arrays data_ptrs;
1262 struct misc_struct misc_vars;
1263 int i;
1264
1265 Gamma gamma;
1266
1267 /* make a local writable copy of the Gamma tables */
1268 memcpy(&gamma, gammat[cdj850->ptype], sizeof(Gamma));
1269 for (i=0; i<256; i++)
1270 gamma.k[i] = (int)(((float)(i*i*i))/(256.0*256.0));
1271 /* gamma.k[i] = (int)(sqrt((float)i)/16);*/
1272 /* if mastergamma, don't use the built in functions */
1273 /* if (cdj850->mastergamma > 1.0) {*/
1274 /* prepare the bw lookup table */
1275 /* do_gamma(cdj850->mastergamma, cdj850->gammavalk, gamma.k);*/
1276 /* prepare the color lookup table */
1277 for (i=0; i<256; i++)
1278 gamma.c[i] = (int)(((float)(i*i*i))/(256.0*256.0));
1279 /* do_gamma(cdj850->mastergamma, cdj850->gammavalc, gamma.c);*/
1280 for (i=0; i<256; i++)
1281 gamma.m[i] = (int)(((float)(i*i*i))/(256.0*256.0));
1282 /* do_gamma(cdj850->mastergamma, cdj850->gammavalm, gamma.m);*/
1283 for (i=0; i<256; i++)
1284 gamma.y[i] = (int)(((float)(i*i*i))/(256.0*256.0));
1285 /* do_gamma(cdj850->mastergamma, cdj850->gammavaly, gamma.y);*/
1286 /* }*/
1287 /* prepare the black correction table for the unbunt mask */
1288 do_black_correction(cdj850->blackcorrect, gamma.correct);
1289
1290 /* Calculate the needed memory */
1291 calculate_memory_size(pdev, &misc_vars);
1292
1293 /* and allocate the memory */
1294
1295 /* Since we need 600 and 300 dpi, we set up several buffers:
1296 storage contains the data as copied from gs, as well as the
1297 plane-data and the out_row buffer.
1298 storagec will contain the rescaled color data. It also contains the
1299 plane_data for the color-planes - these are needed by the
1300 compression routine, but would be overwritten by the
1301 b/w-dithering. The color planes allow for overwriting the
1302 color-data by the error-data. Since we might use the
1303 2bpp feature of the hp850 someday, it is sized like storage.
1304 storagee contains the errors from b/w fs-ditherng */
1305
1306 data_ptrs.storage = (ulong *) gs_malloc(gs_lib_ctx_get_non_gc_memory_t(), misc_vars.storage_size_words, W,
1307 "cdj850_print_page");
1308
1309 /* if we can't allocate working area */
1310 if (data_ptrs.storage == 0) {
1311 return_error(gs_error_VMerror);
1312 }
1313 /* Initialise the needed pointers */
1314 init_data_structure(pdev, &data_ptrs, &misc_vars);
1315
1316 /* Start Raster mode */
1317 (*cdj850->start_raster_mode) (pdev, misc_vars.paper_size, prn_stream);
1318
1319 /* Send each scan line in turn */
1320 send_scan_lines(pdev, &data_ptrs, &misc_vars,
1321 &error_values, &gamma, prn_stream);
1322
1323 /* terminate page and eject paper */
1324 (*cdj850->terminate_page) (pdev, prn_stream);
1325
1326 /* Free Memory */
1327 gs_free(gs_lib_ctx_get_non_gc_memory_t(), (char *)data_ptrs.storage, misc_vars.storage_size_words, W,
1328 "hp850_print_page");
1329
1330 return 0;
1331 }
1332
1333 /* HP2200C compression routines*/
1334
1335 #define kWhite 0x00FFFFFE
1336 #define MIN(x,y) ((x)<(y) ? (x) : (y))
1337 #define MAX(x,y) ((x)>(y) ? (x) : (y))
1338
1339 enum
1340 {
1341 eLiteral = 0,
1342 eRLE = 0x80
1343 };
1344
1345 enum
1346 {
1347 eeNewPixel = 0x0,
1348 eeWPixel = 0x20,
1349 eeNEPixel = 0x40,
1350 eeCachedColor = 0x60,
1351 };
1352
1353 enum
1354 {
1355 eNewColor = 0x0,
1356 eWestColor = 0x1,
1357 eNorthEastColor = 0x2,
1358 eCachedColor = 0x3
1359 };
1360
1361 static inline unsigned int
getPixel(byte * pixAddress,unsigned int pixelOffset)1362 getPixel(byte* pixAddress, unsigned int pixelOffset)
1363 {
1364 pixAddress += (pixelOffset*3); /* assume 3 bytes for each RGB pixel */
1365 /* RGBRGB format */
1366 return (((unsigned int)(*(pixAddress)) << 16) +
1367 ((unsigned int)(*(pixAddress+1)) << 8 ) +
1368 ((*(pixAddress+2)) & kWhite));
1369
1370 /* BGRBGR format */
1371 /*
1372 return (((unsigned int)(*(pixAddress+2)) << 16) +
1373 ((unsigned int)(*(pixAddress+1)) << 8 ) +
1374 ((*(pixAddress)) & kWhite));
1375 */
1376 }
1377
1378 static inline void
putPixel(byte * pixAddress,unsigned int pixelOffset,unsigned int pixel)1379 putPixel(byte* pixAddress, unsigned int pixelOffset, unsigned int pixel)
1380 {
1381 pixAddress += (pixelOffset*3); /* assume 3 bytes for each RGB pixel*/
1382 /* RGBRGB format */
1383 *(pixAddress) = (byte) (pixel >> 16);
1384 *(pixAddress+1) = (byte) (pixel >> 8);
1385 *(pixAddress+2) = (byte) (pixel & 0xFE);
1386
1387 /* BGRBGR format */
1388 /*
1389 *(pixAddress+2) = (byte) (pixel >> 16);
1390 *(pixAddress+1) = (byte) (pixel >> 8);
1391 *(pixAddress) = (byte) (pixel & 0xFE);
1392 */
1393 }
1394
1395 static inline unsigned int
ShortDelta(byte * curPtr,byte * seedPtr,unsigned int pixelOffset)1396 ShortDelta(byte* curPtr, byte* seedPtr, unsigned int pixelOffset)
1397 {
1398 int dr, dg, db;
1399 curPtr += (pixelOffset*3);
1400 seedPtr += (pixelOffset*3);
1401 /* RGBRGB format */
1402 dr = (int)((unsigned int)(*(curPtr)) - (unsigned int)(*(seedPtr)));
1403 dg = (int)((unsigned int)(*(curPtr+1)) - (unsigned int)(*(seedPtr+1)));
1404 db = (int)((unsigned int)((*(curPtr+2))&0xFE) - (unsigned int)((*(seedPtr+2))&0xFE));
1405
1406 /* BGRBGR format */
1407 /*
1408 dr = (int)((unsigned int)(*(curPtr+2)) - (unsigned int)(*(seedPtr+2)));
1409 dg = (int)((unsigned int)(*(curPtr+1)) - (unsigned int)(*(seedPtr+1)));
1410 db = (int)((unsigned int)((*(curPtr))&0xFE) - (unsigned int)((*(seedPtr))&0xFE));
1411 */
1412
1413 if ((dr <= 15) && (dr >= -16) && (dg <= 15) && (dg >= -16) && (db <= 30) && (db >= -32))
1414 { /* Note db is divided by 2 to double it's range from -16..15 to -32..30 */
1415 return (unsigned int)(((dr << 10) & 0x7C00) | (((dg << 5) & 0x03E0) | ((db >> 1) & 0x001F) | 0x8000)); /* set upper bit to signify short delta*/
1416 }
1417 return 0;
1418 }
1419
1420 /* HP2200C - mode 10 compression for RGB data */
1421 static unsigned int
Mode10(unsigned int planeWidthInPixels,byte * pbyColorScanPtr,byte * pbyColorSeedPtr,byte * pbyColorOutputPtr)1422 Mode10(unsigned int planeWidthInPixels,
1423 byte * pbyColorScanPtr, /*input scanline in RGBRGBRGB format*/
1424 byte * pbyColorSeedPtr,
1425 byte * pbyColorOutputPtr)
1426 {
1427 unsigned int curPixel = 0;
1428 unsigned int seedRowPixelCopyCount;
1429 unsigned int cachedColor = kWhite;
1430 unsigned int lastPixel = planeWidthInPixels - 1;
1431 unsigned int realLastPixel = 0;
1432 unsigned int temp1, temp2, temp3;
1433
1434 byte * curPtr = pbyColorScanPtr;
1435 byte * compressedDataPtr = pbyColorOutputPtr;
1436 byte * seedPtr = pbyColorSeedPtr;
1437
1438 byte * compressedDataStart = compressedDataPtr;
1439
1440 /* Setup sentinal value to replace last pixel of curRow.
1441 Simplifies future end condition checking.*/
1442 realLastPixel = getPixel(curPtr, lastPixel);
1443
1444 temp1 = getPixel(curPtr, lastPixel-1);
1445 temp2 = getPixel(seedPtr, lastPixel);
1446 temp3 = realLastPixel;
1447 while ( (temp1 == temp3) || (temp2 == temp3))
1448 {
1449 *(curPtr+1+lastPixel*3) += 1; /* add one to green. */
1450 temp3 = getPixel(curPtr, lastPixel);
1451 }
1452
1453 do /* all pixels in row */
1454 {
1455 byte CMDByte = eLiteral;
1456 unsigned int replacementCount = 0;
1457 int pixelSource = 0;
1458
1459 /* Find seedRowPixelCopyCount for upcoming copy */
1460 seedRowPixelCopyCount = curPixel;
1461 while ( getPixel(seedPtr, curPixel) ==
1462 getPixel(curPtr, curPixel))
1463 {
1464 curPixel++;
1465 }
1466 seedRowPixelCopyCount = curPixel - seedRowPixelCopyCount;
1467
1468 /* On last pixel of row. RLE could also leave us on the last pixel of the row
1469 from the previous iteration. */
1470 if (curPixel == lastPixel)
1471 {
1472 putPixel(curPtr, lastPixel, realLastPixel);
1473
1474 if (getPixel(seedPtr, curPixel) ==
1475 realLastPixel)
1476 {
1477 return compressedDataPtr - compressedDataStart;
1478 }
1479 else /* code last pix as a literal */
1480 {
1481 CMDByte = eLiteral;
1482 pixelSource = eeNewPixel;
1483 replacementCount = 1;
1484 curPixel++;
1485 }
1486 }
1487 else /* prior to last pixel of row */
1488 {
1489 unsigned int RLERun = 0;
1490 replacementCount = curPixel;
1491 RLERun = getPixel(curPtr, curPixel);
1492
1493 curPixel++; /* Adjust for next pixel.*/
1494 while (RLERun == getPixel(curPtr, curPixel))
1495 {
1496 curPixel++;
1497 }
1498 curPixel--; /* snap back to current.*/
1499 replacementCount = curPixel - replacementCount;
1500
1501 if (replacementCount > 0) /* Adjust for total occurance and move to next pixel to do.*/
1502 {
1503 curPixel++;
1504 replacementCount++;
1505
1506 if (cachedColor == RLERun)
1507 pixelSource = eeCachedColor;
1508 else if (getPixel(seedPtr, curPixel-replacementCount+1) == RLERun)
1509 pixelSource = eeNEPixel;
1510 else if ((curPixel-replacementCount > 0) && (getPixel(curPtr, curPixel-replacementCount-1) == RLERun))
1511 pixelSource = eeWPixel;
1512 else
1513 {
1514 pixelSource = eeNewPixel;
1515 cachedColor = RLERun;
1516 }
1517
1518 CMDByte = eRLE; /* Set default for later.*/
1519 }
1520
1521 if (curPixel == lastPixel)
1522 {
1523 /* Already found some RLE pixels */
1524 /* Add to current RLE. Otherwise it'll be part of the literal
1525 from the seedrow section above on the next iteration.*/
1526 if (realLastPixel == RLERun)
1527 {
1528 putPixel(curPtr, lastPixel, realLastPixel);
1529 replacementCount++;
1530 curPixel++;
1531 }
1532 }
1533
1534 if (0 == replacementCount) /* no RLE so it's a literal by default.*/
1535 {
1536 unsigned int tempPixel = getPixel(curPtr, curPixel);
1537 unsigned int tempPixel2 = 0;
1538 CMDByte = eLiteral;
1539
1540 if (cachedColor == tempPixel)
1541 {
1542 pixelSource = (byte) eeCachedColor;
1543 }
1544 else if (getPixel(seedPtr, curPixel+1) == tempPixel)
1545 {
1546 pixelSource = (byte)eeNEPixel;
1547 }
1548 else if ((curPixel > 0) && (getPixel(curPtr, curPixel-1) == tempPixel))
1549 {
1550 pixelSource = (byte) eeWPixel;
1551 }
1552 else
1553 {
1554 pixelSource = (byte) eeNewPixel;
1555 cachedColor = tempPixel;
1556 }
1557
1558 replacementCount = curPixel;
1559 do
1560 {
1561 if (++curPixel == lastPixel)
1562 {
1563 putPixel(curPtr, lastPixel, realLastPixel);
1564 curPixel++;
1565 break;
1566 }
1567
1568 tempPixel2 = getPixel(curPtr, curPixel);
1569
1570 } while ((tempPixel2 != getPixel(curPtr, curPixel+1)) &&
1571 (tempPixel2 != getPixel(seedPtr, curPixel)));
1572
1573 replacementCount = curPixel - replacementCount;
1574 }
1575 }
1576
1577 /* Write out compressed data next.*/
1578 if (eLiteral == CMDByte)
1579 {
1580 unsigned int totalReplacementCount = 0;
1581 unsigned int upwardPixelCount = 0;
1582
1583 replacementCount --; /* normalize it*/
1584
1585 CMDByte |= (byte) pixelSource; /* Could put this directly into CMDByte above.*/
1586 CMDByte |= (byte)(MIN(3, seedRowPixelCopyCount) << 3);
1587 CMDByte |= (byte)MIN(7, replacementCount);
1588
1589 *compressedDataPtr++ = (byte)CMDByte;
1590
1591 if (seedRowPixelCopyCount >= 3)
1592 {
1593 byte temp;
1594 int number = seedRowPixelCopyCount - 3;
1595 do
1596 {
1597 *compressedDataPtr++ = temp = (byte)(MIN(number, 255));
1598 if (255 == number)
1599 {
1600 *compressedDataPtr++ = 0;
1601 }
1602 } while(number -= temp);
1603 }
1604
1605 replacementCount ++; /* denormalize it*/
1606
1607 totalReplacementCount = replacementCount;
1608 upwardPixelCount = 1;
1609
1610 if (eeNewPixel != pixelSource)
1611 {
1612 /* Do not encode 1st pixel of run since it comes from an alternate location.*/
1613 replacementCount --;
1614
1615 upwardPixelCount = 2;
1616 }
1617
1618 for ( ; upwardPixelCount <= totalReplacementCount; upwardPixelCount++)
1619 {
1620 unsigned int tempCount = curPixel-replacementCount;
1621 unsigned int compressedPixel = ShortDelta(curPtr, seedPtr, tempCount);
1622
1623 if (compressedPixel)
1624 {
1625 *compressedDataPtr++ = (byte)(compressedPixel >> 8);
1626 *compressedDataPtr++ = (byte)(compressedPixel);
1627 }
1628 else
1629 {
1630 unsigned int uncompressedPixel = getPixel(curPtr, tempCount) >>1;
1631 *compressedDataPtr++ = (byte)(uncompressedPixel >> 16);
1632 *compressedDataPtr++ = (byte)(uncompressedPixel >> 8);
1633 *compressedDataPtr++ = (byte)(uncompressedPixel);
1634 }
1635 /* See if it's time to spill a single VLI byte.*/
1636 if (upwardPixelCount>=8 && ((upwardPixelCount-8) % 255) == 0)
1637 {
1638 *compressedDataPtr++ = (byte)(MIN(255, totalReplacementCount - upwardPixelCount));
1639 }
1640
1641 replacementCount--;
1642 }
1643 }
1644 else /* RLE */
1645 {
1646 replacementCount -= 2; /* normalize it*/
1647
1648 CMDByte |= pixelSource; /* Could put this directly into CMDByte above.*/
1649 CMDByte |= MIN(3, seedRowPixelCopyCount) << 3;
1650 CMDByte |= MIN(7, replacementCount);
1651
1652 *compressedDataPtr++ = (byte)CMDByte;
1653
1654 if (seedRowPixelCopyCount >= 3)
1655 {
1656 byte temp;
1657 int number = seedRowPixelCopyCount - 3;
1658 do
1659 {
1660 *compressedDataPtr++ = temp = (byte)(MIN(number, 255));
1661 if (255 == number)
1662 {
1663 *compressedDataPtr++ = 0;
1664 }
1665
1666 } while(number -= temp);
1667 }
1668
1669 replacementCount += 2; /* denormalize it*/
1670
1671 if (eeNewPixel == pixelSource)
1672 {
1673 unsigned int tempCount = curPixel - replacementCount;
1674 unsigned int compressedPixel = ShortDelta(curPtr, seedPtr, tempCount);
1675
1676 if (compressedPixel)
1677 {
1678 *compressedDataPtr++ = (byte)(compressedPixel >> 8);
1679 *compressedDataPtr++ = (byte)compressedPixel;
1680 }
1681 else
1682 {
1683 unsigned int uncompressedPixel = getPixel(curPtr, tempCount) >>1;
1684 *compressedDataPtr++ = (byte)(uncompressedPixel >> 16);
1685 *compressedDataPtr++ = (byte)(uncompressedPixel >> 8);
1686 *compressedDataPtr++ = (byte)uncompressedPixel;
1687 }
1688 }
1689
1690 if (replacementCount >= 9)
1691 {
1692 byte temp;
1693 int number = replacementCount - 9;
1694 do
1695 {
1696 *compressedDataPtr++ = temp = (byte)(MIN(number, 255));
1697 if (255 == number)
1698 {
1699 *compressedDataPtr++ = 0;
1700 }
1701
1702 } while(number -= temp);
1703 }
1704 }
1705 } while (curPixel <= lastPixel);
1706
1707 /*return # of compressed bytes*/
1708 return compressedDataPtr - compressedDataStart;
1709 }
1710
1711 /* HP2200 helper function to check if a scanline has any non-white pixels.
1712 This allows us to optimise printing by using PCL moves instead of sending
1713 white rasters.
1714
1715 Since white is 0xFFFFFF (24 bits), there must be non-white pixels if
1716 there is a byte which is not 0xFF
1717 */
1718 static int
IsScanlineDirty(byte * pScanline,int iWidth)1719 IsScanlineDirty(byte* pScanline, int iWidth)
1720 {
1721 byte * pCurr = pScanline;
1722 byte * pStop = pCurr + iWidth;
1723
1724 while (pStop-pCurr)
1725 {
1726 if (*pCurr - 0xFF)
1727 {
1728 /* not 0xFF => dirty */
1729 return 1;
1730 }
1731 ++pCurr;
1732 }
1733 return 0;
1734 }
1735
1736 #define INIT_WHITE(pBuf, uiWidth) memset((void*)(pBuf), 0xFF, (uiWidth))
1737
1738 /* HP2200 output routine -------------------- */
1739 static int
chp2200_print_page(gx_device_printer * pdev,FILE * prn_stream)1740 chp2200_print_page(gx_device_printer * pdev, FILE * prn_stream)
1741 {
1742 gs_memory_t *mem = pdev->memory;
1743 int width_in_pixels = pdev->width;
1744 int width_in_bytes = width_in_pixels * 3; /* assume 24 bits (3 bytes per pixel) */
1745 byte *lbuf = gs_alloc_bytes(mem, width_in_bytes,
1746 "(input)chp2200_print_page");
1747 byte *lseedbuf = gs_alloc_bytes(mem, width_in_bytes,
1748 "(seed)chp2200_print_page");
1749 /* allocate twice the input size for worse case compressed output*/
1750 byte *loutputbuf = gs_alloc_bytes(mem, width_in_bytes*2,
1751 "(output)chp2200_print_page");
1752
1753 int lnum = 0;
1754 int iEmptyRows = 0;
1755 byte *data = lbuf;
1756
1757 if ((lbuf == 0) || (lseedbuf == 0) || (loutputbuf == 0))
1758 return_error(gs_error_VMerror);
1759
1760 /* Start Raster mode */
1761 (*cdj850->start_raster_mode) (pdev,
1762 gdev_pcl_paper_size((gx_device *)pdev),
1763 prn_stream);
1764
1765 /* start the scanline */
1766 fputs("\033*b", prn_stream);
1767
1768 /* initialise buffers */
1769 INIT_WHITE(lseedbuf, width_in_bytes);
1770
1771 for (lnum = 0; lnum < pdev->height; ++lnum)
1772 {
1773 int result = -1;
1774
1775 /*gdev_prn_get_bits(pdev, lnum, lbuf, &data);*/
1776 result = gdev_prn_copy_scan_lines(pdev, lnum, data, width_in_bytes);
1777
1778 if ((result == 1) && IsScanlineDirty(data, width_in_bytes))
1779 {
1780 unsigned int OutputLen = 0;
1781
1782 if (iEmptyRows)
1783 {
1784 /* send vertical Y move */
1785 fprintf(prn_stream, "%dy", iEmptyRows);
1786
1787 /* reset empty row count */
1788 iEmptyRows = 0;
1789
1790 /* reset seed buffer */
1791 INIT_WHITE(lseedbuf, width_in_bytes);
1792 }
1793
1794 OutputLen = Mode10(width_in_pixels,
1795 data,
1796 lseedbuf,
1797 loutputbuf);
1798
1799 if (OutputLen)
1800 {
1801 fprintf(prn_stream, "%dw", OutputLen);
1802 fwrite(loutputbuf, sizeof(byte), OutputLen, prn_stream);
1803
1804 /* save the current scanline as the seed for the next scanline*/
1805 memcpy((void*)lseedbuf, (const void*)data, width_in_bytes);
1806 }
1807 else
1808 {
1809 fputs("0w", prn_stream);
1810 }
1811 }
1812 else
1813 {
1814 iEmptyRows++;
1815 }
1816 }
1817
1818 /* terminate the scanline */
1819 fputs("0Y", prn_stream);
1820
1821 /* terminate page and eject paper */
1822 (*cdj850->terminate_page) (pdev, prn_stream);
1823
1824 gs_free_object(mem, lbuf, "(input)chp2200_print_page");
1825 gs_free_object(mem, lseedbuf, "(seed)chp2200_print_page");
1826 gs_free_object(mem, loutputbuf, "(output)chp2200_print_page");
1827
1828 return 0;
1829 }
1830
1831 #define HIBYTE(w) ((byte)(((unsigned int) (w) >> 8) & 0xFF))
1832 #define LOBYTE(w) ((byte)(w))
1833
1834 /* DNJ500 output routine -------------------- */
1835 static int
cdnj500_print_page(gx_device_printer * pdev,FILE * prn_stream)1836 cdnj500_print_page(gx_device_printer * pdev, FILE * prn_stream)
1837 {
1838 byte CRD_SeqC[] = {0x1b, 0x2a, 0x67, 0x31, 0x32, 0x57, 0x06, 0x1F, 0x00, 0x01,
1839 /* Esc * |g |# of bytes |W |frmt |SP |# of cmpnts*/
1840 0x00, 0x00, 0x00, 0x00, 0x0a, 0x01, 0x20, 0x01};
1841 /* |Horz Res |Vert Rez |compr|orien|bits |planes*/
1842
1843 /* x,y resolution for color planes, assume x=y */
1844 int xres = cdj850->x_pixels_per_inch;
1845 int yres = cdj850->y_pixels_per_inch;
1846
1847 gs_memory_t *mem = pdev->memory;
1848 int width_in_pixels = pdev->width;
1849 int width_in_bytes = width_in_pixels * 3; /* assume 24 bits (3 bytes per pixel) */
1850 byte *lbuf = gs_alloc_bytes(mem, width_in_bytes,
1851 "(input)cdnj500_print_page");
1852 byte *lseedbuf = gs_alloc_bytes(mem, width_in_bytes,
1853 "(seed)cdnj500_print_page");
1854 /* allocate twice the input size for worse case compressed output*/
1855 byte *loutputbuf = gs_alloc_bytes(mem, width_in_bytes*2,
1856 "(output)cdnj500_print_page");
1857
1858 int lnum = 0;
1859 int iEmptyRows = 0;
1860 int iBlock = 0;
1861 bool begin = true;
1862 byte *data = lbuf;
1863
1864 if ((lbuf == 0) || (lseedbuf == 0) || (loutputbuf == 0))
1865 return_error(gs_error_VMerror);
1866
1867 /* Start Raster mode */
1868 (*cdj850->start_raster_mode) (pdev,
1869 gdev_pcl_paper_size((gx_device *)pdev),
1870 prn_stream);
1871
1872 /* This will configure the raster-mode */
1873 CRD_SeqC[10] = HIBYTE(xres);
1874 CRD_SeqC[11] = LOBYTE(xres);
1875 CRD_SeqC[12] = HIBYTE(yres);
1876 CRD_SeqC[13] = LOBYTE(yres);
1877
1878 for (lnum = 0; lnum < pdev->height; ++lnum)
1879 {
1880 int result = -1;
1881
1882 /*gdev_prn_get_bits(pdev, lnum, lbuf, &data);*/
1883 result = gdev_prn_copy_scan_lines(pdev, lnum, data, width_in_bytes);
1884
1885 if ((result == 1) && IsScanlineDirty(data, width_in_bytes))
1886 {
1887 unsigned int OutputLen = 0;
1888
1889 /*
1890 * Printers with low memory (64 MB or less) can run out of memory during decompressing
1891 * the image data and will abort the job. To prevent this, restart raster command.
1892 * Raghu (hpijs)
1893 */
1894 if (iBlock == 448) /* from DesignJet 500 winNT driver */
1895 {
1896 /* terminate the scanline */
1897 fputs("0Y", prn_stream);
1898
1899 /* End graphics */
1900 fputs("\033*rC", prn_stream);
1901
1902 /* Reset in block lines counter */
1903 iBlock = 0;
1904 }
1905 if (iBlock == 0)
1906 {
1907 /* Send CRD */
1908 fwrite(CRD_SeqC, sizeof(byte), sizeof(CRD_SeqC), prn_stream);
1909
1910 /* Raster mode */
1911 fputs("\033*r1A", prn_stream);
1912
1913 /* start the scanline */
1914 fputs("\033*b", prn_stream);
1915
1916 /* reset seed buffer */
1917 INIT_WHITE(lseedbuf, width_in_bytes);
1918 }
1919 iBlock++;
1920
1921 if (iEmptyRows)
1922 {
1923 /* send vertical Y move */
1924 fprintf(prn_stream, "%dy", iEmptyRows);
1925
1926 /* reset empty row count */
1927 iEmptyRows = 0;
1928
1929 /* reset seed buffer */
1930 INIT_WHITE(lseedbuf, width_in_bytes);
1931 }
1932
1933 OutputLen = Mode10(width_in_pixels,
1934 data,
1935 lseedbuf,
1936 loutputbuf);
1937
1938 if (OutputLen)
1939 {
1940 fprintf(prn_stream, "%dw", OutputLen);
1941 fwrite(loutputbuf, sizeof(byte), OutputLen, prn_stream);
1942
1943 /* save the current scanline as the seed for the next scanline*/
1944 memcpy((void*)lseedbuf, (const void*)data, width_in_bytes);
1945 }
1946 else
1947 {
1948 fputs("0w", prn_stream);
1949 }
1950
1951 /* Content printing already started */
1952 begin = false;
1953 }
1954 else
1955 {
1956 /* Skip empty area on top page */
1957 if (begin == false) iEmptyRows++;
1958 }
1959 }
1960
1961 /* terminate the scanline */
1962 fputs("0Y", prn_stream);
1963
1964 /* terminate page and eject paper */
1965 (*cdj850->terminate_page) (pdev, prn_stream);
1966
1967 gs_free_object(mem, lbuf, "(input)cdnj500_print_page");
1968 gs_free_object(mem, lseedbuf, "(seed)cdnj500_print_page");
1969 gs_free_object(mem, loutputbuf, "(output)cdnj500_print_page");
1970
1971 return 0;
1972 }
1973
1974
1975 #define odd(i) ((i & 01) != 0)
1976
1977 static int
GetScanLine(gx_device_printer * pdev,int * lnum,struct ptr_arrays * data_ptrs,struct misc_struct * misc_vars,word rmask)1978 GetScanLine(gx_device_printer * pdev, int *lnum,
1979 struct ptr_arrays *data_ptrs,
1980 struct misc_struct *misc_vars,
1981 word rmask)
1982 {
1983 word *data_words = (word *) data_ptrs->data[misc_vars->scan];
1984 register word *end_data = data_words + misc_vars->line_size_words;
1985
1986 ++(*lnum);
1987 gdev_prn_copy_scan_lines(pdev, *lnum, (byte *) data_words, misc_vars->line_size);
1988
1989 misc_vars->scan = !misc_vars->scan; /* toggle scan direction */
1990 misc_vars->is_two_pass = odd(*lnum); /* color output for odd lines */
1991
1992 /* Mask off 1-bits beyond the line width. */
1993 end_data[-1] &= rmask;
1994
1995 /* Remove trailing 0s. */
1996 while (end_data > data_words && end_data[-1] == 0)
1997 end_data--;
1998
1999 return end_data - data_words;
2000 }
2001
2002 /* Send the scan lines to the printer */
2003 static void
send_scan_lines(gx_device_printer * pdev,struct ptr_arrays * data_ptrs,struct misc_struct * misc_vars,struct error_val_field * error_values,const Gamma * gamma,FILE * prn_stream)2004 send_scan_lines(gx_device_printer * pdev,
2005 struct ptr_arrays *data_ptrs,
2006 struct misc_struct *misc_vars,
2007 struct error_val_field *error_values,
2008 const Gamma *gamma,
2009 FILE * prn_stream)
2010 {
2011 int lnum, lend, llen;
2012 int num_blank_lines = 0;
2013
2014 word rmask =
2015 ~(word) 0 << ((-pdev->width * misc_vars->storage_bpp) & (W * 8 - 1));
2016
2017 lend = pdev->height - (dev_t_margin(pdev) + dev_b_margin(pdev)) * y_dpi;
2018
2019 error_values->c = error_values->m = error_values->y =
2020 error_values->k = 0;
2021
2022 /* init the error buffer */
2023 init_error_buffer(misc_vars, data_ptrs);
2024
2025 misc_vars->zero_row_count = 0;
2026 lnum = -1;
2027 llen = GetScanLine(pdev, &lnum, data_ptrs, misc_vars, rmask);
2028 while (lnum < lend) {
2029 num_blank_lines = 0;
2030 while (lnum < lend && llen == 0) {
2031 ++num_blank_lines;
2032 llen = GetScanLine(pdev, &lnum, data_ptrs, misc_vars, rmask);
2033 }
2034 if (lnum >= lend) {
2035 break;
2036 }
2037 /* Skip blank lines if any */
2038 if (num_blank_lines > 0) {
2039 fprintf(prn_stream, "\033*b%dY", num_blank_lines / (cdj850->yscal + 1));
2040 memset(data_ptrs->plane_data[0][0], 0,
2041 (misc_vars->plane_size * 2 * misc_vars->num_comps));
2042 memset(data_ptrs->plane_data_c[0][0], 0,
2043 (misc_vars->plane_size_c * 2 * misc_vars->num_comps));
2044
2045 }
2046 /* all blank lines printed, now for the non-blank lines */
2047 if (cdj850->yscal && odd(lnum)) {
2048 /* output a blank black plane for odd lines */
2049 fprintf(prn_stream, "\033*b0V");
2050 }
2051 /* now output all non blank lines */
2052 while (lnum < lend && llen != 0) {
2053 misc_vars->is_color_data = 0; /* maybe we have color ? */
2054 (*cdj850->print_non_blank_lines) (pdev, data_ptrs, misc_vars,
2055 error_values, gamma, prn_stream);
2056 llen = GetScanLine(pdev, &lnum, data_ptrs, misc_vars, rmask);
2057 }
2058 if (cdj850->yscal && odd(lnum)) { /* output empty line for odd lines */
2059 (*cdj850->print_non_blank_lines) (pdev, data_ptrs, misc_vars,
2060 error_values, gamma, prn_stream);
2061 }
2062 /* the current line is empty => run the next iteration */
2063 }
2064 }
2065
2066 /* print_line compresses (mode 9) and outputs one plane */
2067 static void
print_c9plane(FILE * prn_stream,char plane_code,int plane_size,const byte * curr,const byte * prev,byte * out_data)2068 print_c9plane(FILE * prn_stream, char plane_code, int plane_size,
2069 const byte * curr, const byte * prev, byte * out_data)
2070 {
2071 /* Compress the output data */
2072 int out_count = gdev_pcl_mode9compress(plane_size, curr, prev, out_data);
2073
2074 /* and output the data */
2075 fprintf(prn_stream, "%d%c", out_count, plane_code);
2076 if (out_count > 0) {
2077 fwrite(out_data, sizeof(byte), out_count, prn_stream);
2078 }
2079 }
2080
2081
2082 /* print_c2plane()
2083 *
2084 * Compresses a single plane with mode 2 (TIFF 4 format) and sends the
2085 * result to the output.
2086 */
2087 static void
print_c2plane(FILE * prn_stream,char plane_code,int plane_size,const byte * curr,byte * out_data)2088 print_c2plane(FILE *prn_stream, char plane_code, int plane_size,
2089 const byte *curr, byte *out_data)
2090 {
2091 /*
2092 * Compress the output data
2093 */
2094 int out_count = gdev_pcl_mode2compress((const word *)curr,
2095 (const word *)(curr +plane_size -2), out_data);
2096
2097 /*
2098 * Send it out
2099 */
2100 fprintf(prn_stream, "%d%c", out_count, plane_code);
2101 if (out_count > 0)
2102 fwrite(out_data, sizeof(byte), out_count, prn_stream);
2103 }
2104
2105
2106 /* print_c0plane()
2107 *
2108 * Outputs a plane with no compression.
2109 */
2110 static void
print_c0plane(FILE * prn_stream,char plane_code,int plane_size,const byte * curr,byte * out_data)2111 print_c0plane(FILE *prn_stream, char plane_code, int plane_size,
2112 const byte *curr, byte *out_data)
2113 {
2114 fprintf(prn_stream, "%d%c", plane_size, plane_code);
2115 if (plane_size > 0)
2116 fwrite(curr, sizeof(byte), plane_size, prn_stream);
2117 }
2118
2119
2120 /* Printing non-blank lines */
2121 static void
cdj850_print_non_blank_lines(gx_device_printer * pdev,struct ptr_arrays * data_ptrs,struct misc_struct * misc_vars,struct error_val_field * error_values,const Gamma * gamma,FILE * prn_stream)2122 cdj850_print_non_blank_lines(gx_device_printer * pdev,
2123 struct ptr_arrays *data_ptrs,
2124 struct misc_struct *misc_vars,
2125 struct error_val_field *error_values,
2126 const Gamma *gamma,
2127 FILE * prn_stream)
2128 {
2129 static const char *const plane_code[2] =
2130 {"wvvv", "vvvv"};
2131
2132 int i;
2133 byte *kP = data_ptrs->plane_data[misc_vars->scan + 2][3];
2134 byte *dp = data_ptrs->data[misc_vars->scan + 2];
2135 int *ep = data_ptrs->errors[misc_vars->scan];
2136
2137 /* we need cmyk color separation befor all the rest, since
2138 black may be contained in the color fields. This needs to
2139 be done on all pixel-rows, since even unused color-bytes
2140 might generate black */
2141
2142 misc_vars->is_color_data =
2143 do_gcr(misc_vars->databuff_size, data_ptrs->data[misc_vars->scan],
2144 gamma->k, gamma->c, gamma->m, gamma->y, gamma->correct,
2145 (word *) data_ptrs->data[misc_vars->scan]);
2146
2147 /* dithering the black-plane */
2148 FSDlinebw(misc_vars->scan, misc_vars->plane_size,
2149 error_values, kP, misc_vars->num_comps, ep, dp);
2150
2151 /* output the black plane */
2152 print_c9plane(prn_stream, 'v', misc_vars->plane_size,
2153 data_ptrs->plane_data[misc_vars->scan][3],
2154 data_ptrs->plane_data[1 - misc_vars->scan][3],
2155 data_ptrs->out_data);
2156
2157 /* since color resolution is only half of the b/w-resolution,
2158 we only output every second row */
2159 if (!cdj850->yscal || misc_vars->is_two_pass) {
2160
2161 int plane_size_c = (*rescale_color_plane[cdj850->xscal][cdj850->yscal])
2162 (misc_vars->databuff_size,
2163 data_ptrs->data[misc_vars->scan],
2164 data_ptrs->data[!misc_vars->scan],
2165 data_ptrs->data_c[misc_vars->cscan]) / misc_vars->storage_bpp;
2166
2167 /* dither the color planes */
2168 do_floyd_steinberg(misc_vars->scan, misc_vars->cscan,
2169 misc_vars->plane_size, plane_size_c,
2170 misc_vars->num_comps, data_ptrs, pdev, error_values);
2171
2172 /* Transfer raster graphics in the order C, M, Y, that is
2173 planes 2,1,0 */
2174 for (i = misc_vars->num_comps - 2; i >= 0; i--) {
2175
2176 /* output the lower color planes */
2177 print_c9plane(prn_stream, plane_code[cdj850->intensities > 2][i],
2178 plane_size_c,
2179 data_ptrs->plane_data_c[misc_vars->cscan][i],
2180 data_ptrs->plane_data_c[1 - misc_vars->cscan][i],
2181 data_ptrs->out_data);
2182
2183 /* output the upper color planes */
2184 if (cdj850->intensities > 2) {
2185 print_c9plane(prn_stream, plane_code[0][i], plane_size_c,
2186 data_ptrs->plane_data_c[misc_vars->cscan][i + 4],
2187 data_ptrs->plane_data_c[1 -
2188 misc_vars->cscan][i
2189 + 4],
2190 data_ptrs->out_data);
2191 } /* end cdj850->intensities > 2 */
2192 } /* End For i = num_comps */
2193 misc_vars->cscan = 1 - misc_vars->cscan;
2194 } /* End of is_two_pass */
2195 return;
2196 }
2197
2198 /* Printing non-blank lines */
2199 static void
cdj880_print_non_blank_lines(gx_device_printer * pdev,struct ptr_arrays * data_ptrs,struct misc_struct * misc_vars,struct error_val_field * error_values,const Gamma * gamma,FILE * prn_stream)2200 cdj880_print_non_blank_lines(gx_device_printer * pdev,
2201 struct ptr_arrays *data_ptrs,
2202 struct misc_struct *misc_vars,
2203 struct error_val_field *error_values,
2204 const Gamma *gamma,
2205 FILE * prn_stream)
2206 {
2207 static const char *const plane_code[2] =
2208 {"WVVV", "VVVV"};
2209
2210 int i;
2211 byte *kP = data_ptrs->plane_data[misc_vars->scan + 2][3];
2212 byte *dp = data_ptrs->data[misc_vars->scan + 2];
2213 int *ep = data_ptrs->errors[misc_vars->scan];
2214
2215 /* we need cmyk color separation befor all the rest, since
2216 black may be contained in the color fields. This needs to
2217 be done on all pixel-rows, since even unused color-bytes
2218 might generate black */
2219
2220 misc_vars->is_color_data =
2221 do_gcr(misc_vars->databuff_size, data_ptrs->data[misc_vars->scan],
2222 gamma->k, gamma->c, gamma->m, gamma->y, gamma->correct,
2223 (word *) data_ptrs->data[misc_vars->scan]);
2224
2225 /* dithering the black-plane */
2226 FSDlinebw(misc_vars->scan, misc_vars->plane_size,
2227 error_values, kP, misc_vars->num_comps, ep, dp);
2228
2229 /* output the black plane */
2230 fputs("\033*b", prn_stream);
2231 print_c2plane(prn_stream, 'V', misc_vars->plane_size,
2232 data_ptrs->plane_data[misc_vars->scan][3],
2233 /* data_ptrs->plane_data[1 - misc_vars->scan][3],*/
2234 data_ptrs->out_data);
2235 /* fputs("\033*b0V", prn_stream);*/
2236
2237 /* since color resolution is only half of the b/w-resolution,
2238 we only output every second row */
2239 if (!cdj850->yscal || misc_vars->is_two_pass) {
2240
2241 int plane_size_c = (*rescale_color_plane[cdj850->xscal][cdj850->yscal])
2242 (misc_vars->databuff_size,
2243 data_ptrs->data[misc_vars->scan],
2244 data_ptrs->data[!misc_vars->scan],
2245 data_ptrs->data_c[misc_vars->cscan]) / misc_vars->storage_bpp;
2246
2247 /* dither the color planes */
2248 do_floyd_steinberg(misc_vars->scan, misc_vars->cscan,
2249 misc_vars->plane_size, plane_size_c,
2250 misc_vars->num_comps, data_ptrs, pdev, error_values);
2251
2252 /* Transfer raster graphics in the order C, M, Y, that is
2253 planes 2,1,0 */
2254 for (i = misc_vars->num_comps - 2; i >= 0; i--) {
2255
2256 /* output the lower color planes */
2257 fputs("\033*b", prn_stream);
2258 print_c2plane(prn_stream, plane_code[cdj850->intensities > 2][i],
2259 plane_size_c,
2260 data_ptrs->plane_data_c[misc_vars->cscan][i],
2261 /* data_ptrs->plane_data_c[1 - misc_vars->cscan][i],*/
2262 data_ptrs->out_data);
2263
2264 /* output the upper color planes */
2265 if (cdj850->intensities > 2) {
2266 fputs("\033*b", prn_stream);
2267 print_c2plane(prn_stream, plane_code[0][i], plane_size_c,
2268 data_ptrs->plane_data_c[misc_vars->cscan][i + 4],
2269 /* data_ptrs->plane_data_c[1 -
2270 misc_vars->cscan][i
2271 + 4],*/
2272 data_ptrs->out_data);
2273 } /* end cdj850->intensities > 2 */
2274 } /* End For i = num_comps */
2275 misc_vars->cscan = 1 - misc_vars->cscan;
2276 } /* End of is_two_pass */
2277 return;
2278 }
2279
2280 /* moved that code into his own subroutine, otherwise things get
2281 somewhat clumsy */
2282 static void
do_floyd_steinberg(int scan,int cscan,int plane_size,int plane_size_c,int n,struct ptr_arrays * data_ptrs,gx_device_printer * pdev,struct error_val_field * error_values)2283 do_floyd_steinberg(int scan, int cscan, int plane_size,
2284 int plane_size_c, int n,
2285 struct ptr_arrays *data_ptrs,
2286 gx_device_printer * pdev,
2287 struct error_val_field *error_values)
2288 {
2289 /* the color pointers */
2290 byte *cPa, *mPa, *yPa, *cPb, *mPb, *yPb;
2291 byte *dpc;
2292 int *epc;
2293
2294 /* the b/w pointers */
2295 byte *kP, *dp;
2296 int *ep;
2297
2298 /* the color pointers, lower byte */
2299 cPa = data_ptrs->plane_data_c[cscan + 2][2];
2300 mPa = data_ptrs->plane_data_c[cscan + 2][1];
2301 yPa = data_ptrs->plane_data_c[cscan + 2][0];
2302 /* upper byte */
2303 cPb = data_ptrs->plane_data_c[cscan + 2][6];
2304 mPb = data_ptrs->plane_data_c[cscan + 2][5];
2305 yPb = data_ptrs->plane_data_c[cscan + 2][4];
2306 /* data and error */
2307 dpc = data_ptrs->data_c[cscan + 2];
2308 epc = data_ptrs->errors_c[cscan];
2309 /* the b/w pointers */
2310 kP = data_ptrs->plane_data[scan + 2][3];
2311 dp = data_ptrs->data[scan + 2];
2312 ep = data_ptrs->errors[scan];
2313
2314 switch (cdj850->intensities) {
2315 case 2:
2316 FSDlinec2(cscan, plane_size_c, error_values,
2317 cPa, mPa, yPa, n, dpc, epc);
2318 break;
2319 case 3:
2320 FSDlinec3(cscan, plane_size_c, error_values,
2321 cPa, mPa, yPa, cPb, mPb, yPb, n, dpc, epc);
2322 break;
2323 case 4:
2324 FSDlinec4(cscan, plane_size_c, error_values,
2325 cPa, mPa, yPa, cPb, mPb, yPb, n, dpc, epc);
2326 break;
2327 default:
2328 assert(0);
2329 }
2330 return;
2331 }
2332
2333 /* here we do our own gamma-correction */
2334 static void
do_gamma(float mastergamma,float gammaval,byte values[256])2335 do_gamma(float mastergamma, float gammaval, byte values[256])
2336 {
2337 int i;
2338 float gamma;
2339
2340 if (gammaval > 0.0) {
2341 gamma = gammaval;
2342 } else {
2343 gamma = mastergamma;
2344 }
2345
2346 for (i = 0; i < 256; i++) {
2347 values[i] = (byte) (255.0 *
2348 (1.0 - pow(((double)(255.0 - (float)i) / 255.0),
2349 (double)(1.0 / gamma))));
2350 }
2351
2352 return;
2353 }
2354
2355 /* here we calculate a lookup-table which is used to compensate the
2356 relative loss of color due to undercolor-removal */
2357 static void
do_black_correction(float kvalue,int kcorrect[256])2358 do_black_correction(float kvalue, int kcorrect[256])
2359 {
2360 int i;
2361
2362 for (i = 0; i < 256; i++) {
2363 kcorrect[i] = 0;
2364 #if 0
2365 kcorrect[i] = (int)
2366 (100.0 * kvalue * (
2367 pow(10.0,
2368 pow((i / 255.0), 3.0)
2369 )
2370 - 1.0
2371 )
2372 );
2373 #endif /* 0 */
2374 }
2375
2376 return;
2377 }
2378
2379 /* For Better Performance we use a macro here */
2380 #define DOUCR(col1, col2, col3, col4)\
2381 {\
2382 /* determine how far we are from the grey axis. This is */\
2383 /* traditionally done by computing MAX(CMY)-MIN(CMY). */\
2384 /* However, if two colors are very similar, we could */\
2385 /* as either CMYRGB and K. Therefore we calculate the */\
2386 /* the distance col1-col2 and col2-col3, and use the */\
2387 /* smaller one. */\
2388 a = *col1 - *col2;\
2389 b = *col2 - *col3;\
2390 if (a >= b) {\
2391 grey_distance = 1.0 - (b/255.0);\
2392 } else {\
2393 grey_distance = 1.0 - (a/255.0);\
2394 }\
2395 ucr = (byte) (*col3 * grey_distance); \
2396 *col4 = *col4 + ucr; /* add removed black to black */\
2397 /* remove only as much color as black is surviving the */\
2398 /* gamma correction */\
2399 ucr = *(kvalues + ucr);\
2400 *col1 = *col1 - ucr ;\
2401 *col2 = *col2 - ucr ;\
2402 *col3 = *col3 - ucr ;\
2403 }
2404
2405 /* For Better Performance we use a macro here */
2406 #define DOGCR(col1, col2, col3, col4)\
2407 {\
2408 int ucr = (int) *col3;\
2409 *col1 -= ucr ;\
2410 *col2 -= ucr ;\
2411 *col3 -= ucr ;\
2412 *col4 += ucr; /* add removed black to black */\
2413 kadd = ucr + *(kcorrect + ucr);\
2414 uca_fac = 1.0 + (kadd/255.0);\
2415 *col1 *= uca_fac;\
2416 *col2 *= uca_fac;\
2417 }
2418
2419 #define NOBLACK(col1, col2, col3, col4)\
2420 {\
2421 ucr = (int) *col4;\
2422 *col1 += ucr;\
2423 *col2 += ucr;\
2424 *col3 += ucr;\
2425 *col4 = 0;\
2426 }
2427
2428 /* Since resolution can be different on different planes, we need to
2429 do real color separation, here we try a real grey component
2430 replacement */
2431 static int
do_gcr(int bytecount,byte * inbyte,const byte kvalues[256],const byte cvalues[256],const byte mvalues[256],const byte yvalues[256],const int kcorrect[256],word * inword)2432 do_gcr(int bytecount, byte * inbyte, const byte kvalues[256],
2433 const byte cvalues[256], const byte mvalues[256],
2434 const byte yvalues[256], const int kcorrect[256],
2435 word * inword)
2436 {
2437 int i, ucr, kadd, is_color = 0;
2438 float uca_fac;
2439 byte *black, *cyan, *magenta, *yellow;
2440 word last_color_value = 0;
2441 word *last_color;
2442 char output[255], out2[128];
2443
2444 /* initialise *last_color with a dummmy value */
2445 last_color = &last_color_value;
2446 /* Grey component replacement */
2447 for (i = 0; i < bytecount; i += 4) {
2448
2449 /* Assign to black the current address of inbyte */
2450 black = inbyte++;
2451 cyan = inbyte++;
2452 magenta = inbyte++;
2453 yellow = inbyte++;
2454
2455 if (*black > 0)
2456 NOBLACK(cyan, magenta, yellow, black);
2457
2458 if (*magenta + *yellow + *cyan > 0) { /* if any color at all */
2459
2460 #if 0
2461 if ((*cyan > 0) && (*magenta > 0) && (*yellow > 0))
2462 {
2463 sprintf(output, "%3d %3d %3d %3d - ", *cyan, *magenta, *yellow, *black);
2464 debug_print_string(output, strlen(output));
2465 }
2466 #endif /* 0 */
2467
2468 is_color = 1;
2469
2470 /* Test whether we 've already computet the value */
2471 if (*inword == last_color_value) {
2472 /* save a copy of the current color before it will be modified */
2473 last_color_value = *inword;
2474 /* debug_print_string("\n", 1);*/
2475 /* copy the result of the old value onto the new position */
2476 *inword = *last_color;
2477 } else {
2478 /* save a copy of the current color before it will be modified */
2479 last_color_value = *inword;
2480 NOBLACK(cyan, magenta, yellow, black);
2481 if ((*cyan >= *magenta)
2482 && (*magenta >= *yellow)
2483 && (*yellow > 0)) { /* if any grey component */
2484 NOBLACK(cyan, magenta, yellow, black);
2485 } else if ((*cyan >= *yellow)
2486 && (*yellow >= *magenta)
2487 && (*magenta > 0)) {
2488 NOBLACK(cyan, yellow, magenta, black);
2489 } else if ((*yellow >= *magenta)
2490 && (*magenta >= *cyan)
2491 && (*cyan > 0)) {
2492 NOBLACK(yellow, magenta, cyan, black);
2493 } else if ((*yellow >= *cyan)
2494 && (*cyan >= *magenta)
2495 && (*magenta > 0)) {
2496 NOBLACK(yellow, cyan, magenta, black);
2497 } else if ((*magenta >= *yellow)
2498 && (*yellow >= *cyan)
2499 && (*cyan > 0)) {
2500 NOBLACK(magenta, yellow, cyan, black);
2501 } else if ((*magenta >= *cyan)
2502 && (*cyan >= *yellow)
2503 && (*yellow > 0)) {
2504 NOBLACK(magenta, cyan, yellow, black);
2505 } else { /* do gamma only if no black */
2506 }
2507 #if 0
2508 if (ucr > 0)
2509 {
2510 sprintf(output, "%3d %3d %3d %3d - %5d\n", *cyan, *magenta, *yellow, *black, ucr);
2511 debug_print_string(output, strlen(output));
2512 }
2513 #endif /* 0 */
2514 if ( *cyan > 255) *cyan = 255;
2515 if (*magenta > 255) *magenta = 255;
2516 if ( *yellow > 255) *yellow = 255;
2517
2518 *cyan = *(cvalues + *cyan);
2519 *magenta = *(mvalues + *magenta);
2520 *yellow = *(yvalues + *yellow);
2521 last_color = inword; /* save pointer */
2522 }/* end current_color */
2523 } /* end of if c+m+y > 0 */
2524 *black = *(kvalues + *black);
2525 inword = inword + 1;
2526 } /* end of for bytecount */
2527 return is_color;
2528 }
2529
2530 /* Since resolution can be different on different planes, we need to
2531 rescale the data byte by byte */
2532 static int
rescale_byte_wise2x2(int bytecount,const byte * inbytea,const byte * inbyteb,byte * outbyte)2533 rescale_byte_wise2x2(int bytecount, const byte * inbytea, const byte * inbyteb,
2534 byte * outbyte)
2535 {
2536 register int i, j;
2537 int max = bytecount / 2;
2538
2539 for (i = 0; i < max; i += 4) {
2540 j = 2 * i;
2541 /* cyan */
2542 outbyte[i + 1] = (inbytea[j + 1] + inbytea[j + 5] + inbyteb[j + 1] +
2543 inbyteb[j + 5]) / 4;
2544 /* magenta */
2545 outbyte[i + 2] = (inbytea[j + 2] + inbytea[j + 6] + inbyteb[j + 2] +
2546 inbyteb[j + 6]) / 4;
2547 /* yellow */
2548 outbyte[i + 3] = (inbytea[j + 3] + inbytea[j + 7] + inbyteb[j + 3] +
2549 inbyteb[j + 7]) / 4;
2550 }
2551 return max;
2552 }
2553
2554 /* Since resolution can be different on different planes, we need to
2555 rescale the data byte by byte */
2556 static int
rescale_byte_wise2x1(int bytecount,const byte * inbytea,const byte * inbyteb,byte * outbyte)2557 rescale_byte_wise2x1(int bytecount, const byte * inbytea, const byte * inbyteb,
2558 byte * outbyte)
2559 {
2560 register int i, j;
2561 int max = bytecount / 2;
2562
2563 for (i = 0; i < max; i += 4) {
2564 j = 2 * i;
2565 /* cyan */
2566 outbyte[i + 1] = (inbytea[j + 1] + inbytea[j + 5]) / 2;
2567 /* magenta */
2568 outbyte[i + 2] = (inbytea[j + 2] + inbytea[j + 6]) / 2;
2569 /* yellow */
2570 outbyte[i + 3] = (inbytea[j + 3] + inbytea[j + 7]) / 2;
2571 }
2572 return max;
2573 }
2574
2575 /* Since resolution can be different on different planes, we need to
2576 rescale the data byte by byte */
2577 static int
rescale_byte_wise1x2(int bytecount,const byte * inbytea,const byte * inbyteb,byte * outbyte)2578 rescale_byte_wise1x2(int bytecount, const byte * inbytea, const byte * inbyteb,
2579 byte * outbyte)
2580 {
2581 register int i;
2582
2583 for (i = 0; i < bytecount; i += 4) {
2584 /* cyan */
2585 outbyte[i + 1] = (inbytea[i + 1] + inbyteb[i + 1]) / 2;
2586 /* magenta */
2587 outbyte[i + 2] = (inbytea[i + 2] + inbyteb[i + 2]) / 2;
2588 /* yellow */
2589 outbyte[i + 3] = (inbytea[i + 3] + inbyteb[i + 3]) / 2;
2590 }
2591 return bytecount;
2592 }
2593
2594 /* Since resolution can be different on different planes, we need to
2595 rescale the data byte by byte */
2596 static int
rescale_byte_wise1x1(int bytecount,const byte * inbytea,const byte * inbyteb,byte * outbyte)2597 rescale_byte_wise1x1(int bytecount, const byte * inbytea, const byte * inbyteb,
2598 byte * outbyte)
2599 {
2600 register int i;
2601
2602 for (i = 0; i < bytecount; i += 4) {
2603 /* cyan */
2604 outbyte[i + 1] = inbytea[i + 1];
2605 /* magenta */
2606 outbyte[i + 2] = inbytea[i + 2];
2607 /* yellow */
2608 outbyte[i + 3] = inbytea[i + 3];
2609 }
2610 return bytecount;
2611 }
2612
2613 /* MACROS FOR DITHERING (we use macros for compact source and faster code) */
2614 /* Floyd-Steinberg dithering. Often results in a dramatic improvement in
2615 * subjective image quality, but can also produce dramatic increases in
2616 * amount of printer data generated and actual printing time!! Mode 9 2D
2617 * compression is still useful for fairly flat colour or blank areas but its
2618 * compression is much less effective in areas where the dithering has
2619 * effectively randomised the dot distribution. */
2620
2621 #define SHIFT ((I * 8) - 13)
2622 #define C 8
2623
2624 #define BLACKOFFSET (128 << SHIFT) /* distance from min to max */
2625 #define THRESHOLD (128 << SHIFT)
2626 #define MAXVALUE (THRESHOLD + BLACKOFFSET)
2627
2628 /* -64 to 64 */
2629 #define RANDOM ((rand() << SHIFT) % THRESHOLD - (THRESHOLD >> 1))
2630
2631 /* --- needed for the hp850 color -- */
2632 /*
2633
2634 Mode Planes Intensity
2635 Low A 1.0
2636 Medium B 1.5
2637 High A&B 2.0
2638
2639 Note that planes A&B is not the sum of the intensities of plane A and plane B.
2640
2641 Range Planes Max Intensity
2642 0-63 A < 50% 0.5
2643 64-127 A > 50% 1.0
2644 128-191 B > 50% 1.5
2645 192-255 A&B > 50% 2.0
2646
2647 Note some specific values:
2648 Value Planes Intensity
2649 0 0 0.0
2650 32 25% A 0.25
2651 64 50% A 0.5
2652 128 100% A 1.0
2653 129 99% A, 1% B 1.01
2654 192 100% B 1.5
2655 255 100% C 2.0
2656
2657 Keep in mind that only the range 0-63 has a pixel rate <50%. All others
2658 have a pixel rate >50%.
2659
2660 */
2661
2662 #define COLOROFFSET ( 64 << SHIFT) /* distance between color intensities */
2663
2664 #define THRESHOLDS ( 64 << SHIFT) /* intensity A */
2665 #define THRESHOLDM (128 << SHIFT) /* intensity B */
2666 #define THRESHOLDL (192 << SHIFT) /* intensities A & B */
2667
2668 #define MAXVALUES (THRESHOLDS + COLOROFFSET)
2669 #define MAXVALUEM (THRESHOLDM + COLOROFFSET)
2670 #define MAXVALUEL (THRESHOLDL + COLOROFFSET)
2671
2672 #define CRANDOM ((rand() << SHIFT) % THRESHOLDS - (THRESHOLDS >> 1))
2673
2674 /* --------------------------- */
2675
2676 /* initialise the error_buffer */
2677 static void
init_error_buffer(struct misc_struct * misc_vars,struct ptr_arrays * data_ptrs)2678 init_error_buffer(struct misc_struct * misc_vars,
2679 struct ptr_arrays * data_ptrs)
2680 {
2681 int i;
2682 int *ep;
2683 int *epc;
2684
2685 ep = data_ptrs->errors[0];
2686 epc = data_ptrs->errors_c[0];
2687
2688 if (misc_vars->bits_per_pixel > 4) { /* Randomly seed initial error
2689 buffer */
2690 /* Otherwise, the first dithered rows would look rather uniform */
2691 for (i = 0; i < misc_vars->databuff_size; i++) { /* 600dpi planes */
2692 *ep++ = RANDOM;
2693 }
2694
2695 /* Now for the 2 * 300dpi color planes */
2696 for (i = 0; i < misc_vars->databuff_size_c; i++) {
2697 *epc++ = CRANDOM;
2698 }
2699 }
2700 return;
2701 }
2702
2703 #define FSdither(inP, out, errP, Err, Bit, Offset, Element)\
2704 {\
2705 oldErr = Err;\
2706 Err = (*(errP + Element)\
2707 + ((Err * 7 + C) >> 4)\
2708 + ((int)*(inP + Element) << SHIFT));\
2709 if (Err > THRESHOLD || *(inP + Element) == 255 /* b/w optimization */) {\
2710 out |= Bit;\
2711 Err -= MAXVALUE;\
2712 }\
2713 *(errP + (Element + Offset)) += ((Err * 3 + C) >> 4);\
2714 *(errP + Element) = ((Err * 5 + oldErr + C) >> 4);\
2715 }
2716
2717
2718 /* FSDlinebw()
2719 *
2720 * Floyd-steinberg dithering for the black plane. The 850C has 600dpi
2721 * black and 300dpi color, but the 880C and siblings have 600dpi black
2722 * AND color. Therefore, we need an adapted dither algorithm.
2723 *
2724 * Inputs: scan
2725 *
2726 * plane_size
2727 *
2728 * error_values
2729 *
2730 * kP
2731 *
2732 * n
2733 *
2734 * ep
2735 *
2736 * dp
2737 *
2738 * Returns: Nothing.
2739 */
2740 static void
FSDlinebw(int scan,int plane_size,struct error_val_field * error_values,byte * kP,int n,int * ep,byte * dp)2741 FSDlinebw(int scan, int plane_size,
2742 struct error_val_field * error_values,
2743 byte * kP, int n, int * ep, byte * dp)
2744 {
2745 if (scan == 0) { /* going_up */
2746 byte k, bitmask; /* k = outbyte byte, whereas bitmask defines the
2747 bit to be set within k */
2748 int oldErr, i;
2749
2750 for (i = 0; i < plane_size; i++) {
2751 bitmask = 0x80;
2752 for (k = 0; bitmask != 0; bitmask >>= 1) {
2753 /* dp points to the first word of the input data which is in
2754 kcmy-format */
2755 /* k points to the beginning of the first outbut byte, which
2756 is filled up, bit by bit while looping over bytemask */
2757 /* ep points to the first word of the error-plane which
2758 contains the errors kcmy format */
2759 /* err_values->k tempararily holds the error-value */
2760 /* bitmask selects the bit to be set in the outbyte */
2761 /* n gives the offset for the byte selection within
2762 words. With simple cmyk-printing, this should be 4 */
2763 /* 0 points to the active color within the input-word, i.e. 0
2764 = black, 1 = cyan, 2 = yellow, 3 = magenta */
2765
2766 FSdither(dp, k, ep, error_values->k, bitmask, -n, 0);
2767 dp += n, ep += n; /* increment the input and error pointer one
2768 word (=4 byte) further, in order to
2769 convert the next word into an bit */
2770 }
2771 *kP++ = k; /* fill the output-plane byte with the computed byte
2772 and increment the output plane pointer one byte */
2773 }
2774
2775 } else { /* going_down */
2776 byte k, bitmask;
2777 int oldErr, i;
2778 for (i = 0; i < plane_size; i++) {
2779 bitmask = 0x01;
2780 for (k = 0; bitmask != 0; bitmask <<= 1) {
2781 dp -= n, ep -= n;
2782 FSdither(dp, k, ep, error_values->k, bitmask, n, 0);
2783 }
2784 *--kP = k;
2785 }
2786 }
2787 return;
2788 }
2789
2790 /* Since bw has already been dithered for the hp850c, we need
2791 an adapted dither algorythm */
2792 static void
FSDlinec2(int scan,int plane_size,struct error_val_field * error_values,byte * cPa,byte * mPa,byte * yPa,int n,byte * dp,int * ep)2793 FSDlinec2(int scan, int plane_size,
2794 struct error_val_field *error_values,
2795 byte * cPa, byte * mPa, byte * yPa, int n,
2796 byte * dp, int *ep)
2797 {
2798 if (scan == 0) { /* going_up */
2799 int oldErr, i;
2800 byte ca, ya, ma, bitmask;
2801
2802 for (i = 0; i < plane_size; i++) {
2803 bitmask = 0x80;
2804 ca = ya = ma = 0;
2805 for (ca = 0; bitmask != 0; bitmask >>= 1) {
2806 FSdither(dp, ca, ep, error_values->c, bitmask, -n, n - 3);
2807 FSdither(dp, ma, ep, error_values->m, bitmask, -n, n - 2);
2808 FSdither(dp, ya, ep, error_values->y, bitmask, -n, n - 1);
2809 dp += n, ep += n;
2810 }
2811 *cPa++ = ca;
2812 *mPa++ = ma;
2813 *yPa++ = ya;
2814 }
2815
2816 } else { /* going_down */
2817 byte ca, ya, ma, bitmask;
2818 int oldErr, i;
2819
2820 for (i = 0; i < plane_size; i++) {
2821 bitmask = 0x01;
2822 ca = ya = ma = 0;
2823 for (ca = 0; bitmask != 0; bitmask <<= 1) {
2824 dp -= n, ep -= n;
2825 FSdither(dp, ya, ep, error_values->y, bitmask, n, n - 1);
2826 FSdither(dp, ma, ep, error_values->m, bitmask, n, n - 2);
2827 FSdither(dp, ca, ep, error_values->c, bitmask, n, n - 3);
2828 }
2829 *--yPa = ya;
2830 *--mPa = ma;
2831 *--cPa = ca;
2832 }
2833 }
2834 return;
2835 }
2836
2837 /* while printing on paper, we only use 3 -intensities */
2838 #define FSdither8503(inP, outa, outb, errP, Err, Bit, Offset, Element)\
2839 {\
2840 oldErr = Err;\
2841 Err = (*(errP + Element)\
2842 + ((Err * 7 + C) >> 4)\
2843 + ((int) *(inP + Element) << SHIFT));\
2844 if ((Err > THRESHOLDS) && (Err <= THRESHOLDM)) {\
2845 outa |= Bit;\
2846 Err -= MAXVALUES;\
2847 }\
2848 if (Err > THRESHOLDM) {\
2849 outb |= Bit;\
2850 Err -= MAXVALUEM;\
2851 }\
2852 *(errP + (Element + Offset)) += ((Err * 3 + C) >> 4);\
2853 *(errP + Element) = ((Err * 5 + oldErr + C) >> 4);\
2854 }
2855
2856 /* On ordinary paper, we'll only use 3 intensities with the hp850 */
2857 static void
FSDlinec3(int scan,int plane_size,struct error_val_field * error_values,byte * cPa,byte * mPa,byte * yPa,byte * cPb,byte * mPb,byte * yPb,int n,byte * dp,int * ep)2858 FSDlinec3(int scan, int plane_size,
2859 struct error_val_field *error_values,
2860 byte * cPa, byte * mPa, byte * yPa,
2861 byte * cPb, byte * mPb, byte * yPb,
2862 int n, byte * dp, int *ep)
2863 {
2864 if (scan == 0) { /* going_up */
2865 byte ca, ya, ma, cb, yb, mb, bitmask;
2866 int oldErr, i;
2867
2868 for (i = 0; i < plane_size; i++) {
2869 bitmask = 0x80;
2870 ca = ya = ma = cb = yb = mb = 0;
2871 for (ca = 0; bitmask != 0; bitmask >>= 1) {
2872 FSdither8503(dp, ca, cb, ep, error_values->c, bitmask, -n, n
2873 - 3);
2874 FSdither8503(dp, ma, mb, ep, error_values->m, bitmask, -n, n
2875 - 2);
2876 FSdither8503(dp, ya, yb, ep, error_values->y, bitmask, -n, n
2877 - 1);
2878 dp += n, ep += n;
2879 }
2880 *cPa++ = ca;
2881 *mPa++ = ma;
2882 *yPa++ = ya;
2883 *cPb++ = cb;
2884 *mPb++ = mb;
2885 *yPb++ = yb;
2886 }
2887 } else { /* going_down */
2888 byte ca, ya, ma, cb, yb, mb, bitmask;
2889 int oldErr, i;
2890
2891 for (i = 0; i < plane_size; i++) {
2892 bitmask = 0x01;
2893 ca = ya = ma = cb = yb = mb = 0;
2894 for (ca = 0; bitmask != 0; bitmask <<= 1) {
2895 dp -= n, ep -= n;
2896 FSdither8503(dp, ya, yb, ep, error_values->y, bitmask, n, n
2897 - 1);
2898 FSdither8503(dp, ma, mb, ep, error_values->m, bitmask, n, n
2899 - 2);
2900 FSdither8503(dp, ca, cb, ep, error_values->c, bitmask, n, n
2901 - 3);
2902 }
2903 *--yPa = ya;
2904 *--mPa = ma;
2905 *--cPa = ca;
2906 *--yPb = yb;
2907 *--mPb = mb;
2908 *--cPb = cb;
2909 }
2910 }
2911 return;
2912 }
2913
2914
2915 /* the hp850 knows about 4 different color intensities per color */
2916 #define FSdither8504(inP, outa, outb, errP, Err, Bit, Offset, Element)\
2917 {\
2918 oldErr = Err;\
2919 Err = (*(errP + Element)\
2920 + ((Err * 7 + C) >> 4)\
2921 + ((int) *(inP + Element) << SHIFT));\
2922 if ((Err > THRESHOLDS) && (Err <= THRESHOLDM)) {\
2923 outa |= Bit;\
2924 Err -= MAXVALUES;\
2925 }\
2926 if ((Err > THRESHOLDM) && (Err <= THRESHOLDL)) {\
2927 outb |= Bit;\
2928 Err -= MAXVALUEM;\
2929 }\
2930 if (Err > THRESHOLDL) {\
2931 outa |= Bit;\
2932 outb |= Bit;\
2933 Err -= MAXVALUEL;\
2934 }\
2935 *(errP + (Element + Offset)) += ((Err * 3 + C) >> 4);\
2936 *(errP + Element) = ((Err * 5 + oldErr + C) >> 4);\
2937 }
2938
2939 /* The hp850c knows about 4 intensity levels per color. Once more, we need
2940 an adapted dither algorythm */
2941 static void
FSDlinec4(int scan,int plane_size,struct error_val_field * error_values,byte * cPa,byte * mPa,byte * yPa,byte * cPb,byte * mPb,byte * yPb,int n,byte * dp,int * ep)2942 FSDlinec4(int scan, int plane_size,
2943 struct error_val_field *error_values,
2944 byte * cPa, byte * mPa, byte * yPa,
2945 byte * cPb, byte * mPb, byte * yPb,
2946 int n, byte * dp, int *ep)
2947 {
2948 if (scan == 0) { /* going_up */
2949 byte ca, ya, ma, cb, yb, mb, bitmask;
2950 int oldErr, i;
2951
2952 for (i = 0; i < plane_size; i++) {
2953 bitmask = 0x80;
2954 ca = ya = ma = cb = yb = mb = 0;
2955 for (ca = 0; bitmask != 0; bitmask >>= 1) {
2956 FSdither8504(dp, ca, cb, ep, error_values->c, bitmask, -n, n
2957 - 3);
2958 FSdither8504(dp, ma, mb, ep, error_values->m, bitmask, -n, n
2959 - 2);
2960 FSdither8504(dp, ya, yb, ep, error_values->y, bitmask, -n, n
2961 - 1);
2962 dp += n, ep += n;
2963 }
2964 *cPa++ = ca;
2965 *mPa++ = ma;
2966 *yPa++ = ya;
2967 *cPb++ = cb;
2968 *mPb++ = mb;
2969 *yPb++ = yb;
2970 }
2971 } else { /* going_down */
2972 byte ca, ya, ma, cb, yb, mb, bitmask;
2973 int oldErr, i;
2974
2975 for (i = 0; i < plane_size; i++) {
2976 bitmask = 0x01;
2977 ca = ya = ma = cb = yb = mb = 0;
2978 for (ca = 0; bitmask != 0; bitmask <<= 1) {
2979 dp -= n, ep -= n;
2980 FSdither8504(dp, ya, yb, ep, error_values->y, bitmask, n, n
2981 - 1);
2982 FSdither8504(dp, ma, mb, ep, error_values->m, bitmask, n, n
2983 - 2);
2984 FSdither8504(dp, ca, cb, ep, error_values->c, bitmask, n, n
2985 - 3);
2986 }
2987 *--yPa = ya;
2988 *--mPa = ma;
2989 *--cPa = ca;
2990 *--yPb = yb;
2991 *--mPb = mb;
2992 *--cPb = cb;
2993 }
2994 }
2995 return;
2996 }
2997
2998
2999 /* calculate the needed memory */
3000 static void
calculate_memory_size(gx_device_printer * pdev,struct misc_struct * misc_vars)3001 calculate_memory_size(gx_device_printer * pdev,
3002 struct misc_struct *misc_vars)
3003 {
3004 int xfac = cdj850->xscal ? 2 : 1;
3005
3006 misc_vars->line_size = gdev_prn_raster(pdev);
3007 misc_vars->line_size_c = misc_vars->line_size / xfac;
3008 misc_vars->line_size_words = (misc_vars->line_size + W - 1) / W;
3009 misc_vars->paper_size = gdev_pcl_paper_size((gx_device *) pdev);
3010 misc_vars->num_comps = pdev->color_info.num_components;
3011 misc_vars->bits_per_pixel = pdev->color_info.depth;
3012 misc_vars->storage_bpp = misc_vars->num_comps * 8;
3013 misc_vars->expanded_bpp = misc_vars->num_comps * 8;
3014 misc_vars->errbuff_size = 0;
3015 misc_vars->errbuff_size_c = 0;
3016
3017 misc_vars->plane_size = calc_buffsize(misc_vars->line_size, misc_vars->storage_bpp);
3018
3019 /* plane_size_c is dependedend on the bits used for
3020 dithering. Currently 2 bits are sufficient */
3021 misc_vars->plane_size_c = 2 * misc_vars->plane_size / xfac;
3022
3023 /* 4n extra values for line ends */
3024 /* might be wrong, see gdevcdj.c */
3025 misc_vars->errbuff_size =
3026 calc_buffsize((misc_vars->plane_size * misc_vars->expanded_bpp +
3027 misc_vars->num_comps * 4) * I, 1);
3028
3029 /* 4n extra values for line ends */
3030 misc_vars->errbuff_size_c =
3031 calc_buffsize((misc_vars->plane_size_c / 2 * misc_vars->expanded_bpp
3032 + misc_vars->num_comps * 4) * I, 1);
3033
3034 misc_vars->databuff_size =
3035 misc_vars->plane_size * misc_vars->storage_bpp;
3036
3037 misc_vars->databuff_size_c =
3038 misc_vars->plane_size_c / 2 * misc_vars->storage_bpp;
3039
3040
3041 misc_vars->outbuff_size = misc_vars->plane_size * 4;
3042
3043 misc_vars->storage_size_words = (((misc_vars->plane_size)
3044 * 2
3045 * misc_vars->num_comps)
3046 + misc_vars->databuff_size
3047 + misc_vars->errbuff_size
3048 + misc_vars->outbuff_size
3049 + ((misc_vars->plane_size_c)
3050 * 2
3051 * misc_vars->num_comps)
3052 + misc_vars->databuff_size_c
3053 + misc_vars->errbuff_size_c
3054 + (4 * misc_vars->plane_size_c))
3055 / W;
3056
3057 return;
3058 }
3059
3060
3061 /* Initialise the needed pointers */
3062 static void
init_data_structure(gx_device_printer * pdev,struct ptr_arrays * data_ptrs,struct misc_struct * misc_vars)3063 init_data_structure(gx_device_printer * pdev,
3064 struct ptr_arrays *data_ptrs,
3065 struct misc_struct *misc_vars)
3066 {
3067 int i;
3068 byte *p = (byte *) data_ptrs->storage;
3069
3070 misc_vars->scan = 0;
3071 misc_vars->cscan = 0;
3072 misc_vars->is_two_pass = 0;
3073
3074 /* the b/w pointer */
3075 data_ptrs->data[0] = data_ptrs->data[1] = data_ptrs->data[2] = p;
3076 data_ptrs->data[3] = p + misc_vars->databuff_size;
3077 /* Note: The output data will overwrite part of the input-data */
3078
3079 if (misc_vars->bits_per_pixel > 1) {
3080 p += misc_vars->databuff_size;
3081 }
3082 if (misc_vars->bits_per_pixel > 4) {
3083 data_ptrs->errors[0] = (int *)p + misc_vars->num_comps * 2;
3084 data_ptrs->errors[1] = data_ptrs->errors[0] + misc_vars->databuff_size;
3085 p += misc_vars->errbuff_size;
3086 }
3087 for (i = 0; i < misc_vars->num_comps; i++) {
3088 data_ptrs->plane_data[0][i] = data_ptrs->plane_data[2][i] = p;
3089 p += misc_vars->plane_size;
3090 }
3091 for (i = 0; i < misc_vars->num_comps; i++) {
3092 data_ptrs->plane_data[1][i] = p;
3093 data_ptrs->plane_data[3][i] = p + misc_vars->plane_size;
3094 p += misc_vars->plane_size;
3095 }
3096 data_ptrs->out_data = p;
3097 p += misc_vars->outbuff_size;
3098
3099 /* ---------------------------------------------------------
3100 now for the color pointers
3101 --------------------------------------------------------- */
3102
3103 data_ptrs->data_c[0] = data_ptrs->data_c[1] = data_ptrs->data_c[2] = p;
3104 data_ptrs->data_c[3] = p + misc_vars->databuff_size_c;
3105 /* Note: The output data will overwrite part of the input-data */
3106
3107 if (misc_vars->bits_per_pixel > 1) {
3108 p += misc_vars->databuff_size_c;
3109 }
3110 if (misc_vars->bits_per_pixel > 4) {
3111 data_ptrs->errors_c[0] = (int *)p + misc_vars->num_comps * 2;
3112 data_ptrs->errors_c[1] = data_ptrs->errors_c[0] + misc_vars->databuff_size_c;
3113 p += misc_vars->errbuff_size_c;
3114 }
3115 /* pointer for the lower bits of the output data */
3116 for (i = 0; i < misc_vars->num_comps; i++) {
3117 data_ptrs->plane_data_c[0][i] = data_ptrs->plane_data_c[2][i] = p;
3118 p += misc_vars->plane_size_c / 2;
3119 }
3120 for (i = 0; i < misc_vars->num_comps; i++) {
3121 data_ptrs->plane_data_c[1][i] = p;
3122 data_ptrs->plane_data_c[3][i] = p + misc_vars->plane_size_c / 2;
3123 p += misc_vars->plane_size_c / 2;
3124 }
3125
3126 /* pointer for the upper bits of the output data */
3127 for (i = 0; i < misc_vars->num_comps; i++) {
3128 data_ptrs->plane_data_c[0][i + 4] = data_ptrs->plane_data_c[2][i +
3129 4] = p;
3130 p += misc_vars->plane_size_c / 2;
3131 }
3132 for (i = 0; i < misc_vars->num_comps; i++) {
3133 data_ptrs->plane_data_c[1][i + 4] = p;
3134 data_ptrs->plane_data_c[3][i + 4] = p + misc_vars->plane_size_c / 2;
3135 p += misc_vars->plane_size_c / 2;
3136 }
3137
3138 for (i = 0; i < misc_vars->num_comps; i++) {
3139 data_ptrs->test_data[i] = p;
3140 p += misc_vars->plane_size_c / 2;
3141 }
3142
3143 /* Clear temp storage */
3144 memset(data_ptrs->storage, 0, misc_vars->storage_size_words * W);
3145
3146 return;
3147 } /* end init_data_structure */
3148
3149 /* Configure the printer and start Raster mode */
3150 static void
cdj850_start_raster_mode(gx_device_printer * pdev,int paper_size,FILE * prn_stream)3151 cdj850_start_raster_mode(gx_device_printer * pdev, int paper_size,
3152 FILE * prn_stream)
3153 {
3154 int xres, yres; /* x,y resolution for color planes */
3155 hp850_cmyk_init_t init;
3156
3157 init = hp850_cmyk_init;
3158 init.a[13] = cdj850->intensities; /* Intensity levels cyan */
3159 init.a[19] = cdj850->intensities; /* Intensity levels magenta */
3160 init.a[25] = cdj850->intensities; /* Intensity levels yellow */
3161
3162 /* black plane resolution */
3163 assign_dpi(cdj850->x_pixels_per_inch, init.a + 2);
3164 assign_dpi(cdj850->y_pixels_per_inch, init.a + 4);
3165 /* color plane resolution */
3166 xres = cdj850->x_pixels_per_inch / (cdj850->xscal + 1);
3167 yres = cdj850->y_pixels_per_inch / (cdj850->yscal + 1);
3168 /* cyan */
3169 assign_dpi(xres, init.a + 8);
3170 assign_dpi(yres, init.a + 10);
3171 /* magenta */
3172 assign_dpi(xres, init.a + 14);
3173 assign_dpi(yres, init.a + 16);
3174 /* yellow */
3175 assign_dpi(xres, init.a + 20);
3176 assign_dpi(yres, init.a + 22);
3177
3178 fputs("\033*rbC", prn_stream); /* End raster graphics */
3179 fputs("\033E", prn_stream); /* Reset */
3180 /* Page size, orientation, top margin & perforation skip */
3181 fprintf(prn_stream, "\033&l%daolE", paper_size);
3182
3183 /* Print Quality, -1 = draft, 0 = normal, 1 = presentation */
3184 fprintf(prn_stream, "\033*o%dM", cdj850->quality);
3185 /* Media Type,0 = plain paper, 1 = bond paper, 2 = special
3186 paper, 3 = glossy film, 4 = transparency film */
3187 fprintf(prn_stream, "\033&l%dM", cdj850->papertype);
3188
3189 /* Move to top left of printed area */
3190 fprintf(prn_stream, "\033*p%dY", (int)(600 * DOFFSET));
3191
3192 /* This will start and configure the raster-mode */
3193 fprintf(prn_stream, "\033*g%dW", (int)sizeof(init.a)); /* The new configure
3194 raster data comand */
3195 fwrite(init.a, sizeof(byte), sizeof(init.a),
3196 prn_stream); /* Transmit config
3197 data */
3198 /* From now on, all escape commands start with \033*b, so we
3199 * combine them (if the printer supports this). */
3200 fputs("\033*b", prn_stream);
3201 /* Set compression if the mode has been defined. */
3202 if (cdj850->compression)
3203 fprintf(prn_stream, "%dm", cdj850->compression);
3204
3205 return;
3206 } /* end configure raster-mode */
3207
3208 /* Configure the printer and start Raster mode */
3209 static void
cdj880_start_raster_mode(gx_device_printer * pdev,int paper_size,FILE * prn_stream)3210 cdj880_start_raster_mode(gx_device_printer * pdev, int paper_size,
3211 FILE * prn_stream)
3212 {
3213 int xres, yres; /* x,y resolution for color planes */
3214 hp850_cmyk_init_t init;
3215
3216 init = hp850_cmyk_init;
3217 init.a[13] = cdj850->intensities; /* Intensity levels cyan */
3218 init.a[19] = cdj850->intensities; /* Intensity levels magenta */
3219 init.a[25] = cdj850->intensities; /* Intensity levels yellow */
3220
3221 /* black plane resolution */
3222 assign_dpi(cdj850->x_pixels_per_inch, init.a + 2);
3223 assign_dpi(cdj850->y_pixels_per_inch, init.a + 4);
3224 /* color plane resolution */
3225 xres = cdj850->x_pixels_per_inch / (cdj850->xscal + 1);
3226 yres = cdj850->y_pixels_per_inch / (cdj850->yscal + 1);
3227 /* cyan */
3228 assign_dpi(xres, init.a + 8);
3229 assign_dpi(yres, init.a + 10);
3230 /* magenta */
3231 assign_dpi(xres, init.a + 14);
3232 assign_dpi(yres, init.a + 16);
3233 /* yellow */
3234 assign_dpi(xres, init.a + 20);
3235 assign_dpi(yres, init.a + 22);
3236
3237 fputs("\033*rbC", prn_stream); /* End raster graphics */
3238 fputs("\033E", prn_stream); /* Reset */
3239
3240 /* Set the language to PCL3 enhanced, DeskJet 880 style */
3241 fprintf(prn_stream, "\033%%-12345X@PJL ENTER LANGUAGE=PCL3GUI\n");
3242
3243 /* Page size, orientation, top margin & perforation skip */
3244 fprintf(prn_stream, "\033&l%daolE", paper_size);
3245
3246 /* Print Quality, -1 = draft, 0 = normal, 1 = presentation */
3247 fprintf(prn_stream, "\033*o%dM", cdj850->quality);
3248 /* Media Type,0 = plain paper, 1 = bond paper, 2 = special
3249 paper, 3 = glossy film, 4 = transparency film */
3250 fprintf(prn_stream, "\033&l%dM", cdj850->papertype);
3251
3252 /* Move to top left of printed area */
3253 fprintf(prn_stream, "\033*p%dY", (int)(600 * DOFFSET));
3254
3255 /* This will configure the raster-mode */
3256 fprintf(prn_stream, "\033*g%dW", (int)sizeof(init.a)); /* The new configure
3257 raster data comand */
3258 fwrite(init.a, sizeof(byte), sizeof(init.a),
3259 prn_stream); /* Transmit config
3260 data */
3261
3262 /* Start the raster graphics mode. The 880C needs this explicit command.
3263 */
3264 fputs("\033*r1A", prn_stream);
3265
3266 /* From now on, all escape commands start with \033*b, so we
3267 * combine them (if the printer supports this). */
3268 /* fputs("\033*b", prn_stream);*/
3269
3270 /* Set compression if the mode has been defined. */
3271 /* if (cdj850->compression)*/
3272 fprintf(prn_stream, "\033*b%dm", cdj850->compression);
3273
3274 return;
3275 } /* end configure raster-mode */
3276
3277 /* Start Raster mode for HP2200 */
3278 static void
chp2200_start_raster_mode(gx_device_printer * pdev,int paper_size,FILE * prn_stream)3279 chp2200_start_raster_mode(gx_device_printer * pdev, int paper_size,
3280 FILE * prn_stream)
3281 {
3282 byte CRD_SeqC[] = {0x1b, 0x2a, 0x67, 0x31, 0x32, 0x57, 0x06, 0x07, 0x00, 0x01,
3283 /* Esc * |g |# of bytes |W |frmt |SP |# of cmpnts*/
3284 0x00, 0x00, 0x00, 0x00, 0x0a, 0x01, 0x20, 0x01};
3285 /* |Horz Res |Vert Rez |compr|orien|bits |planes*/
3286
3287 /* x,y resolution for color planes, assume x=y */
3288 int xres = cdj850->x_pixels_per_inch;
3289 int yres = cdj850->y_pixels_per_inch;
3290 int width_in_pixels = cdj850->width;
3291
3292 /* Exit from any previous language */
3293 fprintf(prn_stream, "\033%%-12345X");
3294
3295 /* send @PJL JOB NAME before entering the language
3296 * this will be matched by a @PJL EOJ after leaving the language
3297 */
3298 fprintf(prn_stream, "@PJL JOB NAME=\"ghostscript job\"\012");
3299
3300 /* Set timeout value */
3301 fprintf(prn_stream, "@PJL SET TIMEOUT=90\n");
3302
3303 /* Set the language to PCL3 enhanced */
3304 fprintf(prn_stream, "@PJL ENTER LANGUAGE=PCL3GUI\n");
3305
3306 /* Paper source: assume AutoFeed */
3307 fprintf(prn_stream, "\033&l7H");
3308
3309 /* Media Type,0 = plain paper, 1 = bond paper, 2 = special
3310 paper, 3 = glossy film, 4 = transparency film */
3311 fprintf(prn_stream, "\033&l%dM", cdj850->papertype);
3312
3313 /* Print Quality, -1 = draft, 0 = normal, 1 = presentation */
3314 fprintf(prn_stream, "\033*o%dM", cdj850->quality);
3315
3316 /* Raster Width */
3317 fprintf(prn_stream, "\033*r%dS", width_in_pixels);
3318
3319 /* Page size */
3320 fprintf(prn_stream, "\033&l%dA", paper_size);
3321
3322 /* Load paper */
3323 fprintf(prn_stream, "\033&l-2H");
3324
3325 /* Unit of Measure*/
3326 fprintf(prn_stream, "\033&u%dD", (int)xres);
3327
3328 /* Move to top of form */
3329 fprintf(prn_stream, "\033*p%dY", (int)(yres * DOFFSET));
3330
3331 /* This will configure the raster-mode */
3332 CRD_SeqC[10] = HIBYTE(xres);
3333 CRD_SeqC[11] = LOBYTE(xres);
3334 CRD_SeqC[12] = HIBYTE(yres);
3335 CRD_SeqC[13] = LOBYTE(yres);
3336 fwrite(CRD_SeqC, sizeof(byte), sizeof(CRD_SeqC), prn_stream);
3337
3338 fputs("\033*r1A", prn_stream);
3339
3340 return;
3341 } /* end configure raster-mode */
3342
3343 /* Start Raster mode for DNJ500 */
3344 static void
cdnj500_start_raster_mode(gx_device_printer * pdev,int paper_size,FILE * prn_stream)3345 cdnj500_start_raster_mode(gx_device_printer * pdev, int paper_size,
3346 FILE * prn_stream)
3347 {
3348 /* x,y resolution for color planes, assume x=y */
3349 int xres = cdj850->x_pixels_per_inch;
3350 int yres = cdj850->y_pixels_per_inch;
3351 float x = pdev->width / pdev->x_pixels_per_inch * 10;
3352 float y = pdev->height / pdev->y_pixels_per_inch * 10;
3353
3354 /* Exit from any previous language */
3355 fprintf(prn_stream, "\033%%-12345X");
3356
3357 /* send @PJL JOB NAME before entering the language
3358 * this will be matched by a @PJL EOJ after leaving the language
3359 */
3360 fprintf(prn_stream, "@PJL JOB NAME=\"GS %.2fx%.2f\" \n", x * 2.54, y * 2.54);
3361
3362 /* Color use */
3363 fprintf(prn_stream, "@PJL SET RENDERMODE = COLOR \n");
3364
3365 /* Color correction */
3366 fprintf(prn_stream, "@PJL SET COLORSPACE = SRGB \n");
3367
3368 /* Predef qual set (TODO: need add options) */
3369 if (cdj850->quality == DRAFT) {
3370 fprintf(prn_stream, "@PJL SET RENDERINTENT = PERCEPTUAL \n");
3371 fprintf(prn_stream, "@PJL SET RET = ON \n");
3372 fprintf(prn_stream, "@PJL SET MAXDETAIL = OFF \n");
3373 } else if (cdj850->quality == NORMAL) {
3374 fprintf(prn_stream, "@PJL SET RENDERINTENT = PERCEPTUAL \n");
3375 fprintf(prn_stream, "@PJL SET RET = ON \n");
3376 fprintf(prn_stream, "@PJL SET MAXDETAIL = ON \n");
3377 } else { /* quality == PRESENTATION */
3378 fprintf(prn_stream, "@PJL SET RENDERINTENT = PERCEPTUAL \n");
3379 fprintf(prn_stream, "@PJL SET RET = OFF \n");
3380 fprintf(prn_stream, "@PJL SET MAXDETAIL = ON \n");
3381 }
3382
3383 /* Set the language to PCL3 enhanced */
3384 fprintf(prn_stream, "@PJL ENTER LANGUAGE=PCL3GUI \n");
3385
3386 /* Print Quality, -1 = draft, 0 = normal, 1 = presentation */
3387 fprintf(prn_stream, "\033*o%dM", cdj850->quality);
3388
3389 /* Unit of Measure*/
3390 fprintf(prn_stream, "\033&u%dD", (int)xres);
3391
3392 return;
3393 } /* end configure raster-mode */
3394
3395 static int near
cdj_put_param_int(gs_param_list * plist,gs_param_name pname,int * pvalue,int minval,int maxval,int ecode)3396 cdj_put_param_int(gs_param_list * plist, gs_param_name pname, int *pvalue,
3397 int minval, int maxval, int ecode)
3398 {
3399 int code, value;
3400
3401 switch (code = param_read_int(plist, pname, &value)) {
3402 default:
3403 return code;
3404 case 1:
3405 return ecode;
3406 case 0:
3407 if (value < minval || value > maxval)
3408 param_signal_error(plist, pname, gs_error_rangecheck);
3409 *pvalue = value;
3410 return (ecode < 0 ? ecode : 1);
3411 }
3412 }
3413
3414 static int near
cdj_put_param_float(gs_param_list * plist,gs_param_name pname,float * pvalue,float minval,float maxval,int ecode)3415 cdj_put_param_float(gs_param_list * plist, gs_param_name pname, float *pvalue,
3416 float minval, float maxval, int ecode)
3417 {
3418 int code;
3419 float value;
3420
3421 switch (code = param_read_float(plist, pname, &value)) {
3422 default:
3423 return code;
3424 case 1:
3425 return ecode;
3426 case 0:
3427 if (value < minval || value > maxval)
3428 param_signal_error(plist, pname, gs_error_rangecheck);
3429 *pvalue = value;
3430 return (ecode < 0 ? ecode : 1);
3431 }
3432 }
3433
3434 static int
cdj_set_bpp(gx_device * pdev,int bpp,int ccomps)3435 cdj_set_bpp(gx_device * pdev, int bpp, int ccomps)
3436 {
3437 gx_device_color_info *ci = &pdev->color_info;
3438
3439 if (ccomps && bpp == 0) {
3440 if (cprn_device->cmyk) {
3441 switch (ccomps) {
3442 default:
3443 return gs_error_rangecheck;
3444 /*NOTREACHED */
3445 break;
3446
3447 case 1:
3448 bpp = 1;
3449 break;
3450
3451 case 3:
3452 bpp = 24;
3453 break;
3454
3455 case 4:
3456 switch (ci->depth) {
3457 case 8:
3458 case 16:
3459 case 24:
3460 case 32:
3461 break;
3462
3463 default:
3464 bpp = cprn_device->default_depth;
3465 break;
3466 }
3467 break;
3468 }
3469 }
3470 }
3471 if (bpp == 0) {
3472 bpp = ci->depth; /* Use the current setting. */
3473 }
3474 if (cprn_device->cmyk < 0) {
3475
3476 /* Reset procedures because we may have been in another mode. */
3477
3478 dev_proc(pdev, map_cmyk_color) = gdev_cmyk_map_cmyk_color;
3479 dev_proc(pdev, map_rgb_color) = NULL;
3480 dev_proc(pdev, map_color_rgb) = gdev_cmyk_map_color_rgb;
3481
3482 if (pdev->is_open)
3483 gs_closedevice(pdev);
3484 }
3485 /* Check for valid bpp values */
3486
3487 switch (bpp) {
3488 case 16:
3489 case 32:
3490 if (cprn_device->cmyk && ccomps && ccomps != 4)
3491 goto bppe;
3492 break;
3493
3494 case 24:
3495 if (!cprn_device->cmyk || ccomps == 0 || ccomps == 4) {
3496 break;
3497 } else if (ccomps == 1) {
3498 goto bppe;
3499 } else {
3500
3501 /* 3 components 24 bpp printing for CMYK device. */
3502
3503 cprn_device->cmyk = -1;
3504 }
3505 break;
3506
3507 case 8:
3508 if (cprn_device->cmyk) {
3509 if (ccomps) {
3510 if (ccomps == 3) {
3511 cprn_device->cmyk = -1;
3512 bpp = 3;
3513 } else if (ccomps != 1 && ccomps != 4) {
3514 goto bppe;
3515 }
3516 }
3517 if (ccomps != 1)
3518 break;
3519 } else {
3520 break;
3521 }
3522
3523 case 1:
3524 if (ccomps != 1)
3525 goto bppe;
3526
3527 if (cprn_device->cmyk && bpp != pdev->color_info.depth) {
3528 dev_proc(pdev, map_cmyk_color) = NULL;
3529 dev_proc(pdev, map_rgb_color) = gdev_cmyk_map_rgb_color;
3530
3531 if (pdev->is_open) {
3532 gs_closedevice(pdev);
3533 }
3534 }
3535 break;
3536
3537 case 3:
3538 if (!cprn_device->cmyk) {
3539 break;
3540 }
3541 default:
3542 bppe:return gs_error_rangecheck;
3543 }
3544
3545
3546 if (cprn_device->cmyk == -1) {
3547 dev_proc(pdev, map_cmyk_color) = NULL;
3548 dev_proc(pdev, map_rgb_color) = gdev_pcl_map_rgb_color;
3549 dev_proc(pdev, map_color_rgb) = gdev_pcl_map_color_rgb;
3550
3551 if (pdev->is_open) {
3552 gs_closedevice(pdev);
3553 }
3554 }
3555 switch (ccomps) {
3556 case 0:
3557 break;
3558
3559 case 1:
3560 if (bpp != 1 && bpp != 8)
3561 goto cce;
3562 break;
3563
3564 case 4:
3565 if (cprn_device->cmyk) {
3566 if (bpp >= 8)
3567 break;
3568 }
3569 case 3:
3570 if (bpp == 1 || bpp == 3 || bpp == 8 || bpp == 16
3571 || bpp == 24 || bpp == 32) {
3572 break;
3573 }
3574 cce: default:
3575 return gs_error_rangecheck;
3576 }
3577
3578 if (cprn_device->cmyk) {
3579 if (cprn_device->cmyk > 0) {
3580 ci->num_components = ccomps ? ccomps : (bpp < 8 ? 1 : 4);
3581 } else {
3582 ci->num_components = ccomps ? ccomps : (bpp < 8 ? 1 : 3);
3583 }
3584 if (bpp != 1 && ci->num_components == 1) { /* We do dithered grays. */
3585 bpp = bpp < 8 ? 8 : bpp;
3586 }
3587 ci->max_color = (1 << (bpp >> 2)) - 1;
3588 ci->max_gray = (bpp >= 8 ? 255 : 1);
3589
3590 if (ci->num_components == 1) {
3591 ci->dither_grays = (bpp >= 8 ? 5 : 2);
3592 ci->dither_colors = (bpp >= 8 ? 5 : bpp > 1 ? 2 : 0);
3593 } else {
3594 ci->dither_grays = (bpp > 8 ? 5 : 2);
3595 ci->dither_colors = (bpp > 8 ? 5 : bpp > 1 ? 2 : 0);
3596 }
3597 } else {
3598 ci->num_components = (bpp == 1 || bpp == 8 ? 1 : 3);
3599 ci->max_color = (bpp >= 8 ? 255 : bpp > 1 ? 1 : 0);
3600 ci->max_gray = (bpp >= 8 ? 255 : 1);
3601 ci->dither_grays = (bpp >= 8 ? 5 : 2);
3602 ci->dither_colors = (bpp >= 8 ? 5 : bpp > 1 ? 2 : 0);
3603 }
3604
3605 ci->depth = ((bpp > 1) && (bpp < 8) ? 8 : bpp);
3606
3607 return 0;
3608 }
3609
3610 /*
3611 * Map a CMYK color to a color index. We just use depth / 4 bits per color
3612 * to produce the color index.
3613 *
3614 * Important note: CMYK values are stored in the order K, C, M, Y because of
3615 * the way the HP drivers work.
3616 *
3617 */
3618
3619 #define gx_color_value_to_bits(cv, b) \
3620 ((cv) >> (gx_color_value_bits - (b)))
3621 #define gx_bits_to_color_value(cv, b) \
3622 ((cv) << (gx_color_value_bits - (b)))
3623
3624 #define gx_cmyk_value_bits(c, m, y, k, b) \
3625 ((gx_color_value_to_bits((k), (b)) << (3 * (b))) | \
3626 (gx_color_value_to_bits((c), (b)) << (2 * (b))) | \
3627 (gx_color_value_to_bits((m), (b)) << (b)) | \
3628 (gx_color_value_to_bits((y), (b))))
3629
3630 #define gx_value_cmyk_bits(v, c, m, y, k, b) \
3631 (k) = gx_bits_to_color_value(((v) >> (3 * (b))) & ((1 << (b)) - 1), (b)), \
3632 (c) = gx_bits_to_color_value(((v) >> (2 * (b))) & ((1 << (b)) - 1), (b)), \
3633 (m) = gx_bits_to_color_value(((v) >> (b)) & ((1 << (b)) - 1), (b)), \
3634 (y) = gx_bits_to_color_value((v) & ((1 << (b)) - 1), (b))
3635
3636 static gx_color_index
gdev_cmyk_map_cmyk_color(gx_device * pdev,const gx_color_value cv[])3637 gdev_cmyk_map_cmyk_color(gx_device * pdev,
3638 const gx_color_value cv[])
3639 {
3640
3641 gx_color_index color;
3642 gx_color_value cyan, magenta, yellow, black;
3643
3644 cyan = cv[0]; magenta = cv[1]; yellow = cv[2]; black = cv[3];
3645 switch (pdev->color_info.depth) {
3646 case 1:
3647 color = (cyan | magenta | yellow | black) > gx_max_color_value / 2 ?
3648 (gx_color_index) 1 : (gx_color_index) 0;
3649 break;
3650
3651 default:{
3652 int nbits = pdev->color_info.depth;
3653
3654 if (cyan == magenta && magenta == yellow) {
3655 /* Convert CMYK to gray -- Red Book 6.2.2 */
3656 float bpart = ((float)cyan) * (lum_red_weight / 100.) +
3657 ((float)magenta) * (lum_green_weight / 100.) +
3658 ((float)yellow) * (lum_blue_weight / 100.) +
3659 (float)black;
3660
3661 cyan = magenta = yellow = (gx_color_index) 0;
3662 black = (gx_color_index) (bpart > gx_max_color_value ?
3663 gx_max_color_value : bpart);
3664 }
3665 color = gx_cmyk_value_bits(cyan, magenta, yellow, black,
3666 nbits >> 2);
3667 }
3668 }
3669
3670 return color;
3671 }
3672
3673 /* Mapping of RGB colors to gray values. */
3674
3675 static gx_color_index
gdev_cmyk_map_rgb_color(gx_device * pdev,const gx_color_value cv[])3676 gdev_cmyk_map_rgb_color(gx_device * pdev, const gx_color_value cv[])
3677 {
3678 gx_color_value r, g, b;
3679
3680 r = cv[0]; g = cv[1]; b = cv[2];
3681 if (gx_color_value_to_byte(r & g & b) == 0xff) {
3682 return (gx_color_index) 0; /* White */
3683 } else {
3684 gx_color_value c = gx_max_color_value - r;
3685 gx_color_value m = gx_max_color_value - g;
3686 gx_color_value y = gx_max_color_value - b;
3687
3688 switch (pdev->color_info.depth) {
3689 case 1:
3690 return (c | m | y) > gx_max_color_value / 2 ?
3691 (gx_color_index) 1 : (gx_color_index) 0;
3692 /*NOTREACHED */
3693 break;
3694
3695 case 8:
3696 return ((ulong) c * lum_red_weight * 10
3697 + (ulong) m * lum_green_weight * 10
3698 + (ulong) y * lum_blue_weight * 10)
3699 >> (gx_color_value_bits + 2);
3700 /*NOTREACHED */
3701 break;
3702 }
3703 }
3704
3705 return (gx_color_index) 0; /* This should never happen. */
3706 }
3707
3708 /* Mapping of CMYK colors. */
3709 static int
gdev_cmyk_map_color_rgb(gx_device * pdev,gx_color_index color,gx_color_value prgb[3])3710 gdev_cmyk_map_color_rgb(gx_device * pdev, gx_color_index color,
3711 gx_color_value prgb[3])
3712 {
3713 switch (pdev->color_info.depth) {
3714 case 1:
3715 prgb[0] = prgb[1] = prgb[2] = gx_max_color_value * (1 - color);
3716 break;
3717
3718 case 8:
3719 if (pdev->color_info.num_components == 1) {
3720 gx_color_value value = (gx_color_value) color ^ 0xff;
3721
3722 prgb[0] = prgb[1] = prgb[2] = (value << 8) + value;
3723
3724 break;
3725 }
3726 default:{
3727 unsigned long bcyan, bmagenta, byellow, black;
3728 int nbits = pdev->color_info.depth;
3729
3730 gx_value_cmyk_bits(color, bcyan, bmagenta, byellow, black,
3731 nbits >> 2);
3732
3733 #ifdef USE_ADOBE_CMYK_RGB
3734
3735 /* R = 1.0 - min(1.0, C + K), etc. */
3736
3737 bcyan += black, bmagenta += black, byellow += black;
3738 prgb[0] = (bcyan > gx_max_color_value ? (gx_color_value) 0 :
3739 gx_max_color_value - bcyan);
3740 prgb[1] = (bmagenta > gx_max_color_value ? (gx_color_value) 0 :
3741 gx_max_color_value - bmagenta);
3742 prgb[2] = (byellow > gx_max_color_value ? (gx_color_value) 0 :
3743 gx_max_color_value - byellow);
3744
3745 #else
3746
3747 /* R = (1.0 - C) * (1.0 - K), etc. */
3748
3749 prgb[0] = (gx_color_value)
3750 ((ulong) (gx_max_color_value - bcyan) *
3751 (gx_max_color_value - black) / gx_max_color_value);
3752 prgb[1] = (gx_color_value)
3753 ((ulong) (gx_max_color_value - bmagenta) *
3754 (gx_max_color_value - black) / gx_max_color_value);
3755 prgb[2] = (gx_color_value)
3756 ((ulong) (gx_max_color_value - byellow) *
3757 (gx_max_color_value - black) / gx_max_color_value);
3758
3759 #endif
3760
3761 }
3762 }
3763
3764 return 0;
3765 }
3766
3767 static gx_color_index
gdev_pcl_map_rgb_color(gx_device * pdev,const gx_color_value cv[])3768 gdev_pcl_map_rgb_color(gx_device * pdev, const gx_color_value cv[])
3769 {
3770 gx_color_value r, g, b;
3771
3772 r = cv[0]; g = cv[1]; b = cv[2];
3773 if (gx_color_value_to_byte(r & g & b) == 0xff)
3774 return (gx_color_index) 0; /* white */
3775 else {
3776 gx_color_value c = gx_max_color_value - r;
3777 gx_color_value m = gx_max_color_value - g;
3778 gx_color_value y = gx_max_color_value - b;
3779
3780 switch (pdev->color_info.depth) {
3781 case 1:
3782 return ((c | m | y) > gx_max_color_value / 2 ?
3783 (gx_color_index) 1 : (gx_color_index) 0);
3784 case 8:
3785 if (pdev->color_info.num_components >= 3)
3786 #define gx_color_value_to_1bit(cv) ((cv) >> (gx_color_value_bits - 1))
3787 return (gx_color_value_to_1bit(c) +
3788 (gx_color_value_to_1bit(m) << 1) +
3789 (gx_color_value_to_1bit(y) << 2));
3790 else
3791 #define red_weight 306
3792 #define green_weight 601
3793 #define blue_weight 117
3794 return ((((ulong) c * red_weight +
3795 (ulong) m * green_weight +
3796 (ulong) y * blue_weight)
3797 >> (gx_color_value_bits + 2)));
3798 case 16:
3799 #define gx_color_value_to_5bits(cv) ((cv) >> (gx_color_value_bits - 5))
3800 #define gx_color_value_to_6bits(cv) ((cv) >> (gx_color_value_bits - 6))
3801 return (gx_color_value_to_5bits(y) +
3802 (gx_color_value_to_6bits(m) << 5) +
3803 (gx_color_value_to_5bits(c) << 11));
3804 case 24:
3805 return (gx_color_value_to_byte(y) +
3806 (gx_color_value_to_byte(m) << 8) +
3807 ((ulong) gx_color_value_to_byte(c) << 16));
3808 case 32:
3809 {
3810 return ((c == m && c == y) ? ((ulong)
3811 gx_color_value_to_byte(c) << 24)
3812 : (gx_color_value_to_byte(y) +
3813 (gx_color_value_to_byte(m) << 8) +
3814 ((ulong) gx_color_value_to_byte(c) << 16)));
3815 }
3816 }
3817 }
3818 return (gx_color_index) 0; /* This never happens */
3819 }
3820
3821 /* Map a color index to a r-g-b color. */
3822 static int
gdev_pcl_map_color_rgb(gx_device * pdev,gx_color_index color,gx_color_value prgb[3])3823 gdev_pcl_map_color_rgb(gx_device * pdev, gx_color_index color,
3824 gx_color_value prgb[3])
3825 {
3826 /* For the moment, we simply ignore any black correction */
3827 switch (pdev->color_info.depth) {
3828 case 1:
3829 prgb[0] = prgb[1] = prgb[2] = -((gx_color_value) color ^ 1);
3830 break;
3831 case 8:
3832 if (pdev->color_info.num_components >= 3) {
3833 gx_color_value c = (gx_color_value) color ^ 7;
3834
3835 prgb[0] = -(c & 1);
3836 prgb[1] = -((c >> 1) & 1);
3837 prgb[2] = -(c >> 2);
3838 } else {
3839 gx_color_value value = (gx_color_value) color ^ 0xff;
3840
3841 prgb[0] = prgb[1] = prgb[2] = (value << 8) + value;
3842 }
3843 break;
3844 case 16:
3845 {
3846 gx_color_value c = (gx_color_value) color ^ 0xffff;
3847 ushort value = c >> 11;
3848
3849 prgb[0] = ((value << 11) + (value << 6) + (value << 1) +
3850 (value >> 4)) >> (16 - gx_color_value_bits);
3851 value = (c >> 6) & 0x3f;
3852 prgb[1] = ((value << 10) + (value << 4) + (value >> 2))
3853 >> (16 - gx_color_value_bits);
3854 value = c & 0x1f;
3855 prgb[2] = ((value << 11) + (value << 6) + (value << 1) +
3856 (value >> 4)) >> (16 - gx_color_value_bits);
3857 }
3858 break;
3859 case 24:
3860 {
3861 gx_color_value c = (gx_color_value) color ^ 0xffffff;
3862
3863 prgb[0] = gx_color_value_from_byte(c >> 16);
3864 prgb[1] = gx_color_value_from_byte((c >> 8) & 0xff);
3865 prgb[2] = gx_color_value_from_byte(c & 0xff);
3866 }
3867 break;
3868 case 32:
3869 #define gx_maxcol gx_color_value_from_byte(gx_color_value_to_byte(gx_max_color_value))
3870 {
3871 gx_color_value w = gx_maxcol - gx_color_value_from_byte(color >> 24);
3872
3873 prgb[0] = w - gx_color_value_from_byte((color >> 16) & 0xff);
3874 prgb[1] = w - gx_color_value_from_byte((color >> 8) & 0xff);
3875 prgb[2] = w - gx_color_value_from_byte(color & 0xff);
3876 }
3877 break;
3878 }
3879 return 0;
3880 }
3881
3882 /* new_bpp == save_bpp or new_bpp == 0 means don't change bpp.
3883 ccomps == 0 means don't change number of color comps.
3884 If new_bpp != 0, it must be the value of the BitsPerPixel element of
3885 the plist; real_bpp may differ from new_bpp.
3886 */
3887 static int
cdj_put_param_bpp(gx_device * pdev,gs_param_list * plist,int new_bpp,int real_bpp,int ccomps)3888 cdj_put_param_bpp(gx_device * pdev, gs_param_list * plist, int new_bpp,
3889 int real_bpp, int ccomps)
3890 {
3891 if (new_bpp == 0 && ccomps == 0)
3892 return gdev_prn_put_params(pdev, plist);
3893 else {
3894 gx_device_color_info save_info;
3895 int save_bpp;
3896 int code;
3897
3898 save_info = pdev->color_info;
3899 save_bpp = save_info.depth;
3900 #define save_ccomps save_info.num_components
3901 if (save_bpp == 8 && save_ccomps == 3 && !cprn_device->cmyk)
3902 save_bpp = 3;
3903 code = cdj_set_bpp(pdev, real_bpp, ccomps);
3904 if (code < 0) {
3905 param_signal_error(plist, "BitsPerPixel", code);
3906 param_signal_error(plist, "ProcessColorModel", code);
3907 return code;
3908 }
3909 pdev->color_info.depth = new_bpp; /* cdj_set_bpp maps 3/6 to 8 */
3910 code = gdev_prn_put_params(pdev, plist);
3911 if (code < 0) {
3912 cdj_set_bpp(pdev, save_bpp, save_ccomps);
3913 return code;
3914 }
3915 cdj_set_bpp(pdev, real_bpp, ccomps); /* reset depth if needed */
3916 if ((cdj850->color_info.depth != save_bpp ||
3917 (ccomps != 0 && ccomps != save_ccomps))
3918 && pdev->is_open)
3919 return gs_closedevice(pdev);
3920 return 0;
3921 #undef save_ccomps
3922 }
3923 }
3924
3925 /* the following code was in the original driver but is unused
3926
3927 * static int
3928 * x_mul_div (int a, int b, int c)
3929 * {
3930 * int result;
3931 *
3932 * result = (int) ((a * b) / c) ;
3933 * return result;
3934 * }
3935 *
3936 * static void
3937 * save_color_data(int size,
3938 * byte * current,
3939 * byte * saved)
3940 * {
3941 * int i;
3942 * for (i=0;i<size;i++){
3943 * *saved++ = *current++;
3944 * }
3945 * return;
3946 * }
3947 *
3948 * static int
3949 * test_scan (int size,
3950 * byte * current,
3951 * byte * last,
3952 * byte * control)
3953 * {
3954 * int error = 0;
3955 * int i;
3956 *
3957 * for (i=0;i<size;i++){
3958 * if (*control != *last){
3959 * error = 1;
3960 * }
3961 * *control = *current;
3962 *
3963 * control++;
3964 * last++;
3965 * current++;
3966 * }
3967 * return error;
3968 * }
3969 *
3970 * * Transform from cmy into hsv
3971 * static void
3972 * cmy2hsv(int *c, int *m, int *y, int *h, int *s, int *v)
3973 * {
3974 * int hue;
3975 * int r, g, b;
3976 * int r1, g1, b1;
3977 * int maxValue, minValue, diff;
3978 *
3979 * r = 255 - *c;
3980 * g = 255 - *m;
3981 * b = 255 - *y;
3982 *
3983 * maxValue = max(r, max(g,b));
3984 * minValue = min(r,min(g,b));
3985 * diff = maxValue - minValue;
3986 * *v = maxValue;
3987 *
3988 * if (maxValue != 0)
3989 * *s = x_mul_div(diff,255,maxValue);
3990 * else
3991 * *s = 0;
3992 *
3993 * if (*s == 0)
3994 * {
3995 * hue = 0;
3996 * }
3997 * else
3998 * {
3999 * r1 = x_mul_div(maxValue - r,255,diff);
4000 * g1 = x_mul_div(maxValue - g,255,diff);
4001 * b1 = x_mul_div(maxValue - b,255,diff);
4002 *
4003 * if (r == maxValue)
4004 * hue = b1 - g1;
4005 * else if (g == maxValue)
4006 * hue = 510 + r1 - b1;
4007 * else
4008 * hue = 1020 + g1 - r1;
4009 *
4010 * if (hue < 0)
4011 * hue += 1530;
4012 * }
4013 *
4014 * *h = (hue + 3) / 6;
4015 *
4016 * return;
4017 * }
4018 * end of unused code */
4019
4020
4021 /************************ the routines for the cdj1600 printer ***************/
4022
4023 /* Configure the printer and start Raster mode */
4024 static void
cdj1600_start_raster_mode(gx_device_printer * pdev,int paper_size,FILE * prn_stream)4025 cdj1600_start_raster_mode(gx_device_printer * pdev, int paper_size,
4026 FILE * prn_stream)
4027 {
4028 uint raster_width = pdev->width -
4029 pdev->x_pixels_per_inch * (dev_l_margin(pdev) + dev_r_margin(pdev));
4030
4031 /* switch to PCL control language */
4032 fputs("\033%-12345X@PJL enter language = PCL\n", prn_stream);
4033
4034 fputs("\033*rbC", prn_stream); /* End raster graphics */
4035 fputs("\033E", prn_stream); /* Reset */
4036
4037 /* resolution */
4038 fprintf(prn_stream, "\033*t%dR", (int)cdj850->x_pixels_per_inch);
4039
4040 /* Page size, orientation, top margin & perforation skip */
4041 fprintf(prn_stream, "\033&l%daolE", paper_size);
4042
4043 /* no negative motion */
4044 fputs("\033&a1N", prn_stream);
4045
4046 /* Print Quality, -1 = draft, 0 = normal, 1 = presentation */
4047 fprintf(prn_stream, "\033*o%dQ", cdj850->quality);
4048
4049 /* Media Type,0 = plain paper, 1 = bond paper, 2 = special
4050 paper, 3 = glossy film, 4 = transparency film */
4051 fprintf(prn_stream, "\033&l%dM", cdj850->papertype);
4052
4053 /* Move to top left of printed area */
4054 fprintf(prn_stream, "\033*p%dY", (int)(300.0 * DOFFSET));
4055
4056 /* raster width and number of planes */
4057 fprintf(prn_stream, "\033*r%ds-%du0A",
4058 raster_width, pdev->color_info.num_components);
4059
4060 /* start raster graphics */
4061 fputs("\033*r1A", prn_stream);
4062
4063 /* From now on, all escape commands start with \033*b, so we
4064 * combine them (if the printer supports this). */
4065 fputs("\033*b", prn_stream);
4066
4067 /* Set compression if the mode has been defined. */
4068 if (cdj850->compression)
4069 fprintf(prn_stream, "%dm", cdj850->compression);
4070
4071 return;
4072 } /* end configure raster-mode */
4073
4074 /* print_plane compresses (mode 3) and outputs one plane */
4075 static void
print_c3plane(FILE * prn_stream,char plane_code,int plane_size,const byte * curr,byte * prev,byte * out_data)4076 print_c3plane(FILE * prn_stream, char plane_code, int plane_size,
4077 const byte * curr, byte * prev, byte * out_data)
4078 {
4079 /* Compress the output data */
4080 int out_count = gdev_pcl_mode3compress(plane_size, curr, prev, out_data);
4081
4082 /* and output the data */
4083 if (out_count > 0) {
4084 fprintf(prn_stream, "%d%c", out_count, plane_code);
4085 fwrite(out_data, sizeof(byte), out_count, prn_stream);
4086 } else {
4087 putc(plane_code, prn_stream);
4088 }
4089 }
4090
4091 static int
copy_color_data(byte * dest,const byte * src,int n)4092 copy_color_data(byte * dest, const byte * src, int n)
4093 {
4094 /* copy word by word */
4095 register int i = n / 4;
4096 register word *d = (word *) dest;
4097 register const word *s = (const word *)src;
4098
4099 while (i-- > 0) {
4100 *d++ = *s++;
4101 }
4102 return n;
4103 }
4104
4105 /* Printing non-blank lines */
4106 static void
cdj1600_print_non_blank_lines(gx_device_printer * pdev,struct ptr_arrays * data_ptrs,struct misc_struct * misc_vars,struct error_val_field * error_values,const Gamma * gamma,FILE * prn_stream)4107 cdj1600_print_non_blank_lines(gx_device_printer * pdev,
4108 struct ptr_arrays *data_ptrs,
4109 struct misc_struct *misc_vars,
4110 struct error_val_field *error_values,
4111 const Gamma *gamma,
4112 FILE * prn_stream)
4113 {
4114 int i, plane_size_c;
4115
4116 /* copy data to data_c in order to make do_floyd_steinberg work */
4117 plane_size_c = copy_color_data
4118 (data_ptrs->data_c[misc_vars->cscan],
4119 data_ptrs->data[misc_vars->scan],
4120 misc_vars->databuff_size) / misc_vars->storage_bpp;
4121
4122 /* dither the color planes */
4123 do_floyd_steinberg(misc_vars->scan, misc_vars->cscan,
4124 misc_vars->plane_size, plane_size_c,
4125 misc_vars->num_comps, data_ptrs, pdev, error_values);
4126
4127 /* Transfer raster graphics in the order C, M, Y, that is
4128 planes 2,1,0 */
4129 for (i = misc_vars->num_comps - 1; i >= 0; i--) {
4130
4131 /* output the lower color planes */
4132 print_c3plane(prn_stream, "wvv"[i], plane_size_c,
4133 data_ptrs->plane_data_c[misc_vars->cscan][i],
4134 data_ptrs->plane_data_c[1 - misc_vars->cscan][i],
4135 data_ptrs->out_data);
4136 } /* End For i = num_comps */
4137 misc_vars->cscan = 1 - misc_vars->cscan;
4138 }
4139
4140 static void
cdj1600_terminate_page(gx_device_printer * pdev,FILE * prn_stream)4141 cdj1600_terminate_page(gx_device_printer * pdev, FILE * prn_stream)
4142 {
4143 cdj850_terminate_page(pdev, prn_stream);
4144 fputs("\033%-12345X", prn_stream);
4145 }
4146