xref: /plan9/sys/src/cmd/gs/src/gdevcd8.c (revision 593dc095aefb2a85c828727bbfa9da139a49bdf4)
1 /*
2    Copyright (C) 1996-1998  <Uli Wortmann uliw@erdw.ethz.ch>
3    Portions Copyright (C) 1999 Aladdin Enterprises.  All rights reserved.
4 
5    This program is free software; you can redistribute it and/or modify
6    it under the terms of the GNU General Public License as published by
7    the Free Software Foundation; either version 2 of the License, or
8    (at your option) any later version.
9 
10    This program is distributed in the hope that it will be useful,
11    but WITHOUT ANY WARRANTY; without even the implied warranty of
12    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13    GNU General Public License for more details.
14 
15    You should have received a copy of the GNU General Public License
16    along with this program; if not, write to the Free Software
17    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111 U.S.A.
18 
19    This program may also be distributed as part of Aladdin Ghostscript,
20    under the terms of the Aladdin Free Public License (the "License").
21 
22    Every copy of Aladdin Ghostscript must include a copy of the
23    License, normally in a plain ASCII text file named PUBLIC.  The
24    License grants you the right to copy, modify and redistribute
25    Aladdin Ghostscript, but only under certain conditions described in
26    the License.  Among other things, the License requires that the
27    copyright notice and this notice be preserved on all copies.
28  */
29 
30 /*$Id: gdevcd8.c,v 1.1 2000/03/09 08:40:40 lpd Exp $*/
31 
32 /*
33    A printer driver for the HP670, HP690, HP850, HP855
34    HP870, HP890, HP1100 and HP1600 color printers.
35 
36    To be used with the Ghostscript printing system.
37    Please report all problems to uliw@erdw.ethz.ch
38 
39    CREDITS: Much of the driver is based on ideas derived
40             from the cdj550 driver of George Cameron.
41 
42 	    The support for the hp670, hp690, hp890
43 	    and hp1600 was added by Martin Gerbershagen.
44 */
45 
46 /* Note: Depending on how you transfered the files,
47    you might need to remove some CR-codes used on intel-based machines:
48 
49    simply type:  unzip -a hp850.zip
50 
51    to compile with gs5.x, simply add
52 
53    DEVICE_DEVS4=cdj850.dev cdj670.dev cdj890.dev cdj1600.dev
54 
55    to your makefile.
56 
57    BTW, it is always a good idea to read Make.htm found in the
58    gs-distrib before attempting to recompile.....
59 
60  */
61 
62 /* 1999-01-07 edited by L. Peter Deutsch <ghost@aladdin.com> to eliminate
63    non-const statics and otherwise bring up to date with Ghostscript coding
64    style guidelines. */
65 
66 /* 01.06.98   Version 1.3  Due to the most welcome contribution
67    of Martin Gerbershagen (ger@ulm.temic.de),
68    support for the hp670, hp690 and hp890
69    and hp1600 has been added. Martin has also
70    resolved all known bugs.
71 
72    Problems  :  Dark colors are still pale.
73 
74 
75    The driver no longer needs special switches to be invoked
76    except -sDEVICE=cdj850, or -sDEVICE=CDJ890, or sDEVICE=CDJ670
77    or -sDEVICE=CDJ1600
78 
79    The hp690 is supported through the hp670 device, the hp855, hp870
80    and the hp1100 through the hp850 device.
81 
82    The driver implements the following switches:
83 
84    -dPapertype= 0  plain paper [default]
85    1  bond paper
86    2  special paper
87    3  glossy film
88    4  transparency film
89 
90    Note, currently the lookuptables are not suited
91    for printing on special paper or transperencies.
92    Please revert to the gamma functions in this case.
93 
94    -dQuality=  -1 draft
95    0 normal       [default]
96    1 presentation
97 
98    -dRetStatus= 0 C-RET off
99    1 C-RET on [default]
100 
101    -dMasterGamma= 3.0 [default = 1.0]
102    __Note__: To take advantage of the calibrated color-transfer
103    functions, be sure not to have any Gamma-Statements
104    left! If you need to (i.e. overhead sheets),
105    you still can use the gamma-functions, but they will
106    override the built-in calibration. To use gamma in the
107    traditional way, set MasterGamma to any value greater
108    1.0 and less 10.0. To adjust individual gamma-values,
109    you have to additionally set MasterGamma to a value
110    greater 1.0 and less 10.0
111 
112    With the next release, gamma functions will be dropped.
113 
114    When using the driver, be aware that printing in 600dpi involves
115    processing of large amounts of data (> 188MB !). Therefore, the
116    driver is not what you would expect to be a fast driver ;-)
117    This is no problem when printing a full sized color page (because
118    printing itself is slow), but it's really annoying if yoy print only
119    text pages. Maybe I can optimize the code for text-only pages in a
120    later release. Right now, it is recommended to use the highest
121    possible optimisation level your compiler offers....
122    For the time beeing, use the cdj550 device with -sBitsPerPixel=3
123    for fast proof-prints. If you simply want to print 600dpi b/w data,
124    use the cdj550 device with -sBitsPerPixel=8 (or 1).
125 
126    Since the printer itself is slow, it may help to set the
127    process-priority of the gs-process to regular or even less. On a
128    486/100MHZ this is still sufficient to maintain a continuos
129    data-flow.
130    Note to OS/2 users: Simply put the gs-window into the background,
131    or minimize it. Also make sure, that print01.sys is invoked without
132    the /irq switch (great speed improvement under warp4).
133 
134    The printer default settings compensate for dot-gain by a
135    calibrated color-transfer function. If this appears to be to light
136    for your business-graphs, or for overhead-sheets, feel free to set
137    -dMasterGamma=1.7.
138 
139    Furthermore, you may tweak the gammavalues independently by setting
140    -dGammaValC, -dGammaValM, -dGammaValY or -dGammaValK (if not set,
141    the values default to MasterGamma). This will only work, when
142    -dMasterGamma is set to a value greater than 1.0.
143 
144    If you want to learn more about gamma, see:
145 
146    http://www.erdw.ethz.ch/~bonk/ftp/misc/gammafaq.pdf
147    http://www.erdw.ethz.ch/~bonk/ftp/misc/colorfaq.pdf
148 
149    Further information, bugs, tips etc, can be found
150    at my website.
151 
152    Have fun!
153 
154    Uli
155 
156    uliw@erdw.ethz.ch
157    http://www.erdw.ethz.ch/~bonk/bonk.html
158 
159  */
160 
161 /* 25.08.97  Version 1.2. Resolved all but one of the
162    known bugs, introduced a couple
163    of perfomance improvements. Complete
164    new color-transfer-function handling.
165    (see gamma). */
166 
167 /* 04.05.97  Version 1.1. For added features, */
168 /* resolved bugs and so forth, please see   */
169 /* http://bonk.ethz.ch                      */
170 
171 /* 11.11.96. Initial release of the driver */
172 
173 #include "math_.h"
174 #include <stdlib.h>		/* for rand() */
175 #include <assert.h>
176 #include "gdevprn.h"
177 #include "gdevpcl.h"
178 #include "gsparam.h"
179 
180 /* Conversion stuff. */
181 #include "gxlum.h"
182 
183 #define P1(x) x
184 #define P2(x,y) x,y
185 #define P3(x,y,z) x,y,z
186 #define P4(x,y,z,a) x,y,z,a
187 #define P5(x,y,z,a,b) x,y,z,a,b
188 #define P6(x,y,z,a,b,c) x,y,z,a,b,c
189 #define P7(x,y,z,a,b,c,d) x,y,z,a,b,c,d
190 #define P8(x,y,z,a,b,c,d,e) x,y,z,a,b,c,d,e
191 #define P9(x,y,z,a,b,c,d,e,f) x,y,z,a,b,c,d,e,f
192 #define P10(x,y,z,a,b,c,d,e,f,g) x,y,z,a,b,c,d,e,f,g
193 #define P11(x,y,z,a,b,c,d,e,f,g,h) x,y,z,a,b,c,d,e,f,g,h
194 #define P12(x,y,z,a,b,c,d,e,f,g,h,i) x,y,z,a,b,c,d,e,f,g,h,i
195 
196 /* this holds the initialisation data of the hp850 */
197 typedef struct hp850_cmyk_init_s {
198     byte a[26];
199 } hp850_cmyk_init_t;
200 private const hp850_cmyk_init_t hp850_cmyk_init =
201 {
202     {
203 	0x02,			/* format */
204 	0x04,			/* number of components */
205       /* black */
206 	0x01,			/* MSB x resolution */
207 	0x2c,			/* LSB x resolution */
208 	0x01,			/* MSB y resolution */
209 	0x2c,			/* LSB y resolution */
210 	0x00,			/* MSB intensity levels */
211 	0x02,			/* LSB intensity levels */
212 
213       /* cyan */
214 	0x01,			/* MSB x resolution */
215 	0x2c,			/* LSB x resolution */
216 	0x01,			/* MSB y resolution */
217 	0x2c,			/* LSB y resolution */
218 	0x00,			/* MSB intensity levels */
219 	0x02,			/* LSB intensity levels */
220 
221       /* magenta */
222 	0x01,			/* MSB x resolution */
223 	0x2c,			/* LSB x resolution */
224 	0x01,			/* MSB y resolution */
225 	0x2c,			/* LSB y resolution */
226 	0x00,			/* MSB intensity levels */
227 	0x02,			/* LSB intensity levels */
228 
229       /* yellow */
230 	0x01,			/* MSB x resolution */
231 	0x2c,			/* LSB x resolution */
232 	0x01,			/* MSB y resolution */
233 	0x2c,			/* LSB y resolution */
234 	0x00,			/* MSB intensity levels */
235 	0x02			/* LSB intensity levels */
236     }
237 };
238 
239 /* this holds the color lookuptable data of the hp850 */
240 typedef struct {
241     byte c[256];		/* Lookuptable for cyan */
242     byte m[256];		/* dito for magenta */
243     byte y[256];		/* dito for yellow */
244     byte k[256];		/* dito for black  */
245     int correct[256];		/* potential undercolor black correction */
246 } Gamma;
247 
248 private const Gamma gammat850 =
249 {
250   /* Lookup values for cyan */
251     {0, 0, 0, 2, 2, 2, 3, 3, 3, 5, 5, 5, 7, 7, 6, 7, 7, 6, 7, 7, 7, 8, 8,
252      8, 8, 8, 8, 9, 9, 9, 9, 9, 10, 10, 10, 10, 10, 10, 11, 11, 12, 12, 12,
253      12, 12, 12, 13, 13, 14, 14, 14, 15, 15, 16, 16, 15, 16, 16, 17, 17,
254      17, 17, 17, 18, 18, 18, 19, 19, 20, 20, 20, 20, 20, 21, 21, 21, 22,
255      22, 23, 23, 23, 23, 23, 24, 24, 25, 25, 26, 26, 26, 26, 26, 27, 27,
256      27, 27, 28, 28, 29, 28, 28, 29, 29, 30, 30, 31, 31, 32, 32, 33, 34,
257      35, 35, 36, 36, 37, 37, 38, 38, 39, 39, 40, 40, 41, 41, 42, 42, 42,
258      43, 43, 43, 44, 45, 45, 46, 46, 47, 47, 48, 48, 49, 50, 50, 51, 51,
259      52, 52, 53, 54, 54, 54, 55, 55, 56, 57, 58, 58, 59, 60, 60, 61, 62,
260      62, 63, 65, 65, 66, 67, 67, 68, 69, 69, 70, 72, 73, 73, 74, 75, 75,
261      76, 77, 79, 79, 80, 81, 82, 83, 83, 84, 86, 87, 88, 88, 89, 90, 91,
262      92, 93, 94, 95, 96, 97, 97, 99, 100, 101, 102, 103, 104, 105, 106,
263      108, 109, 110, 111, 112, 114, 115, 117, 119, 120, 122, 124, 125, 127,
264      129, 131, 132, 135, 136, 138, 140, 142, 144, 146, 147, 150, 152, 154,
265      157, 159, 162, 164, 166, 168, 171, 174, 176, 180, 182, 187, 192, 197,
266      204, 215, 255},
267   /* Lookup values for magenta */
268     {0, 0, 0, 1, 1, 1, 3, 3, 3, 4, 4, 4, 5, 5, 5, 6, 6, 6, 7, 7, 7, 7, 7,
269      7, 8, 8, 8, 9, 9, 10, 10, 9, 10, 10, 10, 11, 11, 11, 11, 11, 12, 12,
270      12, 13, 13, 13, 14, 14, 15, 15, 15, 16, 16, 16, 16, 16, 17, 17, 17,
271      17, 17, 18, 18, 19, 19, 19, 19, 19, 20, 20, 20, 21, 21, 22, 22, 22,
272      23, 23, 24, 24, 25, 25, 25, 26, 26, 27, 27, 28, 29, 29, 29, 29, 30,
273      30, 31, 30, 31, 31, 32, 31, 31, 32, 32, 33, 33, 34, 34, 35, 35, 36,
274      36, 37, 37, 38, 38, 39, 39, 40, 40, 41, 41, 42, 42, 43, 43, 44, 44,
275      45, 45, 46, 46, 47, 48, 48, 49, 49, 50, 50, 51, 51, 52, 53, 53, 54,
276      54, 55, 55, 56, 57, 57, 58, 58, 59, 60, 60, 61, 61, 62, 63, 64, 65,
277      66, 66, 67, 68, 68, 70, 71, 71, 72, 73, 73, 74, 76, 77, 77, 78, 79,
278      79, 80, 81, 82, 83, 84, 85, 86, 87, 87, 88, 89, 90, 91, 91, 92, 93,
279      94, 95, 96, 97, 98, 99, 100, 100, 101, 102, 103, 105, 106, 107, 108,
280      109, 112, 113, 114, 115, 116, 118, 119, 121, 123, 124, 125, 128, 129,
281      130, 133, 134, 135, 138, 139, 142, 144, 145, 148, 150, 152, 154, 157,
282      159, 162, 164, 168, 169, 170, 172, 175, 177, 179, 182, 185, 189, 193,
283      198, 204, 215, 255},
284   /* Lookup values for yellow */
285     {0, 0, 0, 2, 2, 2, 3, 3, 3, 5, 5, 5, 7, 7, 6, 7, 7, 6, 7, 7, 7, 8, 8,
286      8, 8, 8, 8, 9, 9, 9, 9, 9, 10, 9, 9, 10, 10, 10, 10, 10, 11, 11, 11,
287      12, 12, 13, 13, 14, 14, 15, 15, 16, 16, 16, 16, 16, 17, 17, 18, 18,
288      18, 19, 18, 19, 19, 19, 20, 20, 21, 21, 21, 22, 22, 22, 22, 22, 23,
289      23, 24, 24, 25, 25, 25, 26, 27, 28, 28, 29, 29, 29, 30, 30, 30, 30,
290      31, 31, 32, 32, 33, 33, 32, 33, 33, 34, 34, 35, 35, 36, 36, 37, 37,
291      38, 38, 39, 39, 40, 40, 41, 41, 42, 42, 43, 43, 44, 44, 45, 45, 45,
292      45, 46, 46, 47, 48, 48, 49, 49, 50, 50, 51, 51, 52, 53, 53, 54, 54,
293      55, 55, 56, 57, 58, 59, 59, 60, 61, 61, 62, 62, 63, 64, 65, 66, 67,
294      67, 68, 69, 69, 70, 71, 72, 73, 74, 74, 75, 76, 77, 77, 78, 79, 79,
295      80, 81, 82, 83, 84, 85, 86, 87, 87, 88, 89, 90, 91, 91, 93, 94, 95,
296      96, 97, 98, 100, 101, 102, 102, 103, 104, 106, 107, 108, 109, 110,
297      111, 113, 114, 115, 116, 117, 118, 119, 121, 123, 124, 126, 128, 130,
298      131, 134, 135, 137, 139, 140, 143, 145, 146, 148, 150, 152, 154, 156,
299      158, 160, 163, 166, 167, 169, 171, 173, 176, 178, 181, 184, 188, 192,
300      198, 204, 215, 255},
301   /* Lookup values for black */
302     {0, 0, 0, 1, 1, 1, 1, 1, 1, 3, 3, 3, 3, 3, 2, 4, 3, 3, 3, 3, 3, 4, 4,
303      4, 5, 5, 5, 5, 5, 6, 6, 6, 6, 6, 6, 7, 7, 7, 7, 7, 8, 8, 8, 9, 9, 8,
304      8, 8, 9, 9, 9, 10, 10, 10, 10, 10, 11, 11, 11, 11, 12, 12, 12, 13, 13,
305      12, 12, 12, 13, 13, 13, 13, 13, 14, 14, 14, 14, 14, 15, 15, 16, 16,
306      16, 17, 17, 17, 17, 18, 18, 18, 19, 19, 20, 20, 20, 20, 20, 21, 21,
307      21, 21, 22, 22, 22, 22, 23, 22, 23, 23, 24, 24, 24, 24, 25, 25, 26,
308      26, 26, 26, 27, 27, 28, 28, 28, 28, 29, 29, 30, 30, 31, 31, 31, 32,
309      32, 33, 33, 34, 34, 35, 36, 36, 36, 37, 37, 37, 38, 38, 40, 40, 40,
310      41, 41, 42, 43, 43, 43, 43, 44, 45, 45, 46, 47, 47, 48, 49, 49, 50,
311      52, 52, 53, 54, 54, 56, 56, 57, 58, 59, 60, 60, 61, 62, 63, 63, 64,
312      65, 66, 67, 68, 69, 70, 71, 72, 72, 73, 75, 75, 76, 77, 78, 80, 81,
313      82, 82, 83, 84, 85, 86, 88, 89, 90, 91, 94, 95, 96, 98, 99, 100, 101,
314      103, 105, 106, 107, 110, 111, 112, 115, 116, 118, 120, 121, 124, 126,
315      127, 131, 133, 134, 138, 140, 141, 146, 148, 151, 154, 156, 160, 163,
316      166, 169, 174, 177, 182, 187, 194, 203, 215, 255}
317 };
318 
319 private const Gamma gammat890 =
320 {
321 /* Lookup values for cyan */
322     {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
323      16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
324      32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
325      48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,
326      64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79,
327      80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95,
328      96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111,
329      112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125,
330      126, 127,
331      128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141,
332      142, 143,
333      144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157,
334      158, 159,
335      160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173,
336      174, 175,
337      176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189,
338      190, 191,
339      192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205,
340      206, 207,
341      208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221,
342      222, 223,
343      224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237,
344      238, 239,
345      240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253,
346      254, 255},
347 
348 /* Lookup values for magenta */
349     {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
350      16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
351      32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
352      48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,
353      64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79,
354      80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95,
355      96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111,
356      112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125,
357      126, 127,
358      128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141,
359      142, 143,
360      144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157,
361      158, 159,
362      160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173,
363      174, 175,
364      176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189,
365      190, 191,
366      192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205,
367      206, 207,
368      208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221,
369      222, 223,
370      224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237,
371      238, 239,
372      240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253,
373      254, 255},
374 
375 /* Lookup values for yellow */
376     {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
377      16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
378      32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
379      48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,
380      64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79,
381      80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95,
382      96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111,
383      112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125,
384      126, 127,
385      128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141,
386      142, 143,
387      144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157,
388      158, 159,
389      160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173,
390      174, 175,
391      176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189,
392      190, 191,
393      192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205,
394      206, 207,
395      208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221,
396      222, 223,
397      224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237,
398      238, 239,
399      240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253,
400      254, 255},
401 
402  /* Lookup values for black */
403     {0, 0, 0, 1, 1, 1, 1, 1, 1, 3, 3, 3, 3, 3, 2, 4, 3, 3, 3, 3, 3, 4, 4,
404      4, 5, 5, 5, 5, 5, 6, 6, 6, 6, 6, 6, 7, 7, 7, 7, 7, 8, 8, 8, 9, 9, 8,
405      8, 8, 9, 9, 9, 10, 10, 10, 10, 10, 11, 11, 11, 11, 12, 12, 12, 13, 13,
406      12, 12, 12, 13, 13, 13, 13, 13, 14, 14, 14, 14, 14, 15, 15, 16, 16,
407      16, 17, 17, 17, 17, 18, 18, 18, 19, 19, 20, 20, 20, 20, 20, 21, 21,
408      21, 21, 22, 22, 22, 22, 23, 22, 23, 23, 24, 24, 24, 24, 25, 25, 26,
409      26, 26, 26, 27, 27, 28, 28, 28, 28, 29, 29, 30, 30, 31, 31, 31, 32,
410      32, 33, 33, 34, 34, 35, 36, 36, 36, 37, 37, 37, 38, 38, 40, 40, 40,
411      41, 41, 42, 43, 43, 43, 43, 44, 45, 45, 46, 47, 47, 48, 49, 49, 50,
412      52, 52, 53, 54, 54, 56, 56, 57, 58, 59, 60, 60, 61, 62, 63, 63, 64,
413      65, 66, 67, 68, 69, 70, 71, 72, 72, 73, 75, 75, 76, 77, 78, 80, 81,
414      82, 82, 83, 84, 85, 86, 88, 89, 90, 91, 94, 95, 96, 98, 99, 100, 101,
415      103, 105, 106, 107, 110, 111, 112, 115, 116, 118, 120, 121, 124, 126,
416      127, 131, 133, 134, 138, 140, 141, 146, 148, 151, 154, 156, 160, 163,
417      166, 169, 174, 177, 182, 187, 194, 203, 215, 255}
418 };
419 
420 private const Gamma * const gammat[] =
421 {
422     &gammat850,			/* CDJ670 */
423     &gammat850,			/* CDJ850 */
424     &gammat890,			/* CDJ890 */
425     &gammat850			/* CDJ1600 */
426 };
427 
428 private int
429     rescale_byte_wise1x1(P4(int bytecount, const byte * inbytea,
430 			    const byte * inbyteb, byte * outbyte));
431 private int
432     rescale_byte_wise2x1(P4(int bytecount, const byte * inbytea,
433 			    const byte * inbyteb, byte * outbyte));
434 private int
435     rescale_byte_wise1x2(P4(int bytecount, const byte * inbytea,
436 			    const byte * inbyteb, byte * outbyte));
437 private int
438     rescale_byte_wise2x2(P4(int bytecount, const byte * inbytea,
439 			    const byte * inbyteb, byte * outbyte));
440 
441 private int (* const rescale_color_plane[2][2]) (P4(int, const byte *, const byte *, byte *)) = {
442     {
443 	rescale_byte_wise1x1, rescale_byte_wise1x2
444     },
445     {
446 	rescale_byte_wise2x1, rescale_byte_wise2x2
447     }
448 };
449 
450 /*
451  * Drivers stuff.
452  *
453  */
454 #define DESKJET_PRINT_LIMIT  0.04	/* 'real' top margin? */
455 /* Margins are left, bottom, right, top. */
456 #define DESKJET_MARGINS_LETTER   0.25, 0.50, 0.25, 0.167
457 #define DESKJET_MARGINS_A4       0.13, 0.46, 0.13, 0.04
458 /* Define bits-per-pixel - default is 32-bit cmyk-mode */
459 #ifndef BITSPERPIXEL
460 #  define BITSPERPIXEL 32
461 #endif
462 #define DOFFSET (dev_t_margin(pdev) - DESKJET_PRINT_LIMIT)	/* Print position */
463 
464 
465 #define W sizeof(word)
466 #define I sizeof(int)
467 
468 /* paper types */
469 typedef enum {
470     PLAIN_PAPER, BOND_PAPER, SPECIAL_PAPER, GLOSSY_FILM, TRANSPARENCY_FILM
471 } cdj_paper_type_t;
472 
473 /* quality */
474 typedef enum {
475     DRAFT = -1, NORMAL = 0, PRESENTATION = 1
476 } cdj_quality_t;
477 
478 /* Printer types */
479 typedef enum {
480     DJ670C, DJ850C, DJ890C, DJ1600C
481 } cdj_printer_type_t;
482 
483 /* No. of ink jets (used to minimise head movements) */
484 #define HEAD_ROWS_MONO 50
485 #define HEAD_ROWS_COLOUR 16
486 
487 /* Colour mapping procedures */
488 private dev_proc_map_cmyk_color(gdev_cmyk_map_cmyk_color);
489 private dev_proc_map_rgb_color(gdev_cmyk_map_rgb_color);
490 private dev_proc_map_color_rgb(gdev_cmyk_map_color_rgb);
491 
492 private dev_proc_map_rgb_color(gdev_pcl_map_rgb_color);
493 private dev_proc_map_color_rgb(gdev_pcl_map_color_rgb);
494 
495 /* Print-page, parameters and miscellaneous procedures */
496 private dev_proc_open_device(hp_colour_open);
497 
498 private dev_proc_get_params(cdj850_get_params);
499 private dev_proc_put_params(cdj850_put_params);
500 
501 private dev_proc_print_page(cdj850_print_page);
502 
503 /* The device descriptors */
504 
505 /* The basic structure for all printers. Note the presence of the cmyk, depth
506    and correct fields even if some are not used by all printers. */
507 
508 #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)\
509     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
510 
511 
512 
513 #define gx_prn_colour_device_common \
514     gx_prn_device_common; \
515     int cmyk;	  	/* 0: not CMYK-capable, > 0: printing CMYK, */ \
516 		  	/* < 0 : CMYK-capable, not printing CMYK */ \
517     uint default_depth;	/* Used only for CMYK-capable printers now. */ \
518     uint correction
519 
520 
521 /* some definitions needed later */
522 struct error_val_field {
523     int c;		/* Current value of Cyan error during dithering */
524     int m;		/* Current value of Magenta error during dithering */
525     int y;		/* Current value of Yellow error during dithering */
526     int k;		/* Current value of Black error during dithering */
527 };
528 
529 /* this structure holds all the pointers to the different values
530    in all those data fields */
531  /*
532     * The principal data pointers are stored as pairs of values, with
533     * the selection being made by the 'scan' variable. The function of the
534     * scan variable is overloaded, as it controls both the alternating
535     * raster scan direction used in the Floyd-Steinberg dithering and also
536     * the buffer alternation required for line-difference compression.
537     *
538     * Thus, the number of pointers required is as follows:
539   */
540 
541 struct ptr_arrays {
542     byte *data[4];		/* 4 600dpi data, scan direction and alternating buffers */
543     byte *data_c[4];		/* 4 300dpi data, as above, */
544     byte *plane_data[4][4];	/*4 b/w-planes, scan direction and alternating buffers */
545     byte *plane_data_c[4][8];	/* as above, but for 8 planes */
546     byte *out_data;		/* output buffer for the b/w data, one 600dpi plane */
547     byte *test_data[4];		/* holds a copy of the last plane */
548     int *errors[2];		/* 2 b/w dithering erros (scan direction only) */
549     int *errors_c[2];		/* 2 color dithering errors (scan direction only) */
550     word *storage;		/* pointer to the beginning of the b/w-buffer */
551     word *storage_start;	/* used for debugging */
552     word *storage_end;		/* used for debugging */
553     word *storage_size;		/* used for debugging */
554 };
555 
556 /* Some miscellaneous variables */
557 struct misc_struct {
558     int line_size;		/* size of scan_line */
559     int line_size_c;		/* size of rescaled scan_line */
560     int line_size_words;	/* size of scan_line in words */
561     int paper_size;		/* size of paper */
562     int num_comps;		/* number of color components (1 - 4) */
563     int bits_per_pixel;		/* bits per pixel 1,4,8,16,24,32 */
564     int storage_bpp;		/* = bits_per_pixel */
565     int expanded_bpp;		/* = bits_per_pixel */
566     int plane_size;		/* size of b/w bit plane */
567     int plane_size_c;		/* size of color bit plane */
568     int databuff_size;		/* size of databuffer for b/w data */
569     int databuff_size_c;	/* size of databuffer for color data */
570     int errbuff_size;		/* size of error buffer b/w -data */
571     int errbuff_size_c;		/* size of error buffer color -data */
572     int outbuff_size;		/* size of output buffer for b/w data */
573     int scan;			/* scan-line variable [0,1] */
574     int cscan;			/* dito for the color-planes */
575     int is_two_pass;		/* checks if b/w data has already been printed */
576     int zero_row_count;		/* How many empty lines */
577     uint storage_size_words;	/* size of storage in words for b/w data */
578     uint storage_size_words_c;	/* size of storage in words for c-data */
579     int is_color_data;		/* indicates whether there is color data */
580 };
581 
582     /* function pointer typedefs for device driver struct */
583 typedef void (*StartRasterMode) (P3(gx_device_printer * pdev, int paper_size,
584 				    FILE * prn_stream));
585 typedef void (*PrintNonBlankLines) (P6(gx_device_printer * pdev,
586 				       struct ptr_arrays *data_ptrs,
587 				       struct misc_struct *misc_vars,
588 				       struct error_val_field *error_values,
589 				       const Gamma *gamma,
590 				       FILE * prn_stream));
591 
592 typedef void (*TerminatePage) (P2(gx_device_printer * pdev, FILE * prn_stream));
593 
594 typedef struct gx_device_cdj850_s {
595     gx_device_common;
596     gx_prn_colour_device_common;
597     int /*cdj_quality_t*/ quality;  /* -1 draft, 0 normal, 1 best */
598     int /*cdj_paper_type_t*/ papertype;  /* papertype [0,4] */
599     int intensities;		/* intensity values per pixel [2,4] */
600     int xscal;			/* boolean to indicate x scaling by 2 */
601     int yscal;			/* boolean to indicate y scaling by 2 */
602     int /*cdj_printer_type_t*/ ptype;  /* printer type, one of DJ670C, DJ850C, DJ890C, DJ1600C */
603     int compression;		/* compression level */
604     float mastergamma;		/* Gammavalue applied to all colors */
605     float gammavalc;		/* range to which gamma-correction is
606 				   applied to bw values */
607     float gammavalm;		/* amount of gamma correction for bw */
608     float gammavaly;		/* range to which gamma-correction i
609 				   applied to color values */
610     float gammavalk;		/* amount of gamma correction for color */
611     float blackcorrect;		/* amount of gamma correction for color */
612     StartRasterMode start_raster_mode;	/* output function to start raster mode */
613     PrintNonBlankLines print_non_blank_lines;	/* output function to print a non blank line */
614     TerminatePage terminate_page;	/* page termination output function */
615 } gx_device_cdj850;
616 
617 typedef struct {
618     gx_device_common;
619     gx_prn_colour_device_common;
620 } gx_device_colour_prn;
621 
622 
623 /* Use the cprn_device macro to access generic fields (like cmyk,
624    default_depth and correction), and specific macros for specific
625    devices. */
626 
627 #define cprn_device     ((gx_device_colour_prn*) pdev)
628 #define cdj850    ((gx_device_cdj850 *)pdev)
629 
630 #define prn_cmyk_colour_device(dtype, procs, dev_name, x_dpi, y_dpi, bpp, print_page, correct)\
631     prn_colour_device_body(dtype, procs, dev_name,\
632     DEFAULT_WIDTH_10THS, DEFAULT_HEIGHT_10THS, x_dpi, y_dpi, 0, 0, 0, 0,\
633     ((bpp == 1 || bpp == 4) ? 1 : 4), bpp,\
634     (bpp > 8 ? 255 : 1), (1 << (bpp >> 2)) - 1, /* max_gray, max_color */\
635     (bpp > 8 ? 5 : 2), (bpp > 8 ? 5 : bpp > 1 ? 2 : 0),\
636     print_page, 1 /* cmyk */, correct)
637 
638 
639 #define prn_cmy_colour_device(dtype, procs, dev_name, x_dpi, y_dpi, bpp, print_page, correct)\
640     prn_colour_device_body(dtype, procs, dev_name,\
641     DEFAULT_WIDTH_10THS, DEFAULT_HEIGHT_10THS, x_dpi, y_dpi, 0, 0, 0, 0,\
642     ((bpp == 1 || bpp == 4) ? 1 : 3), bpp,\
643     (bpp > 8 ? 255 : 1), (bpp > 8 ? 255 : 1), /* max_gray, max_color */\
644     (bpp > 8 ? 5 : 2), (bpp > 8 ? 5 : bpp > 1 ? 2 : 0),\
645     print_page, -1 /* cmyk */, correct)
646 
647 
648 #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)\
649 { prn_cmyk_colour_device(gx_device_cdj850, procs, dev_name, x_dpi, y_dpi, bpp, print_page, correction),\
650     quality,\
651     papertype,\
652     intensities,\
653     0, 0, /* xscal, yscal */\
654     ptype,\
655     compression,\
656     mastergamma,\
657     gammavalc,\
658     gammavalm,\
659     gammavaly,\
660     gammavalk,\
661     blackcorrect,\
662     start_raster_mode,\
663     print_non_blank_line,\
664     terminate_page\
665 }
666 
667 #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)\
668 { prn_cmy_colour_device(gx_device_cdj850, procs, dev_name, x_dpi, y_dpi, bpp, print_page, correction),\
669     quality,\
670     papertype,\
671     intensities,\
672     0, 0, /* xscal, yscal */\
673     ptype,\
674     compression,\
675     mastergamma,\
676     gammavalc,\
677     gammavalm,\
678     gammavaly,\
679     gammavalk,\
680     blackcorrect,\
681     start_raster_mode,\
682     print_non_blank_line,\
683     terminate_page\
684 }
685 
686 #define cmyk_colour_procs(proc_colour_open, proc_get_params, proc_put_params, \
687 			  map_rgb_color, map_color_rgb, map_cmyk_color) {\
688 	proc_colour_open,\
689 	gx_default_get_initial_matrix,\
690 	gx_default_sync_output,\
691 	gdev_prn_output_page,\
692 	gdev_prn_close,\
693 	map_rgb_color,\
694 	map_color_rgb,\
695 	NULL /* fill_rectangle */,\
696 	NULL /* tile_rectangle */,\
697 	NULL /* copy_mono */,\
698 	NULL /* copy_color */,\
699 	NULL /* draw_line */,\
700 	gx_default_get_bits,\
701 	proc_get_params,\
702 	proc_put_params,\
703         map_cmyk_color\
704 }
705 
706 private void
707      cdj850_start_raster_mode(P3(gx_device_printer * pdev,
708 				 int papersize, FILE * prn_stream));
709 
710 private void
711      cdj850_print_non_blank_lines(P6(gx_device_printer * pdev,
712 				     struct ptr_arrays *data_ptrs,
713 				     struct misc_struct *misc_vars,
714 				     struct error_val_field *error_values,
715 				     const Gamma *gamma,
716 				     FILE * prn_stream));
717 private void
718      cdj850_terminate_page(P2(gx_device_printer * pdev, FILE * prn_stream));
719 
720 private void
721      cdj1600_start_raster_mode(P3(gx_device_printer * pdev,
722 				  int papersize, FILE * prn_stream));
723 private void
724      cdj1600_print_non_blank_lines(P6(gx_device_printer * pdev,
725 				      struct ptr_arrays *data_ptrs,
726 				      struct misc_struct *misc_vars,
727 				      struct error_val_field *error_values,
728 				      const Gamma *gamma,
729 				      FILE * prn_stream));
730 private void
731      cdj1600_terminate_page(P2(gx_device_printer * pdev, FILE * prn_stream));
732 
733 
734 
735 private const gx_device_procs cdj670_procs =
736 cmyk_colour_procs(hp_colour_open, cdj850_get_params, cdj850_put_params,
737 		  NULL, gdev_cmyk_map_color_rgb, gdev_cmyk_map_cmyk_color);
738 
739 private const gx_device_procs cdj850_procs =
740 cmyk_colour_procs(hp_colour_open, cdj850_get_params, cdj850_put_params,
741 		  NULL, gdev_cmyk_map_color_rgb, gdev_cmyk_map_cmyk_color);
742 
743 private const gx_device_procs cdj890_procs =
744 cmyk_colour_procs(hp_colour_open, cdj850_get_params, cdj850_put_params,
745 		  NULL, gdev_cmyk_map_color_rgb, gdev_cmyk_map_cmyk_color);
746 
747 private const gx_device_procs cdj1600_procs =
748 cmyk_colour_procs(hp_colour_open, cdj850_get_params, cdj850_put_params,
749 		  gdev_pcl_map_rgb_color, gdev_pcl_map_color_rgb, NULL);
750 
751 const gx_device_cdj850 gs_cdj670_device =
752 cdj_850_device(cdj670_procs, "cdj670", 600, 600, 32, cdj850_print_page, 0,
753 	       PRESENTATION, PLAIN_PAPER, 2, DJ670C, 9,
754 	       1.0, 0.0, 0.0, 0.0, 0.0, 1.0,
755 	       cdj850_start_raster_mode, cdj850_print_non_blank_lines,
756 	       cdj850_terminate_page);
757 
758 const gx_device_cdj850 gs_cdj850_device =
759 cdj_850_device(cdj850_procs, "cdj850", 600, 600, 32, cdj850_print_page, 0,
760 	       PRESENTATION, PLAIN_PAPER, 4, DJ850C, 9,
761 	       1.0, 0.0, 0.0, 0.0, 0.0, 1.0,
762 	       cdj850_start_raster_mode, cdj850_print_non_blank_lines,
763 	       cdj850_terminate_page);
764 
765 const gx_device_cdj850 gs_cdj890_device =
766 cdj_850_device(cdj890_procs, "cdj890", 600, 600, 32, cdj850_print_page, 0,
767 	       PRESENTATION, PLAIN_PAPER, 4, DJ890C, 9,
768 	       1.0, 0.0, 0.0, 0.0, 0.0, 1.0,
769 	       cdj850_start_raster_mode, cdj850_print_non_blank_lines,
770 	       cdj850_terminate_page);
771 
772 const gx_device_cdj850 gs_cdj1600_device =
773 cdj_1600_device(cdj1600_procs, "cdj1600", 300, 300, 24, cdj850_print_page, 0,
774 		PRESENTATION, PLAIN_PAPER, 2, DJ1600C, 3,
775 		1.0, 0.0, 0.0, 0.0, 0.0, 1.0,
776 		cdj1600_start_raster_mode, cdj1600_print_non_blank_lines,
777 		cdj1600_terminate_page);
778 
779 /* Forward references */
780 private int cdj_put_param_int(P6(gs_param_list *, gs_param_name,
781 				 int *, int, int, int));
782 private int cdj_put_param_float(P6(gs_param_list *, gs_param_name, float
783 				   *, float, float, int));
784 private int cdj_put_param_bpp(P5(gx_device *, gs_param_list *, int, int, int));
785 private int cdj_set_bpp(P3(gx_device *, int, int));
786 
787 
788 /* Open the printer and set up the margins. */
789 private int
hp_colour_open(gx_device * pdev)790 hp_colour_open(gx_device * pdev)
791 {				/* Change the margins if necessary. */
792     static const float dj_a4[4] = {
793 	DESKJET_MARGINS_A4
794     };
795     static const float dj_letter[4] = {
796 	DESKJET_MARGINS_LETTER
797     };
798 
799     /* margins for DJ1600C from manual */
800     static const float m_cdj1600[4] = {
801 	0.25, 0.5, 0.25, 0.5
802     };
803 
804     const float *m = (float *)0;
805 
806     /* Set up colour params if put_params has not already done so */
807     if (pdev->color_info.num_components == 0) {
808 	int code = cdj_set_bpp(pdev, pdev->color_info.depth,
809 			       pdev->color_info.num_components);
810 
811 	if (code < 0)
812 	    return code;
813     }
814     /* assign printer type and set resolution dependent on printer type */
815     switch (cdj850->ptype) {
816     case DJ670C:
817 	if (cdj850->papertype <= SPECIAL_PAPER) {	/* paper */
818 	    if (cdj850->quality == DRAFT) {
819 		gx_device_set_resolution(pdev, 300.0, 300.0);
820 		cdj850->xscal = 0;
821 		cdj850->yscal = 0;
822 	    } else if (cdj850->quality == NORMAL) {
823 		gx_device_set_resolution(pdev, 600.0, 300.0);
824 		cdj850->xscal = 1;
825 		cdj850->yscal = 0;
826 	    } else {		/* quality == PRESENTATION */
827 		gx_device_set_resolution(pdev, 600.0, 600.0);
828 		cdj850->xscal = 1;
829 		cdj850->yscal = 1;
830 	    }
831 	} else {		/* film */
832 	    gx_device_set_resolution(pdev, 600.0, 300.0);
833 	    cdj850->xscal = 0;
834 	    cdj850->yscal = 0;
835 	}
836 	m = (gdev_pcl_paper_size(pdev) == PAPER_SIZE_A4 ? dj_a4 : dj_letter);
837 	break;
838     case DJ850C:
839     case DJ890C:
840 	if (cdj850->quality == DRAFT) {
841 	    gx_device_set_resolution(pdev, 300.0, 300.0);
842 	    cdj850->xscal = 0;
843 	    cdj850->yscal = 0;
844 	    cdj850->intensities = 2;
845 	} else if (cdj850->quality == NORMAL) {
846 	    gx_device_set_resolution(pdev, 600.0, 300.0);
847 	    cdj850->xscal = 1;
848 	    cdj850->yscal = 0;
849 	    /* only 3 intensities for normal paper */
850 	    if (cdj850->papertype <= PLAIN_PAPER) {
851 		cdj850->intensities = 3;
852 	    }			/* else cdj850->intensities = 4 from initialization */
853 	} else {		/* quality == PRESENTATION */
854 	    gx_device_set_resolution(pdev, 600.0, 600.0);
855 	    cdj850->xscal = 1;
856 	    cdj850->yscal = 1;
857 	    /* intensities = 4 from initialization */
858 	}
859 	m = (gdev_pcl_paper_size(pdev) == PAPER_SIZE_A4 ? dj_a4 : dj_letter);
860 	break;
861     case DJ1600C:
862 	gx_device_set_resolution(pdev, 300.0, 300.0);
863 	m = m_cdj1600;
864 	break;
865     default:
866 	assert(0);
867     }
868     gx_device_set_margins(pdev, m, true);
869     return gdev_prn_open(pdev);
870 }
871 
872 /* Added parameters for DeskJet 850C */
873 private int
cdj850_get_params(gx_device * pdev,gs_param_list * plist)874 cdj850_get_params(gx_device * pdev, gs_param_list * plist)
875 {
876     int code = gdev_prn_get_params(pdev, plist);
877 
878     if (code < 0 ||
879 	(code = param_write_int(plist, "Quality", &cdj850->quality)) < 0 ||
880 	(code = param_write_int(plist, "Papertype", &cdj850->papertype)) < 0 ||
881 	(code = param_write_float(plist, "MasterGamma", &cdj850->gammavalc))
882 	< 0 ||
883 	(code = param_write_float(plist, "GammaValC", &cdj850->gammavalc)) <
884 	0 ||
885 	(code = param_write_float(plist, "GammaValM", &cdj850->gammavalm)) <
886 	0 ||
887 	(code = param_write_float(plist, "GammaValY", &cdj850->gammavaly)) <
888 	0 ||
889 	(code = param_write_float(plist, "GammaValK", &cdj850->gammavalk)) <
890 	0 ||
891 	(code = param_write_float(plist, "BlackCorrect",
892 				  &cdj850->blackcorrect)) < 0
893 	)
894 	return code;
895 
896     return code;
897 }
898 
899 private int
cdj850_put_params(gx_device * pdev,gs_param_list * plist)900 cdj850_put_params(gx_device * pdev, gs_param_list * plist)
901 {
902     int quality = cdj850->quality;
903     int papertype = cdj850->papertype;
904     float mastergamma = cdj850->mastergamma;
905     float gammavalc = cdj850->gammavalc;
906     float gammavalm = cdj850->gammavalm;
907     float gammavaly = cdj850->gammavaly;
908     float gammavalk = cdj850->gammavalk;
909     float blackcorrect = cdj850->blackcorrect;
910     int bpp = 0;
911     int code = 0;
912 
913     code = cdj_put_param_int(plist, "BitsPerPixel", &bpp, 1, 32, code);
914     code = cdj_put_param_int(plist, "Quality", &quality, 0, 2, code);
915     code = cdj_put_param_int(plist, "Papertype", &papertype, 0, 4, code);
916     code = cdj_put_param_float(plist, "MasterGamma", &mastergamma, 0.1, 9.0, code);
917     code = cdj_put_param_float(plist, "GammaValC", &gammavalc, 0.0, 9.0, code);
918     code = cdj_put_param_float(plist, "GammaValM", &gammavalm, 0.0, 9.0, code);
919     code = cdj_put_param_float(plist, "GammaValY", &gammavaly, 0.0, 9.0, code);
920     code = cdj_put_param_float(plist, "GammaValK", &gammavalk, 0.0, 9.0, code);
921     code = cdj_put_param_float(plist, "BlackCorrect", &blackcorrect, 0.0,
922 			       9.0, code);
923 
924 
925     if (code < 0)
926 	return code;
927     code = cdj_put_param_bpp(pdev, plist, bpp, bpp, 0);
928     if (code < 0)
929 	return code;
930 
931     cdj850->quality = quality;
932     cdj850->papertype = papertype;
933     cdj850->mastergamma = mastergamma;
934     cdj850->gammavalc = gammavalc;
935     cdj850->gammavalm = gammavalm;
936     cdj850->gammavaly = gammavaly;
937     cdj850->gammavalk = gammavalk;
938     cdj850->blackcorrect = blackcorrect;
939     return 0;
940 }
941 
942 /* ------ Internal routines ------ */
943 /* The DeskJet850C can compress (mode 9) */
944 
945 
946 /* Some convenient shorthand .. */
947 #define x_dpi        (pdev->x_pixels_per_inch)
948 #define y_dpi        (pdev->y_pixels_per_inch)
949 
950 /* To calculate buffer size as next greater multiple of both parameter and W */
951 #define calc_buffsize(a, b) (((((a) + ((b) * W) - 1) / ((b) * W))) * W)
952 
953 /* internal functions */
954 private void
955      FSDlinebw(P7(int scan, int plane_size,
956 		  struct error_val_field *error_values,
957 		  byte * kP,
958 		  int n, int *ep, byte * dp));
959 private void
960      FSDlinec2(P9(int scan, int plane_size,
961 		  struct error_val_field *error_values,
962 		  byte * cPa, byte * mPa, byte * yPa, int n,
963 		  byte * dp, int *ep));
964 private void
965      FSDlinec3(P12(int scan, int plane_size,
966 		   struct error_val_field *error_values,
967 		   byte * cPa, byte * mPa, byte * yPa,
968 		   byte * cPb, byte * mPb, byte * yPb,
969 		   int n, byte * dp, int *ep));
970 private void
971      FSDlinec4(P12(int scan, int plane_size,
972 		   struct error_val_field *error_values,
973 		   byte * cPa, byte * mPa, byte * yPa,
974 		   byte * cPb, byte * mPb, byte * yPb,
975 		   int n, byte * dp, int *ep));
976 private void
977      init_error_buffer(struct misc_struct *misc_vars,
978 		       struct ptr_arrays *data_ptrs);
979 private void
980      do_floyd_steinberg(P8(int scan, int cscan, int plane_size,
981 			   int plane_size_c, int n,
982 			   struct ptr_arrays *data_ptrs,
983 			   gx_device_printer * pdev,
984 			   struct error_val_field *error_values));
985 private int
986     do_gcr(P7(int bytecount, byte * inbyte, const byte * kvalues,
987 	      const byte * cvalues, const byte * mvalues,
988 	      const byte * yvalues, const int *kcorrect));
989 
990 /* UNUSED
991  *private int
992  *test_scan (P4(int size,
993  *            byte * current,
994  *            byte * last,
995  *            byte * control));
996  *private void
997  *save_color_data(P3(int size,
998  *                 byte * current,
999  *                 byte * saved));
1000  *
1001  */
1002 private void
1003      send_scan_lines(P6(gx_device_printer * pdev,
1004 			struct ptr_arrays *data_ptrs,
1005 			struct misc_struct *misc_vars,
1006 			struct error_val_field *error_values,
1007 			const Gamma *gamma,
1008 			FILE * prn_stream));
1009 private void
1010      do_gamma(P3(float mastergamma, float gammaval, byte * values));
1011 private void
1012      do_black_correction(P2(float kvalue, int *kcorrect));
1013 
1014 private void
1015      init_data_structure(P3(gx_device_printer * pdev,
1016 			    struct ptr_arrays *data_ptrs,
1017 			    struct misc_struct *misc_vars));
1018 private void
1019      calculate_memory_size(P2(gx_device_printer * pdev,
1020 			      struct misc_struct *misc_vars));
1021 
1022 
1023 private void
assign_dpi(int dpi,byte * msb)1024 assign_dpi(int dpi, byte * msb)
1025 {
1026     if (dpi == 600) {
1027 	msb[0] = 0x02;
1028 	msb[1] = 0x58;
1029     } else {
1030 	msb[0] = 0x01;
1031 	msb[1] = 0x2c;
1032     }
1033 }
1034 
1035 private void
cdj850_terminate_page(gx_device_printer * pdev,FILE * prn_stream)1036 cdj850_terminate_page(gx_device_printer * pdev, FILE * prn_stream)
1037 {
1038     fputs("0M", prn_stream);	/* Reset compression */
1039     fputs("\033*rC\033E", prn_stream);	/* End Graphics, Reset */
1040     fputs("\033&l0H", prn_stream);	/* eject page */
1041 }
1042 
1043 /* Here comes the hp850 output routine -------------------- */
1044 private int
cdj850_print_page(gx_device_printer * pdev,FILE * prn_stream)1045 cdj850_print_page(gx_device_printer * pdev, FILE * prn_stream)
1046 {
1047 
1048     struct error_val_field error_values;
1049     struct ptr_arrays data_ptrs;
1050     struct misc_struct misc_vars;
1051 
1052     Gamma gamma;
1053 
1054     /* make a local writable copy of the Gamma tables */
1055     memcpy(&gamma, gammat[cdj850->ptype], sizeof(Gamma));
1056     /* if mastergamma, don't use the built in functions */
1057     if (cdj850->mastergamma > 1.0) {
1058 	/* prepare the bw lookup table */
1059 	do_gamma(cdj850->mastergamma, cdj850->gammavalk, gamma.k);
1060 	/* prepare the color lookup table */
1061 	do_gamma(cdj850->mastergamma, cdj850->gammavalc, gamma.c);
1062 	do_gamma(cdj850->mastergamma, cdj850->gammavalm, gamma.m);
1063 	do_gamma(cdj850->mastergamma, cdj850->gammavaly, gamma.y);
1064     }
1065     /* prepare the black correction table for the unbunt mask */
1066     do_black_correction(cdj850->blackcorrect, gamma.correct);
1067 
1068     /* Calculate the needed memory */
1069     calculate_memory_size(pdev, &misc_vars);
1070 
1071     /* and allocate the memory */
1072 
1073     /* Since we need 600 and 300 dpi, we set up several buffers:
1074        storage contains the data as copied from gs, as well as the
1075        plane-data and the out_row buffer.
1076        storagec will contain the rescaled color data. It also contains the
1077        plane_data for the color-planes - these are needed by the
1078        compression routine, but would be overwritten by the
1079        b/w-dithering. The color planes allow for overwriting the
1080        color-data by the error-data. Since we might use the
1081        2bpp feature of the hp850 someday, it is sized like storage.
1082        storagee contains the errors from b/w fs-ditherng */
1083 
1084     data_ptrs.storage = (ulong *) gs_malloc(pdev->memory, misc_vars.storage_size_words, W,
1085 					    "cdj850_print_page");
1086 
1087     /* if we can't allocate working area */
1088     if (data_ptrs.storage == 0) {
1089 	return_error(gs_error_VMerror);
1090     }
1091     /* Initialise the needed pointers */
1092     init_data_structure(pdev, &data_ptrs, &misc_vars);
1093 
1094     /* Start Raster mode */
1095     (*cdj850->start_raster_mode) (pdev, misc_vars.paper_size, prn_stream);
1096 
1097     /* Send each scan line in turn */
1098     send_scan_lines(pdev, &data_ptrs, &misc_vars,
1099 		    &error_values, &gamma, prn_stream);
1100 
1101     /* terminate page and eject paper */
1102     (*cdj850->terminate_page) (pdev, prn_stream);
1103 
1104     /* Free Memory */
1105     gs_free(pdev->memory, (char *)data_ptrs.storage, misc_vars.storage_size_words, W,
1106 	    "hp850_print_page");
1107 
1108     return 0;
1109 }
1110 
1111 #define odd(i) ((i & 01) != 0)
1112 
1113 private int
GetScanLine(gx_device_printer * pdev,int * lnum,struct ptr_arrays * data_ptrs,struct misc_struct * misc_vars,word rmask)1114 GetScanLine(gx_device_printer * pdev, int *lnum,
1115 	    struct ptr_arrays *data_ptrs,
1116 	    struct misc_struct *misc_vars,
1117 	    word rmask)
1118 {
1119     word *data_words = (word *) data_ptrs->data[misc_vars->scan];
1120     register word *end_data = data_words + misc_vars->line_size_words;
1121 
1122     ++(*lnum);
1123     gdev_prn_copy_scan_lines(pdev, *lnum, (byte *) data_words, misc_vars->line_size);
1124 
1125     misc_vars->scan = 1 - misc_vars->scan;	/* toggle scan direction */
1126     misc_vars->is_two_pass = odd(*lnum);	/* color output for odd lines */
1127 
1128     /* Mask off 1-bits beyond the line width. */
1129     end_data[-1] &= rmask;
1130 
1131     /* Remove trailing 0s. */
1132     while (end_data > data_words && end_data[-1] == 0)
1133 	end_data--;
1134 
1135     return end_data - data_words;
1136 }
1137 
1138 /* Send the scan lines to the printer */
1139 private 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)1140 send_scan_lines(gx_device_printer * pdev,
1141 		struct ptr_arrays *data_ptrs,
1142 		struct misc_struct *misc_vars,
1143 		struct error_val_field *error_values,
1144 		const Gamma *gamma,
1145 		FILE * prn_stream)
1146 {
1147     int lnum, lend, llen;
1148     int num_blank_lines = 0;
1149 
1150     word rmask =
1151     ~(word) 0 << ((-pdev->width * misc_vars->storage_bpp) & (W * 8 - 1));
1152 
1153     lend = pdev->height - (dev_t_margin(pdev) + dev_b_margin(pdev)) * y_dpi;
1154 
1155     error_values->c = error_values->m = error_values->y =
1156 	error_values->k = 0;
1157 
1158     /* init the error buffer */
1159     init_error_buffer(misc_vars, data_ptrs);
1160 
1161     misc_vars->zero_row_count = 0;
1162     lnum = -1;
1163     llen = GetScanLine(pdev, &lnum, data_ptrs, misc_vars, rmask);
1164     while (lnum < lend) {
1165 	num_blank_lines = 0;
1166 	while (lnum < lend && llen == 0) {
1167 	    ++num_blank_lines;
1168 	    llen = GetScanLine(pdev, &lnum, data_ptrs, misc_vars, rmask);
1169 	}
1170 	if (lnum >= lend) {
1171 	    break;
1172 	}
1173 	/* Skip blank lines if any */
1174 	if (num_blank_lines > 0) {
1175 	    fprintf(prn_stream, "%dy", num_blank_lines / (cdj850->yscal + 1));
1176 	    memset(data_ptrs->plane_data[0][0], 0,
1177 		   (misc_vars->plane_size * 2 * misc_vars->num_comps));
1178 	    memset(data_ptrs->plane_data_c[0][0], 0,
1179 		   (misc_vars->plane_size_c * 2 * misc_vars->num_comps));
1180 
1181 	}
1182 	/* all blank lines printed, now for the non-blank lines */
1183 	if (cdj850->yscal && odd(lnum)) {
1184 	    /* output a blank black plane for odd lines */
1185 	    putc('v', prn_stream);
1186 	}
1187 	/* now output all non blank lines */
1188 	while (lnum < lend && llen != 0) {
1189 	    misc_vars->is_color_data = 0;	/* maybe we have color ? */
1190 	    (*cdj850->print_non_blank_lines) (pdev, data_ptrs, misc_vars,
1191 					      error_values, gamma, prn_stream);
1192 	    llen = GetScanLine(pdev, &lnum, data_ptrs, misc_vars, rmask);
1193 	}
1194 	if (cdj850->yscal && odd(lnum)) {	/* output empty line for odd lines */
1195 	    (*cdj850->print_non_blank_lines) (pdev, data_ptrs, misc_vars,
1196 					      error_values, gamma, prn_stream);
1197 	}
1198 	/* the current line is empty => run the next iteration */
1199     }
1200 }
1201 
1202 /* print_line compresses (mode 9) and outputs one plane */
1203 private void
print_c9plane(FILE * prn_stream,char plane_code,int plane_size,const byte * curr,const byte * prev,byte * out_data)1204 print_c9plane(FILE * prn_stream, char plane_code, int plane_size,
1205 	      const byte * curr, const byte * prev, byte * out_data)
1206 {
1207     /* Compress the output data */
1208     int out_count = gdev_pcl_mode9compress(plane_size, curr, prev, out_data);
1209 
1210     /* and output the data */
1211     if (out_count > 0) {
1212 	fprintf(prn_stream, "%d%c", out_count, plane_code);
1213 	fwrite(out_data, sizeof(byte), out_count, prn_stream);
1214     } else {
1215 	putc(plane_code, prn_stream);
1216     }
1217 }
1218 
1219 /* Printing non-blank lines */
1220 private 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)1221 cdj850_print_non_blank_lines(gx_device_printer * pdev,
1222 			     struct ptr_arrays *data_ptrs,
1223 			     struct misc_struct *misc_vars,
1224 			     struct error_val_field *error_values,
1225 			     const Gamma *gamma,
1226 			     FILE * prn_stream)
1227 {
1228     static const char *const plane_code[2] =
1229     {"wvvv", "vvvv"};
1230 
1231     int i;
1232     byte *kP = data_ptrs->plane_data[misc_vars->scan + 2][3];
1233     byte *dp = data_ptrs->data[misc_vars->scan + 2];
1234     int *ep = data_ptrs->errors[misc_vars->scan];
1235 
1236     /* we need cmyk color separation befor all the rest, since
1237        black may be contained in the color fields. This needs to
1238        be done on all pixel-rows, since even unused color-bytes
1239        might generate black */
1240 
1241     misc_vars->is_color_data =
1242 	do_gcr(misc_vars->databuff_size, data_ptrs->data[misc_vars->scan],
1243 	       gamma->k, gamma->c, gamma->m, gamma->y, gamma->correct);
1244 
1245     /* dithering the black-plane */
1246     FSDlinebw(misc_vars->scan, misc_vars->plane_size,
1247 	      error_values, kP, misc_vars->num_comps, ep, dp);
1248 
1249     /* output the black plane */
1250     print_c9plane(prn_stream, 'v', misc_vars->plane_size,
1251 		  data_ptrs->plane_data[misc_vars->scan][3],
1252 		  data_ptrs->plane_data[1 - misc_vars->scan][3],
1253 		  data_ptrs->out_data);
1254 
1255     /* since color resolution is only half of the b/w-resolution,
1256        we only output every second row */
1257     if (!cdj850->yscal || misc_vars->is_two_pass) {
1258 
1259 	int plane_size_c = (*rescale_color_plane[cdj850->xscal][cdj850->yscal])
1260 	(misc_vars->databuff_size,
1261 	 data_ptrs->data[misc_vars->scan],
1262 	 data_ptrs->data[1 - misc_vars->scan],
1263 	 data_ptrs->data_c[misc_vars->cscan]) / misc_vars->storage_bpp;
1264 
1265 	/* dither the color planes */
1266 	do_floyd_steinberg(misc_vars->scan, misc_vars->cscan,
1267 			   misc_vars->plane_size, plane_size_c,
1268 			   misc_vars->num_comps, data_ptrs, pdev, error_values);
1269 
1270 	/* Transfer raster graphics in the order C, M, Y, that is
1271 	   planes 2,1,0 */
1272 	for (i = misc_vars->num_comps - 2; i >= 0; i--) {
1273 
1274 	    /* output the lower color planes */
1275 	    print_c9plane(prn_stream, plane_code[cdj850->intensities > 2][i],
1276 			  plane_size_c,
1277 			  data_ptrs->plane_data_c[misc_vars->cscan][i],
1278 			  data_ptrs->plane_data_c[1 - misc_vars->cscan][i],
1279 			  data_ptrs->out_data);
1280 
1281 	    /* output the upper color planes */
1282 	    if (cdj850->intensities > 2) {
1283 		print_c9plane(prn_stream, plane_code[0][i], plane_size_c,
1284 			      data_ptrs->plane_data_c[misc_vars->cscan][i + 4],
1285 			      data_ptrs->plane_data_c[1 -
1286 									    misc_vars->cscan][i
1287 									    + 4],
1288 			      data_ptrs->out_data);
1289 	    }			/* end cdj850->intensities > 2 */
1290 	}			/* End For i = num_comps */
1291 	misc_vars->cscan = 1 - misc_vars->cscan;
1292     }				/* End of is_two_pass */
1293     return;
1294 }
1295 
1296 /* moved that code into his own subroutine, otherwise things get
1297    somewhat clumsy */
1298 private 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)1299 do_floyd_steinberg(int scan, int cscan, int plane_size,
1300 		   int plane_size_c, int n,
1301 		   struct ptr_arrays *data_ptrs,
1302 		   gx_device_printer * pdev,
1303 		   struct error_val_field *error_values)
1304 {
1305     /* the color pointers */
1306     byte *cPa, *mPa, *yPa, *cPb, *mPb, *yPb;
1307     byte *dpc;
1308     int *epc;
1309 
1310     /* the b/w pointers */
1311     byte *kP, *dp;
1312     int *ep;
1313 
1314     /* the color pointers, lower byte */
1315     cPa = data_ptrs->plane_data_c[cscan + 2][2];
1316     mPa = data_ptrs->plane_data_c[cscan + 2][1];
1317     yPa = data_ptrs->plane_data_c[cscan + 2][0];
1318     /* upper byte */
1319     cPb = data_ptrs->plane_data_c[cscan + 2][6];
1320     mPb = data_ptrs->plane_data_c[cscan + 2][5];
1321     yPb = data_ptrs->plane_data_c[cscan + 2][4];
1322     /* data and error */
1323     dpc = data_ptrs->data_c[cscan + 2];
1324     epc = data_ptrs->errors_c[cscan];
1325     /* the b/w pointers */
1326     kP = data_ptrs->plane_data[scan + 2][3];
1327     dp = data_ptrs->data[scan + 2];
1328     ep = data_ptrs->errors[scan];
1329 
1330     switch (cdj850->intensities) {
1331 	case 2:
1332 	FSDlinec2(cscan, plane_size_c, error_values,
1333 		  cPa, mPa, yPa, n, dpc, epc);
1334 	break;
1335 	case 3:
1336 	FSDlinec3(cscan, plane_size_c, error_values,
1337 		  cPa, mPa, yPa, cPb, mPb, yPb, n, dpc, epc);
1338 	break;
1339 	case 4:
1340 	FSDlinec4(cscan, plane_size_c, error_values,
1341 		  cPa, mPa, yPa, cPb, mPb, yPb, n, dpc, epc);
1342 	break;
1343 	default:
1344 	assert(0);
1345     }
1346     return;
1347 }
1348 
1349 /* here we do our own gamma-correction */
1350 private void
do_gamma(float mastergamma,float gammaval,byte values[256])1351 do_gamma(float mastergamma, float gammaval, byte values[256])
1352 {
1353     int i;
1354     float gamma;
1355 
1356     if (gammaval > 0.0) {
1357 	gamma = gammaval;
1358     } else {
1359 	gamma = mastergamma;
1360     }
1361 
1362     for (i = 0; i < 256; i++) {
1363 	values[i] = (byte) (255.0 *
1364 			    (1.0 - pow(((double)(255.0 - (float)i) / 255.0),
1365 			     (double)(1.0 / gamma))));
1366     }
1367 
1368     return;
1369 }
1370 
1371 /* here we calculate a lookup-table which is used to compensate the
1372    relativ loss of color due to undercolor-removal */
1373 private void
do_black_correction(float kvalue,int kcorrect[256])1374 do_black_correction(float kvalue, int kcorrect[256])
1375 {
1376     int i;
1377 
1378     for (i = 0; i < 256; i++) {
1379 	kcorrect[i] = (int)
1380 	    (100.0 * kvalue * (
1381 				  pow(10.0,
1382 				      pow((i / 255.0), 3.0)
1383 				  )
1384 				  - 1.0
1385 	     )
1386 	    );
1387     }
1388 
1389     return;
1390 }
1391 
1392 /* For Better Performance we use a macro here */
1393 #define DOUCR(col1, col2, col3, col4)\
1394 {\
1395   /* determine how far we are from the grey axis. This is  */\
1396   /* traditionally done by computing MAX(CMY)-MIN(CMY).    */\
1397   /* However, if two colors are very similar, we could     */\
1398   /* as either CMYRGB and K. Therefore we calculate the    */\
1399   /* the distance col1-col2 and col2-col3, and use the     */\
1400   /* smaller one.                                          */\
1401   a = *col1 - *col2;\
1402   b = *col2 - *col3;\
1403   if (a >= b) {\
1404     grey_distance = 1.0 - (b/255.0);\
1405   } else {\
1406     grey_distance = 1.0 - (a/255.0);\
1407   }\
1408   ucr   = (byte) (*col3 * grey_distance); \
1409   *col4 = *col4 + ucr;  /* add removed black to black */\
1410   /* remove only as much color as black is surviving the   */\
1411   /* gamma correction */\
1412   ucr   = *(kvalues + ucr);\
1413   *col1 = *col1 - ucr ;\
1414   *col2 = *col2 - ucr ;\
1415   *col3 = *col3 - ucr ;\
1416 }
1417 
1418 /* For Better Performance we use a macro here */
1419 #define DOGCR(col1, col2, col3, col4)\
1420 {\
1421   ucr = (int) *col3;\
1422   *col1 -= ucr ;\
1423   *col2 -= ucr ;\
1424   *col3 -= ucr ;\
1425   *col4 += ucr;  /* add removed black to black */\
1426   kadd  = ucr + *(kcorrect + ucr);\
1427   uca_fac = 1.0 + (kadd/255.0);\
1428   *col1 *= uca_fac;\
1429   *col2 *= uca_fac;\
1430 }
1431 
1432 /* Since resolution can be different on different planes, we need to
1433    do real color separation, here we try a real grey component
1434    replacement */
1435 private 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])1436 do_gcr(int bytecount, byte * inbyte, const byte kvalues[256],
1437        const byte cvalues[256], const byte mvalues[256],
1438        const byte yvalues[256], const int kcorrect[256])
1439 {
1440     int i, ucr, kadd, is_color = 0;
1441     byte *black, *cyan, *magenta, *yellow;
1442     float uca_fac;
1443 
1444     /* Grey component replacement */
1445     for (i = 0; i < bytecount; i += 4) {
1446 	black = inbyte++;	/* Assign to black the current address of  inbyte */
1447 	cyan = inbyte++;
1448 	magenta = inbyte++;
1449 	yellow = inbyte++;
1450 
1451 	if (*magenta + *yellow + *cyan > 0) {	/* if any color at all */
1452 
1453 	    is_color = 1;
1454 
1455 	    if ((*cyan >= *magenta)
1456 		&& (*magenta >= *yellow)
1457 		&& (*yellow > 0)) {	/* if any grey component */
1458 		DOGCR(cyan, magenta, yellow, black);
1459 	    } else if ((*cyan >= *yellow)
1460 		       && (*yellow >= *magenta)
1461 		       && (*magenta > 0)) {
1462 		DOGCR(cyan, yellow, magenta, black);
1463 	    } else if ((*yellow >= *magenta)
1464 		       && (*magenta >= *cyan)
1465 		       && (*cyan > 0)) {
1466 		DOGCR(yellow, magenta, cyan, black);
1467 	    } else if ((*yellow >= *cyan)
1468 		       && (*cyan >= *magenta)
1469 		       && (*magenta > 0)) {
1470 		DOGCR(yellow, cyan, magenta, black);
1471 	    } else if ((*magenta >= *yellow)
1472 		       && (*yellow >= *cyan)
1473 		       && (*cyan > 0)) {
1474 		DOGCR(magenta, yellow, cyan, black);
1475 	    } else if ((*magenta >= *cyan)
1476 		       && (*cyan >= *yellow)
1477 		       && (*yellow > 0)) {
1478 		DOGCR(magenta, cyan, yellow, black);
1479 	    } else {		/* do gamma only if no black */
1480 	    }
1481 	    *cyan = *(cvalues + *cyan);
1482 	    *magenta = *(mvalues + *magenta);
1483 	    *yellow = *(yvalues + *yellow);
1484 	}			/* end of if c+m+y > 0 */
1485 	*black = *(kvalues + *black);
1486     }				/* end of for bytecount */
1487     return is_color;
1488 }
1489 
1490 /* Since resolution can be different on different planes, we need to
1491    rescale the data byte by byte */
1492 private int
rescale_byte_wise2x2(int bytecount,const byte * inbytea,const byte * inbyteb,byte * outbyte)1493 rescale_byte_wise2x2(int bytecount, const byte * inbytea, const byte * inbyteb,
1494 		     byte * outbyte)
1495 {
1496     register int i, j;
1497     int max = bytecount / 2;
1498 
1499     for (i = 0; i < max; i += 4) {
1500 	j = 2 * i;
1501 	/* cyan */
1502 	outbyte[i + 1] = (inbytea[j + 1] + inbytea[j + 5] + inbyteb[j + 1] +
1503 			  inbyteb[j + 5]) / 4;
1504 	/* magenta */
1505 	outbyte[i + 2] = (inbytea[j + 2] + inbytea[j + 6] + inbyteb[j + 2] +
1506 			  inbyteb[j + 6]) / 4;
1507 	/* yellow */
1508 	outbyte[i + 3] = (inbytea[j + 3] + inbytea[j + 7] + inbyteb[j + 3] +
1509 			  inbyteb[j + 7]) / 4;
1510     }
1511     return max;
1512 }
1513 
1514 /* Since resolution can be different on different planes, we need to
1515    rescale the data byte by byte */
1516 private int
rescale_byte_wise2x1(int bytecount,const byte * inbytea,const byte * inbyteb,byte * outbyte)1517 rescale_byte_wise2x1(int bytecount, const byte * inbytea, const byte * inbyteb,
1518 		     byte * outbyte)
1519 {
1520     register int i, j;
1521     int max = bytecount / 2;
1522 
1523     for (i = 0; i < max; i += 4) {
1524 	j = 2 * i;
1525 	/* cyan */
1526 	outbyte[i + 1] = (inbytea[j + 1] + inbytea[j + 5]) / 2;
1527 	/* magenta */
1528 	outbyte[i + 2] = (inbytea[j + 2] + inbytea[j + 6]) / 2;
1529 	/* yellow */
1530 	outbyte[i + 3] = (inbytea[j + 3] + inbytea[j + 7]) / 2;
1531     }
1532     return max;
1533 }
1534 
1535 /* Since resolution can be different on different planes, we need to
1536    rescale the data byte by byte */
1537 private int
rescale_byte_wise1x2(int bytecount,const byte * inbytea,const byte * inbyteb,byte * outbyte)1538 rescale_byte_wise1x2(int bytecount, const byte * inbytea, const byte * inbyteb,
1539 		     byte * outbyte)
1540 {
1541     register int i;
1542 
1543     for (i = 0; i < bytecount; i += 4) {
1544 	/* cyan */
1545 	outbyte[i + 1] = (inbytea[i + 1] + inbyteb[i + 1]) / 2;
1546 	/* magenta */
1547 	outbyte[i + 2] = (inbytea[i + 2] + inbyteb[i + 2]) / 2;
1548 	/* yellow */
1549 	outbyte[i + 3] = (inbytea[i + 3] + inbyteb[i + 3]) / 2;
1550     }
1551     return bytecount;
1552 }
1553 
1554 /* Since resolution can be different on different planes, we need to
1555    rescale the data byte by byte */
1556 private int
rescale_byte_wise1x1(int bytecount,const byte * inbytea,const byte * inbyteb,byte * outbyte)1557 rescale_byte_wise1x1(int bytecount, const byte * inbytea, const byte * inbyteb,
1558 		     byte * outbyte)
1559 {
1560     register int i;
1561 
1562     for (i = 0; i < bytecount; i += 4) {
1563 	/* cyan */
1564 	outbyte[i + 1] = inbytea[i + 1];
1565 	/* magenta */
1566 	outbyte[i + 2] = inbytea[i + 2];
1567 	/* yellow */
1568 	outbyte[i + 3] = inbytea[i + 3];
1569     }
1570     return bytecount;
1571 }
1572 
1573 /* MACROS FOR DITHERING (we use macros for compact source and faster code) */
1574 /* Floyd-Steinberg dithering. Often results in a dramatic improvement in
1575  * subjective image quality, but can also produce dramatic increases in
1576  * amount of printer data generated and actual printing time!! Mode 9 2D
1577  * compression is still useful for fairly flat colour or blank areas but its
1578  * compression is much less effective in areas where the dithering has
1579  * effectively randomised the dot distribution. */
1580 
1581 #define RSHIFT ((I * 8) - 16)
1582 #define SHIFT ((I * 8) - 13)
1583 #define MAXVALUE  (255 << SHIFT)
1584 #define RANDOM (((rand() << RSHIFT) % (MAXVALUE / 2))  - MAXVALUE /4);
1585 #define MINVALUE  0
1586 #define C 8
1587 
1588 #define THRESHOLD (128 << SHIFT)
1589 
1590 /* --- needed for the hp850 -- */
1591 #define SHIFTS ((I * 8) - 14)
1592 #define SHIFTM ((I * 8) - 13)
1593 #define SHIFTL ((I * 8) - 12)
1594 
1595 #define MAXVALUES  (160 << SHIFTM)
1596 #define MAXVALUEM  (226 << SHIFTM)
1597 #define MAXVALUEL  (255 << SHIFTM)
1598 
1599 #define THRESHOLDS (128 << SHIFTM)
1600 #define THRESHOLDM (192 << SHIFTM)
1601 #define THRESHOLDL (226 << SHIFTM)
1602 /* --------------------------- */
1603 
1604 /* initialise the error_buffer */
1605 private void
init_error_buffer(struct misc_struct * misc_vars,struct ptr_arrays * data_ptrs)1606 init_error_buffer(struct misc_struct *misc_vars,
1607 		  struct ptr_arrays *data_ptrs)
1608 {
1609     int i;
1610     int *ep;
1611     int *epc;
1612 
1613     ep = data_ptrs->errors[0];
1614     epc = data_ptrs->errors_c[0];
1615 
1616     if (misc_vars->bits_per_pixel > 4) {	/* Randomly seed initial error
1617 						   buffer */
1618 	/* Otherwise, the first dithered rows would look rather uniform */
1619 	for (i = 0; i < misc_vars->databuff_size; i++) {	/* 600dpi planes */
1620 	    *ep++ = RANDOM;
1621 	}
1622 
1623 	/* Now for the 2 * 300dpi color planes */
1624 	for (i = 0; i < misc_vars->databuff_size_c; i++) {
1625 	    *epc++ = RANDOM;
1626 	}
1627     }
1628     return;
1629 }
1630 
1631 #define FSdither(inP, out, errP, Err, Bit, Offset, Element)\
1632 {\
1633    oldErr = Err;\
1634 	Err = (*(errP + Element)\
1635 	       + ((Err * 7 + C) >> 4)\
1636 	       + ((int)*(inP + Element) << SHIFT));\
1637 	if (Err > THRESHOLD) {\
1638 	  out |= Bit;\
1639 	  Err -= MAXVALUE;\
1640         }\
1641 	*(errP + (Element + Offset)) += ((Err * 3 + C) >> 4);\
1642 	*(errP + Element) = ((Err * 5 + oldErr + C) >> 4);\
1643 }
1644 
1645 /* The hp850c has 600dpi black and 300 dpi color. Therefore, we need
1646    an adapted dither algorythm */
1647 private void
FSDlinebw(int scan,int plane_size,struct error_val_field * error_values,byte * kP,int n,int * ep,byte * dp)1648 FSDlinebw(int scan, int plane_size,
1649 	  struct error_val_field *error_values,
1650 	  byte * kP, int n, int *ep, byte * dp)
1651 {
1652     if (scan == 0) {		/* going_up */
1653 	byte k, bitmask;	/* k = outbyte byte, whereas bitmask defines the
1654 
1655 				   bit to be set within k */
1656 	int oldErr, i;
1657 
1658 	for (i = 0; i < plane_size; i++) {
1659 	    bitmask = 0x80;
1660 	    for (k = 0; bitmask != 0; bitmask >>= 1) {
1661 		/* dp points to the first word of the input data which is in
1662 		   kcmy-format */
1663 		/* k points to the beginning of the first outbut byte, which
1664 		   is filled up, bit by bit while looping over bytemask */
1665 		/* ep points to the first word of the error-plane which
1666 		   contains the errors kcmy format */
1667 		/* err_values->k tempararily holds the error-value */
1668 		/* bitmask selects the bit to be set in the outbyte */
1669 		/* n gives the offset for the byte selection within
1670 		   words. With simple cmyk-printing, this should be 4 */
1671 		/* 0 points to the active color within the input-word, i.e. 0
1672 		   = black, 1 = cyan, 2 = yellow, 3 = magenta */
1673 
1674 		FSdither(dp, k, ep, error_values->k, bitmask, -n, 0);
1675 		dp += n, ep += n;	/* increment the input and error pointer one
1676 					   word (=4 byte) further, in order to
1677 					   convert the next word into an bit */
1678 	    }
1679 	    *kP++ = k;		/* fill the output-plane byte with the computet byte
1680 				   and increment the output plane pointer  one byte */
1681 	}
1682 
1683     } else {			/* going_down */
1684 	byte k, bitmask;
1685 	int oldErr, i;
1686 
1687 	for (i = 0; i < plane_size; i++) {
1688 	    bitmask = 0x01;
1689 	    for (k = 0; bitmask != 0; bitmask <<= 1) {
1690 		dp -= n, ep -= n;
1691 		FSdither(dp, k, ep, error_values->k, bitmask, n, 0);
1692 	    }
1693 	    *--kP = k;
1694 	}
1695     }
1696     return;
1697 }
1698 
1699 /* Since bw has already been dithered for the hp850c, we need
1700    an adapted dither algorythm */
1701 private 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)1702 FSDlinec2(int scan, int plane_size,
1703 	  struct error_val_field *error_values,
1704 	  byte * cPa, byte * mPa, byte * yPa, int n,
1705 	  byte * dp, int *ep)
1706 {
1707     if (scan == 0) {		/* going_up */
1708 	int oldErr, i;
1709 	byte ca, ya, ma, bitmask;
1710 
1711 	for (i = 0; i < plane_size; i++) {
1712 	    bitmask = 0x80;
1713 	    ca = ya = ma = 0;
1714 	    for (ca = 0; bitmask != 0; bitmask >>= 1) {
1715 		FSdither(dp, ca, ep, error_values->c, bitmask, -n, n - 3);
1716 		FSdither(dp, ma, ep, error_values->m, bitmask, -n, n - 2);
1717 		FSdither(dp, ya, ep, error_values->y, bitmask, -n, n - 1);
1718 		dp += n, ep += n;
1719 	    }
1720 	    *cPa++ = ca;
1721 	    *mPa++ = ma;
1722 	    *yPa++ = ya;
1723 	}
1724 
1725     } else {			/* going_down */
1726 	byte ca, ya, ma, bitmask;
1727 	int oldErr, i;
1728 
1729 	for (i = 0; i < plane_size; i++) {
1730 	    bitmask = 0x01;
1731 	    ca = ya = ma = 0;
1732 	    for (ca = 0; bitmask != 0; bitmask <<= 1) {
1733 		dp -= n, ep -= n;
1734 		FSdither(dp, ya, ep, error_values->y, bitmask, n, n - 1);
1735 		FSdither(dp, ma, ep, error_values->m, bitmask, n, n - 2);
1736 		FSdither(dp, ca, ep, error_values->c, bitmask, n, n - 3);
1737 	    }
1738 	    *--yPa = ya;
1739 	    *--mPa = ma;
1740 	    *--cPa = ca;
1741 	}
1742     }
1743     return;
1744 }
1745 
1746 /* while printing on paper, we only use 3 -intensities */
1747 #define FSdither8503(inP, outa, outb, errP, Err, Bit, Offset, Element)\
1748 {\
1749 	oldErr = Err;\
1750 	Err = (*(errP + Element)\
1751 	       + ((Err * 7 + C) >> 4)\
1752 	       + ((int) *(inP + Element) << SHIFT));\
1753 	if ((Err > THRESHOLDS) && (Err <= THRESHOLDM)) {\
1754 	  outa |= Bit;\
1755 	  Err -= MAXVALUES;\
1756 	}\
1757 	if (Err > THRESHOLDM) {\
1758 	  outb |= Bit;\
1759 	  Err -= MAXVALUEM;\
1760 	}\
1761 	*(errP + (Element + Offset)) += ((Err * 3 + C) >> 4);\
1762 	*(errP + Element) = ((Err * 5 + oldErr + C) >> 4);\
1763 }
1764 
1765 /* On ordinary paper, we'll only use 3 intensities with the hp850  */
1766 private 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)1767 FSDlinec3(int scan, int plane_size,
1768 	  struct error_val_field *error_values,
1769 	  byte * cPa, byte * mPa, byte * yPa,
1770 	  byte * cPb, byte * mPb, byte * yPb,
1771 	  int n, byte * dp, int *ep)
1772 {
1773     if (scan == 0) {		/* going_up */
1774 	byte ca, ya, ma, cb, yb, mb, bitmask;
1775 	int oldErr, i;
1776 
1777 	for (i = 0; i < plane_size; i++) {
1778 	    bitmask = 0x80;
1779 	    ca = ya = ma = cb = yb = mb = 0;
1780 	    for (ca = 0; bitmask != 0; bitmask >>= 1) {
1781 		FSdither8503(dp, ca, cb, ep, error_values->c, bitmask, -n, n
1782 			     - 3);
1783 		FSdither8503(dp, ma, mb, ep, error_values->m, bitmask, -n, n
1784 			     - 2);
1785 		FSdither8503(dp, ya, yb, ep, error_values->y, bitmask, -n, n
1786 			     - 1);
1787 		dp += n, ep += n;
1788 	    }
1789 	    *cPa++ = ca;
1790 	    *mPa++ = ma;
1791 	    *yPa++ = ya;
1792 	    *cPb++ = cb;
1793 	    *mPb++ = mb;
1794 	    *yPb++ = yb;
1795 	}
1796     } else {			/* going_down */
1797 	byte ca, ya, ma, cb, yb, mb, bitmask;
1798 	int oldErr, i;
1799 
1800 	for (i = 0; i < plane_size; i++) {
1801 	    bitmask = 0x01;
1802 	    ca = ya = ma = cb = yb = mb = 0;
1803 	    for (ca = 0; bitmask != 0; bitmask <<= 1) {
1804 		dp -= n, ep -= n;
1805 		FSdither8503(dp, ya, yb, ep, error_values->y, bitmask, n, n
1806 			     - 1);
1807 		FSdither8503(dp, ma, mb, ep, error_values->m, bitmask, n, n
1808 			     - 2);
1809 		FSdither8503(dp, ca, cb, ep, error_values->c, bitmask, n, n
1810 			     - 3);
1811 	    }
1812 	    *--yPa = ya;
1813 	    *--mPa = ma;
1814 	    *--cPa = ca;
1815 	    *--yPb = yb;
1816 	    *--mPb = mb;
1817 	    *--cPb = cb;
1818 	}
1819     }
1820     return;
1821 }
1822 
1823 
1824 /* the hp850 knows about 4 different color intensities per color */
1825 #define FSdither8504(inP, outa, outb, errP, Err, Bit, Offset, Element)\
1826 {\
1827 	oldErr = Err;\
1828 	Err = (*(errP + Element)\
1829 	       + ((Err * 7 + C) >> 4)\
1830 	       + ((int) *(inP + Element) << SHIFT));\
1831 	if ((Err > THRESHOLDS) && (Err <= THRESHOLDM)) {\
1832 	  outa |= Bit;\
1833 	  Err -= MAXVALUES;\
1834 	}\
1835 	if ((Err > THRESHOLDM) && (Err <= THRESHOLDL)) {\
1836 	  outb |= Bit;\
1837 	  Err -= MAXVALUEM;\
1838 	}\
1839 	if (Err > THRESHOLDL) {\
1840           outa |= Bit;\
1841 	  outb |= Bit;\
1842 	  Err -= MAXVALUEL;\
1843 	}\
1844 	*(errP + (Element + Offset)) += ((Err * 3 + C) >> 4);\
1845 	*(errP + Element) = ((Err * 5 + oldErr + C) >> 4);\
1846 }
1847 
1848 /* The hp850c knows about 4 intensity levels per color. Once more, we need
1849    an adapted dither algorythm */
1850 private 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)1851 FSDlinec4(int scan, int plane_size,
1852 	  struct error_val_field *error_values,
1853 	  byte * cPa, byte * mPa, byte * yPa,
1854 	  byte * cPb, byte * mPb, byte * yPb,
1855 	  int n, byte * dp, int *ep)
1856 {
1857     if (scan == 0) {		/* going_up */
1858 	byte ca, ya, ma, cb, yb, mb, bitmask;
1859 	int oldErr, i;
1860 
1861 	for (i = 0; i < plane_size; i++) {
1862 	    bitmask = 0x80;
1863 	    ca = ya = ma = cb = yb = mb = 0;
1864 	    for (ca = 0; bitmask != 0; bitmask >>= 1) {
1865 		FSdither8504(dp, ca, cb, ep, error_values->c, bitmask, -n, n
1866 			     - 3);
1867 		FSdither8504(dp, ma, mb, ep, error_values->m, bitmask, -n, n
1868 			     - 2);
1869 		FSdither8504(dp, ya, yb, ep, error_values->y, bitmask, -n, n
1870 			     - 1);
1871 		dp += n, ep += n;
1872 	    }
1873 	    *cPa++ = ca;
1874 	    *mPa++ = ma;
1875 	    *yPa++ = ya;
1876 	    *cPb++ = cb;
1877 	    *mPb++ = mb;
1878 	    *yPb++ = yb;
1879 	}
1880     } else {			/* going_down */
1881 	byte ca, ya, ma, cb, yb, mb, bitmask;
1882 	int oldErr, i;
1883 
1884 	for (i = 0; i < plane_size; i++) {
1885 	    bitmask = 0x01;
1886 	    ca = ya = ma = cb = yb = mb = 0;
1887 	    for (ca = 0; bitmask != 0; bitmask <<= 1) {
1888 		dp -= n, ep -= n;
1889 		FSdither8504(dp, ya, yb, ep, error_values->y, bitmask, n, n
1890 			     - 1);
1891 		FSdither8504(dp, ma, mb, ep, error_values->m, bitmask, n, n
1892 			     - 2);
1893 		FSdither8504(dp, ca, cb, ep, error_values->c, bitmask, n, n
1894 			     - 3);
1895 	    }
1896 	    *--yPa = ya;
1897 	    *--mPa = ma;
1898 	    *--cPa = ca;
1899 	    *--yPb = yb;
1900 	    *--mPb = mb;
1901 	    *--cPb = cb;
1902 	}
1903     }
1904     return;
1905 }
1906 
1907 
1908 /* calculate the needed memory */
1909 private void
calculate_memory_size(gx_device_printer * pdev,struct misc_struct * misc_vars)1910 calculate_memory_size(gx_device_printer * pdev,
1911 		      struct misc_struct *misc_vars)
1912 {
1913     int xfac = cdj850->xscal ? 2 : 1;
1914 
1915     misc_vars->line_size = gdev_prn_raster(pdev);
1916     misc_vars->line_size_c = misc_vars->line_size / xfac;
1917     misc_vars->line_size_words = (misc_vars->line_size + W - 1) / W;
1918     misc_vars->paper_size = gdev_pcl_paper_size((gx_device *) pdev);
1919     misc_vars->num_comps = pdev->color_info.num_components;
1920     misc_vars->bits_per_pixel = pdev->color_info.depth;
1921     misc_vars->storage_bpp = misc_vars->num_comps * 8;
1922     misc_vars->expanded_bpp = misc_vars->num_comps * 8;
1923     misc_vars->errbuff_size = 0;
1924     misc_vars->errbuff_size_c = 0;
1925 
1926     misc_vars->plane_size = calc_buffsize(misc_vars->line_size, misc_vars->storage_bpp);
1927 
1928     /* plane_size_c is dependedend on the bits used for
1929        dithering. Currently 2 bits are sufficient  */
1930     misc_vars->plane_size_c = 2 * misc_vars->plane_size / xfac;
1931 
1932     /* 4n extra values for line ends */
1933     /* might be wrong, see gdevcdj.c */
1934     misc_vars->errbuff_size =
1935 	calc_buffsize((misc_vars->plane_size * misc_vars->expanded_bpp +
1936 		       misc_vars->num_comps * 4) * I, 1);
1937 
1938     /* 4n extra values for line ends */
1939     misc_vars->errbuff_size_c =
1940 	calc_buffsize((misc_vars->plane_size_c / 2 * misc_vars->expanded_bpp
1941 		       + misc_vars->num_comps * 4) * I, 1);
1942 
1943     misc_vars->databuff_size =
1944 	misc_vars->plane_size * misc_vars->storage_bpp;
1945 
1946     misc_vars->databuff_size_c =
1947 	misc_vars->plane_size_c / 2 * misc_vars->storage_bpp;
1948 
1949 
1950     misc_vars->outbuff_size = misc_vars->plane_size * 4;
1951 
1952     misc_vars->storage_size_words = (((misc_vars->plane_size)
1953 				      * 2
1954 				      * misc_vars->num_comps)
1955 				     + misc_vars->databuff_size
1956 				     + misc_vars->errbuff_size
1957 				     + misc_vars->outbuff_size
1958 				     + ((misc_vars->plane_size_c)
1959 					* 2
1960 					* misc_vars->num_comps)
1961 				     + misc_vars->databuff_size_c
1962 				     + misc_vars->errbuff_size_c
1963 				     + (4 * misc_vars->plane_size_c))
1964 	/ W;
1965 
1966     return;
1967 }
1968 
1969 
1970 /* Initialise the needed pointers */
1971 private void
init_data_structure(gx_device_printer * pdev,struct ptr_arrays * data_ptrs,struct misc_struct * misc_vars)1972 init_data_structure(gx_device_printer * pdev,
1973 		    struct ptr_arrays *data_ptrs,
1974 		    struct misc_struct *misc_vars)
1975 {
1976     int i;
1977     byte *p = (byte *) data_ptrs->storage;
1978 
1979     misc_vars->scan = 0;
1980     misc_vars->cscan = 0;
1981     misc_vars->is_two_pass = 1;
1982 
1983     /* the b/w pointer */
1984     data_ptrs->data[0] = data_ptrs->data[1] = data_ptrs->data[2] = p;
1985     data_ptrs->data[3] = p + misc_vars->databuff_size;
1986     /* Note: The output data will overwrite part of the input-data */
1987 
1988     if (misc_vars->bits_per_pixel > 1) {
1989 	p += misc_vars->databuff_size;
1990     }
1991     if (misc_vars->bits_per_pixel > 4) {
1992 	data_ptrs->errors[0] = (int *)p + misc_vars->num_comps * 2;
1993 	data_ptrs->errors[1] = data_ptrs->errors[0] + misc_vars->databuff_size;
1994 	p += misc_vars->errbuff_size;
1995     }
1996     for (i = 0; i < misc_vars->num_comps; i++) {
1997 	data_ptrs->plane_data[0][i] = data_ptrs->plane_data[2][i] = p;
1998 	p += misc_vars->plane_size;
1999     }
2000     for (i = 0; i < misc_vars->num_comps; i++) {
2001 	data_ptrs->plane_data[1][i] = p;
2002 	data_ptrs->plane_data[3][i] = p + misc_vars->plane_size;
2003 	p += misc_vars->plane_size;
2004     }
2005     data_ptrs->out_data = p;
2006     p += misc_vars->outbuff_size;
2007 
2008     /* ---------------------------------------------------------
2009        now for the color pointers
2010        --------------------------------------------------------- */
2011 
2012     data_ptrs->data_c[0] = data_ptrs->data_c[1] = data_ptrs->data_c[2] = p;
2013     data_ptrs->data_c[3] = p + misc_vars->databuff_size_c;
2014     /* Note: The output data will overwrite part of the input-data */
2015 
2016     if (misc_vars->bits_per_pixel > 1) {
2017 	p += misc_vars->databuff_size_c;
2018     }
2019     if (misc_vars->bits_per_pixel > 4) {
2020 	data_ptrs->errors_c[0] = (int *)p + misc_vars->num_comps * 2;
2021 	data_ptrs->errors_c[1] = data_ptrs->errors_c[0] + misc_vars->databuff_size_c;
2022 	p += misc_vars->errbuff_size_c;
2023     }
2024     /* pointer for the lower bits of the output data */
2025     for (i = 0; i < misc_vars->num_comps; i++) {
2026 	data_ptrs->plane_data_c[0][i] = data_ptrs->plane_data_c[2][i] = p;
2027 	p += misc_vars->plane_size_c / 2;
2028     }
2029     for (i = 0; i < misc_vars->num_comps; i++) {
2030 	data_ptrs->plane_data_c[1][i] = p;
2031 	data_ptrs->plane_data_c[3][i] = p + misc_vars->plane_size_c / 2;
2032 	p += misc_vars->plane_size_c / 2;
2033     }
2034 
2035     /* pointer for the upper bits of the output data */
2036     for (i = 0; i < misc_vars->num_comps; i++) {
2037 	data_ptrs->plane_data_c[0][i + 4] = data_ptrs->plane_data_c[2][i +
2038 	    4] = p;
2039 	p += misc_vars->plane_size_c / 2;
2040     }
2041     for (i = 0; i < misc_vars->num_comps; i++) {
2042 	data_ptrs->plane_data_c[1][i + 4] = p;
2043 	data_ptrs->plane_data_c[3][i + 4] = p + misc_vars->plane_size_c / 2;
2044 	p += misc_vars->plane_size_c / 2;
2045     }
2046 
2047     for (i = 0; i < misc_vars->num_comps; i++) {
2048 	data_ptrs->test_data[i] = p;
2049 	p += misc_vars->plane_size_c / 2;
2050     }
2051 
2052     /* Clear temp storage */
2053     memset(data_ptrs->storage, 0, misc_vars->storage_size_words * W);
2054 
2055     return;
2056 }				/* end init_data_structure */
2057 
2058 /* Configure the printer and start Raster mode */
2059 private void
cdj850_start_raster_mode(gx_device_printer * pdev,int paper_size,FILE * prn_stream)2060 cdj850_start_raster_mode(gx_device_printer * pdev, int paper_size,
2061 			 FILE * prn_stream)
2062 {
2063     int xres, yres;		/* x,y resolution for color planes */
2064     hp850_cmyk_init_t init;
2065 
2066     init = hp850_cmyk_init;
2067     init.a[13] = cdj850->intensities;	/* Intensity levels cyan */
2068     init.a[19] = cdj850->intensities;	/* Intensity levels magenta */
2069     init.a[25] = cdj850->intensities;	/* Intensity levels yellow */
2070 
2071     /* black plane resolution */
2072     assign_dpi(cdj850->x_pixels_per_inch, init.a + 2);
2073     assign_dpi(cdj850->y_pixels_per_inch, init.a + 4);
2074     /* color plane resolution */
2075     xres = cdj850->x_pixels_per_inch / (cdj850->xscal + 1);
2076     yres = cdj850->y_pixels_per_inch / (cdj850->yscal + 1);
2077     /* cyan */
2078     assign_dpi(xres, init.a + 8);
2079     assign_dpi(yres, init.a + 10);
2080     /* magenta */
2081     assign_dpi(xres, init.a + 14);
2082     assign_dpi(yres, init.a + 16);
2083     /* yellow */
2084     assign_dpi(xres, init.a + 20);
2085     assign_dpi(yres, init.a + 22);
2086 
2087     fputs("\033*rbC", prn_stream);	/* End raster graphics */
2088     fputs("\033E", prn_stream);	/* Reset */
2089     /* Page size, orientation, top margin & perforation skip */
2090     fprintf(prn_stream, "\033&l%daolE", paper_size);
2091 
2092     /* Print Quality, -1 = draft, 0 = normal, 1 = presentation */
2093     fprintf(prn_stream, "\033*o%dM", cdj850->quality);
2094     /* Media Type,0 = plain paper, 1 = bond paper, 2 = special
2095        paper, 3 = glossy film, 4 = transparency film */
2096     fprintf(prn_stream, "\033&l%dM", cdj850->papertype);
2097 
2098     /* Move to top left of printed area */
2099     fprintf(prn_stream, "\033*p%dY", (int)(600 * DOFFSET));
2100 
2101     /* This will start and configure the raster-mode */
2102     fprintf(prn_stream, "\033*g%dW", (int)sizeof(init.a));	/* The new configure
2103 									   raster data comand */
2104     fwrite(init.a, sizeof(byte), sizeof(init.a),
2105 	   prn_stream);		/* Transmit config
2106 				   data */
2107     /* From now on, all escape commands start with \033*b, so we
2108      * combine them (if the printer supports this). */
2109     fputs("\033*b", prn_stream);
2110     /* Set compression if the mode has been defined. */
2111     if (cdj850->compression)
2112 	fprintf(prn_stream, "%dm", cdj850->compression);
2113 
2114     return;
2115 }				/* end configure raster-mode */
2116 
2117 private int
cdj_put_param_int(gs_param_list * plist,gs_param_name pname,int * pvalue,int minval,int maxval,int ecode)2118 cdj_put_param_int(gs_param_list * plist, gs_param_name pname, int *pvalue,
2119 		  int minval, int maxval, int ecode)
2120 {
2121     int code, value;
2122 
2123     switch (code = param_read_int(plist, pname, &value)) {
2124 	default:
2125 	return code;
2126 	case 1:
2127 	return ecode;
2128 	case 0:
2129 	if (value < minval || value > maxval)
2130 	    param_signal_error(plist, pname, gs_error_rangecheck);
2131 	*pvalue = value;
2132 	return (ecode < 0 ? ecode : 1);
2133     }
2134 }
2135 
2136 private int
cdj_put_param_float(gs_param_list * plist,gs_param_name pname,float * pvalue,float minval,float maxval,int ecode)2137 cdj_put_param_float(gs_param_list * plist, gs_param_name pname, float *pvalue,
2138 		    float minval, float maxval, int ecode)
2139 {
2140     int code;
2141     float value;
2142 
2143     switch (code = param_read_float(plist, pname, &value)) {
2144 	default:
2145 	return code;
2146 	case 1:
2147 	return ecode;
2148 	case 0:
2149 	if (value < minval || value > maxval)
2150 	    param_signal_error(plist, pname, gs_error_rangecheck);
2151 	*pvalue = value;
2152 	return (ecode < 0 ? ecode : 1);
2153     }
2154 }
2155 
2156 private int
cdj_set_bpp(gx_device * pdev,int bpp,int ccomps)2157 cdj_set_bpp(gx_device * pdev, int bpp, int ccomps)
2158 {
2159     gx_device_color_info *ci = &pdev->color_info;
2160 
2161     if (ccomps && bpp == 0) {
2162 	if (cprn_device->cmyk) {
2163 	    switch (ccomps) {
2164 		default:
2165 		return gs_error_rangecheck;
2166 		/*NOTREACHED */
2167 		break;
2168 
2169 		case 1:
2170 		bpp = 1;
2171 		break;
2172 
2173 		case 3:
2174 		bpp = 24;
2175 		break;
2176 
2177 		case 4:
2178 		switch (ci->depth) {
2179 		    case 8:
2180 		    case 16:
2181 		    case 24:
2182 		    case 32:
2183 		    break;
2184 
2185 		    default:
2186 		    bpp = cprn_device->default_depth;
2187 		    break;
2188 		}
2189 		break;
2190 	    }
2191 	}
2192     }
2193     if (bpp == 0) {
2194 	bpp = ci->depth;	/* Use the current setting. */
2195     }
2196     if (cprn_device->cmyk < 0) {
2197 
2198 	/* Reset procedures because we may have been in another mode. */
2199 
2200 	dev_proc(pdev, map_cmyk_color) = gdev_cmyk_map_cmyk_color;
2201 	dev_proc(pdev, map_rgb_color) = NULL;
2202 	dev_proc(pdev, map_color_rgb) = gdev_cmyk_map_color_rgb;
2203 
2204 	if (pdev->is_open)
2205 	    gs_closedevice(pdev);
2206     }
2207     /* Check for valid bpp values */
2208 
2209     switch (bpp) {
2210 	case 16:
2211 	case 32:
2212 	if (cprn_device->cmyk && ccomps && ccomps != 4)
2213 	    goto bppe;
2214 	break;
2215 
2216 	case 24:
2217 	if (!cprn_device->cmyk || ccomps == 0 || ccomps == 4) {
2218 	    break;
2219 	} else if (ccomps == 1) {
2220 	    goto bppe;
2221 	} else {
2222 
2223 	    /* 3 components 24 bpp printing for CMYK device. */
2224 
2225 	    cprn_device->cmyk = -1;
2226 	}
2227 	break;
2228 
2229 	case 8:
2230 	if (cprn_device->cmyk) {
2231 	    if (ccomps) {
2232 		if (ccomps == 3) {
2233 		    cprn_device->cmyk = -1;
2234 		    bpp = 3;
2235 		} else if (ccomps != 1 && ccomps != 4) {
2236 		    goto bppe;
2237 		}
2238 	    }
2239 	    if (ccomps != 1)
2240 		break;
2241 	} else {
2242 	    break;
2243 	}
2244 
2245 	case 1:
2246 	if (ccomps != 1)
2247 	    goto bppe;
2248 
2249 	if (cprn_device->cmyk && bpp != pdev->color_info.depth) {
2250 	    dev_proc(pdev, map_cmyk_color) = NULL;
2251 	    dev_proc(pdev, map_rgb_color) = gdev_cmyk_map_rgb_color;
2252 
2253 	    if (pdev->is_open) {
2254 		gs_closedevice(pdev);
2255 	    }
2256 	}
2257 	break;
2258 
2259 	case 3:
2260 	if (!cprn_device->cmyk) {
2261 	    break;
2262 	}
2263 	default:
2264       bppe:return gs_error_rangecheck;
2265     }
2266 
2267 
2268     if (cprn_device->cmyk == -1) {
2269 	dev_proc(pdev, map_cmyk_color) = NULL;
2270 	dev_proc(pdev, map_rgb_color) = gdev_pcl_map_rgb_color;
2271 	dev_proc(pdev, map_color_rgb) = gdev_pcl_map_color_rgb;
2272 
2273 	if (pdev->is_open) {
2274 	    gs_closedevice(pdev);
2275 	}
2276     }
2277     switch (ccomps) {
2278 	case 0:
2279 	break;
2280 
2281 	case 1:
2282 	if (bpp != 1 && bpp != 8)
2283 	    goto cce;
2284 	break;
2285 
2286 	case 4:
2287 	if (cprn_device->cmyk) {
2288 	    if (bpp >= 8)
2289 		break;
2290 	}
2291 	case 3:
2292 	if (bpp == 1 || bpp == 3 || bpp == 8 || bpp == 16
2293 	    || bpp == 24 || bpp == 32) {
2294 	    break;
2295 	}
2296 	cce: default:
2297 	return gs_error_rangecheck;
2298     }
2299 
2300     if (cprn_device->cmyk) {
2301 	if (cprn_device->cmyk > 0) {
2302 	    ci->num_components = ccomps ? ccomps : (bpp < 8 ? 1 : 4);
2303 	} else {
2304 	    ci->num_components = ccomps ? ccomps : (bpp < 8 ? 1 : 3);
2305 	}
2306 	if (bpp != 1 && ci->num_components == 1) {	/* We do dithered grays. */
2307 	    bpp = bpp < 8 ? 8 : bpp;
2308 	}
2309 	ci->max_color = (1 << (bpp >> 2)) - 1;
2310 	ci->max_gray = (bpp >= 8 ? 255 : 1);
2311 
2312 	if (ci->num_components == 1) {
2313 	    ci->dither_grays = (bpp >= 8 ? 5 : 2);
2314 	    ci->dither_colors = (bpp >= 8 ? 5 : bpp > 1 ? 2 : 0);
2315 	} else {
2316 	    ci->dither_grays = (bpp > 8 ? 5 : 2);
2317 	    ci->dither_colors = (bpp > 8 ? 5 : bpp > 1 ? 2 : 0);
2318 	}
2319     } else {
2320 	ci->num_components = (bpp == 1 || bpp == 8 ? 1 : 3);
2321 	ci->max_color = (bpp >= 8 ? 255 : bpp > 1 ? 1 : 0);
2322 	ci->max_gray = (bpp >= 8 ? 255 : 1);
2323 	ci->dither_grays = (bpp >= 8 ? 5 : 2);
2324 	ci->dither_colors = (bpp >= 8 ? 5 : bpp > 1 ? 2 : 0);
2325     }
2326 
2327     ci->depth = ((bpp > 1) && (bpp < 8) ? 8 : bpp);
2328 
2329     return 0;
2330 }
2331 
2332 /*
2333  * Map a CMYK color to a color index. We just use depth / 4 bits per color
2334  * to produce the color index.
2335  *
2336  * Important note: CMYK values are stored in the order K, C, M, Y because of
2337  * the way the HP drivers work.
2338  *
2339  */
2340 
2341 #define gx_color_value_to_bits(cv, b) \
2342     ((cv) >> (gx_color_value_bits - (b)))
2343 #define gx_bits_to_color_value(cv, b) \
2344     ((cv) << (gx_color_value_bits - (b)))
2345 
2346 #define gx_cmyk_value_bits(c, m, y, k, b) \
2347     ((gx_color_value_to_bits((k), (b)) << (3 * (b))) | \
2348      (gx_color_value_to_bits((c), (b)) << (2 * (b))) | \
2349      (gx_color_value_to_bits((m), (b)) << (b)) | \
2350      (gx_color_value_to_bits((y), (b))))
2351 
2352 #define gx_value_cmyk_bits(v, c, m, y, k, b) \
2353     (k) = gx_bits_to_color_value(((v) >> (3 * (b))) & ((1 << (b)) - 1), (b)), \
2354     (c) = gx_bits_to_color_value(((v) >> (2 * (b))) & ((1 << (b)) - 1), (b)), \
2355     (m) = gx_bits_to_color_value(((v) >> (b)) & ((1 << (b)) - 1), (b)), \
2356     (y) = gx_bits_to_color_value((v) & ((1 << (b)) - 1), (b))
2357 
2358 private gx_color_index
gdev_cmyk_map_cmyk_color(gx_device * pdev,gx_color_value * cmyk)2359 gdev_cmyk_map_cmyk_color(gx_device * pdev,
2360 		gx_color_value *cmyk)
2361 {
2362 
2363 	gx_color_value cyan=cmyk[0], magenta=cmyk[1], yellow=cmyk[3], black=cmyk[4];
2364 
2365     gx_color_index color;
2366 
2367     switch (pdev->color_info.depth) {
2368 	case 1:
2369 	color = (cyan | magenta | yellow | black) > gx_max_color_value / 2 ?
2370 	    (gx_color_index) 1 : (gx_color_index) 0;
2371 	break;
2372 
2373 	default:{
2374 	    int nbits = pdev->color_info.depth;
2375 
2376 	    if (cyan == magenta && magenta == yellow) {
2377 		/* Convert CMYK to gray -- Red Book 6.2.2 */
2378 		float bpart = ((float)cyan) * (lum_red_weight / 100.) +
2379 		((float)magenta) * (lum_green_weight / 100.) +
2380 		((float)yellow) * (lum_blue_weight / 100.) +
2381 		(float)black;
2382 
2383 		cyan = magenta = yellow = (gx_color_index) 0;
2384 		black = (gx_color_index) (bpart > gx_max_color_value ?
2385 					  gx_max_color_value : bpart);
2386 	    }
2387 	    color = gx_cmyk_value_bits(cyan, magenta, yellow, black,
2388 				       nbits >> 2);
2389 	}
2390     }
2391 
2392     return color;
2393 }
2394 
2395 /* Mapping of RGB colors to gray values. */
2396 
2397 private gx_color_index
gdev_cmyk_map_rgb_color(gx_device * pdev,gx_color_value rgb[3])2398 gdev_cmyk_map_rgb_color(gx_device * pdev, gx_color_value rgb[3])
2399 {
2400  gx_color_value r=rgb[0], g=rgb[1], b=rgb[2];
2401 
2402     if (gx_color_value_to_byte(r & g & b) == 0xff) {
2403 	return (gx_color_index) 0;	/* White */
2404     } else {
2405 	gx_color_value c = gx_max_color_value - r;
2406 	gx_color_value m = gx_max_color_value - g;
2407 	gx_color_value y = gx_max_color_value - b;
2408 
2409 	switch (pdev->color_info.depth) {
2410 	    case 1:
2411 	    return (c | m | y) > gx_max_color_value / 2 ?
2412 		(gx_color_index) 1 : (gx_color_index) 0;
2413 	    /*NOTREACHED */
2414 	    break;
2415 
2416 	    case 8:
2417 	    return ((ulong) c * lum_red_weight * 10
2418 		    + (ulong) m * lum_green_weight * 10
2419 		    + (ulong) y * lum_blue_weight * 10)
2420 		>> (gx_color_value_bits + 2);
2421 	    /*NOTREACHED */
2422 	    break;
2423 	}
2424     }
2425 
2426     return (gx_color_index) 0;	/* This should never happen. */
2427 }
2428 
2429 /* Mapping of CMYK colors. */
2430 private int
gdev_cmyk_map_color_rgb(gx_device * pdev,gx_color_index color,gx_color_value prgb[3])2431 gdev_cmyk_map_color_rgb(gx_device * pdev, gx_color_index color,
2432 			gx_color_value prgb[3])
2433 {
2434     switch (pdev->color_info.depth) {
2435 	case 1:
2436 	prgb[0] = prgb[1] = prgb[2] = gx_max_color_value * (1 - color);
2437 	break;
2438 
2439 	case 8:
2440 	if (pdev->color_info.num_components == 1) {
2441 	    gx_color_value value = (gx_color_value) color ^ 0xff;
2442 
2443 	    prgb[0] = prgb[1] = prgb[2] = (value << 8) + value;
2444 
2445 	    break;
2446 	}
2447 	default:{
2448 	    unsigned long bcyan, bmagenta, byellow, black;
2449 	    int nbits = pdev->color_info.depth;
2450 
2451 	    gx_value_cmyk_bits(color, bcyan, bmagenta, byellow, black,
2452 			       nbits >> 2);
2453 
2454 #ifdef USE_ADOBE_CMYK_RGB
2455 
2456 	    /* R = 1.0 - min(1.0, C + K), etc. */
2457 
2458 	    bcyan += black, bmagenta += black, byellow += black;
2459 	    prgb[0] = (bcyan > gx_max_color_value ? (gx_color_value) 0 :
2460 		       gx_max_color_value - bcyan);
2461 	    prgb[1] = (bmagenta > gx_max_color_value ? (gx_color_value) 0 :
2462 		       gx_max_color_value - bmagenta);
2463 	    prgb[2] = (byellow > gx_max_color_value ? (gx_color_value) 0 :
2464 		       gx_max_color_value - byellow);
2465 
2466 #else
2467 
2468 	    /* R = (1.0 - C) * (1.0 - K), etc. */
2469 
2470 	    prgb[0] = (gx_color_value)
2471 		((ulong) (gx_max_color_value - bcyan) *
2472 		 (gx_max_color_value - black) / gx_max_color_value);
2473 	    prgb[1] = (gx_color_value)
2474 		((ulong) (gx_max_color_value - bmagenta) *
2475 		 (gx_max_color_value - black) / gx_max_color_value);
2476 	    prgb[2] = (gx_color_value)
2477 		((ulong) (gx_max_color_value - byellow) *
2478 		 (gx_max_color_value - black) / gx_max_color_value);
2479 
2480 #endif
2481 
2482 	}
2483     }
2484 
2485     return 0;
2486 }
2487 
2488 private gx_color_index
gdev_pcl_map_rgb_color(gx_device * pdev,gx_color_value * rgb)2489 gdev_pcl_map_rgb_color(gx_device * pdev, gx_color_value *rgb)
2490 {
2491 gx_color_value r=rgb[0], g=rgb[1], b=rgb[2];
2492 
2493     if (gx_color_value_to_byte(r & g & b) == 0xff)
2494 	return (gx_color_index) 0;	/* white */
2495     else {
2496 	gx_color_value c = gx_max_color_value - r;
2497 	gx_color_value m = gx_max_color_value - g;
2498 	gx_color_value y = gx_max_color_value - b;
2499 
2500 	switch (pdev->color_info.depth) {
2501 	    case 1:
2502 	    return ((c | m | y) > gx_max_color_value / 2 ?
2503 		    (gx_color_index) 1 : (gx_color_index) 0);
2504 	    case 8:
2505 	    if (pdev->color_info.num_components >= 3)
2506 #define gx_color_value_to_1bit(cv) ((cv) >> (gx_color_value_bits - 1))
2507 		return (gx_color_value_to_1bit(c) +
2508 			(gx_color_value_to_1bit(m) << 1) +
2509 			(gx_color_value_to_1bit(y) << 2));
2510 	    else
2511 #define red_weight 306
2512 #define green_weight 601
2513 #define blue_weight 117
2514 		return ((((ulong) c * red_weight +
2515 			  (ulong) m * green_weight +
2516 			  (ulong) y * blue_weight)
2517 			 >> (gx_color_value_bits + 2)));
2518 	    case 16:
2519 #define gx_color_value_to_5bits(cv) ((cv) >> (gx_color_value_bits - 5))
2520 #define gx_color_value_to_6bits(cv) ((cv) >> (gx_color_value_bits - 6))
2521 	    return (gx_color_value_to_5bits(y) +
2522 		    (gx_color_value_to_6bits(m) << 5) +
2523 		    (gx_color_value_to_5bits(c) << 11));
2524 	    case 24:
2525 	    return (gx_color_value_to_byte(y) +
2526 		    (gx_color_value_to_byte(m) << 8) +
2527 		    ((ulong) gx_color_value_to_byte(c) << 16));
2528 	    case 32:
2529 	    {
2530 		return ((c == m && c == y) ? ((ulong)
2531 					      gx_color_value_to_byte(c) << 24)
2532 			: (gx_color_value_to_byte(y) +
2533 			   (gx_color_value_to_byte(m) << 8) +
2534 			   ((ulong) gx_color_value_to_byte(c) << 16)));
2535 	    }
2536 	}
2537     }
2538     return (gx_color_index) 0;	/* This never happens */
2539 }
2540 
2541 /* Map a color index to a r-g-b color. */
2542 private int
gdev_pcl_map_color_rgb(gx_device * pdev,gx_color_index color,gx_color_value prgb[3])2543 gdev_pcl_map_color_rgb(gx_device * pdev, gx_color_index color,
2544 		       gx_color_value prgb[3])
2545 {
2546     /* For the moment, we simply ignore any black correction */
2547     switch (pdev->color_info.depth) {
2548 	case 1:
2549 	prgb[0] = prgb[1] = prgb[2] = -((gx_color_value) color ^ 1);
2550 	break;
2551 	case 8:
2552 	if (pdev->color_info.num_components >= 3) {
2553 	    gx_color_value c = (gx_color_value) color ^ 7;
2554 
2555 	    prgb[0] = -(c & 1);
2556 	    prgb[1] = -((c >> 1) & 1);
2557 	    prgb[2] = -(c >> 2);
2558 	} else {
2559 	    gx_color_value value = (gx_color_value) color ^ 0xff;
2560 
2561 	    prgb[0] = prgb[1] = prgb[2] = (value << 8) + value;
2562 	}
2563 	break;
2564 	case 16:
2565 	{
2566 	    gx_color_value c = (gx_color_value) color ^ 0xffff;
2567 	    ushort value = c >> 11;
2568 
2569 	    prgb[0] = ((value << 11) + (value << 6) + (value << 1) +
2570 		       (value >> 4)) >> (16 - gx_color_value_bits);
2571 	    value = (c >> 6) & 0x3f;
2572 	    prgb[1] = ((value << 10) + (value << 4) + (value >> 2))
2573 		>> (16 - gx_color_value_bits);
2574 	    value = c & 0x1f;
2575 	    prgb[2] = ((value << 11) + (value << 6) + (value << 1) +
2576 		       (value >> 4)) >> (16 - gx_color_value_bits);
2577 	}
2578 	break;
2579 	case 24:
2580 	{
2581 	    gx_color_value c = (gx_color_value) color ^ 0xffffff;
2582 
2583 	    prgb[0] = gx_color_value_from_byte(c >> 16);
2584 	    prgb[1] = gx_color_value_from_byte((c >> 8) & 0xff);
2585 	    prgb[2] = gx_color_value_from_byte(c & 0xff);
2586 	}
2587 	break;
2588 	case 32:
2589 #define  gx_maxcol gx_color_value_from_byte(gx_color_value_to_byte(gx_max_color_value))
2590 	{
2591 	    gx_color_value w = gx_maxcol - gx_color_value_from_byte(color >> 24);
2592 
2593 	    prgb[0] = w - gx_color_value_from_byte((color >> 16) & 0xff);
2594 	    prgb[1] = w - gx_color_value_from_byte((color >> 8) & 0xff);
2595 	    prgb[2] = w - gx_color_value_from_byte(color & 0xff);
2596 	}
2597 	break;
2598     }
2599     return 0;
2600 }
2601 
2602 /* new_bpp == save_bpp or new_bpp == 0 means don't change bpp.
2603    ccomps == 0 means don't change number of color comps.
2604    If new_bpp != 0, it must be the value of the BitsPerPixel element of
2605    the plist; real_bpp may differ from new_bpp.
2606  */
2607 private int
cdj_put_param_bpp(gx_device * pdev,gs_param_list * plist,int new_bpp,int real_bpp,int ccomps)2608 cdj_put_param_bpp(gx_device * pdev, gs_param_list * plist, int new_bpp,
2609 		  int real_bpp, int ccomps)
2610 {
2611     if (new_bpp == 0 && ccomps == 0)
2612 	return gdev_prn_put_params(pdev, plist);
2613     else {
2614 	gx_device_color_info save_info;
2615 	int save_bpp;
2616 	int code;
2617 
2618 	save_info = pdev->color_info;
2619 	save_bpp = save_info.depth;
2620 #define save_ccomps save_info.num_components
2621 	if (save_bpp == 8 && save_ccomps == 3 && !cprn_device->cmyk)
2622 	    save_bpp = 3;
2623 	code = cdj_set_bpp(pdev, real_bpp, ccomps);
2624 	if (code < 0) {
2625 	    param_signal_error(plist, "BitsPerPixel", code);
2626 	    param_signal_error(plist, "ProcessColorModel", code);
2627 	    return code;
2628 	}
2629 	pdev->color_info.depth = new_bpp;	/* cdj_set_bpp maps 3/6 to 8 */
2630 	code = gdev_prn_put_params(pdev, plist);
2631 	if (code < 0) {
2632 	    cdj_set_bpp(pdev, save_bpp, save_ccomps);
2633 	    return code;
2634 	}
2635 	cdj_set_bpp(pdev, real_bpp, ccomps);	/* reset depth if needed */
2636 	if ((cdj850->color_info.depth != save_bpp ||
2637 	     (ccomps != 0 && ccomps != save_ccomps))
2638 	    && pdev->is_open)
2639 	    return gs_closedevice(pdev);
2640 	return 0;
2641 #undef save_ccomps
2642     }
2643 }
2644 
2645 /* the following code was in the original driver but is unused
2646 
2647  * private int
2648  * x_mul_div (int a, int b, int c)
2649  * {
2650  *   int result;
2651  *
2652  *   result = (int) ((a * b) / c) ;
2653  *  return result;
2654  * }
2655  *
2656  * private void
2657  * save_color_data(int size,
2658  *              byte * current,
2659  *              byte * saved)
2660  * {
2661  *   int i;
2662  *   for (i=0;i<size;i++){
2663  *     *saved++ = *current++;
2664  *   }
2665  *   return;
2666  * }
2667  *
2668  * private int
2669  * test_scan (int size,
2670  *         byte * current,
2671  *         byte * last,
2672  *         byte * control)
2673  *   {
2674  *   int error = 0;
2675  *   int i;
2676  *
2677  *   for (i=0;i<size;i++){
2678  *     if (*control != *last){
2679  *       error = 1;
2680  *     }
2681  *     *control = *current;
2682  *
2683  *     control++;
2684  *     last++;
2685  *     current++;
2686  *   }
2687  *   return error;
2688  * }
2689  *
2690  * * Transform from cmy into hsv
2691  * private void
2692  * cmy2hsv(int *c, int *m, int *y, int *h, int *s, int *v)
2693  * {
2694  *   int hue;
2695  *   int r, g, b;
2696  *   int r1, g1, b1;
2697  *   int maxValue, minValue, diff;
2698  *
2699  *   r = 255 - *c;
2700  *   g = 255 - *m;
2701  *   b = 255 - *y;
2702  *
2703  *   maxValue = max(r, max(g,b));
2704  *   minValue = min(r,min(g,b));
2705  *   diff = maxValue - minValue;
2706  *   *v = maxValue;
2707  *
2708  *   if (maxValue != 0)
2709  *     *s = x_mul_div(diff,255,maxValue);
2710  *   else
2711  *     *s = 0;
2712  *
2713  *   if (*s == 0)
2714  *     {
2715  *       hue = 0;
2716  *     }
2717  *   else
2718  *     {
2719  *       r1 = x_mul_div(maxValue - r,255,diff);
2720  *       g1 = x_mul_div(maxValue - g,255,diff);
2721  *       b1 = x_mul_div(maxValue - b,255,diff);
2722  *
2723  *       if (r == maxValue)
2724  *      hue = b1 - g1;
2725  *       else if (g == maxValue)
2726  *      hue = 510 + r1 - b1;
2727  *       else
2728  *      hue = 1020 + g1 - r1;
2729  *
2730  *       if (hue < 0)
2731  *      hue += 1530;
2732  *     }
2733  *
2734  *   *h = (hue + 3) / 6;
2735  *
2736  *   return;
2737  * }
2738  * end of unused code */
2739 
2740 
2741 /************************ the routines for the cdj1600 printer ***************/
2742 
2743 /* Configure the printer and start Raster mode */
2744 private void
cdj1600_start_raster_mode(gx_device_printer * pdev,int paper_size,FILE * prn_stream)2745 cdj1600_start_raster_mode(gx_device_printer * pdev, int paper_size,
2746 			  FILE * prn_stream)
2747 {
2748     uint raster_width = pdev->width -
2749     pdev->x_pixels_per_inch * (dev_l_margin(pdev) + dev_r_margin(pdev));
2750 
2751     /* switch to PCL control language */
2752     fputs("\033%-12345X@PJL enter language = PCL\n", prn_stream);
2753 
2754     fputs("\033*rbC", prn_stream);	/* End raster graphics */
2755     fputs("\033E", prn_stream);	/* Reset */
2756 
2757     /* resolution */
2758     fprintf(prn_stream, "\033*t%dR", (int)cdj850->x_pixels_per_inch);
2759 
2760     /* Page size, orientation, top margin & perforation skip */
2761     fprintf(prn_stream, "\033&l%daolE", paper_size);
2762 
2763     /* no negative motion */
2764     fputs("\033&a1N", prn_stream);
2765 
2766     /* Print Quality, -1 = draft, 0 = normal, 1 = presentation */
2767     fprintf(prn_stream, "\033*o%dQ", cdj850->quality);
2768 
2769     /* Media Type,0 = plain paper, 1 = bond paper, 2 = special
2770        paper, 3 = glossy film, 4 = transparency film */
2771     fprintf(prn_stream, "\033&l%dM", cdj850->papertype);
2772 
2773     /* Move to top left of printed area */
2774     fprintf(prn_stream, "\033*p%dY", (int)(300.0 * DOFFSET));
2775 
2776     /* raster width and number of planes */
2777     fprintf(prn_stream, "\033*r%ds-%du0A",
2778 	    raster_width, pdev->color_info.num_components);
2779 
2780     /* start raster graphics */
2781     fputs("\033*r1A", prn_stream);
2782 
2783     /* From now on, all escape commands start with \033*b, so we
2784      * combine them (if the printer supports this). */
2785     fputs("\033*b", prn_stream);
2786 
2787     /* Set compression if the mode has been defined. */
2788     if (cdj850->compression)
2789 	fprintf(prn_stream, "%dm", cdj850->compression);
2790 
2791     return;
2792 }				/* end configure raster-mode */
2793 
2794 /* print_plane compresses (mode 3) and outputs one plane */
2795 private void
print_c3plane(FILE * prn_stream,char plane_code,int plane_size,const byte * curr,byte * prev,byte * out_data)2796 print_c3plane(FILE * prn_stream, char plane_code, int plane_size,
2797 	      const byte * curr, byte * prev, byte * out_data)
2798 {
2799     /* Compress the output data */
2800     int out_count = gdev_pcl_mode3compress(plane_size, curr, prev, out_data);
2801 
2802     /* and output the data */
2803     if (out_count > 0) {
2804 	fprintf(prn_stream, "%d%c", out_count, plane_code);
2805 	fwrite(out_data, sizeof(byte), out_count, prn_stream);
2806     } else {
2807 	putc(plane_code, prn_stream);
2808     }
2809 }
2810 
2811 private int
copy_color_data(byte * dest,const byte * src,int n)2812 copy_color_data(byte * dest, const byte * src, int n)
2813 {
2814     /* copy word by word */
2815     register int i = n / 4;
2816     register word *d = (word *) dest;
2817     register const word *s = (const word *)src;
2818 
2819     while (i-- > 0) {
2820 	*d++ = *s++;
2821     }
2822     return n;
2823 }
2824 
2825 /* Printing non-blank lines */
2826 private 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)2827 cdj1600_print_non_blank_lines(gx_device_printer * pdev,
2828 			      struct ptr_arrays *data_ptrs,
2829 			      struct misc_struct *misc_vars,
2830 			      struct error_val_field *error_values,
2831 			      const Gamma *gamma,
2832 			      FILE * prn_stream)
2833 {
2834     int i, plane_size_c;
2835 
2836     /* copy data to data_c in order to make do_floyd_steinberg work */
2837     plane_size_c = copy_color_data
2838 	(data_ptrs->data_c[misc_vars->cscan],
2839 	 data_ptrs->data[misc_vars->scan],
2840 	 misc_vars->databuff_size) / misc_vars->storage_bpp;
2841 
2842     /* dither the color planes */
2843     do_floyd_steinberg(misc_vars->scan, misc_vars->cscan,
2844 		       misc_vars->plane_size, plane_size_c,
2845 		       misc_vars->num_comps, data_ptrs, pdev, error_values);
2846 
2847     /* Transfer raster graphics in the order C, M, Y, that is
2848        planes 2,1,0 */
2849     for (i = misc_vars->num_comps - 1; i >= 0; i--) {
2850 
2851 	/* output the lower color planes */
2852 	print_c3plane(prn_stream, "wvv"[i], plane_size_c,
2853 		      data_ptrs->plane_data_c[misc_vars->cscan][i],
2854 		      data_ptrs->plane_data_c[1 - misc_vars->cscan][i],
2855 		      data_ptrs->out_data);
2856     }				/* End For i = num_comps */
2857     misc_vars->cscan = 1 - misc_vars->cscan;
2858 }
2859 
2860 private void
cdj1600_terminate_page(gx_device_printer * pdev,FILE * prn_stream)2861 cdj1600_terminate_page(gx_device_printer * pdev, FILE * prn_stream)
2862 {
2863     cdj850_terminate_page(pdev, prn_stream);
2864     fputs("\033%-12345X", prn_stream);
2865 }
2866