xref: /plan9-contrib/sys/src/cmd/gs/src/gdevstc.c (revision 593dc095aefb2a85c828727bbfa9da139a49bdf4)
17dd7cddfSDavid du Colombier /* Copyright (C) 1995, 1996 Aladdin Enterprises.  All rights reserved.
27dd7cddfSDavid du Colombier 
3*593dc095SDavid du Colombier   This software is provided AS-IS with no warranty, either express or
4*593dc095SDavid du Colombier   implied.
57dd7cddfSDavid du Colombier 
6*593dc095SDavid du Colombier   This software is distributed under license and may not be copied,
7*593dc095SDavid du Colombier   modified or distributed except as expressly authorized under the terms
8*593dc095SDavid du Colombier   of the license contained in the file LICENSE in this distribution.
93ff48bf5SDavid du Colombier 
10*593dc095SDavid du Colombier   For more information about licensing, please refer to
11*593dc095SDavid du Colombier   http://www.ghostscript.com/licensing/. For information on
12*593dc095SDavid du Colombier   commercial licensing, go to http://www.artifex.com/licensing/ or
13*593dc095SDavid du Colombier   contact Artifex Software, Inc., 101 Lucas Valley Road #110,
14*593dc095SDavid du Colombier   San Rafael, CA  94903, U.S.A., +1(415)492-9861.
157dd7cddfSDavid du Colombier */
167dd7cddfSDavid du Colombier 
17*593dc095SDavid du Colombier /* $Id: gdevstc.c,v 1.11 2004/11/22 19:25:57 giles Exp $*/
187dd7cddfSDavid du Colombier /* Epson Stylus-Color Printer-Driver */
197dd7cddfSDavid du Colombier 
207dd7cddfSDavid du Colombier /***
217dd7cddfSDavid du Colombier  *** This file was "copied" from gdevcdj.c (ghostscript-3.12), which was
227dd7cddfSDavid du Colombier  *** contributed by:
237dd7cddfSDavid du Colombier  ***    George Cameron      - g.cameron@biomed.abdn.ac.ukis
247dd7cddfSDavid du Colombier  ***    Koert Zeilstra      - koert@zen.cais.com
257dd7cddfSDavid du Colombier  ***    Eckhard Rueggeberg  - eckhard@ts.go.dlr.de
267dd7cddfSDavid du Colombier  ***
277dd7cddfSDavid du Colombier  *** Some of the ESC/P2-code was drawn from gdevescp.c, contributed by
287dd7cddfSDavid du Colombier  ***    Richard Brown       - rab@eos.ncsu.edu
297dd7cddfSDavid du Colombier  ***
307dd7cddfSDavid du Colombier  *** The POSIX-Interrupt-Code is from (Compile-Time-Option -DSTC_SIGNAL)
317dd7cddfSDavid du Colombier  ***    Frederic Loyer      - loyer@ensta.fr
327dd7cddfSDavid du Colombier  ***
337dd7cddfSDavid du Colombier  *** And several improvements are based on discussions with
347dd7cddfSDavid du Colombier  ***    Brian Converse      - BCONVERSE@ids.net
357dd7cddfSDavid du Colombier  ***    Bill Davidson       - bdavidson@ra.isisnet.com
367dd7cddfSDavid du Colombier  ***    Gero Guenther       - gero@cs.tu-berlin.de
377dd7cddfSDavid du Colombier  ***    Jason Patterson     - jason@reflections.com.au
387dd7cddfSDavid du Colombier  ***    ? Rueschstroer      - rue@ibe.med.uni-muenchen.de
397dd7cddfSDavid du Colombier  ***    Steven Singer       - S.Singer@ph.surrey.ac.uk
407dd7cddfSDavid du Colombier  ***
417dd7cddfSDavid du Colombier  *** And the remaining little rest, mainly the bugs, were written by me:
427dd7cddfSDavid du Colombier  *** Gunther Hess           - gunther@elmos.de
437dd7cddfSDavid du Colombier  ***
447dd7cddfSDavid du Colombier  *** P.S.: there is some documentation, see devices.doc
457dd7cddfSDavid du Colombier  ***
467dd7cddfSDavid du Colombier  *** Revision-History:
477dd7cddfSDavid du Colombier  *** 16-DEC-1994  1.1  - initial Version (GS-Dithering & Plain-Write)
487dd7cddfSDavid du Colombier      ...
497dd7cddfSDavid du Colombier  *** 30-JAN-1995  1.11 - FS-Improvements, u/sWeave, 1/4/24-Bits
507dd7cddfSDavid du Colombier  ***  5-MAR-1995  1.12 - L. Peter Deutsch - updated put_params routine
517dd7cddfSDavid du Colombier                          (first distributed version with gs3.33)
527dd7cddfSDavid du Colombier  *** 26-APR-1995  1.13 - merged Peters fixes with algorithmic changes:
537dd7cddfSDavid du Colombier                          Changed 24Bit-Mode, added 32Bit-Mode (moves colors)
547dd7cddfSDavid du Colombier                          [Arrgh: much better than 1.12, but patch was lost]
557dd7cddfSDavid du Colombier  ***  5-JUN-1995  1.14 - Added Color-Correction & Transfer-Curves
567dd7cddfSDavid du Colombier                          (Several Beta-Testers, but not distributed)
577dd7cddfSDavid du Colombier      ...
587dd7cddfSDavid du Colombier  *** 24-JUL-1995  1.16 - Made dithering-Algorithms external-functions.
597dd7cddfSDavid du Colombier                          (Mailed for Beta-Distribution)
607dd7cddfSDavid du Colombier  *** 10-AUG-1995  1.17 - Several Bug-Fixes and some new features:
617dd7cddfSDavid du Colombier                          CMYK10-Coding added
627dd7cddfSDavid du Colombier                          Readonly Parameters added
637dd7cddfSDavid du Colombier                           "Algorithms", "BitsPerComponent", "Version"
647dd7cddfSDavid du Colombier                          Parameters Flag0-4, Model, OutputCode
657dd7cddfSDavid du Colombier                          (mailed for distribution)
667dd7cddfSDavid du Colombier  *** 14-SEP-1995  1.18   Fixes Bugs with Borland C (gs3.47)
677dd7cddfSDavid du Colombier  *** 23-SEP-1995  1.19 - reorganized printcode + bug-fixing
687dd7cddfSDavid du Colombier  *** 24-SEP-1995  1.20 - Little Cleanup for the release
697dd7cddfSDavid du Colombier  *** 25-SEP-1995  1.21 - Readonly-Parameters added to put_params.
707dd7cddfSDavid du Colombier  *** 31-Dec-1995  1.22 - Sanitary Engineering on the code
717dd7cddfSDavid du Colombier  *** 16-Jan-1996  1.23 - Added String escp_Release
727dd7cddfSDavid du Colombier  ***  8-May-1996  1.90 - Reintroduced Deltarow & Fixed MEMORY-BUG!
737dd7cddfSDavid du Colombier  ***/
747dd7cddfSDavid du Colombier 
757dd7cddfSDavid du Colombier #include "gdevstc.h"
767dd7cddfSDavid du Colombier #ifdef    STC_SIGNAL
777dd7cddfSDavid du Colombier #  include <signal.h>
787dd7cddfSDavid du Colombier #endif /* STC_SIGNAL */
797dd7cddfSDavid du Colombier /***
807dd7cddfSDavid du Colombier  *** Mode-Table - the various algorithms
817dd7cddfSDavid du Colombier  *** (The intention is, that this source can live alone)
827dd7cddfSDavid du Colombier  ***/
837dd7cddfSDavid du Colombier 
847dd7cddfSDavid du Colombier private stc_proc_dither(stc_gscmyk);   /* resides in this file */
857dd7cddfSDavid du Colombier private stc_proc_dither(stc_hscmyk);   /* resides in this file */
867dd7cddfSDavid du Colombier 
877dd7cddfSDavid du Colombier #include <stdlib.h> /* for rand, used in stc_hscmyk */
887dd7cddfSDavid du Colombier 
897dd7cddfSDavid du Colombier private const stc_dither_t stc_dither[] = {
907dd7cddfSDavid du Colombier   {"gscmyk", stc_gscmyk, DeviceCMYK|STC_BYTE|STC_DIRECT,0,{0.0,1.0}},
917dd7cddfSDavid du Colombier   {"hscmyk", stc_hscmyk,
927dd7cddfSDavid du Colombier   DeviceCMYK|STC_LONG|STC_CMYK10|STC_DIRECT|1*STC_SCAN,1+2*4,
937dd7cddfSDavid du Colombier                                                   {0.0,    1023.0}},
947dd7cddfSDavid du Colombier   STC_MODI
957dd7cddfSDavid du Colombier   { NULL   , NULL      , 0,                  0,{0.0,0.0}}
967dd7cddfSDavid du Colombier };
977dd7cddfSDavid du Colombier 
987dd7cddfSDavid du Colombier /***
997dd7cddfSDavid du Colombier  ***  forward-declarations of routines
1007dd7cddfSDavid du Colombier  ***/
1017dd7cddfSDavid du Colombier 
1027dd7cddfSDavid du Colombier /* Primary Device functions
1037dd7cddfSDavid du Colombier  * (I've the idea to rename the driver to stc)
1047dd7cddfSDavid du Colombier  */
1057dd7cddfSDavid du Colombier private dev_proc_print_page(stc_print_page);
1067dd7cddfSDavid du Colombier private dev_proc_open_device(stc_open);
1077dd7cddfSDavid du Colombier private dev_proc_close_device(stc_close);
1087dd7cddfSDavid du Colombier private dev_proc_get_params(stc_get_params);
1097dd7cddfSDavid du Colombier private dev_proc_put_params(stc_put_params);
1107dd7cddfSDavid du Colombier 
1117dd7cddfSDavid du Colombier /*
1127dd7cddfSDavid du Colombier  * Color-Mapping-functions.
1137dd7cddfSDavid du Colombier  */
1147dd7cddfSDavid du Colombier 
1157dd7cddfSDavid du Colombier /* routines for monochrome monochrome modi */
1167dd7cddfSDavid du Colombier private dev_proc_map_rgb_color(stc_map_gray_color);
1177dd7cddfSDavid du Colombier private dev_proc_map_color_rgb(stc_map_color_gray);
1187dd7cddfSDavid du Colombier 
1197dd7cddfSDavid du Colombier /* routines for RGB-Modi */
1207dd7cddfSDavid du Colombier private dev_proc_map_rgb_color(stc_map_rgb_color);
1217dd7cddfSDavid du Colombier private dev_proc_map_color_rgb(stc_map_color_rgb);
1227dd7cddfSDavid du Colombier 
1237dd7cddfSDavid du Colombier /* routines for general CMYK-Modi */
1247dd7cddfSDavid du Colombier private dev_proc_map_cmyk_color(stc_map_cmyk_color);
1257dd7cddfSDavid du Colombier private dev_proc_map_color_rgb(stc_map_color_cmyk);
1267dd7cddfSDavid du Colombier 
1277dd7cddfSDavid du Colombier /* routines for 10Bit/Component CMYK */
1287dd7cddfSDavid du Colombier private dev_proc_map_cmyk_color(stc_map_cmyk10_color);
1297dd7cddfSDavid du Colombier private dev_proc_map_color_rgb(stc_map_color_cmyk10);
1307dd7cddfSDavid du Colombier 
1317dd7cddfSDavid du Colombier /***
1327dd7cddfSDavid du Colombier  *** Table of Device-Procedures
1337dd7cddfSDavid du Colombier  ***/
1347dd7cddfSDavid du Colombier private gx_device_procs stcolor_procs = {
1357dd7cddfSDavid du Colombier         stc_open,
1367dd7cddfSDavid du Colombier         gx_default_get_initial_matrix,
1377dd7cddfSDavid du Colombier         gx_default_sync_output,
1387dd7cddfSDavid du Colombier         gdev_prn_output_page,
1397dd7cddfSDavid du Colombier         stc_close,
1407dd7cddfSDavid du Colombier         NULL,
1417dd7cddfSDavid du Colombier         stc_map_color_cmyk,
1427dd7cddfSDavid du Colombier         NULL,   /* fill_rectangle */
1437dd7cddfSDavid du Colombier         NULL,   /* tile_rectangle */
1447dd7cddfSDavid du Colombier         NULL,   /* copy_mono */
1457dd7cddfSDavid du Colombier         NULL,   /* copy_color */
1467dd7cddfSDavid du Colombier         NULL,   /* draw_line */
1477dd7cddfSDavid du Colombier         gx_default_get_bits,
1487dd7cddfSDavid du Colombier         stc_get_params,
1497dd7cddfSDavid du Colombier         stc_put_params,
1507dd7cddfSDavid du Colombier         stc_map_cmyk_color
1517dd7cddfSDavid du Colombier };
1527dd7cddfSDavid du Colombier 
1537dd7cddfSDavid du Colombier /***
1547dd7cddfSDavid du Colombier  *** A local dummy-array for extvals
1557dd7cddfSDavid du Colombier  ***/
1567dd7cddfSDavid du Colombier 
1577dd7cddfSDavid du Colombier private float defext[] = { 0.0, 1.0 };
1587dd7cddfSDavid du Colombier 
1597dd7cddfSDavid du Colombier /***
1607dd7cddfSDavid du Colombier  *** Main device-control structure
1617dd7cddfSDavid du Colombier  ***/
1627dd7cddfSDavid du Colombier stcolor_device far_data gs_stcolor_device = {
1637dd7cddfSDavid du Colombier    prn_device_body(stcolor_device, stcolor_procs, "stcolor",
1647dd7cddfSDavid du Colombier       DEFAULT_WIDTH_10THS, DEFAULT_HEIGHT_10THS,
1657dd7cddfSDavid du Colombier       X_DPI,  Y_DPI,
1667dd7cddfSDavid du Colombier       STC_L_MARGIN,STC_B_MARGIN,STC_R_MARGIN,STC_T_MARGIN,
1677dd7cddfSDavid du Colombier       4,  4, 1, 1, 2, 2,            /* default: cmyk-direct */
1687dd7cddfSDavid du Colombier       stc_print_page),
1697dd7cddfSDavid du Colombier      {STCNWEAVE,                    /* stcflags:  noWeave/bidirectional */
1707dd7cddfSDavid du Colombier       1,                            /* stcbits:   matches the default */
1717dd7cddfSDavid du Colombier       stc_dither,                   /* stcdither: first algorithm */
1727dd7cddfSDavid du Colombier       NULL,                         /* stcam:     NULL -> not used */
1737dd7cddfSDavid du Colombier       { NULL, NULL, NULL, NULL},    /* extcode:   none defined yet */
1747dd7cddfSDavid du Colombier       {    0,    0,    0,    0},    /* sizcode:   0, since no extcode yet */
1757dd7cddfSDavid du Colombier       { NULL, NULL, NULL, NULL},    /* stccode:   computed by put_params */
1767dd7cddfSDavid du Colombier       {defext,defext,defext,defext},/* extvals:   default */
1777dd7cddfSDavid du Colombier       {    2,    2,    2,    2},    /* sizvals:   default countof(defext) */
1787dd7cddfSDavid du Colombier       { NULL, NULL, NULL, NULL},    /* stcvals:   computed by put_params */
1797dd7cddfSDavid du Colombier       {    0,    0,    0},          /* white-run */
1807dd7cddfSDavid du Colombier       {    0,    0,    0},          /* white-end */
1817dd7cddfSDavid du Colombier       {NULL,0,false},               /* algorithm-table */
1827dd7cddfSDavid du Colombier       {NULL,0,false},               /* initialization-String (BOP) */
1837dd7cddfSDavid du Colombier       {NULL,0,false},               /* release-String (EOP) */
1847dd7cddfSDavid du Colombier       0,0,0,0,                      /* New escp-stuff */
1857dd7cddfSDavid du Colombier       1}                            /* itemsize used by algorithm */
1867dd7cddfSDavid du Colombier };
1877dd7cddfSDavid du Colombier /***
1887dd7cddfSDavid du Colombier  *** Test for white scan-lines
1897dd7cddfSDavid du Colombier  ***/
190*593dc095SDavid du Colombier private bool stc_iswhite(stcolor_device *, int, byte *);
1917dd7cddfSDavid du Colombier 
1927dd7cddfSDavid du Colombier /***
1937dd7cddfSDavid du Colombier  *** Functions used for conversion inside the print-loop
1947dd7cddfSDavid du Colombier  ***/
1957dd7cddfSDavid du Colombier #define stc_proc_iconvert(Name) \
196*593dc095SDavid du Colombier byte * Name(stcolor_device *sd,byte *ext_data,int prt_pixels,byte *alg_line)
1977dd7cddfSDavid du Colombier 
1987dd7cddfSDavid du Colombier private stc_proc_iconvert(stc_any_depth);    /* general input-conversion */
1997dd7cddfSDavid du Colombier private stc_proc_iconvert(stc_rgb24_long);   /* 24Bit RGB  -> long's */
2007dd7cddfSDavid du Colombier 
2017dd7cddfSDavid du Colombier private stc_proc_iconvert(stc_cmyk32_long);  /* 32Bit CMYK -> long's */
2027dd7cddfSDavid du Colombier private stc_proc_iconvert(stc_any_direct);   /* use ext_data as input */
2037dd7cddfSDavid du Colombier 
2047dd7cddfSDavid du Colombier private stc_proc_iconvert(stc_cmyk10_byte);  /* CMYK10->vals-> any type */
2057dd7cddfSDavid du Colombier private stc_proc_iconvert(stc_cmyk10_long);  /* CMYK10->vals-> any type */
2067dd7cddfSDavid du Colombier private stc_proc_iconvert(stc_cmyk10_float); /* CMYK10->vals-> any type */
2077dd7cddfSDavid du Colombier private stc_proc_iconvert(stc_cmyk10_dbyte); /* CMYK10 direct bytes */
2087dd7cddfSDavid du Colombier private stc_proc_iconvert(stc_cmyk10_dlong); /* CMYK10 direct longs */
2097dd7cddfSDavid du Colombier 
2107dd7cddfSDavid du Colombier /***
2117dd7cddfSDavid du Colombier  *** Print-functions
2127dd7cddfSDavid du Colombier  ***/
213*593dc095SDavid du Colombier private void stc_print_weave(stcolor_device *sd,FILE *prn_stream);
214*593dc095SDavid du Colombier private void stc_print_bands(stcolor_device *sd,FILE *prn_stream);
215*593dc095SDavid du Colombier private void stc_print_delta(stcolor_device *sd,FILE *prn_stream);
216*593dc095SDavid du Colombier private int  stc_print_setup(stcolor_device *sd);
2177dd7cddfSDavid du Colombier 
2187dd7cddfSDavid du Colombier /***
2197dd7cddfSDavid du Colombier  *** compute the ESC/P2 specific values
2207dd7cddfSDavid du Colombier  ***/
2217dd7cddfSDavid du Colombier 
2227dd7cddfSDavid du Colombier private int
stc_print_setup(stcolor_device * sd)2237dd7cddfSDavid du Colombier stc_print_setup(stcolor_device *sd)
2247dd7cddfSDavid du Colombier {
2257dd7cddfSDavid du Colombier 
2267dd7cddfSDavid du Colombier /*
2277dd7cddfSDavid du Colombier  * Compute the resolution-parameters
2287dd7cddfSDavid du Colombier  */
229*593dc095SDavid du Colombier    sd->stc.escp_u = (int)(3600.0 / sd->y_pixels_per_inch); /* y-units */
230*593dc095SDavid du Colombier    sd->stc.escp_h = (int)(3600.0 / sd->x_pixels_per_inch); /* x-units */
2317dd7cddfSDavid du Colombier    sd->stc.escp_v = sd->stc.flags & (STCUWEAVE | STCNWEAVE) ?
2327dd7cddfSDavid du Colombier                     sd->stc.escp_u : 40;
2337dd7cddfSDavid du Colombier /*
2347dd7cddfSDavid du Colombier  * Initialize color
2357dd7cddfSDavid du Colombier  */
2367dd7cddfSDavid du Colombier    sd->stc.escp_c = 0; /* preselect-black */
2377dd7cddfSDavid du Colombier 
2387dd7cddfSDavid du Colombier /*
2397dd7cddfSDavid du Colombier  * Band-Width
2407dd7cddfSDavid du Colombier  */
2417dd7cddfSDavid du Colombier    if((sd->stc.flags & STCBAND) == 0) {
2427dd7cddfSDavid du Colombier       if(sd->stc.escp_v != sd->stc.escp_u)            sd->stc.escp_m = 15;
2437dd7cddfSDavid du Colombier       else if(STCSTCII == (sd->stc.flags & STCMODEL)) sd->stc.escp_m =  1;
2447dd7cddfSDavid du Colombier       else if(  sd->stc.flags & STCUWEAVE)            sd->stc.escp_m =  1;
2457dd7cddfSDavid du Colombier       else if((sd->stc.escp_v == sd->stc.escp_u) &&
2467dd7cddfSDavid du Colombier               (sd->stc.escp_u == 5))                  sd->stc.escp_m =  1;
2477dd7cddfSDavid du Colombier       else                                            sd->stc.escp_m =  1;
2487dd7cddfSDavid du Colombier    }
2497dd7cddfSDavid du Colombier 
2507dd7cddfSDavid du Colombier /*
2517dd7cddfSDavid du Colombier  * Page-Dimensions
2527dd7cddfSDavid du Colombier  */
2537dd7cddfSDavid du Colombier    if((sd->stc.flags & STCWIDTH ) == 0)
254*593dc095SDavid du Colombier        sd->stc.escp_width = (int)(sd->width -
255*593dc095SDavid du Colombier            (dev_l_margin(sd)+dev_r_margin(sd))*sd->x_pixels_per_inch);
2567dd7cddfSDavid du Colombier 
2577dd7cddfSDavid du Colombier    if((sd->stc.flags & STCHEIGHT) == 0)
2587dd7cddfSDavid du Colombier        sd->stc.escp_height = sd->height;
2597dd7cddfSDavid du Colombier 
2607dd7cddfSDavid du Colombier    if((sd->stc.flags & STCTOP) == 0)
261*593dc095SDavid du Colombier        sd->stc.escp_top = (int)(dev_t_margin(sd)*sd->y_pixels_per_inch);
2627dd7cddfSDavid du Colombier 
2637dd7cddfSDavid du Colombier    if((sd->stc.flags & STCBOTTOM) == 0)
264*593dc095SDavid du Colombier       sd->stc.escp_bottom = (int)(sd->height -
265*593dc095SDavid du Colombier 	    dev_b_margin(sd)*sd->y_pixels_per_inch);
2667dd7cddfSDavid du Colombier 
2677dd7cddfSDavid du Colombier    if((sd->stc.flags & STCINIT) == 0) { /* No Initialization-String defined */
2687dd7cddfSDavid du Colombier       int need  = 8  /* Reset, Graphics-Mode 1 */
2697dd7cddfSDavid du Colombier                 + 6  /* MicroWeave */
2707dd7cddfSDavid du Colombier                 + 6  /* Select Units */
2717dd7cddfSDavid du Colombier                 + 7  /* Set Page-Length */
2727dd7cddfSDavid du Colombier                 + 9  /* Set Margins */
2737dd7cddfSDavid du Colombier                 + 3; /* Select Unidirectionality */
2747dd7cddfSDavid du Colombier       byte *bp  = (byte *) (sd->stc.escp_init.data);
2757dd7cddfSDavid du Colombier 
2767dd7cddfSDavid du Colombier       if(need != sd->stc.escp_init.size) {  /* Reallocate */
2777dd7cddfSDavid du Colombier 
278*593dc095SDavid du Colombier          if(NULL != (bp = gs_malloc(sd->memory, need,1,"stcolor/init"))) { /* Replace */
2797dd7cddfSDavid du Colombier             if(0 != sd->stc.escp_init.size)
280*593dc095SDavid du Colombier                gs_free(sd->memory, (byte *)sd->stc.escp_init.data,sd->stc.escp_init.size,1,
2817dd7cddfSDavid du Colombier                        "stcolor/init");
2827dd7cddfSDavid du Colombier             sd->stc.escp_init.data       = bp;
2837dd7cddfSDavid du Colombier             sd->stc.escp_init.size       = need;
2847dd7cddfSDavid du Colombier             sd->stc.escp_init.persistent = false;
2857dd7cddfSDavid du Colombier          }  else {                                             /* Replace */
2867dd7cddfSDavid du Colombier              return_error(gs_error_VMerror);
2877dd7cddfSDavid du Colombier          }
2887dd7cddfSDavid du Colombier       }
2897dd7cddfSDavid du Colombier 
2907dd7cddfSDavid du Colombier       if(need != 39) return_error(gs_error_unregistered);
2917dd7cddfSDavid du Colombier 
2927dd7cddfSDavid du Colombier       memcpy(bp,
2937dd7cddfSDavid du Colombier /*                       1 1 11  1 11  1   1 1  2 22 2  2 22  2 22 3  3 3333  3 33*/
2947dd7cddfSDavid du Colombier /* 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*/
2957dd7cddfSDavid du Colombier "\033@\033(G\001\0\1\033(i\1\0w\033(U\001\000u\033(C\2\000hh\033(c\4\000ttbb\033U",
2967dd7cddfSDavid du Colombier              need);
2977dd7cddfSDavid du Colombier 
2987dd7cddfSDavid du Colombier 
2997dd7cddfSDavid du Colombier       if((sd->stc.flags & STCUWEAVE) != 0) bp[13] = '\1';
3007dd7cddfSDavid du Colombier       else                                 bp[13] = '\0';
3017dd7cddfSDavid du Colombier 
3027dd7cddfSDavid du Colombier       bp[19] =  sd->stc.escp_u;
3037dd7cddfSDavid du Colombier 
3047dd7cddfSDavid du Colombier       bp[25] =  sd->stc.escp_height     & 0xff;
3057dd7cddfSDavid du Colombier       bp[26] = (sd->stc.escp_height>>8) & 0xff;
3067dd7cddfSDavid du Colombier 
3077dd7cddfSDavid du Colombier       bp[32] =  sd->stc.escp_top        & 0xff;
3087dd7cddfSDavid du Colombier       bp[33] = (sd->stc.escp_top>>8)    & 0xff;
3097dd7cddfSDavid du Colombier       bp[34] =  sd->stc.escp_bottom     & 0xff;
3107dd7cddfSDavid du Colombier       bp[35] = (sd->stc.escp_bottom>>8) & 0xff;
3117dd7cddfSDavid du Colombier 
3127dd7cddfSDavid du Colombier       if(sd->stc.flags & STCUNIDIR)        bp[38] = 1;
3137dd7cddfSDavid du Colombier       else                                 bp[38] = 0;
3147dd7cddfSDavid du Colombier 
3157dd7cddfSDavid du Colombier    }                                    /* No Initialization-String defined */
3167dd7cddfSDavid du Colombier 
3177dd7cddfSDavid du Colombier    if((sd->stc.flags & STCRELEASE) == 0) { /* No Release-String defined */
3187dd7cddfSDavid du Colombier       int need  = 3;  /* ESC @ \f */
3197dd7cddfSDavid du Colombier       byte *bp  = (byte *) (sd->stc.escp_release.data);
3207dd7cddfSDavid du Colombier 
3217dd7cddfSDavid du Colombier       if(need != sd->stc.escp_release.size) {  /* Reallocate */
3227dd7cddfSDavid du Colombier 
323*593dc095SDavid du Colombier          if(NULL != (bp = gs_malloc(sd->memory, need,1,"stcolor/release"))) { /* Replace */
3247dd7cddfSDavid du Colombier             if(0 != sd->stc.escp_release.size)
325*593dc095SDavid du Colombier                gs_free(sd->memory, (byte *)sd->stc.escp_release.data,sd->stc.escp_release.size,1,
3267dd7cddfSDavid du Colombier                        "stcolor/release");
3277dd7cddfSDavid du Colombier             sd->stc.escp_release.data       = bp;
3287dd7cddfSDavid du Colombier             sd->stc.escp_release.size       = need;
3297dd7cddfSDavid du Colombier             sd->stc.escp_release.persistent = false;
3307dd7cddfSDavid du Colombier          }  else {                                             /* Replace */
3317dd7cddfSDavid du Colombier              return_error(gs_error_VMerror);
3327dd7cddfSDavid du Colombier          }
3337dd7cddfSDavid du Colombier       }
3347dd7cddfSDavid du Colombier 
3357dd7cddfSDavid du Colombier       if(need != 3) return_error(gs_error_unregistered);
3367dd7cddfSDavid du Colombier 
3377dd7cddfSDavid du Colombier       memcpy(bp,"\033@\f",need);
3387dd7cddfSDavid du Colombier 
3397dd7cddfSDavid du Colombier    }                                    /* No Release-String defined */
3407dd7cddfSDavid du Colombier 
3417dd7cddfSDavid du Colombier    return 0;
3427dd7cddfSDavid du Colombier }
3437dd7cddfSDavid du Colombier 
3447dd7cddfSDavid du Colombier /***
3457dd7cddfSDavid du Colombier  *** stc_print_page: here we go to do the nasty work
3467dd7cddfSDavid du Colombier  ***/
3477dd7cddfSDavid du Colombier 
3487dd7cddfSDavid du Colombier private int
stc_print_page(gx_device_printer * pdev,FILE * prn_stream)3497dd7cddfSDavid du Colombier stc_print_page(gx_device_printer * pdev, FILE * prn_stream)
3507dd7cddfSDavid du Colombier {
3517dd7cddfSDavid du Colombier    stcolor_device *sd    = (stcolor_device *) pdev;
3527dd7cddfSDavid du Colombier    long            flags = sd == NULL ? 0 : sd->stc.flags;
3537dd7cddfSDavid du Colombier 
3547dd7cddfSDavid du Colombier    int  npass;           /* # of print-passes (softweave) */
3557dd7cddfSDavid du Colombier 
3567dd7cddfSDavid du Colombier    int    ext_size;      /* size of a ghostscript-scanline */
3577dd7cddfSDavid du Colombier    byte  *ext_line;      /* dyn: for this scanline */
3587dd7cddfSDavid du Colombier 
3597dd7cddfSDavid du Colombier    int    alg_size;      /* size of a scanline for the dithering-algorithm */
3607dd7cddfSDavid du Colombier    byte  *alg_line;      /* dyn: 1 scanline for the dithering-algorithm */
3617dd7cddfSDavid du Colombier    int    buf_size;      /* size of the private-buffer for dither-function */
3627dd7cddfSDavid du Colombier    byte  *buf;           /* dyn: the private buffer */
3637dd7cddfSDavid du Colombier 
3647dd7cddfSDavid du Colombier    int    prt_pixels;    /* Number of pixels printed */
3657dd7cddfSDavid du Colombier    byte  *col_line;      /* A Line with a byte per pixel */
3667dd7cddfSDavid du Colombier 
3677dd7cddfSDavid du Colombier #define OK4GO        ((flags &   STCOK4GO)              != 0)
3687dd7cddfSDavid du Colombier #define SORRY        ( flags &= ~STCOK4GO)
3697dd7cddfSDavid du Colombier 
3707dd7cddfSDavid du Colombier    if(0 > (npass = stc_print_setup(sd))) return_error(npass);
3717dd7cddfSDavid du Colombier 
3727dd7cddfSDavid du Colombier    npass = sd->stc.escp_v / sd->stc.escp_u;
3737dd7cddfSDavid du Colombier 
3747dd7cddfSDavid du Colombier /***
3757dd7cddfSDavid du Colombier  *** Allocate dynamic memory
3767dd7cddfSDavid du Colombier  ***/
3777dd7cddfSDavid du Colombier 
3787dd7cddfSDavid du Colombier    ext_size   = gdev_prn_raster(sd);
379*593dc095SDavid du Colombier    ext_line   = gs_malloc(sd->memory, ext_size,1,"stc_print_page/ext_line");
3807dd7cddfSDavid du Colombier    if(ext_line == NULL) SORRY;
3817dd7cddfSDavid du Colombier 
3827dd7cddfSDavid du Colombier    prt_pixels        = sd->stc.escp_width;
3837dd7cddfSDavid du Colombier    sd->stc.prt_size  = (prt_pixels+7)/8;
3847dd7cddfSDavid du Colombier    prt_pixels        =  sd->stc.prt_size * 8;
3857dd7cddfSDavid du Colombier 
386*593dc095SDavid du Colombier    sd->stc.prt_scans  = (int)(sd->height -
387*593dc095SDavid du Colombier       (dev_t_margin(sd)+dev_b_margin(sd))*sd->y_pixels_per_inch);
3887dd7cddfSDavid du Colombier 
389*593dc095SDavid du Colombier    col_line   = gs_malloc(sd->memory, prt_pixels,1,"stc_print_page/col_line");
3907dd7cddfSDavid du Colombier    if(col_line == NULL) SORRY;
3917dd7cddfSDavid du Colombier 
3927dd7cddfSDavid du Colombier    alg_size  = prt_pixels;
3937dd7cddfSDavid du Colombier    alg_size *= sd->color_info.num_components;
3947dd7cddfSDavid du Colombier 
3957dd7cddfSDavid du Colombier    if((sd->stc.dither->flags & STC_DIRECT) ||
3967dd7cddfSDavid du Colombier       ((sd->stc.bits                 == 8) &&
3977dd7cddfSDavid du Colombier        (sd->stc.alg_item                     == 1)))  {
3987dd7cddfSDavid du Colombier       alg_line = NULL;
3997dd7cddfSDavid du Colombier    } else {
400*593dc095SDavid du Colombier       alg_line = gs_malloc(sd->memory, alg_size,sd->stc.alg_item,"stc_print_page/alg_line");
4017dd7cddfSDavid du Colombier       if(alg_line == NULL) SORRY;
4027dd7cddfSDavid du Colombier    }
4037dd7cddfSDavid du Colombier 
4047dd7cddfSDavid du Colombier    buf_size = sd->stc.dither->bufadd
4057dd7cddfSDavid du Colombier             + alg_size*(sd->stc.dither->flags/STC_SCAN);
4067dd7cddfSDavid du Colombier    if(buf_size > 0) {
407*593dc095SDavid du Colombier       buf    = gs_malloc(sd->memory, buf_size,sd->stc.alg_item,"stc_print_page/buf");
4087dd7cddfSDavid du Colombier       if(buf == NULL) SORRY;
4097dd7cddfSDavid du Colombier    } else {
4107dd7cddfSDavid du Colombier       buf = NULL;
4117dd7cddfSDavid du Colombier    }
4127dd7cddfSDavid du Colombier 
4137dd7cddfSDavid du Colombier /*
4147dd7cddfSDavid du Colombier  * compute the number of printer-buffers
4157dd7cddfSDavid du Colombier  */
4167dd7cddfSDavid du Colombier 
4177dd7cddfSDavid du Colombier     for(sd->stc.prt_buf   = 16; sd->stc.prt_buf < (sd->stc.escp_m * npass);
4187dd7cddfSDavid du Colombier         sd->stc.prt_buf <<= 1);
4197dd7cddfSDavid du Colombier     if(sd->color_info.num_components > 1) sd->stc.prt_buf *= 4;
4207dd7cddfSDavid du Colombier 
421*593dc095SDavid du Colombier     sd->stc.prt_width = gs_malloc(sd->memory, sd->stc.prt_buf,sizeof(int),
4227dd7cddfSDavid du Colombier                         "stc_print_page/prt_width");
4237dd7cddfSDavid du Colombier     if(sd->stc.prt_width == NULL) SORRY;
4247dd7cddfSDavid du Colombier 
425*593dc095SDavid du Colombier     sd->stc.prt_data  = gs_malloc(sd->memory, sd->stc.prt_buf,sizeof(byte *),
4267dd7cddfSDavid du Colombier                         "stc_print_page/prt_data");
4277dd7cddfSDavid du Colombier 
4287dd7cddfSDavid du Colombier     if(sd->stc.prt_data == NULL) {
4297dd7cddfSDavid du Colombier        SORRY;
4307dd7cddfSDavid du Colombier     } else {
4317dd7cddfSDavid du Colombier        int i;
4327dd7cddfSDavid du Colombier 
4337dd7cddfSDavid du Colombier        for(i = 0; i < sd->stc.prt_buf; ++i) {
434*593dc095SDavid du Colombier           sd->stc.prt_data[i] = gs_malloc(sd->memory, sd->stc.prt_size,1,
4357dd7cddfSDavid du Colombier                                 "stc_print_page/prt");
4367dd7cddfSDavid du Colombier           if(sd->stc.prt_data[i] == NULL) SORRY;
4377dd7cddfSDavid du Colombier        }
4387dd7cddfSDavid du Colombier     }
4397dd7cddfSDavid du Colombier 
4407dd7cddfSDavid du Colombier     sd->stc.seed_size = (sd->stc.prt_size + 2*sizeof(int) - 1)/sizeof(int);
4417dd7cddfSDavid du Colombier     {
4427dd7cddfSDavid du Colombier        int i;
4437dd7cddfSDavid du Colombier        for(i = 0; i < sd->color_info.num_components; ++i) {
4447dd7cddfSDavid du Colombier           if((flags & STCCOMP) == STCDELTA) {
445*593dc095SDavid du Colombier              sd->stc.seed_row[i] = gs_malloc(sd->memory, sd->stc.seed_size,sizeof(int),
4467dd7cddfSDavid du Colombier                                    "stc_print_page/seed_row");
4477dd7cddfSDavid du Colombier              if(sd->stc.seed_row[i] == NULL) SORRY;
4487dd7cddfSDavid du Colombier              else memset(sd->stc.seed_row[i],0,sd->stc.seed_size*sizeof(int));
4497dd7cddfSDavid du Colombier           } else {
4507dd7cddfSDavid du Colombier              sd->stc.seed_row[i] = NULL;
4517dd7cddfSDavid du Colombier           }
4527dd7cddfSDavid du Colombier        }
4537dd7cddfSDavid du Colombier        while(i < countof(sd->stc.seed_row)) sd->stc.seed_row[i++] = NULL;
4547dd7cddfSDavid du Colombier     }
4557dd7cddfSDavid du Colombier 
4567dd7cddfSDavid du Colombier     switch(flags & STCCOMP) {
4577dd7cddfSDavid du Colombier        case STCPLAIN:
4587dd7cddfSDavid du Colombier           sd->stc.escp_size = 64 + sd->stc.prt_size;
4597dd7cddfSDavid du Colombier           break;
4607dd7cddfSDavid du Colombier        case STCDELTA:
4617dd7cddfSDavid du Colombier           sd->stc.escp_size = 64 + 2 * sd->stc.prt_size;
4627dd7cddfSDavid du Colombier           break;
4637dd7cddfSDavid du Colombier        default:
4647dd7cddfSDavid du Colombier           sd->stc.escp_size = 64 +
4657dd7cddfSDavid du Colombier                               sd->stc.prt_size + (sd->stc.prt_size + 127)/128;
4667dd7cddfSDavid du Colombier           break;
4677dd7cddfSDavid du Colombier     }
4687dd7cddfSDavid du Colombier 
469*593dc095SDavid du Colombier     sd->stc.escp_data = gs_malloc(sd->memory, sd->stc.escp_size,1,
4707dd7cddfSDavid du Colombier                                   "stc_print_page/escp_data");
4717dd7cddfSDavid du Colombier     if(sd->stc.escp_data == NULL) SORRY;
4727dd7cddfSDavid du Colombier 
4737dd7cddfSDavid du Colombier /*
4747dd7cddfSDavid du Colombier  * If we're still ok, we can print something
4757dd7cddfSDavid du Colombier  */
4767dd7cddfSDavid du Colombier 
4777dd7cddfSDavid du Colombier    if(OK4GO) {
4787dd7cddfSDavid du Colombier 
4797dd7cddfSDavid du Colombier       int ncolor;
4807dd7cddfSDavid du Colombier       int buf_i;
4817dd7cddfSDavid du Colombier       stc_proc_iconvert((*iconvert)) = stc_any_depth;
4827dd7cddfSDavid du Colombier 
4837dd7cddfSDavid du Colombier /*
4847dd7cddfSDavid du Colombier  * initialize col_line
4857dd7cddfSDavid du Colombier  */
4867dd7cddfSDavid du Colombier       if(sd->color_info.num_components == 3) {
4877dd7cddfSDavid du Colombier          memset(col_line,RED|GREEN|BLUE,prt_pixels);
4887dd7cddfSDavid du Colombier       } else {
4897dd7cddfSDavid du Colombier          memset(col_line,0,             prt_pixels);
4907dd7cddfSDavid du Colombier       }
4917dd7cddfSDavid du Colombier 
4927dd7cddfSDavid du Colombier /*
4937dd7cddfSDavid du Colombier  * select proper conversion for input to algorithm
4947dd7cddfSDavid du Colombier  */
4957dd7cddfSDavid du Colombier       if(     (sd->stc.dither->flags & STC_DIRECT ) ||
4967dd7cddfSDavid du Colombier               ((sd->stc.bits                 == 8) &&
4977dd7cddfSDavid du Colombier                (sd->stc.alg_item                     == 1)))
4987dd7cddfSDavid du Colombier          iconvert = stc_any_direct;
4997dd7cddfSDavid du Colombier       else if((sd->color_info.num_components ==  3) &&
5007dd7cddfSDavid du Colombier               (sd->color_info.depth          == 24) &&
5017dd7cddfSDavid du Colombier               (sizeof(long)                  == sd->stc.alg_item))
5027dd7cddfSDavid du Colombier          iconvert = stc_rgb24_long;
5037dd7cddfSDavid du Colombier       else if(sd->stc.flags & STCCMYK10) {
5047dd7cddfSDavid du Colombier          if(     ((sd->stc.dither->flags & STC_TYPE) == STC_BYTE) &&
5057dd7cddfSDavid du Colombier                  ( sd->stc.dither->minmax[0]         ==    0.0  ))
5067dd7cddfSDavid du Colombier             iconvert = stc_cmyk10_dbyte;
5077dd7cddfSDavid du Colombier          else if ((sd->stc.dither->flags & STC_TYPE) == STC_BYTE)
5087dd7cddfSDavid du Colombier             iconvert = stc_cmyk10_byte;
5097dd7cddfSDavid du Colombier          else if(((sd->stc.dither->flags & STC_TYPE) == STC_LONG) &&
5107dd7cddfSDavid du Colombier                  ( sd->stc.dither->minmax[0]         ==    0.0  ) &&
5117dd7cddfSDavid du Colombier                  ( sd->stc.dither->minmax[1]         <= 1023.0  ))
5127dd7cddfSDavid du Colombier             iconvert = stc_cmyk10_dlong;
5137dd7cddfSDavid du Colombier          else if( (sd->stc.dither->flags & STC_TYPE) == STC_LONG)
5147dd7cddfSDavid du Colombier             iconvert = stc_cmyk10_long;
5157dd7cddfSDavid du Colombier          else
5167dd7cddfSDavid du Colombier             iconvert = stc_cmyk10_float;
5177dd7cddfSDavid du Colombier       }
5187dd7cddfSDavid du Colombier       else if((sd->color_info.num_components ==  4) &&
5197dd7cddfSDavid du Colombier               (sd->color_info.depth          == 32) &&
5207dd7cddfSDavid du Colombier               (sizeof(long)                  == sd->stc.alg_item))
5217dd7cddfSDavid du Colombier          iconvert = stc_cmyk32_long;
5227dd7cddfSDavid du Colombier 
5237dd7cddfSDavid du Colombier /*
5247dd7cddfSDavid du Colombier  * initialize the algorithm
5257dd7cddfSDavid du Colombier  */
5267dd7cddfSDavid du Colombier 
5277dd7cddfSDavid du Colombier       if((*sd->stc.dither->fun)(sd,-prt_pixels,alg_line,buf,col_line) < 0)
5287dd7cddfSDavid du Colombier          SORRY;
5297dd7cddfSDavid du Colombier 
5307dd7cddfSDavid du Colombier /*
5317dd7cddfSDavid du Colombier  * Main-Print-Loop
5327dd7cddfSDavid du Colombier  */
5337dd7cddfSDavid du Colombier 
5347dd7cddfSDavid du Colombier       if(OK4GO) {
5357dd7cddfSDavid du Colombier #ifdef    STC_SIGNAL
5367dd7cddfSDavid du Colombier          sigset_t stc_int_mask, stc_int_save, stc_int_pending;
5377dd7cddfSDavid du Colombier 
5387dd7cddfSDavid du Colombier          sigemptyset(&stc_int_mask);
5397dd7cddfSDavid du Colombier          sigaddset(&stc_int_mask,SIGINT);
5407dd7cddfSDavid du Colombier          sigprocmask(SIG_BLOCK,&stc_int_mask, &stc_int_save);
5417dd7cddfSDavid du Colombier #endif /* STC_SIGNAL */
5427dd7cddfSDavid du Colombier 
5437dd7cddfSDavid du Colombier 
5447dd7cddfSDavid du Colombier          if(sd->color_info.num_components > 1) ncolor = 4;
5457dd7cddfSDavid du Colombier          else                                  ncolor = 1;
5467dd7cddfSDavid du Colombier 
5477dd7cddfSDavid du Colombier /*
5487dd7cddfSDavid du Colombier  * Decide, wether we Adjust Linefeeds or not. (I hate it here)
5497dd7cddfSDavid du Colombier  */
5507dd7cddfSDavid du Colombier          if((0   == ((sd->stc.escp_m*sd->stc.escp_u) % 10)) &&
5517dd7cddfSDavid du Colombier             (256  > ((sd->stc.escp_m*sd->stc.escp_u) / 10))) sd->stc.escp_lf = sd->stc.escp_m;
5527dd7cddfSDavid du Colombier          else                                                sd->stc.escp_lf = 0;
5537dd7cddfSDavid du Colombier 
5547dd7cddfSDavid du Colombier /*
5557dd7cddfSDavid du Colombier  * prepare run-values, then loop over scans
5567dd7cddfSDavid du Colombier  */
5577dd7cddfSDavid du Colombier          sd->stc.stc_y      =  0; /* current printer y-Position */
5587dd7cddfSDavid du Colombier          sd->stc.buf_y      =  0; /* Top-Position within the buffer */
5597dd7cddfSDavid du Colombier          sd->stc.prt_y      =  0; /* physical position of the printer */
5607dd7cddfSDavid du Colombier          buf_i              =  0; /* next free line in buffer */
5617dd7cddfSDavid du Colombier          sd->stc.flags     &= ~STCPRINT; /* no data yet */
5627dd7cddfSDavid du Colombier 
5637dd7cddfSDavid du Colombier          while(sd->stc.stc_y < sd->stc.prt_scans) {  /* Until all scans are processed */
5647dd7cddfSDavid du Colombier             int need;
5657dd7cddfSDavid du Colombier 
5667dd7cddfSDavid du Colombier             need = sd->stc.stc_y + npass * sd->stc.escp_m;
5677dd7cddfSDavid du Colombier 
5687dd7cddfSDavid du Colombier             if(sd->stc.buf_y < need) { /* Nr. 5 (give me input) */
5697dd7cddfSDavid du Colombier 
5707dd7cddfSDavid du Colombier /* read as much as the buffer can hold */
5717dd7cddfSDavid du Colombier                if(ncolor == 1) need = sd->stc.stc_y +  sd->stc.prt_buf;
5727dd7cddfSDavid du Colombier                else            need = sd->stc.stc_y + (sd->stc.prt_buf>>2);
5737dd7cddfSDavid du Colombier 
5747dd7cddfSDavid du Colombier                for(;sd->stc.buf_y < need;
5757dd7cddfSDavid du Colombier                     buf_i = (sd->stc.prt_buf-1) & (buf_i+ncolor),
5767dd7cddfSDavid du Colombier                     ++sd->stc.buf_y) {
5777dd7cddfSDavid du Colombier 
5787dd7cddfSDavid du Colombier                   int color;
5797dd7cddfSDavid du Colombier                   byte *ext_data;
5807dd7cddfSDavid du Colombier                   byte *alg_data;
5817dd7cddfSDavid du Colombier 
5827dd7cddfSDavid du Colombier /* initialize output data 1st -> may take shortcut */
5837dd7cddfSDavid du Colombier 
5847dd7cddfSDavid du Colombier                   for(color = 0; color < ncolor; ++color) {
5857dd7cddfSDavid du Colombier                      memset(sd->stc.prt_data[buf_i+color],0,sd->stc.prt_size);
5867dd7cddfSDavid du Colombier                      sd->stc.prt_width[buf_i+color] = 0;
5877dd7cddfSDavid du Colombier                   }
5887dd7cddfSDavid du Colombier 
5897dd7cddfSDavid du Colombier 
5907dd7cddfSDavid du Colombier /* "read data", immediately continue if all is white */
5917dd7cddfSDavid du Colombier 
5927dd7cddfSDavid du Colombier                   if(sd->stc.buf_y < sd->stc.prt_scans) {  /* Test for White */
5937dd7cddfSDavid du Colombier 
5947dd7cddfSDavid du Colombier                      gdev_prn_get_bits(pdev,sd->stc.buf_y,ext_line,&ext_data);
5957dd7cddfSDavid du Colombier 
5967dd7cddfSDavid du Colombier                      color = stc_iswhite(sd,prt_pixels,ext_data) ? ext_size : 0;
5977dd7cddfSDavid du Colombier 
5987dd7cddfSDavid du Colombier                   } else {
5997dd7cddfSDavid du Colombier 
6007dd7cddfSDavid du Colombier                      color = ext_size;
6017dd7cddfSDavid du Colombier 
6027dd7cddfSDavid du Colombier                   }                        /* Test for White */
6037dd7cddfSDavid du Colombier 
6047dd7cddfSDavid du Colombier                   if(color >= ext_size) {  /* bypass processing */
6057dd7cddfSDavid du Colombier 
6067dd7cddfSDavid du Colombier                      if(sd->stc.dither->flags & STC_WHITE)
6077dd7cddfSDavid du Colombier                         (*sd->stc.dither->fun)(sd,prt_pixels,NULL,buf,col_line);
6087dd7cddfSDavid du Colombier                      continue;
6097dd7cddfSDavid du Colombier 
6107dd7cddfSDavid du Colombier                   }                        /* bypass processing */
6117dd7cddfSDavid du Colombier 
6127dd7cddfSDavid du Colombier /* convert data for the various cases */
6137dd7cddfSDavid du Colombier 
6147dd7cddfSDavid du Colombier                   alg_data = (*iconvert)(sd,ext_data,prt_pixels,alg_line);
6157dd7cddfSDavid du Colombier 
6167dd7cddfSDavid du Colombier 
6177dd7cddfSDavid du Colombier /*
6187dd7cddfSDavid du Colombier  * invoke the dithering-algorithm
6197dd7cddfSDavid du Colombier  */
6207dd7cddfSDavid du Colombier 
6217dd7cddfSDavid du Colombier                   (*sd->stc.dither->fun)(sd,prt_pixels,alg_data,buf,col_line);
6227dd7cddfSDavid du Colombier /*
6237dd7cddfSDavid du Colombier  * convert col_line to printer-format (separate colors)
6247dd7cddfSDavid du Colombier  */
6257dd7cddfSDavid du Colombier                   switch(sd->color_info.num_components) {
6267dd7cddfSDavid du Colombier                   case 1: /* Black & White: just merge into 8 Bytes */
6277dd7cddfSDavid du Colombier                   {
6287dd7cddfSDavid du Colombier                       byte *bytein,*byteout;
6297dd7cddfSDavid du Colombier                       int   width;
6307dd7cddfSDavid du Colombier 
6317dd7cddfSDavid du Colombier                       bytein  = col_line;
6327dd7cddfSDavid du Colombier                       byteout = sd->stc.prt_data[buf_i];
6337dd7cddfSDavid du Colombier 
6347dd7cddfSDavid du Colombier                       for(width = 1; width <= sd->stc.prt_size; ++width) {
6357dd7cddfSDavid du Colombier                           byte tmp = 0;
6367dd7cddfSDavid du Colombier                           byte i;
6377dd7cddfSDavid du Colombier 
6387dd7cddfSDavid du Colombier                           for(i = 128; i; i >>= 1) if(*bytein++) tmp  |= i;
6397dd7cddfSDavid du Colombier 
6407dd7cddfSDavid du Colombier                           if(tmp != 0) sd->stc.prt_width[buf_i] = width;
6417dd7cddfSDavid du Colombier 
6427dd7cddfSDavid du Colombier                           *byteout++ = tmp;
6437dd7cddfSDavid du Colombier                       }
6447dd7cddfSDavid du Colombier                   }
6457dd7cddfSDavid du Colombier                   break;
6467dd7cddfSDavid du Colombier                   case 3: /* convert rgb into cmyk */
6477dd7cddfSDavid du Colombier                   {
6487dd7cddfSDavid du Colombier                       byte *bytein;
6497dd7cddfSDavid du Colombier                       int   width;
6507dd7cddfSDavid du Colombier 
6517dd7cddfSDavid du Colombier                       bytein  = col_line;
6527dd7cddfSDavid du Colombier 
6537dd7cddfSDavid du Colombier                       for(width = 0; width < sd->stc.prt_size; ++width) {
6547dd7cddfSDavid du Colombier                          byte i,tmp,cmyk[4];
6557dd7cddfSDavid du Colombier 
6567dd7cddfSDavid du Colombier                          memset(cmyk,0,4);
6577dd7cddfSDavid du Colombier 
6587dd7cddfSDavid du Colombier                          for(i = 128; i; i >>= 1) {
6597dd7cddfSDavid du Colombier                             static const byte rgb2cmyk[] = {
6607dd7cddfSDavid du Colombier                                BLACK,            /* 0->Black */
6617dd7cddfSDavid du Colombier                                CYAN | MAGENTA,   /* 1->BLUE  */
6627dd7cddfSDavid du Colombier                                CYAN | YELLOW,    /* 2->GREEN */
6637dd7cddfSDavid du Colombier                                CYAN,             /* 3->CYAN  */
6647dd7cddfSDavid du Colombier                                MAGENTA | YELLOW, /* 4->RED   */
6657dd7cddfSDavid du Colombier                                MAGENTA,          /* 5->MAGENTA */
6667dd7cddfSDavid du Colombier                                YELLOW,           /* 6->YELLOW */
6677dd7cddfSDavid du Colombier                                0};               /* 7->WHITE */
6687dd7cddfSDavid du Colombier 
6697dd7cddfSDavid du Colombier                             tmp = rgb2cmyk[(*bytein++) & 7];
6707dd7cddfSDavid du Colombier 
6717dd7cddfSDavid du Colombier                             if(tmp & BLACK)   cmyk[3] |= i;
6727dd7cddfSDavid du Colombier                             if(tmp & YELLOW)  cmyk[2] |= i;
6737dd7cddfSDavid du Colombier                             if(tmp & MAGENTA) cmyk[1] |= i;
6747dd7cddfSDavid du Colombier                             if(tmp & CYAN)    cmyk[0] |= i;
6757dd7cddfSDavid du Colombier                          }
6767dd7cddfSDavid du Colombier 
6777dd7cddfSDavid du Colombier                          for(i = 0; i < 4; ++i) {
6787dd7cddfSDavid du Colombier                             if(cmyk[i] != 0) sd->stc.prt_width[buf_i+i] = width+1;
6797dd7cddfSDavid du Colombier                             sd->stc.prt_data[buf_i+i][width] = cmyk[i];
6807dd7cddfSDavid du Colombier                          }
6817dd7cddfSDavid du Colombier                       }
6827dd7cddfSDavid du Colombier                   }
6837dd7cddfSDavid du Colombier                   break;
6847dd7cddfSDavid du Colombier                   case 4: /* split cmyk */
6857dd7cddfSDavid du Colombier                   {
6867dd7cddfSDavid du Colombier                       byte *bytein;
6877dd7cddfSDavid du Colombier                       int   width;
6887dd7cddfSDavid du Colombier 
6897dd7cddfSDavid du Colombier                       bytein  = col_line;
6907dd7cddfSDavid du Colombier 
6917dd7cddfSDavid du Colombier                       for(width = 0; width < sd->stc.prt_size; ++width) {
6927dd7cddfSDavid du Colombier                          byte i,tmp,cmyk[4];
6937dd7cddfSDavid du Colombier 
6947dd7cddfSDavid du Colombier                          memset(cmyk,0,4);
6957dd7cddfSDavid du Colombier 
6967dd7cddfSDavid du Colombier                          for(i = 128; i; i >>= 1) {
6977dd7cddfSDavid du Colombier                             tmp = (*bytein++) & 15;
6987dd7cddfSDavid du Colombier                             if(tmp & BLACK)   cmyk[3] |= i;
6997dd7cddfSDavid du Colombier                             if(tmp & YELLOW)  cmyk[2] |= i;
7007dd7cddfSDavid du Colombier                             if(tmp & MAGENTA) cmyk[1] |= i;
7017dd7cddfSDavid du Colombier                             if(tmp & CYAN)    cmyk[0] |= i;
7027dd7cddfSDavid du Colombier                          }
7037dd7cddfSDavid du Colombier 
7047dd7cddfSDavid du Colombier                          for(i = 0; i < 4; ++i) {
7057dd7cddfSDavid du Colombier                             if(cmyk[i] != 0) sd->stc.prt_width[buf_i+i] = width+1;
7067dd7cddfSDavid du Colombier                             sd->stc.prt_data[buf_i+i][width] = cmyk[i];
7077dd7cddfSDavid du Colombier                          }
7087dd7cddfSDavid du Colombier                       }
7097dd7cddfSDavid du Colombier                   }
7107dd7cddfSDavid du Colombier                   break;
7117dd7cddfSDavid du Colombier                   default: break;
7127dd7cddfSDavid du Colombier                   }
7137dd7cddfSDavid du Colombier                }
7147dd7cddfSDavid du Colombier             }                  /* Nr. 5 (give me input) */
7157dd7cddfSDavid du Colombier 
7167dd7cddfSDavid du Colombier /*
7177dd7cddfSDavid du Colombier  *    Nr. 5 has got enough input, now we should print it
7187dd7cddfSDavid du Colombier  */
7197dd7cddfSDavid du Colombier             if((flags & STCCOMP) == STCDELTA) stc_print_delta(sd,prn_stream);
7207dd7cddfSDavid du Colombier             else if(npass > 1)                stc_print_weave(sd,prn_stream);
7217dd7cddfSDavid du Colombier             else                              stc_print_bands(sd,prn_stream);
7227dd7cddfSDavid du Colombier 
7237dd7cddfSDavid du Colombier #ifdef    STC_SIGNAL
7247dd7cddfSDavid du Colombier             sigpending(&stc_int_pending);
7257dd7cddfSDavid du Colombier             if(sigismember(&stc_int_pending,SIGINT)) {
7267dd7cddfSDavid du Colombier                fputs("\033@[Aborted]\f", prn_stream);
7277dd7cddfSDavid du Colombier                fflush(prn_stream);
7287dd7cddfSDavid du Colombier                sigprocmask(SIG_SETMASK,&stc_int_save,NULL);
7297dd7cddfSDavid du Colombier                break;
7307dd7cddfSDavid du Colombier             }
7317dd7cddfSDavid du Colombier #endif /* STC_SIGNAL */
7327dd7cddfSDavid du Colombier 
7337dd7cddfSDavid du Colombier          }                           /* Until all scans are processed */
7347dd7cddfSDavid du Colombier 
7357dd7cddfSDavid du Colombier          if(sd->stc.flags & STCPRINT) {
7367dd7cddfSDavid du Colombier             if((flags & STCCOMP) == STCDELTA) fputc(0xe3,prn_stream);
7377dd7cddfSDavid du Colombier             fwrite(sd->stc.escp_release.data,1,sd->stc.escp_release.size,prn_stream);
7387dd7cddfSDavid du Colombier             fflush(prn_stream);
7397dd7cddfSDavid du Colombier          }
7407dd7cddfSDavid du Colombier #ifdef    STC_SIGNAL
7417dd7cddfSDavid du Colombier          sigprocmask(SIG_SETMASK,&stc_int_save,NULL);
7427dd7cddfSDavid du Colombier #endif /* STC_DIGNAL */
7437dd7cddfSDavid du Colombier 
7447dd7cddfSDavid du Colombier       }
7457dd7cddfSDavid du Colombier    }
7467dd7cddfSDavid du Colombier 
7477dd7cddfSDavid du Colombier /***
7487dd7cddfSDavid du Colombier  *** Release the dynamic memory
7497dd7cddfSDavid du Colombier  ***/
7507dd7cddfSDavid du Colombier 
7517dd7cddfSDavid du Colombier    if(ext_line != NULL)
752*593dc095SDavid du Colombier       gs_free(sd->memory, ext_line,ext_size,1,"stc_print_page/ext_line");
7537dd7cddfSDavid du Colombier 
7547dd7cddfSDavid du Colombier    if(col_line != NULL)
755*593dc095SDavid du Colombier       gs_free(sd->memory, col_line,prt_pixels,1,"stc_print_page/col_line");
7567dd7cddfSDavid du Colombier 
7577dd7cddfSDavid du Colombier    if(alg_line != NULL)
758*593dc095SDavid du Colombier       gs_free(sd->memory, alg_line,alg_size,sd->stc.alg_item,
7597dd7cddfSDavid du Colombier          "stc_print_page/alg_line");
7607dd7cddfSDavid du Colombier 
7617dd7cddfSDavid du Colombier    if(buf != NULL)
762*593dc095SDavid du Colombier       gs_free(sd->memory, buf,buf_size,sd->stc.alg_item,"stc_print_page/buf");
7637dd7cddfSDavid du Colombier 
7647dd7cddfSDavid du Colombier     if(sd->stc.prt_width != NULL)
765*593dc095SDavid du Colombier        gs_free(sd->memory, sd->stc.prt_width,sd->stc.prt_buf,sizeof(int),
7667dd7cddfSDavid du Colombier        "stc_print_page/prt_width");
7677dd7cddfSDavid du Colombier 
7687dd7cddfSDavid du Colombier     if(sd->stc.prt_data != NULL) {
7697dd7cddfSDavid du Colombier        int i;
7707dd7cddfSDavid du Colombier 
7717dd7cddfSDavid du Colombier        for(i = 0; i < sd->stc.prt_buf; ++i) {
7727dd7cddfSDavid du Colombier           if(sd->stc.prt_data[i] != NULL)
773*593dc095SDavid du Colombier              gs_free(sd->memory, sd->stc.prt_data[i],sd->stc.prt_size,1,
7747dd7cddfSDavid du Colombier              "stc_print_page/prt");
7757dd7cddfSDavid du Colombier        }
7767dd7cddfSDavid du Colombier 
777*593dc095SDavid du Colombier        gs_free(sd->memory, sd->stc.prt_data,sd->stc.prt_buf,sizeof(byte *),
7787dd7cddfSDavid du Colombier        "stc_print_page/prt_data");
7797dd7cddfSDavid du Colombier     }
7807dd7cddfSDavid du Colombier 
7817dd7cddfSDavid du Colombier     {
7827dd7cddfSDavid du Colombier        int i;
7837dd7cddfSDavid du Colombier        for(i = 0; i < sd->color_info.num_components; ++i) {
7847dd7cddfSDavid du Colombier           if(sd->stc.seed_row[i] != NULL)
785*593dc095SDavid du Colombier             gs_free(sd->memory, sd->stc.seed_row[i],sd->stc.seed_size,sizeof(int),
7867dd7cddfSDavid du Colombier             "stc_print_page/seed_row");
7877dd7cddfSDavid du Colombier        }
7887dd7cddfSDavid du Colombier     }
7897dd7cddfSDavid du Colombier 
7907dd7cddfSDavid du Colombier     if(sd->stc.escp_data != NULL)
791*593dc095SDavid du Colombier        gs_free(sd->memory, sd->stc.escp_data,sd->stc.escp_size,1,
7927dd7cddfSDavid du Colombier        "stc_print_page/escp_data");
7937dd7cddfSDavid du Colombier 
7947dd7cddfSDavid du Colombier    return OK4GO ? 0 : gs_error_undefined;
7957dd7cddfSDavid du Colombier }
7967dd7cddfSDavid du Colombier 
7977dd7cddfSDavid du Colombier /*
7987dd7cddfSDavid du Colombier  * white-check
7997dd7cddfSDavid du Colombier  */
8007dd7cddfSDavid du Colombier private bool
stc_iswhite(stcolor_device * sd,int prt_pixels,byte * ext_data)8017dd7cddfSDavid du Colombier stc_iswhite(stcolor_device *sd, int prt_pixels,byte *ext_data)
8027dd7cddfSDavid du Colombier {
8037dd7cddfSDavid du Colombier    long  b2do = (prt_pixels*sd->color_info.depth+7)>>3;
8047dd7cddfSDavid du Colombier    int   bcmp = 4 * countof(sd->stc.white_run);
8057dd7cddfSDavid du Colombier    byte *wht  = (byte *) sd->stc.white_run;
8067dd7cddfSDavid du Colombier 
8077dd7cddfSDavid du Colombier    while(b2do >= bcmp) {
8087dd7cddfSDavid du Colombier       if(memcmp(ext_data,wht,bcmp)) break;
8097dd7cddfSDavid du Colombier       ext_data += bcmp;
8107dd7cddfSDavid du Colombier       b2do     -= bcmp;
8117dd7cddfSDavid du Colombier    }
8127dd7cddfSDavid du Colombier 
8137dd7cddfSDavid du Colombier    if((b2do > 0) && (b2do < bcmp))
8147dd7cddfSDavid du Colombier       b2do  = memcmp(ext_data,sd->stc.white_end,b2do);
8157dd7cddfSDavid du Colombier 
8167dd7cddfSDavid du Colombier    return b2do ? false : true;
8177dd7cddfSDavid du Colombier }
8187dd7cddfSDavid du Colombier 
8197dd7cddfSDavid du Colombier /***
8207dd7cddfSDavid du Colombier  *** A bunch of routines that convert gslines into algorithms format.
8217dd7cddfSDavid du Colombier  ***/
8227dd7cddfSDavid du Colombier private byte *
stc_any_depth(stcolor_device * sd,byte * ext_data,int prt_pixels,byte * alg_line)8237dd7cddfSDavid du Colombier stc_any_depth(stcolor_device *sd,byte *ext_data,int prt_pixels,byte *alg_line)
8247dd7cddfSDavid du Colombier { /* general conversion */
8257dd7cddfSDavid du Colombier 
8267dd7cddfSDavid du Colombier    int p,c,       niext,         nbits;
8277dd7cddfSDavid du Colombier    gx_color_index ciext,ci,cimsk,cvmsk;
8287dd7cddfSDavid du Colombier    byte          *ap = alg_line;
8297dd7cddfSDavid du Colombier 
8307dd7cddfSDavid du Colombier    nbits =  sd->stc.bits;
8317dd7cddfSDavid du Colombier    cvmsk = ((gx_color_index) 1<<nbits) - 1;
8327dd7cddfSDavid du Colombier 
8337dd7cddfSDavid du Colombier /* it is nonsense to use this algorithm for this cases, but if it claims
8347dd7cddfSDavid du Colombier  * generality, it should deliver correct results in this cases too */
8357dd7cddfSDavid du Colombier    if(sd->color_info.depth == (sd->color_info.num_components<<3)) nbits = 8;
8367dd7cddfSDavid du Colombier 
8377dd7cddfSDavid du Colombier    cimsk = cvmsk;
8387dd7cddfSDavid du Colombier    for(c = 1; c < sd->color_info.num_components; ++c)
8397dd7cddfSDavid du Colombier        cimsk = (cimsk<<nbits) | cvmsk;
8407dd7cddfSDavid du Colombier 
8417dd7cddfSDavid du Colombier    ciext = 0;
8427dd7cddfSDavid du Colombier    niext = 0;
8437dd7cddfSDavid du Colombier 
8447dd7cddfSDavid du Colombier    for(p = 0; p < prt_pixels; ++p) { /* over pixels */
8457dd7cddfSDavid du Colombier 
8467dd7cddfSDavid du Colombier       ci = ciext;
8477dd7cddfSDavid du Colombier       for(c =  sd->color_info.depth-niext; c >= 8; c -= 8)
8487dd7cddfSDavid du Colombier          ci  = (ci<<8) | *ext_data++;
8497dd7cddfSDavid du Colombier 
8507dd7cddfSDavid du Colombier       if(c > 0) {         /* partial byte required */
8517dd7cddfSDavid du Colombier 
8527dd7cddfSDavid du Colombier          niext  = 8 - c;
8537dd7cddfSDavid du Colombier          ciext  = *ext_data++;
8547dd7cddfSDavid du Colombier          ci     = (ci<<c) | (ciext>>niext);
8557dd7cddfSDavid du Colombier          ciext &= (1L<<niext)-1;
8567dd7cddfSDavid du Colombier 
8577dd7cddfSDavid du Colombier       } else if(c < 0) { /* some bits left in ciext */
8587dd7cddfSDavid du Colombier 
8597dd7cddfSDavid du Colombier          niext  = -c;
8607dd7cddfSDavid du Colombier          ciext &= (1L<<niext)-1;
8617dd7cddfSDavid du Colombier          ci     = ci>>niext;
8627dd7cddfSDavid du Colombier 
8637dd7cddfSDavid du Colombier       } else {           /* entire ciext used */
8647dd7cddfSDavid du Colombier 
8657dd7cddfSDavid du Colombier          niext = 0;
8667dd7cddfSDavid du Colombier          ciext = 0;
8677dd7cddfSDavid du Colombier 
8687dd7cddfSDavid du Colombier       }                  /* ciext-adjust */
8697dd7cddfSDavid du Colombier 
8707dd7cddfSDavid du Colombier       ci &= cimsk;
8717dd7cddfSDavid du Colombier 
8727dd7cddfSDavid du Colombier #     define stc_storeapc(T) \
8737dd7cddfSDavid du Colombier          ((T *)ap)[c] = ((T *)(sd->stc.vals[c]))[ci & cvmsk];
8747dd7cddfSDavid du Colombier 
8757dd7cddfSDavid du Colombier       for(c = sd->color_info.num_components; c--;) { /* comp */
8767dd7cddfSDavid du Colombier          STC_TYPESWITCH(sd->stc.dither,stc_storeapc)
8777dd7cddfSDavid du Colombier          ci >>= nbits;
8787dd7cddfSDavid du Colombier       }                                              /* comp */
8797dd7cddfSDavid du Colombier 
8807dd7cddfSDavid du Colombier #     undef  stc_storeapc
8817dd7cddfSDavid du Colombier 
8827dd7cddfSDavid du Colombier       ap += sd->color_info.num_components * sd->stc.alg_item;
8837dd7cddfSDavid du Colombier 
8847dd7cddfSDavid du Colombier    }                                 /* over pixels */
8857dd7cddfSDavid du Colombier 
8867dd7cddfSDavid du Colombier    return alg_line;
8877dd7cddfSDavid du Colombier } /* general conversion */
8887dd7cddfSDavid du Colombier 
8897dd7cddfSDavid du Colombier /*
8907dd7cddfSDavid du Colombier  * rgb-data with depth=24, can use a faster algorithm
8917dd7cddfSDavid du Colombier  */
8927dd7cddfSDavid du Colombier private byte *
stc_rgb24_long(stcolor_device * sd,byte * ext_data,int prt_pixels,byte * alg_line)8937dd7cddfSDavid du Colombier stc_rgb24_long(stcolor_device *sd,byte *ext_data,int prt_pixels,byte *alg_line)
8947dd7cddfSDavid du Colombier { /* convert 3 bytes into appropriate long-Values */
8957dd7cddfSDavid du Colombier   register int   p;
8967dd7cddfSDavid du Colombier   register long *out   = (long *) alg_line;
8977dd7cddfSDavid du Colombier   register long *rvals = (long *) (sd->stc.vals[0]);
8987dd7cddfSDavid du Colombier   register long *gvals = (long *) (sd->stc.vals[1]);
8997dd7cddfSDavid du Colombier   register long *bvals = (long *) (sd->stc.vals[2]);
9007dd7cddfSDavid du Colombier 
9017dd7cddfSDavid du Colombier   for(p = prt_pixels; p; --p) {
9027dd7cddfSDavid du Colombier      *out++ = rvals[*ext_data++];
9037dd7cddfSDavid du Colombier      *out++ = gvals[*ext_data++];
9047dd7cddfSDavid du Colombier      *out++ = bvals[*ext_data++];
9057dd7cddfSDavid du Colombier   }
9067dd7cddfSDavid du Colombier 
9077dd7cddfSDavid du Colombier   return alg_line;
9087dd7cddfSDavid du Colombier } /* convert 3 bytes into appropriate long-Values */
9097dd7cddfSDavid du Colombier 
9107dd7cddfSDavid du Colombier /*
9117dd7cddfSDavid du Colombier  * cmyk-data with depth=32, can use a faster algorithm
9127dd7cddfSDavid du Colombier  */
9137dd7cddfSDavid du Colombier private byte *
stc_cmyk32_long(stcolor_device * sd,byte * ext_data,int prt_pixels,byte * alg_line)9147dd7cddfSDavid du Colombier stc_cmyk32_long(stcolor_device *sd,byte *ext_data,int prt_pixels,byte *alg_line)
9157dd7cddfSDavid du Colombier { /* convert 4 bytes into appropriate long-Values */
9167dd7cddfSDavid du Colombier   register int   p;
9177dd7cddfSDavid du Colombier   register long *out   = (long *) alg_line;
9187dd7cddfSDavid du Colombier   register long *cvals = (long *) (sd->stc.vals[0]);
9197dd7cddfSDavid du Colombier   register long *mvals = (long *) (sd->stc.vals[1]);
9207dd7cddfSDavid du Colombier   register long *yvals = (long *) (sd->stc.vals[2]);
9217dd7cddfSDavid du Colombier   register long *kvals = (long *) (sd->stc.vals[3]);
9227dd7cddfSDavid du Colombier 
9237dd7cddfSDavid du Colombier   for(p = prt_pixels; p; --p) {
9247dd7cddfSDavid du Colombier      *out++ = cvals[*ext_data++];
9257dd7cddfSDavid du Colombier      *out++ = mvals[*ext_data++];
9267dd7cddfSDavid du Colombier      *out++ = yvals[*ext_data++];
9277dd7cddfSDavid du Colombier      *out++ = kvals[*ext_data++];
9287dd7cddfSDavid du Colombier   }
9297dd7cddfSDavid du Colombier 
9307dd7cddfSDavid du Colombier   return alg_line;
9317dd7cddfSDavid du Colombier } /* convert 4 bytes into appropriate long-Values */
9327dd7cddfSDavid du Colombier 
9337dd7cddfSDavid du Colombier /*
9347dd7cddfSDavid du Colombier  * handle indirect encoded cmyk-data
9357dd7cddfSDavid du Colombier  */
9367dd7cddfSDavid du Colombier #define STC_CMYK10_ANY(T)\
9377dd7cddfSDavid du Colombier                                                                             \
9387dd7cddfSDavid du Colombier       register int p               = prt_pixels;                            \
9397dd7cddfSDavid du Colombier       register stc_pixel      ci,k,n,mode;                                  \
9407dd7cddfSDavid du Colombier       register stc_pixel      *in  = (stc_pixel *) ext_data;                \
9417dd7cddfSDavid du Colombier       register T              *out = (T *) alg_line;                        \
9427dd7cddfSDavid du Colombier       register T              *cv  = (T *) sd->stc.vals[0];                 \
9437dd7cddfSDavid du Colombier       register T              *mv  = (T *) sd->stc.vals[1];                 \
9447dd7cddfSDavid du Colombier       register T              *yv  = (T *) sd->stc.vals[2];                 \
9457dd7cddfSDavid du Colombier       register T              *kv  = (T *) sd->stc.vals[3];                 \
9467dd7cddfSDavid du Colombier                                                                             \
9477dd7cddfSDavid du Colombier       while(p--) {                                                          \
9487dd7cddfSDavid du Colombier          ci   = *in++;                                                      \
9497dd7cddfSDavid du Colombier          mode = ci & 3;                                                     \
9507dd7cddfSDavid du Colombier          k    = (ci>>2) & 0x3ff;                                            \
9517dd7cddfSDavid du Colombier          if(mode == 3) {                                                    \
9527dd7cddfSDavid du Colombier             *out++ = cv[0];                                                 \
9537dd7cddfSDavid du Colombier             *out++ = mv[0];                                                 \
9547dd7cddfSDavid du Colombier             *out++ = yv[0];                                                 \
9557dd7cddfSDavid du Colombier             *out++ = kv[k];                                                 \
9567dd7cddfSDavid du Colombier          } else {                                                           \
9577dd7cddfSDavid du Colombier             out[3] = kv[k];                                                 \
9587dd7cddfSDavid du Colombier             n = (ci>>12) & 0x3ff;                                           \
9597dd7cddfSDavid du Colombier             if(mode == 2) { out[2] = yv[k]; }                               \
9607dd7cddfSDavid du Colombier             else          { out[2] = yv[n]; n = (ci>>22) & 0x3ff; }         \
9617dd7cddfSDavid du Colombier             if(mode == 1) { out[1] = mv[k]; }                               \
9627dd7cddfSDavid du Colombier             else          { out[1] = mv[n]; n = (ci>>22) & 0x3ff; }         \
9637dd7cddfSDavid du Colombier             if(mode == 0)   out[0] = cv[k];                                 \
9647dd7cddfSDavid du Colombier             else            out[0] = cv[n];                                 \
9657dd7cddfSDavid du Colombier             out += 4;                                                       \
9667dd7cddfSDavid du Colombier          }                                                                  \
9677dd7cddfSDavid du Colombier       }                                                                     \
9687dd7cddfSDavid du Colombier                                                                             \
9697dd7cddfSDavid du Colombier       return alg_line;
9707dd7cddfSDavid du Colombier 
9717dd7cddfSDavid du Colombier private byte *
stc_cmyk10_byte(stcolor_device * sd,byte * ext_data,int prt_pixels,byte * alg_line)9727dd7cddfSDavid du Colombier stc_cmyk10_byte(stcolor_device *sd,
9737dd7cddfSDavid du Colombier                 byte *ext_data,int prt_pixels,byte *alg_line)
9747dd7cddfSDavid du Colombier {
9757dd7cddfSDavid du Colombier    STC_CMYK10_ANY(byte)
9767dd7cddfSDavid du Colombier }
9777dd7cddfSDavid du Colombier private byte *
stc_cmyk10_long(stcolor_device * sd,byte * ext_data,int prt_pixels,byte * alg_line)9787dd7cddfSDavid du Colombier stc_cmyk10_long(stcolor_device *sd,
9797dd7cddfSDavid du Colombier                 byte *ext_data,int prt_pixels,byte *alg_line)
9807dd7cddfSDavid du Colombier {
9817dd7cddfSDavid du Colombier    STC_CMYK10_ANY(long)
9827dd7cddfSDavid du Colombier }
9837dd7cddfSDavid du Colombier private byte *
stc_cmyk10_float(stcolor_device * sd,byte * ext_data,int prt_pixels,byte * alg_line)9847dd7cddfSDavid du Colombier stc_cmyk10_float(stcolor_device *sd,
9857dd7cddfSDavid du Colombier                 byte *ext_data,int prt_pixels,byte *alg_line)
9867dd7cddfSDavid du Colombier {
9877dd7cddfSDavid du Colombier    STC_CMYK10_ANY(float)
9887dd7cddfSDavid du Colombier }
9897dd7cddfSDavid du Colombier 
9907dd7cddfSDavid du Colombier #undef  STC_CMYK10_ANY
9917dd7cddfSDavid du Colombier 
9927dd7cddfSDavid du Colombier #define STC_CMYK10_DANY(T)\
9937dd7cddfSDavid du Colombier                                                                             \
9947dd7cddfSDavid du Colombier       register int p               = prt_pixels;                            \
9957dd7cddfSDavid du Colombier       register stc_pixel       ci,k,n,mode;                                 \
9967dd7cddfSDavid du Colombier       register stc_pixel      *in  = (stc_pixel *) ext_data;                \
9977dd7cddfSDavid du Colombier       register T              *out = (T *) alg_line;                        \
9987dd7cddfSDavid du Colombier                                                                             \
9997dd7cddfSDavid du Colombier       while(p--) {                                                          \
10007dd7cddfSDavid du Colombier          ci   = *in++;                                                      \
10017dd7cddfSDavid du Colombier          mode = ci & 3;                                                     \
10027dd7cddfSDavid du Colombier          k    = (ci>>2) & 0x3ff;                                            \
10037dd7cddfSDavid du Colombier          if(mode == 3) {                                                    \
10047dd7cddfSDavid du Colombier             *out++ = 0;                                                     \
10057dd7cddfSDavid du Colombier             *out++ = 0;                                                     \
10067dd7cddfSDavid du Colombier             *out++ = 0;                                                     \
10077dd7cddfSDavid du Colombier             *out++ = k;                                                     \
10087dd7cddfSDavid du Colombier          } else {                                                           \
10097dd7cddfSDavid du Colombier             out[3] = k;                                                     \
10107dd7cddfSDavid du Colombier             n = (ci>>12) & 0x3ff;                                           \
10117dd7cddfSDavid du Colombier             if(mode == 2) { out[2] = k; }                                   \
10127dd7cddfSDavid du Colombier             else          { out[2] = n; n = (ci>>22) & 0x3ff; }             \
10137dd7cddfSDavid du Colombier             if(mode == 1) { out[1] = k; }                                   \
10147dd7cddfSDavid du Colombier             else          { out[1] = n; n = (ci>>22) & 0x3ff; }             \
10157dd7cddfSDavid du Colombier             if(mode == 0)   out[0] = k;                                     \
10167dd7cddfSDavid du Colombier             else            out[0] = n;                                     \
10177dd7cddfSDavid du Colombier             out += 4;                                                       \
10187dd7cddfSDavid du Colombier          }                                                                  \
10197dd7cddfSDavid du Colombier       }                                                                     \
10207dd7cddfSDavid du Colombier                                                                             \
10217dd7cddfSDavid du Colombier       return alg_line;
10227dd7cddfSDavid du Colombier 
10237dd7cddfSDavid du Colombier 
10247dd7cddfSDavid du Colombier private byte *
stc_cmyk10_dbyte(stcolor_device * sd,byte * ext_data,int prt_pixels,byte * alg_line)10257dd7cddfSDavid du Colombier stc_cmyk10_dbyte(stcolor_device *sd,
10267dd7cddfSDavid du Colombier                 byte *ext_data,int prt_pixels,byte *alg_line)
10277dd7cddfSDavid du Colombier {
10287dd7cddfSDavid du Colombier    STC_CMYK10_DANY(byte)
10297dd7cddfSDavid du Colombier }
10307dd7cddfSDavid du Colombier private byte *
stc_cmyk10_dlong(stcolor_device * sd,byte * ext_data,int prt_pixels,byte * alg_line)10317dd7cddfSDavid du Colombier stc_cmyk10_dlong(stcolor_device *sd,
10327dd7cddfSDavid du Colombier                 byte *ext_data,int prt_pixels,byte *alg_line)
10337dd7cddfSDavid du Colombier {
10347dd7cddfSDavid du Colombier    STC_CMYK10_DANY(long)
10357dd7cddfSDavid du Colombier }
10367dd7cddfSDavid du Colombier 
10377dd7cddfSDavid du Colombier #undef  STC_CMYK10_DANY
10387dd7cddfSDavid du Colombier 
10397dd7cddfSDavid du Colombier /*
10407dd7cddfSDavid du Colombier  * if the algorithm uses bytes & bytes are in ext_data, use them
10417dd7cddfSDavid du Colombier  */
10427dd7cddfSDavid du Colombier /*ARGSUSED*/
10437dd7cddfSDavid du Colombier private byte *
stc_any_direct(stcolor_device * sd,byte * ext_data,int prt_pixels,byte * alg_line)10447dd7cddfSDavid du Colombier stc_any_direct(stcolor_device *sd,byte *ext_data,int prt_pixels,byte *alg_line)
10457dd7cddfSDavid du Colombier { /* return ext_data */
10467dd7cddfSDavid du Colombier   return ext_data;
10477dd7cddfSDavid du Colombier } /* return ext_data */
10487dd7cddfSDavid du Colombier 
10497dd7cddfSDavid du Colombier /* ----------------------------------------------------------------------- */
10507dd7cddfSDavid du Colombier /* stc_rle: epson ESC/P2 RLE-Encoding
10517dd7cddfSDavid du Colombier  */
10527dd7cddfSDavid du Colombier private int
stc_rle(byte * out,const byte * in,int width)10537dd7cddfSDavid du Colombier stc_rle(byte *out,const byte *in,int width)
10547dd7cddfSDavid du Colombier {
10557dd7cddfSDavid du Colombier 
10567dd7cddfSDavid du Colombier    int used = 0;
10577dd7cddfSDavid du Colombier    int crun,cdata;
10587dd7cddfSDavid du Colombier    byte run;
10597dd7cddfSDavid du Colombier 
10607dd7cddfSDavid du Colombier    if(in != NULL) { /* Data present */
10617dd7cddfSDavid du Colombier 
10627dd7cddfSDavid du Colombier       crun = 1;
10637dd7cddfSDavid du Colombier 
10647dd7cddfSDavid du Colombier       while(width > 0) { /* something to compress */
10657dd7cddfSDavid du Colombier 
10667dd7cddfSDavid du Colombier          run = in[0];
10677dd7cddfSDavid du Colombier 
10687dd7cddfSDavid du Colombier          while((width > crun) && (run == in[crun])) if(++crun == 129) break;
10697dd7cddfSDavid du Colombier 
10707dd7cddfSDavid du Colombier          if((crun > 2) || (crun == width)) { /* use this run */
10717dd7cddfSDavid du Colombier 
10727dd7cddfSDavid du Colombier             *out++ = (257 - crun) & 0xff; *out++ = run; used += 2;
10737dd7cddfSDavid du Colombier 
10747dd7cddfSDavid du Colombier             width -= crun; in    += crun;
10757dd7cddfSDavid du Colombier             crun = 1;
10767dd7cddfSDavid du Colombier 
10777dd7cddfSDavid du Colombier          } else {                            /* ignore this run */
10787dd7cddfSDavid du Colombier 
10797dd7cddfSDavid du Colombier             for(cdata = crun; (width > cdata) && (crun < 4);) {
10807dd7cddfSDavid du Colombier                if(run  == in[cdata]) crun += 1;
10817dd7cddfSDavid du Colombier                else run = in[cdata], crun  = 1;
10827dd7cddfSDavid du Colombier                if(++cdata == 128) break;
10837dd7cddfSDavid du Colombier             }
10847dd7cddfSDavid du Colombier 
10857dd7cddfSDavid du Colombier             if(crun < 3) crun   = 0;    /* ignore trailing run */
10867dd7cddfSDavid du Colombier             else         cdata -= crun;
10877dd7cddfSDavid du Colombier 
10887dd7cddfSDavid du Colombier             *out++ = cdata-1;     used++;
10897dd7cddfSDavid du Colombier             memcpy(out,in,cdata); used += cdata; out   += cdata;
10907dd7cddfSDavid du Colombier 
10917dd7cddfSDavid du Colombier             width -= cdata; in    += cdata;
10927dd7cddfSDavid du Colombier 
10937dd7cddfSDavid du Colombier          }              /* use/ignore run */
10947dd7cddfSDavid du Colombier 
10957dd7cddfSDavid du Colombier       }                  /* something to compress */
10967dd7cddfSDavid du Colombier 
10977dd7cddfSDavid du Colombier    } else {         /* Empty scans to fill bands */
10987dd7cddfSDavid du Colombier 
10997dd7cddfSDavid du Colombier       while(width > 0) {
11007dd7cddfSDavid du Colombier          crun   = width > 129 ? 129 : width;
11017dd7cddfSDavid du Colombier          width -= crun;
11027dd7cddfSDavid du Colombier          *out++ = (257 - crun) & 0xff;
11037dd7cddfSDavid du Colombier          *out++ = 0;
11047dd7cddfSDavid du Colombier          used  += 2;
11057dd7cddfSDavid du Colombier       }
11067dd7cddfSDavid du Colombier    }                /* Data present or empty */
11077dd7cddfSDavid du Colombier    return used;
11087dd7cddfSDavid du Colombier }
11097dd7cddfSDavid du Colombier 
11107dd7cddfSDavid du Colombier 
11117dd7cddfSDavid du Colombier /*
11127dd7cddfSDavid du Colombier  * Horizontal & vertical positioning, color-selection, "ESC ."
11137dd7cddfSDavid du Colombier  */
11147dd7cddfSDavid du Colombier private int
stc_print_escpcmd(stcolor_device * sd,FILE * prn_stream,int escp_used,int color,int m,int wbytes)11157dd7cddfSDavid du Colombier stc_print_escpcmd(stcolor_device *sd, FILE *prn_stream,
11167dd7cddfSDavid du Colombier    int escp_used, int color,int m,int wbytes)
11177dd7cddfSDavid du Colombier {
11187dd7cddfSDavid du Colombier 
11197dd7cddfSDavid du Colombier    int dy  = sd->stc.stc_y - sd->stc.prt_y; /* number of units to skip */
11207dd7cddfSDavid du Colombier    int nlf;
11217dd7cddfSDavid du Colombier 
11227dd7cddfSDavid du Colombier /* ESC-R color codes, used only here */
11237dd7cddfSDavid du Colombier    static const byte stc_colors[] = { 0x02, 0x01, 0x04, 0x00 }; /* CMYK */
11247dd7cddfSDavid du Colombier 
11257dd7cddfSDavid du Colombier /*
11267dd7cddfSDavid du Colombier  * initialize the printer, if necessary
11277dd7cddfSDavid du Colombier  */
11287dd7cddfSDavid du Colombier    if(0 == (sd->stc.flags & STCPRINT)) {
11297dd7cddfSDavid du Colombier 
11307dd7cddfSDavid du Colombier       fwrite(sd->stc.escp_init.data,1,sd->stc.escp_init.size,prn_stream);
11317dd7cddfSDavid du Colombier 
11327dd7cddfSDavid du Colombier       if(0 < sd->stc.escp_lf) { /* Adjust Linefeed */
11337dd7cddfSDavid du Colombier          fputc('\033',        prn_stream);
11347dd7cddfSDavid du Colombier          fputc('+',           prn_stream);
11357dd7cddfSDavid du Colombier          fputc(((sd->stc.escp_m*sd->stc.escp_u) / 10),prn_stream);
11367dd7cddfSDavid du Colombier       }                         /* Adjust Linefeed */
11377dd7cddfSDavid du Colombier       sd->stc.flags |= STCPRINT;
11387dd7cddfSDavid du Colombier    }
11397dd7cddfSDavid du Colombier 
11407dd7cddfSDavid du Colombier    sd->stc.escp_data[escp_used++]  = '\r';     /* leftmost position */
11417dd7cddfSDavid du Colombier 
11427dd7cddfSDavid du Colombier    if(dy) {                                    /* position the printer */
11437dd7cddfSDavid du Colombier       if(( sd->stc.escp_lf      >  0) && /* Linefeed allowed */
11447dd7cddfSDavid du Colombier          ((dy % sd->stc.escp_lf) == 0))   /* and possible */
11457dd7cddfSDavid du Colombier             nlf = dy / sd->stc.escp_lf;
11467dd7cddfSDavid du Colombier       else  nlf = 7;
11477dd7cddfSDavid du Colombier 
11487dd7cddfSDavid du Colombier       if(nlf > 6) {
11497dd7cddfSDavid du Colombier          sd->stc.escp_data[escp_used++]  = '\033';
11507dd7cddfSDavid du Colombier          sd->stc.escp_data[escp_used++]  = '(';
11517dd7cddfSDavid du Colombier          sd->stc.escp_data[escp_used++]  = 'V';
11527dd7cddfSDavid du Colombier          sd->stc.escp_data[escp_used++]  = '\002';
11537dd7cddfSDavid du Colombier          sd->stc.escp_data[escp_used++]  = '\000';
11547dd7cddfSDavid du Colombier          sd->stc.escp_data[escp_used++]  =  sd->stc.stc_y       & 0xff;
11557dd7cddfSDavid du Colombier          sd->stc.escp_data[escp_used++]  = (sd->stc.stc_y >> 8) & 0xff;
11567dd7cddfSDavid du Colombier       } else {
11577dd7cddfSDavid du Colombier          while(nlf--) sd->stc.escp_data[escp_used++] = '\n';
11587dd7cddfSDavid du Colombier       }
11597dd7cddfSDavid du Colombier       sd->stc.prt_y = sd->stc.stc_y;
11607dd7cddfSDavid du Colombier    }                                           /* position the printer */
11617dd7cddfSDavid du Colombier 
11627dd7cddfSDavid du Colombier    if((sd->color_info.num_components > 1) &&
11637dd7cddfSDavid du Colombier       (sd->stc.escp_c != stc_colors[color])) { /* select color */
11647dd7cddfSDavid du Colombier        sd->stc.escp_data[escp_used++]  = '\033';
11657dd7cddfSDavid du Colombier        sd->stc.escp_data[escp_used++]  = 'r';
11667dd7cddfSDavid du Colombier        sd->stc.escp_c                  = stc_colors[color];
11677dd7cddfSDavid du Colombier        sd->stc.escp_data[escp_used++]  = sd->stc.escp_c;
11687dd7cddfSDavid du Colombier    }                                           /* select color */
11697dd7cddfSDavid du Colombier 
11707dd7cddfSDavid du Colombier /*
11717dd7cddfSDavid du Colombier  * Build the command used
11727dd7cddfSDavid du Colombier  */
11737dd7cddfSDavid du Colombier    sd->stc.escp_data[escp_used++] = '\033';
11747dd7cddfSDavid du Colombier    sd->stc.escp_data[escp_used++] = '.';
11757dd7cddfSDavid du Colombier    sd->stc.escp_data[escp_used++] =
11767dd7cddfSDavid du Colombier        (sd->stc.flags & STCCOMP) == STCPLAIN ? 0 : 1;
11777dd7cddfSDavid du Colombier    sd->stc.escp_data[escp_used++] = sd->stc.escp_v;
11787dd7cddfSDavid du Colombier    sd->stc.escp_data[escp_used++] = sd->stc.escp_h;
11797dd7cddfSDavid du Colombier    sd->stc.escp_data[escp_used++] = m;
11807dd7cddfSDavid du Colombier    sd->stc.escp_data[escp_used++] = (wbytes<<3) & 0xff; /* width in Pixels */
11817dd7cddfSDavid du Colombier    sd->stc.escp_data[escp_used++] = (wbytes>>5) & 0xff;
11827dd7cddfSDavid du Colombier 
11837dd7cddfSDavid du Colombier    return escp_used;
11847dd7cddfSDavid du Colombier }
11857dd7cddfSDavid du Colombier 
11867dd7cddfSDavid du Colombier /*
11877dd7cddfSDavid du Colombier  * compute width of a group of scanlines
11887dd7cddfSDavid du Colombier  */
11897dd7cddfSDavid du Colombier private int
stc_bandwidth(stcolor_device * sd,int color,int m,int npass)11907dd7cddfSDavid du Colombier stc_bandwidth(stcolor_device *sd,int color,int m,int npass)
11917dd7cddfSDavid du Colombier {
11927dd7cddfSDavid du Colombier    int ncolor = sd->color_info.num_components == 1 ? 1 : 4;
11937dd7cddfSDavid du Colombier    int buf_a  = (sd->stc.prt_buf-1) & (sd->stc.stc_y * ncolor + color);
11947dd7cddfSDavid du Colombier    int w      = 0;
11957dd7cddfSDavid du Colombier 
11967dd7cddfSDavid du Colombier    while(m-- > 0) { /* check width */
11977dd7cddfSDavid du Colombier       if(sd->stc.prt_width[buf_a] > w) w = sd->stc.prt_width[buf_a];
11987dd7cddfSDavid du Colombier       buf_a = (sd->stc.prt_buf-1) & (buf_a + ncolor * npass);
11997dd7cddfSDavid du Colombier    }                       /* check width */
12007dd7cddfSDavid du Colombier 
12017dd7cddfSDavid du Colombier    return w;
12027dd7cddfSDavid du Colombier }
12037dd7cddfSDavid du Colombier 
12047dd7cddfSDavid du Colombier /*
12057dd7cddfSDavid du Colombier  * Multi-Pass Printing-Routine
12067dd7cddfSDavid du Colombier  */
12077dd7cddfSDavid du Colombier private void
stc_print_weave(stcolor_device * sd,FILE * prn_stream)12087dd7cddfSDavid du Colombier stc_print_weave(stcolor_device *sd, FILE *prn_stream)
12097dd7cddfSDavid du Colombier {
12107dd7cddfSDavid du Colombier 
12117dd7cddfSDavid du Colombier    int escp_used,nprint,nspace,color,buf_a,iprint,w;
12127dd7cddfSDavid du Colombier 
12137dd7cddfSDavid du Colombier    int npass  = sd->stc.escp_v / sd->stc.escp_u;
12147dd7cddfSDavid du Colombier    int ncolor = sd->color_info.num_components == 1 ? 1 : 4;
12157dd7cddfSDavid du Colombier 
12167dd7cddfSDavid du Colombier 
12177dd7cddfSDavid du Colombier    while(sd->stc.stc_y < sd->stc.prt_scans) {
12187dd7cddfSDavid du Colombier 
12197dd7cddfSDavid du Colombier /*
12207dd7cddfSDavid du Colombier  * compute spacing & used heads (seems to work with odd escp_m)
12217dd7cddfSDavid du Colombier  */
12227dd7cddfSDavid du Colombier       if(sd->stc.stc_y >= sd->stc.escp_m) { /* in normal mode */
12237dd7cddfSDavid du Colombier          nprint = sd->stc.escp_m;
12247dd7cddfSDavid du Colombier          nspace = sd->stc.escp_m;
12257dd7cddfSDavid du Colombier       } else if((sd->stc.stc_y) < npass) {                /* initialisation */
12267dd7cddfSDavid du Colombier          nprint = sd->stc.escp_m - sd->stc.stc_y * ((sd->stc.escp_m+1)/npass);
12277dd7cddfSDavid du Colombier          nspace = 1;
12287dd7cddfSDavid du Colombier       } else {                                   /* switch to normal */
12297dd7cddfSDavid du Colombier          nprint = sd->stc.escp_m - sd->stc.stc_y * ((sd->stc.escp_m+1)/npass);
12307dd7cddfSDavid du Colombier          nspace = sd->stc.escp_m - sd->stc.stc_y;
12317dd7cddfSDavid du Colombier       }
12327dd7cddfSDavid du Colombier       iprint = sd->stc.stc_y + npass * nprint;
12337dd7cddfSDavid du Colombier       if(sd->stc.buf_y < iprint) break;
12347dd7cddfSDavid du Colombier 
12357dd7cddfSDavid du Colombier       escp_used = 0;
12367dd7cddfSDavid du Colombier       for(color = 0; color < ncolor; ++color) { /* print the colors */
12377dd7cddfSDavid du Colombier 
12387dd7cddfSDavid du Colombier          if(0 == (w = stc_bandwidth(sd,color,nprint,npass))) continue;
12397dd7cddfSDavid du Colombier 
12407dd7cddfSDavid du Colombier          escp_used = stc_print_escpcmd(sd,prn_stream,
12417dd7cddfSDavid du Colombier                                        escp_used,color,sd->stc.escp_m,w);
12427dd7cddfSDavid du Colombier 
12437dd7cddfSDavid du Colombier          buf_a = (sd->stc.prt_buf-1) & (sd->stc.stc_y * ncolor + color);
12447dd7cddfSDavid du Colombier          for(iprint = 0; iprint < nprint; ++iprint) { /* send data */
12457dd7cddfSDavid du Colombier 
12467dd7cddfSDavid du Colombier             if((sd->stc.flags & STCCOMP) == STCPLAIN) {
12477dd7cddfSDavid du Colombier                memcpy(sd->stc.escp_data+escp_used,sd->stc.prt_data[buf_a],w);
12487dd7cddfSDavid du Colombier                escp_used += w;
12497dd7cddfSDavid du Colombier             } else {
12507dd7cddfSDavid du Colombier                escp_used += stc_rle(sd->stc.escp_data+escp_used,
12517dd7cddfSDavid du Colombier                                     sd->stc.prt_data[buf_a],w);
12527dd7cddfSDavid du Colombier             }
12537dd7cddfSDavid du Colombier 
12547dd7cddfSDavid du Colombier             fwrite(sd->stc.escp_data,1,escp_used,prn_stream);
12557dd7cddfSDavid du Colombier             escp_used = 0;
12567dd7cddfSDavid du Colombier 
12577dd7cddfSDavid du Colombier             buf_a = (sd->stc.prt_buf-1) & (buf_a + ncolor * npass);
12587dd7cddfSDavid du Colombier 
12597dd7cddfSDavid du Colombier          }                                            /* send data */
12607dd7cddfSDavid du Colombier 
12617dd7cddfSDavid du Colombier          while(iprint++ < sd->stc.escp_m) {  /* add empty rows */
12627dd7cddfSDavid du Colombier 
12637dd7cddfSDavid du Colombier             if((sd->stc.flags & STCCOMP) == STCPLAIN) {
12647dd7cddfSDavid du Colombier                memset(sd->stc.escp_data+escp_used,0,w);
12657dd7cddfSDavid du Colombier                escp_used += w;
12667dd7cddfSDavid du Colombier             } else {
12677dd7cddfSDavid du Colombier                escp_used += stc_rle(sd->stc.escp_data+escp_used,NULL,w);
12687dd7cddfSDavid du Colombier             }
12697dd7cddfSDavid du Colombier 
12707dd7cddfSDavid du Colombier             fwrite(sd->stc.escp_data,1,escp_used,prn_stream);
12717dd7cddfSDavid du Colombier             escp_used = 0;
12727dd7cddfSDavid du Colombier          }                               /* add empty rows */
12737dd7cddfSDavid du Colombier       }                                             /* print the colors */
12747dd7cddfSDavid du Colombier 
12757dd7cddfSDavid du Colombier       sd->stc.stc_y += nspace;
12767dd7cddfSDavid du Colombier    }
12777dd7cddfSDavid du Colombier }
12787dd7cddfSDavid du Colombier 
12797dd7cddfSDavid du Colombier /*
12807dd7cddfSDavid du Colombier  * Single-Pass printing-Routine
12817dd7cddfSDavid du Colombier  */
12827dd7cddfSDavid du Colombier private void
stc_print_bands(stcolor_device * sd,FILE * prn_stream)12837dd7cddfSDavid du Colombier stc_print_bands(stcolor_device *sd, FILE *prn_stream)
12847dd7cddfSDavid du Colombier {
12857dd7cddfSDavid du Colombier 
12867dd7cddfSDavid du Colombier    int escp_used,color,buf_a,iprint,w,m;
12877dd7cddfSDavid du Colombier 
12887dd7cddfSDavid du Colombier    int ncolor = sd->color_info.num_components == 1 ? 1 : 4;
12897dd7cddfSDavid du Colombier 
12907dd7cddfSDavid du Colombier    while(sd->stc.stc_y < sd->stc.prt_scans) {
12917dd7cddfSDavid du Colombier 
12927dd7cddfSDavid du Colombier /*
12937dd7cddfSDavid du Colombier  * find the begin of the band
12947dd7cddfSDavid du Colombier  */
12957dd7cddfSDavid du Colombier       for(w = 0; sd->stc.stc_y < sd->stc.buf_y; ++sd->stc.stc_y) {
12967dd7cddfSDavid du Colombier          buf_a = (sd->stc.prt_buf-1) & (sd->stc.stc_y * ncolor);
12977dd7cddfSDavid du Colombier          for(color = 0; color < ncolor; ++color)
12987dd7cddfSDavid du Colombier             if(sd->stc.prt_width[buf_a+color] > w)
12997dd7cddfSDavid du Colombier                w = sd->stc.prt_width[buf_a+color];
13007dd7cddfSDavid du Colombier          if(w != 0) break;
13017dd7cddfSDavid du Colombier       }
13027dd7cddfSDavid du Colombier       if(w == 0) break;
13037dd7cddfSDavid du Colombier /*
13047dd7cddfSDavid du Colombier  * adjust the band-height
13057dd7cddfSDavid du Colombier  */
13067dd7cddfSDavid du Colombier       w = sd->stc.prt_scans - sd->stc.stc_y;
13077dd7cddfSDavid du Colombier       if((w < sd->stc.escp_m) && (sd->stc.escp_v != 40)) {
13087dd7cddfSDavid du Colombier          if(w < 8)       m =  1;
13097dd7cddfSDavid du Colombier          else if(w < 24) m =  8;
13107dd7cddfSDavid du Colombier          else            m = 24;
13117dd7cddfSDavid du Colombier       } else {
13127dd7cddfSDavid du Colombier          m = sd->stc.escp_m;
13137dd7cddfSDavid du Colombier       }
13147dd7cddfSDavid du Colombier 
13157dd7cddfSDavid du Colombier       if(sd->stc.buf_y < (sd->stc.stc_y+m)) break;
13167dd7cddfSDavid du Colombier 
13177dd7cddfSDavid du Colombier       escp_used = 0;
13187dd7cddfSDavid du Colombier       for(color = 0; color < ncolor; ++color) { /* print the colors */
13197dd7cddfSDavid du Colombier 
13207dd7cddfSDavid du Colombier          if(0 == (w = stc_bandwidth(sd,color,m,1))) continue; /* shortcut */
13217dd7cddfSDavid du Colombier 
13227dd7cddfSDavid du Colombier          escp_used = stc_print_escpcmd(sd,prn_stream,escp_used,color,m,w);
13237dd7cddfSDavid du Colombier 
13247dd7cddfSDavid du Colombier          buf_a = (sd->stc.prt_buf-1) & (sd->stc.stc_y * ncolor + color);
13257dd7cddfSDavid du Colombier          for(iprint = 0; iprint < m; ++iprint) { /* send data */
13267dd7cddfSDavid du Colombier 
13277dd7cddfSDavid du Colombier             if((sd->stc.flags & STCCOMP) == STCPLAIN) {
13287dd7cddfSDavid du Colombier                memcpy(sd->stc.escp_data+escp_used,sd->stc.prt_data[buf_a],w);
13297dd7cddfSDavid du Colombier                escp_used += w;
13307dd7cddfSDavid du Colombier             } else {
13317dd7cddfSDavid du Colombier                escp_used += stc_rle(sd->stc.escp_data+escp_used,
13327dd7cddfSDavid du Colombier                                     sd->stc.prt_data[buf_a],w);
13337dd7cddfSDavid du Colombier             }
13347dd7cddfSDavid du Colombier 
13357dd7cddfSDavid du Colombier             fwrite(sd->stc.escp_data,1,escp_used,prn_stream);
13367dd7cddfSDavid du Colombier             escp_used = 0;
13377dd7cddfSDavid du Colombier 
13387dd7cddfSDavid du Colombier             buf_a = (sd->stc.prt_buf-1) & (buf_a + ncolor);
13397dd7cddfSDavid du Colombier 
13407dd7cddfSDavid du Colombier          }                                            /* send data */
13417dd7cddfSDavid du Colombier 
13427dd7cddfSDavid du Colombier       }                                             /* print the colors */
13437dd7cddfSDavid du Colombier 
13447dd7cddfSDavid du Colombier       sd->stc.stc_y += m;
13457dd7cddfSDavid du Colombier    }
13467dd7cddfSDavid du Colombier }
13477dd7cddfSDavid du Colombier /* ----------------------------------------------------------------------- */
13487dd7cddfSDavid du Colombier 
13497dd7cddfSDavid du Colombier private int
stc_deltarow(byte * out,const byte * in,int width,byte * seed)13507dd7cddfSDavid du Colombier stc_deltarow(byte *out,const byte *in,int width,byte *seed)
13517dd7cddfSDavid du Colombier {
13527dd7cddfSDavid du Colombier 
13537dd7cddfSDavid du Colombier    int istop,nmove,ndata,i,j;
13547dd7cddfSDavid du Colombier    int *wseed = (int *) seed;
13557dd7cddfSDavid du Colombier    int used   = 0;
13567dd7cddfSDavid du Colombier 
13577dd7cddfSDavid du Colombier    seed += sizeof(int);
13587dd7cddfSDavid du Colombier 
13597dd7cddfSDavid du Colombier    if((in != NULL) && (width > 0)) { /* Data present */
13607dd7cddfSDavid du Colombier 
13617dd7cddfSDavid du Colombier       istop = width < wseed[0] ? wseed[0] : width;
13627dd7cddfSDavid du Colombier 
13637dd7cddfSDavid du Colombier       i = 0;
13647dd7cddfSDavid du Colombier       while(i < istop) {
13657dd7cddfSDavid du Colombier 
13667dd7cddfSDavid du Colombier          for(j = i; j < istop; ++j) if(in[j] != seed[j]) break;
13677dd7cddfSDavid du Colombier 
13687dd7cddfSDavid du Colombier          nmove = j - i;
13697dd7cddfSDavid du Colombier 
13707dd7cddfSDavid du Colombier          if(nmove > 0) { /* issue a move */
13717dd7cddfSDavid du Colombier            i     = j;
13727dd7cddfSDavid du Colombier            if(i == istop) break;
13737dd7cddfSDavid du Colombier 
13747dd7cddfSDavid du Colombier            if(       nmove <   8) {
13757dd7cddfSDavid du Colombier               out[used++] = 0x40 | nmove;
13767dd7cddfSDavid du Colombier            } else if(nmove < 128) {
13777dd7cddfSDavid du Colombier               out[used++] = 0x51;
13787dd7cddfSDavid du Colombier               out[used++] = nmove;
13797dd7cddfSDavid du Colombier            } else {
13807dd7cddfSDavid du Colombier               out[used++] = 0x52;
13817dd7cddfSDavid du Colombier               out[used++] = 0xff & nmove;
13827dd7cddfSDavid du Colombier               out[used++] = 0xff & (nmove>>8);
13837dd7cddfSDavid du Colombier            }
13847dd7cddfSDavid du Colombier          }           /* issue a move */
13857dd7cddfSDavid du Colombier 
13867dd7cddfSDavid du Colombier /*
13877dd7cddfSDavid du Colombier  * find the end of this run
13887dd7cddfSDavid du Colombier  */
13897dd7cddfSDavid du Colombier          nmove = 0;
13907dd7cddfSDavid du Colombier          for(j = i+1; (j < istop) && ((nmove < 4)); ++j) {
13917dd7cddfSDavid du Colombier             if(in[j] == seed[j]) nmove += 1;
13927dd7cddfSDavid du Colombier             else                 nmove  = 0;
13937dd7cddfSDavid du Colombier          }
13947dd7cddfSDavid du Colombier 
13957dd7cddfSDavid du Colombier          ndata = j-i-nmove;
13967dd7cddfSDavid du Colombier 
13977dd7cddfSDavid du Colombier          nmove = stc_rle(out+used+3,in+i,ndata);
13987dd7cddfSDavid du Colombier          if(nmove < 16) {
13997dd7cddfSDavid du Colombier             out[used++] = 0x20 | nmove;
14007dd7cddfSDavid du Colombier             for(j = 0; j < nmove; ++j) out[used+j] = out[used+j+2];
14017dd7cddfSDavid du Colombier          } else if(nmove < 256) {
14027dd7cddfSDavid du Colombier             out[used++] = 0x31;
14037dd7cddfSDavid du Colombier             out[used++] = nmove;
14047dd7cddfSDavid du Colombier             for(j = 0; j < nmove; ++j) out[used+j] = out[used+j+1];
14057dd7cddfSDavid du Colombier          } else {
14067dd7cddfSDavid du Colombier             out[used++] = 0x32;
14077dd7cddfSDavid du Colombier             out[used++] = 0xff & nmove;
14087dd7cddfSDavid du Colombier             out[used++] = 0xff & (nmove>>8);
14097dd7cddfSDavid du Colombier          }
14107dd7cddfSDavid du Colombier          used += nmove;
14117dd7cddfSDavid du Colombier          i    += ndata;
14127dd7cddfSDavid du Colombier       }
14137dd7cddfSDavid du Colombier 
14147dd7cddfSDavid du Colombier       memcpy(seed,in,istop);
14157dd7cddfSDavid du Colombier       wseed[0] = width;
14167dd7cddfSDavid du Colombier 
14177dd7cddfSDavid du Colombier    } else if(wseed[0] > 0) { /* blank line, but seed has data */
14187dd7cddfSDavid du Colombier 
14197dd7cddfSDavid du Colombier       out[used++] = 0xe1; /* clear row */
14207dd7cddfSDavid du Colombier       memset(seed,0,wseed[0]);
14217dd7cddfSDavid du Colombier       wseed[0] = 0;
14227dd7cddfSDavid du Colombier 
14237dd7cddfSDavid du Colombier    }
14247dd7cddfSDavid du Colombier 
14257dd7cddfSDavid du Colombier    return used;
14267dd7cddfSDavid du Colombier }
14277dd7cddfSDavid du Colombier 
14287dd7cddfSDavid du Colombier /*
14297dd7cddfSDavid du Colombier  * Slightly different single-pass printing
14307dd7cddfSDavid du Colombier  */
14317dd7cddfSDavid du Colombier private void
stc_print_delta(stcolor_device * sd,FILE * prn_stream)14327dd7cddfSDavid du Colombier stc_print_delta(stcolor_device *sd, FILE *prn_stream)
14337dd7cddfSDavid du Colombier {
14347dd7cddfSDavid du Colombier 
14357dd7cddfSDavid du Colombier    int color,buf_a,w;
14367dd7cddfSDavid du Colombier    int escp_used = 0;
14377dd7cddfSDavid du Colombier    int ncolor = sd->color_info.num_components == 1 ? 1 : 4;
14387dd7cddfSDavid du Colombier 
14397dd7cddfSDavid du Colombier    while(sd->stc.stc_y < sd->stc.prt_scans) {
14407dd7cddfSDavid du Colombier 
14417dd7cddfSDavid du Colombier /*
14427dd7cddfSDavid du Colombier  * find the begin of the band
14437dd7cddfSDavid du Colombier  */
14447dd7cddfSDavid du Colombier       for(w = 0; sd->stc.stc_y < sd->stc.buf_y; ++sd->stc.stc_y) {
14457dd7cddfSDavid du Colombier          buf_a = (sd->stc.prt_buf-1) & (sd->stc.stc_y * ncolor);
14467dd7cddfSDavid du Colombier          for(color = 0; color < ncolor; ++color)
14477dd7cddfSDavid du Colombier             if(sd->stc.prt_width[buf_a+color] > w)
14487dd7cddfSDavid du Colombier                w = sd->stc.prt_width[buf_a+color];
14497dd7cddfSDavid du Colombier          if(w != 0) break;
14507dd7cddfSDavid du Colombier       }
14517dd7cddfSDavid du Colombier 
14527dd7cddfSDavid du Colombier       if(sd->stc.buf_y == sd->stc.stc_y) break;
14537dd7cddfSDavid du Colombier 
14547dd7cddfSDavid du Colombier       escp_used = 0;
14557dd7cddfSDavid du Colombier 
14567dd7cddfSDavid du Colombier /*
14577dd7cddfSDavid du Colombier  * Send Initialization & ESC . 3 once
14587dd7cddfSDavid du Colombier  */
14597dd7cddfSDavid du Colombier       if(0 == (sd->stc.flags & STCPRINT)) {
14607dd7cddfSDavid du Colombier 
14617dd7cddfSDavid du Colombier          sd->stc.flags |= STCPRINT;
14627dd7cddfSDavid du Colombier 
14637dd7cddfSDavid du Colombier          fwrite(sd->stc.escp_init.data,1,sd->stc.escp_init.size,prn_stream);
14647dd7cddfSDavid du Colombier 
14657dd7cddfSDavid du Colombier          sd->stc.escp_data[escp_used++] = '\033';
14667dd7cddfSDavid du Colombier          sd->stc.escp_data[escp_used++] = '.';
14677dd7cddfSDavid du Colombier          sd->stc.escp_data[escp_used++] =  3;
14687dd7cddfSDavid du Colombier          sd->stc.escp_data[escp_used++] = sd->stc.escp_v;
14697dd7cddfSDavid du Colombier          sd->stc.escp_data[escp_used++] = sd->stc.escp_h;
14707dd7cddfSDavid du Colombier          sd->stc.escp_data[escp_used++] = sd->stc.escp_m;
14717dd7cddfSDavid du Colombier          sd->stc.escp_data[escp_used++] = 0;
14727dd7cddfSDavid du Colombier          sd->stc.escp_data[escp_used++] = 0;
14737dd7cddfSDavid du Colombier          sd->stc.escp_data[escp_used++] = 0xe4; /* MOVXBYTE */
14747dd7cddfSDavid du Colombier       }
14757dd7cddfSDavid du Colombier 
14767dd7cddfSDavid du Colombier       if(sd->stc.stc_y != sd->stc.prt_y) { /* really position the printer */
14777dd7cddfSDavid du Colombier          w = sd->stc.stc_y - sd->stc.prt_y;
14787dd7cddfSDavid du Colombier          if(       w <  16) {
14797dd7cddfSDavid du Colombier             sd->stc.escp_data[escp_used++] = 0x60 | w;
14807dd7cddfSDavid du Colombier          } else if(w < 256) {
14817dd7cddfSDavid du Colombier             sd->stc.escp_data[escp_used++] = 0x71;
14827dd7cddfSDavid du Colombier             sd->stc.escp_data[escp_used++] = w;
14837dd7cddfSDavid du Colombier          } else {
14847dd7cddfSDavid du Colombier             sd->stc.escp_data[escp_used++] = 0x72;
14857dd7cddfSDavid du Colombier             sd->stc.escp_data[escp_used++] = 0xff & w;
14867dd7cddfSDavid du Colombier             sd->stc.escp_data[escp_used++] = 0xff & (w>>8);
14877dd7cddfSDavid du Colombier          }
14887dd7cddfSDavid du Colombier          sd->stc.prt_y = sd->stc.stc_y;
14897dd7cddfSDavid du Colombier       }                                    /* really position the printer */
14907dd7cddfSDavid du Colombier 
14917dd7cddfSDavid du Colombier       for(color = 0; color < ncolor; ++color) { /* print the colors */
14927dd7cddfSDavid du Colombier 
14937dd7cddfSDavid du Colombier /* Color-Selection */
14947dd7cddfSDavid du Colombier          if(color == (ncolor-1)) {
14957dd7cddfSDavid du Colombier             sd->stc.escp_data[escp_used++] = 0x80; /* Black */
14967dd7cddfSDavid du Colombier          } else {
14977dd7cddfSDavid du Colombier             switch(color) {
14987dd7cddfSDavid du Colombier             case 1:  sd->stc.escp_data[escp_used++] = 0x81; break; /* M */
14997dd7cddfSDavid du Colombier             case 2:  sd->stc.escp_data[escp_used++] = 0x84; break; /* Y */
15007dd7cddfSDavid du Colombier             default: sd->stc.escp_data[escp_used++] = 0x82; break; /* C */
15017dd7cddfSDavid du Colombier             }
15027dd7cddfSDavid du Colombier          }
15037dd7cddfSDavid du Colombier 
15047dd7cddfSDavid du Colombier /* Data-Transfer */
15057dd7cddfSDavid du Colombier          buf_a = (sd->stc.prt_buf-1) & (sd->stc.stc_y * ncolor + color);
15067dd7cddfSDavid du Colombier 
15077dd7cddfSDavid du Colombier          w = stc_deltarow(sd->stc.escp_data+escp_used,
15087dd7cddfSDavid du Colombier              sd->stc.prt_data[buf_a],sd->stc.prt_width[buf_a],
15097dd7cddfSDavid du Colombier              sd->stc.seed_row[color]);
15107dd7cddfSDavid du Colombier 
15117dd7cddfSDavid du Colombier          if(w == 0) escp_used -= 1;
15127dd7cddfSDavid du Colombier          else       escp_used += w;
15137dd7cddfSDavid du Colombier 
15147dd7cddfSDavid du Colombier          if(escp_used > 0) fwrite(sd->stc.escp_data,1,escp_used,prn_stream);
15157dd7cddfSDavid du Colombier          escp_used = 0;
15167dd7cddfSDavid du Colombier 
15177dd7cddfSDavid du Colombier       }                                             /* print the colors */
15187dd7cddfSDavid du Colombier 
15197dd7cddfSDavid du Colombier       sd->stc.stc_y += 1;
15207dd7cddfSDavid du Colombier 
15217dd7cddfSDavid du Colombier    }
15227dd7cddfSDavid du Colombier 
15237dd7cddfSDavid du Colombier }
15247dd7cddfSDavid du Colombier 
15257dd7cddfSDavid du Colombier /* ----------------------------------------------------------------------- */
15267dd7cddfSDavid du Colombier 
15277dd7cddfSDavid du Colombier /***
15287dd7cddfSDavid du Colombier  *** Free-Data: release the specific-Arrays
15297dd7cddfSDavid du Colombier  ***/
15307dd7cddfSDavid du Colombier private void
stc_freedata(gs_memory_t * mem,stc_t * stc)1531*593dc095SDavid du Colombier stc_freedata(gs_memory_t *mem, stc_t *stc)
15327dd7cddfSDavid du Colombier {
15337dd7cddfSDavid du Colombier    int i,j;
15347dd7cddfSDavid du Colombier 
15357dd7cddfSDavid du Colombier    for(i = 0; i < 4; ++i) {
15367dd7cddfSDavid du Colombier       if(stc->code[i] != NULL) {
15377dd7cddfSDavid du Colombier 
15387dd7cddfSDavid du Colombier          for(j = 0; j < i; ++j) if(stc->code[i] == stc->code[j]) break;
15397dd7cddfSDavid du Colombier 
1540*593dc095SDavid du Colombier          if(i == j) gs_free(mem, stc->code[i],1<<stc->bits,sizeof(gx_color_value),
15417dd7cddfSDavid du Colombier                            "stcolor/code");
15427dd7cddfSDavid du Colombier       }
15437dd7cddfSDavid du Colombier 
15447dd7cddfSDavid du Colombier       if(stc->vals[i] != NULL) {
15457dd7cddfSDavid du Colombier 
15467dd7cddfSDavid du Colombier          for(j = 0; j < i; ++j)
15477dd7cddfSDavid du Colombier             if(stc->vals[i] == stc->vals[j]) break;
15487dd7cddfSDavid du Colombier 
1549*593dc095SDavid du Colombier          if(i == j) gs_free(mem, stc->vals[i],1<<stc->bits,sd->stc.alg_item,
15507dd7cddfSDavid du Colombier                            "stcolor/transfer");
15517dd7cddfSDavid du Colombier       }
15527dd7cddfSDavid du Colombier    }
15537dd7cddfSDavid du Colombier 
15547dd7cddfSDavid du Colombier    for(i = 0; i < 4; ++i) {
15557dd7cddfSDavid du Colombier       stc->code[i] = NULL;
15567dd7cddfSDavid du Colombier       stc->vals[i] = NULL;
15577dd7cddfSDavid du Colombier    }
15587dd7cddfSDavid du Colombier }
15597dd7cddfSDavid du Colombier 
15607dd7cddfSDavid du Colombier /***
15617dd7cddfSDavid du Colombier  *** open the device and initialize margins & arrays
15627dd7cddfSDavid du Colombier  ***/
15637dd7cddfSDavid du Colombier 
15647dd7cddfSDavid du Colombier private int
stc_open(gx_device * pdev)15657dd7cddfSDavid du Colombier stc_open(gx_device *pdev) /* setup margins & arrays */
15667dd7cddfSDavid du Colombier {
15677dd7cddfSDavid du Colombier   stcolor_device *sd = (stcolor_device *) pdev;
15687dd7cddfSDavid du Colombier   int i,j,code;
15697dd7cddfSDavid du Colombier   gx_color_index white;
15707dd7cddfSDavid du Colombier   byte *bpw,*bpm;
15717dd7cddfSDavid du Colombier 
15727dd7cddfSDavid du Colombier   code = 0;
15737dd7cddfSDavid du Colombier /*
15747dd7cddfSDavid du Colombier  * Establish Algorithm-Table, if not present
15757dd7cddfSDavid du Colombier  */
15767dd7cddfSDavid du Colombier   if(sd->stc.algorithms.size == 0) {
15777dd7cddfSDavid du Colombier      gs_param_string *dp;
15787dd7cddfSDavid du Colombier      for(i = 0; stc_dither[i].name != NULL; ++i); /* count 'em */
15797dd7cddfSDavid du Colombier      sd->stc.algorithms.size = i;
1580*593dc095SDavid du Colombier      dp = gs_malloc(sd->memory, i,sizeof(gs_param_string),
15817dd7cddfSDavid du Colombier                                         "stcolor/algorithms");
15827dd7cddfSDavid du Colombier      if(dp == NULL) {
15837dd7cddfSDavid du Colombier         code = gs_error_VMerror;
15847dd7cddfSDavid du Colombier         sd->stc.algorithms.size = 0;
15857dd7cddfSDavid du Colombier      } else {
15867dd7cddfSDavid du Colombier         sd->stc.algorithms.data       = dp;
15877dd7cddfSDavid du Colombier         sd->stc.algorithms.persistent = true;
15887dd7cddfSDavid du Colombier         for(i = 0; stc_dither[i].name != NULL; ++i) {
15897dd7cddfSDavid du Colombier         param_string_from_string(dp[i],stc_dither[i].name);
15907dd7cddfSDavid du Colombier         }
15917dd7cddfSDavid du Colombier      }
15927dd7cddfSDavid du Colombier   }
15937dd7cddfSDavid du Colombier 
15947dd7cddfSDavid du Colombier # define stc_sizeofitem(T) sd->stc.alg_item = sizeof(T)
15957dd7cddfSDavid du Colombier   STC_TYPESWITCH(sd->stc.dither,stc_sizeofitem)
15967dd7cddfSDavid du Colombier 
15977dd7cddfSDavid du Colombier   stc_print_setup(sd);
15987dd7cddfSDavid du Colombier 
15997dd7cddfSDavid du Colombier /*
16007dd7cddfSDavid du Colombier  * Establish internal Value & Code-Arrays
16017dd7cddfSDavid du Colombier  */
16027dd7cddfSDavid du Colombier 
16037dd7cddfSDavid du Colombier 
16047dd7cddfSDavid du Colombier   for(i = 0; i < sd->color_info.num_components; ++i) { /* comp */
16057dd7cddfSDavid du Colombier 
16067dd7cddfSDavid du Colombier      if((sd->stc.sizc[i] >  1) && (sd->stc.extc[i] != NULL)) { /* code req. */
16077dd7cddfSDavid du Colombier 
16087dd7cddfSDavid du Colombier         for(j = 0; j < i; ++j) if(sd->stc.extc[i] == sd->stc.extc[j]) break;
16097dd7cddfSDavid du Colombier 
16107dd7cddfSDavid du Colombier         if(i == j) { /* new one */
1611*593dc095SDavid du Colombier            sd->stc.code[i] = gs_malloc(sd->memory, 1<<sd->stc.bits,sizeof(gx_color_value),
16127dd7cddfSDavid du Colombier                              "stcolor/code");
16137dd7cddfSDavid du Colombier 
16147dd7cddfSDavid du Colombier            if(sd->stc.code[i] == NULL) { /* error */
16157dd7cddfSDavid du Colombier               code = gs_error_VMerror;
16167dd7cddfSDavid du Colombier            } else {                      /* success */
16177dd7cddfSDavid du Colombier /*
16187dd7cddfSDavid du Colombier  * Try making things easier:
16197dd7cddfSDavid du Colombier  *     normalize values to 0.0/1.0-Range
16207dd7cddfSDavid du Colombier  *     X-Axis:   Color-Values (implied)
16217dd7cddfSDavid du Colombier  *     Y-Values: Indices      (given)
16227dd7cddfSDavid du Colombier  */
16237dd7cddfSDavid du Colombier               unsigned long ly,iy;
16247dd7cddfSDavid du Colombier               double ystep,xstep,fx,fy;
16257dd7cddfSDavid du Colombier 
16267dd7cddfSDavid du Colombier /* normalize */
16277dd7cddfSDavid du Colombier 
16287dd7cddfSDavid du Colombier               fx =  1e18;
16297dd7cddfSDavid du Colombier               fy = -1e18;
16307dd7cddfSDavid du Colombier               for(ly = 0; ly < sd->stc.sizc[i]; ++ly) {
16317dd7cddfSDavid du Colombier                  if(sd->stc.extc[i][ly] < fx) fx = sd->stc.extc[i][ly];
16327dd7cddfSDavid du Colombier                  if(sd->stc.extc[i][ly] > fy) fy = sd->stc.extc[i][ly];
16337dd7cddfSDavid du Colombier               }
16347dd7cddfSDavid du Colombier               if((fx != 0.0) || (fy != 1.0)) {
16357dd7cddfSDavid du Colombier                  fy = 1.0 / (fy - fx);
16367dd7cddfSDavid du Colombier                  for(ly = 0; ly < sd->stc.sizc[i]; ++ly)
16377dd7cddfSDavid du Colombier                     sd->stc.extc[i][ly] = fy * (sd->stc.extc[i][ly]-fx);
16387dd7cddfSDavid du Colombier               }
16397dd7cddfSDavid du Colombier 
16407dd7cddfSDavid du Colombier /* interpolate */
16417dd7cddfSDavid du Colombier               ystep = 1.0 / (double)((1<<sd->stc.bits)-1);
16427dd7cddfSDavid du Colombier               xstep = 1.0 / (double)( sd->stc.sizc[i] -1);
16437dd7cddfSDavid du Colombier 
16447dd7cddfSDavid du Colombier               iy = 0;
16457dd7cddfSDavid du Colombier               for(ly = 0; ly < (1<<sd->stc.bits); ++ly) {
16467dd7cddfSDavid du Colombier                  fy = ystep * ly;
16477dd7cddfSDavid du Colombier                  while(((iy+1) < sd->stc.sizc[i]) &&
16487dd7cddfSDavid du Colombier                        (  fy   > sd->stc.extc[i][iy+1])) ++iy;
16497dd7cddfSDavid du Colombier                  fx  = iy + (fy - sd->stc.extc[i][iy])
16507dd7cddfSDavid du Colombier                             / (sd->stc.extc[i][iy+1] - sd->stc.extc[i][iy]);
16517dd7cddfSDavid du Colombier                  fx *= xstep * gx_max_color_value;
16527dd7cddfSDavid du Colombier 
16537dd7cddfSDavid du Colombier                  fx = fx < 0.0 ? 0.0 :
16547dd7cddfSDavid du Colombier                       (fx > gx_max_color_value ? gx_max_color_value : fx);
16557dd7cddfSDavid du Colombier 
1656*593dc095SDavid du Colombier                  sd->stc.code[i][ly] = (gx_color_value)fx;
16577dd7cddfSDavid du Colombier                  if((fx-sd->stc.code[i][ly]) >= 0.5) sd->stc.code[i][ly] += 1;
16587dd7cddfSDavid du Colombier               }
16597dd7cddfSDavid du Colombier            }                             /* error || success */
16607dd7cddfSDavid du Colombier 
16617dd7cddfSDavid du Colombier         } else {     /* shared one */
16627dd7cddfSDavid du Colombier 
16637dd7cddfSDavid du Colombier            sd->stc.code[i] = sd->stc.code[j];
16647dd7cddfSDavid du Colombier 
16657dd7cddfSDavid du Colombier         }           /* new || shared one */
16667dd7cddfSDavid du Colombier      }                                                         /* code req. */
16677dd7cddfSDavid du Colombier 
16687dd7cddfSDavid du Colombier      if((sd->stc.sizv[i] >  1) && (sd->stc.extv[i] != NULL)) { /* vals req. */
16697dd7cddfSDavid du Colombier 
16707dd7cddfSDavid du Colombier         for(j = 0; j < i; ++j)
16717dd7cddfSDavid du Colombier            if((sd->stc.extc[i] == sd->stc.extc[j]) &&
16727dd7cddfSDavid du Colombier               (sd->stc.extv[i] == sd->stc.extv[j])) break;
16737dd7cddfSDavid du Colombier 
16747dd7cddfSDavid du Colombier         if(i == j) { /* new one */
16757dd7cddfSDavid du Colombier 
16767dd7cddfSDavid du Colombier              sd->stc.vals[i] =
1677*593dc095SDavid du Colombier                 gs_malloc(sd->memory, 1<<sd->stc.bits,sd->stc.alg_item,"stcolor/transfer");
16787dd7cddfSDavid du Colombier 
16797dd7cddfSDavid du Colombier            if(sd->stc.vals[i] == NULL) {
16807dd7cddfSDavid du Colombier 
16817dd7cddfSDavid du Colombier               code = gs_error_VMerror;
16827dd7cddfSDavid du Colombier 
16837dd7cddfSDavid du Colombier            } else {                      /* success */
16847dd7cddfSDavid du Colombier 
16857dd7cddfSDavid du Colombier 
16867dd7cddfSDavid du Colombier               if(sd->stc.code[i] == NULL) { /* linear */
16877dd7cddfSDavid du Colombier 
16887dd7cddfSDavid du Colombier                  byte  *Out  = sd->stc.vals[i];
16897dd7cddfSDavid du Colombier                  int    Nout = 1<<sd->stc.bits;
16907dd7cddfSDavid du Colombier                  double Omin = sd->stc.dither->minmax[0];
16917dd7cddfSDavid du Colombier                  double Omax = sd->stc.dither->minmax[1];
16927dd7cddfSDavid du Colombier                  float *In   = sd->stc.extv[i];
16937dd7cddfSDavid du Colombier                  int    Nin  = sd->stc.sizv[i];
16947dd7cddfSDavid du Colombier                  unsigned long I,io;
16957dd7cddfSDavid du Colombier                  double Istep,Ostep,Y;
16967dd7cddfSDavid du Colombier                  byte   Ovb; long Ovl;
16977dd7cddfSDavid du Colombier 
16987dd7cddfSDavid du Colombier                  Istep = 1.0 / (double) ((Nin)-1);
16997dd7cddfSDavid du Colombier                  Ostep = 1.0 / (double) ((Nout)-1);
17007dd7cddfSDavid du Colombier 
17017dd7cddfSDavid du Colombier                  for(io = 0; io < (Nout); ++io) {
17027dd7cddfSDavid du Colombier                     I = (long)(io * ((Nin)-1))/((Nout)-1);
17037dd7cddfSDavid du Colombier 
17047dd7cddfSDavid du Colombier                     if((I+1) < (Nin))
17057dd7cddfSDavid du Colombier                        Y = In[I] + (In[I+1]-In[I])
17067dd7cddfSDavid du Colombier                                      * ((double) io * Ostep - (double)I * Istep)
17077dd7cddfSDavid du Colombier                                                /  (double) Istep;
17087dd7cddfSDavid du Colombier                     else
17097dd7cddfSDavid du Colombier                        Y = In[I] + (In[I]-In[I-1])
17107dd7cddfSDavid du Colombier                                      * ((double) io * Ostep - (double)I * Istep)
17117dd7cddfSDavid du Colombier                                                /  (double) Istep;
17127dd7cddfSDavid du Colombier 
17137dd7cddfSDavid du Colombier                     Y = Omin + (Omax-Omin) * Y;
17147dd7cddfSDavid du Colombier                     Y = Y < Omin ? Omin : (Y > Omax ? Omax : Y);
17157dd7cddfSDavid du Colombier 
17167dd7cddfSDavid du Colombier 
17177dd7cddfSDavid du Colombier                     switch(sd->stc.dither->flags & STC_TYPE) {
17187dd7cddfSDavid du Colombier                        case STC_BYTE:
1719*593dc095SDavid du Colombier                           Ovb = (byte)Y;
17207dd7cddfSDavid du Colombier                           if(((Y-Ovb) >= 0.5) && ((Ovb+1) <= Omax)) Ovb += 1;
17217dd7cddfSDavid du Colombier                           Out[io] = Ovb;
17227dd7cddfSDavid du Colombier                           break;
17237dd7cddfSDavid du Colombier                        case STC_LONG:
1724*593dc095SDavid du Colombier                           Ovl = (long)Y;
17257dd7cddfSDavid du Colombier                           if(((Y-Ovl) >= 0.5) && ((Ovl+1) <= Omax)) Ovl += 1;
17267dd7cddfSDavid du Colombier                           if(((Ovl-Y) >= 0.5) && ((Ovl-1) >= Omax)) Ovl -= 1;
17277dd7cddfSDavid du Colombier                           ((long *)Out)[io] = Ovl;
17287dd7cddfSDavid du Colombier                           break;
17297dd7cddfSDavid du Colombier                        default:
17307dd7cddfSDavid du Colombier                           ((float *)Out)[io] = Y;
17317dd7cddfSDavid du Colombier                           break;
17327dd7cddfSDavid du Colombier                     }
17337dd7cddfSDavid du Colombier                  }
17347dd7cddfSDavid du Colombier 
17357dd7cddfSDavid du Colombier               } else {                     /* encoded */
17367dd7cddfSDavid du Colombier                  unsigned long j,o;
17377dd7cddfSDavid du Colombier                  double xstep,x,y;
17387dd7cddfSDavid du Colombier 
17397dd7cddfSDavid du Colombier                  xstep = 1.0 / (double) (sd->stc.sizv[i]-1);
17407dd7cddfSDavid du Colombier 
17417dd7cddfSDavid du Colombier /*
17427dd7cddfSDavid du Colombier  * The following differs in so far from the previous, that the desired
17437dd7cddfSDavid du Colombier  * X-Values are stored in another array.
17447dd7cddfSDavid du Colombier  */
17457dd7cddfSDavid du Colombier                  for(o = 0; o < (1<<sd->stc.bits); ++o) { /* code-loop */
17467dd7cddfSDavid du Colombier 
17477dd7cddfSDavid du Colombier                     x = sd->stc.code[i][o]; x /= gx_max_color_value;
17487dd7cddfSDavid du Colombier 
1749*593dc095SDavid du Colombier                     j = (unsigned long)(x / xstep);
17507dd7cddfSDavid du Colombier 
17517dd7cddfSDavid du Colombier                     if((j+1) < sd->stc.sizv[i]) {
17527dd7cddfSDavid du Colombier                        y  = sd->stc.extv[i][j];
17537dd7cddfSDavid du Colombier                        y += (sd->stc.extv[i][j+1]-y)*(x-(double)j*xstep)/xstep;
17547dd7cddfSDavid du Colombier                     } else {
17557dd7cddfSDavid du Colombier                        y  = sd->stc.extv[i][j];
17567dd7cddfSDavid du Colombier                        y += (y-sd->stc.extv[i][j-1])*(x-(double)j*xstep)/xstep;
17577dd7cddfSDavid du Colombier                     }
17587dd7cddfSDavid du Colombier 
17597dd7cddfSDavid du Colombier                     y = sd->stc.dither->minmax[0]
17607dd7cddfSDavid du Colombier                       +(sd->stc.dither->minmax[1]-sd->stc.dither->minmax[0])*y;
17617dd7cddfSDavid du Colombier 
17627dd7cddfSDavid du Colombier #                   define stc_adjvals(T)                                             \
1763*593dc095SDavid du Colombier                      ((T *)(sd->stc.vals[i]))[o] = (T)y;                                 \
17647dd7cddfSDavid du Colombier                                                                                       \
17657dd7cddfSDavid du Colombier                     if(((y-((T *)(sd->stc.vals[i]))[o]) >= 0.5) &&                    \
17667dd7cddfSDavid du Colombier                        ((1+((T *)(sd->stc.vals[i]))[o]) <= sd->stc.dither->minmax[1]))\
17677dd7cddfSDavid du Colombier                        ((T *)(sd->stc.vals[i]))[o]      += 1;                         \
17687dd7cddfSDavid du Colombier                                                                                       \
17697dd7cddfSDavid du Colombier                     if(((((T *)(sd->stc.vals[i]))[o]-y) >= 0.5) &&                    \
17707dd7cddfSDavid du Colombier                        ((((T *)(sd->stc.vals[i]))[o]-1) >= sd->stc.dither->minmax[0]))\
17717dd7cddfSDavid du Colombier                        ((T *)(sd->stc.vals[i]))[o]      -= 1;
17727dd7cddfSDavid du Colombier 
17737dd7cddfSDavid du Colombier                     STC_TYPESWITCH(sd->stc.dither,stc_adjvals)
17747dd7cddfSDavid du Colombier 
17757dd7cddfSDavid du Colombier #                   undef stc_adjvals
17767dd7cddfSDavid du Colombier                  }                                       /* code-loop */
17777dd7cddfSDavid du Colombier               }                            /* lineaer / encoded */
17787dd7cddfSDavid du Colombier            }                             /* error || success */
17797dd7cddfSDavid du Colombier 
17807dd7cddfSDavid du Colombier         } else {     /* shared one */
17817dd7cddfSDavid du Colombier 
17827dd7cddfSDavid du Colombier            sd->stc.vals[i] = sd->stc.vals[j];
17837dd7cddfSDavid du Colombier 
17847dd7cddfSDavid du Colombier         }           /* new || shared one */
17857dd7cddfSDavid du Colombier      }                                                         /* vals req. */
17867dd7cddfSDavid du Colombier   }                                                    /* comp */
17877dd7cddfSDavid du Colombier 
17887dd7cddfSDavid du Colombier   if(code == 0) {
1789*593dc095SDavid du Colombier       gx_color_value cv[4];
17907dd7cddfSDavid du Colombier       sd->stc.flags |= STCOK4GO;
17917dd7cddfSDavid du Colombier 
17927dd7cddfSDavid du Colombier /*
17937dd7cddfSDavid du Colombier  * Arrgh: open-procedure seems to be the right-place, but it is
17947dd7cddfSDavid du Colombier  *        necessary to establish the defaults for omitted procedures too.
17957dd7cddfSDavid du Colombier  */
17967dd7cddfSDavid du Colombier 
17977dd7cddfSDavid du Colombier       switch(sd->color_info.num_components) { /* Establish color-procs */
17987dd7cddfSDavid du Colombier       case 1:
17997dd7cddfSDavid du Colombier          set_dev_proc(sd,map_rgb_color, stc_map_gray_color);
18007dd7cddfSDavid du Colombier          set_dev_proc(sd,map_cmyk_color,gx_default_map_cmyk_color);
18017dd7cddfSDavid du Colombier          set_dev_proc(sd,map_color_rgb, stc_map_color_gray);
1802*593dc095SDavid du Colombier 	 set_dev_proc(sd,encode_color, stc_map_gray_color);
1803*593dc095SDavid du Colombier          set_dev_proc(sd,decode_color, stc_map_color_gray);
1804*593dc095SDavid du Colombier          cv[0] = cv[1] = cv[2] = gx_max_color_value;
1805*593dc095SDavid du Colombier          white = stc_map_gray_color((gx_device *) sd, cv);
18067dd7cddfSDavid du Colombier          break;
18077dd7cddfSDavid du Colombier       case 3:
18087dd7cddfSDavid du Colombier          set_dev_proc(sd,map_rgb_color, stc_map_rgb_color);
18097dd7cddfSDavid du Colombier          set_dev_proc(sd,map_cmyk_color,gx_default_map_cmyk_color);
18107dd7cddfSDavid du Colombier          set_dev_proc(sd,map_color_rgb, stc_map_color_rgb);
1811*593dc095SDavid du Colombier 	 set_dev_proc(sd,encode_color, stc_map_rgb_color);
1812*593dc095SDavid du Colombier          set_dev_proc(sd,decode_color, stc_map_color_rgb);
1813*593dc095SDavid du Colombier          cv[0] = cv[1] = cv[2] = gx_max_color_value;
1814*593dc095SDavid du Colombier          white = stc_map_rgb_color((gx_device *) sd, cv);
18157dd7cddfSDavid du Colombier          break;
18167dd7cddfSDavid du Colombier       default:
18177dd7cddfSDavid du Colombier          set_dev_proc(sd,map_rgb_color, gx_default_map_rgb_color);
18187dd7cddfSDavid du Colombier          if(sd->stc.flags & STCCMYK10) {
18197dd7cddfSDavid du Colombier             set_dev_proc(sd,map_cmyk_color,stc_map_cmyk10_color);
18207dd7cddfSDavid du Colombier             set_dev_proc(sd,map_color_rgb, stc_map_color_cmyk10);
1821*593dc095SDavid du Colombier 	    set_dev_proc(sd,encode_color,stc_map_cmyk10_color);
1822*593dc095SDavid du Colombier             set_dev_proc(sd,decode_color, stc_map_color_cmyk10);
1823*593dc095SDavid du Colombier             cv[0] = cv[1] = cv[2] = cv[3] = 0;
1824*593dc095SDavid du Colombier             white = stc_map_cmyk10_color((gx_device *) sd, cv);
18257dd7cddfSDavid du Colombier          } else {
18267dd7cddfSDavid du Colombier             set_dev_proc(sd,map_cmyk_color,stc_map_cmyk_color);
18277dd7cddfSDavid du Colombier             set_dev_proc(sd,map_color_rgb, stc_map_color_cmyk);
1828*593dc095SDavid du Colombier 	    set_dev_proc(sd,encode_color,stc_map_cmyk_color);
1829*593dc095SDavid du Colombier             set_dev_proc(sd,decode_color, stc_map_color_cmyk);
1830*593dc095SDavid du Colombier             cv[0] = cv[1] = cv[2] = cv[3] = 0;
1831*593dc095SDavid du Colombier             white = stc_map_cmyk_color((gx_device *) sd,cv);
18327dd7cddfSDavid du Colombier          }
18337dd7cddfSDavid du Colombier          break;                               /* Establish color-procs */
18347dd7cddfSDavid du Colombier       }
18357dd7cddfSDavid du Colombier 
18367dd7cddfSDavid du Colombier 
18377dd7cddfSDavid du Colombier /*
18387dd7cddfSDavid du Colombier  * create at least a Byte
18397dd7cddfSDavid du Colombier  */
18407dd7cddfSDavid du Colombier       if(sd->color_info.depth < 2) white |= (white<<1);
18417dd7cddfSDavid du Colombier       if(sd->color_info.depth < 4) white |= (white<<2);
18427dd7cddfSDavid du Colombier       if(sd->color_info.depth < 8) white |= (white<<4);
18437dd7cddfSDavid du Colombier 
18447dd7cddfSDavid du Colombier /*
18457dd7cddfSDavid du Colombier  * copy the Bytes
18467dd7cddfSDavid du Colombier  */
18477dd7cddfSDavid du Colombier       bpw = (byte *) sd->stc.white_run;
18487dd7cddfSDavid du Colombier 
18497dd7cddfSDavid du Colombier       if(sd->color_info.depth < 16) {
18507dd7cddfSDavid du Colombier          for(i = 0; i < sizeof(sd->stc.white_run); i += 1) {
18517dd7cddfSDavid du Colombier             bpw[i] = 0xff & white;
18527dd7cddfSDavid du Colombier          }
18537dd7cddfSDavid du Colombier       } else if(sd->color_info.depth < 24) {
18547dd7cddfSDavid du Colombier          for(i = 0; i < sizeof(sd->stc.white_run); i += 2) {
18557dd7cddfSDavid du Colombier             bpw[i]   = 0xff & (white>>8);
18567dd7cddfSDavid du Colombier             bpw[i+1] = 0xff &  white;
18577dd7cddfSDavid du Colombier          }
18587dd7cddfSDavid du Colombier       } else if(sd->color_info.depth < 32) {
18597dd7cddfSDavid du Colombier          for(i = 0; i < sizeof(sd->stc.white_run); i += 3) {
18607dd7cddfSDavid du Colombier             bpw[i]   = 0xff & (white>>16);
18617dd7cddfSDavid du Colombier             bpw[i+1] = 0xff & (white>> 8);
18627dd7cddfSDavid du Colombier             bpw[i+2] = 0xff &  white;
18637dd7cddfSDavid du Colombier          }
18647dd7cddfSDavid du Colombier       } else {
18657dd7cddfSDavid du Colombier          for(i = 0; i < sizeof(sd->stc.white_run); i += 4) {
18667dd7cddfSDavid du Colombier             bpw[i]   = 0xff & (white>>24);
18677dd7cddfSDavid du Colombier             bpw[i+1] = 0xff & (white>>16);
18687dd7cddfSDavid du Colombier             bpw[i+2] = 0xff & (white>> 8);
18697dd7cddfSDavid du Colombier             bpw[i+3] = 0xff &  white;
18707dd7cddfSDavid du Colombier          }
18717dd7cddfSDavid du Colombier       }
18727dd7cddfSDavid du Colombier /*
18737dd7cddfSDavid du Colombier  *    compute the trailer
18747dd7cddfSDavid du Colombier  */
1875*593dc095SDavid du Colombier       j  = (unsigned long)(sd->width -
1876*593dc095SDavid du Colombier           (dev_l_margin(sd)+dev_r_margin(sd))*sd->x_pixels_per_inch);
18777dd7cddfSDavid du Colombier       j  = j * sd->color_info.depth;            /* the Bit-count */
18787dd7cddfSDavid du Colombier       j  = j % (32*countof(sd->stc.white_run)); /* remaining Bits */
18797dd7cddfSDavid du Colombier 
18807dd7cddfSDavid du Colombier       bpm = (byte *) sd->stc.white_end;
18817dd7cddfSDavid du Colombier       for(i = 0; i < (4*countof(sd->stc.white_end)); ++i) {
18827dd7cddfSDavid du Colombier          if(       j <= 0) {
18837dd7cddfSDavid du Colombier             bpm[i] = 0;
18847dd7cddfSDavid du Colombier          } else if(j >= 8) {
18857dd7cddfSDavid du Colombier             bpm[i] = 0xff;
18867dd7cddfSDavid du Colombier             j -= 8;
18877dd7cddfSDavid du Colombier          } else {
18887dd7cddfSDavid du Colombier             bpm[i] = 0xff ^ ((1<<(8-j))-1);
18897dd7cddfSDavid du Colombier             j  = 0;
18907dd7cddfSDavid du Colombier          }
18917dd7cddfSDavid du Colombier          bpm[i] &= bpw[i];
18927dd7cddfSDavid du Colombier       }
18937dd7cddfSDavid du Colombier 
18947dd7cddfSDavid du Colombier /*
18957dd7cddfSDavid du Colombier  * Call super-class open
18967dd7cddfSDavid du Colombier  */
18977dd7cddfSDavid du Colombier 
18987dd7cddfSDavid du Colombier       return gdev_prn_open(pdev);
18997dd7cddfSDavid du Colombier 
19007dd7cddfSDavid du Colombier    } else {
19017dd7cddfSDavid du Colombier 
1902*593dc095SDavid du Colombier       stc_freedata(sd->memory, &sd->stc);
19037dd7cddfSDavid du Colombier 
19047dd7cddfSDavid du Colombier       return_error(code);
19057dd7cddfSDavid du Colombier    }
19067dd7cddfSDavid du Colombier 
19077dd7cddfSDavid du Colombier }
19087dd7cddfSDavid du Colombier 
19097dd7cddfSDavid du Colombier /***
19107dd7cddfSDavid du Colombier  *** stc_close: release the internal data
19117dd7cddfSDavid du Colombier  ***/
19127dd7cddfSDavid du Colombier private int
stc_close(gx_device * pdev)19137dd7cddfSDavid du Colombier stc_close(gx_device *pdev)
19147dd7cddfSDavid du Colombier {
1915*593dc095SDavid du Colombier    stc_freedata(pdev->memory, &((stcolor_device *) pdev)->stc);
19167dd7cddfSDavid du Colombier    ((stcolor_device *) pdev)->stc.flags &= ~STCOK4GO;
19177dd7cddfSDavid du Colombier    return gdev_prn_close(pdev);
19187dd7cddfSDavid du Colombier }
19197dd7cddfSDavid du Colombier 
19207dd7cddfSDavid du Colombier 
19217dd7cddfSDavid du Colombier /***
19227dd7cddfSDavid du Colombier  *** Function for Bit-Truncation, including direct-byte-transfer
19237dd7cddfSDavid du Colombier  ***/
19247dd7cddfSDavid du Colombier private gx_color_value
stc_truncate(stcolor_device * sd,int i,gx_color_value v)19257dd7cddfSDavid du Colombier stc_truncate(stcolor_device *sd,int i,gx_color_value v)
19267dd7cddfSDavid du Colombier {
19277dd7cddfSDavid du Colombier 
19287dd7cddfSDavid du Colombier    if(sd->stc.bits < gx_color_value_bits) {
19297dd7cddfSDavid du Colombier       if(sd->stc.code[i] != NULL) {
19307dd7cddfSDavid du Colombier /*
19317dd7cddfSDavid du Colombier  * Perform binary search in the code-array
19327dd7cddfSDavid du Colombier  */
19337dd7cddfSDavid du Colombier          long  s;
19347dd7cddfSDavid du Colombier          gx_color_value *p;
19357dd7cddfSDavid du Colombier 
19367dd7cddfSDavid du Colombier          s = sd->stc.bits > 1 ? 1L<<(sd->stc.bits-2) : 0L;
19377dd7cddfSDavid du Colombier          p = sd->stc.code[i]+(1L<<(sd->stc.bits-1));
19387dd7cddfSDavid du Colombier 
19397dd7cddfSDavid du Colombier          while(s > 0) {
19407dd7cddfSDavid du Colombier             if(v > *p) {
19417dd7cddfSDavid du Colombier                p += s;
19427dd7cddfSDavid du Colombier             } else if(v < p[-1]) {
19437dd7cddfSDavid du Colombier                p -= s;
19447dd7cddfSDavid du Colombier             } else {
19457dd7cddfSDavid du Colombier                if((v-p[-1]) < (p[0]-v)) p -= 1;
19467dd7cddfSDavid du Colombier                break;
19477dd7cddfSDavid du Colombier             }
19487dd7cddfSDavid du Colombier             s >>= 1;
19497dd7cddfSDavid du Colombier          }
19507dd7cddfSDavid du Colombier          if((v-p[-1]) < (p[0]-v)) p -= 1;
19517dd7cddfSDavid du Colombier          v = p - sd->stc.code[i];
19527dd7cddfSDavid du Colombier 
19537dd7cddfSDavid du Colombier       } else {
19547dd7cddfSDavid du Colombier 
19557dd7cddfSDavid du Colombier          v >>= gx_color_value_bits-sd->stc.bits;
19567dd7cddfSDavid du Colombier 
19577dd7cddfSDavid du Colombier       }
19587dd7cddfSDavid du Colombier 
19597dd7cddfSDavid du Colombier /*
19607dd7cddfSDavid du Colombier       V = (((1L<<D->stc.bits)-1)*V+(gx_max_color_value>>1))\
19617dd7cddfSDavid du Colombier           /gx_max_color_value;                             \
19627dd7cddfSDavid du Colombier */
19637dd7cddfSDavid du Colombier    }
19647dd7cddfSDavid du Colombier    return v;
19657dd7cddfSDavid du Colombier }
19667dd7cddfSDavid du Colombier 
19677dd7cddfSDavid du Colombier private gx_color_value
stc_truncate1(stcolor_device * sd,int i,gx_color_value v)19687dd7cddfSDavid du Colombier stc_truncate1(stcolor_device *sd,int i,gx_color_value v)
19697dd7cddfSDavid du Colombier {
19707dd7cddfSDavid du Colombier 
19717dd7cddfSDavid du Colombier    return sd->stc.vals[i][stc_truncate(sd,i,v)];
19727dd7cddfSDavid du Colombier }
19737dd7cddfSDavid du Colombier 
19747dd7cddfSDavid du Colombier /***
19757dd7cddfSDavid du Colombier  *** Expansion of indices for reverse-mapping
19767dd7cddfSDavid du Colombier  ***/
19777dd7cddfSDavid du Colombier private gx_color_value
stc_expand(stcolor_device * sd,int i,gx_color_index col)19787dd7cddfSDavid du Colombier stc_expand(stcolor_device *sd,int i,gx_color_index col)
19797dd7cddfSDavid du Colombier {
19807dd7cddfSDavid du Colombier 
19817dd7cddfSDavid du Colombier    gx_color_index cv;
19827dd7cddfSDavid du Colombier    gx_color_index l = (1<<sd->stc.bits)-1;
19837dd7cddfSDavid du Colombier 
19847dd7cddfSDavid du Colombier    if(sd->stc.code[i] != NULL) {
19857dd7cddfSDavid du Colombier 
19867dd7cddfSDavid du Colombier       cv  = sd->stc.code[i][col & l];
19877dd7cddfSDavid du Colombier 
19887dd7cddfSDavid du Colombier    } else if(sd->stc.bits < gx_color_value_bits) {
19897dd7cddfSDavid du Colombier 
19907dd7cddfSDavid du Colombier       cv  = (col & l)<<(gx_color_value_bits-sd->stc.bits);
19917dd7cddfSDavid du Colombier       cv += (col & l)/l * ((1<<(gx_color_value_bits-sd->stc.bits))-1);
19927dd7cddfSDavid du Colombier 
19937dd7cddfSDavid du Colombier    } else if(sd->stc.bits > gx_color_value_bits) {
19947dd7cddfSDavid du Colombier 
19957dd7cddfSDavid du Colombier       cv  = (col & l)>>(sd->stc.bits-gx_color_value_bits);
19967dd7cddfSDavid du Colombier 
19977dd7cddfSDavid du Colombier    } else {
19987dd7cddfSDavid du Colombier 
19997dd7cddfSDavid du Colombier       cv  = col & l;
20007dd7cddfSDavid du Colombier 
20017dd7cddfSDavid du Colombier    }
20027dd7cddfSDavid du Colombier 
20037dd7cddfSDavid du Colombier    return cv;
20047dd7cddfSDavid du Colombier }
20057dd7cddfSDavid du Colombier 
20067dd7cddfSDavid du Colombier /***
20077dd7cddfSDavid du Colombier  *** color-mapping of gray-scales
20087dd7cddfSDavid du Colombier  ***/
20097dd7cddfSDavid du Colombier private gx_color_index
stc_map_gray_color(gx_device * pdev,const gx_color_value cv[])2010*593dc095SDavid du Colombier stc_map_gray_color(gx_device *pdev, const gx_color_value cv[])
20117dd7cddfSDavid du Colombier {
20127dd7cddfSDavid du Colombier 
20137dd7cddfSDavid du Colombier    stcolor_device *sd = (stcolor_device *) pdev;
20147dd7cddfSDavid du Colombier    gx_color_index rv;
2015*593dc095SDavid du Colombier    gx_color_value r = cv[0];
2016*593dc095SDavid du Colombier    gx_color_value g = cv[1];
2017*593dc095SDavid du Colombier    gx_color_value b = cv[2];
20187dd7cddfSDavid du Colombier 
20197dd7cddfSDavid du Colombier    if((r == g) && (g == b)) {
20207dd7cddfSDavid du Colombier 
20217dd7cddfSDavid du Colombier       rv = gx_max_color_value - r;
20227dd7cddfSDavid du Colombier 
20237dd7cddfSDavid du Colombier    } else if(sd->stc.am != NULL) {
20247dd7cddfSDavid du Colombier       float *m,fv;
20257dd7cddfSDavid du Colombier 
20267dd7cddfSDavid du Colombier       m   = sd->stc.am;
20277dd7cddfSDavid du Colombier 
20287dd7cddfSDavid du Colombier       fv  = gx_max_color_value;
20297dd7cddfSDavid du Colombier       fv -= *m++ * (float) r; fv -= *m++ * (float) g; fv -= *m   * (float) b;
20307dd7cddfSDavid du Colombier 
20317dd7cddfSDavid du Colombier       if(     fv < 0.0)                      rv = 0;
20327dd7cddfSDavid du Colombier       else if((fv+0.5) > gx_max_color_value) rv = gx_max_color_value;
2033*593dc095SDavid du Colombier       else                                   rv = (gx_color_index)(fv+0.5);
20347dd7cddfSDavid du Colombier 
20357dd7cddfSDavid du Colombier    } else {
20367dd7cddfSDavid du Colombier 
20377dd7cddfSDavid du Colombier       rv  = ((gx_color_index)gx_max_color_value)<<3;
20387dd7cddfSDavid du Colombier       rv -= (gx_color_index) 3 * r;
20397dd7cddfSDavid du Colombier       rv -= (gx_color_index) 3 * g;
20407dd7cddfSDavid du Colombier       rv -= ((gx_color_index)b)<<1;
20417dd7cddfSDavid du Colombier       rv  = (rv+4)>>3;
20427dd7cddfSDavid du Colombier       if(rv > gx_max_color_value) rv = gx_max_color_value;
20437dd7cddfSDavid du Colombier 
20447dd7cddfSDavid du Colombier    }
20457dd7cddfSDavid du Colombier 
20467dd7cddfSDavid du Colombier    if(( sd->stc.bits                      ==    8) &&
20477dd7cddfSDavid du Colombier       ((sd->stc.dither->flags & STC_TYPE) == STC_BYTE))
20487dd7cddfSDavid du Colombier       rv = stc_truncate1(sd,0,(gx_color_value)rv);
20497dd7cddfSDavid du Colombier    else
20507dd7cddfSDavid du Colombier       rv =  stc_truncate(sd,0,(gx_color_value)rv);
20517dd7cddfSDavid du Colombier 
20527dd7cddfSDavid du Colombier    return rv;
20537dd7cddfSDavid du Colombier }
20547dd7cddfSDavid du Colombier 
20557dd7cddfSDavid du Colombier private int
stc_map_color_gray(gx_device * pdev,gx_color_index color,gx_color_value prgb[3])20567dd7cddfSDavid du Colombier stc_map_color_gray(gx_device *pdev, gx_color_index color,gx_color_value prgb[3])
20577dd7cddfSDavid du Colombier {
20587dd7cddfSDavid du Colombier    stcolor_device *sd = (stcolor_device *) pdev;
20597dd7cddfSDavid du Colombier    gx_color_index l = ((gx_color_index)1<<sd->stc.bits)-1;
20607dd7cddfSDavid du Colombier 
20617dd7cddfSDavid du Colombier    prgb[0] = gx_max_color_value - stc_expand(sd,0,color & l);
20627dd7cddfSDavid du Colombier    prgb[1] = prgb[0]; prgb[2] = prgb[0];
20637dd7cddfSDavid du Colombier 
20647dd7cddfSDavid du Colombier    return 0;
20657dd7cddfSDavid du Colombier }
20667dd7cddfSDavid du Colombier 
20677dd7cddfSDavid du Colombier /***
20687dd7cddfSDavid du Colombier  *** color-mapping of rgb-values
20697dd7cddfSDavid du Colombier  ***/
20707dd7cddfSDavid du Colombier private gx_color_index
stc_map_rgb_color(gx_device * pdev,const gx_color_value cv[])2071*593dc095SDavid du Colombier stc_map_rgb_color(gx_device *pdev, const gx_color_value cv[])
20727dd7cddfSDavid du Colombier {
20737dd7cddfSDavid du Colombier 
20747dd7cddfSDavid du Colombier    stcolor_device *sd = (stcolor_device *) pdev;
20757dd7cddfSDavid du Colombier    int          shift = sd->color_info.depth == 24 ? 8 : sd->stc.bits;
20767dd7cddfSDavid du Colombier    gx_color_index  rv = 0;
2077*593dc095SDavid du Colombier    gx_color_value r = cv[0];
2078*593dc095SDavid du Colombier    gx_color_value g = cv[1];
2079*593dc095SDavid du Colombier    gx_color_value b = cv[2];
20807dd7cddfSDavid du Colombier    if((sd->stc.am != NULL) && ((r != g) || (g != b))) {
20817dd7cddfSDavid du Colombier       float *m,fr,fg,fb,fv;
20827dd7cddfSDavid du Colombier 
20837dd7cddfSDavid du Colombier       m  = sd->stc.am;
20847dd7cddfSDavid du Colombier       fr = r; fg = g; fb = b;
20857dd7cddfSDavid du Colombier 
20867dd7cddfSDavid du Colombier       fv = *m++ * fr; fv += *m++ * fg; fv += *m++ * fb;
20877dd7cddfSDavid du Colombier 
20887dd7cddfSDavid du Colombier       if(     fv < 0.0)                      r = 0;
20897dd7cddfSDavid du Colombier       else if((fv+0.5) > gx_max_color_value) r = gx_max_color_value;
2090*593dc095SDavid du Colombier       else                                   r = (gx_color_value)(fv+0.5);
20917dd7cddfSDavid du Colombier 
20927dd7cddfSDavid du Colombier       fv = *m++ * fr; fv += *m++ * fg; fv += *m++ * fb;
20937dd7cddfSDavid du Colombier 
20947dd7cddfSDavid du Colombier       if(     fv < 0.0)                      g = 0;
20957dd7cddfSDavid du Colombier       else if((fv+0.5) > gx_max_color_value) g = gx_max_color_value;
2096*593dc095SDavid du Colombier       else                                   g = (gx_color_value)(fv+0.5);
20977dd7cddfSDavid du Colombier 
20987dd7cddfSDavid du Colombier       fv = *m++ * fr; fv += *m++ * fg; fv += *m++ * fb;
20997dd7cddfSDavid du Colombier 
21007dd7cddfSDavid du Colombier       if(     fv < 0.0)                      b = 0;
21017dd7cddfSDavid du Colombier       else if((fv+0.5) > gx_max_color_value) b = gx_max_color_value;
2102*593dc095SDavid du Colombier       else                                   b = (gx_color_value)(fv+0.5);
21037dd7cddfSDavid du Colombier 
21047dd7cddfSDavid du Colombier    }
21057dd7cddfSDavid du Colombier 
21067dd7cddfSDavid du Colombier    if(( sd->stc.bits                      ==    8) &&
21077dd7cddfSDavid du Colombier       ((sd->stc.dither->flags & STC_TYPE) == STC_BYTE)) {
21087dd7cddfSDavid du Colombier       rv =               stc_truncate1(sd,0,r);
21097dd7cddfSDavid du Colombier       rv = (rv<<shift) | stc_truncate1(sd,1,g);
21107dd7cddfSDavid du Colombier       rv = (rv<<shift) | stc_truncate1(sd,2,b);
21117dd7cddfSDavid du Colombier    } else {
21127dd7cddfSDavid du Colombier       rv =                stc_truncate(sd,0,r);
21137dd7cddfSDavid du Colombier       rv = (rv<<shift) |  stc_truncate(sd,1,g);
21147dd7cddfSDavid du Colombier       rv = (rv<<shift) |  stc_truncate(sd,2,b);
21157dd7cddfSDavid du Colombier    }
21167dd7cddfSDavid du Colombier 
21177dd7cddfSDavid du Colombier    return rv;
21187dd7cddfSDavid du Colombier }
21197dd7cddfSDavid du Colombier 
21207dd7cddfSDavid du Colombier private int
stc_map_color_rgb(gx_device * pdev,gx_color_index color,gx_color_value prgb[3])21217dd7cddfSDavid du Colombier stc_map_color_rgb(gx_device *pdev, gx_color_index color,gx_color_value prgb[3])
21227dd7cddfSDavid du Colombier {
21237dd7cddfSDavid du Colombier 
21247dd7cddfSDavid du Colombier    stcolor_device *sd = (stcolor_device *) pdev;
21257dd7cddfSDavid du Colombier    int          shift = sd->color_info.depth == 24 ? 8 : sd->stc.bits;
21267dd7cddfSDavid du Colombier    gx_color_index l =   ((gx_color_index)1<<sd->stc.bits)-1;
21277dd7cddfSDavid du Colombier 
21287dd7cddfSDavid du Colombier    prgb[0] = stc_expand(sd,0,((color>>(shift<<1)) & l));
21297dd7cddfSDavid du Colombier    prgb[1] = stc_expand(sd,1,((color>> shift    ) & l));
21307dd7cddfSDavid du Colombier    prgb[2] = stc_expand(sd,2,( color              & l));
21317dd7cddfSDavid du Colombier 
21327dd7cddfSDavid du Colombier    return 0;
21337dd7cddfSDavid du Colombier }
21347dd7cddfSDavid du Colombier 
21357dd7cddfSDavid du Colombier /***
21367dd7cddfSDavid du Colombier  *** color-mapping of cmyk-values
21377dd7cddfSDavid du Colombier  ***/
21387dd7cddfSDavid du Colombier private gx_color_index
stc_map_cmyk_color(gx_device * pdev,const gx_color_value cv[])2139*593dc095SDavid du Colombier stc_map_cmyk_color(gx_device *pdev, const gx_color_value cv[])
21407dd7cddfSDavid du Colombier {
21417dd7cddfSDavid du Colombier 
21427dd7cddfSDavid du Colombier    stcolor_device *sd = (stcolor_device *) pdev;
21437dd7cddfSDavid du Colombier    int          shift = sd->color_info.depth == 32 ? 8 : sd->stc.bits;
21447dd7cddfSDavid du Colombier    gx_color_index rv = 0;
2145*593dc095SDavid du Colombier    gx_color_value c = cv[0];
2146*593dc095SDavid du Colombier    gx_color_value m = cv[1];
2147*593dc095SDavid du Colombier    gx_color_value y = cv[2];
2148*593dc095SDavid du Colombier    gx_color_value k = cv[3];
21497dd7cddfSDavid du Colombier 
21507dd7cddfSDavid du Colombier    if((c == m) && (m == y)) {
21517dd7cddfSDavid du Colombier 
21527dd7cddfSDavid du Colombier       k = c > k ? c : k;
21537dd7cddfSDavid du Colombier       c = m = y = 0;
21547dd7cddfSDavid du Colombier 
21557dd7cddfSDavid du Colombier       if(( sd->stc.bits                      ==    8) &&
21567dd7cddfSDavid du Colombier       ((sd->stc.dither->flags & STC_TYPE) == STC_BYTE)) {
21577dd7cddfSDavid du Colombier          k  = stc_truncate1(sd,3,k);
21587dd7cddfSDavid du Colombier       } else {
21597dd7cddfSDavid du Colombier          k  =  stc_truncate(sd,3,k);
21607dd7cddfSDavid du Colombier       }
21617dd7cddfSDavid du Colombier 
21627dd7cddfSDavid du Colombier    } else {
21637dd7cddfSDavid du Colombier 
21647dd7cddfSDavid du Colombier       if(sd->stc.am != NULL) {
21657dd7cddfSDavid du Colombier 
21667dd7cddfSDavid du Colombier          float *a,fc,fm,fy,fk,fv;
21677dd7cddfSDavid du Colombier 
21687dd7cddfSDavid du Colombier          if(k == 0) { /* no separated black yet */
21697dd7cddfSDavid du Colombier             k  = c < m ? c : m;
21707dd7cddfSDavid du Colombier             k  = k < y ? k : y;
21717dd7cddfSDavid du Colombier             if(k) { /* no black at all */
21727dd7cddfSDavid du Colombier                c -= k;
21737dd7cddfSDavid du Colombier                m -= k;
21747dd7cddfSDavid du Colombier                y -= k;
21757dd7cddfSDavid du Colombier            }       /* no black at all */
21767dd7cddfSDavid du Colombier          }            /* no separated black yet */
21777dd7cddfSDavid du Colombier 
21787dd7cddfSDavid du Colombier          a  = sd->stc.am;
21797dd7cddfSDavid du Colombier          fc = c; fm = m; fy = y; fk = k;
21807dd7cddfSDavid du Colombier 
21817dd7cddfSDavid du Colombier          fv = *a++ * fc; fv += *a++ * fm; fv += *a++ * fy; fv += *a++ * fk;
21827dd7cddfSDavid du Colombier          if(     fv < 0.0)                      c = 0;
21837dd7cddfSDavid du Colombier          else if((fv+0.5) > gx_max_color_value) c = gx_max_color_value;
2184*593dc095SDavid du Colombier          else                                   c = (gx_color_value)(fv+0.5);
21857dd7cddfSDavid du Colombier 
21867dd7cddfSDavid du Colombier          fv = *a++ * fc; fv += *a++ * fm; fv += *a++ * fy; fv += *a++ * fk;
21877dd7cddfSDavid du Colombier          if(     fv < 0.0)                      m = 0;
21887dd7cddfSDavid du Colombier          else if((fv+0.5) > gx_max_color_value) m = gx_max_color_value;
2189*593dc095SDavid du Colombier          else                                   m = (gx_color_value)(fv+0.5);
21907dd7cddfSDavid du Colombier 
21917dd7cddfSDavid du Colombier          fv = *a++ * fc; fv += *a++ * fm; fv += *a++ * fy; fv += *a++ * fk;
21927dd7cddfSDavid du Colombier          if(     fv < 0.0)                      y = 0;
21937dd7cddfSDavid du Colombier          else if((fv+0.5) > gx_max_color_value) y = gx_max_color_value;
2194*593dc095SDavid du Colombier          else                                   y = (gx_color_value)(fv+0.5);
21957dd7cddfSDavid du Colombier 
21967dd7cddfSDavid du Colombier          fv = *a++ * fc; fv += *a++ * fm; fv += *a++ * fy; fv += *a++ * fk;
21977dd7cddfSDavid du Colombier          if(     fv < 0.0)                      k = 0;
21987dd7cddfSDavid du Colombier          else if((fv+0.5) > gx_max_color_value) k = gx_max_color_value;
2199*593dc095SDavid du Colombier          else                                   k = (gx_color_value)(fv+0.5);
22007dd7cddfSDavid du Colombier 
22017dd7cddfSDavid du Colombier       } else if(k == 0) {
22027dd7cddfSDavid du Colombier 
22037dd7cddfSDavid du Colombier          k  = c < m ? c : m;
22047dd7cddfSDavid du Colombier          k  = k < y ? k : y;
22057dd7cddfSDavid du Colombier       }
22067dd7cddfSDavid du Colombier 
22077dd7cddfSDavid du Colombier       if(( sd->stc.bits                      ==    8) &&
22087dd7cddfSDavid du Colombier          ((sd->stc.dither->flags & STC_TYPE) == STC_BYTE)) {
22097dd7cddfSDavid du Colombier          c = stc_truncate1(sd,0,c);
22107dd7cddfSDavid du Colombier          m = stc_truncate1(sd,1,m);
22117dd7cddfSDavid du Colombier          y = stc_truncate1(sd,2,y);
22127dd7cddfSDavid du Colombier          k = stc_truncate1(sd,3,k);
22137dd7cddfSDavid du Colombier       } else {
22147dd7cddfSDavid du Colombier          c = stc_truncate(sd,0,c);
22157dd7cddfSDavid du Colombier          m = stc_truncate(sd,1,m);
22167dd7cddfSDavid du Colombier          y = stc_truncate(sd,2,y);
22177dd7cddfSDavid du Colombier          k = stc_truncate(sd,3,k);
22187dd7cddfSDavid du Colombier       }
22197dd7cddfSDavid du Colombier    }
22207dd7cddfSDavid du Colombier 
22217dd7cddfSDavid du Colombier    rv =               c;
22227dd7cddfSDavid du Colombier    rv = (rv<<shift) | m;
22237dd7cddfSDavid du Colombier    rv = (rv<<shift) | y;
22247dd7cddfSDavid du Colombier    rv = (rv<<shift) | k;
22257dd7cddfSDavid du Colombier 
22267dd7cddfSDavid du Colombier    if(rv == gx_no_color_index) rv ^= 1;
22277dd7cddfSDavid du Colombier 
22287dd7cddfSDavid du Colombier    return rv;
22297dd7cddfSDavid du Colombier }
22307dd7cddfSDavid du Colombier 
2231*593dc095SDavid du Colombier /* Modified to be a "decode_color" routine */
22327dd7cddfSDavid du Colombier private int
stc_map_color_cmyk(gx_device * pdev,gx_color_index color,gx_color_value cv[4])2233*593dc095SDavid du Colombier stc_map_color_cmyk(gx_device *pdev, gx_color_index color,gx_color_value cv[4])
22347dd7cddfSDavid du Colombier {
22357dd7cddfSDavid du Colombier 
22367dd7cddfSDavid du Colombier    stcolor_device *sd = (stcolor_device *) pdev;
22377dd7cddfSDavid du Colombier    int          shift = sd->color_info.depth == 32 ? 8 : sd->stc.bits;
22387dd7cddfSDavid du Colombier    gx_color_index   l = ((gx_color_index)1<<sd->stc.bits)-1;
22397dd7cddfSDavid du Colombier    gx_color_value c,m,y,k;
22407dd7cddfSDavid du Colombier 
22417dd7cddfSDavid du Colombier    k = stc_expand(sd,3, color & l); color >>= shift;
22427dd7cddfSDavid du Colombier    y = stc_expand(sd,2, color & l); color >>= shift;
22437dd7cddfSDavid du Colombier    m = stc_expand(sd,1, color & l); color >>= shift;
22447dd7cddfSDavid du Colombier    c = stc_expand(sd,0, color & l);
22457dd7cddfSDavid du Colombier 
2246*593dc095SDavid du Colombier 
2247*593dc095SDavid du Colombier    cv[0] = c;
2248*593dc095SDavid du Colombier    cv[1] = m;
2249*593dc095SDavid du Colombier    cv[2] = y;
2250*593dc095SDavid du Colombier    cv[3] = k;
2251*593dc095SDavid du Colombier 
22527dd7cddfSDavid du Colombier    return 0;
22537dd7cddfSDavid du Colombier }
22547dd7cddfSDavid du Colombier 
22557dd7cddfSDavid du Colombier /***
22567dd7cddfSDavid du Colombier  *** color-mapping of cmyk10-values
22577dd7cddfSDavid du Colombier  ***/
22587dd7cddfSDavid du Colombier private gx_color_index
stc_map_cmyk10_color(gx_device * pdev,const gx_color_value cv[])2259*593dc095SDavid du Colombier stc_map_cmyk10_color(gx_device *pdev, const gx_color_value cv[])
22607dd7cddfSDavid du Colombier {
22617dd7cddfSDavid du Colombier 
22627dd7cddfSDavid du Colombier    stcolor_device *sd = (stcolor_device *) pdev;
22637dd7cddfSDavid du Colombier    int             mode;
22647dd7cddfSDavid du Colombier    gx_color_index rv  = 0;
22657dd7cddfSDavid du Colombier 
2266*593dc095SDavid du Colombier    gx_color_value c = cv[0];
2267*593dc095SDavid du Colombier    gx_color_value m = cv[1];
2268*593dc095SDavid du Colombier    gx_color_value y = cv[2];
2269*593dc095SDavid du Colombier    gx_color_value k = cv[3];
2270*593dc095SDavid du Colombier 
22717dd7cddfSDavid du Colombier    if((c == m) && (m == y)) {
22727dd7cddfSDavid du Colombier 
22737dd7cddfSDavid du Colombier       k = c > k ? c : k;
22747dd7cddfSDavid du Colombier       c = m = y = 0;
22757dd7cddfSDavid du Colombier       mode = 3;
22767dd7cddfSDavid du Colombier 
22777dd7cddfSDavid du Colombier    } else {
22787dd7cddfSDavid du Colombier 
22797dd7cddfSDavid du Colombier       if(sd->stc.am != NULL) {
22807dd7cddfSDavid du Colombier 
22817dd7cddfSDavid du Colombier          float *a,fc,fm,fy,fk,fv;
22827dd7cddfSDavid du Colombier 
22837dd7cddfSDavid du Colombier          k  = c < m ? c : m;
22847dd7cddfSDavid du Colombier          k  = k < y ? k : y;
22857dd7cddfSDavid du Colombier          if(k) { /* no black at all */
22867dd7cddfSDavid du Colombier             c -= k;
22877dd7cddfSDavid du Colombier             m -= k;
22887dd7cddfSDavid du Colombier             y -= k;
22897dd7cddfSDavid du Colombier          }       /* no black at all */
22907dd7cddfSDavid du Colombier 
22917dd7cddfSDavid du Colombier          a  = sd->stc.am;
22927dd7cddfSDavid du Colombier          fc = c; fm = m; fy = y; fk = k;
22937dd7cddfSDavid du Colombier 
22947dd7cddfSDavid du Colombier          fv = *a++ * fc; fv += *a++ * fm; fv += *a++ * fy; fv += *a++ * fk;
22957dd7cddfSDavid du Colombier          if(     fv < 0.0)                      c = 0;
22967dd7cddfSDavid du Colombier          else if((fv+0.5) > gx_max_color_value) c = gx_max_color_value;
2297*593dc095SDavid du Colombier          else                                   c = (gx_color_value)(fv+0.5);
22987dd7cddfSDavid du Colombier 
22997dd7cddfSDavid du Colombier          fv = *a++ * fc; fv += *a++ * fm; fv += *a++ * fy; fv += *a++ * fk;
23007dd7cddfSDavid du Colombier          if(     fv < 0.0)                      m = 0;
23017dd7cddfSDavid du Colombier          else if((fv+0.5) > gx_max_color_value) m = gx_max_color_value;
2302*593dc095SDavid du Colombier          else                                   m = (gx_color_value)(fv+0.5);
23037dd7cddfSDavid du Colombier 
23047dd7cddfSDavid du Colombier          fv = *a++ * fc; fv += *a++ * fm; fv += *a++ * fy; fv += *a++ * fk;
23057dd7cddfSDavid du Colombier          if(     fv < 0.0)                      y = 0;
23067dd7cddfSDavid du Colombier          else if((fv+0.5) > gx_max_color_value) y = gx_max_color_value;
2307*593dc095SDavid du Colombier          else                                   y = (gx_color_value)(fv+0.5);
23087dd7cddfSDavid du Colombier 
23097dd7cddfSDavid du Colombier       }
23107dd7cddfSDavid du Colombier 
23117dd7cddfSDavid du Colombier       if(c < m) {
23127dd7cddfSDavid du Colombier         if(c < y) { k = c; c = 0; mode = 0; }
23137dd7cddfSDavid du Colombier         else      { k = y; y = 0; mode = 2; }
23147dd7cddfSDavid du Colombier       } else {
23157dd7cddfSDavid du Colombier         if(m < y) { k = m; m = 0; mode = 1; }
23167dd7cddfSDavid du Colombier         else      { k = y; y = 0; mode = 2; }
23177dd7cddfSDavid du Colombier       }
23187dd7cddfSDavid du Colombier    }
23197dd7cddfSDavid du Colombier 
23207dd7cddfSDavid du Colombier /*
23217dd7cddfSDavid du Colombier  * truncate only the values that require it
23227dd7cddfSDavid du Colombier  */
23237dd7cddfSDavid du Colombier    if(c) c = stc_truncate(sd,0,c);
23247dd7cddfSDavid du Colombier    if(m) m = stc_truncate(sd,1,m);
23257dd7cddfSDavid du Colombier    if(y) y = stc_truncate(sd,2,y);
23267dd7cddfSDavid du Colombier    if(k) k = stc_truncate(sd,3,k);
23277dd7cddfSDavid du Colombier 
23287dd7cddfSDavid du Colombier /*
23297dd7cddfSDavid du Colombier  * make sure that truncation-white becomes white.
23307dd7cddfSDavid du Colombier  */
23317dd7cddfSDavid du Colombier    if((c|m|y) == 0) mode = 3;
23327dd7cddfSDavid du Colombier 
23337dd7cddfSDavid du Colombier /*
23347dd7cddfSDavid du Colombier  * check wether value-arrays can be bypassed
23357dd7cddfSDavid du Colombier  */
23367dd7cddfSDavid du Colombier    if(((sd->stc.dither->flags & STC_TYPE) == STC_BYTE) &&
23377dd7cddfSDavid du Colombier       ( sd->stc.dither->minmax[0]         ==    0.0 )) {
23387dd7cddfSDavid du Colombier       c = sd->stc.vals[0][c];
23397dd7cddfSDavid du Colombier       m = sd->stc.vals[1][m];
23407dd7cddfSDavid du Colombier       y = sd->stc.vals[2][y];
23417dd7cddfSDavid du Colombier       k = sd->stc.vals[3][k];
23427dd7cddfSDavid du Colombier    } else if(((sd->stc.dither->flags & STC_TYPE) == STC_LONG) &&
23437dd7cddfSDavid du Colombier              ( sd->stc.dither->minmax[0]         ==     0.0 ) &&
23447dd7cddfSDavid du Colombier              ( sd->stc.dither->minmax[1]         <=  1023.0 )) {
23457dd7cddfSDavid du Colombier       c = ((long *)(sd->stc.vals[0]))[c];
23467dd7cddfSDavid du Colombier       m = ((long *)(sd->stc.vals[1]))[m];
23477dd7cddfSDavid du Colombier       y = ((long *)(sd->stc.vals[2]))[y];
23487dd7cddfSDavid du Colombier       k = ((long *)(sd->stc.vals[3]))[k];
23497dd7cddfSDavid du Colombier    }                                                       /* direct */
23507dd7cddfSDavid du Colombier /*
23517dd7cddfSDavid du Colombier  * compute the long-representation of gx_color_index
23527dd7cddfSDavid du Colombier  */
23537dd7cddfSDavid du Colombier    switch(mode) {
23547dd7cddfSDavid du Colombier    case 0:
23557dd7cddfSDavid du Colombier       rv = (((gx_color_index) m)<<22)|
23567dd7cddfSDavid du Colombier            (((gx_color_index) y)<<12)|
23577dd7cddfSDavid du Colombier            (((gx_color_index) k)<< 2)|mode;
23587dd7cddfSDavid du Colombier       break;
23597dd7cddfSDavid du Colombier    case 1:
23607dd7cddfSDavid du Colombier       rv = (((gx_color_index) c)<<22)|
23617dd7cddfSDavid du Colombier            (((gx_color_index) y)<<12)|
23627dd7cddfSDavid du Colombier            (((gx_color_index) k)<< 2)|mode;
23637dd7cddfSDavid du Colombier       break;
23647dd7cddfSDavid du Colombier    case 2:
23657dd7cddfSDavid du Colombier       rv = (((gx_color_index) c)<<22)|
23667dd7cddfSDavid du Colombier            (((gx_color_index) m)<<12)|
23677dd7cddfSDavid du Colombier            (((gx_color_index) k)<< 2)|mode;
23687dd7cddfSDavid du Colombier       break;
23697dd7cddfSDavid du Colombier    default:
23707dd7cddfSDavid du Colombier       rv = (((gx_color_index) k)<< 2)|mode;
23717dd7cddfSDavid du Colombier       break;
23727dd7cddfSDavid du Colombier    }
23737dd7cddfSDavid du Colombier 
23747dd7cddfSDavid du Colombier /*
23757dd7cddfSDavid du Colombier  * We may need some swapping
23767dd7cddfSDavid du Colombier  */
23777dd7cddfSDavid du Colombier #if !arch_is_big_endian
23787dd7cddfSDavid du Colombier    {
23797dd7cddfSDavid du Colombier       union { stc_pixel cv; byte bv[4]; } ui,uo;
23807dd7cddfSDavid du Colombier       ui.cv = rv;
23817dd7cddfSDavid du Colombier       uo.bv[0] = ui.bv[3];
23827dd7cddfSDavid du Colombier       uo.bv[1] = ui.bv[2];
23837dd7cddfSDavid du Colombier       uo.bv[2] = ui.bv[1];
23847dd7cddfSDavid du Colombier       uo.bv[3] = ui.bv[0];
23857dd7cddfSDavid du Colombier       rv       = uo.cv;
23867dd7cddfSDavid du Colombier    }
23877dd7cddfSDavid du Colombier #endif
23887dd7cddfSDavid du Colombier    return rv;
23897dd7cddfSDavid du Colombier }
23907dd7cddfSDavid du Colombier 
23917dd7cddfSDavid du Colombier private int
stc_map_color_cmyk10(gx_device * pdev,gx_color_index color,gx_color_value cv[3])23927dd7cddfSDavid du Colombier stc_map_color_cmyk10(gx_device *pdev, gx_color_index color,
2393*593dc095SDavid du Colombier                      gx_color_value cv[3])
23947dd7cddfSDavid du Colombier {
23957dd7cddfSDavid du Colombier 
23967dd7cddfSDavid du Colombier    stcolor_device *sd = (stcolor_device *) pdev;
23977dd7cddfSDavid du Colombier    gx_color_value c,m,y;
23987dd7cddfSDavid du Colombier 
23997dd7cddfSDavid du Colombier /*
24007dd7cddfSDavid du Colombier  * We may need some swapping
24017dd7cddfSDavid du Colombier  */
24027dd7cddfSDavid du Colombier #if !arch_is_big_endian
24037dd7cddfSDavid du Colombier    union { stc_pixel cv; byte bv[4]; } ui,uo;
24047dd7cddfSDavid du Colombier    ui.cv = color;
24057dd7cddfSDavid du Colombier    uo.bv[0] = ui.bv[3];
24067dd7cddfSDavid du Colombier    uo.bv[1] = ui.bv[2];
24077dd7cddfSDavid du Colombier    uo.bv[2] = ui.bv[1];
24087dd7cddfSDavid du Colombier    uo.bv[3] = ui.bv[0];
24097dd7cddfSDavid du Colombier    color    = uo.cv;
24107dd7cddfSDavid du Colombier #endif
24117dd7cddfSDavid du Colombier 
24127dd7cddfSDavid du Colombier    c    =   stc_expand(sd,3,(color>>2)&0x3ff);
24137dd7cddfSDavid du Colombier 
2414*593dc095SDavid du Colombier    /* cast the 64 bit switch argument to work around broken HPUX 10 cc */
2415*593dc095SDavid du Colombier    switch((int)(color & 3)) {
24167dd7cddfSDavid du Colombier      case 0:
24177dd7cddfSDavid du Colombier         m = stc_expand(sd,1,(color>>22) & 0x3ff);
24187dd7cddfSDavid du Colombier         y = stc_expand(sd,2,(color>>12) & 0x3ff);
24197dd7cddfSDavid du Colombier         break;
24207dd7cddfSDavid du Colombier      case 1:
24217dd7cddfSDavid du Colombier         m = c;
24227dd7cddfSDavid du Colombier         c = stc_expand(sd,0,(color>>22) & 0x3ff);
24237dd7cddfSDavid du Colombier         y = stc_expand(sd,2,(color>>12) & 0x3ff);
24247dd7cddfSDavid du Colombier         break;
24257dd7cddfSDavid du Colombier      case 2:
24267dd7cddfSDavid du Colombier         y = c;
24277dd7cddfSDavid du Colombier         c = stc_expand(sd,0,(color>>22) & 0x3ff);
24287dd7cddfSDavid du Colombier         m = stc_expand(sd,1,(color>>12) & 0x3ff);
24297dd7cddfSDavid du Colombier         break;
24307dd7cddfSDavid du Colombier      default:
24317dd7cddfSDavid du Colombier         m = c;
24327dd7cddfSDavid du Colombier         y = c;
24337dd7cddfSDavid du Colombier         break;
24347dd7cddfSDavid du Colombier    }
24357dd7cddfSDavid du Colombier 
2436*593dc095SDavid du Colombier    cv[0] = c;
2437*593dc095SDavid du Colombier    cv[1] = m;
2438*593dc095SDavid du Colombier    cv[2] = y;
24397dd7cddfSDavid du Colombier 
24407dd7cddfSDavid du Colombier    return 0;
24417dd7cddfSDavid du Colombier }
24427dd7cddfSDavid du Colombier 
24437dd7cddfSDavid du Colombier /***
24447dd7cddfSDavid du Colombier  *** Macros for parameter-handling
24457dd7cddfSDavid du Colombier  ***/
24467dd7cddfSDavid du Colombier 
24477dd7cddfSDavid du Colombier #define set_param_array(A, D, S)\
24487dd7cddfSDavid du Colombier     {A.data = D; A.size = S; A.persistent = false;}
24497dd7cddfSDavid du Colombier 
24507dd7cddfSDavid du Colombier #define stc_write_null(N)                        \
24517dd7cddfSDavid du Colombier     set_param_array(pfa,defext,countof(defext))  \
24527dd7cddfSDavid du Colombier     code = param_write_null(plist,N);            \
24537dd7cddfSDavid du Colombier     if (code < 0) return code;
24547dd7cddfSDavid du Colombier 
24557dd7cddfSDavid du Colombier #define stc_write_xarray(I,Coding,Transfer)                  \
24567dd7cddfSDavid du Colombier     if(sd->stc.sizc[I] > 0) {                                \
24577dd7cddfSDavid du Colombier        set_param_array(pfa, sd->stc.extc[I],sd->stc.sizc[I]) \
24587dd7cddfSDavid du Colombier        code = param_write_float_array(plist,Coding,&pfa);    \
24597dd7cddfSDavid du Colombier     } else {                                                 \
24607dd7cddfSDavid du Colombier        code = param_write_null(plist,Coding);                \
24617dd7cddfSDavid du Colombier     }                                                        \
24627dd7cddfSDavid du Colombier     if ( code < 0 ) return code;                             \
24637dd7cddfSDavid du Colombier                                                              \
24647dd7cddfSDavid du Colombier     if(sd->stc.sizv[I] > 0)                                  \
24657dd7cddfSDavid du Colombier        set_param_array(pfa, sd->stc.extv[I],sd->stc.sizv[I]) \
24667dd7cddfSDavid du Colombier     else                                                     \
24677dd7cddfSDavid du Colombier        set_param_array(pfa,defext,countof(defext))           \
24687dd7cddfSDavid du Colombier     code = param_write_float_array(plist,Transfer,&pfa);     \
24697dd7cddfSDavid du Colombier     if ( code < 0 ) return code;
24707dd7cddfSDavid du Colombier 
24717dd7cddfSDavid du Colombier #define stc_read_null(N)                                   \
24727dd7cddfSDavid du Colombier     code = param_read_null(plist,N);                       \
24737dd7cddfSDavid du Colombier     if(code == gs_error_typecheck)                         \
24747dd7cddfSDavid du Colombier        code = param_read_float_array(plist,N,&pfa);        \
24757dd7cddfSDavid du Colombier     if(code < 0) param_signal_error(plist,N,code);         \
24767dd7cddfSDavid du Colombier     error = error > code ? code : error;
24777dd7cddfSDavid du Colombier 
24787dd7cddfSDavid du Colombier #define stc_read_xarray(I,Coding,Transfer)                 \
24797dd7cddfSDavid du Colombier     code = param_read_float_array(plist,Coding,&pfa);      \
24807dd7cddfSDavid du Colombier     if((error == 0) && (code == 0)) {                      \
24817dd7cddfSDavid du Colombier        if(pfa.size > 1) {                                  \
24827dd7cddfSDavid du Colombier           sd->stc.extc[I] = (float *) pfa.data;            \
24837dd7cddfSDavid du Colombier           sd->stc.sizc[I] = pfa.size;                      \
24847dd7cddfSDavid du Colombier        } else {                                            \
24857dd7cddfSDavid du Colombier           code = gs_error_rangecheck;                      \
24867dd7cddfSDavid du Colombier        }                                                   \
24877dd7cddfSDavid du Colombier     } else if(code < 0) {                                  \
24887dd7cddfSDavid du Colombier        code = param_read_null(plist,Coding);               \
24897dd7cddfSDavid du Colombier        if(code == 0) {                                     \
24907dd7cddfSDavid du Colombier           sd->stc.extc[I] = NULL;                          \
24917dd7cddfSDavid du Colombier           sd->stc.sizc[I] = 0;                             \
24927dd7cddfSDavid du Colombier        }                                                   \
24937dd7cddfSDavid du Colombier     }                                                      \
24947dd7cddfSDavid du Colombier     if(code < 0) param_signal_error(plist,Coding,code);    \
24957dd7cddfSDavid du Colombier     error = error > code ? code : error;                   \
24967dd7cddfSDavid du Colombier     code = param_read_float_array(plist,Transfer,&pfa);    \
24977dd7cddfSDavid du Colombier     if((error == 0) && (code == 0)) {                      \
24987dd7cddfSDavid du Colombier        sd->stc.extv[I] = (float *) pfa.data;               \
24997dd7cddfSDavid du Colombier        sd->stc.sizv[I] = pfa.size;                         \
25007dd7cddfSDavid du Colombier     } else if(code < 0) {                                  \
25017dd7cddfSDavid du Colombier        code = param_read_null(plist,Transfer);             \
25027dd7cddfSDavid du Colombier        if(code == 0) {                                     \
25037dd7cddfSDavid du Colombier           sd->stc.extv[I] = defext;                        \
25047dd7cddfSDavid du Colombier           sd->stc.sizv[I] = countof(defext);               \
25057dd7cddfSDavid du Colombier        }                                                   \
25067dd7cddfSDavid du Colombier     }                                                      \
25077dd7cddfSDavid du Colombier     if(code < 0) param_signal_error(plist,Transfer,code);  \
25087dd7cddfSDavid du Colombier     error = error > code ? code : error;
25097dd7cddfSDavid du Colombier 
25107dd7cddfSDavid du Colombier /***
25117dd7cddfSDavid du Colombier  *** Get parameters == Make them accessable via PostScript
25127dd7cddfSDavid du Colombier  ***/
25137dd7cddfSDavid du Colombier 
25147dd7cddfSDavid du Colombier private int
stc_get_params(gx_device * pdev,gs_param_list * plist)25157dd7cddfSDavid du Colombier stc_get_params(gx_device *pdev, gs_param_list *plist)
25167dd7cddfSDavid du Colombier {
25177dd7cddfSDavid du Colombier    int code,nc;
25187dd7cddfSDavid du Colombier    gs_param_string      ps;
25197dd7cddfSDavid du Colombier    gs_param_float_array pfa;
25207dd7cddfSDavid du Colombier    bool btmp;
25217dd7cddfSDavid du Colombier    stcolor_device *sd = (stcolor_device *) pdev;
25227dd7cddfSDavid du Colombier 
25237dd7cddfSDavid du Colombier    code = gdev_prn_get_params(pdev, plist);
25247dd7cddfSDavid du Colombier    if ( code < 0 ) return code;
25257dd7cddfSDavid du Colombier 
25267dd7cddfSDavid du Colombier /*
25277dd7cddfSDavid du Colombier  * Export some readonly-Parameters, used by stcinfo.ps
25287dd7cddfSDavid du Colombier  */
25297dd7cddfSDavid du Colombier    param_string_from_string(ps,"1.91");
25307dd7cddfSDavid du Colombier    code = param_write_string(plist,"Version",&ps);
25317dd7cddfSDavid du Colombier    if ( code < 0 ) return code;
25327dd7cddfSDavid du Colombier 
25337dd7cddfSDavid du Colombier    code = param_write_int(plist,"BitsPerComponent",&sd->stc.bits);
25347dd7cddfSDavid du Colombier    if ( code < 0 ) return code;
25357dd7cddfSDavid du Colombier 
25367dd7cddfSDavid du Colombier    if(sd->stc.algorithms.size > 0) {
25377dd7cddfSDavid du Colombier      code = param_write_string_array(plist,"Algorithms",&sd->stc.algorithms);
25387dd7cddfSDavid du Colombier    } else {
25397dd7cddfSDavid du Colombier      code = param_write_null(plist,"Algorithms");
25407dd7cddfSDavid du Colombier    }
25417dd7cddfSDavid du Colombier    if ( code < 0 ) return code;
25427dd7cddfSDavid du Colombier 
25437dd7cddfSDavid du Colombier /*
25447dd7cddfSDavid du Colombier  * Export OutputCode
25457dd7cddfSDavid du Colombier  */
25467dd7cddfSDavid du Colombier    switch(sd->stc.flags & STCCOMP) {
25477dd7cddfSDavid du Colombier    case STCPLAIN: param_string_from_string(ps,"plain");     break;
25487dd7cddfSDavid du Colombier    case STCDELTA: param_string_from_string(ps,"deltarow");  break;
25497dd7cddfSDavid du Colombier    default:       param_string_from_string(ps,"runlength"); break;
25507dd7cddfSDavid du Colombier    }
25517dd7cddfSDavid du Colombier    code = param_write_string(plist,"OutputCode",&ps);
25527dd7cddfSDavid du Colombier    if ( code < 0 ) return code;
25537dd7cddfSDavid du Colombier /*
25547dd7cddfSDavid du Colombier  * Export Model
25557dd7cddfSDavid du Colombier  */
25567dd7cddfSDavid du Colombier    switch(sd->stc.flags & STCMODEL) {
25577dd7cddfSDavid du Colombier    case STCST800: param_string_from_string(ps,"st800");   break;
25587dd7cddfSDavid du Colombier    case STCSTCII: param_string_from_string(ps,"stcii");   break;
25597dd7cddfSDavid du Colombier    default:       param_string_from_string(ps,"stc");     break;
25607dd7cddfSDavid du Colombier    }
25617dd7cddfSDavid du Colombier    code = param_write_string(plist,"Model",&ps);
25627dd7cddfSDavid du Colombier    if ( code < 0 ) return code;
25637dd7cddfSDavid du Colombier 
25647dd7cddfSDavid du Colombier /*
25657dd7cddfSDavid du Colombier  * Export the booleans
25667dd7cddfSDavid du Colombier  */
25677dd7cddfSDavid du Colombier #define stc_write_flag(Mask,Name)                \
25687dd7cddfSDavid du Colombier    btmp = sd->stc.flags & (Mask) ? true : false; \
25697dd7cddfSDavid du Colombier    code = param_write_bool(plist,Name,&btmp);    \
25707dd7cddfSDavid du Colombier    if ( code < 0 ) return code;
25717dd7cddfSDavid du Colombier 
25727dd7cddfSDavid du Colombier    stc_write_flag(STCUNIDIR,"Unidirectional")
25737dd7cddfSDavid du Colombier    stc_write_flag(STCUWEAVE,"Microweave")
25747dd7cddfSDavid du Colombier    btmp = sd->stc.flags & (STCUNIDIR|STCUWEAVE) ? false : true;
25757dd7cddfSDavid du Colombier    code = param_write_bool(plist,"Softweave",&btmp);
25767dd7cddfSDavid du Colombier    if ( code < 0 ) return code;
25777dd7cddfSDavid du Colombier    stc_write_flag(STCNWEAVE,"noWeave")
25787dd7cddfSDavid du Colombier    stc_write_flag(STCDFLAG0, "Flag0")
25797dd7cddfSDavid du Colombier    stc_write_flag(STCDFLAG1, "Flag1")
25807dd7cddfSDavid du Colombier    stc_write_flag(STCDFLAG2, "Flag2")
25817dd7cddfSDavid du Colombier    stc_write_flag(STCDFLAG3, "Flag3")
25827dd7cddfSDavid du Colombier    stc_write_flag(STCDFLAG4, "Flag4")
25837dd7cddfSDavid du Colombier 
25847dd7cddfSDavid du Colombier #undef stc_write_flag
25857dd7cddfSDavid du Colombier 
25867dd7cddfSDavid du Colombier #  define stc_write_int(Mask,Name,Val)         \
25877dd7cddfSDavid du Colombier       code = param_write_int(plist,Name,&Val); \
25887dd7cddfSDavid du Colombier       if ( code < 0 ) return code
25897dd7cddfSDavid du Colombier 
25907dd7cddfSDavid du Colombier    stc_write_int(STCBAND,  "escp_Band",  sd->stc.escp_m);
25917dd7cddfSDavid du Colombier    stc_write_int(STCWIDTH, "escp_Width", sd->stc.escp_width);
25927dd7cddfSDavid du Colombier    stc_write_int(STCHEIGHT,"escp_Height",sd->stc.escp_height);
25937dd7cddfSDavid du Colombier    stc_write_int(STCTOP,   "escp_Top",   sd->stc.escp_top);
25947dd7cddfSDavid du Colombier    stc_write_int(STCBOTTOM,"escp_Bottom",sd->stc.escp_bottom);
25957dd7cddfSDavid du Colombier 
25967dd7cddfSDavid du Colombier #  undef stc_write_int
25977dd7cddfSDavid du Colombier 
25987dd7cddfSDavid du Colombier    code = param_write_string(plist,"escp_Init",&sd->stc.escp_init);
25997dd7cddfSDavid du Colombier    code = param_write_string(plist,"escp_Release",&sd->stc.escp_release);
26007dd7cddfSDavid du Colombier 
26017dd7cddfSDavid du Colombier    if(sd->stc.dither != NULL) {
26027dd7cddfSDavid du Colombier       param_string_from_string(ps,sd->stc.dither->name);
26037dd7cddfSDavid du Colombier       code = param_write_string(plist,"Dithering",&ps);
26047dd7cddfSDavid du Colombier    } else {
26057dd7cddfSDavid du Colombier       code = param_write_null(plist,"Dithering");
26067dd7cddfSDavid du Colombier    }
26077dd7cddfSDavid du Colombier    if ( code < 0 ) return code;
26087dd7cddfSDavid du Colombier 
26097dd7cddfSDavid du Colombier    nc = sd->color_info.num_components;
26107dd7cddfSDavid du Colombier 
26117dd7cddfSDavid du Colombier    if(sd->stc.am != NULL) {
26127dd7cddfSDavid du Colombier       if(     nc == 1) set_param_array(pfa, sd->stc.am, 3)
26137dd7cddfSDavid du Colombier       else if(nc == 3) set_param_array(pfa, sd->stc.am, 9)
26147dd7cddfSDavid du Colombier       else             set_param_array(pfa, sd->stc.am,16)
26157dd7cddfSDavid du Colombier       code = param_write_float_array(plist,"ColorAdjustMatrix",&pfa);
26167dd7cddfSDavid du Colombier    } else {
26177dd7cddfSDavid du Colombier       code = param_write_null(plist,"ColorAdjustMatrix");
26187dd7cddfSDavid du Colombier    }
26197dd7cddfSDavid du Colombier    if ( code < 0 ) return code;
26207dd7cddfSDavid du Colombier 
26217dd7cddfSDavid du Colombier    if(nc == 1) {        /* DeviceGray */
26227dd7cddfSDavid du Colombier 
26237dd7cddfSDavid du Colombier       stc_write_xarray(0,"Kcoding","Ktransfer");
26247dd7cddfSDavid du Colombier 
26257dd7cddfSDavid du Colombier       stc_write_null("Rcoding"); stc_write_null("Rtransfer");
26267dd7cddfSDavid du Colombier       stc_write_null("Gcoding"); stc_write_null("Gtransfer");
26277dd7cddfSDavid du Colombier       stc_write_null("Bcoding"); stc_write_null("Btransfer");
26287dd7cddfSDavid du Colombier 
26297dd7cddfSDavid du Colombier       stc_write_null("Ccoding"); stc_write_null("Ctransfer");
26307dd7cddfSDavid du Colombier       stc_write_null("Mcoding"); stc_write_null("Mtransfer");
26317dd7cddfSDavid du Colombier       stc_write_null("Ycoding"); stc_write_null("Ytransfer");
26327dd7cddfSDavid du Colombier 
26337dd7cddfSDavid du Colombier    } else if(nc == 3) { /* DeviceRGB */
26347dd7cddfSDavid du Colombier 
26357dd7cddfSDavid du Colombier       stc_write_xarray(0,"Rcoding","Rtransfer");
26367dd7cddfSDavid du Colombier       stc_write_xarray(1,"Gcoding","Gtransfer");
26377dd7cddfSDavid du Colombier       stc_write_xarray(2,"Bcoding","Btransfer");
26387dd7cddfSDavid du Colombier 
26397dd7cddfSDavid du Colombier       stc_write_null("Ccoding"); stc_write_null("Ctransfer");
26407dd7cddfSDavid du Colombier       stc_write_null("Mcoding"); stc_write_null("Mtransfer");
26417dd7cddfSDavid du Colombier       stc_write_null("Ycoding"); stc_write_null("Ytransfer");
26427dd7cddfSDavid du Colombier       stc_write_null("Kcoding"); stc_write_null("Ktransfer");
26437dd7cddfSDavid du Colombier 
26447dd7cddfSDavid du Colombier    } else {             /* DeviceCMYK */
26457dd7cddfSDavid du Colombier 
26467dd7cddfSDavid du Colombier       stc_write_xarray(0,"Ccoding","Ctransfer");
26477dd7cddfSDavid du Colombier       stc_write_xarray(1,"Mcoding","Mtransfer");
26487dd7cddfSDavid du Colombier       stc_write_xarray(2,"Ycoding","Ytransfer");
26497dd7cddfSDavid du Colombier       stc_write_xarray(3,"Kcoding","Ktransfer");
26507dd7cddfSDavid du Colombier 
26517dd7cddfSDavid du Colombier       stc_write_null("Rcoding"); stc_write_null("Rtransfer");
26527dd7cddfSDavid du Colombier       stc_write_null("Gcoding"); stc_write_null("Gtransfer");
26537dd7cddfSDavid du Colombier       stc_write_null("Bcoding"); stc_write_null("Btransfer");
26547dd7cddfSDavid du Colombier 
26557dd7cddfSDavid du Colombier    }
26567dd7cddfSDavid du Colombier    return code;
26577dd7cddfSDavid du Colombier }
26587dd7cddfSDavid du Colombier 
26597dd7cddfSDavid du Colombier /***
26607dd7cddfSDavid du Colombier  *** put parameters == Store them in the device-structure
26617dd7cddfSDavid du Colombier  ***/
26627dd7cddfSDavid du Colombier 
26637dd7cddfSDavid du Colombier private int
stc_put_params(gx_device * pdev,gs_param_list * plist)26647dd7cddfSDavid du Colombier stc_put_params(gx_device *pdev, gs_param_list *plist)
26657dd7cddfSDavid du Colombier {
26667dd7cddfSDavid du Colombier    int code,error,i,l;
26677dd7cddfSDavid du Colombier    bool b1,b2,b3;
26687dd7cddfSDavid du Colombier    float fv,*fp;
26697dd7cddfSDavid du Colombier    gs_param_string      ps;
26707dd7cddfSDavid du Colombier    gs_param_string_array psa;
26717dd7cddfSDavid du Colombier    gs_param_float_array pfa;
26727dd7cddfSDavid du Colombier    stcolor_device *sd = (stcolor_device *) pdev;
26737dd7cddfSDavid du Colombier    gx_device_color_info oldcolor;
26747dd7cddfSDavid du Colombier    stc_t                oldstc;
26757dd7cddfSDavid du Colombier 
26767dd7cddfSDavid du Colombier /*
26777dd7cddfSDavid du Colombier  * save old Values
26787dd7cddfSDavid du Colombier  */
26797dd7cddfSDavid du Colombier    memcpy(&oldcolor,&sd->color_info,sizeof(oldcolor));
26807dd7cddfSDavid du Colombier    memcpy(&oldstc  ,&sd->stc       ,sizeof(oldstc  ));
26817dd7cddfSDavid du Colombier 
26827dd7cddfSDavid du Colombier /*
26837dd7cddfSDavid du Colombier  * Arrrgh:
26847dd7cddfSDavid du Colombier  * With Version 3.4x and above my simple minded read-only Parameters
26857dd7cddfSDavid du Colombier  * do not work any more. So read them here for heavens sake.
26867dd7cddfSDavid du Colombier  */
26877dd7cddfSDavid du Colombier    code = param_read_string(plist,"Version",&ps);
26887dd7cddfSDavid du Colombier    code = param_read_int(plist,"BitsPerComponent",&i);
26897dd7cddfSDavid du Colombier    code = param_read_string_array(plist,"Algorithms",&psa);
26907dd7cddfSDavid du Colombier 
26917dd7cddfSDavid du Colombier /*
26927dd7cddfSDavid du Colombier  * Fetch Major-Parameters (Model, Dithering, BitsPerPixel/BitsPerComponent)
26937dd7cddfSDavid du Colombier  */
26947dd7cddfSDavid du Colombier    error = 0;
26957dd7cddfSDavid du Colombier 
26967dd7cddfSDavid du Colombier    code  = param_read_string(plist,"Model",&ps);
26977dd7cddfSDavid du Colombier    if(code == 0) {   /* Analyze the Model-String */
26987dd7cddfSDavid du Colombier /*
26997dd7cddfSDavid du Colombier  * Arrgh: I should have known, that internal strings are not zero-terminated.
27007dd7cddfSDavid du Colombier  */
27017dd7cddfSDavid du Colombier       for(l = ps.size; (l > 0) && (ps.data[l-1] == 0); --l);
27027dd7cddfSDavid du Colombier #     define stc_putcmp(Name) \
27037dd7cddfSDavid du Colombier         ((strlen(Name) != l) || (0 != strncmp(Name, (const char *)ps.data,l)))
27047dd7cddfSDavid du Colombier 
27057dd7cddfSDavid du Colombier       sd->stc.flags &= ~STCMODEL;
27067dd7cddfSDavid du Colombier       if(     !stc_putcmp("st800"))  sd->stc.flags |= STCST800;
27077dd7cddfSDavid du Colombier       else if(!stc_putcmp("stcii"))  sd->stc.flags |= STCSTCII;
27087dd7cddfSDavid du Colombier 
27097dd7cddfSDavid du Colombier    }                 /* Analyze the Model-String */
27107dd7cddfSDavid du Colombier    if(code < 0) param_signal_error(plist,"Model",code);
27117dd7cddfSDavid du Colombier    error = error > code ? code : error;
27127dd7cddfSDavid du Colombier 
27137dd7cddfSDavid du Colombier /* If we're running for st800, #components must be 1 */
27147dd7cddfSDavid du Colombier    if(((sd->stc.flags & STCMODEL) == STCST800) &&
27157dd7cddfSDavid du Colombier       (( sd->color_info.num_components > 1) ||
27167dd7cddfSDavid du Colombier        ( sd->stc.dither                == NULL) ||
27177dd7cddfSDavid du Colombier        ((sd->stc.dither->flags & 7)    > 1))) {
27187dd7cddfSDavid du Colombier         sd->color_info.num_components  = 1;
27197dd7cddfSDavid du Colombier         sd->stc.dither = NULL;
27207dd7cddfSDavid du Colombier     }
27217dd7cddfSDavid du Colombier 
27227dd7cddfSDavid du Colombier /* Weaving isn't a feature for the st800 */
27237dd7cddfSDavid du Colombier    if((sd->stc.flags & STCMODEL) == STCST800) {
27247dd7cddfSDavid du Colombier       sd->stc.flags &= ~STCUWEAVE;
27257dd7cddfSDavid du Colombier       sd->stc.flags |=  STCNWEAVE;
27267dd7cddfSDavid du Colombier    } else if((sd->stc.flags & STCMODEL) == STCSTCII) { /* no SoftWeave */
27277dd7cddfSDavid du Colombier       sd->stc.flags |=  STCNWEAVE;
27287dd7cddfSDavid du Colombier    }
27297dd7cddfSDavid du Colombier 
27307dd7cddfSDavid du Colombier    code  = param_read_string(plist,"Dithering",&ps);
27317dd7cddfSDavid du Colombier    if(code == 0) {                     /* lookup new value new value */
27327dd7cddfSDavid du Colombier 
27337dd7cddfSDavid du Colombier       for(l = ps.size; (l > 0) && (ps.data[l-1] == 0); --l);
27347dd7cddfSDavid du Colombier 
27357dd7cddfSDavid du Colombier       for(i = 0; stc_dither[i].name != NULL; ++i)
27367dd7cddfSDavid du Colombier          if(!stc_putcmp(stc_dither[i].name)) break;
27377dd7cddfSDavid du Colombier 
27387dd7cddfSDavid du Colombier    } else if(sd->stc.dither != NULL) {  /* compute index of given value */
27397dd7cddfSDavid du Colombier 
27407dd7cddfSDavid du Colombier       i = sd->stc.dither - stc_dither;
27417dd7cddfSDavid du Colombier 
27427dd7cddfSDavid du Colombier    } else {                            /* find matching value */
27437dd7cddfSDavid du Colombier 
27447dd7cddfSDavid du Colombier       for(i = 0; stc_dither[i].name != NULL; ++i)
27457dd7cddfSDavid du Colombier          if((stc_dither[i].flags & 7) == sd->color_info.num_components) break;
27467dd7cddfSDavid du Colombier 
27477dd7cddfSDavid du Colombier    }                                   /* we've got an index */
27487dd7cddfSDavid du Colombier 
27497dd7cddfSDavid du Colombier    if(stc_dither[i].name != NULL) { /* establish data */
27507dd7cddfSDavid du Colombier 
27517dd7cddfSDavid du Colombier /*
27527dd7cddfSDavid du Colombier  * Establish new dithering algorithm & color-model
27537dd7cddfSDavid du Colombier  */
27547dd7cddfSDavid du Colombier       sd->stc.dither                = stc_dither+i;
27557dd7cddfSDavid du Colombier       sd->color_info.num_components = sd->stc.dither->flags & 7;
27567dd7cddfSDavid du Colombier   STC_TYPESWITCH(sd->stc.dither,stc_sizeofitem)
27577dd7cddfSDavid du Colombier # undef stc_sizeofitem
27587dd7cddfSDavid du Colombier       if(((sd->stc.flags & STCMODEL)    == STCST800) &&
27597dd7cddfSDavid du Colombier          ( sd->color_info.num_components > 1       ))
27607dd7cddfSDavid du Colombier          code = gs_error_rangecheck;
27617dd7cddfSDavid du Colombier 
27627dd7cddfSDavid du Colombier /*
27637dd7cddfSDavid du Colombier  * reset Parameters related to the color-model, if it changed
27647dd7cddfSDavid du Colombier  */
27657dd7cddfSDavid du Colombier 
27667dd7cddfSDavid du Colombier       if(sd->color_info.num_components != oldcolor.num_components) {
27677dd7cddfSDavid du Colombier 
27687dd7cddfSDavid du Colombier          for(i = 0; i < sd->color_info.num_components; ++i) {
27697dd7cddfSDavid du Colombier             sd->stc.extv[i]   = (float *) defext;
27707dd7cddfSDavid du Colombier             sd->stc.sizv[i]   = countof(defext);
27717dd7cddfSDavid du Colombier 
27727dd7cddfSDavid du Colombier             sd->stc.extc[i] = NULL;
27737dd7cddfSDavid du Colombier             sd->stc.sizc[i] = 0;
27747dd7cddfSDavid du Colombier 
27757dd7cddfSDavid du Colombier          }
27767dd7cddfSDavid du Colombier 
27777dd7cddfSDavid du Colombier          sd->stc.am = NULL;
27787dd7cddfSDavid du Colombier 
27797dd7cddfSDavid du Colombier       } else { /* guarantee, that extvals is present */
27807dd7cddfSDavid du Colombier 
27817dd7cddfSDavid du Colombier          for(i = 0; i < sd->color_info.num_components; ++i) {
27827dd7cddfSDavid du Colombier             if(sd->stc.sizv[i] < 2) {
27837dd7cddfSDavid du Colombier                sd->stc.extv[i]   = (float *) defext;
27847dd7cddfSDavid du Colombier                sd->stc.sizv[i]   = countof(defext);
27857dd7cddfSDavid du Colombier             }
27867dd7cddfSDavid du Colombier          }
27877dd7cddfSDavid du Colombier       }
27887dd7cddfSDavid du Colombier 
27897dd7cddfSDavid du Colombier       for(i = sd->color_info.num_components; i < 4; ++ i) { /* clear unused */
27907dd7cddfSDavid du Colombier          sd->stc.extv[i]   = NULL;
27917dd7cddfSDavid du Colombier          sd->stc.sizv[i]   = 0;
27927dd7cddfSDavid du Colombier          sd->stc.vals[i]   = NULL;
27937dd7cddfSDavid du Colombier 
27947dd7cddfSDavid du Colombier          sd->stc.extc[i] = NULL;
27957dd7cddfSDavid du Colombier          sd->stc.sizc[i] = 0;
27967dd7cddfSDavid du Colombier          sd->stc.code[i] = NULL;
27977dd7cddfSDavid du Colombier 
27987dd7cddfSDavid du Colombier       }                                                     /* clear unused */
27997dd7cddfSDavid du Colombier 
28007dd7cddfSDavid du Colombier /*
28017dd7cddfSDavid du Colombier  * Guess default depth from range of values
28027dd7cddfSDavid du Colombier  */
28037dd7cddfSDavid du Colombier       if((sd->stc.dither != oldstc.dither)||(oldstc.vals[0] == NULL)) {
28047dd7cddfSDavid du Colombier 
28057dd7cddfSDavid du Colombier          if((sd->stc.dither->flags & STC_CMYK10) != 0) {
28067dd7cddfSDavid du Colombier 
28077dd7cddfSDavid du Colombier             sd->stc.flags       |= STCCMYK10;
28087dd7cddfSDavid du Colombier             sd->stc.bits         = 10;
28097dd7cddfSDavid du Colombier             sd->color_info.depth = 32;
28107dd7cddfSDavid du Colombier 
28117dd7cddfSDavid du Colombier          } else {
28127dd7cddfSDavid du Colombier 
28137dd7cddfSDavid du Colombier             sd->stc.flags       &= ~STCCMYK10;
28147dd7cddfSDavid du Colombier 
28157dd7cddfSDavid du Colombier             if((sd->stc.dither->flags & STC_FLOAT) != STC_FLOAT) {
28167dd7cddfSDavid du Colombier                fv = 2.0;
28177dd7cddfSDavid du Colombier                for(i = 1;(i  < gx_color_value_bits) &&
28187dd7cddfSDavid du Colombier                   (fv <= (sd->stc.dither->minmax[1]-sd->stc.dither->minmax[0]));
28197dd7cddfSDavid du Colombier                  ++i) fv *= 2.0;
28207dd7cddfSDavid du Colombier 
28217dd7cddfSDavid du Colombier             } else {
28227dd7cddfSDavid du Colombier                i = 8; /* arbitrary */
28237dd7cddfSDavid du Colombier             }
28247dd7cddfSDavid du Colombier 
28257dd7cddfSDavid du Colombier             if((i*sd->color_info.num_components) > (sizeof(stc_pixel)*8)) {
28267dd7cddfSDavid du Colombier 
28277dd7cddfSDavid du Colombier                sd->stc.bits         = (sizeof(stc_pixel)*8) /
28287dd7cddfSDavid du Colombier                                        sd->color_info.num_components;
28297dd7cddfSDavid du Colombier                sd->color_info.depth = sd->stc.bits * sd->color_info.num_components;
28307dd7cddfSDavid du Colombier 
28317dd7cddfSDavid du Colombier             } else {
28327dd7cddfSDavid du Colombier 
28337dd7cddfSDavid du Colombier                sd->stc.bits         = i;
28347dd7cddfSDavid du Colombier                sd->color_info.depth = sd->stc.bits * sd->color_info.num_components;
28357dd7cddfSDavid du Colombier 
28367dd7cddfSDavid du Colombier             }
28377dd7cddfSDavid du Colombier          }
28387dd7cddfSDavid du Colombier       }
28397dd7cddfSDavid du Colombier 
28407dd7cddfSDavid du Colombier    } else {
28417dd7cddfSDavid du Colombier 
28427dd7cddfSDavid du Colombier       code = gs_error_rangecheck;
28437dd7cddfSDavid du Colombier 
28447dd7cddfSDavid du Colombier    }               /* verify new value */
28457dd7cddfSDavid du Colombier    if(code < 0) param_signal_error(plist,"Dithering",code);
28467dd7cddfSDavid du Colombier    error = error > code ? code : error;
28477dd7cddfSDavid du Colombier 
28487dd7cddfSDavid du Colombier /*
28497dd7cddfSDavid du Colombier  * now fetch the desired depth, if the algorithm allows it
28507dd7cddfSDavid du Colombier  */
28517dd7cddfSDavid du Colombier /*
28527dd7cddfSDavid du Colombier  * Arrrgh: We get code == 0, even if nobody sets BitsPerPixel.
28537dd7cddfSDavid du Colombier  *         The value is the old one, but this may cause trouble
28547dd7cddfSDavid du Colombier  *         with CMYK10.
28557dd7cddfSDavid du Colombier  */
28567dd7cddfSDavid du Colombier    code = param_read_int(plist, "BitsPerPixel", &i);
28577dd7cddfSDavid du Colombier    if((error == 0) && (code == 0) &&
28587dd7cddfSDavid du Colombier       (((sd->stc.flags & STCCMYK10) == 0) || (i != sd->color_info.depth))) {
28597dd7cddfSDavid du Colombier 
28607dd7cddfSDavid du Colombier       if((1 > i) || (i > (sizeof(stc_pixel)*8)))
28617dd7cddfSDavid du Colombier          code = gs_error_rangecheck;
28627dd7cddfSDavid du Colombier       else
28637dd7cddfSDavid du Colombier          sd->color_info.depth = i;
28647dd7cddfSDavid du Colombier 
28657dd7cddfSDavid du Colombier       sd->stc.bits = i / sd->color_info.num_components;
28667dd7cddfSDavid du Colombier 
28677dd7cddfSDavid du Colombier       if(1 > sd->stc.bits) code = gs_error_rangecheck;
28687dd7cddfSDavid du Colombier 
28697dd7cddfSDavid du Colombier       if((sd->stc.dither->flags & STC_DIRECT) &&
28707dd7cddfSDavid du Colombier          (sd->stc.dither->flags & STC_CMYK10))
28717dd7cddfSDavid du Colombier          code           = gs_error_rangecheck;
28727dd7cddfSDavid du Colombier       else
28737dd7cddfSDavid du Colombier          sd->stc.flags &= ~STCCMYK10;
28747dd7cddfSDavid du Colombier 
28757dd7cddfSDavid du Colombier    }
28767dd7cddfSDavid du Colombier    if(code < 0) param_signal_error(plist,"BitsPerPixel",code);
28777dd7cddfSDavid du Colombier    error = error > code ? code : error;
28787dd7cddfSDavid du Colombier 
28797dd7cddfSDavid du Colombier /*
28807dd7cddfSDavid du Colombier  * Fetch OutputCode
28817dd7cddfSDavid du Colombier  */
28827dd7cddfSDavid du Colombier    code  = param_read_string(plist,"OutputCode",&ps);
28837dd7cddfSDavid du Colombier    if(code == 0) {   /* Analyze the OutputCode-String */
28847dd7cddfSDavid du Colombier 
28857dd7cddfSDavid du Colombier       for(l = ps.size; (l > 0) && (ps.data[l-1] == 0); --l);
28867dd7cddfSDavid du Colombier 
28877dd7cddfSDavid du Colombier       sd->stc.flags &= ~STCCOMP;
28887dd7cddfSDavid du Colombier       if(!stc_putcmp("plain"))         sd->stc.flags |= STCPLAIN;
28897dd7cddfSDavid du Colombier       else if(!stc_putcmp("deltarow")) sd->stc.flags |= STCDELTA;
28907dd7cddfSDavid du Colombier 
28917dd7cddfSDavid du Colombier    }                 /* Analyze the OutputCode-String */
28927dd7cddfSDavid du Colombier    if((sd->stc.flags & STCCOMP) == STCDELTA) {
28937dd7cddfSDavid du Colombier       sd->stc.flags |=  STCUWEAVE;
28947dd7cddfSDavid du Colombier       sd->stc.flags &= ~STCNWEAVE;
28957dd7cddfSDavid du Colombier    }
28967dd7cddfSDavid du Colombier    if(code < 0) param_signal_error(plist,"OutputCode",code);
28977dd7cddfSDavid du Colombier    error = error > code ? code : error;
28987dd7cddfSDavid du Colombier 
28997dd7cddfSDavid du Colombier /*
29007dd7cddfSDavid du Colombier  * fetch the weave-mode (noWeave wins)
29017dd7cddfSDavid du Colombier  */
29027dd7cddfSDavid du Colombier    b1 = sd->stc.flags & STCUWEAVE ? true : false;
29037dd7cddfSDavid du Colombier    b2 = sd->stc.flags & STCNWEAVE ? true : false;
29047dd7cddfSDavid du Colombier    b3 = sd->stc.flags & (STCUWEAVE|STCNWEAVE) ? false : true;
29057dd7cddfSDavid du Colombier 
29067dd7cddfSDavid du Colombier    code = param_read_bool(plist,"Microweave",&b1);
29077dd7cddfSDavid du Colombier    if(code < 0) {
29087dd7cddfSDavid du Colombier       param_signal_error(plist,"Microweave",code);
29097dd7cddfSDavid du Colombier    } else if(code == 0) {
29107dd7cddfSDavid du Colombier       if(b1) { b2 = false; b3 = false; }
29117dd7cddfSDavid du Colombier    }
29127dd7cddfSDavid du Colombier    error = error > code ? code : error;
29137dd7cddfSDavid du Colombier 
29147dd7cddfSDavid du Colombier    code = param_read_bool(plist,"noWeave",&b2);
29157dd7cddfSDavid du Colombier    if(code < 0) {
29167dd7cddfSDavid du Colombier       param_signal_error(plist,"noWeave",code);
29177dd7cddfSDavid du Colombier    } else if (code == 0) {
29187dd7cddfSDavid du Colombier       if(b2) { b1 = false; b3 = false; }
29197dd7cddfSDavid du Colombier    }
29207dd7cddfSDavid du Colombier    error = error > code ? code : error;
29217dd7cddfSDavid du Colombier 
29227dd7cddfSDavid du Colombier    code = param_read_bool(plist,"Softweave",&b3);
29237dd7cddfSDavid du Colombier    if(code < 0) {
29247dd7cddfSDavid du Colombier       param_signal_error(plist,"Softweave",code);
29257dd7cddfSDavid du Colombier    } else if (code == 0) {
29267dd7cddfSDavid du Colombier       if(b3) { b1 = false; b2 = false; }
29277dd7cddfSDavid du Colombier    }
29287dd7cddfSDavid du Colombier    error = error > code ? code : error;
29297dd7cddfSDavid du Colombier 
29307dd7cddfSDavid du Colombier    if(b1) sd->stc.flags |=  STCUWEAVE;
29317dd7cddfSDavid du Colombier    else   sd->stc.flags &= ~STCUWEAVE;
29327dd7cddfSDavid du Colombier 
29337dd7cddfSDavid du Colombier    if(b2) sd->stc.flags |=  STCNWEAVE;
29347dd7cddfSDavid du Colombier    else   sd->stc.flags &= ~STCNWEAVE;
29357dd7cddfSDavid du Colombier 
29367dd7cddfSDavid du Colombier /*
29377dd7cddfSDavid du Colombier  * Check the simple Flags
29387dd7cddfSDavid du Colombier  */
29397dd7cddfSDavid du Colombier #  define stc_read_flag(Mask,Name)                \
29407dd7cddfSDavid du Colombier       code = param_read_bool(plist,Name,&b1);     \
29417dd7cddfSDavid du Colombier       if(code < 0) {                              \
29427dd7cddfSDavid du Colombier          param_signal_error(plist,Name,code);     \
29437dd7cddfSDavid du Colombier       } else if(code == 0) {                      \
29447dd7cddfSDavid du Colombier          if(b1 == true) sd->stc.flags |=  Mask;   \
29457dd7cddfSDavid du Colombier          else           sd->stc.flags &= ~(Mask); \
29467dd7cddfSDavid du Colombier       }                                           \
29477dd7cddfSDavid du Colombier       error = error > code ? code : error;
29487dd7cddfSDavid du Colombier 
29497dd7cddfSDavid du Colombier    stc_read_flag(STCUNIDIR,"Unidirectional")
29507dd7cddfSDavid du Colombier    stc_read_flag(STCDFLAG0, "Flag0")
29517dd7cddfSDavid du Colombier    stc_read_flag(STCDFLAG1, "Flag1")
29527dd7cddfSDavid du Colombier    stc_read_flag(STCDFLAG2, "Flag2")
29537dd7cddfSDavid du Colombier    stc_read_flag(STCDFLAG3, "Flag3")
29547dd7cddfSDavid du Colombier    stc_read_flag(STCDFLAG4, "Flag4")
29557dd7cddfSDavid du Colombier 
29567dd7cddfSDavid du Colombier /*
29577dd7cddfSDavid du Colombier  * Now deal with the escp-Stuff
29587dd7cddfSDavid du Colombier  */
29597dd7cddfSDavid du Colombier #  define stc_read_int(Mask,Name,Val)             \
29607dd7cddfSDavid du Colombier       code = param_read_int(plist,Name,&Val);     \
29617dd7cddfSDavid du Colombier       if(code < 0)                                \
29627dd7cddfSDavid du Colombier          param_signal_error(plist,Name,code);     \
29637dd7cddfSDavid du Colombier       else if(code == 0)                          \
29647dd7cddfSDavid du Colombier          sd->stc.flags |= Mask;                   \
29657dd7cddfSDavid du Colombier       error = error > code ? code : error
29667dd7cddfSDavid du Colombier 
29677dd7cddfSDavid du Colombier    stc_read_int(STCBAND,  "escp_Band",  sd->stc.escp_m);
29687dd7cddfSDavid du Colombier    stc_read_int(STCWIDTH, "escp_Width", sd->stc.escp_width);
29697dd7cddfSDavid du Colombier    stc_read_int(STCHEIGHT,"escp_Height",sd->stc.escp_height);
29707dd7cddfSDavid du Colombier    stc_read_int(STCTOP,   "escp_Top",   sd->stc.escp_top);
29717dd7cddfSDavid du Colombier    stc_read_int(STCBOTTOM,"escp_Bottom",sd->stc.escp_bottom);
29727dd7cddfSDavid du Colombier 
29737dd7cddfSDavid du Colombier #  undef stc_read_int
29747dd7cddfSDavid du Colombier 
29757dd7cddfSDavid du Colombier    code = param_read_string(plist,"escp_Init",&sd->stc.escp_init);
29767dd7cddfSDavid du Colombier    if(code == 0) sd->stc.flags |= STCINIT;
29777dd7cddfSDavid du Colombier    error = error > code ? code : error;
29787dd7cddfSDavid du Colombier 
29797dd7cddfSDavid du Colombier    code = param_read_string(plist,"escp_Release",&sd->stc.escp_release);
29807dd7cddfSDavid du Colombier    if(code == 0) sd->stc.flags |= STCRELEASE;
29817dd7cddfSDavid du Colombier    error = error > code ? code : error;
29827dd7cddfSDavid du Colombier 
29837dd7cddfSDavid du Colombier /*
29847dd7cddfSDavid du Colombier  * ColorAdjustMatrix must match the required size,
29857dd7cddfSDavid du Colombier  * setting it explicitly to null, erases old matrix
29867dd7cddfSDavid du Colombier  */
29877dd7cddfSDavid du Colombier    code = param_read_float_array(plist,"ColorAdjustMatrix",&pfa);
29887dd7cddfSDavid du Colombier    if((error == 0) && (code == 0)) {
29897dd7cddfSDavid du Colombier       if(((sd->color_info.num_components == 1) && (pfa.size ==  3)) ||
29907dd7cddfSDavid du Colombier          ((sd->color_info.num_components == 3) && (pfa.size ==  9)) ||
29917dd7cddfSDavid du Colombier          ((sd->color_info.num_components == 4) && (pfa.size == 16)))
29927dd7cddfSDavid du Colombier          sd->stc.am = (float *) pfa.data;
29937dd7cddfSDavid du Colombier       else
29947dd7cddfSDavid du Colombier          code =  gs_error_rangecheck;
29957dd7cddfSDavid du Colombier    } else if(code < 0) {
29967dd7cddfSDavid du Colombier       code = param_read_null(plist,"ColorAdjustMatrix");
29977dd7cddfSDavid du Colombier       if(code == 0) sd->stc.am = NULL;
29987dd7cddfSDavid du Colombier    }
29997dd7cddfSDavid du Colombier    if(code < 0) param_signal_error(plist,"ColorAdjustMatrix",code);
30007dd7cddfSDavid du Colombier    error = error > code ? code : error;
30017dd7cddfSDavid du Colombier 
30027dd7cddfSDavid du Colombier /*
30037dd7cddfSDavid du Colombier  * Read the external array-Parameters
30047dd7cddfSDavid du Colombier  */
30057dd7cddfSDavid du Colombier    if(sd->color_info.num_components == 1) {        /* DeviceGray */
30067dd7cddfSDavid du Colombier 
30077dd7cddfSDavid du Colombier       stc_read_xarray(0,"Kcoding","Ktransfer");
30087dd7cddfSDavid du Colombier 
30097dd7cddfSDavid du Colombier       stc_read_null("Rcoding"); stc_read_null("Rtransfer");
30107dd7cddfSDavid du Colombier       stc_read_null("Gcoding"); stc_read_null("Gtransfer");
30117dd7cddfSDavid du Colombier       stc_read_null("Bcoding"); stc_read_null("Btransfer");
30127dd7cddfSDavid du Colombier 
30137dd7cddfSDavid du Colombier       stc_read_null("Ccoding"); stc_read_null("Ctransfer");
30147dd7cddfSDavid du Colombier       stc_read_null("Mcoding"); stc_read_null("Mtransfer");
30157dd7cddfSDavid du Colombier       stc_read_null("Ycoding"); stc_read_null("Ytransfer");
30167dd7cddfSDavid du Colombier 
30177dd7cddfSDavid du Colombier    } else if(sd->color_info.num_components == 3) { /* DeviceRGB */
30187dd7cddfSDavid du Colombier 
30197dd7cddfSDavid du Colombier       stc_read_xarray(0,"Rcoding","Rtransfer");
30207dd7cddfSDavid du Colombier       stc_read_xarray(1,"Gcoding","Gtransfer");
30217dd7cddfSDavid du Colombier       stc_read_xarray(2,"Bcoding","Btransfer");
30227dd7cddfSDavid du Colombier 
30237dd7cddfSDavid du Colombier       stc_read_null("Ccoding"); stc_read_null("Ctransfer");
30247dd7cddfSDavid du Colombier       stc_read_null("Mcoding"); stc_read_null("Mtransfer");
30257dd7cddfSDavid du Colombier       stc_read_null("Ycoding"); stc_read_null("Ytransfer");
30267dd7cddfSDavid du Colombier       stc_read_null("Kcoding"); stc_read_null("Ktransfer");
30277dd7cddfSDavid du Colombier 
30287dd7cddfSDavid du Colombier    } else {                                        /* DeviceCMYK */
30297dd7cddfSDavid du Colombier 
30307dd7cddfSDavid du Colombier       stc_read_xarray(0,"Ccoding","Ctransfer");
30317dd7cddfSDavid du Colombier       stc_read_xarray(1,"Mcoding","Mtransfer");
30327dd7cddfSDavid du Colombier       stc_read_xarray(2,"Ycoding","Ytransfer");
30337dd7cddfSDavid du Colombier       stc_read_xarray(3,"Kcoding","Ktransfer");
30347dd7cddfSDavid du Colombier 
30357dd7cddfSDavid du Colombier       stc_read_null("Rcoding"); stc_read_null("Rtransfer");
30367dd7cddfSDavid du Colombier       stc_read_null("Gcoding"); stc_read_null("Gtransfer");
30377dd7cddfSDavid du Colombier       stc_read_null("Bcoding"); stc_read_null("Btransfer");
30387dd7cddfSDavid du Colombier 
30397dd7cddfSDavid du Colombier    }
30407dd7cddfSDavid du Colombier /*
30417dd7cddfSDavid du Colombier  * Update remaining color_info values
30427dd7cddfSDavid du Colombier  */
30437dd7cddfSDavid du Colombier    if(error == 0) {
30447dd7cddfSDavid du Colombier 
30457dd7cddfSDavid du Colombier /*    compute #values from the component-bits */
30467dd7cddfSDavid du Colombier       sd->color_info.max_gray  = sd->stc.bits < gx_color_value_bits ?
30477dd7cddfSDavid du Colombier                             (1<<sd->stc.bits)-1 : gx_max_color_value;
30487dd7cddfSDavid du Colombier 
30497dd7cddfSDavid du Colombier /*    An integer-algorithm might reduce the number of values */
30507dd7cddfSDavid du Colombier       if(((sd->stc.dither->flags & STC_TYPE) != STC_FLOAT) &&
30517dd7cddfSDavid du Colombier          ((sd->stc.dither->minmax[1]-sd->stc.dither->minmax[0]) <
30527dd7cddfSDavid du Colombier            sd->color_info.max_gray))
3053*593dc095SDavid du Colombier          sd->color_info.max_gray = (gx_color_value)
3054*593dc095SDavid du Colombier                 (sd->stc.dither->minmax[1]-sd->stc.dither->minmax[0]+0.5);
30557dd7cddfSDavid du Colombier 
30567dd7cddfSDavid du Colombier       sd->color_info.max_color = sd->color_info.num_components < 3 ? 0 :
30577dd7cddfSDavid du Colombier                                  sd->color_info.max_gray;
30587dd7cddfSDavid du Colombier       sd->color_info.dither_grays =
30597dd7cddfSDavid du Colombier           sd->color_info.max_gray < gx_max_color_value ?
30607dd7cddfSDavid du Colombier           sd->color_info.max_gray+1  : gx_max_color_value;
30617dd7cddfSDavid du Colombier       sd->color_info.dither_colors  = sd->color_info.num_components < 3 ? 0 :
30627dd7cddfSDavid du Colombier           sd->color_info.dither_grays;
30637dd7cddfSDavid du Colombier    }
30647dd7cddfSDavid du Colombier 
30657dd7cddfSDavid du Colombier /*
30667dd7cddfSDavid du Colombier  * Call superclass-Update
30677dd7cddfSDavid du Colombier  */
30687dd7cddfSDavid du Colombier 
30697dd7cddfSDavid du Colombier    code = gdev_prn_put_params(pdev, plist);
30707dd7cddfSDavid du Colombier    error = error > code ? code : error;
30717dd7cddfSDavid du Colombier 
30727dd7cddfSDavid du Colombier /*
30737dd7cddfSDavid du Colombier  * Arrrgh, writing BitsPerPixel is really *VERY* special:
30747dd7cddfSDavid du Colombier  *    gdev_prn_put_params verifies, that the external value
30757dd7cddfSDavid du Colombier  *    is written, if not, it raises a rangecheck-error.
30767dd7cddfSDavid du Colombier  *    On the other hand ghostscript is quite unhappy with odd
30777dd7cddfSDavid du Colombier  *    values, so we do the necessary rounding *AFTER* the
30787dd7cddfSDavid du Colombier  *    "superclass-Update".
30797dd7cddfSDavid du Colombier  */
30807dd7cddfSDavid du Colombier 
30817dd7cddfSDavid du Colombier    if(sd->color_info.depth ==  3) sd->color_info.depth = 4;
30827dd7cddfSDavid du Colombier    else if(sd->color_info.depth > 4)
30837dd7cddfSDavid du Colombier       sd->color_info.depth =  (sd->color_info.depth+7) & ~7;
30847dd7cddfSDavid du Colombier 
30857dd7cddfSDavid du Colombier /*
30867dd7cddfSDavid du Colombier  * Allocate the storage for the arrays in memory
30877dd7cddfSDavid du Colombier  */
30887dd7cddfSDavid du Colombier    if(error == 0) { /* Allocate new external-arrays */
30897dd7cddfSDavid du Colombier 
30907dd7cddfSDavid du Colombier      for(i = 0; i < sd->color_info.num_components; ++i){ /* Active components */
30917dd7cddfSDavid du Colombier         int j;
30927dd7cddfSDavid du Colombier 
30937dd7cddfSDavid du Colombier         if((sd->stc.extv[i] != oldstc.extv[i]) &&
30947dd7cddfSDavid du Colombier            (sd->stc.extv[i] != defext        )) { /* Value-Arrays */
30957dd7cddfSDavid du Colombier 
30967dd7cddfSDavid du Colombier            for(j = 0; j < i; ++j)
30977dd7cddfSDavid du Colombier               if((sd->stc.sizv[j] == sd->stc.sizv[i]) &&
30987dd7cddfSDavid du Colombier                  (memcmp(sd->stc.extv[j],sd->stc.extv[i],
30997dd7cddfSDavid du Colombier                          sd->stc.sizv[i]*sizeof(float)) == 0)) break;
31007dd7cddfSDavid du Colombier 
31017dd7cddfSDavid du Colombier            if(j < i) {
31027dd7cddfSDavid du Colombier               sd->stc.extv[i] = sd->stc.extv[j];
31037dd7cddfSDavid du Colombier            } else {
3104*593dc095SDavid du Colombier               fp = gs_malloc(sd->memory, sd->stc.sizv[i],sizeof(float),"stc_put_params");
31057dd7cddfSDavid du Colombier               if(fp != NULL)
31067dd7cddfSDavid du Colombier                  memcpy(fp,sd->stc.extv[i],sd->stc.sizv[i]*sizeof(float));
31077dd7cddfSDavid du Colombier                else
31087dd7cddfSDavid du Colombier                  code = gs_error_VMerror;
31097dd7cddfSDavid du Colombier                sd->stc.extv[i] = fp;
31107dd7cddfSDavid du Colombier            }
31117dd7cddfSDavid du Colombier         }                                         /* Value-Arrays */
31127dd7cddfSDavid du Colombier 
31137dd7cddfSDavid du Colombier         if((sd->stc.sizc[i] > 1) &&
31147dd7cddfSDavid du Colombier            (sd->stc.extc[i] != oldstc.extc[i])) { /* Code-Arrays */
31157dd7cddfSDavid du Colombier 
31167dd7cddfSDavid du Colombier            for(j = 0; j < i; ++j)
31177dd7cddfSDavid du Colombier               if((sd->stc.sizc[j] == sd->stc.sizc[i]) &&
31187dd7cddfSDavid du Colombier                  (memcmp(sd->stc.extc[j],sd->stc.extc[i],
31197dd7cddfSDavid du Colombier                          sd->stc.sizc[i]*sizeof(float)) == 0)) break;
31207dd7cddfSDavid du Colombier 
31217dd7cddfSDavid du Colombier            if(j < i) {
31227dd7cddfSDavid du Colombier               sd->stc.extc[i] = sd->stc.extc[j];
31237dd7cddfSDavid du Colombier            } else {
3124*593dc095SDavid du Colombier               fp = gs_malloc(sd->memory, sd->stc.sizc[i],sizeof(float),"stc_put_params");
31257dd7cddfSDavid du Colombier               if(fp != NULL)
31267dd7cddfSDavid du Colombier                  memcpy(fp,sd->stc.extc[i],sd->stc.sizc[i]*sizeof(float));
31277dd7cddfSDavid du Colombier                else
31287dd7cddfSDavid du Colombier                  code = gs_error_VMerror;
31297dd7cddfSDavid du Colombier                sd->stc.extc[i] = fp;
31307dd7cddfSDavid du Colombier            }
31317dd7cddfSDavid du Colombier         }                                         /* Code-Arrays */
31327dd7cddfSDavid du Colombier 
31337dd7cddfSDavid du Colombier      }                                                   /* Active components */
31347dd7cddfSDavid du Colombier 
31357dd7cddfSDavid du Colombier      if((sd->stc.am != NULL) && (sd->stc.am != oldstc.am)) {
31367dd7cddfSDavid du Colombier         if(     sd->color_info.num_components == 1) i =  3;
31377dd7cddfSDavid du Colombier         else if(sd->color_info.num_components == 3) i =  9;
31387dd7cddfSDavid du Colombier         else                                        i = 16;
3139*593dc095SDavid du Colombier         fp = gs_malloc(sd->memory, i,sizeof(float),"stc_put_params");
31407dd7cddfSDavid du Colombier         if(fp != NULL) memcpy(fp,sd->stc.am,i*sizeof(float));
31417dd7cddfSDavid du Colombier         else           code = gs_error_VMerror;
31427dd7cddfSDavid du Colombier         sd->stc.am = fp;
31437dd7cddfSDavid du Colombier      }
31447dd7cddfSDavid du Colombier 
31457dd7cddfSDavid du Colombier      if(sd->stc.escp_init.data != oldstc.escp_init.data) {
31467dd7cddfSDavid du Colombier         byte *ip = NULL;
31477dd7cddfSDavid du Colombier 
31487dd7cddfSDavid du Colombier         if(sd->stc.escp_init.size > 0) {
3149*593dc095SDavid du Colombier            ip = gs_malloc(sd->memory, sd->stc.escp_init.size,1,"stcolor/init");
31507dd7cddfSDavid du Colombier            if(ip == NULL) {
31517dd7cddfSDavid du Colombier               code = gs_error_VMerror;
31527dd7cddfSDavid du Colombier               sd->stc.escp_init.size = 0;
31537dd7cddfSDavid du Colombier            } else {
31547dd7cddfSDavid du Colombier               memcpy(ip,sd->stc.escp_init.data,sd->stc.escp_init.size);
31557dd7cddfSDavid du Colombier            }
31567dd7cddfSDavid du Colombier         }
31577dd7cddfSDavid du Colombier         sd->stc.escp_init.data       = ip;
31587dd7cddfSDavid du Colombier         sd->stc.escp_init.persistent = false;
31597dd7cddfSDavid du Colombier      }
31607dd7cddfSDavid du Colombier 
31617dd7cddfSDavid du Colombier      if(sd->stc.escp_release.data != oldstc.escp_release.data) {
31627dd7cddfSDavid du Colombier         byte *ip = NULL;
31637dd7cddfSDavid du Colombier 
31647dd7cddfSDavid du Colombier         if(sd->stc.escp_release.size > 0) {
3165*593dc095SDavid du Colombier            ip = gs_malloc(sd->memory, sd->stc.escp_release.size,1,"stcolor/release");
31667dd7cddfSDavid du Colombier            if(ip == NULL) {
31677dd7cddfSDavid du Colombier               code = gs_error_VMerror;
31687dd7cddfSDavid du Colombier               sd->stc.escp_release.size = 0;
31697dd7cddfSDavid du Colombier            } else {
31707dd7cddfSDavid du Colombier               memcpy(ip,sd->stc.escp_release.data,sd->stc.escp_release.size);
31717dd7cddfSDavid du Colombier            }
31727dd7cddfSDavid du Colombier         }
31737dd7cddfSDavid du Colombier         sd->stc.escp_release.data       = ip;
31747dd7cddfSDavid du Colombier         sd->stc.escp_release.persistent = false;
31757dd7cddfSDavid du Colombier      }
31767dd7cddfSDavid du Colombier 
31777dd7cddfSDavid du Colombier      if(code < 0) { /* free newly allocated arrays */
31787dd7cddfSDavid du Colombier 
31797dd7cddfSDavid du Colombier         if((sd->stc.am != NULL) && (sd->stc.am != oldstc.am)) {
31807dd7cddfSDavid du Colombier            if(     sd->color_info.num_components == 1) i =  3;
31817dd7cddfSDavid du Colombier            else if(sd->color_info.num_components == 3) i =  9;
31827dd7cddfSDavid du Colombier            else                                        i = 16;
3183*593dc095SDavid du Colombier            gs_free(sd->memory, sd->stc.am,i,sizeof(float),"stc_put_params");
31847dd7cddfSDavid du Colombier         }
31857dd7cddfSDavid du Colombier 
31867dd7cddfSDavid du Colombier         if((sd->stc.escp_init.data != NULL) &&
31877dd7cddfSDavid du Colombier            (sd->stc.escp_init.data != oldstc.escp_init.data))
3188*593dc095SDavid du Colombier            gs_free(sd->memory, (byte *) sd->stc.escp_init.data,sd->stc.escp_init.size,1,
31897dd7cddfSDavid du Colombier               "stcolor/init");
31907dd7cddfSDavid du Colombier 
31917dd7cddfSDavid du Colombier         if((sd->stc.escp_release.data != NULL) &&
31927dd7cddfSDavid du Colombier            (sd->stc.escp_release.data != oldstc.escp_release.data))
3193*593dc095SDavid du Colombier            gs_free(sd->memory, (byte *) sd->stc.escp_release.data,sd->stc.escp_release.
31947dd7cddfSDavid du Colombier               size,1,"stcolor/release");
31957dd7cddfSDavid du Colombier 
31967dd7cddfSDavid du Colombier         for(i = 0; i < sd->color_info.num_components; ++i) { /* components */
31977dd7cddfSDavid du Colombier            int j;
31987dd7cddfSDavid du Colombier 
31997dd7cddfSDavid du Colombier            if((sd->stc.extc[i] != NULL) &&
32007dd7cddfSDavid du Colombier               (sd->stc.extc[i] != defext) &&
32017dd7cddfSDavid du Colombier               (sd->stc.extc[i] != oldstc.extc[i])) {
32027dd7cddfSDavid du Colombier 
32037dd7cddfSDavid du Colombier               for(j = 0; j < i; ++j)
32047dd7cddfSDavid du Colombier                  if(sd->stc.extc[i] == sd->stc.extc[j]) break;
32057dd7cddfSDavid du Colombier 
3206*593dc095SDavid du Colombier               if(i == j) gs_free(sd->memory, sd->stc.extc[i],sd->stc.sizc[i],sizeof(float),
32077dd7cddfSDavid du Colombier                             "stc_put_params");
32087dd7cddfSDavid du Colombier            }
32097dd7cddfSDavid du Colombier 
32107dd7cddfSDavid du Colombier            if((sd->stc.extv[i] != NULL) &&
32117dd7cddfSDavid du Colombier               (sd->stc.extv[i] != oldstc.extv[i]) &&
32127dd7cddfSDavid du Colombier               (sd->stc.extv[i] != defext)) {
32137dd7cddfSDavid du Colombier 
32147dd7cddfSDavid du Colombier               for(j = 0; j < i; ++j)
32157dd7cddfSDavid du Colombier                  if(sd->stc.extv[i] == sd->stc.extv[j]) break;
32167dd7cddfSDavid du Colombier 
3217*593dc095SDavid du Colombier               if(i == j) gs_free(sd->memory, sd->stc.extv[i],sd->stc.sizv[i],sizeof(float),
32187dd7cddfSDavid du Colombier                             "stc_put_params");
32197dd7cddfSDavid du Colombier            }
32207dd7cddfSDavid du Colombier         }                                                    /* components */
32217dd7cddfSDavid du Colombier      }              /* free newly allocated arrays */
32227dd7cddfSDavid du Colombier    }                /* Allocate new arrays */
32237dd7cddfSDavid du Colombier    error = error > code ? code : error;
32247dd7cddfSDavid du Colombier 
32257dd7cddfSDavid du Colombier /*
32267dd7cddfSDavid du Colombier  * finally decide upon restore or release of old, unused data
32277dd7cddfSDavid du Colombier  */
32287dd7cddfSDavid du Colombier    if(error != 0) { /* Undo changes */
32297dd7cddfSDavid du Colombier 
32307dd7cddfSDavid du Colombier       memcpy(&sd->color_info,&oldcolor,sizeof(oldcolor));
32317dd7cddfSDavid du Colombier       memcpy(&sd->stc       ,&oldstc  ,sizeof(oldstc  ));
32327dd7cddfSDavid du Colombier    } else {        /* undo / release */
32337dd7cddfSDavid du Colombier 
32347dd7cddfSDavid du Colombier       if((oldstc.escp_init.data != NULL) &&
32357dd7cddfSDavid du Colombier          (oldstc.escp_init.data != sd->stc.escp_init.data)) {
3236*593dc095SDavid du Colombier             gs_free(sd->memory, (byte *)oldstc.escp_init.data,
32377dd7cddfSDavid du Colombier                             oldstc.escp_init.size,1,"stcolor/init");
32387dd7cddfSDavid du Colombier       }
32397dd7cddfSDavid du Colombier 
32407dd7cddfSDavid du Colombier       if((oldstc.escp_release.data != NULL) &&
32417dd7cddfSDavid du Colombier          (oldstc.escp_release.data != sd->stc.escp_release.data)) {
3242*593dc095SDavid du Colombier             gs_free(sd->memory, (byte *)oldstc.escp_release.data,
32437dd7cddfSDavid du Colombier                             oldstc.escp_release.size,1,"stcolor/release");
32447dd7cddfSDavid du Colombier       }
32457dd7cddfSDavid du Colombier 
32467dd7cddfSDavid du Colombier       if((oldstc.am != NULL) && (oldstc.am != sd->stc.am)) {
32477dd7cddfSDavid du Colombier          if(     oldcolor.num_components == 1) i =  3;
32487dd7cddfSDavid du Colombier          else if(oldcolor.num_components == 3) i =  9;
32497dd7cddfSDavid du Colombier          else                                  i = 16;
3250*593dc095SDavid du Colombier          gs_free(sd->memory, oldstc.am,i,sizeof(float),"stc_put_params");
32517dd7cddfSDavid du Colombier       }
32527dd7cddfSDavid du Colombier 
32537dd7cddfSDavid du Colombier       for(i = 0; i < 4; ++i) {
32547dd7cddfSDavid du Colombier          int j;
32557dd7cddfSDavid du Colombier 
32567dd7cddfSDavid du Colombier          if((oldstc.extc[i] != NULL) &&
32577dd7cddfSDavid du Colombier             (oldstc.extc[i] != sd->stc.extc[i]) &&
32587dd7cddfSDavid du Colombier             (oldstc.dither  != NULL) &&
32597dd7cddfSDavid du Colombier             (oldstc.extc[i] != defext)) {
32607dd7cddfSDavid du Colombier 
32617dd7cddfSDavid du Colombier             for(j = 0; j < i; ++j) if(oldstc.extc[i] == oldstc.extc[j]) break;
32627dd7cddfSDavid du Colombier 
3263*593dc095SDavid du Colombier             if(i == j) gs_free(sd->memory, oldstc.extc[i],oldstc.sizc[i],sizeof(float),
32647dd7cddfSDavid du Colombier                             "stc_put_params");
32657dd7cddfSDavid du Colombier          }
32667dd7cddfSDavid du Colombier 
32677dd7cddfSDavid du Colombier          if((oldstc.extv[i] != NULL) &&
32687dd7cddfSDavid du Colombier             (oldstc.extv[i] != sd->stc.extv[i]) &&
32697dd7cddfSDavid du Colombier             (oldstc.extv[i] != defext)) {
32707dd7cddfSDavid du Colombier 
32717dd7cddfSDavid du Colombier             for(j = 0; j < i; ++j) if(oldstc.extv[i] == oldstc.extv[j]) break;
32727dd7cddfSDavid du Colombier 
3273*593dc095SDavid du Colombier             if(i == j) gs_free(sd->memory, oldstc.extv[i],oldstc.sizv[i],sizeof(float),
32747dd7cddfSDavid du Colombier                             "stc_put_params");
32757dd7cddfSDavid du Colombier          }
32767dd7cddfSDavid du Colombier       }
32777dd7cddfSDavid du Colombier 
32787dd7cddfSDavid du Colombier /*
32797dd7cddfSDavid du Colombier  * Close the device if colormodel changed or recomputation
32807dd7cddfSDavid du Colombier  * of internal arrays is required
32817dd7cddfSDavid du Colombier  */
32827dd7cddfSDavid du Colombier       if(sd->is_open) { /* we might need to close it */
32837dd7cddfSDavid du Colombier          bool doclose = false;
32847dd7cddfSDavid du Colombier          if((sd->color_info.num_components != oldcolor.num_components) ||
32857dd7cddfSDavid du Colombier             (sd->color_info.depth          != oldcolor.depth         ) ||
32867dd7cddfSDavid du Colombier             (sd->stc.bits                  != oldstc.bits            ) ||
32877dd7cddfSDavid du Colombier             (sd->stc.dither                != oldstc.dither          ))
32887dd7cddfSDavid du Colombier             doclose = true;
32897dd7cddfSDavid du Colombier 
32907dd7cddfSDavid du Colombier          for(i = 0; i < sd->color_info.num_components; ++i) {
32917dd7cddfSDavid du Colombier             if(sd->stc.extv[i] != oldstc.extv[i]) doclose = true;
32927dd7cddfSDavid du Colombier             if(sd->stc.extc[i] != oldstc.extc[i]) doclose = true;
32937dd7cddfSDavid du Colombier          }
32947dd7cddfSDavid du Colombier          if(doclose) {
3295*593dc095SDavid du Colombier             stc_freedata(pdev->memory, &oldstc);
32967dd7cddfSDavid du Colombier             for(i = 0; i < 4; ++i) {
32977dd7cddfSDavid du Colombier                sd->stc.vals[i] = NULL;
32987dd7cddfSDavid du Colombier                sd->stc.code[i] = NULL;
32997dd7cddfSDavid du Colombier             }
33007dd7cddfSDavid du Colombier 
33017dd7cddfSDavid du Colombier             gs_closedevice(pdev);
33027dd7cddfSDavid du Colombier          }
33037dd7cddfSDavid du Colombier       }                 /* we might need to close it */
33047dd7cddfSDavid du Colombier 
33057dd7cddfSDavid du Colombier    }
33067dd7cddfSDavid du Colombier 
33077dd7cddfSDavid du Colombier    return error;
33087dd7cddfSDavid du Colombier }
33097dd7cddfSDavid du Colombier /*
33107dd7cddfSDavid du Colombier  * 1Bit CMYK-Algorithm
33117dd7cddfSDavid du Colombier  */
33127dd7cddfSDavid du Colombier 
33137dd7cddfSDavid du Colombier private int
stc_gscmyk(stcolor_device * sdev,int npixel,byte * in,byte * buf,byte * out)33147dd7cddfSDavid du Colombier stc_gscmyk(stcolor_device *sdev,int npixel,byte *in,byte *buf,byte *out)
33157dd7cddfSDavid du Colombier {
33167dd7cddfSDavid du Colombier 
33177dd7cddfSDavid du Colombier    byte *ip = in;
33187dd7cddfSDavid du Colombier    int   error = 0;
33197dd7cddfSDavid du Colombier 
33207dd7cddfSDavid du Colombier 
33217dd7cddfSDavid du Colombier /* ============================================================= */
33227dd7cddfSDavid du Colombier    if(npixel > 0) {  /* npixel >  0 -> scanline-processing       */
33237dd7cddfSDavid du Colombier /* ============================================================= */
33247dd7cddfSDavid du Colombier 
33257dd7cddfSDavid du Colombier       int p;
33267dd7cddfSDavid du Colombier 
33277dd7cddfSDavid du Colombier /*
33287dd7cddfSDavid du Colombier  *    simply split the two pixels rsiding in a byte
33297dd7cddfSDavid du Colombier  */
33307dd7cddfSDavid du Colombier       for(p = npixel; p > 0; --p) { /* loop over pixels */
33317dd7cddfSDavid du Colombier          byte tmp =*ip++;
33327dd7cddfSDavid du Colombier 
33337dd7cddfSDavid du Colombier          *out++ = (tmp>>4) & 15;
33347dd7cddfSDavid du Colombier          if(--p <= 0) break;
33357dd7cddfSDavid du Colombier 
33367dd7cddfSDavid du Colombier          *out++ =  tmp     & 15;
33377dd7cddfSDavid du Colombier 
33387dd7cddfSDavid du Colombier       }                                   /* loop over pixels */
33397dd7cddfSDavid du Colombier 
33407dd7cddfSDavid du Colombier /* ============================================================= */
33417dd7cddfSDavid du Colombier    } else {          /* npixel <= 0 -> initialisation            */
33427dd7cddfSDavid du Colombier /* ============================================================= */
33437dd7cddfSDavid du Colombier 
33447dd7cddfSDavid du Colombier /*    we didn't check for the white-calls above, so this may cause errors */
33457dd7cddfSDavid du Colombier       if(sdev->stc.dither->flags & STC_WHITE)              error = -1;
33467dd7cddfSDavid du Colombier 
33477dd7cddfSDavid du Colombier /*    if we're not setup for bytes, this is an error too */
33487dd7cddfSDavid du Colombier       if((sdev->stc.dither->flags & STC_TYPE) != STC_BYTE) error = -2;
33497dd7cddfSDavid du Colombier 
33507dd7cddfSDavid du Colombier /*    This IS a direct-driver, so STC_DIRECT must be set! */
33517dd7cddfSDavid du Colombier       if((sdev->stc.dither->flags & STC_DIRECT) == 0)      error = -3;
33527dd7cddfSDavid du Colombier 
33537dd7cddfSDavid du Colombier /*    and cmyk-mode is the only supported mode */
33547dd7cddfSDavid du Colombier       if(sdev->color_info.num_components != 4)             error = -4;
33557dd7cddfSDavid du Colombier 
33567dd7cddfSDavid du Colombier /*    and we support only 4Bit-Depth here */
33577dd7cddfSDavid du Colombier       if(sdev->color_info.depth != 4)                      error = -5;
33587dd7cddfSDavid du Colombier 
33597dd7cddfSDavid du Colombier /* ============================================================= */
33607dd7cddfSDavid du Colombier    } /* scanline-processing or initialisation */
33617dd7cddfSDavid du Colombier /* ============================================================= */
33627dd7cddfSDavid du Colombier 
33637dd7cddfSDavid du Colombier    return error;
33647dd7cddfSDavid du Colombier }
33657dd7cddfSDavid du Colombier 
33667dd7cddfSDavid du Colombier /*
33677dd7cddfSDavid du Colombier  * The following is an algorithm under test
33687dd7cddfSDavid du Colombier  */
33697dd7cddfSDavid du Colombier private int
stc_hscmyk(stcolor_device * sdev,int npixel,byte * in,byte * buf,byte * out)33707dd7cddfSDavid du Colombier stc_hscmyk(stcolor_device *sdev,int npixel,byte *in,byte *buf,byte *out)
33717dd7cddfSDavid du Colombier {
33727dd7cddfSDavid du Colombier 
33737dd7cddfSDavid du Colombier /* ============================================================= */
33747dd7cddfSDavid du Colombier    if(npixel < 0) {  /* npixel <= 0 -> initialisation            */
33757dd7cddfSDavid du Colombier /* ============================================================= */
33767dd7cddfSDavid du Colombier 
33777dd7cddfSDavid du Colombier       int i,i2do;
33787dd7cddfSDavid du Colombier       long *lp = (long *) buf;
33797dd7cddfSDavid du Colombier 
33807dd7cddfSDavid du Colombier /* CMYK-only algorithm */
33817dd7cddfSDavid du Colombier       if( sdev->color_info.num_components != 4)                      return -1;
33827dd7cddfSDavid du Colombier 
33837dd7cddfSDavid du Colombier /*
33847dd7cddfSDavid du Colombier  * check wether stcdither & TYPE are correct
33857dd7cddfSDavid du Colombier  */
33867dd7cddfSDavid du Colombier       if(( sdev->stc.dither                    == NULL) ||
33877dd7cddfSDavid du Colombier          ((sdev->stc.dither->flags & STC_TYPE) != STC_LONG))         return -2;
33887dd7cddfSDavid du Colombier 
33897dd7cddfSDavid du Colombier /*
33907dd7cddfSDavid du Colombier  * check wether the buffer-size is sufficiently large
33917dd7cddfSDavid du Colombier  */
33927dd7cddfSDavid du Colombier       if(((sdev->stc.dither->flags/STC_SCAN) < 1) ||
33937dd7cddfSDavid du Colombier          ( sdev->stc.dither->bufadd          <
33947dd7cddfSDavid du Colombier           (1 + 2*sdev->color_info.num_components)))                  return -3;
33957dd7cddfSDavid du Colombier 
33967dd7cddfSDavid du Colombier /*
33977dd7cddfSDavid du Colombier  * must have STC_CMYK10, STC_DIRECT, but not STC_WHITE
33987dd7cddfSDavid du Colombier  */
33997dd7cddfSDavid du Colombier       if((sdev->stc.dither->flags & STC_CMYK10) == 0)                return -4;
34007dd7cddfSDavid du Colombier       if((sdev->stc.dither->flags & STC_DIRECT) == 0)                return -5;
34017dd7cddfSDavid du Colombier       if((sdev->stc.dither->flags & STC_WHITE ) != 0)                return -6;
34027dd7cddfSDavid du Colombier 
34037dd7cddfSDavid du Colombier /*
34047dd7cddfSDavid du Colombier  * Must have values between 0-1023.0
34057dd7cddfSDavid du Colombier  */
34067dd7cddfSDavid du Colombier       if((sdev->stc.dither->minmax[0] !=    0.0) ||
34077dd7cddfSDavid du Colombier          (sdev->stc.dither->minmax[1] != 1023.0))                    return -7;
34087dd7cddfSDavid du Colombier /*
34097dd7cddfSDavid du Colombier  * initialize buffer
34107dd7cddfSDavid du Colombier  */
34117dd7cddfSDavid du Colombier 
34127dd7cddfSDavid du Colombier      i2do            = 1 + 8 - 4 * npixel;
34137dd7cddfSDavid du Colombier      lp[0] = 0;
34147dd7cddfSDavid du Colombier 
34157dd7cddfSDavid du Colombier       if(sdev->stc.flags & STCDFLAG0) {
34167dd7cddfSDavid du Colombier         for(i = 1; i < i2do; ++i) lp[i] = 0;
34177dd7cddfSDavid du Colombier       } else {
34187dd7cddfSDavid du Colombier         for(i = 1; i < i2do; ++i)  lp[i] = (rand() % 381) - 190;
34197dd7cddfSDavid du Colombier       }
34207dd7cddfSDavid du Colombier 
34217dd7cddfSDavid du Colombier /* ============================================================= */
34227dd7cddfSDavid du Colombier    } else {  /* npixel > 0 && in != NULL  -> scanline-processing */
34237dd7cddfSDavid du Colombier /* ============================================================= */
34247dd7cddfSDavid du Colombier 
34257dd7cddfSDavid du Colombier       long errc[4],*errv;
34267dd7cddfSDavid du Colombier       int             step  = buf[0] ? -1 : 1;
34277dd7cddfSDavid du Colombier       stc_pixel *ip    =  (stc_pixel *) in;
34287dd7cddfSDavid du Colombier 
34297dd7cddfSDavid du Colombier       buf[0] = ~ buf[0];
34307dd7cddfSDavid du Colombier       errv   =  (long *) buf + 5;
34317dd7cddfSDavid du Colombier 
34327dd7cddfSDavid du Colombier       if(step < 0) {
34337dd7cddfSDavid du Colombier         ip   += npixel-1;
34347dd7cddfSDavid du Colombier         out  += npixel-1;
34357dd7cddfSDavid du Colombier         errv += 4*(npixel-1);
34367dd7cddfSDavid du Colombier       }
34377dd7cddfSDavid du Colombier 
34387dd7cddfSDavid du Colombier       errc[0] = 0; errc[1] = 0; errc[2] = 0; errc[3] = 0;
34397dd7cddfSDavid du Colombier 
34407dd7cddfSDavid du Colombier       while(npixel-- > 0) {
34417dd7cddfSDavid du Colombier 
34427dd7cddfSDavid du Colombier          register  stc_pixel ci,mode;
34437dd7cddfSDavid du Colombier          register  long           k,v,n;
34447dd7cddfSDavid du Colombier          register  int pixel; /* internal pixel-value */
34457dd7cddfSDavid du Colombier 
34467dd7cddfSDavid du Colombier          ci      = *ip; ip += step;
34477dd7cddfSDavid du Colombier 
34487dd7cddfSDavid du Colombier          mode    = ci & 3;
34497dd7cddfSDavid du Colombier          k       = (ci>>2) & 0x3ff;
34507dd7cddfSDavid du Colombier          pixel   = 0;
34517dd7cddfSDavid du Colombier 
34527dd7cddfSDavid du Colombier          v       = k+errv[3]+((7*errc[3])>>4);
34537dd7cddfSDavid du Colombier 
34547dd7cddfSDavid du Colombier          if(mode == 3) { /* only Black allowed to fire */
34557dd7cddfSDavid du Colombier 
34567dd7cddfSDavid du Colombier             if(v > 511) {
34577dd7cddfSDavid du Colombier                v     -= 1023;
34587dd7cddfSDavid du Colombier                pixel  = BLACK;
34597dd7cddfSDavid du Colombier             }
34607dd7cddfSDavid du Colombier             errv[3-(step<<2)] += ((3*v+8)>>4);        /* 3/16 */
34617dd7cddfSDavid du Colombier             errv[3]            = ((5*v+errc[3]+8)>>4);/* 5/16 +1/16 (rest) */
34627dd7cddfSDavid du Colombier             errc[3]            = v;
34637dd7cddfSDavid du Colombier 
34647dd7cddfSDavid du Colombier             errv[0] = errv[0] < -190 ? -190 : errv[0] < 190 ? errv[0] : 190;
34657dd7cddfSDavid du Colombier             errv[1] = errv[1] < -190 ? -190 : errv[1] < 190 ? errv[1] : 190;
34667dd7cddfSDavid du Colombier             errv[2] = errv[2] < -190 ? -190 : errv[2] < 190 ? errv[2] : 190;
34677dd7cddfSDavid du Colombier 
34687dd7cddfSDavid du Colombier             errc[0] = 0; errc[1] = 0; errc[2] = 0;
34697dd7cddfSDavid du Colombier 
34707dd7cddfSDavid du Colombier          } else if(v > 511) { /* black known to fire */
34717dd7cddfSDavid du Colombier 
34727dd7cddfSDavid du Colombier             v    -= 1023;
34737dd7cddfSDavid du Colombier             pixel = BLACK;
34747dd7cddfSDavid du Colombier 
34757dd7cddfSDavid du Colombier             errv[3-(step<<2)] += ((3*v+8)>>4);        /* 3/16 */
34767dd7cddfSDavid du Colombier             errv[3]            = ((5*v+errc[3]+8)>>4);/* 5/16 +1/16 (rest) */
34777dd7cddfSDavid du Colombier             errc[3]            = v;
34787dd7cddfSDavid du Colombier 
34797dd7cddfSDavid du Colombier             n = (ci>>12) & 0x3ff;
34807dd7cddfSDavid du Colombier 
34817dd7cddfSDavid du Colombier             if(mode == 2) { v = k; }
34827dd7cddfSDavid du Colombier             else          { v = n; n = (ci>>22) & 0x3ff; }
34837dd7cddfSDavid du Colombier 
34847dd7cddfSDavid du Colombier             v += errv[2]+((7*errc[2])>>4)-1023;
34857dd7cddfSDavid du Colombier             if(v < -511) v = -511;
34867dd7cddfSDavid du Colombier             errv[2-(step<<2)] += ((3*v+8)>>4);        /* 3/16 */
34877dd7cddfSDavid du Colombier             errv[2]            = ((5*v+errc[2]+8)>>4);/* 5/16 +1/16 (rest) */
34887dd7cddfSDavid du Colombier             errc[2]            = v;
34897dd7cddfSDavid du Colombier 
34907dd7cddfSDavid du Colombier             if(mode == 1) { v = k; }
34917dd7cddfSDavid du Colombier             else          { v = n; n = (ci>>22) & 0x3ff; }
34927dd7cddfSDavid du Colombier 
34937dd7cddfSDavid du Colombier             v += errv[1]+((7*errc[1])>>4)-1023;
34947dd7cddfSDavid du Colombier             if(v < -511) v = -511;
34957dd7cddfSDavid du Colombier             errv[1-(step<<2)] += ((3*v+8)>>4);        /* 3/16 */
34967dd7cddfSDavid du Colombier             errv[1]            = ((5*v+errc[1]+8)>>4);/* 5/16 +1/16 (rest) */
34977dd7cddfSDavid du Colombier             errc[1]            = v;
34987dd7cddfSDavid du Colombier 
34997dd7cddfSDavid du Colombier             if(mode == 0) v = k;
35007dd7cddfSDavid du Colombier             else          v = n;
35017dd7cddfSDavid du Colombier 
35027dd7cddfSDavid du Colombier             v += errv[0]+((7*errc[0])>>4)-1023;
35037dd7cddfSDavid du Colombier             if(v < -511) v = -511;
35047dd7cddfSDavid du Colombier             errv[0-(step<<2)] += ((3*v+8)>>4);        /* 3/16 */
35057dd7cddfSDavid du Colombier             errv[0]            = ((5*v+errc[0]+8)>>4);/* 5/16 +1/16 (rest) */
35067dd7cddfSDavid du Colombier             errc[0]            = v;
35077dd7cddfSDavid du Colombier 
35087dd7cddfSDavid du Colombier          } else { /* Black does not fire initially */
35097dd7cddfSDavid du Colombier 
35107dd7cddfSDavid du Colombier             long kv = v; /* Black computed after colors */
35117dd7cddfSDavid du Colombier 
35127dd7cddfSDavid du Colombier             n = (ci>>12) & 0x3ff;
35137dd7cddfSDavid du Colombier 
35147dd7cddfSDavid du Colombier             if(mode == 2) { v = k; }
35157dd7cddfSDavid du Colombier             else          { v = n; n = (ci>>22) & 0x3ff; }
35167dd7cddfSDavid du Colombier 
35177dd7cddfSDavid du Colombier             v += errv[2]+((7*errc[2])>>4);
35187dd7cddfSDavid du Colombier             if(v > 511) {
35197dd7cddfSDavid du Colombier                pixel |= YELLOW;
35207dd7cddfSDavid du Colombier                v     -= 1023;
35217dd7cddfSDavid du Colombier             }
35227dd7cddfSDavid du Colombier             errv[2-(step<<2)] += ((3*v+8)>>4);        /* 3/16 */
35237dd7cddfSDavid du Colombier             errv[2]            = ((5*v+errc[2]+8)>>4);/* 5/16 +1/16 (rest) */
35247dd7cddfSDavid du Colombier             errc[2]            = v;
35257dd7cddfSDavid du Colombier 
35267dd7cddfSDavid du Colombier             if(mode == 1) { v = k; }
35277dd7cddfSDavid du Colombier             else          { v = n; n = (ci>>22) & 0x3ff; }
35287dd7cddfSDavid du Colombier 
35297dd7cddfSDavid du Colombier             v += errv[1]+((7*errc[1])>>4);
35307dd7cddfSDavid du Colombier             if(v > 511) {
35317dd7cddfSDavid du Colombier                pixel |= MAGENTA;
35327dd7cddfSDavid du Colombier                v     -= 1023;
35337dd7cddfSDavid du Colombier             }
35347dd7cddfSDavid du Colombier             errv[1-(step<<2)] += ((3*v+8)>>4);        /* 3/16 */
35357dd7cddfSDavid du Colombier             errv[1]            = ((5*v+errc[1]+8)>>4);/* 5/16 +1/16 (rest) */
35367dd7cddfSDavid du Colombier             errc[1]            = v;
35377dd7cddfSDavid du Colombier 
35387dd7cddfSDavid du Colombier             if(mode == 0) v = k;
35397dd7cddfSDavid du Colombier             else          v = n;
35407dd7cddfSDavid du Colombier 
35417dd7cddfSDavid du Colombier             v += errv[0]+((7*errc[0])>>4);
35427dd7cddfSDavid du Colombier             if(v > 511) {
35437dd7cddfSDavid du Colombier                pixel |= CYAN;
35447dd7cddfSDavid du Colombier                v     -= 1023;
35457dd7cddfSDavid du Colombier             }
35467dd7cddfSDavid du Colombier             errv[0-(step<<2)] += ((3*v+8)>>4);        /* 3/16 */
35477dd7cddfSDavid du Colombier             errv[0]            = ((5*v+errc[0]+8)>>4);/* 5/16 +1/16 (rest) */
35487dd7cddfSDavid du Colombier             errc[0]            = v;
35497dd7cddfSDavid du Colombier 
35507dd7cddfSDavid du Colombier             v = kv;
35517dd7cddfSDavid du Colombier             if(pixel == (CYAN|MAGENTA|YELLOW)) {
35527dd7cddfSDavid du Colombier                pixel = BLACK;
35537dd7cddfSDavid du Colombier                v     = v > 511 ? v-1023 : -511;
35547dd7cddfSDavid du Colombier             }
35557dd7cddfSDavid du Colombier             errv[3-(step<<2)] += ((3*v+8)>>4);        /* 3/16 */
35567dd7cddfSDavid du Colombier             errv[3]            = ((5*v+errc[3]+8)>>4);/* 5/16 +1/16 (rest) */
35577dd7cddfSDavid du Colombier             errc[3]            = v;
35587dd7cddfSDavid du Colombier 
35597dd7cddfSDavid du Colombier          }
35607dd7cddfSDavid du Colombier 
35617dd7cddfSDavid du Colombier          errv += step<<2;
35627dd7cddfSDavid du Colombier          *out  = pixel; out += step;
35637dd7cddfSDavid du Colombier 
35647dd7cddfSDavid du Colombier       }                                         /* loop over pixels */
35657dd7cddfSDavid du Colombier 
35667dd7cddfSDavid du Colombier /* ============================================================= */
35677dd7cddfSDavid du Colombier    } /* initialisation, white or scanline-processing             */
35687dd7cddfSDavid du Colombier /* ============================================================= */
35697dd7cddfSDavid du Colombier 
35707dd7cddfSDavid du Colombier    return 0;
35717dd7cddfSDavid du Colombier }
3572