1 /* Copyright (C) 1991, 1992, 1993 Aladdin Enterprises.  All rights reserved.
2 
3 This file is part of Ghostscript.
4 
5 Ghostscript is distributed in the hope that it will be useful, but
6 WITHOUT ANY WARRANTY.  No author or distributor accepts responsibility
7 to anyone for the consequences of using it or for whether it serves any
8 particular purpose or works at all, unless he says so in writing.  Refer
9 to the Ghostscript General Public License for full details.
10 
11 Everyone is granted permission to copy, modify and redistribute
12 Ghostscript, but only under the conditions described in the Ghostscript
13 General Public License.  A copy of this license is supposed to have been
14 given to you along with Ghostscript so you can know your rights and
15 responsibilities.  It should be in a file named COPYING.  Among other
16 things, the copyright notice and this notice must be preserved on all
17 copies.  */
18 
19 /* gdevmjc.c */
20 /* Many parts of this file are copied from gdevcdj.c and gdevescp.c */
21 
22 /* EPSON MJ-700V2C colour printer drivers for Ghostscript */
23 
24 /*
25    These drivers may also work with EPSON Stylus color printer,
26    though the author hasn't tried.
27 */
28 
29 /*
30    Any comments, suggestions, and bug reports are welcomed.
31    The e-mail address of the author Kubo, Hiroshi is
32 
33    h-kubo@kuee.kyoto-u.ac.jp
34 
35            or
36 
37    JBD02172@niftyserve.or.jp
38 
39 */
40 
41 /*
42 
43   Modified by Norihito Ohmori.
44    Support -r / -dBitsPerPixel  option.
45    Change -dMicroweave / -dUnidirectional option.
46 
47  */
48 
49 #include "std.h"                /* to stop stdlib.h redefining types */
50 #include <stdlib.h>		/* for rand() */
51 #include <limits.h>
52 #include "gdevprn.h"
53 #include "gdevpcl.h"
54 #include "gdevmjc.h"
55 
56 #ifndef __WORDSIZE
57 #ifdef __DragonFly__
58 #define __WORDSIZE	64
59 #endif
60 #endif
61 
62 /***
63  *** Note: Original driver gdevcdj.c for HP color printer was written
64  ***       by a user,  George Cameron.
65  ***
66  ***       An idea of Kuniyoshi Yoshio to borrow the codes of gdevcdj.c
67  ***       for another color printer BJC-600J inspired the author.
68  ***
69  ***       Basic control sequences and compression algorithm for ESC/P
70  ***       V2 printer are taken from gdevescp.c, written by Richard Brown.
71  ***
72  ***       The author Kubo, Hiroshi gathered necessary codes for EPSON
73  ***       MJ-700V2C and Sylus color printer in gdevmjc.c.
74  ***/
75 
76 /*
77   available drivers
78 
79   1. mj700v2c         EPSON Mach Jet Color, for ALL CMYK printer
80 
81   2. mj500c           EPSON Mach Jet Color,
82                        CMY or K printer: MJ-500C, MJ-510C,
83                        CMY + K printer:  MJ-800C (for plane paper),
84                                          MJ-3000C (for plane paper)
85   3. mj6000c          EPSON MJ-830C, MJ-930C, MJ-6000C
86                        Use "High Performance Monochrome Mode"
87   4. mj8000c          EPSON MJ-8000C
88                        Use "High Performance Monochrome Mode"
89                        A2 Paper Size Margin is different from mj6000c
90 */
91 
92 /*
93  **  Options  **
94  *
95  name		type	description
96 
97  Density	int	Controls densty of dots. 1024 is normal setting
98                         for 360dpi.
99  Cyan		int	Controls depth of Cyan. 1024 is normal setting.
100  Magenta	int	Controls depth of Magenta. 1024 is normal setting.
101  Yellow		int	Controls depth of Yellow. 1024 is normal setting.
102  Black		int	Controls depth of Black. 1024 is normal setting.
103  Unidirectional	bool	if true, Force unidirectional printing.
104  Microweave	bool	if true, set micro weave mode.
105  DotSize	int	Controls the size of the dots. 0 means default,
106                         1 means small, 2 means normal.
107 
108  **   Examples   **
109 
110  % gs -sDEVICE=mj700v2c -sOutputFile=tiger.mj gdevmjc.ps tiger.ps
111 
112  % gs -sDEVICE=mj700v2c -dDensity=1152 -dCyan=1000 -dMagenta=896 \
113    -dYellow=1024 -dBlack=512 -dUnidirectional -sOutputFile=tiger.mj \
114    gdevmjc.ps tiger.ps
115 
116  */
117 
118 #define MJ700V2C_PRINT_LIMIT 0.34       /* taken from gdevescp.c */
119 
120 /* Margins are left, bottom, right, top. */
121 /* left bottom right top */
122 #define MJ700V2C_MARGINS_A4     0.118f, 0.52f, 0.118f, 0.33465f
123 #define MJ6000C_MARGINS_A2      0.948f, 0.52f, 1.969f, 0.33465f
124 #define MJ8000C_MARGINS_A2      0.194f, 0.52f, 0.194f, 0.33465f
125 
126 /* Define bits-per-pixel for generic drivers - default is 24-bit mode */
127 #ifndef BITSPERPIXEL
128 #define BITSPERPIXEL 32
129 #endif
130 
131 #define W sizeof(word)
132 #define I sizeof(int)
133 
134 /* Printer types */
135 #define MJ700V2C 1
136 #define MJ500C 2
137 #define MJ6000C 3
138 #define MJ8000C 4
139 
140 /* No. of ink jets (used to minimise head movements) */
141 #define HEAD_ROWS_MONO 50
142 #define HEAD_ROWS_COLOUR 16
143 /* only for mj700v2c */
144 #define MJ_HEAD_ROWS_MONO 64
145 #define MJ_HEAD_ROWS_COLOUR 16
146 
147 /* Colour mapping procedures */
148 static dev_proc_map_rgb_color (gdev_mjc_map_rgb_color);
149 static dev_proc_map_color_rgb (gdev_mjc_map_color_rgb);
150 static dev_proc_encode_color(gdev_mjc_encode_color);
151 static dev_proc_decode_color(gdev_mjc_decode_color);
152 
153 /* Print-page, properties and miscellaneous procedures */
154 static dev_proc_open_device(mj700v2c_open);
155 static dev_proc_open_device(mj500c_open);
156 static dev_proc_open_device(mj6000c_open);
157 static dev_proc_open_device(mj8000c_open);
158 static dev_proc_print_page(mj700v2c_print_page);
159 static dev_proc_print_page(mj500c_print_page);
160 static dev_proc_print_page(mj6000c_print_page);
161 static dev_proc_print_page(mj8000c_print_page);
162 
163 static dev_proc_get_params(mj_get_params);
164 static dev_proc_put_params(mj700v2c_put_params);
165 static dev_proc_put_params(mj500c_put_params);
166 
167 static int mj_open(gx_device * pdev, int ptype);
168 static int mj_put_params(gx_device * pdev, gs_param_list * plist, int ptype);
169 static int mj_print_page(gx_device_printer * pdev, gp_file * prn_stream, int ptype);
170 static void expand_line(word *, int, int, int);
171 static int put_param_int(gs_param_list *, gs_param_name, int *, int, int, int);
172 static void set_bpp(gx_device *, int);
173 static void mj500c_set_bpp(gx_device *, int);
174 static gx_color_index mjc_correct_color(gx_device_printer *, gx_color_index);
175 
176 /* The device descriptors */
177 struct gx_device_mj_s {
178         gx_device_common;
179         gx_prn_device_common;
180         int colorcomp;    /* 1: grayscale 3: CMY 4: CMYK */
181         int density;	/* (color depth) * density/1024  = otuput */
182         int cyan;       /* weight for cyan */
183         int magenta;     /* weight for magenta */
184         int yellow;      /* weight for yellow */
185         int black;      /* weight for black */
186         bool direction;   /* direction of the head. 1: one way 2: both way */
187         bool microweave;  /* Micro weave switch. 0: off 1: on */
188         int dotsize;      /* dot size switch.
189                             0: default, 1: small, 2: normal */
190 };
191 
192 typedef struct gx_device_mj_s gx_device_mj;
193 
194 #define mj    ((gx_device_mj *) pdev)
195 
196 #define prn_hp_colour_device(procs, dev_name, x_dpi, y_dpi, bpp, print_page)\
197     prn_device_body(gx_device_mj, procs, dev_name,\
198     DEFAULT_WIDTH_10THS, DEFAULT_HEIGHT_10THS, x_dpi, y_dpi,\
199     0.118, 0.52, 0.118, 0.33465,\
200     (bpp == 32 ? 4 : (bpp == 1 || bpp == 8) ? 1 : 3), bpp,\
201     (bpp >= 8 ? 255 : 1), (bpp >= 8 ? 255 : bpp > 1 ? 1 : 0),\
202     (bpp >= 8 ? 5 : 2), (bpp >= 8 ? 5 : bpp > 1 ? 2 : 0),\
203     print_page)
204 
205 #define mjcmyk_device(procs, dev_name, x_dpi, y_dpi, bpp, print_page,\
206                   dns, r, g, b, k, drct, mcrwv, dtsz)\
207 { prn_hp_colour_device(procs, dev_name, x_dpi, y_dpi, bpp, print_page),\
208          (bpp == 32 ? 4 : 1), dns, r, g, b, k, drct, mcrwv, dtsz \
209 }
210 
211 #define mjcmy_device(procs, dev_name, x_dpi, y_dpi, bpp, print_page,\
212                   dns, r, g, b, k, drct, mcrwv, dtsz)\
213 { prn_hp_colour_device(procs, dev_name, x_dpi, y_dpi, bpp, print_page),\
214          (bpp == 32 ? 3 : 1), dns, r, g, b, k, drct, mcrwv, dtsz \
215 }
216 
217 #define mj_colour_procs(proc_colour_open, proc_get_params, proc_put_params)\
218 {	proc_colour_open,\
219         gx_default_get_initial_matrix,\
220         gx_default_sync_output,\
221         gdev_prn_output_page,\
222         gdev_prn_close,\
223         gdev_mjc_map_rgb_color,\
224         gdev_mjc_map_color_rgb,\
225         NULL,	/* fill_rectangle */\
226         NULL,	/* tile_rectangle */\
227         NULL,	/* copy_mono */\
228         NULL,	/* copy_color */\
229         NULL,	/* draw_line */\
230         gx_default_get_bits,\
231         proc_get_params,\
232         proc_put_params,\
233         NULL,	/* map_cmyk_color */\
234         NULL,	/* get_xfont_procs */\
235         NULL,	/* get_xfont_device */\
236         NULL,	/* map_rgb_alpha_color */\
237         NULL,   /* get_page_device */\
238         NULL,	/* get_alpha_bits */\
239         NULL,   /* copy_alpha */\
240         NULL,	/* get_band */\
241         NULL,	/* copy_rop */\
242         NULL,	/* fill_path */\
243         NULL,	/* stroke_path */\
244         NULL,	/* fill_mask */\
245         NULL,	/* fill_trapezoid */\
246         NULL,	/* fill_parallelogram */\
247         NULL,	/* fill_triangle */\
248         NULL,	/* draw_thin_line */\
249         NULL,	/* begin_image */\
250         NULL,	/* image_data */\
251         NULL,	/* end_image */\
252         NULL,	/* strip_tile_rectangle */\
253         NULL,	/* strip_copy_rop, */\
254         NULL,	/* get_clipping_box */\
255         NULL,	/* begin_typed_image */\
256         NULL,	/* get_bits_rectangle */\
257         NULL,	/* map_color_rgb_alpha */\
258         NULL,	/* create_compositor */\
259         NULL,	/* get_hardware_params */\
260         NULL,	/* text_begin */\
261         NULL,	/* finish_copydevice */\
262         NULL, 	/* begin_transparency_group */\
263         NULL, 	/* end_transparency_group */\
264         NULL, 	/* begin_transparency_mask */\
265         NULL, 	/* end_transparency_mask */\
266         NULL, 	/* discard_transparency_layer */\
267         NULL,   /* get_color_mapping_procs */\
268         NULL,   /* get_color_comp_index */\
269         gdev_mjc_encode_color,\
270         gdev_mjc_decode_color\
271 }
272 
273 static gx_device_procs mj700v2c_procs =
274 mj_colour_procs(mj700v2c_open, mj_get_params, mj700v2c_put_params);
275 
276 static gx_device_procs mj500c_procs =
277 mj_colour_procs(mj500c_open, mj_get_params, mj500c_put_params);
278 
279 static gx_device_procs mj6000c_procs =
280 mj_colour_procs(mj6000c_open, mj_get_params, mj700v2c_put_params);
281 
282 static gx_device_procs mj8000c_procs =
283 mj_colour_procs(mj8000c_open, mj_get_params, mj700v2c_put_params);
284 
285 gx_device_mj far_data gs_mj700v2c_device =
286 mjcmyk_device(mj700v2c_procs, "mj700v2c", 360, 360, BITSPERPIXEL,
287           mj700v2c_print_page, 1024, 1024, 1024, 1024, 1024, 0, 1, 1);
288 
289 gx_device_mj far_data gs_mj500c_device =
290 mjcmy_device(mj500c_procs, "mj500c", 360, 360, BITSPERPIXEL,
291           mj500c_print_page, 1024, 1024, 1024, 1024, 1024, 0, 1, 1);
292 
293 gx_device_mj far_data gs_mj6000c_device =
294 mjcmyk_device(mj6000c_procs, "mj6000c", 360, 360, BITSPERPIXEL,
295           mj6000c_print_page, 1024, 1024, 1024, 1024, 1024, 0, 1, 1);
296 
297 gx_device_mj far_data gs_mj8000c_device =
298 mjcmyk_device(mj8000c_procs, "mj8000c", 360, 360, BITSPERPIXEL,
299           mj8000c_print_page, 1024, 1024, 1024, 1024, 1024, 0, 1, 1);
300 
301 /* Get the paper size code, based on width and height. */
302 static int
gdev_mjc_paper_size(gx_device * dev)303 gdev_mjc_paper_size(gx_device *dev)
304 {
305   int width = (int)dev->MediaSize[0];
306   int height = (int)dev->MediaSize[1];
307 
308   if (width == 1190 && height == 1684)
309     return PAPER_SIZE_A2;
310   else
311     return PAPER_SIZE_A4;
312 }
313 
314 static int
mj700v2c_open(gx_device * pdev)315 mj700v2c_open(gx_device * pdev)
316 {
317   return mj_open(pdev, MJ700V2C);
318 }
319 
320 static int
mj500c_open(gx_device * pdev)321 mj500c_open(gx_device * pdev)
322 {
323   return mj_open(pdev, MJ700V2C);
324 }
325 
326 static int
mj6000c_open(gx_device * pdev)327 mj6000c_open(gx_device * pdev)
328 {
329   return mj_open(pdev, MJ700V2C);
330 }
331 
332 static int
mj8000c_open(gx_device * pdev)333 mj8000c_open(gx_device * pdev)
334 {
335   return mj_open(pdev, MJ700V2C);
336 }
337 
338 /* Open the printer and set up the margins. */
339 static int
mj_open(gx_device * pdev,int ptype)340 mj_open(gx_device *pdev, int ptype)
341 {       /* Change the margins if necessary. */
342   int xdpi = (int)pdev->x_pixels_per_inch;
343   int ydpi = (int)pdev->y_pixels_per_inch;
344 
345   static const float mj_margin[4] = { MJ700V2C_MARGINS_A4 };
346   static const float mj6000c_a2[4] = { MJ6000C_MARGINS_A2 };
347   static const float mj8000c_a2[4] = { MJ8000C_MARGINS_A2 };
348 
349   const float *m;
350 
351   int paper_size;
352 
353 #if 0
354   /* Set up colour params if put_props has not already done so */
355   if (pdev->color_info.num_components == 0)
356     set_bpp(pdev, pdev->color_info.depth);
357 #endif
358 
359   paper_size = gdev_mjc_paper_size(pdev);
360   if (paper_size == PAPER_SIZE_A2 ) {
361     if (ptype == MJ6000C)
362       m = mj6000c_a2;
363     else if (ptype == MJ8000C)
364       m = mj8000c_a2;
365     else
366       m = mj_margin;
367   } else {
368     m = mj_margin;
369   }
370 
371   gx_device_set_margins(pdev, m, true);
372 
373   if (mj->colorcomp == 3)
374     mj->density = (int)(mj->density * 720 / ydpi) * 1.5;
375   else
376     mj->density = mj->density * 720 / ydpi;
377 
378   /* Print Resolution Check */
379   if (!((xdpi == 180 && ydpi == 180) ||
380       (xdpi == 360 && ydpi == 360) ||
381       (xdpi == 720 && ydpi == 720) ||
382       (xdpi == 360 && ydpi == 720) ||
383       (xdpi == 720 && ydpi == 360)))
384     return_error(gs_error_rangecheck);
385 
386   return gdev_prn_open(pdev);
387 }
388 
389 /* Get properties.  In addition to the standard and printer
390  * properties, we supply shingling and depletion parameters,
391  * and control over the bits-per-pixel used in output rendering */
392 /* Added properties for DeskJet 5xxC */
393 
394 static int
mj_get_params(gx_device * pdev,gs_param_list * plist)395 mj_get_params(gx_device *pdev, gs_param_list *plist)
396 {
397         int code = gdev_prn_get_params(pdev, plist);
398 
399         if ( code < 0 ||
400             (code = param_write_int(plist, "Density", &mj->density)) < 0 ||
401             (code = param_write_int(plist, "Cyan", &mj->cyan)) < 0 ||
402             (code = param_write_int(plist, "Magenta", &mj->magenta)) < 0 ||
403             (code = param_write_int(plist, "Yellow", &mj->yellow)) < 0 ||
404             (code = param_write_int(plist, "Black", &mj->black)) < 0 ||
405             (code = param_write_bool(plist, "Unidirectional", &mj->direction)) < 0 ||
406             (code = param_write_bool(plist, "Microweave", &mj->microweave)) < 0 ||
407             (code = param_write_int(plist, "DotSize", &mj->dotsize)) < 0
408            )
409           return code;
410 
411         return code;
412 }
413 
414 /* Put properties. */
415 static int
mj700v2c_put_params(gx_device * pdev,gs_param_list * plist)416 mj700v2c_put_params(gx_device *pdev, gs_param_list *plist)
417 {
418   return mj_put_params(pdev, plist, MJ700V2C);
419 }
420 
421 static int
mj500c_put_params(gx_device * pdev,gs_param_list * plist)422 mj500c_put_params(gx_device *pdev, gs_param_list *plist)
423 {
424   return mj_put_params(pdev, plist, MJ500C);
425 }
426 
427 static int
mj_put_params(gx_device * pdev,gs_param_list * plist,int ptype)428 mj_put_params(gx_device *pdev,  gs_param_list *plist, int ptype)
429 {
430         int old_bpp = mj->color_info.depth;
431         int bpp = 0;
432         int code = 0;
433         int density = mj->density;
434         int cyan = mj->cyan;
435         int magenta = mj->magenta;
436         int yellow = mj->yellow;
437         int black = mj->black;
438         bool direction = mj->direction;
439         bool microweave = mj->microweave;
440         int dotsize = mj->dotsize;
441         gs_param_name param_name;
442         int ecode = 0;
443 
444         code = put_param_int(plist, "Density", &density, 0, INT_MAX, code);
445         code = put_param_int(plist, "Cyan", &cyan, 0, INT_MAX, code);
446         code = put_param_int(plist, "Magenta", &magenta, 0, INT_MAX, code);
447         code = put_param_int(plist, "Yellow", &yellow, 0, INT_MAX, code);
448         code = put_param_int(plist, "Black", &black, 0, INT_MAX, code);
449         (void) code;
450 
451         if ((code = param_read_bool(plist,
452                                      (param_name = "Unidirectional"),
453                                      &direction))< 0) {
454           param_signal_error(plist, param_name, ecode = code);
455         }
456 
457         if ((code = param_read_bool(plist,
458                                      (param_name = "Microweave"),
459                                      &microweave))< 0) {
460           param_signal_error(plist, param_name, ecode = code);
461         }
462         if (ecode < 0)
463           return code;
464 
465         if (microweave && pdev->x_pixels_per_inch == 180)
466             return_error(gs_error_rangecheck);
467 
468         code = put_param_int(plist, "DotSize", &dotsize, 0, 1, code);
469         code = put_param_int(plist, "BitsPerPixel", &bpp, 1, 32, code);
470 
471         if ( code < 0 )
472           return code;
473 
474         mj->density = density;
475         mj->cyan = cyan;
476         mj->magenta = magenta;
477         mj->yellow = yellow;
478         mj->black = black;
479         mj->direction = direction;
480         mj->microweave = microweave;
481         mj->dotsize = dotsize;
482 
483         if ( bpp != 0 ) {
484           if (bpp != 8 && bpp != 32)
485             return_error(gs_error_rangecheck);
486 
487           if (ptype == MJ500C)
488             mj500c_set_bpp(pdev, bpp);
489           else
490             set_bpp(pdev, bpp);
491           gdev_prn_put_params(pdev, plist);
492           if ( bpp != old_bpp && pdev->is_open )
493             return gs_closedevice(pdev);
494           return 0;
495         }
496         else
497           return gdev_prn_put_params(pdev, plist);
498 }
499 
500 /* ------ Internal routines ------ */
501 /* MACROS FOR DITHERING (we use macros for compact source and faster code) */
502 /* Floyd-Steinberg dithering. Often results in a dramatic improvement in
503  * subjective image quality, but can also produce dramatic increases in
504  * amount of printer data generated and actual printing time!! Mode 9 2D
505  * compression is still useful for fairly flat colour or blank areas but its
506  * compression is much less effective in areas where the dithering has
507  * effectively randomised the dot distribution. */
508 
509 #define SHIFT (I * I)
510 #define MINVALUE  0
511 #define MAXVALUE  ((256 << SHIFT) - 1)
512 #define THRESHOLD (128 << SHIFT)
513 
514 #define FSditherI(inP, out, errP, Err, Bit, Offset)\
515         oldErr = Err;\
516         Err = (*errP + ((Err * 7) >> 4) + (*inP++ << SHIFT));\
517         if (Err > MAXVALUE) Err = MAXVALUE;\
518         else if (Err < MINVALUE) Err = MINVALUE;\
519         if (Err > THRESHOLD) {\
520           out |= Bit;\
521           Err -= MAXVALUE;\
522         }\
523         errP[Offset] += ((Err * 3) >> 4);\
524         *errP++ = ((Err * 5 + oldErr) >> 4);
525 
526 #define FSditherD(inP, out, errP, Err, Bit, Offset)\
527         oldErr = Err;\
528         Err = (*--errP + ((Err * 7) >> 4) + (*--inP << SHIFT));\
529         if (Err > MAXVALUE) Err = MAXVALUE;\
530         else if (Err < MINVALUE) Err = MINVALUE;\
531         if (Err > THRESHOLD) {\
532           out |= Bit;\
533           Err -= MAXVALUE;\
534         }\
535         errP[Offset] += ((Err * 3) >> 4);\
536         *errP = ((Err * 5 + oldErr) >> 4);
537 
538 #define MATRIX_I(inP, out, Bit, Offset)\
539         if ((*inP++ << 6) > Offset) {\
540           out |= Bit;\
541         }
542 
543 #define MATRIX_D(inP, out, Bit, Offset)\
544         if ((*--inP << 6) > Offset) {\
545           out |= Bit;\
546         }
547 
548 /* Here we rely on compiler optimisation to remove lines of the form
549  * (if (1 >= 4) {...}, ie. the constant boolean expressions */
550 
551 #define FSDline(scan, i, j, plane_size, cErr, mErr, yErr, kErr, cP, mP, yP, kP, n)\
552 {\
553     unsigned short *mat = matrix2 + (lnum & 127)*128;\
554     int x;\
555     (void)cErr; /* Stop compiler warning */\
556     if (scan == 0) {       /* going_up */\
557       x = 0;\
558       for (i = 0; i < plane_size; i++) {\
559         byte c, y, m, k, bitmask;\
560         int val;\
561         bitmask = 0x80;\
562         for (c = m = y = k = j = 0; j < 8; j++) {\
563           val = *(mat + (x++ & 127));\
564           if (n >= 4)\
565             {\
566                          MATRIX_I(dp, k, bitmask, val);\
567             }\
568           if (n >= 3)\
569             { MATRIX_I(dp, c, bitmask, val);\
570               MATRIX_I(dp, m, bitmask, val);\
571             }\
572           MATRIX_I(dp, y, bitmask, val);\
573           bitmask >>= 1;\
574         }\
575         if (n >= 4)\
576           *kP++ = k;\
577         if (n >= 3)\
578           { *cP++ = c;\
579             *mP++ = m;\
580           }\
581             *yP++ = y;\
582       }\
583     } else {		/* going_down */\
584       x = plane_size*8;\
585       for (i = 0; i < plane_size; i++) {\
586         byte c, y, m, k, bitmask;\
587         int val;\
588         bitmask = 0x01;\
589         for (c = m = y = k = j = 0; j < 8; j++) {\
590           val = *(mat + (--x & 127));\
591           MATRIX_D(dp, y, bitmask, val);\
592           if (n >= 3)\
593             { MATRIX_D(dp, m, bitmask, val);\
594               MATRIX_D(dp, c, bitmask, val);\
595             }\
596           if (n >= 4)\
597             { MATRIX_D(dp, k, bitmask, val);\
598             }\
599           bitmask <<= 1;\
600         }\
601         *--yP = y;\
602         if (n >= 3)\
603           { *--mP = m;\
604             *--cP = c;\
605           }\
606         if (n >= 4)\
607           *--kP = k;\
608       }\
609     }\
610 }
611 /* END MACROS FOR DITHERING */
612 
613 /* Some convenient shorthand .. */
614 #define x_dpi        (pdev->x_pixels_per_inch)
615 #define y_dpi        (pdev->y_pixels_per_inch)
616 #define CONFIG_16BIT "\033*v6W\000\003\000\005\006\005"
617 #define CONFIG_24BIT "\033*v6W\000\003\000\010\010\010"
618 
619 /* To calculate buffer size as next greater multiple of both parameter and W */
620 #define calc_buffsize(a, b) (((((a) + ((b) * W) - 1) / ((b) * W))) * W)
621 
622 /*
623  * Miscellaneous functions for Canon BJC-600J printers in raster command mode.
624  */
625 #define fputshort(n, f) gp_fputc((n)%256,f);gp_fputc((n)/256,f)
626 
627 #define row_bytes (img_rows / 8)
628 #define row_words (row_bytes / sizeof(word))
629 #define min_rows (32)		/* for optimization of text image printing */
630 
631 static int
mj_raster_cmd(int c_id,int in_size,byte * in,byte * buf2,gx_device_printer * pdev,gp_file * prn_stream)632 mj_raster_cmd(int c_id, int in_size, byte* in, byte* buf2,
633               gx_device_printer* pdev, gp_file* prn_stream)
634 {
635   int band_size = 1;	/* 1, 8, or 24 */
636 
637   byte *out = buf2;
638 
639   int width = in_size;
640   int count;
641 
642   byte* in_end = in + in_size;
643 
644   static char colour_number[] = "\004\001\002\000"; /* color ID for MJ700V2C */
645 
646   byte *inp = in;
647   byte *outp = out;
648   register byte *p, *q;
649 
650   /* specifying a colour */
651 
652   gp_fputs("\033r",prn_stream); /* secape sequence to specify a color */
653   gp_fputc(colour_number[c_id], prn_stream);
654 
655   /* end of specifying a colour */
656 
657         /* Following codes for compression are borrowed from gdevescp.c */
658 
659   for( p = inp, q = inp + 1 ; q < in_end ; ) {
660 
661     if( *p != *q ) {
662       p += 2;
663       q += 2;
664     } else {
665 
666       /*
667        ** Check behind us, just in case:
668        */
669 
670       if( p > inp && *p == *(p-1) )
671            p--;
672 
673       /*
674        ** walk forward, looking for matches:
675        */
676 
677       for( q++ ; q < in_end && *q == *p ; q++ ) {
678         if( (q-p) >= 128 ) {
679           if( p > inp ) {
680             count = p - inp;
681             while( count > 128 ) {
682               *outp++ = '\177';
683               memcpy(outp, inp, 128);	/* data */
684               inp += 128;
685               outp += 128;
686               count -= 128;
687             }
688             *outp++ = (char) (count - 1); /* count */
689             memcpy(outp, inp, count);	/* data */
690             outp += count;
691           }
692           *outp++ = '\201';	/* Repeat 128 times */
693           *outp++ = *p;
694           p += 128;
695           inp = p;
696         }
697       }
698 
699       if( (q - p) > 2 ) {	/* output this sequence */
700         if( p > inp ) {
701           count = p - inp;
702           while( count > 128 ) {
703             *outp++ = '\177';
704             memcpy(outp, inp, 128);	/* data */
705             inp += 128;
706             outp += 128;
707             count -= 128;
708           }
709           *outp++ = (char) (count - 1);	/* byte count */
710           memcpy(outp, inp, count);	/* data */
711           outp += count;
712         }
713         count = q - p;
714         *outp++ = (char) (256 - count + 1);
715         *outp++ = *p;
716         p += count;
717         inp = p;
718       } else	/* add to non-repeating data list */
719            p = q;
720       if( q < in_end )
721            q++;
722     }
723   }
724 
725   /*
726    ** copy remaining part of line:
727    */
728 
729   if( inp < in_end ) {
730 
731     count = in_end - inp;
732 
733     /*
734      ** If we've had a long run of varying data followed by a
735      ** sequence of repeated data and then hit the end of line,
736      ** it's possible to get data counts > 128.
737      */
738 
739     while( count > 128 ) {
740       *outp++ = '\177';
741       memcpy(outp, inp, 128);	/* data */
742       inp += 128;
743       outp += 128;
744       count -= 128;
745     }
746 
747     *outp++ = (char) (count - 1);	/* byte count */
748     memcpy(outp, inp, count);	/* data */
749     outp += count;
750   }
751   /*
752    ** Output data:
753    */
754 
755   gp_fwrite("\033.\001", 1, 3, prn_stream);
756 
757   if(pdev->y_pixels_per_inch == 720)
758        gp_fputc('\005', prn_stream);
759   else if(pdev->y_pixels_per_inch == 180)
760        gp_fputc('\024', prn_stream);
761   else /* pdev->y_pixels_per_inch == 360 */
762        gp_fputc('\012', prn_stream);
763 
764   if(pdev->x_pixels_per_inch == 720)
765        gp_fputc('\005', prn_stream);
766   else if(pdev->x_pixels_per_inch == 180)
767        gp_fputc('\024', prn_stream);
768   else /* pdev->x_pixels_per_inch == 360 */
769        gp_fputc('\012', prn_stream);
770 
771   gp_fputc(band_size, prn_stream);
772 
773   gp_fputc((width << 3) & 0xff, prn_stream);
774   gp_fputc( width >> 5,	   prn_stream);
775 
776   gp_fwrite(out, 1, (outp - out), prn_stream);
777 
778   gp_fputc('\r', prn_stream);
779 
780   return 0;
781 }
782 
783 static int
mj_v_skip(int n,gx_device_printer * pdev,gp_file * stream)784 mj_v_skip(int n, gx_device_printer *pdev, gp_file *stream)
785 {
786         /* This is a kind of magic number. */
787   static const int max_y_step = (256 * 15 + 255);
788 
789   int l = n - max_y_step;
790   for (; l > 0; l -= max_y_step) {    /* move 256 * 15 + 255 dots at once*/
791     gp_fwrite("\033(v\2\0\xff\x0f", sizeof(byte), 7, stream);
792   }
793   l += max_y_step;
794   /* move to the end. */
795   {
796     int n2 = l / 256;
797     int n1 = l - n2 * 256;
798     gp_fwrite("\033(v\2\0", sizeof(byte) ,5 ,stream);
799     gp_fputc(n1, stream);
800     gp_fputc(n2, stream);
801     gp_fputc('\r', stream);
802   }
803   return 0;
804 }
805 
806 /* NOZ */
807 
808 static void
bld_barrier(short ** bar,int x)809 bld_barrier( short **bar , int x )
810 {
811         int i , j;
812 
813         short t;
814         short *p;
815         short *b;
816         short *dat = barrier_dat + 1;
817 
818         p = *bar++ + x + 1;
819 
820         for ( i = 0 ; i < 11 ; i++ ) {
821                 t = *dat++;
822                 if (*p < t )
823                         *p = t;
824                 p++;
825         }
826 
827         for ( j = 0 ; j < 11 ; j++ ) {
828                 p = *bar++ + x;
829                 b = p;
830 
831                 t = *dat++;
832                 if (*p < t )
833                         *p = t;
834                 p++;
835                 for ( i = 0 ; i < 11 ; i++ ) {
836                         t = *dat++;
837                         if (*p < t )
838                                 *p = t;
839                         p++;
840 
841                         if (*(--b) < t )
842                                 *b = t;
843                 }
844         }
845 }
846 
847 static void
DifSubK(int d0,short * a4,short * a5)848 DifSubK( int d0 , short *a4 , short *a5 )
849 {
850 /*
851                                 +---+---+---+
852                                 |   | X |1/2|
853                                 +---+---+---+
854                                 |1/4|1/8|1/8|
855                                 +---+---+---+
856 */
857         *a4++   =  0;
858         d0 >>= 1;
859         *a4     += d0;
860         d0 >>= 1;
861         *(a5-1) += d0;
862         d0 >>= 1;
863         *a5++   += d0;
864         *a5     += d0;
865 }
866 
867 /* a4.w , a5.w , */
868 static  byte
Xtal(byte bitmask,short d0,int x,short ** bar,short * b1,short * b2)869 Xtal( byte bitmask , short d0 , int x , short **bar , short *b1 , short *b2 )
870 {
871         short *a2;
872 
873         if (d0 != 0)
874                 d0 += *b1;
875 
876         a2 = *bar + x;
877 
878 /*dprintf1("[%02X]",*a2);*/
879         if (*a2 < d0) {
880                 d0 -= 16400;
881                 if (-4096 >= d0) {
882                         DifSubK( d0 , b1 , b2 );
883                         bld_barrier( bar , x );
884                 } else {
885                         DifSubK( d0 , b1 , b2 );
886                 }
887                 return( bitmask );
888         } else {
889                 if (d0 > 56)
890                         d0 -= 56;
891                 DifSubK( d0 , b1 , b2 );
892                 return( 0 );
893         }
894 }
895 
896 static void
xtal_plane(byte * dp,short * buf[],byte * oP,short ** bar,int plane_size,int xtalbuff_size)897 xtal_plane( byte *dp , short *buf[] , byte *oP , short **bar , int plane_size , int xtalbuff_size )
898 {
899         int i;
900         int j;
901         int x = 0;
902         byte bitmask;
903         byte out;
904         short *p;
905         short *b1 , *b2;
906 
907         b1 = buf[0];
908         b2 = buf[1];
909 /*
910         for ( i = 0 ; i < 100 ; i++ ) {
911                 dprintf1("[%04X]",bar[0][i]);
912         }
913         dprintf("\n");
914 */
915         for ( i = 0 ; i < plane_size ; i++ ) {
916                 bitmask = 0x80;
917                 out = 0;
918                 for ( j = 0 ; j < 8 ; j++ ) {
919                         out |= Xtal( bitmask , (short)(*dp) << 6 , x++ , bar , b1++ , b2++ );
920                         dp += 4;
921                         bitmask >>= 1;
922                 }
923                 *oP++ = out;
924         }
925 /*dprintf("\n");*/
926         p = buf[0];
927 /*	dprintf("\n"); */
928         buf[0] = buf[1];
929         buf[1] = p;
930 
931         p = bar[0];
932         for ( i = 0 ; i < plane_size*8 ; i++ )
933                 *p++ = 0;
934 
935         /*	memset( p, 0, (xtalbuff_size-16) * W);*/
936         p = bar[0];
937         for ( i = 0 ; i <= 14 ; i++ )
938                 bar[i] = bar[i+1];
939         bar[15] = p;
940 }
941 
942 static int
mj700v2c_print_page(gx_device_printer * pdev,gp_file * prn_stream)943 mj700v2c_print_page(gx_device_printer * pdev, gp_file * prn_stream)
944 {
945   return mj_print_page(pdev, prn_stream, MJ700V2C);
946 }
947 
948 static int
mj500c_print_page(gx_device_printer * pdev,gp_file * prn_stream)949 mj500c_print_page(gx_device_printer * pdev, gp_file * prn_stream)
950 {
951   return mj_print_page(pdev, prn_stream, MJ500C);
952 }
953 
954 static int
mj6000c_print_page(gx_device_printer * pdev,gp_file * prn_stream)955 mj6000c_print_page(gx_device_printer * pdev, gp_file * prn_stream)
956 {
957   return mj_print_page(pdev, prn_stream, MJ6000C);
958 }
959 
960 static int
mj8000c_print_page(gx_device_printer * pdev,gp_file * prn_stream)961 mj8000c_print_page(gx_device_printer * pdev, gp_file * prn_stream)
962 {
963   return mj_print_page(pdev, prn_stream, MJ8000C);
964 }
965 
966 /* Send the page to the printer.  Compress each scan line. */
967 static int
mj_print_page(gx_device_printer * pdev,gp_file * prn_stream,int ptype)968 mj_print_page(gx_device_printer * pdev, gp_file * prn_stream, int ptype)
969 {
970 /*  int line_size = gdev_prn_rasterwidth(pdev, 0); */
971   int line_size = gdev_prn_raster(pdev);
972   int line_size_words = (line_size + W - 1) / W;
973   int num_comps = pdev->color_info.num_components;
974   int bits_per_pixel = pdev->color_info.depth;
975   int storage_bpp = bits_per_pixel;
976   int expanded_bpp = bits_per_pixel;
977   int plane_size, databuff_size;
978   int errbuff_size = 0;
979   int outbuff_size = 0;
980   int scan = 0;
981   int *errors[2];
982   byte *data[4], *plane_data[4][4], *out_data;
983   byte *out_row;
984   word *storage;
985   uint storage_size_words;
986   uint mj_tmp_buf_size;
987   byte* mj_tmp_buf;
988   int xtalbuff_size;
989   short *xtalbuff;
990   short *Cbar[16];
991   short *Mbar[16];
992   short *Ybar[16];
993   short *Kbar[16];
994   short *Cbuf[2];
995   short *Mbuf[2];
996   short *Ybuf[2];
997   short *Kbuf[2];
998 
999   /* Tricks and cheats ... */
1000   if (num_comps == 3) num_comps = 4;            /* print CMYK */
1001 
1002   if (storage_bpp == 8 && num_comps >= 3)
1003     bits_per_pixel = expanded_bpp = 3;  /* Only 3 bits of each byte used */
1004 
1005   plane_size = calc_buffsize(line_size, storage_bpp);
1006 
1007   if (bits_per_pixel == 1) {            /* Data printed direct from i/p */
1008     outbuff_size = plane_size * 4;      /* but need separate output buffers */
1009   }
1010 
1011   if (bits_per_pixel > 4) {             /* Error buffer for FS dithering */
1012     expanded_bpp = storage_bpp =        /* 8, 24 or 32 bits */
1013       num_comps * 8;
1014     errbuff_size =                      /* 4n extra values for line ends */
1015       calc_buffsize((plane_size * expanded_bpp + num_comps * 4) * I, 1);
1016   }
1017 
1018   databuff_size = plane_size * storage_bpp;
1019 
1020   storage_size_words = ((plane_size + plane_size) * num_comps +
1021                         databuff_size + errbuff_size + outbuff_size) / W;
1022 
1023 /* NOZ */
1024   xtalbuff_size = plane_size*8 + 64;
1025   xtalbuff = (short *) gs_malloc(pdev->memory->non_gc_memory,  xtalbuff_size*(16*4+2*4) , W, "mj_colour_print_barrier");
1026   memset(xtalbuff, 0, xtalbuff_size*(16*4+2*4) * W);
1027   {
1028         int i;
1029         short *p = xtalbuff + 16;
1030         for ( i = 0 ; i < 16 ; i++ ) {
1031                 Cbar[i] = p;
1032                 p += xtalbuff_size;
1033         }
1034         for ( i = 0 ; i < 16 ; i++ ) {
1035                 Mbar[i] = p;
1036                 p += xtalbuff_size;
1037         }
1038         for ( i = 0 ; i < 16 ; i++ ) {
1039                 Ybar[i] = p;
1040                 p += xtalbuff_size;
1041         }
1042         for ( i = 0 ; i < 16 ; i++ ) {
1043                 Kbar[i] = p;
1044                 p += xtalbuff_size;
1045         }
1046         Cbuf[0] = p;
1047         p += xtalbuff_size;
1048         Cbuf[1] = p;
1049         p += xtalbuff_size;
1050         Mbuf[0] = p;
1051         p += xtalbuff_size;
1052         Mbuf[1] = p;
1053         p += xtalbuff_size;
1054         Ybuf[0] = p;
1055         p += xtalbuff_size;
1056         Ybuf[1] = p;
1057         p += xtalbuff_size;
1058         Kbuf[0] = p;
1059         p += xtalbuff_size;
1060         Kbuf[1] = p;
1061         p += xtalbuff_size;
1062         (void) p;
1063   }
1064 
1065   storage = (word *) gs_malloc(pdev->memory->non_gc_memory, storage_size_words, W, "mj_colour_print_page");
1066 
1067 /* prepare a temporary buffer for mj_raster_cmd */
1068 
1069   mj_tmp_buf_size = plane_size;
1070   mj_tmp_buf = (byte *) gs_malloc(pdev->memory->non_gc_memory, mj_tmp_buf_size, W ,"mj_raster_buffer");
1071 
1072 #if 0
1073   dprintf1("storage_size_words :%d\n", storage_size_words);
1074   dprintf1("mj_tmp_buf_size :%d\n", mj_tmp_buf_size);
1075 #endif
1076   /*
1077    * The principal data pointers are stored as pairs of values, with
1078    * the selection being made by the 'scan' variable. The function of the
1079    * scan variable is overloaded, as it controls both the alternating
1080    * raster scan direction used in the Floyd-Steinberg dithering and also
1081    * the buffer alternation required for line-difference compression.
1082    *
1083    * Thus, the number of pointers required is as follows:
1084    *
1085    *   errors:      2  (scan direction only)
1086    *   data:        4  (scan direction and alternating buffers)
1087    *   plane_data:  4  (scan direction and alternating buffers)
1088    */
1089 
1090   if (storage == NULL || mj_tmp_buf == NULL) /* can't allocate working area */
1091     return_error(gs_error_VMerror);
1092   else {
1093     int i;
1094     byte *p = out_data = out_row = (byte *)storage;
1095     data[0] = data[1] = data[2] = p;
1096     data[3] = p + databuff_size;
1097     if (bits_per_pixel > 1) {
1098       p += databuff_size;
1099     }
1100     if (bits_per_pixel > 4) {
1101       errors[0] = (int *)p + num_comps * 2;
1102       errors[1] = errors[0] + databuff_size;
1103       p += errbuff_size;
1104     }
1105     for (i = 0; i < num_comps; i++) {
1106       plane_data[0][i] = plane_data[2][i] = p;
1107       p += plane_size;
1108     }
1109     for (i = 0; i < num_comps; i++) {
1110       plane_data[1][i] = p;
1111       plane_data[3][i] = p + plane_size;
1112       p += plane_size;
1113     }
1114     if (bits_per_pixel == 1) {
1115       data[1] += databuff_size;   /* coincides with plane_data pointers */
1116       data[3] += databuff_size;
1117     }
1118   }
1119 
1120   /* Clear temp storage */
1121   memset(storage, 0, storage_size_words * W);
1122 
1123   /* Initialize printer. */
1124   {
1125     /** Reset printer, enter graphics mode: */
1126 
1127     gp_fwrite("\033@\033(G\001\000\001", sizeof(byte), 8, prn_stream);
1128 
1129     /** Micro-weave-Mode */
1130     if (mj->microweave) {
1131       gp_fwrite("\033(i\001\000\001", sizeof(byte), 6, prn_stream);
1132     }
1133     /** Dot-Size define */
1134     if (mj->dotsize) {
1135       gp_fwrite("\033(e\002\000\000\001", sizeof(byte), 7, prn_stream);
1136     }
1137 
1138     if (ptype == MJ6000C || ptype == MJ8000C) {
1139       /* Select Monochrome/Color Printing Mode Command */
1140       if (pdev->color_info.depth == 8)
1141         gp_fwrite("\033(K\002\000\000\001", sizeof(byte), 7, prn_stream);
1142     }
1143 
1144     if (mj->direction) /* set the direction of the head */
1145       gp_fwrite("\033U\1", 1, 3, prn_stream); /* Unidirectional Printing */
1146     else
1147       gp_fwrite("\033U\0", 1, 3, prn_stream);
1148 
1149 #if 0
1150 #ifdef A4
1151         /*
1152         ** After reset, the Stylus is set up for US letter paper.
1153         ** We need to set the page size appropriately for A4 paper.
1154         ** For some bizarre reason the ESC/P2 language wants the bottom
1155         ** margin measured from the *top* of the page:
1156         */
1157 
1158         gp_fwrite("\033(U\001\0\n\033(C\002\0t\020\033(c\004\0\0\0t\020",
1159                                                         1, 22, prn_stream);
1160 #endif
1161 #endif
1162 
1163         /*
1164         ** Set the line spacing to match the band height:
1165         */
1166 
1167         if( pdev->y_pixels_per_inch >= 720 )
1168           gp_fwrite("\033(U\001\0\005\033+\001", sizeof(byte), 9, prn_stream);
1169         else if( pdev->y_pixels_per_inch >= 360 )
1170            gp_fwrite("\033(U\001\0\012\033+\001", sizeof(byte), 9, prn_stream);
1171         else /* 180 dpi */
1172            gp_fwrite("\033(U\001\0\024\033+\002", sizeof(byte), 9, prn_stream);
1173 
1174     /* set the length of the page */
1175         gp_fwrite("\033(C\2\0", sizeof(byte), 5, prn_stream);
1176         gp_fputc(((pdev->height) % 256), prn_stream);
1177         gp_fputc(((pdev->height) / 256), prn_stream);
1178   }
1179 
1180 #define MOFFSET (pdev->t_margin - MJ700V2C_PRINT_LIMIT) /* Print position */
1181 
1182   {
1183     gp_fwrite("\033(V\2\0\0\0",sizeof(byte), 7, prn_stream);
1184     gp_fwrite("\033(v\2\0\0\xff",sizeof(byte), 7, prn_stream);
1185   }
1186 
1187   /* Send each scan line in turn */
1188   {
1189     long int lend = (int)(pdev->height -
1190       (dev_t_margin_points(pdev) + dev_b_margin_points(pdev)));
1191     int cErr, mErr, yErr, kErr;
1192     int this_pass, i;
1193     long int lnum;
1194     int num_blank_lines = 0;
1195     int start_rows = (num_comps == 1) ?
1196       HEAD_ROWS_MONO - 1 : HEAD_ROWS_COLOUR - 1;
1197     word rmask = ~(word) 0 << ((-pdev->width * storage_bpp) & (W * 8 - 1));
1198 
1199     cErr = mErr = yErr = kErr = 0;
1200 
1201     if (bits_per_pixel > 4) { /* Randomly seed initial error buffer */
1202       int *ep = errors[0];
1203       for (i = 0; i < databuff_size; i++) {
1204         *ep++ = (rand() % (MAXVALUE / 2))  - MAXVALUE / 4;
1205       }
1206     }
1207 
1208     this_pass = start_rows;
1209 
1210     lnum = 0;
1211 
1212     /* for Debug */
1213 
1214     for (; lnum < lend; lnum++) {
1215       word *data_words = (word *)data[scan];
1216       register word *end_data = data_words + line_size_words;
1217       gx_color_index *p_data;
1218 
1219       gdev_prn_copy_scan_lines(pdev, lnum, data[scan], line_size);
1220 
1221       /* Mask off 1-bits beyond the line width. */
1222       end_data[-1] &= rmask;
1223 
1224       /* Remove trailing 0s. */
1225       while (end_data > data_words && end_data[-1] == 0)
1226         end_data--;
1227       if (end_data == data_words) {	/* Blank line */
1228         num_blank_lines++;
1229         continue; /* skip to  for (lnum) loop */
1230       }
1231       /* Skip blank lines if any */
1232       if (num_blank_lines > 0 ) {
1233         mj_v_skip(num_blank_lines, pdev, prn_stream);
1234         memset(plane_data[1 - scan][0], 0, plane_size * num_comps);
1235         num_blank_lines = 0;
1236         this_pass = start_rows;
1237       }
1238 
1239       /* Correct color depth. */
1240           if (mj->density != 1024 || mj->yellow != 1024 || mj->cyan != 1024
1241                   || mj->magenta != 1024 || mj->black != 1024 ) {
1242               for (p_data = (gx_color_index*) data_words; p_data < (gx_color_index *)end_data; p_data++) {
1243                         *p_data = mjc_correct_color(pdev, *p_data);
1244               }
1245           }
1246 
1247       {			/* Printing non-blank lines */
1248         register byte *kP = plane_data[scan + 2][3];
1249         register byte *cP = plane_data[scan + 2][2];
1250         register byte *mP = plane_data[scan + 2][1];
1251         register byte *yP = plane_data[scan + 2][0];
1252         register byte *dp = data[scan + 2];
1253         int i, j;
1254         byte *odp;
1255 
1256         if (this_pass)
1257           this_pass--;
1258         else
1259           this_pass = start_rows;
1260 
1261         if (expanded_bpp > bits_per_pixel)   /* Expand line if required */
1262           expand_line(data_words, line_size, bits_per_pixel, expanded_bpp);
1263 
1264         /* In colour modes, we have some bit-shuffling to do before
1265          * we can print the data; in FS mode we also have the
1266          * dithering to take care of. */
1267         switch (expanded_bpp) {    /* Can be 1, 3, 8, 24 or 32 */
1268         case 3:
1269           /* Transpose the data to get pixel planes. */
1270           for (i = 0, odp = plane_data[scan][0]; i < databuff_size;
1271                i += 8, odp++) {	/* The following is for 16-bit
1272                                  * machines */
1273 #define spread3(c)\
1274     { 0, c, c*0x100, c*0x101, c*0x10000L, c*0x10001L, c*0x10100L, c*0x10101L }
1275             static word spr40[8] = spread3(0x40);
1276             static word spr08[8] = spread3(8);
1277             static word spr02[8] = spread3(2);
1278             register byte *dp = data[scan] + i;
1279             register word pword =
1280             (spr40[dp[0]] << 1) +
1281             (spr40[dp[1]]) +
1282             (spr40[dp[2]] >> 1) +
1283             (spr08[dp[3]] << 1) +
1284             (spr08[dp[4]]) +
1285             (spr08[dp[5]] >> 1) +
1286             (spr02[dp[6]]) +
1287             (spr02[dp[7]] >> 1);
1288             odp[0] = (byte) (pword >> 16);
1289             odp[plane_size] = (byte) (pword >> 8);
1290             odp[plane_size * 2] = (byte) (pword);
1291           }
1292           break;
1293 
1294         case 8:
1295           FSDline(scan, i, j, plane_size, cErr, mErr, yErr, kErr,
1296                   cP, mP, yP, kP, 1);
1297           break;
1298         case 24:
1299           FSDline(scan, i, j, plane_size, cErr, mErr, yErr, kErr,
1300                   cP, mP, yP, kP, 3);
1301           break;
1302         case 32:
1303                 if (scan == 1) {
1304                         dp -= plane_size*8*4;
1305                         cP -= plane_size;
1306                         mP -= plane_size;
1307                         yP -= plane_size;
1308                         kP -= plane_size;
1309                 }
1310 /*
1311 {
1312         byte *p = dp;
1313         int i;
1314         for ( i = 0 ; i < plane_size ; i++ ) {
1315                 dprintf4 ( "[%02X%02X%02X%02X]" , p[0] , p[1] , p[2] , p[3] );
1316                 p += 4;
1317         }
1318         dprintf("\n");
1319 
1320 }
1321 */
1322 /*
1323           FSDline(scan, i, j, plane_size, cErr, mErr, yErr, kErr,
1324                   cP, mP, yP, kP, 4);
1325 */
1326 /* NOZ */
1327           xtal_plane( dp++ , Kbuf , kP , Kbar , plane_size , xtalbuff_size );
1328           xtal_plane( dp++ , Cbuf , cP , Cbar , plane_size , xtalbuff_size );
1329           xtal_plane( dp++ , Mbuf , mP , Mbar , plane_size , xtalbuff_size );
1330           xtal_plane( dp++ , Ybuf , yP , Ybar , plane_size , xtalbuff_size );
1331 
1332           break;
1333 
1334         } /* switch(expanded_bpp) */
1335 
1336         /* Make sure all black is in the k plane */
1337         if (num_comps == 4 ) {
1338           if (mj->colorcomp > 3 ) {
1339             register word *kp = (word *)plane_data[scan][3];
1340             register word *cp = (word *)plane_data[scan][2];
1341             register word *mp = (word *)plane_data[scan][1];
1342             register word *yp = (word *)plane_data[scan][0];
1343             if (bits_per_pixel > 4) {  /* This has been done as 4 planes */
1344 #if 0
1345               for (i = 0; i < plane_size / W; i++) {
1346                 word bits = ~*kp++;
1347                 *cp++ &= bits;
1348                 *mp++ &= bits;
1349                 *yp++ &= bits;
1350               }
1351 #endif
1352             } else {  /* This has really been done as 3 planes */
1353               for (i = 0; i < plane_size / W; i++) {
1354                 word bits = *cp & *mp & *yp;
1355                 *kp++ = bits;
1356                 bits = ~bits;
1357                 *cp++ &= bits;
1358                 *mp++ &= bits;
1359                 *yp++ &= bits;
1360               }
1361             }
1362           } else if (mj->colorcomp == 3 ) {
1363             register word *kp = (word *)plane_data[scan][3];
1364             register word *cp = (word *)plane_data[scan][2];
1365             register word *mp = (word *)plane_data[scan][1];
1366             register word *yp = (word *)plane_data[scan][0];
1367             if (bits_per_pixel > 4) {  /* This has been done as 4 planes */
1368               for (i = 0; i < plane_size / W; i++) {
1369                 word bits = *kp++; /* kp will not be used when printing */
1370                 *cp++ |= bits;
1371                 *mp++ |= bits;
1372                 *yp++ |= bits;
1373               }
1374             } else {  /* This has really been done as 3 planes */
1375             }
1376           }
1377         }
1378 
1379         /* Transfer raster graphics
1380          * in the order (K), C, M, Y. */
1381         switch (mj->colorcomp) {
1382         case 1:
1383           out_data = (byte*) plane_data[scan][0];
1384           /* 3 for balck */
1385           mj_raster_cmd(3, plane_size, out_data, mj_tmp_buf, pdev, prn_stream);
1386           break;
1387         case 3:
1388           for (i = 3 - 1; i >= 0; i--) {
1389             out_data = (byte*) plane_data[scan][i];
1390             mj_raster_cmd(i, plane_size, out_data, mj_tmp_buf, pdev, prn_stream);
1391           }
1392           break;
1393         default:
1394           for (i = num_comps - 1; i >= 0; i--) {
1395             out_data = (byte*) plane_data[scan][i];
1396             mj_raster_cmd(i, plane_size, out_data, mj_tmp_buf, pdev, prn_stream);
1397           }
1398           break;
1399         } /* Transfer Raster Graphics ... */
1400 
1401         {
1402           if ( pdev->y_pixels_per_inch > 360 ) {
1403              gp_fwrite("\033(v\2\0\1\0",sizeof(byte),7, prn_stream);
1404            } else {
1405              gp_fputc('\n', prn_stream);
1406            }
1407         }
1408         scan = 1 - scan;          /* toggle scan direction */
1409       }	  /* Printing non-blank lines */
1410     }     /* for lnum ... */
1411   }       /* send each scan line in turn */
1412 
1413   /* end raster graphics & reset printer */
1414 
1415   /* eject page */
1416   {
1417     gp_fputs("\f\033@", prn_stream);
1418     gp_fflush(prn_stream);
1419   }
1420   /* free temporary storage */
1421   gs_free(pdev->memory->non_gc_memory, (char *) storage, storage_size_words, W, "mj_colour_print_page");
1422   gs_free(pdev->memory->non_gc_memory, (char *) mj_tmp_buf, mj_tmp_buf_size, W, "mj_raster_buffer");
1423   gs_free(pdev->memory->non_gc_memory, (char *) xtalbuff , xtalbuff_size*(16*4+2*4) , W, "mj_colour_print_barrier");
1424 
1425   return 0;
1426 }
1427 
1428 static void
mj_color_correct(gx_color_value * Rptr,gx_color_value * Gptr,gx_color_value * Bptr)1429 mj_color_correct(gx_color_value *Rptr ,gx_color_value *Gptr , gx_color_value *Bptr )
1430                                                                 /* R,G,B : 0 to 255 */
1431 {
1432         short	R,G,B;				/* R,G,B : 0 to 255  */
1433         short	C,M,Y;				/* C,M,Y : 0 to 1023 */
1434         short	H,D,Wa;				/* ese-HSV         */
1435         long	S;					/*     HSV         */
1436 
1437         R = *Rptr;
1438         G = *Gptr;
1439         B = *Bptr;
1440         if (R==G) {
1441                 if (G==B) {						/* R=G=B */
1442                         C=M=Y=1023-v_tbl[R];
1443                         *Rptr = C;
1444                         *Gptr = M;
1445                         *Bptr = Y;
1446                         return;
1447                 }
1448         }
1449 
1450         if (R>G) {
1451                 if (G>=B) {			/* R>G>B */
1452                         Wa=R;
1453                         D=R-B;
1454                         H=(G-B)*256/D;
1455                 } else if (R>B) {		/* R>B>G */
1456                         Wa=R;
1457                         D=R-G;
1458                         H=1536-(B-G)*256/D;
1459                 } else {			/* B>R>G */
1460                         Wa=B;
1461                         D=B-G;
1462                         H=1024+(R-G)*256/D;
1463                 }
1464         } else {
1465                 if (R>B) {			/* G>R>B */
1466                         Wa=G;
1467                         D=G-B;
1468                         H=512-(R-B)*256/D;
1469                 } else if (G>B) {		/* G>B>R */
1470                         Wa=G;
1471                         D=G-R;
1472                         H=512+(B-R)*256/D;
1473                 } else {			/* B>G>R */
1474                         Wa=B;
1475                         D=B-R;
1476                         H=1024-(G-R)*256/D;
1477                 }
1478         }
1479 
1480         if(Wa!=0){
1481                 if(Wa==D){
1482                         Wa=v_tbl[Wa];
1483                         D=Wa/4;
1484                 } else {
1485                         S=((long)D<<16)/Wa;
1486                         Wa=v_tbl[Wa];
1487                         D= ( ((long)S*Wa)>>18 );
1488                 }
1489         }
1490         Wa=1023-Wa;
1491 
1492         C=(HtoCMY[H*3  ])*D/256+Wa;
1493         M=(HtoCMY[H*3+1])*D/256+Wa;
1494         Y=(HtoCMY[H*3+2])*D/256+Wa;
1495         if (C<0)
1496                 C=0;
1497         if (M<0)
1498                 M=0;
1499         if (Y<0)
1500                 Y=0;
1501 
1502         /* 2019-10-29 this used to be 'if(H>256 && H<1024)', which can then go
1503         beyond bounds of the 512-element grnsep2[]. So have patched up to avoid
1504         this, but without any proper idea about what's going on. */
1505         if(H>256 && H<768){		/* green correct */
1506                 short	work;
1507                 work=(((long)grnsep[M]*(long)grnsep2[H-256])>>16);
1508                 C+=work;
1509                 Y+=work+work;
1510                 M-=work+work;
1511                 if(C>1023) C=1023;
1512                 if(Y>1023) Y=1023;
1513         }
1514 
1515         *Rptr = C;
1516         *Gptr = M;
1517         *Bptr = Y;
1518 }
1519 
1520 /*
1521  * Map a r-g-b color to a color index.
1522  * We complement the colours, since we're using cmy anyway, and
1523  * because the buffering routines expect white to be zero.
1524  * Includes colour balancing, following HP recommendations, to try
1525  * and correct the greenish cast resulting from an equal mix of the
1526  * c, m, y, inks by reducing the cyan component to give a truer black.
1527  */
1528 static gx_color_index
gdev_mjc_map_rgb_color(gx_device * pdev,const gx_color_value cv[])1529 gdev_mjc_map_rgb_color(gx_device *pdev, const gx_color_value cv[])
1530 {
1531   gx_color_value r, g, b;
1532 
1533   r = cv[0]; g = cv[1]; b = cv[2];
1534   if (gx_color_value_to_byte(r & g & b) == 0xff)
1535     return (gx_color_index)0;         /* white */
1536   else {
1537     gx_color_value c = gx_max_color_value - r;
1538     gx_color_value m = gx_max_color_value - g;
1539     gx_color_value y = gx_max_color_value - b;
1540 
1541     switch (pdev->color_info.depth) {
1542     case 1:
1543       return ((c | m | y) > gx_max_color_value / 2 ?
1544               (gx_color_index)1 : (gx_color_index)0);
1545     case 8:
1546       if (pdev->color_info.num_components >= 3)
1547 #define gx_color_value_to_1bit(cv) ((cv) >> (gx_color_value_bits - 1))
1548         return (gx_color_value_to_1bit(c) +
1549                 (gx_color_value_to_1bit(m) << 1) +
1550                 (gx_color_value_to_1bit(y) << 2));
1551       else
1552 #define red_weight 306
1553 #define green_weight 601
1554 #define blue_weight 117
1555         return ((((word)c * red_weight +
1556                   (word)m * green_weight +
1557                   (word)y * blue_weight)
1558                  >> (gx_color_value_bits + 2)));
1559     case 16:
1560 #define gx_color_value_to_5bits(cv) ((cv) >> (gx_color_value_bits - 5))
1561 #define gx_color_value_to_6bits(cv) ((cv) >> (gx_color_value_bits - 6))
1562       return (gx_color_value_to_5bits(y) +
1563               (gx_color_value_to_6bits(m) << 5) +
1564               (gx_color_value_to_5bits(c) << 11));
1565     case 24:
1566       return (gx_color_value_to_byte(y) +
1567               (gx_color_value_to_byte(m) << 8) +
1568               ((word)gx_color_value_to_byte(c) << 16));
1569     case 32:
1570         {
1571                 gx_color_value k;
1572                 c = gx_color_value_to_byte(r);
1573                 m = gx_color_value_to_byte(g);
1574                 y = gx_color_value_to_byte(b);
1575 
1576                 mj_color_correct( &c , &m , &y );
1577 
1578                 c = esp_dat_c[c];
1579                 m = esp_dat_m[m];
1580                 y = esp_dat_y[y];
1581 
1582                 k = c <= m ? (c <= y ? c : y) : (m <= y ? m : y);
1583                 k = black_sep[ k >> 4 ] >> 6;
1584                 c >>= 6;
1585                 m >>= 6;
1586                 y >>= 6;
1587 
1588         return ( (y - k) + ((m - k) << 8) +
1589                 ((word)(c - k) << 16) + ((word)(k) << 24) );
1590       }
1591     }
1592   }
1593   return (gx_color_index)0;   /* This never happens */
1594 }
1595 
1596 /* Map a color index to a r-g-b color. */
1597 static int
gdev_mjc_map_color_rgb(gx_device * pdev,gx_color_index color,gx_color_value prgb[3])1598 gdev_mjc_map_color_rgb(gx_device *pdev, gx_color_index color,
1599                             gx_color_value prgb[3])
1600 {
1601   /* For the moment, we simply ignore any black correction */
1602   switch (pdev->color_info.depth) {
1603   case 1:
1604     prgb[0] = prgb[1] = prgb[2] = -((gx_color_value)color ^ 1);
1605     break;
1606   case 8:
1607       if (pdev->color_info.num_components >= 3)
1608         { gx_color_value c = (gx_color_value)color ^ 7;
1609           prgb[0] = -(c & 1);
1610           prgb[1] = -((c >> 1) & 1);
1611           prgb[2] = -(c >> 2);
1612         }
1613       else
1614         { gx_color_index value = (gx_color_index)color ^ 0xff;
1615           prgb[0] = prgb[1] = prgb[2] = (value << 8) + value;
1616         }
1617     break;
1618   case 16:
1619     { gx_color_index c = (gx_color_index)color ^ 0xffff;
1620       ushort value = c >> 11;
1621       prgb[0] = ((value << 11) + (value << 6) + (value << 1) +
1622                  (value >> 4)) >> (16 - gx_color_value_bits);
1623       value = (c >> 6) & 0x3f;
1624       prgb[1] = ((value << 10) + (value << 4) + (value >> 2))
1625         >> (16 - gx_color_value_bits);
1626       value = c & 0x1f;
1627       prgb[2] = ((value << 11) + (value << 6) + (value << 1) +
1628                  (value >> 4)) >> (16 - gx_color_value_bits);
1629     }
1630     break;
1631   case 24:
1632     { gx_color_index c = (gx_color_index)color ^ 0xffffff;
1633       prgb[0] = gx_color_value_from_byte(c >> 16);
1634       prgb[1] = gx_color_value_from_byte((c >> 8) & 0xff);
1635       prgb[2] = gx_color_value_from_byte(c & 0xff);
1636     }
1637     break;
1638   case 32:
1639 #define  gx_maxcol gx_color_value_from_byte(gx_color_value_to_byte(gx_max_color_value))
1640     { gx_color_value w = gx_maxcol - gx_color_value_from_byte(color >> 24);
1641       prgb[0] = w - gx_color_value_from_byte((color >> 16) & 0xff);
1642       prgb[1] = w - gx_color_value_from_byte((color >> 8) & 0xff);
1643       prgb[2] = w - gx_color_value_from_byte(color & 0xff);
1644     }
1645     break;
1646   }
1647   return 0;
1648 }
1649 
1650 /*
1651 * Encode a list of colorant values into a gx_color_index_value.
1652 */
1653 static gx_color_index
gdev_mjc_encode_color(gx_device * dev,const gx_color_value colors[])1654 gdev_mjc_encode_color(gx_device *dev, const gx_color_value colors[])
1655 {
1656     return gdev_mjc_map_rgb_color(dev, colors);
1657 }
1658 
1659 /*
1660 * Decode a gx_color_index value back to a list of colorant values.
1661 */
1662 static int
gdev_mjc_decode_color(gx_device * dev,gx_color_index color,gx_color_value * out)1663 gdev_mjc_decode_color(gx_device * dev, gx_color_index color, gx_color_value * out)
1664 {
1665     return gdev_mjc_map_color_rgb(dev, color, out);
1666 }
1667 
1668 /*
1669  * Convert and expand scanlines:
1670  *
1671  *       (a)    16 -> 24 bit   (1-stage)
1672  *       (b)    16 -> 32 bit   (2-stage)
1673  *   or  (c)    24 -> 32 bit   (1-stage)
1674  */
1675 static void
expand_line(word * line,int linesize,int bpp,int ebpp)1676 expand_line(word *line, int linesize, int bpp, int ebpp)
1677 {
1678   int endline = linesize;
1679   byte *start = (byte *)line;
1680   register byte *in, *out;
1681 
1682   if (bpp == 16)              /* 16 to 24 (cmy) if required */
1683     { register byte b0, b1;
1684       endline = ((endline + 1) / 2);
1685       in = start + endline * 2;
1686       out = start + (endline *= 3);
1687 
1688       while (in > start)
1689         { b0 = *--in;
1690           b1 = *--in;
1691           *--out = (b0 << 3) + ((b0 >> 2) & 0x7);
1692           *--out = (b1 << 5) + ((b0 >> 3)  & 0x1c) + ((b1 >> 1) & 0x3);
1693           *--out = (b1 & 0xf8) + (b1 >> 5);
1694         }
1695     }
1696 
1697   if (ebpp == 32)             /* 24 (cmy) to 32 (cmyk) if required */
1698     { register byte c, m, y, k;
1699       endline = ((endline + 2) / 3);
1700       in = start + endline * 3;
1701       out = start + endline * 4;
1702 
1703       while (in > start)
1704         { y = *--in;
1705           m = *--in;
1706           c = *--in;
1707           k = c < m ? (c < y ? c : y) : (m < y ? m : y);
1708           *--out = y - k;
1709           *--out = m - k;
1710           *--out = c - k;
1711           *--out = k;
1712         }
1713     }
1714 }
1715 
1716 static int
put_param_int(gs_param_list * plist,gs_param_name pname,int * pvalue,int minval,int maxval,int ecode)1717 put_param_int(gs_param_list *plist, gs_param_name pname, int *pvalue, int minval, int maxval, int ecode)
1718 {       int code, value;
1719         switch ( code = param_read_int(plist, pname, &value) )
1720         {
1721         default:
1722                 return code;
1723         case 1:
1724                 return ecode;
1725         case 0:
1726                 if ( value < minval || value > maxval )
1727                    param_signal_error(plist, pname, gs_error_rangecheck);
1728                 *pvalue = value;
1729                 return (ecode < 0 ? ecode : 1);
1730         }
1731 }
1732 
1733 static void
set_bpp(gx_device * pdev,int bits_per_pixel)1734 set_bpp(gx_device *pdev, int bits_per_pixel)
1735 { gx_device_color_info *ci = &pdev->color_info;
1736   /* Only valid bits-per-pixel are 1, 3, 8, 16, 24, 32 */
1737   int bpp = bits_per_pixel < 3 ? 1 : bits_per_pixel < 8 ? 3 :
1738     (bits_per_pixel >> 3) << 3;
1739   ci->num_components = ((bpp == 1) || (bpp == 8) ? 1 : 3);
1740   ci->depth = ((bpp > 1) && (bpp < 8) ? 8 : bpp);
1741   ci->max_gray = (bpp >= 8 ? 255 : 1);
1742   ci->max_color = (bpp >= 8 ? 255 : bpp > 1 ? 1 : 0);
1743   ci->dither_grays = (bpp >= 8 ? 5 : 2);
1744   ci->dither_colors = (bpp >= 8 ? 5 : bpp > 1 ? 2 : 0);
1745   mj->colorcomp = (bpp == 8 ? 1 : 4);
1746 }
1747 
1748 static void
mj500c_set_bpp(gx_device * pdev,int bits_per_pixel)1749 mj500c_set_bpp(gx_device *pdev, int bits_per_pixel)
1750 { gx_device_color_info *ci = &pdev->color_info;
1751   /* Only valid bits-per-pixel are 1, 3, 8, 16, 24, 32 */
1752   int bpp = bits_per_pixel < 3 ? 1 : bits_per_pixel < 8 ? 3 :
1753     (bits_per_pixel >> 3) << 3;
1754   ci->num_components = ((bpp == 1) || (bpp == 8) ? 1 : 3);
1755   ci->depth = ((bpp > 1) && (bpp < 8) ? 8 : bpp);
1756   ci->max_gray = (bpp >= 8 ? 255 : 1);
1757   ci->max_color = (bpp >= 8 ? 255 : bpp > 1 ? 1 : 0);
1758   ci->dither_grays = (bpp >= 8 ? 5 : 2);
1759   ci->dither_colors = (bpp >= 8 ? 5 : bpp > 1 ? 2 : 0);
1760   mj->colorcomp = (bpp == 8 ? 1 : 3);
1761 }
1762 
1763 static gx_color_index
mjc_correct_color(gx_device_printer * pdev,gx_color_index ci)1764 mjc_correct_color(gx_device_printer *pdev, gx_color_index ci)
1765 {
1766   gx_color_index c, m, y, k, co;
1767   gx_color_index k2, k3, k4;
1768 #if __WORDSIZE == 64
1769   gx_color_index c2, m2, y2, k5, k6, k7, k8;
1770 #endif
1771   const uint cmask = 0xff;
1772   uint dn = mj->density;
1773   uint mjy = mj->yellow;
1774   uint mjc = mj->cyan;
1775   uint mjm = mj->magenta;
1776   uint mjb = mj->black;
1777   switch (pdev->color_info.depth) {
1778  case 8:
1779     k = ((ci & cmask) * (mjb)) >> 10;
1780     k = (k < cmask) ? k : cmask;
1781     k2 = (((ci >> 8) & cmask) * (mjb)) >> 10;
1782     k2 = (k2 < cmask) ? k2 : cmask;
1783     k3 = (((ci >> 16) & cmask) * (mjb)) >> 10;
1784     k3 = (k3 < cmask) ? k3 : cmask;
1785     k4 = (((ci >> 24) & cmask) * (mjb)) >> 10;
1786     k4 = (k4 < cmask) ? k4 : cmask;
1787 #if __WORDSIZE == 64
1788     /* This code is ugly... (for 64 bit OS) */
1789     if (sizeof(word) == 8)
1790       {
1791         k5 = (((ci >> 32) & cmask) * (mjb)) >> 10;
1792         k5 = (k5 < cmask) ? k5 : cmask;
1793         k6 = (((ci >> 40) & cmask) * (mjb)) >> 10;
1794         k6 = (k6 < cmask) ? k6 : cmask;
1795         k7 = (((ci >> 48) & cmask) * (mjb)) >> 10;
1796         k7 = (k7 < cmask) ? k7 : cmask;
1797         k8 = (((ci >> 56) & cmask) * (mjb)) >> 10;
1798         k8 = (k8 < cmask) ? k8 : cmask;
1799         co = k + (k2 << 8) + (k3 << 16) + (k4 << 24)
1800           + (k5 << 32) + (k6 << 40) + (k7 << 48) + (k8 << 56);
1801         if (ci != co)
1802           dprintf1("%s\n", "error");
1803         return co;
1804       }
1805 #endif
1806     return k + (k2 << 8) + (k3 << 16) + (k << 24);
1807     break;
1808  case 32:
1809     y = ((ci & cmask) * mjy * dn) >> 20;
1810     y = (y < cmask) ? y : cmask;
1811     m = (((ci >> 8) & cmask) * mjm * dn) >> 20;
1812     m = (m < cmask) ? m : cmask;
1813     c = (((ci >> 16) & cmask) * mjc * dn) >> 20;
1814     c = (c < cmask) ? c : cmask;
1815     k = (((ci >> 24) & cmask) * mjb * dn) >> 20;
1816     k = (k < cmask) ? k : cmask;
1817 #if __WORDSIZE == 64
1818     /* This code is ugly... (for 64 bit OS) */
1819     if (sizeof(word) == 8)
1820       {
1821         y2 = (((ci >> 32) & cmask) * mjy * dn) >> 20;
1822         y2 = (y2 < cmask) ? y2 : cmask;
1823         m2 = (((ci >> 40) & cmask) * mjm * dn) >> 20;
1824         m2 = (m2 < cmask) ? m2 : cmask;
1825         c2 = (((ci >> 48) & cmask) * mjc * dn) >> 20;
1826         c2 = (c2 < cmask) ? c2 : cmask;
1827         k2 = (((ci >> 56) & cmask) * mjb * dn) >> 20;
1828         k2 = (k2 < cmask) ? k2 : cmask;
1829 
1830         co = y + (m << 8) + (c << 16) + (k << 24)
1831           + (y2 << 32) + (m2 << 40) + (c2 << 48) + (k2 << 56);
1832 
1833         return co;
1834       }
1835 #endif
1836     co =    (y + (m << 8) + (c << 16) + (k << 24));
1837 /*     dprintf6("%d,%d:%d,%d,%d,%d\n", ci,co, y, m, c, k); */
1838     return co;
1839 /*    return (gx_color_value_to_byte(y) +
1840             (gx_color_value_to_byte(m) << 8) +
1841             ((word)gx_color_value_to_byte(c) << 16) +
1842             ((word)gx_color_value_to_byte(k) << 24)); */
1843     break;
1844   }
1845   return ci;
1846 }
1847