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