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