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