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