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