Subversion Repositories planix.SVN

Rev

Details | Last modification | View Log | RSS feed

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