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