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