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