Subversion Repositories planix.SVN

Rev

Rev 2 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
2 - 1
/* Copyright (C) 1991, 1995-2001 artofcode LLC.  All rights reserved.
2
 
3
  This software is provided AS-IS with no warranty, either express or
4
  implied.
5
 
6
  This software is distributed under license and may not be copied,
7
  modified or distributed except as expressly authorized under the terms
8
  of the license contained in the file LICENSE in this distribution.
9
 
10
  For more information about licensing, please refer to
11
  http://www.ghostscript.com/licensing/. For information on
12
  commercial licensing, go to http://www.artifex.com/licensing/ or
13
  contact Artifex Software, Inc., 101 Lucas Valley Road #110,
14
  San Rafael, CA  94903, U.S.A., +1(415)492-9861.
15
*/
16
 
17
/* $Id: gdevcdj.c,v 1.15 2004/08/04 19:36:12 stefan Exp $*/
18
/* HP and Canon colour printer drivers */
19
 
20
/****************************************************************
21
 * The code in this file was contributed by the authors whose names and/or
22
 * e-mail addresses appear below: Aladdin Enterprises takes no
23
 * responsibility for it.  In the past, we have tried to keep it working,
24
 * but too many users have made too many "improvements" without regard to
25
 * the overall structure; the last three "improvements" required me to spend
26
 * several hours fixing each one so that the code worked again at all.  For
27
 * this reason, no further changes to this file will be accepted.  We are
28
 * planning eventually to get these drivers rewritten from scratch.
29
 *
30
 *				L. Peter Deutsch
31
 *				Aladdin Enterprises
32
 *				February 28, 1996
33
 ****************************************************************/
34
 
35
/*
36
 * Change history:
37
 *	2000-08-20 Jonathan Kamens <jik@kamens.brookline.ma.us>:
38
 *	  change to support printers with different X and Y resolution.
39
 */
40
 
41
/*
42
 * Important compilation notes (YA).
43
 *
44
 * You may also try the cdj550cmyk driver after having defined
45
 * USE_CDJ550_CMYK and added the needed definition in devs.mak. Not tried!
46
 * (I have a BJC!) Also note that modes descriptions of CMYK printing
47
 * is done under the BJC section of devices.doc.
48
 *
49
 * CMYK to RGB conversion is made a la GhostScript unless you define
50
 * the preprocessor symbol USE_ADOBE_CMYK_RGB.
51
 *
52
 *   Ghostscript:	R = (1.0 - C) * (1.0 - K)
53
 *   Adobe:		R = 1.0 - min(1.0, C + K)
54
 *
55
 * (and similarly for G and B).  Ghostscript claims its method achieves
56
 * better results.
57
 *
58
 * For the BJC drivers, define BJC_DEFAULT_CENTEREDAREA if you want to
59
 * have the  same top and bottom margins (default to use the tallest
60
 * imageable area available, usually with a top margin smaller than
61
 * the bottom one). Defining USE_RECOMMENDED_MARGINS has the same
62
 * effect and also sets these margins to 12.4 mm. Other compilation
63
 * defines are explained in devices.doc.
64
 *
65
 * You can also define BJC_INIT_800_AS_600 to not use BJC-800-specific code
66
 * in the page initialization sequence (normally not useful to you at all,
67
 * just for my debugging of the driver margins).
68
 *
69
 */
70
 
71
#include "std.h"		/* to stop stdlib.h redefining types */
72
#include <stdlib.h>		/* for rand() */
73
#include "gdevprn.h"
74
#include "gdevpcl.h"
75
#include "gsparam.h"
76
#include "gsstate.h"
77
 
78
/* Conversion stuff. */
79
#include "gxlum.h"
80
 
81
/* Canon stuff */
82
 
83
#include "gdevbjc.h"
84
 
85
/***
86
 *** This file contains multiple drivers.  The main body of code, and all
87
 *** but the DesignJet driver, were contributed by George Cameron;
88
 *** please contact g.cameron@biomed.abdn.ac.uk if you have questions.
89
 *     1 - cdj500:	HP DeskJet 500C
90
 *     2 - cdj550:	HP DeskJet 550C
91
 *     3 - pjxl300:	HP PaintJet XL300
92
 *     4 - pj:		HP PaintJet
93
 *     5 - pjxl:	HP PaintJet XL
94
 *     6 - declj250:	DEC LJ250
95
 *** The DesignJet 650C driver was contributed by Koert Zeilstra;
96
 *** please contact koert@zen.cais.com if you have questions.
97
 *     7 - dnj650c      HP DesignJet 650C
98
 *** The LaserJet 4 driver with dithering was contributed by Eckhard
99
 *** Rueggeberg; please contact eckhard@ts.go.dlr.de if you have questions.
100
 *     8 - lj4dith:	HP LaserJet 4 with dithering
101
 *** The ESC/P driver (for Epson ESC/P compatible printers) was written by
102
 *** Yoshio Kuniyoshi <yoshio@nak.math.keio.ac.jp>, but is not maintained at
103
 *** the moment.
104
 *     9 - esc/p:       Epson ESC/P-compatible printers
105
 *** The BJC600 driver (which also works for BJC4000) was written first
106
 *** by Yoshio Kuniyoshi <yoshio@nak.math.keio.ac.jp> and later modified by
107
 *** Yves Arrouye <yves.arrouye@usa.net>. The current driver has been
108
 *** completely rewritten by me (YA) for good color handling.
109
 *    10 - bjc600:	BJC 600//4000 printers
110
 *** The BJC800 driver is based on the bjc600 one. By YA too.
111
 *    11 - bjc800:	BJC 800 printer
112
 ***/
113
 
114
/*
115
 * All of the HP-like drivers have 8-bit (monochrome), 16-bit and 24-bit
116
 *     (colour) and for the DJ 550C 32-bit, (colour, cmyk mode)
117
 *     options in addition to the usual 1-bit and 3-bit modes
118
 * It is also possible to set various printer-specific parameters
119
 *     from the gs command line, eg.
120
 *
121
 *  gs -sDEVICE=cdj550 -dBitsPerPixel=16 -dDepletion=1 -dShingling=2 tiger.eps
122
 *
123
 * Please consult the appropriate section in the devices.doc file for
124
 * further details on all these drivers.
125
 *
126
 * All of the BJC-like drivers have 1-bit and 8-bit monochrome modes, 8-bit,
127
 *     16-bit, 24-bit and 32-bit colour cmyk mode (the 8-bit monochrome mode
128
 *     is called "4-bit". If you want to add a CMYK printer, look at the
129
 *     bjc6000/bjc800 devices declarations and initialization.
130
 *
131
 * If you want to support different color components for the same depth
132
 * on a non-CMYK printer, look how this is done for CMYK printers in
133
 * cdj_set_bpp.
134
 *
135
 */
136
 
137
/*
138
 * This taken from gsdparam.c. I hope it will be useable directly some day.
139
 *
140
 */
141
 
142
#define BEGIN_ARRAY_PARAM(pread, pname, pa, psize, e)\
143
  switch ( ncode = pread(plist, (oname = pname), &pa) )\
144
  {\
145
  case 0:\
146
	if ( pa.size != psize )\
147
	  code = gs_error_rangecheck;\
148
	else { 
149
/* The body of the processing code goes here. */
150
/* If it succeeds, it should do a 'break'; */
151
/* if it fails, it should set ecode and fall through. */
152
#define END_PARAM(pa, e)\
153
	}\
154
	goto e;\
155
  default:\
156
	code = ncode;\
157
e:	param_signal_error(plist, oname, code);\
158
  case 1:\
159
	pa.data = 0;		/* mark as not filled */\
160
  }
161
 
162
private int cdj_param_check_bytes(gs_param_list *, gs_param_name, const byte *, uint, bool);
163
private int cdj_param_check_float(gs_param_list *, gs_param_name, floatp, bool);
164
#define cdj_param_check_string(plist, pname, str, is_defined)\
165
  cdj_param_check_bytes(plist, pname, (const byte *)(str), strlen(str),\
166
			is_defined)
167
 
168
/*
169
 * Drivers stuff.
170
 *
171
 */
172
 
173
#define DESKJET_PRINT_LIMIT  0.04	/* 'real' top margin? */
174
#define PAINTJET_PRINT_LIMIT 0.0	/* This is a guess.. */
175
#define ESC_P_PRINT_LIMIT    0.335
176
 
177
/* Margins are left, bottom, right, top. */
178
#define DESKJET_MARGINS_LETTER   (float)0.25, (float)0.50, (float)0.25, (float)0.167
179
#define DESKJET_MARGINS_A4       (float)0.125, (float)0.50, (float)0.143, (float)0.167
180
#define LJET4_MARGINS  		 (float)0.26, (float)0.0, (float)0.0, (float)0.0
181
/* The PaintJet and DesignJet seem to have the same margins */
182
/* regardless of paper size. */
183
#define PAINTJET_MARGINS         (float)0.167, (float)0.167, (float)0.167, (float)0.167
184
#define DESIGNJET_MARGINS        (float)0.167, (float)0.167, (float)0.167, (float)0.167
185
 
186
/*
187
 * With ESC/P commands, BJC-600 can print no more than 8 inches width.
188
 * So it can't use full width of letter size paper.  Since non printable
189
 * left side area is 0.134 inch, we set up margins as follows.
190
 *
191
 * Note to readers: the bjc drivers series do *not* use ESC/P commands
192
 * but raster ops. Configuration of these drivers can be done through
193
 * the gdevbjc.h file.
194
 *
195
 */
196
#define ESC_P_MARGINS_LETTER    (float)0.134, (float)(0.276+0.2), \
197
 				(float)(0.366+0.01), (float)0.335
198
#define ESC_P_MARGINS_A4        (float)0.134, (float)(0.276+0.2), \
199
				(float)(0.166+0.01), (float)0.335
200
 
201
/* Define bits-per-pixel for generic drivers - default is 24-bit mode */
202
#ifndef BITSPERPIXEL
203
#  define BITSPERPIXEL 24
204
#endif
205
 
206
/*
207
 * The following use of size_of rather than sizeof is required to work
208
 * around a bug in Microsoft Visual C++ 5.0, which considers the THRESHOLD
209
 * value (128 << SHIFT) to be unsigned because SHIFT is unsigned (because
210
 * sizeof() is unsigned).
211
 */
212
#define W size_of(word)
213
#define I size_of(int)
214
 
215
 
216
#define invert_word(v)\
217
     ((v) >> 24) + (((v) >> 8) & 0xff00L) +\
218
	 (((word)(v) << 8) & 0xff0000L) + ((word)(v) << 24)
219
 
220
 
221
/* Printer types */
222
#define DJ500C   0
223
#define DJ550C   1
224
#define PJXL300  2
225
#define PJ180    3
226
#define PJXL180  4
227
#define DECLJ250 5
228
#define DNJ650C  6
229
#define LJ4DITH  7
230
#define ESC_P	 8
231
#define BJC600	 9
232
#define BJC800	 10
233
 
234
/* No. of ink jets (used to minimise head movements) */
235
#define HEAD_ROWS_MONO 50
236
#define HEAD_ROWS_COLOUR 16
237
 
238
/* Colour mapping procedures */
239
private dev_proc_map_cmyk_color (gdev_cmyk_map_cmyk_color);
240
private dev_proc_map_rgb_color (gdev_cmyk_map_rgb_color);
241
 
242
private dev_proc_map_rgb_color (gdev_pcl_map_rgb_color);
243
private dev_proc_map_color_rgb (gdev_pcl_map_color_rgb);
244
private dev_proc_decode_color  (gdev_cmyk_map_color_cmyk);
245
 
246
/* Print-page, parameters and miscellaneous procedures */
247
private dev_proc_open_device(dj500c_open);
248
private dev_proc_open_device(dj550c_open);
249
private dev_proc_open_device(dnj650c_open);
250
private dev_proc_open_device(lj4dith_open);
251
private dev_proc_open_device(pj_open);
252
private dev_proc_open_device(pjxl_open);
253
private dev_proc_open_device(pjxl300_open);
254
private dev_proc_open_device(escp_open);
255
private dev_proc_open_device(bjc_open);
256
 
257
private dev_proc_print_page(declj250_print_page);
258
private dev_proc_print_page(dj500c_print_page);
259
private dev_proc_print_page(dj550c_print_page);
260
private dev_proc_print_page(dnj650c_print_page);
261
private dev_proc_print_page(lj4dith_print_page);
262
private dev_proc_print_page(pj_print_page);
263
private dev_proc_print_page(pjxl_print_page);
264
private dev_proc_print_page(pjxl300_print_page);
265
private dev_proc_print_page(escp_print_page);
266
private dev_proc_print_page(bjc_print_page);
267
 
268
private dev_proc_get_params(cdj_get_params);
269
private dev_proc_get_params(pjxl_get_params);
270
private dev_proc_get_params(bjc_get_params);
271
#define ep_get_params cdj_get_params
272
 
273
private dev_proc_put_params(cdj_put_params);
274
private dev_proc_put_params(pj_put_params);
275
private dev_proc_put_params(pjxl_put_params);
276
private dev_proc_put_params(bjc_put_params);
277
#define ep_put_params cdj_put_params
278
 
279
/* The device descriptors */
280
 
281
#define gx_prn_colour_device_common \
282
    gx_prn_device_common; \
283
    short cmyk;	  	/* 0: not CMYK-capable, > 0: printing CMYK, */ \
284
		  	/* < 0 : CMYK-capable, not printing CMYK */ \
285
    uint default_depth;	/* Used only for CMYK-capable printers now. */ \
286
    uint correction
287
 
288
typedef struct gx_device_cdj_s gx_device_cdj;
289
struct gx_device_cdj_s {
290
	gx_device_common;
291
	gx_prn_colour_device_common;
292
	int shingling;		  /* Interlaced, multi-pass printing */
293
	int depletion;		  /* 'Intelligent' dot-removal */
294
};
295
 
296
typedef struct gx_device_pjxl_s gx_device_pjxl;
297
struct gx_device_pjxl_s {
298
	gx_device_common;
299
	gx_prn_colour_device_common;
300
	int printqual;            /* Mechanical print quality */
301
	int rendertype;           /* Driver or printer dithering control */
302
};
303
 
304
typedef struct gx_device_hp_s gx_device_hp;
305
struct gx_device_hp_s {
306
	gx_device_common;
307
	gx_prn_colour_device_common;
308
};
309
 
310
typedef struct gx_device_hp_s gx_device_pj;
311
 
312
typedef struct gx_device_bjc600_s gx_device_bjc600;
313
typedef struct gx_device_bjc800_s gx_device_bjc800;
314
 
315
typedef struct gx_device_bjc800_s gx_device_bjc;
316
 
317
#define bjc_params_common \
318
    bool manualFeed;		/* Use manual feed */ \
319
    int mediaType;		/* Cf. strings below */ \
320
    bool mediaWeight_isSet;	/* Say if weight is an integer or null */ \
321
    int mediaWeight;		/* Weigth of the media */ \
322
    int printQuality;		/* Cf. strings below */ \
323
    bool ditheringType;		/* Do dithering */ \
324
    int colorComponents;	/* The number of *desired* color comps */ \
325
    int printColors		/* 0: Transparent, \
326
				   1: C, 2: M, 4: Y, 7: K (Color decomp). \
327
				   if > 8, print in black ink. */
328
 
329
typedef struct {
330
    bjc_params_common;
331
 
332
    bool monochromePrint;	/* Print with black only */
333
} bjc600_params;
334
 
335
typedef struct {
336
    bjc_params_common;
337
} bjc_params;
338
 
339
typedef bjc_params bjc800_params;
340
 
341
#define gx_bjc_device_common \
342
    gx_device_common; \
343
    gx_prn_colour_device_common; \
344
    int ptype; \
345
    float printLimit
346
 
347
struct gx_device_bjc600_s {
348
        gx_bjc_device_common;
349
	bjc600_params bjc_p;
350
};
351
struct gx_device_bjc800_s {
352
        gx_bjc_device_common;
353
	bjc800_params bjc_p;
354
};
355
 
356
typedef struct {
357
    gx_device_common;
358
    gx_prn_colour_device_common;
359
} gx_device_colour_prn;
360
 
361
/* Use the cprn_device macro to access generic fields (like cmyk,
362
   default_depth and correction), and specific macros for specific
363
   devices. */
364
 
365
#define cprn_device     ((gx_device_colour_prn*) pdev)
366
 
367
#define cdj       ((gx_device_cdj *)pdev)
368
#define pjxl      ((gx_device_pjxl *)pdev)
369
#define pj	((gx_device_pj *)pdev)
370
 
371
#define bjc             ((gx_device_bjc*) pdev)
372
#define bjc600          ((gx_device_bjc600*) pdev)
373
#define bjc800          ((gx_device_bjc800*) pdev)
374
 
375
#define bjcparams	(bjc->bjc_p)
376
#define bjc600params	(bjc600->bjc_p)
377
#define bjc800params	(bjc800->bjc_p)
378
 
379
#define bjcversion(p)	(((gx_device_bjc*) pdev)->ptype == BJC800 ? \
380
    BJC_BJC800_VERSION : BJC_BJC600_VERSION)
381
#define bjcversionstring(p)	(((gx_device_bjc*) pdev)->ptype == BJC800 ? \
382
    BJC_BJC800_VERSIONSTR : BJC_BJC600_VERSIONSTR)
383
 
384
#define bjcthickpaper(l) \
385
    (bjcparams.mediaWeight_isSet && bjcparams.mediaWeight > l)
386
#define bjc600thickpaper() bjcthickpaper(BJC600_MEDIAWEIGHT_THICKLIMIT)
387
#define bjc800thickpaper() bjcthickpaper(BJC800_MEDIAWEIGHT_THICKLIMIT)
388
 
389
/* The basic structure for all printers. Note the presence of the cmyk, depth
390
   and correct fields even if soem are not used by all printers. */
391
 
392
#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)\
393
    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
394
 
395
/* Note: the computation of color_info values here must match */
396
/* the computation in the cdj_set_bpp procedure below. */
397
 
398
#define prn_hp_colour_device(dtype, procs, dev_name, x_dpi, y_dpi, bpp, print_page, correct)\
399
    prn_colour_device_body(dtype, procs, dev_name,\
400
    DEFAULT_WIDTH_10THS, DEFAULT_HEIGHT_10THS, x_dpi, y_dpi, 0, 0, 0, 0,\
401
    (bpp == 32 ? 4 : (bpp == 1 || bpp == 8) ? 1 : 3), bpp,\
402
    (bpp >= 8 ? 255 : 1), (bpp >= 8 ? 255 : bpp > 1 ? 1 : 0),\
403
    (bpp >= 8 ? 256 : 2), (bpp >= 8 ? 256 : bpp > 1 ? 2 : 0),\
404
    print_page, 0 /* cmyk */, correct)
405
 
406
#define prn_cmyk_colour_device(dtype, procs, dev_name, x_dpi, y_dpi, bpp, print_page, correct)\
407
    prn_colour_device_body(dtype, procs, dev_name,\
408
    DEFAULT_WIDTH_10THS, DEFAULT_HEIGHT_10THS, x_dpi, y_dpi, 0, 0, 0, 0,\
409
    ((bpp == 1 || bpp == 4) ? 1 : 4), bpp,\
410
    (bpp > 8 ? 255 : 1), (1 << (bpp >> 2)) - 1, /* max_gray, max_color */\
411
    (bpp > 8 ? 256 : 2), (bpp > 8 ? 256 : bpp > 1 ? 2 : 0),\
412
    print_page, 1 /* cmyk */, correct)
413
 
414
#define bjc_device(dtype, p, d, x, y, b, pp, c) \
415
    prn_cmyk_colour_device(dtype, p, d, x, y, b, pp, c)
416
 
417
#define cdj_device(procs, dev_name, x_dpi, y_dpi, bpp, print_page, correction, shingling, depletion)\
418
{ prn_hp_colour_device(gx_device_cdj, procs, dev_name, x_dpi, y_dpi, bpp, print_page, correction),\
419
    shingling,\
420
    depletion\
421
}
422
 
423
#define pjxl_device(procs, dev_name, x_dpi, y_dpi, bpp, print_page, printqual, rendertype)\
424
{ prn_hp_colour_device(gx_device_pjxl, procs, dev_name, x_dpi, y_dpi, bpp, print_page, 0), \
425
    printqual,\
426
    rendertype\
427
}
428
 
429
#define pj_device(procs, dev_name, x_dpi, y_dpi, bpp, print_page)\
430
{ prn_hp_colour_device(gx_device_pj, procs, dev_name, x_dpi, y_dpi, bpp, print_page, 0) }
431
 
432
#define bjc600_device(procs, dev_name, x_dpi, y_dpi, bpp, print_page, t, mf, mt, mws, mw, pq, dt, cc, pc, mp) \
433
{ bjc_device(gx_device_bjc600, procs, dev_name, x_dpi, y_dpi, bpp, print_page, 0),\
434
    t, 0., { mf, mt, mws, mw, pq, dt, cc, pc, mp }\
435
}
436
#define bjc800_device(procs, dev_name, x_dpi, y_dpi, bpp, print_page, t, mf, mt, mws, mw, pq, dt, cc, pc) \
437
{ bjc_device(gx_device_bjc800, procs, dev_name, x_dpi, y_dpi, bpp, print_page, 0),\
438
    t, 0., { mf, mt, mws, mw, pq, dt, cc, pc }\
439
}
440
 
441
#define hp_colour_procs(proc_colour_open, proc_get_params, proc_put_params) {\
442
	proc_colour_open,\
443
	gx_default_get_initial_matrix,\
444
	gx_default_sync_output,\
445
	gdev_prn_output_page,\
446
	gdev_prn_close,\
447
	gdev_pcl_map_rgb_color,\
448
	gdev_pcl_map_color_rgb,\
449
	NULL,	/* fill_rectangle */\
450
	NULL,	/* tile_rectangle */\
451
	NULL,	/* copy_mono */\
452
	NULL,	/* copy_color */\
453
	NULL,	/* draw_line */\
454
	gx_default_get_bits,\
455
	proc_get_params,\
456
	proc_put_params\
457
}
458
 
459
#define cmyk_colour_procs(proc_colour_open, proc_get_params, proc_put_params) {\
460
	proc_colour_open,\
461
	gx_default_get_initial_matrix,\
462
	gx_default_sync_output,\
463
	gdev_prn_output_page,\
464
	gdev_prn_close,\
465
	NULL /* map_rgb_color */,\
466
	NULL /* map_color_rgb */,\
467
	NULL /* fill_rectangle */,\
468
	NULL /* tile_rectangle */,\
469
	NULL /* copy_mono */,\
470
	NULL /* copy_color */,\
471
	NULL /* draw_line */,\
472
	gx_default_get_bits,\
473
	proc_get_params,\
474
	proc_put_params,\
475
        gdev_cmyk_map_cmyk_color,\
476
	NULL,	/* get_xfont_procs */\
477
	NULL,	/* get_xfont_device */\
478
	NULL,	/* map_rgb_alpha_color */\
479
	NULL,	/* get_page_device */\
480
	NULL,	/* get_alpha_bits */\
481
	NULL,	/* copy_alpha */\
482
	NULL,	/* get_band */\
483
	NULL,	/* copy_rop */\
484
	NULL,	/* fill_path */\
485
	NULL,	/* stroke_path */\
486
	NULL,	/* fill_mask */\
487
	NULL,	/* fill_trapezoid */\
488
	NULL,	/* fill_parallelogram */\
489
	NULL,	/* fill_triangle */\
490
	NULL,	/* draw_thin_line */\
491
	NULL,	/* begin_image */\
492
	NULL,	/* image_data */\
493
	NULL,	/* end_image */\
494
	NULL,	/* strip_tile_rectangle */\
495
	NULL,	/* strip_copy_rop */\
496
	NULL,	/* get_clipping_box */\
497
	NULL,	/* begin_typed_image */\
498
	NULL,	/* get_bits_rectangle */\
499
	NULL,	/* map_color_rgb_alpha */\
500
	NULL,	/* create_compositor */\
501
	NULL,	/* get_hardware_params */\
502
	NULL,	/* text_begin */\
503
	NULL,	/* finish_copydevice */\
504
	NULL,	/* begin_transparency_group */\
505
	NULL,	/* end_transparency_group */\
506
	NULL,	/* begin_transparency_mask */\
507
	NULL,	/* end_transparency_mask */\
508
	NULL,	/* discard_transparency_layer */\
509
	NULL,	/* get_color_mapping_procs */\
510
	NULL,	/* get_color_comp_index */\
511
	gdev_cmyk_map_cmyk_color,	/* encode_color */\
512
	gdev_cmyk_map_color_cmyk	/* decode_color */\
513
}
514
 
515
private gx_device_procs cdj500_procs =
516
hp_colour_procs(dj500c_open, cdj_get_params, cdj_put_params);
517
 
518
private gx_device_procs cdj550_procs =
519
hp_colour_procs(dj550c_open, cdj_get_params, cdj_put_params);
520
 
521
#ifdef USE_CDJ550_CMYK
522
private gx_device_procs cdj550cmyk_procs =
523
cmyk_colour_procs(dj550c_open, cdj_get_params, cdj_put_params);
524
#endif
525
 
526
private gx_device_procs dnj650c_procs =
527
hp_colour_procs(dnj650c_open, cdj_get_params, cdj_put_params);
528
 
529
private gx_device_procs lj4dith_procs =
530
hp_colour_procs(lj4dith_open, cdj_get_params, cdj_put_params);
531
 
532
private gx_device_procs pj_procs =
533
hp_colour_procs(pj_open, gdev_prn_get_params, pj_put_params);
534
 
535
private gx_device_procs pjxl_procs =
536
hp_colour_procs(pjxl_open, pjxl_get_params, pjxl_put_params);
537
 
538
private gx_device_procs pjxl300_procs =
539
hp_colour_procs(pjxl300_open, pjxl_get_params, pjxl_put_params);
540
 
541
private gx_device_procs bjc_procs =
542
cmyk_colour_procs(bjc_open, bjc_get_params, bjc_put_params);
543
 
544
private gx_device_procs escp_procs =
545
hp_colour_procs(escp_open, ep_get_params, ep_put_params);
546
 
547
gx_device_cdj far_data gs_cdjmono_device =
548
cdj_device(cdj500_procs, "cdjmono", 300, 300, 1,
549
	   dj500c_print_page, 4, 0, 1);
550
 
551
gx_device_cdj far_data gs_cdeskjet_device =
552
cdj_device(cdj500_procs, "cdeskjet", 300, 300, 3,
553
	   dj500c_print_page, 4, 2, 1);
554
 
555
gx_device_cdj far_data gs_cdjcolor_device =
556
cdj_device(cdj500_procs, "cdjcolor", 300, 300, 24,
557
	   dj500c_print_page, 4, 2, 1);
558
 
559
gx_device_cdj far_data gs_cdj500_device =
560
cdj_device(cdj500_procs, "cdj500", 300, 300, BITSPERPIXEL,
561
	   dj500c_print_page, 4, 2, 1);
562
 
563
gx_device_cdj far_data gs_cdj550_device =
564
cdj_device(cdj550_procs, "cdj550", 300, 300, BITSPERPIXEL,
565
	   dj550c_print_page, 0, 2, 1);
566
 
567
#ifdef USE_CDJ550_CMYK
568
gx_device_cdj far_data gs_cdj550cmyk_device = {
569
    prn_cmyk_colour_device(cdj550cmyk_procs, "cdj550cmyk", 300, 300,
570
        BITSPERPIXEL, dj550c_print_page, 0), 2, 1
571
};
572
#endif
573
 
574
gx_device_pj far_data gs_declj250_device =
575
pj_device(pj_procs, "declj250", 180, 180, BITSPERPIXEL,
576
	  declj250_print_page);
577
 
578
gx_device_cdj far_data gs_dnj650c_device =
579
cdj_device(dnj650c_procs, "dnj650c", 300, 300, BITSPERPIXEL,
580
	   dnj650c_print_page, 0, 2, 1);
581
 
582
gx_device_cdj far_data gs_lj4dith_device =
583
cdj_device(lj4dith_procs, "lj4dith", 600, 600, 8,
584
	   lj4dith_print_page, 4, 0, 1);
585
 
586
gx_device_pj far_data gs_pj_device =
587
pj_device(pj_procs, "pj", 180, 180, BITSPERPIXEL,
588
	  pj_print_page);
589
 
590
gx_device_pjxl far_data gs_pjxl_device =
591
pjxl_device(pjxl_procs, "pjxl", 180, 180, BITSPERPIXEL,
592
	    pjxl_print_page, 0, 0);
593
 
594
gx_device_pjxl far_data gs_pjxl300_device =
595
pjxl_device(pjxl300_procs, "pjxl300", 300, 300, BITSPERPIXEL,
596
	    pjxl300_print_page, 0, 0);
597
 
598
gx_device_cdj far_data gs_escp_device =
599
cdj_device(escp_procs, "escp", 360, 360, 8,
600
	   escp_print_page, 0, 0, 1);
601
 
602
gx_device_cdj far_data gs_escpc_device =
603
cdj_device(escp_procs, "escpc", 360, 360, 24,
604
	   escp_print_page, 0, 0, 1);
605
 
606
/* Args of bjc drivers are manualFeed, mediaType, printQuality, printColor,
607
   mediaWeight_isSet, mediaWeight, (monochromePrint) */
608
 
609
gx_device_bjc600 far_data gs_bjc600_device =
610
    bjc600_device(
611
	bjc_procs,
612
        BJC_BJC600,
613
        BJC600_DEFAULT_RESOLUTION,
614
        BJC600_DEFAULT_RESOLUTION,
615
        BJC600_DEFAULT_BITSPERPIXEL,
616
	bjc_print_page,
617
        BJC600,
618
	BJC600_DEFAULT_MANUALFEED,
619
	BJC600_DEFAULT_MEDIATYPE,
620
	BJC600_DEFAULT_SETMEDIAWEIGHT,
621
	BJC600_DEFAULT_MEDIAWEIGHT,
622
	BJC600_DEFAULT_PRINTQUALITY,
623
	BJC600_DEFAULT_DITHERINGTYPE,
624
	BJC600_DEFAULT_COLORCOMPONENTS,
625
	BJC600_DEFAULT_PRINTCOLORS,
626
	BJC600_DEFAULT_MONOCHROMEPRINT);
627
 
628
gx_device_bjc800 far_data gs_bjc800_device =
629
    bjc800_device(
630
        bjc_procs,
631
        BJC_BJC800,
632
        BJC800_DEFAULT_RESOLUTION,
633
        BJC800_DEFAULT_RESOLUTION,
634
        BJC800_DEFAULT_BITSPERPIXEL,
635
	bjc_print_page,
636
        BJC800,
637
	BJC800_DEFAULT_MANUALFEED,
638
	BJC800_DEFAULT_MEDIATYPE,
639
	BJC800_DEFAULT_SETMEDIAWEIGHT,
640
	BJC800_DEFAULT_MEDIAWEIGHT,
641
	BJC800_DEFAULT_PRINTQUALITY,
642
	BJC800_DEFAULT_DITHERINGTYPE,
643
	BJC600_DEFAULT_COLORCOMPONENTS,
644
	BJC800_DEFAULT_PRINTCOLORS);
645
 
646
/* Forward references */
647
private int gdev_pcl_mode1compress(const byte *, const byte *, byte *);
648
private int hp_colour_open(gx_device *, int);
649
private int hp_colour_print_page(gx_device_printer *, FILE *, int);
650
private int cdj_put_param_int(gs_param_list *, gs_param_name, int *, int, int, int);
651
private uint gdev_prn_rasterwidth(const gx_device_printer *, int);
652
private int cdj_put_param_bpp(gx_device *, gs_param_list *, int, int, int);
653
private int cdj_set_bpp(gx_device *, int, int);
654
private void cdj_expand_line(word *, int, short, int, int);
655
private int bjc_fscmyk(byte**, byte*[4][4], int**, int, int);
656
 
657
/* String parameters manipulation */
658
 
659
typedef struct {
660
    const char* p_name;
661
    int p_value;
662
} stringParamDescription;
663
 
664
private const byte* paramValueToString(const stringParamDescription*, int);
665
private int paramStringValue(const stringParamDescription*,
666
    const byte*, int, int*);
667
 
668
private int put_param_string(gs_param_list*, const byte*,
669
    gs_param_string*, const stringParamDescription*, int *, int);
670
private int get_param_string(gs_param_list*, const byte*,
671
    gs_param_string*, const stringParamDescription*, int, bool, int);
672
 
673
/* Open the printer and set up the margins. */
674
private int
675
dj500c_open(gx_device *pdev)
676
{ return hp_colour_open(pdev, DJ500C);
677
}
678
 
679
private int
680
dj550c_open(gx_device *pdev)
681
{  return hp_colour_open(pdev, DJ550C);
682
}
683
 
684
private int
685
dnj650c_open(gx_device *pdev)
686
{ return hp_colour_open(pdev, DNJ650C);
687
}
688
 
689
private int
690
lj4dith_open(gx_device *pdev)
691
{ return hp_colour_open(pdev, LJ4DITH);
692
}
693
 
694
private int
695
pjxl300_open(gx_device *pdev)
696
{ return hp_colour_open(pdev, PJXL300);
697
}
698
 
699
private int
700
pj_open(gx_device *pdev)
701
{ return hp_colour_open(pdev, PJ180);
702
}
703
 
704
private int
705
pjxl_open(gx_device *pdev)
706
{ return hp_colour_open(pdev, PJXL180);
707
}
708
 
709
private int
710
escp_open(gx_device *pdev)
711
{ return hp_colour_open(pdev, ESC_P);
712
}
713
 
714
private int
715
bjc_open(gx_device *pdev)
716
{  return hp_colour_open(pdev, bjc->ptype);
717
}
718
 
719
private int
720
hp_colour_open(gx_device *pdev, int ptype)
721
{	/* Change the margins if necessary. */
722
  static const float dj_a4[4] = { DESKJET_MARGINS_A4 };
723
  static const float dj_letter[4] = { DESKJET_MARGINS_LETTER };
724
  static const float lj4_all[4] = { LJET4_MARGINS };
725
  static const float pj_all[4] = { PAINTJET_MARGINS };
726
  static const float dnj_all[4] = { DESIGNJET_MARGINS };
727
  static const float ep_a4[4] = { ESC_P_MARGINS_A4 };
728
  static const float ep_letter[4] = { ESC_P_MARGINS_LETTER };
729
 
730
  static float bjc_a3[4] = { BJC_MARGINS_A3 };		/* Not const! */
731
  static float bjc_letter[4] = { BJC_MARGINS_LETTER };  /* Not const! */
732
  static float bjc_a4[4] = { BJC_MARGINS_A4 };		/* Not const! */
733
 
734
  const float *m = (float *) 0;
735
 
736
  /* Set up colour params if put_params has not already done so */
737
  if (pdev->color_info.num_components == 0)
738
    {	int code = cdj_set_bpp(pdev, pdev->color_info.depth,
739
	    pdev->color_info.num_components);
740
	if ( code < 0 )
741
	  return code;
742
    }
743
 
744
  switch (ptype) {
745
  case DJ500C:
746
  case DJ550C:
747
    m = (gdev_pcl_paper_size(pdev) == PAPER_SIZE_A4 ? dj_a4 :
748
	 dj_letter);
749
    break;
750
  case DNJ650C:
751
    m = dnj_all;
752
    break;
753
  case LJ4DITH:
754
    m = lj4_all;
755
    break;  
756
  case PJ180:
757
  case PJXL300:
758
  case PJXL180:
759
    m = pj_all;
760
    break;
761
  case ESC_P:
762
    m = (gdev_pcl_paper_size(pdev) == PAPER_SIZE_A4 ? ep_a4 :
763
	 ep_letter);
764
    break;
765
  case BJC600:
766
  case BJC800:
767
    switch (gdev_pcl_paper_size(pdev)) {
768
	case PAPER_SIZE_LEGAL:
769
	case PAPER_SIZE_LETTER:
770
	    m = bjc_letter;
771
	    break;
772
 
773
	case PAPER_SIZE_A0:
774
	case PAPER_SIZE_A1:
775
	case PAPER_SIZE_A3:
776
	    m = bjc_a3;
777
	    break;
778
 
779
	default:
780
	    m = bjc_a4;
781
    }
782
 
783
#ifndef USE_FIXED_MARGINS
784
    if (ptype == BJC800) {
785
	((float *) m)[1] = (float)BJC_HARD_LOWER_LIMIT;
786
    }
787
#endif
788
 
789
    bjc->printLimit = m[3];		/* The real hardware limit. */
790
 
791
#ifdef BJC_DEFAULT_CENTEREDAREA
792
    if (m[3] < m[1]) {
793
	((float *) m)[3] = m[1];  	/* Top margin = bottom one. */
794
    } else {
795
	((float *) m)[1] = m[3];  	/* Bottom margin = top one. */
796
    }
797
#endif
798
 
799
    break;
800
 
801
    /*NOTREACHED*/
802
 
803
    /*
804
     * The margins must be set so that the resulting page length will be 
805
     * expressed exactly as a multiple of tenthes of inches.
806
     *
807
     */
808
 
809
    /**/ {
810
	float *bjcm = (float *) m;
811
 
812
	byte pdimen = (byte)
813
	    (pdev->height / pdev->y_pixels_per_inch * 10.
814
	     - bjcm[3] * 10. - bjcm[1] * 10. + .5) + 1;
815
	do {
816
	    --pdimen;
817
	    bjcm[1] = pdev->height / pdev->y_pixels_per_inch
818
	        - bjcm[3] - (float) pdimen / 10.;
819
	} while (bjcm[1] < BJC_LOWER_LIMIT);
820
    }
821
 
822
    break;
823
  }
824
  gx_device_set_margins(pdev, m, true);
825
  return gdev_prn_open(pdev);
826
}
827
 
828
/* Added parameters for DeskJet 5xxC */
829
 
830
/* Get parameters.  In addition to the standard and printer 
831
 * parameters, we supply shingling and depletion parameters,
832
 * and control over the bits-per-pixel used in output rendering */
833
private int
834
cdj_get_params(gx_device *pdev, gs_param_list *plist)
835
{	int code = gdev_prn_get_params(pdev, plist);
836
	if ( code < 0 ||
837
	    (code = param_write_int(plist, "BlackCorrect", (int *)&cdj->correction)) < 0 ||
838
	    (code = param_write_int(plist, "Shingling", &cdj->shingling)) < 0 ||
839
	    (code = param_write_int(plist, "Depletion", &cdj->depletion)) < 0
840
	   )
841
	  return code;
842
 
843
	return code;
844
}
845
 
846
/* Put parameters. */
847
private int
848
cdj_put_params(gx_device *pdev, gs_param_list *plist)
849
{	int correction = cdj->correction;
850
	int shingling = cdj->shingling;
851
	int depletion = cdj->depletion;
852
	int bpp = 0;
853
	int code = 0;
854
 
855
	code = cdj_put_param_int(plist, "BlackCorrect", &correction, 0, 9, code);
856
	code = cdj_put_param_int(plist, "Shingling", &shingling, 0, 2, code);
857
	code = cdj_put_param_int(plist, "Depletion", &depletion, 1, 3, code);
858
	code = cdj_put_param_int(plist, "BitsPerPixel", &bpp, 1, 32, code);
859
 
860
	if ( code < 0 )
861
	  return code;
862
	code = cdj_put_param_bpp(pdev, plist, bpp, bpp, 0);
863
	if ( code < 0 )
864
	  return code;
865
 
866
	cdj->correction = correction;
867
	cdj->shingling = shingling;
868
	cdj->depletion = depletion;
869
	return 0;
870
}
871
 
872
/* Added parameters for PaintJet XL and PaintJet XL300 */
873
 
874
/* Get parameters.  In addition to the standard and printer
875
 * parameters, we supply print_quality and render_type 
876
 * parameters, together with bpp control. */
877
private int
878
pjxl_get_params(gx_device *pdev, gs_param_list *plist)
879
{	int code = gdev_prn_get_params(pdev, plist);
880
	if ( code < 0 ||
881
	    (code = param_write_int(plist, "PrintQuality", &pjxl->printqual)) < 0 ||
882
	    (code = param_write_int(plist, "RenderType", &pjxl->rendertype)) < 0
883
	   )
884
	  return code;
885
 
886
	return code;
887
}
888
 
889
/* Put parameters. */
890
private int
891
pjxl_put_params(gx_device *pdev, gs_param_list *plist)
892
{	int printqual = pjxl->printqual;
893
	int rendertype = pjxl->rendertype;
894
	int bpp = 0, real_bpp = 0;
895
	int code = 0;
896
 
897
	code = cdj_put_param_int(plist, "PrintQuality", &printqual, -1, 1, code);
898
	code = cdj_put_param_int(plist, "RenderType", &rendertype, 0, 10, code);
899
	code = cdj_put_param_int(plist, "BitsPerPixel", &bpp, 1, 32, code);
900
 
901
	if ( code < 0 )
902
	  return code;
903
	real_bpp = bpp;
904
	if ( rendertype > 0 )
905
	  {	/* If printer is doing the dithering, we must have a
906
		 * true-colour mode, ie. 16 or 24 bits per pixel */
907
		if ( bpp > 0 && bpp < 16 )
908
		  real_bpp = 24;
909
	  }
910
	code = cdj_put_param_bpp(pdev, plist, bpp, real_bpp, 0);
911
	if ( code < 0 )
912
	  return code;
913
 
914
	pjxl->printqual = printqual;
915
	pjxl->rendertype = rendertype;
916
	return 0;
917
}
918
 
919
/* Added parameters for PaintJet */
920
 
921
/* Put parameters.  In addition to the standard and printer */
922
/* parameters, we allow control of the bits-per-pixel */
923
private int
924
pj_put_params(gx_device *pdev, gs_param_list *plist)
925
{	int bpp = 0;
926
	int code = cdj_put_param_int(plist, "BitsPerPixel", &bpp, 1, 32, 0);
927
 
928
	if ( code < 0 )
929
	  return code;
930
	return cdj_put_param_bpp(pdev, plist, bpp, bpp, 0);
931
}
932
 
933
private stringParamDescription bjc_processColorsStrings[] = {
934
    { "DeviceGray",		1 },
935
    { "DeviceRGB",		3 },
936
    { "DeviceCMYK",		4 },
937
    { 0 }
938
};
939
 
940
private stringParamDescription bjc_mediaTypeStrings[] = {
941
    { "PlainPaper",		BJC_MEDIA_PLAINPAPER },
942
    { "CoatedPaper",		BJC_MEDIA_COATEDPAPER },
943
    { "TransparencyFilm",	BJC_MEDIA_TRANSPARENCYFILM },
944
    { "Envelope",		BJC_MEDIA_ENVELOPE },
945
    { "Card",			BJC_MEDIA_CARD},
946
    { "Other",		        BJC_MEDIA_OTHER },
947
    { 0 }
948
};
949
 
950
private stringParamDescription bjc600_printQualityStrings[] = {
951
    { "Normal",	0 },
952
    { "High",	1 },
953
    { "Draft",  2 },
954
    { 0 }
955
};
956
 
957
private stringParamDescription bjc800_printQualityStrings[] = {
958
    { "Normal",		0 },
959
    { "High",		1 },
960
    { "Low",    	3 },
961
    { "Draft",		4 },
962
    { 0 },
963
};
964
 
965
private stringParamDescription bjc_ditheringTypeStrings[] = {
966
    { "None",			BJC_DITHER_NONE },
967
    { "Floyd-Steinberg",	BJC_DITHER_FS },
968
    { 0 }
969
};
970
 
971
private int
972
bjc_get_params(gx_device *pdev, gs_param_list *plist)
973
{
974
    int code = gdev_prn_get_params(pdev, plist);
975
    int ncode;
976
 
977
    gs_param_string pmedia;
978
    gs_param_string pquality;
979
    gs_param_string dithering;
980
 
981
    if (code < 0) return_error(code);
982
 
983
    if ((ncode = param_write_bool(plist, BJC_OPTION_MANUALFEED,
984
	&bjcparams.manualFeed)) < 0) {
985
	code = ncode;
986
    }
987
 
988
    code = get_param_string(plist, (unsigned char *)BJC_OPTION_MEDIATYPE, &pmedia,
989
        bjc_mediaTypeStrings, bjcparams.mediaType, true, code);
990
 
991
    code = get_param_string(plist, (unsigned char *)BJC_OPTION_PRINTQUALITY, &pquality,
992
        (bjc->ptype == BJC800 ? bjc800_printQualityStrings :
993
	bjc600_printQualityStrings), bjcparams.printQuality,
994
	true, code);
995
 
996
    code = get_param_string(plist, (unsigned char *)BJC_OPTION_DITHERINGTYPE, &dithering,
997
        bjc_ditheringTypeStrings, bjcparams.ditheringType, true, code);
998
 
999
    if ((ncode = param_write_int(plist, BJC_OPTION_PRINTCOLORS,
1000
	&bjcparams.printColors)) < 0) {
1001
	code = ncode;
1002
    }
1003
 
1004
    if ((ncode = (bjcparams.mediaWeight_isSet ?
1005
	param_write_int(plist, BJC_OPTION_MEDIAWEIGHT,
1006
	    &bjcparams.mediaWeight) :
1007
	param_write_null(plist, BJC_OPTION_MEDIAWEIGHT))) < 0) {
1008
	code = ncode;
1009
    }
1010
 
1011
    if (bjc->ptype != BJC800) {
1012
	if ((ncode = param_write_bool(plist, BJC_OPTION_MONOCHROMEPRINT,
1013
	    &bjc600params.monochromePrint)) < 0) {
1014
	    code = ncode;
1015
	}
1016
    }
1017
 
1018
    /**/ {
1019
	float version;
1020
	gs_param_string versionString;
1021
 
1022
	bool bTrue = true;
1023
 
1024
	version = bjcversion(pdev);
1025
	versionString.data = (byte *)bjcversionstring(pdev);
1026
 
1027
	versionString.size = strlen((char *)versionString.data);
1028
	versionString.persistent = true;
1029
 
1030
	if ((ncode = param_write_float(plist, BJC_DEVINFO_VERSION,
1031
		&version)) < 0) {
1032
	    code = ncode;
1033
	}
1034
	if ((ncode = param_write_string(plist, BJC_DEVINFO_VERSIONSTRING,
1035
	    &versionString)) < 0) {
1036
	    code = ncode;
1037
	}
1038
 
1039
	if ((ncode = param_write_bool(plist, BJC_DEVINFO_OUTPUTFACEUP,
1040
	    &bTrue)) < 0) {
1041
	    code = ncode;
1042
 	}
1043
    }
1044
 
1045
    return code;
1046
}
1047
 
1048
/* Put properties for the bjc drivers. */
1049
 
1050
private int
1051
bjc_put_params(gx_device *pdev, gs_param_list *plist)
1052
{
1053
    int bpp = 0, ccomps = 0;
1054
 
1055
    int code = 0;
1056
    int ncode;
1057
 
1058
    bool aBool = true;
1059
 
1060
    const char* oname = (const char*) 0;
1061
 
1062
    bjc600_params new600Params;
1063
    bjc800_params new800Params;
1064
 
1065
    bjc_params* params;
1066
 
1067
    gs_param_string pprocesscolors;
1068
    gs_param_string pmedia;
1069
    gs_param_string pquality;
1070
 
1071
    gs_param_float_array hwra;
1072
 
1073
    if (bjc->ptype != BJC800) {
1074
	new600Params = bjc600params;
1075
	params = (bjc_params*) &new600Params;
1076
    } else {
1077
	new800Params = bjc800params;
1078
	params = (bjc_params*) &new800Params;
1079
    }
1080
 
1081
    if ((code = cdj_put_param_int(plist, "BitsPerPixel",
1082
	&bpp, 1, 32, code)) != 1) {
1083
        bpp = pdev->color_info.depth;
1084
    }
1085
 
1086
    if ((code = put_param_string(plist, (unsigned char *)"ProcessColorModel",
1087
	&pprocesscolors, bjc_processColorsStrings, &ccomps, code)) != 1) {
1088
        ccomps = pdev->color_info.num_components;
1089
    }
1090
 
1091
    if ((ncode = param_read_bool(plist, oname = BJC_OPTION_MANUALFEED,
1092
	&params->manualFeed)) < 0) {
1093
	param_signal_error(plist, oname, code = ncode);
1094
    }
1095
 
1096
    code = put_param_string(plist, (unsigned char *)BJC_OPTION_MEDIATYPE, &pmedia,
1097
        bjc_mediaTypeStrings, &params->mediaType, code);
1098
 
1099
    code = cdj_put_param_int(plist, BJC_OPTION_PRINTCOLORS,
1100
	&params->printColors, 0, 15, code);
1101
 
1102
    code = put_param_string(plist, (unsigned char *)BJC_OPTION_PRINTQUALITY, &pquality,
1103
	(bjc->ptype == BJC800 ? bjc800_printQualityStrings :
1104
	bjc600_printQualityStrings), &params->printQuality, code);
1105
 
1106
    switch (ncode = param_read_int(plist,
1107
	oname = BJC_OPTION_MEDIAWEIGHT, &params->mediaWeight)) {
1108
	case 0:
1109
	    if (params->mediaWeight <= 0) {
1110
		ncode = gs_error_rangecheck;
1111
	    } else {
1112
		params->mediaWeight_isSet = 1;
1113
		break;
1114
	    }
1115
	    goto mwe;
1116
 
1117
	default:
1118
	    if ((ncode = param_read_null(plist, oname)) == 0) {
1119
		params->mediaWeight_isSet = 0;
1120
		break;
1121
	    }
1122
mwe:   	    param_signal_error(plist, oname, code = ncode);
1123
 
1124
	case 1:
1125
	    break;
1126
    }
1127
 
1128
    if (bjc->ptype != BJC800) {
1129
	bjc600_params* params600 = (bjc600_params*) params;
1130
	if ((ncode = param_read_bool(plist,
1131
	    oname = BJC_OPTION_MONOCHROMEPRINT,
1132
	    &params600->monochromePrint)) < 0) {
1133
	    param_signal_error(plist, oname, code = ncode);
1134
	}
1135
    }
1136
 
1137
    if ((ncode = cdj_param_check_float(plist, BJC_DEVINFO_VERSION,
1138
	bjcversion(pdev), true)) < 0) {
1139
	code = ncode;
1140
    }
1141
    if ((ncode = cdj_param_check_string(plist, BJC_DEVINFO_VERSIONSTRING,
1142
	bjcversionstring(pdev), true)) < 0) {
1143
	code = ncode;
1144
    }
1145
 
1146
    if ((ncode = param_read_bool(plist, oname = BJC_DEVINFO_OUTPUTFACEUP,
1147
	&aBool)) < 0) {
1148
	param_signal_error(plist, oname, code = ncode);
1149
    } else if (aBool != true) {
1150
	param_signal_error(plist, oname, code = ncode = gs_error_rangecheck);
1151
    }
1152
 
1153
    /* Check for invalid resolution. The array macros are taken from
1154
       gsdparam.c and modified to use oname, ncode and code instead
1155
       of param_name, code and ecode respectively. */
1156
 
1157
    BEGIN_ARRAY_PARAM(param_read_float_array, "HWResolution", hwra, 2, hwre)
1158
	if ( hwra.data[0] <= 0 || hwra.data[1] <= 0 ||
1159
	     hwra.data[0] != hwra.data[1] )
1160
	    ncode = gs_error_rangecheck;
1161
	else {
1162
#ifdef BJC_STRICT
1163
	    if (hwra.data[0] != BJC_RESOLUTION_LOW &&
1164
		hwra.data[0] != BJC_RESOLUTION_NORMAL &&
1165
		hwra.data[0] != BJC_RESOLUTION_HIGH) {
1166
		ncode = gs_error_rangecheck; 
1167
	    }
1168
#else
1169
	    /* A small hack for checking resolution without logarithms. */
1170
 
1171
	    /**/ {
1172
		int n;
1173
 
1174
		for (n = 0; n < 8 * sizeof(n) / BJC_RESOLUTION_BASE; ++n) {
1175
		    float res = (float)(BJC_RESOLUTION_BASE * (1 << n));
1176
 
1177
		    if (res == hwra.data[0]) break;
1178
 
1179
		    if (res > hwra.data[0]) {
1180
			ncode = gs_error_rangecheck;
1181
		    }
1182
		}
1183
 
1184
		if (n == 8 * sizeof(n)) {
1185
		    ncode = gs_error_rangecheck;
1186
		}
1187
	    }
1188
#endif
1189
	    if (ncode < 0) {
1190
		code = ncode;
1191
	    } else {
1192
		break;
1193
	    }
1194
	}
1195
    END_PARAM(hwra, hwre)
1196
 
1197
    if ((ncode = cdj_put_param_bpp(pdev, plist, bpp, bpp, ccomps)) < 0) {
1198
	code = ncode;
1199
    }
1200
 
1201
    if (code < 0)
1202
	return code;
1203
 
1204
    if (bpp == 1) {
1205
	params->ditheringType = BJC_DITHER_NONE;
1206
    }
1207
 
1208
    /* Write values that did change */
1209
 
1210
    if (bjc->ptype != BJC800) {
1211
	bjc600params = new600Params;
1212
    } else {
1213
	bjc800params = new800Params;
1214
    }
1215
 
1216
    return code;
1217
}
1218
 
1219
/* ------ Internal routines ------ */
1220
 
1221
/* The DeskJet500C can compress (mode 9) */
1222
private int
1223
dj500c_print_page(gx_device_printer * pdev, FILE * prn_stream)
1224
{
1225
  return hp_colour_print_page(pdev, prn_stream, DJ500C);
1226
}
1227
 
1228
/* The DeskJet550C can compress (mode 9) */
1229
private int
1230
dj550c_print_page(gx_device_printer * pdev, FILE * prn_stream)
1231
{
1232
  return hp_colour_print_page(pdev, prn_stream, DJ550C);
1233
}
1234
 
1235
/* The DesignJet650C can compress (mode 1) */
1236
private int
1237
dnj650c_print_page(gx_device_printer * pdev, FILE * prn_stream)
1238
{
1239
  return hp_colour_print_page(pdev, prn_stream, DNJ650C);
1240
}
1241
 
1242
private int
1243
lj4dith_print_page(gx_device_printer * pdev, FILE * prn_stream)
1244
{
1245
  return hp_colour_print_page(pdev, prn_stream, LJ4DITH);
1246
}
1247
 
1248
/* The PJXL300 can compress (modes 2 & 3) */
1249
private int
1250
pjxl300_print_page(gx_device_printer * pdev, FILE * prn_stream)
1251
{ int ret_code;
1252
  /* Ensure we're operating in PCL mode */
1253
  fputs("\033%-12345X@PJL enter language = PCL\n", prn_stream);
1254
  ret_code = hp_colour_print_page(pdev, prn_stream, PJXL300);
1255
  /* Reenter switch-configured language */
1256
  fputs("\033%-12345X", prn_stream);
1257
  return ret_code;
1258
}
1259
 
1260
/* The PaintJet XL can compress (modes 2 & 3) */
1261
private int
1262
pjxl_print_page(gx_device_printer * pdev, FILE * prn_stream)
1263
{
1264
  return hp_colour_print_page(pdev, prn_stream, PJXL180);
1265
}
1266
 
1267
/* The PaintJet can compress (mode 1) */
1268
private int
1269
pj_print_page(gx_device_printer * pdev, FILE * prn_stream)
1270
{
1271
  return hp_colour_print_page(pdev, prn_stream, PJ180);
1272
}
1273
 
1274
/* The LJ250 can compress (mode 1) */
1275
private int
1276
declj250_print_page(gx_device_printer * pdev, FILE * prn_stream)
1277
{ int ret_code;
1278
  fputs("\033%8", prn_stream);	/* Enter PCL emulation mode */
1279
  ret_code = hp_colour_print_page(pdev, prn_stream, DECLJ250);
1280
  fputs("\033%@", prn_stream);	/* Exit PCL emulation mode */
1281
  return ret_code;
1282
}
1283
 
1284
/* The BJC-600 cannot compress w/o raster image commands. */
1285
private int
1286
escp_print_page(gx_device_printer * pdev, FILE * prn_stream)
1287
{
1288
  return hp_colour_print_page(pdev, prn_stream, ESC_P);
1289
}
1290
 
1291
/* The BJC-600 can compress w/ raster image commands. */
1292
private int
1293
bjc_print_page(gx_device_printer * pdev, FILE * prn_stream)
1294
{
1295
  return hp_colour_print_page(pdev, prn_stream, bjc->ptype);
1296
}
1297
 
1298
/* MACROS FOR DITHERING (we use macros for compact source and faster code) */
1299
/* Floyd-Steinberg dithering. Often results in a dramatic improvement in
1300
 * subjective image quality, but can also produce dramatic increases in
1301
 * amount of printer data generated and actual printing time!! Mode 9 2D
1302
 * compression is still useful for fairly flat colour or blank areas but its
1303
 * compression is much less effective in areas where the dithering has
1304
 * effectively randomised the dot distribution. */
1305
 
1306
#define SHIFT ((I * 8) - 13)
1307
#define RSHIFT ((I * 8) - 16)
1308
#define RANDOM (((rand() << RSHIFT) % (MAXVALUE / 2))  - MAXVALUE / 4);
1309
#define MINVALUE  0
1310
#define MAXVALUE  (255 << SHIFT)
1311
#define THRESHOLD (128 << SHIFT)
1312
#define C 8
1313
 
1314
#define FSdither(inP, out, errP, Err, Bit, Offset, Element)\
1315
	oldErr = Err;\
1316
	Err = (errP[Element] + ((Err * 7 + C) >> 4) + ((int)inP[Element] << SHIFT));\
1317
	if (Err > THRESHOLD) {\
1318
	  out |= Bit;\
1319
	  Err -= MAXVALUE;\
1320
	}\
1321
	errP[Element + Offset] += ((Err * 3 + C) >> 4);\
1322
	errP[Element] = ((Err * 5 + oldErr + C) >> 4);
1323
 
1324
/* Here we rely on compiler optimisation to remove lines of the form
1325
 * (if (1 >= 4) {...}, ie. the constant boolean expressions */
1326
 
1327
/* The original code is in the #else part. Since by default NEW_DITHER
1328
   is not defined, the old code is used. No enhancement is visible for the
1329
   bjc600 drivers with the new code, anyway :-( */
1330
 
1331
#ifdef NEW_DITHER
1332
 
1333
#define FSDline(scan, i, j, plane_size, cErr, mErr, yErr, kErr, cP, mP, yP, kP, n)\
1334
{\
1335
    if (scan == 0) {       /* going_up */\
1336
      for (i = 0; i < plane_size; i++) {\
1337
	byte c, y, m, k, bitmask;\
1338
	int oldErr;\
1339
	bitmask = 0x80;\
1340
	for (c = m = y = k = 0; bitmask != 0; bitmask >>= 1) {\
1341
	  if (n >= 4) {\
1342
	      FSdither(dp, k, ep, kErr, bitmask, -n, 0);\
1343
	  }\
1344
	  if (n >= 3) {\
1345
	      FSdither(dp, c, ep, cErr, bitmask, -n, n - 3);\
1346
	      FSdither(dp, m, ep, mErr, bitmask, -n, n - 2);\
1347
	  }\
1348
	  FSdither(dp, y, ep, yErr, bitmask, -n, n - 1);\
1349
	  dp += n, ep += n;\
1350
	}\
1351
	if (n >= 4)\
1352
	  *kP++ = k;\
1353
	if (n >= 3) {\
1354
	  *cP++ = c;\
1355
          *mP++ = m;\
1356
	}\
1357
	*yP++ = y;\
1358
      }\
1359
    } else {		/* going_down */\
1360
      for (i = 0; i < plane_size; i++) {\
1361
	byte c, y, m, k, bitmask;\
1362
	int oldErr;\
1363
	bitmask = 0x01;\
1364
	for (c = m = y = k = 0; bitmask != 0; bitmask <<= 1) {\
1365
          dp -= n, ep -= n;\
1366
	  FSdither(dp, y, ep, yErr, bitmask, n, n - 1);\
1367
	  if (n >= 3) {\
1368
	    FSdither(dp, m, ep, mErr, bitmask, n, n - 2);\
1369
	    FSdither(dp, c, ep, cErr, bitmask, n, n - 3);\
1370
	  }\
1371
	  if (n >= 4) {\
1372
	    FSdither(dp, k, ep, kErr, bitmask, n, 0);\
1373
	  }\
1374
	}\
1375
	*--yP = y;\
1376
	if (n >= 3)\
1377
	  { *--mP = m;\
1378
	    *--cP = c;\
1379
	  }\
1380
	if (n >= 4)\
1381
	  *--kP = k;\
1382
      }\
1383
    }\
1384
}
1385
 
1386
#else
1387
 
1388
#define FSDline(scan, i, j, plane_size, cErr, mErr, yErr, kErr, cP, mP, yP, kP, n)\
1389
{\
1390
    if (scan == 0) {       /* going_up */\
1391
      for (i = 0; i < plane_size; i++) {\
1392
	byte c, y, m, k, bitmask;\
1393
	int oldErr;\
1394
	bitmask = 0x80;\
1395
	for (c = m = y = k = 0; bitmask != 0; bitmask >>= 1) {\
1396
	  if (n >= 4) {\
1397
	    if (*dp) {\
1398
	      FSdither(dp, k, ep, kErr, bitmask, -n, 0);\
1399
	      cErr = mErr = yErr = 0;\
1400
	    } else {\
1401
	      FSdither(dp, c, ep, cErr, bitmask, -n, n - 3);\
1402
	      FSdither(dp, m, ep, mErr, bitmask, -n, n - 2);\
1403
	      FSdither(dp, y, ep, yErr, bitmask, -n, n - 1);\
1404
	    }\
1405
	  } else {\
1406
	    if (n >= 3) {\
1407
	      FSdither(dp, c, ep, cErr, bitmask, -n, n - 3);\
1408
	      FSdither(dp, m, ep, mErr, bitmask, -n, n - 2);\
1409
	    }\
1410
	    FSdither(dp, y, ep, yErr, bitmask, -n, n - 1);\
1411
	  }\
1412
	  dp += n, ep += n;\
1413
	}\
1414
	if (n >= 4)\
1415
	  *kP++ = k;\
1416
	if (n >= 3) {\
1417
	  *cP++ = c;\
1418
          *mP++ = m;\
1419
	}\
1420
	*yP++ = y;\
1421
      }\
1422
    } else {		/* going_down */\
1423
      for (i = 0; i < plane_size; i++) {\
1424
	byte c, y, m, k, bitmask;\
1425
	int oldErr;\
1426
	bitmask = 0x01;\
1427
	for (c = m = y = k = 0; bitmask != 0; bitmask <<= 1) {\
1428
          dp -= n, ep -= n;\
1429
	  if (n >= 4) {\
1430
            if (*dp) {\
1431
	      FSdither(dp, k, ep, kErr, bitmask, n, 0);\
1432
	      cErr = mErr = yErr = 0;\
1433
	    } else {\
1434
	      FSdither(dp, y, ep, yErr, bitmask, n, n - 1);\
1435
	      FSdither(dp, m, ep, mErr, bitmask, n, n - 2);\
1436
	      FSdither(dp, c, ep, cErr, bitmask, n, n - 3);\
1437
	    }\
1438
	  } else {\
1439
	    FSdither(dp, y, ep, yErr, bitmask, n, n - 1);\
1440
	    if (n >= 3) {\
1441
	      FSdither(dp, m, ep, mErr, bitmask, n, n - 2);\
1442
	      FSdither(dp, c, ep, cErr, bitmask, n, n - 3);\
1443
	    }\
1444
	  }\
1445
	}\
1446
	*--yP = y;\
1447
	if (n >= 3)\
1448
	  { *--mP = m;\
1449
	    *--cP = c;\
1450
	  }\
1451
	if (n >= 4)\
1452
	  *--kP = k;\
1453
      }\
1454
    }\
1455
}
1456
 
1457
#endif
1458
 
1459
/* END MACROS FOR DITHERING */
1460
 
1461
#define CPbit(inP, out, Bit, Element)\
1462
  if (inP[Element]) {\
1463
    out |= Bit;\
1464
  }
1465
 
1466
#define COPYline(scan, i, j, plane_size, cP, mP, yP, kP, n)\
1467
{\
1468
    if (scan == 0) {       /* going_up */\
1469
      for (i = 0; i < plane_size; i++) {\
1470
	byte c, y, m, k, bitmask;\
1471
	bitmask = 0x80;\
1472
	for (c = m = y = k = 0; bitmask != 0; bitmask >>= 1) {\
1473
	  if (n >= 4) {\
1474
	    CPbit(dp, k, bitmask, 0);\
1475
	  } \
1476
          if (n >= 3) {\
1477
	    CPbit(dp, c, bitmask, n - 3);\
1478
	    CPbit(dp, m, bitmask, n - 2);\
1479
	  }\
1480
	  CPbit(dp, y, bitmask, n - 1);\
1481
	  dp += n, ep += n;\
1482
	}\
1483
	if (n >= 4)\
1484
	  *kP++ = k;\
1485
	if (n >= 3) {\
1486
	  *cP++ = c;\
1487
          *mP++ = m;\
1488
	}\
1489
	*yP++ = y;\
1490
      }\
1491
    } else {		/* going_down */\
1492
      for (i = 0; i < plane_size; i++) {\
1493
	byte c, y, m, k, bitmask;\
1494
	bitmask = 0x01;\
1495
	for (c = m = y = k = 0; bitmask != 0; bitmask <<= 1) {\
1496
          dp -= n, ep -= n;\
1497
	  if (n >= 4) {\
1498
            CPbit(dp, k, bitmask, 0);\
1499
	  }\
1500
	  if (n >= 3) {\
1501
	    CPbit(dp, m, bitmask, n - 2);\
1502
	    CPbit(dp, c, bitmask, n - 3);\
1503
	  }\
1504
	  CPbit(dp, y, bitmask, n - 1);\
1505
	}\
1506
	*--yP = y;\
1507
	if (n >= 3)\
1508
	  { *--mP = m;\
1509
	    *--cP = c;\
1510
	  }\
1511
	if (n >= 4)\
1512
	  *--kP = k;\
1513
      }\
1514
    }\
1515
}
1516
 
1517
/* Some convenient shorthand .. */
1518
#define x_dpi        (pdev->x_pixels_per_inch)
1519
#define y_dpi        (pdev->y_pixels_per_inch)
1520
#define CONFIG_16BIT "\033*v6W\000\003\000\005\006\005"
1521
#define CONFIG_24BIT "\033*v6W\000\003\000\010\010\010"
1522
 
1523
/* To calculate buffer size as next greater multiple of both parameter and W */
1524
#define calc_buffsize(a, b) (((((a) + ((b) * W) - 1) / ((b) * W))) * W)
1525
 
1526
 
1527
/*
1528
 * Miscellaneous functions for Canon BJC-600 printers in raster command mode.
1529
 */
1530
#define fputshort(n, f) fputc((n)%256,f);fputc((n)/256,f)
1531
 
1532
private int
1533
bjc_cmd(byte cmd, int argsize, byte* arg, gx_device_printer* pdev,
1534
    FILE* f)
1535
{
1536
  fputs("\033(", f);
1537
  putc(cmd, f);
1538
  fputshort(argsize, f);
1539
  fwrite(arg, sizeof(byte), argsize, f);
1540
 
1541
  return 0;
1542
}
1543
 
1544
 
1545
private int
1546
bjc_raster_cmd_sub(char c, int rastsize, byte* data, FILE* f)
1547
{
1548
  fputs("\033(A", f);
1549
  fputshort(rastsize + 1, f);
1550
  putc(c, f);
1551
  fwrite(data, sizeof(byte), rastsize, f);
1552
  putc('\015', f);
1553
 
1554
  return 0;
1555
}
1556
 
1557
private int
1558
bjc_raster_cmd(int c_id, int rastsize, byte* data, gx_device_printer* pdev,
1559
    FILE* f)
1560
{
1561
    if (bjcparams.printColors == BJC_COLOR_ALLBLACK) {
1562
	bjc_raster_cmd_sub('K', rastsize, data, f);
1563
    } else if (pdev->color_info.num_components == 1) {
1564
	if (bjcparams.printColors & BJC_COLOR_BLACK) {
1565
	    bjc_raster_cmd_sub('K', rastsize, data, f);
1566
	} else {
1567
	    if (bjcparams.printColors & BJC_COLOR_YELLOW)
1568
		bjc_raster_cmd_sub('Y', rastsize, data, f);
1569
	    if (bjcparams.printColors & BJC_COLOR_MAGENTA)
1570
		bjc_raster_cmd_sub('M', rastsize, data, f);
1571
	    if (bjcparams.printColors & BJC_COLOR_CYAN)
1572
		bjc_raster_cmd_sub('C', rastsize, data, f);
1573
	}
1574
    }else {			/* Color decomposition */
1575
	private byte ymckCodes[] = {
1576
	    BJC_COLOR_YELLOW,
1577
	    BJC_COLOR_MAGENTA,
1578
	    BJC_COLOR_CYAN,
1579
	    BJC_COLOR_BLACK,
1580
	};
1581
 
1582
	if (bjcparams.printColors & (int) ymckCodes[c_id]) {
1583
	    bjc_raster_cmd_sub("YMCK"[c_id], rastsize, data, f);
1584
	}
1585
    }
1586
 
1587
    return 0;
1588
}
1589
 
1590
private int
1591
bjc_init_page(gx_device_printer* pdev, FILE* f)
1592
{
1593
    byte pagemargins[3], resolution[4], paperloading[2];
1594
 
1595
    /* Compute page margins. */
1596
 
1597
    pagemargins[0] = (byte) ((float) pdev->height / pdev->y_pixels_per_inch
1598
        * 10 + .5);
1599
    pagemargins[1] = (byte) 1;
1600
    pagemargins[2] = (byte) ((pdev->width / pdev->x_pixels_per_inch * 10) -
1601
        pdev->HWMargins[0] / 7.2 - pdev->HWMargins[2] / 7.2 + .5);
1602
 
1603
    /* Cheat to keep margins into bounds (while waiting to have the right
1604
       margins for big papers. */
1605
 
1606
    switch (bjc->ptype) {
1607
	case BJC800:
1608
	    if (pagemargins[2] > 114) pagemargins[2] = 114;
1609
	    break;
1610
 
1611
	default:
1612
	    if (pagemargins[2] > 80) pagemargins[2] = 80;
1613
	    break;
1614
    }
1615
 
1616
    /* Initialize resolution argument. */
1617
 
1618
    resolution[0] = (byte) ((int)pdev->y_pixels_per_inch / 256);
1619
    resolution[1] = (byte) ((int)pdev->y_pixels_per_inch % 256);
1620
    resolution[2] = (byte) ((int)pdev->x_pixels_per_inch / 256);
1621
    resolution[3] = (byte) ((int)pdev->x_pixels_per_inch % 256);
1622
 
1623
    /* Initialize paper loading argument. */
1624
 
1625
    paperloading[0] = 0x10 + ((1 - bjcparams.manualFeed) << 2);
1626
    paperloading[1] = bjcparams.mediaType << 4;
1627
 
1628
    /* Reinitialize printer in raster mode. */
1629
 
1630
    fputs("\033[K", f);
1631
    fputshort(2, f);
1632
    fputc(0x00, f);
1633
    fputc(0x0f, f);
1634
 
1635
    /* Set page mode on (ignore data at end of page) */
1636
 
1637
    bjc_cmd('a', 1, (byte*) "\001", pdev, f);
1638
 
1639
    /* Set page margins */
1640
 
1641
    bjc_cmd('g', 3, pagemargins, pdev, f);
1642
 
1643
    /* Set compression on (this is PackBits compression a la TIFF/Mac) */
1644
 
1645
    bjc_cmd('b', 1, (byte*) "\001", pdev, f);
1646
 
1647
    /* Set paper loading. */
1648
 
1649
    bjc_cmd('l', 2, paperloading, pdev, f);
1650
 
1651
    /* Set printing method. */
1652
 
1653
#ifndef BJC_INIT_800_AS_600
1654
    if (bjc->ptype == BJC800) {
1655
#else
1656
    if (0) {
1657
#endif
1658
	byte printmode[2];
1659
 
1660
	printmode[0] = bjcparams.printQuality;
1661
 
1662
	/* Modes not used are 3 (CN, Color Normal) and 2 (TP+ (?)) */
1663
 
1664
	switch (bjcparams.printQuality) {
1665
	    case BJC_QUALITY_DRAFT:
1666
	        printmode[0] = 4;			/* Draft */
1667
		break;
1668
	}
1669
 
1670
	printmode[1] = (bjcparams.mediaType >= BJC_MEDIA_ENVELOPE ? 1 :
1671
	    bjc800thickpaper());
1672
 
1673
	bjc_cmd('c', 2, printmode, pdev, f);
1674
    } else /* BJC600 */ {
1675
	byte printmeth[3];
1676
 
1677
	printmeth[0] = 0x10 + ((1 - bjcparams.manualFeed) << 2);
1678
	printmeth[1] = (bjcparams.mediaType << 4) + bjcparams.printQuality;
1679
	printmeth[2] = (bjcparams.printQuality == BJC_QUALITY_HIGH ?
1680
	    0x10 : 0) + (bjcparams.mediaType >= BJC_MEDIA_ENVELOPE ? 1 :
1681
	         bjc600thickpaper());
1682
 
1683
    	bjc_cmd('c', 3, printmeth, pdev, f);
1684
    }
1685
 
1686
    /* Set raster resolution */
1687
 
1688
    bjc_cmd('d', 4, resolution, pdev, f);
1689
 
1690
    return 0;
1691
}
1692
 
1693
private int
1694
bjc_v_skip(int n, gx_device_printer* pdev, FILE* f)
1695
{
1696
    if (n) {
1697
	fputs("\033(e", f);
1698
	putc(2, f);
1699
	putc(0, f);
1700
	putc(n / 256, f);
1701
	putc(n % 256, f);
1702
    }
1703
 
1704
    return 0;
1705
}
1706
 
1707
private int
1708
bjc_finish_page(gx_device_printer* pdev, FILE* f)
1709
{
1710
    bjc_cmd('a', 1, (byte*) "\000", pdev, f);
1711
    bjc_cmd('b', 1, (byte*) "\000", pdev, f);
1712
    fputc('\014', f);
1713
    fputs("\033@", f);
1714
 
1715
    return 0;
1716
}
1717
 
1718
/* 1D runlength compression for BJC-600
1719
 * this code is borrowed from gdevpcl.c:gdev_pcl_mode2compress.
1720
 */
1721
private int
1722
bjc_compress(const byte *row, const byte *end_row, byte *compressed)
1723
{
1724
  register const byte *exam = row;
1725
  register byte *cptr = compressed; /* output pointer into compressed bytes */
1726
 
1727
 
1728
  while ( exam < end_row ) {
1729
    /* Search ahead in the input looking for a run */
1730
    /* of at least 4 identical bytes. */
1731
    const byte *compr = exam;
1732
    const byte *end_dis;
1733
    const byte *next;
1734
    register byte test, test2;
1735
 
1736
    test = *exam;
1737
    while ( exam < end_row ) {
1738
      test2 = *++exam;
1739
      if ( test == test2 )
1740
	  break;
1741
      test = test2;
1742
    }
1743
 
1744
 
1745
    /* Find out how long the run is */
1746
    end_dis = exam - 1;
1747
    if ( exam == end_row ) { /* no run */
1748
      next = --end_row;
1749
    } else { 
1750
 
1751
      next = exam + 1;
1752
      while ( next < end_row && *next == test ) next++;
1753
    }
1754
 
1755
 
1756
    /* Now [compr..end_dis) should be encoded as dissimilar, */
1757
    /* and [end_dis..next) should be encoded as similar. */
1758
    /* Note that either of these ranges may be empty. */
1759
 
1760
 
1761
    for ( ; ; ) {	/* Encode up to 128 dissimilar bytes */
1762
      uint count = end_dis - compr; /* uint for faster switch */
1763
      switch ( count ) { /* Use memcpy only if it's worthwhile. */
1764
      case 6: cptr[6] = compr[5];
1765
      case 5: cptr[5] = compr[4];
1766
      case 4: cptr[4] = compr[3];
1767
      case 3: cptr[3] = compr[2];
1768
      case 2: cptr[2] = compr[1];
1769
      case 1: cptr[1] = compr[0];
1770
	*cptr = count - 1;
1771
	cptr += count + 1;
1772
      case 0: /* all done */
1773
	break;
1774
      default:
1775
	if ( count > 128 ) count = 128;
1776
	*cptr++ = count - 1;
1777
	memcpy(cptr, compr, count);
1778
	cptr += count, compr += count;
1779
	continue;
1780
      }
1781
      break;
1782
    }
1783
 
1784
 
1785
    {	/* Encode up to 128 similar bytes. */
1786
      /* Note that count may be <0 at end of row. */
1787
      int count = next - end_dis;
1788
      if (next < end_row || test != 0)
1789
	while ( count > 0 ) { 
1790
 
1791
	  int this = (count > 128 ? 128 : count);
1792
	  *cptr++ = 257 - this;
1793
	  *cptr++ = (byte)test;
1794
	  count -= this;
1795
	}
1796
      exam = next;
1797
    }
1798
  }
1799
  return cptr - compressed;
1800
}
1801
 
1802
/*
1803
 * For the ESC/P mode, resolution is fixed as 360dpi and we must transform
1804
 * image data to serialized data.
1805
 */
1806
private word *ep_storage;
1807
private uint ep_storage_size_words;
1808
private byte *ep_raster_buf[4][BJC_HEAD_ROWS], *ep_print_buf;
1809
private int ep_num_comps, ep_plane_size, img_rows=BJC_HEAD_ROWS;
1810
 
1811
 
1812
#define row_bytes (img_rows / 8)
1813
#define row_words (row_bytes / sizeof(word))
1814
#define min_rows (32)		/* for optimization of text image printing */
1815
 
1816
 
1817
private int
1818
ep_print_image(FILE *prn_stream, char cmd, byte *data, int size)
1819
{
1820
  static int ln_idx=0, vskip1=0, vskip2=0, real_rows;
1821
  int i;
1822
  static const char color[4] = {4,1,2,0};
1823
 
1824
 
1825
  switch (cmd) {
1826
  case 3:			/* Black */
1827
  case 2:			/* Cyan */
1828
  case 1:			/* Magenta */
1829
  case 0:			/* Yellow */
1830
    memcpy(ep_raster_buf[((int) cmd)][ln_idx+vskip2], data, size);
1831
    return 0;
1832
  case 'B':			/* blank line skip */
1833
    if (!ln_idx) {
1834
      vskip1 += size;
1835
    } else if (size >= img_rows - (ln_idx+vskip2) || ln_idx+vskip2 >= min_rows) {
1836
      /* The 'I' cmd must precede 'B' cmd! */
1837
      vskip2 += size;
1838
      ep_print_image(prn_stream, 'F', 0, 0); /* flush and reset status */
1839
    } else {
1840
      vskip2 += size;
1841
    }
1842
    return 0;
1843
  case 'I':			/* Increment index */
1844
    ln_idx += vskip2 + 1;
1845
    vskip2 = 0;
1846
    if (ln_idx < img_rows) return 0;
1847
    /* if ep_raster_buf filled up, then fall through here and flush buffer */
1848
  case 'F':			/* flush print buffer */
1849
    if (!ln_idx) return 0;	/* The end of the page. */
1850
 
1851
 
1852
    /* before print the image, perform vertical skip. */
1853
    while (vskip1 >= (255*2)) {
1854
      fputs("\033J\377", prn_stream); /* n/180in. feeding */
1855
      vskip1 -= (255*2);
1856
    }
1857
    if (vskip1 > 255) {
1858
      fputs("\033J\200", prn_stream);
1859
      vskip1 -= 256;
1860
    }
1861
    if (vskip1) {
1862
      /* n/360in. feeding */
1863
      fputs("\033|J", prn_stream); putc(0, prn_stream); putc(vskip1, prn_stream);
1864
    }
1865
 
1866
 
1867
    /* Optimize the number of nozzles to be used. */
1868
    if (ln_idx > 56) {		/* use 64 nozzles */
1869
      real_rows = 64;
1870
    } else if (ln_idx > 48) {	/* use 56 nozzles */
1871
      real_rows = 56;
1872
    } else if (ln_idx > 32) {	/* use 48 nozzles */
1873
      real_rows = 48;
1874
    } else {			/* use 32 nozzles */
1875
      real_rows = 32;
1876
    }
1877
 
1878
 
1879
    for (i = 0; i < ep_num_comps; i++) {
1880
      int lnum, hskip, print_size, img_rows;
1881
      byte *p0, *p1, *p2, *p3;
1882
      byte *inp, *inbuf, *outp, *outbuf;
1883
 
1884
 
1885
      img_rows = real_rows;	/* Note that this img_rows is not the one that
1886
				 * defined out of this function. */
1887
      outbuf = ep_print_buf;
1888
 
1889
 
1890
      /* Transpose raster image for serial printer image */
1891
      for (lnum=0; lnum < img_rows; lnum+=8, outbuf++) {
1892
	inbuf = inp = ep_raster_buf[i][lnum];
1893
	for (outp = outbuf; inp < inbuf+ep_plane_size; inp++, outp += img_rows) {
1894
	  memflip8x8(inp, ep_plane_size, outp, row_bytes);
1895
	}
1896
      }
1897
 
1898
 
1899
      /* Set color */
1900
      if (ep_num_comps == 1) {
1901
	/* Don't set color (to enable user setting). */
1902
	putc('\015', prn_stream);
1903
      } else {
1904
	/* set color to one of CMYK. */
1905
	fputs("\015\033r", prn_stream);
1906
	putc(color[i], prn_stream);
1907
      }
1908
 
1909
 
1910
      *(outp = ep_print_buf + ep_plane_size * img_rows) = 1; /* sentinel */
1911
 
1912
 
1913
      p0 = p3 = ep_print_buf;
1914
 
1915
 
1916
      /* print image p0 to p1 and h skip p1 to p2 if p2<outp,
1917
       * then make p0=p2 and continue */
1918
      while (p0 < outp) {
1919
	static const word zeros[8] = {0,0,0,0,0,0,0,0};
1920
 
1921
 
1922
	if (p3 < outp) {
1923
	  /* p1 is the head of running zeros. */
1924
	  /* note that h skip unit is 1/180inch */
1925
	  for (p1 = p3; !memcmp(p3, zeros, row_bytes*2); p3 += row_bytes*2);
1926
	  /* p2 is the head of non zero image. */
1927
	  p2 = p3;
1928
	redo:
1929
	  for (p3 += row_bytes; memcmp(p3, zeros, row_bytes); p3 += row_bytes);
1930
	  if (p3 < outp && memcmp(p3+row_bytes, zeros, row_bytes)) goto redo;
1931
	} else p1 = p2 = outp;
1932
 
1933
 
1934
	if (p0 < p1) {	/* print the image between p0 and p1 */
1935
	  print_size = ((p1 < outp) ? p1 : outp) - p0;
1936
	  fputs("\033|B", prn_stream); putc(img_rows, prn_stream);
1937
	  fputshort(print_size, prn_stream);
1938
	  fwrite(p0, sizeof(byte), print_size, prn_stream);
1939
	}
1940
	if (p1 < p2) {	/* skip running zeros from p1 to p2 */
1941
	  hskip = (((p2 < outp) ? p2 : outp) - p1) / row_bytes / 2;
1942
	  fputs("\033\\", prn_stream);
1943
	  fputshort(hskip, prn_stream);
1944
	}
1945
	p0 = p2;
1946
      }
1947
    }
1948
    return ep_print_image(prn_stream, 'R', 0, vskip2 + ln_idx); 
1949
  case 'R':			/* Reset status */
1950
    ln_idx = 0;
1951
    vskip1 = size;
1952
    vskip2 = 0;
1953
    memset(ep_storage, 0, ep_storage_size_words * W);
1954
    return 0;
1955
  default:			/* This should not happen */
1956
    errprintf("ep_print_image: illegal command character `%c'.\n", cmd);
1957
    return 1;
1958
  }
1959
 
1960
 
1961
  /* NOT REACHED */
1962
}
1963
 
1964
 
1965
/* Send the page to the printer.  Compress each scan line. */
1966
private int
1967
hp_colour_print_page(gx_device_printer * pdev, FILE * prn_stream, int ptype)
1968
{
1969
  uint raster_width = gdev_prn_rasterwidth(pdev, 1);
1970
/*  int line_size = gdev_prn_rasterwidth(pdev, 0); */
1971
  int line_size = gdev_prn_raster(pdev);
1972
  int line_size_words = (line_size + W - 1) / W;
1973
  int paper_size = gdev_pcl_paper_size((gx_device *)pdev);
1974
  int num_comps = pdev->color_info.num_components;
1975
  int bits_per_pixel = pdev->color_info.depth;
1976
  int storage_bpp = bits_per_pixel;
1977
  int expanded_bpp = bits_per_pixel;
1978
  int plane_size, databuff_size;
1979
  int combined_escapes = 1;
1980
  int errbuff_size = 0;
1981
  int outbuff_size = 0;
1982
  int compression = 0;
1983
  int scan = 0;
1984
  int *errors[2];
1985
  const char *cid_string = (const char*) 0;
1986
  byte *data[4], *plane_data[4][4], *out_data;
1987
  byte *out_row, *out_row_alt;
1988
  word *storage;
1989
  uint storage_size_words;
1990
 
1991
  /* Tricks and cheats ... */
1992
  switch (ptype) {
1993
  case DJ550C:
1994
    if (num_comps == 3 && !cprn_device->cmyk)
1995
      num_comps = 4;                      /* 4-component printing */
1996
    break;
1997
  case ESC_P:
1998
    if (bits_per_pixel == 24)	/* prefer 3-component printing for bpp=24. */
1999
      num_comps = 3;
2000
    else
2001
      if (num_comps != 1)
2002
        num_comps = 4;
2003
    break;
2004
  case PJXL300:
2005
  case PJXL180:
2006
    if (pjxl->rendertype > 0) {
2007
      if (bits_per_pixel < 16)
2008
	pjxl->rendertype = 0;
2009
      else {
2010
	/* Control codes for CID sequence */
2011
	cid_string = (bits_per_pixel == 16) ? CONFIG_16BIT : CONFIG_24BIT;
2012
	/* Pretend we're a monobit device so we send the data out unchanged */
2013
	bits_per_pixel = storage_bpp = expanded_bpp = 1;
2014
	num_comps = 1;
2015
      }
2016
    }
2017
    break;
2018
  }
2019
 
2020
  if (cprn_device->cmyk <= 0) {
2021
      if (storage_bpp == 8 && num_comps >= 3)
2022
	  bits_per_pixel = expanded_bpp = 3;	/* Only 3 bits of each byte used */
2023
  }
2024
 
2025
  plane_size = calc_buffsize(line_size, storage_bpp);
2026
  ep_plane_size = plane_size;
2027
 
2028
  if (bits_per_pixel == 1) {		/* Data printed direct from i/p */
2029
    databuff_size = 0;			/* so no data buffer required, */
2030
    outbuff_size = plane_size * 4;	/* but need separate output buffers */
2031
  }
2032
 
2033
  if (bits_per_pixel > 4) {		/* Error buffer for FS dithering */
2034
    storage_bpp = expanded_bpp = 
2035
      num_comps * 8;			/* 8, 24 or 32 bits */
2036
 
2037
    if (cprn_device->cmyk > 0) {	/* Use CMYK dithering algorithm. */
2038
	errbuff_size = 4 * (5 + 1 + 1 + line_size + 1 + 2) * I;
2039
    } else {			/* Use original (RGB) dithering. */
2040
	errbuff_size =			/* 4n extra values for line ends */
2041
	    calc_buffsize((plane_size * expanded_bpp + num_comps * 4) * I, 1);
2042
    }
2043
  }
2044
 
2045
  databuff_size = plane_size * storage_bpp;
2046
 
2047
  storage_size_words = ((plane_size + plane_size) * num_comps +
2048
			databuff_size + errbuff_size + outbuff_size) / W;
2049
 
2050
  storage = (ulong *) gs_malloc(pdev->memory, storage_size_words, W, "hp_colour_print_page");
2051
  ep_storage_size_words = (plane_size * (num_comps + 1)) / W * img_rows
2052
      + 16;			/* Redundant space for sentinel and aligning. */
2053
  ep_storage = (word *) gs_malloc(pdev->memory, ep_storage_size_words, W, "ep_print_buffer");
2054
 
2055
  /*
2056
   * The principal data pointers are stored as pairs of values, with
2057
   * the selection being made by the 'scan' variable. The function of the
2058
   * scan variable is overloaded, as it controls both the alternating
2059
   * raster scan direction used in the Floyd-Steinberg dithering and also
2060
   * the buffer alternation required for line-difference compression.
2061
   *
2062
   * Thus, the number of pointers required is as follows:
2063
   * 
2064
   *   errors:      2  (scan direction only)
2065
   *   data:        4  (scan direction and alternating buffers)
2066
   *   plane_data:  4  (scan direction and alternating buffers)
2067
   */
2068
 
2069
  if (storage == 0 || ep_storage == 0) /* can't allocate working area */
2070
    return_error(gs_error_VMerror);
2071
  else {
2072
    int i, j;
2073
    byte *p = out_data = out_row = (byte *)storage;
2074
    byte *ep_p = (byte *)ep_storage;
2075
    data[0] = data[1] = data[2] = p;
2076
    data[3] = p + databuff_size;
2077
    out_row_alt = out_row + plane_size * 2;
2078
    if (bits_per_pixel > 1) {
2079
      p += databuff_size;
2080
    }
2081
    if (bits_per_pixel > 4) {
2082
      errors[0] = (int *)p + num_comps * 2;
2083
      errors[1] = errors[0] + databuff_size;
2084
      p += errbuff_size;
2085
    }
2086
    for (i = 0; i < num_comps; i++) {
2087
      plane_data[0][i] = plane_data[2][i] = p;
2088
      p += plane_size;
2089
    }
2090
    for (i = 0; i < num_comps; i++) {
2091
      plane_data[1][i] = p;
2092
      plane_data[3][i] = p + plane_size;
2093
      p += plane_size;
2094
    }
2095
    if (bits_per_pixel == 1) {
2096
      out_data = out_row = p;	  /* size is outbuff_size * 4 */
2097
      out_row_alt = out_row + plane_size * 2;
2098
      data[1] += databuff_size;   /* coincides with plane_data pointers */
2099
      data[3] += databuff_size;
2100
    }
2101
    for (i = 0; i < num_comps; i++) {
2102
      for (j = 0; j < img_rows; j++) {
2103
	ep_raster_buf[i][j] = ep_p;
2104
	ep_p += plane_size;
2105
      }
2106
      /* Make a sentinel and align to word size.  */
2107
      ep_print_buf = (byte *)((word)(ep_p + sizeof(word)) & ~(sizeof(word)-1));
2108
    }
2109
    ep_num_comps = num_comps;
2110
  }
2111
 
2112
  /* Initialize printer. */
2113
  if (ptype == BJC600 || ptype == BJC800) {
2114
    bjc_init_page(pdev, prn_stream);
2115
  } else {
2116
      if (ptype == LJ4DITH)  {
2117
	  fputs("\033*rB", prn_stream);
2118
      } else {
2119
	  fputs("\033*rbC", prn_stream);                   /* End raster graphics */
2120
      }
2121
      fprintf(prn_stream, "\033*t%dR", (int)x_dpi); 
2122
  /* Set resolution */
2123
  }
2124
 
2125
  /* Clear temp storage */
2126
  memset(storage, 0, storage_size_words * W);
2127
 
2128
#define DOFFSET (dev_t_margin(pdev) - DESKJET_PRINT_LIMIT)	/* Print position */
2129
#define POFFSET (dev_t_margin(pdev) - PAINTJET_PRINT_LIMIT)
2130
#define EOFFSET (dev_t_margin(pdev) - ESC_P_PRINT_LIMIT)
2131
#define BOFFSET (dev_t_margin(pdev) - bjc->printLimit)
2132
  switch (ptype) {
2133
  case LJ4DITH:
2134
    /* Page size, orientation, top margin & perforation skip */
2135
    fprintf(prn_stream, "\033&l26A\033&l0o0e0L\033*r0F" );
2136
    fprintf(prn_stream, "\033*p0x0Y" ); /* These Offsets are hacked ! */
2137
    fprintf(prn_stream, "\033&u600D\033*r1A" );
2138
    /* Select data compression */
2139
    compression = 3;
2140
    combined_escapes = 0;
2141
    break;
2142
  case DJ500C:
2143
  case DJ550C:
2144
    /* Page size, orientation, top margin & perforation skip */
2145
    fprintf(prn_stream, "\033&l%daolE", paper_size);
2146
    /* Set depletion and shingling levels */
2147
    fprintf(prn_stream, "\033*o%dd%dQ", cdj->depletion, cdj->shingling);
2148
    /* Move to top left of printed area */
2149
    fprintf(prn_stream, "\033*p%dY", (int)(300 * DOFFSET));
2150
    /* Set number of planes ((-)1 is mono, (-)3 is (cmy)rgb, -4 is cmyk),
2151
     * and raster width, then start raster graphics */
2152
    fprintf(prn_stream, "\033*r%ds-%du0A", raster_width, num_comps);
2153
    /* Select data compression */
2154
    compression = 9;
2155
    break;
2156
  case DNJ650C:
2157
    if (pdev->x_pixels_per_inch == 600) {
2158
        /* set resolution to 600dpi 1st through PJL command */
2159
        fprintf(prn_stream,"\033%%-12345X@PJL SET RESOLUTION = 600\n");
2160
    }
2161
    fprintf (prn_stream, "\033%%0B"); /* Enter HPGL/2 mode */
2162
    fprintf (prn_stream, "BP5,1"); /* Turn off autorotation */
2163
    fprintf (prn_stream, "PS%d,%d",
2164
	     (int)((pdev->height/pdev->y_pixels_per_inch)*1016),
2165
	     (int)((pdev->width/pdev->x_pixels_per_inch)*1016)); /* Set length/width of page */
2166
    fprintf (prn_stream, "PU"); /* Pen up */
2167
    fprintf (prn_stream, "PA%d,%d", 0, 0); /* Move pen to upper-left */
2168
    fprintf (prn_stream, "\033%%1A"); /* Enter HP-RTL mode */
2169
    fprintf (prn_stream, "\033&a1N"); /* No negative motion - allow plotting
2170
						while receiving */
2171
    if (pdev->x_pixels_per_inch == 600) 
2172
        fprintf (prn_stream, "\033*t600R"); /* request 600dpi via HP RTL */
2173
    { static const char temp[] = {
2174
        033, '*', 'v', '6', 'W',
2175
	000 /* color model */,
2176
	000 /* pixel encoding mode */,
2177
	003 /* number of bits per index */,
2178
	010 /* bits red */,
2179
	010 /* bits green */,
2180
	010 /* bits blue */
2181
      };
2182
      fwrite (temp, 1, sizeof(temp), prn_stream);
2183
    }
2184
 
2185
    /* Set raster width */
2186
    fprintf(prn_stream, "\033*r%dS", raster_width);
2187
    /* Start raster graphics */
2188
    fprintf(prn_stream, "\033*r1A");
2189
 
2190
    /* Select data compression */
2191
    compression = 1;
2192
    /* No combined escapes for raster transfers */
2193
    combined_escapes = 0;
2194
    break;
2195
  case PJXL300:
2196
    /* Page size, orientation, top margin & perforation skip */
2197
    fprintf(prn_stream, "\033&l%daolE", paper_size);
2198
    /* Set no-negative-motion mode, for faster (unbuffered) printing */
2199
    fprintf(prn_stream, "\033&a1N");
2200
    /* Set print quality */
2201
    fprintf(prn_stream, "\033*o%dQ", pjxl->printqual);
2202
    /* Move to top left of printed area */
2203
    fprintf(prn_stream, "\033*p%dY", (int)(300 * POFFSET));
2204
    /* Configure colour setup */
2205
    if (pjxl->rendertype > 0) {
2206
      /* Set render type */
2207
      fprintf(prn_stream, "\033*t%dJ", pjxl->rendertype);
2208
      /* Configure image data */
2209
      fputs(cid_string, prn_stream);
2210
      /* Set raster width, then start raster graphics */
2211
      fprintf(prn_stream, "\033*r%ds1A", raster_width);
2212
    } else {
2213
      /* Set number of planes (1 is mono, 3 is rgb),
2214
       * and raster width, then start raster graphics */
2215
      fprintf(prn_stream, "\033*r%ds-%du0A", raster_width, num_comps);
2216
    }
2217
    /* No combined escapes for raster transfers */
2218
    combined_escapes = 0;
2219
    break;
2220
  case PJXL180:
2221
    /* Page size, orientation, top margin & perforation skip */
2222
    fprintf(prn_stream, "\033&l%daolE", paper_size);
2223
    /* Set print quality */
2224
    fprintf(prn_stream, "\033*o%dQ", pjxl->printqual);
2225
    /* Move to top left of printed area */
2226
    fprintf(prn_stream, "\033*p%dY", (int)(180 * POFFSET));
2227
    /* Configure colour setup */
2228
    if (pjxl->rendertype > 0) {
2229
      /* Set render type */
2230
      fprintf(prn_stream, "\033*t%dJ", pjxl->rendertype);
2231
      /* Configure image data */
2232
      fputs(cid_string, prn_stream);
2233
      /* Set raster width, then start raster graphics */
2234
      fprintf(prn_stream, "\033*r%ds1A", raster_width);
2235
    } else {
2236
      /* Set number of planes (1 is mono, 3 is rgb),
2237
       * and raster width, then start raster graphics */
2238
      fprintf(prn_stream, "\033*r%ds%du0A", raster_width, num_comps);
2239
    }
2240
    break;
2241
  case PJ180:
2242
  case DECLJ250:
2243
    /* Disable perforation skip */
2244
    fprintf(prn_stream, "\033&lL");
2245
    /* Move to top left of printed area */
2246
    fprintf(prn_stream, "\033&a%dV", (int)(720 * POFFSET));
2247
    /* Set number of planes (1 is mono, 3 is rgb),
2248
     * and raster width, then start raster graphics */
2249
    fprintf(prn_stream, "\033*r%ds%du0A", raster_width, num_comps);
2250
    if (ptype == DECLJ250) {
2251
      /* No combined escapes for raster transfers */
2252
      combined_escapes = 0;
2253
      /* From here on, we're a standard Paintjet .. */
2254
      ptype = PJ180;
2255
    }
2256
    /* Select data compression */
2257
    compression = 1;
2258
    break;
2259
  case ESC_P:
2260
    /* Move to top left of printed area (must be modified for large movement(YK))*/
2261
    if ((int)(EOFFSET*360)) fprintf(prn_stream, "\033|J%c%c", 0, (int)(360*EOFFSET));
2262
    combined_escapes = 0;
2263
    break;
2264
  case BJC600:
2265
  case BJC800:
2266
    /* Move to top left of printed area */
2267
    bjc_v_skip((int)(pdev->HWResolution[1] * BOFFSET), pdev, prn_stream);
2268
    combined_escapes = 0;
2269
    compression = 2;		/* BJC600 uses the same method as mode 2 compression */
2270
    break;
2271
  }
2272
 
2273
  /* Unfortunately, the Paintjet XL300 PCL interpreter introduces a
2274
   * version of the PCL language which is different to all earlier HP
2275
   * colour and mono inkjets, in that it loses the very useful ability
2276
   * to use combined escape sequences with the raster transfer
2277
   * commands. In this respect, it is incompatible even with the older
2278
   * 180 dpi PaintJet and PaintJet XL printers!  Another regrettable
2279
   * omission is that 'mode 9' compression is not supported, as this
2280
   * mode can give both computational and PCL file size advantages. */
2281
 
2282
  if (combined_escapes) {
2283
    /* From now on, all escape commands start with \033*b, so we
2284
     * combine them (if the printer supports this). */
2285
    fputs("\033*b", prn_stream);
2286
     /* Set compression if the mode has been defined. */
2287
    if (compression)
2288
      fprintf(prn_stream, "%dm", compression);
2289
  }
2290
  else if (ptype == BJC600 || ptype == BJC800)
2291
      ;				/* Currently, nothing to do. */
2292
  else
2293
    if (compression)
2294
      fprintf(prn_stream, "\033*b%dM", compression);
2295
 
2296
  /* Send each scan line in turn */
2297
  {
2298
    int cErr, mErr, yErr, kErr;
2299
    int this_pass, lnum, i;
2300
    int start_rows;
2301
    int lend, num_blank_lines = 0;
2302
 
2303
    word rmask = ~(word) 0 << ((-pdev->width * storage_bpp) & (W * 8 - 1));
2304
 
2305
    lend = pdev->height - 
2306
	(int)((dev_t_margin(pdev) + dev_b_margin(pdev)) * y_dpi);
2307
 
2308
    switch (ptype) {
2309
	case BJC600:
2310
	case BJC800:
2311
	    start_rows = BJC_HEAD_ROWS;
2312
	    break;
2313
 
2314
	/* Inhibit blank line printing for RGB-only printers, since in
2315
	 * this case 'blank' means black!  Also disabled for XL300 due to
2316
	 * an obscure bug in the printer's firmware */
2317
 
2318
	case PJ180:
2319
	case PJXL180:
2320
	case PJXL300:
2321
	    start_rows = -1;
2322
	    break;
2323
 
2324
	default:
2325
	    start_rows = (num_comps == 1) ? HEAD_ROWS_MONO - 1 :
2326
		HEAD_ROWS_COLOUR - 1;
2327
	    break;
2328
    }
2329
 
2330
    cErr = mErr = yErr = kErr = 0;
2331
 
2332
    if (bits_per_pixel > 4) { /* Randomly seed initial error buffer */
2333
      if (cprn_device->cmyk > 0 && expanded_bpp == 32) {
2334
	  bjc_fscmyk(data, plane_data, errors, plane_size, -1);
2335
      } else {
2336
	  int *ep = errors[0];
2337
	  for (i = 0; i < databuff_size; i++) {
2338
	      *ep++ = RANDOM;
2339
	  }
2340
      }
2341
    }
2342
 
2343
    this_pass = start_rows;
2344
    for (lnum = 0; lnum < lend; lnum++) {
2345
      word *data_words = (word *)data[scan];
2346
      register word *end_data = data_words + line_size_words;
2347
 
2348
      gdev_prn_copy_scan_lines(pdev, lnum, data[scan], line_size);
2349
 
2350
      /* Mask off 1-bits beyond the line width. */
2351
      end_data[-1] &= rmask;
2352
 
2353
      /* Remove trailing 0s. */
2354
      while (end_data > data_words && end_data[-1] == 0)
2355
	end_data--;
2356
      if (ptype != DNJ650C)	/* DesignJet can't skip blank lines ? ? */
2357
	if (end_data == data_words) {	/* Blank line */
2358
	  num_blank_lines++;
2359
	  continue;
2360
	}
2361
      /* Skip blank lines if any */
2362
      if (num_blank_lines > 0) {
2363
	if (ptype == ESC_P) {
2364
	  ep_print_image(prn_stream, 'B', 0, num_blank_lines);
2365
	} else if (ptype == BJC600 || ptype == BJC800) {
2366
	    bjc_v_skip(num_blank_lines, pdev, prn_stream);
2367
	} else if (num_blank_lines < this_pass) {
2368
	  /* Moving down from current position
2369
	   * causes head motion on the DeskJets, so
2370
	   * if the number of lines is within the
2371
	   * current pass of the print head, we're
2372
	   * better off printing blanks. */
2373
	  this_pass -= num_blank_lines;
2374
	  if (combined_escapes) {
2375
	    fputc('y', prn_stream);   /* Clear current and seed rows */
2376
	    for (; num_blank_lines; num_blank_lines--)
2377
	      fputc('w', prn_stream);
2378
	  } else {
2379
#if 0
2380
/**************** The following code has been proposed ****************/
2381
/**************** as a replacement: ****************/
2382
	    fputs("\033*b1Y", prn_stream);   /* Clear current and seed rows */
2383
	    if ( num_blank_lines > 1 )
2384
	      fprintf(prn_stream, "\033*b%dY", num_blank_lines - 1);
2385
	    num_blank_lines = 0;
2386
#else
2387
	    fputs("\033*bY", prn_stream);   /* Clear current and seed rows */
2388
	    if (ptype == DNJ650C) {
2389
	      fprintf (prn_stream, "\033*b%dY", num_blank_lines);
2390
	      num_blank_lines = 0;
2391
	    }
2392
	    else {
2393
	      for (; num_blank_lines; num_blank_lines--)
2394
	        fputs("\033*bW", prn_stream);
2395
	    }
2396
#endif
2397
	  }
2398
	} else {
2399
	  if (combined_escapes)
2400
	    fprintf(prn_stream, "%dy", num_blank_lines);
2401
	  else
2402
	    fprintf(prn_stream, "\033*b%dY", num_blank_lines);
2403
	}
2404
	memset(plane_data[1 - scan][0], 0, plane_size * num_comps);
2405
	num_blank_lines = 0;
2406
	this_pass = start_rows;
2407
      }
2408
      {			/* Printing non-blank lines */
2409
	register byte *kP = plane_data[scan + 2][3];
2410
	register byte *cP = plane_data[scan + 2][2];
2411
	register byte *mP = plane_data[scan + 2][1];
2412
	register byte *yP = plane_data[scan + 2][0];
2413
	register byte *dp = data[scan + 2];
2414
	register int *ep = errors[scan];
2415
	int zero_row_count;
2416
	int i, j;
2417
	byte *odp;
2418
 
2419
	if (this_pass)
2420
	  this_pass--;
2421
	else
2422
	  this_pass = start_rows;
2423
 
2424
	if (expanded_bpp > bits_per_pixel) {  /* Expand line if required */
2425
	    cdj_expand_line(data_words, line_size,
2426
		cprn_device->cmyk,
2427
	        bits_per_pixel, expanded_bpp);
2428
	}
2429
 
2430
	/* In colour modes, we have some bit-shuffling to do before
2431
	 * we can print the data; in FS mode we also have the
2432
	 * dithering to take care of. */
2433
	switch (expanded_bpp) {    /* Can be 1, 3, 8, 24 or 32 */
2434
	case 3:
2435
	  /* Transpose the data to get pixel planes. */
2436
	  for (i = 0, odp = plane_data[scan][0]; i < databuff_size;
2437
	       i += 8, odp++) {	/* The following is for 16-bit
2438
				 * machines */
2439
#define spread3(c)\
2440
    { 0, c, c*0x100, c*0x101, c*0x10000L, c*0x10001L, c*0x10100L, c*0x10101L }
2441
	    static ulong spr40[8] = spread3(0x40);
2442
	    static ulong spr08[8] = spread3(8);
2443
	    static ulong spr02[8] = spread3(2);
2444
	    register byte *dp = data[scan] + i;
2445
	    register ulong pword =
2446
	    (spr40[dp[0]] << 1) +
2447
	    (spr40[dp[1]]) +
2448
	    (spr40[dp[2]] >> 1) +
2449
	    (spr08[dp[3]] << 1) +
2450
	    (spr08[dp[4]]) +
2451
	    (spr08[dp[5]] >> 1) +
2452
	    (spr02[dp[6]]) +
2453
	    (spr02[dp[7]] >> 1);
2454
	    odp[0] = (byte) (pword >> 16);
2455
	    odp[plane_size] = (byte) (pword >> 8);
2456
	    odp[plane_size * 2] = (byte) (pword);
2457
	  }
2458
	  break;
2459
 
2460
	case 8:
2461
	  switch (ptype) {
2462
	      case BJC600:
2463
	      case BJC800:
2464
	          if (bjcparams.ditheringType == BJC_DITHER_NONE) {
2465
		      COPYline(scan, i, j, plane_size, cP, mP, yP, kP, 1);
2466
		      break;
2467
		  }
2468
 
2469
	      default:
2470
		  FSDline(scan, i, j, plane_size, cErr, mErr, yErr, kErr,
2471
			  cP, mP, yP, kP, 1);
2472
	  }
2473
	  break;
2474
	case 24:
2475
	  FSDline(scan, i, j, plane_size, cErr, mErr, yErr, kErr,
2476
		  cP, mP, yP, kP, 3);
2477
	  break;
2478
	case 32:
2479
	  if (cprn_device->cmyk > 0) {
2480
	      bjc_fscmyk(data, plane_data, errors, plane_size, scan);
2481
	  } else {
2482
	      FSDline(scan, i, j, plane_size, cErr, mErr, yErr, kErr,
2483
		      cP, mP, yP, kP, 4);
2484
	  }
2485
	  break;
2486
 
2487
	} /* switch(expanded_bpp) */
2488
 
2489
	/* Make sure all black is in the k plane */
2490
 
2491
	if (num_comps == 4 && (cprn_device->cmyk <= 0 || expanded_bpp != 32)) {
2492
	    register word *kp = (word *)plane_data[scan][3];
2493
	    register word *cp = (word *)plane_data[scan][2];
2494
	    register word *mp = (word *)plane_data[scan][1];
2495
	    register word *yp = (word *)plane_data[scan][0];
2496
	    if (bits_per_pixel > 4) {  /* Done as 4 planes */
2497
		for (i = 0; i < plane_size / W; i++) {
2498
		    word bits = *cp & *mp & *yp;
2499
		    *kp++ |= bits;
2500
 		    bits = ~bits;
2501
		    *cp++ &= bits;
2502
		    *mp++ &= bits;
2503
		    *yp++ &= bits;
2504
		}
2505
	    } else {  /* This has really been done as 3 planes */
2506
		for (i = 0; i < plane_size / W; i++) {
2507
		    word bits = *cp & *mp & *yp;
2508
		    *kp++ = bits;
2509
		    bits = ~bits;
2510
		    *cp++ &= bits;
2511
		    *mp++ &= bits;
2512
		    *yp++ &= bits;
2513
		}
2514
	    }
2515
	}
2516
 
2517
	/* Transfer raster graphics in the order (K), C, M, Y */
2518
 
2519
	for (zero_row_count = 0, i = num_comps - 1; i >= 0; i--) {
2520
	  int output_plane = 1;
2521
	  int out_count = 0;
2522
 
2523
	  switch (ptype) {
2524
	  case DJ500C:    /* Always compress using mode 9 */
2525
	  case DJ550C:
2526
	    out_count = gdev_pcl_mode9compress(plane_size,
2527
					       plane_data[scan][i],
2528
					       plane_data[1 - scan][i],
2529
					       out_data);
2530
 
2531
	    /* This optimisation allows early termination of the
2532
	     * row, but this doesn't work correctly in an alternating
2533
	     * mode 2 / mode 3 regime, so we only use it with mode 9
2534
	     * compression */
2535
           if (out_count == 0)
2536
             { output_plane = 0;      /* No further output for this plane */
2537
               if (i == 0)
2538
                 fputc('w', prn_stream);
2539
               else
2540
                 zero_row_count++;
2541
             }
2542
           else
2543
             { for (; zero_row_count; zero_row_count--)
2544
                 fputc('v', prn_stream);
2545
             }
2546
	    break;
2547
	  case PJ180:
2548
	  case DNJ650C:
2549
	    if (num_comps > 1)
2550
	      { word *wp = (word *)plane_data[scan][i];
2551
		for (j = 0; j < plane_size / W; j++, wp++)
2552
		  *wp = ~*wp;
2553
	      }
2554
	    out_count = gdev_pcl_mode1compress((const byte *)
2555
					       plane_data[scan][i],
2556
					       (const byte *)
2557
					       plane_data[scan][i] + plane_size - 1,
2558
					       out_data);
2559
	    break;
2560
	  case PJXL180:    /* Need to invert data as CMY not supported */
2561
	    if (num_comps > 1)
2562
	      { word *wp = (word *)plane_data[scan][i];
2563
		for (j = 0; j < plane_size / W; j++, wp++)
2564
		  *wp = ~*wp;
2565
	      }
2566
	    /* fall through .. */
2567
	  case PJXL300:     /* Compression modes 2 and 3 are both 
2568
			     * available.  Try both and see which one
2569
			     * produces the least output data. */
2570
	  case LJ4DITH:
2571
	    { const byte *plane = plane_data[scan][i];
2572
	      byte *prev_plane = plane_data[1 - scan][i];
2573
	      const word *row = (word *)plane;
2574
	      const word *end_row = row + plane_size/W;
2575
	      int count2 = gdev_pcl_mode2compress(row, end_row, out_row_alt);
2576
	      int count3 = gdev_pcl_mode3compress(plane_size, plane, prev_plane, out_row);
2577
	      int penalty = combined_escapes ? strlen("#m") : strlen("\033*b#M");
2578
	      int penalty2 = (compression == 2 ? 0 : penalty);
2579
	      int penalty3 = (compression == 3 ? 0 : penalty);
2580
 
2581
	      if (count3 + penalty3 < count2 + penalty2)
2582
		{ if ( compression != 3 ) {
2583
		    if (combined_escapes)
2584
		      fputs("3m", prn_stream);
2585
		    else
2586
		      fputs("\033*b3M", prn_stream);
2587
		    compression = 3;
2588
		  }
2589
		  out_data = out_row;
2590
		  out_count = count3;
2591
		}
2592
	      else
2593
		{ if ( compression != 2 ) {
2594
		    if (combined_escapes)
2595
		      fputs("2m", prn_stream);
2596
		    else
2597
		      fputs("\033*b2M", prn_stream);
2598
		    compression = 2;
2599
		  }
2600
		  out_data = out_row_alt;
2601
		  out_count = count2;
2602
		}
2603
	    }
2604
	    break;
2605
	  case BJC600:
2606
	  case BJC800:
2607
	    { const byte *plane = (byte *)plane_data[scan][i];
2608
	      int count2 = bjc_compress(plane, plane + plane_size, out_row_alt);
2609
 
2610
 	      out_data = out_row_alt;
2611
	      out_count = count2;
2612
	    }
2613
	    break;
2614
	  }
2615
	  if (output_plane) {
2616
	    if (combined_escapes)
2617
	      fprintf(prn_stream, "%d%c", out_count, "wvvv"[i]);
2618
	    else if (ptype == BJC600 || ptype == BJC800) {
2619
	      if (out_count)
2620
		  bjc_raster_cmd(num_comps == 1 ? 3 : i,
2621
				out_count, out_data, pdev, prn_stream);
2622
	      if (i == 0) bjc_v_skip(1, pdev, prn_stream);
2623
	    } else if (ptype == ESC_P)
2624
		ep_print_image(prn_stream, (char)i, plane_data[scan][i], plane_size);
2625
	    else
2626
	      fprintf(prn_stream, "\033*b%d%c", out_count, "WVVV"[i]);
2627
	    if (ptype < ESC_P)
2628
	      fwrite(out_data, sizeof(byte), out_count, prn_stream);
2629
	  }
2630
 
2631
	} /* Transfer Raster Graphics ... */
2632
	if (ptype == ESC_P)
2633
	    ep_print_image(prn_stream, 'I', 0, 0); /* increment line index */
2634
	scan = 1 - scan;          /* toggle scan direction */
2635
      }	  /* Printing non-blank lines */
2636
    }     /* for lnum ... */
2637
  }       /* send each scan line in turn */
2638
 
2639
  if (combined_escapes)
2640
    fputs("0M", prn_stream);
2641
 
2642
  /* end raster graphics */
2643
  if (ptype == BJC600 || ptype == BJC800) {
2644
    bjc_finish_page(pdev, prn_stream);
2645
  }
2646
  else if (ptype != ESC_P) 
2647
    fputs("\033*rbC\033E", prn_stream);
2648
 
2649
  /* eject page */
2650
  if (ptype == PJ180)
2651
    fputc('\f', prn_stream);
2652
  else if (ptype == DNJ650C)
2653
    fputs ("\033*rC\033%0BPG;", prn_stream);
2654
  else if (ptype == BJC600 || ptype == BJC800)
2655
      ;				/* Already done */
2656
  else if (ptype == ESC_P) {
2657
    ep_print_image(prn_stream, 'F', 0, 0); /* flush print buffer */
2658
    fputs("\014\033@", prn_stream);	/* reset after eject page */
2659
  } else 
2660
    fputs("\033&l0H", prn_stream);
2661
 
2662
  /* free temporary storage */
2663
  gs_free(pdev->memory, (char *) ep_storage, ep_storage_size_words, W, "ep_print_buffer");
2664
  gs_free(pdev->memory, (char *) storage, storage_size_words, W, "hp_colour_print_page");
2665
 
2666
  return 0;
2667
}
2668
 
2669
/*
2670
 * Row compression for the H-P PaintJet.
2671
 * Compresses data from row up to end_row, storing the result
2672
 * starting at compressed.  Returns the number of bytes stored.
2673
 * The compressed format consists of a byte N followed by a
2674
 * data byte that is to be repeated N+1 times.
2675
 * In the worst case, the `compressed' representation is
2676
 * twice as large as the input.
2677
 * We complement the bytes at the same time, because
2678
 * we accumulated the image in complemented form.
2679
 */
2680
private int
2681
gdev_pcl_mode1compress(const byte *row, const byte *end_row, byte *compressed)
2682
{	register const byte *in = row;
2683
	register byte *out = compressed;
2684
	while ( in < end_row )
2685
           {	byte test = *in++;
2686
		const byte *run = in;
2687
		while ( in < end_row && *in == test ) in++;
2688
		/* Note that in - run + 1 is the repetition count. */
2689
		while ( in - run > 255 )
2690
                   {	*out++ = 255;
2691
			*out++ = test;
2692
			run += 256;
2693
                   }
2694
		*out++ = in - run;
2695
		*out++ = test;
2696
           }
2697
	return out - compressed;
2698
}
2699
 
2700
/*
2701
 * Map a CMYK color to a color index. We just use depth / 4 bits per color
2702
 * to produce the color index.
2703
 *
2704
 * Important note: CMYK values are stored in the order K, C, M, Y because of
2705
 * the way the HP drivers work.
2706
 *
2707
 */
2708
 
2709
#define gx_color_value_to_bits(cv, b) \
2710
    ((cv) >> (gx_color_value_bits - (b)))
2711
#define gx_bits_to_color_value(cv, b) \
2712
    ((cv) << (gx_color_value_bits - (b)))
2713
 
2714
#define gx_cmyk_value_bits(c, m, y, k, b) \
2715
    ((gx_color_value_to_bits((k), (b)) << (3 * (b))) | \
2716
     (gx_color_value_to_bits((c), (b)) << (2 * (b))) | \
2717
     (gx_color_value_to_bits((m), (b)) << (b)) | \
2718
     (gx_color_value_to_bits((y), (b))))
2719
 
2720
#define gx_value_cmyk_bits(v, c, m, y, k, b) \
2721
    (k) = gx_bits_to_color_value(((v) >> (3 * (b))) & ((1 << (b)) - 1), (b)), \
2722
    (c) = gx_bits_to_color_value(((v) >> (2 * (b))) & ((1 << (b)) - 1), (b)), \
2723
    (m) = gx_bits_to_color_value(((v) >> (b)) & ((1 << (b)) - 1), (b)), \
2724
    (y) = gx_bits_to_color_value((v) & ((1 << (b)) - 1), (b))
2725
 
2726
private gx_color_index
2727
gdev_cmyk_map_cmyk_color(gx_device* pdev, const gx_color_value cv[])
2728
{
2729
    gx_color_value cyan, magenta, yellow, black;
2730
    gx_color_index color;
2731
    cyan = cv[0]; magenta = cv[1]; yellow = cv[2]; black = cv[3];
2732
    switch (pdev->color_info.depth) {
2733
	case 1:
2734
	   color = (cyan | magenta | yellow | black) > gx_max_color_value / 2 ?
2735
	       (gx_color_index) 1 : (gx_color_index) 0;
2736
	   break;
2737
 
2738
	default: {
2739
	    int nbits = pdev->color_info.depth;
2740
 
2741
	    color = gx_cmyk_value_bits(cyan, magenta, yellow, black,
2742
	        nbits >> 2);
2743
	 }
2744
   }
2745
 
2746
   return color;
2747
}
2748
 
2749
/* Mapping of RGB colors to gray values. */
2750
 
2751
private gx_color_index
2752
gdev_cmyk_map_rgb_color(gx_device *pdev, const gx_color_value cv[])
2753
{
2754
    gx_color_value r, g, b;
2755
    r = cv[0]; g = cv[1]; b = cv[2];
2756
    if (gx_color_value_to_byte(r & g & b) == 0xff) {
2757
        return (gx_color_index) 0;	/* White */
2758
    } else {
2759
        gx_color_value c = gx_max_color_value - r;
2760
        gx_color_value m = gx_max_color_value - g;
2761
        gx_color_value y = gx_max_color_value - b;
2762
 
2763
        switch (pdev->color_info.depth) {
2764
        case 1:
2765
            return (c | m | y) > gx_max_color_value / 2 ?
2766
                (gx_color_index) 1 : (gx_color_index) 0;
2767
            /*NOTREACHED*/
2768
            break;
2769
 
2770
        case 8:
2771
            return ((ulong) c * lum_red_weight * 10
2772
                    + (ulong) m * lum_green_weight * 10
2773
                    + (ulong) y * lum_blue_weight * 10)
2774
                        >> (gx_color_value_bits + 2);
2775
            /*NOTREACHED*/
2776
            break;
2777
        }
2778
    }
2779
 
2780
    return (gx_color_index) 0;	/* This should never happen. */
2781
}
2782
 
2783
/* Mapping of CMYK colors. */
2784
 
2785
private int
2786
gdev_cmyk_map_color_cmyk(gx_device *pdev, gx_color_index color, gx_color_value prgb[3])
2787
{
2788
    switch (pdev->color_info.depth) {
2789
	case 1:
2790
	   prgb[0] = gx_max_color_value * (1 - color);
2791
	   break;
2792
 
2793
	case 8:
2794
	   if (pdev->color_info.num_components == 1) {
2795
	       gx_color_value value = (gx_color_value) color ^ 0xff;
2796
 
2797
	       prgb[0] = (value << 8) + value;
2798
 
2799
	       break;
2800
	   }
2801
 
2802
	default: {
2803
	    unsigned long bcyan, bmagenta, byellow, black;
2804
	    int nbits = pdev->color_info.depth;
2805
 
2806
	    gx_value_cmyk_bits(color, bcyan, bmagenta, byellow, black,
2807
	        nbits >> 2);
2808
 
2809
	    prgb[0] = bcyan;
2810
	    prgb[1] = bmagenta;
2811
	    prgb[2] = byellow;
2812
	    prgb[3] = black;
2813
	}
2814
    }
2815
 
2816
    return 0;
2817
}
2818
 
2819
/*
2820
 * Map a r-g-b color to a color index.
2821
 * We complement the colours, since we're using cmy anyway, and
2822
 * because the buffering routines expect white to be zero.
2823
 * Includes colour balancing, following HP recommendations, to try
2824
 * and correct the greenish cast resulting from an equal mix of the
2825
 * c, m, y, inks by reducing the cyan component to give a truer black.
2826
 */
2827
 
2828
/* Simple black generation/under-color removal with BG(k) = UG(k) = k. YA. */
2829
 
2830
#define bg_and_ucr(c, c_v, m, m_v, y, y_v, k) \
2831
    do { \
2832
       register byte cv = c_v, mv = m_v, yv = y_v, kv; \
2833
 \
2834
        kv = (cv > mv ? mv : cv); \
2835
	kv = (yv > k ? k : y); \
2836
        y = yv - kv; m = mv - kv; c = cv -kv; k = kv; \
2837
   } while (0)
2838
 
2839
private gx_color_index
2840
gdev_pcl_map_rgb_color(gx_device *pdev, const gx_color_value cv[])
2841
{
2842
  gx_color_value r, g, b;
2843
  r = cv[0]; g = cv[1]; b = cv[2];
2844
  if (gx_color_value_to_byte(r & g & b) == 0xff)
2845
    return (gx_color_index)0;         /* white */
2846
  else {
2847
    int correction = cprn_device->correction;
2848
    gx_color_value c = gx_max_color_value - r;
2849
    gx_color_value m = gx_max_color_value - g;
2850
    gx_color_value y = gx_max_color_value - b;
2851
 
2852
    /* Colour correction for better blacks when using the colour ink
2853
     * cartridge (on the DeskJet 500C only). We reduce the cyan component
2854
     * by some fraction (eg. 4/5) to correct the slightly greenish cast
2855
     * resulting from an equal mix of the three inks */
2856
    if (correction) {
2857
      ulong maxval, minval, range;
2858
 
2859
      maxval = c >= m ? (c >= y ? c : y) : (m >= y ? m : y);
2860
      if (maxval > 0) {
2861
	minval = c <= m ? (c <= y ? c : y) : (m <= y? m : y);
2862
	range = maxval - minval;
2863
 
2864
#define shift (gx_color_value_bits - 12)
2865
	c = ((c >> shift) * (range + (maxval * correction))) /
2866
	  ((maxval * (correction + 1)) >> shift);
2867
      }
2868
    }
2869
 
2870
    switch (pdev->color_info.depth) {
2871
    case 1:
2872
      return ((c | m | y) > gx_max_color_value / 2 ?
2873
	      (gx_color_index)1 : (gx_color_index)0);
2874
    case 8:
2875
      if (pdev->color_info.num_components >= 3)
2876
#define gx_color_value_to_1bit(cv) ((cv) >> (gx_color_value_bits - 1))
2877
	return (gx_color_value_to_1bit(c) +
2878
		(gx_color_value_to_1bit(m) << 1) +
2879
		(gx_color_value_to_1bit(y) << 2));
2880
      else
2881
#define red_weight 306
2882
#define green_weight 601
2883
#define blue_weight 117
2884
	return ((((ulong)c * red_weight +
2885
		  (ulong)m * green_weight +
2886
		  (ulong)y * blue_weight)
2887
		 >> (gx_color_value_bits + 2)));
2888
    case 16:
2889
#define gx_color_value_to_5bits(cv) ((cv) >> (gx_color_value_bits - 5))
2890
#define gx_color_value_to_6bits(cv) ((cv) >> (gx_color_value_bits - 6))
2891
      return (gx_color_value_to_5bits(y) +
2892
	      (gx_color_value_to_6bits(m) << 5) +
2893
	      (gx_color_value_to_5bits(c) << 11));
2894
    case 24:
2895
      return (gx_color_value_to_byte(y) +
2896
	      (gx_color_value_to_byte(m) << 8) +
2897
	      ((ulong)gx_color_value_to_byte(c) << 16));
2898
    case 32:
2899
      { return ((c == m && c == y) ? ((ulong)gx_color_value_to_byte(c) << 24)
2900
     : (gx_color_value_to_byte(y) +
2901
        (gx_color_value_to_byte(m) << 8) +
2902
        ((ulong)gx_color_value_to_byte(c) << 16)));
2903
      }
2904
    }
2905
  }
2906
  return (gx_color_index)0;   /* This never happens */
2907
}
2908
 
2909
/* Map a color index to a r-g-b color. */
2910
private int
2911
gdev_pcl_map_color_rgb(gx_device *pdev, gx_color_index color,
2912
			    gx_color_value prgb[3])
2913
{
2914
  /* For the moment, we simply ignore any black correction */
2915
  switch (pdev->color_info.depth) {
2916
  case 1:
2917
    prgb[0] = prgb[1] = prgb[2] = -((gx_color_value)color ^ 1);
2918
    break;
2919
  case 8:
2920
      if (pdev->color_info.num_components >= 3)
2921
	{ gx_color_value c = (gx_color_value)color ^ 7;
2922
	  prgb[0] = -(c & 1);
2923
	  prgb[1] = -((c >> 1) & 1);
2924
	  prgb[2] = -(c >> 2);
2925
	}
2926
      else
2927
	{ gx_color_value value = (gx_color_value)color ^ 0xff;
2928
	  prgb[0] = prgb[1] = prgb[2] = (value << 8) + value;
2929
	}
2930
    break;
2931
  case 16:
2932
    { gx_color_value c = (gx_color_value)color ^ 0xffff;
2933
      ushort value = c >> 11;
2934
      prgb[0] = ((value << 11) + (value << 6) + (value << 1) +
2935
		 (value >> 4)) >> (16 - gx_color_value_bits);
2936
      value = (c >> 6) & 0x3f;
2937
      prgb[1] = ((value << 10) + (value << 4) + (value >> 2))
2938
	>> (16 - gx_color_value_bits);
2939
      value = c & 0x1f;
2940
      prgb[2] = ((value << 11) + (value << 6) + (value << 1) +
2941
		 (value >> 4)) >> (16 - gx_color_value_bits);
2942
    }
2943
    break;
2944
  case 24:
2945
    { gx_color_index c = color ^ 0xffffff;
2946
      prgb[0] = gx_color_value_from_byte((gx_color_value)(c >> 16));
2947
      prgb[1] = gx_color_value_from_byte((gx_color_value)((c >> 8) & 0xff));
2948
      prgb[2] = gx_color_value_from_byte((gx_color_value)(c & 0xff));
2949
    }
2950
    break;
2951
  case 32:
2952
#define  gx_maxcol gx_color_value_from_byte(gx_color_value_to_byte(gx_max_color_value))
2953
    { gx_color_value w = gx_maxcol - gx_color_value_from_byte(color >> 24);
2954
      prgb[0] = w - gx_color_value_from_byte((color >> 16) & 0xff);
2955
      prgb[1] = w - gx_color_value_from_byte((color >> 8) & 0xff);
2956
      prgb[2] = w - gx_color_value_from_byte(color & 0xff);
2957
    }
2958
    break;
2959
  }
2960
  return 0;
2961
}
2962
 
2963
/*
2964
 * Convert and expand scanlines:
2965
 *
2966
 * For devices with 3 components:
2967
 *
2968
 *       (a)	16 -> 24 bit   (1-stage)
2969
 *       (b)	16 -> 32 bit   (2-stage)
2970
 *   or  (c)	24 -> 32 bit   (1-stage)
2971
 *
2972
 * For devices with 4 components:
2973
 *
2974
 *       (a)    16 -> 32 bit   (1-stage)
2975
 *       (b)     8 -> 32 bit   (2-stage)
2976
 *  or   (c)    24 -> 32 bit   (1-stage)
2977
 *
2978
 */
2979
 
2980
private void
2981
cdj_expand_line(word *line, int linesize, short cmyk, int bpp, int ebpp)
2982
{
2983
  int endline = linesize;
2984
  byte *start = (byte *)line;
2985
  register byte *in, *out;
2986
 
2987
  if (cmyk > 0) {
2988
      if (bpp == 8) {
2989
	  in = start + endline;
2990
	  out = start + (endline *=  2);
2991
 
2992
	  while (in > start) {
2993
	      register byte b0;
2994
	      register byte bs0, bs1, bs2, bs3;
2995
 
2996
	      b0 = *--in;
2997
 
2998
	      bs0 = b0 & 0x03;
2999
	      bs1 = (b0 >> 2) & 0x03;
3000
	      bs2 = (b0 >> 4) & 0x03;
3001
	      bs3 = (b0 >> 6) & 0x03;
3002
 
3003
	      *--out = (bs0 << 2) + bs0 + (bs1 << 6) + (bs1 << 4);
3004
	      *--out = (bs2 << 2) + bs2 + (bs3 << 6) + (bs3 << 4);
3005
	  }
3006
      }
3007
 
3008
      if (bpp == 24) {
3009
	  endline = (endline + 2) / 3;
3010
 
3011
	  in = start + endline * 3;
3012
	  out = start + endline * 4;
3013
 
3014
	  while (in > start) {
3015
	      register byte b0, b1, b2;
3016
 
3017
	      b0 = *--in;
3018
	      b1 = *--in;
3019
	      b2 = *--in;
3020
 
3021
	      *--out = (b0 << 2) + ((b0 >> 4) & 0x03);
3022
	      *--out = ((b1 & 0x0f) << 4) + ((b0 >> 6) << 2)
3023
	          + ((b1 >> 2) & 0x03);
3024
	      *--out = ((b2 & 0x03) << 6) + ((b1 >> 4) << 2) + (b2 & 0x03);
3025
	      *--out = (b2 & 0xfc) + ((b2 >> 6) & 0x03);
3026
	  }
3027
      } else if (ebpp == 32) {
3028
	  endline = (endline + 1) / 2;
3029
 
3030
	  in = start + endline * 2;
3031
	  out = start + (endline *= 4);
3032
 
3033
	  while (in > start) {
3034
	      register byte b0, b1;
3035
 
3036
	      b0 = *--in;
3037
	      b1 = *--in;
3038
 
3039
	      *--out = (b0 << 4) + ((b0 >> 4) & 0x07);
3040
	      *--out = (b0 & 0xf0) + ((b0 >> 4) & 0xf);
3041
	      *--out = (b1 << 4) + ((b1 >> 4) & 0x0f);
3042
	      *--out = (b1 & 0xf0) + ((b1 >> 4) & 0xf);
3043
	  }
3044
      }
3045
  } else /* cmyk > 0 */ {
3046
      if (bpp == 16)              /* 16 to 24 (cmy) if required */
3047
	  { register byte b0, b1;
3048
	    endline = ((endline + 1) / 2);
3049
	    in = start + endline * 2;
3050
	    out = start + (endline *= 3);
3051
 
3052
	    while (in > start)
3053
		{ b0 = *--in;
3054
		  b1 = *--in;
3055
		  *--out = (b0 << 3) + ((b0 >> 2) & 0x7);
3056
		  *--out = (b1 << 5) + ((b0 >> 3)  & 0x1c) + ((b1 >> 1) & 0x3);
3057
		  *--out = (b1 & 0xf8) + (b1 >> 5);
3058
	      }
3059
	}
3060
 
3061
      if (ebpp == 32)             /* 24/32 (cmy) to 32 (cmyk) if required */
3062
	  { register byte c, m, y;
3063
	    endline = ((endline + 2) / 3);
3064
	    in = start + endline * 3;
3065
	    out = start + endline * 4;
3066
 
3067
	    while (in > start)
3068
		{ 
3069
		  y = *--in;
3070
		  m = *--in;
3071
		  c = *--in;
3072
 
3073
		  if (c == y && c == m) {
3074
		      *--out = 0, *--out = 0, *--out = 0;
3075
		      *--out = c;
3076
		  } else {
3077
		      *--out = y, *--out = m, *--out = c;
3078
		      *--out = 0;
3079
		  }
3080
	      }
3081
	}
3082
  }
3083
}
3084
 
3085
private int
3086
cdj_put_param_int(gs_param_list *plist, gs_param_name pname, int *pvalue,
3087
  int minval, int maxval, int ecode)
3088
{	int code, value;
3089
	switch ( code = param_read_int(plist, pname, &value) )
3090
	{
3091
	default:
3092
		return code;
3093
	case 1:
3094
		return ecode;
3095
	case 0:
3096
		if ( value < minval || value > maxval )
3097
		   param_signal_error(plist, pname, gs_error_rangecheck);
3098
		*pvalue = value;
3099
		return (ecode < 0 ? ecode : 1);
3100
	}
3101
}	
3102
 
3103
private int
3104
cdj_set_bpp(gx_device *pdev, int bpp, int ccomps)
3105
{ gx_device_color_info *ci = &pdev->color_info;
3106
 
3107
  if (ccomps && bpp == 0) {
3108
      if (cprn_device->cmyk) {
3109
	  switch (ccomps) {
3110
	      default:
3111
	          return gs_error_rangecheck;
3112
		  /*NOTREACHED*/
3113
		  break;
3114
 
3115
	      case 1:
3116
	          bpp = 1;
3117
		  break;
3118
 
3119
	      case 3:
3120
		  bpp = 24;
3121
		  break;
3122
 
3123
	      case 4:
3124
		  switch (ci->depth) {
3125
		      case 8:
3126
		      case 16:
3127
		      case 24:
3128
		      case 32:
3129
		          break;
3130
 
3131
		      default:
3132
			  bpp = cprn_device->default_depth;
3133
			  break;
3134
		  }
3135
		  break;
3136
	  }
3137
      }
3138
  }
3139
 
3140
  if (bpp == 0) {
3141
      bpp = ci->depth;		/* Use the current setting. */
3142
  }
3143
 
3144
  if (cprn_device->cmyk < 0) {
3145
 
3146
      /* Reset procedures because we may have been in another mode. */
3147
 
3148
      dev_proc(pdev, encode_color) = gdev_cmyk_map_cmyk_color;
3149
      dev_proc(pdev, map_rgb_color) = NULL;
3150
      dev_proc(pdev, decode_color) = gdev_cmyk_map_color_cmyk;
3151
 
3152
      if (pdev->is_open) gs_closedevice(pdev);
3153
  }
3154
 
3155
  /* Check for valid bpp values */
3156
 
3157
  switch ( bpp )
3158
    {
3159
    case 16:
3160
    case 32:
3161
	if (cprn_device->cmyk && ccomps && ccomps != 4) goto bppe;
3162
	break;
3163
 
3164
    case 24:
3165
       if (!cprn_device->cmyk || ccomps == 0 || ccomps == 4) {
3166
	   break;
3167
       } else if (ccomps == 1) {
3168
	   goto bppe;
3169
       } else {
3170
 
3171
	   /* 3 components 24 bpp printing for CMYK device. */
3172
 
3173
	   cprn_device->cmyk = -1;
3174
       }
3175
       break;
3176
 
3177
    case 8:
3178
	if (cprn_device->cmyk) {
3179
	    if (ccomps) {
3180
		if (ccomps == 3) {
3181
		    cprn_device->cmyk = -1;
3182
		    bpp = 3;
3183
		} else if (ccomps != 1 && ccomps != 4) {
3184
		    goto bppe;
3185
		}
3186
	    }
3187
	    if (ccomps != 1) break;
3188
	} else {
3189
	    break;
3190
	}
3191
 
3192
    case 1:
3193
       if (ccomps != 1) goto bppe;
3194
 
3195
       if (cprn_device->cmyk && bpp != pdev->color_info.depth) {
3196
	   dev_proc(pdev, map_cmyk_color) = NULL;
3197
	   dev_proc(pdev, map_rgb_color) = gdev_cmyk_map_rgb_color;
3198
 
3199
	   if (pdev->is_open) {
3200
	       gs_closedevice(pdev);
3201
	   }
3202
       }
3203
       break;
3204
 
3205
    case 3:
3206
	if (!cprn_device->cmyk) {
3207
	    break;
3208
	}
3209
 
3210
    default:
3211
bppe:  return gs_error_rangecheck;
3212
    }
3213
 
3214
 
3215
    if (cprn_device->cmyk == -1) {
3216
	dev_proc(pdev, map_cmyk_color) = NULL;
3217
	dev_proc(pdev, map_rgb_color) = gdev_pcl_map_rgb_color;
3218
	dev_proc(pdev, map_color_rgb) = gdev_pcl_map_color_rgb;
3219
 
3220
	if (pdev->is_open) {
3221
	    gs_closedevice(pdev);
3222
	}
3223
    }
3224
 
3225
  switch (ccomps) {
3226
      case 0:
3227
          break;
3228
 
3229
      case 1:
3230
	  if (bpp != 1 && bpp != 8) goto cce;
3231
	  break;
3232
 
3233
      case 4:
3234
	  if (cprn_device->cmyk) {
3235
	      if (bpp >= 8) break;
3236
	  }
3237
 
3238
      case 3:
3239
	  if (bpp == 1 || bpp == 3 || bpp == 8 || bpp == 16
3240
	      || bpp == 24 || bpp == 32) {
3241
	      break;
3242
	  }
3243
 
3244
cce:  default: return gs_error_rangecheck;
3245
  }
3246
 
3247
  if (cprn_device->cmyk) {
3248
      if (cprn_device->cmyk > 0) {
3249
	  ci->num_components = ccomps ? ccomps : (bpp < 8 ? 1 : 4);
3250
      } else {
3251
	  ci->num_components = ccomps ? ccomps : (bpp < 8 ? 1 : 3);
3252
      }
3253
      if (bpp != 1 && ci->num_components == 1) { /* We do dithered grays. */
3254
	  bpp = bpp < 8 ? 8 : bpp;
3255
      }
3256
 
3257
      ci->max_color = (1 << (bpp >> 2)) - 1;
3258
      ci->max_gray = (bpp >= 8 ? 255 : 1);
3259
 
3260
      if (ci->num_components == 1) {
3261
	  ci->dither_grays = (bpp >= 8 ? 256 : 2);
3262
	  ci->dither_colors = (bpp >= 8 ? 256 : bpp > 1 ? 2 : 0);
3263
      } else {
3264
	  ci->dither_grays = (bpp > 8 ? 256 : 2);
3265
	  ci->dither_colors = (bpp > 8 ? 256 : bpp > 1 ? 2 : 0);
3266
      }
3267
  } else {
3268
      ci->num_components = (bpp == 1 || bpp == 8 ? 1 : 3);
3269
      ci->max_color = (bpp >= 8 ? 255 : bpp > 1 ? 1 : 0);
3270
      ci->max_gray = (bpp >= 8 ? 255 : 1);
3271
      ci->dither_grays = (bpp >= 8 ? 256 : 2);
3272
      ci->dither_colors = (bpp >= 8 ? 256 : bpp > 1 ? 2 : 0);
3273
  }
3274
 
3275
  ci->depth = ((bpp > 1) && (bpp < 8) ? 8 : bpp);
3276
 
3277
  return 0;
3278
}
3279
 
3280
/* new_bpp == save_bpp or new_bpp == 0 means don't change bpp.
3281
   ccomps == 0 means don't change number of color comps.
3282
   If new_bpp != 0, it must be the value of the BitsPerPixel element of
3283
     the plist; real_bpp may differ from new_bpp.
3284
*/
3285
private int
3286
cdj_put_param_bpp(gx_device *pdev, gs_param_list *plist, int new_bpp,
3287
  int real_bpp, int ccomps)
3288
{
3289
	if (new_bpp == 0 && ccomps == 0)
3290
	  return gdev_prn_put_params(pdev, plist);
3291
	else
3292
	  {
3293
		gx_device_color_info save_info;
3294
		int save_bpp;
3295
		int code;
3296
 
3297
		save_info = pdev->color_info;
3298
		save_bpp = save_info.depth;
3299
#define save_ccomps save_info.num_components
3300
		if ( save_bpp == 8 && save_ccomps == 3 && !cprn_device->cmyk)
3301
		  save_bpp = 3;
3302
		code = cdj_set_bpp(pdev, real_bpp, ccomps);
3303
		if ( code < 0 ) {
3304
		  param_signal_error(plist, "BitsPerPixel", code);
3305
		  param_signal_error(plist, "ProcessColorModel", code);
3306
		  return code;
3307
	        }
3308
		pdev->color_info.depth = new_bpp;  /* cdj_set_bpp maps 3/6 to 8 */
3309
		code = gdev_prn_put_params(pdev, plist);
3310
		if ( code < 0 )
3311
		  {	cdj_set_bpp(pdev, save_bpp, save_ccomps);
3312
			return code;
3313
		  }
3314
		cdj_set_bpp(pdev, real_bpp, ccomps);	/* reset depth if needed */
3315
		if ((cdj->color_info.depth != save_bpp ||
3316
		     (ccomps != 0 && ccomps != save_ccomps))
3317
		    && pdev->is_open )
3318
		  return gs_closedevice(pdev);
3319
		return 0;
3320
#undef save_ccomps
3321
	  }
3322
}
3323
 
3324
/* This returns either the number of pixels in a scan line, or the number
3325
 * of bytes required to store the line, both clipped to the page margins */
3326
private uint
3327
gdev_prn_rasterwidth(const gx_device_printer *pdev, int pixelcount)
3328
{
3329
  ulong raster_width = (ulong)(pdev->width - 
3330
    pdev->x_pixels_per_inch * (dev_l_margin(pdev) + dev_r_margin(pdev)));
3331
  return (pixelcount ?
3332
          (uint)raster_width :
3333
          (uint)((raster_width * pdev->color_info.depth + 7) >> 3));
3334
}
3335
 
3336
/* Functions for manipulation params strings */
3337
 
3338
private const byte*
3339
paramValueToString(const stringParamDescription* params, int value)
3340
{
3341
 
3342
    for (; params->p_name; ++params) {
3343
	if (params->p_value == value) {
3344
	    return (const byte *)params->p_name;
3345
	}
3346
    }
3347
 
3348
    return (const byte*) 0;
3349
}
3350
 
3351
private int
3352
paramStringValue(const stringParamDescription* params,
3353
    const byte* name, int namelen, int* value)
3354
{
3355
 
3356
    for (; params->p_name; ++params) {
3357
	if (strncmp(params->p_name, (char *)name, namelen) == 0 &&
3358
	    params->p_name[namelen] == 0) {
3359
	    *value = params->p_value;
3360
	    return 1;
3361
	}
3362
    }
3363
 
3364
    return 0;
3365
}
3366
 
3367
private int
3368
put_param_string(gs_param_list* plist,
3369
    const byte* pname, gs_param_string* pstring,
3370
    const stringParamDescription* params, int *pvalue, int code)
3371
{
3372
 
3373
    int ncode;
3374
 
3375
    if ((ncode = param_read_string(plist, (char *)pname, pstring)) < 0) {
3376
	param_signal_error(plist, (char *)pname, code = ncode);
3377
    } else if (ncode == 1) {
3378
	pstring->data = 0, pstring->size = 0;
3379
    } else {
3380
	int value = 0;
3381
 
3382
	if (paramStringValue(params, pstring->data, pstring->size,
3383
            &value) == 0) {
3384
	    param_signal_error(plist, (char *)pname, code = gs_error_rangecheck);
3385
	} else {
3386
	    *pvalue = value;
3387
	}
3388
    }
3389
 
3390
    return code;
3391
}
3392
 
3393
private int
3394
get_param_string(gs_param_list* plist,
3395
    const byte* pname, gs_param_string* pstring,
3396
    const stringParamDescription* params, int pvalue, bool persist, int code)
3397
{
3398
 
3399
    int ncode;
3400
 
3401
    pstring->data = paramValueToString(params, pvalue);
3402
 
3403
    if (pstring->data == (byte*) 0) {
3404
	param_signal_error(plist, (char *)pname, ncode = gs_error_unknownerror);
3405
    } else {
3406
        pstring->size = strlen((char *)pstring->data);
3407
	pstring->persistent = persist;
3408
    }
3409
 
3410
    if ((ncode = param_write_string(plist, (char *)pname, pstring)) < 0) {
3411
	code = ncode;
3412
    }
3413
 
3414
    return code;
3415
}
3416
 
3417
/*
3418
 * This taken from gsdparam.c. I hope it will be useable directly some day.
3419
 *
3420
 */
3421
 
3422
private int
3423
cdj_param_check_bytes(gs_param_list *plist, gs_param_name pname,
3424
		      const byte *str, uint size, bool is_defined)
3425
{       int code;
3426
        gs_param_string new_value;
3427
        switch ( code = param_read_string(plist, pname, &new_value) )
3428
          {
3429
          case 0:
3430
                if ( is_defined && new_value.size == size &&
3431
                     !memcmp((const char *)str, (const char *)new_value.data,
3432
                             size)
3433
                   )
3434
                  break;
3435
                code = gs_note_error(gs_error_rangecheck);
3436
                goto e;
3437
          default:
3438
                if ( param_read_null(plist, pname) == 0 )
3439
                  return 1;
3440
e:              param_signal_error(plist, pname, code);
3441
          case 1:
3442
                ;
3443
          }
3444
        return code;
3445
}
3446
 
3447
/* This is original code. */
3448
 
3449
private int
3450
cdj_param_check_float(gs_param_list *plist, gs_param_name pname, floatp fval,
3451
		      bool is_defined)
3452
{       int code;
3453
        float new_value;
3454
        switch ( code = param_read_float(plist, pname, &new_value) )
3455
          {
3456
          case 0:
3457
                if ( is_defined && new_value == fval)
3458
                  break;
3459
                code = gs_note_error(gs_error_rangecheck);
3460
                goto e;
3461
          default:
3462
                if ( param_read_null(plist, pname) == 0 )
3463
                  return 1;
3464
e:              param_signal_error(plist, pname, code);
3465
          case 1:
3466
                ;
3467
          }
3468
        return code;
3469
}
3470
 
3471
/* The following dithering algorithm has been kindly given to me (YA) by
3472
 * Klaus-Gunther Hess, I just adapted it for use with the code here. */
3473
 
3474
/*
3475
 
3476
(From KGH:)
3477
 
3478
Just about the features of the code:
3479
 
3480
    - Stored Color-Values are BYTES in the order C-M-Y-K.
3481
      (Indices need to change with gdevcdj.c)
3482
 
3483
    - There are individual THRESHOLDs and SPOTSIZEs for
3484
      the color-components. The following relation should
3485
      be maintained:
3486
                 SPOTSIZE = 2 * THRESHOLD + 1
3487
      (The internal calculation is dedicated for limiting
3488
       ink-density at the 720x720DpI-Resolution of the 
3489
       Epson-Printers, without loss of dynamic color-range)
3490
 
3491
    - In addition to that there are EMIN & EMAX-Values 
3492
      for the components. The Values are computed from
3493
      the dithering-algorithm and can be replaced by
3494
      constants, if neither the implementation nor 
3495
      THRESHOLD and SPOTSIZE can change.
3496
 
3497
    - The algorithm is tuned for speed. (K-only, if gray-
3498
      levels are detected, with EMIN/EMAX-clipping of
3499
      stored CMY-Errors. [Notice: cerr, merr, yerr are
3500
      *not* reset to zero! Clearing them would cause 
3501
      regular patterns & "Halos" to appear!])
3502
 
3503
*/
3504
 
3505
/*
3506
 * Macros, that represent the undisturbed dithering-algorithm
3507
 *
3508
 * FSerror:   compute the desired Value
3509
 * FSdecide:  decision based on the value computed by FSerror
3510
 * FSdiffuse: distribute remaining error among pixels
3511
 */
3512
 
3513
#define FSerror(Val,Erow,Ecol) (Val + Erow + ((7 * Ecol)>>4))
3514
 
3515
#define FSdecide(Error,Threshold,Spotsize,Pixel,Bit) \
3516
         if(Error > Threshold) {\
3517
            Pixel |= Bit;\
3518
            Error -= Spotsize;\
3519
         }
3520
 
3521
#define FSdiffuse(Error,Erow,Ecol,Eprev)\
3522
         Eprev  += (3 * Error + 8)>>4;\
3523
         Erow    = (5 * Error + Ecol + 8)>>4;\
3524
         Ecol    = Error;
3525
 
3526
/*
3527
 * some aliases for values from the device-structure
3528
 */
3529
#define DIRECTION    direction[0]
3530
#define CMYK_THRESHOLD(I) threshold[I]
3531
#define SPOTSIZE(I)  spotsize[I]
3532
#define EMIN(I)      emin[I]
3533
#define EMAX(I)      emax[I]
3534
#define NPIXEL       (plane_size * 8)
3535
 
3536
#define IDX_C	     1
3537
#define IDX_M	     2
3538
#define IDX_Y	     3
3539
#define IDX_K	     0
3540
 
3541
#define ODX_C	     2
3542
#define ODX_M	     1
3543
#define ODX_Y	     0
3544
#define ODX_K	     3
3545
 
3546
private int
3547
bjc_fscmyk(byte** inplanes, byte* outplanes[4][4], int** errplanes,
3548
    int plane_size, int scan) {
3549
 
3550
    byte* err = (byte*) errplanes[0];
3551
 
3552
/* =========================================================== */
3553
   if(scan < 0) { /* scan <   0 -> initialize private buffer */
3554
/* =========================================================== */
3555
 
3556
      int p,i,v;
3557
      int *direction,*threshold,*spotsize,*emin,*emax;
3558
      int *errv,*errc;
3559
/*
3560
 * allocate the error-buffer
3561
 */
3562
      /*KGHorig
3563
      i = 4 * (5 + 1 + 1 + sd->stc.prt_pixels + 1) * sizeof(errv[0]);
3564
      if((sd->stc.err_size < i) || (NULL == sd->stc.err)) {
3565
         if(NULL != sd->stc.err) 
3566
            gs_free(sd->stc.err,sd->stc.err_size,1,"stcm/err");
3567
         sd->stc.err_size = i;
3568
         sd->stc.err = gs_malloc(sd->stc.err_size,1,"stcm/err");
3569
         if(sd->stc.err == NULL) return_error(gs_error_VMerror);
3570
      }
3571
      */
3572
 
3573
      direction = (int *) err;
3574
      threshold = direction + 4;
3575
      spotsize  = threshold + 4;
3576
      emin      = spotsize  + 4;
3577
      emax      = emin      + 4;
3578
      errc      = emax      + 4;
3579
      errv      = errc      + 2*4;
3580
/*
3581
 * compute initial values
3582
 */
3583
      DIRECTION = -1;
3584
      for(i = 0; i < 4; ++i) {
3585
         int j;
3586
         float maxv = 1.0;
3587
	 /*KGHorig
3588
         if((sd->stc.xfer[i].size < 1) || (sd->stc.xfer[i].data == NULL)) {
3589
            maxv = 1.0;
3590
         } else {
3591
            maxv = 1.0/255.0;
3592
            for(j = 0; j < sd->stc.xfer[i].size; ++j)
3593
               if(maxv < sd->stc.xfer[i].data[j])
3594
	         maxv = sd->stc.xfer[i].data[j];
3595
         }
3596
	 */
3597
         CMYK_THRESHOLD(i) = (int)(127.0 / maxv + 0.5);
3598
         SPOTSIZE(i)  = ((int) CMYK_THRESHOLD(i)<<1)+1;
3599
         j = CMYK_THRESHOLD(i); /* Maximum Error-Value */
3600
         errc[3] = 0;
3601
         FSdiffuse(CMYK_THRESHOLD(i),errv[0],errc[0],errv[-4]);
3602
         FSdiffuse(CMYK_THRESHOLD(i),errv[0],errc[0],errv[-4]);
3603
         EMAX(i) = errv[0];
3604
         errc[0] = 0;
3605
         FSdiffuse((-CMYK_THRESHOLD(i)),errv[0],errc[0],errv[-4]);
3606
         FSdiffuse((-CMYK_THRESHOLD(i)),errv[0],errc[0],errv[-4]);
3607
         EMIN(i) = errv[0];
3608
      }
3609
 
3610
#ifdef CDJ_DEBUG_FS
3611
      for(i = 0; i < 4; ++i) errprintf(
3612
         "CMYK_THRESHOLD(%d)=%5d, spotsize(%d)=%5d, emin(%d)=%5d, emax(%d)=%5d\n",
3613
         i,CMYK_THRESHOLD(i),i,SPOTSIZE(i),i,EMIN(i),i,EMAX(i));
3614
#endif
3615
 
3616
      for(i = 0; i < 4; ++i) errc[i] = 0;
3617
 
3618
      for(p = 0; p < NPIXEL; ++p) {
3619
         for(i = 0; i < 4; ++i) {
3620
	    /*KHGOrig
3621
            if(sd->stc.flags & STCDFLAG0) v = 0;
3622
	    */
3623
	    if (0) v = 0;	/* Must provide a default for that. */
3624
            else                      v = (rand() % SPOTSIZE(i)) - CMYK_THRESHOLD(i);
3625
            FSdiffuse(v,errv[i],errc[i],errv[i-4]);
3626
         }
3627
         errv += i;
3628
      }
3629
 
3630
/* =========================================================== */
3631
   } else {        /* scan >=  0 -> scanline-processing       */
3632
/* =========================================================== */
3633
 
3634
      int w,p,dir,thedir;
3635
      byte *out[4],pixel[4],bit;
3636
      /*KGHorig
3637
      int  *width     = outplanes[scan];
3638
      */
3639
      int  *direction = (int *) err;
3640
      int  *threshold = direction + 4;
3641
      int  *spotsize  = threshold + 4;
3642
      int  *emin      = spotsize  + 4;
3643
      int  *emax      = emin      + 4;
3644
      int  *errc      = emax      + 4;
3645
      int  *errv      = errc      + 2*4;
3646
      int   kerr,cerr,merr,yerr;
3647
 
3648
      byte* in;
3649
 
3650
      /*KGHorig
3651
      if(sd->stc.flags & STCDFLAG1) {
3652
      */
3653
      if (0) {			/* Eventually will provide a flag for this. */
3654
         cerr = merr = yerr = kerr = 0;
3655
      } else {
3656
         cerr = errc[0];
3657
         merr = errc[1];
3658
         yerr = errc[2];
3659
         kerr = errc[3];
3660
      }
3661
 
3662
      out[0]   = outplanes[scan + 2][ODX_C];
3663
      out[1]   = outplanes[scan + 2][ODX_M];
3664
      out[2]   = outplanes[scan + 2][ODX_Y];
3665
      out[3]   = outplanes[scan + 2][ODX_K];
3666
      pixel[0] = pixel[1] = pixel[2] = pixel[3] = 0;
3667
 
3668
      if(DIRECTION < 0) { /* scan == 0, run backward */
3669
         w      = NPIXEL;
3670
	 in     = inplanes[2] + 4 * (NPIXEL - 1);
3671
         errv  += (w-1)<<2;
3672
         dir    = -4;
3673
	 /*KGHorig
3674
         if(w > 8) for(p = 0; p < 4; ++p) out[p] += (w-1)>>3;
3675
	 */
3676
	 thedir = -1;
3677
	 for (p = 0; p < 4; ++p) {
3678
	     out[p] += plane_size - 1;
3679
	 }
3680
      } else {      /* run forward */
3681
         w      = 1;
3682
	 in      = inplanes[3] - 4 * NPIXEL;
3683
         dir    = 4;
3684
	 thedir = 1;
3685
	 for (p = 0; p < 4; ++p) {
3686
	     out[p] -= plane_size;
3687
	 }
3688
      }             /* run backward/forward */
3689
 
3690
      /*KGHorig
3691
      if(0 == (sd->stc.flags & STCDFLAG1)) DIRECTION = -DIRECTION;
3692
      */
3693
      if (1) DIRECTION = -DIRECTION; /* Scan in other direction. */
3694
 
3695
      bit = 0x80>>((w-1) & 7);
3696
      w   = (w+7)>>3;
3697
 
3698
      for(p = NPIXEL; p; --p) { /* loop over pixels */
3699
 
3700
         int cmy = in[IDX_C] | in[IDX_M] | in[IDX_Y];
3701
         int kv  = FSerror(in[IDX_K],errv[3],kerr);
3702
         int cv;
3703
 
3704
         FSdecide(kv,CMYK_THRESHOLD(3),SPOTSIZE(3),pixel[3],bit);
3705
 
3706
         if(cmy) {
3707
 
3708
            if(pixel[3] & bit) { /* black known to fire */
3709
 
3710
               FSdiffuse(kv,errv[3],kerr,errv[3-dir]);
3711
 
3712
               cv  = FSerror(in[IDX_C],errv[0],cerr);
3713
               cv -= SPOTSIZE(0); 
3714
               if ((cv+CMYK_THRESHOLD(0)) < 0) cv = -CMYK_THRESHOLD(0);
3715
               FSdiffuse(cv,errv[0],cerr,errv[0-dir]);
3716
 
3717
               cv  = FSerror(in[IDX_M],errv[1],merr);
3718
               cv -= SPOTSIZE(1);
3719
               if ((cv+CMYK_THRESHOLD(1)) < 0) cv = -CMYK_THRESHOLD(1);
3720
 
3721
               FSdiffuse(cv,errv[1],merr,errv[1-dir]);
3722
 
3723
               cv  = FSerror(in[IDX_Y],errv[2],yerr);
3724
               cv -= SPOTSIZE(2);
3725
               if ((cv+CMYK_THRESHOLD(2)) < 0) cv = -CMYK_THRESHOLD(2);
3726
               FSdiffuse(cv,errv[2],yerr,errv[2-dir]);
3727
 
3728
            } else {
3729
 
3730
               cv  = FSerror(in[IDX_C],errv[0],cerr);
3731
               FSdecide(cv,CMYK_THRESHOLD(0),SPOTSIZE(0),pixel[0],bit);
3732
               FSdiffuse(cv,errv[0],cerr,errv[0-dir]);
3733
 
3734
               cv  = FSerror(in[IDX_M],errv[1],merr);
3735
               FSdecide(cv,CMYK_THRESHOLD(1),SPOTSIZE(1),pixel[1],bit);
3736
               FSdiffuse(cv,errv[1],merr,errv[1-dir]);
3737
 
3738
               cv  = FSerror(in[IDX_Y],errv[2],yerr);
3739
               FSdecide(cv,CMYK_THRESHOLD(2),SPOTSIZE(2),pixel[2],bit);
3740
               FSdiffuse(cv,errv[2],yerr,errv[2-dir]);
3741
 
3742
               if(pixel[0] & pixel[1] & pixel[2] & bit) {
3743
                  pixel[0] &= ~bit;
3744
                  pixel[1] &= ~bit;
3745
                  pixel[2] &= ~bit;
3746
                  pixel[3] |=  bit;
3747
                  kv -= SPOTSIZE(3);
3748
                  if ((kv+CMYK_THRESHOLD(3)) < 0) kv = -CMYK_THRESHOLD(0);  
3749
                  FSdiffuse(kv,errv[3],kerr,errv[3-dir]);
3750
               }
3751
	   }
3752
 
3753
         } else {
3754
 
3755
            FSdiffuse(kv,errv[3],kerr,errv[3-dir]);
3756
 
3757
            if(     errv[0] > EMAX(0)) errv[0] = EMAX(0);
3758
            else if(errv[0] < EMIN(0)) errv[0] = EMIN(0);
3759
 
3760
            if(     errv[1] > EMAX(1)) errv[1] = EMAX(1);
3761
            else if(errv[1] < EMIN(1)) errv[1] = EMIN(1);
3762
 
3763
            if(     errv[2] > EMAX(2)) errv[2] = EMAX(2);
3764
            else if(errv[2] < EMIN(2)) errv[2] = EMIN(2);
3765
 
3766
         }
3767
 
3768
/*
3769
 * Adjust indices
3770
 */
3771
         bit   = dir > 0 ? (bit>>1) : (bit<<1);
3772
         if(bit == 0) {
3773
	    /*KGHorig
3774
            if(((*out[0]  = pixel[0]) != 0) && (width[0] < w)) width[0] = w;
3775
            if(((*out[1]  = pixel[1]) != 0) && (width[1] < w)) width[1] = w;
3776
            if(((*out[2]  = pixel[2]) != 0) && (width[2] < w)) width[2] = w;
3777
            if(((*out[3]  = pixel[3]) != 0) && (width[3] < w)) width[3] = w;
3778
	    */
3779
	    *out[0] = pixel[0];
3780
	    *out[1] = pixel[1];
3781
	    *out[2] = pixel[2];
3782
	    *out[3] = pixel[3];
3783
            out[0] += thedir; out[1] += thedir;
3784
            out[2] += thedir; out[3] += thedir;
3785
            pixel[0] = pixel[1] = pixel[2] = pixel[3] = 0;
3786
 
3787
            if(dir > 0) bit = 0x80;
3788
            else        bit = 0x01;
3789
            w    += dir>>2;
3790
         }
3791
 
3792
	 in += dir;
3793
         errv += dir;
3794
      }                                         /* loop over pixels */
3795
 
3796
      /*KGHorig
3797
      if(0 == (sd->stc.flags & STCDFLAG1)) {
3798
      */
3799
      if (1) {
3800
         cerr = errc[0] = cerr;
3801
         merr = errc[1] = merr;
3802
         yerr = errc[2] = yerr;
3803
         kerr = errc[3] = kerr;
3804
      }
3805
 
3806
/* =========================================================== */
3807
   }                  /* initialization or scanline-Processing */
3808
/* =========================================================== */
3809
 
3810
   return 0;
3811
}
3812