1 /* Copyright (C) 2001-2012 Artifex Software, Inc.
2 All Rights Reserved.
3
4 This software is provided AS-IS with no warranty, either express or
5 implied.
6
7 This software is distributed under license and may not be copied,
8 modified or distributed except as expressly authorized under the terms
9 of the license contained in the file LICENSE in this distribution.
10
11 Refer to licensing information at http://www.artifex.com or contact
12 Artifex Software, Inc., 7 Mt. Lassen Drive - Suite A-134, San Rafael,
13 CA 94903, U.S.A., +1(415)492-9861, for further information.
14 */
15
16
17 /* Epson Stylus-Color Printer-Driver */
18
19 /***
20 *** This file was "copied" from gdevcdj.c (ghostscript-3.12), which was
21 *** contributed by:
22 *** George Cameron - g.cameron@biomed.abdn.ac.ukis
23 *** Koert Zeilstra - koert@zen.cais.com
24 *** Eckhard Rueggeberg - eckhard@ts.go.dlr.de
25 ***
26 *** Some of the ESC/P2-code was drawn from gdevescp.c, contributed by
27 *** Richard Brown - rab@eos.ncsu.edu
28 ***
29 *** The POSIX-Interrupt-Code is from (Compile-Time-Option -DSTC_SIGNAL)
30 *** Frederic Loyer - loyer@ensta.fr
31 ***
32 *** And several improvements are based on discussions with
33 *** Brian Converse - BCONVERSE@ids.net
34 *** Bill Davidson - bdavidson@ra.isisnet.com
35 *** Gero Guenther - gero@cs.tu-berlin.de
36 *** Jason Patterson - jason@reflections.com.au
37 *** ? Rueschstroer - rue@ibe.med.uni-muenchen.de
38 *** Steven Singer - S.Singer@ph.surrey.ac.uk
39 ***
40 *** And the remaining little rest, mainly the bugs, were written by me:
41 *** Gunther Hess - gunther@elmos.de
42 ***
43 *** P.S.: there is some documentation, see devices.doc
44 ***
45 *** Revision-History:
46 *** 16-DEC-1994 1.1 - initial Version (GS-Dithering & Plain-Write)
47 ...
48 *** 30-JAN-1995 1.11 - FS-Improvements, u/sWeave, 1/4/24-Bits
49 *** 5-MAR-1995 1.12 - L. Peter Deutsch - updated put_params routine
50 (first distributed version with gs3.33)
51 *** 26-APR-1995 1.13 - merged Peters fixes with algorithmic changes:
52 Changed 24Bit-Mode, added 32Bit-Mode (moves colors)
53 [Arrgh: much better than 1.12, but patch was lost]
54 *** 5-JUN-1995 1.14 - Added Color-Correction & Transfer-Curves
55 (Several Beta-Testers, but not distributed)
56 ...
57 *** 24-JUL-1995 1.16 - Made dithering-Algorithms external-functions.
58 (Mailed for Beta-Distribution)
59 *** 10-AUG-1995 1.17 - Several Bug-Fixes and some new features:
60 CMYK10-Coding added
61 Readonly Parameters added
62 "Algorithms", "BitsPerComponent", "Version"
63 Parameters Flag0-4, Model, OutputCode
64 (mailed for distribution)
65 *** 14-SEP-1995 1.18 Fixes Bugs with Borland C (gs3.47)
66 *** 23-SEP-1995 1.19 - reorganized printcode + bug-fixing
67 *** 24-SEP-1995 1.20 - Little Cleanup for the release
68 *** 25-SEP-1995 1.21 - Readonly-Parameters added to put_params.
69 *** 31-Dec-1995 1.22 - Sanitary Engineering on the code
70 *** 16-Jan-1996 1.23 - Added String escp_Release
71 *** 8-May-1996 1.90 - Reintroduced Deltarow & Fixed MEMORY-BUG!
72 ***/
73
74 #include "gdevstc.h"
75 #ifdef STC_SIGNAL
76 # include <signal.h>
77 #endif /* STC_SIGNAL */
78 /***
79 *** Mode-Table - the various algorithms
80 *** (The intention is, that this source can live alone)
81 ***/
82
83 static stc_proc_dither(stc_gscmyk); /* resides in this file */
84 static stc_proc_dither(stc_hscmyk); /* resides in this file */
85
86 #include <stdlib.h> /* for rand, used in stc_hscmyk */
87
88 static const stc_dither_t stc_dither[] = {
89 {"gscmyk", stc_gscmyk, DeviceCMYK|STC_BYTE|STC_DIRECT,0,{0.0,1.0}},
90 {"hscmyk", stc_hscmyk,
91 DeviceCMYK|STC_LONG|STC_CMYK10|STC_DIRECT|1*STC_SCAN,1+2*4,
92 {0.0, 1023.0}},
93 STC_MODI
94 { NULL , NULL , 0, 0,{0.0,0.0}}
95 };
96
97 /***
98 *** forward-declarations of routines
99 ***/
100
101 /* Primary Device functions
102 * (I've the idea to rename the driver to stc)
103 */
104 static dev_proc_print_page(stc_print_page);
105 static dev_proc_open_device(stc_open);
106 static dev_proc_close_device(stc_close);
107 static dev_proc_get_params(stc_get_params);
108 static dev_proc_put_params(stc_put_params);
109
110 /*
111 * Color-Mapping-functions.
112 */
113
114 /* routines for monochrome monochrome modi */
115 static dev_proc_map_rgb_color(stc_map_gray_color);
116 static dev_proc_map_color_rgb(stc_map_color_gray);
117
118 /* routines for RGB-Modi */
119 static dev_proc_map_rgb_color(stc_map_rgb_color);
120 static dev_proc_map_color_rgb(stc_map_color_rgb);
121
122 /* routines for general CMYK-Modi */
123 static dev_proc_map_cmyk_color(stc_map_cmyk_color);
124 static dev_proc_map_color_rgb(stc_map_color_cmyk);
125
126 /* routines for 10Bit/Component CMYK */
127 static dev_proc_map_cmyk_color(stc_map_cmyk10_color);
128 static dev_proc_map_color_rgb(stc_map_color_cmyk10);
129
130 /***
131 *** Table of Device-Procedures
132 ***/
133 static gx_device_procs stcolor_procs = {
134 stc_open,
135 gx_default_get_initial_matrix,
136 gx_default_sync_output,
137 gdev_prn_output_page,
138 stc_close,
139 NULL,
140 stc_map_color_cmyk,
141 NULL, /* fill_rectangle */
142 NULL, /* tile_rectangle */
143 NULL, /* copy_mono */
144 NULL, /* copy_color */
145 NULL, /* draw_line */
146 gx_default_get_bits,
147 stc_get_params,
148 stc_put_params,
149 stc_map_cmyk_color
150 };
151
152 /***
153 *** A local dummy-array for extvals
154 ***/
155
156 static float defext[] = { 0.0, 1.0 };
157
158 /***
159 *** Main device-control structure
160 ***/
161 stcolor_device far_data gs_stcolor_device = {
162 prn_device_body(stcolor_device, stcolor_procs, "stcolor",
163 DEFAULT_WIDTH_10THS, DEFAULT_HEIGHT_10THS,
164 X_DPI, Y_DPI,
165 STC_L_MARGIN,STC_B_MARGIN,STC_R_MARGIN,STC_T_MARGIN,
166 4, 4, 1, 1, 2, 2, /* default: cmyk-direct */
167 stc_print_page),
168 {STCNWEAVE, /* stcflags: noWeave/bidirectional */
169 1, /* stcbits: matches the default */
170 stc_dither, /* stcdither: first algorithm */
171 NULL, /* stcam: NULL -> not used */
172 { NULL, NULL, NULL, NULL}, /* extcode: none defined yet */
173 { 0, 0, 0, 0}, /* sizcode: 0, since no extcode yet */
174 { NULL, NULL, NULL, NULL}, /* stccode: computed by put_params */
175 {defext,defext,defext,defext},/* extvals: default */
176 { 2, 2, 2, 2}, /* sizvals: default countof(defext) */
177 { NULL, NULL, NULL, NULL}, /* stcvals: computed by put_params */
178 { 0, 0, 0}, /* white-run */
179 { 0, 0, 0}, /* white-end */
180 {NULL,0,false}, /* algorithm-table */
181 {NULL,0,false}, /* initialization-String (BOP) */
182 {NULL,0,false}, /* release-String (EOP) */
183 0,0,0,0, /* New escp-stuff */
184 1} /* itemsize used by algorithm */
185 };
186 /***
187 *** Test for white scan-lines
188 ***/
189 static bool stc_iswhite(stcolor_device *, int, byte *);
190
191 /***
192 *** Functions used for conversion inside the print-loop
193 ***/
194 #define stc_proc_iconvert(Name) \
195 byte * Name(stcolor_device *sd,byte *ext_data,int prt_pixels,byte *alg_line)
196
197 static stc_proc_iconvert(stc_any_depth); /* general input-conversion */
198 static stc_proc_iconvert(stc_rgb24_long); /* 24Bit RGB -> long's */
199
200 static stc_proc_iconvert(stc_cmyk32_long); /* 32Bit CMYK -> long's */
201 static stc_proc_iconvert(stc_any_direct); /* use ext_data as input */
202
203 static stc_proc_iconvert(stc_cmyk10_byte); /* CMYK10->vals-> any type */
204 static stc_proc_iconvert(stc_cmyk10_long); /* CMYK10->vals-> any type */
205 static stc_proc_iconvert(stc_cmyk10_float); /* CMYK10->vals-> any type */
206 static stc_proc_iconvert(stc_cmyk10_dbyte); /* CMYK10 direct bytes */
207 static stc_proc_iconvert(stc_cmyk10_dlong); /* CMYK10 direct longs */
208
209 /***
210 *** Print-functions
211 ***/
212 static void stc_print_weave(stcolor_device *sd,FILE *prn_stream);
213 static void stc_print_bands(stcolor_device *sd,FILE *prn_stream);
214 static void stc_print_delta(stcolor_device *sd,FILE *prn_stream);
215 static int stc_print_setup(stcolor_device *sd);
216
217 /***
218 *** compute the ESC/P2 specific values
219 ***/
220
221 static int
stc_print_setup(stcolor_device * sd)222 stc_print_setup(stcolor_device *sd)
223 {
224
225 /*
226 * Compute the resolution-parameters
227 */
228 sd->stc.escp_u = (int)(3600.0 / sd->y_pixels_per_inch); /* y-units */
229 sd->stc.escp_h = (int)(3600.0 / sd->x_pixels_per_inch); /* x-units */
230 sd->stc.escp_v = sd->stc.flags & (STCUWEAVE | STCNWEAVE) ?
231 sd->stc.escp_u : 40;
232 /*
233 * Initialize color
234 */
235 sd->stc.escp_c = 0; /* preselect-black */
236
237 /*
238 * Band-Width
239 */
240 if((sd->stc.flags & STCBAND) == 0) {
241 if(sd->stc.escp_v != sd->stc.escp_u) sd->stc.escp_m = 15;
242 else if(STCSTCII == (sd->stc.flags & STCMODEL)) sd->stc.escp_m = 1;
243 else if( sd->stc.flags & STCUWEAVE) sd->stc.escp_m = 1;
244 else if((sd->stc.escp_v == sd->stc.escp_u) &&
245 (sd->stc.escp_u == 5)) sd->stc.escp_m = 1;
246 else sd->stc.escp_m = 1;
247 }
248
249 /*
250 * Page-Dimensions
251 */
252 if((sd->stc.flags & STCWIDTH ) == 0)
253 sd->stc.escp_width = (int)(sd->width -
254 (dev_l_margin(sd)+dev_r_margin(sd))*sd->x_pixels_per_inch);
255
256 if((sd->stc.flags & STCHEIGHT) == 0)
257 sd->stc.escp_height = sd->height;
258
259 if((sd->stc.flags & STCTOP) == 0)
260 sd->stc.escp_top = (int)(dev_t_margin(sd)*sd->y_pixels_per_inch);
261
262 if((sd->stc.flags & STCBOTTOM) == 0)
263 sd->stc.escp_bottom = (int)(sd->height -
264 dev_b_margin(sd)*sd->y_pixels_per_inch);
265
266 if((sd->stc.flags & STCINIT) == 0) { /* No Initialization-String defined */
267 int need = 8 /* Reset, Graphics-Mode 1 */
268 + 6 /* MicroWeave */
269 + 6 /* Select Units */
270 + 7 /* Set Page-Length */
271 + 9 /* Set Margins */
272 + 3; /* Select Unidirectionality */
273 byte *bp = (byte *) (sd->stc.escp_init.data);
274
275 if(need != sd->stc.escp_init.size) { /* Reallocate */
276
277 if(NULL != (bp = gs_malloc(sd->memory, need,1,"stcolor/init"))) { /* Replace */
278 if(0 != sd->stc.escp_init.size)
279 gs_free(sd->memory, (byte *)sd->stc.escp_init.data,sd->stc.escp_init.size,1,
280 "stcolor/init");
281 sd->stc.escp_init.data = bp;
282 sd->stc.escp_init.size = need;
283 sd->stc.escp_init.persistent = false;
284 } else { /* Replace */
285 return_error(gs_error_VMerror);
286 }
287 }
288
289 if(need != 39) return_error(gs_error_unregistered);
290
291 memcpy(bp,
292 /* 1 1 11 1 11 1 1 1 2 22 2 2 22 2 22 3 3 3333 3 33*/
293 /* 0 1 2 34 5 6 7 8 90 1 23 4 56 7 8 9 0 12 3 4 56 7 89 0 1 2345 6 78*/
294 "\033@\033(G\001\0\1\033(i\1\0w\033(U\001\000u\033(C\2\000hh\033(c\4\000ttbb\033U",
295 need);
296
297 if((sd->stc.flags & STCUWEAVE) != 0) bp[13] = '\1';
298 else bp[13] = '\0';
299
300 bp[19] = sd->stc.escp_u;
301
302 bp[25] = sd->stc.escp_height & 0xff;
303 bp[26] = (sd->stc.escp_height>>8) & 0xff;
304
305 bp[32] = sd->stc.escp_top & 0xff;
306 bp[33] = (sd->stc.escp_top>>8) & 0xff;
307 bp[34] = sd->stc.escp_bottom & 0xff;
308 bp[35] = (sd->stc.escp_bottom>>8) & 0xff;
309
310 if(sd->stc.flags & STCUNIDIR) bp[38] = 1;
311 else bp[38] = 0;
312
313 } /* No Initialization-String defined */
314
315 if((sd->stc.flags & STCRELEASE) == 0) { /* No Release-String defined */
316 int need = 3; /* ESC @ \f */
317 byte *bp = (byte *) (sd->stc.escp_release.data);
318
319 if(need != sd->stc.escp_release.size) { /* Reallocate */
320
321 if(NULL != (bp = gs_malloc(sd->memory, need,1,"stcolor/release"))) { /* Replace */
322 if(0 != sd->stc.escp_release.size)
323 gs_free(sd->memory, (byte *)sd->stc.escp_release.data,sd->stc.escp_release.size,1,
324 "stcolor/release");
325 sd->stc.escp_release.data = bp;
326 sd->stc.escp_release.size = need;
327 sd->stc.escp_release.persistent = false;
328 } else { /* Replace */
329 return_error(gs_error_VMerror);
330 }
331 }
332
333 if(need != 3) return_error(gs_error_unregistered);
334
335 memcpy(bp,"\033@\f",need);
336
337 } /* No Release-String defined */
338
339 return 0;
340 }
341
342 /***
343 *** stc_print_page: here we go to do the nasty work
344 ***/
345
346 static int
stc_print_page(gx_device_printer * pdev,FILE * prn_stream)347 stc_print_page(gx_device_printer * pdev, FILE * prn_stream)
348 {
349 stcolor_device *sd = (stcolor_device *) pdev;
350 long flags = sd == NULL ? 0 : sd->stc.flags;
351
352 int npass; /* # of print-passes (softweave) */
353
354 int ext_size; /* size of a ghostscript-scanline */
355 byte *ext_line; /* dyn: for this scanline */
356
357 int alg_size; /* size of a scanline for the dithering-algorithm */
358 byte *alg_line; /* dyn: 1 scanline for the dithering-algorithm */
359 int buf_size; /* size of the private-buffer for dither-function */
360 byte *buf; /* dyn: the private buffer */
361
362 int prt_pixels; /* Number of pixels printed */
363 byte *col_line; /* A Line with a byte per pixel */
364
365 #define OK4GO ((flags & STCOK4GO) != 0)
366 #define SORRY ( flags &= ~STCOK4GO)
367
368 if(0 > (npass = stc_print_setup(sd))) return_error(npass);
369
370 npass = sd->stc.escp_v / sd->stc.escp_u;
371
372 /***
373 *** Allocate dynamic memory
374 ***/
375
376 ext_size = gdev_prn_raster(sd);
377 ext_line = gs_malloc(sd->memory, ext_size,1,"stc_print_page/ext_line");
378 if(ext_line == NULL) SORRY;
379
380 prt_pixels = sd->stc.escp_width;
381 sd->stc.prt_size = (prt_pixels+7)/8;
382 prt_pixels = sd->stc.prt_size * 8;
383
384 sd->stc.prt_scans = (int)(sd->height -
385 (dev_t_margin(sd)+dev_b_margin(sd))*sd->y_pixels_per_inch);
386
387 col_line = gs_malloc(sd->memory, prt_pixels,1,"stc_print_page/col_line");
388 if(col_line == NULL) SORRY;
389
390 alg_size = prt_pixels;
391 alg_size *= sd->color_info.num_components;
392
393 if((sd->stc.dither->flags & STC_DIRECT) ||
394 ((sd->stc.bits == 8) &&
395 (sd->stc.alg_item == 1))) {
396 alg_line = NULL;
397 } else {
398 alg_line = gs_malloc(sd->memory, alg_size,sd->stc.alg_item,"stc_print_page/alg_line");
399 if(alg_line == NULL) SORRY;
400 }
401
402 buf_size = sd->stc.dither->bufadd
403 + alg_size*(sd->stc.dither->flags/STC_SCAN);
404 if(buf_size > 0) {
405 buf = gs_malloc(sd->memory, buf_size,sd->stc.alg_item,"stc_print_page/buf");
406 if(buf == NULL) SORRY;
407 } else {
408 buf = NULL;
409 }
410
411 /*
412 * compute the number of printer-buffers
413 */
414
415 for(sd->stc.prt_buf = 16; sd->stc.prt_buf < (sd->stc.escp_m * npass);
416 sd->stc.prt_buf <<= 1);
417 if(sd->color_info.num_components > 1) sd->stc.prt_buf *= 4;
418
419 sd->stc.prt_width = gs_malloc(sd->memory, sd->stc.prt_buf,sizeof(int),
420 "stc_print_page/prt_width");
421 if(sd->stc.prt_width == NULL) SORRY;
422
423 sd->stc.prt_data = gs_malloc(sd->memory, sd->stc.prt_buf,sizeof(byte *),
424 "stc_print_page/prt_data");
425
426 if(sd->stc.prt_data == NULL) {
427 SORRY;
428 } else {
429 int i;
430
431 for(i = 0; i < sd->stc.prt_buf; ++i) {
432 sd->stc.prt_data[i] = gs_malloc(sd->memory, sd->stc.prt_size,1,
433 "stc_print_page/prt");
434 if(sd->stc.prt_data[i] == NULL) SORRY;
435 }
436 }
437
438 sd->stc.seed_size = (sd->stc.prt_size + 2*sizeof(int) - 1)/sizeof(int);
439 {
440 int i;
441 for(i = 0; i < sd->color_info.num_components; ++i) {
442 if((flags & STCCOMP) == STCDELTA) {
443 sd->stc.seed_row[i] = gs_malloc(sd->memory, sd->stc.seed_size,sizeof(int),
444 "stc_print_page/seed_row");
445 if(sd->stc.seed_row[i] == NULL) SORRY;
446 else memset(sd->stc.seed_row[i],0,sd->stc.seed_size*sizeof(int));
447 } else {
448 sd->stc.seed_row[i] = NULL;
449 }
450 }
451 while(i < countof(sd->stc.seed_row)) sd->stc.seed_row[i++] = NULL;
452 }
453
454 switch(flags & STCCOMP) {
455 case STCPLAIN:
456 sd->stc.escp_size = 64 + sd->stc.prt_size;
457 break;
458 case STCDELTA:
459 sd->stc.escp_size = 64 + 2 * sd->stc.prt_size;
460 break;
461 default:
462 sd->stc.escp_size = 64 +
463 sd->stc.prt_size + (sd->stc.prt_size + 127)/128;
464 break;
465 }
466
467 sd->stc.escp_data = gs_malloc(sd->memory, sd->stc.escp_size,1,
468 "stc_print_page/escp_data");
469 if(sd->stc.escp_data == NULL) SORRY;
470
471 /*
472 * If we're still ok, we can print something
473 */
474
475 if(OK4GO) {
476
477 int ncolor;
478 int buf_i;
479 stc_proc_iconvert((*iconvert)) = stc_any_depth;
480
481 /*
482 * initialize col_line
483 */
484 if(sd->color_info.num_components == 3) {
485 memset(col_line,RED|GREEN|BLUE,prt_pixels);
486 } else {
487 memset(col_line,0, prt_pixels);
488 }
489
490 /*
491 * select proper conversion for input to algorithm
492 */
493 if( (sd->stc.dither->flags & STC_DIRECT ) ||
494 ((sd->stc.bits == 8) &&
495 (sd->stc.alg_item == 1)))
496 iconvert = stc_any_direct;
497 else if((sd->color_info.num_components == 3) &&
498 (sd->color_info.depth == 24) &&
499 (sizeof(long) == sd->stc.alg_item))
500 iconvert = stc_rgb24_long;
501 else if(sd->stc.flags & STCCMYK10) {
502 if( ((sd->stc.dither->flags & STC_TYPE) == STC_BYTE) &&
503 ( sd->stc.dither->minmax[0] == 0.0 ))
504 iconvert = stc_cmyk10_dbyte;
505 else if ((sd->stc.dither->flags & STC_TYPE) == STC_BYTE)
506 iconvert = stc_cmyk10_byte;
507 else if(((sd->stc.dither->flags & STC_TYPE) == STC_LONG) &&
508 ( sd->stc.dither->minmax[0] == 0.0 ) &&
509 ( sd->stc.dither->minmax[1] <= 1023.0 ))
510 iconvert = stc_cmyk10_dlong;
511 else if( (sd->stc.dither->flags & STC_TYPE) == STC_LONG)
512 iconvert = stc_cmyk10_long;
513 else
514 iconvert = stc_cmyk10_float;
515 }
516 else if((sd->color_info.num_components == 4) &&
517 (sd->color_info.depth == 32) &&
518 (sizeof(long) == sd->stc.alg_item))
519 iconvert = stc_cmyk32_long;
520
521 /*
522 * initialize the algorithm
523 */
524
525 if((*sd->stc.dither->fun)(sd,-prt_pixels,alg_line,buf,col_line) < 0)
526 SORRY;
527
528 /*
529 * Main-Print-Loop
530 */
531
532 if(OK4GO) {
533 #ifdef STC_SIGNAL
534 sigset_t stc_int_mask, stc_int_save, stc_int_pending;
535
536 sigemptyset(&stc_int_mask);
537 sigaddset(&stc_int_mask,SIGINT);
538 sigprocmask(SIG_BLOCK,&stc_int_mask, &stc_int_save);
539 #endif /* STC_SIGNAL */
540
541 if(sd->color_info.num_components > 1) ncolor = 4;
542 else ncolor = 1;
543
544 /*
545 * Decide, wether we Adjust Linefeeds or not. (I hate it here)
546 */
547 if((0 == ((sd->stc.escp_m*sd->stc.escp_u) % 10)) &&
548 (256 > ((sd->stc.escp_m*sd->stc.escp_u) / 10))) sd->stc.escp_lf = sd->stc.escp_m;
549 else sd->stc.escp_lf = 0;
550
551 /*
552 * prepare run-values, then loop over scans
553 */
554 sd->stc.stc_y = 0; /* current printer y-Position */
555 sd->stc.buf_y = 0; /* Top-Position within the buffer */
556 sd->stc.prt_y = 0; /* physical position of the printer */
557 buf_i = 0; /* next free line in buffer */
558 sd->stc.flags &= ~STCPRINT; /* no data yet */
559
560 while(sd->stc.stc_y < sd->stc.prt_scans) { /* Until all scans are processed */
561 int need;
562
563 need = sd->stc.stc_y + npass * sd->stc.escp_m;
564
565 if(sd->stc.buf_y < need) { /* Nr. 5 (give me input) */
566
567 /* read as much as the buffer can hold */
568 if(ncolor == 1) need = sd->stc.stc_y + sd->stc.prt_buf;
569 else need = sd->stc.stc_y + (sd->stc.prt_buf>>2);
570
571 for(;sd->stc.buf_y < need;
572 buf_i = (sd->stc.prt_buf-1) & (buf_i+ncolor),
573 ++sd->stc.buf_y) {
574
575 int color;
576 byte *ext_data;
577 byte *alg_data;
578
579 /* initialize output data 1st -> may take shortcut */
580
581 for(color = 0; color < ncolor; ++color) {
582 memset(sd->stc.prt_data[buf_i+color],0,sd->stc.prt_size);
583 sd->stc.prt_width[buf_i+color] = 0;
584 }
585
586 /* "read data", immediately continue if all is white */
587
588 if(sd->stc.buf_y < sd->stc.prt_scans) { /* Test for White */
589
590 gdev_prn_get_bits(pdev,sd->stc.buf_y,ext_line,&ext_data);
591
592 color = stc_iswhite(sd,prt_pixels,ext_data) ? ext_size : 0;
593
594 } else {
595
596 color = ext_size;
597
598 } /* Test for White */
599
600 if(color >= ext_size) { /* bypass processing */
601
602 if(sd->stc.dither->flags & STC_WHITE)
603 (*sd->stc.dither->fun)(sd,prt_pixels,NULL,buf,col_line);
604 continue;
605
606 } /* bypass processing */
607
608 /* convert data for the various cases */
609
610 alg_data = (*iconvert)(sd,ext_data,prt_pixels,alg_line);
611
612 /*
613 * invoke the dithering-algorithm
614 */
615
616 (*sd->stc.dither->fun)(sd,prt_pixels,alg_data,buf,col_line);
617 /*
618 * convert col_line to printer-format (separate colors)
619 */
620 switch(sd->color_info.num_components) {
621 case 1: /* Black & White: just merge into 8 Bytes */
622 {
623 byte *bytein,*byteout;
624 int width;
625
626 bytein = col_line;
627 byteout = sd->stc.prt_data[buf_i];
628
629 for(width = 1; width <= sd->stc.prt_size; ++width) {
630 byte tmp = 0;
631 byte i;
632
633 for(i = 128; i; i >>= 1) if(*bytein++) tmp |= i;
634
635 if(tmp != 0) sd->stc.prt_width[buf_i] = width;
636
637 *byteout++ = tmp;
638 }
639 }
640 break;
641 case 3: /* convert rgb into cmyk */
642 {
643 byte *bytein;
644 int width;
645
646 bytein = col_line;
647
648 for(width = 0; width < sd->stc.prt_size; ++width) {
649 byte i,tmp,cmyk[4];
650
651 memset(cmyk,0,4);
652
653 for(i = 128; i; i >>= 1) {
654 static const byte rgb2cmyk[] = {
655 BLACK, /* 0->Black */
656 CYAN | MAGENTA, /* 1->BLUE */
657 CYAN | YELLOW, /* 2->GREEN */
658 CYAN, /* 3->CYAN */
659 MAGENTA | YELLOW, /* 4->RED */
660 MAGENTA, /* 5->MAGENTA */
661 YELLOW, /* 6->YELLOW */
662 0}; /* 7->WHITE */
663
664 tmp = rgb2cmyk[(*bytein++) & 7];
665
666 if(tmp & BLACK) cmyk[3] |= i;
667 if(tmp & YELLOW) cmyk[2] |= i;
668 if(tmp & MAGENTA) cmyk[1] |= i;
669 if(tmp & CYAN) cmyk[0] |= i;
670 }
671
672 for(i = 0; i < 4; ++i) {
673 if(cmyk[i] != 0) sd->stc.prt_width[buf_i+i] = width+1;
674 sd->stc.prt_data[buf_i+i][width] = cmyk[i];
675 }
676 }
677 }
678 break;
679 case 4: /* split cmyk */
680 {
681 byte *bytein;
682 int width;
683
684 bytein = col_line;
685
686 for(width = 0; width < sd->stc.prt_size; ++width) {
687 byte i,tmp,cmyk[4];
688
689 memset(cmyk,0,4);
690
691 for(i = 128; i; i >>= 1) {
692 tmp = (*bytein++) & 15;
693 if(tmp & BLACK) cmyk[3] |= i;
694 if(tmp & YELLOW) cmyk[2] |= i;
695 if(tmp & MAGENTA) cmyk[1] |= i;
696 if(tmp & CYAN) cmyk[0] |= i;
697 }
698
699 for(i = 0; i < 4; ++i) {
700 if(cmyk[i] != 0) sd->stc.prt_width[buf_i+i] = width+1;
701 sd->stc.prt_data[buf_i+i][width] = cmyk[i];
702 }
703 }
704 }
705 break;
706 default: break;
707 }
708 }
709 } /* Nr. 5 (give me input) */
710
711 /*
712 * Nr. 5 has got enough input, now we should print it
713 */
714 if((flags & STCCOMP) == STCDELTA) stc_print_delta(sd,prn_stream);
715 else if(npass > 1) stc_print_weave(sd,prn_stream);
716 else stc_print_bands(sd,prn_stream);
717
718 #ifdef STC_SIGNAL
719 sigpending(&stc_int_pending);
720 if(sigismember(&stc_int_pending,SIGINT)) {
721 fputs("\033@[Aborted]\f", prn_stream);
722 fflush(prn_stream);
723 sigprocmask(SIG_SETMASK,&stc_int_save,NULL);
724 break;
725 }
726 #endif /* STC_SIGNAL */
727
728 } /* Until all scans are processed */
729
730 if(sd->stc.flags & STCPRINT) {
731 if((flags & STCCOMP) == STCDELTA) fputc(0xe3,prn_stream);
732 fwrite(sd->stc.escp_release.data,1,sd->stc.escp_release.size,prn_stream);
733 fflush(prn_stream);
734 }
735 #ifdef STC_SIGNAL
736 sigprocmask(SIG_SETMASK,&stc_int_save,NULL);
737 #endif /* STC_DIGNAL */
738
739 }
740 }
741
742 /***
743 *** Release the dynamic memory
744 ***/
745
746 if(ext_line != NULL)
747 gs_free(sd->memory, ext_line,ext_size,1,"stc_print_page/ext_line");
748
749 if(col_line != NULL)
750 gs_free(sd->memory, col_line,prt_pixels,1,"stc_print_page/col_line");
751
752 if(alg_line != NULL)
753 gs_free(sd->memory, alg_line,alg_size,sd->stc.alg_item,
754 "stc_print_page/alg_line");
755
756 if(buf != NULL)
757 gs_free(sd->memory, buf,buf_size,sd->stc.alg_item,"stc_print_page/buf");
758
759 if(sd->stc.prt_width != NULL)
760 gs_free(sd->memory, sd->stc.prt_width,sd->stc.prt_buf,sizeof(int),
761 "stc_print_page/prt_width");
762
763 if(sd->stc.prt_data != NULL) {
764 int i;
765
766 for(i = 0; i < sd->stc.prt_buf; ++i) {
767 if(sd->stc.prt_data[i] != NULL)
768 gs_free(sd->memory, sd->stc.prt_data[i],sd->stc.prt_size,1,
769 "stc_print_page/prt");
770 }
771
772 gs_free(sd->memory, sd->stc.prt_data,sd->stc.prt_buf,sizeof(byte *),
773 "stc_print_page/prt_data");
774 }
775
776 {
777 int i;
778 for(i = 0; i < sd->color_info.num_components; ++i) {
779 if(sd->stc.seed_row[i] != NULL)
780 gs_free(sd->memory, sd->stc.seed_row[i],sd->stc.seed_size,sizeof(int),
781 "stc_print_page/seed_row");
782 }
783 }
784
785 if(sd->stc.escp_data != NULL)
786 gs_free(sd->memory, sd->stc.escp_data,sd->stc.escp_size,1,
787 "stc_print_page/escp_data");
788
789 return OK4GO ? 0 : gs_error_undefined;
790 }
791
792 /*
793 * white-check
794 */
795 static bool
stc_iswhite(stcolor_device * sd,int prt_pixels,byte * ext_data)796 stc_iswhite(stcolor_device *sd, int prt_pixels,byte *ext_data)
797 {
798 long b2do = (prt_pixels*sd->color_info.depth+7)>>3;
799 int bcmp = 4 * countof(sd->stc.white_run);
800 byte *wht = (byte *) sd->stc.white_run;
801
802 while(b2do >= bcmp) {
803 if(memcmp(ext_data,wht,bcmp)) break;
804 ext_data += bcmp;
805 b2do -= bcmp;
806 }
807
808 if((b2do > 0) && (b2do < bcmp))
809 b2do = memcmp(ext_data,sd->stc.white_end,b2do);
810
811 return b2do ? false : true;
812 }
813
814 /***
815 *** A bunch of routines that convert gslines into algorithms format.
816 ***/
817 static byte *
stc_any_depth(stcolor_device * sd,byte * ext_data,int prt_pixels,byte * alg_line)818 stc_any_depth(stcolor_device *sd,byte *ext_data,int prt_pixels,byte *alg_line)
819 { /* general conversion */
820
821 int p,c, niext, nbits;
822 gx_color_index ciext,ci,cimsk,cvmsk;
823 byte *ap = alg_line;
824
825 nbits = sd->stc.bits;
826 cvmsk = ((gx_color_index) 1<<nbits) - 1;
827
828 /* it is nonsense to use this algorithm for this cases, but if it claims
829 * generality, it should deliver correct results in this cases too */
830 if(sd->color_info.depth == (sd->color_info.num_components<<3)) nbits = 8;
831
832 cimsk = cvmsk;
833 for(c = 1; c < sd->color_info.num_components; ++c)
834 cimsk = (cimsk<<nbits) | cvmsk;
835
836 ciext = 0;
837 niext = 0;
838
839 for(p = 0; p < prt_pixels; ++p) { /* over pixels */
840
841 ci = ciext;
842 for(c = sd->color_info.depth-niext; c >= 8; c -= 8)
843 ci = (ci<<8) | *ext_data++;
844
845 if(c > 0) { /* partial byte required */
846
847 niext = 8 - c;
848 ciext = *ext_data++;
849 ci = (ci<<c) | (ciext>>niext);
850 ciext &= (1L<<niext)-1;
851
852 } else if(c < 0) { /* some bits left in ciext */
853
854 niext = -c;
855 ciext &= (1L<<niext)-1;
856 ci = ci>>niext;
857
858 } else { /* entire ciext used */
859
860 niext = 0;
861 ciext = 0;
862
863 } /* ciext-adjust */
864
865 ci &= cimsk;
866
867 # define stc_storeapc(T) \
868 ((T *)ap)[c] = ((T *)(sd->stc.vals[c]))[ci & cvmsk];
869
870 for(c = sd->color_info.num_components; c--;) { /* comp */
871 STC_TYPESWITCH(sd->stc.dither,stc_storeapc)
872 ci >>= nbits;
873 } /* comp */
874
875 # undef stc_storeapc
876
877 ap += sd->color_info.num_components * sd->stc.alg_item;
878
879 } /* over pixels */
880
881 return alg_line;
882 } /* general conversion */
883
884 /*
885 * rgb-data with depth=24, can use a faster algorithm
886 */
887 static byte *
stc_rgb24_long(stcolor_device * sd,byte * ext_data,int prt_pixels,byte * alg_line)888 stc_rgb24_long(stcolor_device *sd,byte *ext_data,int prt_pixels,byte *alg_line)
889 { /* convert 3 bytes into appropriate long-Values */
890 register int p;
891 register long *out = (long *) alg_line;
892 register long *rvals = (long *) (sd->stc.vals[0]);
893 register long *gvals = (long *) (sd->stc.vals[1]);
894 register long *bvals = (long *) (sd->stc.vals[2]);
895
896 for(p = prt_pixels; p; --p) {
897 *out++ = rvals[*ext_data++];
898 *out++ = gvals[*ext_data++];
899 *out++ = bvals[*ext_data++];
900 }
901
902 return alg_line;
903 } /* convert 3 bytes into appropriate long-Values */
904
905 /*
906 * cmyk-data with depth=32, can use a faster algorithm
907 */
908 static byte *
stc_cmyk32_long(stcolor_device * sd,byte * ext_data,int prt_pixels,byte * alg_line)909 stc_cmyk32_long(stcolor_device *sd,byte *ext_data,int prt_pixels,byte *alg_line)
910 { /* convert 4 bytes into appropriate long-Values */
911 register int p;
912 register long *out = (long *) alg_line;
913 register long *cvals = (long *) (sd->stc.vals[0]);
914 register long *mvals = (long *) (sd->stc.vals[1]);
915 register long *yvals = (long *) (sd->stc.vals[2]);
916 register long *kvals = (long *) (sd->stc.vals[3]);
917
918 for(p = prt_pixels; p; --p) {
919 *out++ = cvals[*ext_data++];
920 *out++ = mvals[*ext_data++];
921 *out++ = yvals[*ext_data++];
922 *out++ = kvals[*ext_data++];
923 }
924
925 return alg_line;
926 } /* convert 4 bytes into appropriate long-Values */
927
928 /*
929 * handle indirect encoded cmyk-data
930 */
931 #define STC_CMYK10_ANY(T)\
932 \
933 register int p = prt_pixels; \
934 register stc_pixel ci,k,n,mode; \
935 register stc_pixel *in = (stc_pixel *) ext_data; \
936 register T *out = (T *) alg_line; \
937 register T *cv = (T *) sd->stc.vals[0]; \
938 register T *mv = (T *) sd->stc.vals[1]; \
939 register T *yv = (T *) sd->stc.vals[2]; \
940 register T *kv = (T *) sd->stc.vals[3]; \
941 \
942 while(p--) { \
943 ci = *in++; \
944 mode = ci & 3; \
945 k = (ci>>2) & 0x3ff; \
946 if(mode == 3) { \
947 *out++ = cv[0]; \
948 *out++ = mv[0]; \
949 *out++ = yv[0]; \
950 *out++ = kv[k]; \
951 } else { \
952 out[3] = kv[k]; \
953 n = (ci>>12) & 0x3ff; \
954 if(mode == 2) { out[2] = yv[k]; } \
955 else { out[2] = yv[n]; n = (ci>>22) & 0x3ff; } \
956 if(mode == 1) { out[1] = mv[k]; } \
957 else { out[1] = mv[n]; n = (ci>>22) & 0x3ff; } \
958 if(mode == 0) out[0] = cv[k]; \
959 else out[0] = cv[n]; \
960 out += 4; \
961 } \
962 } \
963 \
964 return alg_line;
965
966 static byte *
stc_cmyk10_byte(stcolor_device * sd,byte * ext_data,int prt_pixels,byte * alg_line)967 stc_cmyk10_byte(stcolor_device *sd,
968 byte *ext_data,int prt_pixels,byte *alg_line)
969 {
970 STC_CMYK10_ANY(byte)
971 }
972 static byte *
stc_cmyk10_long(stcolor_device * sd,byte * ext_data,int prt_pixels,byte * alg_line)973 stc_cmyk10_long(stcolor_device *sd,
974 byte *ext_data,int prt_pixels,byte *alg_line)
975 {
976 STC_CMYK10_ANY(long)
977 }
978 static byte *
stc_cmyk10_float(stcolor_device * sd,byte * ext_data,int prt_pixels,byte * alg_line)979 stc_cmyk10_float(stcolor_device *sd,
980 byte *ext_data,int prt_pixels,byte *alg_line)
981 {
982 STC_CMYK10_ANY(float)
983 }
984
985 #undef STC_CMYK10_ANY
986
987 #define STC_CMYK10_DANY(T)\
988 \
989 register int p = prt_pixels; \
990 register stc_pixel ci,k,n,mode; \
991 register stc_pixel *in = (stc_pixel *) ext_data; \
992 register T *out = (T *) alg_line; \
993 \
994 while(p--) { \
995 ci = *in++; \
996 mode = ci & 3; \
997 k = (ci>>2) & 0x3ff; \
998 if(mode == 3) { \
999 *out++ = 0; \
1000 *out++ = 0; \
1001 *out++ = 0; \
1002 *out++ = k; \
1003 } else { \
1004 out[3] = k; \
1005 n = (ci>>12) & 0x3ff; \
1006 if(mode == 2) { out[2] = k; } \
1007 else { out[2] = n; n = (ci>>22) & 0x3ff; } \
1008 if(mode == 1) { out[1] = k; } \
1009 else { out[1] = n; n = (ci>>22) & 0x3ff; } \
1010 if(mode == 0) out[0] = k; \
1011 else out[0] = n; \
1012 out += 4; \
1013 } \
1014 } \
1015 \
1016 return alg_line;
1017
1018 static byte *
stc_cmyk10_dbyte(stcolor_device * sd,byte * ext_data,int prt_pixels,byte * alg_line)1019 stc_cmyk10_dbyte(stcolor_device *sd,
1020 byte *ext_data,int prt_pixels,byte *alg_line)
1021 {
1022 STC_CMYK10_DANY(byte)
1023 }
1024 static byte *
stc_cmyk10_dlong(stcolor_device * sd,byte * ext_data,int prt_pixels,byte * alg_line)1025 stc_cmyk10_dlong(stcolor_device *sd,
1026 byte *ext_data,int prt_pixels,byte *alg_line)
1027 {
1028 STC_CMYK10_DANY(long)
1029 }
1030
1031 #undef STC_CMYK10_DANY
1032
1033 /*
1034 * if the algorithm uses bytes & bytes are in ext_data, use them
1035 */
1036 /*ARGSUSED*/
1037 static byte *
stc_any_direct(stcolor_device * sd,byte * ext_data,int prt_pixels,byte * alg_line)1038 stc_any_direct(stcolor_device *sd,byte *ext_data,int prt_pixels,byte *alg_line)
1039 { /* return ext_data */
1040 return ext_data;
1041 } /* return ext_data */
1042
1043 /* ----------------------------------------------------------------------- */
1044 /* stc_rle: epson ESC/P2 RLE-Encoding
1045 */
1046 static int
stc_rle(byte * out,const byte * in,int width)1047 stc_rle(byte *out,const byte *in,int width)
1048 {
1049
1050 int used = 0;
1051 int crun,cdata;
1052 byte run;
1053
1054 if(in != NULL) { /* Data present */
1055
1056 crun = 1;
1057
1058 while(width > 0) { /* something to compress */
1059
1060 run = in[0];
1061
1062 while((width > crun) && (run == in[crun])) if(++crun == 129) break;
1063
1064 if((crun > 2) || (crun == width)) { /* use this run */
1065
1066 *out++ = (257 - crun) & 0xff; *out++ = run; used += 2;
1067
1068 width -= crun; in += crun;
1069 crun = 1;
1070
1071 } else { /* ignore this run */
1072
1073 for(cdata = crun; (width > cdata) && (crun < 4);) {
1074 if(run == in[cdata]) crun += 1;
1075 else run = in[cdata], crun = 1;
1076 if(++cdata == 128) break;
1077 }
1078
1079 if(crun < 3) crun = 0; /* ignore trailing run */
1080 else cdata -= crun;
1081
1082 *out++ = cdata-1; used++;
1083 memcpy(out,in,cdata); used += cdata; out += cdata;
1084
1085 width -= cdata; in += cdata;
1086
1087 } /* use/ignore run */
1088
1089 } /* something to compress */
1090
1091 } else { /* Empty scans to fill bands */
1092
1093 while(width > 0) {
1094 crun = width > 129 ? 129 : width;
1095 width -= crun;
1096 *out++ = (257 - crun) & 0xff;
1097 *out++ = 0;
1098 used += 2;
1099 }
1100 } /* Data present or empty */
1101 return used;
1102 }
1103
1104 /*
1105 * Horizontal & vertical positioning, color-selection, "ESC ."
1106 */
1107 static int
stc_print_escpcmd(stcolor_device * sd,FILE * prn_stream,int escp_used,int color,int m,int wbytes)1108 stc_print_escpcmd(stcolor_device *sd, FILE *prn_stream,
1109 int escp_used, int color,int m,int wbytes)
1110 {
1111
1112 int dy = sd->stc.stc_y - sd->stc.prt_y; /* number of units to skip */
1113 int nlf;
1114
1115 /* ESC-R color codes, used only here */
1116 static const byte stc_colors[] = { 0x02, 0x01, 0x04, 0x00 }; /* CMYK */
1117
1118 /*
1119 * initialize the printer, if necessary
1120 */
1121 if(0 == (sd->stc.flags & STCPRINT)) {
1122
1123 fwrite(sd->stc.escp_init.data,1,sd->stc.escp_init.size,prn_stream);
1124
1125 if(0 < sd->stc.escp_lf) { /* Adjust Linefeed */
1126 fputc('\033', prn_stream);
1127 fputc('+', prn_stream);
1128 fputc(((sd->stc.escp_m*sd->stc.escp_u) / 10),prn_stream);
1129 } /* Adjust Linefeed */
1130 sd->stc.flags |= STCPRINT;
1131 }
1132
1133 sd->stc.escp_data[escp_used++] = '\r'; /* leftmost position */
1134
1135 if(dy) { /* position the printer */
1136 if(( sd->stc.escp_lf > 0) && /* Linefeed allowed */
1137 ((dy % sd->stc.escp_lf) == 0)) /* and possible */
1138 nlf = dy / sd->stc.escp_lf;
1139 else nlf = 7;
1140
1141 if(nlf > 6) {
1142 sd->stc.escp_data[escp_used++] = '\033';
1143 sd->stc.escp_data[escp_used++] = '(';
1144 sd->stc.escp_data[escp_used++] = 'V';
1145 sd->stc.escp_data[escp_used++] = '\002';
1146 sd->stc.escp_data[escp_used++] = '\000';
1147 sd->stc.escp_data[escp_used++] = sd->stc.stc_y & 0xff;
1148 sd->stc.escp_data[escp_used++] = (sd->stc.stc_y >> 8) & 0xff;
1149 } else {
1150 while(nlf--) sd->stc.escp_data[escp_used++] = '\n';
1151 }
1152 sd->stc.prt_y = sd->stc.stc_y;
1153 } /* position the printer */
1154
1155 if((sd->color_info.num_components > 1) &&
1156 (sd->stc.escp_c != stc_colors[color])) { /* select color */
1157 sd->stc.escp_data[escp_used++] = '\033';
1158 sd->stc.escp_data[escp_used++] = 'r';
1159 sd->stc.escp_c = stc_colors[color];
1160 sd->stc.escp_data[escp_used++] = sd->stc.escp_c;
1161 } /* select color */
1162
1163 /*
1164 * Build the command used
1165 */
1166 sd->stc.escp_data[escp_used++] = '\033';
1167 sd->stc.escp_data[escp_used++] = '.';
1168 sd->stc.escp_data[escp_used++] =
1169 (sd->stc.flags & STCCOMP) == STCPLAIN ? 0 : 1;
1170 sd->stc.escp_data[escp_used++] = sd->stc.escp_v;
1171 sd->stc.escp_data[escp_used++] = sd->stc.escp_h;
1172 sd->stc.escp_data[escp_used++] = m;
1173 sd->stc.escp_data[escp_used++] = (wbytes<<3) & 0xff; /* width in Pixels */
1174 sd->stc.escp_data[escp_used++] = (wbytes>>5) & 0xff;
1175
1176 return escp_used;
1177 }
1178
1179 /*
1180 * compute width of a group of scanlines
1181 */
1182 static int
stc_bandwidth(stcolor_device * sd,int color,int m,int npass)1183 stc_bandwidth(stcolor_device *sd,int color,int m,int npass)
1184 {
1185 int ncolor = sd->color_info.num_components == 1 ? 1 : 4;
1186 int buf_a = (sd->stc.prt_buf-1) & (sd->stc.stc_y * ncolor + color);
1187 int w = 0;
1188
1189 while(m-- > 0) { /* check width */
1190 if(sd->stc.prt_width[buf_a] > w) w = sd->stc.prt_width[buf_a];
1191 buf_a = (sd->stc.prt_buf-1) & (buf_a + ncolor * npass);
1192 } /* check width */
1193
1194 return w;
1195 }
1196
1197 /*
1198 * Multi-Pass Printing-Routine
1199 */
1200 static void
stc_print_weave(stcolor_device * sd,FILE * prn_stream)1201 stc_print_weave(stcolor_device *sd, FILE *prn_stream)
1202 {
1203
1204 int escp_used,nprint,nspace,color,buf_a,iprint,w;
1205
1206 int npass = sd->stc.escp_v / sd->stc.escp_u;
1207 int ncolor = sd->color_info.num_components == 1 ? 1 : 4;
1208
1209 while(sd->stc.stc_y < sd->stc.prt_scans) {
1210
1211 /*
1212 * compute spacing & used heads (seems to work with odd escp_m)
1213 */
1214 if(sd->stc.stc_y >= sd->stc.escp_m) { /* in normal mode */
1215 nprint = sd->stc.escp_m;
1216 nspace = sd->stc.escp_m;
1217 } else if((sd->stc.stc_y) < npass) { /* initialisation */
1218 nprint = sd->stc.escp_m - sd->stc.stc_y * ((sd->stc.escp_m+1)/npass);
1219 nspace = 1;
1220 } else { /* switch to normal */
1221 nprint = sd->stc.escp_m - sd->stc.stc_y * ((sd->stc.escp_m+1)/npass);
1222 nspace = sd->stc.escp_m - sd->stc.stc_y;
1223 }
1224 iprint = sd->stc.stc_y + npass * nprint;
1225 if(sd->stc.buf_y < iprint) break;
1226
1227 escp_used = 0;
1228 for(color = 0; color < ncolor; ++color) { /* print the colors */
1229
1230 if(0 == (w = stc_bandwidth(sd,color,nprint,npass))) continue;
1231
1232 escp_used = stc_print_escpcmd(sd,prn_stream,
1233 escp_used,color,sd->stc.escp_m,w);
1234
1235 buf_a = (sd->stc.prt_buf-1) & (sd->stc.stc_y * ncolor + color);
1236 for(iprint = 0; iprint < nprint; ++iprint) { /* send data */
1237
1238 if((sd->stc.flags & STCCOMP) == STCPLAIN) {
1239 memcpy(sd->stc.escp_data+escp_used,sd->stc.prt_data[buf_a],w);
1240 escp_used += w;
1241 } else {
1242 escp_used += stc_rle(sd->stc.escp_data+escp_used,
1243 sd->stc.prt_data[buf_a],w);
1244 }
1245
1246 fwrite(sd->stc.escp_data,1,escp_used,prn_stream);
1247 escp_used = 0;
1248
1249 buf_a = (sd->stc.prt_buf-1) & (buf_a + ncolor * npass);
1250
1251 } /* send data */
1252
1253 while(iprint++ < sd->stc.escp_m) { /* add empty rows */
1254
1255 if((sd->stc.flags & STCCOMP) == STCPLAIN) {
1256 memset(sd->stc.escp_data+escp_used,0,w);
1257 escp_used += w;
1258 } else {
1259 escp_used += stc_rle(sd->stc.escp_data+escp_used,NULL,w);
1260 }
1261
1262 fwrite(sd->stc.escp_data,1,escp_used,prn_stream);
1263 escp_used = 0;
1264 } /* add empty rows */
1265 } /* print the colors */
1266
1267 sd->stc.stc_y += nspace;
1268 }
1269 }
1270
1271 /*
1272 * Single-Pass printing-Routine
1273 */
1274 static void
stc_print_bands(stcolor_device * sd,FILE * prn_stream)1275 stc_print_bands(stcolor_device *sd, FILE *prn_stream)
1276 {
1277
1278 int escp_used,color,buf_a,iprint,w,m;
1279
1280 int ncolor = sd->color_info.num_components == 1 ? 1 : 4;
1281
1282 while(sd->stc.stc_y < sd->stc.prt_scans) {
1283
1284 /*
1285 * find the begin of the band
1286 */
1287 for(w = 0; sd->stc.stc_y < sd->stc.buf_y; ++sd->stc.stc_y) {
1288 buf_a = (sd->stc.prt_buf-1) & (sd->stc.stc_y * ncolor);
1289 for(color = 0; color < ncolor; ++color)
1290 if(sd->stc.prt_width[buf_a+color] > w)
1291 w = sd->stc.prt_width[buf_a+color];
1292 if(w != 0) break;
1293 }
1294 if(w == 0) break;
1295 /*
1296 * adjust the band-height
1297 */
1298 w = sd->stc.prt_scans - sd->stc.stc_y;
1299 if((w < sd->stc.escp_m) && (sd->stc.escp_v != 40)) {
1300 if(w < 8) m = 1;
1301 else if(w < 24) m = 8;
1302 else m = 24;
1303 } else {
1304 m = sd->stc.escp_m;
1305 }
1306
1307 if(sd->stc.buf_y < (sd->stc.stc_y+m)) break;
1308
1309 escp_used = 0;
1310 for(color = 0; color < ncolor; ++color) { /* print the colors */
1311
1312 if(0 == (w = stc_bandwidth(sd,color,m,1))) continue; /* shortcut */
1313
1314 escp_used = stc_print_escpcmd(sd,prn_stream,escp_used,color,m,w);
1315
1316 buf_a = (sd->stc.prt_buf-1) & (sd->stc.stc_y * ncolor + color);
1317 for(iprint = 0; iprint < m; ++iprint) { /* send data */
1318
1319 if((sd->stc.flags & STCCOMP) == STCPLAIN) {
1320 memcpy(sd->stc.escp_data+escp_used,sd->stc.prt_data[buf_a],w);
1321 escp_used += w;
1322 } else {
1323 escp_used += stc_rle(sd->stc.escp_data+escp_used,
1324 sd->stc.prt_data[buf_a],w);
1325 }
1326
1327 fwrite(sd->stc.escp_data,1,escp_used,prn_stream);
1328 escp_used = 0;
1329
1330 buf_a = (sd->stc.prt_buf-1) & (buf_a + ncolor);
1331
1332 } /* send data */
1333
1334 } /* print the colors */
1335
1336 sd->stc.stc_y += m;
1337 }
1338 }
1339 /* ----------------------------------------------------------------------- */
1340
1341 static int
stc_deltarow(byte * out,const byte * in,int width,byte * seed)1342 stc_deltarow(byte *out,const byte *in,int width,byte *seed)
1343 {
1344
1345 int istop,nmove,ndata,i,j;
1346 int *wseed = (int *) seed;
1347 int used = 0;
1348
1349 seed += sizeof(int);
1350
1351 if((in != NULL) && (width > 0)) { /* Data present */
1352
1353 istop = width < wseed[0] ? wseed[0] : width;
1354
1355 i = 0;
1356 while(i < istop) {
1357
1358 for(j = i; j < istop; ++j) if(in[j] != seed[j]) break;
1359
1360 nmove = j - i;
1361
1362 if(nmove > 0) { /* issue a move */
1363 i = j;
1364 if(i == istop) break;
1365
1366 if( nmove < 8) {
1367 out[used++] = 0x40 | nmove;
1368 } else if(nmove < 128) {
1369 out[used++] = 0x51;
1370 out[used++] = nmove;
1371 } else {
1372 out[used++] = 0x52;
1373 out[used++] = 0xff & nmove;
1374 out[used++] = 0xff & (nmove>>8);
1375 }
1376 } /* issue a move */
1377
1378 /*
1379 * find the end of this run
1380 */
1381 nmove = 0;
1382 for(j = i+1; (j < istop) && ((nmove < 4)); ++j) {
1383 if(in[j] == seed[j]) nmove += 1;
1384 else nmove = 0;
1385 }
1386
1387 ndata = j-i-nmove;
1388
1389 nmove = stc_rle(out+used+3,in+i,ndata);
1390 if(nmove < 16) {
1391 out[used++] = 0x20 | nmove;
1392 for(j = 0; j < nmove; ++j) out[used+j] = out[used+j+2];
1393 } else if(nmove < 256) {
1394 out[used++] = 0x31;
1395 out[used++] = nmove;
1396 for(j = 0; j < nmove; ++j) out[used+j] = out[used+j+1];
1397 } else {
1398 out[used++] = 0x32;
1399 out[used++] = 0xff & nmove;
1400 out[used++] = 0xff & (nmove>>8);
1401 }
1402 used += nmove;
1403 i += ndata;
1404 }
1405
1406 memcpy(seed,in,istop);
1407 wseed[0] = width;
1408
1409 } else if(wseed[0] > 0) { /* blank line, but seed has data */
1410
1411 out[used++] = 0xe1; /* clear row */
1412 memset(seed,0,wseed[0]);
1413 wseed[0] = 0;
1414
1415 }
1416
1417 return used;
1418 }
1419
1420 /*
1421 * Slightly different single-pass printing
1422 */
1423 static void
stc_print_delta(stcolor_device * sd,FILE * prn_stream)1424 stc_print_delta(stcolor_device *sd, FILE *prn_stream)
1425 {
1426
1427 int color,buf_a,w;
1428 int escp_used = 0;
1429 int ncolor = sd->color_info.num_components == 1 ? 1 : 4;
1430
1431 while(sd->stc.stc_y < sd->stc.prt_scans) {
1432
1433 /*
1434 * find the begin of the band
1435 */
1436 for(w = 0; sd->stc.stc_y < sd->stc.buf_y; ++sd->stc.stc_y) {
1437 buf_a = (sd->stc.prt_buf-1) & (sd->stc.stc_y * ncolor);
1438 for(color = 0; color < ncolor; ++color)
1439 if(sd->stc.prt_width[buf_a+color] > w)
1440 w = sd->stc.prt_width[buf_a+color];
1441 if(w != 0) break;
1442 }
1443
1444 if(sd->stc.buf_y == sd->stc.stc_y) break;
1445
1446 escp_used = 0;
1447
1448 /*
1449 * Send Initialization & ESC . 3 once
1450 */
1451 if(0 == (sd->stc.flags & STCPRINT)) {
1452
1453 sd->stc.flags |= STCPRINT;
1454
1455 fwrite(sd->stc.escp_init.data,1,sd->stc.escp_init.size,prn_stream);
1456
1457 sd->stc.escp_data[escp_used++] = '\033';
1458 sd->stc.escp_data[escp_used++] = '.';
1459 sd->stc.escp_data[escp_used++] = 3;
1460 sd->stc.escp_data[escp_used++] = sd->stc.escp_v;
1461 sd->stc.escp_data[escp_used++] = sd->stc.escp_h;
1462 sd->stc.escp_data[escp_used++] = sd->stc.escp_m;
1463 sd->stc.escp_data[escp_used++] = 0;
1464 sd->stc.escp_data[escp_used++] = 0;
1465 sd->stc.escp_data[escp_used++] = 0xe4; /* MOVXBYTE */
1466 }
1467
1468 if(sd->stc.stc_y != sd->stc.prt_y) { /* really position the printer */
1469 w = sd->stc.stc_y - sd->stc.prt_y;
1470 if( w < 16) {
1471 sd->stc.escp_data[escp_used++] = 0x60 | w;
1472 } else if(w < 256) {
1473 sd->stc.escp_data[escp_used++] = 0x71;
1474 sd->stc.escp_data[escp_used++] = w;
1475 } else {
1476 sd->stc.escp_data[escp_used++] = 0x72;
1477 sd->stc.escp_data[escp_used++] = 0xff & w;
1478 sd->stc.escp_data[escp_used++] = 0xff & (w>>8);
1479 }
1480 sd->stc.prt_y = sd->stc.stc_y;
1481 } /* really position the printer */
1482
1483 for(color = 0; color < ncolor; ++color) { /* print the colors */
1484
1485 /* Color-Selection */
1486 if(color == (ncolor-1)) {
1487 sd->stc.escp_data[escp_used++] = 0x80; /* Black */
1488 } else {
1489 switch(color) {
1490 case 1: sd->stc.escp_data[escp_used++] = 0x81; break; /* M */
1491 case 2: sd->stc.escp_data[escp_used++] = 0x84; break; /* Y */
1492 default: sd->stc.escp_data[escp_used++] = 0x82; break; /* C */
1493 }
1494 }
1495
1496 /* Data-Transfer */
1497 buf_a = (sd->stc.prt_buf-1) & (sd->stc.stc_y * ncolor + color);
1498
1499 w = stc_deltarow(sd->stc.escp_data+escp_used,
1500 sd->stc.prt_data[buf_a],sd->stc.prt_width[buf_a],
1501 sd->stc.seed_row[color]);
1502
1503 if(w == 0) escp_used -= 1;
1504 else escp_used += w;
1505
1506 if(escp_used > 0) fwrite(sd->stc.escp_data,1,escp_used,prn_stream);
1507 escp_used = 0;
1508
1509 } /* print the colors */
1510
1511 sd->stc.stc_y += 1;
1512
1513 }
1514
1515 }
1516
1517 /* ----------------------------------------------------------------------- */
1518
1519 /***
1520 *** Free-Data: release the specific-Arrays
1521 ***/
1522 static void
stc_freedata(gs_memory_t * mem,stc_t * stc)1523 stc_freedata(gs_memory_t *mem, stc_t *stc)
1524 {
1525 int i,j;
1526
1527 for(i = 0; i < 4; ++i) {
1528 if(stc->code[i] != NULL) {
1529
1530 for(j = 0; j < i; ++j) if(stc->code[i] == stc->code[j]) break;
1531
1532 if(i == j) gs_free(mem, stc->code[i],1<<stc->bits,sizeof(gx_color_value),
1533 "stcolor/code");
1534 }
1535
1536 if(stc->vals[i] != NULL) {
1537
1538 for(j = 0; j < i; ++j)
1539 if(stc->vals[i] == stc->vals[j]) break;
1540
1541 if(i == j) gs_free(mem, stc->vals[i],1<<stc->bits,sd->stc.alg_item,
1542 "stcolor/transfer");
1543 }
1544 }
1545
1546 for(i = 0; i < 4; ++i) {
1547 stc->code[i] = NULL;
1548 stc->vals[i] = NULL;
1549 }
1550 }
1551
1552 /***
1553 *** open the device and initialize margins & arrays
1554 ***/
1555
1556 static int
stc_open(gx_device * pdev)1557 stc_open(gx_device *pdev) /* setup margins & arrays */
1558 {
1559 stcolor_device *sd = (stcolor_device *) pdev;
1560 int i,j,code;
1561 gx_color_index white;
1562 byte *bpw,*bpm;
1563
1564 code = 0;
1565 /*
1566 * Establish Algorithm-Table, if not present
1567 */
1568 if(sd->stc.algorithms.size == 0) {
1569 gs_param_string *dp;
1570 for(i = 0; stc_dither[i].name != NULL; ++i); /* count 'em */
1571 sd->stc.algorithms.size = i;
1572 dp = gs_malloc(sd->memory, i,sizeof(gs_param_string),
1573 "stcolor/algorithms");
1574 if(dp == NULL) {
1575 code = gs_error_VMerror;
1576 sd->stc.algorithms.size = 0;
1577 } else {
1578 sd->stc.algorithms.data = dp;
1579 sd->stc.algorithms.persistent = true;
1580 for(i = 0; stc_dither[i].name != NULL; ++i) {
1581 param_string_from_string(dp[i],stc_dither[i].name);
1582 }
1583 }
1584 }
1585
1586 # define stc_sizeofitem(T) sd->stc.alg_item = sizeof(T)
1587 STC_TYPESWITCH(sd->stc.dither,stc_sizeofitem)
1588
1589 stc_print_setup(sd);
1590
1591 /*
1592 * Establish internal Value & Code-Arrays
1593 */
1594
1595 for(i = 0; i < sd->color_info.num_components; ++i) { /* comp */
1596
1597 if((sd->stc.sizc[i] > 1) && (sd->stc.extc[i] != NULL)) { /* code req. */
1598
1599 for(j = 0; j < i; ++j) if(sd->stc.extc[i] == sd->stc.extc[j]) break;
1600
1601 if(i == j) { /* new one */
1602 sd->stc.code[i] = gs_malloc(sd->memory, 1<<sd->stc.bits,sizeof(gx_color_value),
1603 "stcolor/code");
1604
1605 if(sd->stc.code[i] == NULL) { /* error */
1606 code = gs_error_VMerror;
1607 } else { /* success */
1608 /*
1609 * Try making things easier:
1610 * normalize values to 0.0/1.0-Range
1611 * X-Axis: Color-Values (implied)
1612 * Y-Values: Indices (given)
1613 */
1614 unsigned long ly,iy;
1615 double ystep,xstep,fx,fy;
1616
1617 /* normalize */
1618
1619 fx = 1e18;
1620 fy = -1e18;
1621 for(ly = 0; ly < sd->stc.sizc[i]; ++ly) {
1622 if(sd->stc.extc[i][ly] < fx) fx = sd->stc.extc[i][ly];
1623 if(sd->stc.extc[i][ly] > fy) fy = sd->stc.extc[i][ly];
1624 }
1625 if((fx != 0.0) || (fy != 1.0)) {
1626 fy = 1.0 / (fy - fx);
1627 for(ly = 0; ly < sd->stc.sizc[i]; ++ly)
1628 sd->stc.extc[i][ly] = fy * (sd->stc.extc[i][ly]-fx);
1629 }
1630
1631 /* interpolate */
1632 ystep = 1.0 / (double)((1<<sd->stc.bits)-1);
1633 xstep = 1.0 / (double)( sd->stc.sizc[i] -1);
1634
1635 iy = 0;
1636 for(ly = 0; ly < (1<<sd->stc.bits); ++ly) {
1637 fy = ystep * ly;
1638 while(((iy+1) < sd->stc.sizc[i]) &&
1639 ( fy > sd->stc.extc[i][iy+1])) ++iy;
1640 fx = iy + (fy - sd->stc.extc[i][iy])
1641 / (sd->stc.extc[i][iy+1] - sd->stc.extc[i][iy]);
1642 fx *= xstep * gx_max_color_value;
1643
1644 fx = fx < 0.0 ? 0.0 :
1645 (fx > gx_max_color_value ? gx_max_color_value : fx);
1646
1647 sd->stc.code[i][ly] = (gx_color_value)fx;
1648 if((fx-sd->stc.code[i][ly]) >= 0.5) sd->stc.code[i][ly] += 1;
1649 }
1650 } /* error || success */
1651
1652 } else { /* shared one */
1653
1654 sd->stc.code[i] = sd->stc.code[j];
1655
1656 } /* new || shared one */
1657 } /* code req. */
1658
1659 if((sd->stc.sizv[i] > 1) && (sd->stc.extv[i] != NULL)) { /* vals req. */
1660
1661 for(j = 0; j < i; ++j)
1662 if((sd->stc.extc[i] == sd->stc.extc[j]) &&
1663 (sd->stc.extv[i] == sd->stc.extv[j])) break;
1664
1665 if(i == j) { /* new one */
1666
1667 sd->stc.vals[i] =
1668 gs_malloc(sd->memory, 1<<sd->stc.bits,sd->stc.alg_item,"stcolor/transfer");
1669
1670 if(sd->stc.vals[i] == NULL) {
1671
1672 code = gs_error_VMerror;
1673
1674 } else { /* success */
1675
1676 if(sd->stc.code[i] == NULL) { /* linear */
1677
1678 byte *Out = sd->stc.vals[i];
1679 int Nout = 1<<sd->stc.bits;
1680 double Omin = sd->stc.dither->minmax[0];
1681 double Omax = sd->stc.dither->minmax[1];
1682 float *In = sd->stc.extv[i];
1683 int Nin = sd->stc.sizv[i];
1684 unsigned long I,io;
1685 double Istep,Ostep,Y;
1686 byte Ovb; long Ovl;
1687
1688 Istep = 1.0 / (double) ((Nin)-1);
1689 Ostep = 1.0 / (double) ((Nout)-1);
1690
1691 for(io = 0; io < (Nout); ++io) {
1692 I = (long)(io * ((Nin)-1))/((Nout)-1);
1693
1694 if((I+1) < (Nin))
1695 Y = In[I] + (In[I+1]-In[I])
1696 * ((double) io * Ostep - (double)I * Istep)
1697 / (double) Istep;
1698 else
1699 Y = In[I] + (In[I]-In[I-1])
1700 * ((double) io * Ostep - (double)I * Istep)
1701 / (double) Istep;
1702
1703 Y = Omin + (Omax-Omin) * Y;
1704 Y = Y < Omin ? Omin : (Y > Omax ? Omax : Y);
1705
1706 switch(sd->stc.dither->flags & STC_TYPE) {
1707 case STC_BYTE:
1708 Ovb = (byte)Y;
1709 if(((Y-Ovb) >= 0.5) && ((Ovb+1) <= Omax)) Ovb += 1;
1710 Out[io] = Ovb;
1711 break;
1712 case STC_LONG:
1713 Ovl = (long)Y;
1714 if(((Y-Ovl) >= 0.5) && ((Ovl+1) <= Omax)) Ovl += 1;
1715 if(((Ovl-Y) >= 0.5) && ((Ovl-1) >= Omax)) Ovl -= 1;
1716 ((long *)Out)[io] = Ovl;
1717 break;
1718 default:
1719 ((float *)Out)[io] = Y;
1720 break;
1721 }
1722 }
1723
1724 } else { /* encoded */
1725 unsigned long j,o;
1726 double xstep,x,y;
1727
1728 xstep = 1.0 / (double) (sd->stc.sizv[i]-1);
1729
1730 /*
1731 * The following differs in so far from the previous, that the desired
1732 * X-Values are stored in another array.
1733 */
1734 for(o = 0; o < (1<<sd->stc.bits); ++o) { /* code-loop */
1735
1736 x = sd->stc.code[i][o]; x /= gx_max_color_value;
1737
1738 j = (unsigned long)(x / xstep);
1739
1740 if((j+1) < sd->stc.sizv[i]) {
1741 y = sd->stc.extv[i][j];
1742 y += (sd->stc.extv[i][j+1]-y)*(x-(double)j*xstep)/xstep;
1743 } else {
1744 y = sd->stc.extv[i][j];
1745 y += (y-sd->stc.extv[i][j-1])*(x-(double)j*xstep)/xstep;
1746 }
1747
1748 y = sd->stc.dither->minmax[0]
1749 +(sd->stc.dither->minmax[1]-sd->stc.dither->minmax[0])*y;
1750
1751 # define stc_adjvals(T) \
1752 ((T *)(sd->stc.vals[i]))[o] = (T)y; \
1753 \
1754 if(((y-((T *)(sd->stc.vals[i]))[o]) >= 0.5) && \
1755 ((1+((T *)(sd->stc.vals[i]))[o]) <= sd->stc.dither->minmax[1]))\
1756 ((T *)(sd->stc.vals[i]))[o] += 1; \
1757 \
1758 if(((((T *)(sd->stc.vals[i]))[o]-y) >= 0.5) && \
1759 ((((T *)(sd->stc.vals[i]))[o]-1) >= sd->stc.dither->minmax[0]))\
1760 ((T *)(sd->stc.vals[i]))[o] -= 1;
1761
1762 STC_TYPESWITCH(sd->stc.dither,stc_adjvals)
1763
1764 # undef stc_adjvals
1765 } /* code-loop */
1766 } /* lineaer / encoded */
1767 } /* error || success */
1768
1769 } else { /* shared one */
1770
1771 sd->stc.vals[i] = sd->stc.vals[j];
1772
1773 } /* new || shared one */
1774 } /* vals req. */
1775 } /* comp */
1776
1777 if(code == 0) {
1778 gx_color_value cv[4];
1779 sd->stc.flags |= STCOK4GO;
1780
1781 /*
1782 * Arrgh: open-procedure seems to be the right-place, but it is
1783 * necessary to establish the defaults for omitted procedures too.
1784 */
1785
1786 switch(sd->color_info.num_components) { /* Establish color-procs */
1787 case 1:
1788 sd->color_info.polarity = GX_CINFO_POLARITY_ADDITIVE;
1789 set_dev_proc(sd,map_rgb_color, stc_map_gray_color);
1790 set_dev_proc(sd,map_cmyk_color,gx_default_map_cmyk_color);
1791 set_dev_proc(sd,map_color_rgb, stc_map_color_gray);
1792 set_dev_proc(sd,encode_color, stc_map_gray_color);
1793 set_dev_proc(sd,decode_color, stc_map_color_gray);
1794 set_dev_proc(sd, get_color_mapping_procs,
1795 gx_default_DevGray_get_color_mapping_procs);
1796 set_dev_proc(sd, get_color_comp_index,
1797 gx_default_DevGray_get_color_comp_index );
1798 cv[0] = cv[1] = cv[2] = gx_max_color_value;
1799 white = stc_map_gray_color((gx_device *) sd, cv);
1800 break;
1801 case 3:
1802 sd->color_info.polarity = GX_CINFO_POLARITY_ADDITIVE;
1803 set_dev_proc(sd,map_rgb_color, stc_map_rgb_color);
1804 set_dev_proc(sd,map_cmyk_color,gx_default_map_cmyk_color);
1805 set_dev_proc(sd,map_color_rgb, stc_map_color_rgb);
1806 set_dev_proc(sd,encode_color, stc_map_rgb_color);
1807 set_dev_proc(sd,decode_color, stc_map_color_rgb);
1808 set_dev_proc(sd, get_color_mapping_procs,
1809 gx_default_DevRGB_get_color_mapping_procs);
1810 set_dev_proc(sd, get_color_comp_index,
1811 gx_default_DevRGB_get_color_comp_index );
1812 cv[0] = cv[1] = cv[2] = gx_max_color_value;
1813 white = stc_map_rgb_color((gx_device *) sd, cv);
1814 break;
1815 default:
1816 sd->color_info.polarity = GX_CINFO_POLARITY_SUBTRACTIVE;
1817 set_dev_proc(sd,map_rgb_color, gx_default_map_rgb_color);
1818 set_dev_proc(sd, get_color_mapping_procs,
1819 gx_default_DevCMYK_get_color_mapping_procs);
1820 set_dev_proc(sd, get_color_comp_index,
1821 gx_default_DevCMYK_get_color_comp_index );
1822 if(sd->stc.flags & STCCMYK10) {
1823 set_dev_proc(sd,map_cmyk_color,stc_map_cmyk10_color);
1824 set_dev_proc(sd,map_color_rgb, stc_map_color_cmyk10);
1825 set_dev_proc(sd,encode_color,stc_map_cmyk10_color);
1826 set_dev_proc(sd,decode_color, stc_map_color_cmyk10);
1827 cv[0] = cv[1] = cv[2] = cv[3] = 0;
1828 white = stc_map_cmyk10_color((gx_device *) sd, cv);
1829 } else {
1830 set_dev_proc(sd,map_cmyk_color,stc_map_cmyk_color);
1831 set_dev_proc(sd,map_color_rgb, stc_map_color_cmyk);
1832 set_dev_proc(sd,encode_color,stc_map_cmyk_color);
1833 set_dev_proc(sd,decode_color, stc_map_color_cmyk);
1834 cv[0] = cv[1] = cv[2] = cv[3] = 0;
1835 white = stc_map_cmyk_color((gx_device *) sd,cv);
1836 }
1837 break; /* Establish color-procs */
1838 }
1839
1840 /*
1841 * create at least a Byte
1842 */
1843 if(sd->color_info.depth < 2) white |= (white<<1);
1844 if(sd->color_info.depth < 4) white |= (white<<2);
1845 if(sd->color_info.depth < 8) white |= (white<<4);
1846
1847 /*
1848 * copy the Bytes
1849 */
1850 bpw = (byte *) sd->stc.white_run;
1851
1852 if(sd->color_info.depth < 16) {
1853 for(i = 0; i < sizeof(sd->stc.white_run); i += 1) {
1854 bpw[i] = 0xff & white;
1855 }
1856 } else if(sd->color_info.depth < 24) {
1857 for(i = 0; i < sizeof(sd->stc.white_run); i += 2) {
1858 bpw[i] = 0xff & (white>>8);
1859 bpw[i+1] = 0xff & white;
1860 }
1861 } else if(sd->color_info.depth < 32) {
1862 for(i = 0; i < sizeof(sd->stc.white_run); i += 3) {
1863 bpw[i] = 0xff & (white>>16);
1864 bpw[i+1] = 0xff & (white>> 8);
1865 bpw[i+2] = 0xff & white;
1866 }
1867 } else {
1868 for(i = 0; i < sizeof(sd->stc.white_run); i += 4) {
1869 bpw[i] = 0xff & (white>>24);
1870 bpw[i+1] = 0xff & (white>>16);
1871 bpw[i+2] = 0xff & (white>> 8);
1872 bpw[i+3] = 0xff & white;
1873 }
1874 }
1875 /*
1876 * compute the trailer
1877 */
1878 j = (unsigned long)(sd->width -
1879 (dev_l_margin(sd)+dev_r_margin(sd))*sd->x_pixels_per_inch);
1880 j = j * sd->color_info.depth; /* the Bit-count */
1881 j = j % (32*countof(sd->stc.white_run)); /* remaining Bits */
1882
1883 bpm = (byte *) sd->stc.white_end;
1884 for(i = 0; i < (4*countof(sd->stc.white_end)); ++i) {
1885 if( j <= 0) {
1886 bpm[i] = 0;
1887 } else if(j >= 8) {
1888 bpm[i] = 0xff;
1889 j -= 8;
1890 } else {
1891 bpm[i] = 0xff ^ ((1<<(8-j))-1);
1892 j = 0;
1893 }
1894 bpm[i] &= bpw[i];
1895 }
1896
1897 /*
1898 * Call super-class open
1899 */
1900
1901 return gdev_prn_open(pdev);
1902
1903 } else {
1904
1905 stc_freedata(sd->memory, &sd->stc);
1906
1907 return_error(code);
1908 }
1909
1910 }
1911
1912 /***
1913 *** stc_close: release the internal data
1914 ***/
1915 static int
stc_close(gx_device * pdev)1916 stc_close(gx_device *pdev)
1917 {
1918 stc_freedata(pdev->memory, &((stcolor_device *) pdev)->stc);
1919 ((stcolor_device *) pdev)->stc.flags &= ~STCOK4GO;
1920 return gdev_prn_close(pdev);
1921 }
1922
1923 /***
1924 *** Function for Bit-Truncation, including direct-byte-transfer
1925 ***/
1926 static gx_color_value
stc_truncate(stcolor_device * sd,int i,gx_color_value v)1927 stc_truncate(stcolor_device *sd,int i,gx_color_value v)
1928 {
1929
1930 if(sd->stc.bits < gx_color_value_bits) {
1931 if(sd->stc.code[i] != NULL) {
1932 /*
1933 * Perform binary search in the code-array
1934 */
1935 long s;
1936 gx_color_value *p;
1937
1938 s = sd->stc.bits > 1 ? 1L<<(sd->stc.bits-2) : 0L;
1939 p = sd->stc.code[i]+(1L<<(sd->stc.bits-1));
1940
1941 while(s > 0) {
1942 if(v > *p) {
1943 p += s;
1944 } else if(v < p[-1]) {
1945 p -= s;
1946 } else {
1947 if((v-p[-1]) < (p[0]-v)) p -= 1;
1948 break;
1949 }
1950 s >>= 1;
1951 }
1952 if((v-p[-1]) < (p[0]-v)) p -= 1;
1953 v = p - sd->stc.code[i];
1954
1955 } else {
1956
1957 v >>= gx_color_value_bits-sd->stc.bits;
1958
1959 }
1960
1961 /*
1962 V = (((1L<<D->stc.bits)-1)*V+(gx_max_color_value>>1))\
1963 /gx_max_color_value; \
1964 */
1965 }
1966 return v;
1967 }
1968
1969 static gx_color_value
stc_truncate1(stcolor_device * sd,int i,gx_color_value v)1970 stc_truncate1(stcolor_device *sd,int i,gx_color_value v)
1971 {
1972
1973 return sd->stc.vals[i][stc_truncate(sd,i,v)];
1974 }
1975
1976 /***
1977 *** Expansion of indices for reverse-mapping
1978 ***/
1979 static gx_color_value
stc_expand(stcolor_device * sd,int i,gx_color_index col)1980 stc_expand(stcolor_device *sd,int i,gx_color_index col)
1981 {
1982
1983 gx_color_index cv;
1984 gx_color_index l = (1<<sd->stc.bits)-1;
1985
1986 if(sd->stc.code[i] != NULL) {
1987
1988 cv = sd->stc.code[i][col & l];
1989
1990 } else if(sd->stc.bits < gx_color_value_bits) {
1991
1992 cv = (col & l)<<(gx_color_value_bits-sd->stc.bits);
1993 cv += (col & l)/l * ((1<<(gx_color_value_bits-sd->stc.bits))-1);
1994
1995 } else if(sd->stc.bits > gx_color_value_bits) {
1996
1997 cv = (col & l)>>(sd->stc.bits-gx_color_value_bits);
1998
1999 } else {
2000
2001 cv = col & l;
2002
2003 }
2004
2005 return cv;
2006 }
2007
2008 /***
2009 *** color-mapping of gray-scales
2010 ***/
2011 static gx_color_index
stc_map_gray_color(gx_device * pdev,const gx_color_value cv[])2012 stc_map_gray_color(gx_device *pdev, const gx_color_value cv[])
2013 {
2014
2015 stcolor_device *sd = (stcolor_device *) pdev;
2016 gx_color_index rv;
2017 gx_color_value r = cv[0];
2018 gx_color_value g = cv[1];
2019 gx_color_value b = cv[2];
2020
2021 if((r == g) && (g == b)) {
2022
2023 rv = gx_max_color_value - r;
2024
2025 } else if(sd->stc.am != NULL) {
2026 float *m,fv;
2027
2028 m = sd->stc.am;
2029
2030 fv = gx_max_color_value;
2031 fv -= *m++ * (float) r; fv -= *m++ * (float) g; fv -= *m * (float) b;
2032
2033 if( fv < 0.0) rv = 0;
2034 else if((fv+0.5) > gx_max_color_value) rv = gx_max_color_value;
2035 else rv = (gx_color_index)(fv+0.5);
2036
2037 } else {
2038
2039 rv = ((gx_color_index)gx_max_color_value)<<3;
2040 rv -= (gx_color_index) 3 * r;
2041 rv -= (gx_color_index) 3 * g;
2042 rv -= ((gx_color_index)b)<<1;
2043 rv = (rv+4)>>3;
2044 if(rv > gx_max_color_value) rv = gx_max_color_value;
2045
2046 }
2047
2048 if(( sd->stc.bits == 8) &&
2049 ((sd->stc.dither->flags & STC_TYPE) == STC_BYTE))
2050 rv = stc_truncate1(sd,0,(gx_color_value)rv);
2051 else
2052 rv = stc_truncate(sd,0,(gx_color_value)rv);
2053
2054 return rv;
2055 }
2056
2057 static int
stc_map_color_gray(gx_device * pdev,gx_color_index color,gx_color_value prgb[3])2058 stc_map_color_gray(gx_device *pdev, gx_color_index color,gx_color_value prgb[3])
2059 {
2060 stcolor_device *sd = (stcolor_device *) pdev;
2061 gx_color_index l = ((gx_color_index)1<<sd->stc.bits)-1;
2062
2063 prgb[0] = gx_max_color_value - stc_expand(sd,0,color & l);
2064 prgb[1] = prgb[0]; prgb[2] = prgb[0];
2065
2066 return 0;
2067 }
2068
2069 /***
2070 *** color-mapping of rgb-values
2071 ***/
2072 static gx_color_index
stc_map_rgb_color(gx_device * pdev,const gx_color_value cv[])2073 stc_map_rgb_color(gx_device *pdev, const gx_color_value cv[])
2074 {
2075
2076 stcolor_device *sd = (stcolor_device *) pdev;
2077 int shift = sd->color_info.depth == 24 ? 8 : sd->stc.bits;
2078 gx_color_index rv = 0;
2079 gx_color_value r = cv[0];
2080 gx_color_value g = cv[1];
2081 gx_color_value b = cv[2];
2082 if((sd->stc.am != NULL) && ((r != g) || (g != b))) {
2083 float *m,fr,fg,fb,fv;
2084
2085 m = sd->stc.am;
2086 fr = r; fg = g; fb = b;
2087
2088 fv = *m++ * fr; fv += *m++ * fg; fv += *m++ * fb;
2089
2090 if( fv < 0.0) r = 0;
2091 else if((fv+0.5) > gx_max_color_value) r = gx_max_color_value;
2092 else r = (gx_color_value)(fv+0.5);
2093
2094 fv = *m++ * fr; fv += *m++ * fg; fv += *m++ * fb;
2095
2096 if( fv < 0.0) g = 0;
2097 else if((fv+0.5) > gx_max_color_value) g = gx_max_color_value;
2098 else g = (gx_color_value)(fv+0.5);
2099
2100 fv = *m++ * fr; fv += *m++ * fg; fv += *m++ * fb;
2101
2102 if( fv < 0.0) b = 0;
2103 else if((fv+0.5) > gx_max_color_value) b = gx_max_color_value;
2104 else b = (gx_color_value)(fv+0.5);
2105
2106 }
2107
2108 if(( sd->stc.bits == 8) &&
2109 ((sd->stc.dither->flags & STC_TYPE) == STC_BYTE)) {
2110 rv = stc_truncate1(sd,0,r);
2111 rv = (rv<<shift) | stc_truncate1(sd,1,g);
2112 rv = (rv<<shift) | stc_truncate1(sd,2,b);
2113 } else {
2114 rv = stc_truncate(sd,0,r);
2115 rv = (rv<<shift) | stc_truncate(sd,1,g);
2116 rv = (rv<<shift) | stc_truncate(sd,2,b);
2117 }
2118
2119 return rv;
2120 }
2121
2122 static int
stc_map_color_rgb(gx_device * pdev,gx_color_index color,gx_color_value prgb[3])2123 stc_map_color_rgb(gx_device *pdev, gx_color_index color,gx_color_value prgb[3])
2124 {
2125
2126 stcolor_device *sd = (stcolor_device *) pdev;
2127 int shift = sd->color_info.depth == 24 ? 8 : sd->stc.bits;
2128 gx_color_index l = ((gx_color_index)1<<sd->stc.bits)-1;
2129
2130 prgb[0] = stc_expand(sd,0,((color>>(shift<<1)) & l));
2131 prgb[1] = stc_expand(sd,1,((color>> shift ) & l));
2132 prgb[2] = stc_expand(sd,2,( color & l));
2133
2134 return 0;
2135 }
2136
2137 /***
2138 *** color-mapping of cmyk-values
2139 ***/
2140 static gx_color_index
stc_map_cmyk_color(gx_device * pdev,const gx_color_value cv[])2141 stc_map_cmyk_color(gx_device *pdev, const gx_color_value cv[])
2142 {
2143
2144 stcolor_device *sd = (stcolor_device *) pdev;
2145 int shift = sd->color_info.depth == 32 ? 8 : sd->stc.bits;
2146 gx_color_index rv = 0;
2147 gx_color_value c = cv[0];
2148 gx_color_value m = cv[1];
2149 gx_color_value y = cv[2];
2150 gx_color_value k = cv[3];
2151
2152 if((c == m) && (m == y)) {
2153
2154 k = c > k ? c : k;
2155 c = m = y = 0;
2156
2157 if(( sd->stc.bits == 8) &&
2158 ((sd->stc.dither->flags & STC_TYPE) == STC_BYTE)) {
2159 k = stc_truncate1(sd,3,k);
2160 } else {
2161 k = stc_truncate(sd,3,k);
2162 }
2163
2164 } else {
2165
2166 if(sd->stc.am != NULL) {
2167
2168 float *a,fc,fm,fy,fk,fv;
2169
2170 if(k == 0) { /* no separated black yet */
2171 k = c < m ? c : m;
2172 k = k < y ? k : y;
2173 if(k) { /* no black at all */
2174 c -= k;
2175 m -= k;
2176 y -= k;
2177 } /* no black at all */
2178 } /* no separated black yet */
2179
2180 a = sd->stc.am;
2181 fc = c; fm = m; fy = y; fk = k;
2182
2183 fv = *a++ * fc; fv += *a++ * fm; fv += *a++ * fy; fv += *a++ * fk;
2184 if( fv < 0.0) c = 0;
2185 else if((fv+0.5) > gx_max_color_value) c = gx_max_color_value;
2186 else c = (gx_color_value)(fv+0.5);
2187
2188 fv = *a++ * fc; fv += *a++ * fm; fv += *a++ * fy; fv += *a++ * fk;
2189 if( fv < 0.0) m = 0;
2190 else if((fv+0.5) > gx_max_color_value) m = gx_max_color_value;
2191 else m = (gx_color_value)(fv+0.5);
2192
2193 fv = *a++ * fc; fv += *a++ * fm; fv += *a++ * fy; fv += *a++ * fk;
2194 if( fv < 0.0) y = 0;
2195 else if((fv+0.5) > gx_max_color_value) y = gx_max_color_value;
2196 else y = (gx_color_value)(fv+0.5);
2197
2198 fv = *a++ * fc; fv += *a++ * fm; fv += *a++ * fy; fv += *a++ * fk;
2199 if( fv < 0.0) k = 0;
2200 else if((fv+0.5) > gx_max_color_value) k = gx_max_color_value;
2201 else k = (gx_color_value)(fv+0.5);
2202
2203 } else if(k == 0) {
2204
2205 k = c < m ? c : m;
2206 k = k < y ? k : y;
2207 }
2208
2209 if(( sd->stc.bits == 8) &&
2210 ((sd->stc.dither->flags & STC_TYPE) == STC_BYTE)) {
2211 c = stc_truncate1(sd,0,c);
2212 m = stc_truncate1(sd,1,m);
2213 y = stc_truncate1(sd,2,y);
2214 k = stc_truncate1(sd,3,k);
2215 } else {
2216 c = stc_truncate(sd,0,c);
2217 m = stc_truncate(sd,1,m);
2218 y = stc_truncate(sd,2,y);
2219 k = stc_truncate(sd,3,k);
2220 }
2221 }
2222
2223 rv = c;
2224 rv = (rv<<shift) | m;
2225 rv = (rv<<shift) | y;
2226 rv = (rv<<shift) | k;
2227
2228 if(rv == gx_no_color_index) rv ^= 1;
2229
2230 return rv;
2231 }
2232
2233 /* Modified to be a "decode_color" routine */
2234 static int
stc_map_color_cmyk(gx_device * pdev,gx_color_index color,gx_color_value cv[4])2235 stc_map_color_cmyk(gx_device *pdev, gx_color_index color,gx_color_value cv[4])
2236 {
2237
2238 stcolor_device *sd = (stcolor_device *) pdev;
2239 int shift = sd->color_info.depth == 32 ? 8 : sd->stc.bits;
2240 gx_color_index l = ((gx_color_index)1<<sd->stc.bits)-1;
2241 gx_color_value c,m,y,k;
2242
2243 k = stc_expand(sd,3, color & l); color >>= shift;
2244 y = stc_expand(sd,2, color & l); color >>= shift;
2245 m = stc_expand(sd,1, color & l); color >>= shift;
2246 c = stc_expand(sd,0, color & l);
2247
2248 cv[0] = c;
2249 cv[1] = m;
2250 cv[2] = y;
2251 cv[3] = k;
2252
2253 return 0;
2254 }
2255
2256 /***
2257 *** color-mapping of cmyk10-values
2258 ***/
2259 static gx_color_index
stc_map_cmyk10_color(gx_device * pdev,const gx_color_value cv[])2260 stc_map_cmyk10_color(gx_device *pdev, const gx_color_value cv[])
2261 {
2262
2263 stcolor_device *sd = (stcolor_device *) pdev;
2264 int mode;
2265 gx_color_index rv = 0;
2266
2267 gx_color_value c = cv[0];
2268 gx_color_value m = cv[1];
2269 gx_color_value y = cv[2];
2270 gx_color_value k = cv[3];
2271
2272 if((c == m) && (m == y)) {
2273
2274 k = c > k ? c : k;
2275 c = m = y = 0;
2276 mode = 3;
2277
2278 } else {
2279
2280 if(sd->stc.am != NULL) {
2281
2282 float *a,fc,fm,fy,fk,fv;
2283
2284 k = c < m ? c : m;
2285 k = k < y ? k : y;
2286 if(k) { /* no black at all */
2287 c -= k;
2288 m -= k;
2289 y -= k;
2290 } /* no black at all */
2291
2292 a = sd->stc.am;
2293 fc = c; fm = m; fy = y; fk = k;
2294
2295 fv = *a++ * fc; fv += *a++ * fm; fv += *a++ * fy; fv += *a++ * fk;
2296 if( fv < 0.0) c = 0;
2297 else if((fv+0.5) > gx_max_color_value) c = gx_max_color_value;
2298 else c = (gx_color_value)(fv+0.5);
2299
2300 fv = *a++ * fc; fv += *a++ * fm; fv += *a++ * fy; fv += *a++ * fk;
2301 if( fv < 0.0) m = 0;
2302 else if((fv+0.5) > gx_max_color_value) m = gx_max_color_value;
2303 else m = (gx_color_value)(fv+0.5);
2304
2305 fv = *a++ * fc; fv += *a++ * fm; fv += *a++ * fy; fv += *a++ * fk;
2306 if( fv < 0.0) y = 0;
2307 else if((fv+0.5) > gx_max_color_value) y = gx_max_color_value;
2308 else y = (gx_color_value)(fv+0.5);
2309
2310 }
2311
2312 if(c < m) {
2313 if(c < y) { k = c; c = 0; mode = 0; }
2314 else { k = y; y = 0; mode = 2; }
2315 } else {
2316 if(m < y) { k = m; m = 0; mode = 1; }
2317 else { k = y; y = 0; mode = 2; }
2318 }
2319 }
2320
2321 /*
2322 * truncate only the values that require it
2323 */
2324 if(c) c = stc_truncate(sd,0,c);
2325 if(m) m = stc_truncate(sd,1,m);
2326 if(y) y = stc_truncate(sd,2,y);
2327 if(k) k = stc_truncate(sd,3,k);
2328
2329 /*
2330 * make sure that truncation-white becomes white.
2331 */
2332 if((c|m|y) == 0) mode = 3;
2333
2334 /*
2335 * check wether value-arrays can be bypassed
2336 */
2337 if(((sd->stc.dither->flags & STC_TYPE) == STC_BYTE) &&
2338 ( sd->stc.dither->minmax[0] == 0.0 )) {
2339 c = sd->stc.vals[0][c];
2340 m = sd->stc.vals[1][m];
2341 y = sd->stc.vals[2][y];
2342 k = sd->stc.vals[3][k];
2343 } else if(((sd->stc.dither->flags & STC_TYPE) == STC_LONG) &&
2344 ( sd->stc.dither->minmax[0] == 0.0 ) &&
2345 ( sd->stc.dither->minmax[1] <= 1023.0 )) {
2346 c = ((long *)(sd->stc.vals[0]))[c];
2347 m = ((long *)(sd->stc.vals[1]))[m];
2348 y = ((long *)(sd->stc.vals[2]))[y];
2349 k = ((long *)(sd->stc.vals[3]))[k];
2350 } /* direct */
2351 /*
2352 * compute the long-representation of gx_color_index
2353 */
2354 switch(mode) {
2355 case 0:
2356 rv = (((gx_color_index) m)<<22)|
2357 (((gx_color_index) y)<<12)|
2358 (((gx_color_index) k)<< 2)|mode;
2359 break;
2360 case 1:
2361 rv = (((gx_color_index) c)<<22)|
2362 (((gx_color_index) y)<<12)|
2363 (((gx_color_index) k)<< 2)|mode;
2364 break;
2365 case 2:
2366 rv = (((gx_color_index) c)<<22)|
2367 (((gx_color_index) m)<<12)|
2368 (((gx_color_index) k)<< 2)|mode;
2369 break;
2370 default:
2371 rv = (((gx_color_index) k)<< 2)|mode;
2372 break;
2373 }
2374
2375 /*
2376 * We may need some swapping
2377 */
2378 #if !arch_is_big_endian
2379 {
2380 union { stc_pixel cv; byte bv[4]; } ui,uo;
2381 ui.cv = rv;
2382 uo.bv[0] = ui.bv[3];
2383 uo.bv[1] = ui.bv[2];
2384 uo.bv[2] = ui.bv[1];
2385 uo.bv[3] = ui.bv[0];
2386 rv = uo.cv;
2387 }
2388 #endif
2389 return rv;
2390 }
2391
2392 static int
stc_map_color_cmyk10(gx_device * pdev,gx_color_index color,gx_color_value cv[3])2393 stc_map_color_cmyk10(gx_device *pdev, gx_color_index color,
2394 gx_color_value cv[3])
2395 {
2396
2397 stcolor_device *sd = (stcolor_device *) pdev;
2398 gx_color_value c,m,y;
2399
2400 /*
2401 * We may need some swapping
2402 */
2403 #if !arch_is_big_endian
2404 union { stc_pixel cv; byte bv[4]; } ui,uo;
2405 ui.cv = color;
2406 uo.bv[0] = ui.bv[3];
2407 uo.bv[1] = ui.bv[2];
2408 uo.bv[2] = ui.bv[1];
2409 uo.bv[3] = ui.bv[0];
2410 color = uo.cv;
2411 #endif
2412
2413 c = stc_expand(sd,3,(color>>2)&0x3ff);
2414
2415 /* cast the 64 bit switch argument to work around broken HPUX 10 cc */
2416 switch((int)(color & 3)) {
2417 case 0:
2418 m = stc_expand(sd,1,(color>>22) & 0x3ff);
2419 y = stc_expand(sd,2,(color>>12) & 0x3ff);
2420 break;
2421 case 1:
2422 m = c;
2423 c = stc_expand(sd,0,(color>>22) & 0x3ff);
2424 y = stc_expand(sd,2,(color>>12) & 0x3ff);
2425 break;
2426 case 2:
2427 y = c;
2428 c = stc_expand(sd,0,(color>>22) & 0x3ff);
2429 m = stc_expand(sd,1,(color>>12) & 0x3ff);
2430 break;
2431 default:
2432 m = c;
2433 y = c;
2434 break;
2435 }
2436
2437 cv[0] = c;
2438 cv[1] = m;
2439 cv[2] = y;
2440
2441 return 0;
2442 }
2443
2444 /***
2445 *** Macros for parameter-handling
2446 ***/
2447
2448 #define set_param_array(A, D, S)\
2449 {A.data = D; A.size = S; A.persistent = false;}
2450
2451 #define stc_write_null(N) \
2452 set_param_array(pfa,defext,countof(defext)) \
2453 code = param_write_null(plist,N); \
2454 if (code < 0) return code;
2455
2456 #define stc_write_xarray(I,Coding,Transfer) \
2457 if(sd->stc.sizc[I] > 0) { \
2458 set_param_array(pfa, sd->stc.extc[I],sd->stc.sizc[I]) \
2459 code = param_write_float_array(plist,Coding,&pfa); \
2460 } else { \
2461 code = param_write_null(plist,Coding); \
2462 } \
2463 if ( code < 0 ) return code; \
2464 \
2465 if(sd->stc.sizv[I] > 0) \
2466 set_param_array(pfa, sd->stc.extv[I],sd->stc.sizv[I]) \
2467 else \
2468 set_param_array(pfa,defext,countof(defext)) \
2469 code = param_write_float_array(plist,Transfer,&pfa); \
2470 if ( code < 0 ) return code;
2471
2472 #define stc_read_null(N) \
2473 code = param_read_null(plist,N); \
2474 if(code == gs_error_typecheck) \
2475 code = param_read_float_array(plist,N,&pfa); \
2476 if(code < 0) param_signal_error(plist,N,code); \
2477 error = error > code ? code : error;
2478
2479 #define stc_read_xarray(I,Coding,Transfer) \
2480 code = param_read_float_array(plist,Coding,&pfa); \
2481 if((error == 0) && (code == 0)) { \
2482 if(pfa.size > 1) { \
2483 sd->stc.extc[I] = (float *) pfa.data; \
2484 sd->stc.sizc[I] = pfa.size; \
2485 } else { \
2486 code = gs_error_rangecheck; \
2487 } \
2488 } else if(code < 0) { \
2489 code = param_read_null(plist,Coding); \
2490 if(code == 0) { \
2491 sd->stc.extc[I] = NULL; \
2492 sd->stc.sizc[I] = 0; \
2493 } \
2494 } \
2495 if(code < 0) param_signal_error(plist,Coding,code); \
2496 error = error > code ? code : error; \
2497 code = param_read_float_array(plist,Transfer,&pfa); \
2498 if((error == 0) && (code == 0)) { \
2499 sd->stc.extv[I] = (float *) pfa.data; \
2500 sd->stc.sizv[I] = pfa.size; \
2501 } else if(code < 0) { \
2502 code = param_read_null(plist,Transfer); \
2503 if(code == 0) { \
2504 sd->stc.extv[I] = defext; \
2505 sd->stc.sizv[I] = countof(defext); \
2506 } \
2507 } \
2508 if(code < 0) param_signal_error(plist,Transfer,code); \
2509 error = error > code ? code : error;
2510
2511 /***
2512 *** Get parameters == Make them accessable via PostScript
2513 ***/
2514
2515 static int
stc_get_params(gx_device * pdev,gs_param_list * plist)2516 stc_get_params(gx_device *pdev, gs_param_list *plist)
2517 {
2518 int code,nc;
2519 gs_param_string ps;
2520 gs_param_float_array pfa;
2521 bool btmp;
2522 stcolor_device *sd = (stcolor_device *) pdev;
2523
2524 code = gdev_prn_get_params(pdev, plist);
2525 if ( code < 0 ) return code;
2526
2527 /*
2528 * Export some readonly-Parameters, used by stcinfo.ps
2529 */
2530 param_string_from_string(ps,"1.91");
2531 code = param_write_string(plist,"Version",&ps);
2532 if ( code < 0 ) return code;
2533
2534 code = param_write_int(plist,"BitsPerComponent",&sd->stc.bits);
2535 if ( code < 0 ) return code;
2536
2537 if(sd->stc.algorithms.size > 0) {
2538 code = param_write_string_array(plist,"Algorithms",&sd->stc.algorithms);
2539 } else {
2540 code = param_write_null(plist,"Algorithms");
2541 }
2542 if ( code < 0 ) return code;
2543
2544 /*
2545 * Export OutputCode
2546 */
2547 switch(sd->stc.flags & STCCOMP) {
2548 case STCPLAIN: param_string_from_string(ps,"plain"); break;
2549 case STCDELTA: param_string_from_string(ps,"deltarow"); break;
2550 default: param_string_from_string(ps,"runlength"); break;
2551 }
2552 code = param_write_string(plist,"OutputCode",&ps);
2553 if ( code < 0 ) return code;
2554 /*
2555 * Export Model
2556 */
2557 switch(sd->stc.flags & STCMODEL) {
2558 case STCST800: param_string_from_string(ps,"st800"); break;
2559 case STCSTCII: param_string_from_string(ps,"stcii"); break;
2560 default: param_string_from_string(ps,"stc"); break;
2561 }
2562 code = param_write_string(plist,"Model",&ps);
2563 if ( code < 0 ) return code;
2564
2565 /*
2566 * Export the booleans
2567 */
2568 #define stc_write_flag(Mask,Name) \
2569 btmp = sd->stc.flags & (Mask) ? true : false; \
2570 code = param_write_bool(plist,Name,&btmp); \
2571 if ( code < 0 ) return code;
2572
2573 stc_write_flag(STCUNIDIR,"Unidirectional")
2574 stc_write_flag(STCUWEAVE,"Microweave")
2575 btmp = sd->stc.flags & (STCUNIDIR|STCUWEAVE) ? false : true;
2576 code = param_write_bool(plist,"Softweave",&btmp);
2577 if ( code < 0 ) return code;
2578 stc_write_flag(STCNWEAVE,"noWeave")
2579 stc_write_flag(STCDFLAG0, "Flag0")
2580 stc_write_flag(STCDFLAG1, "Flag1")
2581 stc_write_flag(STCDFLAG2, "Flag2")
2582 stc_write_flag(STCDFLAG3, "Flag3")
2583 stc_write_flag(STCDFLAG4, "Flag4")
2584
2585 #undef stc_write_flag
2586
2587 # define stc_write_int(Mask,Name,Val) \
2588 code = param_write_int(plist,Name,&Val); \
2589 if ( code < 0 ) return code
2590
2591 stc_write_int(STCBAND, "escp_Band", sd->stc.escp_m);
2592 stc_write_int(STCWIDTH, "escp_Width", sd->stc.escp_width);
2593 stc_write_int(STCHEIGHT,"escp_Height",sd->stc.escp_height);
2594 stc_write_int(STCTOP, "escp_Top", sd->stc.escp_top);
2595 stc_write_int(STCBOTTOM,"escp_Bottom",sd->stc.escp_bottom);
2596
2597 # undef stc_write_int
2598
2599 code = param_write_string(plist,"escp_Init",&sd->stc.escp_init);
2600 code = param_write_string(plist,"escp_Release",&sd->stc.escp_release);
2601
2602 if(sd->stc.dither != NULL) {
2603 param_string_from_string(ps,sd->stc.dither->name);
2604 code = param_write_string(plist,"Dithering",&ps);
2605 } else {
2606 code = param_write_null(plist,"Dithering");
2607 }
2608 if ( code < 0 ) return code;
2609
2610 nc = sd->color_info.num_components;
2611
2612 if(sd->stc.am != NULL) {
2613 if( nc == 1) set_param_array(pfa, sd->stc.am, 3)
2614 else if(nc == 3) set_param_array(pfa, sd->stc.am, 9)
2615 else set_param_array(pfa, sd->stc.am,16)
2616 code = param_write_float_array(plist,"ColorAdjustMatrix",&pfa);
2617 } else {
2618 code = param_write_null(plist,"ColorAdjustMatrix");
2619 }
2620 if ( code < 0 ) return code;
2621
2622 if(nc == 1) { /* DeviceGray */
2623
2624 stc_write_xarray(0,"Kcoding","Ktransfer");
2625
2626 stc_write_null("Rcoding"); stc_write_null("Rtransfer");
2627 stc_write_null("Gcoding"); stc_write_null("Gtransfer");
2628 stc_write_null("Bcoding"); stc_write_null("Btransfer");
2629
2630 stc_write_null("Ccoding"); stc_write_null("Ctransfer");
2631 stc_write_null("Mcoding"); stc_write_null("Mtransfer");
2632 stc_write_null("Ycoding"); stc_write_null("Ytransfer");
2633
2634 } else if(nc == 3) { /* DeviceRGB */
2635
2636 stc_write_xarray(0,"Rcoding","Rtransfer");
2637 stc_write_xarray(1,"Gcoding","Gtransfer");
2638 stc_write_xarray(2,"Bcoding","Btransfer");
2639
2640 stc_write_null("Ccoding"); stc_write_null("Ctransfer");
2641 stc_write_null("Mcoding"); stc_write_null("Mtransfer");
2642 stc_write_null("Ycoding"); stc_write_null("Ytransfer");
2643 stc_write_null("Kcoding"); stc_write_null("Ktransfer");
2644
2645 } else { /* DeviceCMYK */
2646
2647 stc_write_xarray(0,"Ccoding","Ctransfer");
2648 stc_write_xarray(1,"Mcoding","Mtransfer");
2649 stc_write_xarray(2,"Ycoding","Ytransfer");
2650 stc_write_xarray(3,"Kcoding","Ktransfer");
2651
2652 stc_write_null("Rcoding"); stc_write_null("Rtransfer");
2653 stc_write_null("Gcoding"); stc_write_null("Gtransfer");
2654 stc_write_null("Bcoding"); stc_write_null("Btransfer");
2655
2656 }
2657 return code;
2658 }
2659
2660 /***
2661 *** put parameters == Store them in the device-structure
2662 ***/
2663
2664 static int
stc_put_params(gx_device * pdev,gs_param_list * plist)2665 stc_put_params(gx_device *pdev, gs_param_list *plist)
2666 {
2667 int code,error,i,l;
2668 bool b1,b2,b3;
2669 float fv,*fp;
2670 gs_param_string ps;
2671 gs_param_string_array psa;
2672 gs_param_float_array pfa;
2673 stcolor_device *sd = (stcolor_device *) pdev;
2674 gx_device_color_info oldcolor;
2675 stc_t oldstc;
2676
2677 /*
2678 * save old Values
2679 */
2680 memcpy(&oldcolor,&sd->color_info,sizeof(oldcolor));
2681 memcpy(&oldstc ,&sd->stc ,sizeof(oldstc ));
2682
2683 /*
2684 * Arrrgh:
2685 * With Version 3.4x and above my simple minded read-only Parameters
2686 * do not work any more. So read them here for heavens sake.
2687 */
2688 code = param_read_string(plist,"Version",&ps);
2689 code = param_read_int(plist,"BitsPerComponent",&i);
2690 code = param_read_string_array(plist,"Algorithms",&psa);
2691
2692 /*
2693 * Fetch Major-Parameters (Model, Dithering, BitsPerPixel/BitsPerComponent)
2694 */
2695 error = 0;
2696
2697 code = param_read_string(plist,"Model",&ps);
2698 if(code == 0) { /* Analyze the Model-String */
2699 /*
2700 * Arrgh: I should have known, that internal strings are not zero-terminated.
2701 */
2702 for(l = ps.size; (l > 0) && (ps.data[l-1] == 0); --l);
2703 # define stc_putcmp(Name) \
2704 ((strlen(Name) != l) || (0 != strncmp(Name, (const char *)ps.data,l)))
2705
2706 sd->stc.flags &= ~STCMODEL;
2707 if( !stc_putcmp("st800")) sd->stc.flags |= STCST800;
2708 else if(!stc_putcmp("stcii")) sd->stc.flags |= STCSTCII;
2709
2710 } /* Analyze the Model-String */
2711 if(code < 0) param_signal_error(plist,"Model",code);
2712 error = error > code ? code : error;
2713
2714 /* If we're running for st800, #components must be 1 */
2715 if(((sd->stc.flags & STCMODEL) == STCST800) &&
2716 (( sd->color_info.num_components > 1) ||
2717 ( sd->stc.dither == NULL) ||
2718 ((sd->stc.dither->flags & 7) > 1))) {
2719 sd->color_info.num_components = 1;
2720 sd->stc.dither = NULL;
2721 }
2722
2723 /* Weaving isn't a feature for the st800 */
2724 if((sd->stc.flags & STCMODEL) == STCST800) {
2725 sd->stc.flags &= ~STCUWEAVE;
2726 sd->stc.flags |= STCNWEAVE;
2727 } else if((sd->stc.flags & STCMODEL) == STCSTCII) { /* no SoftWeave */
2728 sd->stc.flags |= STCNWEAVE;
2729 }
2730
2731 code = param_read_string(plist,"Dithering",&ps);
2732 if(code == 0) { /* lookup new value new value */
2733
2734 for(l = ps.size; (l > 0) && (ps.data[l-1] == 0); --l);
2735
2736 for(i = 0; stc_dither[i].name != NULL; ++i)
2737 if(!stc_putcmp(stc_dither[i].name)) break;
2738
2739 } else if(sd->stc.dither != NULL) { /* compute index of given value */
2740
2741 i = sd->stc.dither - stc_dither;
2742
2743 } else { /* find matching value */
2744
2745 for(i = 0; stc_dither[i].name != NULL; ++i)
2746 if((stc_dither[i].flags & 7) == sd->color_info.num_components) break;
2747
2748 } /* we've got an index */
2749
2750 if(stc_dither[i].name != NULL) { /* establish data */
2751
2752 /*
2753 * Establish new dithering algorithm & color-model
2754 */
2755 sd->stc.dither = stc_dither+i;
2756 sd->color_info.num_components = sd->stc.dither->flags & 7;
2757 STC_TYPESWITCH(sd->stc.dither,stc_sizeofitem)
2758 # undef stc_sizeofitem
2759 if(((sd->stc.flags & STCMODEL) == STCST800) &&
2760 ( sd->color_info.num_components > 1 ))
2761 code = gs_error_rangecheck;
2762
2763 /*
2764 * reset Parameters related to the color-model, if it changed
2765 */
2766
2767 if(sd->color_info.num_components != oldcolor.num_components) {
2768
2769 for(i = 0; i < sd->color_info.num_components; ++i) {
2770 sd->stc.extv[i] = (float *) defext;
2771 sd->stc.sizv[i] = countof(defext);
2772
2773 sd->stc.extc[i] = NULL;
2774 sd->stc.sizc[i] = 0;
2775
2776 }
2777
2778 sd->stc.am = NULL;
2779
2780 } else { /* guarantee, that extvals is present */
2781
2782 for(i = 0; i < sd->color_info.num_components; ++i) {
2783 if(sd->stc.sizv[i] < 2) {
2784 sd->stc.extv[i] = (float *) defext;
2785 sd->stc.sizv[i] = countof(defext);
2786 }
2787 }
2788 }
2789
2790 for(i = sd->color_info.num_components; i < 4; ++ i) { /* clear unused */
2791 sd->stc.extv[i] = NULL;
2792 sd->stc.sizv[i] = 0;
2793 sd->stc.vals[i] = NULL;
2794
2795 sd->stc.extc[i] = NULL;
2796 sd->stc.sizc[i] = 0;
2797 sd->stc.code[i] = NULL;
2798
2799 } /* clear unused */
2800
2801 /*
2802 * Guess default depth from range of values
2803 */
2804 if((sd->stc.dither != oldstc.dither)||(oldstc.vals[0] == NULL)) {
2805
2806 if((sd->stc.dither->flags & STC_CMYK10) != 0) {
2807
2808 sd->stc.flags |= STCCMYK10;
2809 sd->stc.bits = 10;
2810 sd->color_info.depth = 32;
2811
2812 } else {
2813
2814 sd->stc.flags &= ~STCCMYK10;
2815
2816 if((sd->stc.dither->flags & STC_FLOAT) != STC_FLOAT) {
2817 fv = 2.0;
2818 for(i = 1;(i < gx_color_value_bits) &&
2819 (fv <= (sd->stc.dither->minmax[1]-sd->stc.dither->minmax[0]));
2820 ++i) fv *= 2.0;
2821
2822 } else {
2823 i = 8; /* arbitrary */
2824 }
2825
2826 if((i*sd->color_info.num_components) > (sizeof(stc_pixel)*8)) {
2827
2828 sd->stc.bits = (sizeof(stc_pixel)*8) /
2829 sd->color_info.num_components;
2830 sd->color_info.depth = sd->stc.bits * sd->color_info.num_components;
2831
2832 } else {
2833
2834 sd->stc.bits = i;
2835 sd->color_info.depth = sd->stc.bits * sd->color_info.num_components;
2836
2837 }
2838 }
2839 }
2840
2841 } else {
2842
2843 code = gs_error_rangecheck;
2844
2845 } /* verify new value */
2846 if(code < 0) param_signal_error(plist,"Dithering",code);
2847 error = error > code ? code : error;
2848
2849 /*
2850 * now fetch the desired depth, if the algorithm allows it
2851 */
2852 /*
2853 * Arrrgh: We get code == 0, even if nobody sets BitsPerPixel.
2854 * The value is the old one, but this may cause trouble
2855 * with CMYK10.
2856 */
2857 code = param_read_int(plist, "BitsPerPixel", &i);
2858 if((error == 0) && (code == 0) &&
2859 (((sd->stc.flags & STCCMYK10) == 0) || (i != sd->color_info.depth))) {
2860
2861 if((1 > i) || (i > (sizeof(stc_pixel)*8)))
2862 code = gs_error_rangecheck;
2863 else
2864 sd->color_info.depth = i;
2865
2866 sd->stc.bits = i / sd->color_info.num_components;
2867
2868 if(1 > sd->stc.bits) code = gs_error_rangecheck;
2869
2870 if((sd->stc.dither->flags & STC_DIRECT) &&
2871 (sd->stc.dither->flags & STC_CMYK10))
2872 code = gs_error_rangecheck;
2873 else
2874 sd->stc.flags &= ~STCCMYK10;
2875
2876 }
2877 if(code < 0) param_signal_error(plist,"BitsPerPixel",code);
2878 error = error > code ? code : error;
2879
2880 /*
2881 * Fetch OutputCode
2882 */
2883 code = param_read_string(plist,"OutputCode",&ps);
2884 if(code == 0) { /* Analyze the OutputCode-String */
2885
2886 for(l = ps.size; (l > 0) && (ps.data[l-1] == 0); --l);
2887
2888 sd->stc.flags &= ~STCCOMP;
2889 if(!stc_putcmp("plain")) sd->stc.flags |= STCPLAIN;
2890 else if(!stc_putcmp("deltarow")) sd->stc.flags |= STCDELTA;
2891
2892 } /* Analyze the OutputCode-String */
2893 if((sd->stc.flags & STCCOMP) == STCDELTA) {
2894 sd->stc.flags |= STCUWEAVE;
2895 sd->stc.flags &= ~STCNWEAVE;
2896 }
2897 if(code < 0) param_signal_error(plist,"OutputCode",code);
2898 error = error > code ? code : error;
2899
2900 /*
2901 * fetch the weave-mode (noWeave wins)
2902 */
2903 b1 = sd->stc.flags & STCUWEAVE ? true : false;
2904 b2 = sd->stc.flags & STCNWEAVE ? true : false;
2905 b3 = sd->stc.flags & (STCUWEAVE|STCNWEAVE) ? false : true;
2906
2907 code = param_read_bool(plist,"Microweave",&b1);
2908 if(code < 0) {
2909 param_signal_error(plist,"Microweave",code);
2910 } else if(code == 0) {
2911 if(b1) { b2 = false; b3 = false; }
2912 }
2913 error = error > code ? code : error;
2914
2915 code = param_read_bool(plist,"noWeave",&b2);
2916 if(code < 0) {
2917 param_signal_error(plist,"noWeave",code);
2918 } else if (code == 0) {
2919 if(b2) { b1 = false; b3 = false; }
2920 }
2921 error = error > code ? code : error;
2922
2923 code = param_read_bool(plist,"Softweave",&b3);
2924 if(code < 0) {
2925 param_signal_error(plist,"Softweave",code);
2926 } else if (code == 0) {
2927 if(b3) { b1 = false; b2 = false; }
2928 }
2929 error = error > code ? code : error;
2930
2931 if(b1) sd->stc.flags |= STCUWEAVE;
2932 else sd->stc.flags &= ~STCUWEAVE;
2933
2934 if(b2) sd->stc.flags |= STCNWEAVE;
2935 else sd->stc.flags &= ~STCNWEAVE;
2936
2937 /*
2938 * Check the simple Flags
2939 */
2940 # define stc_read_flag(Mask,Name) \
2941 code = param_read_bool(plist,Name,&b1); \
2942 if(code < 0) { \
2943 param_signal_error(plist,Name,code); \
2944 } else if(code == 0) { \
2945 if(b1 == true) sd->stc.flags |= Mask; \
2946 else sd->stc.flags &= ~(Mask); \
2947 } \
2948 error = error > code ? code : error;
2949
2950 stc_read_flag(STCUNIDIR,"Unidirectional")
2951 stc_read_flag(STCDFLAG0, "Flag0")
2952 stc_read_flag(STCDFLAG1, "Flag1")
2953 stc_read_flag(STCDFLAG2, "Flag2")
2954 stc_read_flag(STCDFLAG3, "Flag3")
2955 stc_read_flag(STCDFLAG4, "Flag4")
2956
2957 /*
2958 * Now deal with the escp-Stuff
2959 */
2960 # define stc_read_int(Mask,Name,Val) \
2961 code = param_read_int(plist,Name,&Val); \
2962 if(code < 0) \
2963 param_signal_error(plist,Name,code); \
2964 else if(code == 0) \
2965 sd->stc.flags |= Mask; \
2966 error = error > code ? code : error
2967
2968 stc_read_int(STCBAND, "escp_Band", sd->stc.escp_m);
2969 stc_read_int(STCWIDTH, "escp_Width", sd->stc.escp_width);
2970 stc_read_int(STCHEIGHT,"escp_Height",sd->stc.escp_height);
2971 stc_read_int(STCTOP, "escp_Top", sd->stc.escp_top);
2972 stc_read_int(STCBOTTOM,"escp_Bottom",sd->stc.escp_bottom);
2973
2974 # undef stc_read_int
2975
2976 code = param_read_string(plist,"escp_Init",&sd->stc.escp_init);
2977 if(code == 0) sd->stc.flags |= STCINIT;
2978 error = error > code ? code : error;
2979
2980 code = param_read_string(plist,"escp_Release",&sd->stc.escp_release);
2981 if(code == 0) sd->stc.flags |= STCRELEASE;
2982 error = error > code ? code : error;
2983
2984 /*
2985 * ColorAdjustMatrix must match the required size,
2986 * setting it explicitly to null, erases old matrix
2987 */
2988 code = param_read_float_array(plist,"ColorAdjustMatrix",&pfa);
2989 if((error == 0) && (code == 0)) {
2990 if(((sd->color_info.num_components == 1) && (pfa.size == 3)) ||
2991 ((sd->color_info.num_components == 3) && (pfa.size == 9)) ||
2992 ((sd->color_info.num_components == 4) && (pfa.size == 16)))
2993 sd->stc.am = (float *) pfa.data;
2994 else
2995 code = gs_error_rangecheck;
2996 } else if(code < 0) {
2997 code = param_read_null(plist,"ColorAdjustMatrix");
2998 if(code == 0) sd->stc.am = NULL;
2999 }
3000 if(code < 0) param_signal_error(plist,"ColorAdjustMatrix",code);
3001 error = error > code ? code : error;
3002
3003 /*
3004 * Read the external array-Parameters
3005 */
3006 if(sd->color_info.num_components == 1) { /* DeviceGray */
3007
3008 stc_read_xarray(0,"Kcoding","Ktransfer");
3009
3010 stc_read_null("Rcoding"); stc_read_null("Rtransfer");
3011 stc_read_null("Gcoding"); stc_read_null("Gtransfer");
3012 stc_read_null("Bcoding"); stc_read_null("Btransfer");
3013
3014 stc_read_null("Ccoding"); stc_read_null("Ctransfer");
3015 stc_read_null("Mcoding"); stc_read_null("Mtransfer");
3016 stc_read_null("Ycoding"); stc_read_null("Ytransfer");
3017
3018 } else if(sd->color_info.num_components == 3) { /* DeviceRGB */
3019
3020 stc_read_xarray(0,"Rcoding","Rtransfer");
3021 stc_read_xarray(1,"Gcoding","Gtransfer");
3022 stc_read_xarray(2,"Bcoding","Btransfer");
3023
3024 stc_read_null("Ccoding"); stc_read_null("Ctransfer");
3025 stc_read_null("Mcoding"); stc_read_null("Mtransfer");
3026 stc_read_null("Ycoding"); stc_read_null("Ytransfer");
3027 stc_read_null("Kcoding"); stc_read_null("Ktransfer");
3028
3029 } else { /* DeviceCMYK */
3030
3031 stc_read_xarray(0,"Ccoding","Ctransfer");
3032 stc_read_xarray(1,"Mcoding","Mtransfer");
3033 stc_read_xarray(2,"Ycoding","Ytransfer");
3034 stc_read_xarray(3,"Kcoding","Ktransfer");
3035
3036 stc_read_null("Rcoding"); stc_read_null("Rtransfer");
3037 stc_read_null("Gcoding"); stc_read_null("Gtransfer");
3038 stc_read_null("Bcoding"); stc_read_null("Btransfer");
3039
3040 }
3041 /*
3042 * Update remaining color_info values
3043 */
3044 if(error == 0) {
3045
3046 /* compute #values from the component-bits */
3047 sd->color_info.max_gray = sd->stc.bits < gx_color_value_bits ?
3048 (1<<sd->stc.bits)-1 : gx_max_color_value;
3049
3050 /* An integer-algorithm might reduce the number of values */
3051 if(((sd->stc.dither->flags & STC_TYPE) != STC_FLOAT) &&
3052 ((sd->stc.dither->minmax[1]-sd->stc.dither->minmax[0]) <
3053 sd->color_info.max_gray))
3054 sd->color_info.max_gray = (gx_color_value)
3055 (sd->stc.dither->minmax[1]-sd->stc.dither->minmax[0]+0.5);
3056
3057 sd->color_info.max_color = sd->color_info.num_components < 3 ? 0 :
3058 sd->color_info.max_gray;
3059 sd->color_info.dither_grays =
3060 sd->color_info.max_gray < gx_max_color_value ?
3061 sd->color_info.max_gray+1 : gx_max_color_value;
3062 sd->color_info.dither_colors = sd->color_info.num_components < 3 ? 0 :
3063 sd->color_info.dither_grays;
3064 }
3065
3066 /*
3067 * Call superclass-Update
3068 */
3069
3070 code = gdev_prn_put_params(pdev, plist);
3071 error = error > code ? code : error;
3072
3073 /*
3074 * Arrrgh, writing BitsPerPixel is really *VERY* special:
3075 * gdev_prn_put_params verifies, that the external value
3076 * is written, if not, it raises a rangecheck-error.
3077 * On the other hand ghostscript is quite unhappy with odd
3078 * values, so we do the necessary rounding *AFTER* the
3079 * "superclass-Update".
3080 */
3081
3082 if(sd->color_info.depth == 3) sd->color_info.depth = 4;
3083 else if(sd->color_info.depth > 4)
3084 sd->color_info.depth = (sd->color_info.depth+7) & ~7;
3085
3086 /*
3087 * Allocate the storage for the arrays in memory
3088 */
3089 if(error == 0) { /* Allocate new external-arrays */
3090
3091 for(i = 0; i < sd->color_info.num_components; ++i){ /* Active components */
3092 int j;
3093
3094 if((sd->stc.extv[i] != oldstc.extv[i]) &&
3095 (sd->stc.extv[i] != defext )) { /* Value-Arrays */
3096
3097 for(j = 0; j < i; ++j)
3098 if((sd->stc.sizv[j] == sd->stc.sizv[i]) &&
3099 (memcmp(sd->stc.extv[j],sd->stc.extv[i],
3100 sd->stc.sizv[i]*sizeof(float)) == 0)) break;
3101
3102 if(j < i) {
3103 sd->stc.extv[i] = sd->stc.extv[j];
3104 } else {
3105 fp = gs_malloc(sd->memory, sd->stc.sizv[i],sizeof(float),"stc_put_params");
3106 if(fp != NULL)
3107 memcpy(fp,sd->stc.extv[i],sd->stc.sizv[i]*sizeof(float));
3108 else
3109 code = gs_error_VMerror;
3110 sd->stc.extv[i] = fp;
3111 }
3112 } /* Value-Arrays */
3113
3114 if((sd->stc.sizc[i] > 1) &&
3115 (sd->stc.extc[i] != oldstc.extc[i])) { /* Code-Arrays */
3116
3117 for(j = 0; j < i; ++j)
3118 if((sd->stc.sizc[j] == sd->stc.sizc[i]) &&
3119 (memcmp(sd->stc.extc[j],sd->stc.extc[i],
3120 sd->stc.sizc[i]*sizeof(float)) == 0)) break;
3121
3122 if(j < i) {
3123 sd->stc.extc[i] = sd->stc.extc[j];
3124 } else {
3125 fp = gs_malloc(sd->memory, sd->stc.sizc[i],sizeof(float),"stc_put_params");
3126 if(fp != NULL)
3127 memcpy(fp,sd->stc.extc[i],sd->stc.sizc[i]*sizeof(float));
3128 else
3129 code = gs_error_VMerror;
3130 sd->stc.extc[i] = fp;
3131 }
3132 } /* Code-Arrays */
3133
3134 } /* Active components */
3135
3136 if((sd->stc.am != NULL) && (sd->stc.am != oldstc.am)) {
3137 if( sd->color_info.num_components == 1) i = 3;
3138 else if(sd->color_info.num_components == 3) i = 9;
3139 else i = 16;
3140 fp = gs_malloc(sd->memory, i,sizeof(float),"stc_put_params");
3141 if(fp != NULL) memcpy(fp,sd->stc.am,i*sizeof(float));
3142 else code = gs_error_VMerror;
3143 sd->stc.am = fp;
3144 }
3145
3146 if(sd->stc.escp_init.data != oldstc.escp_init.data) {
3147 byte *ip = NULL;
3148
3149 if(sd->stc.escp_init.size > 0) {
3150 ip = gs_malloc(sd->memory, sd->stc.escp_init.size,1,"stcolor/init");
3151 if(ip == NULL) {
3152 code = gs_error_VMerror;
3153 sd->stc.escp_init.size = 0;
3154 } else {
3155 memcpy(ip,sd->stc.escp_init.data,sd->stc.escp_init.size);
3156 }
3157 }
3158 sd->stc.escp_init.data = ip;
3159 sd->stc.escp_init.persistent = false;
3160 }
3161
3162 if(sd->stc.escp_release.data != oldstc.escp_release.data) {
3163 byte *ip = NULL;
3164
3165 if(sd->stc.escp_release.size > 0) {
3166 ip = gs_malloc(sd->memory, sd->stc.escp_release.size,1,"stcolor/release");
3167 if(ip == NULL) {
3168 code = gs_error_VMerror;
3169 sd->stc.escp_release.size = 0;
3170 } else {
3171 memcpy(ip,sd->stc.escp_release.data,sd->stc.escp_release.size);
3172 }
3173 }
3174 sd->stc.escp_release.data = ip;
3175 sd->stc.escp_release.persistent = false;
3176 }
3177
3178 if(code < 0) { /* free newly allocated arrays */
3179
3180 if((sd->stc.am != NULL) && (sd->stc.am != oldstc.am)) {
3181 if( sd->color_info.num_components == 1) i = 3;
3182 else if(sd->color_info.num_components == 3) i = 9;
3183 else i = 16;
3184 gs_free(sd->memory, sd->stc.am,i,sizeof(float),"stc_put_params");
3185 }
3186
3187 if((sd->stc.escp_init.data != NULL) &&
3188 (sd->stc.escp_init.data != oldstc.escp_init.data))
3189 gs_free(sd->memory, (byte *) sd->stc.escp_init.data,sd->stc.escp_init.size,1,
3190 "stcolor/init");
3191
3192 if((sd->stc.escp_release.data != NULL) &&
3193 (sd->stc.escp_release.data != oldstc.escp_release.data))
3194 gs_free(sd->memory, (byte *) sd->stc.escp_release.data,sd->stc.escp_release.
3195 size,1,"stcolor/release");
3196
3197 for(i = 0; i < sd->color_info.num_components; ++i) { /* components */
3198 int j;
3199
3200 if((sd->stc.extc[i] != NULL) &&
3201 (sd->stc.extc[i] != defext) &&
3202 (sd->stc.extc[i] != oldstc.extc[i])) {
3203
3204 for(j = 0; j < i; ++j)
3205 if(sd->stc.extc[i] == sd->stc.extc[j]) break;
3206
3207 if(i == j) gs_free(sd->memory, sd->stc.extc[i],sd->stc.sizc[i],sizeof(float),
3208 "stc_put_params");
3209 }
3210
3211 if((sd->stc.extv[i] != NULL) &&
3212 (sd->stc.extv[i] != oldstc.extv[i]) &&
3213 (sd->stc.extv[i] != defext)) {
3214
3215 for(j = 0; j < i; ++j)
3216 if(sd->stc.extv[i] == sd->stc.extv[j]) break;
3217
3218 if(i == j) gs_free(sd->memory, sd->stc.extv[i],sd->stc.sizv[i],sizeof(float),
3219 "stc_put_params");
3220 }
3221 } /* components */
3222 } /* free newly allocated arrays */
3223 } /* Allocate new arrays */
3224 error = error > code ? code : error;
3225
3226 /*
3227 * finally decide upon restore or release of old, unused data
3228 */
3229 if(error != 0) { /* Undo changes */
3230
3231 memcpy(&sd->color_info,&oldcolor,sizeof(oldcolor));
3232 memcpy(&sd->stc ,&oldstc ,sizeof(oldstc ));
3233 } else { /* undo / release */
3234
3235 if((oldstc.escp_init.data != NULL) &&
3236 (oldstc.escp_init.data != sd->stc.escp_init.data)) {
3237 gs_free(sd->memory, (byte *)oldstc.escp_init.data,
3238 oldstc.escp_init.size,1,"stcolor/init");
3239 }
3240
3241 if((oldstc.escp_release.data != NULL) &&
3242 (oldstc.escp_release.data != sd->stc.escp_release.data)) {
3243 gs_free(sd->memory, (byte *)oldstc.escp_release.data,
3244 oldstc.escp_release.size,1,"stcolor/release");
3245 }
3246
3247 if((oldstc.am != NULL) && (oldstc.am != sd->stc.am)) {
3248 if( oldcolor.num_components == 1) i = 3;
3249 else if(oldcolor.num_components == 3) i = 9;
3250 else i = 16;
3251 gs_free(sd->memory, oldstc.am,i,sizeof(float),"stc_put_params");
3252 }
3253
3254 for(i = 0; i < 4; ++i) {
3255 int j;
3256
3257 if((oldstc.extc[i] != NULL) &&
3258 (oldstc.extc[i] != sd->stc.extc[i]) &&
3259 (oldstc.dither != NULL) &&
3260 (oldstc.extc[i] != defext)) {
3261
3262 for(j = 0; j < i; ++j) if(oldstc.extc[i] == oldstc.extc[j]) break;
3263
3264 if(i == j) gs_free(sd->memory, oldstc.extc[i],oldstc.sizc[i],sizeof(float),
3265 "stc_put_params");
3266 }
3267
3268 if((oldstc.extv[i] != NULL) &&
3269 (oldstc.extv[i] != sd->stc.extv[i]) &&
3270 (oldstc.extv[i] != defext)) {
3271
3272 for(j = 0; j < i; ++j) if(oldstc.extv[i] == oldstc.extv[j]) break;
3273
3274 if(i == j) gs_free(sd->memory, oldstc.extv[i],oldstc.sizv[i],sizeof(float),
3275 "stc_put_params");
3276 }
3277 }
3278
3279 /*
3280 * Close the device if colormodel changed or recomputation
3281 * of internal arrays is required
3282 */
3283 if(sd->is_open) { /* we might need to close it */
3284 bool doclose = false;
3285 if((sd->color_info.num_components != oldcolor.num_components) ||
3286 (sd->color_info.depth != oldcolor.depth ) ||
3287 (sd->stc.bits != oldstc.bits ) ||
3288 (sd->stc.dither != oldstc.dither ))
3289 doclose = true;
3290
3291 for(i = 0; i < sd->color_info.num_components; ++i) {
3292 if(sd->stc.extv[i] != oldstc.extv[i]) doclose = true;
3293 if(sd->stc.extc[i] != oldstc.extc[i]) doclose = true;
3294 }
3295 if(doclose) {
3296 stc_freedata(pdev->memory, &oldstc);
3297 for(i = 0; i < 4; ++i) {
3298 sd->stc.vals[i] = NULL;
3299 sd->stc.code[i] = NULL;
3300 }
3301
3302 gs_closedevice(pdev);
3303 }
3304 } /* we might need to close it */
3305
3306 }
3307
3308 return error;
3309 }
3310 /*
3311 * 1Bit CMYK-Algorithm
3312 */
3313
3314 static int
stc_gscmyk(stcolor_device * sdev,int npixel,byte * in,byte * buf,byte * out)3315 stc_gscmyk(stcolor_device *sdev,int npixel,byte *in,byte *buf,byte *out)
3316 {
3317
3318 byte *ip = in;
3319 int error = 0;
3320
3321 /* ============================================================= */
3322 if(npixel > 0) { /* npixel > 0 -> scanline-processing */
3323 /* ============================================================= */
3324
3325 int p;
3326
3327 /*
3328 * simply split the two pixels rsiding in a byte
3329 */
3330 for(p = npixel; p > 0; --p) { /* loop over pixels */
3331 byte tmp =*ip++;
3332
3333 *out++ = (tmp>>4) & 15;
3334 if(--p <= 0) break;
3335
3336 *out++ = tmp & 15;
3337
3338 } /* loop over pixels */
3339
3340 /* ============================================================= */
3341 } else { /* npixel <= 0 -> initialisation */
3342 /* ============================================================= */
3343
3344 /* we didn't check for the white-calls above, so this may cause errors */
3345 if(sdev->stc.dither->flags & STC_WHITE) error = -1;
3346
3347 /* if we're not setup for bytes, this is an error too */
3348 if((sdev->stc.dither->flags & STC_TYPE) != STC_BYTE) error = -2;
3349
3350 /* This IS a direct-driver, so STC_DIRECT must be set! */
3351 if((sdev->stc.dither->flags & STC_DIRECT) == 0) error = -3;
3352
3353 /* and cmyk-mode is the only supported mode */
3354 if(sdev->color_info.num_components != 4) error = -4;
3355
3356 /* and we support only 4Bit-Depth here */
3357 if(sdev->color_info.depth != 4) error = -5;
3358
3359 /* ============================================================= */
3360 } /* scanline-processing or initialisation */
3361 /* ============================================================= */
3362
3363 return error;
3364 }
3365
3366 /*
3367 * The following is an algorithm under test
3368 */
3369 static int
stc_hscmyk(stcolor_device * sdev,int npixel,byte * in,byte * buf,byte * out)3370 stc_hscmyk(stcolor_device *sdev,int npixel,byte *in,byte *buf,byte *out)
3371 {
3372
3373 /* ============================================================= */
3374 if(npixel < 0) { /* npixel <= 0 -> initialisation */
3375 /* ============================================================= */
3376
3377 int i,i2do;
3378 long *lp = (long *) buf;
3379
3380 /* CMYK-only algorithm */
3381 if( sdev->color_info.num_components != 4) return -1;
3382
3383 /*
3384 * check wether stcdither & TYPE are correct
3385 */
3386 if(( sdev->stc.dither == NULL) ||
3387 ((sdev->stc.dither->flags & STC_TYPE) != STC_LONG)) return -2;
3388
3389 /*
3390 * check wether the buffer-size is sufficiently large
3391 */
3392 if(((sdev->stc.dither->flags/STC_SCAN) < 1) ||
3393 ( sdev->stc.dither->bufadd <
3394 (1 + 2*sdev->color_info.num_components))) return -3;
3395
3396 /*
3397 * must have STC_CMYK10, STC_DIRECT, but not STC_WHITE
3398 */
3399 if((sdev->stc.dither->flags & STC_CMYK10) == 0) return -4;
3400 if((sdev->stc.dither->flags & STC_DIRECT) == 0) return -5;
3401 if((sdev->stc.dither->flags & STC_WHITE ) != 0) return -6;
3402
3403 /*
3404 * Must have values between 0-1023.0
3405 */
3406 if((sdev->stc.dither->minmax[0] != 0.0) ||
3407 (sdev->stc.dither->minmax[1] != 1023.0)) return -7;
3408 /*
3409 * initialize buffer
3410 */
3411
3412 i2do = 1 + 8 - 4 * npixel;
3413 lp[0] = 0;
3414
3415 if(sdev->stc.flags & STCDFLAG0) {
3416 for(i = 1; i < i2do; ++i) lp[i] = 0;
3417 } else {
3418 for(i = 1; i < i2do; ++i) lp[i] = (rand() % 381) - 190;
3419 }
3420
3421 /* ============================================================= */
3422 } else { /* npixel > 0 && in != NULL -> scanline-processing */
3423 /* ============================================================= */
3424
3425 long errc[4],*errv;
3426 int step = buf[0] ? -1 : 1;
3427 stc_pixel *ip = (stc_pixel *) in;
3428
3429 buf[0] = ~ buf[0];
3430 errv = (long *) buf + 5;
3431
3432 if(step < 0) {
3433 ip += npixel-1;
3434 out += npixel-1;
3435 errv += 4*(npixel-1);
3436 }
3437
3438 errc[0] = 0; errc[1] = 0; errc[2] = 0; errc[3] = 0;
3439
3440 while(npixel-- > 0) {
3441
3442 register stc_pixel ci,mode;
3443 register long k,v,n;
3444 register int pixel; /* internal pixel-value */
3445
3446 ci = *ip; ip += step;
3447
3448 mode = ci & 3;
3449 k = (ci>>2) & 0x3ff;
3450 pixel = 0;
3451
3452 v = k+errv[3]+((7*errc[3])>>4);
3453
3454 if(mode == 3) { /* only Black allowed to fire */
3455
3456 if(v > 511) {
3457 v -= 1023;
3458 pixel = BLACK;
3459 }
3460 errv[3-(step<<2)] += ((3*v+8)>>4); /* 3/16 */
3461 errv[3] = ((5*v+errc[3]+8)>>4);/* 5/16 +1/16 (rest) */
3462 errc[3] = v;
3463
3464 errv[0] = errv[0] < -190 ? -190 : errv[0] < 190 ? errv[0] : 190;
3465 errv[1] = errv[1] < -190 ? -190 : errv[1] < 190 ? errv[1] : 190;
3466 errv[2] = errv[2] < -190 ? -190 : errv[2] < 190 ? errv[2] : 190;
3467
3468 errc[0] = 0; errc[1] = 0; errc[2] = 0;
3469
3470 } else if(v > 511) { /* black known to fire */
3471
3472 v -= 1023;
3473 pixel = BLACK;
3474
3475 errv[3-(step<<2)] += ((3*v+8)>>4); /* 3/16 */
3476 errv[3] = ((5*v+errc[3]+8)>>4);/* 5/16 +1/16 (rest) */
3477 errc[3] = v;
3478
3479 n = (ci>>12) & 0x3ff;
3480
3481 if(mode == 2) { v = k; }
3482 else { v = n; n = (ci>>22) & 0x3ff; }
3483
3484 v += errv[2]+((7*errc[2])>>4)-1023;
3485 if(v < -511) v = -511;
3486 errv[2-(step<<2)] += ((3*v+8)>>4); /* 3/16 */
3487 errv[2] = ((5*v+errc[2]+8)>>4);/* 5/16 +1/16 (rest) */
3488 errc[2] = v;
3489
3490 if(mode == 1) { v = k; }
3491 else { v = n; n = (ci>>22) & 0x3ff; }
3492
3493 v += errv[1]+((7*errc[1])>>4)-1023;
3494 if(v < -511) v = -511;
3495 errv[1-(step<<2)] += ((3*v+8)>>4); /* 3/16 */
3496 errv[1] = ((5*v+errc[1]+8)>>4);/* 5/16 +1/16 (rest) */
3497 errc[1] = v;
3498
3499 if(mode == 0) v = k;
3500 else v = n;
3501
3502 v += errv[0]+((7*errc[0])>>4)-1023;
3503 if(v < -511) v = -511;
3504 errv[0-(step<<2)] += ((3*v+8)>>4); /* 3/16 */
3505 errv[0] = ((5*v+errc[0]+8)>>4);/* 5/16 +1/16 (rest) */
3506 errc[0] = v;
3507
3508 } else { /* Black does not fire initially */
3509
3510 long kv = v; /* Black computed after colors */
3511
3512 n = (ci>>12) & 0x3ff;
3513
3514 if(mode == 2) { v = k; }
3515 else { v = n; n = (ci>>22) & 0x3ff; }
3516
3517 v += errv[2]+((7*errc[2])>>4);
3518 if(v > 511) {
3519 pixel |= YELLOW;
3520 v -= 1023;
3521 }
3522 errv[2-(step<<2)] += ((3*v+8)>>4); /* 3/16 */
3523 errv[2] = ((5*v+errc[2]+8)>>4);/* 5/16 +1/16 (rest) */
3524 errc[2] = v;
3525
3526 if(mode == 1) { v = k; }
3527 else { v = n; n = (ci>>22) & 0x3ff; }
3528
3529 v += errv[1]+((7*errc[1])>>4);
3530 if(v > 511) {
3531 pixel |= MAGENTA;
3532 v -= 1023;
3533 }
3534 errv[1-(step<<2)] += ((3*v+8)>>4); /* 3/16 */
3535 errv[1] = ((5*v+errc[1]+8)>>4);/* 5/16 +1/16 (rest) */
3536 errc[1] = v;
3537
3538 if(mode == 0) v = k;
3539 else v = n;
3540
3541 v += errv[0]+((7*errc[0])>>4);
3542 if(v > 511) {
3543 pixel |= CYAN;
3544 v -= 1023;
3545 }
3546 errv[0-(step<<2)] += ((3*v+8)>>4); /* 3/16 */
3547 errv[0] = ((5*v+errc[0]+8)>>4);/* 5/16 +1/16 (rest) */
3548 errc[0] = v;
3549
3550 v = kv;
3551 if(pixel == (CYAN|MAGENTA|YELLOW)) {
3552 pixel = BLACK;
3553 v = v > 511 ? v-1023 : -511;
3554 }
3555 errv[3-(step<<2)] += ((3*v+8)>>4); /* 3/16 */
3556 errv[3] = ((5*v+errc[3]+8)>>4);/* 5/16 +1/16 (rest) */
3557 errc[3] = v;
3558
3559 }
3560
3561 errv += step<<2;
3562 *out = pixel; out += step;
3563
3564 } /* loop over pixels */
3565
3566 /* ============================================================= */
3567 } /* initialisation, white or scanline-processing */
3568 /* ============================================================= */
3569
3570 return 0;
3571 }
3572