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