~ubuntu-branches/ubuntu/vivid/ghostscript/vivid-security

« back to all changes in this revision

Viewing changes to base/gdevcdj.c

  • Committer: Package Import Robot
  • Author(s): Till Kamppeter
  • Date: 2013-08-09 20:01:36 UTC
  • mfrom: (1.1.37)
  • Revision ID: package-import@ubuntu.com-20130809200136-amb6zrr7hnjb5jq9
Tags: 9.08~rc1~dfsg-0ubuntu1
* New upstream release
   - Ghostscript 9.08rc1.
   - We are using the system's liblcms2 and libopenjpeg now.
* debian/patches/020130401-852e545-pxl-xl-driver-produced-drawing-commands-without-setting-color-space.patch:
  Removed patch backported from upstream.
* debian/patches/ojdk-8007925+8007926.patch,
  debian/patches/ojdk-8007927.patch,
  debian/patches/ojdk-8007929.patch,
  debian/patches/ojdk-8009654.patch: Removed patches on build in liblcms2, we
  use the system's liblcms2 now.
* debian/patches/2001_docdir_fix_for_debian.patch: Manually updated to new
  upstream source code.
* debian/patches/2003_support_multiarch.patch: Refreshed with quilt.
* debian/control: Added build dependencies on liblcms2-dev and
  libopenjpeg-dev.
* debian/rules: Check for removed lcms2/ and openjpeg/ subdirectories in
  the repackaging check again, also set build options for shared liblcms2
  and libopenjpeg libraries.
* debian/rules: Makefile.in and configure.ac are in the root directory of
  the source now and do not need to get linked from base/. Also there is no
  gstoraster and gstopxl CUPS filter in the package any more and no
  "install-cups" make target any more.
* debian/control, debian/rules, debian/ghostscript-cups.install,
  debian/ghostscript-cups.ppd-updater: Removed the ghostscript-cups binary
  package. The files are now provided by cups-filters.
* debian/symbols.common: Updated for new upstream source. Applied patch
  which dpkg-gensymbols generated for debian/libgs9.symbols to this file.

Show diffs side-by-side

added added

removed removed

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