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