1
/* Copyright (C) 2001-2012 Artifex Software, Inc.
4
This software is provided AS-IS with no warranty, either express or
7
This software is distributed under license and may not be copied,
8
modified or distributed except as expressly authorized under the terms
9
of the license contained in the file LICENSE in this distribution.
11
Refer to licensing information at http://www.artifex.com or contact
12
Artifex Software, Inc., 7 Mt. Lassen Drive - Suite A-134, San Rafael,
13
CA 94903, U.S.A., +1(415)492-9861, for further information.
16
/* HP and Canon colour printer drivers */
19
* HP DeskJet 505J Support (dj505j.dev)
20
* -- taken from dj505j driver for Ghostscript 2.6.1 by Kazunori Asayama
21
* NEC PICTY180 (PC-PR101J/180) Support (picty180.dev)
22
* HP LaserJet 4V/4LJ Pro dither Suport (lj4dithp.dev)
24
* Norihito Ohmori <ohmori@p.chiba-u.ac.jp>
28
/****************************************************************
29
* The code in this file was contributed by the authors whose names and/or
30
* e-mail addresses appear below: Aladdin Enterprises takes no
31
* responsibility for it. In the past, we have tried to keep it working,
32
* but too many users have made too many "improvements" without regard to
33
* the overall structure; the last three "improvements" required me to spend
34
* several hours fixing each one so that the code worked again at all. For
35
* this reason, no further changes to this file will be accepted. We are
36
* planning eventually to get these drivers rewritten from scratch.
41
****************************************************************/
45
* 2000-08-20 Jonathan Kamens <jik@kamens.brookline.ma.us>:
46
* change to support printers with different X and Y resolution.
50
* Important compilation notes (YA).
52
* You may also try the cdj550cmyk driver after having defined
53
* USE_CDJ550_CMYK and added the needed definition in devs.mak. Not tried!
54
* (I have a BJC!) Also note that modes descriptions of CMYK printing
55
* is done under the BJC section of devices.doc.
57
* CMYK to RGB conversion is made a la GhostScript unless you define
58
* the preprocessor symbol USE_ADOBE_CMYK_RGB.
60
* Ghostscript: R = (1.0 - C) * (1.0 - K)
61
* Adobe: R = 1.0 - min(1.0, C + K)
63
* (and similarly for G and B). Ghostscript claims its method achieves
66
* For the BJC drivers, define BJC_DEFAULT_CENTEREDAREA if you want to
67
* have the same top and bottom margins (default to use the tallest
68
* imageable area available, usually with a top margin smaller than
69
* the bottom one). Defining USE_RECOMMENDED_MARGINS has the same
70
* effect and also sets these margins to 12.4 mm. Other compilation
71
* defines are explained in devices.doc.
73
* You can also define BJC_INIT_800_AS_600 to not use BJC-800-specific code
74
* in the page initialization sequence (normally not useful to you at all,
75
* just for my debugging of the driver margins).
79
#include "std.h" /* to stop stdlib.h redefining types */
80
#include <stdlib.h> /* for rand() */
86
/* Conversion stuff. */
94
*** This file contains multiple drivers. The main body of code, and all
95
*** but the DesignJet driver, were contributed by George Cameron;
96
*** please contact g.cameron@biomed.abdn.ac.uk if you have questions.
97
* 1 - cdj500: HP DeskJet 500C
98
* 2 - cdj550: HP DeskJet 550C
99
* 3 - pjxl300: HP PaintJet XL300
100
* 4 - pj: HP PaintJet
101
* 5 - pjxl: HP PaintJet XL
102
* 6 - declj250: DEC LJ250
103
*** The DesignJet 650C driver was contributed by Koert Zeilstra;
104
*** please contact koert@zen.cais.com if you have questions.
105
* 7 - dnj650c HP DesignJet 650C
106
*** The LaserJet 4 driver with dithering was contributed by Eckhard
107
*** Rueggeberg; please contact eckhard@ts.go.dlr.de if you have questions.
108
* 8 - lj4dith: HP LaserJet 4 with dithering
109
*** The ESC/P driver (for Epson ESC/P compatible printers) was written by
110
*** Yoshio Kuniyoshi <yoshio@nak.math.keio.ac.jp>, but is not maintained at
112
* 9 - esc/p: Epson ESC/P-compatible printers
113
*** The BJC600 driver (which also works for BJC4000) was written first
114
*** by Yoshio Kuniyoshi <yoshio@nak.math.keio.ac.jp> and later modified by
115
*** Yves Arrouye <yves.arrouye@usa.net>. The current driver has been
116
*** completely rewritten by me (YA) for good color handling.
117
* 10 - bjc600: BJC 600//4000 printers
118
*** The BJC800 driver is based on the bjc600 one. By YA too.
119
* 11 - bjc800: BJC 800 printer
120
* 12 - dj505j: HP DeskJet 505J
121
* 13 - pixty180: NEC PICTY 180 (PC-PR101J/180)
125
* All of the HP-like drivers have 8-bit (monochrome), 16-bit and 24-bit
126
* (colour) and for the DJ 550C 32-bit, (colour, cmyk mode)
127
* options in addition to the usual 1-bit and 3-bit modes
128
* It is also possible to set various printer-specific parameters
129
* from the gs command line, eg.
131
* gs -sDEVICE=cdj550 -dBitsPerPixel=16 -dDepletion=1 -dShingling=2 tiger.eps
133
* Please consult the appropriate section in the devices.doc file for
134
* further details on all these drivers.
136
* All of the BJC-like drivers have 1-bit and 8-bit monochrome modes, 8-bit,
137
* 16-bit, 24-bit and 32-bit colour cmyk mode (the 8-bit monochrome mode
138
* is called "4-bit". If you want to add a CMYK printer, look at the
139
* bjc6000/bjc800 devices declarations and initialization.
141
* If you want to support different color components for the same depth
142
* on a non-CMYK printer, look how this is done for CMYK printers in
148
* This taken from gsdparam.c. I hope it will be useable directly some day.
152
#define BEGIN_ARRAY_PARAM(pread, pname, pa, psize, e)\
153
switch ( ncode = pread(plist, (oname = pname), &pa) )\
156
if ( pa.size != psize )\
157
code = gs_error_rangecheck;\
159
/* The body of the processing code goes here. */
160
/* If it succeeds, it should do a 'break'; */
161
/* if it fails, it should set ecode and fall through. */
162
#define END_PARAM(pa, e)\
167
e: param_signal_error(plist, oname, code);\
169
pa.data = 0; /* mark as not filled */\
172
static int cdj_param_check_bytes(gs_param_list *, gs_param_name, const byte *, uint, bool);
173
static int cdj_param_check_float(gs_param_list *, gs_param_name, floatp, bool);
174
#define cdj_param_check_string(plist, pname, str, is_defined)\
175
cdj_param_check_bytes(plist, pname, (const byte *)(str), strlen(str),\
183
#define DESKJET_PRINT_LIMIT 0.04 /* 'real' top margin? */
184
#define PAINTJET_PRINT_LIMIT 0.0 /* This is a guess.. */
185
#define ESC_P_PRINT_LIMIT 0.335
187
/* Margins are left, bottom, right, top. */
188
#define DESKJET_MARGINS_LETTER (float)0.25, (float)0.50, (float)0.25, (float)0.167
189
#define DESKJET_MARGINS_A4 (float)0.125, (float)0.50, (float)0.143, (float)0.167
190
#define DESKJET_505J_MARGINS (float)0.125, (float)0.50, (float)0.125, (float)0.167
191
#define DESKJET_505J_MARGINS_COLOR (float)0.125, (float)0.665, (float)0.125, (float)0.167
192
#define LJET4_MARGINS (float)0.26, (float)0.0, (float)0.0, (float)0.0
193
/* The PaintJet and DesignJet seem to have the same margins */
194
/* regardless of paper size. */
195
#define PAINTJET_MARGINS (float)0.167, (float)0.167, (float)0.167, (float)0.167
196
#define DESIGNJET_MARGINS (float)0.167, (float)0.167, (float)0.167, (float)0.167
199
* With ESC/P commands, BJC-600 can print no more than 8 inches width.
200
* So it can't use full width of letter size paper. Since non printable
201
* left side area is 0.134 inch, we set up margins as follows.
203
* Note to readers: the bjc drivers series do *not* use ESC/P commands
204
* but raster ops. Configuration of these drivers can be done through
205
* the gdevbjc.h file.
208
#define ESC_P_MARGINS_LETTER (float)0.134, (float)(0.276+0.2), \
209
(float)(0.366+0.01), (float)0.335
210
#define ESC_P_MARGINS_A4 (float)0.134, (float)(0.276+0.2), \
211
(float)(0.166+0.01), (float)0.335
213
/* Define bits-per-pixel for generic drivers - default is 24-bit mode */
215
# define BITSPERPIXEL 24
219
* The following use of size_of rather than sizeof is required to work
220
* around a bug in Microsoft Visual C++ 5.0, which considers the THRESHOLD
221
* value (128 << SHIFT) to be unsigned because SHIFT is unsigned (because
222
* sizeof() is unsigned).
224
#define W size_of(word)
225
#define I size_of(int)
227
#define invert_word(v)\
228
((v) >> 24) + (((v) >> 8) & 0xff00L) +\
229
(((word)(v) << 8) & 0xff0000L) + ((word)(v) << 24)
245
/* No. of ink jets (used to minimise head movements) */
246
#define HEAD_ROWS_MONO 50
247
#define HEAD_ROWS_COLOUR 16
249
/* Colour mapping procedures */
250
static dev_proc_map_cmyk_color (gdev_cmyk_map_cmyk_color);
251
static dev_proc_map_rgb_color (gdev_cmyk_map_rgb_color);
253
static dev_proc_map_rgb_color (gdev_pcl_map_rgb_color);
254
static dev_proc_map_color_rgb (gdev_pcl_map_color_rgb);
255
static dev_proc_decode_color (gdev_cmyk_map_color_cmyk);
257
/* Print-page, parameters and miscellaneous procedures */
258
static dev_proc_open_device(dj500c_open);
259
static dev_proc_open_device(dj550c_open);
260
static dev_proc_open_device(dj505j_open);
261
static dev_proc_open_device(dnj650c_open);
262
static dev_proc_open_device(lj4dith_open);
263
static dev_proc_open_device(pj_open);
264
static dev_proc_open_device(pjxl_open);
265
static dev_proc_open_device(pjxl300_open);
266
static dev_proc_open_device(escp_open);
267
static dev_proc_open_device(bjc_open);
269
static dev_proc_print_page(declj250_print_page);
270
static dev_proc_print_page(dj500c_print_page);
271
static dev_proc_print_page(dj550c_print_page);
272
static dev_proc_print_page(dj505j_print_page);
273
static dev_proc_print_page(picty180_print_page);
274
static dev_proc_print_page(dnj650c_print_page);
275
static dev_proc_print_page(lj4dith_print_page);
276
static dev_proc_print_page(lj4dithp_print_page);
277
static dev_proc_print_page(pj_print_page);
278
static dev_proc_print_page(pjxl_print_page);
279
static dev_proc_print_page(pjxl300_print_page);
280
static dev_proc_print_page(escp_print_page);
281
static dev_proc_print_page(bjc_print_page);
283
static dev_proc_get_params(cdj_get_params);
284
static dev_proc_get_params(pjxl_get_params);
285
static dev_proc_get_params(bjc_get_params);
286
#define ep_get_params cdj_get_params
288
static dev_proc_put_params(cdj_put_params);
289
static dev_proc_put_params(pj_put_params);
290
static dev_proc_put_params(pjxl_put_params);
291
static dev_proc_put_params(bjc_put_params);
292
#define ep_put_params cdj_put_params
294
/* The device descriptors */
296
#define gx_prn_colour_device_common \
297
gx_prn_device_common; \
298
short cmyk; /* 0: not CMYK-capable, > 0: printing CMYK, */ \
299
/* < 0 : CMYK-capable, not printing CMYK */ \
300
uint default_depth; /* Used only for CMYK-capable printers now. */ \
303
typedef struct gx_device_cdj_s gx_device_cdj;
304
struct gx_device_cdj_s {
306
gx_prn_colour_device_common;
307
int shingling; /* Interlaced, multi-pass printing */
308
int depletion; /* 'Intelligent' dot-removal */
311
typedef struct gx_device_pjxl_s gx_device_pjxl;
312
struct gx_device_pjxl_s {
314
gx_prn_colour_device_common;
315
int printqual; /* Mechanical print quality */
316
int rendertype; /* Driver or printer dithering control */
319
typedef struct gx_device_hp_s gx_device_hp;
320
struct gx_device_hp_s {
322
gx_prn_colour_device_common;
325
typedef struct gx_device_hp_s gx_device_pj;
327
typedef struct gx_device_bjc600_s gx_device_bjc600;
328
typedef struct gx_device_bjc800_s gx_device_bjc800;
330
typedef struct gx_device_bjc800_s gx_device_bjc;
332
#define bjc_params_common \
333
bool manualFeed; /* Use manual feed */ \
334
int mediaType; /* Cf. strings below */ \
335
bool mediaWeight_isSet; /* Say if weight is an integer or null */ \
336
int mediaWeight; /* Weigth of the media */ \
337
int printQuality; /* Cf. strings below */ \
338
bool ditheringType; /* Do dithering */ \
339
int colorComponents; /* The number of *desired* color comps */ \
340
int printColors /* 0: Transparent, \
341
1: C, 2: M, 4: Y, 7: K (Color decomp). \
342
if > 8, print in black ink. */
347
bool monochromePrint; /* Print with black only */
354
typedef bjc_params bjc800_params;
356
#define gx_bjc_device_common \
358
gx_prn_colour_device_common; \
362
struct gx_device_bjc600_s {
363
gx_bjc_device_common;
366
struct gx_device_bjc800_s {
367
gx_bjc_device_common;
373
gx_prn_colour_device_common;
374
} gx_device_colour_prn;
376
/* Use the cprn_device macro to access generic fields (like cmyk,
377
default_depth and correction), and specific macros for specific
380
#define cprn_device ((gx_device_colour_prn*) pdev)
382
#define cdj ((gx_device_cdj *)pdev)
383
#define pjxl ((gx_device_pjxl *)pdev)
384
#define pj ((gx_device_pj *)pdev)
386
#define bjc ((gx_device_bjc*) pdev)
387
#define bjc600 ((gx_device_bjc600*) pdev)
388
#define bjc800 ((gx_device_bjc800*) pdev)
390
#define bjcparams (bjc->bjc_p)
391
#define bjc600params (bjc600->bjc_p)
392
#define bjc800params (bjc800->bjc_p)
394
#define bjcversion(p) (((gx_device_bjc*) pdev)->ptype == BJC800 ? \
395
BJC_BJC800_VERSION : BJC_BJC600_VERSION)
396
#define bjcversionstring(p) (((gx_device_bjc*) pdev)->ptype == BJC800 ? \
397
BJC_BJC800_VERSIONSTR : BJC_BJC600_VERSIONSTR)
399
#define bjcthickpaper(l) \
400
(bjcparams.mediaWeight_isSet && bjcparams.mediaWeight > l)
401
#define bjc600thickpaper() bjcthickpaper(BJC600_MEDIAWEIGHT_THICKLIMIT)
402
#define bjc800thickpaper() bjcthickpaper(BJC800_MEDIAWEIGHT_THICKLIMIT)
404
/* The basic structure for all printers. Note the presence of the cmyk, depth
405
and correct fields even if soem are not used by all printers. */
407
#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)\
408
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
410
/* Note: the computation of color_info values here must match */
411
/* the computation in the cdj_set_bpp procedure below. */
413
#define prn_hp_colour_device(dtype, procs, dev_name, x_dpi, y_dpi, bpp, print_page, correct)\
414
prn_colour_device_body(dtype, procs, dev_name,\
415
DEFAULT_WIDTH_10THS, DEFAULT_HEIGHT_10THS, x_dpi, y_dpi, 0, 0, 0, 0,\
416
(bpp == 32 ? 4 : (bpp == 1 || bpp == 8) ? 1 : 3), bpp,\
417
(bpp >= 8 ? 255 : 1), (bpp >= 8 ? 255 : bpp > 1 ? 1 : 0),\
418
(bpp >= 8 ? 256 : 2), (bpp >= 8 ? 256 : bpp > 1 ? 2 : 0),\
419
print_page, 0 /* cmyk */, correct)
421
#define prn_cmyk_colour_device(dtype, procs, dev_name, x_dpi, y_dpi, bpp, print_page, correct)\
422
prn_colour_device_body(dtype, procs, dev_name,\
423
DEFAULT_WIDTH_10THS, DEFAULT_HEIGHT_10THS, x_dpi, y_dpi, 0, 0, 0, 0,\
424
((bpp == 1 || bpp == 4) ? 1 : 4), bpp,\
425
(bpp > 8 ? 255 : 1), (1 << (bpp >> 2)) - 1, /* max_gray, max_color */\
426
(bpp > 8 ? 256 : 2), (bpp > 8 ? 256 : bpp > 1 ? 2 : 0),\
427
print_page, 1 /* cmyk */, correct)
429
#define bjc_device(dtype, p, d, x, y, b, pp, c) \
430
prn_cmyk_colour_device(dtype, p, d, x, y, b, pp, c)
432
#define cdj_device(procs, dev_name, x_dpi, y_dpi, bpp, print_page, correction, shingling, depletion)\
433
{ prn_hp_colour_device(gx_device_cdj, procs, dev_name, x_dpi, y_dpi, bpp, print_page, correction),\
438
#define pjxl_device(procs, dev_name, x_dpi, y_dpi, bpp, print_page, printqual, rendertype)\
439
{ prn_hp_colour_device(gx_device_pjxl, procs, dev_name, x_dpi, y_dpi, bpp, print_page, 0), \
444
#define pj_device(procs, dev_name, x_dpi, y_dpi, bpp, print_page)\
445
{ prn_hp_colour_device(gx_device_pj, procs, dev_name, x_dpi, y_dpi, bpp, print_page, 0) }
447
#define bjc600_device(procs, dev_name, x_dpi, y_dpi, bpp, print_page, t, mf, mt, mws, mw, pq, dt, cc, pc, mp) \
448
{ bjc_device(gx_device_bjc600, procs, dev_name, x_dpi, y_dpi, bpp, print_page, 0),\
449
t, 0., { mf, mt, mws, mw, pq, dt, cc, pc, mp }\
451
#define bjc800_device(procs, dev_name, x_dpi, y_dpi, bpp, print_page, t, mf, mt, mws, mw, pq, dt, cc, pc) \
452
{ bjc_device(gx_device_bjc800, procs, dev_name, x_dpi, y_dpi, bpp, print_page, 0),\
453
t, 0., { mf, mt, mws, mw, pq, dt, cc, pc }\
456
#define hp_colour_procs(proc_colour_open, proc_get_params, proc_put_params) {\
458
gx_default_get_initial_matrix,\
459
gx_default_sync_output,\
460
gdev_prn_output_page,\
462
gdev_pcl_map_rgb_color,\
463
gdev_pcl_map_color_rgb,\
464
NULL, /* fill_rectangle */\
465
NULL, /* tile_rectangle */\
466
NULL, /* copy_mono */\
467
NULL, /* copy_color */\
468
NULL, /* draw_line */\
469
gx_default_get_bits,\
474
#define cmyk_colour_procs(proc_colour_open, proc_get_params, proc_put_params) {\
476
gx_default_get_initial_matrix,\
477
gx_default_sync_output,\
478
gdev_prn_output_page,\
480
NULL /* map_rgb_color */,\
481
NULL /* map_color_rgb */,\
482
NULL /* fill_rectangle */,\
483
NULL /* tile_rectangle */,\
484
NULL /* copy_mono */,\
485
NULL /* copy_color */,\
486
NULL /* draw_line */,\
487
gx_default_get_bits,\
490
gdev_cmyk_map_cmyk_color,\
491
NULL, /* get_xfont_procs */\
492
NULL, /* get_xfont_device */\
493
NULL, /* map_rgb_alpha_color */\
494
NULL, /* get_page_device */\
495
NULL, /* get_alpha_bits */\
496
NULL, /* copy_alpha */\
497
NULL, /* get_band */\
498
NULL, /* copy_rop */\
499
NULL, /* fill_path */\
500
NULL, /* stroke_path */\
501
NULL, /* fill_mask */\
502
NULL, /* fill_trapezoid */\
503
NULL, /* fill_parallelogram */\
504
NULL, /* fill_triangle */\
505
NULL, /* draw_thin_line */\
506
NULL, /* begin_image */\
507
NULL, /* image_data */\
508
NULL, /* end_image */\
509
NULL, /* strip_tile_rectangle */\
510
NULL, /* strip_copy_rop */\
511
NULL, /* get_clipping_box */\
512
NULL, /* begin_typed_image */\
513
NULL, /* get_bits_rectangle */\
514
NULL, /* map_color_rgb_alpha */\
515
NULL, /* create_compositor */\
516
NULL, /* get_hardware_params */\
517
NULL, /* text_begin */\
518
NULL, /* finish_copydevice */\
519
NULL, /* begin_transparency_group */\
520
NULL, /* end_transparency_group */\
521
NULL, /* begin_transparency_mask */\
522
NULL, /* end_transparency_mask */\
523
NULL, /* discard_transparency_layer */\
524
NULL, /* get_color_mapping_procs */\
525
NULL, /* get_color_comp_index */\
526
gdev_cmyk_map_cmyk_color, /* encode_color */\
527
gdev_cmyk_map_color_cmyk /* decode_color */\
530
static gx_device_procs cdj500_procs =
531
hp_colour_procs(dj500c_open, cdj_get_params, cdj_put_params);
533
static gx_device_procs cdj550_procs =
534
hp_colour_procs(dj550c_open, cdj_get_params, cdj_put_params);
536
#ifdef USE_CDJ550_CMYK
537
static gx_device_procs cdj550cmyk_procs =
538
cmyk_colour_procs(dj550c_open, cdj_get_params, cdj_put_params);
541
static gx_device_procs dj505j_procs =
542
hp_colour_procs(dj505j_open, cdj_get_params, cdj_put_params);
544
static gx_device_procs dnj650c_procs =
545
hp_colour_procs(dnj650c_open, cdj_get_params, cdj_put_params);
547
static gx_device_procs lj4dith_procs =
548
hp_colour_procs(lj4dith_open, cdj_get_params, cdj_put_params);
550
static gx_device_procs pj_procs =
551
hp_colour_procs(pj_open, gdev_prn_get_params, pj_put_params);
553
static gx_device_procs pjxl_procs =
554
hp_colour_procs(pjxl_open, pjxl_get_params, pjxl_put_params);
556
static gx_device_procs pjxl300_procs =
557
hp_colour_procs(pjxl300_open, pjxl_get_params, pjxl_put_params);
559
static gx_device_procs bjc_procs =
560
cmyk_colour_procs(bjc_open, bjc_get_params, bjc_put_params);
562
static gx_device_procs escp_procs =
563
hp_colour_procs(escp_open, ep_get_params, ep_put_params);
565
gx_device_cdj far_data gs_cdjmono_device =
566
cdj_device(cdj500_procs, "cdjmono", 300, 300, 1,
567
dj500c_print_page, 4, 0, 1);
569
gx_device_cdj far_data gs_cdeskjet_device =
570
cdj_device(cdj500_procs, "cdeskjet", 300, 300, 3,
571
dj500c_print_page, 4, 2, 1);
573
gx_device_cdj far_data gs_cdjcolor_device =
574
cdj_device(cdj500_procs, "cdjcolor", 300, 300, 24,
575
dj500c_print_page, 4, 2, 1);
577
gx_device_cdj far_data gs_cdj500_device =
578
cdj_device(cdj500_procs, "cdj500", 300, 300, BITSPERPIXEL,
579
dj500c_print_page, 4, 2, 1);
581
gx_device_cdj far_data gs_cdj550_device =
582
cdj_device(cdj550_procs, "cdj550", 300, 300, BITSPERPIXEL,
583
dj550c_print_page, 0, 2, 1);
585
#ifdef USE_CDJ550_CMYK
586
gx_device_cdj far_data gs_cdj550cmyk_device = {
587
prn_cmyk_colour_device(cdj550cmyk_procs, "cdj550cmyk", 300, 300,
588
BITSPERPIXEL, dj550c_print_page, 0), 2, 1
592
gx_device_cdj far_data gs_picty180_device =
593
cdj_device(cdj550_procs, "picty180", 300, 300, BITSPERPIXEL,
594
picty180_print_page, 0, 2, 1);
596
gx_device_cdj far_data gs_dj505j_device =
597
cdj_device(dj505j_procs, "dj505j", 300, 300, 1,
598
dj505j_print_page, 4, 0, 1);
600
gx_device_pj far_data gs_declj250_device =
601
pj_device(pj_procs, "declj250", 180, 180, BITSPERPIXEL,
602
declj250_print_page);
604
gx_device_cdj far_data gs_dnj650c_device =
605
cdj_device(dnj650c_procs, "dnj650c", 300, 300, BITSPERPIXEL,
606
dnj650c_print_page, 0, 2, 1);
608
gx_device_cdj far_data gs_lj4dith_device =
609
cdj_device(lj4dith_procs, "lj4dith", 600, 600, 8,
610
lj4dith_print_page, 4, 0, 1);
612
gx_device_cdj far_data gs_lj4dithp_device =
613
cdj_device(lj4dith_procs, "lj4dithp", 600, 600, 8,
614
lj4dithp_print_page, 4, 0, 1);
616
gx_device_pj far_data gs_pj_device =
617
pj_device(pj_procs, "pj", 180, 180, BITSPERPIXEL,
620
gx_device_pjxl far_data gs_pjxl_device =
621
pjxl_device(pjxl_procs, "pjxl", 180, 180, BITSPERPIXEL,
622
pjxl_print_page, 0, 0);
624
gx_device_pjxl far_data gs_pjxl300_device =
625
pjxl_device(pjxl300_procs, "pjxl300", 300, 300, BITSPERPIXEL,
626
pjxl300_print_page, 0, 0);
628
gx_device_cdj far_data gs_escp_device =
629
cdj_device(escp_procs, "escp", 360, 360, 8,
630
escp_print_page, 0, 0, 1);
632
gx_device_cdj far_data gs_escpc_device =
633
cdj_device(escp_procs, "escpc", 360, 360, 24,
634
escp_print_page, 0, 0, 1);
636
/* Args of bjc drivers are manualFeed, mediaType, printQuality, printColor,
637
mediaWeight_isSet, mediaWeight, (monochromePrint) */
639
gx_device_bjc600 far_data gs_bjc600_device =
643
BJC600_DEFAULT_RESOLUTION,
644
BJC600_DEFAULT_RESOLUTION,
645
BJC600_DEFAULT_BITSPERPIXEL,
648
BJC600_DEFAULT_MANUALFEED,
649
BJC600_DEFAULT_MEDIATYPE,
650
BJC600_DEFAULT_SETMEDIAWEIGHT,
651
BJC600_DEFAULT_MEDIAWEIGHT,
652
BJC600_DEFAULT_PRINTQUALITY,
653
BJC600_DEFAULT_DITHERINGTYPE,
654
BJC600_DEFAULT_COLORCOMPONENTS,
655
BJC600_DEFAULT_PRINTCOLORS,
656
BJC600_DEFAULT_MONOCHROMEPRINT);
658
gx_device_bjc800 far_data gs_bjc800_device =
662
BJC800_DEFAULT_RESOLUTION,
663
BJC800_DEFAULT_RESOLUTION,
664
BJC800_DEFAULT_BITSPERPIXEL,
667
BJC800_DEFAULT_MANUALFEED,
668
BJC800_DEFAULT_MEDIATYPE,
669
BJC800_DEFAULT_SETMEDIAWEIGHT,
670
BJC800_DEFAULT_MEDIAWEIGHT,
671
BJC800_DEFAULT_PRINTQUALITY,
672
BJC800_DEFAULT_DITHERINGTYPE,
673
BJC600_DEFAULT_COLORCOMPONENTS,
674
BJC800_DEFAULT_PRINTCOLORS);
676
/* Forward references */
677
static int gdev_pcl_mode1compress(const byte *, const byte *, byte *);
678
static int hp_colour_open(gx_device *, int);
679
static int hp_colour_print_page(gx_device_printer *, FILE *, int);
680
static int cdj_put_param_int(gs_param_list *, gs_param_name, int *, int, int, int);
681
static uint gdev_prn_rasterwidth(const gx_device_printer *, int);
682
static int cdj_put_param_bpp(gx_device *, gs_param_list *, int, int, int);
683
static int cdj_set_bpp(gx_device *, int, int);
684
static void cdj_expand_line(word *, int, short, int, int);
685
static int bjc_fscmyk(byte**, byte*[4][4], int**, int, int);
687
/* String parameters manipulation */
692
} stringParamDescription;
694
static const byte* paramValueToString(const stringParamDescription*, int);
695
static int paramStringValue(const stringParamDescription*,
696
const byte*, int, int*);
698
static int put_param_string(gs_param_list*, const byte*,
699
gs_param_string*, const stringParamDescription*, int *, int);
700
static int get_param_string(gs_param_list*, const byte*,
701
gs_param_string*, const stringParamDescription*, int, bool, int);
703
/* Open the printer and set up the margins. */
705
dj500c_open(gx_device *pdev)
706
{ return hp_colour_open(pdev, DJ500C);
710
dj550c_open(gx_device *pdev)
711
{ return hp_colour_open(pdev, DJ550C);
715
dj505j_open(gx_device *pdev)
716
{ return hp_colour_open(pdev, DJ505J);
720
dnj650c_open(gx_device *pdev)
721
{ return hp_colour_open(pdev, DNJ650C);
725
lj4dith_open(gx_device *pdev)
726
{ return hp_colour_open(pdev, LJ4DITH);
730
pjxl300_open(gx_device *pdev)
731
{ return hp_colour_open(pdev, PJXL300);
735
pj_open(gx_device *pdev)
736
{ return hp_colour_open(pdev, PJ180);
740
pjxl_open(gx_device *pdev)
741
{ return hp_colour_open(pdev, PJXL180);
745
escp_open(gx_device *pdev)
746
{ return hp_colour_open(pdev, ESC_P);
750
bjc_open(gx_device *pdev)
751
{ return hp_colour_open(pdev, bjc->ptype);
755
hp_colour_open(gx_device *pdev, int ptype)
756
{ /* Change the margins if necessary. */
757
static const float dj_a4[4] = { DESKJET_MARGINS_A4 };
758
static const float dj_letter[4] = { DESKJET_MARGINS_LETTER };
759
static const float dj_505j[4] = { DESKJET_505J_MARGINS };
760
static const float dj_505jc[4] = { DESKJET_505J_MARGINS_COLOR };
761
static const float lj4_all[4] = { LJET4_MARGINS };
762
static const float pj_all[4] = { PAINTJET_MARGINS };
763
static const float dnj_all[4] = { DESIGNJET_MARGINS };
764
static const float ep_a4[4] = { ESC_P_MARGINS_A4 };
765
static const float ep_letter[4] = { ESC_P_MARGINS_LETTER };
767
static float bjc_a3[4] = { BJC_MARGINS_A3 }; /* Not const! */
768
static float bjc_letter[4] = { BJC_MARGINS_LETTER }; /* Not const! */
769
static float bjc_a4[4] = { BJC_MARGINS_A4 }; /* Not const! */
771
const float *m = (float *) 0;
773
/* Set up colour params if put_params has not already done so */
774
if (pdev->color_info.num_components == 0)
775
{ int code = cdj_set_bpp(pdev, pdev->color_info.depth,
776
pdev->color_info.num_components);
784
m = (gdev_pcl_paper_size(pdev) == PAPER_SIZE_A4 ? dj_a4 :
788
m = pdev->color_info.num_components > 1 ? dj_505jc : dj_505j;
802
m = (gdev_pcl_paper_size(pdev) == PAPER_SIZE_A4 ? ep_a4 :
807
switch (gdev_pcl_paper_size(pdev)) {
808
case PAPER_SIZE_LEGAL:
809
case PAPER_SIZE_LETTER:
823
#ifndef USE_FIXED_MARGINS
824
if (ptype == BJC800) {
825
((float *) m)[1] = (float)BJC_HARD_LOWER_LIMIT;
829
bjc->printLimit = m[3]; /* The real hardware limit. */
831
#ifdef BJC_DEFAULT_CENTEREDAREA
833
((float *) m)[3] = m[1]; /* Top margin = bottom one. */
835
((float *) m)[1] = m[3]; /* Bottom margin = top one. */
844
* The margins must be set so that the resulting page length will be
845
* expressed exactly as a multiple of tenthes of inches.
850
float *bjcm = (float *) m;
853
(pdev->height / pdev->y_pixels_per_inch * 10.
854
- bjcm[3] * 10. - bjcm[1] * 10. + .5) + 1;
857
bjcm[1] = pdev->height / pdev->y_pixels_per_inch
858
- bjcm[3] - (float) pdimen / 10.;
859
} while (bjcm[1] < BJC_LOWER_LIMIT);
864
gx_device_set_margins(pdev, m, true);
865
return gdev_prn_open(pdev);
868
/* Added parameters for DeskJet 5xxC */
870
/* Get parameters. In addition to the standard and printer
871
* parameters, we supply shingling and depletion parameters,
872
* and control over the bits-per-pixel used in output rendering */
874
cdj_get_params(gx_device *pdev, gs_param_list *plist)
875
{ int code = gdev_prn_get_params(pdev, plist);
877
(code = param_write_int(plist, "BlackCorrect", (int *)&cdj->correction)) < 0 ||
878
(code = param_write_int(plist, "Shingling", &cdj->shingling)) < 0 ||
879
(code = param_write_int(plist, "Depletion", &cdj->depletion)) < 0
886
/* Put parameters. */
888
cdj_put_params(gx_device *pdev, gs_param_list *plist)
889
{ int correction = cdj->correction;
890
int shingling = cdj->shingling;
891
int depletion = cdj->depletion;
895
code = cdj_put_param_int(plist, "BlackCorrect", &correction, 0, 9, code);
896
code = cdj_put_param_int(plist, "Shingling", &shingling, 0, 2, code);
897
code = cdj_put_param_int(plist, "Depletion", &depletion, 1, 3, code);
898
code = cdj_put_param_int(plist, "BitsPerPixel", &bpp, 1, 32, code);
902
code = cdj_put_param_bpp(pdev, plist, bpp, bpp, 0);
906
cdj->correction = correction;
907
cdj->shingling = shingling;
908
cdj->depletion = depletion;
912
/* Added parameters for PaintJet XL and PaintJet XL300 */
914
/* Get parameters. In addition to the standard and printer
915
* parameters, we supply print_quality and render_type
916
* parameters, together with bpp control. */
918
pjxl_get_params(gx_device *pdev, gs_param_list *plist)
919
{ int code = gdev_prn_get_params(pdev, plist);
921
(code = param_write_int(plist, "PrintQuality", &pjxl->printqual)) < 0 ||
922
(code = param_write_int(plist, "RenderType", &pjxl->rendertype)) < 0
929
/* Put parameters. */
931
pjxl_put_params(gx_device *pdev, gs_param_list *plist)
932
{ int printqual = pjxl->printqual;
933
int rendertype = pjxl->rendertype;
934
int bpp = 0, real_bpp = 0;
937
code = cdj_put_param_int(plist, "PrintQuality", &printqual, -1, 1, code);
938
code = cdj_put_param_int(plist, "RenderType", &rendertype, 0, 10, code);
939
code = cdj_put_param_int(plist, "BitsPerPixel", &bpp, 1, 32, code);
944
if ( rendertype > 0 )
945
{ /* If printer is doing the dithering, we must have a
946
* true-colour mode, ie. 16 or 24 bits per pixel */
947
if ( bpp > 0 && bpp < 16 )
950
code = cdj_put_param_bpp(pdev, plist, bpp, real_bpp, 0);
954
pjxl->printqual = printqual;
955
pjxl->rendertype = rendertype;
959
/* Added parameters for PaintJet */
961
/* Put parameters. In addition to the standard and printer */
962
/* parameters, we allow control of the bits-per-pixel */
964
pj_put_params(gx_device *pdev, gs_param_list *plist)
966
int code = cdj_put_param_int(plist, "BitsPerPixel", &bpp, 1, 32, 0);
970
return cdj_put_param_bpp(pdev, plist, bpp, bpp, 0);
973
static stringParamDescription bjc_processColorsStrings[] = {
980
static stringParamDescription bjc_mediaTypeStrings[] = {
981
{ "PlainPaper", BJC_MEDIA_PLAINPAPER },
982
{ "CoatedPaper", BJC_MEDIA_COATEDPAPER },
983
{ "TransparencyFilm", BJC_MEDIA_TRANSPARENCYFILM },
984
{ "Envelope", BJC_MEDIA_ENVELOPE },
985
{ "Card", BJC_MEDIA_CARD},
986
{ "Other", BJC_MEDIA_OTHER },
990
static stringParamDescription bjc600_printQualityStrings[] = {
997
static stringParamDescription bjc800_printQualityStrings[] = {
1005
static stringParamDescription bjc_ditheringTypeStrings[] = {
1006
{ "None", BJC_DITHER_NONE },
1007
{ "Floyd-Steinberg", BJC_DITHER_FS },
1012
bjc_get_params(gx_device *pdev, gs_param_list *plist)
1014
int code = gdev_prn_get_params(pdev, plist);
1017
gs_param_string pmedia;
1018
gs_param_string pquality;
1019
gs_param_string dithering;
1021
if (code < 0) return_error(code);
1023
if ((ncode = param_write_bool(plist, BJC_OPTION_MANUALFEED,
1024
&bjcparams.manualFeed)) < 0) {
1028
code = get_param_string(plist, (unsigned char *)BJC_OPTION_MEDIATYPE, &pmedia,
1029
bjc_mediaTypeStrings, bjcparams.mediaType, true, code);
1031
code = get_param_string(plist, (unsigned char *)BJC_OPTION_PRINTQUALITY, &pquality,
1032
(bjc->ptype == BJC800 ? bjc800_printQualityStrings :
1033
bjc600_printQualityStrings), bjcparams.printQuality,
1036
code = get_param_string(plist, (unsigned char *)BJC_OPTION_DITHERINGTYPE, &dithering,
1037
bjc_ditheringTypeStrings, bjcparams.ditheringType, true, code);
1039
if ((ncode = param_write_int(plist, BJC_OPTION_PRINTCOLORS,
1040
&bjcparams.printColors)) < 0) {
1044
if ((ncode = (bjcparams.mediaWeight_isSet ?
1045
param_write_int(plist, BJC_OPTION_MEDIAWEIGHT,
1046
&bjcparams.mediaWeight) :
1047
param_write_null(plist, BJC_OPTION_MEDIAWEIGHT))) < 0) {
1051
if (bjc->ptype != BJC800) {
1052
if ((ncode = param_write_bool(plist, BJC_OPTION_MONOCHROMEPRINT,
1053
&bjc600params.monochromePrint)) < 0) {
1060
gs_param_string versionString;
1064
version = bjcversion(pdev);
1065
versionString.data = (byte *)bjcversionstring(pdev);
1067
versionString.size = strlen((char *)versionString.data);
1068
versionString.persistent = true;
1070
if ((ncode = param_write_float(plist, BJC_DEVINFO_VERSION,
1074
if ((ncode = param_write_string(plist, BJC_DEVINFO_VERSIONSTRING,
1075
&versionString)) < 0) {
1079
if ((ncode = param_write_bool(plist, BJC_DEVINFO_OUTPUTFACEUP,
1088
/* Put properties for the bjc drivers. */
1091
bjc_put_params(gx_device *pdev, gs_param_list *plist)
1093
int bpp = 0, ccomps = 0;
1100
const char* oname = (const char*) 0;
1102
bjc600_params new600Params;
1103
bjc800_params new800Params;
1107
gs_param_string pprocesscolors;
1108
gs_param_string pmedia;
1109
gs_param_string pquality;
1110
gs_param_string dithering;
1112
gs_param_float_array hwra;
1114
if (bjc->ptype != BJC800) {
1115
new600Params = bjc600params;
1116
params = (bjc_params*) &new600Params;
1118
new800Params = bjc800params;
1119
params = (bjc_params*) &new800Params;
1122
if ((code = cdj_put_param_int(plist, "BitsPerPixel",
1123
&bpp, 1, 32, code)) != 1) {
1124
bpp = pdev->color_info.depth;
1127
if ((code = put_param_string(plist, (unsigned char *)"ProcessColorModel",
1128
&pprocesscolors, bjc_processColorsStrings, &ccomps, code)) != 1) {
1129
ccomps = pdev->color_info.num_components;
1132
if ((ncode = param_read_bool(plist, oname = BJC_OPTION_MANUALFEED,
1133
¶ms->manualFeed)) < 0) {
1134
param_signal_error(plist, oname, code = ncode);
1137
code = put_param_string(plist, (unsigned char *)BJC_OPTION_MEDIATYPE, &pmedia,
1138
bjc_mediaTypeStrings, ¶ms->mediaType, code);
1140
code = cdj_put_param_int(plist, BJC_OPTION_PRINTCOLORS,
1141
¶ms->printColors, 0, 15, code);
1143
code = put_param_string(plist, (unsigned char *)BJC_OPTION_PRINTQUALITY, &pquality,
1144
(bjc->ptype == BJC800 ? bjc800_printQualityStrings :
1145
bjc600_printQualityStrings), ¶ms->printQuality, code);
1147
code = put_param_string(plist, (unsigned char *)BJC_OPTION_DITHERINGTYPE, &dithering,
1148
bjc_ditheringTypeStrings, ¶ms->ditheringType, code);
1150
switch (ncode = param_read_int(plist,
1151
oname = BJC_OPTION_MEDIAWEIGHT, ¶ms->mediaWeight)) {
1153
if (params->mediaWeight <= 0) {
1154
ncode = gs_error_rangecheck;
1156
params->mediaWeight_isSet = 1;
1162
if ((ncode = param_read_null(plist, oname)) == 0) {
1163
params->mediaWeight_isSet = 0;
1166
mwe: param_signal_error(plist, oname, code = ncode);
1172
if (bjc->ptype != BJC800) {
1173
bjc600_params* params600 = (bjc600_params*) params;
1174
if ((ncode = param_read_bool(plist,
1175
oname = BJC_OPTION_MONOCHROMEPRINT,
1176
¶ms600->monochromePrint)) < 0) {
1177
param_signal_error(plist, oname, code = ncode);
1181
if ((ncode = cdj_param_check_float(plist, BJC_DEVINFO_VERSION,
1182
bjcversion(pdev), true)) < 0) {
1185
if ((ncode = cdj_param_check_string(plist, BJC_DEVINFO_VERSIONSTRING,
1186
bjcversionstring(pdev), true)) < 0) {
1190
if ((ncode = param_read_bool(plist, oname = BJC_DEVINFO_OUTPUTFACEUP,
1192
param_signal_error(plist, oname, code = ncode);
1193
} else if (aBool != true) {
1194
param_signal_error(plist, oname, code = ncode = gs_error_rangecheck);
1197
/* Check for invalid resolution. The array macros are taken from
1198
gsdparam.c and modified to use oname, ncode and code instead
1199
of param_name, code and ecode respectively. */
1201
BEGIN_ARRAY_PARAM(param_read_float_array, "HWResolution", hwra, 2, hwre)
1202
if ( hwra.data[0] <= 0 || hwra.data[1] <= 0 ||
1203
hwra.data[0] != hwra.data[1] )
1204
ncode = gs_error_rangecheck;
1207
if (hwra.data[0] != BJC_RESOLUTION_LOW &&
1208
hwra.data[0] != BJC_RESOLUTION_NORMAL &&
1209
hwra.data[0] != BJC_RESOLUTION_HIGH) {
1210
ncode = gs_error_rangecheck;
1213
/* A small hack for checking resolution without logarithms. */
1218
for (n = 0; n < 8 * sizeof(n) / BJC_RESOLUTION_BASE; ++n) {
1219
float res = (float)(BJC_RESOLUTION_BASE * (1 << n));
1221
if (res == hwra.data[0]) break;
1223
if (res > hwra.data[0]) {
1224
ncode = gs_error_rangecheck;
1228
if (n == 8 * sizeof(n)) {
1229
ncode = gs_error_rangecheck;
1239
END_PARAM(hwra, hwre)
1241
if ((ncode = cdj_put_param_bpp(pdev, plist, bpp, bpp, ccomps)) < 0) {
1249
params->ditheringType = BJC_DITHER_NONE;
1252
/* Write values that did change */
1254
if (bjc->ptype != BJC800) {
1255
bjc600params = new600Params;
1257
bjc800params = new800Params;
1263
/* ------ Internal routines ------ */
1265
/* The DeskJet500C can compress (mode 9) */
1267
dj500c_print_page(gx_device_printer * pdev, FILE * prn_stream)
1269
return hp_colour_print_page(pdev, prn_stream, DJ500C);
1272
/* The DeskJet550C can compress (mode 9) */
1274
dj550c_print_page(gx_device_printer * pdev, FILE * prn_stream)
1276
return hp_colour_print_page(pdev, prn_stream, DJ550C);
1279
/* The Picty180C can compress (mode 9) */
1280
/* This printer need switching mode using PJL */
1282
picty180_print_page(gx_device_printer * pdev, FILE * prn_stream)
1284
/* Ensure we're operating in PCL mode */
1285
fputs("\033%-12345X@PJL ENTER LANGUAGE = PCLSLEEK\n", prn_stream);
1286
ret_code = hp_colour_print_page(pdev, prn_stream, DJ550C);
1287
/* Reenter switch-configured language */
1288
fputs("\033%-12345X", prn_stream);
1292
/* The DeskJet505J can compress */
1294
dj505j_print_page(gx_device_printer * pdev, FILE * prn_stream)
1296
return hp_colour_print_page(pdev, prn_stream, DJ505J);
1299
/* The DesignJet650C can compress (mode 1) */
1301
dnj650c_print_page(gx_device_printer * pdev, FILE * prn_stream)
1303
return hp_colour_print_page(pdev, prn_stream, DNJ650C);
1307
lj4dith_print_page(gx_device_printer * pdev, FILE * prn_stream)
1309
return hp_colour_print_page(pdev, prn_stream, LJ4DITH);
1313
lj4dithp_print_page(gx_device_printer * pdev, FILE * prn_stream)
1315
/* Ensure we're operating in PCL mode */
1316
fputs("\033%-12345X@PJL\r\n@PJL ENTER LANGUAGE = PCL\r\n", prn_stream);
1317
ret_code = hp_colour_print_page(pdev, prn_stream, LJ4DITH);
1318
/* Reenter switch-configured language */
1319
fputs("\033%-12345X", prn_stream);
1323
/* The PJXL300 can compress (modes 2 & 3) */
1325
pjxl300_print_page(gx_device_printer * pdev, FILE * prn_stream)
1327
/* Ensure we're operating in PCL mode */
1328
fputs("\033%-12345X@PJL enter language = PCL\n", prn_stream);
1329
ret_code = hp_colour_print_page(pdev, prn_stream, PJXL300);
1330
/* Reenter switch-configured language */
1331
fputs("\033%-12345X", prn_stream);
1335
/* The PaintJet XL can compress (modes 2 & 3) */
1337
pjxl_print_page(gx_device_printer * pdev, FILE * prn_stream)
1339
return hp_colour_print_page(pdev, prn_stream, PJXL180);
1342
/* The PaintJet can compress (mode 1) */
1344
pj_print_page(gx_device_printer * pdev, FILE * prn_stream)
1346
return hp_colour_print_page(pdev, prn_stream, PJ180);
1349
/* The LJ250 can compress (mode 1) */
1351
declj250_print_page(gx_device_printer * pdev, FILE * prn_stream)
1353
fputs("\033%8", prn_stream); /* Enter PCL emulation mode */
1354
ret_code = hp_colour_print_page(pdev, prn_stream, DECLJ250);
1355
fputs("\033%@", prn_stream); /* Exit PCL emulation mode */
1359
/* The BJC-600 cannot compress w/o raster image commands. */
1361
escp_print_page(gx_device_printer * pdev, FILE * prn_stream)
1363
return hp_colour_print_page(pdev, prn_stream, ESC_P);
1366
/* The BJC-600 can compress w/ raster image commands. */
1368
bjc_print_page(gx_device_printer * pdev, FILE * prn_stream)
1370
return hp_colour_print_page(pdev, prn_stream, bjc->ptype);
1373
/* MACROS FOR DITHERING (we use macros for compact source and faster code) */
1374
/* Floyd-Steinberg dithering. Often results in a dramatic improvement in
1375
* subjective image quality, but can also produce dramatic increases in
1376
* amount of printer data generated and actual printing time!! Mode 9 2D
1377
* compression is still useful for fairly flat colour or blank areas but its
1378
* compression is much less effective in areas where the dithering has
1379
* effectively randomised the dot distribution. */
1381
#define SHIFT ((I * 8) - 13)
1382
#define RSHIFT ((I * 8) - 16)
1383
#define RANDOM (((rand() << RSHIFT) % (MAXVALUE / 2)) - MAXVALUE / 4);
1385
#define MAXVALUE (255 << SHIFT)
1386
#define THRESHOLD (128 << SHIFT)
1389
#define FSdither(inP, out, errP, Err, Bit, Offset, Element)\
1391
Err = (errP[Element] + ((Err * 7 + C) >> 4) + ((int)inP[Element] << SHIFT));\
1392
if (Err > THRESHOLD) {\
1396
errP[Element + Offset] += ((Err * 3 + C) >> 4);\
1397
errP[Element] = ((Err * 5 + oldErr + C) >> 4);
1399
/* Here we rely on compiler optimisation to remove lines of the form
1400
* (if (1 >= 4) {...}, ie. the constant boolean expressions */
1402
/* The original code is in the #else part. Since by default NEW_DITHER
1403
is not defined, the old code is used. No enhancement is visible for the
1404
bjc600 drivers with the new code, anyway :-( */
1408
#define FSDline(scan, i, j, plane_size, cErr, mErr, yErr, kErr, cP, mP, yP, kP, n)\
1410
if (scan == 0) { /* going_up */\
1411
for (i = 0; i < plane_size; i++) {\
1412
byte c, y, m, k, bitmask;\
1415
for (c = m = y = k = 0; bitmask != 0; bitmask >>= 1) {\
1417
FSdither(dp, k, ep, kErr, bitmask, -n, 0);\
1420
FSdither(dp, c, ep, cErr, bitmask, -n, n - 3);\
1421
FSdither(dp, m, ep, mErr, bitmask, -n, n - 2);\
1423
FSdither(dp, y, ep, yErr, bitmask, -n, n - 1);\
1434
} else { /* going_down */\
1435
for (i = 0; i < plane_size; i++) {\
1436
byte c, y, m, k, bitmask;\
1439
for (c = m = y = k = 0; bitmask != 0; bitmask <<= 1) {\
1441
FSdither(dp, y, ep, yErr, bitmask, n, n - 1);\
1443
FSdither(dp, m, ep, mErr, bitmask, n, n - 2);\
1444
FSdither(dp, c, ep, cErr, bitmask, n, n - 3);\
1447
FSdither(dp, k, ep, kErr, bitmask, n, 0);\
1463
#define FSDline(scan, i, j, plane_size, cErr, mErr, yErr, kErr, cP, mP, yP, kP, n)\
1465
if (scan == 0) { /* going_up */\
1466
for (i = 0; i < plane_size; i++) {\
1467
byte c, y, m, k, bitmask;\
1470
for (c = m = y = k = 0; bitmask != 0; bitmask >>= 1) {\
1473
FSdither(dp, k, ep, kErr, bitmask, -n, 0);\
1474
cErr = mErr = yErr = 0;\
1476
FSdither(dp, c, ep, cErr, bitmask, -n, n - 3);\
1477
FSdither(dp, m, ep, mErr, bitmask, -n, n - 2);\
1478
FSdither(dp, y, ep, yErr, bitmask, -n, n - 1);\
1482
FSdither(dp, c, ep, cErr, bitmask, -n, n - 3);\
1483
FSdither(dp, m, ep, mErr, bitmask, -n, n - 2);\
1485
FSdither(dp, y, ep, yErr, bitmask, -n, n - 1);\
1497
} else { /* going_down */\
1498
for (i = 0; i < plane_size; i++) {\
1499
byte c, y, m, k, bitmask;\
1502
for (c = m = y = k = 0; bitmask != 0; bitmask <<= 1) {\
1506
FSdither(dp, k, ep, kErr, bitmask, n, 0);\
1507
cErr = mErr = yErr = 0;\
1509
FSdither(dp, y, ep, yErr, bitmask, n, n - 1);\
1510
FSdither(dp, m, ep, mErr, bitmask, n, n - 2);\
1511
FSdither(dp, c, ep, cErr, bitmask, n, n - 3);\
1514
FSdither(dp, y, ep, yErr, bitmask, n, n - 1);\
1516
FSdither(dp, m, ep, mErr, bitmask, n, n - 2);\
1517
FSdither(dp, c, ep, cErr, bitmask, n, n - 3);\
1534
/* END MACROS FOR DITHERING */
1536
#define CPbit(inP, out, Bit, Element)\
1537
if (inP[Element]) {\
1541
#define COPYline(scan, i, j, plane_size, cP, mP, yP, kP, n)\
1543
if (scan == 0) { /* going_up */\
1544
for (i = 0; i < plane_size; i++) {\
1545
byte c, y, m, k, bitmask;\
1547
for (c = m = y = k = 0; bitmask != 0; bitmask >>= 1) {\
1549
CPbit(dp, k, bitmask, 0);\
1552
CPbit(dp, c, bitmask, n - 3);\
1553
CPbit(dp, m, bitmask, n - 2);\
1555
CPbit(dp, y, bitmask, n - 1);\
1566
} else { /* going_down */\
1567
for (i = 0; i < plane_size; i++) {\
1568
byte c, y, m, k, bitmask;\
1570
for (c = m = y = k = 0; bitmask != 0; bitmask <<= 1) {\
1573
CPbit(dp, k, bitmask, 0);\
1576
CPbit(dp, m, bitmask, n - 2);\
1577
CPbit(dp, c, bitmask, n - 3);\
1579
CPbit(dp, y, bitmask, n - 1);\
1592
/* Some convenient shorthand .. */
1593
#define x_dpi (pdev->x_pixels_per_inch)
1594
#define y_dpi (pdev->y_pixels_per_inch)
1595
#define CONFIG_16BIT "\033*v6W\000\003\000\005\006\005"
1596
#define CONFIG_24BIT "\033*v6W\000\003\000\010\010\010"
1598
/* To calculate buffer size as next greater multiple of both parameter and W */
1599
#define calc_buffsize(a, b) (((((a) + ((b) * W) - 1) / ((b) * W))) * W)
1602
* Miscellaneous functions for Canon BJC-600 printers in raster command mode.
1604
#define fputshort(n, f) fputc((n)%256,f);fputc((n)/256,f)
1607
bjc_cmd(byte cmd, int argsize, byte* arg, gx_device_printer* pdev,
1612
fputshort(argsize, f);
1613
fwrite(arg, sizeof(byte), argsize, f);
1619
bjc_raster_cmd_sub(char c, int rastsize, byte* data, FILE* f)
1622
fputshort(rastsize + 1, f);
1624
fwrite(data, sizeof(byte), rastsize, f);
1631
bjc_raster_cmd(int c_id, int rastsize, byte* data, gx_device_printer* pdev,
1634
if (bjcparams.printColors == BJC_COLOR_ALLBLACK) {
1635
bjc_raster_cmd_sub('K', rastsize, data, f);
1636
} else if (pdev->color_info.num_components == 1) {
1637
if (bjcparams.printColors & BJC_COLOR_BLACK) {
1638
bjc_raster_cmd_sub('K', rastsize, data, f);
1640
if (bjcparams.printColors & BJC_COLOR_YELLOW)
1641
bjc_raster_cmd_sub('Y', rastsize, data, f);
1642
if (bjcparams.printColors & BJC_COLOR_MAGENTA)
1643
bjc_raster_cmd_sub('M', rastsize, data, f);
1644
if (bjcparams.printColors & BJC_COLOR_CYAN)
1645
bjc_raster_cmd_sub('C', rastsize, data, f);
1647
}else { /* Color decomposition */
1648
static byte ymckCodes[] = {
1655
if (bjcparams.printColors & (int) ymckCodes[c_id]) {
1656
bjc_raster_cmd_sub("YMCK"[c_id], rastsize, data, f);
1664
bjc_init_page(gx_device_printer* pdev, FILE* f)
1666
byte pagemargins[3], resolution[4], paperloading[2];
1668
/* Compute page margins. */
1670
pagemargins[0] = (byte) ((float) pdev->height / pdev->y_pixels_per_inch
1672
pagemargins[1] = (byte) 1;
1673
pagemargins[2] = (byte) ((pdev->width / pdev->x_pixels_per_inch * 10) -
1674
pdev->HWMargins[0] / 7.2 - pdev->HWMargins[2] / 7.2 + .5);
1676
/* Cheat to keep margins into bounds (while waiting to have the right
1677
margins for big papers. */
1679
switch (bjc->ptype) {
1681
if (pagemargins[2] > 114) pagemargins[2] = 114;
1685
if (pagemargins[2] > 80) pagemargins[2] = 80;
1689
/* Initialize resolution argument. */
1691
resolution[0] = (byte) ((int)pdev->y_pixels_per_inch / 256);
1692
resolution[1] = (byte) ((int)pdev->y_pixels_per_inch % 256);
1693
resolution[2] = (byte) ((int)pdev->x_pixels_per_inch / 256);
1694
resolution[3] = (byte) ((int)pdev->x_pixels_per_inch % 256);
1696
/* Initialize paper loading argument. */
1698
paperloading[0] = 0x10 + ((1 - bjcparams.manualFeed) << 2);
1699
paperloading[1] = bjcparams.mediaType << 4;
1701
/* Reinitialize printer in raster mode. */
1708
/* Set page mode on (ignore data at end of page) */
1710
bjc_cmd('a', 1, (byte*) "\001", pdev, f);
1712
/* Set page margins */
1714
bjc_cmd('g', 3, pagemargins, pdev, f);
1716
/* Set compression on (this is PackBits compression a la TIFF/Mac) */
1718
bjc_cmd('b', 1, (byte*) "\001", pdev, f);
1720
/* Set paper loading. */
1722
bjc_cmd('l', 2, paperloading, pdev, f);
1724
/* Set printing method. */
1726
#ifndef BJC_INIT_800_AS_600
1727
if (bjc->ptype == BJC800) {
1733
printmode[0] = bjcparams.printQuality;
1735
/* Modes not used are 3 (CN, Color Normal) and 2 (TP+ (?)) */
1737
switch (bjcparams.printQuality) {
1738
case BJC_QUALITY_DRAFT:
1739
printmode[0] = 4; /* Draft */
1743
printmode[1] = (bjcparams.mediaType >= BJC_MEDIA_ENVELOPE ? 1 :
1744
bjc800thickpaper());
1746
bjc_cmd('c', 2, printmode, pdev, f);
1747
} else /* BJC600 */ {
1750
printmeth[0] = 0x10 + ((1 - bjcparams.manualFeed) << 2);
1751
printmeth[1] = (bjcparams.mediaType << 4) + bjcparams.printQuality;
1752
printmeth[2] = (bjcparams.printQuality == BJC_QUALITY_HIGH ?
1753
0x10 : 0) + (bjcparams.mediaType >= BJC_MEDIA_ENVELOPE ? 1 :
1754
bjc600thickpaper());
1756
bjc_cmd('c', 3, printmeth, pdev, f);
1759
/* Set raster resolution */
1761
bjc_cmd('d', 4, resolution, pdev, f);
1767
bjc_v_skip(int n, gx_device_printer* pdev, FILE* f)
1781
bjc_finish_page(gx_device_printer* pdev, FILE* f)
1783
bjc_cmd('a', 1, (byte*) "\000", pdev, f);
1784
bjc_cmd('b', 1, (byte*) "\000", pdev, f);
1791
/* 1D runlength compression for BJC-600
1792
* this code is borrowed from gdevpcl.c:gdev_pcl_mode2compress.
1795
bjc_compress(const byte *row, const byte *end_row, byte *compressed)
1797
register const byte *exam = row;
1798
register byte *cptr = compressed; /* output pointer into compressed bytes */
1800
while ( exam < end_row ) {
1801
/* Search ahead in the input looking for a run */
1802
/* of at least 4 identical bytes. */
1803
const byte *compr = exam;
1804
const byte *end_dis;
1806
register byte test, test2;
1809
while ( exam < end_row ) {
1811
if ( test == test2 )
1816
/* Find out how long the run is */
1818
if ( exam == end_row ) { /* no run */
1823
while ( next < end_row && *next == test ) next++;
1826
/* Now [compr..end_dis) should be encoded as dissimilar, */
1827
/* and [end_dis..next) should be encoded as similar. */
1828
/* Note that either of these ranges may be empty. */
1830
for ( ; ; ) { /* Encode up to 128 dissimilar bytes */
1831
uint count = end_dis - compr; /* uint for faster switch */
1832
switch ( count ) { /* Use memcpy only if it's worthwhile. */
1833
case 6: cptr[6] = compr[5];
1834
case 5: cptr[5] = compr[4];
1835
case 4: cptr[4] = compr[3];
1836
case 3: cptr[3] = compr[2];
1837
case 2: cptr[2] = compr[1];
1838
case 1: cptr[1] = compr[0];
1841
case 0: /* all done */
1844
if ( count > 128 ) count = 128;
1845
*cptr++ = count - 1;
1846
memcpy(cptr, compr, count);
1847
cptr += count, compr += count;
1853
{ /* Encode up to 128 similar bytes. */
1854
/* Note that count may be <0 at end of row. */
1855
int count = next - end_dis;
1856
if (next < end_row || test != 0)
1857
while ( count > 0 ) {
1859
int this = (count > 128 ? 128 : count);
1860
*cptr++ = 257 - this;
1861
*cptr++ = (byte)test;
1867
return cptr - compressed;
1871
* For the ESC/P mode, resolution is fixed as 360dpi and we must transform
1872
* image data to serialized data.
1876
uint storage_size_words;
1877
byte *raster_buf[4][BJC_HEAD_ROWS];
1885
const gs_memory_t *mem;
1888
#define row_bytes (img_rows / 8)
1889
#define min_rows (32) /* for optimization of text image printing */
1892
ep_print_image(FILE *prn_stream, ep_globals *eg, char cmd, byte *data, int size)
1895
static const char color[4] = {4,1,2,0};
1900
case 1: /* Magenta */
1901
case 0: /* Yellow */
1902
memcpy(eg->raster_buf[((int) cmd)][eg->ln_idx+eg->vskip2], data, size);
1904
case 'B': /* blank line skip */
1907
} else if (size >= eg->img_rows - (eg->ln_idx+eg->vskip2) || eg->ln_idx+eg->vskip2 >= min_rows) {
1908
/* The 'I' cmd must precede 'B' cmd! */
1910
ep_print_image(prn_stream, eg, 'F', 0, 0); /* flush and reset status */
1915
case 'I': /* Increment index */
1916
eg->ln_idx += eg->vskip2 + 1;
1918
if (eg->ln_idx < eg->img_rows) return 0;
1919
/* if eg->raster_buf filled up, then fall through here and flush buffer */
1920
case 'F': /* flush print buffer */
1921
if (!eg->ln_idx) return 0; /* The end of the page. */
1923
/* before print the image, perform vertical skip. */
1924
while (eg->vskip1 >= (255*2)) {
1925
fputs("\033J\377", prn_stream); /* n/180in. feeding */
1926
eg->vskip1 -= (255*2);
1928
if (eg->vskip1 > 255) {
1929
fputs("\033J\200", prn_stream);
1933
/* n/360in. feeding */
1934
fputs("\033|J", prn_stream); putc(0, prn_stream); putc(eg->vskip1, prn_stream);
1937
/* Optimize the number of nozzles to be used. */
1938
if (eg->ln_idx > 56) { /* use 64 nozzles */
1940
} else if (eg->ln_idx > 48) { /* use 56 nozzles */
1942
} else if (eg->ln_idx > 32) { /* use 48 nozzles */
1944
} else { /* use 32 nozzles */
1948
for (i = 0; i < eg->num_comps; i++) {
1949
int lnum, hskip, print_size, img_rows;
1950
byte *p0, *p1, *p2, *p3;
1951
byte *inp, *inbuf, *outp, *outbuf;
1953
img_rows = real_rows; /* Note that this img_rows is not the one in
1954
* the globals struct. */
1955
outbuf = eg->print_buf;
1957
/* Transpose raster image for serial printer image */
1958
for (lnum=0; lnum < img_rows; lnum+=8, outbuf++) {
1959
inbuf = inp = eg->raster_buf[i][lnum];
1960
for (outp = outbuf; inp < inbuf+eg->plane_size; inp++, outp += img_rows) {
1961
memflip8x8(inp, eg->plane_size, outp, row_bytes);
1966
if (eg->num_comps == 1) {
1967
/* Don't set color (to enable user setting). */
1968
putc('\015', prn_stream);
1970
/* set color to one of CMYK. */
1971
fputs("\015\033r", prn_stream);
1972
putc(color[i], prn_stream);
1975
*(outp = eg->print_buf + eg->plane_size * img_rows) = 1; /* sentinel */
1977
p0 = p3 = eg->print_buf;
1979
/* print image p0 to p1 and h skip p1 to p2 if p2<outp,
1980
* then make p0=p2 and continue */
1982
static const word zeros[8] = {0,0,0,0,0,0,0,0};
1985
/* p1 is the head of running zeros. */
1986
/* note that h skip unit is 1/180inch */
1987
for (p1 = p3; !memcmp(p3, zeros, row_bytes*2); p3 += row_bytes*2);
1988
/* p2 is the head of non zero image. */
1991
for (p3 += row_bytes; memcmp(p3, zeros, row_bytes); p3 += row_bytes);
1992
if (p3 < outp && memcmp(p3+row_bytes, zeros, row_bytes)) goto redo;
1993
} else p1 = p2 = outp;
1995
if (p0 < p1) { /* print the image between p0 and p1 */
1996
print_size = ((p1 < outp) ? p1 : outp) - p0;
1997
fputs("\033|B", prn_stream); putc(img_rows, prn_stream);
1998
fputshort(print_size, prn_stream);
1999
fwrite(p0, sizeof(byte), print_size, prn_stream);
2001
if (p1 < p2) { /* skip running zeros from p1 to p2 */
2002
hskip = (((p2 < outp) ? p2 : outp) - p1) / row_bytes / 2;
2003
fputs("\033\\", prn_stream);
2004
fputshort(hskip, prn_stream);
2009
return ep_print_image(prn_stream, eg, 'R', 0, eg->vskip2 + eg->ln_idx);
2010
case 'R': /* Reset status */
2014
memset(eg->storage, 0, eg->storage_size_words * W);
2016
default: /* This should not happen */
2017
errprintf(eg->mem, "ep_print_image: illegal command character `%c'.\n", cmd);
2024
/* Send the page to the printer. Compress each scan line. */
2026
hp_colour_print_page(gx_device_printer * pdev, FILE * prn_stream, int ptype)
2028
uint raster_width = gdev_prn_rasterwidth(pdev, 1);
2029
/* int line_size = gdev_prn_rasterwidth(pdev, 0); */
2030
int line_size = gdev_prn_raster(pdev);
2031
int line_size_words = (line_size + W - 1) / W;
2032
int paper_size = gdev_pcl_paper_size((gx_device *)pdev);
2033
int num_comps = pdev->color_info.num_components;
2034
int bits_per_pixel = pdev->color_info.depth;
2035
int storage_bpp = bits_per_pixel;
2036
int expanded_bpp = bits_per_pixel;
2037
int plane_size, databuff_size;
2038
int combined_escapes = 1;
2039
int errbuff_size = 0;
2040
int outbuff_size = 0;
2041
int compression = 0;
2044
const char *cid_string = (const char*) 0;
2045
byte *data[4], *plane_data[4][4], *out_data;
2046
byte *out_row, *out_row_alt;
2048
uint storage_size_words;
2051
memset(&eg, 0, sizeof(eg));
2052
eg.img_rows=BJC_HEAD_ROWS;
2053
eg.mem=pdev->memory;
2055
/* Tricks and cheats ... */
2058
if (num_comps == 3 && !cprn_device->cmyk)
2059
num_comps = 4; /* 4-component printing */
2062
if (bits_per_pixel == 24) /* prefer 3-component printing for bpp=24. */
2070
if (pjxl->rendertype > 0) {
2071
if (bits_per_pixel < 16)
2072
pjxl->rendertype = 0;
2074
/* Control codes for CID sequence */
2075
cid_string = (bits_per_pixel == 16) ? CONFIG_16BIT : CONFIG_24BIT;
2076
/* Pretend we're a monobit device so we send the data out unchanged */
2077
bits_per_pixel = storage_bpp = expanded_bpp = 1;
2084
if (cprn_device->cmyk <= 0) {
2085
if (storage_bpp == 8 && num_comps >= 3)
2086
bits_per_pixel = expanded_bpp = 3; /* Only 3 bits of each byte used */
2089
plane_size = calc_buffsize(line_size, storage_bpp);
2090
eg.plane_size = plane_size;
2092
if (bits_per_pixel == 1) { /* Data printed direct from i/p */
2093
databuff_size = 0; /* so no data buffer required, */
2094
outbuff_size = plane_size * 4; /* but need separate output buffers */
2097
if (bits_per_pixel > 4) { /* Error buffer for FS dithering */
2098
storage_bpp = expanded_bpp =
2099
num_comps * 8; /* 8, 24 or 32 bits */
2101
if (cprn_device->cmyk > 0) { /* Use CMYK dithering algorithm. */
2102
errbuff_size = 4 * (5 + 1 + 1 + line_size + 1 + 2) * I;
2103
} else { /* Use original (RGB) dithering. */
2104
errbuff_size = /* 4n extra values for line ends */
2105
calc_buffsize((plane_size * expanded_bpp + num_comps * 4) * I, 1);
2109
databuff_size = plane_size * storage_bpp;
2111
storage_size_words = ((plane_size + plane_size) * num_comps +
2112
databuff_size + errbuff_size + outbuff_size) / W;
2114
storage = (ulong *) gs_malloc(pdev->memory, storage_size_words, W, "hp_colour_print_page");
2115
eg.storage_size_words = (plane_size * (num_comps + 1)) / W * eg.img_rows
2116
+ 16; /* Redundant space for sentinel and aligning. */
2117
eg.storage = (word *) gs_malloc(pdev->memory, eg.storage_size_words, W, "ep_print_buffer");
2120
* The principal data pointers are stored as pairs of values, with
2121
* the selection being made by the 'scan' variable. The function of the
2122
* scan variable is overloaded, as it controls both the alternating
2123
* raster scan direction used in the Floyd-Steinberg dithering and also
2124
* the buffer alternation required for line-difference compression.
2126
* Thus, the number of pointers required is as follows:
2128
* errors: 2 (scan direction only)
2129
* data: 4 (scan direction and alternating buffers)
2130
* plane_data: 4 (scan direction and alternating buffers)
2133
if (storage == 0 || eg.storage == 0) /* can't allocate working area */
2134
return_error(gs_error_VMerror);
2137
byte *p = out_data = out_row = (byte *)storage;
2138
byte *ep_p = (byte *)eg.storage;
2139
data[0] = data[1] = data[2] = p;
2140
data[3] = p + databuff_size;
2141
out_row_alt = out_row + plane_size * 2;
2142
if (bits_per_pixel > 1) {
2145
if (bits_per_pixel > 4) {
2146
errors[0] = (int *)p + num_comps * 2;
2147
errors[1] = errors[0] + databuff_size;
2150
for (i = 0; i < num_comps; i++) {
2151
plane_data[0][i] = plane_data[2][i] = p;
2154
for (i = 0; i < num_comps; i++) {
2155
plane_data[1][i] = p;
2156
plane_data[3][i] = p + plane_size;
2159
if (bits_per_pixel == 1) {
2160
out_data = out_row = p; /* size is outbuff_size * 4 */
2161
out_row_alt = out_row + plane_size * 2;
2162
data[1] += databuff_size; /* coincides with plane_data pointers */
2163
data[3] += databuff_size;
2165
for (i = 0; i < num_comps; i++) {
2166
for (j = 0; j < eg.img_rows; j++) {
2167
eg.raster_buf[i][j] = ep_p;
2170
/* Make a sentinel and align to word size. */
2171
eg.print_buf = (byte *)((word)(ep_p + sizeof(word)) & ~(sizeof(word)-1));
2173
eg.num_comps = num_comps;
2176
/* Initialize printer. */
2177
if (ptype == DJ505J) {
2178
fputs("\033@",prn_stream); /* Reset printer */
2179
fprintf(prn_stream,"\033_R%c%c", /* Set resolution */
2180
(int)x_dpi & 0xff,((int)x_dpi >> 8) & 0xff);
2181
} else if (ptype == BJC600 || ptype == BJC800) {
2182
bjc_init_page(pdev, prn_stream);
2184
if (ptype == LJ4DITH) {
2185
fputs("\033*rB", prn_stream);
2187
fputs("\033*rbC", prn_stream); /* End raster graphics */
2189
fprintf(prn_stream, "\033*t%dR", (int)x_dpi);
2190
/* Set resolution */
2193
/* Clear temp storage */
2194
memset(storage, 0, storage_size_words * W);
2196
#define DOFFSET (dev_t_margin(pdev) - DESKJET_PRINT_LIMIT) /* Print position */
2197
#define POFFSET (dev_t_margin(pdev) - PAINTJET_PRINT_LIMIT)
2198
#define EOFFSET (dev_t_margin(pdev) - ESC_P_PRINT_LIMIT)
2199
#define BOFFSET (dev_t_margin(pdev) - bjc->printLimit)
2202
/* Page size, orientation, top margin & perforation skip */
2203
fprintf(prn_stream, "\033&l%dA\033&l0o0e0L\033*r0F", paper_size);
2204
fprintf(prn_stream, "\033*p0x0Y" ); /* These Offsets are hacked ! */
2205
fprintf(prn_stream, "\033&u600D\033*r1A" );
2206
/* Select data compression */
2208
combined_escapes = 0;
2212
/* Page size, orientation, top margin & perforation skip */
2213
fprintf(prn_stream, "\033&l%daolE", paper_size);
2214
/* Set depletion and shingling levels */
2215
fprintf(prn_stream, "\033*o%dd%dQ", cdj->depletion, cdj->shingling);
2216
/* Move to top left of printed area */
2217
fprintf(prn_stream, "\033*p%dY", (int)(300 * DOFFSET));
2218
/* Set number of planes ((-)1 is mono, (-)3 is (cmy)rgb, -4 is cmyk),
2219
* and raster width, then start raster graphics */
2220
fprintf(prn_stream, "\033*r%ds-%du0A", raster_width, num_comps);
2221
/* Select data compression */
2225
/* Set depletion and shingling levels */
2226
fprintf(prn_stream, "\033_D%c\033_E%c",
2227
cdj->depletion, cdj->shingling);
2228
/* Move to top left of printed area */
2229
fwrite("\033_N\000", 4, 1, prn_stream);
2230
fwrite("\033_J\xc4\xff", 5, 1, prn_stream);
2231
/* Set number of planes ((-)1 is mono, (-)3 is (cmy)rgb, -4 is cmyk),
2232
* and raster width, then start raster graphics */
2233
fprintf(prn_stream, "\033_U%c%c",
2234
(0xffff - num_comps + 1) & 0xff, ((0xffff - num_comps + 1) >> 8) & 0xff);
2236
"\033_S%c%c", raster_width & 0xff, (raster_width >> 8) & 0xff);
2238
fwrite("\033_A\001", 4, 1, prn_stream);
2240
combined_escapes = 0;
2243
if (pdev->x_pixels_per_inch == 600) {
2244
/* set resolution to 600dpi 1st through PJL command */
2245
fprintf(prn_stream,"\033%%-12345X@PJL SET RESOLUTION = 600\n");
2247
fprintf (prn_stream, "\033%%0B"); /* Enter HPGL/2 mode */
2248
fprintf (prn_stream, "BP5,1"); /* Turn off autorotation */
2249
fprintf (prn_stream, "PS%d,%d",
2250
(int)((pdev->height/pdev->y_pixels_per_inch)*1016),
2251
(int)((pdev->width/pdev->x_pixels_per_inch)*1016)); /* Set length/width of page */
2252
fprintf (prn_stream, "PU"); /* Pen up */
2253
fprintf (prn_stream, "PA%d,%d", 0, 0); /* Move pen to upper-left */
2254
fprintf (prn_stream, "\033%%1A"); /* Enter HP-RTL mode */
2255
fprintf (prn_stream, "\033&a1N"); /* No negative motion - allow plotting
2257
if (pdev->x_pixels_per_inch == 600)
2258
fprintf (prn_stream, "\033*t600R"); /* request 600dpi via HP RTL */
2259
{ static const char temp[] = {
2260
033, '*', 'v', '6', 'W',
2261
000 /* color model */,
2262
000 /* pixel encoding mode */,
2263
003 /* number of bits per index */,
2265
010 /* bits green */,
2268
fwrite (temp, 1, sizeof(temp), prn_stream);
2271
/* Set raster width */
2272
fprintf(prn_stream, "\033*r%dS", raster_width);
2273
/* Start raster graphics */
2274
fprintf(prn_stream, "\033*r1A");
2276
/* Select data compression */
2278
/* No combined escapes for raster transfers */
2279
combined_escapes = 0;
2282
/* Page size, orientation, top margin & perforation skip */
2283
fprintf(prn_stream, "\033&l%daolE", paper_size);
2284
/* Set no-negative-motion mode, for faster (unbuffered) printing */
2285
fprintf(prn_stream, "\033&a1N");
2286
/* Set print quality */
2287
fprintf(prn_stream, "\033*o%dQ", pjxl->printqual);
2288
/* Move to top left of printed area */
2289
fprintf(prn_stream, "\033*p%dY", (int)(300 * POFFSET));
2290
/* Configure colour setup */
2291
if (pjxl->rendertype > 0) {
2292
/* Set render type */
2293
fprintf(prn_stream, "\033*t%dJ", pjxl->rendertype);
2294
/* Configure image data */
2295
fputs(cid_string, prn_stream);
2296
/* Set raster width, then start raster graphics */
2297
fprintf(prn_stream, "\033*r%ds1A", raster_width);
2299
/* Set number of planes (1 is mono, 3 is rgb),
2300
* and raster width, then start raster graphics */
2301
fprintf(prn_stream, "\033*r%ds-%du0A", raster_width, num_comps);
2303
/* No combined escapes for raster transfers */
2304
combined_escapes = 0;
2307
/* Page size, orientation, top margin & perforation skip */
2308
fprintf(prn_stream, "\033&l%daolE", paper_size);
2309
/* Set print quality */
2310
fprintf(prn_stream, "\033*o%dQ", pjxl->printqual);
2311
/* Move to top left of printed area */
2312
fprintf(prn_stream, "\033*p%dY", (int)(180 * POFFSET));
2313
/* Configure colour setup */
2314
if (pjxl->rendertype > 0) {
2315
/* Set render type */
2316
fprintf(prn_stream, "\033*t%dJ", pjxl->rendertype);
2317
/* Configure image data */
2318
fputs(cid_string, prn_stream);
2319
/* Set raster width, then start raster graphics */
2320
fprintf(prn_stream, "\033*r%ds1A", raster_width);
2322
/* Set number of planes (1 is mono, 3 is rgb),
2323
* and raster width, then start raster graphics */
2324
fprintf(prn_stream, "\033*r%ds%du0A", raster_width, num_comps);
2329
/* Disable perforation skip */
2330
fprintf(prn_stream, "\033&lL");
2331
/* Move to top left of printed area */
2332
fprintf(prn_stream, "\033&a%dV", (int)(720 * POFFSET));
2333
/* Set number of planes (1 is mono, 3 is rgb),
2334
* and raster width, then start raster graphics */
2335
fprintf(prn_stream, "\033*r%ds%du0A", raster_width, num_comps);
2336
if (ptype == DECLJ250) {
2337
/* No combined escapes for raster transfers */
2338
combined_escapes = 0;
2339
/* From here on, we're a standard Paintjet .. */
2342
/* Select data compression */
2346
/* Move to top left of printed area (must be modified for large movement(YK))*/
2347
if ((int)(EOFFSET*360)) fprintf(prn_stream, "\033|J%c%c", 0, (int)(360*EOFFSET));
2348
combined_escapes = 0;
2352
/* Move to top left of printed area */
2353
bjc_v_skip((int)(pdev->HWResolution[1] * BOFFSET), pdev, prn_stream);
2354
combined_escapes = 0;
2355
compression = 2; /* BJC600 uses the same method as mode 2 compression */
2359
/* Unfortunately, the Paintjet XL300 PCL interpreter introduces a
2360
* version of the PCL language which is different to all earlier HP
2361
* colour and mono inkjets, in that it loses the very useful ability
2362
* to use combined escape sequences with the raster transfer
2363
* commands. In this respect, it is incompatible even with the older
2364
* 180 dpi PaintJet and PaintJet XL printers! Another regrettable
2365
* omission is that 'mode 9' compression is not supported, as this
2366
* mode can give both computational and PCL file size advantages. */
2368
if (ptype == DJ505J) {
2369
fprintf(prn_stream, "\033_M%c", compression);
2370
} else if (combined_escapes) {
2371
/* From now on, all escape commands start with \033*b, so we
2372
* combine them (if the printer supports this). */
2373
fputs("\033*b", prn_stream);
2374
/* Set compression if the mode has been defined. */
2376
fprintf(prn_stream, "%dm", compression);
2378
else if (ptype == BJC600 || ptype == BJC800)
2379
; /* Currently, nothing to do. */
2382
fprintf(prn_stream, "\033*b%dM", compression);
2384
/* Send each scan line in turn */
2386
int cErr, mErr, yErr, kErr;
2387
int this_pass, lnum, i;
2389
int lend, num_blank_lines = 0;
2391
word rmask = ~(word) 0 << ((-pdev->width * storage_bpp) & (W * 8 - 1));
2393
lend = pdev->height -
2394
(int)((dev_t_margin(pdev) + dev_b_margin(pdev)) * y_dpi);
2399
start_rows = BJC_HEAD_ROWS;
2402
/* Inhibit blank line printing for RGB-only printers, since in
2403
* this case 'blank' means black! Also disabled for XL300 due to
2404
* an obscure bug in the printer's firmware */
2413
start_rows = (num_comps == 1) ? HEAD_ROWS_MONO - 1 :
2414
HEAD_ROWS_COLOUR - 1;
2418
cErr = mErr = yErr = kErr = 0;
2420
if (bits_per_pixel > 4) { /* Randomly seed initial error buffer */
2421
if (cprn_device->cmyk > 0 && expanded_bpp == 32) {
2422
bjc_fscmyk(data, plane_data, errors, plane_size, -1);
2424
int *ep = errors[0];
2425
for (i = 0; i < databuff_size; i++) {
2431
this_pass = start_rows;
2432
for (lnum = 0; lnum < lend; lnum++) {
2433
word *data_words = (word *)data[scan];
2434
register word *end_data = data_words + line_size_words;
2436
gdev_prn_copy_scan_lines(pdev, lnum, data[scan], line_size);
2438
/* Mask off 1-bits beyond the line width. */
2439
end_data[-1] &= rmask;
2441
/* Remove trailing 0s. */
2442
while (end_data > data_words && end_data[-1] == 0)
2444
if (ptype != DNJ650C) /* DesignJet can't skip blank lines ? ? */
2445
if (end_data == data_words) { /* Blank line */
2449
/* Skip blank lines if any */
2450
if (num_blank_lines > 0) {
2451
if (ptype == DJ505J) {
2452
fprintf(prn_stream,"\033_Y%c%c",
2453
num_blank_lines & 0xff, (num_blank_lines >> 8) & 0xff);
2454
} else if (ptype == ESC_P) {
2455
ep_print_image(prn_stream, &eg, 'B', 0, num_blank_lines);
2456
} else if (ptype == BJC600 || ptype == BJC800) {
2457
bjc_v_skip(num_blank_lines, pdev, prn_stream);
2458
} else if (num_blank_lines < this_pass) {
2459
/* Moving down from current position
2460
* causes head motion on the DeskJets, so
2461
* if the number of lines is within the
2462
* current pass of the print head, we're
2463
* better off printing blanks. */
2464
this_pass -= num_blank_lines;
2465
if (combined_escapes) {
2466
fputc('y', prn_stream); /* Clear current and seed rows */
2467
for (; num_blank_lines; num_blank_lines--)
2468
fputc('w', prn_stream);
2471
/**************** The following code has been proposed ****************/
2472
/**************** as a replacement: ****************/
2473
fputs("\033*b1Y", prn_stream); /* Clear current and seed rows */
2474
if ( num_blank_lines > 1 )
2475
fprintf(prn_stream, "\033*b%dY", num_blank_lines - 1);
2476
num_blank_lines = 0;
2478
fputs("\033*bY", prn_stream); /* Clear current and seed rows */
2479
if (ptype == DNJ650C) {
2480
fprintf (prn_stream, "\033*b%dY", num_blank_lines);
2481
num_blank_lines = 0;
2484
for (; num_blank_lines; num_blank_lines--)
2485
fputs("\033*bW", prn_stream);
2490
if (combined_escapes)
2491
fprintf(prn_stream, "%dy", num_blank_lines);
2493
fprintf(prn_stream, "\033*b%dY", num_blank_lines);
2495
memset(plane_data[1 - scan][0], 0, plane_size * num_comps);
2496
num_blank_lines = 0;
2497
this_pass = start_rows;
2499
{ /* Printing non-blank lines */
2500
register byte *kP = plane_data[scan + 2][3];
2501
register byte *cP = plane_data[scan + 2][2];
2502
register byte *mP = plane_data[scan + 2][1];
2503
register byte *yP = plane_data[scan + 2][0];
2504
register byte *dp = data[scan + 2];
2505
register int *ep = errors[scan];
2513
this_pass = start_rows;
2515
if (expanded_bpp > bits_per_pixel) { /* Expand line if required */
2516
cdj_expand_line(data_words, line_size,
2518
bits_per_pixel, expanded_bpp);
2521
/* In colour modes, we have some bit-shuffling to do before
2522
* we can print the data; in FS mode we also have the
2523
* dithering to take care of. */
2524
switch (expanded_bpp) { /* Can be 1, 3, 8, 24 or 32 */
2526
/* Transpose the data to get pixel planes. */
2527
for (i = 0, odp = plane_data[scan][0]; i < databuff_size;
2528
i += 8, odp++) { /* The following is for 16-bit
2531
{ 0, c, c*0x100, c*0x101, c*0x10000L, c*0x10001L, c*0x10100L, c*0x10101L }
2532
static ulong spr40[8] = spread3(0x40);
2533
static ulong spr08[8] = spread3(8);
2534
static ulong spr02[8] = spread3(2);
2535
register byte *dp = data[scan] + i;
2536
register ulong pword =
2537
(spr40[dp[0]] << 1) +
2539
(spr40[dp[2]] >> 1) +
2540
(spr08[dp[3]] << 1) +
2542
(spr08[dp[5]] >> 1) +
2544
(spr02[dp[7]] >> 1);
2545
odp[0] = (byte) (pword >> 16);
2546
odp[plane_size] = (byte) (pword >> 8);
2547
odp[plane_size * 2] = (byte) (pword);
2555
if (bjcparams.ditheringType == BJC_DITHER_NONE) {
2556
COPYline(scan, i, j, plane_size, cP, mP, yP, kP, 1);
2561
FSDline(scan, i, j, plane_size, cErr, mErr, yErr, kErr,
2566
FSDline(scan, i, j, plane_size, cErr, mErr, yErr, kErr,
2570
if (cprn_device->cmyk > 0) {
2571
bjc_fscmyk(data, plane_data, errors, plane_size, scan);
2573
FSDline(scan, i, j, plane_size, cErr, mErr, yErr, kErr,
2578
} /* switch(expanded_bpp) */
2580
/* Make sure all black is in the k plane */
2582
if (num_comps == 4 && (cprn_device->cmyk <= 0 || expanded_bpp != 32)) {
2583
register word *kp = (word *)plane_data[scan][3];
2584
register word *cp = (word *)plane_data[scan][2];
2585
register word *mp = (word *)plane_data[scan][1];
2586
register word *yp = (word *)plane_data[scan][0];
2587
if (bits_per_pixel > 4) { /* Done as 4 planes */
2588
for (i = 0; i < plane_size / W; i++) {
2589
word bits = *cp & *mp & *yp;
2596
} else { /* This has really been done as 3 planes */
2597
for (i = 0; i < plane_size / W; i++) {
2598
word bits = *cp & *mp & *yp;
2608
/* Transfer raster graphics in the order (K), C, M, Y */
2610
for (zero_row_count = 0, i = num_comps - 1; i >= 0; i--) {
2611
int output_plane = 1;
2615
case DJ500C: /* Always compress using mode 9 */
2617
out_count = gdev_pcl_mode9compress(plane_size,
2618
plane_data[scan][i],
2619
plane_data[1 - scan][i],
2622
/* This optimisation allows early termination of the
2623
* row, but this doesn't work correctly in an alternating
2624
* mode 2 / mode 3 regime, so we only use it with mode 9
2627
{ output_plane = 0; /* No further output for this plane */
2629
fputc('w', prn_stream);
2634
{ for (; zero_row_count; zero_row_count--)
2635
fputc('v', prn_stream);
2639
out_count = gdev_pcl_mode1compress((const byte *)
2640
plane_data[scan][i],
2642
plane_data[scan][i] + plane_size - 1,
2648
{ word *wp = (word *)plane_data[scan][i];
2649
for (j = 0; j < plane_size / W; j++, wp++)
2652
out_count = gdev_pcl_mode1compress((const byte *)
2653
plane_data[scan][i],
2655
plane_data[scan][i] + plane_size - 1,
2658
case PJXL180: /* Need to invert data as CMY not supported */
2660
{ word *wp = (word *)plane_data[scan][i];
2661
for (j = 0; j < plane_size / W; j++, wp++)
2664
/* fall through .. */
2665
case PJXL300: /* Compression modes 2 and 3 are both
2666
* available. Try both and see which one
2667
* produces the least output data. */
2669
{ const byte *plane = plane_data[scan][i];
2670
byte *prev_plane = plane_data[1 - scan][i];
2671
const word *row = (word *)plane;
2672
const word *end_row = row + plane_size/W;
2673
int count2 = gdev_pcl_mode2compress(row, end_row, out_row_alt);
2674
int count3 = gdev_pcl_mode3compress(plane_size, plane, prev_plane, out_row);
2675
int penalty = combined_escapes ? strlen("#m") : strlen("\033*b#M");
2676
int penalty2 = (compression == 2 ? 0 : penalty);
2677
int penalty3 = (compression == 3 ? 0 : penalty);
2679
if (count3 + penalty3 < count2 + penalty2)
2680
{ if ( compression != 3 ) {
2681
if (combined_escapes)
2682
fputs("3m", prn_stream);
2684
fputs("\033*b3M", prn_stream);
2691
{ if ( compression != 2 ) {
2692
if (combined_escapes)
2693
fputs("2m", prn_stream);
2695
fputs("\033*b2M", prn_stream);
2698
out_data = out_row_alt;
2705
{ const byte *plane = (byte *)plane_data[scan][i];
2706
int count2 = bjc_compress(plane, plane + plane_size, out_row_alt);
2708
out_data = out_row_alt;
2714
if (ptype == DJ505J)
2715
fprintf(prn_stream, "\033_%c%c%c",
2716
"WVVV"[i], out_count & 0xff, (out_count >> 8) & 0xff);
2717
else if (combined_escapes)
2718
fprintf(prn_stream, "%d%c", out_count, "wvvv"[i]);
2719
else if (ptype == BJC600 || ptype == BJC800) {
2721
bjc_raster_cmd(num_comps == 1 ? 3 : i,
2722
out_count, out_data, pdev, prn_stream);
2723
if (i == 0) bjc_v_skip(1, pdev, prn_stream);
2724
} else if (ptype == ESC_P)
2725
ep_print_image(prn_stream, &eg, (char)i, plane_data[scan][i], plane_size);
2727
fprintf(prn_stream, "\033*b%d%c", out_count, "WVVV"[i]);
2729
fwrite(out_data, sizeof(byte), out_count, prn_stream);
2732
} /* Transfer Raster Graphics ... */
2734
ep_print_image(prn_stream, &eg, 'I', 0, 0); /* increment line index */
2735
scan = 1 - scan; /* toggle scan direction */
2736
} /* Printing non-blank lines */
2737
} /* for lnum ... */
2738
} /* send each scan line in turn */
2740
if (combined_escapes)
2741
fputs("0M", prn_stream);
2743
/* end raster graphics */
2744
if (ptype == BJC600 || ptype == BJC800) {
2745
bjc_finish_page(pdev, prn_stream);
2746
} else if (ptype == DJ505J)
2747
fputs("\033_C", prn_stream);
2748
else if (ptype != ESC_P)
2749
fputs("\033*rbC\033E", prn_stream);
2753
fputc('\f', prn_stream);
2754
else if (ptype == DJ505J)
2755
fputs("\f\033@", prn_stream);
2756
else if (ptype == DNJ650C)
2757
fputs ("\033*rC\033%0BPG;", prn_stream);
2758
else if (ptype == BJC600 || ptype == BJC800)
2759
; /* Already done */
2760
else if (ptype == ESC_P) {
2761
ep_print_image(prn_stream, &eg, 'F', 0, 0); /* flush print buffer */
2762
fputs("\014\033@", prn_stream); /* reset after eject page */
2764
fputs("\033&l0H", prn_stream);
2766
/* free temporary storage */
2767
gs_free(pdev->memory, (char *) eg.storage, eg.storage_size_words, W, "ep_print_buffer");
2768
gs_free(pdev->memory, (char *) storage, storage_size_words, W, "hp_colour_print_page");
2774
* Row compression for the H-P PaintJet.
2775
* Compresses data from row up to end_row, storing the result
2776
* starting at compressed. Returns the number of bytes stored.
2777
* The compressed format consists of a byte N followed by a
2778
* data byte that is to be repeated N+1 times.
2779
* In the worst case, the `compressed' representation is
2780
* twice as large as the input.
2781
* We complement the bytes at the same time, because
2782
* we accumulated the image in complemented form.
2785
gdev_pcl_mode1compress(const byte *row, const byte *end_row, byte *compressed)
2786
{ register const byte *in = row;
2787
register byte *out = compressed;
2788
while ( in < end_row )
2789
{ byte test = *in++;
2790
const byte *run = in;
2791
while ( in < end_row && *in == test ) in++;
2792
/* Note that in - run + 1 is the repetition count. */
2793
while ( in - run > 255 )
2801
return out - compressed;
2805
* Map a CMYK color to a color index. We just use depth / 4 bits per color
2806
* to produce the color index.
2808
* Important note: CMYK values are stored in the order K, C, M, Y because of
2809
* the way the HP drivers work.
2813
#define gx_color_value_to_bits(cv, b) \
2814
((cv) >> (gx_color_value_bits - (b)))
2815
#define gx_bits_to_color_value(cv, b) \
2816
((cv) << (gx_color_value_bits - (b)))
2818
#define gx_cmyk_value_bits(c, m, y, k, b) \
2819
(((COLROUND_ROUND(k)) << (3 * (b))) | \
2820
((COLROUND_ROUND(c)) << (2 * (b))) | \
2821
((COLROUND_ROUND(m)) << (b)) | \
2822
((COLROUND_ROUND(y))))
2824
#define gx_value_cmyk_bits(v, c, m, y, k, b) \
2825
(k) = COLDUP_DUP(((v) >> (3 * (b))) & ((1 << (b)) - 1)), \
2826
(c) = COLDUP_DUP(((v) >> (2 * (b))) & ((1 << (b)) - 1)), \
2827
(m) = COLDUP_DUP(((v) >> (b)) & ((1 << (b)) - 1)), \
2828
(y) = COLDUP_DUP((v) & ((1 << (b)) - 1))
2830
static gx_color_index
2831
gdev_cmyk_map_cmyk_color(gx_device* pdev, const gx_color_value cv[])
2833
gx_color_value cyan, magenta, yellow, black;
2834
gx_color_index color;
2835
cyan = cv[0]; magenta = cv[1]; yellow = cv[2]; black = cv[3];
2836
switch (pdev->color_info.depth) {
2838
color = (cyan | magenta | yellow | black) > gx_max_color_value / 2 ?
2839
(gx_color_index) 1 : (gx_color_index) 0;
2844
int nbits = pdev->color_info.depth>>2;
2845
COLROUND_SETUP(nbits);
2847
color = gx_cmyk_value_bits(cyan, magenta, yellow, black, nbits);
2854
/* Mapping of RGB colors to gray values. */
2856
static gx_color_index
2857
gdev_cmyk_map_rgb_color(gx_device *pdev, const gx_color_value cv[])
2859
gx_color_value r, g, b;
2860
r = cv[0]; g = cv[1]; b = cv[2];
2861
if (gx_color_value_to_byte(r & g & b) == 0xff) {
2862
return (gx_color_index) 0; /* White */
2864
gx_color_value c = gx_max_color_value - r;
2865
gx_color_value m = gx_max_color_value - g;
2866
gx_color_value y = gx_max_color_value - b;
2868
switch (pdev->color_info.depth) {
2870
return (c | m | y) > gx_max_color_value / 2 ?
2871
(gx_color_index) 1 : (gx_color_index) 0;
2876
return ((ulong) c * lum_red_weight * 10
2877
+ (ulong) m * lum_green_weight * 10
2878
+ (ulong) y * lum_blue_weight * 10)
2879
>> (gx_color_value_bits + 2);
2885
return (gx_color_index) 0; /* This should never happen. */
2888
/* Mapping of CMYK colors. */
2891
gdev_cmyk_map_color_cmyk(gx_device *pdev, gx_color_index color, gx_color_value prgb[3])
2893
switch (pdev->color_info.depth) {
2895
prgb[0] = gx_max_color_value * (1 - color);
2899
if (pdev->color_info.num_components == 1) {
2900
gx_color_value value = (gx_color_value) color ^ 0xff;
2902
prgb[0] = (value << 8) + value;
2908
unsigned long bcyan, bmagenta, byellow, black;
2909
int nbits = pdev->color_info.depth>>2;
2912
COLDUP_SETUP(nbits);
2913
gx_value_cmyk_bits(color, bcyan, bmagenta, byellow, black, nbits);
2926
* Map a r-g-b color to a color index.
2927
* We complement the colours, since we're using cmy anyway, and
2928
* because the buffering routines expect white to be zero.
2929
* Includes colour balancing, following HP recommendations, to try
2930
* and correct the greenish cast resulting from an equal mix of the
2931
* c, m, y, inks by reducing the cyan component to give a truer black.
2934
/* Simple black generation/under-color removal with BG(k) = UG(k) = k. YA. */
2936
#define bg_and_ucr(c, c_v, m, m_v, y, y_v, k) \
2938
register byte cv = c_v, mv = m_v, yv = y_v, kv; \
2940
kv = (cv > mv ? mv : cv); \
2941
kv = (yv > k ? k : y); \
2942
y = yv - kv; m = mv - kv; c = cv -kv; k = kv; \
2945
static gx_color_index
2946
gdev_pcl_map_rgb_color(gx_device *pdev, const gx_color_value cv[])
2948
gx_color_value r, g, b;
2949
r = cv[0]; g = cv[1]; b = cv[2];
2950
if (gx_color_value_to_byte(r & g & b) == 0xff)
2951
return (gx_color_index)0; /* white */
2953
int correction = cprn_device->correction;
2954
gx_color_value c = gx_max_color_value - r;
2955
gx_color_value m = gx_max_color_value - g;
2956
gx_color_value y = gx_max_color_value - b;
2958
/* Colour correction for better blacks when using the colour ink
2959
* cartridge (on the DeskJet 500C only). We reduce the cyan component
2960
* by some fraction (eg. 4/5) to correct the slightly greenish cast
2961
* resulting from an equal mix of the three inks */
2963
ulong maxval, minval, range;
2965
maxval = c >= m ? (c >= y ? c : y) : (m >= y ? m : y);
2967
minval = c <= m ? (c <= y ? c : y) : (m <= y? m : y);
2968
range = maxval - minval;
2970
#define shift (gx_color_value_bits - 12)
2971
c = ((c >> shift) * (range + (maxval * correction))) /
2972
((maxval * (correction + 1)) >> shift);
2976
switch (pdev->color_info.depth) {
2978
return ((c | m | y) > gx_max_color_value / 2 ?
2979
(gx_color_index)1 : (gx_color_index)0);
2981
if (pdev->color_info.num_components >= 3)
2982
#define gx_color_value_to_1bit(cv) ((cv) >> (gx_color_value_bits - 1))
2983
return (gx_color_value_to_1bit(c) +
2984
(gx_color_value_to_1bit(m) << 1) +
2985
(gx_color_value_to_1bit(y) << 2));
2987
#define red_weight 306
2988
#define green_weight 601
2989
#define blue_weight 117
2990
return ((((ulong)c * red_weight +
2991
(ulong)m * green_weight +
2992
(ulong)y * blue_weight)
2993
>> (gx_color_value_bits + 2)));
2995
/* FIXME: Simple truncation is not ideal. Should round really. */
2996
#define gx_color_value_to_5bits(cv) ((cv) >> (gx_color_value_bits - 5))
2997
#define gx_color_value_to_6bits(cv) ((cv) >> (gx_color_value_bits - 6))
2998
return (gx_color_value_to_5bits(y) +
2999
(gx_color_value_to_6bits(m) << 5) +
3000
(gx_color_value_to_5bits(c) << 11));
3002
return (gx_color_value_to_byte(y) +
3003
(gx_color_value_to_byte(m) << 8) +
3004
((ulong)gx_color_value_to_byte(c) << 16));
3006
{ return ((c == m && c == y) ? ((ulong)gx_color_value_to_byte(c) << 24)
3007
: (gx_color_value_to_byte(y) +
3008
(gx_color_value_to_byte(m) << 8) +
3009
((ulong)gx_color_value_to_byte(c) << 16)));
3013
return (gx_color_index)0; /* This never happens */
3016
/* Map a color index to a r-g-b color. */
3018
gdev_pcl_map_color_rgb(gx_device *pdev, gx_color_index color,
3019
gx_color_value prgb[3])
3021
/* For the moment, we simply ignore any black correction */
3022
switch (pdev->color_info.depth) {
3024
prgb[0] = prgb[1] = prgb[2] = -((gx_color_value)color ^ 1);
3027
if (pdev->color_info.num_components >= 3)
3028
{ gx_color_value c = (gx_color_value)color ^ 7;
3030
prgb[1] = -((c >> 1) & 1);
3031
prgb[2] = -(c >> 2);
3034
{ gx_color_value value = (gx_color_value)color ^ 0xff;
3035
prgb[0] = prgb[1] = prgb[2] = (value << 8) + value;
3039
{ gx_color_value c = (gx_color_value)color ^ 0xffff;
3040
ushort value = c >> 11;
3041
prgb[0] = ((value << 11) + (value << 6) + (value << 1) +
3042
(value >> 4)) >> (16 - gx_color_value_bits);
3043
value = (c >> 6) & 0x3f;
3044
prgb[1] = ((value << 10) + (value << 4) + (value >> 2))
3045
>> (16 - gx_color_value_bits);
3047
prgb[2] = ((value << 11) + (value << 6) + (value << 1) +
3048
(value >> 4)) >> (16 - gx_color_value_bits);
3052
{ gx_color_index c = color ^ 0xffffff;
3053
prgb[0] = gx_color_value_from_byte((gx_color_value)(c >> 16));
3054
prgb[1] = gx_color_value_from_byte((gx_color_value)((c >> 8) & 0xff));
3055
prgb[2] = gx_color_value_from_byte((gx_color_value)(c & 0xff));
3059
#define gx_maxcol gx_color_value_from_byte(gx_color_value_to_byte(gx_max_color_value))
3060
{ gx_color_value w = gx_maxcol - gx_color_value_from_byte(color >> 24);
3061
prgb[0] = w - gx_color_value_from_byte((color >> 16) & 0xff);
3062
prgb[1] = w - gx_color_value_from_byte((color >> 8) & 0xff);
3063
prgb[2] = w - gx_color_value_from_byte(color & 0xff);
3071
* Convert and expand scanlines:
3073
* For devices with 3 components:
3075
* (a) 16 -> 24 bit (1-stage)
3076
* (b) 16 -> 32 bit (2-stage)
3077
* or (c) 24 -> 32 bit (1-stage)
3079
* For devices with 4 components:
3081
* (a) 16 -> 32 bit (1-stage)
3082
* (b) 8 -> 32 bit (2-stage)
3083
* or (c) 24 -> 32 bit (1-stage)
3088
cdj_expand_line(word *line, int linesize, short cmyk, int bpp, int ebpp)
3090
int endline = linesize;
3091
byte *start = (byte *)line;
3092
register byte *in, *out;
3096
in = start + endline;
3097
out = start + (endline *= 2);
3099
while (in > start) {
3101
register byte bs0, bs1, bs2, bs3;
3106
bs1 = (b0 >> 2) & 0x03;
3107
bs2 = (b0 >> 4) & 0x03;
3108
bs3 = (b0 >> 6) & 0x03;
3110
*--out = (bs0 << 2) + bs0 + (bs1 << 6) + (bs1 << 4);
3111
*--out = (bs2 << 2) + bs2 + (bs3 << 6) + (bs3 << 4);
3116
endline = (endline + 2) / 3;
3118
in = start + endline * 3;
3119
out = start + endline * 4;
3121
while (in > start) {
3122
register byte b0, b1, b2;
3128
*--out = (b0 << 2) + ((b0 >> 4) & 0x03);
3129
*--out = ((b1 & 0x0f) << 4) + ((b0 >> 6) << 2)
3130
+ ((b1 >> 2) & 0x03);
3131
*--out = ((b2 & 0x03) << 6) + ((b1 >> 4) << 2) + (b2 & 0x03);
3132
*--out = (b2 & 0xfc) + ((b2 >> 6) & 0x03);
3134
} else if (ebpp == 32) {
3135
endline = (endline + 1) / 2;
3137
in = start + endline * 2;
3138
out = start + (endline *= 4);
3140
while (in > start) {
3141
register byte b0, b1;
3146
*--out = (b0 << 4) + ((b0 >> 4) & 0x07);
3147
*--out = (b0 & 0xf0) + ((b0 >> 4) & 0xf);
3148
*--out = (b1 << 4) + ((b1 >> 4) & 0x0f);
3149
*--out = (b1 & 0xf0) + ((b1 >> 4) & 0xf);
3152
} else /* cmyk > 0 */ {
3153
if (bpp == 16) /* 16 to 24 (cmy) if required */
3154
{ register byte b0, b1;
3155
endline = ((endline + 1) / 2);
3156
in = start + endline * 2;
3157
out = start + (endline *= 3);
3162
*--out = (b0 << 3) + ((b0 >> 2) & 0x7);
3163
*--out = (b1 << 5) + ((b0 >> 3) & 0x1c) + ((b1 >> 1) & 0x3);
3164
*--out = (b1 & 0xf8) + (b1 >> 5);
3168
if (ebpp == 32) /* 24/32 (cmy) to 32 (cmyk) if required */
3169
{ register byte c, m, y;
3170
endline = ((endline + 2) / 3);
3171
in = start + endline * 3;
3172
out = start + endline * 4;
3180
if (c == y && c == m) {
3181
*--out = 0, *--out = 0, *--out = 0;
3184
*--out = y, *--out = m, *--out = c;
3193
cdj_put_param_int(gs_param_list *plist, gs_param_name pname, int *pvalue,
3194
int minval, int maxval, int ecode)
3196
switch ( code = param_read_int(plist, pname, &value) )
3203
if ( value < minval || value > maxval )
3204
param_signal_error(plist, pname, gs_error_rangecheck);
3206
return (ecode < 0 ? ecode : 1);
3211
cdj_set_bpp(gx_device *pdev, int bpp, int ccomps)
3212
{ gx_device_color_info *ci = &pdev->color_info;
3214
if (ccomps && bpp == 0) {
3215
if (cprn_device->cmyk) {
3218
return gs_error_rangecheck;
3231
switch (ci->depth) {
3239
bpp = cprn_device->default_depth;
3248
bpp = ci->depth; /* Use the current setting. */
3251
if (cprn_device->cmyk < 0) {
3253
/* Reset procedures because we may have been in another mode. */
3255
dev_proc(pdev, encode_color) = gdev_cmyk_map_cmyk_color;
3256
dev_proc(pdev, map_rgb_color) = NULL;
3257
dev_proc(pdev, decode_color) = gdev_cmyk_map_color_cmyk;
3259
if (pdev->is_open) gs_closedevice(pdev);
3262
/* Check for valid bpp values */
3268
if (cprn_device->cmyk && ccomps && ccomps != 4) goto bppe;
3272
if (!cprn_device->cmyk || ccomps == 0 || ccomps == 4) {
3274
} else if (ccomps == 1) {
3278
/* 3 components 24 bpp printing for CMYK device. */
3280
cprn_device->cmyk = -1;
3285
if (cprn_device->cmyk) {
3288
cprn_device->cmyk = -1;
3290
} else if (ccomps != 1 && ccomps != 4) {
3294
if (ccomps != 1) break;
3300
if (ccomps != 1) goto bppe;
3302
if (cprn_device->cmyk && bpp != pdev->color_info.depth) {
3303
dev_proc(pdev, map_cmyk_color) = NULL;
3304
dev_proc(pdev, map_rgb_color) = gdev_cmyk_map_rgb_color;
3306
if (pdev->is_open) {
3307
gs_closedevice(pdev);
3313
if (!cprn_device->cmyk) {
3318
bppe: return gs_error_rangecheck;
3321
if (cprn_device->cmyk == -1) {
3322
dev_proc(pdev, map_cmyk_color) = NULL;
3323
dev_proc(pdev, map_rgb_color) = gdev_pcl_map_rgb_color;
3324
dev_proc(pdev, map_color_rgb) = gdev_pcl_map_color_rgb;
3326
if (pdev->is_open) {
3327
gs_closedevice(pdev);
3329
if (pdev->is_open) {
3330
int code; /* Return code */
3331
gdev_prn_space_params sp; /* Space parameter data */
3333
/* Reallocate memory for device */
3334
sp = ((gx_device_printer *)pdev)->space_params;
3336
if ((code = gdev_prn_reallocate_memory(pdev, &sp, pdev->width,
3347
if (bpp != 1 && bpp != 8) goto cce;
3351
if (cprn_device->cmyk) {
3352
if (bpp >= 8) break;
3356
if (bpp == 1 || bpp == 3 || bpp == 8 || bpp == 16
3357
|| bpp == 24 || bpp == 32) {
3361
cce: default: return gs_error_rangecheck;
3364
if (cprn_device->cmyk) {
3365
if (cprn_device->cmyk > 0) {
3366
ci->num_components = ccomps ? ccomps : (bpp < 8 ? 1 : 4);
3368
ci->num_components = ccomps ? ccomps : (bpp < 8 ? 1 : 3);
3370
if (bpp != 1 && ci->num_components == 1) { /* We do dithered grays. */
3371
bpp = bpp < 8 ? 8 : bpp;
3374
ci->max_color = (1 << (bpp >> 2)) - 1;
3375
ci->max_gray = (bpp >= 8 ? 255 : 1);
3377
if (ci->num_components == 1) {
3378
ci->dither_grays = (bpp >= 8 ? 256 : 2);
3379
ci->dither_colors = (bpp >= 8 ? 256 : bpp > 1 ? 2 : 0);
3381
ci->dither_grays = (bpp > 8 ? 256 : 2);
3382
ci->dither_colors = (bpp > 8 ? 256 : bpp > 1 ? 2 : 0);
3385
ci->num_components = (bpp == 1 || bpp == 8 ? 1 : 3);
3386
ci->max_color = (bpp >= 8 ? 255 : bpp > 1 ? 1 : 0);
3387
ci->max_gray = (bpp >= 8 ? 255 : 1);
3388
ci->dither_grays = (bpp >= 8 ? 256 : 2);
3389
ci->dither_colors = (bpp >= 8 ? 256 : bpp > 1 ? 2 : 0);
3392
ci->depth = ((bpp > 1) && (bpp < 8) ? 8 : bpp);
3397
/* new_bpp == save_bpp or new_bpp == 0 means don't change bpp.
3398
ccomps == 0 means don't change number of color comps.
3399
If new_bpp != 0, it must be the value of the BitsPerPixel element of
3400
the plist; real_bpp may differ from new_bpp.
3403
cdj_put_param_bpp(gx_device *pdev, gs_param_list *plist, int new_bpp,
3404
int real_bpp, int ccomps)
3406
if (new_bpp == 0 && ccomps == 0)
3407
return gdev_prn_put_params(pdev, plist);
3410
gx_device_color_info save_info;
3414
save_info = pdev->color_info;
3415
save_bpp = save_info.depth;
3416
#define save_ccomps save_info.num_components
3417
if ( save_bpp == 8 && save_ccomps == 3 && !cprn_device->cmyk)
3419
code = cdj_set_bpp(pdev, real_bpp, ccomps);
3421
param_signal_error(plist, "BitsPerPixel", code);
3422
param_signal_error(plist, "ProcessColorModel", code);
3425
pdev->color_info.depth = new_bpp; /* cdj_set_bpp maps 3/6 to 8 */
3426
code = gdev_prn_put_params(pdev, plist);
3428
{ cdj_set_bpp(pdev, save_bpp, save_ccomps);
3431
cdj_set_bpp(pdev, real_bpp, ccomps); /* reset depth if needed */
3432
if ((cdj->color_info.depth != save_bpp ||
3433
(ccomps != 0 && ccomps != save_ccomps))
3435
return gs_closedevice(pdev);
3441
/* This returns either the number of pixels in a scan line, or the number
3442
* of bytes required to store the line, both clipped to the page margins */
3444
gdev_prn_rasterwidth(const gx_device_printer *pdev, int pixelcount)
3446
ulong raster_width = (ulong)(pdev->width -
3447
pdev->x_pixels_per_inch * (dev_l_margin(pdev) + dev_r_margin(pdev)));
3448
return (pixelcount ?
3449
(uint)raster_width :
3450
(uint)((raster_width * pdev->color_info.depth + 7) >> 3));
3453
/* Functions for manipulation params strings */
3456
paramValueToString(const stringParamDescription* params, int value)
3459
for (; params->p_name; ++params) {
3460
if (params->p_value == value) {
3461
return (const byte *)params->p_name;
3465
return (const byte*) 0;
3469
paramStringValue(const stringParamDescription* params,
3470
const byte* name, int namelen, int* value)
3473
for (; params->p_name; ++params) {
3474
if (strncmp(params->p_name, (char *)name, namelen) == 0 &&
3475
params->p_name[namelen] == 0) {
3476
*value = params->p_value;
3485
put_param_string(gs_param_list* plist,
3486
const byte* pname, gs_param_string* pstring,
3487
const stringParamDescription* params, int *pvalue, int code)
3492
if ((ncode = param_read_string(plist, (char *)pname, pstring)) < 0) {
3493
param_signal_error(plist, (char *)pname, code = ncode);
3494
} else if (ncode == 1) {
3495
pstring->data = 0, pstring->size = 0;
3499
if (paramStringValue(params, pstring->data, pstring->size,
3501
param_signal_error(plist, (char *)pname, code = gs_error_rangecheck);
3511
get_param_string(gs_param_list* plist,
3512
const byte* pname, gs_param_string* pstring,
3513
const stringParamDescription* params, int pvalue, bool persist, int code)
3518
pstring->data = paramValueToString(params, pvalue);
3520
if (pstring->data == (byte*) 0) {
3521
param_signal_error(plist, (char *)pname, ncode = gs_error_unknownerror);
3523
pstring->size = strlen((char *)pstring->data);
3524
pstring->persistent = persist;
3527
if ((ncode = param_write_string(plist, (char *)pname, pstring)) < 0) {
3535
* This taken from gsdparam.c. I hope it will be useable directly some day.
3540
cdj_param_check_bytes(gs_param_list *plist, gs_param_name pname,
3541
const byte *str, uint size, bool is_defined)
3543
gs_param_string new_value;
3544
switch ( code = param_read_string(plist, pname, &new_value) )
3547
if ( is_defined && new_value.size == size &&
3548
!memcmp((const char *)str, (const char *)new_value.data,
3552
code = gs_note_error(gs_error_rangecheck);
3555
if ( param_read_null(plist, pname) == 0 )
3557
e: param_signal_error(plist, pname, code);
3564
/* This is original code. */
3567
cdj_param_check_float(gs_param_list *plist, gs_param_name pname, floatp fval,
3571
switch ( code = param_read_float(plist, pname, &new_value) )
3574
if ( is_defined && new_value == (float)fval)
3576
code = gs_note_error(gs_error_rangecheck);
3579
if ( param_read_null(plist, pname) == 0 )
3581
e: param_signal_error(plist, pname, code);
3588
/* The following dithering algorithm has been kindly given to me (YA) by
3589
* Klaus-Gunther Hess, I just adapted it for use with the code here. */
3595
Just about the features of the code:
3597
- Stored Color-Values are BYTES in the order C-M-Y-K.
3598
(Indices need to change with gdevcdj.c)
3600
- There are individual THRESHOLDs and SPOTSIZEs for
3601
the color-components. The following relation should
3603
SPOTSIZE = 2 * THRESHOLD + 1
3604
(The internal calculation is dedicated for limiting
3605
ink-density at the 720x720DpI-Resolution of the
3606
Epson-Printers, without loss of dynamic color-range)
3608
- In addition to that there are EMIN & EMAX-Values
3609
for the components. The Values are computed from
3610
the dithering-algorithm and can be replaced by
3611
constants, if neither the implementation nor
3612
THRESHOLD and SPOTSIZE can change.
3614
- The algorithm is tuned for speed. (K-only, if gray-
3615
levels are detected, with EMIN/EMAX-clipping of
3616
stored CMY-Errors. [Notice: cerr, merr, yerr are
3617
*not* reset to zero! Clearing them would cause
3618
regular patterns & "Halos" to appear!])
3623
* Macros, that represent the undisturbed dithering-algorithm
3625
* FSerror: compute the desired Value
3626
* FSdecide: decision based on the value computed by FSerror
3627
* FSdiffuse: distribute remaining error among pixels
3630
#define FSerror(Val,Erow,Ecol) (Val + Erow + ((7 * Ecol)>>4))
3632
#define FSdecide(Error,Threshold,Spotsize,Pixel,Bit) \
3633
if(Error > Threshold) {\
3638
#define FSdiffuse(Error,Erow,Ecol,Eprev)\
3639
Eprev += (3 * Error + 8)>>4;\
3640
Erow = (5 * Error + Ecol + 8)>>4;\
3644
* some aliases for values from the device-structure
3646
#define DIRECTION direction[0]
3647
#define CMYK_THRESHOLD(I) threshold[I]
3648
#define SPOTSIZE(I) spotsize[I]
3649
#define EMIN(I) emin[I]
3650
#define EMAX(I) emax[I]
3651
#define NPIXEL (plane_size * 8)
3664
bjc_fscmyk(byte** inplanes, byte* outplanes[4][4], int** errplanes,
3665
int plane_size, int scan) {
3667
byte* err = (byte*) errplanes[0];
3669
/* =========================================================== */
3670
if(scan < 0) { /* scan < 0 -> initialize private buffer */
3671
/* =========================================================== */
3674
int *direction,*threshold,*spotsize,*emin,*emax;
3677
* allocate the error-buffer
3680
i = 4 * (5 + 1 + 1 + sd->stc.prt_pixels + 1) * sizeof(errv[0]);
3681
if((sd->stc.err_size < i) || (NULL == sd->stc.err)) {
3682
if(NULL != sd->stc.err)
3683
gs_free(sd->stc.err,sd->stc.err_size,1,"stcm/err");
3684
sd->stc.err_size = i;
3685
sd->stc.err = gs_malloc(sd->stc.err_size,1,"stcm/err");
3686
if(sd->stc.err == NULL) return_error(gs_error_VMerror);
3690
direction = (int *) err;
3691
threshold = direction + 4;
3692
spotsize = threshold + 4;
3693
emin = spotsize + 4;
3698
* compute initial values
3701
for(i = 0; i < 4; ++i) {
3705
if((sd->stc.xfer[i].size < 1) || (sd->stc.xfer[i].data == NULL)) {
3709
for(j = 0; j < sd->stc.xfer[i].size; ++j)
3710
if(maxv < sd->stc.xfer[i].data[j])
3711
maxv = sd->stc.xfer[i].data[j];
3714
CMYK_THRESHOLD(i) = (int)(127.0 / maxv + 0.5);
3715
SPOTSIZE(i) = ((int) CMYK_THRESHOLD(i)<<1)+1;
3716
j = CMYK_THRESHOLD(i); /* Maximum Error-Value */
3718
FSdiffuse(CMYK_THRESHOLD(i),errv[0],errc[0],errv[-4]);
3719
FSdiffuse(CMYK_THRESHOLD(i),errv[0],errc[0],errv[-4]);
3722
FSdiffuse((-CMYK_THRESHOLD(i)),errv[0],errc[0],errv[-4]);
3723
FSdiffuse((-CMYK_THRESHOLD(i)),errv[0],errc[0],errv[-4]);
3728
for(i = 0; i < 4; ++i) errprintf_nomem(
3729
"CMYK_THRESHOLD(%d)=%5d, spotsize(%d)=%5d, emin(%d)=%5d, emax(%d)=%5d\n",
3730
i,CMYK_THRESHOLD(i),i,SPOTSIZE(i),i,EMIN(i),i,EMAX(i));
3733
for(i = 0; i < 4; ++i) errc[i] = 0;
3735
for(p = 0; p < NPIXEL; ++p) {
3736
for(i = 0; i < 4; ++i) {
3738
if(sd->stc.flags & STCDFLAG0) v = 0;
3740
if (0) v = 0; /* Must provide a default for that. */
3741
else v = (rand() % SPOTSIZE(i)) - CMYK_THRESHOLD(i);
3742
FSdiffuse(v,errv[i],errc[i],errv[i-4]);
3747
/* =========================================================== */
3748
} else { /* scan >= 0 -> scanline-processing */
3749
/* =========================================================== */
3752
byte *out[4],pixel[4],bit;
3754
int *width = outplanes[scan];
3756
int *direction = (int *) err;
3757
int *threshold = direction + 4;
3758
int *spotsize = threshold + 4;
3759
int *emin = spotsize + 4;
3760
int *emax = emin + 4;
3761
int *errc = emax + 4;
3762
int *errv = errc + 2*4;
3763
int kerr,cerr,merr,yerr;
3768
if(sd->stc.flags & STCDFLAG1) {
3770
if (0) { /* Eventually will provide a flag for this. */
3771
cerr = merr = yerr = kerr = 0;
3779
out[0] = outplanes[scan + 2][ODX_C];
3780
out[1] = outplanes[scan + 2][ODX_M];
3781
out[2] = outplanes[scan + 2][ODX_Y];
3782
out[3] = outplanes[scan + 2][ODX_K];
3783
pixel[0] = pixel[1] = pixel[2] = pixel[3] = 0;
3785
if(DIRECTION < 0) { /* scan == 0, run backward */
3787
in = inplanes[2] + 4 * (NPIXEL - 1);
3791
if(w > 8) for(p = 0; p < 4; ++p) out[p] += (w-1)>>3;
3794
for (p = 0; p < 4; ++p) {
3795
out[p] += plane_size - 1;
3797
} else { /* run forward */
3799
in = inplanes[3] - 4 * NPIXEL;
3802
for (p = 0; p < 4; ++p) {
3803
out[p] -= plane_size;
3805
} /* run backward/forward */
3808
if(0 == (sd->stc.flags & STCDFLAG1)) DIRECTION = -DIRECTION;
3810
if (1) DIRECTION = -DIRECTION; /* Scan in other direction. */
3812
bit = 0x80>>((w-1) & 7);
3815
for(p = NPIXEL; p; --p) { /* loop over pixels */
3817
int cmy = in[IDX_C] | in[IDX_M] | in[IDX_Y];
3818
int kv = FSerror(in[IDX_K],errv[3],kerr);
3821
FSdecide(kv,CMYK_THRESHOLD(3),SPOTSIZE(3),pixel[3],bit);
3825
if(pixel[3] & bit) { /* black known to fire */
3827
FSdiffuse(kv,errv[3],kerr,errv[3-dir]);
3829
cv = FSerror(in[IDX_C],errv[0],cerr);
3831
if ((cv+CMYK_THRESHOLD(0)) < 0) cv = -CMYK_THRESHOLD(0);
3832
FSdiffuse(cv,errv[0],cerr,errv[0-dir]);
3834
cv = FSerror(in[IDX_M],errv[1],merr);
3836
if ((cv+CMYK_THRESHOLD(1)) < 0) cv = -CMYK_THRESHOLD(1);
3838
FSdiffuse(cv,errv[1],merr,errv[1-dir]);
3840
cv = FSerror(in[IDX_Y],errv[2],yerr);
3842
if ((cv+CMYK_THRESHOLD(2)) < 0) cv = -CMYK_THRESHOLD(2);
3843
FSdiffuse(cv,errv[2],yerr,errv[2-dir]);
3847
cv = FSerror(in[IDX_C],errv[0],cerr);
3848
FSdecide(cv,CMYK_THRESHOLD(0),SPOTSIZE(0),pixel[0],bit);
3849
FSdiffuse(cv,errv[0],cerr,errv[0-dir]);
3851
cv = FSerror(in[IDX_M],errv[1],merr);
3852
FSdecide(cv,CMYK_THRESHOLD(1),SPOTSIZE(1),pixel[1],bit);
3853
FSdiffuse(cv,errv[1],merr,errv[1-dir]);
3855
cv = FSerror(in[IDX_Y],errv[2],yerr);
3856
FSdecide(cv,CMYK_THRESHOLD(2),SPOTSIZE(2),pixel[2],bit);
3857
FSdiffuse(cv,errv[2],yerr,errv[2-dir]);
3859
if(pixel[0] & pixel[1] & pixel[2] & bit) {
3865
if ((kv+CMYK_THRESHOLD(3)) < 0) kv = -CMYK_THRESHOLD(0);
3866
FSdiffuse(kv,errv[3],kerr,errv[3-dir]);
3872
FSdiffuse(kv,errv[3],kerr,errv[3-dir]);
3874
if( errv[0] > EMAX(0)) errv[0] = EMAX(0);
3875
else if(errv[0] < EMIN(0)) errv[0] = EMIN(0);
3877
if( errv[1] > EMAX(1)) errv[1] = EMAX(1);
3878
else if(errv[1] < EMIN(1)) errv[1] = EMIN(1);
3880
if( errv[2] > EMAX(2)) errv[2] = EMAX(2);
3881
else if(errv[2] < EMIN(2)) errv[2] = EMIN(2);
3888
bit = dir > 0 ? (bit>>1) : (bit<<1);
3891
if(((*out[0] = pixel[0]) != 0) && (width[0] < w)) width[0] = w;
3892
if(((*out[1] = pixel[1]) != 0) && (width[1] < w)) width[1] = w;
3893
if(((*out[2] = pixel[2]) != 0) && (width[2] < w)) width[2] = w;
3894
if(((*out[3] = pixel[3]) != 0) && (width[3] < w)) width[3] = w;
3900
out[0] += thedir; out[1] += thedir;
3901
out[2] += thedir; out[3] += thedir;
3902
pixel[0] = pixel[1] = pixel[2] = pixel[3] = 0;
3904
if(dir > 0) bit = 0x80;
3911
} /* loop over pixels */
3914
if(0 == (sd->stc.flags & STCDFLAG1)) {
3917
cerr = errc[0] = cerr;
3918
merr = errc[1] = merr;
3919
yerr = errc[2] = yerr;
3920
kerr = errc[3] = kerr;
3923
/* =========================================================== */
3924
} /* initialization or scanline-Processing */
3925
/* =========================================================== */