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