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