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