1
/* Copyright (C) 2001-2006 Artifex Software, Inc.
4
This software is provided AS-IS with no warranty, either express or
7
This software is distributed under license and may not be copied, modified
8
or distributed except as expressly authorized under the terms of that
9
license. Refer to licensing information at http://www.artifex.com/
10
or contact Artifex Software, Inc., 7 Mt. Lassen Drive - Suite A-134,
11
San Rafael, CA 94903, U.S.A., +1(415)492-9861, for further information.
14
/* $Id: gdevstc.c 8250 2007-09-25 13:31:24Z giles $*/
15
/* Epson Stylus-Color Printer-Driver */
18
*** This file was "copied" from gdevcdj.c (ghostscript-3.12), which was
20
*** George Cameron - g.cameron@biomed.abdn.ac.ukis
21
*** Koert Zeilstra - koert@zen.cais.com
22
*** Eckhard Rueggeberg - eckhard@ts.go.dlr.de
24
*** Some of the ESC/P2-code was drawn from gdevescp.c, contributed by
25
*** Richard Brown - rab@eos.ncsu.edu
27
*** The POSIX-Interrupt-Code is from (Compile-Time-Option -DSTC_SIGNAL)
28
*** Frederic Loyer - loyer@ensta.fr
30
*** And several improvements are based on discussions with
31
*** Brian Converse - BCONVERSE@ids.net
32
*** Bill Davidson - bdavidson@ra.isisnet.com
33
*** Gero Guenther - gero@cs.tu-berlin.de
34
*** Jason Patterson - jason@reflections.com.au
35
*** ? Rueschstroer - rue@ibe.med.uni-muenchen.de
36
*** Steven Singer - S.Singer@ph.surrey.ac.uk
38
*** And the remaining little rest, mainly the bugs, were written by me:
39
*** Gunther Hess - gunther@elmos.de
41
*** P.S.: there is some documentation, see devices.doc
44
*** 16-DEC-1994 1.1 - initial Version (GS-Dithering & Plain-Write)
46
*** 30-JAN-1995 1.11 - FS-Improvements, u/sWeave, 1/4/24-Bits
47
*** 5-MAR-1995 1.12 - L. Peter Deutsch - updated put_params routine
48
(first distributed version with gs3.33)
49
*** 26-APR-1995 1.13 - merged Peters fixes with algorithmic changes:
50
Changed 24Bit-Mode, added 32Bit-Mode (moves colors)
51
[Arrgh: much better than 1.12, but patch was lost]
52
*** 5-JUN-1995 1.14 - Added Color-Correction & Transfer-Curves
53
(Several Beta-Testers, but not distributed)
55
*** 24-JUL-1995 1.16 - Made dithering-Algorithms external-functions.
56
(Mailed for Beta-Distribution)
57
*** 10-AUG-1995 1.17 - Several Bug-Fixes and some new features:
59
Readonly Parameters added
60
"Algorithms", "BitsPerComponent", "Version"
61
Parameters Flag0-4, Model, OutputCode
62
(mailed for distribution)
63
*** 14-SEP-1995 1.18 Fixes Bugs with Borland C (gs3.47)
64
*** 23-SEP-1995 1.19 - reorganized printcode + bug-fixing
65
*** 24-SEP-1995 1.20 - Little Cleanup for the release
66
*** 25-SEP-1995 1.21 - Readonly-Parameters added to put_params.
67
*** 31-Dec-1995 1.22 - Sanitary Engineering on the code
68
*** 16-Jan-1996 1.23 - Added String escp_Release
69
*** 8-May-1996 1.90 - Reintroduced Deltarow & Fixed MEMORY-BUG!
75
#endif /* STC_SIGNAL */
77
*** Mode-Table - the various algorithms
78
*** (The intention is, that this source can live alone)
81
static stc_proc_dither(stc_gscmyk); /* resides in this file */
82
static stc_proc_dither(stc_hscmyk); /* resides in this file */
84
#include <stdlib.h> /* for rand, used in stc_hscmyk */
86
static const stc_dither_t stc_dither[] = {
87
{"gscmyk", stc_gscmyk, DeviceCMYK|STC_BYTE|STC_DIRECT,0,{0.0,1.0}},
88
{"hscmyk", stc_hscmyk,
89
DeviceCMYK|STC_LONG|STC_CMYK10|STC_DIRECT|1*STC_SCAN,1+2*4,
92
{ NULL , NULL , 0, 0,{0.0,0.0}}
96
*** forward-declarations of routines
99
/* Primary Device functions
100
* (I've the idea to rename the driver to stc)
102
static dev_proc_print_page(stc_print_page);
103
static dev_proc_open_device(stc_open);
104
static dev_proc_close_device(stc_close);
105
static dev_proc_get_params(stc_get_params);
106
static dev_proc_put_params(stc_put_params);
109
* Color-Mapping-functions.
112
/* routines for monochrome monochrome modi */
113
static dev_proc_map_rgb_color(stc_map_gray_color);
114
static dev_proc_map_color_rgb(stc_map_color_gray);
116
/* routines for RGB-Modi */
117
static dev_proc_map_rgb_color(stc_map_rgb_color);
118
static dev_proc_map_color_rgb(stc_map_color_rgb);
120
/* routines for general CMYK-Modi */
121
static dev_proc_map_cmyk_color(stc_map_cmyk_color);
122
static dev_proc_map_color_rgb(stc_map_color_cmyk);
124
/* routines for 10Bit/Component CMYK */
125
static dev_proc_map_cmyk_color(stc_map_cmyk10_color);
126
static dev_proc_map_color_rgb(stc_map_color_cmyk10);
129
*** Table of Device-Procedures
131
static gx_device_procs stcolor_procs = {
133
gx_default_get_initial_matrix,
134
gx_default_sync_output,
135
gdev_prn_output_page,
139
NULL, /* fill_rectangle */
140
NULL, /* tile_rectangle */
141
NULL, /* copy_mono */
142
NULL, /* copy_color */
143
NULL, /* draw_line */
151
*** A local dummy-array for extvals
154
static float defext[] = { 0.0, 1.0 };
157
*** Main device-control structure
159
stcolor_device far_data gs_stcolor_device = {
160
prn_device_body(stcolor_device, stcolor_procs, "stcolor",
161
DEFAULT_WIDTH_10THS, DEFAULT_HEIGHT_10THS,
163
STC_L_MARGIN,STC_B_MARGIN,STC_R_MARGIN,STC_T_MARGIN,
164
4, 4, 1, 1, 2, 2, /* default: cmyk-direct */
166
{STCNWEAVE, /* stcflags: noWeave/bidirectional */
167
1, /* stcbits: matches the default */
168
stc_dither, /* stcdither: first algorithm */
169
NULL, /* stcam: NULL -> not used */
170
{ NULL, NULL, NULL, NULL}, /* extcode: none defined yet */
171
{ 0, 0, 0, 0}, /* sizcode: 0, since no extcode yet */
172
{ NULL, NULL, NULL, NULL}, /* stccode: computed by put_params */
173
{defext,defext,defext,defext},/* extvals: default */
174
{ 2, 2, 2, 2}, /* sizvals: default countof(defext) */
175
{ NULL, NULL, NULL, NULL}, /* stcvals: computed by put_params */
176
{ 0, 0, 0}, /* white-run */
177
{ 0, 0, 0}, /* white-end */
178
{NULL,0,false}, /* algorithm-table */
179
{NULL,0,false}, /* initialization-String (BOP) */
180
{NULL,0,false}, /* release-String (EOP) */
181
0,0,0,0, /* New escp-stuff */
182
1} /* itemsize used by algorithm */
185
*** Test for white scan-lines
187
static bool stc_iswhite(stcolor_device *, int, byte *);
190
*** Functions used for conversion inside the print-loop
192
#define stc_proc_iconvert(Name) \
193
byte * Name(stcolor_device *sd,byte *ext_data,int prt_pixels,byte *alg_line)
195
static stc_proc_iconvert(stc_any_depth); /* general input-conversion */
196
static stc_proc_iconvert(stc_rgb24_long); /* 24Bit RGB -> long's */
198
static stc_proc_iconvert(stc_cmyk32_long); /* 32Bit CMYK -> long's */
199
static stc_proc_iconvert(stc_any_direct); /* use ext_data as input */
201
static stc_proc_iconvert(stc_cmyk10_byte); /* CMYK10->vals-> any type */
202
static stc_proc_iconvert(stc_cmyk10_long); /* CMYK10->vals-> any type */
203
static stc_proc_iconvert(stc_cmyk10_float); /* CMYK10->vals-> any type */
204
static stc_proc_iconvert(stc_cmyk10_dbyte); /* CMYK10 direct bytes */
205
static stc_proc_iconvert(stc_cmyk10_dlong); /* CMYK10 direct longs */
210
static void stc_print_weave(stcolor_device *sd,FILE *prn_stream);
211
static void stc_print_bands(stcolor_device *sd,FILE *prn_stream);
212
static void stc_print_delta(stcolor_device *sd,FILE *prn_stream);
213
static int stc_print_setup(stcolor_device *sd);
216
*** compute the ESC/P2 specific values
220
stc_print_setup(stcolor_device *sd)
224
* Compute the resolution-parameters
226
sd->stc.escp_u = (int)(3600.0 / sd->y_pixels_per_inch); /* y-units */
227
sd->stc.escp_h = (int)(3600.0 / sd->x_pixels_per_inch); /* x-units */
228
sd->stc.escp_v = sd->stc.flags & (STCUWEAVE | STCNWEAVE) ?
233
sd->stc.escp_c = 0; /* preselect-black */
238
if((sd->stc.flags & STCBAND) == 0) {
239
if(sd->stc.escp_v != sd->stc.escp_u) sd->stc.escp_m = 15;
240
else if(STCSTCII == (sd->stc.flags & STCMODEL)) sd->stc.escp_m = 1;
241
else if( sd->stc.flags & STCUWEAVE) sd->stc.escp_m = 1;
242
else if((sd->stc.escp_v == sd->stc.escp_u) &&
243
(sd->stc.escp_u == 5)) sd->stc.escp_m = 1;
244
else sd->stc.escp_m = 1;
250
if((sd->stc.flags & STCWIDTH ) == 0)
251
sd->stc.escp_width = (int)(sd->width -
252
(dev_l_margin(sd)+dev_r_margin(sd))*sd->x_pixels_per_inch);
254
if((sd->stc.flags & STCHEIGHT) == 0)
255
sd->stc.escp_height = sd->height;
257
if((sd->stc.flags & STCTOP) == 0)
258
sd->stc.escp_top = (int)(dev_t_margin(sd)*sd->y_pixels_per_inch);
260
if((sd->stc.flags & STCBOTTOM) == 0)
261
sd->stc.escp_bottom = (int)(sd->height -
262
dev_b_margin(sd)*sd->y_pixels_per_inch);
264
if((sd->stc.flags & STCINIT) == 0) { /* No Initialization-String defined */
265
int need = 8 /* Reset, Graphics-Mode 1 */
267
+ 6 /* Select Units */
268
+ 7 /* Set Page-Length */
269
+ 9 /* Set Margins */
270
+ 3; /* Select Unidirectionality */
271
byte *bp = (byte *) (sd->stc.escp_init.data);
273
if(need != sd->stc.escp_init.size) { /* Reallocate */
275
if(NULL != (bp = gs_malloc(sd->memory, need,1,"stcolor/init"))) { /* Replace */
276
if(0 != sd->stc.escp_init.size)
277
gs_free(sd->memory, (byte *)sd->stc.escp_init.data,sd->stc.escp_init.size,1,
279
sd->stc.escp_init.data = bp;
280
sd->stc.escp_init.size = need;
281
sd->stc.escp_init.persistent = false;
282
} else { /* Replace */
283
return_error(gs_error_VMerror);
287
if(need != 39) return_error(gs_error_unregistered);
290
/* 1 1 11 1 11 1 1 1 2 22 2 2 22 2 22 3 3 3333 3 33*/
291
/* 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*/
292
"\033@\033(G\001\0\1\033(i\1\0w\033(U\001\000u\033(C\2\000hh\033(c\4\000ttbb\033U",
296
if((sd->stc.flags & STCUWEAVE) != 0) bp[13] = '\1';
299
bp[19] = sd->stc.escp_u;
301
bp[25] = sd->stc.escp_height & 0xff;
302
bp[26] = (sd->stc.escp_height>>8) & 0xff;
304
bp[32] = sd->stc.escp_top & 0xff;
305
bp[33] = (sd->stc.escp_top>>8) & 0xff;
306
bp[34] = sd->stc.escp_bottom & 0xff;
307
bp[35] = (sd->stc.escp_bottom>>8) & 0xff;
309
if(sd->stc.flags & STCUNIDIR) bp[38] = 1;
312
} /* No Initialization-String defined */
314
if((sd->stc.flags & STCRELEASE) == 0) { /* No Release-String defined */
315
int need = 3; /* ESC @ \f */
316
byte *bp = (byte *) (sd->stc.escp_release.data);
318
if(need != sd->stc.escp_release.size) { /* Reallocate */
320
if(NULL != (bp = gs_malloc(sd->memory, need,1,"stcolor/release"))) { /* Replace */
321
if(0 != sd->stc.escp_release.size)
322
gs_free(sd->memory, (byte *)sd->stc.escp_release.data,sd->stc.escp_release.size,1,
324
sd->stc.escp_release.data = bp;
325
sd->stc.escp_release.size = need;
326
sd->stc.escp_release.persistent = false;
327
} else { /* Replace */
328
return_error(gs_error_VMerror);
332
if(need != 3) return_error(gs_error_unregistered);
334
memcpy(bp,"\033@\f",need);
336
} /* No Release-String defined */
342
*** stc_print_page: here we go to do the nasty work
346
stc_print_page(gx_device_printer * pdev, FILE * prn_stream)
348
stcolor_device *sd = (stcolor_device *) pdev;
349
long flags = sd == NULL ? 0 : sd->stc.flags;
351
int npass; /* # of print-passes (softweave) */
353
int ext_size; /* size of a ghostscript-scanline */
354
byte *ext_line; /* dyn: for this scanline */
356
int alg_size; /* size of a scanline for the dithering-algorithm */
357
byte *alg_line; /* dyn: 1 scanline for the dithering-algorithm */
358
int buf_size; /* size of the private-buffer for dither-function */
359
byte *buf; /* dyn: the private buffer */
361
int prt_pixels; /* Number of pixels printed */
362
byte *col_line; /* A Line with a byte per pixel */
364
#define OK4GO ((flags & STCOK4GO) != 0)
365
#define SORRY ( flags &= ~STCOK4GO)
367
if(0 > (npass = stc_print_setup(sd))) return_error(npass);
369
npass = sd->stc.escp_v / sd->stc.escp_u;
372
*** Allocate dynamic memory
375
ext_size = gdev_prn_raster(sd);
376
ext_line = gs_malloc(sd->memory, ext_size,1,"stc_print_page/ext_line");
377
if(ext_line == NULL) SORRY;
379
prt_pixels = sd->stc.escp_width;
380
sd->stc.prt_size = (prt_pixels+7)/8;
381
prt_pixels = sd->stc.prt_size * 8;
383
sd->stc.prt_scans = (int)(sd->height -
384
(dev_t_margin(sd)+dev_b_margin(sd))*sd->y_pixels_per_inch);
386
col_line = gs_malloc(sd->memory, prt_pixels,1,"stc_print_page/col_line");
387
if(col_line == NULL) SORRY;
389
alg_size = prt_pixels;
390
alg_size *= sd->color_info.num_components;
392
if((sd->stc.dither->flags & STC_DIRECT) ||
393
((sd->stc.bits == 8) &&
394
(sd->stc.alg_item == 1))) {
397
alg_line = gs_malloc(sd->memory, alg_size,sd->stc.alg_item,"stc_print_page/alg_line");
398
if(alg_line == NULL) SORRY;
401
buf_size = sd->stc.dither->bufadd
402
+ alg_size*(sd->stc.dither->flags/STC_SCAN);
404
buf = gs_malloc(sd->memory, buf_size,sd->stc.alg_item,"stc_print_page/buf");
405
if(buf == NULL) SORRY;
411
* compute the number of printer-buffers
414
for(sd->stc.prt_buf = 16; sd->stc.prt_buf < (sd->stc.escp_m * npass);
415
sd->stc.prt_buf <<= 1);
416
if(sd->color_info.num_components > 1) sd->stc.prt_buf *= 4;
418
sd->stc.prt_width = gs_malloc(sd->memory, sd->stc.prt_buf,sizeof(int),
419
"stc_print_page/prt_width");
420
if(sd->stc.prt_width == NULL) SORRY;
422
sd->stc.prt_data = gs_malloc(sd->memory, sd->stc.prt_buf,sizeof(byte *),
423
"stc_print_page/prt_data");
425
if(sd->stc.prt_data == NULL) {
430
for(i = 0; i < sd->stc.prt_buf; ++i) {
431
sd->stc.prt_data[i] = gs_malloc(sd->memory, sd->stc.prt_size,1,
432
"stc_print_page/prt");
433
if(sd->stc.prt_data[i] == NULL) SORRY;
437
sd->stc.seed_size = (sd->stc.prt_size + 2*sizeof(int) - 1)/sizeof(int);
440
for(i = 0; i < sd->color_info.num_components; ++i) {
441
if((flags & STCCOMP) == STCDELTA) {
442
sd->stc.seed_row[i] = gs_malloc(sd->memory, sd->stc.seed_size,sizeof(int),
443
"stc_print_page/seed_row");
444
if(sd->stc.seed_row[i] == NULL) SORRY;
445
else memset(sd->stc.seed_row[i],0,sd->stc.seed_size*sizeof(int));
447
sd->stc.seed_row[i] = NULL;
450
while(i < countof(sd->stc.seed_row)) sd->stc.seed_row[i++] = NULL;
453
switch(flags & STCCOMP) {
455
sd->stc.escp_size = 64 + sd->stc.prt_size;
458
sd->stc.escp_size = 64 + 2 * sd->stc.prt_size;
461
sd->stc.escp_size = 64 +
462
sd->stc.prt_size + (sd->stc.prt_size + 127)/128;
466
sd->stc.escp_data = gs_malloc(sd->memory, sd->stc.escp_size,1,
467
"stc_print_page/escp_data");
468
if(sd->stc.escp_data == NULL) SORRY;
471
* If we're still ok, we can print something
478
stc_proc_iconvert((*iconvert)) = stc_any_depth;
481
* initialize col_line
483
if(sd->color_info.num_components == 3) {
484
memset(col_line,RED|GREEN|BLUE,prt_pixels);
486
memset(col_line,0, prt_pixels);
490
* select proper conversion for input to algorithm
492
if( (sd->stc.dither->flags & STC_DIRECT ) ||
493
((sd->stc.bits == 8) &&
494
(sd->stc.alg_item == 1)))
495
iconvert = stc_any_direct;
496
else if((sd->color_info.num_components == 3) &&
497
(sd->color_info.depth == 24) &&
498
(sizeof(long) == sd->stc.alg_item))
499
iconvert = stc_rgb24_long;
500
else if(sd->stc.flags & STCCMYK10) {
501
if( ((sd->stc.dither->flags & STC_TYPE) == STC_BYTE) &&
502
( sd->stc.dither->minmax[0] == 0.0 ))
503
iconvert = stc_cmyk10_dbyte;
504
else if ((sd->stc.dither->flags & STC_TYPE) == STC_BYTE)
505
iconvert = stc_cmyk10_byte;
506
else if(((sd->stc.dither->flags & STC_TYPE) == STC_LONG) &&
507
( sd->stc.dither->minmax[0] == 0.0 ) &&
508
( sd->stc.dither->minmax[1] <= 1023.0 ))
509
iconvert = stc_cmyk10_dlong;
510
else if( (sd->stc.dither->flags & STC_TYPE) == STC_LONG)
511
iconvert = stc_cmyk10_long;
513
iconvert = stc_cmyk10_float;
515
else if((sd->color_info.num_components == 4) &&
516
(sd->color_info.depth == 32) &&
517
(sizeof(long) == sd->stc.alg_item))
518
iconvert = stc_cmyk32_long;
521
* initialize the algorithm
524
if((*sd->stc.dither->fun)(sd,-prt_pixels,alg_line,buf,col_line) < 0)
533
sigset_t stc_int_mask, stc_int_save, stc_int_pending;
535
sigemptyset(&stc_int_mask);
536
sigaddset(&stc_int_mask,SIGINT);
537
sigprocmask(SIG_BLOCK,&stc_int_mask, &stc_int_save);
538
#endif /* STC_SIGNAL */
541
if(sd->color_info.num_components > 1) ncolor = 4;
545
* Decide, wether we Adjust Linefeeds or not. (I hate it here)
547
if((0 == ((sd->stc.escp_m*sd->stc.escp_u) % 10)) &&
548
(256 > ((sd->stc.escp_m*sd->stc.escp_u) / 10))) sd->stc.escp_lf = sd->stc.escp_m;
549
else sd->stc.escp_lf = 0;
552
* prepare run-values, then loop over scans
554
sd->stc.stc_y = 0; /* current printer y-Position */
555
sd->stc.buf_y = 0; /* Top-Position within the buffer */
556
sd->stc.prt_y = 0; /* physical position of the printer */
557
buf_i = 0; /* next free line in buffer */
558
sd->stc.flags &= ~STCPRINT; /* no data yet */
560
while(sd->stc.stc_y < sd->stc.prt_scans) { /* Until all scans are processed */
563
need = sd->stc.stc_y + npass * sd->stc.escp_m;
565
if(sd->stc.buf_y < need) { /* Nr. 5 (give me input) */
567
/* read as much as the buffer can hold */
568
if(ncolor == 1) need = sd->stc.stc_y + sd->stc.prt_buf;
569
else need = sd->stc.stc_y + (sd->stc.prt_buf>>2);
571
for(;sd->stc.buf_y < need;
572
buf_i = (sd->stc.prt_buf-1) & (buf_i+ncolor),
579
/* initialize output data 1st -> may take shortcut */
581
for(color = 0; color < ncolor; ++color) {
582
memset(sd->stc.prt_data[buf_i+color],0,sd->stc.prt_size);
583
sd->stc.prt_width[buf_i+color] = 0;
587
/* "read data", immediately continue if all is white */
589
if(sd->stc.buf_y < sd->stc.prt_scans) { /* Test for White */
591
gdev_prn_get_bits(pdev,sd->stc.buf_y,ext_line,&ext_data);
593
color = stc_iswhite(sd,prt_pixels,ext_data) ? ext_size : 0;
599
} /* Test for White */
601
if(color >= ext_size) { /* bypass processing */
603
if(sd->stc.dither->flags & STC_WHITE)
604
(*sd->stc.dither->fun)(sd,prt_pixels,NULL,buf,col_line);
607
} /* bypass processing */
609
/* convert data for the various cases */
611
alg_data = (*iconvert)(sd,ext_data,prt_pixels,alg_line);
615
* invoke the dithering-algorithm
618
(*sd->stc.dither->fun)(sd,prt_pixels,alg_data,buf,col_line);
620
* convert col_line to printer-format (separate colors)
622
switch(sd->color_info.num_components) {
623
case 1: /* Black & White: just merge into 8 Bytes */
625
byte *bytein,*byteout;
629
byteout = sd->stc.prt_data[buf_i];
631
for(width = 1; width <= sd->stc.prt_size; ++width) {
635
for(i = 128; i; i >>= 1) if(*bytein++) tmp |= i;
637
if(tmp != 0) sd->stc.prt_width[buf_i] = width;
643
case 3: /* convert rgb into cmyk */
650
for(width = 0; width < sd->stc.prt_size; ++width) {
655
for(i = 128; i; i >>= 1) {
656
static const byte rgb2cmyk[] = {
657
BLACK, /* 0->Black */
658
CYAN | MAGENTA, /* 1->BLUE */
659
CYAN | YELLOW, /* 2->GREEN */
661
MAGENTA | YELLOW, /* 4->RED */
662
MAGENTA, /* 5->MAGENTA */
663
YELLOW, /* 6->YELLOW */
666
tmp = rgb2cmyk[(*bytein++) & 7];
668
if(tmp & BLACK) cmyk[3] |= i;
669
if(tmp & YELLOW) cmyk[2] |= i;
670
if(tmp & MAGENTA) cmyk[1] |= i;
671
if(tmp & CYAN) cmyk[0] |= i;
674
for(i = 0; i < 4; ++i) {
675
if(cmyk[i] != 0) sd->stc.prt_width[buf_i+i] = width+1;
676
sd->stc.prt_data[buf_i+i][width] = cmyk[i];
681
case 4: /* split cmyk */
688
for(width = 0; width < sd->stc.prt_size; ++width) {
693
for(i = 128; i; i >>= 1) {
694
tmp = (*bytein++) & 15;
695
if(tmp & BLACK) cmyk[3] |= i;
696
if(tmp & YELLOW) cmyk[2] |= i;
697
if(tmp & MAGENTA) cmyk[1] |= i;
698
if(tmp & CYAN) cmyk[0] |= i;
701
for(i = 0; i < 4; ++i) {
702
if(cmyk[i] != 0) sd->stc.prt_width[buf_i+i] = width+1;
703
sd->stc.prt_data[buf_i+i][width] = cmyk[i];
711
} /* Nr. 5 (give me input) */
714
* Nr. 5 has got enough input, now we should print it
716
if((flags & STCCOMP) == STCDELTA) stc_print_delta(sd,prn_stream);
717
else if(npass > 1) stc_print_weave(sd,prn_stream);
718
else stc_print_bands(sd,prn_stream);
721
sigpending(&stc_int_pending);
722
if(sigismember(&stc_int_pending,SIGINT)) {
723
fputs("\033@[Aborted]\f", prn_stream);
725
sigprocmask(SIG_SETMASK,&stc_int_save,NULL);
728
#endif /* STC_SIGNAL */
730
} /* Until all scans are processed */
732
if(sd->stc.flags & STCPRINT) {
733
if((flags & STCCOMP) == STCDELTA) fputc(0xe3,prn_stream);
734
fwrite(sd->stc.escp_release.data,1,sd->stc.escp_release.size,prn_stream);
738
sigprocmask(SIG_SETMASK,&stc_int_save,NULL);
739
#endif /* STC_DIGNAL */
745
*** Release the dynamic memory
749
gs_free(sd->memory, ext_line,ext_size,1,"stc_print_page/ext_line");
752
gs_free(sd->memory, col_line,prt_pixels,1,"stc_print_page/col_line");
755
gs_free(sd->memory, alg_line,alg_size,sd->stc.alg_item,
756
"stc_print_page/alg_line");
759
gs_free(sd->memory, buf,buf_size,sd->stc.alg_item,"stc_print_page/buf");
761
if(sd->stc.prt_width != NULL)
762
gs_free(sd->memory, sd->stc.prt_width,sd->stc.prt_buf,sizeof(int),
763
"stc_print_page/prt_width");
765
if(sd->stc.prt_data != NULL) {
768
for(i = 0; i < sd->stc.prt_buf; ++i) {
769
if(sd->stc.prt_data[i] != NULL)
770
gs_free(sd->memory, sd->stc.prt_data[i],sd->stc.prt_size,1,
771
"stc_print_page/prt");
774
gs_free(sd->memory, sd->stc.prt_data,sd->stc.prt_buf,sizeof(byte *),
775
"stc_print_page/prt_data");
780
for(i = 0; i < sd->color_info.num_components; ++i) {
781
if(sd->stc.seed_row[i] != NULL)
782
gs_free(sd->memory, sd->stc.seed_row[i],sd->stc.seed_size,sizeof(int),
783
"stc_print_page/seed_row");
787
if(sd->stc.escp_data != NULL)
788
gs_free(sd->memory, sd->stc.escp_data,sd->stc.escp_size,1,
789
"stc_print_page/escp_data");
791
return OK4GO ? 0 : gs_error_undefined;
798
stc_iswhite(stcolor_device *sd, int prt_pixels,byte *ext_data)
800
long b2do = (prt_pixels*sd->color_info.depth+7)>>3;
801
int bcmp = 4 * countof(sd->stc.white_run);
802
byte *wht = (byte *) sd->stc.white_run;
804
while(b2do >= bcmp) {
805
if(memcmp(ext_data,wht,bcmp)) break;
810
if((b2do > 0) && (b2do < bcmp))
811
b2do = memcmp(ext_data,sd->stc.white_end,b2do);
813
return b2do ? false : true;
817
*** A bunch of routines that convert gslines into algorithms format.
820
stc_any_depth(stcolor_device *sd,byte *ext_data,int prt_pixels,byte *alg_line)
821
{ /* general conversion */
823
int p,c, niext, nbits;
824
gx_color_index ciext,ci,cimsk,cvmsk;
827
nbits = sd->stc.bits;
828
cvmsk = ((gx_color_index) 1<<nbits) - 1;
830
/* it is nonsense to use this algorithm for this cases, but if it claims
831
* generality, it should deliver correct results in this cases too */
832
if(sd->color_info.depth == (sd->color_info.num_components<<3)) nbits = 8;
835
for(c = 1; c < sd->color_info.num_components; ++c)
836
cimsk = (cimsk<<nbits) | cvmsk;
841
for(p = 0; p < prt_pixels; ++p) { /* over pixels */
844
for(c = sd->color_info.depth-niext; c >= 8; c -= 8)
845
ci = (ci<<8) | *ext_data++;
847
if(c > 0) { /* partial byte required */
851
ci = (ci<<c) | (ciext>>niext);
852
ciext &= (1L<<niext)-1;
854
} else if(c < 0) { /* some bits left in ciext */
857
ciext &= (1L<<niext)-1;
860
} else { /* entire ciext used */
869
# define stc_storeapc(T) \
870
((T *)ap)[c] = ((T *)(sd->stc.vals[c]))[ci & cvmsk];
872
for(c = sd->color_info.num_components; c--;) { /* comp */
873
STC_TYPESWITCH(sd->stc.dither,stc_storeapc)
879
ap += sd->color_info.num_components * sd->stc.alg_item;
884
} /* general conversion */
887
* rgb-data with depth=24, can use a faster algorithm
890
stc_rgb24_long(stcolor_device *sd,byte *ext_data,int prt_pixels,byte *alg_line)
891
{ /* convert 3 bytes into appropriate long-Values */
893
register long *out = (long *) alg_line;
894
register long *rvals = (long *) (sd->stc.vals[0]);
895
register long *gvals = (long *) (sd->stc.vals[1]);
896
register long *bvals = (long *) (sd->stc.vals[2]);
898
for(p = prt_pixels; p; --p) {
899
*out++ = rvals[*ext_data++];
900
*out++ = gvals[*ext_data++];
901
*out++ = bvals[*ext_data++];
905
} /* convert 3 bytes into appropriate long-Values */
908
* cmyk-data with depth=32, can use a faster algorithm
911
stc_cmyk32_long(stcolor_device *sd,byte *ext_data,int prt_pixels,byte *alg_line)
912
{ /* convert 4 bytes into appropriate long-Values */
914
register long *out = (long *) alg_line;
915
register long *cvals = (long *) (sd->stc.vals[0]);
916
register long *mvals = (long *) (sd->stc.vals[1]);
917
register long *yvals = (long *) (sd->stc.vals[2]);
918
register long *kvals = (long *) (sd->stc.vals[3]);
920
for(p = prt_pixels; p; --p) {
921
*out++ = cvals[*ext_data++];
922
*out++ = mvals[*ext_data++];
923
*out++ = yvals[*ext_data++];
924
*out++ = kvals[*ext_data++];
928
} /* convert 4 bytes into appropriate long-Values */
931
* handle indirect encoded cmyk-data
933
#define STC_CMYK10_ANY(T)\
935
register int p = prt_pixels; \
936
register stc_pixel ci,k,n,mode; \
937
register stc_pixel *in = (stc_pixel *) ext_data; \
938
register T *out = (T *) alg_line; \
939
register T *cv = (T *) sd->stc.vals[0]; \
940
register T *mv = (T *) sd->stc.vals[1]; \
941
register T *yv = (T *) sd->stc.vals[2]; \
942
register T *kv = (T *) sd->stc.vals[3]; \
947
k = (ci>>2) & 0x3ff; \
955
n = (ci>>12) & 0x3ff; \
956
if(mode == 2) { out[2] = yv[k]; } \
957
else { out[2] = yv[n]; n = (ci>>22) & 0x3ff; } \
958
if(mode == 1) { out[1] = mv[k]; } \
959
else { out[1] = mv[n]; n = (ci>>22) & 0x3ff; } \
960
if(mode == 0) out[0] = cv[k]; \
961
else out[0] = cv[n]; \
969
stc_cmyk10_byte(stcolor_device *sd,
970
byte *ext_data,int prt_pixels,byte *alg_line)
975
stc_cmyk10_long(stcolor_device *sd,
976
byte *ext_data,int prt_pixels,byte *alg_line)
981
stc_cmyk10_float(stcolor_device *sd,
982
byte *ext_data,int prt_pixels,byte *alg_line)
984
STC_CMYK10_ANY(float)
987
#undef STC_CMYK10_ANY
989
#define STC_CMYK10_DANY(T)\
991
register int p = prt_pixels; \
992
register stc_pixel ci,k,n,mode; \
993
register stc_pixel *in = (stc_pixel *) ext_data; \
994
register T *out = (T *) alg_line; \
999
k = (ci>>2) & 0x3ff; \
1007
n = (ci>>12) & 0x3ff; \
1008
if(mode == 2) { out[2] = k; } \
1009
else { out[2] = n; n = (ci>>22) & 0x3ff; } \
1010
if(mode == 1) { out[1] = k; } \
1011
else { out[1] = n; n = (ci>>22) & 0x3ff; } \
1012
if(mode == 0) out[0] = k; \
1022
stc_cmyk10_dbyte(stcolor_device *sd,
1023
byte *ext_data,int prt_pixels,byte *alg_line)
1025
STC_CMYK10_DANY(byte)
1028
stc_cmyk10_dlong(stcolor_device *sd,
1029
byte *ext_data,int prt_pixels,byte *alg_line)
1031
STC_CMYK10_DANY(long)
1034
#undef STC_CMYK10_DANY
1037
* if the algorithm uses bytes & bytes are in ext_data, use them
1041
stc_any_direct(stcolor_device *sd,byte *ext_data,int prt_pixels,byte *alg_line)
1042
{ /* return ext_data */
1044
} /* return ext_data */
1046
/* ----------------------------------------------------------------------- */
1047
/* stc_rle: epson ESC/P2 RLE-Encoding
1050
stc_rle(byte *out,const byte *in,int width)
1057
if(in != NULL) { /* Data present */
1061
while(width > 0) { /* something to compress */
1065
while((width > crun) && (run == in[crun])) if(++crun == 129) break;
1067
if((crun > 2) || (crun == width)) { /* use this run */
1069
*out++ = (257 - crun) & 0xff; *out++ = run; used += 2;
1071
width -= crun; in += crun;
1074
} else { /* ignore this run */
1076
for(cdata = crun; (width > cdata) && (crun < 4);) {
1077
if(run == in[cdata]) crun += 1;
1078
else run = in[cdata], crun = 1;
1079
if(++cdata == 128) break;
1082
if(crun < 3) crun = 0; /* ignore trailing run */
1085
*out++ = cdata-1; used++;
1086
memcpy(out,in,cdata); used += cdata; out += cdata;
1088
width -= cdata; in += cdata;
1090
} /* use/ignore run */
1092
} /* something to compress */
1094
} else { /* Empty scans to fill bands */
1097
crun = width > 129 ? 129 : width;
1099
*out++ = (257 - crun) & 0xff;
1103
} /* Data present or empty */
1109
* Horizontal & vertical positioning, color-selection, "ESC ."
1112
stc_print_escpcmd(stcolor_device *sd, FILE *prn_stream,
1113
int escp_used, int color,int m,int wbytes)
1116
int dy = sd->stc.stc_y - sd->stc.prt_y; /* number of units to skip */
1119
/* ESC-R color codes, used only here */
1120
static const byte stc_colors[] = { 0x02, 0x01, 0x04, 0x00 }; /* CMYK */
1123
* initialize the printer, if necessary
1125
if(0 == (sd->stc.flags & STCPRINT)) {
1127
fwrite(sd->stc.escp_init.data,1,sd->stc.escp_init.size,prn_stream);
1129
if(0 < sd->stc.escp_lf) { /* Adjust Linefeed */
1130
fputc('\033', prn_stream);
1131
fputc('+', prn_stream);
1132
fputc(((sd->stc.escp_m*sd->stc.escp_u) / 10),prn_stream);
1133
} /* Adjust Linefeed */
1134
sd->stc.flags |= STCPRINT;
1137
sd->stc.escp_data[escp_used++] = '\r'; /* leftmost position */
1139
if(dy) { /* position the printer */
1140
if(( sd->stc.escp_lf > 0) && /* Linefeed allowed */
1141
((dy % sd->stc.escp_lf) == 0)) /* and possible */
1142
nlf = dy / sd->stc.escp_lf;
1146
sd->stc.escp_data[escp_used++] = '\033';
1147
sd->stc.escp_data[escp_used++] = '(';
1148
sd->stc.escp_data[escp_used++] = 'V';
1149
sd->stc.escp_data[escp_used++] = '\002';
1150
sd->stc.escp_data[escp_used++] = '\000';
1151
sd->stc.escp_data[escp_used++] = sd->stc.stc_y & 0xff;
1152
sd->stc.escp_data[escp_used++] = (sd->stc.stc_y >> 8) & 0xff;
1154
while(nlf--) sd->stc.escp_data[escp_used++] = '\n';
1156
sd->stc.prt_y = sd->stc.stc_y;
1157
} /* position the printer */
1159
if((sd->color_info.num_components > 1) &&
1160
(sd->stc.escp_c != stc_colors[color])) { /* select color */
1161
sd->stc.escp_data[escp_used++] = '\033';
1162
sd->stc.escp_data[escp_used++] = 'r';
1163
sd->stc.escp_c = stc_colors[color];
1164
sd->stc.escp_data[escp_used++] = sd->stc.escp_c;
1165
} /* select color */
1168
* Build the command used
1170
sd->stc.escp_data[escp_used++] = '\033';
1171
sd->stc.escp_data[escp_used++] = '.';
1172
sd->stc.escp_data[escp_used++] =
1173
(sd->stc.flags & STCCOMP) == STCPLAIN ? 0 : 1;
1174
sd->stc.escp_data[escp_used++] = sd->stc.escp_v;
1175
sd->stc.escp_data[escp_used++] = sd->stc.escp_h;
1176
sd->stc.escp_data[escp_used++] = m;
1177
sd->stc.escp_data[escp_used++] = (wbytes<<3) & 0xff; /* width in Pixels */
1178
sd->stc.escp_data[escp_used++] = (wbytes>>5) & 0xff;
1184
* compute width of a group of scanlines
1187
stc_bandwidth(stcolor_device *sd,int color,int m,int npass)
1189
int ncolor = sd->color_info.num_components == 1 ? 1 : 4;
1190
int buf_a = (sd->stc.prt_buf-1) & (sd->stc.stc_y * ncolor + color);
1193
while(m-- > 0) { /* check width */
1194
if(sd->stc.prt_width[buf_a] > w) w = sd->stc.prt_width[buf_a];
1195
buf_a = (sd->stc.prt_buf-1) & (buf_a + ncolor * npass);
1202
* Multi-Pass Printing-Routine
1205
stc_print_weave(stcolor_device *sd, FILE *prn_stream)
1208
int escp_used,nprint,nspace,color,buf_a,iprint,w;
1210
int npass = sd->stc.escp_v / sd->stc.escp_u;
1211
int ncolor = sd->color_info.num_components == 1 ? 1 : 4;
1214
while(sd->stc.stc_y < sd->stc.prt_scans) {
1217
* compute spacing & used heads (seems to work with odd escp_m)
1219
if(sd->stc.stc_y >= sd->stc.escp_m) { /* in normal mode */
1220
nprint = sd->stc.escp_m;
1221
nspace = sd->stc.escp_m;
1222
} else if((sd->stc.stc_y) < npass) { /* initialisation */
1223
nprint = sd->stc.escp_m - sd->stc.stc_y * ((sd->stc.escp_m+1)/npass);
1225
} else { /* switch to normal */
1226
nprint = sd->stc.escp_m - sd->stc.stc_y * ((sd->stc.escp_m+1)/npass);
1227
nspace = sd->stc.escp_m - sd->stc.stc_y;
1229
iprint = sd->stc.stc_y + npass * nprint;
1230
if(sd->stc.buf_y < iprint) break;
1233
for(color = 0; color < ncolor; ++color) { /* print the colors */
1235
if(0 == (w = stc_bandwidth(sd,color,nprint,npass))) continue;
1237
escp_used = stc_print_escpcmd(sd,prn_stream,
1238
escp_used,color,sd->stc.escp_m,w);
1240
buf_a = (sd->stc.prt_buf-1) & (sd->stc.stc_y * ncolor + color);
1241
for(iprint = 0; iprint < nprint; ++iprint) { /* send data */
1243
if((sd->stc.flags & STCCOMP) == STCPLAIN) {
1244
memcpy(sd->stc.escp_data+escp_used,sd->stc.prt_data[buf_a],w);
1247
escp_used += stc_rle(sd->stc.escp_data+escp_used,
1248
sd->stc.prt_data[buf_a],w);
1251
fwrite(sd->stc.escp_data,1,escp_used,prn_stream);
1254
buf_a = (sd->stc.prt_buf-1) & (buf_a + ncolor * npass);
1258
while(iprint++ < sd->stc.escp_m) { /* add empty rows */
1260
if((sd->stc.flags & STCCOMP) == STCPLAIN) {
1261
memset(sd->stc.escp_data+escp_used,0,w);
1264
escp_used += stc_rle(sd->stc.escp_data+escp_used,NULL,w);
1267
fwrite(sd->stc.escp_data,1,escp_used,prn_stream);
1269
} /* add empty rows */
1270
} /* print the colors */
1272
sd->stc.stc_y += nspace;
1277
* Single-Pass printing-Routine
1280
stc_print_bands(stcolor_device *sd, FILE *prn_stream)
1283
int escp_used,color,buf_a,iprint,w,m;
1285
int ncolor = sd->color_info.num_components == 1 ? 1 : 4;
1287
while(sd->stc.stc_y < sd->stc.prt_scans) {
1290
* find the begin of the band
1292
for(w = 0; sd->stc.stc_y < sd->stc.buf_y; ++sd->stc.stc_y) {
1293
buf_a = (sd->stc.prt_buf-1) & (sd->stc.stc_y * ncolor);
1294
for(color = 0; color < ncolor; ++color)
1295
if(sd->stc.prt_width[buf_a+color] > w)
1296
w = sd->stc.prt_width[buf_a+color];
1301
* adjust the band-height
1303
w = sd->stc.prt_scans - sd->stc.stc_y;
1304
if((w < sd->stc.escp_m) && (sd->stc.escp_v != 40)) {
1306
else if(w < 24) m = 8;
1312
if(sd->stc.buf_y < (sd->stc.stc_y+m)) break;
1315
for(color = 0; color < ncolor; ++color) { /* print the colors */
1317
if(0 == (w = stc_bandwidth(sd,color,m,1))) continue; /* shortcut */
1319
escp_used = stc_print_escpcmd(sd,prn_stream,escp_used,color,m,w);
1321
buf_a = (sd->stc.prt_buf-1) & (sd->stc.stc_y * ncolor + color);
1322
for(iprint = 0; iprint < m; ++iprint) { /* send data */
1324
if((sd->stc.flags & STCCOMP) == STCPLAIN) {
1325
memcpy(sd->stc.escp_data+escp_used,sd->stc.prt_data[buf_a],w);
1328
escp_used += stc_rle(sd->stc.escp_data+escp_used,
1329
sd->stc.prt_data[buf_a],w);
1332
fwrite(sd->stc.escp_data,1,escp_used,prn_stream);
1335
buf_a = (sd->stc.prt_buf-1) & (buf_a + ncolor);
1339
} /* print the colors */
1344
/* ----------------------------------------------------------------------- */
1347
stc_deltarow(byte *out,const byte *in,int width,byte *seed)
1350
int istop,nmove,ndata,i,j;
1351
int *wseed = (int *) seed;
1354
seed += sizeof(int);
1356
if((in != NULL) && (width > 0)) { /* Data present */
1358
istop = width < wseed[0] ? wseed[0] : width;
1363
for(j = i; j < istop; ++j) if(in[j] != seed[j]) break;
1367
if(nmove > 0) { /* issue a move */
1369
if(i == istop) break;
1372
out[used++] = 0x40 | nmove;
1373
} else if(nmove < 128) {
1375
out[used++] = nmove;
1378
out[used++] = 0xff & nmove;
1379
out[used++] = 0xff & (nmove>>8);
1381
} /* issue a move */
1384
* find the end of this run
1387
for(j = i+1; (j < istop) && ((nmove < 4)); ++j) {
1388
if(in[j] == seed[j]) nmove += 1;
1394
nmove = stc_rle(out+used+3,in+i,ndata);
1396
out[used++] = 0x20 | nmove;
1397
for(j = 0; j < nmove; ++j) out[used+j] = out[used+j+2];
1398
} else if(nmove < 256) {
1400
out[used++] = nmove;
1401
for(j = 0; j < nmove; ++j) out[used+j] = out[used+j+1];
1404
out[used++] = 0xff & nmove;
1405
out[used++] = 0xff & (nmove>>8);
1411
memcpy(seed,in,istop);
1414
} else if(wseed[0] > 0) { /* blank line, but seed has data */
1416
out[used++] = 0xe1; /* clear row */
1417
memset(seed,0,wseed[0]);
1426
* Slightly different single-pass printing
1429
stc_print_delta(stcolor_device *sd, FILE *prn_stream)
1434
int ncolor = sd->color_info.num_components == 1 ? 1 : 4;
1436
while(sd->stc.stc_y < sd->stc.prt_scans) {
1439
* find the begin of the band
1441
for(w = 0; sd->stc.stc_y < sd->stc.buf_y; ++sd->stc.stc_y) {
1442
buf_a = (sd->stc.prt_buf-1) & (sd->stc.stc_y * ncolor);
1443
for(color = 0; color < ncolor; ++color)
1444
if(sd->stc.prt_width[buf_a+color] > w)
1445
w = sd->stc.prt_width[buf_a+color];
1449
if(sd->stc.buf_y == sd->stc.stc_y) break;
1454
* Send Initialization & ESC . 3 once
1456
if(0 == (sd->stc.flags & STCPRINT)) {
1458
sd->stc.flags |= STCPRINT;
1460
fwrite(sd->stc.escp_init.data,1,sd->stc.escp_init.size,prn_stream);
1462
sd->stc.escp_data[escp_used++] = '\033';
1463
sd->stc.escp_data[escp_used++] = '.';
1464
sd->stc.escp_data[escp_used++] = 3;
1465
sd->stc.escp_data[escp_used++] = sd->stc.escp_v;
1466
sd->stc.escp_data[escp_used++] = sd->stc.escp_h;
1467
sd->stc.escp_data[escp_used++] = sd->stc.escp_m;
1468
sd->stc.escp_data[escp_used++] = 0;
1469
sd->stc.escp_data[escp_used++] = 0;
1470
sd->stc.escp_data[escp_used++] = 0xe4; /* MOVXBYTE */
1473
if(sd->stc.stc_y != sd->stc.prt_y) { /* really position the printer */
1474
w = sd->stc.stc_y - sd->stc.prt_y;
1476
sd->stc.escp_data[escp_used++] = 0x60 | w;
1477
} else if(w < 256) {
1478
sd->stc.escp_data[escp_used++] = 0x71;
1479
sd->stc.escp_data[escp_used++] = w;
1481
sd->stc.escp_data[escp_used++] = 0x72;
1482
sd->stc.escp_data[escp_used++] = 0xff & w;
1483
sd->stc.escp_data[escp_used++] = 0xff & (w>>8);
1485
sd->stc.prt_y = sd->stc.stc_y;
1486
} /* really position the printer */
1488
for(color = 0; color < ncolor; ++color) { /* print the colors */
1490
/* Color-Selection */
1491
if(color == (ncolor-1)) {
1492
sd->stc.escp_data[escp_used++] = 0x80; /* Black */
1495
case 1: sd->stc.escp_data[escp_used++] = 0x81; break; /* M */
1496
case 2: sd->stc.escp_data[escp_used++] = 0x84; break; /* Y */
1497
default: sd->stc.escp_data[escp_used++] = 0x82; break; /* C */
1502
buf_a = (sd->stc.prt_buf-1) & (sd->stc.stc_y * ncolor + color);
1504
w = stc_deltarow(sd->stc.escp_data+escp_used,
1505
sd->stc.prt_data[buf_a],sd->stc.prt_width[buf_a],
1506
sd->stc.seed_row[color]);
1508
if(w == 0) escp_used -= 1;
1509
else escp_used += w;
1511
if(escp_used > 0) fwrite(sd->stc.escp_data,1,escp_used,prn_stream);
1514
} /* print the colors */
1522
/* ----------------------------------------------------------------------- */
1525
*** Free-Data: release the specific-Arrays
1528
stc_freedata(gs_memory_t *mem, stc_t *stc)
1532
for(i = 0; i < 4; ++i) {
1533
if(stc->code[i] != NULL) {
1535
for(j = 0; j < i; ++j) if(stc->code[i] == stc->code[j]) break;
1537
if(i == j) gs_free(mem, stc->code[i],1<<stc->bits,sizeof(gx_color_value),
1541
if(stc->vals[i] != NULL) {
1543
for(j = 0; j < i; ++j)
1544
if(stc->vals[i] == stc->vals[j]) break;
1546
if(i == j) gs_free(mem, stc->vals[i],1<<stc->bits,sd->stc.alg_item,
1547
"stcolor/transfer");
1551
for(i = 0; i < 4; ++i) {
1552
stc->code[i] = NULL;
1553
stc->vals[i] = NULL;
1558
*** open the device and initialize margins & arrays
1562
stc_open(gx_device *pdev) /* setup margins & arrays */
1564
stcolor_device *sd = (stcolor_device *) pdev;
1566
gx_color_index white;
1571
* Establish Algorithm-Table, if not present
1573
if(sd->stc.algorithms.size == 0) {
1574
gs_param_string *dp;
1575
for(i = 0; stc_dither[i].name != NULL; ++i); /* count 'em */
1576
sd->stc.algorithms.size = i;
1577
dp = gs_malloc(sd->memory, i,sizeof(gs_param_string),
1578
"stcolor/algorithms");
1580
code = gs_error_VMerror;
1581
sd->stc.algorithms.size = 0;
1583
sd->stc.algorithms.data = dp;
1584
sd->stc.algorithms.persistent = true;
1585
for(i = 0; stc_dither[i].name != NULL; ++i) {
1586
param_string_from_string(dp[i],stc_dither[i].name);
1591
# define stc_sizeofitem(T) sd->stc.alg_item = sizeof(T)
1592
STC_TYPESWITCH(sd->stc.dither,stc_sizeofitem)
1594
stc_print_setup(sd);
1597
* Establish internal Value & Code-Arrays
1601
for(i = 0; i < sd->color_info.num_components; ++i) { /* comp */
1603
if((sd->stc.sizc[i] > 1) && (sd->stc.extc[i] != NULL)) { /* code req. */
1605
for(j = 0; j < i; ++j) if(sd->stc.extc[i] == sd->stc.extc[j]) break;
1607
if(i == j) { /* new one */
1608
sd->stc.code[i] = gs_malloc(sd->memory, 1<<sd->stc.bits,sizeof(gx_color_value),
1611
if(sd->stc.code[i] == NULL) { /* error */
1612
code = gs_error_VMerror;
1613
} else { /* success */
1615
* Try making things easier:
1616
* normalize values to 0.0/1.0-Range
1617
* X-Axis: Color-Values (implied)
1618
* Y-Values: Indices (given)
1620
unsigned long ly,iy;
1621
double ystep,xstep,fx,fy;
1627
for(ly = 0; ly < sd->stc.sizc[i]; ++ly) {
1628
if(sd->stc.extc[i][ly] < fx) fx = sd->stc.extc[i][ly];
1629
if(sd->stc.extc[i][ly] > fy) fy = sd->stc.extc[i][ly];
1631
if((fx != 0.0) || (fy != 1.0)) {
1632
fy = 1.0 / (fy - fx);
1633
for(ly = 0; ly < sd->stc.sizc[i]; ++ly)
1634
sd->stc.extc[i][ly] = fy * (sd->stc.extc[i][ly]-fx);
1638
ystep = 1.0 / (double)((1<<sd->stc.bits)-1);
1639
xstep = 1.0 / (double)( sd->stc.sizc[i] -1);
1642
for(ly = 0; ly < (1<<sd->stc.bits); ++ly) {
1644
while(((iy+1) < sd->stc.sizc[i]) &&
1645
( fy > sd->stc.extc[i][iy+1])) ++iy;
1646
fx = iy + (fy - sd->stc.extc[i][iy])
1647
/ (sd->stc.extc[i][iy+1] - sd->stc.extc[i][iy]);
1648
fx *= xstep * gx_max_color_value;
1650
fx = fx < 0.0 ? 0.0 :
1651
(fx > gx_max_color_value ? gx_max_color_value : fx);
1653
sd->stc.code[i][ly] = (gx_color_value)fx;
1654
if((fx-sd->stc.code[i][ly]) >= 0.5) sd->stc.code[i][ly] += 1;
1656
} /* error || success */
1658
} else { /* shared one */
1660
sd->stc.code[i] = sd->stc.code[j];
1662
} /* new || shared one */
1665
if((sd->stc.sizv[i] > 1) && (sd->stc.extv[i] != NULL)) { /* vals req. */
1667
for(j = 0; j < i; ++j)
1668
if((sd->stc.extc[i] == sd->stc.extc[j]) &&
1669
(sd->stc.extv[i] == sd->stc.extv[j])) break;
1671
if(i == j) { /* new one */
1674
gs_malloc(sd->memory, 1<<sd->stc.bits,sd->stc.alg_item,"stcolor/transfer");
1676
if(sd->stc.vals[i] == NULL) {
1678
code = gs_error_VMerror;
1680
} else { /* success */
1683
if(sd->stc.code[i] == NULL) { /* linear */
1685
byte *Out = sd->stc.vals[i];
1686
int Nout = 1<<sd->stc.bits;
1687
double Omin = sd->stc.dither->minmax[0];
1688
double Omax = sd->stc.dither->minmax[1];
1689
float *In = sd->stc.extv[i];
1690
int Nin = sd->stc.sizv[i];
1692
double Istep,Ostep,Y;
1695
Istep = 1.0 / (double) ((Nin)-1);
1696
Ostep = 1.0 / (double) ((Nout)-1);
1698
for(io = 0; io < (Nout); ++io) {
1699
I = (long)(io * ((Nin)-1))/((Nout)-1);
1702
Y = In[I] + (In[I+1]-In[I])
1703
* ((double) io * Ostep - (double)I * Istep)
1706
Y = In[I] + (In[I]-In[I-1])
1707
* ((double) io * Ostep - (double)I * Istep)
1710
Y = Omin + (Omax-Omin) * Y;
1711
Y = Y < Omin ? Omin : (Y > Omax ? Omax : Y);
1714
switch(sd->stc.dither->flags & STC_TYPE) {
1717
if(((Y-Ovb) >= 0.5) && ((Ovb+1) <= Omax)) Ovb += 1;
1722
if(((Y-Ovl) >= 0.5) && ((Ovl+1) <= Omax)) Ovl += 1;
1723
if(((Ovl-Y) >= 0.5) && ((Ovl-1) >= Omax)) Ovl -= 1;
1724
((long *)Out)[io] = Ovl;
1727
((float *)Out)[io] = Y;
1732
} else { /* encoded */
1736
xstep = 1.0 / (double) (sd->stc.sizv[i]-1);
1739
* The following differs in so far from the previous, that the desired
1740
* X-Values are stored in another array.
1742
for(o = 0; o < (1<<sd->stc.bits); ++o) { /* code-loop */
1744
x = sd->stc.code[i][o]; x /= gx_max_color_value;
1746
j = (unsigned long)(x / xstep);
1748
if((j+1) < sd->stc.sizv[i]) {
1749
y = sd->stc.extv[i][j];
1750
y += (sd->stc.extv[i][j+1]-y)*(x-(double)j*xstep)/xstep;
1752
y = sd->stc.extv[i][j];
1753
y += (y-sd->stc.extv[i][j-1])*(x-(double)j*xstep)/xstep;
1756
y = sd->stc.dither->minmax[0]
1757
+(sd->stc.dither->minmax[1]-sd->stc.dither->minmax[0])*y;
1759
# define stc_adjvals(T) \
1760
((T *)(sd->stc.vals[i]))[o] = (T)y; \
1762
if(((y-((T *)(sd->stc.vals[i]))[o]) >= 0.5) && \
1763
((1+((T *)(sd->stc.vals[i]))[o]) <= sd->stc.dither->minmax[1]))\
1764
((T *)(sd->stc.vals[i]))[o] += 1; \
1766
if(((((T *)(sd->stc.vals[i]))[o]-y) >= 0.5) && \
1767
((((T *)(sd->stc.vals[i]))[o]-1) >= sd->stc.dither->minmax[0]))\
1768
((T *)(sd->stc.vals[i]))[o] -= 1;
1770
STC_TYPESWITCH(sd->stc.dither,stc_adjvals)
1774
} /* lineaer / encoded */
1775
} /* error || success */
1777
} else { /* shared one */
1779
sd->stc.vals[i] = sd->stc.vals[j];
1781
} /* new || shared one */
1786
gx_color_value cv[4];
1787
sd->stc.flags |= STCOK4GO;
1790
* Arrgh: open-procedure seems to be the right-place, but it is
1791
* necessary to establish the defaults for omitted procedures too.
1794
switch(sd->color_info.num_components) { /* Establish color-procs */
1796
sd->color_info.polarity = GX_CINFO_POLARITY_ADDITIVE;
1797
set_dev_proc(sd,map_rgb_color, stc_map_gray_color);
1798
set_dev_proc(sd,map_cmyk_color,gx_default_map_cmyk_color);
1799
set_dev_proc(sd,map_color_rgb, stc_map_color_gray);
1800
set_dev_proc(sd,encode_color, stc_map_gray_color);
1801
set_dev_proc(sd,decode_color, stc_map_color_gray);
1802
set_dev_proc(sd, get_color_mapping_procs,
1803
gx_default_DevGray_get_color_mapping_procs);
1804
set_dev_proc(sd, get_color_comp_index,
1805
gx_default_DevGray_get_color_comp_index );
1806
cv[0] = cv[1] = cv[2] = gx_max_color_value;
1807
white = stc_map_gray_color((gx_device *) sd, cv);
1810
sd->color_info.polarity = GX_CINFO_POLARITY_ADDITIVE;
1811
set_dev_proc(sd,map_rgb_color, stc_map_rgb_color);
1812
set_dev_proc(sd,map_cmyk_color,gx_default_map_cmyk_color);
1813
set_dev_proc(sd,map_color_rgb, stc_map_color_rgb);
1814
set_dev_proc(sd,encode_color, stc_map_rgb_color);
1815
set_dev_proc(sd,decode_color, stc_map_color_rgb);
1816
set_dev_proc(sd, get_color_mapping_procs,
1817
gx_default_DevRGB_get_color_mapping_procs);
1818
set_dev_proc(sd, get_color_comp_index,
1819
gx_default_DevRGB_get_color_comp_index );
1820
cv[0] = cv[1] = cv[2] = gx_max_color_value;
1821
white = stc_map_rgb_color((gx_device *) sd, cv);
1824
sd->color_info.polarity = GX_CINFO_POLARITY_SUBTRACTIVE;
1825
set_dev_proc(sd,map_rgb_color, gx_default_map_rgb_color);
1826
set_dev_proc(sd, get_color_mapping_procs,
1827
gx_default_DevCMYK_get_color_mapping_procs);
1828
set_dev_proc(sd, get_color_comp_index,
1829
gx_default_DevCMYK_get_color_comp_index );
1830
if(sd->stc.flags & STCCMYK10) {
1831
set_dev_proc(sd,map_cmyk_color,stc_map_cmyk10_color);
1832
set_dev_proc(sd,map_color_rgb, stc_map_color_cmyk10);
1833
set_dev_proc(sd,encode_color,stc_map_cmyk10_color);
1834
set_dev_proc(sd,decode_color, stc_map_color_cmyk10);
1835
cv[0] = cv[1] = cv[2] = cv[3] = 0;
1836
white = stc_map_cmyk10_color((gx_device *) sd, cv);
1838
set_dev_proc(sd,map_cmyk_color,stc_map_cmyk_color);
1839
set_dev_proc(sd,map_color_rgb, stc_map_color_cmyk);
1840
set_dev_proc(sd,encode_color,stc_map_cmyk_color);
1841
set_dev_proc(sd,decode_color, stc_map_color_cmyk);
1842
cv[0] = cv[1] = cv[2] = cv[3] = 0;
1843
white = stc_map_cmyk_color((gx_device *) sd,cv);
1845
break; /* Establish color-procs */
1850
* create at least a Byte
1852
if(sd->color_info.depth < 2) white |= (white<<1);
1853
if(sd->color_info.depth < 4) white |= (white<<2);
1854
if(sd->color_info.depth < 8) white |= (white<<4);
1859
bpw = (byte *) sd->stc.white_run;
1861
if(sd->color_info.depth < 16) {
1862
for(i = 0; i < sizeof(sd->stc.white_run); i += 1) {
1863
bpw[i] = 0xff & white;
1865
} else if(sd->color_info.depth < 24) {
1866
for(i = 0; i < sizeof(sd->stc.white_run); i += 2) {
1867
bpw[i] = 0xff & (white>>8);
1868
bpw[i+1] = 0xff & white;
1870
} else if(sd->color_info.depth < 32) {
1871
for(i = 0; i < sizeof(sd->stc.white_run); i += 3) {
1872
bpw[i] = 0xff & (white>>16);
1873
bpw[i+1] = 0xff & (white>> 8);
1874
bpw[i+2] = 0xff & white;
1877
for(i = 0; i < sizeof(sd->stc.white_run); i += 4) {
1878
bpw[i] = 0xff & (white>>24);
1879
bpw[i+1] = 0xff & (white>>16);
1880
bpw[i+2] = 0xff & (white>> 8);
1881
bpw[i+3] = 0xff & white;
1885
* compute the trailer
1887
j = (unsigned long)(sd->width -
1888
(dev_l_margin(sd)+dev_r_margin(sd))*sd->x_pixels_per_inch);
1889
j = j * sd->color_info.depth; /* the Bit-count */
1890
j = j % (32*countof(sd->stc.white_run)); /* remaining Bits */
1892
bpm = (byte *) sd->stc.white_end;
1893
for(i = 0; i < (4*countof(sd->stc.white_end)); ++i) {
1900
bpm[i] = 0xff ^ ((1<<(8-j))-1);
1907
* Call super-class open
1910
return gdev_prn_open(pdev);
1914
stc_freedata(sd->memory, &sd->stc);
1922
*** stc_close: release the internal data
1925
stc_close(gx_device *pdev)
1927
stc_freedata(pdev->memory, &((stcolor_device *) pdev)->stc);
1928
((stcolor_device *) pdev)->stc.flags &= ~STCOK4GO;
1929
return gdev_prn_close(pdev);
1934
*** Function for Bit-Truncation, including direct-byte-transfer
1936
static gx_color_value
1937
stc_truncate(stcolor_device *sd,int i,gx_color_value v)
1940
if(sd->stc.bits < gx_color_value_bits) {
1941
if(sd->stc.code[i] != NULL) {
1943
* Perform binary search in the code-array
1948
s = sd->stc.bits > 1 ? 1L<<(sd->stc.bits-2) : 0L;
1949
p = sd->stc.code[i]+(1L<<(sd->stc.bits-1));
1954
} else if(v < p[-1]) {
1957
if((v-p[-1]) < (p[0]-v)) p -= 1;
1962
if((v-p[-1]) < (p[0]-v)) p -= 1;
1963
v = p - sd->stc.code[i];
1967
v >>= gx_color_value_bits-sd->stc.bits;
1972
V = (((1L<<D->stc.bits)-1)*V+(gx_max_color_value>>1))\
1973
/gx_max_color_value; \
1979
static gx_color_value
1980
stc_truncate1(stcolor_device *sd,int i,gx_color_value v)
1983
return sd->stc.vals[i][stc_truncate(sd,i,v)];
1987
*** Expansion of indices for reverse-mapping
1989
static gx_color_value
1990
stc_expand(stcolor_device *sd,int i,gx_color_index col)
1994
gx_color_index l = (1<<sd->stc.bits)-1;
1996
if(sd->stc.code[i] != NULL) {
1998
cv = sd->stc.code[i][col & l];
2000
} else if(sd->stc.bits < gx_color_value_bits) {
2002
cv = (col & l)<<(gx_color_value_bits-sd->stc.bits);
2003
cv += (col & l)/l * ((1<<(gx_color_value_bits-sd->stc.bits))-1);
2005
} else if(sd->stc.bits > gx_color_value_bits) {
2007
cv = (col & l)>>(sd->stc.bits-gx_color_value_bits);
2019
*** color-mapping of gray-scales
2021
static gx_color_index
2022
stc_map_gray_color(gx_device *pdev, const gx_color_value cv[])
2025
stcolor_device *sd = (stcolor_device *) pdev;
2027
gx_color_value r = cv[0];
2028
gx_color_value g = cv[1];
2029
gx_color_value b = cv[2];
2031
if((r == g) && (g == b)) {
2033
rv = gx_max_color_value - r;
2035
} else if(sd->stc.am != NULL) {
2040
fv = gx_max_color_value;
2041
fv -= *m++ * (float) r; fv -= *m++ * (float) g; fv -= *m * (float) b;
2043
if( fv < 0.0) rv = 0;
2044
else if((fv+0.5) > gx_max_color_value) rv = gx_max_color_value;
2045
else rv = (gx_color_index)(fv+0.5);
2049
rv = ((gx_color_index)gx_max_color_value)<<3;
2050
rv -= (gx_color_index) 3 * r;
2051
rv -= (gx_color_index) 3 * g;
2052
rv -= ((gx_color_index)b)<<1;
2054
if(rv > gx_max_color_value) rv = gx_max_color_value;
2058
if(( sd->stc.bits == 8) &&
2059
((sd->stc.dither->flags & STC_TYPE) == STC_BYTE))
2060
rv = stc_truncate1(sd,0,(gx_color_value)rv);
2062
rv = stc_truncate(sd,0,(gx_color_value)rv);
2068
stc_map_color_gray(gx_device *pdev, gx_color_index color,gx_color_value prgb[3])
2070
stcolor_device *sd = (stcolor_device *) pdev;
2071
gx_color_index l = ((gx_color_index)1<<sd->stc.bits)-1;
2073
prgb[0] = gx_max_color_value - stc_expand(sd,0,color & l);
2074
prgb[1] = prgb[0]; prgb[2] = prgb[0];
2080
*** color-mapping of rgb-values
2082
static gx_color_index
2083
stc_map_rgb_color(gx_device *pdev, const gx_color_value cv[])
2086
stcolor_device *sd = (stcolor_device *) pdev;
2087
int shift = sd->color_info.depth == 24 ? 8 : sd->stc.bits;
2088
gx_color_index rv = 0;
2089
gx_color_value r = cv[0];
2090
gx_color_value g = cv[1];
2091
gx_color_value b = cv[2];
2092
if((sd->stc.am != NULL) && ((r != g) || (g != b))) {
2093
float *m,fr,fg,fb,fv;
2096
fr = r; fg = g; fb = b;
2098
fv = *m++ * fr; fv += *m++ * fg; fv += *m++ * fb;
2100
if( fv < 0.0) r = 0;
2101
else if((fv+0.5) > gx_max_color_value) r = gx_max_color_value;
2102
else r = (gx_color_value)(fv+0.5);
2104
fv = *m++ * fr; fv += *m++ * fg; fv += *m++ * fb;
2106
if( fv < 0.0) g = 0;
2107
else if((fv+0.5) > gx_max_color_value) g = gx_max_color_value;
2108
else g = (gx_color_value)(fv+0.5);
2110
fv = *m++ * fr; fv += *m++ * fg; fv += *m++ * fb;
2112
if( fv < 0.0) b = 0;
2113
else if((fv+0.5) > gx_max_color_value) b = gx_max_color_value;
2114
else b = (gx_color_value)(fv+0.5);
2118
if(( sd->stc.bits == 8) &&
2119
((sd->stc.dither->flags & STC_TYPE) == STC_BYTE)) {
2120
rv = stc_truncate1(sd,0,r);
2121
rv = (rv<<shift) | stc_truncate1(sd,1,g);
2122
rv = (rv<<shift) | stc_truncate1(sd,2,b);
2124
rv = stc_truncate(sd,0,r);
2125
rv = (rv<<shift) | stc_truncate(sd,1,g);
2126
rv = (rv<<shift) | stc_truncate(sd,2,b);
2133
stc_map_color_rgb(gx_device *pdev, gx_color_index color,gx_color_value prgb[3])
2136
stcolor_device *sd = (stcolor_device *) pdev;
2137
int shift = sd->color_info.depth == 24 ? 8 : sd->stc.bits;
2138
gx_color_index l = ((gx_color_index)1<<sd->stc.bits)-1;
2140
prgb[0] = stc_expand(sd,0,((color>>(shift<<1)) & l));
2141
prgb[1] = stc_expand(sd,1,((color>> shift ) & l));
2142
prgb[2] = stc_expand(sd,2,( color & l));
2148
*** color-mapping of cmyk-values
2150
static gx_color_index
2151
stc_map_cmyk_color(gx_device *pdev, const gx_color_value cv[])
2154
stcolor_device *sd = (stcolor_device *) pdev;
2155
int shift = sd->color_info.depth == 32 ? 8 : sd->stc.bits;
2156
gx_color_index rv = 0;
2157
gx_color_value c = cv[0];
2158
gx_color_value m = cv[1];
2159
gx_color_value y = cv[2];
2160
gx_color_value k = cv[3];
2162
if((c == m) && (m == y)) {
2167
if(( sd->stc.bits == 8) &&
2168
((sd->stc.dither->flags & STC_TYPE) == STC_BYTE)) {
2169
k = stc_truncate1(sd,3,k);
2171
k = stc_truncate(sd,3,k);
2176
if(sd->stc.am != NULL) {
2178
float *a,fc,fm,fy,fk,fv;
2180
if(k == 0) { /* no separated black yet */
2183
if(k) { /* no black at all */
2187
} /* no black at all */
2188
} /* no separated black yet */
2191
fc = c; fm = m; fy = y; fk = k;
2193
fv = *a++ * fc; fv += *a++ * fm; fv += *a++ * fy; fv += *a++ * fk;
2194
if( fv < 0.0) c = 0;
2195
else if((fv+0.5) > gx_max_color_value) c = gx_max_color_value;
2196
else c = (gx_color_value)(fv+0.5);
2198
fv = *a++ * fc; fv += *a++ * fm; fv += *a++ * fy; fv += *a++ * fk;
2199
if( fv < 0.0) m = 0;
2200
else if((fv+0.5) > gx_max_color_value) m = gx_max_color_value;
2201
else m = (gx_color_value)(fv+0.5);
2203
fv = *a++ * fc; fv += *a++ * fm; fv += *a++ * fy; fv += *a++ * fk;
2204
if( fv < 0.0) y = 0;
2205
else if((fv+0.5) > gx_max_color_value) y = gx_max_color_value;
2206
else y = (gx_color_value)(fv+0.5);
2208
fv = *a++ * fc; fv += *a++ * fm; fv += *a++ * fy; fv += *a++ * fk;
2209
if( fv < 0.0) k = 0;
2210
else if((fv+0.5) > gx_max_color_value) k = gx_max_color_value;
2211
else k = (gx_color_value)(fv+0.5);
2219
if(( sd->stc.bits == 8) &&
2220
((sd->stc.dither->flags & STC_TYPE) == STC_BYTE)) {
2221
c = stc_truncate1(sd,0,c);
2222
m = stc_truncate1(sd,1,m);
2223
y = stc_truncate1(sd,2,y);
2224
k = stc_truncate1(sd,3,k);
2226
c = stc_truncate(sd,0,c);
2227
m = stc_truncate(sd,1,m);
2228
y = stc_truncate(sd,2,y);
2229
k = stc_truncate(sd,3,k);
2234
rv = (rv<<shift) | m;
2235
rv = (rv<<shift) | y;
2236
rv = (rv<<shift) | k;
2238
if(rv == gx_no_color_index) rv ^= 1;
2243
/* Modified to be a "decode_color" routine */
2245
stc_map_color_cmyk(gx_device *pdev, gx_color_index color,gx_color_value cv[4])
2248
stcolor_device *sd = (stcolor_device *) pdev;
2249
int shift = sd->color_info.depth == 32 ? 8 : sd->stc.bits;
2250
gx_color_index l = ((gx_color_index)1<<sd->stc.bits)-1;
2251
gx_color_value c,m,y,k;
2253
k = stc_expand(sd,3, color & l); color >>= shift;
2254
y = stc_expand(sd,2, color & l); color >>= shift;
2255
m = stc_expand(sd,1, color & l); color >>= shift;
2256
c = stc_expand(sd,0, color & l);
2268
*** color-mapping of cmyk10-values
2270
static gx_color_index
2271
stc_map_cmyk10_color(gx_device *pdev, const gx_color_value cv[])
2274
stcolor_device *sd = (stcolor_device *) pdev;
2276
gx_color_index rv = 0;
2278
gx_color_value c = cv[0];
2279
gx_color_value m = cv[1];
2280
gx_color_value y = cv[2];
2281
gx_color_value k = cv[3];
2283
if((c == m) && (m == y)) {
2291
if(sd->stc.am != NULL) {
2293
float *a,fc,fm,fy,fk,fv;
2297
if(k) { /* no black at all */
2301
} /* no black at all */
2304
fc = c; fm = m; fy = y; fk = k;
2306
fv = *a++ * fc; fv += *a++ * fm; fv += *a++ * fy; fv += *a++ * fk;
2307
if( fv < 0.0) c = 0;
2308
else if((fv+0.5) > gx_max_color_value) c = gx_max_color_value;
2309
else c = (gx_color_value)(fv+0.5);
2311
fv = *a++ * fc; fv += *a++ * fm; fv += *a++ * fy; fv += *a++ * fk;
2312
if( fv < 0.0) m = 0;
2313
else if((fv+0.5) > gx_max_color_value) m = gx_max_color_value;
2314
else m = (gx_color_value)(fv+0.5);
2316
fv = *a++ * fc; fv += *a++ * fm; fv += *a++ * fy; fv += *a++ * fk;
2317
if( fv < 0.0) y = 0;
2318
else if((fv+0.5) > gx_max_color_value) y = gx_max_color_value;
2319
else y = (gx_color_value)(fv+0.5);
2324
if(c < y) { k = c; c = 0; mode = 0; }
2325
else { k = y; y = 0; mode = 2; }
2327
if(m < y) { k = m; m = 0; mode = 1; }
2328
else { k = y; y = 0; mode = 2; }
2333
* truncate only the values that require it
2335
if(c) c = stc_truncate(sd,0,c);
2336
if(m) m = stc_truncate(sd,1,m);
2337
if(y) y = stc_truncate(sd,2,y);
2338
if(k) k = stc_truncate(sd,3,k);
2341
* make sure that truncation-white becomes white.
2343
if((c|m|y) == 0) mode = 3;
2346
* check wether value-arrays can be bypassed
2348
if(((sd->stc.dither->flags & STC_TYPE) == STC_BYTE) &&
2349
( sd->stc.dither->minmax[0] == 0.0 )) {
2350
c = sd->stc.vals[0][c];
2351
m = sd->stc.vals[1][m];
2352
y = sd->stc.vals[2][y];
2353
k = sd->stc.vals[3][k];
2354
} else if(((sd->stc.dither->flags & STC_TYPE) == STC_LONG) &&
2355
( sd->stc.dither->minmax[0] == 0.0 ) &&
2356
( sd->stc.dither->minmax[1] <= 1023.0 )) {
2357
c = ((long *)(sd->stc.vals[0]))[c];
2358
m = ((long *)(sd->stc.vals[1]))[m];
2359
y = ((long *)(sd->stc.vals[2]))[y];
2360
k = ((long *)(sd->stc.vals[3]))[k];
2363
* compute the long-representation of gx_color_index
2367
rv = (((gx_color_index) m)<<22)|
2368
(((gx_color_index) y)<<12)|
2369
(((gx_color_index) k)<< 2)|mode;
2372
rv = (((gx_color_index) c)<<22)|
2373
(((gx_color_index) y)<<12)|
2374
(((gx_color_index) k)<< 2)|mode;
2377
rv = (((gx_color_index) c)<<22)|
2378
(((gx_color_index) m)<<12)|
2379
(((gx_color_index) k)<< 2)|mode;
2382
rv = (((gx_color_index) k)<< 2)|mode;
2387
* We may need some swapping
2389
#if !arch_is_big_endian
2391
union { stc_pixel cv; byte bv[4]; } ui,uo;
2393
uo.bv[0] = ui.bv[3];
2394
uo.bv[1] = ui.bv[2];
2395
uo.bv[2] = ui.bv[1];
2396
uo.bv[3] = ui.bv[0];
2404
stc_map_color_cmyk10(gx_device *pdev, gx_color_index color,
2405
gx_color_value cv[3])
2408
stcolor_device *sd = (stcolor_device *) pdev;
2409
gx_color_value c,m,y;
2412
* We may need some swapping
2414
#if !arch_is_big_endian
2415
union { stc_pixel cv; byte bv[4]; } ui,uo;
2417
uo.bv[0] = ui.bv[3];
2418
uo.bv[1] = ui.bv[2];
2419
uo.bv[2] = ui.bv[1];
2420
uo.bv[3] = ui.bv[0];
2424
c = stc_expand(sd,3,(color>>2)&0x3ff);
2426
/* cast the 64 bit switch argument to work around broken HPUX 10 cc */
2427
switch((int)(color & 3)) {
2429
m = stc_expand(sd,1,(color>>22) & 0x3ff);
2430
y = stc_expand(sd,2,(color>>12) & 0x3ff);
2434
c = stc_expand(sd,0,(color>>22) & 0x3ff);
2435
y = stc_expand(sd,2,(color>>12) & 0x3ff);
2439
c = stc_expand(sd,0,(color>>22) & 0x3ff);
2440
m = stc_expand(sd,1,(color>>12) & 0x3ff);
2456
*** Macros for parameter-handling
2459
#define set_param_array(A, D, S)\
2460
{A.data = D; A.size = S; A.persistent = false;}
2462
#define stc_write_null(N) \
2463
set_param_array(pfa,defext,countof(defext)) \
2464
code = param_write_null(plist,N); \
2465
if (code < 0) return code;
2467
#define stc_write_xarray(I,Coding,Transfer) \
2468
if(sd->stc.sizc[I] > 0) { \
2469
set_param_array(pfa, sd->stc.extc[I],sd->stc.sizc[I]) \
2470
code = param_write_float_array(plist,Coding,&pfa); \
2472
code = param_write_null(plist,Coding); \
2474
if ( code < 0 ) return code; \
2476
if(sd->stc.sizv[I] > 0) \
2477
set_param_array(pfa, sd->stc.extv[I],sd->stc.sizv[I]) \
2479
set_param_array(pfa,defext,countof(defext)) \
2480
code = param_write_float_array(plist,Transfer,&pfa); \
2481
if ( code < 0 ) return code;
2483
#define stc_read_null(N) \
2484
code = param_read_null(plist,N); \
2485
if(code == gs_error_typecheck) \
2486
code = param_read_float_array(plist,N,&pfa); \
2487
if(code < 0) param_signal_error(plist,N,code); \
2488
error = error > code ? code : error;
2490
#define stc_read_xarray(I,Coding,Transfer) \
2491
code = param_read_float_array(plist,Coding,&pfa); \
2492
if((error == 0) && (code == 0)) { \
2493
if(pfa.size > 1) { \
2494
sd->stc.extc[I] = (float *) pfa.data; \
2495
sd->stc.sizc[I] = pfa.size; \
2497
code = gs_error_rangecheck; \
2499
} else if(code < 0) { \
2500
code = param_read_null(plist,Coding); \
2502
sd->stc.extc[I] = NULL; \
2503
sd->stc.sizc[I] = 0; \
2506
if(code < 0) param_signal_error(plist,Coding,code); \
2507
error = error > code ? code : error; \
2508
code = param_read_float_array(plist,Transfer,&pfa); \
2509
if((error == 0) && (code == 0)) { \
2510
sd->stc.extv[I] = (float *) pfa.data; \
2511
sd->stc.sizv[I] = pfa.size; \
2512
} else if(code < 0) { \
2513
code = param_read_null(plist,Transfer); \
2515
sd->stc.extv[I] = defext; \
2516
sd->stc.sizv[I] = countof(defext); \
2519
if(code < 0) param_signal_error(plist,Transfer,code); \
2520
error = error > code ? code : error;
2523
*** Get parameters == Make them accessable via PostScript
2527
stc_get_params(gx_device *pdev, gs_param_list *plist)
2531
gs_param_float_array pfa;
2533
stcolor_device *sd = (stcolor_device *) pdev;
2535
code = gdev_prn_get_params(pdev, plist);
2536
if ( code < 0 ) return code;
2539
* Export some readonly-Parameters, used by stcinfo.ps
2541
param_string_from_string(ps,"1.91");
2542
code = param_write_string(plist,"Version",&ps);
2543
if ( code < 0 ) return code;
2545
code = param_write_int(plist,"BitsPerComponent",&sd->stc.bits);
2546
if ( code < 0 ) return code;
2548
if(sd->stc.algorithms.size > 0) {
2549
code = param_write_string_array(plist,"Algorithms",&sd->stc.algorithms);
2551
code = param_write_null(plist,"Algorithms");
2553
if ( code < 0 ) return code;
2558
switch(sd->stc.flags & STCCOMP) {
2559
case STCPLAIN: param_string_from_string(ps,"plain"); break;
2560
case STCDELTA: param_string_from_string(ps,"deltarow"); break;
2561
default: param_string_from_string(ps,"runlength"); break;
2563
code = param_write_string(plist,"OutputCode",&ps);
2564
if ( code < 0 ) return code;
2568
switch(sd->stc.flags & STCMODEL) {
2569
case STCST800: param_string_from_string(ps,"st800"); break;
2570
case STCSTCII: param_string_from_string(ps,"stcii"); break;
2571
default: param_string_from_string(ps,"stc"); break;
2573
code = param_write_string(plist,"Model",&ps);
2574
if ( code < 0 ) return code;
2577
* Export the booleans
2579
#define stc_write_flag(Mask,Name) \
2580
btmp = sd->stc.flags & (Mask) ? true : false; \
2581
code = param_write_bool(plist,Name,&btmp); \
2582
if ( code < 0 ) return code;
2584
stc_write_flag(STCUNIDIR,"Unidirectional")
2585
stc_write_flag(STCUWEAVE,"Microweave")
2586
btmp = sd->stc.flags & (STCUNIDIR|STCUWEAVE) ? false : true;
2587
code = param_write_bool(plist,"Softweave",&btmp);
2588
if ( code < 0 ) return code;
2589
stc_write_flag(STCNWEAVE,"noWeave")
2590
stc_write_flag(STCDFLAG0, "Flag0")
2591
stc_write_flag(STCDFLAG1, "Flag1")
2592
stc_write_flag(STCDFLAG2, "Flag2")
2593
stc_write_flag(STCDFLAG3, "Flag3")
2594
stc_write_flag(STCDFLAG4, "Flag4")
2596
#undef stc_write_flag
2598
# define stc_write_int(Mask,Name,Val) \
2599
code = param_write_int(plist,Name,&Val); \
2600
if ( code < 0 ) return code
2602
stc_write_int(STCBAND, "escp_Band", sd->stc.escp_m);
2603
stc_write_int(STCWIDTH, "escp_Width", sd->stc.escp_width);
2604
stc_write_int(STCHEIGHT,"escp_Height",sd->stc.escp_height);
2605
stc_write_int(STCTOP, "escp_Top", sd->stc.escp_top);
2606
stc_write_int(STCBOTTOM,"escp_Bottom",sd->stc.escp_bottom);
2608
# undef stc_write_int
2610
code = param_write_string(plist,"escp_Init",&sd->stc.escp_init);
2611
code = param_write_string(plist,"escp_Release",&sd->stc.escp_release);
2613
if(sd->stc.dither != NULL) {
2614
param_string_from_string(ps,sd->stc.dither->name);
2615
code = param_write_string(plist,"Dithering",&ps);
2617
code = param_write_null(plist,"Dithering");
2619
if ( code < 0 ) return code;
2621
nc = sd->color_info.num_components;
2623
if(sd->stc.am != NULL) {
2624
if( nc == 1) set_param_array(pfa, sd->stc.am, 3)
2625
else if(nc == 3) set_param_array(pfa, sd->stc.am, 9)
2626
else set_param_array(pfa, sd->stc.am,16)
2627
code = param_write_float_array(plist,"ColorAdjustMatrix",&pfa);
2629
code = param_write_null(plist,"ColorAdjustMatrix");
2631
if ( code < 0 ) return code;
2633
if(nc == 1) { /* DeviceGray */
2635
stc_write_xarray(0,"Kcoding","Ktransfer");
2637
stc_write_null("Rcoding"); stc_write_null("Rtransfer");
2638
stc_write_null("Gcoding"); stc_write_null("Gtransfer");
2639
stc_write_null("Bcoding"); stc_write_null("Btransfer");
2641
stc_write_null("Ccoding"); stc_write_null("Ctransfer");
2642
stc_write_null("Mcoding"); stc_write_null("Mtransfer");
2643
stc_write_null("Ycoding"); stc_write_null("Ytransfer");
2645
} else if(nc == 3) { /* DeviceRGB */
2647
stc_write_xarray(0,"Rcoding","Rtransfer");
2648
stc_write_xarray(1,"Gcoding","Gtransfer");
2649
stc_write_xarray(2,"Bcoding","Btransfer");
2651
stc_write_null("Ccoding"); stc_write_null("Ctransfer");
2652
stc_write_null("Mcoding"); stc_write_null("Mtransfer");
2653
stc_write_null("Ycoding"); stc_write_null("Ytransfer");
2654
stc_write_null("Kcoding"); stc_write_null("Ktransfer");
2656
} else { /* DeviceCMYK */
2658
stc_write_xarray(0,"Ccoding","Ctransfer");
2659
stc_write_xarray(1,"Mcoding","Mtransfer");
2660
stc_write_xarray(2,"Ycoding","Ytransfer");
2661
stc_write_xarray(3,"Kcoding","Ktransfer");
2663
stc_write_null("Rcoding"); stc_write_null("Rtransfer");
2664
stc_write_null("Gcoding"); stc_write_null("Gtransfer");
2665
stc_write_null("Bcoding"); stc_write_null("Btransfer");
2672
*** put parameters == Store them in the device-structure
2676
stc_put_params(gx_device *pdev, gs_param_list *plist)
2682
gs_param_string_array psa;
2683
gs_param_float_array pfa;
2684
stcolor_device *sd = (stcolor_device *) pdev;
2685
gx_device_color_info oldcolor;
2691
memcpy(&oldcolor,&sd->color_info,sizeof(oldcolor));
2692
memcpy(&oldstc ,&sd->stc ,sizeof(oldstc ));
2696
* With Version 3.4x and above my simple minded read-only Parameters
2697
* do not work any more. So read them here for heavens sake.
2699
code = param_read_string(plist,"Version",&ps);
2700
code = param_read_int(plist,"BitsPerComponent",&i);
2701
code = param_read_string_array(plist,"Algorithms",&psa);
2704
* Fetch Major-Parameters (Model, Dithering, BitsPerPixel/BitsPerComponent)
2708
code = param_read_string(plist,"Model",&ps);
2709
if(code == 0) { /* Analyze the Model-String */
2711
* Arrgh: I should have known, that internal strings are not zero-terminated.
2713
for(l = ps.size; (l > 0) && (ps.data[l-1] == 0); --l);
2714
# define stc_putcmp(Name) \
2715
((strlen(Name) != l) || (0 != strncmp(Name, (const char *)ps.data,l)))
2717
sd->stc.flags &= ~STCMODEL;
2718
if( !stc_putcmp("st800")) sd->stc.flags |= STCST800;
2719
else if(!stc_putcmp("stcii")) sd->stc.flags |= STCSTCII;
2721
} /* Analyze the Model-String */
2722
if(code < 0) param_signal_error(plist,"Model",code);
2723
error = error > code ? code : error;
2725
/* If we're running for st800, #components must be 1 */
2726
if(((sd->stc.flags & STCMODEL) == STCST800) &&
2727
(( sd->color_info.num_components > 1) ||
2728
( sd->stc.dither == NULL) ||
2729
((sd->stc.dither->flags & 7) > 1))) {
2730
sd->color_info.num_components = 1;
2731
sd->stc.dither = NULL;
2734
/* Weaving isn't a feature for the st800 */
2735
if((sd->stc.flags & STCMODEL) == STCST800) {
2736
sd->stc.flags &= ~STCUWEAVE;
2737
sd->stc.flags |= STCNWEAVE;
2738
} else if((sd->stc.flags & STCMODEL) == STCSTCII) { /* no SoftWeave */
2739
sd->stc.flags |= STCNWEAVE;
2742
code = param_read_string(plist,"Dithering",&ps);
2743
if(code == 0) { /* lookup new value new value */
2745
for(l = ps.size; (l > 0) && (ps.data[l-1] == 0); --l);
2747
for(i = 0; stc_dither[i].name != NULL; ++i)
2748
if(!stc_putcmp(stc_dither[i].name)) break;
2750
} else if(sd->stc.dither != NULL) { /* compute index of given value */
2752
i = sd->stc.dither - stc_dither;
2754
} else { /* find matching value */
2756
for(i = 0; stc_dither[i].name != NULL; ++i)
2757
if((stc_dither[i].flags & 7) == sd->color_info.num_components) break;
2759
} /* we've got an index */
2761
if(stc_dither[i].name != NULL) { /* establish data */
2764
* Establish new dithering algorithm & color-model
2766
sd->stc.dither = stc_dither+i;
2767
sd->color_info.num_components = sd->stc.dither->flags & 7;
2768
STC_TYPESWITCH(sd->stc.dither,stc_sizeofitem)
2769
# undef stc_sizeofitem
2770
if(((sd->stc.flags & STCMODEL) == STCST800) &&
2771
( sd->color_info.num_components > 1 ))
2772
code = gs_error_rangecheck;
2775
* reset Parameters related to the color-model, if it changed
2778
if(sd->color_info.num_components != oldcolor.num_components) {
2780
for(i = 0; i < sd->color_info.num_components; ++i) {
2781
sd->stc.extv[i] = (float *) defext;
2782
sd->stc.sizv[i] = countof(defext);
2784
sd->stc.extc[i] = NULL;
2785
sd->stc.sizc[i] = 0;
2791
} else { /* guarantee, that extvals is present */
2793
for(i = 0; i < sd->color_info.num_components; ++i) {
2794
if(sd->stc.sizv[i] < 2) {
2795
sd->stc.extv[i] = (float *) defext;
2796
sd->stc.sizv[i] = countof(defext);
2801
for(i = sd->color_info.num_components; i < 4; ++ i) { /* clear unused */
2802
sd->stc.extv[i] = NULL;
2803
sd->stc.sizv[i] = 0;
2804
sd->stc.vals[i] = NULL;
2806
sd->stc.extc[i] = NULL;
2807
sd->stc.sizc[i] = 0;
2808
sd->stc.code[i] = NULL;
2810
} /* clear unused */
2813
* Guess default depth from range of values
2815
if((sd->stc.dither != oldstc.dither)||(oldstc.vals[0] == NULL)) {
2817
if((sd->stc.dither->flags & STC_CMYK10) != 0) {
2819
sd->stc.flags |= STCCMYK10;
2821
sd->color_info.depth = 32;
2825
sd->stc.flags &= ~STCCMYK10;
2827
if((sd->stc.dither->flags & STC_FLOAT) != STC_FLOAT) {
2829
for(i = 1;(i < gx_color_value_bits) &&
2830
(fv <= (sd->stc.dither->minmax[1]-sd->stc.dither->minmax[0]));
2834
i = 8; /* arbitrary */
2837
if((i*sd->color_info.num_components) > (sizeof(stc_pixel)*8)) {
2839
sd->stc.bits = (sizeof(stc_pixel)*8) /
2840
sd->color_info.num_components;
2841
sd->color_info.depth = sd->stc.bits * sd->color_info.num_components;
2846
sd->color_info.depth = sd->stc.bits * sd->color_info.num_components;
2854
code = gs_error_rangecheck;
2856
} /* verify new value */
2857
if(code < 0) param_signal_error(plist,"Dithering",code);
2858
error = error > code ? code : error;
2861
* now fetch the desired depth, if the algorithm allows it
2864
* Arrrgh: We get code == 0, even if nobody sets BitsPerPixel.
2865
* The value is the old one, but this may cause trouble
2868
code = param_read_int(plist, "BitsPerPixel", &i);
2869
if((error == 0) && (code == 0) &&
2870
(((sd->stc.flags & STCCMYK10) == 0) || (i != sd->color_info.depth))) {
2872
if((1 > i) || (i > (sizeof(stc_pixel)*8)))
2873
code = gs_error_rangecheck;
2875
sd->color_info.depth = i;
2877
sd->stc.bits = i / sd->color_info.num_components;
2879
if(1 > sd->stc.bits) code = gs_error_rangecheck;
2881
if((sd->stc.dither->flags & STC_DIRECT) &&
2882
(sd->stc.dither->flags & STC_CMYK10))
2883
code = gs_error_rangecheck;
2885
sd->stc.flags &= ~STCCMYK10;
2888
if(code < 0) param_signal_error(plist,"BitsPerPixel",code);
2889
error = error > code ? code : error;
2894
code = param_read_string(plist,"OutputCode",&ps);
2895
if(code == 0) { /* Analyze the OutputCode-String */
2897
for(l = ps.size; (l > 0) && (ps.data[l-1] == 0); --l);
2899
sd->stc.flags &= ~STCCOMP;
2900
if(!stc_putcmp("plain")) sd->stc.flags |= STCPLAIN;
2901
else if(!stc_putcmp("deltarow")) sd->stc.flags |= STCDELTA;
2903
} /* Analyze the OutputCode-String */
2904
if((sd->stc.flags & STCCOMP) == STCDELTA) {
2905
sd->stc.flags |= STCUWEAVE;
2906
sd->stc.flags &= ~STCNWEAVE;
2908
if(code < 0) param_signal_error(plist,"OutputCode",code);
2909
error = error > code ? code : error;
2912
* fetch the weave-mode (noWeave wins)
2914
b1 = sd->stc.flags & STCUWEAVE ? true : false;
2915
b2 = sd->stc.flags & STCNWEAVE ? true : false;
2916
b3 = sd->stc.flags & (STCUWEAVE|STCNWEAVE) ? false : true;
2918
code = param_read_bool(plist,"Microweave",&b1);
2920
param_signal_error(plist,"Microweave",code);
2921
} else if(code == 0) {
2922
if(b1) { b2 = false; b3 = false; }
2924
error = error > code ? code : error;
2926
code = param_read_bool(plist,"noWeave",&b2);
2928
param_signal_error(plist,"noWeave",code);
2929
} else if (code == 0) {
2930
if(b2) { b1 = false; b3 = false; }
2932
error = error > code ? code : error;
2934
code = param_read_bool(plist,"Softweave",&b3);
2936
param_signal_error(plist,"Softweave",code);
2937
} else if (code == 0) {
2938
if(b3) { b1 = false; b2 = false; }
2940
error = error > code ? code : error;
2942
if(b1) sd->stc.flags |= STCUWEAVE;
2943
else sd->stc.flags &= ~STCUWEAVE;
2945
if(b2) sd->stc.flags |= STCNWEAVE;
2946
else sd->stc.flags &= ~STCNWEAVE;
2949
* Check the simple Flags
2951
# define stc_read_flag(Mask,Name) \
2952
code = param_read_bool(plist,Name,&b1); \
2954
param_signal_error(plist,Name,code); \
2955
} else if(code == 0) { \
2956
if(b1 == true) sd->stc.flags |= Mask; \
2957
else sd->stc.flags &= ~(Mask); \
2959
error = error > code ? code : error;
2961
stc_read_flag(STCUNIDIR,"Unidirectional")
2962
stc_read_flag(STCDFLAG0, "Flag0")
2963
stc_read_flag(STCDFLAG1, "Flag1")
2964
stc_read_flag(STCDFLAG2, "Flag2")
2965
stc_read_flag(STCDFLAG3, "Flag3")
2966
stc_read_flag(STCDFLAG4, "Flag4")
2969
* Now deal with the escp-Stuff
2971
# define stc_read_int(Mask,Name,Val) \
2972
code = param_read_int(plist,Name,&Val); \
2974
param_signal_error(plist,Name,code); \
2975
else if(code == 0) \
2976
sd->stc.flags |= Mask; \
2977
error = error > code ? code : error
2979
stc_read_int(STCBAND, "escp_Band", sd->stc.escp_m);
2980
stc_read_int(STCWIDTH, "escp_Width", sd->stc.escp_width);
2981
stc_read_int(STCHEIGHT,"escp_Height",sd->stc.escp_height);
2982
stc_read_int(STCTOP, "escp_Top", sd->stc.escp_top);
2983
stc_read_int(STCBOTTOM,"escp_Bottom",sd->stc.escp_bottom);
2985
# undef stc_read_int
2987
code = param_read_string(plist,"escp_Init",&sd->stc.escp_init);
2988
if(code == 0) sd->stc.flags |= STCINIT;
2989
error = error > code ? code : error;
2991
code = param_read_string(plist,"escp_Release",&sd->stc.escp_release);
2992
if(code == 0) sd->stc.flags |= STCRELEASE;
2993
error = error > code ? code : error;
2996
* ColorAdjustMatrix must match the required size,
2997
* setting it explicitly to null, erases old matrix
2999
code = param_read_float_array(plist,"ColorAdjustMatrix",&pfa);
3000
if((error == 0) && (code == 0)) {
3001
if(((sd->color_info.num_components == 1) && (pfa.size == 3)) ||
3002
((sd->color_info.num_components == 3) && (pfa.size == 9)) ||
3003
((sd->color_info.num_components == 4) && (pfa.size == 16)))
3004
sd->stc.am = (float *) pfa.data;
3006
code = gs_error_rangecheck;
3007
} else if(code < 0) {
3008
code = param_read_null(plist,"ColorAdjustMatrix");
3009
if(code == 0) sd->stc.am = NULL;
3011
if(code < 0) param_signal_error(plist,"ColorAdjustMatrix",code);
3012
error = error > code ? code : error;
3015
* Read the external array-Parameters
3017
if(sd->color_info.num_components == 1) { /* DeviceGray */
3019
stc_read_xarray(0,"Kcoding","Ktransfer");
3021
stc_read_null("Rcoding"); stc_read_null("Rtransfer");
3022
stc_read_null("Gcoding"); stc_read_null("Gtransfer");
3023
stc_read_null("Bcoding"); stc_read_null("Btransfer");
3025
stc_read_null("Ccoding"); stc_read_null("Ctransfer");
3026
stc_read_null("Mcoding"); stc_read_null("Mtransfer");
3027
stc_read_null("Ycoding"); stc_read_null("Ytransfer");
3029
} else if(sd->color_info.num_components == 3) { /* DeviceRGB */
3031
stc_read_xarray(0,"Rcoding","Rtransfer");
3032
stc_read_xarray(1,"Gcoding","Gtransfer");
3033
stc_read_xarray(2,"Bcoding","Btransfer");
3035
stc_read_null("Ccoding"); stc_read_null("Ctransfer");
3036
stc_read_null("Mcoding"); stc_read_null("Mtransfer");
3037
stc_read_null("Ycoding"); stc_read_null("Ytransfer");
3038
stc_read_null("Kcoding"); stc_read_null("Ktransfer");
3040
} else { /* DeviceCMYK */
3042
stc_read_xarray(0,"Ccoding","Ctransfer");
3043
stc_read_xarray(1,"Mcoding","Mtransfer");
3044
stc_read_xarray(2,"Ycoding","Ytransfer");
3045
stc_read_xarray(3,"Kcoding","Ktransfer");
3047
stc_read_null("Rcoding"); stc_read_null("Rtransfer");
3048
stc_read_null("Gcoding"); stc_read_null("Gtransfer");
3049
stc_read_null("Bcoding"); stc_read_null("Btransfer");
3053
* Update remaining color_info values
3057
/* compute #values from the component-bits */
3058
sd->color_info.max_gray = sd->stc.bits < gx_color_value_bits ?
3059
(1<<sd->stc.bits)-1 : gx_max_color_value;
3061
/* An integer-algorithm might reduce the number of values */
3062
if(((sd->stc.dither->flags & STC_TYPE) != STC_FLOAT) &&
3063
((sd->stc.dither->minmax[1]-sd->stc.dither->minmax[0]) <
3064
sd->color_info.max_gray))
3065
sd->color_info.max_gray = (gx_color_value)
3066
(sd->stc.dither->minmax[1]-sd->stc.dither->minmax[0]+0.5);
3068
sd->color_info.max_color = sd->color_info.num_components < 3 ? 0 :
3069
sd->color_info.max_gray;
3070
sd->color_info.dither_grays =
3071
sd->color_info.max_gray < gx_max_color_value ?
3072
sd->color_info.max_gray+1 : gx_max_color_value;
3073
sd->color_info.dither_colors = sd->color_info.num_components < 3 ? 0 :
3074
sd->color_info.dither_grays;
3078
* Call superclass-Update
3081
code = gdev_prn_put_params(pdev, plist);
3082
error = error > code ? code : error;
3085
* Arrrgh, writing BitsPerPixel is really *VERY* special:
3086
* gdev_prn_put_params verifies, that the external value
3087
* is written, if not, it raises a rangecheck-error.
3088
* On the other hand ghostscript is quite unhappy with odd
3089
* values, so we do the necessary rounding *AFTER* the
3090
* "superclass-Update".
3093
if(sd->color_info.depth == 3) sd->color_info.depth = 4;
3094
else if(sd->color_info.depth > 4)
3095
sd->color_info.depth = (sd->color_info.depth+7) & ~7;
3098
* Allocate the storage for the arrays in memory
3100
if(error == 0) { /* Allocate new external-arrays */
3102
for(i = 0; i < sd->color_info.num_components; ++i){ /* Active components */
3105
if((sd->stc.extv[i] != oldstc.extv[i]) &&
3106
(sd->stc.extv[i] != defext )) { /* Value-Arrays */
3108
for(j = 0; j < i; ++j)
3109
if((sd->stc.sizv[j] == sd->stc.sizv[i]) &&
3110
(memcmp(sd->stc.extv[j],sd->stc.extv[i],
3111
sd->stc.sizv[i]*sizeof(float)) == 0)) break;
3114
sd->stc.extv[i] = sd->stc.extv[j];
3116
fp = gs_malloc(sd->memory, sd->stc.sizv[i],sizeof(float),"stc_put_params");
3118
memcpy(fp,sd->stc.extv[i],sd->stc.sizv[i]*sizeof(float));
3120
code = gs_error_VMerror;
3121
sd->stc.extv[i] = fp;
3123
} /* Value-Arrays */
3125
if((sd->stc.sizc[i] > 1) &&
3126
(sd->stc.extc[i] != oldstc.extc[i])) { /* Code-Arrays */
3128
for(j = 0; j < i; ++j)
3129
if((sd->stc.sizc[j] == sd->stc.sizc[i]) &&
3130
(memcmp(sd->stc.extc[j],sd->stc.extc[i],
3131
sd->stc.sizc[i]*sizeof(float)) == 0)) break;
3134
sd->stc.extc[i] = sd->stc.extc[j];
3136
fp = gs_malloc(sd->memory, sd->stc.sizc[i],sizeof(float),"stc_put_params");
3138
memcpy(fp,sd->stc.extc[i],sd->stc.sizc[i]*sizeof(float));
3140
code = gs_error_VMerror;
3141
sd->stc.extc[i] = fp;
3145
} /* Active components */
3147
if((sd->stc.am != NULL) && (sd->stc.am != oldstc.am)) {
3148
if( sd->color_info.num_components == 1) i = 3;
3149
else if(sd->color_info.num_components == 3) i = 9;
3151
fp = gs_malloc(sd->memory, i,sizeof(float),"stc_put_params");
3152
if(fp != NULL) memcpy(fp,sd->stc.am,i*sizeof(float));
3153
else code = gs_error_VMerror;
3157
if(sd->stc.escp_init.data != oldstc.escp_init.data) {
3160
if(sd->stc.escp_init.size > 0) {
3161
ip = gs_malloc(sd->memory, sd->stc.escp_init.size,1,"stcolor/init");
3163
code = gs_error_VMerror;
3164
sd->stc.escp_init.size = 0;
3166
memcpy(ip,sd->stc.escp_init.data,sd->stc.escp_init.size);
3169
sd->stc.escp_init.data = ip;
3170
sd->stc.escp_init.persistent = false;
3173
if(sd->stc.escp_release.data != oldstc.escp_release.data) {
3176
if(sd->stc.escp_release.size > 0) {
3177
ip = gs_malloc(sd->memory, sd->stc.escp_release.size,1,"stcolor/release");
3179
code = gs_error_VMerror;
3180
sd->stc.escp_release.size = 0;
3182
memcpy(ip,sd->stc.escp_release.data,sd->stc.escp_release.size);
3185
sd->stc.escp_release.data = ip;
3186
sd->stc.escp_release.persistent = false;
3189
if(code < 0) { /* free newly allocated arrays */
3191
if((sd->stc.am != NULL) && (sd->stc.am != oldstc.am)) {
3192
if( sd->color_info.num_components == 1) i = 3;
3193
else if(sd->color_info.num_components == 3) i = 9;
3195
gs_free(sd->memory, sd->stc.am,i,sizeof(float),"stc_put_params");
3198
if((sd->stc.escp_init.data != NULL) &&
3199
(sd->stc.escp_init.data != oldstc.escp_init.data))
3200
gs_free(sd->memory, (byte *) sd->stc.escp_init.data,sd->stc.escp_init.size,1,
3203
if((sd->stc.escp_release.data != NULL) &&
3204
(sd->stc.escp_release.data != oldstc.escp_release.data))
3205
gs_free(sd->memory, (byte *) sd->stc.escp_release.data,sd->stc.escp_release.
3206
size,1,"stcolor/release");
3208
for(i = 0; i < sd->color_info.num_components; ++i) { /* components */
3211
if((sd->stc.extc[i] != NULL) &&
3212
(sd->stc.extc[i] != defext) &&
3213
(sd->stc.extc[i] != oldstc.extc[i])) {
3215
for(j = 0; j < i; ++j)
3216
if(sd->stc.extc[i] == sd->stc.extc[j]) break;
3218
if(i == j) gs_free(sd->memory, sd->stc.extc[i],sd->stc.sizc[i],sizeof(float),
3222
if((sd->stc.extv[i] != NULL) &&
3223
(sd->stc.extv[i] != oldstc.extv[i]) &&
3224
(sd->stc.extv[i] != defext)) {
3226
for(j = 0; j < i; ++j)
3227
if(sd->stc.extv[i] == sd->stc.extv[j]) break;
3229
if(i == j) gs_free(sd->memory, sd->stc.extv[i],sd->stc.sizv[i],sizeof(float),
3233
} /* free newly allocated arrays */
3234
} /* Allocate new arrays */
3235
error = error > code ? code : error;
3238
* finally decide upon restore or release of old, unused data
3240
if(error != 0) { /* Undo changes */
3242
memcpy(&sd->color_info,&oldcolor,sizeof(oldcolor));
3243
memcpy(&sd->stc ,&oldstc ,sizeof(oldstc ));
3244
} else { /* undo / release */
3246
if((oldstc.escp_init.data != NULL) &&
3247
(oldstc.escp_init.data != sd->stc.escp_init.data)) {
3248
gs_free(sd->memory, (byte *)oldstc.escp_init.data,
3249
oldstc.escp_init.size,1,"stcolor/init");
3252
if((oldstc.escp_release.data != NULL) &&
3253
(oldstc.escp_release.data != sd->stc.escp_release.data)) {
3254
gs_free(sd->memory, (byte *)oldstc.escp_release.data,
3255
oldstc.escp_release.size,1,"stcolor/release");
3258
if((oldstc.am != NULL) && (oldstc.am != sd->stc.am)) {
3259
if( oldcolor.num_components == 1) i = 3;
3260
else if(oldcolor.num_components == 3) i = 9;
3262
gs_free(sd->memory, oldstc.am,i,sizeof(float),"stc_put_params");
3265
for(i = 0; i < 4; ++i) {
3268
if((oldstc.extc[i] != NULL) &&
3269
(oldstc.extc[i] != sd->stc.extc[i]) &&
3270
(oldstc.dither != NULL) &&
3271
(oldstc.extc[i] != defext)) {
3273
for(j = 0; j < i; ++j) if(oldstc.extc[i] == oldstc.extc[j]) break;
3275
if(i == j) gs_free(sd->memory, oldstc.extc[i],oldstc.sizc[i],sizeof(float),
3279
if((oldstc.extv[i] != NULL) &&
3280
(oldstc.extv[i] != sd->stc.extv[i]) &&
3281
(oldstc.extv[i] != defext)) {
3283
for(j = 0; j < i; ++j) if(oldstc.extv[i] == oldstc.extv[j]) break;
3285
if(i == j) gs_free(sd->memory, oldstc.extv[i],oldstc.sizv[i],sizeof(float),
3291
* Close the device if colormodel changed or recomputation
3292
* of internal arrays is required
3294
if(sd->is_open) { /* we might need to close it */
3295
bool doclose = false;
3296
if((sd->color_info.num_components != oldcolor.num_components) ||
3297
(sd->color_info.depth != oldcolor.depth ) ||
3298
(sd->stc.bits != oldstc.bits ) ||
3299
(sd->stc.dither != oldstc.dither ))
3302
for(i = 0; i < sd->color_info.num_components; ++i) {
3303
if(sd->stc.extv[i] != oldstc.extv[i]) doclose = true;
3304
if(sd->stc.extc[i] != oldstc.extc[i]) doclose = true;
3307
stc_freedata(pdev->memory, &oldstc);
3308
for(i = 0; i < 4; ++i) {
3309
sd->stc.vals[i] = NULL;
3310
sd->stc.code[i] = NULL;
3313
gs_closedevice(pdev);
3315
} /* we might need to close it */
3322
* 1Bit CMYK-Algorithm
3326
stc_gscmyk(stcolor_device *sdev,int npixel,byte *in,byte *buf,byte *out)
3333
/* ============================================================= */
3334
if(npixel > 0) { /* npixel > 0 -> scanline-processing */
3335
/* ============================================================= */
3340
* simply split the two pixels rsiding in a byte
3342
for(p = npixel; p > 0; --p) { /* loop over pixels */
3345
*out++ = (tmp>>4) & 15;
3350
} /* loop over pixels */
3352
/* ============================================================= */
3353
} else { /* npixel <= 0 -> initialisation */
3354
/* ============================================================= */
3356
/* we didn't check for the white-calls above, so this may cause errors */
3357
if(sdev->stc.dither->flags & STC_WHITE) error = -1;
3359
/* if we're not setup for bytes, this is an error too */
3360
if((sdev->stc.dither->flags & STC_TYPE) != STC_BYTE) error = -2;
3362
/* This IS a direct-driver, so STC_DIRECT must be set! */
3363
if((sdev->stc.dither->flags & STC_DIRECT) == 0) error = -3;
3365
/* and cmyk-mode is the only supported mode */
3366
if(sdev->color_info.num_components != 4) error = -4;
3368
/* and we support only 4Bit-Depth here */
3369
if(sdev->color_info.depth != 4) error = -5;
3371
/* ============================================================= */
3372
} /* scanline-processing or initialisation */
3373
/* ============================================================= */
3379
* The following is an algorithm under test
3382
stc_hscmyk(stcolor_device *sdev,int npixel,byte *in,byte *buf,byte *out)
3385
/* ============================================================= */
3386
if(npixel < 0) { /* npixel <= 0 -> initialisation */
3387
/* ============================================================= */
3390
long *lp = (long *) buf;
3392
/* CMYK-only algorithm */
3393
if( sdev->color_info.num_components != 4) return -1;
3396
* check wether stcdither & TYPE are correct
3398
if(( sdev->stc.dither == NULL) ||
3399
((sdev->stc.dither->flags & STC_TYPE) != STC_LONG)) return -2;
3402
* check wether the buffer-size is sufficiently large
3404
if(((sdev->stc.dither->flags/STC_SCAN) < 1) ||
3405
( sdev->stc.dither->bufadd <
3406
(1 + 2*sdev->color_info.num_components))) return -3;
3409
* must have STC_CMYK10, STC_DIRECT, but not STC_WHITE
3411
if((sdev->stc.dither->flags & STC_CMYK10) == 0) return -4;
3412
if((sdev->stc.dither->flags & STC_DIRECT) == 0) return -5;
3413
if((sdev->stc.dither->flags & STC_WHITE ) != 0) return -6;
3416
* Must have values between 0-1023.0
3418
if((sdev->stc.dither->minmax[0] != 0.0) ||
3419
(sdev->stc.dither->minmax[1] != 1023.0)) return -7;
3424
i2do = 1 + 8 - 4 * npixel;
3427
if(sdev->stc.flags & STCDFLAG0) {
3428
for(i = 1; i < i2do; ++i) lp[i] = 0;
3430
for(i = 1; i < i2do; ++i) lp[i] = (rand() % 381) - 190;
3433
/* ============================================================= */
3434
} else { /* npixel > 0 && in != NULL -> scanline-processing */
3435
/* ============================================================= */
3438
int step = buf[0] ? -1 : 1;
3439
stc_pixel *ip = (stc_pixel *) in;
3442
errv = (long *) buf + 5;
3447
errv += 4*(npixel-1);
3450
errc[0] = 0; errc[1] = 0; errc[2] = 0; errc[3] = 0;
3452
while(npixel-- > 0) {
3454
register stc_pixel ci,mode;
3455
register long k,v,n;
3456
register int pixel; /* internal pixel-value */
3458
ci = *ip; ip += step;
3461
k = (ci>>2) & 0x3ff;
3464
v = k+errv[3]+((7*errc[3])>>4);
3466
if(mode == 3) { /* only Black allowed to fire */
3472
errv[3-(step<<2)] += ((3*v+8)>>4); /* 3/16 */
3473
errv[3] = ((5*v+errc[3]+8)>>4);/* 5/16 +1/16 (rest) */
3476
errv[0] = errv[0] < -190 ? -190 : errv[0] < 190 ? errv[0] : 190;
3477
errv[1] = errv[1] < -190 ? -190 : errv[1] < 190 ? errv[1] : 190;
3478
errv[2] = errv[2] < -190 ? -190 : errv[2] < 190 ? errv[2] : 190;
3480
errc[0] = 0; errc[1] = 0; errc[2] = 0;
3482
} else if(v > 511) { /* black known to fire */
3487
errv[3-(step<<2)] += ((3*v+8)>>4); /* 3/16 */
3488
errv[3] = ((5*v+errc[3]+8)>>4);/* 5/16 +1/16 (rest) */
3491
n = (ci>>12) & 0x3ff;
3493
if(mode == 2) { v = k; }
3494
else { v = n; n = (ci>>22) & 0x3ff; }
3496
v += errv[2]+((7*errc[2])>>4)-1023;
3497
if(v < -511) v = -511;
3498
errv[2-(step<<2)] += ((3*v+8)>>4); /* 3/16 */
3499
errv[2] = ((5*v+errc[2]+8)>>4);/* 5/16 +1/16 (rest) */
3502
if(mode == 1) { v = k; }
3503
else { v = n; n = (ci>>22) & 0x3ff; }
3505
v += errv[1]+((7*errc[1])>>4)-1023;
3506
if(v < -511) v = -511;
3507
errv[1-(step<<2)] += ((3*v+8)>>4); /* 3/16 */
3508
errv[1] = ((5*v+errc[1]+8)>>4);/* 5/16 +1/16 (rest) */
3511
if(mode == 0) v = k;
3514
v += errv[0]+((7*errc[0])>>4)-1023;
3515
if(v < -511) v = -511;
3516
errv[0-(step<<2)] += ((3*v+8)>>4); /* 3/16 */
3517
errv[0] = ((5*v+errc[0]+8)>>4);/* 5/16 +1/16 (rest) */
3520
} else { /* Black does not fire initially */
3522
long kv = v; /* Black computed after colors */
3524
n = (ci>>12) & 0x3ff;
3526
if(mode == 2) { v = k; }
3527
else { v = n; n = (ci>>22) & 0x3ff; }
3529
v += errv[2]+((7*errc[2])>>4);
3534
errv[2-(step<<2)] += ((3*v+8)>>4); /* 3/16 */
3535
errv[2] = ((5*v+errc[2]+8)>>4);/* 5/16 +1/16 (rest) */
3538
if(mode == 1) { v = k; }
3539
else { v = n; n = (ci>>22) & 0x3ff; }
3541
v += errv[1]+((7*errc[1])>>4);
3546
errv[1-(step<<2)] += ((3*v+8)>>4); /* 3/16 */
3547
errv[1] = ((5*v+errc[1]+8)>>4);/* 5/16 +1/16 (rest) */
3550
if(mode == 0) v = k;
3553
v += errv[0]+((7*errc[0])>>4);
3558
errv[0-(step<<2)] += ((3*v+8)>>4); /* 3/16 */
3559
errv[0] = ((5*v+errc[0]+8)>>4);/* 5/16 +1/16 (rest) */
3563
if(pixel == (CYAN|MAGENTA|YELLOW)) {
3565
v = v > 511 ? v-1023 : -511;
3567
errv[3-(step<<2)] += ((3*v+8)>>4); /* 3/16 */
3568
errv[3] = ((5*v+errc[3]+8)>>4);/* 5/16 +1/16 (rest) */
3574
*out = pixel; out += step;
3576
} /* loop over pixels */
3578
/* ============================================================= */
3579
} /* initialisation, white or scanline-processing */
3580
/* ============================================================= */