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 µweave))< 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