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