~ubuntu-branches/ubuntu/jaunty/ghostscript/jaunty-updates

« back to all changes in this revision

Viewing changes to src/gdevstc.c

  • Committer: Bazaar Package Importer
  • Author(s): Till Kamppeter
  • Date: 2009-01-20 16:40:45 UTC
  • mfrom: (1.1.10 upstream)
  • Revision ID: james.westby@ubuntu.com-20090120164045-lnfhi0n30o5lwhwa
Tags: 8.64.dfsg.1~svn9377-0ubuntu1
* New upstream release (SVN rev 9377)
   o Fixes many bugs concerning PDF rendering, to make the PDF printing
     workflow correctly working.
   o Fixes long-standing bugs in many drivers, like input paper tray and
     duplex options not working for the built-in PCL 4, 5, 5c, 5e, and
     6/XL drivers, PDF input not working for bjc600, bjc800, and cups
     output devices, several options not working and uninitialized
     memory with cups output device.
   o Merged nearly all patches of the Ubuntu and Debian packages upstream.
   o Fixes LP: #317810, LP: #314439, LP: #314018.
* debian/patches/03_libpaper_support.dpatch,
  debian/patches/11_gs-cjk_font_glyph_handling_fix.dpatch,
  debian/patches/12_gs-cjk_vertical_writing_metrics_fix.dpatch,
  debian/patches/13_gs-cjk_cjkps_examples.dpatch,
  debian/patches/20_bbox_segv_fix.dpatch,
  debian/patches/21_brother_7x0_gdi_fix.dpatch,
  debian/patches/22_epsn_margin_workaround.dpatch,
  debian/patches/24_gs_man_fix.dpatch,
  debian/patches/25_toolbin_insecure_tmp_usage_fix.dpatch,
  debian/patches/26_assorted_script_fixes.dpatch,
  debian/patches/29_gs_css_fix.dpatch,
  debian/patches/30_ps2pdf_man_improvement.dpatch,
  debian/patches/31_fix-gc-sigbus.dpatch,
  debian/patches/34_ftbfs-on-hurd-fix.dpatch,
  debian/patches/35_disable_libcairo.dpatch,
  debian/patches/38_pxl-duplex.dpatch,
  debian/patches/39_pxl-resolution.dpatch,
  debian/patches/42_gs-init-ps-delaybind-fix.dpatch,
  debian/patches/45_bjc600-bjc800-pdf-input.dpatch,
  debian/patches/48_cups-output-device-pdf-duplex-uninitialized-memory-fix.dpatch,
  debian/patches/50_lips4-floating-point-exception.dpatch,
  debian/patches/52_cups-device-logging.dpatch,
  debian/patches/55_pcl-input-slot-fix.dpatch,
  debian/patches/57_pxl-input-slot-fix.dpatch,
  debian/patches/60_pxl-cups-driver-pdf.dpatch,
  debian/patches/62_onebitcmyk-pdf.dpatch,
  debian/patches/65_too-big-temp-files-1.dpatch,
  debian/patches/67_too-big-temp-files-2.dpatch,
  debian/patches/70_take-into-account-data-in-stream-buffer-before-refill.dpatch:
  Removed, applied upstream.
* debian/patches/01_docdir_fix_for_debian.dpatch,
  debian/patches/02_gs_man_fix_debian.dpatch,
  debian/patches/01_docdir-fix-for-debian.dpatch,
  debian/patches/02_docdir-fix-for-debian.dpatch: Renamed patches to
  make merging with Debian easier.
* debian/patches/32_improve-handling-of-media-size-changes-from-gv.dpatch, 
  debian/patches/33_bad-params-to-xinitimage-on-large-bitmaps.dpatch:
  regenerated for new source directory structure.
* debian/rules: Corrected paths to remove cidfmap (it is in Resource/Init/
  in GS 8.64) and to install headers (source paths are psi/ and base/ now).
* debian/rules: Remove all fontmaps, as DeFoMa replaces them.
* debian/local/pdftoraster/pdftoraster.c,
  debian/local/pdftoraster/pdftoraster.convs, debian/rules: Removed
  added pdftoraster filter and use the one which comes with Ghostscript.
* debian/ghostscript.links: s/8.63/8.64/

Show diffs side-by-side

added added

removed removed

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