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