~ubuntu-branches/ubuntu/vivid/ghostscript/vivid-security

« back to all changes in this revision

Viewing changes to base/gdevupd.c

  • Committer: Package Import Robot
  • Author(s): Till Kamppeter
  • Date: 2013-08-09 20:01:36 UTC
  • mfrom: (1.1.37)
  • Revision ID: package-import@ubuntu.com-20130809200136-amb6zrr7hnjb5jq9
Tags: 9.08~rc1~dfsg-0ubuntu1
* New upstream release
   - Ghostscript 9.08rc1.
   - We are using the system's liblcms2 and libopenjpeg now.
* debian/patches/020130401-852e545-pxl-xl-driver-produced-drawing-commands-without-setting-color-space.patch:
  Removed patch backported from upstream.
* debian/patches/ojdk-8007925+8007926.patch,
  debian/patches/ojdk-8007927.patch,
  debian/patches/ojdk-8007929.patch,
  debian/patches/ojdk-8009654.patch: Removed patches on build in liblcms2, we
  use the system's liblcms2 now.
* debian/patches/2001_docdir_fix_for_debian.patch: Manually updated to new
  upstream source code.
* debian/patches/2003_support_multiarch.patch: Refreshed with quilt.
* debian/control: Added build dependencies on liblcms2-dev and
  libopenjpeg-dev.
* debian/rules: Check for removed lcms2/ and openjpeg/ subdirectories in
  the repackaging check again, also set build options for shared liblcms2
  and libopenjpeg libraries.
* debian/rules: Makefile.in and configure.ac are in the root directory of
  the source now and do not need to get linked from base/. Also there is no
  gstoraster and gstopxl CUPS filter in the package any more and no
  "install-cups" make target any more.
* debian/control, debian/rules, debian/ghostscript-cups.install,
  debian/ghostscript-cups.ppd-updater: Removed the ghostscript-cups binary
  package. The files are now provided by cups-filters.
* debian/symbols.common: Updated for new upstream source. Applied patch
  which dpkg-gensymbols generated for debian/libgs9.symbols to this file.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/* Copyright (C) 2001-2012 Artifex Software, Inc.
2
 
   All Rights Reserved.
3
 
 
4
 
   This software is provided AS-IS with no warranty, either express or
5
 
   implied.
6
 
 
7
 
   This software is distributed under license and may not be copied,
8
 
   modified or distributed except as expressly authorized under the terms
9
 
   of the license contained in the file LICENSE in this distribution.
10
 
 
11
 
   Refer to licensing information at http://www.artifex.com or contact
12
 
   Artifex Software, Inc.,  7 Mt. Lassen Drive - Suite A-134, San Rafael,
13
 
   CA  94903, U.S.A., +1(415)492-9861, for further information.
14
 
*/
15
 
 
16
 
 
17
 
/* gdevupd.c Revision: 1.88 */
18
 
/* "uniprint" -- Ugly Printer Driver by Gunther Hess (ghess@elmos.de) */
19
 
 
20
 
/* Revision-History:
21
 
   23-Mar-1997 -  1.43: First published version
22
 
   24-Mar-1997 -  1.44: gs4.03 compatible version on the web
23
 
   31-Mar-1997 -  1.53: First Version inside gs-fileset (limited)
24
 
   28-Apr-1997 -  1.54: Version intended for public gs-release
25
 
    4-May-1997 -  1.55: Deactivated an accidentially active Debug-Option
26
 
   14-Jun-1997 -  1.56: Bug-Workaround for White on White Printing (gs5.0)
27
 
   17-Jun-1997 -  1.57: More reasonable Fix for the above Bug
28
 
   ...
29
 
    7-Jul-1997 -  1.68: NULL-Param-BUG, HR's BJC, Pwidth/-height BUG, YFlip
30
 
   25-Jul-1997 -  1.69: Bug-Fix: incomplete Change of PHEIGHT-Treatment
31
 
    4-Aug-1997 -  1.70: Arrgh: still incomplete Change of PHEIGHT-Treatment
32
 
   17-AUG-1997 -  1.71: Fix of BSD-sprintf bug. (returns char * there)
33
 
   ...
34
 
   28-Sep-1997 -  1.77: Fixed the byte<>char and casted-lvalue Problems
35
 
   ...
36
 
   12-Mar-1998 -  1.80: Some PJL-Functions, Map-Bug-Fix (by Wonder-Wolfgang)
37
 
   21-Oct-1998 -  1.81: Added RGB2CMY[_]K Modi (Eric Domenjoud)
38
 
   ...
39
 
   27-Feb-2000 -  1.84: CMYKgenerate with forced K-Control [distributed]
40
 
    2-Apr-2000 -        Unofficial modifications for Epson Stylus Color 300. GR
41
 
    5-Apr-2000 -        GR fixed last row not filled bug in wrtescnm
42
 
    7-May-2000 -  1.85: Always BOP/EOP-Massaging for RTL-Output (Dan Coby)
43
 
  ...
44
 
    7-May-2000 -  1.87: integrated stc300-code by Glenn Ramsey
45
 
       "       -  1.88: reduced "cast discards `const'" warnings to 1
46
 
 
47
 
*/
48
 
 
49
 
/* Canon BJC 610 additions from (hr)
50
 
      Helmut Riegler <helmut-riegler@net4you.co.at>
51
 
 
52
 
   The BJC-4000 can be supported very easily, only by creating the right .upp
53
 
   parameter file. If you have this printer and you are willing to do this,
54
 
   contact me, I'll give you the technical details (ESC codes).
55
 
*/
56
 
 
57
 
/* Epson Stylus Color 300 (FMT_ESCNMY) additions 2-Apr-2000.
58
 
   Glenn Ramsey <glennr@es.co.nz>
59
 
*/
60
 
 
61
 
/* ------------------------------------------------------------------- */
62
 
/* Compile-Time-Options                                                */
63
 
/* ------------------------------------------------------------------- */
64
 
 
65
 
/**
66
 
There are two compile-time options for this driver:
67
 
   1. UPD_SIGNAL   enables interrupt detection, that aborts printing and
68
 
   2. UPD_MESSAGES controls the amount of messages generated by the driver
69
 
*/
70
 
 
71
 
#ifndef   UPD_SIGNAL
72
 
#ifdef      __unix__
73
 
#define       UPD_SIGNAL 1 /** Activated, if undefined, on UNIX-Systems */
74
 
#else  /*  !__unix__ */
75
 
#define       UPD_SIGNAL 0 /** Inactive on others, by default */
76
 
#endif /*  ?__unix__ */
77
 
#endif /* UPD_SIGNAL */
78
 
 
79
 
#ifndef   UPD_MESSAGES
80
 
#define   UPD_MESSAGES UPD_M_ERROR /** Error-messages only, if not defined */
81
 
#endif /* UPD_MESSAGES */
82
 
 
83
 
/* ------------------------------------------------------------------- */
84
 
/* Required Header-Files                                               */
85
 
/* ------------------------------------------------------------------- */
86
 
 
87
 
#include "stdint_.h"
88
 
 
89
 
#ifndef   hess_test_INCLUDED /* A private test-Option */
90
 
 
91
 
#include "gdevprn.h" /** Printer-superclass header */
92
 
#include "gsparam.h" /** For the Parameter-Handling (optional) */
93
 
 
94
 
#include <stdlib.h>  /** for rand */
95
 
#include <limits.h>  /** for INT_MIN */
96
 
#include <ctype.h>   /** for isupper */
97
 
 
98
 
#endif /* hess_test_INCLUDED    A private test-Option */
99
 
 
100
 
#if       UPD_SIGNAL
101
 
#include <signal.h> /** Only included, if UPD_SIGNAL is active (true) */
102
 
#endif /* UPD_SIGNAL */
103
 
 
104
 
/* ------------------------------------------------------------------- */
105
 
/* Device-Structure (including an additional Structure-Pointer-Type)   */
106
 
/* ------------------------------------------------------------------- */
107
 
 
108
 
typedef struct upd_s upd_t,*upd_p; /** Type & Pointer of device-specifics */
109
 
typedef const upd_t *upd_pc;       /** Pointer to constant device-specfics */
110
 
 
111
 
typedef struct upd_device_s {      /** The driver must typedef ... */
112
 
   gx_device_common;               /**    common fields for all devices */
113
 
   gx_prn_device_common;           /**    common fields for printing-devices */
114
 
   gs_param_string upd_version;    /**    Source-Code Version */
115
 
   upd_p           upd;            /**    uniprint-specific extension */
116
 
} upd_device;                      /** some type usually  <name>_device> */
117
 
 
118
 
/* ------------------------------------------------------------------- */
119
 
/* Major Driver-Functions                                              */
120
 
/* ------------------------------------------------------------------- */
121
 
 
122
 
static dev_proc_print_page(upd_print_page); /** print a page (required) */
123
 
 
124
 
static dev_proc_open_device(upd_open);      /** device-initialization (opt) */
125
 
static dev_proc_close_device(upd_close);    /** device-release (opt) */
126
 
 
127
 
static dev_proc_get_params(upd_get_params); /** export parameters (opt) */
128
 
static dev_proc_put_params(upd_put_params); /** import parameters (opt) */
129
 
 
130
 
/**
131
 
A `normal' Device-Driver wil only implement one of the following pairs
132
 
of functions for the colormapping. But "uniprint" is something special and
133
 
it really provides all four reasonable pairs and in addition to that
134
 
a fifth set of functions, that delivers better FS-Results with KCMY.
135
 
 
136
 
The first pair is for the mapping into a single stored component, that
137
 
usually represents a grayscale. But nevertheless GHOSTSCRIPT deals with
138
 
RGB-Values, but promises to deal with R==G==B-Values when asking to map.
139
 
 
140
 
The second pair deals with RGB-Values.
141
 
*/
142
 
 
143
 
static dev_proc_encode_color( upd_rgb_1color);  /** Gray-Gray->Index */
144
 
static dev_proc_decode_color( upd_1color_rgb);  /** Gray-Index->Gray */
145
 
 
146
 
static dev_proc_encode_color( upd_rgb_3color);  /** RGB->RGB-Index */
147
 
static dev_proc_decode_color( upd_3color_rgb);  /** RGB-Index->RGB */
148
 
 
149
 
/**
150
 
The third pair maps RGB-Values into four components, which one might
151
 
expect to be KCMY-Values, but they are not: "uniprint" considers this four
152
 
Values as White+RGB Values!
153
 
*/
154
 
 
155
 
static dev_proc_encode_color( upd_rgb_4color);  /** RGB->WRGB-Index */
156
 
static dev_proc_decode_color(upd_4color_rgb);   /** WRGB-Index->RGB */
157
 
 
158
 
/**
159
 
The fourth pair deals with KCMY-Values. The Mapping-Function
160
 
is of a different type, due to the additional argument, but the
161
 
inverse-Function is of the same type, and expects RGB-Values to be
162
 
deliverd into the receiving 3-Component-Array!
163
 
*/
164
 
 
165
 
static dev_proc_encode_color(upd_cmyk_icolor); /** KCMY->KCMY-Index */
166
 
static dev_proc_decode_color( upd_icolor_rgb);  /** KCMY->RGB-Index */
167
 
 
168
 
/**
169
 
The difference between the icolor-pair and the kcolor-pair is the enforced
170
 
black-generation in the forward-mapping. that is taken into account by the
171
 
reverse-mapping too.
172
 
*/
173
 
 
174
 
static dev_proc_encode_color(upd_cmyk_kcolor); /** adds black generation */
175
 
static dev_proc_decode_color( upd_kcolor_rgb);  /** watches black-gen */
176
 
 
177
 
/**
178
 
"ovcolor" is CMYK with Black-Generation and Undercolor-Removal, which
179
 
is suitable for overprinting:
180
 
   CMY' = (CMY-K')/(1-K')
181
 
with
182
 
   K'   = min(C,M,Y)
183
 
*/
184
 
 
185
 
static dev_proc_encode_color(upd_rgb_ovcolor);  /** RGB->CMYK-Index */
186
 
#define upd_ovcolor_rgb upd_icolor_rgb            /** CMYK-Index->RGB */
187
 
 
188
 
/**
189
 
"novcolor" is CMYK with Black-Generation and Undercolor-Removal, which
190
 
is suitable for CMY / K - Printing:
191
 
   CMY' = CMY-K'
192
 
with
193
 
   K'   = min(C,M,Y)
194
 
*/
195
 
 
196
 
static dev_proc_encode_color(upd_rgb_novcolor); /** RGB->CMYK-Index */
197
 
#define upd_novcolor_rgb upd_icolor_rgb           /** CMYK-Index->RGB */
198
 
 
199
 
/**
200
 
For the sake of efficiency there is that bunch of functions and they
201
 
perform no validity checks, thus it has to be assured that they are
202
 
only active, if there is a valid device-structure for then.
203
 
upd_procs_map performs this task.
204
 
*/
205
 
 
206
 
static int             upd_procs_map( upd_device *udev);
207
 
 
208
 
/* ------------------------------------------------------------------- */
209
 
/* Prototype of the Device-Structure (the only thing exported!)        */
210
 
/* ------------------------------------------------------------------- */
211
 
 
212
 
/**
213
 
"uniprint" needs a procedure-table of its own, since it provides several
214
 
optional procedures. Simpler-Drivers (e.g. non-color-drivers) may use
215
 
prn_std_procs instead of defining their own procedure-table.
216
 
*/
217
 
 
218
 
#define upd_set_dev_proc(dev, p, proc) \
219
 
   ((dev)->std_procs.p = (dev)->orig_procs.p = (proc))
220
 
 
221
 
static gx_device_procs upd_procs = {  /** Table of procedures */
222
 
   upd_open,                      /** open-function, upd-special */
223
 
   gx_default_get_initial_matrix, /** retrieve matrix */
224
 
   gx_default_sync_output,        /** sync display */
225
 
   gdev_prn_output_page,          /** superclass-print (calls back) */
226
 
   upd_close,                     /** close-function, upd-special */
227
 
   gx_default_map_rgb_color,      /** RGB-mapping */
228
 
   gx_default_map_color_rgb,      /** reverse mapping */
229
 
   NULL,                          /** fill_rectangle */
230
 
   NULL,                          /** tile_rectangle */
231
 
   NULL,                          /** copy_mono */
232
 
   NULL,                          /** copy_color */
233
 
   NULL,                          /** draw_line */
234
 
   gx_default_get_bits,           /** reads scanlines, e.g. for the driver */
235
 
   upd_get_params,                /** Export parameters, upd-special */
236
 
   upd_put_params,                /** Import parameters, upd-special */
237
 
   gx_default_map_cmyk_color      /** KCMY-mapping */
238
 
};                                     /** */
239
 
 
240
 
/**
241
 
The prototype-instance of the device-structure _must_ have the name
242
 
"gs_uniprint_device", where "uniprint" is the external name of the driver.
243
 
This notice is bluntly copied from drivers.txt, which a potential
244
 
driver-author should carefully read.
245
 
 
246
 
Just to mention: this prototype is quite similar to the one, that
247
 
"prn_device" produces and it identifies "uniprint" as a monochrome 1Bit
248
 
device to GHOSTSCRIPT. But during the lifetime of a driver-instance
249
 
this might change.
250
 
 
251
 
This is the end of the part of declarations, that are common for
252
 
color-drivers. The next sections address "uniprint"-specific data-types
253
 
and the reader might directly skip to the section titled
254
 
 
255
 
    upd_print_page: The main workhorse
256
 
*/
257
 
 
258
 
upd_device far_data gs_uniprint_device = { /** */
259
 
   prn_device_body(upd_device, upd_procs,  /** The Type and Procedures */
260
 
      "uniprint",                          /** External name of the Device */
261
 
      DEFAULT_WIDTH_10THS,                 /** X-Size (1/10") */
262
 
      DEFAULT_HEIGHT_10THS,                /** Y-Size (1/10") */
263
 
      72, 72,                              /** X,Y-DpI */
264
 
      0.0, 0.0, 0.0, 0.0,                  /** L,B,R,T-Margin */
265
 
      1, /**  color_info.num_components 1/3/4 */
266
 
      1, /**  color_info.depth         1/2/4/8/16/24/32 */
267
 
      1, /**  color_info.max_gray      # of distinct gray levels -1 (255/1) */
268
 
      0, /**  color_info.max_color     # of distinct color levels -1 (255/1/0)*/
269
 
      2, /**  color_info.dither_grays  size of gray ramp for dithering (256/2) */
270
 
      0, /**  color_info.dither_colors size of color cube ditto (256/2/0) */
271
 
      upd_print_page),                     /** Print-procedure */
272
 
      { NULL, 0, true },                   /** Driver-Version */
273
 
      NULL                                 /** upd-field: Initially none */
274
 
};                                         /** */
275
 
 
276
 
/* ------------------------------------------------------------------- */
277
 
/* UPD-Data- and Prototypes                                            */
278
 
/* ------------------------------------------------------------------- */
279
 
 
280
 
/*@ gdevupd.h < */
281
 
/* ------------------------------------------------------------------- */
282
 
/* External names of the UPD-Parameters                                */
283
 
/* ------------------------------------------------------------------- */
284
 
 
285
 
/** UPD-Parameters
286
 
 
287
 
"uniprint" supports a hole bunch of external parameters. This Parameters
288
 
fall into the following categories:
289
 
 
290
 
 0. special-string the upd_version, readonly          upd_version
291
 
 1. choice         name-indices, stored in            upd->choice
292
 
 2. boolean        single bits, stored in             upd->flags
293
 
 3. integers       single numbers, stored in          upd->ints
294
 
 4. integer-Arrays arrays of numbers, stored in       upd->int_a
295
 
 5. string         device-commands, stored in         upd->strings
296
 
 6. string-Arrays  arrayed device-commands, stored in upd->string_a
297
 
 7. float-Arrays   arrays of floats, stored in        upd->float_a
298
 
 
299
 
Currently there is no need for single floats, but they may be introduced in
300
 
future versions. Since "uniprint" somtimes manipulates the contents of the
301
 
array-variables it dynamically allocates storage for all this parameters.
302
 
 
303
 
The following sections defines the names for this parameters in the order,
304
 
they are stored within the mentioned dynamic fields of the upd-structure.
305
 
A NULL-name means that the corresponding parameter is not externally visible.
306
 
Besides the name, there is always a symbolic index #defined, that MUST match
307
 
the Index-Number of the name.
308
 
Actually
309
 
*/
310
 
 
311
 
static const char *const upd_version = "upVersion"; /** Readonly Version */
312
 
 
313
 
/** Names for the multiple-choice-Parameters
314
 
 
315
 
Currently there are three Parameters, that are handled as named choices.
316
 
For each of them, there is an array of constant strings that consists of
317
 
 
318
 
1.       the Parameter-Name
319
 
2. - n-1 the available choices.
320
 
n.       A terminating NULL
321
 
*/
322
 
 
323
 
static const char *const upd_mapper[] = { "upColorModel",
324
 
#define MAP_GRAY        1   /** Monochrome & Grayscale Devices */
325
 
"DeviceGray",               /** Monochrome & Grayscale Devices */
326
 
#define MAP_RGBW        2   /** RGB with White-Generation */
327
 
"DeviceRGBW",               /** RGB with White-Generation */
328
 
#define MAP_RGB         3   /** RGB-Mapping */
329
 
"DeviceRGB",                /** RGB-Mapping */
330
 
#define MAP_CMYK        4   /** CMYK-Mapping */
331
 
"DeviceCMYK",               /** CMYK-Mapping */
332
 
#define MAP_CMYKGEN     5   /** CMYK-Mapping with Black-Generation */
333
 
"DeviceCMYKgenerate",       /** CMYK-Mapping with Black-Generation */
334
 
#define MAP_RGBOV       6   /** RGB->CMYK with BG and UCR for CMYK */
335
 
"DeviceRGB2CMYK",           /** RGB->CMYK with BG and UCR for CMYK */
336
 
#define MAP_RGBNOV      7   /** RGB->CMYK with BG and UCR for CMY + K */
337
 
"DeviceRGB2CMY_K",          /** RGB->CMYK with BG and UCR for CMY + K */
338
 
NULL
339
 
};
340
 
 
341
 
static const char *const upd_render[] = { "upRendering",
342
 
#define RND_FSCOMP      1   /** Componentwise Floyd-Steinberg */
343
 
"ErrorDiffusion",           /** Componentwise Floyd-Steinberg */
344
 
#define RND_FSCMYK      2   /** CMYK-specialized 32Bit Floyd-Steinberg */
345
 
"FSCMYK32",                 /** CMYK-specialized 32Bit Floyd-Steinberg */
346
 
#define RND_FSCMY_K     3   /** CMY_K Rendering */
347
 
"FSCMY_K",
348
 
NULL
349
 
};
350
 
 
351
 
static const char *const upd_format[] = { "upOutputFormat",
352
 
#define FMT_RAS         1   /** Generates SUN-Rasterfiles */
353
 
"SunRaster",                /** Generates SUN-Rasterfiles */
354
 
#define FMT_EPSON       2   /** Generates X+Y-Weaved ESC/P-Output */
355
 
"Epson",                    /** Generates X+Y-Weaved ESC/P-Output */
356
 
#define FMT_ESCP2Y      3   /** Generates Y-Weaved ESC/P2-Output */
357
 
"EscP2",                    /** Generates Y-Weaved ESC/P2-Output */
358
 
#define FMT_ESCP2XY     4   /** Generates X+Y-Weaved ESC/P2-Output */
359
 
"EscP2XY",                  /** Generates X+Y-Weaved ESC/P2-Output */
360
 
#define FMT_RTL         5   /** Generates HP-PCL/RTL-Output */
361
 
"Pcl",                      /** Generates HP-PCL/RTL-Output */
362
 
#define FMT_CANON       6   /** Generates Output for Canon extended mode (hr) */
363
 
"Canon",                    /** Generates Output for Canon extended mode (hr) */
364
 
#define FMT_ESCNMY      7   /** Generates Output for Epson Stylus Color 300 (GR) */
365
 
"EscNozzleMap",             /** Generates Output for Epson Stylus Color 300 (GR) */
366
 
NULL
367
 
};
368
 
 
369
 
static const char *const *const upd_choice[] = {
370
 
#define C_MAPPER        0   /** the selected Mapper */
371
 
   upd_mapper,
372
 
#define C_RENDER        1   /** the selected Rendering */
373
 
   upd_render,
374
 
#define C_FORMAT        2   /** the selected Choice */
375
 
   upd_format
376
 
};
377
 
 
378
 
/** Names for the flags (bool)
379
 
*/
380
 
 
381
 
static const char *const upd_flags[] = {      /** */
382
 
#define B_REVDIR            ((uint32_t) 1<<0)   /** FS-Dir-Flag */
383
 
"upFSReverseDirection",                       /** FS-Dir-Flag */
384
 
#define B_FIXDIR            ((uint32_t) 1<<1)   /** Do not alter FS-direction */
385
 
"upFSFixedDirection",                         /** Do not alter FS-direction */
386
 
#define B_FSWHITE           ((uint32_t) 1<<2)   /** Process white in FS */
387
 
"upFSProcessWhiteSpace",                      /** Process white in FS */
388
 
#define B_FSZERO            ((uint32_t) 1<<3)   /** Zero FS-Initialization */
389
 
"upFSZeroInit",                               /** Zero FS-Initialization */
390
 
 
391
 
#define B_PAGEWIDTH         ((uint32_t) 1<<4)   /** Adjust Width in BOP */
392
 
"upAdjustPageWidthCommand",                   /** Adjust Page-Width in BOP */
393
 
#define B_PAGELENGTH        ((uint32_t) 1<<5)   /** Adjust Length in BOP */
394
 
"upAdjustPageLengthCommand",                  /** Adjust Page-Length in BOP */
395
 
#define B_TOPMARGIN         ((uint32_t) 1<<6)   /** Adjust Top-Margin in BOP */
396
 
"upAdjustTopMarginCommand",                   /** Adjust Top-Margin in BOP */
397
 
#define B_BOTTOMMARGIN      ((uint32_t) 1<<7)   /** Adjust Bottom-Margin in BOP */
398
 
"upAdjustBottomMarginCommand",                /** Adjust Bottom-Margin in BOP */
399
 
#define B_RESOLUTION        ((uint32_t) 1<<8)   /** Adjust Resolution in BOP */
400
 
"upAdjustResolutionCommand",                  /** Adjust Resolution in BOP */
401
 
#define B_MEDIASIZE         ((uint32_t) 1<<9)   /** Adjust Mediasize in BOP */
402
 
"upAdjustMediaSize",                          /** Adjust Mediasize in BOP */
403
 
 
404
 
#define B_XABS              ((uint32_t) 1<<10)  /** Use Absolute X-Values */
405
 
"upFormatXabsolute",                          /** Use Absolute X-Values */
406
 
#define B_YABS              ((uint32_t) 1<<11)  /** Use Absolute Y-Values */
407
 
"upFormatYabsolute",                          /** Use Absolute Y-Values */
408
 
 
409
 
#define B_MAP               ((uint32_t) 1<<12)  /** Mapping Initialized */
410
 
"upColorModelInitialized",                    /** Mapping Initialized */
411
 
#define B_BUF               ((uint32_t) 1<<13)  /** Raster-Buffer Initialized */
412
 
"upRasterBufferInitialized",                  /** Raster-Buffer Initialized */
413
 
#define B_RENDER            ((uint32_t) 1<<14)  /** Rendering Initialized */
414
 
"upRenderingInitialized",                     /** Rendering Initialized */
415
 
#define B_FORMAT            ((uint32_t) 1<<15)  /** Formatter Initialized */
416
 
"upOutputFormatInitialized",                  /** Formatter Initialized */
417
 
#define B_ABORT             ((uint32_t) 1<<16)  /** Abort on Interrupt */
418
 
"upOutputAborted",                            /** Abort on Interrupt */
419
 
#define B_ERROR             ((uint32_t) 1<<17)  /** Severe Error detected */
420
 
"upErrorDetected",                            /** Severe Error detected */
421
 
 
422
 
#define B_OPEN              ((uint32_t) 1<<18)  /** Open-Command written */
423
 
"upWroteData",                                /** Open-Command written */
424
 
 
425
 
#define B_YFLIP             ((uint32_t) 1<<19)  /** Mirrored printing (hr) */
426
 
"upYFlip",                                    /** Mirrored printing (hr) */
427
 
 
428
 
#define B_REDUCEK           ((uint32_t) 1<<20)  /** CMY->Black Reduction */
429
 
"upFSReduceK"
430
 
 
431
 
};
432
 
 
433
 
/** B_OK4GO: Bits required to execute the print-loop */
434
 
 
435
 
#define B_OK4GO  (B_MAP | B_BUF | B_RENDER | B_FORMAT)
436
 
 
437
 
/** Names for the ints
438
 
*/
439
 
 
440
 
static const char *const upd_ints[] = {
441
 
#define I_PWIDTH            0                 /** Output-Width */
442
 
"upOutputWidth",
443
 
#define I_PHEIGHT           1                 /** Output-Height */
444
 
"upOutputHeight",
445
 
#define I_OCOMP             2                 /** Output-Components */
446
 
"upOutputComponents",
447
 
#define I_NSCNBUF           3                 /** Output-Buffers */
448
 
"upOutputBuffers",
449
 
#define I_XSTEP             4                 /** Unit-Step */
450
 
"upOutputXStep", /* > 0 -> divide Raster-X, < 0 muliply Raster-X */
451
 
#define I_XOFS              5                 /** abs. X-Offset */
452
 
"upOutputXOffset",
453
 
#define I_YSTEP             6                 /** Unit-Step */
454
 
"upOutputYStep", /* > 0 -> divide Raster-Y, < 0 muliply Raster-Y */
455
 
#define I_YOFS              7                 /** abs. Y-Offset */
456
 
"upOutputYOffset",
457
 
#define I_PINS2WRITE        8                 /** Number of Pins */
458
 
"upOutputPins",
459
 
 
460
 
#define I_NXPASS            9                 /** X-Passes */
461
 
"upWeaveXPasses",
462
 
#define I_NYPASS           10                 /** Y-Passes */
463
 
"upWeaveYPasses",
464
 
#define I_NPASS            11                 /** Total # Passes */
465
 
"upWeavePasses",
466
 
#define I_BEG_Y            12                 /** Start of normal Weaving */
467
 
"upWeaveInitialScan",
468
 
#define I_END_Y            13                 /** End of normal Weaving */
469
 
"upWeaveFinalScan",
470
 
#define I_BEGSKIP          14                 /** A Scan-Offset */
471
 
"upWeaveYOffset",
472
 
#define I_ROWS             15                 /** Output rows per pass */
473
 
"upNozzleMapRowsPerPass",
474
 
#define I_PATRPT           16                 /** mask pattern repeat interval */
475
 
"upNozzleMapPatternRepeat"
476
 
};
477
 
 
478
 
/** Names for the Integer-Arrays
479
 
*/
480
 
 
481
 
static const char *const upd_int_a[] = {      /** */
482
 
#define IA_COLOR_INFO       0                 /** external color_info */
483
 
"upColorInfo",                                /** external color_info */
484
 
 
485
 
#define IA_COMPBITS         1                 /** Bits stored per Component */
486
 
"upComponentBits",                            /** Bits stored per Component */
487
 
#define IA_COMPSHIFT        2                 /** Shift for the stored Bits */
488
 
"upComponentShift",                           /** Shift for the stored Bits */
489
 
#define IA_COMPORDER        3                 /** Order of Output-Components */
490
 
"upOutputComponentOrder",                     /** Order of Output-Components */
491
 
 
492
 
#define IA_STD_DY           4                 /** Standard-Weave Feeds */
493
 
"upWeaveYFeeds",                              /** Standard-Weave Feeds */
494
 
#define IA_STD_IX           5                 /** Standard-Weave X-Passes */
495
 
"upWeaveXStarts",                             /** Standard-Weave X-Start */
496
 
#define IA_BEG_DY           6                 /** Initial-Weave Feeds */
497
 
"upWeaveInitialYFeeds",                       /** Initial-Weave Feeds */
498
 
#define IA_BEG_IX           7                 /** Initial-Weave X-Start */
499
 
"upWeaveInitialXStarts",                      /** Initial-Weave X-Start */
500
 
#define IA_BEGBOT           8                 /** Initial-Weave #Pins */
501
 
"upWeaveInitialPins",                         /** Initial-Weave #Pins */
502
 
#define IA_END_DY           9                 /** Final-Weave Feeds */
503
 
"upWeaveFinalYFeeds",                         /** Final-Weave Feeds */
504
 
#define IA_END_IX          10                 /** Final-Weave X-Start */
505
 
"upWeaveFinalXStarts",                        /** Final-Weave X-Start */
506
 
#define IA_ENDTOP          11                 /** Final-Weave #Pins */
507
 
"upWeaveFinalPins",                           /** Final-Weave #Pins */
508
 
#define IA_ROWMASK         12                 /** The nozzle to row map */
509
 
"upNozzleMapRowMask",
510
 
#define IA_SCNOFS       13                 /** Mask to scan map */
511
 
"upNozzleMapMaskScanOffset"
512
 
};
513
 
 
514
 
/** Names of the String-Parameters
515
 
*/
516
 
 
517
 
static const char *const upd_strings[] = { /** */
518
 
#define S_MODEL             0                 /** Name of the Printer-Model */
519
 
"upModel",                                    /** Name of the Printer-Model */
520
 
#define S_OPEN              1                 /** Printer-Begin-Job */
521
 
"upBeginJobCommand",                          /** Printer-Begin-Job */
522
 
#define S_CLOSE             2                 /** Printer-End-Job */
523
 
"upEndJobCommand",                            /** Printer-End-Job */
524
 
#define S_BEGIN             3                 /** Printer-Begin-Page */
525
 
"upBeginPageCommand",                         /** Printer-Begin-Page */
526
 
#define  S_END              4                 /** Printer-End-Page */
527
 
"upEndPageCommand",                           /** Printer-End-Page */
528
 
#define  S_ABORT            5                 /** Printer-Abort-Command */
529
 
"upAbortCommand",                             /** Printer-Abort-Command */
530
 
 
531
 
#define S_XMOVE             6                 /** X-Positioning-Command */
532
 
"upXMoveCommand",                             /** X-Positioning-Command */
533
 
#define S_XSTEP             7                 /** X-Step Command (1<I_XSTEP) */
534
 
"upXStepCommand",                             /** X-Step Command (1<I_XSTEP) */
535
 
#define S_SETLF             8                 /** Set-Linefeed-Command */
536
 
"upSetLineFeedCommand",                       /** Set-Linefeed-Command */
537
 
#define S_YMOVE             9                 /** Y-Positioning-Command */
538
 
"upYMoveCommand",                             /** Y-Positioning-Command */
539
 
#define S_YSTEP            10                 /** Y-Step Command (1<I_YSTEP) */
540
 
"upYStepCommand"                              /** Y-Step Command (1<I_YSTEP) */
541
 
}; /** */
542
 
 
543
 
/** Names for the String-Arrays
544
 
*/
545
 
 
546
 
static const char *const upd_string_a[] = {   /** */
547
 
#define SA_SETCOMP          0                 /** Select Components */
548
 
"upSelectComponentCommands",                  /** Select Components */
549
 
#define SA_WRITECOMP        1                 /** Write Component Comands */
550
 
"upWriteComponentCommands"                    /** Write Component Commands */
551
 
};                                            /** */
552
 
 
553
 
/** Names for the float-Arrays
554
 
*/
555
 
static const char *const upd_float_a[] = {    /** */
556
 
#define FA_WXFER            0                 /** White-Transfer */
557
 
"upWhiteTransfer",                            /** White-Transfer */
558
 
#define FA_RXFER            1                 /** Red-Transfer */
559
 
"upRedTransfer",                              /** Red-Transfer */
560
 
#define FA_GXFER            2                 /** Green-Transfer */
561
 
"upGreenTransfer",                            /** Green-Transfer */
562
 
#define FA_BXFER            3                 /** Blue-Transfer */
563
 
"upBlueTransfer",                             /** Blue-Transfer */
564
 
#define FA_KXFER            4                 /** Black-Transfer */
565
 
"upBlackTransfer",                            /** Black-Transfer */
566
 
#define FA_CXFER            5                 /** Cyan-Transfer */
567
 
"upCyanTransfer",                             /** Cyan-Transfer */
568
 
#define FA_MXFER            6                 /** Magenta-Transfer */
569
 
"upMagentaTransfer",                          /** Magenta-Transfer */
570
 
#define FA_YXFER            7                 /** Yellow-Transfer */
571
 
"upYellowTransfer",                           /** Yellow-Transfer */
572
 
#define FA_MARGINS          8                 /** private Margins */
573
 
"upMargins",                                  /** private Margins */
574
 
#define FA_MAP              9                 /** Color-Map       */
575
 
"upColorMap"                                  /** Color-Map       */
576
 
};                                            /** */
577
 
 
578
 
/* ------------------------------------------------------------------- */
579
 
/* UPD-specific datatypes                                              */
580
 
/* ------------------------------------------------------------------- */
581
 
 
582
 
/**
583
 
int32_t and uint32_t are 32Bit-Integer-Types used in the
584
 
Floyd-Steinberg Algorithm and instead of gx_color_index. The
585
 
8-Byte long's on some 64Bit-Machines are apparently useless,
586
 
since gdevprn.c does (currently) support only 32-Bit Rasterdata.
587
 
*/
588
 
 
589
 
#undef INT32_MIN
590
 
#undef INT32_MAX
591
 
#undef UINT32_MAX
592
 
 
593
 
#if     arch_log2_sizeof_int < 2  /* int is too small */
594
 
#define                   INT32_MIN  LONG_MIN
595
 
#define                   INT32_MAX  LONG_MAX
596
 
#define                  UINT32_MAX ULONG_MAX
597
 
#else                             /* int is sufficient */
598
 
#define                   INT32_MIN   INT_MIN
599
 
#define                   INT32_MAX   INT_MAX
600
 
#define                  UINT32_MAX  UINT_MAX
601
 
#endif                            /* use int or long ? */
602
 
 
603
 
/**
604
 
"updcmap" is used by the color-mapping functions of the driver.
605
 
there are four cmaps in the "uniprint"-structure, one for each component.
606
 
To be exact, it's not "4" but rather "UPD_CMAP_MAX", which is a synonym.
607
 
*/
608
 
 
609
 
typedef struct updcmap_s { /** */
610
 
   gx_color_value      *code;      /** Values related to codes */
611
 
   uint32_t               bitmsk;    /** Mask, right justified */
612
 
   int                  bitshf;    /** Shift to right-justify */
613
 
   int                  xfer;      /** Index to the Xfer-Array */
614
 
   int                  bits;      /** # of Bits */
615
 
   int                  comp;      /** Output-Number */
616
 
   bool                 rise;      /* Rising/Falling Curve */
617
 
} updcmap_t, *updcmap_p;  /** */
618
 
typedef const updcmap_t *updcmap_pc;
619
 
 
620
 
/**
621
 
"updcomp" holds similar informations, but is used for the rendering
622
 
*/
623
 
 
624
 
typedef struct updcomp_s {  /* Parameters for Floyd-Steinberg */
625
 
   int32_t                offset;    /* Offset added to scaled values */
626
 
   int32_t                scale;     /* Scale for the raw values */
627
 
   int32_t                threshold; /* Val must be larger than this to fire */
628
 
   int32_t                spotsize;  /* subtracted from Val when fired */
629
 
   uint32_t               bitmsk;    /* Mask */
630
 
   int                  bitshf;    /* shift */
631
 
   int                  bits;      /* # of Bits */
632
 
   int                  cmap;      /* Index for the Parameter-name */
633
 
} updcomp_t, *updcomp_p;    /* Parameters for Floyd-Steinberg */
634
 
 
635
 
/** updscan is the Element of the scan-buffer. */
636
 
 
637
 
typedef struct updscan_s { /* Single Scanline (1 Bit/Pixel) */
638
 
   byte   *bytes;      /* Buffer used w. 32-Bit Words */
639
 
   int    *xbegin;     /* 1st  Pixel set (or nbytes<<3 if none) */
640
 
   int    *xend;       /* last Pixel set (or -1, if none) */
641
 
} updscan_t, *updscan_p;   /* Single Scanline (1 Bit/Pixel) */
642
 
 
643
 
/** Main upd-Structure ***/
644
 
 
645
 
#define UPD_CMAP_MAX     4 /** Number of Colormaps provided */
646
 
#define UPD_VALPTR_MAX  32 /** Number of valbuf-Pointers */
647
 
 
648
 
#define upd_proc_pxlget(name) uint32_t name(upd_p upd)
649
 
#define upd_proc_render(name) int name(upd_p upd)
650
 
#define upd_proc_writer(name) int name(upd_p upd,FILE *out)
651
 
 
652
 
struct upd_s { /* All upd-specific data */
653
 
 
654
 
   int                   *choice;     /** Named-Choices */
655
 
   int                   *ints;       /** Integers */
656
 
   gs_param_int_array    *int_a;      /** Integer-Arrays */
657
 
   gs_param_string       *strings;    /** Strings */
658
 
   gs_param_string_array *string_a;   /** String-Arrays */
659
 
   gs_param_float_array  *float_a;    /** Float-Arrays */
660
 
 
661
 
   updcmap_t              cmap[UPD_CMAP_MAX]; /** Mapping-Data */
662
 
 
663
 
   byte                  *gsbuf;      /* Storage for GS-Rasterdata */
664
 
   byte                  *gsscan;     /* Begin of GS-Rasterdata */
665
 
 
666
 
   byte                  *pxlptr;     /* Source for pxlget */
667
 
   upd_proc_pxlget(     (*pxlget));   /* The Pixel-Reader */
668
 
   upd_proc_render(     (*render));   /* Actual Rendering */
669
 
   upd_proc_writer(     (*writer));
670
 
 
671
 
   updscan_p             *scnbuf;     /* Output-Values */
672
 
   int32_t                 *valbuf;     /* Floyd-Steinberg-Buffer */
673
 
   void                  *valptr[UPD_VALPTR_MAX];
674
 
 
675
 
   byte                  *outbuf;     /* Output-Buffer */
676
 
   upd_proc_render(     (*start_render)); /* Setup for rendering */
677
 
   upd_proc_writer(     (*start_writer)); /* Setup for writilg */
678
 
 
679
 
   uint32_t                 flags;      /** Some flags */
680
 
   int                    pdwidth;    /** pdev-width upon open */
681
 
   int                    pdheight;   /** pdev-height upon open */
682
 
 
683
 
   uint                   ngsbuf;     /* Size of gsbuf */
684
 
   int                    gswidth;    /* Width in GS-Pixels */
685
 
   int                    gsheight;   /* Height in GS-Pixels */
686
 
 
687
 
   int                    rwidth;     /* Rendering-Width */
688
 
 
689
 
   int                    pwidth;     /* Printing-Width */
690
 
   int                    pheight;    /* # scanlines printed */
691
 
 
692
 
   int                    ncomp;      /* # Components in gsbuf */
693
 
   int                    nmap;       /* # Entries in color-map */
694
 
 
695
 
   uint                   nvalbuf;    /* Size of valbuf */
696
 
   int                    nscnbuf;    /* Number of entries in scnbuf. */
697
 
 
698
 
   int                    ocomp;      /* # Components written */
699
 
   int                    nbytes;     /* Size of scnbuf[][].words */
700
 
   int                    nlimits;    /* Size of scnbuf[][].xbegin/end */
701
 
   int                    scnmsk;     /* Size of scanbuf - 1 */
702
 
   uint                   noutbuf;    /* Size of the Output-Buffer */
703
 
 
704
 
   int                    ixpass;     /* Current X-pass (0 ... nxpass-1) */
705
 
   int                    ipass;      /* Current pass (0 ... npass-1) */
706
 
   int                    icomp;      /* Selected Component */
707
 
   int                    lf;         /* Selected Line-Space */
708
 
 
709
 
   int                    xprinter;   /* Actual X-Position */
710
 
 
711
 
   int                    yscan;      /* Top-Scan (page-vari) */
712
 
   int                    yprinter;   /* Actual Y-Position (page-vari) */
713
 
   int                    yscnbuf;    /* Y not yet buffered */
714
 
   const gs_memory_t     *memory;     /* Memory pointer - for errprintf */
715
 
};             /* All upd-specific data */
716
 
 
717
 
/* ------------------------------------------------------------------- */
718
 
/* Various Message-Levels                                              */
719
 
/* ------------------------------------------------------------------- */
720
 
 
721
 
/**
722
 
UPD_MESSAGES, Is collection of Bits, that controls Messages
723
 
*/
724
 
 
725
 
#define UPD_M_NONE      0x0000 /** No Messages at all */
726
 
#define UPD_M_ERROR     0x0001 /** Errors */
727
 
#define UPD_M_WARNING   0x0002 /** Warnings */
728
 
#define UPD_M_TOPCALLS  0x0004 /** Log Calls to main Functions */
729
 
#define UPD_M_MAPCALLS  0x0008 /** Log Color-Mapping-Calls */
730
 
#define UPD_M_SETUP     0x0010 /** Log Setup-Activity */
731
 
#define UPD_M_FSBUF     0x0020 /** Error-Summary for valbuf */
732
 
#define UPD_M_FMTVARS   0x0040 /** (GR) Formatting variables */
733
 
 
734
 
/* ------------------------------------------------------------------- */
735
 
/* The UPD-Routines                                                    */
736
 
/* ------------------------------------------------------------------- */
737
 
 
738
 
/**
739
 
Besides the main routines required for the color-mapping, that were
740
 
declared near the beginning, there are some auxillary functions.
741
 
Most prominent are "upd_open_map" and "upd_close_map", which
742
 
do the proper actions when opening and closing the device.
743
 
*/
744
 
 
745
 
static int             upd_open_map( upd_device *udev);
746
 
static int             upd_close_map(upd_device *udev);
747
 
 
748
 
/**
749
 
But "upd_truncate" and "upd_expand" are also mentionable. They are
750
 
the actual workhorses for the component-oriented mapping. When mapping
751
 
the 16Bit Component-Values to the indices, some truncation takes place
752
 
and this is what "upd_truncate" does, in the most general manner i can
753
 
think of and with O(log(n)) in time. "upd_expand" is required for the
754
 
reverse mapping-functions and is a constant-time `algorithm'.
755
 
*/
756
 
static inline uint32_t   upd_truncate(upd_pc,int,gx_color_value);
757
 
 
758
 
/* ------------------------------------------------------------------- */
759
 
/* Return the gx_color_value for a given component                     */
760
 
/* ------------------------------------------------------------------- */
761
 
static inline gx_color_value
762
 
upd_expand(upd_pc upd,int i,gx_color_index ci0)
763
 
{
764
 
   const updcmap_pc cmap = upd->cmap + i;    /* Writing-Shortcut */
765
 
   uint32_t ci = (uint32_t)((ci0 >> cmap->bitshf) & cmap->bitmsk); /* Extract the component */
766
 
 
767
 
   if(!cmap->rise) ci = cmap->bitmsk - ci;   /* Invert, if necessary */
768
 
/* no Truncation/Expansion on full range */
769
 
   if(gx_color_value_bits > cmap->bits) return cmap->code[ci];
770
 
   else                                 return (gx_color_value) ci;
771
 
}
772
 
/* That's simple, isn't it? */
773
 
 
774
 
/**
775
 
The next group of internal functions adresses the rendering. Besides
776
 
the main-functions "upd_open_render" and "upd_close_render", there
777
 
are groups of up to 3 Functions, for each algorithm available with
778
 
UPD. Two routines are invoked during open and close and the third
779
 
is called for each scanline. Actually a fourth function is provided,
780
 
that is invoked at the beginning of each page to be printed, but the
781
 
current algorithms do not need it.
782
 
*/
783
 
static void            upd_open_render(   upd_device *udev);
784
 
static void            upd_close_render(  upd_device *udev);
785
 
 
786
 
static void            upd_open_fscomp(   upd_device *udev);
787
 
static int             upd_fscomp(        upd_p upd);
788
 
static void            upd_close_fscomp(  upd_device *udev);
789
 
 
790
 
static void            upd_open_fscmyk(   upd_device *udev);
791
 
static int             upd_fscmyk(        upd_p upd);
792
 
 
793
 
static void            upd_open_fscmy_k(  upd_device *udev);
794
 
static int             upd_fscmy_k(       upd_p upd);
795
 
 
796
 
/**
797
 
I hope that the formatting stuff can be kept simple and thus most
798
 
of the work is done inside the general open and close-functions.
799
 
During open, there is a call to a format-specific open-function, but
800
 
this is only for checking and determining the amount of of bytes required
801
 
for the output-buffer (and limit-values in the scan-buffer).
802
 
*/
803
 
static int             upd_open_writer(   upd_device *udev);
804
 
static void            upd_close_writer(  upd_device *udev);
805
 
#if UPD_SIGNAL
806
 
static void            upd_signal_handler(int sig);
807
 
#endif
808
 
 
809
 
/**
810
 
The first format are the uncompressed! SUN-Rasterfiles. The primary intention
811
 
of this format is testing, but it might turn out to be useful for other
812
 
purposes, even if the amount of generated data is huge. On the other hand
813
 
it is a violation of UPD's rules: the start-routine computes the Begin-Page
814
 
sequence (the Rasterfile header) since it would be a nuisance to provide
815
 
this code within each (test-)personalization in PostScript.
816
 
*/
817
 
static int             upd_open_rascomp(   upd_device *udev);
818
 
static int             upd_start_rascomp(  upd_p upd, FILE *out);
819
 
static int             upd_rascomp(        upd_p upd, FILE *out);
820
 
 
821
 
/**
822
 
The second format is ESC/P, the format introduced with the first Epson
823
 
impact printers. This format is used by a lot of other printers too.
824
 
It is also uncompressed. This formatter supports X- and Y-Weaving,
825
 
which makes it the most sophisticated one inside this driver.
826
 
*/
827
 
 
828
 
static void            upd_limits(        upd_p upd, bool check);
829
 
static int             upd_open_wrtescp(  upd_device *udev);
830
 
static int             upd_wrtescp(       upd_p upd, FILE *out);
831
 
 
832
 
/**
833
 
The third format is ESC/P2, the format use by the newer Epson-Printers.
834
 
It allows runlength-Compression similar to the RTL/PCL-Family of Printers.
835
 
This formatter does not allow for X-Weaving.
836
 
 
837
 
The fourth writer is a ESC/P2-Writer, that supports X-Weaving
838
 
*/
839
 
static int             upd_rle(byte *out,const byte *in,int nbytes);
840
 
static int             upd_open_wrtescp2( upd_device *udev);
841
 
static int             upd_wrtescp2(      upd_p upd, FILE *out);
842
 
static int             upd_wrtescp2x(     upd_p upd, FILE *out);
843
 
 
844
 
/**
845
 
The fifth writer is a HP-RTL/PCL-Writer
846
 
*/
847
 
 
848
 
static int             upd_open_wrtrtl(   upd_device *udev);
849
 
static int             upd_wrtrtl(        upd_p upd, FILE *out);
850
 
 
851
 
/**
852
 
The sixth writer is for Canon Extended Mode (currently BJC610) (hr)
853
 
*/
854
 
 
855
 
static int             upd_open_wrtcanon( upd_device *udev);
856
 
static int             upd_wrtcanon(      upd_p upd, FILE *out);
857
 
 
858
 
/**
859
 
The seventh writer is for ESC P/2 Nozzle Map Mode (currently Stylus Color 300) (GR)
860
 
*/
861
 
 
862
 
static int             upd_wrtescnm(      upd_p upd, FILE *out);
863
 
 
864
 
/**
865
 
Generalized Pixel Get & Read
866
 
*/
867
 
static uint32_t upd_pxlfwd(upd_p upd);
868
 
static uint32_t upd_pxlrev(upd_p upd);
869
 
#define upd_pxlget(UPD) (*UPD->pxlget)(UPD)
870
 
 
871
 
static void *upd_cast(const void *);
872
 
 
873
 
/* ------------------------------------------------------------------- */
874
 
/* Macros to deal with the Parameter-Memory                            */
875
 
/* ------------------------------------------------------------------- */
876
 
 
877
 
/**
878
 
Usually the creation of copies of external parameters is not necessary,
879
 
at least with gs-versions > 4.03. But uniprint writes to the parameters
880
 
in some cases or creates some by itself, thus to get a unified interface
881
 
all parameter-data are copied and thus it is legal to manipulate them.
882
 
 
883
 
Here are several Macros, named "UPD_MM_*" to deal with that.
884
 
*/
885
 
 
886
 
/** UPD_MM_GET_ARRAY allocates & initializes an array of values */
887
 
#define UPD_MM_GET_ARRAY(mem, Which,Nelts)                                 \
888
 
   Which = NULL;                                                      \
889
 
   if(0 < (Nelts)) {                                                  \
890
 
      byte *tmp = gs_malloc(mem, Nelts,sizeof(Which[0]),"uniprint/params");\
891
 
      if(tmp) {                                                       \
892
 
         memset(tmp,0,(Nelts)*sizeof(Which[0]));                      \
893
 
         Which = (void *) tmp;                                        \
894
 
      } else {                                                        \
895
 
          return_error(gs_error_VMerror);                             \
896
 
      }                                                               \
897
 
   }
898
 
 
899
 
/** UPD_MM_DEL_ARRAY frees an array of values */
900
 
#define UPD_MM_DEL_ARRAY(mem, Which,Nelts,Delete)                            \
901
 
   if(Which && 0 < (Nelts)) {                                           \
902
 
      uint ii;                                                          \
903
 
      for(ii = 0; (Nelts) > ii; ++ii) Delete(mem, Which[ii]);                \
904
 
      gs_free(mem, upd_cast(Which),Nelts,sizeof(Which[0]),"uniprint/params");\
905
 
   }                                                                    \
906
 
   Which = 0
907
 
 
908
 
/** UPD_MM_DEL_VALUE deletes a value, does nothing */
909
 
#define UPD_MM_DEL_VALUE(mem, Which) /* */
910
 
 
911
 
/** UPD_MM_DEL_PARAM deletes a single gs-array-parameter */
912
 
#define UPD_MM_DEL_PARAM(mem, Which)  {                                  \
913
 
   if(Which.data && Which.size)                                     \
914
 
      gs_free(mem, upd_cast(Which.data),Which.size,sizeof(Which.data[0]),\
915
 
         "uniprint/params");                                        \
916
 
}
917
 
 
918
 
/** UPD_MM_DEL_APARAM deletes a nested gs-array-parameter */
919
 
#define UPD_MM_DEL_APARAM(mem, Which) {                                  \
920
 
   if(Which.data && Which.size) {                                   \
921
 
      uint iii;                                                     \
922
 
      for(iii = 0; iii < Which.size; ++iii)                         \
923
 
         UPD_MM_DEL_PARAM(mem, Which.data[iii]);                         \
924
 
      gs_free(mem, upd_cast(Which.data),Which.size,sizeof(Which.data[0]),\
925
 
         "uniprint/params");                                        \
926
 
   }                                                                \
927
 
}
928
 
 
929
 
/** UPD_MM_CPY_ARRAY creates a new copy of an array of values */
930
 
#define UPD_MM_CPY_ARRAY(mem, To,From,Nelts,Copy)                \
931
 
   UPD_MM_GET_ARRAY(mem, To,Nelts);                              \
932
 
   if(To && From) {                                         \
933
 
      uint ii;                                              \
934
 
      for(ii = 0; (Nelts) > ii; ++ii) Copy(mem, To[ii],From[ii]);\
935
 
   }
936
 
 
937
 
/** UPD_MM_CPY_VALUE Copies a simple Value */
938
 
#define UPD_MM_CPY_VALUE(mem,To,From)  To = From
939
 
 
940
 
#define UPD_MM_CPY_VALUE_3(mem,To,From)  To = From
941
 
 
942
 
/** UPD_MM_CPY_PARAM Creates a copy of a gs-parameter */
943
 
#define UPD_MM_CPY_PARAM(mem, To, From)                                       \
944
 
   if(From.data && From.size) {                                         \
945
 
      UPD_MM_GET_ARRAY(mem, To.data,From.size);                              \
946
 
      if(To.data) {                                                     \
947
 
         To.size = From.size;                                           \
948
 
         memcpy(upd_cast(To.data),From.data,To.size*sizeof(To.data[0]));\
949
 
      }                                                                 \
950
 
   }
951
 
 
952
 
/** UPD_MM_CPY_APARAM Creates a copy of a nested gs-parameter */
953
 
#define UPD_MM_CPY_APARAM(mem, To,From)                                     \
954
 
   if(From.data && From.size) {                                        \
955
 
       UPD_MM_GET_ARRAY(mem, To.data,From.size);                               \
956
 
      if(To.data) {                                                    \
957
 
         gs_param_string *tmp2 = (gs_param_string *) upd_cast(To.data);\
958
 
         uint iii;                                                     \
959
 
         To.size = From.size;                                          \
960
 
         for(iii = 0; To.size > iii; ++iii)                            \
961
 
             UPD_MM_CPY_PARAM(mem, tmp2[iii],From.data[iii]);          \
962
 
      }                                                                \
963
 
   }
964
 
 
965
 
/* ------------------------------------------------------------------- */
966
 
/* UPD-Initialized-Data                                                */
967
 
/* ------------------------------------------------------------------- */
968
 
 
969
 
/** Version-String */
970
 
 
971
 
static const char rcsid[] = "$Revision: 5215 $";
972
 
 
973
 
/** Default-Transfer-curve */
974
 
 
975
 
static const float upd_data_xfer[2] = { 0.0, 1.0 };
976
 
 
977
 
/*@ > */
978
 
 
979
 
/* ------------------------------------------------------------------- */
980
 
/* upd_cast: keeps some compilers more happy [dangerous]               */
981
 
/* ------------------------------------------------------------------- */
982
 
 
983
 
static void *
984
 
upd_cast(const void *data)
985
 
{
986
 
  return (void *) data;
987
 
}
988
 
 
989
 
/* ------------------------------------------------------------------- */
990
 
/* upd_signal_handler: Catch interrupts                                */
991
 
/* ------------------------------------------------------------------- */
992
 
 
993
 
#if UPD_SIGNAL
994
 
static upd_p sigupd = NULL;
995
 
static void
996
 
upd_signal_handler(int sig)
997
 
{
998
 
  if(sigupd) sigupd->flags |= B_ABORT;
999
 
}
1000
 
#endif
1001
 
 
1002
 
/* ------------------------------------------------------------------- */
1003
 
/* upd_print_page: The main workhorse                                  */
1004
 
/* ------------------------------------------------------------------- */
1005
 
 
1006
 
/**
1007
 
Function: upd_print_page
1008
 
 
1009
 
This is the top-level printing routine. It works through this
1010
 
steps:
1011
 
 
1012
 
 1. Once for each generated file, the "device-open-sequence" is written.
1013
 
 2. The "page-begin-sequence" is written.
1014
 
 
1015
 
 3. The data are generated and written:
1016
 
    3.1: Data are converted into a "printer-family"-specific format.
1017
 
         This step includes the halftoning, if selected.
1018
 
    3.2: Data are written with a printer-specific function.
1019
 
         There is not much code-compression inside theese functions,
1020
 
         since i observed to improvments in print-speed. Other
1021
 
         drivers do a better job in this.
1022
 
 
1023
 
 4. The "page-end-sequence" is written.
1024
 
 5. If a one-page-per-file mode is selected, the "device-close-sequence"
1025
 
    is added to the output. For multi-page files, this writing is
1026
 
    performed in "upd_close", the drivers close-function.
1027
 
 
1028
 
The routine is quite short, since all the allocation and checking
1029
 
occur in upd_open and upd_putparams. The only test, that upd_print_page
1030
 
does, is the verification wether the device is in a sane state. This
1031
 
must be done here, since during the initialisation, the device is
1032
 
usually opened several times, before obtaining a valid state.
1033
 
*/
1034
 
 
1035
 
static int
1036
 
upd_print_page(gx_device_printer *pdev, FILE *out)
1037
 
{
1038
 
   upd_device *const udev  = (upd_device *) pdev;
1039
 
   const upd_p       upd   = udev->upd;
1040
 
   const int *const  ints  = upd ? upd->ints : NULL;
1041
 
   int error,need,yfill;
1042
 
 
1043
 
#if UPD_SIGNAL /* variables required for signal-handling only */
1044
 
   void (*oldint )(int) = NULL;
1045
 
   void (*oldterm)(int) = NULL;
1046
 
   upd_p  oldupd            = sigupd;
1047
 
#endif         /* variables required for signal-handling only */
1048
 
 
1049
 
/*
1050
 
 * Refuse to work, if not explicitly enabled during open
1051
 
 * (some/lot of allocated memory is required)
1052
 
 */
1053
 
   if(!upd || B_OK4GO != (upd->flags & (B_OK4GO | B_ERROR))) {
1054
 
#if UPD_MESSAGES & (UPD_M_ERROR | UPD_M_TOPCALLS)
1055
 
         errprintf(pdev->memory, "CALL-REJECTED upd_print_page(0x%05lx,0x%05lx)\n",
1056
 
             (long) udev,(long) out);
1057
 
#endif
1058
 
      return gs_error_undefined;
1059
 
   }
1060
 
 
1061
 
#if UPD_MESSAGES & UPD_M_TOPCALLS
1062
 
   errprintf(pdev->memory, "CALL: upd_print_page(0x%05lx,0x%05lx)\n",
1063
 
      (long) udev,(long) out);
1064
 
#endif
1065
 
 
1066
 
#if UPD_SIGNAL /* Setup of signal-handling */
1067
 
   sigupd  = upd;
1068
 
   oldint  = signal(SIGINT, upd_signal_handler);
1069
 
   oldterm = signal(SIGTERM,upd_signal_handler);
1070
 
#endif         /* Setup of signal-handling */
1071
 
 
1072
 
/*
1073
 
 * If the OutputFile was just opened, transfer the Open-Sequence to it.
1074
 
 */
1075
 
   if(!(upd->flags & B_OPEN)) {
1076
 
 
1077
 
      if(0   <  upd->strings[S_OPEN].size)
1078
 
         fwrite(upd->strings[S_OPEN].data,1,upd->strings[S_OPEN].size,out);
1079
 
      upd->flags |= B_OPEN;
1080
 
   }
1081
 
/*
1082
 
 * Always write the the Page-begin-sequence
1083
 
 */
1084
 
   if(0  <   upd->strings[S_BEGIN].size)
1085
 
      fwrite(upd->strings[S_BEGIN].data,1,upd->strings[S_BEGIN].size,out);
1086
 
/*
1087
 
 * Establish page-variables
1088
 
 */
1089
 
 
1090
 
/* Positions */
1091
 
   upd->xprinter  = 0;
1092
 
   upd->yscan     = 0; /* Position we are processing */
1093
 
   upd->yprinter  = 0; /* Actual Printer-Positions */
1094
 
   upd->yscnbuf   = 0; /* Next free scnbuf-Line */
1095
 
 
1096
 
/* Rendering & Writing Setup, if available */
1097
 
   if(upd->start_render) (*upd->start_render)(upd);
1098
 
   if(upd->start_writer) (*upd->start_writer)(upd,out);
1099
 
 
1100
 
/* How many scanlines do we need ? */
1101
 
   need = ints[I_NYPASS] * ints[I_PINS2WRITE];
1102
 
   if(0 >= need) need = 1;
1103
 
 
1104
 
/* The Weave-counters */
1105
 
   upd->ipass  =  0;
1106
 
   upd->ixpass =  0;
1107
 
   upd->icomp  = -1; /* Enforces initial selection */
1108
 
   upd->lf     = -1; /* Enforces initial selection */
1109
 
/*
1110
 
 * Main Loop
1111
 
 */
1112
 
   while(upd->pheight > upd->yscan) { /* Main-Loop */
1113
 
 
1114
 
/*
1115
 
 *    Load as much data into the scan-buffer as possible
1116
 
 *    (this is done in scan-sequence, the printing not necessarily.)
1117
 
 */
1118
 
      if(ints[I_BEGSKIP] > upd->yscan) yfill = 0;
1119
 
      else                             yfill = upd->yscan - ints[I_BEGSKIP];
1120
 
 
1121
 
      for(yfill += upd->nscnbuf; upd->yscnbuf < yfill; upd->yscnbuf++) {
1122
 
 
1123
 
         if(upd->gsheight > upd->yscnbuf)  {
1124
 
 
1125
 
            if(0 > (*dev_proc(udev,get_bits))((gx_device *) udev,
1126
 
                                   upd->yscnbuf,upd->gsbuf,&upd->gsscan)) {
1127
 
#if UPD_MESSAGES & UPD_M_WARNING
1128
 
               errprintf(udev->memory, "get_bits aborted with error, yscnbuf = %4d\n",
1129
 
                         upd->yscnbuf);
1130
 
#endif
1131
 
               break;
1132
 
            }
1133
 
         } else {
1134
 
 
1135
 
            memset(upd->gsscan = upd->gsbuf,0,upd->ngsbuf);
1136
 
 
1137
 
         }
1138
 
 
1139
 
         if(0 > (*upd->render)(upd)) {
1140
 
#if UPD_MESSAGES & UPD_M_WARNING
1141
 
            errprintf(udev->memory, "Rendering aborted with error, yscnbuf = %4d\n",
1142
 
               upd->yscnbuf);
1143
 
#endif
1144
 
            break;
1145
 
         }
1146
 
 
1147
 
      }
1148
 
/*
1149
 
 *    Did the buffering loop take an error exit ?
1150
 
 */
1151
 
      if((upd->yscnbuf ^ yfill) & upd->scnmsk) break;
1152
 
/*
1153
 
 *    Print as much as possible
1154
 
 */
1155
 
      while((upd->yscan - ints[I_BEGSKIP] + need) < upd->yscnbuf) {
1156
 
 
1157
 
/*        first write the scan(s) */
1158
 
          (*upd->writer)(upd,out);
1159
 
 
1160
 
/*        Check for termination */
1161
 
          if(upd->yscan >= upd->pheight) break;
1162
 
          if(upd->flags  & B_ABORT ) {
1163
 
#if UPD_MESSAGES & UPD_M_WARNING
1164
 
             errprintf(udev->memory, "Printing aborted upon interrupt, yscan = %4d\n",
1165
 
                upd->yscan);
1166
 
#endif
1167
 
             break;
1168
 
          }
1169
 
      }
1170
 
/*
1171
 
 *    Did the print-Loop take an error exit ?
1172
 
 */
1173
 
      if((upd->yscan - ints[I_BEGSKIP] + need) < upd->yscnbuf) break;
1174
 
   }                                  /* Main-Loop */
1175
 
 
1176
 
/*
1177
 
 * If we aborted for some reason, use the dedicated sequence
1178
 
 */
1179
 
 
1180
 
   if((upd->pheight > upd->yscan) &&
1181
 
      (0  <  upd->strings[S_ABORT].size)) { /* Only This! */
1182
 
      fwrite(upd->strings[S_ABORT].data,1,upd->strings[S_ABORT].size,out);
1183
 
 
1184
 
      upd->flags &= ~B_OPEN; /* Inhibit Close-Sequence ! */
1185
 
/*
1186
 
 * If there is no special sequence, or we came to normal end,
1187
 
 * write the normal sequence, if any
1188
 
 */
1189
 
 
1190
 
   } else if(0  <   upd->strings[S_END].size) {
1191
 
      fwrite(upd->strings[S_END].data,1,upd->strings[S_END].size,out);
1192
 
   }
1193
 
/*
1194
 
 * If necessary, write the close-sequence
1195
 
 */
1196
 
    {
1197
 
        gs_parsed_file_name_t parsed;
1198
 
        const char *fmt;
1199
 
 
1200
 
        if (NULL != udev->fname &&
1201
 
            0 <= gx_parse_output_file_name(&parsed, &fmt, udev->fname,
1202
 
                                           strlen(udev->fname), udev->memory) &&
1203
 
            fmt
1204
 
            ) {
1205
 
            if (0 < upd->strings[S_CLOSE].size)
1206
 
                fwrite(upd->strings[S_CLOSE].data,1,upd->strings[S_CLOSE].size,out);
1207
 
            upd->flags &= ~B_OPEN;
1208
 
        }
1209
 
    }
1210
 
 
1211
 
/*
1212
 
 * clean up, and return status
1213
 
 */
1214
 
 
1215
 
   fflush(out); /* just to prepare for ferror */
1216
 
 
1217
 
   if(upd->pheight > upd->yscan) error = gs_error_interrupt;
1218
 
   else if(ferror(out))          error = gs_error_ioerror;
1219
 
   else                          error = 0;
1220
 
 
1221
 
#if UPD_MESSAGES & UPD_M_TOPCALLS
1222
 
   errprintf(udev->memory, "RETURN: %d = upd_print_page(0x%05lx,0x%05lx)\n",
1223
 
      error,(long) udev,(long)out);
1224
 
#endif
1225
 
 
1226
 
#if UPD_SIGNAL /* Restore Interrupt-state */
1227
 
      sigupd = oldupd;
1228
 
      (void) signal(SIGINT ,oldint);
1229
 
      (void) signal(SIGTERM,oldterm);
1230
 
#endif         /* Restore Interrupt-state */
1231
 
 
1232
 
   return error;
1233
 
}
1234
 
 
1235
 
/* ------------------------------------------------------------------- */
1236
 
/* upd_open: Initialize everything for printing                        */
1237
 
/* ------------------------------------------------------------------- */
1238
 
/**
1239
 
"upd_open" is -through the specified table of procedures- called instead
1240
 
of the normal open-procedures for printer-devices, that performs quite
1241
 
a complex job. Thus it is necessary to call this  `superclass-open�
1242
 
here.
1243
 
 
1244
 
Besides that, this routine does quite a complex job too, in initializes
1245
 
everything required to print a page. This might be time-consuming, the
1246
 
alternative would be "upd_print_page", but i often print 100 pages or
1247
 
more, but i never experienced more than 5-6 open-calls.
1248
 
*/
1249
 
 
1250
 
static int
1251
 
upd_open(gx_device *pdev)
1252
 
{
1253
 
   upd_device *const udev    =  (upd_device *) pdev;
1254
 
   const upd_p       upd     =  udev->upd;
1255
 
   int              error;
1256
 
 
1257
 
#if UPD_MESSAGES & UPD_M_TOPCALLS
1258
 
      errprintf(udev->memory, "CALL: upd_open(0x%05lx)\n",(long) pdev);
1259
 
#endif
1260
 
 
1261
 
/** enforce the UPD-Margins */
1262
 
 
1263
 
   if((NULL != upd) &&
1264
 
      (NULL != upd->float_a[FA_MARGINS].data) &&
1265
 
      (4    == upd->float_a[FA_MARGINS].size)    ) {
1266
 
      float m[4];
1267
 
      m[1] = upd->float_a[FA_MARGINS].data[1] / 72.0;
1268
 
      m[3] = upd->float_a[FA_MARGINS].data[3] / 72.0;
1269
 
      if(B_YFLIP & upd->flags) {
1270
 
         m[0] = upd->float_a[FA_MARGINS].data[2] / 72.0;
1271
 
         m[2] = upd->float_a[FA_MARGINS].data[0] / 72.0;
1272
 
      } else {
1273
 
         m[0] = upd->float_a[FA_MARGINS].data[0] / 72.0;
1274
 
         m[2] = upd->float_a[FA_MARGINS].data[2] / 72.0;
1275
 
      }
1276
 
      gx_device_set_margins((gx_device *) udev, m, true);
1277
 
   }
1278
 
 
1279
 
/** call the super-class open **/
1280
 
   error = gdev_prn_open(pdev);
1281
 
 
1282
 
/** invoke the subroutines, if an upd is present. */
1283
 
 
1284
 
   if(upd) {
1285
 
 
1286
 
      upd->flags &= ~B_OK4GO;
1287
 
 
1288
 
/**
1289
 
The following initializations are run, even in case of an error in
1290
 
the super-class open, just to bring our upd into a sane state.
1291
 
*/
1292
 
      if(0 > error) upd->flags |= B_ERROR;
1293
 
 
1294
 
      if(gs_error_VMerror == upd_open_map(udev)) error = gs_error_VMerror;
1295
 
 
1296
 
/**
1297
 
The following piece of code is here for demonstration-purposes:
1298
 
It determines the size of the printed image and allocates the
1299
 
buffer for the raw raster-data
1300
 
*/
1301
 
      upd->gswidth  = udev->width -
1302
 
         (int)((dev_l_margin(udev)+dev_r_margin(udev))*udev->x_pixels_per_inch);
1303
 
 
1304
 
      upd->gsheight = udev->height -
1305
 
         (int)((dev_t_margin(udev)+dev_b_margin(udev))*udev->y_pixels_per_inch);
1306
 
 
1307
 
      upd->ngsbuf = 0;    /* Ensure sane values */
1308
 
      upd->gsbuf  = NULL; /* Ensure sane values */
1309
 
 
1310
 
      if(B_MAP & upd->flags) { /* Only if prerequisites were met */
1311
 
         uint want  = gx_device_raster(pdev,true);
1312
 
         upd->gsbuf = gs_malloc(pdev->memory, want,1,"upd/gsbuf");
1313
 
 
1314
 
         if(upd->gsbuf) {
1315
 
            upd->ngsbuf = want;
1316
 
            upd->flags |= B_BUF;  /* Signal Success */
1317
 
         } else {
1318
 
            error = gs_error_VMerror; /* Signal Error */
1319
 
            upd->flags |= B_ERROR;
1320
 
         }
1321
 
 
1322
 
      }                            /* Only if prerequisites were met */
1323
 
 
1324
 
      upd_open_render(udev);  /* First subloop in printing */
1325
 
 
1326
 
      if(gs_error_VMerror == upd_open_writer(udev)) error = gs_error_VMerror;
1327
 
 
1328
 
      udev->upd->pdwidth  = udev->width;
1329
 
      udev->upd->pdheight = udev->height;
1330
 
 
1331
 
#if UPD_MESSAGES & UPD_M_SETUP
1332
 
      if((upd->flags & (B_OK4GO | B_ERROR)) == B_OK4GO) {
1333
 
        int i,j,l,ln,lv;
1334
 
        errprintf(udev->memory,"\nupd->flags    = 0x%05lx\n",(unsigned long)upd->flags);
1335
 
        errprintf(udev->memory,  "upd->pdwidth  = %5d\n",upd->pdwidth);
1336
 
        errprintf(udev->memory,  "upd->pdheight = %5d\n",upd->pdheight);
1337
 
        errprintf(udev->memory,  "upd->ngsbuf   = %5u\n",upd->ngsbuf);
1338
 
        errprintf(udev->memory,  "upd->gswidth  = %5d\n",upd->gswidth);
1339
 
        errprintf(udev->memory,  "upd->gsheight = %5d\n",upd->gsheight);
1340
 
        errprintf(udev->memory,  "upd->rwidth   = %5d\n",upd->rwidth);
1341
 
        errprintf(udev->memory,  "upd->pwidth   = %5d\n",upd->pwidth);
1342
 
        errprintf(udev->memory,  "upd->pheight  = %5d\n",upd->pheight);
1343
 
        errprintf(udev->memory,  "upd->nvalbuf  = %5u\n",upd->nvalbuf);
1344
 
        errprintf(udev->memory,  "upd->nscnbuf  = %5d\n",upd->nscnbuf);
1345
 
        errprintf(udev->memory,  "upd->ncomp    = %5d\n",upd->ncomp);
1346
 
        errprintf(udev->memory,  "upd->ocomp    = %5d\n",upd->ocomp);
1347
 
        errprintf(udev->memory,  "upd->nbytes   = %5d\n",upd->nbytes);
1348
 
        errprintf(udev->memory,  "upd->nlimits  = %5d\n",upd->nlimits);
1349
 
        errprintf(udev->memory,  "upd->scnmsk   = %5d\n",upd->scnmsk);
1350
 
        errprintf(udev->memory,  "upd->noutbuf  = %5u\n",upd->noutbuf);
1351
 
        errprintf(udev->memory,  "upd->ixpass   = %5d\n",upd->ixpass);
1352
 
        errprintf(udev->memory,  "upd->ipass    = %5d\n",upd->ipass);
1353
 
        errprintf(udev->memory,  "upd->icomp    = %5d\n",upd->icomp);
1354
 
        errprintf(udev->memory,  "upd->lf       = %5d\n",upd->lf);
1355
 
        errprintf(udev->memory,  "upd->xprinter = %5d\n",upd->xprinter);
1356
 
        errprintf(udev->memory,  "upd->yscan    = %5d\n",upd->yscan);
1357
 
        errprintf(udev->memory,  "upd->yprinter = %5d\n",upd->yprinter);
1358
 
        errprintf(udev->memory,  "upd->yscnbuf  = %5d\n",upd->yscnbuf);
1359
 
 
1360
 
        ln = 13;
1361
 
        lv = 5;
1362
 
        for(i = 0; countof(upd_choice) > i; ++i) {
1363
 
          if(!upd_choice[i]) continue;
1364
 
          l = strlen(upd_choice[i][0]);
1365
 
          if(ln < l) ln = l;
1366
 
          for(j = 1; upd_choice[i][j]; ++j) {
1367
 
            l = strlen(upd_choice[i][j]);
1368
 
            if(lv < l) lv = l;
1369
 
          }
1370
 
        }
1371
 
 
1372
 
        for(i = 0; countof(upd_flags) > i; ++i) {
1373
 
          if(upd_flags[i]) {
1374
 
            l = strlen(upd_flags[i]);
1375
 
            if(ln < l) ln = l;
1376
 
          }
1377
 
        }
1378
 
 
1379
 
        for(i = 0; countof(upd_ints) > i; ++i) {
1380
 
          if(upd_ints[i]) {
1381
 
            l = strlen(upd_ints[i]);
1382
 
            if(ln < l) ln = l;
1383
 
          }
1384
 
        }
1385
 
 
1386
 
        for(i = 0; countof(upd_int_a) > i; ++i) {
1387
 
          if(upd_int_a[i]) {
1388
 
            l = strlen(upd_int_a[i]);
1389
 
            if(ln < l) ln = l;
1390
 
          }
1391
 
        }
1392
 
 
1393
 
        for(i = 0; countof(upd_strings) > i; ++i) {
1394
 
          if(upd_strings[i]) {
1395
 
            l = strlen(upd_strings[i]);
1396
 
            if(ln < l) ln = l;
1397
 
          }
1398
 
        }
1399
 
 
1400
 
        for(i = 0; countof(upd_string_a) > i; ++i) {
1401
 
          if(upd_string_a[i]) {
1402
 
            l = strlen(upd_string_a[i]);
1403
 
            if(ln < l) ln = l;
1404
 
          }
1405
 
        }
1406
 
 
1407
 
        for(i = 0; countof(upd_float_a) > i; ++i) {
1408
 
          if(upd_float_a[i]) {
1409
 
            l = strlen(upd_float_a[i]);
1410
 
            if(ln < l) ln = l;
1411
 
          }
1412
 
        }
1413
 
 
1414
 
        for(i = 0; countof(upd_choice) > i; ++i) {
1415
 
          if(upd_choice[i]) {
1416
 
            errprintf(udev->memory,"%*s = %-*s (%2d)\n",ln,upd_choice[i][0],
1417
 
               lv,upd_choice[i][upd->choice[i]],upd->choice[i]);
1418
 
          } else {
1419
 
            errprintf(udev->memory,"%*s[%2d] = %2d\n",ln-4,"upd_choice",i,
1420
 
               upd->choice[i]);
1421
 
          }
1422
 
        }
1423
 
 
1424
 
        for(i = 0; countof(upd_flags) > i; ++i) {
1425
 
          if(upd_flags[i]) {
1426
 
            errprintf(udev->memory,"%*s = %s\n",ln,upd_flags[i],
1427
 
               ((uint32_t) 1 << i) & upd->flags ? "true" : "false");
1428
 
          } else {
1429
 
            errprintf(udev->memory,"%*s[%2d] = %s\n",ln-4,"upd_flags",i,
1430
 
               ((uint32_t) 1 << i) & upd->flags ? "true" : "false");
1431
 
 
1432
 
          }
1433
 
        }
1434
 
 
1435
 
        for(i = 0; countof(upd_ints) > i; ++i) {
1436
 
          if(upd_ints[i]) {
1437
 
            errprintf(udev->memory,"%*s = %5d\n",ln,upd_ints[i],upd->ints[i]);
1438
 
          } else {
1439
 
            errprintf(udev->memory,"%*s[%2d] = %5d\n",ln-4,"upd_ints",i,upd->ints[i]);
1440
 
          }
1441
 
        }
1442
 
 
1443
 
      }
1444
 
 
1445
 
      errprintf(udev->memory,"\n%sready to print\n\n",
1446
 
         B_OK4GO != (upd->flags & (B_OK4GO | B_ERROR)) ?
1447
 
         "NOT " : "");
1448
 
#endif
1449
 
 
1450
 
   }
1451
 
 
1452
 
#if UPD_MESSAGES & UPD_M_TOPCALLS
1453
 
      errprintf(udev->memory,"RETURN: %d = upd_open(0x%05lx)\n",
1454
 
         error,(long) pdev);
1455
 
#endif
1456
 
 
1457
 
   return error;
1458
 
}
1459
 
 
1460
 
/* ------------------------------------------------------------------- */
1461
 
/* upd_close: Release everything allocated in upd_open                 */
1462
 
/* ------------------------------------------------------------------- */
1463
 
 
1464
 
static int
1465
 
upd_close(gx_device *pdev)
1466
 
{
1467
 
   upd_device *const udev    =  (upd_device *) pdev;
1468
 
   const upd_p       upd     =  udev->upd;
1469
 
   int         error = 0;
1470
 
   int         code;
1471
 
 
1472
 
#if UPD_MESSAGES & UPD_M_TOPCALLS
1473
 
   errprintf(udev->memory,"CALL: upd_close(0x%05lx)\n",(long)pdev);
1474
 
#endif
1475
 
 
1476
 
/** If necessary, write the close-sequence **/
1477
 
 
1478
 
   if( upd && (( B_OPEN | B_OK4GO) ==
1479
 
               ((B_OPEN | B_OK4GO | B_ERROR) & upd->flags))) {
1480
 
 
1481
 
      if(udev->file && upd->strings && 0 < upd->strings[S_CLOSE].size)
1482
 
         fwrite(upd->strings[S_CLOSE].data,1,
1483
 
                upd->strings[S_CLOSE].size,udev->file);
1484
 
 
1485
 
      upd->flags &= ~B_OPEN;
1486
 
   }
1487
 
 
1488
 
/** Then release the open-allocated memory */
1489
 
   if(upd) {
1490
 
 
1491
 
      upd_close_writer(udev);
1492
 
 
1493
 
      if(upd->gsbuf)
1494
 
         gs_free(pdev->memory, upd->gsbuf,upd->ngsbuf,1,"uniprint/gsbuf");
1495
 
      upd->gsbuf  = NULL;
1496
 
      upd->ngsbuf = 0;
1497
 
      upd->flags &= ~B_BUF;
1498
 
 
1499
 
      upd_close_render(udev);
1500
 
      upd_close_map(udev);
1501
 
 
1502
 
      UPD_MM_DEL_ARRAY(pdev->memory, upd->choice,  countof(upd_choice),  UPD_MM_DEL_VALUE);
1503
 
      UPD_MM_DEL_ARRAY(pdev->memory, upd->ints,    countof(upd_ints),    UPD_MM_DEL_VALUE);
1504
 
      UPD_MM_DEL_ARRAY(pdev->memory, upd->int_a,   countof(upd_int_a),   UPD_MM_DEL_PARAM);
1505
 
      UPD_MM_DEL_ARRAY(pdev->memory, upd->strings, countof(upd_strings), UPD_MM_DEL_PARAM);
1506
 
      UPD_MM_DEL_ARRAY(pdev->memory, upd->string_a,countof(upd_string_a),UPD_MM_DEL_APARAM);
1507
 
      UPD_MM_DEL_ARRAY(pdev->memory, upd->float_a, countof(upd_float_a), UPD_MM_DEL_PARAM);
1508
 
 
1509
 
      gs_free(pdev->memory, upd,sizeof(upd[0]),1,"uniprint");
1510
 
 
1511
 
      udev->upd = NULL;
1512
 
   }
1513
 
 
1514
 
/** Then call the superclass close **/
1515
 
   code = gdev_prn_close(pdev);
1516
 
   error = error > code ? code : error;
1517
 
 
1518
 
#if UPD_MESSAGES & UPD_M_TOPCALLS
1519
 
      errprintf(pdev->memory,"RETURN: %d = upd_close(0x%05lx)\n",
1520
 
         error,(long) pdev);
1521
 
#endif
1522
 
 
1523
 
   return error;
1524
 
}
1525
 
 
1526
 
/* ------------------------------------------------------------------- */
1527
 
/* upd_get_params: Export Parameters to the Interpreter                */
1528
 
/* ------------------------------------------------------------------- */
1529
 
 
1530
 
#if UPD_MESSAGES & UPD_M_TOPCALLS
1531
 
#define UPD_EXIT_GET(Err,Dev,List)                                      \
1532
 
   if(0 > Err) {                                                        \
1533
 
      errprintf(Dev->memory,"RETURN-%d: %d upd_get_params(0x%05lx,0x%05lx)\n", \
1534
 
         __LINE__,Err,(long) Dev,(long) List);                          \
1535
 
      return_error(Err);                                                \
1536
 
   }
1537
 
#else
1538
 
#define UPD_EXIT_GET(Err,Dev,List) if(0 > Err) return_error(Err);
1539
 
#endif
1540
 
 
1541
 
static int
1542
 
upd_get_params(gx_device *pdev, gs_param_list *plist)
1543
 
{
1544
 
   upd_device *const udev    =  (upd_device *) pdev;
1545
 
   const upd_p       upd     =  udev->upd;
1546
 
   int               error,i;
1547
 
 
1548
 
#if UPD_MESSAGES & UPD_M_TOPCALLS
1549
 
      errprintf(udev->memory,"CALL: upd_get_params(0x%05lx,0x%05lx)\n",
1550
 
         (long) udev,(long) plist);
1551
 
#endif
1552
 
 
1553
 
/** Call the SuperClass-get_params at the beginning */
1554
 
   error = gdev_prn_get_params((gx_device *)udev,plist);
1555
 
   UPD_EXIT_GET(error,udev,plist);
1556
 
 
1557
 
/** Export the version */
1558
 
   if(upd_version) { /* Version-Export enabled */
1559
 
      udev->upd_version.data       = (const byte *) rcsid;
1560
 
      udev->upd_version.size       = strlen(rcsid);
1561
 
      udev->upd_version.persistent = true;
1562
 
      error = param_write_string(plist,upd_version,&udev->upd_version);
1563
 
      UPD_EXIT_GET(error,udev,plist);
1564
 
   }                 /* Version-Export enabled */
1565
 
 
1566
 
/** Export the Named choices */
1567
 
   for(i = 0; i < countof(upd_choice); ++i) {
1568
 
      if(!upd_choice[i]) continue; /* Choice-Export disabled */
1569
 
      if(upd && upd->choice && upd->choice[i]) {
1570
 
         gs_param_string name;
1571
 
         name.data       = (const byte *) upd_choice[i][upd->choice[i]];
1572
 
         name.size       = strlen((const char *) name.data);
1573
 
         name.persistent = true;
1574
 
         error = param_write_name(plist,upd_choice[i][0],&name);
1575
 
      } else {
1576
 
         error = param_write_null(plist,upd_choice[i][0]);
1577
 
      }
1578
 
      UPD_EXIT_GET(error,udev,plist);
1579
 
   }
1580
 
 
1581
 
/** Export the flags (bool) */
1582
 
   for(i = 0; i < countof(upd_flags); ++i) {
1583
 
      if(!upd_flags[i]) continue; /* Flag-Export disabled */
1584
 
      if(upd) {
1585
 
         bool value = upd->flags & ((uint32_t) 1 << i);
1586
 
         error = param_write_bool(plist,upd_flags[i],&value);
1587
 
      } else {
1588
 
         error = param_write_null(plist,upd_flags[i]);
1589
 
      }
1590
 
      UPD_EXIT_GET(error,udev,plist);
1591
 
   }
1592
 
 
1593
 
/** Export the ints */
1594
 
   for(i = 0; i < countof(upd_ints); ++i) {
1595
 
      if(!upd_ints[i]) continue; /* int-Export disabled */
1596
 
      if(upd && upd->ints && upd->ints[i]) {
1597
 
         int value = upd->ints[i];
1598
 
         error = param_write_int( plist,upd_ints[i],&value);
1599
 
      } else {
1600
 
         error = param_write_null(plist,upd_ints[i]);
1601
 
      }
1602
 
      UPD_EXIT_GET(error,udev,plist);
1603
 
   }
1604
 
 
1605
 
/** Export the int-arrays */
1606
 
   for(i = 0; i < countof(upd_int_a); ++i) {
1607
 
      if(!upd_int_a[i]) continue; /* int-Array-Export disabled */
1608
 
      if(upd && upd->int_a && upd->int_a[i].size) {
1609
 
         error = param_write_int_array( plist,upd_int_a[i],(upd->int_a+i));
1610
 
      } else {
1611
 
         error = param_write_null(plist,upd_int_a[i]);
1612
 
      }
1613
 
      UPD_EXIT_GET(error,udev,plist);
1614
 
   }
1615
 
 
1616
 
/** Export the strings */
1617
 
   for(i = 0; i < countof(upd_strings); ++i) {
1618
 
      if(!upd_strings[i]) continue; /* String-Export disabled */
1619
 
      if(upd && upd->strings && upd->strings[i].size) {
1620
 
         error = param_write_string( plist,upd_strings[i],(upd->strings+i));
1621
 
      } else {
1622
 
         error = param_write_null(plist,upd_strings[i]);
1623
 
      }
1624
 
      UPD_EXIT_GET(error,udev,plist);
1625
 
   }
1626
 
 
1627
 
/** Export the string-Arrays */
1628
 
   for(i = 0; i < countof(upd_string_a); ++i) {
1629
 
      if(!upd_string_a[i]) continue; /* String-Array-Export disabled */
1630
 
      if(upd && upd->string_a && upd->string_a[i].size) {
1631
 
         error =
1632
 
            param_write_string_array( plist,upd_string_a[i],(upd->string_a+i));
1633
 
      } else {
1634
 
         error = param_write_null(plist,upd_string_a[i]);
1635
 
      }
1636
 
      UPD_EXIT_GET(error,udev,plist);
1637
 
   }
1638
 
 
1639
 
/** Export the float-Arrays */
1640
 
   for(i = 0; i < countof(upd_float_a); ++i) {
1641
 
      if(!upd_float_a[i]) continue; /* Float-Array-Export disabled */
1642
 
      if(upd && upd->float_a && upd->float_a[i].size) {
1643
 
         error =
1644
 
            param_write_float_array( plist,upd_float_a[i],(upd->float_a+i));
1645
 
      } else {
1646
 
         error = param_write_null(plist,upd_float_a[i]);
1647
 
      }
1648
 
      UPD_EXIT_GET(error,udev,plist);
1649
 
   }
1650
 
 
1651
 
#if UPD_MESSAGES & UPD_M_TOPCALLS
1652
 
   errprintf(udev->memory,"RETURN: %d = upd_get_params(0x%05lx,0x%05lx)\n",
1653
 
       error,(long) udev,(long) plist);
1654
 
#endif
1655
 
 
1656
 
   return error;
1657
 
}
1658
 
 
1659
 
#undef UPD_EXIT_GET
1660
 
 
1661
 
/* ------------------------------------------------------------------- */
1662
 
/* upd_put_params: Load Parameters into the device-structure           */
1663
 
/* ------------------------------------------------------------------- */
1664
 
 
1665
 
static int
1666
 
upd_put_params(gx_device *pdev, gs_param_list *plist)
1667
 
{
1668
 
   upd_device *const      udev       = (upd_device *) pdev;
1669
 
   upd_p                  upd        = udev->upd;
1670
 
   int                    error      = 0, code,i;
1671
 
 
1672
 
   float                  MarginsHWResolution[2],Margins[2];
1673
 
   gx_device_color_info   color_info;
1674
 
   uint32_t                 flags      = 0;
1675
 
   int                   *choice     = NULL;
1676
 
   int                   *ints       = NULL;
1677
 
   gs_param_int_array    *int_a      = NULL;
1678
 
   gs_param_string       *strings    = NULL;
1679
 
   gs_param_string_array *string_a   = NULL;
1680
 
   gs_param_float_array  *float_a    = NULL, mfa;
1681
 
 
1682
 
/**
1683
 
Error is used for two purposes: either it holds a negative error
1684
 
code or it is used as a bitfield, that tells, which parameters
1685
 
were actually loaded.  If any of the important parameters changed
1686
 
upd_put_params closes the device, since the real parameter-evaluation
1687
 
is carried out by upd_open.
1688
 
*/
1689
 
 
1690
 
#define UPD_PUT_FLAGS       0x0002
1691
 
#define UPD_PUT_CHOICE      0x0004
1692
 
#define UPD_PUT_INTS        0x0008
1693
 
#define UPD_PUT_INT_A       0x0010
1694
 
#define UPD_PUT_STRINGS     0x0020
1695
 
#define UPD_PUT_STRING_A    0x0040
1696
 
#define UPD_PUT_FLOAT_A     0x0080
1697
 
#define UPD_PUT_CHANGEDSIZE 0x0100
1698
 
 
1699
 
#if UPD_MESSAGES & UPD_M_TOPCALLS
1700
 
      errprintf(udev->memory,"CALL: upd_put_params(0x%05lx,0x%05lx)\n",
1701
 
         (long)udev,(long)plist);
1702
 
#endif
1703
 
 
1704
 
/**
1705
 
I consider the following part of upd_put_params a bad-nasty-hack-hack
1706
 
and i am uncertain, wether it really works in the intended way. I provide it
1707
 
just for the case someone is performing nasty-parameter-changes on the
1708
 
active device, especially switching the OutputFile. If this happens in
1709
 
a situation, where data were written to the file, but the termination
1710
 
sequence is required, the driver does it now. (If you want to know, why
1711
 
i am writing bad-nasty-hack-hack, visit http://www.zark.com )
1712
 
*/
1713
 
   if(upd && (B_OPEN & udev->upd->flags) && (NULL != udev->file)) {
1714
 
 
1715
 
      gs_param_string fname = { NULL, 0, false };
1716
 
 
1717
 
      code = param_read_string(plist,"OutputFile",&fname);
1718
 
      if((1 != code) && (0 != code)) {
1719
 
         code = param_read_null(plist,"OutputFile");
1720
 
         if(0 == code) {
1721
 
            fname.data = (const byte *) "";
1722
 
            fname.size = 0;
1723
 
         }
1724
 
      }
1725
 
 
1726
 
      if((0 == code) &&
1727
 
         strncmp((const char *)fname.data,udev->fname,fname.size)) {
1728
 
         if(upd->strings && 0 < udev->upd->strings[S_CLOSE].size)
1729
 
            fwrite(upd->strings[S_CLOSE].data,1,
1730
 
                   upd->strings[S_CLOSE].size,udev->file);
1731
 
 
1732
 
         upd->flags &= ~B_OPEN;
1733
 
      }
1734
 
   }
1735
 
/* Done with the bad-nasty-hack-hack */
1736
 
 
1737
 
/**
1738
 
The next thing "upd_put_params" does, is a little strange too. It imports
1739
 
a readonly-parameter, the version-string. I do not know wether it is still
1740
 
required, but some versions of GHOSTSCRIPT disliked it very much, if an
1741
 
existing parameter was not touched by the put-operation.
1742
 
 
1743
 
On the other hand it is the right time to show the basic-outline of the
1744
 
parameter-importing flow. Basically the proper "param_read"-procedure
1745
 
is called. If it indicated, that the parameter was present, but of the
1746
 
wrong type, a read for the null-type is attempted, which is by convention
1747
 
somehow an reset to default. This sequence is applied to all the parameters
1748
 
and in case of the array-parameters, a succesful null-read is marked by
1749
 
setting data and size to 0.
1750
 
*/
1751
 
#if UPD_MESSAGES & UPD_M_SETUP
1752
 
#define UPD_PARAM_READ(Param_read,Name,Object,Mem)   \
1753
 
   code = Param_read(plist,Name,&Object);            \
1754
 
   if(0 > code) {                                    \
1755
 
      code = param_read_null(plist,Name);            \
1756
 
      if(0 == code) memset(&Object,0,sizeof(Object));\
1757
 
   }                                                 \
1758
 
   if(!code) errprintf(Mem,                          \
1759
 
      "upd_put_params: retrieved parameter \"%s\"\n",\
1760
 
      Name);                                         \
1761
 
   if(0 > code) {                                    \
1762
 
      param_signal_error(plist,Name,code);           \
1763
 
      if(error > code) error = code;                 \
1764
 
   }
1765
 
#else
1766
 
#define UPD_PARAM_READ(Param_read,Name,Object,Mem)   \
1767
 
   code = Param_read(plist,Name,&Object);            \
1768
 
   if(0 > code) {                                    \
1769
 
      code = param_read_null(plist,Name);            \
1770
 
      if(0 == code) memset(&Object,0,sizeof(Object));\
1771
 
   }                                                 \
1772
 
   if(0 > code) {                                    \
1773
 
      param_signal_error(plist,Name,code);           \
1774
 
      if(error > code) error = code;                 \
1775
 
   }
1776
 
#endif
1777
 
 
1778
 
   UPD_PARAM_READ(param_read_string,upd_version,udev->upd_version,udev->memory)
1779
 
 
1780
 
/**
1781
 
upd_put_params begins it's normal work by creating a copy, of
1782
 
the data, that it might change, except for color_info that might
1783
 
be changed in the device-structure, all manipulations are carried
1784
 
out on this copies.
1785
 
*/
1786
 
   MarginsHWResolution[0] = udev->MarginsHWResolution[0];
1787
 
   MarginsHWResolution[1] = udev->MarginsHWResolution[1];
1788
 
               Margins[0] = udev->Margins[0];
1789
 
               Margins[1] = udev->Margins[1];
1790
 
 
1791
 
   color_info = udev->color_info;
1792
 
   if(upd) {
1793
 
     flags = upd->flags;
1794
 
     UPD_MM_CPY_ARRAY(udev->memory, choice,  upd->choice,  countof(upd_choice),
1795
 
        UPD_MM_CPY_VALUE);
1796
 
     UPD_MM_CPY_ARRAY(udev->memory, ints,    upd->ints,    countof(upd_ints),
1797
 
        UPD_MM_CPY_VALUE);
1798
 
     UPD_MM_CPY_ARRAY(udev->memory, int_a,   upd->int_a,   countof(upd_int_a),
1799
 
        UPD_MM_CPY_PARAM);
1800
 
     UPD_MM_CPY_ARRAY(udev->memory, strings, upd->strings, countof(upd_strings),
1801
 
        UPD_MM_CPY_PARAM);
1802
 
     UPD_MM_CPY_ARRAY(udev->memory, string_a,upd->string_a,countof(upd_string_a),
1803
 
        UPD_MM_CPY_APARAM);
1804
 
     UPD_MM_CPY_ARRAY(udev->memory, float_a, upd->float_a, countof(upd_float_a),
1805
 
        UPD_MM_CPY_PARAM);
1806
 
   } else {
1807
 
     flags = 0;
1808
 
     UPD_MM_GET_ARRAY(udev->memory, choice,  countof(upd_choice));
1809
 
     UPD_MM_GET_ARRAY(udev->memory, ints,    countof(upd_ints));
1810
 
     UPD_MM_GET_ARRAY(udev->memory, int_a,   countof(upd_int_a));
1811
 
     UPD_MM_GET_ARRAY(udev->memory, strings, countof(upd_strings));
1812
 
     UPD_MM_GET_ARRAY(udev->memory, string_a,countof(upd_string_a));
1813
 
     UPD_MM_GET_ARRAY(udev->memory, float_a, countof(upd_float_a));
1814
 
   }
1815
 
 
1816
 
/** Import the Multiple-Choices */
1817
 
   for(i = 0; countof(upd_choice) > i; ++i) {
1818
 
      gs_param_string value = { NULL, 0, false};
1819
 
      if(!upd_choice[i][0]) continue;
1820
 
      UPD_PARAM_READ(param_read_name,upd_choice[i][0],value,udev->memory);
1821
 
      if(0 == code) {
1822
 
         if(0 <= error) error |= UPD_PUT_CHOICE;
1823
 
         choice[i] = 0;
1824
 
         if(0 < value.size) {
1825
 
            int j;
1826
 
            for(j = 1; upd_choice[i][j]; ++j) {
1827
 
               if((strlen(upd_choice[i][j]) == value.size) &&
1828
 
                  (0 == strncmp(upd_choice[i][j],
1829
 
                            (const char *) value.data,value.size))) {
1830
 
                  choice[i] = j;
1831
 
                  break;
1832
 
               }
1833
 
            }
1834
 
         }
1835
 
      }
1836
 
   }
1837
 
 
1838
 
/** Import the Boolean Values */
1839
 
   for(i = 0; countof(upd_flags) > i; ++i) {
1840
 
      uint32_t bit  = (uint32_t) 1 << i;
1841
 
      bool   flag = flags & bit ? true : false;
1842
 
      if(!upd_flags[i]) continue;
1843
 
      UPD_PARAM_READ(param_read_bool,upd_flags[i],flag,udev->memory);
1844
 
      if(0 == code) {
1845
 
         if(0 <= error) error |= UPD_PUT_FLAGS;
1846
 
         if(flag) flags |=  bit;
1847
 
         else     flags &= ~bit;
1848
 
      }
1849
 
   }
1850
 
 
1851
 
/** Import the Integer Values */
1852
 
   for(i = 0; countof(upd_ints) > i; ++i) {
1853
 
      int value = ints[i];
1854
 
      if(!upd_ints[i]) continue;
1855
 
      UPD_PARAM_READ(param_read_int,upd_ints[i],value,udev->memory);
1856
 
      if(0 == code) {
1857
 
         if(0 <= error) error |= UPD_PUT_INTS;
1858
 
         ints[i] = value;
1859
 
      }
1860
 
   }
1861
 
 
1862
 
/** Import the Integer Arrays */
1863
 
   for(i = 0; countof(upd_int_a) > i; ++i) {
1864
 
      gs_param_int_array value = int_a[i];
1865
 
      if(!upd_int_a[i]) continue;
1866
 
      UPD_PARAM_READ(param_read_int_array,upd_int_a[i],value,udev->memory);
1867
 
      if(0 == code) {
1868
 
         if(0 <= error) error |= UPD_PUT_INT_A;
1869
 
         UPD_MM_DEL_PARAM(udev->memory, int_a[i]);
1870
 
         if(!value.size) {
1871
 
            value.data = NULL;
1872
 
            int_a[i]   = value;
1873
 
         } else {
1874
 
            UPD_MM_CPY_PARAM(udev->memory, int_a[i],value);
1875
 
         }
1876
 
      }
1877
 
   }
1878
 
 
1879
 
/** Import the Strings */
1880
 
   for(i = 0; countof(upd_strings) > i; ++i) {
1881
 
      gs_param_string value = strings[i];
1882
 
      if(!upd_strings[i]) continue;
1883
 
      UPD_PARAM_READ(param_read_string,upd_strings[i],value,udev->memory);
1884
 
      if(0 == code) {
1885
 
         if(0 <= error) error |= UPD_PUT_STRINGS;
1886
 
         UPD_MM_DEL_PARAM(udev->memory, strings[i]);
1887
 
         if(!value.size) {
1888
 
            value.data = NULL;
1889
 
            strings[i]   = value;
1890
 
         } else {
1891
 
            UPD_MM_CPY_PARAM(udev->memory, strings[i],value);
1892
 
         }
1893
 
      }
1894
 
   }
1895
 
 
1896
 
/** Import the String Arrays */
1897
 
   for(i = 0; countof(upd_string_a) > i; ++i) {
1898
 
      gs_param_string_array value = string_a[i];
1899
 
      if(!upd_string_a[i]) continue;
1900
 
      UPD_PARAM_READ(param_read_string_array,upd_string_a[i],value,udev->memory);
1901
 
      if(0 == code) {
1902
 
         if(0 <= error) error |= UPD_PUT_STRING_A;
1903
 
         UPD_MM_DEL_APARAM(udev->memory, string_a[i]);
1904
 
         if(!value.size) {
1905
 
            value.data  = NULL;
1906
 
            string_a[i] = value;
1907
 
         } else {
1908
 
            UPD_MM_CPY_APARAM(udev->memory, string_a[i],value);
1909
 
         }
1910
 
      }
1911
 
   }
1912
 
 
1913
 
/** Import the Float Arrays */
1914
 
   for(i = 0; countof(upd_float_a) > i; ++i) {
1915
 
      gs_param_float_array value = float_a[i];
1916
 
      if(!upd_float_a[i]) continue;
1917
 
      UPD_PARAM_READ(param_read_float_array,upd_float_a[i],value,udev->memory);
1918
 
      if(0 == code) {
1919
 
         if(0 <= error) error |= UPD_PUT_FLOAT_A;
1920
 
         UPD_MM_DEL_PARAM(udev->memory, float_a[i]);
1921
 
         if(!value.size) {
1922
 
            value.data = NULL;
1923
 
            float_a[i] = value;
1924
 
         } else {
1925
 
            UPD_MM_CPY_PARAM(udev->memory, float_a[i],value);
1926
 
         }
1927
 
      }
1928
 
   }
1929
 
 
1930
 
/**
1931
 
Prior to the call to the superclass-put_params, the memory-layout and
1932
 
the color-model needs adjustment. This is performed here, if any parameters
1933
 
were set.
1934
 
In addition to that, Resolution & Margin-Parameters are tested & adjusted.
1935
 
*/
1936
 
   if(0 < error) {
1937
 
 
1938
 
      int *ip,*ip2,ncomp,nbits;
1939
 
 
1940
 
      if(6 > int_a[IA_COLOR_INFO].size) {
1941
 
         UPD_MM_DEL_PARAM(udev->memory, int_a[IA_COLOR_INFO]);
1942
 
         UPD_MM_GET_ARRAY(udev->memory, int_a[IA_COLOR_INFO].data,6);
1943
 
         int_a[IA_COLOR_INFO].size = 6;
1944
 
      }
1945
 
      ip = (int *) upd_cast(int_a[IA_COLOR_INFO].data);
1946
 
 
1947
 
      if(0 == ip[0]) { /* Try to obtain num_components */
1948
 
         switch(choice[C_MAPPER]) {
1949
 
            case MAP_GRAY:     ip[0] = 1; break;
1950
 
            case MAP_RGBW:     ip[0] = 3; break;
1951
 
            case MAP_RGB:      ip[0] = 3; break;
1952
 
            case MAP_CMYK:     ip[0] = 4; break;
1953
 
            case MAP_CMYKGEN:  ip[0] = 4; break;
1954
 
            case MAP_RGBOV:    ip[0] = 3; break;
1955
 
            case MAP_RGBNOV:   ip[0] = 3; break;
1956
 
            default:           ip[0] = color_info.num_components; break;
1957
 
         }
1958
 
      }                /* Try to obtain num_components */
1959
 
 
1960
 
      switch(choice[C_MAPPER]) {
1961
 
         case MAP_GRAY:     ncomp = 1; break;
1962
 
         case MAP_RGBW:     ncomp = 4; break;
1963
 
         case MAP_RGB:      ncomp = 3; break;
1964
 
         case MAP_CMYK:     ncomp = 4; break;
1965
 
         case MAP_CMYKGEN:  ncomp = 4; break;
1966
 
         case MAP_RGBOV:    ncomp = 4; break;
1967
 
         case MAP_RGBNOV:   ncomp = 4; break;
1968
 
         default:           ncomp = ip[0]; break;
1969
 
      }
1970
 
      if(UPD_CMAP_MAX < ncomp) ncomp = UPD_CMAP_MAX;
1971
 
 
1972
 
      if(ncomp > int_a[IA_COMPBITS].size) { /* Default ComponentBits */
1973
 
         UPD_MM_GET_ARRAY(udev->memory, ip2,ncomp);
1974
 
         nbits = 32 / ncomp;
1975
 
         if(8 < nbits) nbits = 8;
1976
 
         for(i = 0; i < ncomp; ++i) ip2[i] = nbits;
1977
 
         UPD_MM_DEL_PARAM(udev->memory, int_a[IA_COMPBITS]);
1978
 
         int_a[IA_COMPBITS].data = ip2;
1979
 
         int_a[IA_COMPBITS].size = ncomp;
1980
 
      }                                     /* Default ComponentBits */
1981
 
 
1982
 
      if(ncomp > int_a[IA_COMPSHIFT].size) {  /* Default ComponentShift */
1983
 
         nbits = 0;
1984
 
         for(i = 0; i < ncomp; ++i) nbits += int_a[IA_COMPBITS].data[i];
1985
 
         UPD_MM_GET_ARRAY(udev->memory, ip2,ncomp);
1986
 
         for(i = 0; i < ncomp; ++i) {
1987
 
            ip2[i] = nbits - int_a[IA_COMPBITS].data[i];
1988
 
            nbits -= int_a[IA_COMPBITS].data[i];
1989
 
         }
1990
 
         UPD_MM_DEL_PARAM(udev->memory, int_a[IA_COMPSHIFT]);
1991
 
         int_a[IA_COMPSHIFT].data = ip2;
1992
 
         int_a[IA_COMPSHIFT].size = ncomp;
1993
 
      }                                       /* Default ComponentShift */
1994
 
 
1995
 
      if(0 == ip[1]) { /* Try to compute the depth */
1996
 
         nbits = 0;
1997
 
         for(i = 0; i < ncomp; ++i) {
1998
 
            if(nbits < (int_a[IA_COMPBITS].data[i] +
1999
 
                        int_a[IA_COMPSHIFT].data[i]))
2000
 
               nbits =  int_a[IA_COMPBITS].data[i] +
2001
 
                        int_a[IA_COMPSHIFT].data[i];
2002
 
         }
2003
 
         if(      1 >= nbits) nbits =  1;
2004
 
         else if( 2 >= nbits) nbits =  2;
2005
 
         else if( 4 >= nbits) nbits =  4;
2006
 
         else if( 8 >= nbits) nbits =  8;
2007
 
         else if(16 >= nbits) nbits = 16;
2008
 
         else if(24 >= nbits) nbits = 24;
2009
 
         else                 nbits = 32;
2010
 
 
2011
 
         ip[1] = nbits;
2012
 
 
2013
 
      }                /* Try to compute the depth */
2014
 
 
2015
 
      if(0 == ip[2]) { /* Number of Gray-Levels */
2016
 
         nbits = 0;
2017
 
         for(i = 0; i < ncomp; ++i) if(nbits < int_a[IA_COMPBITS].data[i])
2018
 
            nbits = int_a[IA_COMPBITS].data[i];
2019
 
         if(nbits > 8) nbits = 8;
2020
 
         ip[2] = (1 << nbits) - 1;
2021
 
      }                /* Number of Gray-Levels */
2022
 
 
2023
 
      if(0 == ip[3] && 1 < ip[0]) { /* Number of Colors */
2024
 
         nbits = 0;
2025
 
         for(i = 0; i < ip[0]; ++i) nbits += int_a[IA_COMPBITS].data[i];
2026
 
         if(nbits > 8) nbits = 8;
2027
 
         ip[3] = (1 << nbits) - 1;
2028
 
      }                             /* Number of Colors */
2029
 
 
2030
 
      if(0 == ip[4]) { /* Gray-Ramp */
2031
 
         nbits = 0;
2032
 
         for(i = 0; i < ncomp; ++i) if(nbits < int_a[IA_COMPBITS].data[i])
2033
 
            nbits = int_a[IA_COMPBITS].data[i];
2034
 
         if(2 < nbits) ip[4] = 256;
2035
 
         else          ip[4] = 2;
2036
 
      }                /* Gray-Ramp */
2037
 
 
2038
 
      if(0 == ip[5] && 1 < ip[0]) { /* Color-Ramp */
2039
 
         nbits = 0;
2040
 
         for(i = 0; i < ncomp; ++i) if(nbits < int_a[IA_COMPBITS].data[i])
2041
 
            nbits = int_a[IA_COMPBITS].data[i];
2042
 
         if(2 < nbits) ip[5] = 256;
2043
 
         else          ip[5] = 2;
2044
 
      }                             /* Color-Ramp */
2045
 
 
2046
 
      udev->color_info.num_components = ip[0];
2047
 
      udev->color_info.depth          = ip[1];
2048
 
      udev->color_info.max_gray       = (gx_color_value) ip[2];
2049
 
      udev->color_info.max_color      = (gx_color_value) ip[3];
2050
 
      udev->color_info.dither_grays   = (gx_color_value) ip[4];
2051
 
      udev->color_info.dither_colors  = (gx_color_value) ip[5];
2052
 
 
2053
 
/*
2054
 
 * Now we're dealing with the Resolution- & Margin-Stuff
2055
 
 * (This is close to be a bad-nasty-hack-hack)
2056
 
 */
2057
 
      if((0 == param_read_float_array(plist,"HWResolution",&mfa)) &&
2058
 
         (2 == mfa.size) && (0 != mfa.data)) {
2059
 
         udev->MarginsHWResolution[0] = mfa.data[0];
2060
 
         udev->MarginsHWResolution[1] = mfa.data[1];
2061
 
      } else {
2062
 
         udev->MarginsHWResolution[0] = udev->HWResolution[0];
2063
 
         udev->MarginsHWResolution[1] = udev->HWResolution[1];
2064
 
      }
2065
 
 
2066
 
      if((0 == param_read_float_array(plist,".HWMargins",&mfa)) &&
2067
 
         (4 == mfa.size) && (0 != mfa.data)) {
2068
 
         udev->Margins[0] = -mfa.data[0] * udev->MarginsHWResolution[0] / 72.0;
2069
 
         udev->Margins[1] = -mfa.data[3] * udev->MarginsHWResolution[1] / 72.0;
2070
 
      }
2071
 
   }                                       /* Change the color-Info */
2072
 
 
2073
 
/* Call the superclass-put_params now */
2074
 
   code = gdev_prn_put_params((gx_device *)udev,plist);
2075
 
   if(0 > code) error = code;
2076
 
 
2077
 
/**
2078
 
If the superclass-"put_params" went o.k. too, then the new parameters are
2079
 
transferred into the device-structure. In the case of "uniprint", this may
2080
 
 
2081
 
 1. Close the device, which might fail.
2082
 
 2. Allocate new memory for the upd-specific structure, that might fail too.
2083
 
 
2084
 
*/
2085
 
/* *HGS* recognize a changed device geometry */
2086
 
   if( udev->upd &&                              /* HGS */
2087
 
      ((udev->width  != udev->upd->pdwidth) ||   /* HGS */
2088
 
      (udev->height != udev->upd->pdheight)  ))  /* HGS */
2089
 
        error |= UPD_PUT_CHANGEDSIZE;            /* HGS */
2090
 
 
2091
 
   if(0 < error && udev->is_open) {
2092
 
      code = gs_closedevice((gx_device *)udev);
2093
 
      if(0 > code) error = code;
2094
 
   }
2095
 
 
2096
 
   if(0 < error) { /* Actually something loaded without error */
2097
 
 
2098
 
      if(!(upd = udev->upd)) {
2099
 
        UPD_MM_GET_ARRAY(udev->memory, udev->upd,1);
2100
 
        upd = udev->upd;
2101
 
      } else {
2102
 
        UPD_MM_DEL_ARRAY(udev->memory, upd->choice,  countof(upd_choice),  UPD_MM_DEL_VALUE);
2103
 
        UPD_MM_DEL_ARRAY(udev->memory, upd->ints,    countof(upd_ints),    UPD_MM_DEL_VALUE);
2104
 
        UPD_MM_DEL_ARRAY(udev->memory, upd->int_a,   countof(upd_int_a),   UPD_MM_DEL_PARAM);
2105
 
        UPD_MM_DEL_ARRAY(udev->memory, upd->strings, countof(upd_strings), UPD_MM_DEL_PARAM);
2106
 
        UPD_MM_DEL_ARRAY(udev->memory, upd->string_a,countof(upd_string_a),UPD_MM_DEL_APARAM);
2107
 
        UPD_MM_DEL_ARRAY(udev->memory, upd->float_a, countof(upd_float_a), UPD_MM_DEL_PARAM);
2108
 
      }
2109
 
 
2110
 
      upd->choice   = choice;
2111
 
      upd->flags    = flags;
2112
 
      upd->ints     = ints;
2113
 
      upd->int_a    = int_a;
2114
 
      upd->strings  = strings;
2115
 
      upd->string_a = string_a;
2116
 
      upd->float_a  = float_a;
2117
 
      upd->memory   = udev->memory;
2118
 
 
2119
 
      if(0 < error) error = 0;
2120
 
 
2121
 
   } else {
2122
 
 
2123
 
                  udev->Margins[0] =             Margins[0];
2124
 
                  udev->Margins[1] =             Margins[1];
2125
 
      udev->MarginsHWResolution[0] = MarginsHWResolution[0];
2126
 
      udev->MarginsHWResolution[1] = MarginsHWResolution[1];
2127
 
 
2128
 
      udev->color_info = color_info;
2129
 
      UPD_MM_DEL_ARRAY(udev->memory, choice,  countof(upd_choice),  UPD_MM_DEL_VALUE);
2130
 
      UPD_MM_DEL_ARRAY(udev->memory, ints,    countof(upd_ints),    UPD_MM_DEL_VALUE);
2131
 
      UPD_MM_DEL_ARRAY(udev->memory, int_a,   countof(upd_int_a),   UPD_MM_DEL_PARAM);
2132
 
      UPD_MM_DEL_ARRAY(udev->memory, strings, countof(upd_strings), UPD_MM_DEL_PARAM);
2133
 
      UPD_MM_DEL_ARRAY(udev->memory, string_a,countof(upd_string_a),UPD_MM_DEL_APARAM);
2134
 
      UPD_MM_DEL_ARRAY(udev->memory, float_a, countof(upd_float_a), UPD_MM_DEL_PARAM);
2135
 
 
2136
 
   }
2137
 
 
2138
 
/*
2139
 
 * upd_put_params keeps the Procedures upd to date
2140
 
 */
2141
 
 
2142
 
   upd_procs_map(udev);
2143
 
 
2144
 
#if UPD_MESSAGES & UPD_M_TOPCALLS
2145
 
      errprintf(udev->memory,"RETURN: %d = upd_put_params(0x%05lx,0x%05lx)\n",
2146
 
         error,(long) udev, (long) plist);
2147
 
#endif
2148
 
 
2149
 
   return error;
2150
 
}
2151
 
 
2152
 
/* ------------------------------------------------------------------- */
2153
 
/* upd_cmyk_icolor: KCMY->KCMY-Index Mapping                           */
2154
 
/* ------------------------------------------------------------------- */
2155
 
/**
2156
 
The next Routines, that follow, are the color-mapping routines.
2157
 
GHOSTSCRIPT talks about "gx_color_values" and the driver has
2158
 
to merge the 1, 3 or four values into up to 32 Bits, that means
2159
 
it is necessary to do some truncation and shifting. For the truncation
2160
 
"uniprint" uses the internal function "upd_truncate" and "upd_expand"
2161
 
reverses this in the reverse-mapping procedures.
2162
 
*/
2163
 
 
2164
 
static gx_color_index
2165
 
upd_cmyk_icolor(gx_device *pdev, const gx_color_value cv[])
2166
 
{
2167
 
   const upd_p     upd = ((upd_device *)pdev)->upd;
2168
 
   gx_color_index  rv;
2169
 
   gx_color_value c, m, y, k;
2170
 
   c = cv[0]; m = cv[1]; y = cv[2]; k = cv[3];
2171
 
 
2172
 
/**
2173
 
All 4-Component-Modi have to deal with the Problem, that a value
2174
 
with all bits set can be produced, which is treated as an error-return
2175
 
from the mapping-functions. But with RGBW or KCMY, there is a neat
2176
 
trick: Grayscale are transferred as RGB/CMY=0 and holding Data only
2177
 
in the W- or K-Component.
2178
 
*/
2179
 
 
2180
 
   if((c == m) && (m == y)) {
2181
 
 
2182
 
      rv = upd_truncate(upd,0,(gx_color_value)(c > k ? c : k));
2183
 
 
2184
 
   } else {
2185
 
 
2186
 
      rv  = upd_truncate(upd,0,k) | upd_truncate(upd,1,c)
2187
 
          | upd_truncate(upd,2,m) | upd_truncate(upd,3,y);
2188
 
 
2189
 
/* It might still become a "gx_no_color_value" due to truncation, thus: */
2190
 
 
2191
 
      if(rv == gx_no_color_index) rv ^= 1;
2192
 
   }
2193
 
 
2194
 
#if UPD_MESSAGES & UPD_M_MAPCALLS
2195
 
  errprintf(pdev->memory,
2196
 
"cmyk_icolor: (%5.1f,%5.1f,%5.1f,%5.1f) : (%5.1f,%5.1f,%5.1f,%5.1f) : 0x%0*lx\n",
2197
 
   255.0 * (double) c / (double) gx_max_color_value,
2198
 
   255.0 * (double) m / (double) gx_max_color_value,
2199
 
   255.0 * (double) y / (double) gx_max_color_value,
2200
 
   255.0 * (double) k / (double) gx_max_color_value,
2201
 
   255.0 * (double) ((rv >> upd->cmap[1].bitshf) & upd->cmap[1].bitmsk)
2202
 
                 / (double) upd->cmap[1].bitmsk,
2203
 
   255.0 * (double) ((rv >> upd->cmap[2].bitshf) & upd->cmap[2].bitmsk)
2204
 
                 / (double) upd->cmap[2].bitmsk,
2205
 
   255.0 * (double) ((rv >> upd->cmap[3].bitshf) & upd->cmap[3].bitmsk)
2206
 
                 / (double) upd->cmap[3].bitmsk,
2207
 
   255.0 * (double) ((rv >> upd->cmap[0].bitshf) & upd->cmap[0].bitmsk)
2208
 
                 / (double) upd->cmap[0].bitmsk,
2209
 
   (pdev->color_info.depth + 3)>>2,rv);
2210
 
#endif
2211
 
 
2212
 
   return rv;
2213
 
}
2214
 
 
2215
 
/* ------------------------------------------------------------------- */
2216
 
/* upd_icolor_rgb: Stored KCMY back to a RGB                           */
2217
 
/* ------------------------------------------------------------------- */
2218
 
 
2219
 
static int
2220
 
upd_icolor_rgb(gx_device *pdev, gx_color_index color, gx_color_value prgb[3])
2221
 
{
2222
 
   const upd_p     upd = ((upd_device *)pdev)->upd;
2223
 
   gx_color_value c,m,y,k;
2224
 
 
2225
 
/*
2226
 
 * Expand to the Component-Values
2227
 
 */
2228
 
   k = upd_expand(upd,0,color);
2229
 
   c = upd_expand(upd,1,color);
2230
 
   m = upd_expand(upd,2,color);
2231
 
   y = upd_expand(upd,3,color);
2232
 
 
2233
 
/*
2234
 
 * Then Invert and subtract K from the colors
2235
 
 */
2236
 
   prgb[0] = gx_max_color_value - c;
2237
 
   if(prgb[0] > k) prgb[0] -= k;
2238
 
   else            prgb[0]  = 0;
2239
 
 
2240
 
   prgb[1] = gx_max_color_value - m;
2241
 
   if(prgb[1] > k) prgb[1] -= k;
2242
 
   else            prgb[1]  = 0;
2243
 
 
2244
 
   prgb[2] = gx_max_color_value - y;
2245
 
   if(prgb[2] > k) prgb[2] -= k;
2246
 
   else            prgb[2]  = 0;
2247
 
 
2248
 
#if UPD_MESSAGES & UPD_M_MAPCALLS
2249
 
   errprintf(pdev->memory,
2250
 
    "icolor_rgb: 0x%0*lx -> (%5.1f,%5.1f,%5.1f,%5.1f) -> (%5.1f,%5.1f,%5.1f,%5.1f) -> (%5.1f,%5.1f,%5.1f)\n",
2251
 
    (pdev->color_info.depth + 3)>>2,color,
2252
 
    255.0 * (double) ((color >> upd->cmap[1].bitshf) & upd->cmap[1].bitmsk)
2253
 
                     / (double) upd->cmap[1].bitmsk,
2254
 
    255.0 * (double) ((color >> upd->cmap[2].bitshf) & upd->cmap[2].bitmsk)
2255
 
                     / (double) upd->cmap[2].bitmsk,
2256
 
    255.0 * (double) ((color >> upd->cmap[3].bitshf) & upd->cmap[3].bitmsk)
2257
 
                     / (double) upd->cmap[3].bitmsk,
2258
 
    255.0 * (double) ((color >> upd->cmap[0].bitshf) & upd->cmap[0].bitmsk)
2259
 
                     / (double) upd->cmap[0].bitmsk,
2260
 
    255.0 * (double)   c     / (double) gx_max_color_value,
2261
 
    255.0 * (double)   m     / (double) gx_max_color_value,
2262
 
    255.0 * (double)   y     / (double) gx_max_color_value,
2263
 
    255.0 * (double)   k     / (double) gx_max_color_value,
2264
 
    255.0 * (double) prgb[0] / (double) gx_max_color_value,
2265
 
    255.0 * (double) prgb[1] / (double) gx_max_color_value,
2266
 
    255.0 * (double) prgb[2] / (double) gx_max_color_value);
2267
 
#endif
2268
 
 
2269
 
   return 0;
2270
 
}
2271
 
 
2272
 
/* ------------------------------------------------------------------- */
2273
 
/* upd_rgb_1color: Grayscale->Grayscale-index-Mapping              */
2274
 
/* ------------------------------------------------------------------- */
2275
 
 
2276
 
static gx_color_index
2277
 
upd_rgb_1color(gx_device *pdev, const gx_color_value cv[])
2278
 
{
2279
 
   const upd_p     upd = ((upd_device *)pdev)->upd;
2280
 
   gx_color_index  rv;
2281
 
   gx_color_value g;
2282
 
 
2283
 
   g = cv[0];
2284
 
   rv = upd_truncate(upd,0,g);
2285
 
 
2286
 
#if UPD_MESSAGES & UPD_M_MAPCALLS
2287
 
   errprintf(pdev->memory,
2288
 
      "rgb_1color: (%5.1f) : (%5.1f) : 0x%0*lx\n",
2289
 
      255.0 * (double) g  / (double) gx_max_color_value,
2290
 
      255.0 * (double) ((rv >> upd->cmap[0].bitshf) & upd->cmap[0].bitmsk)
2291
 
                    / (double) upd->cmap[0].bitmsk,
2292
 
      (pdev->color_info.depth + 3)>>2,rv);
2293
 
#endif
2294
 
 
2295
 
   return rv;
2296
 
}
2297
 
 
2298
 
/* ------------------------------------------------------------------- */
2299
 
/* upd_1color_rgb: reversal of the above                               */
2300
 
/* ------------------------------------------------------------------- */
2301
 
 
2302
 
static int
2303
 
upd_1color_rgb(gx_device *pdev, gx_color_index color, gx_color_value cv[1])
2304
 
{
2305
 
   const upd_p     upd = ((upd_device *)pdev)->upd;
2306
 
/*
2307
 
 * Actual task: expand to full range of gx_color_value
2308
 
 */
2309
 
   cv[0] = upd_expand(upd,0,color);
2310
 
 
2311
 
#if UPD_MESSAGES & UPD_M_MAPCALLS
2312
 
   errprintf(pdev->memory,"1color_rgb: 0x%0*lx -> %5.1f -> (%5.1f,%5.1f,%5.1f)\n",
2313
 
      (pdev->color_info.depth + 3)>>2,color,
2314
 
      255.0 * (double) ((color >> upd->cmap[0].bitshf) & upd->cmap[0].bitmsk)
2315
 
                       / (double) upd->cmap[0].bitmsk,
2316
 
      255.0 * (double) prgb[0] / (double) gx_max_color_value,
2317
 
      255.0 * (double) prgb[0] / (double) gx_max_color_value,
2318
 
      255.0 * (double) prgb[0] / (double) gx_max_color_value);
2319
 
#endif
2320
 
 
2321
 
   return 0;
2322
 
}
2323
 
 
2324
 
/* ------------------------------------------------------------------- */
2325
 
/* upd_rgb_3color: component-wise RGB->RGB-Mapping                     */
2326
 
/* ------------------------------------------------------------------- */
2327
 
 
2328
 
static gx_color_index
2329
 
upd_rgb_3color(gx_device *pdev, const gx_color_value cv[])
2330
 
{
2331
 
   const upd_p     upd = ((upd_device *)pdev)->upd;
2332
 
   gx_color_index  rv;
2333
 
   gx_color_value r, g, b;
2334
 
   r = cv[0]; g = cv[1]; b = cv[2];
2335
 
 
2336
 
   rv = upd_truncate(upd,0,r) | upd_truncate(upd,1,g) | upd_truncate(upd,2,b);
2337
 
   if(rv == gx_no_color_index) rv ^= 1;
2338
 
 
2339
 
#if UPD_MESSAGES & UPD_M_MAPCALLS
2340
 
  errprintf(pdev->memory,
2341
 
   "rgb_3color: (%5.1f,%5.1f,%5.1f) : (%5.1f,%5.1f,%5.1f) : 0x%0*lx\n",
2342
 
   255.0 * (double) r / (double) gx_max_color_value,
2343
 
   255.0 * (double) g / (double) gx_max_color_value,
2344
 
   255.0 * (double) b / (double) gx_max_color_value,
2345
 
   255.0 * (double) ((rv >> upd->cmap[0].bitshf) & upd->cmap[0].bitmsk)
2346
 
                 / (double) upd->cmap[0].bitmsk,
2347
 
   255.0 * (double) ((rv >> upd->cmap[1].bitshf) & upd->cmap[1].bitmsk)
2348
 
                 / (double) upd->cmap[1].bitmsk,
2349
 
   255.0 * (double) ((rv >> upd->cmap[2].bitshf) & upd->cmap[2].bitmsk)
2350
 
                 / (double) upd->cmap[2].bitmsk,
2351
 
   (pdev->color_info.depth + 3)>>2,rv);
2352
 
#endif
2353
 
 
2354
 
   return rv;
2355
 
}
2356
 
 
2357
 
/* ------------------------------------------------------------------- */
2358
 
/* upd_3color_rgb: reversal of the above                               */
2359
 
/* ------------------------------------------------------------------- */
2360
 
 
2361
 
static int
2362
 
upd_3color_rgb(gx_device *pdev, gx_color_index color, gx_color_value prgb[3])
2363
 
{
2364
 
   const upd_p     upd = ((upd_device *)pdev)->upd;
2365
 
 
2366
 
   prgb[0] = upd_expand(upd,0,color);
2367
 
   prgb[1] = upd_expand(upd,1,color);
2368
 
   prgb[2] = upd_expand(upd,2,color);
2369
 
 
2370
 
#if UPD_MESSAGES & UPD_M_MAPCALLS
2371
 
   errprintf(pdev->memory,
2372
 
     "3color_rgb: 0x%0*lx -> (%5.1f,%5.1f,%5.1f) -> (%5.1f,%5.1f,%5.1f)\n",
2373
 
      (pdev->color_info.depth + 3)>>2,color,
2374
 
      255.0 * (double) ((color >> upd->cmap[0].bitshf) & upd->cmap[0].bitmsk)
2375
 
                       / (double) upd->cmap[0].bitmsk,
2376
 
      255.0 * (double) ((color >> upd->cmap[1].bitshf) & upd->cmap[1].bitmsk)
2377
 
                       / (double) upd->cmap[1].bitmsk,
2378
 
      255.0 * (double) ((color >> upd->cmap[2].bitshf) & upd->cmap[2].bitmsk)
2379
 
                       / (double) upd->cmap[2].bitmsk,
2380
 
 
2381
 
      255.0 * (double) prgb[0] / (double) gx_max_color_value,
2382
 
      255.0 * (double) prgb[1] / (double) gx_max_color_value,
2383
 
      255.0 * (double) prgb[2] / (double) gx_max_color_value);
2384
 
#endif
2385
 
 
2386
 
   return 0;
2387
 
}
2388
 
 
2389
 
/* ------------------------------------------------------------------- */
2390
 
/* upd_rgb_4color: Create an WRGB-Index from RGB                       */
2391
 
/* ------------------------------------------------------------------- */
2392
 
 
2393
 
static gx_color_index
2394
 
upd_rgb_4color(gx_device *pdev, const gx_color_value cv[])
2395
 
{
2396
 
   const upd_p     upd = ((upd_device *)pdev)->upd;
2397
 
   gx_color_index  rv;
2398
 
   gx_color_value r, g, b;
2399
 
 
2400
 
   r = cv[0]; g = cv[1]; b = cv[2];
2401
 
 
2402
 
   if((r == g) && (g == b)) {
2403
 
 
2404
 
      rv = upd_truncate(upd,0,r);
2405
 
 
2406
 
   } else {
2407
 
 
2408
 
      gx_color_value w = g < r ? g : r; w = w < b ? w : b; /* Minimum */
2409
 
 
2410
 
      rv = upd_truncate(upd,0,w) | upd_truncate(upd,1,r) |
2411
 
           upd_truncate(upd,2,g) | upd_truncate(upd,3,b);
2412
 
 
2413
 
/* It might still become a "gx_no_color_value" due to truncation, thus: */
2414
 
 
2415
 
      if(rv == gx_no_color_index) rv ^= 1;
2416
 
   }
2417
 
 
2418
 
#if UPD_MESSAGES & UPD_M_MAPCALLS
2419
 
  errprintf(pdev->memory,
2420
 
   "rgb_4color: (%5.1f,%5.1f,%5.1f) : (%5.1f,%5.1f,%5.1f,%5.1f) : 0x%0*lx\n",
2421
 
   255.0 * (double) r / (double) gx_max_color_value,
2422
 
   255.0 * (double) g / (double) gx_max_color_value,
2423
 
   255.0 * (double) b / (double) gx_max_color_value,
2424
 
   255.0 * (double) ((rv >> upd->cmap[1].bitshf) & upd->cmap[1].bitmsk)
2425
 
                 / (double) upd->cmap[1].bitmsk,
2426
 
   255.0 * (double) ((rv >> upd->cmap[2].bitshf) & upd->cmap[2].bitmsk)
2427
 
                 / (double) upd->cmap[2].bitmsk,
2428
 
   255.0 * (double) ((rv >> upd->cmap[3].bitshf) & upd->cmap[3].bitmsk)
2429
 
                 / (double) upd->cmap[3].bitmsk,
2430
 
   255.0 * (double) ((rv >> upd->cmap[0].bitshf) & upd->cmap[0].bitmsk)
2431
 
                 / (double) upd->cmap[0].bitmsk,
2432
 
   (pdev->color_info.depth + 3)>>2,rv);
2433
 
#endif
2434
 
 
2435
 
   return rv;
2436
 
}
2437
 
 
2438
 
/* ------------------------------------------------------------------- */
2439
 
/* upd_4color_rgb: Stored WRGB-Index back to a RGB                     */
2440
 
/* ------------------------------------------------------------------- */
2441
 
 
2442
 
static int
2443
 
upd_4color_rgb(gx_device *pdev, gx_color_index color, gx_color_value prgb[3])
2444
 
{
2445
 
   const upd_p     upd = ((upd_device *)pdev)->upd;
2446
 
 
2447
 
/*
2448
 
 * Expand to the Component-Values
2449
 
 */
2450
 
   prgb[0] = upd_expand(upd,1,color);
2451
 
   prgb[1] = upd_expand(upd,2,color);
2452
 
   prgb[2] = upd_expand(upd,3,color);
2453
 
 
2454
 
/* Revert our Grayscale-Trick: */
2455
 
   if(!(prgb[0] || prgb[1] || prgb[2]))
2456
 
      prgb[0] = prgb[1] = prgb[2] = upd_expand(upd,0,color);
2457
 
 
2458
 
#if UPD_MESSAGES & UPD_M_MAPCALLS
2459
 
   errprintf(pdev->memory,
2460
 
    "4color_rgb: 0x%0*lx -> (%5.1f,%5.1f,%5.1f,%5.1f) -> (%5.1f,%5.1f,%5.1f)\n",
2461
 
    (pdev->color_info.depth + 3)>>2,color,
2462
 
    255.0 * (double) ((color >> upd->cmap[1].bitshf) & upd->cmap[1].bitmsk)
2463
 
                     / (double) upd->cmap[1].bitmsk,
2464
 
    255.0 * (double) ((color >> upd->cmap[2].bitshf) & upd->cmap[2].bitmsk)
2465
 
                     / (double) upd->cmap[2].bitmsk,
2466
 
    255.0 * (double) ((color >> upd->cmap[3].bitshf) & upd->cmap[3].bitmsk)
2467
 
                     / (double) upd->cmap[3].bitmsk,
2468
 
    255.0 * (double) ((color >> upd->cmap[0].bitshf) & upd->cmap[0].bitmsk)
2469
 
                     / (double) upd->cmap[0].bitmsk,
2470
 
    255.0 * (double) prgb[0] / (double) gx_max_color_value,
2471
 
    255.0 * (double) prgb[1] / (double) gx_max_color_value,
2472
 
    255.0 * (double) prgb[2] / (double) gx_max_color_value);
2473
 
#endif
2474
 
 
2475
 
   return 0;
2476
 
}
2477
 
 
2478
 
/* ------------------------------------------------------------------- */
2479
 
/* upd_cmyk_kcolor: KCMY->KCMY-Index Mapping with Black Generation     */
2480
 
/* ------------------------------------------------------------------- */
2481
 
 
2482
 
static gx_color_index
2483
 
upd_cmyk_kcolor(gx_device *pdev, const gx_color_value cv[])
2484
 
{
2485
 
   const upd_p     upd = ((upd_device *)pdev)->upd;
2486
 
   gx_color_index  rv;
2487
 
   gx_color_value  black;
2488
 
 
2489
 
   gx_color_value c, m, y, k;
2490
 
   c = cv[0]; m = cv[1]; y = cv[2]; k = cv[3];
2491
 
 
2492
 
   if((c == m) && (m == y)) {
2493
 
 
2494
 
      black = c > k ? c : k;
2495
 
      rv = upd_truncate(upd,0,black);
2496
 
 
2497
 
   } else {
2498
 
 
2499
 
      if(k && !(c | m | y)) {
2500
 
         black = k;
2501
 
      } else {
2502
 
         black = c     < m ? c     : m;
2503
 
         black = black < y ? black : y;
2504
 
      }
2505
 
 
2506
 
      rv  = upd_truncate(upd,0,black) | upd_truncate(upd,1,c)
2507
 
          | upd_truncate(upd,2,m)     | upd_truncate(upd,3,y);
2508
 
 
2509
 
/* It might still become a "gx_no_color_value" due to truncation, thus: */
2510
 
 
2511
 
      if(rv == gx_no_color_index) rv ^= 1;
2512
 
   }
2513
 
 
2514
 
#if UPD_MESSAGES & UPD_M_MAPCALLS
2515
 
  errprintf(pdev->memory,
2516
 
"cmyk_kcolor: (%5.1f,%5.1f,%5.1f,%5.1f) : (%5.1f,%5.1f,%5.1f,%5.1f) : 0x%0*lx\n",
2517
 
   255.0 * (double) c / (double) gx_max_color_value,
2518
 
   255.0 * (double) m / (double) gx_max_color_value,
2519
 
   255.0 * (double) y / (double) gx_max_color_value,
2520
 
   255.0 * (double) k / (double) gx_max_color_value,
2521
 
   255.0 * (double) ((rv >> upd->cmap[1].bitshf) & upd->cmap[1].bitmsk)
2522
 
                 / (double) upd->cmap[1].bitmsk,
2523
 
   255.0 * (double) ((rv >> upd->cmap[2].bitshf) & upd->cmap[2].bitmsk)
2524
 
                 / (double) upd->cmap[2].bitmsk,
2525
 
   255.0 * (double) ((rv >> upd->cmap[3].bitshf) & upd->cmap[3].bitmsk)
2526
 
                 / (double) upd->cmap[3].bitmsk,
2527
 
   255.0 * (double) ((rv >> upd->cmap[0].bitshf) & upd->cmap[0].bitmsk)
2528
 
                 / (double) upd->cmap[0].bitmsk,
2529
 
   (pdev->color_info.depth + 3)>>2,rv);
2530
 
#endif
2531
 
 
2532
 
   return rv;
2533
 
}
2534
 
 
2535
 
/* ------------------------------------------------------------------- */
2536
 
/* upd_kcolor_rgb: Stored CMY+generated K back to a RGB                */
2537
 
/* ------------------------------------------------------------------- */
2538
 
 
2539
 
static int
2540
 
upd_kcolor_rgb(gx_device *pdev, gx_color_index color, gx_color_value prgb[3])
2541
 
{
2542
 
   const upd_p     upd = ((upd_device *)pdev)->upd;
2543
 
   gx_color_value c,m,y,k;
2544
 
 
2545
 
/*
2546
 
 * Expand to the Component-Values
2547
 
 */
2548
 
   k = upd_expand(upd,0,color);
2549
 
   c = upd_expand(upd,1,color);
2550
 
   m = upd_expand(upd,2,color);
2551
 
   y = upd_expand(upd,3,color);
2552
 
 
2553
 
/*
2554
 
 * Check for plain Gray-Values
2555
 
 */
2556
 
   if(!(c | m | y )) {
2557
 
 
2558
 
      prgb[2] = prgb[1] = prgb[0] = gx_max_color_value - k;
2559
 
 
2560
 
   } else {
2561
 
      prgb[0] = gx_max_color_value - c;
2562
 
      prgb[1] = gx_max_color_value - m;
2563
 
      prgb[2] = gx_max_color_value - y;
2564
 
   }
2565
 
 
2566
 
#if UPD_MESSAGES & UPD_M_MAPCALLS
2567
 
   errprintf(pdev->memory,
2568
 
    "kcolor_rgb: 0x%0*lx -> (%5.1f,%5.1f,%5.1f,%5.1f) -> (%5.1f,%5.1f,%5.1f,%5.1f) -> (%5.1f,%5.1f,%5.1f)\n",
2569
 
    (pdev->color_info.depth + 3)>>2,color,
2570
 
    255.0 * (double) ((color >> upd->cmap[1].bitshf) & upd->cmap[1].bitmsk)
2571
 
                     / (double) upd->cmap[1].bitmsk,
2572
 
    255.0 * (double) ((color >> upd->cmap[2].bitshf) & upd->cmap[2].bitmsk)
2573
 
                     / (double) upd->cmap[2].bitmsk,
2574
 
    255.0 * (double) ((color >> upd->cmap[3].bitshf) & upd->cmap[3].bitmsk)
2575
 
                     / (double) upd->cmap[3].bitmsk,
2576
 
    255.0 * (double) ((color >> upd->cmap[0].bitshf) & upd->cmap[0].bitmsk)
2577
 
                     / (double) upd->cmap[0].bitmsk,
2578
 
    255.0 * (double)   c     / (double) gx_max_color_value,
2579
 
    255.0 * (double)   m     / (double) gx_max_color_value,
2580
 
    255.0 * (double)   y     / (double) gx_max_color_value,
2581
 
    255.0 * (double)   k     / (double) gx_max_color_value,
2582
 
    255.0 * (double) prgb[0] / (double) gx_max_color_value,
2583
 
    255.0 * (double) prgb[1] / (double) gx_max_color_value,
2584
 
    255.0 * (double) prgb[2] / (double) gx_max_color_value);
2585
 
#endif
2586
 
 
2587
 
   return 0;
2588
 
}
2589
 
 
2590
 
/* ------------------------------------------------------------------- */
2591
 
/* upd_rgb_ovcolor: Create an KCMY-Index from RGB                      */
2592
 
/* ------------------------------------------------------------------- */
2593
 
 
2594
 
static gx_color_index
2595
 
upd_rgb_ovcolor(gx_device *pdev, const gx_color_value cv[])
2596
 
{
2597
 
   const upd_p     upd = ((upd_device *)pdev)->upd;
2598
 
   gx_color_index  rv;
2599
 
   gx_color_value  c,m,y,black;
2600
 
   gx_color_value r, g, b;
2601
 
   r = cv[0]; g = cv[1]; b = cv[2];
2602
 
   if((r == g) && (g == b)) {
2603
 
 
2604
 
      black  = gx_max_color_value - r;
2605
 
      rv     = upd_truncate(upd,0,black);
2606
 
      c = m = y = 0;
2607
 
 
2608
 
   } else {
2609
 
 
2610
 
      c = gx_max_color_value - r;
2611
 
      m = gx_max_color_value - g;
2612
 
      y = gx_max_color_value - b;
2613
 
 
2614
 
      black = c     < m ? c     : m;
2615
 
      black = black < y ? black : y;
2616
 
 
2617
 
      if(black != gx_max_color_value) {
2618
 
        float tmp,d;
2619
 
 
2620
 
        d   = (float)(gx_max_color_value - black);
2621
 
 
2622
 
        tmp = (float) (c-black) / d;
2623
 
        if(      0.0 > tmp) tmp = 0.0;
2624
 
        else if( 1.0 < tmp) tmp = 1.0;
2625
 
        c   = (gx_color_value)(tmp * gx_max_color_value + 0.499);
2626
 
 
2627
 
        tmp = (float) (m-black) / d;
2628
 
        if(      0.0 > tmp) tmp = 0.0;
2629
 
        else if( 1.0 < tmp) tmp = 1.0;
2630
 
        m   = (gx_color_value)(tmp * gx_max_color_value + 0.499);
2631
 
 
2632
 
        tmp = (float) (y-black) / d;
2633
 
        if(      0.0 > tmp) tmp = 0.0;
2634
 
        else if( 1.0 < tmp) tmp = 1.0;
2635
 
        y   = (gx_color_value)(tmp * gx_max_color_value + 0.499);
2636
 
 
2637
 
      } else {
2638
 
 
2639
 
        c = m = y = gx_max_color_value;
2640
 
 
2641
 
      }
2642
 
 
2643
 
      rv = upd_truncate(upd,0,black) | upd_truncate(upd,1,c) |
2644
 
           upd_truncate(upd,2,m)     | upd_truncate(upd,3,y);
2645
 
 
2646
 
/* It might still become a "gx_no_color_value" due to truncation, thus: */
2647
 
 
2648
 
      if(rv == gx_no_color_index) rv ^= 1;
2649
 
   }
2650
 
 
2651
 
#if UPD_MESSAGES & UPD_M_MAPCALLS
2652
 
  errprintf(pdev->memory,
2653
 
   "rgb_ovcolor: (%5.1f,%5.1f,%5.1f) : (%5.1f,%5.1f,%5.1f,%5.1f) : 0x%0*lx\n",
2654
 
   255.0 * (double) r / (double) gx_max_color_value,
2655
 
   255.0 * (double) g / (double) gx_max_color_value,
2656
 
   255.0 * (double) b / (double) gx_max_color_value,
2657
 
   255.0 * (double) ((rv >> upd->cmap[1].bitshf) & upd->cmap[1].bitmsk)
2658
 
                 / (double) upd->cmap[1].bitmsk,
2659
 
   255.0 * (double) ((rv >> upd->cmap[2].bitshf) & upd->cmap[2].bitmsk)
2660
 
                 / (double) upd->cmap[2].bitmsk,
2661
 
   255.0 * (double) ((rv >> upd->cmap[3].bitshf) & upd->cmap[3].bitmsk)
2662
 
                 / (double) upd->cmap[3].bitmsk,
2663
 
   255.0 * (double) ((rv >> upd->cmap[0].bitshf) & upd->cmap[0].bitmsk)
2664
 
                 / (double) upd->cmap[0].bitmsk,
2665
 
   (pdev->color_info.depth + 3)>>2,rv);
2666
 
#endif
2667
 
 
2668
 
   return rv;
2669
 
}
2670
 
 
2671
 
/* ------------------------------------------------------------------- */
2672
 
/* upd_rgb_novcolor: Create an KCMY-Index from RGB                      */
2673
 
/* ------------------------------------------------------------------- */
2674
 
 
2675
 
static gx_color_index
2676
 
upd_rgb_novcolor(gx_device *pdev, const gx_color_value cv[])
2677
 
{
2678
 
   const upd_p     upd = ((upd_device *)pdev)->upd;
2679
 
   gx_color_index  rv;
2680
 
   gx_color_value  c,m,y,black;
2681
 
   gx_color_value r, g, b;
2682
 
   r = cv[0]; g = cv[1]; b = cv[2];
2683
 
 
2684
 
   if((r == g) && (g == b)) {
2685
 
 
2686
 
      black  = gx_max_color_value - r;
2687
 
      rv     = upd_truncate(upd,0,black);
2688
 
      c = m = y = 0;
2689
 
 
2690
 
   } else {
2691
 
 
2692
 
      c = gx_max_color_value - r;
2693
 
      m = gx_max_color_value - g;
2694
 
      y = gx_max_color_value - b;
2695
 
 
2696
 
      black = c     < m ? c     : m;
2697
 
      black = black < y ? black : y;
2698
 
      c     = c - black;
2699
 
      m     = m - black;
2700
 
      y     = y - black;
2701
 
 
2702
 
      rv = upd_truncate(upd,0,black) | upd_truncate(upd,1,c) |
2703
 
           upd_truncate(upd,2,m)     | upd_truncate(upd,3,y);
2704
 
 
2705
 
/* It might still become a "gx_no_color_value" due to truncation, thus: */
2706
 
 
2707
 
      if(rv == gx_no_color_index) rv ^= 1;
2708
 
   }
2709
 
 
2710
 
#if UPD_MESSAGES & UPD_M_MAPCALLS
2711
 
  errprintf(pdev->memory,
2712
 
   "rgb_ovcolor: (%5.1f,%5.1f,%5.1f) : (%5.1f,%5.1f,%5.1f,%5.1f) : 0x%0*lx\n",
2713
 
   255.0 * (double) r / (double) gx_max_color_value,
2714
 
   255.0 * (double) g / (double) gx_max_color_value,
2715
 
   255.0 * (double) b / (double) gx_max_color_value,
2716
 
   255.0 * (double) ((rv >> upd->cmap[1].bitshf) & upd->cmap[1].bitmsk)
2717
 
                 / (double) upd->cmap[1].bitmsk,
2718
 
   255.0 * (double) ((rv >> upd->cmap[2].bitshf) & upd->cmap[2].bitmsk)
2719
 
                 / (double) upd->cmap[2].bitmsk,
2720
 
   255.0 * (double) ((rv >> upd->cmap[3].bitshf) & upd->cmap[3].bitmsk)
2721
 
                 / (double) upd->cmap[3].bitmsk,
2722
 
   255.0 * (double) ((rv >> upd->cmap[0].bitshf) & upd->cmap[0].bitmsk)
2723
 
                 / (double) upd->cmap[0].bitmsk,
2724
 
   (pdev->color_info.depth + 3)>>2,rv);
2725
 
#endif
2726
 
 
2727
 
   return rv;
2728
 
}
2729
 
 
2730
 
/* ------------------------------------------------------------------- */
2731
 
/* NOTE: Beyond this point only "uniprint"-special-items.              */
2732
 
/* ------------------------------------------------------------------- */
2733
 
 
2734
 
/* ------------------------------------------------------------------- */
2735
 
/* Truncate a gx_color_value to the desired number of bits.            */
2736
 
/* ------------------------------------------------------------------- */
2737
 
 
2738
 
static uint32_t
2739
 
upd_truncate(upd_pc upd,int i,gx_color_value v) {
2740
 
   const updcmap_pc cmap = upd->cmap + i;
2741
 
   int32_t           s; /* step size */
2742
 
   gx_color_value *p; /* value-pointer */
2743
 
 
2744
 
   if(0 == cmap->bits) {                          /* trivial case */
2745
 
 
2746
 
      v = 0;
2747
 
 
2748
 
   } else if(gx_color_value_bits > cmap->bits) { /* really truncate ? */
2749
 
 
2750
 
      p = cmap->code + ((cmap->bitmsk + 1) >> 1);
2751
 
      s =              ((cmap->bitmsk + 1) >> 2);
2752
 
/*
2753
 
 * Perform search in monotonic code-array
2754
 
 */
2755
 
      while(s > 0) {
2756
 
         if(v > *p) {           /* we're below */
2757
 
            p += s;
2758
 
         } else if(v < p[-1]) { /* we're ahead for sure */
2759
 
            p -= s;
2760
 
         } else {
2761
 
/* years ago, i knew what this was good for */
2762
 
            if((v-p[-1]) < (p[0]-v)) p -= 1;
2763
 
            break;
2764
 
         }
2765
 
         s >>= 1;
2766
 
      }
2767
 
      if((v-p[-1]) < (p[0]-v)) p -= 1;
2768
 
      v = p - cmap->code;
2769
 
   }
2770
 
 
2771
 
   if(!cmap->rise) v = cmap->bitmsk - v; /* Again reverse, if necessary */
2772
 
 
2773
 
   return ((uint32_t) v) << cmap->bitshf;
2774
 
}
2775
 
 
2776
 
/* ------------------------------------------------------------------- */
2777
 
/* upd_open_map: install the color-mapping                             */
2778
 
/* ------------------------------------------------------------------- */
2779
 
 
2780
 
static int
2781
 
upd_open_map(upd_device *udev)
2782
 
{
2783
 
   const upd_p      upd   = udev->upd;
2784
 
   int imap;
2785
 
 
2786
 
/** _always_ initialize crucial Values! */
2787
 
   for(imap = 0; UPD_CMAP_MAX > imap; ++imap) upd->cmap[imap].code   = NULL;
2788
 
   upd->ncomp = 0;
2789
 
 
2790
 
/** There should not be an error yet */
2791
 
   if(B_ERROR & upd->flags)    imap = 0;
2792
 
 
2793
 
/** Establish the xfer-Indices */
2794
 
   if(imap) {
2795
 
      for(imap = 0; UPD_CMAP_MAX > imap; ++imap) {
2796
 
         upd->cmap[imap].xfer = -1;
2797
 
         upd->cmap[imap].bits =  0;
2798
 
      }
2799
 
      switch(upd->choice[C_MAPPER]) {
2800
 
         case MAP_GRAY:
2801
 
            upd->cmap[0].xfer = FA_WXFER;
2802
 
         break;
2803
 
         case MAP_RGBW:
2804
 
            upd->cmap[0].xfer = FA_WXFER;
2805
 
            upd->cmap[1].xfer = FA_RXFER;
2806
 
            upd->cmap[2].xfer = FA_GXFER;
2807
 
            upd->cmap[3].xfer = FA_BXFER;
2808
 
         break;
2809
 
         case MAP_RGB:
2810
 
            upd->cmap[0].xfer = FA_RXFER;
2811
 
            upd->cmap[1].xfer = FA_GXFER;
2812
 
            upd->cmap[2].xfer = FA_BXFER;
2813
 
         break;
2814
 
         case MAP_CMYK:
2815
 
            upd->cmap[0].xfer = FA_KXFER;
2816
 
            upd->cmap[1].xfer = FA_CXFER;
2817
 
            upd->cmap[2].xfer = FA_MXFER;
2818
 
            upd->cmap[3].xfer = FA_YXFER;
2819
 
         break;
2820
 
         case MAP_CMYKGEN:
2821
 
            upd->cmap[0].xfer = FA_KXFER;
2822
 
            upd->cmap[1].xfer = FA_CXFER;
2823
 
            upd->cmap[2].xfer = FA_MXFER;
2824
 
            upd->cmap[3].xfer = FA_YXFER;
2825
 
         break;
2826
 
         case MAP_RGBOV:
2827
 
            upd->cmap[0].xfer = FA_KXFER;
2828
 
            upd->cmap[1].xfer = FA_CXFER;
2829
 
            upd->cmap[2].xfer = FA_MXFER;
2830
 
            upd->cmap[3].xfer = FA_YXFER;
2831
 
         break;
2832
 
         case MAP_RGBNOV:
2833
 
            upd->cmap[0].xfer = FA_KXFER;
2834
 
            upd->cmap[1].xfer = FA_CXFER;
2835
 
            upd->cmap[2].xfer = FA_MXFER;
2836
 
            upd->cmap[3].xfer = FA_YXFER;
2837
 
         break;
2838
 
         default:
2839
 
#if         UPD_MESSAGES & UPD_M_WARNING
2840
 
               if(upd_choice[C_MAPPER][0])
2841
 
                  errprintf(udev->memory,
2842
 
                     "upd_open_map: unsupported %s=%d\n",
2843
 
                     upd_choice[C_MAPPER][0],upd->choice[C_MAPPER]);
2844
 
               else
2845
 
                  errprintf(udev->memory,
2846
 
                     "upd_open_map: unsupported choce[%d]=%d\n",
2847
 
                     C_MAPPER,upd->choice[C_MAPPER]);
2848
 
#endif
2849
 
            imap = 0;
2850
 
         break;
2851
 
      }
2852
 
   }
2853
 
 
2854
 
/** The bit number sould be positive & fit into the storage */
2855
 
 
2856
 
   if(imap) { /* Check number of Bits & Shifts */
2857
 
 
2858
 
#if      UPD_MESSAGES & UPD_M_WARNING
2859
 
      uint32_t used = 0,bitmsk;
2860
 
#endif
2861
 
      bool success = true;
2862
 
 
2863
 
      for(imap = 0; UPD_CMAP_MAX > imap; ++imap) {
2864
 
         if(0 > upd->cmap[imap].xfer) continue;
2865
 
 
2866
 
         if((0                     > upd->int_a[IA_COMPBITS].data[imap])  ||
2867
 
            (gx_color_value_bits   < upd->int_a[IA_COMPBITS].data[imap])  ||
2868
 
            (0                     > upd->int_a[IA_COMPSHIFT].data[imap]) ||
2869
 
            (upd->int_a[IA_COMPBITS].data[imap] >
2870
 
             (udev->color_info.depth - upd->int_a[IA_COMPSHIFT].data[imap]))) {
2871
 
#if         UPD_MESSAGES & UPD_M_WARNING
2872
 
               errprintf(udev->memory,
2873
 
                  "upd_open_map: %d Bits << %d is illegal for %d. Component\n",
2874
 
                  upd->int_a[IA_COMPBITS].data[imap],
2875
 
                  upd->int_a[IA_COMPSHIFT].data[imap],imap+1);
2876
 
#endif
2877
 
 
2878
 
            success = false;
2879
 
 
2880
 
         } else {
2881
 
 
2882
 
            int         n;
2883
 
            const float *now;
2884
 
            float       last;
2885
 
 
2886
 
            if((NULL == upd->float_a[upd->cmap[imap].xfer].data) ||
2887
 
               (2    >  upd->float_a[upd->cmap[imap].xfer].size)   ) {
2888
 
               float *fp;
2889
 
               UPD_MM_DEL_PARAM(udev->memory, upd->float_a[upd->cmap[imap].xfer]);
2890
 
               UPD_MM_GET_ARRAY(udev->memory, fp,2);
2891
 
               fp[0] = 0.0;
2892
 
               fp[1] = 1.0;
2893
 
               upd->float_a[upd->cmap[imap].xfer].data = fp;
2894
 
               upd->float_a[upd->cmap[imap].xfer].size = 2;
2895
 
            }
2896
 
            n    = upd->float_a[upd->cmap[imap].xfer].size-1;
2897
 
            now  = upd->float_a[upd->cmap[imap].xfer].data;
2898
 
            last = now[n];
2899
 
 
2900
 
            if(     *now < last) { /* Rising */
2901
 
               last = *now++;
2902
 
               while(n--) {
2903
 
                 if(last >= *now) break;
2904
 
                 last = *now++;
2905
 
               }
2906
 
            } else if(*now > last) { /* Falling */
2907
 
               last = *now++;
2908
 
               while(n--) {
2909
 
                 if(last <= *now) break;
2910
 
                 last = *now++;
2911
 
               }
2912
 
            }                      /* Monotony-check */
2913
 
 
2914
 
            if(0 <= n) {
2915
 
#if            UPD_MESSAGES & UPD_M_WARNING
2916
 
               errprintf(udev->memory,
2917
 
                  "upd_open_map: %d. Component has non monoton Xfer\n",imap+1);
2918
 
#endif
2919
 
               success = false;
2920
 
 
2921
 
            } else {
2922
 
 
2923
 
#if            UPD_MESSAGES & UPD_M_WARNING
2924
 
 
2925
 
               bitmsk   = ((uint32_t) 1 << upd->int_a[IA_COMPBITS].data[imap]) -1;
2926
 
               bitmsk <<= upd->int_a[IA_COMPSHIFT].data[imap];
2927
 
 
2928
 
               if(used & bitmsk) errprintf(udev->memory,
2929
 
                  "upd_open_map: %d. Component overlaps with others\n",imap+1);
2930
 
 
2931
 
               used |= bitmsk;
2932
 
#endif
2933
 
            }
2934
 
         }
2935
 
      }
2936
 
 
2937
 
      if(!success) imap = 0;
2938
 
 
2939
 
   }             /* Check number of Bits */
2940
 
 
2941
 
/** Do the allocation */
2942
 
 
2943
 
   if(imap) {
2944
 
 
2945
 
      for(imap = 0; UPD_CMAP_MAX > imap; ++imap) {
2946
 
         if(0 > upd->cmap[imap].xfer) continue;
2947
 
 
2948
 
         upd->cmap[imap].bits     = upd->int_a[IA_COMPBITS].data[imap];
2949
 
         upd->cmap[imap].bitshf   = upd->int_a[IA_COMPSHIFT].data[imap];
2950
 
         upd->cmap[imap].bitmsk   = 1;
2951
 
         upd->cmap[imap].bitmsk <<= upd->cmap[imap].bits;
2952
 
         upd->cmap[imap].bitmsk  -= 1;
2953
 
         upd->cmap[imap].rise     =
2954
 
            upd->float_a[upd->cmap[imap].xfer].data[0] <
2955
 
            upd->float_a[upd->cmap[imap].xfer].data[
2956
 
               upd->float_a[upd->cmap[imap].xfer].size-1] ?
2957
 
            true : false;
2958
 
         upd->cmap[imap].code     = gs_malloc(udev->memory, upd->cmap[imap].bitmsk+1,
2959
 
             sizeof(upd->cmap[imap].code[0]),"upd/code");
2960
 
         if(!upd->cmap[imap].code) break;
2961
 
      }
2962
 
 
2963
 
      if(UPD_CMAP_MAX > imap) {
2964
 
 
2965
 
         imap = 0;
2966
 
 
2967
 
#if      UPD_MESSAGES & UPD_M_ERROR
2968
 
            errprintf(udev->memory,
2969
 
                      "upd_open_map: could not allocate code-arrays\n");
2970
 
#        endif
2971
 
 
2972
 
      }
2973
 
   }
2974
 
 
2975
 
/** then fill the code-arrays */
2976
 
 
2977
 
   if(imap) {
2978
 
/*
2979
 
 * Try making things easier: (than with stcolor)
2980
 
 *     normalize values to 0.0/1.0-Range
2981
 
 *     X-Axis:   Color-Values (implied)
2982
 
 *     Y-Values: Indices      (given)
2983
 
 */
2984
 
 
2985
 
      for(imap = 0; UPD_CMAP_MAX > imap; ++imap) {
2986
 
 
2987
 
         const updcmap_p cmap = upd->cmap + imap;
2988
 
         uint32_t ly,iy;
2989
 
         float ystep,xstep,fx,fy;
2990
 
 
2991
 
/*       Variables & Macro for Range-Normalization */
2992
 
         double offset,scale;
2993
 
#define  XFVAL(I) ((upd->float_a[cmap->xfer].data[I]-offset)*scale)
2994
 
 
2995
 
         if(0 > cmap->xfer) continue;
2996
 
 
2997
 
         cmap->code[cmap->bitmsk] = gx_max_color_value;
2998
 
 
2999
 
         if(!cmap->bits) continue;
3000
 
 
3001
 
         offset = upd->float_a[cmap->xfer].data[0];
3002
 
         if(     0.0 > offset) offset = 0.0;
3003
 
         else if(1.0 < offset) offset = 1.0;
3004
 
 
3005
 
         scale  = upd->float_a[cmap->xfer].data[upd->float_a[cmap->xfer].size-1];
3006
 
         if(     0.0 > scale ) scale  = 0.0;
3007
 
         else if(1.0 < scale ) scale  = 1.0;
3008
 
 
3009
 
         if(scale != offset) scale = 1.0 / (scale - offset);
3010
 
         else                scale = 0.0;
3011
 
 
3012
 
/*       interpolate */
3013
 
         ystep = (float) 1.0 / (float) cmap->bitmsk;
3014
 
         xstep = (float) 1.0 / (float)(upd->float_a[cmap->xfer].size - 1);
3015
 
 
3016
 
         iy = 0;
3017
 
         for(ly = 0; ly <= cmap->bitmsk; ++ly) {
3018
 
 
3019
 
            fy = ystep * ly; /* Target-Value */
3020
 
 
3021
 
            while(((iy+2) < upd->float_a[cmap->xfer].size) &&
3022
 
                  (fy > XFVAL(iy+1))) ++iy;
3023
 
 
3024
 
            fx  = iy + (fy - XFVAL(iy))/(XFVAL(iy+1) - XFVAL(iy));
3025
 
 
3026
 
            fx *= xstep * gx_max_color_value;
3027
 
 
3028
 
            fx  = fx < 0.0 ? 0.0 :
3029
 
                 (fx > gx_max_color_value ? gx_max_color_value : fx);
3030
 
 
3031
 
            cmap->code[ly] = (gx_color_value)fx;
3032
 
            if((fx - cmap->code[ly]) >= 0.5) cmap->code[ly] += 1;
3033
 
         }
3034
 
 
3035
 
#undef   XFVAL
3036
 
 
3037
 
      }
3038
 
   }
3039
 
 
3040
 
/** If we're ok, massage upd->ncomp */
3041
 
 
3042
 
   if(imap) {
3043
 
      switch(upd->choice[C_MAPPER]) {
3044
 
         case MAP_GRAY:
3045
 
           if(1 > imap) imap = 0;
3046
 
           upd->ncomp = 1;
3047
 
         break;
3048
 
         case MAP_RGBW: /* RGB->RGBW */
3049
 
           if(4 > imap) imap = 0;
3050
 
           upd->ncomp = 4;
3051
 
         break;
3052
 
         case MAP_RGB: /* Plain RGB */
3053
 
           if(3 > imap) imap = 0;
3054
 
           upd->ncomp = 3;
3055
 
         break;
3056
 
         case MAP_CMYK: /* Plain KCMY */
3057
 
           if(4 > imap) imap = 0;
3058
 
            upd->ncomp = 4;
3059
 
         break;
3060
 
         case MAP_CMYKGEN: /* KCMY with black-generation */
3061
 
           if(4 > imap) imap = 0;
3062
 
           upd->ncomp = 4;
3063
 
         break;
3064
 
         case MAP_RGBOV: /* RGB->KCMY with black-generation */
3065
 
           if(4 > imap) imap = 0;
3066
 
           upd->ncomp = 4;
3067
 
         break;
3068
 
         case MAP_RGBNOV: /* RGB->KCMY with black-generation */
3069
 
           if(4 > imap) imap = 0;
3070
 
           upd->ncomp = 4;
3071
 
         break;
3072
 
 
3073
 
         default:
3074
 
           imap = 0;
3075
 
#if        UPD_MESSAGES & UPD_M_WARNING
3076
 
              errprintf(udev->memory,
3077
 
                 "upd_open: Mapping %d unknown\n",upd->choice[C_MAPPER]);
3078
 
#endif
3079
 
 
3080
 
         break;
3081
 
      }
3082
 
   }
3083
 
 
3084
 
/** If unsuccesful, install the default routines */
3085
 
 
3086
 
   if(!imap) {
3087
 
      upd_close_map(udev);
3088
 
   } else {
3089
 
      upd->flags |= B_MAP;
3090
 
      upd_procs_map(udev);
3091
 
   }
3092
 
 
3093
 
   return imap ? 1 : -1;
3094
 
}
3095
 
 
3096
 
/* ------------------------------------------------------------------- */
3097
 
/* upd_procs_map: (de-) install the color-mapping-procedures           */
3098
 
/* ------------------------------------------------------------------- */
3099
 
 
3100
 
static int
3101
 
upd_procs_map(upd_device *udev)
3102
 
{
3103
 
   int imap;
3104
 
 
3105
 
   if( udev->upd &&
3106
 
      (udev->upd->flags & B_MAP)) imap = udev->upd->choice[C_MAPPER];
3107
 
   else                           imap = 0;
3108
 
 
3109
 
   switch(imap) {
3110
 
     case MAP_GRAY: /* Grayscale -> Grayscale */
3111
 
       set_dev_proc(udev,encode_color, upd_rgb_1color);
3112
 
       set_dev_proc(udev,decode_color, upd_1color_rgb);
3113
 
       set_dev_proc(udev,map_rgb_color, upd_rgb_1color);
3114
 
       set_dev_proc(udev,map_cmyk_color,gx_default_map_cmyk_color);
3115
 
       set_dev_proc(udev,map_color_rgb, upd_1color_rgb);
3116
 
     break;
3117
 
     case MAP_RGBW: /* RGB->RGBW */
3118
 
       set_dev_proc(udev,encode_color, upd_rgb_4color);
3119
 
       set_dev_proc(udev,decode_color, upd_4color_rgb);
3120
 
       set_dev_proc(udev,map_rgb_color, upd_rgb_4color);
3121
 
       set_dev_proc(udev,map_cmyk_color,gx_default_map_cmyk_color);
3122
 
       set_dev_proc(udev,map_color_rgb, upd_4color_rgb);
3123
 
     break;
3124
 
     case MAP_RGB: /* Plain RGB */
3125
 
       set_dev_proc(udev,encode_color, upd_rgb_3color);
3126
 
       set_dev_proc(udev,decode_color, upd_3color_rgb);
3127
 
       set_dev_proc(udev,map_rgb_color, upd_rgb_3color);
3128
 
       set_dev_proc(udev,map_cmyk_color,gx_default_map_cmyk_color);
3129
 
       set_dev_proc(udev,map_color_rgb, upd_3color_rgb);
3130
 
     break;
3131
 
     case MAP_CMYK: /* Plain KCMY */
3132
 
       set_dev_proc(udev,encode_color, upd_cmyk_icolor);
3133
 
       set_dev_proc(udev,decode_color, upd_icolor_rgb);
3134
 
       set_dev_proc(udev,map_rgb_color, gx_default_map_rgb_color);
3135
 
       set_dev_proc(udev,map_cmyk_color,upd_cmyk_icolor);
3136
 
       set_dev_proc(udev,map_color_rgb, upd_icolor_rgb);
3137
 
     break;
3138
 
     case MAP_CMYKGEN: /* KCMY with black-generation */
3139
 
       set_dev_proc(udev,encode_color, upd_cmyk_kcolor);
3140
 
       set_dev_proc(udev,decode_color, upd_kcolor_rgb);
3141
 
       set_dev_proc(udev,map_rgb_color, gx_default_map_rgb_color);
3142
 
       set_dev_proc(udev,map_cmyk_color,upd_cmyk_kcolor);
3143
 
       set_dev_proc(udev,map_color_rgb, upd_kcolor_rgb);
3144
 
     break;
3145
 
     case MAP_RGBOV: /* RGB -> KCMY with BG and UCR for CMYK-Output */
3146
 
       set_dev_proc(udev,encode_color, upd_rgb_ovcolor);
3147
 
       set_dev_proc(udev,decode_color, upd_ovcolor_rgb);
3148
 
       set_dev_proc(udev,map_rgb_color, upd_rgb_ovcolor);
3149
 
       set_dev_proc(udev,map_cmyk_color,gx_default_map_cmyk_color);
3150
 
       set_dev_proc(udev,map_color_rgb, upd_ovcolor_rgb);
3151
 
     break;
3152
 
     case MAP_RGBNOV: /* RGB -> KCMY with BG and UCR for CMY+K-Output */
3153
 
       set_dev_proc(udev,encode_color, upd_rgb_novcolor);
3154
 
       set_dev_proc(udev,decode_color, upd_novcolor_rgb);
3155
 
       set_dev_proc(udev,map_rgb_color, upd_rgb_novcolor);
3156
 
       set_dev_proc(udev,map_cmyk_color,gx_default_map_cmyk_color);
3157
 
       set_dev_proc(udev,map_color_rgb, upd_novcolor_rgb);
3158
 
     break;
3159
 
 
3160
 
     default:
3161
 
       set_dev_proc(udev,encode_color, gx_default_map_rgb_color);
3162
 
       set_dev_proc(udev,decode_color, gx_default_map_color_rgb);
3163
 
       set_dev_proc(udev,map_rgb_color, gx_default_map_rgb_color);
3164
 
       set_dev_proc(udev,map_cmyk_color,gx_default_map_cmyk_color);
3165
 
       set_dev_proc(udev,map_color_rgb, gx_default_map_color_rgb);
3166
 
     break;
3167
 
  }
3168
 
  return 0;
3169
 
 
3170
 
}
3171
 
 
3172
 
/* ------------------------------------------------------------------- */
3173
 
/* upd_close_map: remove color mapping                                 */
3174
 
/* ------------------------------------------------------------------- */
3175
 
 
3176
 
static int
3177
 
upd_close_map(upd_device *udev)
3178
 
{
3179
 
   const upd_p      upd   = udev->upd;
3180
 
   int imap;
3181
 
 
3182
 
   if(upd) {
3183
 
 
3184
 
      for(imap = 0; UPD_CMAP_MAX > imap; ++imap) {
3185
 
 
3186
 
         if(upd->cmap[imap].code)
3187
 
            gs_free(udev->memory, upd->cmap[imap].code,sizeof(upd->cmap[imap].code[0]),
3188
 
                upd->cmap[imap].bitmsk+1,"upd/code");
3189
 
         upd->cmap[imap].code   = NULL;
3190
 
 
3191
 
         upd->cmap[imap].bitmsk = 0;
3192
 
         upd->cmap[imap].bitshf = 0;
3193
 
         upd->cmap[imap].bits   = 0;
3194
 
         upd->cmap[imap].rise   = false;
3195
 
      }
3196
 
      upd->flags &= ~B_MAP;
3197
 
   }
3198
 
 
3199
 
   upd_procs_map(udev);
3200
 
 
3201
 
   return 0;
3202
 
}
3203
 
 
3204
 
/* ------------------------------------------------------------------- */
3205
 
/* Functions for the rendering of data                                 */
3206
 
/* ------------------------------------------------------------------- */
3207
 
 
3208
 
/**
3209
 
Inside the main-upd-type are a "valbuf" and some unidentified
3210
 
pointers. This stuff is used in conjunction with the rendering,
3211
 
which is the process of converting gx_color_indices into something
3212
 
suitable for the device.
3213
 
 
3214
 
*/
3215
 
 
3216
 
/* ------------------------------------------------------------------- */
3217
 
/* upd_open_render: Initialize rendering                               */
3218
 
/* ------------------------------------------------------------------- */
3219
 
 
3220
 
static void
3221
 
upd_open_render(upd_device *udev)
3222
 
{
3223
 
   const upd_p upd = udev->upd;
3224
 
   int  icomp;
3225
 
 
3226
 
/** Reset everything related to rendering */
3227
 
   upd->flags       &= ~B_RENDER;
3228
 
   upd->valbuf       = NULL;
3229
 
   upd->nvalbuf      = 0;
3230
 
   upd->render       = NULL;
3231
 
   upd->start_render = NULL;
3232
 
   for(icomp = 0; UPD_VALPTR_MAX > icomp; ++icomp) upd->valptr[icomp] = NULL;
3233
 
 
3234
 
   if( (B_BUF | B_MAP) ==
3235
 
      ((B_BUF | B_MAP | B_ERROR) & upd->flags)) {
3236
 
 
3237
 
/** Establish the renderingwidth in upd */
3238
 
      upd->rwidth = upd->gswidth;
3239
 
      if((0            < upd->ints[I_PWIDTH]) &&
3240
 
         (upd->gswidth > upd->ints[I_PWIDTH])   )
3241
 
          upd->rwidth  = upd->ints[I_PWIDTH];
3242
 
 
3243
 
/** Call the Render-specific Open-Function */
3244
 
      switch(upd->choice[C_RENDER]) {
3245
 
         case RND_FSCOMP:
3246
 
            upd_open_fscomp(udev);
3247
 
         break;
3248
 
         case RND_FSCMYK:
3249
 
            upd_open_fscmyk(udev);
3250
 
         break;
3251
 
         case RND_FSCMY_K:
3252
 
            upd_open_fscmy_k(udev);
3253
 
         break;
3254
 
         default:
3255
 
#if UPD_MESSAGES & UPD_M_WARNING
3256
 
            errprintf(udev->memory, "upd_open_render: Unknown rendering type %d\n",
3257
 
                upd->choice[C_RENDER]);
3258
 
#endif
3259
 
         break;
3260
 
      }
3261
 
   }
3262
 
 
3263
 
   if(B_RENDER != ((B_ERROR | B_RENDER) & upd->flags))
3264
 
      upd_close_render(udev);
3265
 
 
3266
 
   return;
3267
 
}
3268
 
 
3269
 
/* ------------------------------------------------------------------- */
3270
 
/* upd_close_render: Deinitialize rendering                            */
3271
 
/* ------------------------------------------------------------------- */
3272
 
 
3273
 
static void
3274
 
upd_close_render(upd_device *udev)
3275
 
{
3276
 
   const upd_p upd = udev->upd;
3277
 
 
3278
 
   if(upd) {
3279
 
      int icomp;
3280
 
 
3281
 
      if((upd->render == upd_fscomp) ||
3282
 
         (upd->render == upd_fscmyk)   )  upd_close_fscomp(udev);
3283
 
 
3284
 
      if((0 < upd->nvalbuf) && upd->valbuf)
3285
 
         gs_free(udev->memory, upd->valbuf,upd->nvalbuf,sizeof(upd->valbuf[0]),"upd/valbuf");
3286
 
      upd->valbuf  = NULL;
3287
 
      upd->nvalbuf = 0;
3288
 
 
3289
 
      upd->flags       &= ~B_RENDER;
3290
 
      upd->render       = NULL;
3291
 
      upd->start_render = NULL;
3292
 
      for(icomp = 0; UPD_VALPTR_MAX > icomp; ++icomp) upd->valptr[icomp] = NULL;
3293
 
 
3294
 
   }
3295
 
   return;
3296
 
}
3297
 
 
3298
 
/* ------------------------------------------------------------------- */
3299
 
/* upd_open_fscomp: Initialize Component-Floyd-Steinberg               */
3300
 
/* ------------------------------------------------------------------- */
3301
 
#if UPD_MESSAGES & UPD_M_FSBUF
3302
 
static int32_t fs_emin[UPD_VALPTR_MAX],fs_emax[UPD_VALPTR_MAX];
3303
 
#endif
3304
 
static void
3305
 
upd_open_fscomp(upd_device *udev)
3306
 
{
3307
 
   const upd_p upd = udev->upd;
3308
 
   int icomp,order[UPD_CMAP_MAX];
3309
 
 
3310
 
#if UPD_MESSAGES & UPD_M_FSBUF
3311
 
   for(icomp = 0; UPD_VALPTR_MAX < icomp; ++icomp)
3312
 
      fs_emin[icomp] = fs_emax[icomp] = 0;
3313
 
#endif
3314
 
 
3315
 
   icomp = upd->ncomp;
3316
 
 
3317
 
   if((0              >= icomp) ||
3318
 
      (UPD_VALPTR_MAX <  icomp) ||
3319
 
      (UPD_CMAP_MAX   <  icomp)   ) icomp      = 0;
3320
 
 
3321
 
/**
3322
 
This Version of the FS-algorithm works on the mapped components, but
3323
 
the printing-order might be different from the order dictated by the
3324
 
mapping-routines. The optional COMPORDER-Array is used for that. The
3325
 
initial test checks it's integrity.
3326
 
*/
3327
 
   if(icomp) {
3328
 
      if(upd->ncomp <= upd->int_a[IA_COMPORDER].size) { /* Reordering */
3329
 
         bool success = true;
3330
 
         for(icomp = 0; upd->ncomp > icomp; ++icomp) {
3331
 
            order[icomp] = upd->int_a[IA_COMPORDER].data[icomp];
3332
 
            if((0            >  order[icomp]) ||
3333
 
               (UPD_CMAP_MAX <= order[icomp])   ) {
3334
 
               success = false;
3335
 
#if UPD_MESSAGES & UPD_M_WARNING
3336
 
                  errprintf(udev->memory,
3337
 
                   "upd_open_fscomp: %d is illegal component-index\n",
3338
 
                   order[icomp]);
3339
 
#endif
3340
 
            }
3341
 
         }
3342
 
         if(!success) icomp = 0;
3343
 
      } else {                                          /* Default-Ordering */
3344
 
         for(icomp = 0; UPD_CMAP_MAX > icomp; ++icomp) order[icomp] = icomp;
3345
 
      }                                                 /* Ordering defined */
3346
 
   }
3347
 
 
3348
 
/**
3349
 
If anything was ok. up to now, memory get's allocated.
3350
 
*/
3351
 
   if(icomp) {
3352
 
 
3353
 
      for(icomp = 0; upd->ncomp > icomp; ++icomp) {
3354
 
         upd->valptr[icomp] = gs_malloc(udev->memory, 1,sizeof(updcomp_t),"upd/fscomp");
3355
 
         if(NULL == upd->valptr[icomp]) {
3356
 
#if UPD_MESSAGES & UPD_M_ERROR
3357
 
            errprintf(udev->memory,
3358
 
                      "upd_open_fscomp: could not allocate %d. updcomp\n",
3359
 
                      icomp);
3360
 
#endif
3361
 
            icomp = 0;
3362
 
            break;
3363
 
         }
3364
 
      }
3365
 
   }
3366
 
 
3367
 
   if(icomp) {
3368
 
      uint need;
3369
 
 
3370
 
      need  = (2 + upd->rwidth) * upd->ncomp;
3371
 
      upd->valbuf = gs_malloc(udev->memory, need,sizeof(upd->valbuf[0]),"upd/valbuf");
3372
 
 
3373
 
      if(upd->valbuf) {
3374
 
         upd->nvalbuf = need;
3375
 
         memset(upd->valbuf,0,need*sizeof(upd->valbuf[0]));
3376
 
      } else {
3377
 
#if UPD_MESSAGES & UPD_M_ERROR
3378
 
         errprintf(udev->memory,
3379
 
                   "upd_open_fscomp: could not allocate %u words for valbuf\n",
3380
 
                   need);
3381
 
#endif
3382
 
         icomp = 0;
3383
 
      }
3384
 
   }
3385
 
 
3386
 
/* Still happy? then compute component-values */
3387
 
 
3388
 
   if(icomp) {
3389
 
      for(icomp = 0; upd->ncomp > icomp; ++icomp) {
3390
 
 
3391
 
         const updcomp_p comp   = upd->valptr[icomp];
3392
 
         const int32_t     nsteps = upd->cmap[order[icomp]].bitmsk;
3393
 
         float ymin,ymax;
3394
 
         int32_t highmod,highval;
3395
 
         int i;
3396
 
 
3397
 
         comp->threshold = nsteps;
3398
 
         comp->spotsize  = nsteps;
3399
 
         comp->offset    = 0;
3400
 
         comp->scale     = 1;
3401
 
         comp->cmap      = order[icomp];
3402
 
         upd->cmap[comp->cmap].comp = icomp;
3403
 
         comp->bits      = upd->cmap[comp->cmap].bits;
3404
 
         comp->bitshf    = upd->cmap[comp->cmap].bitshf;
3405
 
         comp->bitmsk    = upd->cmap[comp->cmap].bitmsk;
3406
 
 
3407
 
         if(!nsteps) continue; /* A 0-Bit component is legal! */
3408
 
 
3409
 
         if(upd->cmap[comp->cmap].rise) {
3410
 
            ymin = upd->float_a[upd->cmap[comp->cmap].xfer].data[0];
3411
 
            ymax = upd->float_a[upd->cmap[comp->cmap].xfer].data[
3412
 
                      upd->float_a[upd->cmap[comp->cmap].xfer].size-1];
3413
 
         } else {
3414
 
            ymax = upd->float_a[upd->cmap[comp->cmap].xfer].data[0];
3415
 
            ymin = upd->float_a[upd->cmap[comp->cmap].xfer].data[
3416
 
                      upd->float_a[upd->cmap[comp->cmap].xfer].size-1];
3417
 
         }
3418
 
 
3419
 
         if(0.0 > ymin) {
3420
 
            ymin = 0.0;
3421
 
            if(0.0 > ymax) ymax = 1.0 / (float) (nsteps+1);
3422
 
         }
3423
 
         if(1.0 < ymax) ymax = 1.0;
3424
 
 
3425
 
         comp->spotsize = ((int32_t) 1 << 28) - 1;
3426
 
 
3427
 
         for(i = 0; i < 32; ++i) { /* Attempt Ideal */
3428
 
 
3429
 
            highval = (int32_t)((ymax-ymin) * (double) comp->spotsize + 0.5);
3430
 
 
3431
 
            if(!(highmod = highval % nsteps)) break; /* Gotcha */
3432
 
 
3433
 
            highval += nsteps - highmod;
3434
 
            comp->spotsize = (int32_t)((double) highval / (ymax-ymin) + 0.5);
3435
 
 
3436
 
            if(!(comp->spotsize % 2)) comp->spotsize++;
3437
 
 
3438
 
         }                         /* Attempt Ideal */
3439
 
 
3440
 
         comp->offset    = (int32_t)(ymin * (double) comp->spotsize + (double) 0.5);
3441
 
         comp->scale     = highval / nsteps;
3442
 
         comp->threshold = comp->spotsize / 2;
3443
 
 
3444
 
#if UPD_MESSAGES & UPD_M_SETUP
3445
 
         errprintf(udev->memory,
3446
 
             "Values for %d. Component after %d iterations\n",comp->cmap+1,i);
3447
 
         errprintf(udev->memory,
3448
 
             "steps:     %10ld, Bits: %d\n",(long) comp->bitmsk,comp->bits);
3449
 
         errprintf(udev->memory,
3450
 
             "xfer:      %10d Points, %s\n",
3451
 
             upd->float_a[upd->cmap[comp->cmap].xfer].size,
3452
 
             upd->cmap[comp->cmap].rise ? "rising" : "falling");
3453
 
         errprintf(udev->memory,
3454
 
             "offset:    %10d 0x%08x\n",comp->offset,comp->offset);
3455
 
         errprintf(udev->memory,
3456
 
             "scale:     %10d 0x%08x\n",comp->scale,comp->scale);
3457
 
         errprintf(udev->memory,
3458
 
             "threshold: %10d 0x%08x\n",comp->threshold,comp->threshold);
3459
 
         errprintf(udev->memory,
3460
 
             "spotsize:  %10d 0x%08x\n",comp->spotsize,comp->spotsize);
3461
 
#endif
3462
 
      }
3463
 
   }
3464
 
/**
3465
 
Optional Random Initialization of the value-Buffer
3466
 
*/
3467
 
   if(icomp && !(B_FSZERO & upd->flags)) {
3468
 
      for(icomp = 0; icomp < upd->ncomp; ++icomp) {
3469
 
         const updcomp_p comp = upd->valptr[icomp];
3470
 
         int i;
3471
 
         int32_t lv = INT32_MAX, hv = INT32_MIN, v;
3472
 
         float scale;
3473
 
         for(i = icomp; i < upd->nvalbuf; i += upd->ncomp) {
3474
 
            v = rand();
3475
 
            if(lv > v) lv = v;
3476
 
            if(hv < v) hv = v;
3477
 
            upd->valbuf[i] = v;
3478
 
         }
3479
 
         scale = (float) comp->threshold / (float) (hv - lv);
3480
 
         lv   += (int32_t)(comp->threshold / (2*scale));
3481
 
         for(i = icomp; i < upd->nvalbuf; i += upd->ncomp)
3482
 
            upd->valbuf[i] = (int32_t)(scale * (upd->valbuf[i] - lv));
3483
 
      }
3484
 
   }
3485
 
 
3486
 
/**
3487
 
The render-Routine acts as an indicator, which render-close is to use!
3488
 
*/
3489
 
   upd->render = upd_fscomp;
3490
 
 
3491
 
   if(icomp) upd->flags |=  B_RENDER;
3492
 
   else      upd->flags &= ~B_RENDER;
3493
 
 
3494
 
   return;
3495
 
}
3496
 
 
3497
 
/* ------------------------------------------------------------------- */
3498
 
/* upd_close_fscomp: Deinitialize Component-Floyd-Steinberg            */
3499
 
/* ------------------------------------------------------------------- */
3500
 
 
3501
 
static void
3502
 
upd_close_fscomp(upd_device *udev)
3503
 
{
3504
 
   const upd_p upd = udev->upd;
3505
 
   int icomp;
3506
 
 
3507
 
#if UPD_MESSAGES & UPD_M_FSBUF
3508
 
   if(upd && (upd->flags & B_RENDER)) {
3509
 
 
3510
 
      for(icomp = 0; icomp < upd->ncomp; ++icomp) {
3511
 
         updcomp_p comp = upd->valptr[icomp];
3512
 
         if(!comp) continue;
3513
 
         if(!comp->spotsize) continue;
3514
 
         errprintf(udev->memory,"%d. Component: %6.3f <= error <= %6.3f\n",
3515
 
             icomp+1,
3516
 
             (double) fs_emin[icomp] / (double) comp->spotsize,
3517
 
             (double) fs_emax[icomp] / (double) comp->spotsize);
3518
 
      }
3519
 
 
3520
 
   }
3521
 
#endif
3522
 
 
3523
 
   for(icomp = 0; UPD_VALPTR_MAX > icomp; ++icomp) {
3524
 
      if(!upd->valptr[icomp]) continue;
3525
 
      gs_free(udev->memory, upd->valptr[icomp],1,sizeof(updcomp_t),"upd/fscomp");
3526
 
      upd->valptr[icomp] = NULL;
3527
 
   }
3528
 
}
3529
 
 
3530
 
/* ------------------------------------------------------------------- */
3531
 
/* upd_fscomp: Apply Floyd-Steinberg to each component                 */
3532
 
/* ------------------------------------------------------------------- */
3533
 
 
3534
 
/**
3535
 
   With UPD_M_FSBUF Max/Min-Values for the Errors are computed
3536
 
*/
3537
 
#if   UPD_MESSAGES & UPD_M_FSBUF
3538
 
#define FS_M_ROWERR(I)                                        \
3539
 
           if(fs_emin[I] > rowerr[I]) fs_emin[I] = rowerr[I]; \
3540
 
           if(fs_emax[I] < rowerr[I]) fs_emax[I] = rowerr[I];
3541
 
#else
3542
 
#define FS_M_ROWERR(I) ;
3543
 
#endif
3544
 
/**
3545
 
   FS_GOAL computes the desired Pixel-Value
3546
 
*/
3547
 
#define FS_GOAL(Raw,I)                                                     \
3548
 
   pixel[I] = (int32_t)(Raw) * comp[I]->scale +    comp[I]->offset           \
3549
 
            + rowerr[I]  + colerr[I] -       ((colerr[I]+4)>>3);           \
3550
 
   if(         pixel[I] < 0)                    pixel[I] = 0;              \
3551
 
   else if(    pixel[I] >    comp[I]->spotsize) pixel[I] = comp[I]->spotsize;
3552
 
 
3553
 
/*
3554
 
 *    Distribute the error:   prev  now   next
3555
 
 *                                   X    7/16 Y
3556
 
 *                            3/16  5/16  1/16 Y+1
3557
 
 */
3558
 
#define FS_DIST(I)                                                    \
3559
 
   if(!first) rowerr[I-dir] += ((3*pixel[I]+8)>>4); /* 3/16 */        \
3560
 
              rowerr[I    ]  = ((5*pixel[I]  )>>4)  /* 5/16 */        \
3561
 
                             + (( colerr[I]+4)>>3); /* 1/16 (rest) */ \
3562
 
              colerr[I    ]  = pixel[I]             /* 8/16 (neu) */  \
3563
 
                             - ((5*pixel[I]  )>>4)                    \
3564
 
                             - ((3*pixel[I]+8)>>4);
3565
 
/**
3566
 
   S_FSTEP   adjusts the Indices (rowerr, bit and iword)
3567
 
*/
3568
 
#define S_FSTEP                                \
3569
 
   rowerr += dir;                              \
3570
 
   first   = false;                            \
3571
 
   if(0 > dir) { /* Reverse */                 \
3572
 
      if(!(bit <<= 1)) { bit = 0x01; ibyte--; }\
3573
 
   } else {      /* Forward */                 \
3574
 
      if(!(bit >>= 1)) { bit = 0x80; ibyte++; }\
3575
 
   }             /* Inc/Dec Bit */
3576
 
 
3577
 
static int
3578
 
upd_fscomp(upd_p upd)
3579
 
{
3580
 
   const updscan_p  scan    = upd->scnbuf[upd->yscnbuf & upd->scnmsk];
3581
 
   const updcomp_p *comp    = (updcomp_p *) upd->valptr;
3582
 
   int32_t *const     pixel  = upd->valbuf;
3583
 
   int32_t *const     colerr = pixel  + upd->ncomp;
3584
 
   int32_t           *rowerr = colerr + upd->ncomp;
3585
 
   int              pwidth = upd->rwidth;
3586
 
   int              dir,ibyte;
3587
 
   int              iblack,bblack,pxlset;
3588
 
   uint32_t       ci;
3589
 
   byte         bit;
3590
 
   bool         first = true;
3591
 
/*
3592
 
 * Erase the component-Data
3593
 
 */
3594
 
   switch(upd->ncomp) {
3595
 
     case 4:  memset(scan[3].bytes,0,upd->nbytes);
3596
 
     case 3:  memset(scan[2].bytes,0,upd->nbytes);
3597
 
              memset(scan[1].bytes,0,upd->nbytes);
3598
 
     default: memset(scan[0].bytes,0,upd->nbytes);
3599
 
   }
3600
 
/*
3601
 
 * determine the direction
3602
 
 */
3603
 
   if(upd->flags &   B_REVDIR) { /* This one reverse */
3604
 
 
3605
 
      if(upd->flags & B_YFLIP) {
3606
 
         dir     = upd->ncomp;
3607
 
         bit     = 0x80;
3608
 
         ibyte   = 0;
3609
 
      } else {
3610
 
         dir     =  -upd->ncomp;
3611
 
         rowerr +=   upd->ncomp * (pwidth-1);
3612
 
         bit     =   0x80 >>     ((pwidth-1) & 7);
3613
 
         ibyte   =                (pwidth-1) >> 3;
3614
 
      }
3615
 
 
3616
 
      if(!(upd->flags & B_FSWHITE)) {
3617
 
         upd_pxlfwd(upd);
3618
 
         while((0 < pwidth) && !upd_pxlget(upd)) pwidth--;
3619
 
      }
3620
 
 
3621
 
      upd_pxlrev(upd);
3622
 
 
3623
 
   } else {                       /* This one forward */
3624
 
 
3625
 
      if(upd->flags & B_YFLIP) {
3626
 
         dir     =  -upd->ncomp;
3627
 
         rowerr +=   upd->ncomp * (pwidth-1);
3628
 
         bit     =   0x80 >>     ((pwidth-1) & 7);
3629
 
         ibyte   =                (pwidth-1) >> 3;
3630
 
      } else {
3631
 
         dir     = upd->ncomp;
3632
 
         bit     = 0x80;
3633
 
         ibyte   = 0;
3634
 
      }
3635
 
 
3636
 
      if(!(upd->flags & B_FSWHITE)) {
3637
 
         upd_pxlrev(upd);
3638
 
         while((0 < pwidth) && !upd_pxlget(upd)) pwidth--;
3639
 
      }
3640
 
 
3641
 
      upd_pxlfwd(upd);
3642
 
 
3643
 
   }                              /* reverse or forward */
3644
 
/*
3645
 
 * Toggle Direction, if not fixed
3646
 
 */
3647
 
   if(!(upd->flags & B_FIXDIR)) upd->flags ^= B_REVDIR;
3648
 
/*
3649
 
 * Skip over leading white-space
3650
 
 */
3651
 
   if(!(upd->flags & B_FSWHITE)) {
3652
 
      upd_proc_pxlget((*fun)) = upd->pxlget;
3653
 
      byte             *ptr   = upd->pxlptr;
3654
 
      while((0 < pwidth) && !upd_pxlget(upd)) {
3655
 
         pwidth--;
3656
 
         fun = upd->pxlget;
3657
 
         ptr = upd->pxlptr;
3658
 
         S_FSTEP
3659
 
      }
3660
 
      upd->pxlget = fun;
3661
 
      upd->pxlptr = ptr;
3662
 
   }
3663
 
/*
3664
 
 * Set iblack, if black-reduction is active
3665
 
 */
3666
 
  iblack = -1;
3667
 
  bblack =  0;
3668
 
  if((4 == upd->ncomp) && (B_REDUCEK & upd->flags)) {
3669
 
    iblack = upd->cmap[0].comp;
3670
 
    bblack = 1<<iblack;
3671
 
  }
3672
 
/*
3673
 
 * Process all Pixels
3674
 
 */
3675
 
   first = true;
3676
 
   while(0 < pwidth--) {
3677
 
/*
3678
 
 *    Execute FS-Algorithm for each active component
3679
 
 */
3680
 
      pxlset = 0;
3681
 
      ci = upd_pxlget(upd);
3682
 
      switch(upd->ncomp) {
3683
 
         case 4:  FS_M_ROWERR(3)
3684
 
                  FS_GOAL(comp[3]->bitmsk & (ci >> comp[3]->bitshf),3)
3685
 
                  if(pixel[3] >  comp[3]->threshold) { /* "Fire" */
3686
 
                     pixel[3] -= comp[3]->spotsize;
3687
 
                      scan[3].bytes[ibyte] |= bit;
3688
 
                      pxlset  |= 8;
3689
 
                  }                                    /* "Fire" */
3690
 
                  FS_DIST(3)
3691
 
 
3692
 
         case 3:  FS_M_ROWERR(2)
3693
 
                  FS_GOAL(comp[2]->bitmsk & (ci >> comp[2]->bitshf),2)
3694
 
                  if(pixel[2] >  comp[2]->threshold) { /* "Fire" */
3695
 
                     pixel[2] -= comp[2]->spotsize;
3696
 
                      scan[2].bytes[ibyte] |= bit;
3697
 
                      pxlset  |= 4;
3698
 
                  }                                    /* "Fire" */
3699
 
                  FS_DIST(2)
3700
 
 
3701
 
                  FS_M_ROWERR(1)
3702
 
                  FS_GOAL(comp[1]->bitmsk & (ci >> comp[1]->bitshf),1)
3703
 
                  if(pixel[1] >  comp[1]->threshold) { /* "Fire" */
3704
 
                     pixel[1] -= comp[1]->spotsize;
3705
 
                      scan[1].bytes[ibyte] |= bit;
3706
 
                      pxlset  |= 2;
3707
 
                  }                                    /* "Fire" */
3708
 
                  FS_DIST(1)
3709
 
 
3710
 
         default: FS_M_ROWERR(0)
3711
 
                  FS_GOAL(comp[0]->bitmsk & (ci >> comp[0]->bitshf),0)
3712
 
                  if(pixel[0] >  comp[0]->threshold) { /* "Fire" */
3713
 
                     pixel[0] -= comp[0]->spotsize;
3714
 
                      scan[0].bytes[ibyte] |= bit;
3715
 
                      pxlset  |= 1;
3716
 
                  }                                    /* "Fire" */
3717
 
                  FS_DIST(0)
3718
 
      }
3719
 
/*
3720
 
 *    Black-Reduction
3721
 
 */
3722
 
      if(bblack) {
3723
 
        if(pxlset & bblack) pxlset |= 15;
3724
 
        switch(pxlset) {
3725
 
          case  0:
3726
 
          case  1:
3727
 
          case  2:
3728
 
          case  4:
3729
 
          case  8:
3730
 
          case  3:
3731
 
          case  5:
3732
 
          case  9:
3733
 
          case  6:
3734
 
          case 10:
3735
 
          case 12:
3736
 
            break;
3737
 
          default:
3738
 
            scan[0].bytes[ibyte]      &= ~bit;
3739
 
            scan[1].bytes[ibyte]      &= ~bit;
3740
 
            scan[2].bytes[ibyte]      &= ~bit;
3741
 
            scan[3].bytes[ibyte]      &= ~bit;
3742
 
            scan[iblack].bytes[ibyte] |=  bit;
3743
 
          break;
3744
 
        }
3745
 
      }
3746
 
/*
3747
 
 *    Adjust rowerr, bit & iword, depending on direction
3748
 
 */
3749
 
      S_FSTEP
3750
 
   }
3751
 
/*
3752
 
 * Finally call the limits-Routine
3753
 
 */
3754
 
   if(0 < upd->nlimits) upd_limits(upd,true);
3755
 
   return 0;
3756
 
}
3757
 
 
3758
 
/* ------------------------------------------------------------------- */
3759
 
/* upd_open_fscmyk: Initialize Component-Floyd-Steinberg               */
3760
 
/* ------------------------------------------------------------------- */
3761
 
 
3762
 
static void
3763
 
upd_open_fscmyk(upd_device *udev)
3764
 
{
3765
 
   const upd_p upd = udev->upd;
3766
 
 
3767
 
   upd_open_fscomp(udev);
3768
 
 
3769
 
   if((B_RENDER & upd->flags) &&
3770
 
      (4 == upd->ncomp) &&
3771
 
      (8 <= upd->cmap[0].bits) && (24 == upd->cmap[0].bitshf) &&
3772
 
      (8 <= upd->cmap[1].bits) && (16 == upd->cmap[1].bitshf) &&
3773
 
      (8 <= upd->cmap[2].bits) && ( 8 == upd->cmap[2].bitshf) &&
3774
 
      (8 <= upd->cmap[3].bits) && ( 0 == upd->cmap[3].bitshf)   ) {
3775
 
      upd->render = upd_fscmyk;
3776
 
   } else {
3777
 
      upd->flags &= ~B_RENDER;
3778
 
   }
3779
 
 
3780
 
}
3781
 
 
3782
 
/* ------------------------------------------------------------------- */
3783
 
/* upd_fscmyk: 32 Bit, K-CMY-Order Dithering                           */
3784
 
/* ------------------------------------------------------------------- */
3785
 
 
3786
 
static int
3787
 
upd_fscmyk(upd_p upd)
3788
 
{
3789
 
   const updscan_p  scan   = upd->scnbuf[upd->yscnbuf & upd->scnmsk];
3790
 
   int32_t *const     pixel  = upd->valbuf;
3791
 
   const updcomp_p *comp   = (updcomp_p *) upd->valptr;
3792
 
   int32_t *const     colerr = pixel  + 4;
3793
 
   int32_t           *rowerr = colerr + 4;
3794
 
   int32_t            pwidth = upd->rwidth;
3795
 
   int              dir,ibyte;
3796
 
   byte             bit,*data;
3797
 
   bool             first = false;
3798
 
/*
3799
 
 * Erase the component-Data
3800
 
 */
3801
 
   memset(scan[0].bytes,0,upd->nbytes);
3802
 
   memset(scan[1].bytes,0,upd->nbytes);
3803
 
   memset(scan[2].bytes,0,upd->nbytes);
3804
 
   memset(scan[3].bytes,0,upd->nbytes);
3805
 
 
3806
 
/*
3807
 
 * determine the direction
3808
 
 */
3809
 
   if(upd->flags &   B_REVDIR) { /* This one reverse */
3810
 
 
3811
 
      if(!(upd->flags & B_FSWHITE)) {
3812
 
         data = upd->gsscan;
3813
 
         while(0 < pwidth && !*(uint32_t *)data) pwidth--, data += 4;
3814
 
         if(0 >= pwidth) {
3815
 
            if(0 < upd->nlimits) upd_limits(upd,false);
3816
 
            return 0;
3817
 
         }
3818
 
      }
3819
 
 
3820
 
      data        = upd->gsscan + 4 * (upd->rwidth-1);
3821
 
 
3822
 
   } else {                          /* This one forward */
3823
 
 
3824
 
      if(!(upd->flags & B_FSWHITE)) {
3825
 
         data = upd->gsscan + 4 * (upd->rwidth-1);
3826
 
         while(0 < pwidth && !*(uint32_t *)data) pwidth--, data -= 4;
3827
 
         if(0 >= pwidth) {
3828
 
            if(0 < upd->nlimits) upd_limits(upd,false);
3829
 
            return 0;
3830
 
         }
3831
 
      }
3832
 
 
3833
 
      data        = upd->gsscan;
3834
 
 
3835
 
   }                              /* reverse or forward */
3836
 
/*
3837
 
 * Bits depend on FLIP & Direction
3838
 
 */
3839
 
   if(!(B_REVDIR & upd->flags) == !(B_YFLIP  & upd->flags)) {
3840
 
      dir         = 4;
3841
 
      bit         = 0x80;
3842
 
      ibyte       = 0;
3843
 
   } else {
3844
 
      dir         =  -4;
3845
 
      rowerr     +=   4 *             (upd->rwidth-1);
3846
 
      bit         =   0x80 >>        ((upd->rwidth-1) & 7);
3847
 
      ibyte       =                   (upd->rwidth-1) >> 3;
3848
 
   }
3849
 
 
3850
 
/*
3851
 
 * Toggle Direction, if not fixed
3852
 
 */
3853
 
   if(!(upd->flags & B_FIXDIR)) upd->flags ^= B_REVDIR;
3854
 
/*
3855
 
 * Skip over leading white-space
3856
 
 */
3857
 
   if(!(upd->flags & B_FSWHITE)) {
3858
 
      while(0 < pwidth && !*((uint32_t *)data)) {
3859
 
         pwidth--;
3860
 
         if(B_YFLIP  & upd->flags) data -= dir;
3861
 
         else                      data += dir;
3862
 
         S_FSTEP
3863
 
      }
3864
 
   }
3865
 
/*
3866
 
 * Process all Pixels
3867
 
 */
3868
 
   first = true;
3869
 
   while(0 < pwidth--) {
3870
 
/*
3871
 
 *    Compute the Black-Value first
3872
 
 */
3873
 
      FS_M_ROWERR(upd->cmap[0].comp) FS_GOAL(data[0],upd->cmap[0].comp);
3874
 
 
3875
 
/*
3876
 
 *    Decide wether this is a color value
3877
 
 */
3878
 
      if(data[1] || data[2] || data[3]) {
3879
 
 
3880
 
         FS_M_ROWERR(upd->cmap[1].comp) FS_GOAL(data[1],upd->cmap[1].comp)
3881
 
         FS_M_ROWERR(upd->cmap[2].comp) FS_GOAL(data[2],upd->cmap[2].comp)
3882
 
         FS_M_ROWERR(upd->cmap[3].comp) FS_GOAL(data[3],upd->cmap[3].comp)
3883
 
/*
3884
 
 *       if black fires, then all other components fire logically too
3885
 
 */
3886
 
         if(pixel[upd->cmap[0].comp] > comp[upd->cmap[0].comp]->threshold) {
3887
 
 
3888
 
            pixel[0] -= comp[0]->spotsize;
3889
 
            pixel[1] -= comp[1]->spotsize;
3890
 
            pixel[2] -= comp[2]->spotsize;
3891
 
            pixel[3] -= comp[3]->spotsize;
3892
 
            scan[upd->cmap[0].comp].bytes[ibyte] |= bit;
3893
 
 
3894
 
/*
3895
 
 *       if black is below threshold, only components with larger data-values
3896
 
 *       are allowed to fire
3897
 
 */
3898
 
         } else {                                 /* Restricted firing */
3899
 
 
3900
 
            if(( data[0] < data[1]) &&
3901
 
               (pixel[upd->cmap[1].comp] >
3902
 
                 comp[upd->cmap[1].comp]->threshold)) { /* "Fire" */
3903
 
                pixel[upd->cmap[1].comp] -= comp[upd->cmap[1].comp]->spotsize;
3904
 
                 scan[upd->cmap[1].comp].bytes[ibyte] |= bit;
3905
 
            }                                           /* "Fire" */
3906
 
 
3907
 
            if(( data[0] < data[2]) &&
3908
 
               (pixel[upd->cmap[2].comp] >
3909
 
                 comp[upd->cmap[2].comp]->threshold)) { /* "Fire" */
3910
 
                pixel[upd->cmap[2].comp] -= comp[upd->cmap[2].comp]->spotsize;
3911
 
                 scan[upd->cmap[2].comp].bytes[ibyte] |= bit;
3912
 
            }                                           /* "Fire" */
3913
 
 
3914
 
            if(( data[0] < data[3]) &&
3915
 
               (pixel[upd->cmap[3].comp] >
3916
 
                 comp[upd->cmap[3].comp]->threshold)) { /* "Fire" */
3917
 
                pixel[upd->cmap[3].comp] -= comp[upd->cmap[3].comp]->spotsize;
3918
 
                 scan[upd->cmap[3].comp].bytes[ibyte] |= bit;
3919
 
            }                                           /* "Fire" */
3920
 
 
3921
 
         }                                        /* Fire-Mode */
3922
 
 
3923
 
/*
3924
 
 * Handle Color-Errors
3925
 
 */
3926
 
         FS_DIST(upd->cmap[3].comp)
3927
 
         FS_DIST(upd->cmap[2].comp)
3928
 
         FS_DIST(upd->cmap[1].comp)
3929
 
 
3930
 
      } else if(pixel[upd->cmap[0].comp] > comp[upd->cmap[0].comp]->threshold) {
3931
 
                 scan[upd->cmap[0].comp].bytes[ibyte] |= bit;
3932
 
                pixel[upd->cmap[0].comp] -= comp[upd->cmap[0].comp]->spotsize;
3933
 
      }
3934
 
 
3935
 
      FS_DIST(upd->cmap[0].comp)
3936
 
/*
3937
 
 *    Adjust bit & iword, depending on direction
3938
 
 */
3939
 
      S_FSTEP
3940
 
      if(upd->flags & B_YFLIP) data -= dir;
3941
 
      else                     data += dir;
3942
 
   }
3943
 
/*
3944
 
 * Finally call the limits-Routine
3945
 
 */
3946
 
   if(0 < upd->nlimits) upd_limits(upd,true);
3947
 
   return 0;
3948
 
}
3949
 
 
3950
 
/* ------------------------------------------------------------------- */
3951
 
/* upd_open_fscmy_k: Initialize for CMY_K Printing                     */
3952
 
/* ------------------------------------------------------------------- */
3953
 
 
3954
 
static void
3955
 
upd_open_fscmy_k(upd_device *udev)
3956
 
{
3957
 
   const upd_p upd = udev->upd;
3958
 
 
3959
 
   upd_open_fscomp(udev);
3960
 
 
3961
 
   if((B_RENDER & upd->flags) &&
3962
 
      (4 == upd->ncomp)) {
3963
 
      upd->render = upd_fscmy_k;
3964
 
   } else {
3965
 
      upd->flags &= ~B_RENDER;
3966
 
   }
3967
 
 
3968
 
}
3969
 
 
3970
 
/* ------------------------------------------------------------------- */
3971
 
/* upd_fscmy_k: CMY_K rendering                                        */
3972
 
/* ------------------------------------------------------------------- */
3973
 
 
3974
 
static int
3975
 
upd_fscmy_k(upd_p upd)
3976
 
{
3977
 
   const updscan_p  scan    = upd->scnbuf[upd->yscnbuf & upd->scnmsk];
3978
 
   const updcomp_p *comp    = (updcomp_p *) upd->valptr;
3979
 
   int32_t *const     pixel  = upd->valbuf;
3980
 
   int32_t *const     colerr = pixel  + upd->ncomp;
3981
 
   int32_t           *rowerr = colerr + upd->ncomp;
3982
 
   int              pwidth = upd->rwidth;
3983
 
   int              dir,ibyte;
3984
 
   uint32_t       ci;
3985
 
   byte         bit;
3986
 
   bool         first = true;
3987
 
/*
3988
 
 * Erase the component-Data
3989
 
 */
3990
 
   memset(scan[3].bytes,0,upd->nbytes);
3991
 
   memset(scan[2].bytes,0,upd->nbytes);
3992
 
   memset(scan[1].bytes,0,upd->nbytes);
3993
 
   memset(scan[0].bytes,0,upd->nbytes);
3994
 
/*
3995
 
 * determine the direction
3996
 
 */
3997
 
   if(upd->flags &   B_REVDIR) { /* This one reverse */
3998
 
 
3999
 
      if(upd->flags & B_YFLIP) {
4000
 
         dir     = 4;
4001
 
         bit     = 0x80;
4002
 
         ibyte   = 0;
4003
 
      } else {
4004
 
         dir     =  -4;
4005
 
         rowerr +=   4 * (pwidth-1);
4006
 
         bit     =   0x80 >>     ((pwidth-1) & 7);
4007
 
         ibyte   =                (pwidth-1) >> 3;
4008
 
      }
4009
 
 
4010
 
      if(!(upd->flags & B_FSWHITE)) {
4011
 
         upd_pxlfwd(upd);
4012
 
         while((0 < pwidth) && !upd_pxlget(upd)) pwidth--;
4013
 
      }
4014
 
 
4015
 
      upd_pxlrev(upd);
4016
 
 
4017
 
   } else {                       /* This one forward */
4018
 
 
4019
 
      if(upd->flags & B_YFLIP) {
4020
 
         dir     =  -4;
4021
 
         rowerr +=   4          * (pwidth-1);
4022
 
         bit     =   0x80 >>     ((pwidth-1) & 7);
4023
 
         ibyte   =                (pwidth-1) >> 3;
4024
 
      } else {
4025
 
         dir     = 4;
4026
 
         bit     = 0x80;
4027
 
         ibyte   = 0;
4028
 
      }
4029
 
 
4030
 
      if(!(upd->flags & B_FSWHITE)) {
4031
 
         upd_pxlrev(upd);
4032
 
         while((0 < pwidth) && !upd_pxlget(upd)) pwidth--;
4033
 
      }
4034
 
 
4035
 
      upd_pxlfwd(upd);
4036
 
 
4037
 
   }                              /* reverse or forward */
4038
 
/*
4039
 
 * Toggle Direction, if not fixed
4040
 
 */
4041
 
   if(!(upd->flags & B_FIXDIR)) upd->flags ^= B_REVDIR;
4042
 
/*
4043
 
 * Skip over leading white-space
4044
 
 */
4045
 
   if(!(upd->flags & B_FSWHITE)) {
4046
 
      upd_proc_pxlget((*fun)) = upd->pxlget;
4047
 
      byte             *ptr   = upd->pxlptr;
4048
 
      while((0 < pwidth) && !upd_pxlget(upd)) {
4049
 
         pwidth--;
4050
 
         fun = upd->pxlget;
4051
 
         ptr = upd->pxlptr;
4052
 
         S_FSTEP
4053
 
      }
4054
 
      upd->pxlget = fun;
4055
 
      upd->pxlptr = ptr;
4056
 
   }
4057
 
/*
4058
 
 * Process all Pixels
4059
 
 */
4060
 
   first = true;
4061
 
   while(0 < pwidth--) {
4062
 
 
4063
 
/*    get the Pixel-Value */
4064
 
 
4065
 
      ci = upd_pxlget(upd);
4066
 
 
4067
 
/*    process all components */
4068
 
 
4069
 
      FS_M_ROWERR(0) FS_GOAL(comp[0]->bitmsk & (ci >> comp[0]->bitshf),0)
4070
 
      FS_M_ROWERR(1) FS_GOAL(comp[1]->bitmsk & (ci >> comp[1]->bitshf),1)
4071
 
      FS_M_ROWERR(2) FS_GOAL(comp[2]->bitmsk & (ci >> comp[2]->bitshf),2)
4072
 
      FS_M_ROWERR(3) FS_GOAL(comp[3]->bitmsk & (ci >> comp[3]->bitshf),3)
4073
 
 
4074
 
      if(pixel[0] >  comp[0]->threshold) { /* Black fires */
4075
 
 
4076
 
        pixel[0]             -= comp[0]->spotsize;
4077
 
        scan[0].bytes[ibyte] |= bit;
4078
 
 
4079
 
      } else {                             /* Colors may fire */
4080
 
 
4081
 
         if((pixel[1] <= comp[1]->threshold) ||
4082
 
            (pixel[2] <= comp[2]->threshold) ||
4083
 
            (pixel[3] <= comp[3]->threshold)   ) { /* Really a Color */
4084
 
 
4085
 
            if(pixel[1] >               comp[1]->threshold) {
4086
 
               pixel[1]              -= comp[1]->spotsize;
4087
 
                scan[1].bytes[ibyte] |= bit;
4088
 
            }
4089
 
 
4090
 
            if(pixel[2] >               comp[2]->threshold) {
4091
 
               pixel[2]              -= comp[2]->spotsize;
4092
 
                scan[2].bytes[ibyte] |= bit;
4093
 
            }
4094
 
 
4095
 
            if(pixel[3] >               comp[3]->threshold) {
4096
 
               pixel[3]              -= comp[3]->spotsize;
4097
 
                scan[3].bytes[ibyte] |= bit;
4098
 
            }
4099
 
 
4100
 
         } else {
4101
 
            pixel[1]              -= comp[1]->spotsize;
4102
 
            pixel[2]              -= comp[2]->spotsize;
4103
 
            pixel[3]              -= comp[3]->spotsize;
4104
 
            scan[0].bytes[ibyte] |= bit;
4105
 
         }
4106
 
      }
4107
 
 
4108
 
      FS_DIST(0)
4109
 
      FS_DIST(1)
4110
 
      FS_DIST(2)
4111
 
      FS_DIST(3)
4112
 
 
4113
 
/*
4114
 
 *    Adjust rowerr, bit & iword, depending on direction
4115
 
 */
4116
 
      S_FSTEP
4117
 
   }
4118
 
/*
4119
 
 * Finally call the limits-Routine
4120
 
 */
4121
 
   if(0 < upd->nlimits) upd_limits(upd,true);
4122
 
   return 0;
4123
 
}
4124
 
 
4125
 
/* ------------------------------------------------------------------- */
4126
 
/* upd_open_writer: Initialize rendering                               */
4127
 
/* ------------------------------------------------------------------- */
4128
 
 
4129
 
static int
4130
 
upd_open_writer(upd_device *udev)
4131
 
{
4132
 
   const upd_p upd                 = udev->upd;
4133
 
   bool        success             = true;
4134
 
 
4135
 
/** Reset the crucial values */
4136
 
   upd->start_writer = NULL;
4137
 
   upd->writer       = NULL;
4138
 
   upd->scnbuf       = NULL;
4139
 
   upd->nscnbuf      = 0;
4140
 
   upd->nbytes       = 0;
4141
 
   upd->nlimits      = 0;
4142
 
   upd->outbuf       = NULL;
4143
 
   upd->noutbuf      = 0;
4144
 
 
4145
 
/** Rendering should be succesfully initialized */
4146
 
   if(B_RENDER != ((B_RENDER | B_ERROR) & upd->flags))
4147
 
      success = false;
4148
 
 
4149
 
/** Create number of components */
4150
 
   upd->ocomp = upd->ncomp;
4151
 
   if(0 < upd->ints[I_OCOMP]) upd->ocomp = upd->ints[I_OCOMP];
4152
 
 
4153
 
/** Massage some Parameters */
4154
 
   if(success) {
4155
 
 
4156
 
/*    Make sure, that Pass & Pin-Numbers are at least 1 */
4157
 
      if(1 >  upd->ints[I_NYPASS]) upd->ints[I_NYPASS] = 1;
4158
 
      if(1 >  upd->ints[I_NXPASS]) upd->ints[I_NXPASS] = 1;
4159
 
      if(1 >  upd->ints[I_PINS2WRITE]) upd->ints[I_PINS2WRITE] = 1;
4160
 
 
4161
 
      if((upd->ints[I_NXPASS] * upd->ints[I_NYPASS]) > upd->ints[I_NPASS])
4162
 
         upd->ints[I_NPASS] = upd->ints[I_NXPASS] * upd->ints[I_NYPASS];
4163
 
 
4164
 
/*    Create Default noWeave-Feeds */
4165
 
 
4166
 
      if(upd->ints[I_NPASS] > upd->int_a[IA_STD_DY].size) {
4167
 
         int ix,iy,*ip;
4168
 
         UPD_MM_DEL_PARAM(udev->memory, upd->int_a[IA_STD_DY]);
4169
 
         UPD_MM_GET_ARRAY(udev->memory, ip,upd->ints[I_NPASS]);
4170
 
         upd->int_a[IA_STD_DY].data = ip;
4171
 
         upd->int_a[IA_STD_DY].size = upd->ints[I_NPASS];
4172
 
 
4173
 
         for(iy = 1; iy < upd->ints[I_NYPASS]; ++iy) {
4174
 
            for(ix = 1; ix < upd->ints[I_NXPASS]; ++ix) *ip++ = 0;
4175
 
            *ip++ = 1;
4176
 
         }
4177
 
         for(ix = 1; ix < upd->ints[I_NXPASS]; ++ix) *ip++ = 0;
4178
 
         *ip = upd->ints[I_NYPASS] * upd->ints[I_PINS2WRITE]
4179
 
             - upd->ints[I_NYPASS] + 1;
4180
 
 
4181
 
         upd->ints[I_BEG_Y] = 0;
4182
 
         upd->ints[I_END_Y] = upd->ints[I_PHEIGHT] ?
4183
 
                              upd->ints[I_PHEIGHT] : upd->gsheight;
4184
 
      }
4185
 
 
4186
 
/*    Adjust BEG_Y */
4187
 
      if(0 >= upd->ints[I_BEG_Y]) {
4188
 
         if(0 <  upd->int_a[IA_BEG_DY].size) {
4189
 
            int i,sum = 0;
4190
 
            for(i = 0; i < upd->int_a[IA_BEG_DY].size; ++i)
4191
 
               sum +=  upd->int_a[IA_BEG_DY].data[i];
4192
 
            upd->ints[I_BEG_Y] = sum;
4193
 
         } else {
4194
 
            upd->ints[I_BEG_Y] = 0;
4195
 
         }
4196
 
      }
4197
 
 
4198
 
/*    Adjust END_Y */
4199
 
/*    Arrgh, I knew, why I refused to provide defaults for crucial */
4200
 
/*    parameters in uniprint. But o.k. it's nice for size-changing */
4201
 
/*    PostScript-Code. Nevertheless, it's still not perfect.       */
4202
 
 
4203
 
      if(0 >= upd->int_a[IA_ENDTOP].size ||
4204
 
         0 >= upd->int_a[IA_END_DY].size   ) upd->ints[I_END_Y] =
4205
 
         upd->ints[I_PHEIGHT] ? upd->ints[I_PHEIGHT] : upd->gsheight;
4206
 
 
4207
 
      if(0 >= upd->ints[I_END_Y]) upd->ints[I_END_Y] = upd->ints[I_PHEIGHT] ?
4208
 
        upd->ints[I_PHEIGHT] : upd->gsheight;
4209
 
 
4210
 
/*    Create Default X-Passes */
4211
 
 
4212
 
      if(0 >= upd->int_a[IA_STD_IX].size) {
4213
 
         int ix,i,*ip;
4214
 
         UPD_MM_DEL_PARAM(udev->memory, upd->int_a[IA_STD_IX]);
4215
 
         UPD_MM_GET_ARRAY(udev->memory, ip,upd->int_a[IA_STD_DY].size);
4216
 
         upd->int_a[IA_STD_IX].data = ip;
4217
 
         upd->int_a[IA_STD_IX].size = upd->int_a[IA_STD_DY].size;
4218
 
 
4219
 
         for(i = 0, ix = 0; i < upd->int_a[IA_STD_IX].size; ++i) {
4220
 
            *ip++ = ix++;
4221
 
            if(ix == upd->ints[I_NXPASS]) ix = 0;
4222
 
         }
4223
 
      }
4224
 
 
4225
 
      if((0 >= upd->int_a[IA_BEG_IX].size) &&
4226
 
         (0 <  upd->int_a[IA_BEG_DY].size)   ) {
4227
 
         int ix,i,*ip;
4228
 
         UPD_MM_DEL_PARAM(udev->memory, upd->int_a[IA_BEG_IX]);
4229
 
         UPD_MM_GET_ARRAY(udev->memory, ip,upd->int_a[IA_BEG_DY].size);
4230
 
         upd->int_a[IA_BEG_IX].data = ip;
4231
 
         upd->int_a[IA_BEG_IX].size = upd->int_a[IA_BEG_DY].size;
4232
 
 
4233
 
         for(i = 0, ix = 0; i < upd->int_a[IA_BEG_IX].size; ++i) {
4234
 
            *ip++ = ix++;
4235
 
            if(ix == upd->ints[I_NXPASS]) ix = 0;
4236
 
         }
4237
 
      }
4238
 
 
4239
 
      if((0 >= upd->int_a[IA_END_IX].size) &&
4240
 
         (0 <  upd->int_a[IA_END_DY].size)   ) {
4241
 
         int ix,i,*ip;
4242
 
         UPD_MM_DEL_PARAM(udev->memory, upd->int_a[IA_END_IX]);
4243
 
         UPD_MM_GET_ARRAY(udev->memory, ip,upd->int_a[IA_END_DY].size);
4244
 
         upd->int_a[IA_END_IX].data = ip;
4245
 
         upd->int_a[IA_END_IX].size = upd->int_a[IA_END_DY].size;
4246
 
 
4247
 
         for(i = 0, ix = 0; i < upd->int_a[IA_END_IX].size; ++i) {
4248
 
            *ip++ = ix++;
4249
 
            if(ix == upd->ints[I_NXPASS]) ix = 0;
4250
 
         }
4251
 
      }
4252
 
   }
4253
 
 
4254
 
   if(upd->ints[I_NPASS] > upd->int_a[IA_STD_DY].size) {
4255
 
#if UPD_MESSAGES & UPD_M_WARNING
4256
 
      errprintf(udev->memory,
4257
 
        "upd_open_writer: Only %d instead of %d normal Feeds\n",
4258
 
        (int) upd->int_a[IA_STD_DY].size,upd->ints[I_NPASS]);
4259
 
#endif
4260
 
      success = false;
4261
 
 
4262
 
   } else if(upd->int_a[IA_STD_IX].size < upd->int_a[IA_STD_DY].size) {
4263
 
#if UPD_MESSAGES & UPD_M_WARNING
4264
 
      errprintf(udev->memory,
4265
 
        "upd_open_writer: Only %d instead of %d normal Xstarts\n",
4266
 
        (int) upd->int_a[IA_STD_IX].size,
4267
 
        (int) upd->int_a[IA_STD_DY].size);
4268
 
#endif
4269
 
      success = false;
4270
 
   }
4271
 
 
4272
 
/** The sum of Values in STD_DY should equal NYPASS * PINS2WRITE (diagnostic) */
4273
 
 
4274
 
#if UPD_MESSAGES & UPD_M_WARNING
4275
 
   if(success) {
4276
 
      int i,sum = 0;
4277
 
      for(i = 0; upd->ints[I_NPASS] > i; ++i)
4278
 
         sum += upd->int_a[IA_STD_DY].data[i];
4279
 
      if((upd->ints[I_NYPASS]*upd->ints[I_PINS2WRITE]) != sum)
4280
 
         errprintf(udev->memory,
4281
 
         "upd_open_writer: Sum of normal Feeds is %d rather than %d\n",
4282
 
         sum,upd->ints[I_NYPASS]*upd->ints[I_PINS2WRITE]);
4283
 
   }
4284
 
#endif
4285
 
 
4286
 
   if(upd->int_a[IA_BEG_IX].size < upd->int_a[IA_BEG_DY].size) {
4287
 
#if UPD_MESSAGES & UPD_M_WARNING
4288
 
      errprintf(udev->memory,
4289
 
        "upd_open_writer: Only %d instead of %d initial Xstarts\n",
4290
 
        (int) upd->int_a[IA_BEG_IX].size,
4291
 
        (int) upd->int_a[IA_BEG_DY].size);
4292
 
#endif
4293
 
      success = false;
4294
 
   }
4295
 
 
4296
 
   if(upd->int_a[IA_BEGBOT].size < upd->int_a[IA_BEG_DY].size) {
4297
 
#if UPD_MESSAGES & UPD_M_WARNING
4298
 
      errprintf(udev->memory,
4299
 
        "upd_open_writer: Only %d instead of %d initial Pins\n",
4300
 
        (int) upd->int_a[IA_BEGBOT].size,
4301
 
        (int) upd->int_a[IA_BEG_DY].size);
4302
 
#endif
4303
 
      success = false;
4304
 
 
4305
 
   } else {
4306
 
 
4307
 
      int i;
4308
 
      for(i = 0; i < upd->int_a[IA_BEG_DY].size; ++i)
4309
 
         if((upd->int_a[IA_BEGBOT].data[i] > upd->ints[I_PINS2WRITE]) ||
4310
 
            (upd->int_a[IA_BEGBOT].data[i] < 0                      )   ) break;
4311
 
 
4312
 
      if(i < upd->int_a[IA_BEG_DY].size) {
4313
 
#if UPD_MESSAGES & UPD_M_WARNING
4314
 
         errprintf(udev->memory,
4315
 
           "upd_open_writer: Only %d is invalid initial Pins\n",
4316
 
           upd->int_a[IA_BEGBOT].data[i]);
4317
 
#endif
4318
 
         success = false;
4319
 
      }
4320
 
   }
4321
 
 
4322
 
/** The sum of Values in BEG_DY should equal BEG_Y */
4323
 
 
4324
 
#if UPD_MESSAGES & UPD_M_WARNING
4325
 
   if(success) {
4326
 
      int i,sum = 0;
4327
 
      for(i = 0;  upd->int_a[IA_BEG_DY].size > i; ++i)
4328
 
         sum += upd->int_a[IA_BEG_DY].data[i];
4329
 
      if(upd->ints[I_BEG_Y] != sum)
4330
 
         errprintf(udev->memory,
4331
 
         "upd_open_writer: Sum of initial Feeds is %d rather than %d\n",
4332
 
         sum,upd->ints[I_BEG_Y]);
4333
 
   }
4334
 
#endif
4335
 
 
4336
 
   if(upd->int_a[IA_END_IX].size < upd->int_a[IA_END_DY].size) {
4337
 
#if UPD_MESSAGES & UPD_M_WARNING
4338
 
      errprintf(udev->memory,
4339
 
        "upd_open_writer: Only %d instead of %d final Xstarts\n",
4340
 
        (int) upd->int_a[IA_END_IX].size,
4341
 
        (int) upd->int_a[IA_END_DY].size);
4342
 
#endif
4343
 
      success = false;
4344
 
   }
4345
 
 
4346
 
   if(upd->int_a[IA_ENDTOP].size < upd->int_a[IA_END_DY].size) {
4347
 
#if UPD_MESSAGES & UPD_M_WARNING
4348
 
      errprintf(udev->memory,
4349
 
        "upd_open_writer: Only %d instead of %d Final Pins\n",
4350
 
        (int) upd->int_a[IA_ENDTOP].size,
4351
 
        (int) upd->int_a[IA_END_DY].size);
4352
 
#endif
4353
 
      success = false;
4354
 
 
4355
 
   } else {
4356
 
 
4357
 
      int i;
4358
 
      for(i = 0; i < upd->int_a[IA_END_DY].size; ++i)
4359
 
         if((upd->int_a[IA_ENDTOP].data[i] > upd->ints[I_PINS2WRITE]) ||
4360
 
            (upd->int_a[IA_ENDTOP].data[i] < 0                      )   ) break;
4361
 
 
4362
 
      if(i < upd->int_a[IA_END_DY].size) {
4363
 
#if UPD_MESSAGES & UPD_M_WARNING
4364
 
         errprintf(udev->memory,
4365
 
           "upd_open_writer: Only %d is invalid initial Pins\n",
4366
 
           upd->int_a[IA_ENDTOP].data[i]);
4367
 
#endif
4368
 
         success = false;
4369
 
      }
4370
 
   }
4371
 
 
4372
 
/** SA_SETCOMP must be valid, if present */
4373
 
   if((0 < upd->string_a[SA_SETCOMP].size) &&
4374
 
      (upd->ocomp > upd->string_a[SA_SETCOMP].size)) {
4375
 
#if UPD_MESSAGES & UPD_M_WARNING
4376
 
      errprintf(udev->memory,
4377
 
         "upd_open_writer: Only %d SETCOMP-Commands (%d required)\n",
4378
 
         (int) upd->string_a[SA_SETCOMP].size,upd->ocomp);
4379
 
#endif
4380
 
      success = false;
4381
 
   }
4382
 
 
4383
 
/** Determine required number of scan-Buffers */
4384
 
 
4385
 
   if(success) { /* Compute nscnbuf */
4386
 
      int32_t want,use;
4387
 
 
4388
 
      want  = upd->ints[I_NYPASS];
4389
 
      want *= upd->ints[I_PINS2WRITE];
4390
 
 
4391
 
      if(upd->ints[I_NSCNBUF] > want) want = upd->ints[I_NSCNBUF];
4392
 
 
4393
 
      if(1 > want)                         want = 1;
4394
 
 
4395
 
      for(use = 1; 0 < use; use <<= 1) if(use > want) break;
4396
 
 
4397
 
      if(use <= INT_MAX) upd->nscnbuf = upd->ints[I_NSCNBUF] = use;
4398
 
      else               success      = false;
4399
 
 
4400
 
   }                /* Compute nscnbuf */
4401
 
 
4402
 
/** Determine number of words in scan-buffers */
4403
 
 
4404
 
   if(success) { /* Compute pwidth, scnmsk, nbytes, pheight */
4405
 
 
4406
 
      if(0 < upd->ints[I_PWIDTH]) upd->pwidth = upd->ints[I_PWIDTH];
4407
 
      else                        upd->pwidth = upd->gswidth;
4408
 
 
4409
 
      upd->nbytes  = (upd->pwidth+CHAR_BIT*sizeof(upd->scnbuf[0]->bytes[0]) - 1)
4410
 
            /                   (CHAR_BIT*sizeof(upd->scnbuf[0]->bytes[0]));
4411
 
 
4412
 
      upd->scnmsk  = upd->nscnbuf - 1;
4413
 
 
4414
 
      if(0 < upd->ints[I_PHEIGHT]) upd->pheight = upd->ints[I_PHEIGHT];
4415
 
      else                         upd->pheight = upd->gsheight;
4416
 
 
4417
 
   }             /* Compute pwidth, scnmsk, nbytes */
4418
 
 
4419
 
/** Call the writer-specific open-function */
4420
 
 
4421
 
   if(success) { /* Determine sizes */
4422
 
      switch(upd->choice[C_FORMAT]) {
4423
 
         case FMT_RAS:
4424
 
            if(0 > upd_open_rascomp(udev)) success = false;
4425
 
         break;
4426
 
         case FMT_EPSON:
4427
 
            if(0 > upd_open_wrtescp(udev)) success = false;
4428
 
         break;
4429
 
         case FMT_ESCP2Y:
4430
 
         case FMT_ESCP2XY:
4431
 
         case FMT_ESCNMY: /* (GR) */
4432
 
            if(0 > upd_open_wrtescp2(udev)) success = false;
4433
 
         break;
4434
 
         case FMT_RTL:
4435
 
            if(0 > upd_open_wrtrtl(udev))   success = false;
4436
 
         break;
4437
 
         case FMT_CANON: /* (hr) */
4438
 
            if(0 > upd_open_wrtcanon(udev)) success = false;
4439
 
         break;
4440
 
         default:
4441
 
            success = false;
4442
 
#if UPD_MESSAGES & UPD_M_WARNING
4443
 
            errprintf(udev->memory,"upd_open_writer: Unknown writer-type %d\n",
4444
 
                upd->choice[C_FORMAT]);
4445
 
#endif
4446
 
         break;
4447
 
      }
4448
 
   }             /* Determine sizes*/
4449
 
 
4450
 
/** Allocate the Outputbuffer */
4451
 
   if(success && (0 < upd->noutbuf)) { /* Allocate outbuf */
4452
 
      upd->outbuf = gs_malloc(udev->memory, upd->noutbuf,sizeof(upd->outbuf[0]),"upd/outbuf");
4453
 
      if(!upd->outbuf) success = false;
4454
 
   }                                   /* Allocate outbuf */
4455
 
 
4456
 
/** Allocate the desired scan-buffer-pointers */
4457
 
   if(success) {
4458
 
      upd->scnbuf = gs_malloc(udev->memory, upd->nscnbuf,sizeof(upd->scnbuf[0]),"upd/scnbuf");
4459
 
      if(NULL == upd->scnbuf) {
4460
 
         success = false;
4461
 
      } else {
4462
 
         int ibuf;
4463
 
         for(ibuf = 0; ibuf < upd->nscnbuf; ++ibuf) {
4464
 
            if(success) upd->scnbuf[ibuf] =
4465
 
               gs_malloc(udev->memory, upd->ocomp,sizeof(upd->scnbuf[0][0]),"upd/scnbuf[]");
4466
 
            else upd->scnbuf[ibuf] = NULL;
4467
 
 
4468
 
            if(!upd->scnbuf[ibuf]) {
4469
 
               success = false;
4470
 
            } else {
4471
 
               int icomp;
4472
 
               for(icomp = 0; icomp < upd->ocomp; ++icomp) {
4473
 
                  if(success) upd->scnbuf[ibuf][icomp].bytes =
4474
 
                    gs_malloc(udev->memory, upd->nbytes,sizeof(upd->scnbuf[0][0].bytes[0]),
4475
 
                    "upd/bytes");
4476
 
                  else        upd->scnbuf[ibuf][icomp].bytes = NULL;
4477
 
                  if(!upd->scnbuf[ibuf][icomp].bytes) success = false;
4478
 
 
4479
 
                  if(0 < upd->nlimits) {
4480
 
 
4481
 
                     upd->scnbuf[ibuf][icomp].xbegin = gs_malloc(udev->memory, upd->nlimits,
4482
 
                        sizeof(upd->scnbuf[0][0].xbegin[0]),"upd/xbegin");
4483
 
                     if(!upd->scnbuf[ibuf][icomp].xbegin) success = false;
4484
 
 
4485
 
                     upd->scnbuf[ibuf][icomp].xend   = gs_malloc(udev->memory, upd->nlimits,
4486
 
                        sizeof(upd->scnbuf[0][0].xend[0]),"upd/xend");
4487
 
                     if(!upd->scnbuf[ibuf][icomp].xbegin) success = false;
4488
 
 
4489
 
                  } else {
4490
 
 
4491
 
                     upd->scnbuf[ibuf][icomp].xbegin = NULL;
4492
 
                     upd->scnbuf[ibuf][icomp].xend   = NULL;
4493
 
 
4494
 
                  }
4495
 
               }
4496
 
            }
4497
 
         }
4498
 
      }
4499
 
   }
4500
 
 
4501
 
   if(success) upd->flags |= B_FORMAT;
4502
 
   else        upd_close_writer(udev);
4503
 
 
4504
 
   return success ? 1 : -1;
4505
 
}
4506
 
 
4507
 
/* ------------------------------------------------------------------- */
4508
 
/* upd_close_writer: Deinitialize rendering                            */
4509
 
/* ------------------------------------------------------------------- */
4510
 
 
4511
 
static void
4512
 
upd_close_writer(upd_device *udev)
4513
 
{
4514
 
   const upd_p upd = udev->upd;
4515
 
 
4516
 
   if(upd) {
4517
 
      int ibuf,icomp;
4518
 
 
4519
 
      if((0 < upd->noutbuf) && upd->outbuf)
4520
 
         gs_free(udev->memory, upd->outbuf,upd->noutbuf,sizeof(upd->outbuf[0]),"upd/outbuf");
4521
 
      upd->noutbuf = 0;
4522
 
      upd->outbuf  = NULL;
4523
 
 
4524
 
      if((0 < upd->nscnbuf) && upd->scnbuf) {
4525
 
         for(ibuf = 0; upd->nscnbuf > ibuf; ++ibuf) {
4526
 
 
4527
 
            if(!upd->scnbuf[ibuf]) continue;
4528
 
 
4529
 
            for(icomp = 0; icomp < upd->ocomp; ++icomp) {
4530
 
 
4531
 
               if((0 < upd->nbytes) && upd->scnbuf[ibuf][icomp].bytes)
4532
 
                  gs_free(udev->memory, upd->scnbuf[ibuf][icomp].bytes,upd->nbytes,
4533
 
                     sizeof(upd->scnbuf[ibuf][icomp].words[0]),"upd/bytes");
4534
 
               upd->scnbuf[ibuf][icomp].bytes = NULL;
4535
 
 
4536
 
               if((0 < upd->nlimits) && upd->scnbuf[ibuf][icomp].xbegin)
4537
 
                  gs_free(udev->memory, upd->scnbuf[ibuf][icomp].xbegin,upd->nlimits,
4538
 
                     sizeof(upd->scnbuf[ibuf][icomp].xbegin[0]),"upd/xbegin");
4539
 
               upd->scnbuf[ibuf][icomp].xbegin = NULL;
4540
 
 
4541
 
               if((0 < upd->nlimits) && upd->scnbuf[ibuf][icomp].xend)
4542
 
                  gs_free(udev->memory, upd->scnbuf[ibuf][icomp].xend,upd->nlimits,
4543
 
                     sizeof(upd->scnbuf[ibuf][icomp].xend[0]),"upd/xend");
4544
 
               upd->scnbuf[ibuf][icomp].xend = NULL;
4545
 
            }
4546
 
 
4547
 
            if(icomp)
4548
 
               gs_free(udev->memory, upd->scnbuf[ibuf],upd->ocomp,sizeof(upd->scnbuf[0][0]),
4549
 
                  "upd/scnbuf[]");
4550
 
            upd->scnbuf[ibuf] = NULL;
4551
 
 
4552
 
         }
4553
 
         gs_free(udev->memory, upd->scnbuf,upd->nscnbuf,sizeof(upd->scnbuf[0]),"upd/scnbuf");
4554
 
      }
4555
 
 
4556
 
      upd->flags &= ~B_FORMAT;
4557
 
   }
4558
 
}
4559
 
 
4560
 
/* ------------------------------------------------------------------- */
4561
 
/* upd_limits: Establish passwise limits, after rendering              */
4562
 
/* ------------------------------------------------------------------- */
4563
 
 
4564
 
static void
4565
 
upd_limits(upd_p upd, bool check)
4566
 
{
4567
 
   updscan_p  scans = upd->scnbuf[upd->yscnbuf & upd->scnmsk], scan;
4568
 
   int   xs,x,xe,icomp,pass;
4569
 
   byte *bytes,bit;
4570
 
 
4571
 
   for(icomp = 0; icomp < upd->ocomp; ++icomp) {
4572
 
      scan = scans + icomp;
4573
 
      for(pass = 0; pass < upd->nlimits; ++pass) {
4574
 
         scan->xbegin[pass] = upd->pwidth;
4575
 
         scan->xend[  pass] = -1;
4576
 
      }
4577
 
   }
4578
 
 
4579
 
   if(check) { /* Really check */
4580
 
      for(icomp = 0; icomp < upd->ocomp; ++icomp) { /* Check Components */
4581
 
         scan  = scans + icomp;
4582
 
         bytes = scan->bytes;
4583
 
 
4584
 
         for(xs = 0; xs < upd->nbytes  && !bytes[xs];   ++xs);
4585
 
 
4586
 
         if(xs < upd->nbytes) { /* Has Data */
4587
 
            for(xe = upd->nbytes; xs < xe && !bytes[xe-1]; --xe);
4588
 
 
4589
 
            for(pass = 0; pass < upd->nlimits; ++pass) { /* limit (pass) loop */
4590
 
 
4591
 
               x = ((xs<<3)/upd->nlimits)*upd->nlimits + pass;
4592
 
               while((x >> 3) < xs) x += upd->nlimits;
4593
 
 
4594
 
               bit = 0x80 >> (x & 7);
4595
 
               while(x < scan->xbegin[pass]) {
4596
 
                  if(bytes[x>>3] & bit) scan->xbegin[pass] = x;
4597
 
                  x  += upd->nlimits;
4598
 
                  bit = 0x80 >> (x & 7);
4599
 
               }
4600
 
 
4601
 
               x = (((xe<<3)|7)/upd->nlimits)*upd->nlimits + pass;
4602
 
 
4603
 
               while((x >> 3) < xe) x += upd->nlimits;
4604
 
               while((x >> 3) > xe) x -= upd->nlimits;
4605
 
 
4606
 
               bit = 0x80 >> (xs & 7);
4607
 
               while(x > scan->xend[pass]) {
4608
 
                  if(bytes[x>>3] & bit) scan->xend[pass] = x;
4609
 
                  x -= upd->nlimits;
4610
 
                  bit = 0x80 >> (x & 7);
4611
 
               }
4612
 
 
4613
 
            }                                            /* limit (pass) loop */
4614
 
 
4615
 
         }                      /* Has Data */
4616
 
 
4617
 
      }                                             /* Check Components */
4618
 
 
4619
 
   }           /* Really check */
4620
 
 
4621
 
}
4622
 
 
4623
 
/* ------------------------------------------------------------------- */
4624
 
/* upd_open_rascomp: ncomp * 1Bit Raster-Writer                        */
4625
 
/* ------------------------------------------------------------------- */
4626
 
 
4627
 
static int
4628
 
upd_open_rascomp(upd_device *udev)
4629
 
{
4630
 
   const upd_p upd = udev->upd;
4631
 
   int32_t noutbuf;
4632
 
   int error = 0;
4633
 
 
4634
 
   noutbuf = upd->pwidth;
4635
 
 
4636
 
   if(1 < upd->ncomp) noutbuf *= 8; /* ??? upd->ocomp */
4637
 
 
4638
 
   noutbuf = ((noutbuf+15)>>4)<<1;
4639
 
 
4640
 
   if(INT_MAX >= noutbuf) {
4641
 
      upd->noutbuf = noutbuf;
4642
 
      upd->start_writer = upd_start_rascomp;
4643
 
      upd->writer       = upd_rascomp;
4644
 
   } else {
4645
 
      error = -1;
4646
 
   }
4647
 
 
4648
 
   return error;
4649
 
}
4650
 
 
4651
 
/* ------------------------------------------------------------------- */
4652
 
/* upd_start_rascomp: write appropiate raster-header                   */
4653
 
/* ------------------------------------------------------------------- */
4654
 
#if arch_is_big_endian
4655
 
#define put32(I32,Out)       \
4656
 
   fwrite(&I32,1,4,Out)
4657
 
#else
4658
 
#define put32(I32,Out)       \
4659
 
   putc(((I32)>>24)&255,Out),\
4660
 
   putc(((I32)>>16)&255,Out),\
4661
 
   putc(((I32)>> 8)&255,Out),\
4662
 
   putc( (I32)     &255,Out)
4663
 
#endif
4664
 
 
4665
 
static int
4666
 
upd_start_rascomp(upd_p upd, FILE *out) {
4667
 
 
4668
 
/** if no begin-sequence externally set */
4669
 
   if(0 == upd->strings[S_BEGIN].size) {
4670
 
      int32_t val;
4671
 
 
4672
 
/**   ras_magic */
4673
 
      val = 0x59a66a95;
4674
 
      put32(val,out);
4675
 
 
4676
 
/**   ras_width */
4677
 
      val = upd->pwidth;
4678
 
      put32(val,out);
4679
 
 
4680
 
/**   ras_height */
4681
 
      val = upd->pheight;
4682
 
      put32(val,out);
4683
 
 
4684
 
/**   ras_depth */
4685
 
      if(1 < upd->ncomp) val = 8; /* ??? upd->ocomp */
4686
 
      else               val = 1;
4687
 
      put32(val,out);
4688
 
 
4689
 
/**   ras_length */
4690
 
      val *= upd->pwidth;
4691
 
      val = ((val+15)>>4)<<1;
4692
 
      val *= upd->pheight;
4693
 
      put32(val,out);
4694
 
 
4695
 
/**   ras_type */
4696
 
      val = 1;
4697
 
      put32(val,out);
4698
 
 
4699
 
/**   ras_maptype */
4700
 
      val = 1;
4701
 
      put32(val,out);
4702
 
 
4703
 
/**   ras_maplength */
4704
 
      val = 3 * (1 << upd->ncomp); /* ??? upd->ocomp */
4705
 
      put32(val,out);
4706
 
 
4707
 
/**   R,G,B-Map */
4708
 
      if(1 == upd->ncomp) { /* ??? upd->ocomp */
4709
 
         const updcomp_p comp = upd->valptr[0];
4710
 
 
4711
 
         if(upd->cmap[comp->cmap].rise) {
4712
 
            putc((char) 0x00,out); putc((char) 0xff,out);
4713
 
            putc((char) 0x00,out); putc((char) 0xff,out);
4714
 
            putc((char) 0x00,out); putc((char) 0xff,out);
4715
 
         } else {
4716
 
            putc((char) 0xff,out); putc((char) 0x00,out);
4717
 
            putc((char) 0xff,out); putc((char) 0x00,out);
4718
 
            putc((char) 0xff,out); putc((char) 0x00,out);
4719
 
         }
4720
 
 
4721
 
      } else if(3 == upd->ncomp) { /* ??? upd->ocomp */
4722
 
         int rgb;
4723
 
 
4724
 
         for( rgb = 0; rgb < 3; ++rgb) {
4725
 
            int entry;
4726
 
            for(entry = 0; entry < 8; ++entry) {
4727
 
               byte xval = upd->cmap[rgb].rise ? 0x00 : 0xff;
4728
 
               if(entry & (1<<upd->cmap[rgb].comp)) xval ^= 0xff;
4729
 
               putc(xval,out);
4730
 
            }
4731
 
         }
4732
 
      } else { /* we have 4 components */
4733
 
         int rgb;
4734
 
 
4735
 
         for(rgb = 16; 0 <= rgb; rgb -= 8) {
4736
 
            int entry;
4737
 
            for(entry = 0; entry < 16; ++entry) {
4738
 
               uint32_t rgbval = 0;
4739
 
 
4740
 
               if(entry & (1<<upd->cmap[0].comp)) {
4741
 
 
4742
 
                  rgbval = 0xffffff;
4743
 
 
4744
 
               } else {
4745
 
 
4746
 
                  if(entry & (1<<upd->cmap[1].comp)) rgbval |= 0xff0000;
4747
 
                  if(entry & (1<<upd->cmap[2].comp)) rgbval |= 0x00ff00;
4748
 
                  if(entry & (1<<upd->cmap[3].comp)) rgbval |= 0x0000ff;
4749
 
               }
4750
 
 
4751
 
               if(!upd->cmap[1].rise) rgbval ^= 0xff0000;
4752
 
               if(!upd->cmap[2].rise) rgbval ^= 0x00ff00;
4753
 
               if(!upd->cmap[3].rise) rgbval ^= 0x0000ff;
4754
 
 
4755
 
               if(!(upd->choice[C_MAPPER] == MAP_RGBW)) rgbval ^= 0xffffff;
4756
 
 
4757
 
               putc((rgbval>>rgb)&255,out);
4758
 
            }
4759
 
         }
4760
 
      }
4761
 
   }
4762
 
   memset(upd->outbuf,0,upd->noutbuf);
4763
 
 
4764
 
   return 0;
4765
 
}
4766
 
 
4767
 
/* ------------------------------------------------------------------- */
4768
 
/* upd_rascomp: assemble & write a scanline                            */
4769
 
/* ------------------------------------------------------------------- */
4770
 
static int
4771
 
upd_rascomp(upd_p upd, FILE *out) {
4772
 
   updscan_p scan = upd->scnbuf[upd->yscan & upd->scnmsk];
4773
 
   uint bits = upd->pwidth;
4774
 
 
4775
 
   if(1 == upd->ncomp) { /* ??? upd->ocomp */
4776
 
      uint nbytes;
4777
 
 
4778
 
      nbytes = (bits+7)>>3;
4779
 
      memcpy(upd->outbuf,scan->bytes,nbytes);
4780
 
      if((bits &= 7)) upd->outbuf[nbytes-1] &= ((byte) 0xff) << (8-bits);
4781
 
 
4782
 
   } else {
4783
 
 
4784
 
      byte  *buf   = upd->outbuf, bit = 0x80;
4785
 
      int    ibyte = 0;
4786
 
 
4787
 
      while(0 < bits--) {
4788
 
         byte val = 0;
4789
 
         switch(upd->ncomp) { /* ??? upd->ocomp */
4790
 
            case 4:  if(scan[3].bytes[ibyte] & bit) val |= 8;
4791
 
            case 3:  if(scan[2].bytes[ibyte] & bit) val |= 4;
4792
 
                     if(scan[1].bytes[ibyte] & bit) val |= 2;
4793
 
            case 1:  if(scan[0].bytes[ibyte] & bit) val |= 1;
4794
 
         }
4795
 
         *buf++ = val;
4796
 
         if(!(bit >>= 1)) {
4797
 
            bit    = 0x80;
4798
 
            ibyte += 1;
4799
 
         }
4800
 
      }
4801
 
   }
4802
 
 
4803
 
   fwrite(upd->outbuf,1,upd->noutbuf,out);
4804
 
   upd->yscan += 1;
4805
 
 
4806
 
   return 0;
4807
 
}
4808
 
 
4809
 
/* ------------------------------------------------------------------- */
4810
 
/* upd_open_wrtescp: ESC/P Writer intended for ESC * m commands        */
4811
 
/* ------------------------------------------------------------------- */
4812
 
 
4813
 
static int
4814
 
upd_open_wrtescp(upd_device *udev)
4815
 
{
4816
 
   const upd_p      upd  = udev->upd;
4817
 
   int              error = 0;
4818
 
 
4819
 
/** Adjust the PageLength, If Requested */
4820
 
   if((B_PAGELENGTH & upd->flags) &&
4821
 
      (0 < upd->strings[S_BEGIN].size)) { /* BOP-Checker */
4822
 
     int   i,state = 0,value = 0;
4823
 
     byte *bp = (byte *) upd_cast(upd->strings[S_BEGIN].data);
4824
 
     for(i = 0; i < upd->strings[S_BEGIN].size; ++i) {
4825
 
        switch(state) {
4826
 
           case  0:
4827
 
              if(0x1b == bp[i]) state = 1;
4828
 
           break;
4829
 
           case  1:
4830
 
              if('C'  == bp[i]) state = 2;
4831
 
              else              state = 0;
4832
 
           break;
4833
 
           case  2:
4834
 
              if(bp[i]) {
4835
 
                 value = (int)(0.5 + udev->height * (float) bp[i]
4836
 
                               / udev->y_pixels_per_inch);
4837
 
                 if(       0 >= value) bp[i] = 1;
4838
 
                 else if(128 >  value) bp[i] = value;
4839
 
                 else                  bp[i] = 127;
4840
 
                 state = 0;
4841
 
              } else {
4842
 
                 state = 3;
4843
 
              }
4844
 
           break;
4845
 
           case  3:
4846
 
              value = (int)(0.5 + udev->height / udev->y_pixels_per_inch);
4847
 
              if(       0 >= value) bp[i] = 1;
4848
 
              else if( 22 >  value) bp[i] = value;
4849
 
              else                  bp[i] = 22;
4850
 
              state = 0;
4851
 
           break;
4852
 
        }
4853
 
     }
4854
 
   }                                    /* BOP-Checker */
4855
 
 
4856
 
/** Either SETLF or YMOVE must be set */
4857
 
   if((0 == upd->strings[S_SETLF].size) &&
4858
 
      (0 == upd->strings[S_YMOVE].size)   ) {
4859
 
#if UPD_MESSAGES & UPD_M_WARNING
4860
 
      errprintf(udev->memory,
4861
 
        "ESC/P-Open: Either SETLF- or YMOVE-Command must be present\n");
4862
 
#endif
4863
 
      error = -1;
4864
 
   }
4865
 
 
4866
 
/** X-Positioning must be set too */
4867
 
   if(((1 <  upd->ints[I_XSTEP]        ) &&
4868
 
       (0 == upd->strings[S_XSTEP].size)   ) ||
4869
 
      ((1 < upd->ints[I_NXPASS]        ) &&
4870
 
       (0 == upd->strings[S_XMOVE].size) &&
4871
 
       (0 == upd->strings[S_XSTEP].size)   )   ) {
4872
 
#if UPD_MESSAGES & UPD_M_WARNING
4873
 
      errprintf(udev->memory,
4874
 
         "ESC/P-Open: Missing XSTEP- and/or XMOVE-Command\n");
4875
 
#endif
4876
 
      error = -1;
4877
 
   }
4878
 
 
4879
 
/** SA_WRITECOMP must be valid */
4880
 
   if(upd->ncomp > upd->string_a[SA_WRITECOMP].size) { /* ??? upd->ocomp */
4881
 
#if UPD_MESSAGES & UPD_M_WARNING
4882
 
      errprintf(udev->memory,
4883
 
         "ESC/P-Open: WRITECOMP-Commands must be given\n");
4884
 
#endif
4885
 
      error = -1;
4886
 
   }
4887
 
 
4888
 
/**
4889
 
If all this is correct, it's time to coumput the size of the output-buffer.
4890
 
It must hold:
4891
 
  1. Y-Positioning
4892
 
  2. X-Positioning
4893
 
  3. Component-Selection
4894
 
  4. The Raster-Command
4895
 
  5. The Data
4896
 
*/
4897
 
   if(0 <= error) {
4898
 
      int32_t i,noutbuf,need;
4899
 
 
4900
 
      if(0 < upd->strings[S_YMOVE].size) {
4901
 
         noutbuf = upd->strings[S_YMOVE].size + 2;
4902
 
      } else {
4903
 
         int nmax = upd->pheight;
4904
 
         if(      1 < upd->ints[I_YSTEP]) nmax /=  upd->ints[I_YSTEP];
4905
 
         else if(-1 > upd->ints[I_YSTEP]) nmax *= -upd->ints[I_YSTEP];
4906
 
         noutbuf  = 2 * upd->strings[S_SETLF].size + 2;
4907
 
         noutbuf += nmax/255 + 1;
4908
 
      }
4909
 
 
4910
 
      if(1 < upd->ints[I_YSTEP])
4911
 
         noutbuf += (upd->ints[I_YSTEP]-1) * upd->strings[S_YSTEP].size;
4912
 
 
4913
 
      noutbuf +=  upd->strings[S_XMOVE].size + 2;
4914
 
 
4915
 
      if(1 < upd->ints[I_XSTEP])
4916
 
         noutbuf += (upd->ints[I_XSTEP]-1) * upd->strings[S_XSTEP].size;
4917
 
 
4918
 
      if(0 < upd->string_a[SA_SETCOMP].size) {
4919
 
         need = 0;
4920
 
         for(i = 0; i < upd->ocomp; ++i)
4921
 
            if(need < upd->string_a[SA_SETCOMP].data[i].size)
4922
 
               need = upd->string_a[SA_SETCOMP].data[i].size;
4923
 
         noutbuf += need;
4924
 
      }
4925
 
 
4926
 
      need = 0;
4927
 
      for(i = 0; i < upd->ocomp; ++i)
4928
 
         if(need < upd->string_a[SA_WRITECOMP].data[i].size)
4929
 
            need = upd->string_a[SA_WRITECOMP].data[i].size;
4930
 
      noutbuf += need + 2;
4931
 
 
4932
 
      noutbuf += ((upd->ints[I_PINS2WRITE] + 7) / 8)
4933
 
               * ((upd->pwidth + upd->ints[I_NXPASS] - 1)/upd->ints[I_NXPASS]);
4934
 
 
4935
 
      if((0 < noutbuf) && (noutbuf <= INT_MAX)) {
4936
 
         upd->noutbuf      = noutbuf;
4937
 
         upd->writer       = upd_wrtescp;
4938
 
         upd->nlimits      = upd->ints[I_NXPASS];
4939
 
         error             = 1;
4940
 
      } else {
4941
 
         error = -1;
4942
 
#if      UPD_MESSAGES & UPD_M_WARNING
4943
 
            errprintf(udev->memory,
4944
 
              "ESC/P-Open: %ld is unreasonable size of Outputbuffer\n",
4945
 
              (long) noutbuf);
4946
 
#endif
4947
 
      }
4948
 
   }
4949
 
 
4950
 
   return error;
4951
 
}
4952
 
 
4953
 
/* ------------------------------------------------------------------- */
4954
 
/* upd_wrtescp: Write a pass                                           */
4955
 
/* ------------------------------------------------------------------- */
4956
 
 
4957
 
static int
4958
 
upd_wrtescp(upd_p upd, FILE *out)
4959
 
{
4960
 
   int  pinbot,pin,pintop,xbegin,x,xend,icomp,ybegin,yend,y,ioutbuf,n,ixpass;
4961
 
   byte *obytes,bit;
4962
 
   updscan_p scan;
4963
 
 
4964
 
/** Determine the number of pins to write */
4965
 
 
4966
 
   if(upd->yscan < upd->ints[I_BEG_Y]) {
4967
 
      ixpass = upd->int_a[IA_BEG_IX].data[upd->ipass];
4968
 
      pintop = 0;
4969
 
      pinbot = upd->int_a[IA_BEGBOT].data[upd->ipass];
4970
 
   } else if(upd->yscan >= upd->ints[I_END_Y]) {
4971
 
      ixpass = upd->int_a[IA_END_IX].data[upd->ipass];
4972
 
      pinbot = upd->ints[I_PINS2WRITE];
4973
 
      pintop = pinbot - upd->int_a[IA_ENDTOP].data[upd->ipass];
4974
 
   } else {
4975
 
      ixpass = upd->int_a[IA_STD_IX].data[upd->ipass];
4976
 
      pintop = 0;
4977
 
      pinbot = upd->ints[I_PINS2WRITE];
4978
 
   }
4979
 
 
4980
 
   ybegin =  pintop * upd->ints[I_NYPASS] + upd->yscan - upd->ints[I_BEGSKIP];
4981
 
   yend   =  pinbot * upd->ints[I_NYPASS] + upd->yscan - upd->ints[I_BEGSKIP];
4982
 
 
4983
 
/** Determine Width of this scan */
4984
 
 
4985
 
   xbegin = upd->pwidth;
4986
 
   xend   = -1;
4987
 
 
4988
 
   for(y = ybegin; y < yend; y += upd->ints[I_NYPASS]) { /* Pin-testloop */
4989
 
 
4990
 
      if(0 > y) continue; /* Inserted Scanlines */
4991
 
 
4992
 
      scan = upd->scnbuf[y & upd->scnmsk];
4993
 
 
4994
 
      for(icomp = 0; icomp < upd->ocomp; ++icomp) { /* Compwise test */
4995
 
         if(xbegin > scan[icomp].xbegin[ixpass])
4996
 
            xbegin = scan[icomp].xbegin[ixpass];
4997
 
         if(xend   < scan[icomp].xend[  ixpass])
4998
 
            xend   = scan[icomp].xend[  ixpass];
4999
 
      }                                             /* Compwise test */
5000
 
 
5001
 
   }                                                     /* Pin-testloop */
5002
 
 
5003
 
   if(xbegin <= xend) { /* Some data to write */
5004
 
 
5005
 
      ioutbuf = 0;
5006
 
 
5007
 
      if(0 == upd->strings[S_XMOVE].size) xbegin = ixpass;
5008
 
 
5009
 
/*
5010
 
 *    Adjust the Printers Y-Position
5011
 
 */
5012
 
      if(upd->yscan != upd->yprinter) { /* Adjust Y-Position */
5013
 
         if(B_YABS & upd->flags) y = upd->yscan + upd->ints[I_YOFS];
5014
 
         else                    y = upd->yscan - upd->yprinter;
5015
 
 
5016
 
         if(      1 < upd->ints[I_YSTEP]) {
5017
 
            n      =  y / upd->ints[I_YSTEP];  /* Major-Steps */
5018
 
            y     -=  n * upd->ints[I_YSTEP];  /* Minor-Steps */
5019
 
         } else if(-1 > upd->ints[I_YSTEP]) {
5020
 
            n      = y * -upd->ints[I_YSTEP];  /* May this work? */
5021
 
            y      = 0;
5022
 
         } else {
5023
 
            n      = y;
5024
 
            y      = 0;
5025
 
         }
5026
 
 
5027
 
         if(n) { /* Coarse Positioning */
5028
 
            if(0 < upd->strings[S_YMOVE].size) {
5029
 
 
5030
 
               memcpy(upd->outbuf+ioutbuf,
5031
 
                          upd->strings[S_YMOVE].data,
5032
 
                          upd->strings[S_YMOVE].size);
5033
 
               ioutbuf += upd->strings[S_YMOVE].size;
5034
 
 
5035
 
               upd->outbuf[ioutbuf++] =  n     & 0xff;
5036
 
               upd->outbuf[ioutbuf++] = (n>>8) & 0xff;
5037
 
 
5038
 
            } else {
5039
 
 
5040
 
               while(n) {
5041
 
                  int n2do = n > 255 ? 255 : n;
5042
 
                  if(upd->lf != n2do) {
5043
 
                     memcpy(upd->outbuf+ioutbuf,
5044
 
                                upd->strings[S_SETLF].data,
5045
 
                                upd->strings[S_SETLF].size);
5046
 
                     ioutbuf += upd->strings[S_SETLF].size;
5047
 
                     upd->outbuf[ioutbuf++] = n2do;
5048
 
                     upd->lf                = n2do;
5049
 
                  }
5050
 
                  upd->outbuf[ioutbuf++] = '\n';
5051
 
                  n -= n2do;
5052
 
               }
5053
 
            }
5054
 
         }       /* Coarse Positioning */
5055
 
 
5056
 
         if(0 < upd->strings[S_YSTEP].size) {
5057
 
            while(y--) {
5058
 
               memcpy(upd->outbuf+ioutbuf,
5059
 
                          upd->strings[S_YSTEP].data,
5060
 
                          upd->strings[S_YSTEP].size);
5061
 
               ioutbuf += upd->strings[S_YSTEP].size;
5062
 
            }
5063
 
         }
5064
 
 
5065
 
         upd->yprinter = upd->yscan;
5066
 
      }                                 /* Adjust Y-Position */
5067
 
 
5068
 
/*
5069
 
 * Now write the required components
5070
 
 */
5071
 
      for(icomp = 0; icomp < upd->ocomp; ++icomp) { /* Component-Print */
5072
 
/*
5073
 
 *       First check, wether this Component needs printing
5074
 
 */
5075
 
         for(y = ybegin; y < yend; y += upd->ints[I_NYPASS]) { /* Comp-Test */
5076
 
            if(0 > y) continue;
5077
 
            scan = upd->scnbuf[y & upd->scnmsk]+icomp;
5078
 
            if(0 <= scan->xend[ixpass]) break;
5079
 
         }                                                     /* Comp-Test */
5080
 
         if(y >= yend) continue; /* Component not required */
5081
 
/*
5082
 
 *       Select the Component
5083
 
 */
5084
 
         if((0 < upd->string_a[SA_SETCOMP].size) &&
5085
 
            (upd->icomp != icomp               )   ) { /* Selection enabled */
5086
 
            upd->icomp = icomp;
5087
 
            if(0 < upd->string_a[SA_SETCOMP].data[icomp].size) {
5088
 
               memcpy(upd->outbuf+ioutbuf,
5089
 
                          upd->string_a[SA_SETCOMP].data[icomp].data,
5090
 
                          upd->string_a[SA_SETCOMP].data[icomp].size);
5091
 
               ioutbuf += upd->string_a[SA_SETCOMP].data[icomp].size;
5092
 
            }
5093
 
         }                                      /* Selection enabled */
5094
 
/*
5095
 
 *       Establish the X-Position
5096
 
 */
5097
 
         if(xbegin != upd->xprinter) {
5098
 
 
5099
 
            if(0 == upd->strings[S_XMOVE].size) {
5100
 
 
5101
 
               upd->outbuf[ioutbuf++] = '\r';
5102
 
               upd->xprinter          =  0;
5103
 
               n = 0;
5104
 
               x = ixpass;
5105
 
 
5106
 
            } else {
5107
 
 
5108
 
               if(B_XABS & upd->flags) n = x = xbegin + upd->ints[I_XOFS];
5109
 
               else                    n = x = xbegin - upd->xprinter;
5110
 
 
5111
 
               if(        1 < upd->ints[I_XSTEP]) {
5112
 
                  if(0 > n) {
5113
 
                     n  -= upd->ints[I_XSTEP];
5114
 
                     x  -= n;
5115
 
                  }
5116
 
                  if(n) n  /= upd->ints[I_XSTEP]; /* Major-Steps */
5117
 
                  if(x) x  %= upd->ints[I_XSTEP]; /* Minor-Steps */
5118
 
 
5119
 
               } else if(-1 > upd->ints[I_XSTEP]) {
5120
 
                  n *= -upd->ints[I_XSTEP]; /* May this work? */
5121
 
                  x  = 0;
5122
 
               }
5123
 
 
5124
 
               if(n) { /* Adjust X-Position */
5125
 
 
5126
 
                 memcpy(upd->outbuf+ioutbuf,
5127
 
                             upd->strings[S_XMOVE].data,
5128
 
                             upd->strings[S_XMOVE].size);
5129
 
                  ioutbuf += upd->strings[S_XMOVE].size;
5130
 
 
5131
 
                  upd->outbuf[ioutbuf++] =  n     & 0xff;
5132
 
                  upd->outbuf[ioutbuf++] = (n>>8) & 0xff;
5133
 
 
5134
 
               }       /* Adjust X-Position */
5135
 
 
5136
 
            }
5137
 
 
5138
 
            if(x && 0 < upd->strings[S_XSTEP].size) { /* Fine-Adjust X */
5139
 
               while(x--) {
5140
 
                  memcpy(upd->outbuf+ioutbuf,
5141
 
                             upd->strings[S_XSTEP].data,
5142
 
                             upd->strings[S_XSTEP].size);
5143
 
                  ioutbuf += upd->strings[S_XSTEP].size;
5144
 
               }
5145
 
            }                                         /* Fine-Adjust X */
5146
 
         }
5147
 
         upd->xprinter = xend+1;
5148
 
/*
5149
 
 *       Send the Write-Command
5150
 
 */
5151
 
         if(0 < upd->string_a[SA_WRITECOMP].data[icomp].size) {
5152
 
            memcpy(upd->outbuf+ioutbuf,
5153
 
                       upd->string_a[SA_WRITECOMP].data[icomp].data,
5154
 
                       upd->string_a[SA_WRITECOMP].data[icomp].size);
5155
 
            ioutbuf += upd->string_a[SA_WRITECOMP].data[icomp].size;
5156
 
         }
5157
 
         n = (xend - xbegin) / upd->ints[I_NXPASS] + 1;;
5158
 
         upd->outbuf[ioutbuf++] =  n     & 255;
5159
 
         upd->outbuf[ioutbuf++] = (n>>8) & 255;
5160
 
/*
5161
 
 *       Clear the data-Part
5162
 
 */
5163
 
         obytes   =  upd->outbuf+ioutbuf;
5164
 
         n       *= (upd->ints[I_PINS2WRITE]+7)>>3;
5165
 
         memset(obytes,0,n);
5166
 
         ioutbuf += n;
5167
 
/*
5168
 
 *       Set the Pixels
5169
 
 */
5170
 
         for(x = xbegin; x <= xend; x += upd->ints[I_NXPASS]) {
5171
 
 
5172
 
            bit     = 0x80 >> (pintop & 7);
5173
 
            obytes += pintop>>3;
5174
 
 
5175
 
            for(pin = pintop, y = ybegin; pin < pinbot;
5176
 
                pin++,        y += upd->ints[I_NYPASS]) {
5177
 
               if(0 <= y) {
5178
 
                  scan = upd->scnbuf[y & upd->scnmsk]+icomp;
5179
 
                  if(scan->bytes[x>>3] & (0x80 >> (x & 7))) *obytes |= bit;
5180
 
               }
5181
 
               if(!(bit >>= 1)) { obytes++; bit = 0x80; }
5182
 
            }
5183
 
 
5184
 
            obytes += (upd->ints[I_PINS2WRITE]-pinbot+7)>>3;
5185
 
         }
5186
 
/*
5187
 
 *       Send this Component to the Printer
5188
 
 */
5189
 
         fwrite(upd->outbuf,1,ioutbuf,out);
5190
 
         ioutbuf = 0;
5191
 
      }                                             /* Component-Print */
5192
 
   }                    /* Some data to write */
5193
 
 
5194
 
/** Advance counters in upd, change modi */
5195
 
 
5196
 
   if(upd->yscan < upd->ints[I_BEG_Y]) {
5197
 
      upd->yscan += upd->int_a[IA_BEG_DY].data[upd->ipass++];
5198
 
      if(     upd->ints[I_BEG_Y] <= upd->yscan) upd->ipass = 0;
5199
 
      else if(upd->int_a[IA_BEG_DY].size <= upd->ipass) upd->ipass = 0;
5200
 
   } else if(upd->yscan >= upd->ints[I_END_Y]) {
5201
 
      upd->yscan += upd->int_a[IA_END_DY].data[upd->ipass++];
5202
 
      if(upd->int_a[IA_END_DY].size <= upd->ipass) upd->ipass = 0;
5203
 
   } else {
5204
 
      upd->yscan += upd->int_a[IA_STD_DY].data[upd->ipass++];
5205
 
      if(upd->int_a[IA_STD_DY].size <= upd->ipass) upd->ipass = 0;
5206
 
      if(upd->yscan >= upd->ints[I_END_Y])         upd->ipass = 0;
5207
 
   }
5208
 
 
5209
 
   return 0;
5210
 
}
5211
 
 
5212
 
/* ------------------------------------------------------------------- */
5213
 
/* upd_open_wrtescp2: ESC/P2 Writer intended for ESC . 1  commands     */
5214
 
/* ------------------------------------------------------------------- */
5215
 
 
5216
 
static int
5217
 
upd_open_wrtescp2(upd_device *udev)
5218
 
{
5219
 
   const upd_p      upd             = udev->upd;
5220
 
   int              error           = 0;
5221
 
   float            pixels_per_inch = 360.0;
5222
 
 
5223
 
/** Analyze (and optionally adjust) the BOP-Sequence */
5224
 
   if(0 < upd->strings[S_BEGIN].size) { /* BOP-Checker */
5225
 
     int   i,state = 0,value = 0;
5226
 
     byte *bp = (byte *) upd_cast(upd->strings[S_BEGIN].data);
5227
 
     for(i = 0; i < upd->strings[S_BEGIN].size; ++i) {
5228
 
        switch(state) {
5229
 
           case  0:
5230
 
              if(0x1b == bp[i]) state = 1;
5231
 
           break;
5232
 
           case  1:
5233
 
              if('('  == bp[i]) state = 2;
5234
 
              else              state = 0;
5235
 
           break;
5236
 
           case  2:
5237
 
              switch(bp[i]) {
5238
 
                 case 'U': state =  3; break; /* Printer-Resolution */
5239
 
                 case 'C': state =  6; break; /* Page-Length */
5240
 
                 case 'c': state = 10; break; /* Top/Bottom Margin */
5241
 
                 default:  state =  0; break;
5242
 
              }
5243
 
           break;
5244
 
           case  3:
5245
 
              if(1 == bp[i]) state = 4;
5246
 
              else           state = 0;
5247
 
           break;
5248
 
           case  4:
5249
 
              if(0 == bp[i]) state = 5;
5250
 
              else           state = 0;
5251
 
           break;
5252
 
           case  5:
5253
 
              pixels_per_inch = 3600.0 / (float) bp[i];
5254
 
              state = 0;
5255
 
           break;
5256
 
           case  6:
5257
 
              if(2 == bp[i]) state = 7;
5258
 
              else           state = 0;
5259
 
           break;
5260
 
           case  7:
5261
 
              if(0 == bp[i]) state = 8;
5262
 
              else           state = 0;
5263
 
           break;
5264
 
           case  8:
5265
 
              if(B_PAGELENGTH & upd->flags) {
5266
 
                 value = (int)(0.5 + udev->height
5267
 
                               * pixels_per_inch / udev->y_pixels_per_inch);
5268
 
                 bp[i] =  value     & 0xff;
5269
 
              }
5270
 
              state = 9;
5271
 
           break;
5272
 
           case  9:
5273
 
              if(B_PAGELENGTH & upd->flags) {
5274
 
                 bp[i] = (value>>8) & 0xff;
5275
 
              }
5276
 
              state = 0;
5277
 
           break;
5278
 
           case 10:
5279
 
              if(4 == bp[i]) state = 11;
5280
 
              else           state =  0;
5281
 
           break;
5282
 
           case 11:
5283
 
              if(0 == bp[i]) state = 12;
5284
 
              else           state =  0;
5285
 
           break;
5286
 
           case  12:
5287
 
              if(B_TOPMARGIN & upd->flags) {
5288
 
                 value =  (int)(dev_t_margin(udev) * pixels_per_inch);
5289
 
                 bp[i] =  value     & 0xff;
5290
 
              }
5291
 
              state = 13;
5292
 
           break;
5293
 
           case  13:
5294
 
              if(B_TOPMARGIN & upd->flags) {
5295
 
                 bp[i] = (value>>8) & 0xff;
5296
 
              }
5297
 
              state = 14;
5298
 
           break;
5299
 
           case  14:
5300
 
              if(B_BOTTOMMARGIN & upd->flags) {
5301
 
                 value = (int)(0.5 + udev->height
5302
 
                               * pixels_per_inch / udev->y_pixels_per_inch
5303
 
                       - dev_b_margin(udev) * pixels_per_inch);
5304
 
                 bp[i] =  value     & 0xff;
5305
 
              }
5306
 
              state = 15;
5307
 
           break;
5308
 
           case  15:
5309
 
              if(B_BOTTOMMARGIN & upd->flags) {
5310
 
                 bp[i] = (value>>8) & 0xff;
5311
 
              }
5312
 
              state =  0;
5313
 
           break;
5314
 
        }
5315
 
     }
5316
 
   }                                    /* BOP-Checker */
5317
 
 
5318
 
/** Create Y-Move-Command, if not given */
5319
 
   if(0 == upd->strings[S_YMOVE].size) {
5320
 
      byte *bp;
5321
 
      UPD_MM_DEL_PARAM(udev->memory, upd->strings[S_YMOVE]);
5322
 
      UPD_MM_GET_ARRAY(udev->memory, bp,5);
5323
 
      upd->strings[S_YMOVE].data = bp;
5324
 
      upd->strings[S_YMOVE].size = 5;
5325
 
      *bp++ = 0x1b; /* ESC */
5326
 
      *bp++ = '(';
5327
 
      *bp++ = upd->flags & B_YABS ? 'V' : 'v';
5328
 
      *bp++ =  2;
5329
 
      *bp++ =  0;
5330
 
   }
5331
 
 
5332
 
/** X-Positioning must be set too, sometimes */
5333
 
   if((1 < upd->ints[I_XSTEP]) && (0 == upd->strings[S_XSTEP].size)) {
5334
 
 
5335
 
#if UPD_MESSAGES & UPD_M_WARNING
5336
 
      errprintf(udev->memory,
5337
 
         "ESC/P2-Open: XSTEP-Command required for XSTEP=%d\n",
5338
 
         upd->ints[I_XSTEP]);
5339
 
#endif
5340
 
      error = -1;
5341
 
 
5342
 
   } else if((1 <  upd->ints[I_NXPASS]       ) &&
5343
 
             (0 == upd->strings[S_XMOVE].size) &&
5344
 
             (0 == upd->strings[S_XSTEP].size)   ) {
5345
 
      byte *bp;
5346
 
      int ratio;
5347
 
 
5348
 
      ratio = (int)((udev->y_pixels_per_inch + 0.5) / udev->x_pixels_per_inch);
5349
 
 
5350
 
      if(0 == upd->ints[I_XSTEP]) { /* Adjust scale-factor too! */
5351
 
         if(ratio > 1) upd->ints[I_XSTEP] = -ratio;
5352
 
      } else {                     /* Adjust scale-factor too! */
5353
 
         ratio = -upd->ints[I_XSTEP];
5354
 
      }
5355
 
 
5356
 
      if(2 == upd->ints[I_NXPASS]) { /* Use a relative Step */
5357
 
 
5358
 
         UPD_MM_DEL_PARAM(udev->memory, upd->strings[S_XSTEP]);
5359
 
         UPD_MM_GET_ARRAY(udev->memory, bp,4);
5360
 
         upd->strings[S_XSTEP].size = 4;
5361
 
         upd->strings[S_XSTEP].data = bp;
5362
 
         *bp++ = 0x1b;
5363
 
         *bp++ = '\\';
5364
 
         *bp++ =  ratio     & 0xff;
5365
 
         *bp++ = (ratio>>8) & 0xff;
5366
 
 
5367
 
      } else {                      /* Use relative or absolute Move */
5368
 
 
5369
 
         UPD_MM_DEL_PARAM(udev->memory, upd->strings[S_XMOVE]);
5370
 
         UPD_MM_GET_ARRAY(udev->memory, bp,2);
5371
 
         upd->strings[S_XMOVE].size = 2;
5372
 
         upd->strings[S_XMOVE].data = bp;
5373
 
         *bp++  = 0x1b;
5374
 
         *bp++  = upd->flags & B_XABS ? '$' : '\\';
5375
 
 
5376
 
      }
5377
 
   }
5378
 
 
5379
 
   /* Check the Nozzle Map parameters and set some defaults */
5380
 
   /* Used a switch construct in case FMT_ESCNMXY is added later */
5381
 
   switch(upd->choice[C_FORMAT]){
5382
 
      case FMT_ESCNMY:
5383
 
         /* RowsPerPass */
5384
 
         if( 0 == upd->ints[I_ROWS] ){
5385
 
            upd->ints[I_ROWS] = 1;
5386
 
         }
5387
 
         /* PatternRepeat */
5388
 
         if( 0 == upd->ints[I_PATRPT] ){
5389
 
            upd->ints[I_PATRPT] = 1;
5390
 
         }
5391
 
         /* RowMask - default is all 1's */
5392
 
         if( upd->ints[I_PATRPT] != upd->int_a[IA_ROWMASK].size ) {
5393
 
            int i, *bp;
5394
 
            UPD_MM_DEL_PARAM(udev->memory, upd->int_a[IA_ROWMASK]);
5395
 
            UPD_MM_GET_ARRAY(udev->memory, bp,upd->ints[I_PATRPT]);
5396
 
            upd->int_a[IA_ROWMASK].size = upd->ints[I_PATRPT];
5397
 
            upd->int_a[IA_ROWMASK].data = bp;
5398
 
            for (i = 0 ; i < upd->ints[I_PATRPT] ; i++){
5399
 
               *bp++  = 1; /* black */
5400
 
            }
5401
 
         }
5402
 
         /* MaskScanOffset - default is 0-patternRepeat */
5403
 
         if( upd->ints[I_PATRPT] != upd->int_a[IA_SCNOFS].size ) {
5404
 
            int i, *bp;
5405
 
            UPD_MM_DEL_PARAM(udev->memory, upd->int_a[IA_SCNOFS]);
5406
 
            UPD_MM_GET_ARRAY(udev->memory, bp,upd->ints[I_PATRPT]);
5407
 
            upd->int_a[IA_SCNOFS].size = upd->ints[I_PATRPT];
5408
 
            upd->int_a[IA_SCNOFS].data = bp;
5409
 
            for (i = 0 ; i < upd->ints[I_PATRPT] ; i++){
5410
 
               *bp++  = i;
5411
 
            }
5412
 
         }
5413
 
      break;
5414
 
      case FMT_ESCP2Y:
5415
 
      case FMT_ESCP2XY:
5416
 
         /* Nozzle map parameters are not valid for these formats
5417
 
            so ignore them*/
5418
 
      break;
5419
 
   }
5420
 
 
5421
 
/** If there is neither a writecomp nor a setcomp-command, generate both */
5422
 
   if((0 == upd->string_a[SA_WRITECOMP].size) &&
5423
 
      (0 == upd->string_a[SA_SETCOMP].size  )   ) { /* Default-commands */
5424
 
      byte *bp;
5425
 
      gs_param_string *ap;
5426
 
      int   i;
5427
 
 
5428
 
      if(4 == upd->ocomp) { /* Establish Component-Selection */
5429
 
         UPD_MM_DEL_APARAM(udev->memory, upd->string_a[SA_SETCOMP]);
5430
 
         UPD_MM_GET_ARRAY(udev->memory, ap,4);
5431
 
         upd->string_a[SA_SETCOMP].data = ap;
5432
 
         upd->string_a[SA_SETCOMP].size = 4;
5433
 
         for(i = 0; i < 4; ++i) {
5434
 
            UPD_MM_GET_ARRAY(udev->memory, bp,3);
5435
 
            ap[i].size = 3;
5436
 
            ap[i].data = bp;
5437
 
            *bp++ = 0x1b;
5438
 
            *bp++ = 'r';
5439
 
            switch(((updcomp_p)upd->valptr[i])->cmap) { /* use COMPORDER! */
5440
 
               case 0: *bp++ = 0; break; /* Black */
5441
 
               case 1: *bp++ = 2; break; /* Cyan */
5442
 
               case 2: *bp++ = 1; break; /* Magenta */
5443
 
               case 3: *bp++ = 4; break; /* Yellow */
5444
 
            }                                           /* use COMPORDER! */
5445
 
         }
5446
 
      }                     /* Establish Component-Selection */
5447
 
 
5448
 
      UPD_MM_DEL_APARAM(udev->memory, upd->string_a[SA_WRITECOMP]);
5449
 
      UPD_MM_GET_ARRAY(udev->memory, ap,upd->ocomp);
5450
 
      upd->string_a[SA_WRITECOMP].data = ap;
5451
 
      upd->string_a[SA_WRITECOMP].size = upd->ncomp;
5452
 
      for(i = 0; i < upd->ocomp; ++i) {
5453
 
         UPD_MM_GET_ARRAY(udev->memory, bp,6);
5454
 
         ap[i].size = 6;
5455
 
         ap[i].data = bp;
5456
 
         *bp++ = 0x1b;
5457
 
         *bp++ = '.';
5458
 
         *bp++ =  1;  /* RLE */
5459
 
         switch(upd->choice[C_FORMAT]){
5460
 
            case FMT_ESCP2Y:
5461
 
            case FMT_ESCP2XY:
5462
 
               *bp++ = (byte)(3600.0 * upd->ints[I_NYPASS] /
5463
 
                                 udev->y_pixels_per_inch + 0.5);
5464
 
               *bp++ = (byte)(3600.0 * upd->ints[I_NXPASS] /
5465
 
                                 udev->x_pixels_per_inch + 0.5);
5466
 
               *bp++ = upd->ints[I_PINS2WRITE];
5467
 
            break;
5468
 
            case FMT_ESCNMY:
5469
 
               /*
5470
 
               *bp++ = 3600.0 / udev->y_pixels_per_inch + 0.5;
5471
 
               *bp++ = 3600.0 / udev->x_pixels_per_inch + 0.5;
5472
 
               */
5473
 
               *bp++ = 10; /* needs to always be this for esc300 */
5474
 
               *bp++ = 10;
5475
 
               *bp++ = upd->ints[I_ROWS];
5476
 
            break;
5477
 
         }
5478
 
      }
5479
 
   }                                                /* Default-commands */
5480
 
 
5481
 
/** SA_WRITECOMP must be valid */
5482
 
   if(upd->ocomp > upd->string_a[SA_WRITECOMP].size) {
5483
 
#if UPD_MESSAGES & UPD_M_WARNING
5484
 
      errprintf(udev->memory,
5485
 
         "ESC/P2-Open: WRITECOMP-Commands must be given\n");
5486
 
#endif
5487
 
      error = -1;
5488
 
   }
5489
 
 
5490
 
/** Check Validity of X-Pass */
5491
 
   switch(upd->choice[C_FORMAT]) {
5492
 
      case FMT_ESCP2Y:
5493
 
         if(1 < upd->ints[I_NXPASS]) {
5494
 
#if         UPD_MESSAGES & UPD_M_WARNING
5495
 
               errprintf(udev->memory,
5496
 
                  "ESC/P2-Open: FMT_ESCP2Y cannot handle multiple X-Passes\n");
5497
 
#endif
5498
 
            error = -1;
5499
 
         } else {
5500
 
            upd->writer = upd_wrtescp2;
5501
 
         }
5502
 
      break;
5503
 
      case FMT_ESCP2XY:
5504
 
         upd->writer  = upd_wrtescp2x;
5505
 
         upd->nlimits = upd->ints[I_NXPASS];
5506
 
#if      UPD_MESSAGES & UPD_M_WARNING
5507
 
            if(1 == upd->ints[I_NXPASS])
5508
 
               errprintf(udev->memory,
5509
 
                  "ESC/P2-Open: FMT_ESCP2XY should not be used with 1X-Pass\n");
5510
 
#endif
5511
 
      break;
5512
 
      case FMT_ESCNMY:
5513
 
         if(1 < upd->ints[I_NXPASS]) {
5514
 
#if         UPD_MESSAGES & UPD_M_WARNING
5515
 
               errprintf(udev->memory,
5516
 
                  "ESC/P2-Open: FMT_ESCNMY cannot handle multiple X-Passes\n");
5517
 
#endif
5518
 
            error = -1;
5519
 
         } else {
5520
 
            upd->writer = upd_wrtescnm;
5521
 
         }
5522
 
      break;
5523
 
      default:
5524
 
#if      UPD_MESSAGES & UPD_M_WARNING
5525
 
            errprintf(udev->memory,
5526
 
               "ESC/P2-Open: %d is not a ESC/P2-Format\n",
5527
 
               upd->choice[C_FORMAT]);
5528
 
#endif
5529
 
         error = - 1;
5530
 
      break;
5531
 
   }
5532
 
 
5533
 
/**
5534
 
If all this is correct, it's time to compute the size of the output-buffer.
5535
 
It must hold:
5536
 
  1. Y-Positioning
5537
 
  2. X-Positioning
5538
 
  3. Component-Selection
5539
 
  4. The Raster-Command
5540
 
  5. The Data
5541
 
*/
5542
 
   if(0 <= error) {
5543
 
      int32_t i,noutbuf,need;
5544
 
      /* Y-Positioning */
5545
 
      if(0 < upd->strings[S_YMOVE].size) {
5546
 
         noutbuf = upd->strings[S_YMOVE].size + 2;
5547
 
      } else {
5548
 
         int nmax = upd->pheight;
5549
 
         if(      1 < upd->ints[I_YSTEP]) nmax /=  upd->ints[I_YSTEP];
5550
 
         else if(-1 > upd->ints[I_YSTEP]) nmax *= -upd->ints[I_YSTEP];
5551
 
         noutbuf  = 2 * upd->strings[S_SETLF].size + 2;
5552
 
         noutbuf += nmax/255 + 1;
5553
 
      }
5554
 
 
5555
 
      if(1 < upd->ints[I_YSTEP])
5556
 
         noutbuf += (upd->ints[I_YSTEP]-1) * upd->strings[S_YSTEP].size;
5557
 
 
5558
 
      /* X-Positioning */
5559
 
      if(0 == upd->strings[S_XMOVE].size) {
5560
 
         noutbuf += 1; /* The CR */
5561
 
         noutbuf += (upd->ints[I_NXPASS]-1) * upd->strings[S_XSTEP].size;
5562
 
      } else {
5563
 
         noutbuf +=  upd->strings[S_XMOVE].size + 2;
5564
 
 
5565
 
         if(1 < upd->ints[I_XSTEP])
5566
 
            noutbuf += (upd->ints[I_XSTEP]-1) * upd->strings[S_XSTEP].size;
5567
 
      }
5568
 
 
5569
 
      /* Component-Selection */
5570
 
      if(0 < upd->string_a[SA_SETCOMP].size) {
5571
 
          need = 0;
5572
 
          for(i = 0; i < upd->ocomp; ++i)
5573
 
             if(need < upd->string_a[SA_SETCOMP].data[i].size)
5574
 
                need = upd->string_a[SA_SETCOMP].data[i].size;
5575
 
          noutbuf += need;
5576
 
      }
5577
 
 
5578
 
      /* The Raster-Command */
5579
 
      need = 0;
5580
 
      for(i = 0; i < upd->ocomp; ++i)
5581
 
         if(need < upd->string_a[SA_WRITECOMP].data[i].size)
5582
 
            need = upd->string_a[SA_WRITECOMP].data[i].size;
5583
 
      noutbuf += need + 2;
5584
 
 
5585
 
      /* The Data */
5586
 
      noutbuf += 2*upd->nbytes + (upd->nbytes + 127) / 128;
5587
 
 
5588
 
      upd->noutbuf      = noutbuf;
5589
 
      error             = 1;
5590
 
   }
5591
 
 
5592
 
   return error;
5593
 
}
5594
 
 
5595
 
/* ------------------------------------------------------------------- */
5596
 
/* upd_wrtescp2: Write a pass                                          */
5597
 
/* ------------------------------------------------------------------- */
5598
 
 
5599
 
static int
5600
 
upd_wrtescp2(upd_p upd, FILE *out)
5601
 
{
5602
 
   int  pinbot,pin,pintop,xbegin,x,xend,icomp,ybegin,yend,y,ioutbuf,n;
5603
 
   byte *obytes;
5604
 
   updscan_p scan;
5605
 
 
5606
 
/** Determine the number of pins to write */
5607
 
 
5608
 
   if(upd->yscan < upd->ints[I_BEG_Y]) {
5609
 
      pintop = 0;
5610
 
      pinbot = upd->int_a[IA_BEGBOT].data[upd->ipass];
5611
 
   } else if(upd->yscan >= upd->ints[I_END_Y]) {
5612
 
      pinbot = upd->ints[I_PINS2WRITE];
5613
 
      pintop = pinbot - upd->int_a[IA_ENDTOP].data[upd->ipass];
5614
 
   } else {
5615
 
      pintop = 0;
5616
 
      pinbot = upd->ints[I_PINS2WRITE];
5617
 
   }
5618
 
 
5619
 
   ybegin =  pintop * upd->ints[I_NYPASS] + upd->yscan - upd->ints[I_BEGSKIP];
5620
 
   yend   =  pinbot * upd->ints[I_NYPASS] + upd->yscan - upd->ints[I_BEGSKIP];
5621
 
 
5622
 
/** Determine Width of this scan */
5623
 
 
5624
 
   xbegin = upd->nbytes;
5625
 
   xend   = -1;
5626
 
 
5627
 
   for(y = ybegin; y < yend; y += upd->ints[I_NYPASS]) { /* Pin-testloop */
5628
 
 
5629
 
      if(0 > y) continue; /* Inserted Scanlines */
5630
 
 
5631
 
      scan = upd->scnbuf[y & upd->scnmsk];
5632
 
 
5633
 
      for(icomp = 0; icomp < upd->ocomp; ++icomp) { /* Compwise test */
5634
 
         obytes = scan[icomp].bytes;
5635
 
 
5636
 
         for(x = 0; x < xbegin && !obytes[x]; x++);
5637
 
         if(x < xbegin) xbegin = x;
5638
 
 
5639
 
         if(x < upd->nbytes) {
5640
 
            for(x = upd->nbytes-1; x > xend && !obytes[x]; x--);
5641
 
            if(x > xend) xend = x;
5642
 
         }
5643
 
      }                                             /* Compwise test */
5644
 
 
5645
 
   }                                                     /* Pin-testloop */
5646
 
 
5647
 
   if(xbegin <= xend) { /* Some data to write */
5648
 
 
5649
 
      ioutbuf = 0;
5650
 
 
5651
 
      if(0 == upd->strings[S_XMOVE].size) xbegin = 0;
5652
 
 
5653
 
/*
5654
 
 *    Adjust the Printers Y-Position
5655
 
 */
5656
 
      if(upd->yscan != upd->yprinter) { /* Adjust Y-Position */
5657
 
         if(B_YABS & upd->flags) y = upd->yscan + upd->ints[I_YOFS];
5658
 
         else                    y = upd->yscan - upd->yprinter;
5659
 
 
5660
 
         if(      1 < upd->ints[I_YSTEP]) {
5661
 
            n      =  y / upd->ints[I_YSTEP];  /* Major-Steps */
5662
 
            y     -=  n * upd->ints[I_YSTEP];  /* Minor-Steps */
5663
 
         } else if(-1 > upd->ints[I_YSTEP]) {
5664
 
            n      = y * -upd->ints[I_YSTEP];  /* May this work? */
5665
 
            y      = 0;
5666
 
         } else {
5667
 
            n      = y;
5668
 
            y      = 0;
5669
 
         }
5670
 
 
5671
 
         if(n) { /* Coarse Positioning */
5672
 
            memcpy(upd->outbuf+ioutbuf,
5673
 
                       upd->strings[S_YMOVE].data,upd->strings[S_YMOVE].size);
5674
 
            ioutbuf += upd->strings[S_YMOVE].size;
5675
 
 
5676
 
            upd->outbuf[ioutbuf++] =  n     & 0xff;
5677
 
            upd->outbuf[ioutbuf++] = (n>>8) & 0xff;
5678
 
 
5679
 
         }       /* Coarse Positioning */
5680
 
 
5681
 
         if(0 < upd->strings[S_YSTEP].size) {
5682
 
            while(y--) {
5683
 
               memcpy(upd->outbuf+ioutbuf,
5684
 
                          upd->strings[S_YSTEP].data,
5685
 
                          upd->strings[S_YSTEP].size);
5686
 
               ioutbuf += upd->strings[S_YSTEP].size;
5687
 
            }
5688
 
         }
5689
 
 
5690
 
         upd->yprinter = upd->yscan;
5691
 
      }                                 /* Adjust Y-Position */
5692
 
/*
5693
 
 * Now write the required components
5694
 
 */
5695
 
      for(icomp = 0; icomp < upd->ocomp; ++icomp) { /* Component-Print */
5696
 
/*
5697
 
 *       First check, wether this Component needs printing
5698
 
 */
5699
 
         for(y = ybegin; y < yend; y += upd->ints[I_NYPASS]) { /* Comp-Test */
5700
 
            if(0 > y) continue;
5701
 
            obytes = upd->scnbuf[y & upd->scnmsk][icomp].bytes;
5702
 
            for(x = xbegin; x <= xend && !obytes[x]; ++x);
5703
 
            if(             x <= xend) break;
5704
 
         }                                                     /* Comp-Test */
5705
 
         if(y >= yend) continue; /* Component not required */
5706
 
/*
5707
 
 *       Select the Component
5708
 
 */
5709
 
         if((0 < upd->string_a[SA_SETCOMP].size) &&
5710
 
            (upd->icomp != icomp               )   ) { /* Selection enabled */
5711
 
            upd->icomp = icomp;
5712
 
            if(0 < upd->string_a[SA_SETCOMP].data[icomp].size) {
5713
 
               memcpy(upd->outbuf+ioutbuf,
5714
 
                          upd->string_a[SA_SETCOMP].data[icomp].data,
5715
 
                          upd->string_a[SA_SETCOMP].data[icomp].size);
5716
 
               ioutbuf += upd->string_a[SA_SETCOMP].data[icomp].size;
5717
 
            }
5718
 
         }                                      /* Selection enabled */
5719
 
/*
5720
 
 *       Establish the X-Position
5721
 
 */
5722
 
         if(xbegin != upd->xprinter) {
5723
 
 
5724
 
            if(0 == upd->strings[S_XMOVE].size) {
5725
 
 
5726
 
               upd->outbuf[ioutbuf++] = '\r';
5727
 
               upd->xprinter          =  0;
5728
 
               n = 0;
5729
 
               x = 0;
5730
 
 
5731
 
            } else {
5732
 
 
5733
 
               if(B_XABS & upd->flags) n = x = xbegin + upd->ints[I_XOFS];
5734
 
               else                    n = x = xbegin - upd->xprinter;
5735
 
 
5736
 
               if(        1 < upd->ints[I_XSTEP]) {
5737
 
                  if(0 > n) {
5738
 
                     n  -= upd->ints[I_XSTEP];
5739
 
                     x  -= n;
5740
 
                  }
5741
 
                  if(n) n  /= upd->ints[I_XSTEP]; /* Major-Steps */
5742
 
                  if(x) x  %= upd->ints[I_XSTEP]; /* Minor-Steps */
5743
 
 
5744
 
               } else if(-1 > upd->ints[I_XSTEP]) {
5745
 
                  n *= -upd->ints[I_XSTEP]; /* May this work? */
5746
 
                  x  = 0;
5747
 
               }
5748
 
 
5749
 
               if(n) { /* Adjust X-Position */
5750
 
 
5751
 
                 memcpy(upd->outbuf+ioutbuf,
5752
 
                             upd->strings[S_XMOVE].data,
5753
 
                             upd->strings[S_XMOVE].size);
5754
 
                  ioutbuf += upd->strings[S_XMOVE].size;
5755
 
 
5756
 
                  upd->outbuf[ioutbuf++] =  n     & 0xff;
5757
 
                  upd->outbuf[ioutbuf++] = (n>>8) & 0xff;
5758
 
 
5759
 
               }       /* Adjust X-Position */
5760
 
 
5761
 
            }
5762
 
 
5763
 
            if(x && 0 < upd->strings[S_XSTEP].size) { /* Fine-Adjust X */
5764
 
               while(x--) {
5765
 
                  memcpy(upd->outbuf+ioutbuf,
5766
 
                             upd->strings[S_XSTEP].data,
5767
 
                             upd->strings[S_XSTEP].size);
5768
 
                  ioutbuf += upd->strings[S_XSTEP].size;
5769
 
               }
5770
 
            }                                         /* Fine-Adjust X */
5771
 
         }
5772
 
         upd->xprinter = xend+1;
5773
 
 
5774
 
/*
5775
 
 *       Send the Write-Command
5776
 
 */
5777
 
         if(0 < upd->string_a[SA_WRITECOMP].data[icomp].size) {
5778
 
            memcpy(upd->outbuf+ioutbuf,
5779
 
                       upd->string_a[SA_WRITECOMP].data[icomp].data,
5780
 
                       upd->string_a[SA_WRITECOMP].data[icomp].size);
5781
 
            ioutbuf += upd->string_a[SA_WRITECOMP].data[icomp].size;
5782
 
         }
5783
 
         n = xend + 1 - xbegin;
5784
 
         upd->outbuf[ioutbuf++] = (n<<3) & 255;
5785
 
         upd->outbuf[ioutbuf++] = (n>>5) & 255;
5786
 
/*
5787
 
 *       Set the Pixels
5788
 
 */
5789
 
         for(pin = 0; pin < pintop; ++pin) {
5790
 
            ioutbuf += upd_rle(upd->outbuf+ioutbuf,NULL,n);
5791
 
            fwrite(upd->outbuf,1,ioutbuf,out);
5792
 
            ioutbuf = 0;
5793
 
         }
5794
 
 
5795
 
         for(y = ybegin; 0 > y;    y += upd->ints[I_NYPASS]) {
5796
 
            ioutbuf += upd_rle(upd->outbuf+ioutbuf,NULL,n);
5797
 
            fwrite(upd->outbuf,1,ioutbuf,out);
5798
 
            ioutbuf = 0;
5799
 
         }
5800
 
 
5801
 
         for(; y < yend; y += upd->ints[I_NYPASS]) {
5802
 
            ioutbuf += upd_rle(upd->outbuf+ioutbuf,
5803
 
               upd->scnbuf[y & upd->scnmsk][icomp].bytes+xbegin,n);
5804
 
            fwrite(upd->outbuf,1,ioutbuf,out);
5805
 
            ioutbuf = 0;
5806
 
         }
5807
 
 
5808
 
         for(pin = pinbot; pin < upd->ints[I_PINS2WRITE]; ++pin) {
5809
 
            ioutbuf += upd_rle(upd->outbuf+ioutbuf,NULL,n);
5810
 
            fwrite(upd->outbuf,1,ioutbuf,out);
5811
 
            ioutbuf = 0;
5812
 
         }
5813
 
      }                                             /* Component-Print */
5814
 
   }                    /* Some data to write */
5815
 
 
5816
 
/** Advance counters in upd, change modi */
5817
 
   if(upd->yscan < upd->ints[I_BEG_Y]) {
5818
 
      upd->yscan += upd->int_a[IA_BEG_DY].data[upd->ipass++];
5819
 
      if(     upd->ints[I_BEG_Y] <= upd->yscan) upd->ipass = 0;
5820
 
      else if(upd->int_a[IA_BEG_DY].size <= upd->ipass) upd->ipass = 0;
5821
 
   } else if(upd->yscan >= upd->ints[I_END_Y]) {
5822
 
      upd->yscan += upd->int_a[IA_END_DY].data[upd->ipass++];
5823
 
      if(upd->int_a[IA_END_DY].size <= upd->ipass) upd->ipass = 0;
5824
 
   } else {
5825
 
      upd->yscan += upd->int_a[IA_STD_DY].data[upd->ipass++];
5826
 
      if(upd->int_a[IA_STD_DY].size <= upd->ipass) upd->ipass = 0;
5827
 
      if(upd->yscan >= upd->ints[I_END_Y])         upd->ipass = 0;
5828
 
   }
5829
 
 
5830
 
   return 0;
5831
 
}
5832
 
 
5833
 
/* ------------------------------------------------------------------- */
5834
 
/* upd_wrtescnm: Write a pass                                          */
5835
 
/* ------------------------------------------------------------------- */
5836
 
 
5837
 
/*GR copied from upd_wrtescp2 and modified */
5838
 
 
5839
 
static int
5840
 
upd_wrtescnm(upd_p upd, FILE *out)
5841
 
{
5842
 
   int  pinbot,pin,pintop,xbegin,x,xend,icomp,ybegin,yend,y,ioutbuf,n;
5843
 
   int  irow,imask,iyofs;
5844
 
   byte *obytes;
5845
 
   updscan_p scan;
5846
 
 
5847
 
/** Determine the number of pins to write */
5848
 
 
5849
 
   if(upd->yscan < upd->ints[I_BEG_Y]) {
5850
 
      pintop = 0;
5851
 
      pinbot = upd->int_a[IA_BEGBOT].data[upd->ipass];
5852
 
   } else if(upd->yscan >= upd->ints[I_END_Y]) {
5853
 
      pinbot = upd->ints[I_PINS2WRITE];
5854
 
      pintop = pinbot - upd->int_a[IA_ENDTOP].data[upd->ipass];
5855
 
   } else {
5856
 
      pintop = 0;
5857
 
      pinbot = upd->ints[I_PINS2WRITE];
5858
 
   }
5859
 
 
5860
 
   ybegin =  pintop * upd->ints[I_NYPASS] + upd->yscan - upd->ints[I_BEGSKIP];
5861
 
   yend   =  pinbot * upd->ints[I_NYPASS] + upd->yscan - upd->ints[I_BEGSKIP];
5862
 
 
5863
 
/** Determine Width of this scan */
5864
 
 
5865
 
   xbegin = upd->nbytes;
5866
 
   xend   = -1;
5867
 
 
5868
 
   for(y = ybegin; y < yend; y += upd->ints[I_NYPASS]) { /* Pin-testloop */
5869
 
 
5870
 
      if(0 > y) continue; /* Inserted Scanlines */
5871
 
 
5872
 
      scan = upd->scnbuf[y & upd->scnmsk];
5873
 
 
5874
 
      for(icomp = 0; icomp < upd->ocomp; ++icomp) { /* Compwise test */
5875
 
         obytes = scan[icomp].bytes;
5876
 
 
5877
 
         for(x = 0; x < xbegin && !obytes[x]; x++);
5878
 
         if(x < xbegin) xbegin = x;
5879
 
 
5880
 
         if(x < upd->nbytes) {
5881
 
            for(x = upd->nbytes-1; x > xend && !obytes[x]; x--);
5882
 
            if(x > xend) xend = x;
5883
 
         }
5884
 
      }                                             /* Compwise test */
5885
 
   }                                                     /* Pin-testloop */
5886
 
 
5887
 
   if(xbegin <= xend) { /* Some data to write */
5888
 
 
5889
 
      ioutbuf = 0;
5890
 
 
5891
 
      if(0 == upd->strings[S_XMOVE].size) xbegin = 0;
5892
 
 
5893
 
/*
5894
 
 *    Adjust the Printers Y-Position
5895
 
 */
5896
 
      if(upd->yscan != upd->yprinter) { /* Adjust Y-Position */
5897
 
         if(B_YABS & upd->flags) y = upd->yscan + upd->ints[I_YOFS];
5898
 
         else                    y = upd->yscan - upd->yprinter;
5899
 
 
5900
 
         if(      1 < upd->ints[I_YSTEP]) {
5901
 
            n      =  y / upd->ints[I_YSTEP];  /* Major-Steps */
5902
 
            y     -=  n * upd->ints[I_YSTEP];  /* Minor-Steps */
5903
 
         } else if(-1 > upd->ints[I_YSTEP]) {
5904
 
            n      = y * -upd->ints[I_YSTEP];  /* May this work? */
5905
 
            y      = 0;
5906
 
         } else {
5907
 
            n      = y;
5908
 
            y      = 0;
5909
 
         }
5910
 
 
5911
 
         if(n) { /* Coarse Positioning */
5912
 
            memcpy(upd->outbuf+ioutbuf,
5913
 
                       upd->strings[S_YMOVE].data,upd->strings[S_YMOVE].size);
5914
 
            ioutbuf += upd->strings[S_YMOVE].size;
5915
 
 
5916
 
            upd->outbuf[ioutbuf++] =  n     & 0xff;
5917
 
            upd->outbuf[ioutbuf++] = (n>>8) & 0xff;
5918
 
 
5919
 
         }       /* Coarse Positioning */
5920
 
 
5921
 
         if(0 < upd->strings[S_YSTEP].size) {
5922
 
            while(y--) {
5923
 
               memcpy(upd->outbuf+ioutbuf,
5924
 
                          upd->strings[S_YSTEP].data,
5925
 
                          upd->strings[S_YSTEP].size);
5926
 
               ioutbuf += upd->strings[S_YSTEP].size;
5927
 
            }
5928
 
         }
5929
 
 
5930
 
         upd->yprinter = upd->yscan;
5931
 
      }                                 /* Adjust Y-Position */
5932
 
/*
5933
 
 * Now write the required components
5934
 
 */
5935
 
 
5936
 
/*
5937
 
*     Select the Component
5938
 
*
5939
 
*     Always issue an ESC 'r' 0 - don't know why - that
5940
 
*     is just what the windows driver does.
5941
 
*/
5942
 
      icomp=0;
5943
 
      if((0 < upd->string_a[SA_SETCOMP].size) /* &&
5944
 
         (upd->icomp != icomp               )   */) { /* Selection enabled */
5945
 
         upd->icomp = icomp;
5946
 
         if(0 < upd->string_a[SA_SETCOMP].data[icomp].size) {
5947
 
            memcpy(upd->outbuf+ioutbuf,
5948
 
                       upd->string_a[SA_SETCOMP].data[icomp].data,
5949
 
                       upd->string_a[SA_SETCOMP].data[icomp].size);
5950
 
            ioutbuf += upd->string_a[SA_SETCOMP].data[icomp].size;
5951
 
         }
5952
 
      }                                      /* Selection enabled */
5953
 
/*
5954
 
*     Establish the X-Position
5955
 
*/
5956
 
      if(xbegin != upd->xprinter) {
5957
 
 
5958
 
         if(0 == upd->strings[S_XMOVE].size) {
5959
 
 
5960
 
            upd->outbuf[ioutbuf++] = '\r';
5961
 
            upd->xprinter          =  0;
5962
 
            n = 0;
5963
 
            x = 0;
5964
 
 
5965
 
         } else {
5966
 
 
5967
 
            if(B_XABS & upd->flags) n = x = xbegin + upd->ints[I_XOFS];
5968
 
            else                    n = x = xbegin - upd->xprinter;
5969
 
 
5970
 
            if(        1 < upd->ints[I_XSTEP]) {
5971
 
               if(0 > n) {
5972
 
                  n  -= upd->ints[I_XSTEP];
5973
 
                  x  -= n;
5974
 
               }
5975
 
               if(n) n  /= upd->ints[I_XSTEP]; /* Major-Steps */
5976
 
               if(x) x  %= upd->ints[I_XSTEP]; /* Minor-Steps */
5977
 
 
5978
 
            } else if(-1 > upd->ints[I_XSTEP]) {
5979
 
               n *= -upd->ints[I_XSTEP]; /* May this work? */
5980
 
               x  = 0;
5981
 
            }
5982
 
 
5983
 
            if(n) { /* Adjust X-Position */
5984
 
 
5985
 
              memcpy(upd->outbuf+ioutbuf,
5986
 
                          upd->strings[S_XMOVE].data,
5987
 
                          upd->strings[S_XMOVE].size);
5988
 
               ioutbuf += upd->strings[S_XMOVE].size;
5989
 
 
5990
 
               upd->outbuf[ioutbuf++] =  n     & 0xff;
5991
 
               upd->outbuf[ioutbuf++] = (n>>8) & 0xff;
5992
 
 
5993
 
            }       /* Adjust X-Position */
5994
 
 
5995
 
         }
5996
 
 
5997
 
         if(x && 0 < upd->strings[S_XSTEP].size) { /* Fine-Adjust X */
5998
 
            while(x--) {
5999
 
               memcpy(upd->outbuf+ioutbuf,
6000
 
                          upd->strings[S_XSTEP].data,
6001
 
                          upd->strings[S_XSTEP].size);
6002
 
               ioutbuf += upd->strings[S_XSTEP].size;
6003
 
            }
6004
 
         }                                         /* Fine-Adjust X */
6005
 
      }
6006
 
      upd->xprinter = xend+1;
6007
 
 
6008
 
/*
6009
 
*     Send the Write-Command - the default is ESC '.' 1
6010
 
*/
6011
 
      if(0 < upd->string_a[SA_WRITECOMP].data[icomp].size) {
6012
 
         memcpy(upd->outbuf+ioutbuf,
6013
 
                    upd->string_a[SA_WRITECOMP].data[icomp].data,
6014
 
                    upd->string_a[SA_WRITECOMP].data[icomp].size);
6015
 
         ioutbuf += upd->string_a[SA_WRITECOMP].data[icomp].size;
6016
 
      }
6017
 
      n = xend + 1 - xbegin;
6018
 
      upd->outbuf[ioutbuf++] = (n<<3) & 255;
6019
 
      upd->outbuf[ioutbuf++] = (n>>5) & 255;
6020
 
/*
6021
 
*       Set the Pixels
6022
 
*/
6023
 
      irow=0; /* row counter for output data */
6024
 
 
6025
 
      /*  pins at the top of the head that don't print */
6026
 
      for(pin = 0; pin < pintop; ++pin) {
6027
 
         int i;
6028
 
         for(i=0 ; i < upd->ints[I_PATRPT]; i++){
6029
 
            if(irow >= upd->ints[I_ROWS]) break;
6030
 
            ioutbuf += upd_rle(upd->outbuf+ioutbuf,NULL,n);
6031
 
            fwrite(upd->outbuf,1,ioutbuf,out);
6032
 
            irow++;
6033
 
            ioutbuf = 0;
6034
 
         }
6035
 
      }
6036
 
 
6037
 
      /*  I'm not really sure what this does */
6038
 
      /* it looks like we're filling in empty rows */
6039
 
      for(y = ybegin; 0 > y;    y += upd->ints[I_NYPASS]) {
6040
 
 
6041
 
         int i;
6042
 
         for(i=0 ; i < upd->ints[I_PATRPT]; i++){
6043
 
            if(irow >= upd->ints[I_ROWS]) break;
6044
 
            ioutbuf += upd_rle(upd->outbuf+ioutbuf,NULL,n);
6045
 
            fwrite(upd->outbuf,1,ioutbuf,out);
6046
 
            ioutbuf = 0;
6047
 
            irow++;
6048
 
         }
6049
 
      }
6050
 
 
6051
 
      for(; y < yend; y += upd->ints[I_NYPASS]) {
6052
 
 
6053
 
         int i,masklen=upd->ints[I_PATRPT],yinc=0;
6054
 
 
6055
 
         for(i=0 ; (i < upd->ints[I_PATRPT]); i++){
6056
 
            if(irow >= upd->ints[I_ROWS]) break;
6057
 
            imask = irow%masklen;
6058
 
            icomp = upd->int_a[IA_ROWMASK].data[imask];
6059
 
            if(icomp == 0) {
6060
 
               ioutbuf += upd_rle(upd->outbuf+ioutbuf,NULL,n);
6061
 
            } else {
6062
 
               --icomp;
6063
 
               iyofs = upd->int_a[IA_SCNOFS].data[imask];
6064
 
               ioutbuf += upd_rle(upd->outbuf+ioutbuf,
6065
 
               upd->scnbuf[(y+iyofs) & upd->scnmsk][icomp].bytes+xbegin,n);
6066
 
               yinc+=upd->ints[I_NYPASS];
6067
 
            }
6068
 
            fwrite(upd->outbuf,1,ioutbuf,out);
6069
 
            ioutbuf = 0;
6070
 
            irow++;
6071
 
         }
6072
 
 
6073
 
         if (upd->ints[I_NYPASS] < upd->ints[I_PATRPT]) {
6074
 
            y+=yinc;
6075
 
            if (y > 0)
6076
 
               y-=upd->ints[I_NYPASS];
6077
 
         }
6078
 
      }
6079
 
 
6080
 
      /*  I think this is the pins at the bottom of the head that don't print */
6081
 
      for(pin = pinbot; pin < upd->ints[I_PINS2WRITE]; ++pin) {
6082
 
         int i;
6083
 
         for(i=0 ; i < upd->ints[I_PATRPT]; i++){
6084
 
            if(irow >= upd->ints[I_ROWS]) break;
6085
 
            ioutbuf += upd_rle(upd->outbuf+ioutbuf,NULL,n);
6086
 
            fwrite(upd->outbuf,1,ioutbuf,out);
6087
 
            ioutbuf = 0;
6088
 
            irow++;
6089
 
         }
6090
 
      }
6091
 
 
6092
 
      /* pad empty rows that haven't been filled yet*/
6093
 
       if (irow < upd->ints[I_ROWS]) {
6094
 
         for( ; irow < upd->ints[I_ROWS]; irow++){
6095
 
            ioutbuf += upd_rle(upd->outbuf+ioutbuf,NULL,n);
6096
 
            fwrite(upd->outbuf,1,ioutbuf,out);
6097
 
            ioutbuf = 0;
6098
 
         }
6099
 
      }
6100
 
 
6101
 
   }              /* Some data to write */
6102
 
 
6103
 
/** Advance counters in upd, change modi */
6104
 
   if(upd->yscan < upd->ints[I_BEG_Y]) {
6105
 
      upd->yscan += upd->int_a[IA_BEG_DY].data[upd->ipass++];
6106
 
      if(     upd->ints[I_BEG_Y] <= upd->yscan) upd->ipass = 0;
6107
 
      else if(upd->int_a[IA_BEG_DY].size <= upd->ipass) upd->ipass = 0;
6108
 
   } else if(upd->yscan >= upd->ints[I_END_Y]) {
6109
 
      upd->yscan += upd->int_a[IA_END_DY].data[upd->ipass++];
6110
 
      if(upd->int_a[IA_END_DY].size <= upd->ipass) upd->ipass = 0;
6111
 
   } else {
6112
 
      upd->yscan += upd->int_a[IA_STD_DY].data[upd->ipass++];
6113
 
      if(upd->int_a[IA_STD_DY].size <= upd->ipass) upd->ipass = 0;
6114
 
      if(upd->yscan >= upd->ints[I_END_Y])         upd->ipass = 0;
6115
 
   }
6116
 
 
6117
 
   return 0;
6118
 
}
6119
 
 
6120
 
/* ------------------------------------------------------------------- */
6121
 
/* upd_wrtescp2x: Write an ESC/P2-pass with X-Weaving                  */
6122
 
/* ------------------------------------------------------------------- */
6123
 
 
6124
 
static int
6125
 
upd_wrtescp2x(upd_p upd, FILE *out)
6126
 
{
6127
 
   int  pinbot,pin,pintop,xbegin,x,xend,icomp,ybegin,yend,y,ioutbuf,n,ixpass;
6128
 
   byte *obytes,bit;
6129
 
   updscan_p scan;
6130
 
 
6131
 
/** Determine the number of pins to write */
6132
 
 
6133
 
   if(upd->yscan < upd->ints[I_BEG_Y]) {
6134
 
      ixpass = upd->int_a[IA_BEG_IX].data[upd->ipass];
6135
 
      pintop = 0;
6136
 
      pinbot = upd->int_a[IA_BEGBOT].data[upd->ipass];
6137
 
   } else if(upd->yscan >= upd->ints[I_END_Y]) {
6138
 
      ixpass = upd->int_a[IA_END_IX].data[upd->ipass];
6139
 
      pinbot = upd->ints[I_PINS2WRITE];
6140
 
      pintop = pinbot - upd->int_a[IA_ENDTOP].data[upd->ipass];
6141
 
   } else {
6142
 
      ixpass = upd->int_a[IA_STD_IX].data[upd->ipass];
6143
 
      pintop = 0;
6144
 
      pinbot = upd->ints[I_PINS2WRITE];
6145
 
   }
6146
 
 
6147
 
   ybegin =  pintop * upd->ints[I_NYPASS] + upd->yscan - upd->ints[I_BEGSKIP];
6148
 
   yend   =  pinbot * upd->ints[I_NYPASS] + upd->yscan - upd->ints[I_BEGSKIP];
6149
 
 
6150
 
/** Determine Width of this scan */
6151
 
 
6152
 
   xbegin = upd->pwidth;
6153
 
   xend   = -1;
6154
 
 
6155
 
   for(y = ybegin; y < yend; y += upd->ints[I_NYPASS]) { /* Pin-testloop */
6156
 
 
6157
 
      if(0 > y) continue; /* Inserted Scanlines */
6158
 
 
6159
 
      scan = upd->scnbuf[y & upd->scnmsk];
6160
 
 
6161
 
      for(icomp = 0; icomp < upd->ocomp; ++icomp) { /* Compwise test */
6162
 
         if(xbegin > scan[icomp].xbegin[ixpass])
6163
 
            xbegin = scan[icomp].xbegin[ixpass];
6164
 
         if(xend   < scan[icomp].xend[  ixpass])
6165
 
            xend   = scan[icomp].xend[  ixpass];
6166
 
      }                                             /* Compwise test */
6167
 
 
6168
 
   }                                                     /* Pin-testloop */
6169
 
 
6170
 
   if(xbegin <= xend) { /* Some data to write */
6171
 
 
6172
 
      ioutbuf = upd->nbytes;
6173
 
 
6174
 
      if(0 == upd->strings[S_XMOVE].size) xbegin = ixpass;
6175
 
 
6176
 
/*
6177
 
 *    Adjust the Printers Y-Position
6178
 
 */
6179
 
      if(upd->yscan != upd->yprinter) { /* Adjust Y-Position */
6180
 
         if(B_YABS & upd->flags) y = upd->yscan + upd->ints[I_YOFS];
6181
 
         else                    y = upd->yscan - upd->yprinter;
6182
 
 
6183
 
         if(      1 < upd->ints[I_YSTEP]) {
6184
 
            n      =  y / upd->ints[I_YSTEP];  /* Major-Steps */
6185
 
            y     -=  n * upd->ints[I_YSTEP];  /* Minor-Steps */
6186
 
         } else if(-1 > upd->ints[I_YSTEP]) {
6187
 
            n      = y * -upd->ints[I_YSTEP];  /* May this work? */
6188
 
            y      = 0;
6189
 
         } else {
6190
 
            n      = y;
6191
 
            y      = 0;
6192
 
         }
6193
 
 
6194
 
         if(n) { /* Coarse Positioning */
6195
 
            memcpy(upd->outbuf+ioutbuf,
6196
 
                       upd->strings[S_YMOVE].data,upd->strings[S_YMOVE].size);
6197
 
            ioutbuf += upd->strings[S_YMOVE].size;
6198
 
 
6199
 
            upd->outbuf[ioutbuf++] =  n     & 0xff;
6200
 
            upd->outbuf[ioutbuf++] = (n>>8) & 0xff;
6201
 
 
6202
 
         }       /* Coarse Positioning */
6203
 
 
6204
 
         if(0 < upd->strings[S_YSTEP].size) {
6205
 
            while(y--) {
6206
 
               memcpy(upd->outbuf+ioutbuf,
6207
 
                          upd->strings[S_YSTEP].data,
6208
 
                          upd->strings[S_YSTEP].size);
6209
 
               ioutbuf += upd->strings[S_YSTEP].size;
6210
 
            }
6211
 
         }
6212
 
 
6213
 
         upd->yprinter = upd->yscan;
6214
 
      }                                 /* Adjust Y-Position */
6215
 
 
6216
 
/*
6217
 
 * Now write the required components
6218
 
 */
6219
 
      for(icomp = 0; icomp < upd->ocomp; ++icomp) { /* Component-Print */
6220
 
/*
6221
 
 *       First check, wether this Component needs printing
6222
 
 */
6223
 
         for(y = ybegin; y < yend; y += upd->ints[I_NYPASS]) { /* Comp-Test */
6224
 
            if(0 > y) continue;
6225
 
            scan = upd->scnbuf[y & upd->scnmsk]+icomp;
6226
 
            if(0 <= scan->xend[ixpass]) break;
6227
 
         }                                                     /* Comp-Test */
6228
 
         if(y >= yend) continue; /* Component not required */
6229
 
/*
6230
 
 *       Select the Component
6231
 
 */
6232
 
         if((0 < upd->string_a[SA_SETCOMP].size) &&
6233
 
            (upd->icomp != icomp               )   ) { /* Selection enabled */
6234
 
            upd->icomp = icomp;
6235
 
            if(0 < upd->string_a[SA_SETCOMP].data[icomp].size) {
6236
 
               memcpy(upd->outbuf+ioutbuf,
6237
 
                          upd->string_a[SA_SETCOMP].data[icomp].data,
6238
 
                          upd->string_a[SA_SETCOMP].data[icomp].size);
6239
 
               ioutbuf += upd->string_a[SA_SETCOMP].data[icomp].size;
6240
 
            }
6241
 
         }                                      /* Selection enabled */
6242
 
/*
6243
 
 *       Establish the X-Position
6244
 
 */
6245
 
         if(xbegin != upd->xprinter) {
6246
 
 
6247
 
            if(0 == upd->strings[S_XMOVE].size) {
6248
 
 
6249
 
               upd->outbuf[ioutbuf++] = '\r';
6250
 
               upd->xprinter          =  0;
6251
 
               n = 0;
6252
 
               x = ixpass;
6253
 
 
6254
 
            } else {
6255
 
 
6256
 
               if(B_XABS & upd->flags) n = x = xbegin + upd->ints[I_XOFS];
6257
 
               else                    n = x = xbegin - upd->xprinter;
6258
 
 
6259
 
               if(        1 < upd->ints[I_XSTEP]) {
6260
 
                  if(0 > n) {
6261
 
                     n  -= upd->ints[I_XSTEP];
6262
 
                     x  -= n;
6263
 
                  }
6264
 
                  if(n) n  /= upd->ints[I_XSTEP]; /* Major-Steps */
6265
 
                  if(x) x  %= upd->ints[I_XSTEP]; /* Minor-Steps */
6266
 
 
6267
 
               } else if(-1 > upd->ints[I_XSTEP]) {
6268
 
                  n *= -upd->ints[I_XSTEP]; /* May this work? */
6269
 
                  x  = 0;
6270
 
               }
6271
 
 
6272
 
               if(n) { /* Adjust X-Position */
6273
 
 
6274
 
                 memcpy(upd->outbuf+ioutbuf,
6275
 
                             upd->strings[S_XMOVE].data,
6276
 
                             upd->strings[S_XMOVE].size);
6277
 
                  ioutbuf += upd->strings[S_XMOVE].size;
6278
 
 
6279
 
                  upd->outbuf[ioutbuf++] =  n     & 0xff;
6280
 
                  upd->outbuf[ioutbuf++] = (n>>8) & 0xff;
6281
 
 
6282
 
               }       /* Adjust X-Position */
6283
 
 
6284
 
            }
6285
 
 
6286
 
            if(x && 0 < upd->strings[S_XSTEP].size) { /* Fine-Adjust X */
6287
 
               while(x--) {
6288
 
                  memcpy(upd->outbuf+ioutbuf,
6289
 
                             upd->strings[S_XSTEP].data,
6290
 
                             upd->strings[S_XSTEP].size);
6291
 
                  ioutbuf += upd->strings[S_XSTEP].size;
6292
 
               }
6293
 
            }                                         /* Fine-Adjust X */
6294
 
         }
6295
 
         upd->xprinter = xend+1;
6296
 
 
6297
 
/*
6298
 
 *       Send the Write-Command
6299
 
 */
6300
 
         if(0 < upd->string_a[SA_WRITECOMP].data[icomp].size) {
6301
 
            memcpy(upd->outbuf+ioutbuf,
6302
 
                       upd->string_a[SA_WRITECOMP].data[icomp].data,
6303
 
                       upd->string_a[SA_WRITECOMP].data[icomp].size);
6304
 
            ioutbuf += upd->string_a[SA_WRITECOMP].data[icomp].size;
6305
 
         }
6306
 
         n = ((xend - xbegin) / upd->ints[I_NXPASS] + 8) & ~7;
6307
 
         upd->outbuf[ioutbuf++] =  n     & 255;
6308
 
         upd->outbuf[ioutbuf++] = (n>>8) & 255;
6309
 
         n >>= 3;
6310
 
/*
6311
 
 *       Set the Pixels
6312
 
 */
6313
 
         for(pin = 0; pin < pintop; ++pin) {
6314
 
            ioutbuf += upd_rle(upd->outbuf+ioutbuf,NULL,n);
6315
 
            fwrite(upd->outbuf+upd->nbytes,1,ioutbuf-upd->nbytes,out);
6316
 
            ioutbuf = upd->nbytes;
6317
 
         }
6318
 
 
6319
 
         for(y = ybegin; 0 > y;    y += upd->ints[I_NYPASS]) {
6320
 
            ioutbuf += upd_rle(upd->outbuf+ioutbuf,NULL,n);
6321
 
            fwrite(upd->outbuf+upd->nbytes,1,ioutbuf-upd->nbytes,out);
6322
 
            ioutbuf = upd->nbytes;
6323
 
         }
6324
 
 
6325
 
         for(;           y < yend; y += upd->ints[I_NYPASS]) {
6326
 
            byte * ibytes = upd->scnbuf[y & upd->scnmsk][icomp].bytes;
6327
 
            obytes = upd->outbuf;
6328
 
            memset(obytes,0,upd->nbytes);
6329
 
            bit = 0x80;
6330
 
            for(x = xbegin; x <= xend; x += upd->ints[I_NXPASS]) {
6331
 
               if(ibytes[x>>3] & (0x80 >> (x & 7))) *obytes |= bit;
6332
 
               if(!(bit >>= 1)) { obytes++; bit = 0x80; }
6333
 
            }
6334
 
            ioutbuf += upd_rle(upd->outbuf+ioutbuf,upd->outbuf,n);
6335
 
            fwrite(upd->outbuf+upd->nbytes,1,ioutbuf-upd->nbytes,out);
6336
 
            ioutbuf = upd->nbytes;
6337
 
         }
6338
 
 
6339
 
         for(pin = pinbot; pin < upd->ints[I_PINS2WRITE]; ++pin) {
6340
 
            ioutbuf += upd_rle(upd->outbuf+ioutbuf,NULL,n);
6341
 
            fwrite(upd->outbuf+upd->nbytes,1,ioutbuf-upd->nbytes,out);
6342
 
            ioutbuf = upd->nbytes;
6343
 
         }
6344
 
      }                                             /* Component-Print */
6345
 
   }                    /* Some data to write */
6346
 
 
6347
 
/** Advance counters in upd, change modi */
6348
 
 
6349
 
   if(upd->yscan < upd->ints[I_BEG_Y]) {
6350
 
      upd->yscan += upd->int_a[IA_BEG_DY].data[upd->ipass++];
6351
 
      if(     upd->ints[I_BEG_Y] <= upd->yscan) upd->ipass = 0;
6352
 
      else if(upd->int_a[IA_BEG_DY].size <= upd->ipass) upd->ipass = 0;
6353
 
   } else if(upd->yscan >= upd->ints[I_END_Y]) {
6354
 
      upd->yscan += upd->int_a[IA_END_DY].data[upd->ipass++];
6355
 
      if(upd->int_a[IA_END_DY].size <= upd->ipass) upd->ipass = 0;
6356
 
   } else {
6357
 
      upd->yscan += upd->int_a[IA_STD_DY].data[upd->ipass++];
6358
 
      if(upd->int_a[IA_STD_DY].size <= upd->ipass) upd->ipass = 0;
6359
 
      if(upd->yscan >= upd->ints[I_END_Y])         upd->ipass = 0;
6360
 
   }
6361
 
 
6362
 
   return 0;
6363
 
}
6364
 
 
6365
 
/* ------------------------------------------------------------------- */
6366
 
/* upd_rle: The Runlength-Compressor                                   */
6367
 
/* ------------------------------------------------------------------- */
6368
 
 
6369
 
static int
6370
 
upd_rle(byte *out,const byte *in,int nbytes)
6371
 
{
6372
 
 
6373
 
   int used = 0;
6374
 
   int crun,cdata;
6375
 
   byte run;
6376
 
 
6377
 
   if(in != NULL) { /* Data present */
6378
 
 
6379
 
      crun = 1;
6380
 
 
6381
 
      while(nbytes > 0) { /* something to compress */
6382
 
 
6383
 
         run = in[0];
6384
 
 
6385
 
         while((nbytes > crun) && (run == in[crun])) if(++crun == 128) break;
6386
 
 
6387
 
         if((crun > 2) || (crun == nbytes)) { /* use this run */
6388
 
 
6389
 
            *out++  = (257 - crun) & 0xff; *out++ = run; used += 2;
6390
 
 
6391
 
            nbytes -= crun; in    += crun;
6392
 
            crun = 1;
6393
 
 
6394
 
         } else {                            /* ignore this run */
6395
 
 
6396
 
            for(cdata = crun; (nbytes > cdata) && (crun < 4);) {
6397
 
               if(run  == in[cdata]) crun += 1;
6398
 
               else run = in[cdata], crun  = 1;
6399
 
               if(++cdata == 128) break;
6400
 
            }
6401
 
 
6402
 
            if(crun < 3) crun   = 0;    /* ignore trailing run */
6403
 
            else         cdata -= crun;
6404
 
 
6405
 
            *out++ = cdata-1;     used++;
6406
 
            memcpy(out,in,cdata); used += cdata; out   += cdata;
6407
 
 
6408
 
            nbytes -= cdata; in    += cdata;
6409
 
 
6410
 
         }              /* use/ignore run */
6411
 
 
6412
 
      }                  /* something to compress */
6413
 
 
6414
 
   } else {         /* Empty scans to fill bands */
6415
 
 
6416
 
      while(nbytes > 0) {
6417
 
         crun    = nbytes > 128 ? 128 : nbytes;
6418
 
         nbytes -= crun;
6419
 
         *out++  = (257 - crun) & 0xff;
6420
 
         *out++  = 0;
6421
 
         used   += 2;
6422
 
      }
6423
 
   }                /* Data present or empty */
6424
 
   return used;
6425
 
}
6426
 
 
6427
 
/* ------------------------------------------------------------------- */
6428
 
/* upd_open_wrtrtl: Basic HP-RTL Writer                                */
6429
 
/* ------------------------------------------------------------------- */
6430
 
 
6431
 
static int
6432
 
upd_open_wrtrtl(upd_device *udev)
6433
 
{
6434
 
   const upd_p      upd  = udev->upd;
6435
 
   int              error = 0;
6436
 
 
6437
 
/** Adjust the Raster-Width */
6438
 
 
6439
 
   if(0 < upd->strings[S_BEGIN].size) { /* BOP-Checker */
6440
 
 
6441
 
     int   i,j,state;
6442
 
     char  cv[24];
6443
 
     byte  *bp;
6444
 
     uint  ncv,nbp;
6445
 
 
6446
 
     j     = -1;
6447
 
     state = 0;
6448
 
     for(i = 0; i < upd->strings[S_BEGIN].size; ++i) {
6449
 
       const int c = upd->strings[S_BEGIN].data[i];
6450
 
 
6451
 
       switch(state) {
6452
 
/* ----- any character */
6453
 
         case  0:
6454
 
           if(        c == 0x1b) state =  1; /* ESC */
6455
 
         break;
6456
 
 
6457
 
/* ----- last was ESC */
6458
 
         case  1:
6459
 
           if(        c == 0x2a) state =  2; /* ESC * */
6460
 
           else if(   c == 0x25) state =  5; /* ESC % */
6461
 
           else                  state =  0;
6462
 
         break;
6463
 
 
6464
 
/* ----- got ESC * */
6465
 
         case  2:
6466
 
           j = i; /* This character is not part of the replaced text */
6467
 
           if(        c == 0x72) state =  3; /* ESC * r */
6468
 
           else if(   c == 0x74) state =  4; /* ESC * t */
6469
 
           else                  state =  0;
6470
 
         break;
6471
 
 
6472
 
/* ----- got ESC * r */
6473
 
/*         Pagewidth and Pagelength might be replaced */
6474
 
         case  3:
6475
 
 
6476
 
           if(       (B_PAGEWIDTH  & upd->flags) &&
6477
 
                     ((c == 0x73) || (c == 0x53))  ) { /* esc * r # S */
6478
 
 
6479
 
             sprintf(cv,"%d",upd->pwidth);
6480
 
             ncv = strlen(cv);
6481
 
 
6482
 
             nbp = (j+1) + ncv + (upd->strings[S_BEGIN].size-i);
6483
 
             UPD_MM_GET_ARRAY(udev->memory, bp,nbp);
6484
 
 
6485
 
             if(0 <= j) memcpy(bp,upd->strings[S_BEGIN].data,j+1);
6486
 
             memcpy(bp+j+1,    cv,ncv);
6487
 
             memcpy(bp+j+1+ncv,upd->strings[S_BEGIN].data+i,
6488
 
                               upd->strings[S_BEGIN].size-i);
6489
 
             i = j+1+ncv;
6490
 
             UPD_MM_DEL_PARAM(udev->memory, upd->strings[S_BEGIN]);
6491
 
             upd->strings[S_BEGIN].data = bp;
6492
 
             upd->strings[S_BEGIN].size = nbp;
6493
 
 
6494
 
           } else if((B_PAGELENGTH & upd->flags) &&
6495
 
                     ((c == 0x74) || (c == 0x54))  ) { /* esc * r # T */
6496
 
 
6497
 
             sprintf(cv,"%d",upd->pheight);
6498
 
             ncv = strlen(cv);
6499
 
 
6500
 
             nbp = (j+1) + ncv + (upd->strings[S_BEGIN].size-i);
6501
 
             UPD_MM_GET_ARRAY(udev->memory, bp,nbp);
6502
 
 
6503
 
             if(0 <= j) memcpy(bp,upd->strings[S_BEGIN].data,j+1);
6504
 
             memcpy(bp+j+1,    cv,ncv);
6505
 
             memcpy(bp+j+1+ncv,upd->strings[S_BEGIN].data+i,
6506
 
                               upd->strings[S_BEGIN].size-i);
6507
 
             i = j+1+ncv;
6508
 
             UPD_MM_DEL_PARAM(udev->memory, upd->strings[S_BEGIN]);
6509
 
             upd->strings[S_BEGIN].data = bp;
6510
 
             upd->strings[S_BEGIN].size = nbp;
6511
 
 
6512
 
           }
6513
 
 
6514
 
           if(       (0x40 < c) && (c < 0x5b))  state = 0; /* Term. cmd. */
6515
 
           else if(!((0x2f < c) && (c < 0x3a))) j     = i; /* Non-Number */
6516
 
 
6517
 
         break;
6518
 
 
6519
 
/* ----- got ESC * t */
6520
 
/*         Resolution might be replaced */
6521
 
         case  4: /* esc * t */
6522
 
 
6523
 
           if(        (B_RESOLUTION  & upd->flags) &&
6524
 
                     ((c == 0x72) || (c == 0x52))  ) { /* esc * t # R */
6525
 
 
6526
 
             sprintf(cv,"%d",(int)
6527
 
               ((udev->y_pixels_per_inch < udev->x_pixels_per_inch ?
6528
 
                 udev->x_pixels_per_inch : udev->y_pixels_per_inch)
6529
 
               +0.5));
6530
 
             ncv = strlen(cv);
6531
 
 
6532
 
             nbp = (j+1) + ncv + (upd->strings[S_BEGIN].size-i);
6533
 
             UPD_MM_GET_ARRAY(udev->memory, bp,nbp);
6534
 
 
6535
 
             if(0 <= j) memcpy(bp,upd->strings[S_BEGIN].data,j+1);
6536
 
             memcpy(bp+j+1,    cv,ncv);
6537
 
             memcpy(bp+j+1+ncv,upd->strings[S_BEGIN].data+i,
6538
 
                               upd->strings[S_BEGIN].size-i);
6539
 
             i = j+1+ncv;
6540
 
             UPD_MM_DEL_PARAM(udev->memory, upd->strings[S_BEGIN]);
6541
 
             upd->strings[S_BEGIN].data = bp;
6542
 
             upd->strings[S_BEGIN].size = nbp;
6543
 
 
6544
 
           }
6545
 
 
6546
 
           if(       (0x40 < c) && (c < 0x5b))  state = 0; /* Term. cmd. */
6547
 
           else if(!((0x2f < c) && (c < 0x3a))) j     = i; /* Non-Number */
6548
 
 
6549
 
         break;
6550
 
 
6551
 
         case  5: /* ESC % - 1 2 3 4 5 X */
6552
 
           if( c == 0x2d) state =  6; /* ESC % - */
6553
 
           else           state =  0;
6554
 
         break;
6555
 
 
6556
 
         case  6: /* ESC %  - 1 2 3 4 5 X */
6557
 
           if( c == 0x31) state =  7; /* ESC % - 1 */
6558
 
           else           state =  0;
6559
 
         break;
6560
 
 
6561
 
         case  7: /* ESC %  - 1 2 3 4 5 X */
6562
 
           if( c == 0x32) state =  8; /* ESC % - 1 2 */
6563
 
           else           state =  0;
6564
 
         break;
6565
 
 
6566
 
         case  8: /* ESC %  - 1 2 3 4 5 X */
6567
 
           if( c == 0x33) state =  9; /* ESC % - 1 2 3 */
6568
 
           else           state =  0;
6569
 
         break;
6570
 
 
6571
 
         case  9: /* ESC %  - 1 2 3 4 5 X */
6572
 
           if( c == 0x34) state = 10; /* ESC % - 1 2 3 4 */
6573
 
           else           state =  0;
6574
 
         break;
6575
 
 
6576
 
         case 10: /* ESC %  - 1 2 3 4 5 X */
6577
 
           if( c == 0x35) state = 11; /* ESC % - 1 2 3 4 5 */
6578
 
           else           state =  0;
6579
 
         break;
6580
 
 
6581
 
         case 11: /* ESC %  - 1 2 3 4 5 X */
6582
 
           if( c == 0x58) state = 12; /* ESC % - 1 2 3 4 5 X */
6583
 
           else           state =  0;
6584
 
         break;
6585
 
 
6586
 
         case 12: /* PJL-BOL:  @ P J L ws */
6587
 
           if( c == 0x40) state = 13; /* @ */
6588
 
           else           state =  0;
6589
 
         break;
6590
 
 
6591
 
         case 13: /* PJL-BOL  @ P J L ws */
6592
 
           if( c == 0x50) state = 14; /* @ P */
6593
 
           else           state =  0;
6594
 
         break;
6595
 
 
6596
 
         case 14: /* PJL-BOL  @ P J L ws */
6597
 
           if( c == 0x4a) state = 15; /* @ P J */
6598
 
           else           state =  0;
6599
 
         break;
6600
 
 
6601
 
         case 15: /* PJL-BOL  @ P J L ws */
6602
 
           if( c == 0x4c) state = 16; /* @ P J L */
6603
 
           else           state =  0;
6604
 
         break;
6605
 
 
6606
 
         case 16: /* PJL-BOL  @ P J L ws */
6607
 
           if((c == 0x20) || (c == 0x09)) state = 19; /* @ P J L ws */
6608
 
           else if(           c == 0x0d ) state = 17;
6609
 
           else if(           c == 0x0a ) state = 12;
6610
 
           else                           state =  0; /* PJL-Error */
6611
 
         break;
6612
 
 
6613
 
         case 17: /* PJL-EOL  */
6614
 
           if( c == 0x0a) state = 12; /* Next PJL-Command */
6615
 
           else           state =  0; /* PJL-Error */
6616
 
         break;
6617
 
 
6618
 
         case 18: /* PJL-Eatup: Expect Newline */
6619
 
           if( c == 0x0a) state = 12;
6620
 
         break;
6621
 
 
6622
 
         case 19: /* Begin of PJL-Command */
6623
 
           if(     (c == 0x53) || (c == 0x73)) state = 20; /* S E T*/
6624
 
           else if( c == 0x0a                ) state = 12; /* BOL */
6625
 
           else if( c == 0x0d                ) state = 17;
6626
 
         break;
6627
 
 
6628
 
         case 20: /* PJL-Set: S E T  */
6629
 
           if(     (c == 0x45) || (c == 0x65)) state = 21; /* S E */
6630
 
           else if( c == 0x0a                ) state = 12; /* BOL */
6631
 
           else                                state = 18;
6632
 
         break;
6633
 
 
6634
 
         case 21: /* PJL-Set: S E T  */
6635
 
           if(     (c == 0x54) || (c == 0x74)) state = 22; /* S E T */
6636
 
           else if( c == 0x0a                ) state = 12; /* BOL */
6637
 
           else                                state = 18;
6638
 
         break;
6639
 
 
6640
 
         case 22: /* PJL-Set: S E T ws  */
6641
 
           if(     (c == 0x20) || (c == 0x09)) state = 23; /* S E T ws */
6642
 
           else if( c == 0x0a                ) state = 12; /* BOL */
6643
 
           else                                state = 18;
6644
 
         break;
6645
 
 
6646
 
         case 23: /* PJL-Set: S E T ws  */
6647
 
           if(     (c == 0x50) || (c == 0x70)) state = 24; /* set paper... */
6648
 
           else if((c == 0x52) || (c == 0x72)) state = 41; /* set resolution */
6649
 
           else if( c == 0x0a                ) state = 12; /* BOL */
6650
 
           else                                state = 18;
6651
 
         break;
6652
 
 
6653
 
         case 24: /* PJL-Set: set paper...  */
6654
 
           if(     (c == 0x41) || (c == 0x61)) state = 25; /* set pa */
6655
 
           else if( c == 0x0a                ) state = 12; /* BOL */
6656
 
           else                                state = 18;
6657
 
         break;
6658
 
 
6659
 
         case 25: /* PJL-Set: set paper...  */
6660
 
           if(     (c == 0x50) || (c == 0x70)) state = 26; /* set pap */
6661
 
           else if( c == 0x0a                ) state = 12; /* BOL */
6662
 
           else                                state = 18;
6663
 
         break;
6664
 
 
6665
 
         case 26: /* PJL-Set: set paper...  */
6666
 
           if(     (c == 0x45) || (c == 0x65)) state = 27; /* set pape */
6667
 
           else if( c == 0x0a                ) state = 12; /* BOL */
6668
 
           else                                state = 18;
6669
 
         break;
6670
 
 
6671
 
         case 27: /* PJL-Set: set paper...  */
6672
 
           if(     (c == 0x52) || (c == 0x72)) state = 28; /* set paper */
6673
 
           else if( c == 0x0a                ) state = 12; /* BOL */
6674
 
           else                                state = 18;
6675
 
         break;
6676
 
 
6677
 
         case 28: /* PJL-Set: set paper?  */
6678
 
           if(     (c == 0x4c) || (c == 0x6c)) state = 29; /* set paperlength */
6679
 
           else if((c == 0x57) || (c == 0x77)) state = 36; /* set paperwidth */
6680
 
           else if( c == 0x0a                ) state = 12; /* BOL */
6681
 
           else                                state = 18;
6682
 
         break;
6683
 
 
6684
 
         case 29: /* PJL: set paperlength  */
6685
 
           if(     (c == 0x45) || (c == 0x65)) state = 30; /* set paperle */
6686
 
           else if( c == 0x0a                ) state = 12; /* BOL */
6687
 
           else                                state = 18;
6688
 
         break;
6689
 
 
6690
 
         case 30: /* PJL: set paperlength  */
6691
 
           if(     (c == 0x4e) || (c == 0x6e)) state = 31; /* set paperlen */
6692
 
           else if( c == 0x0a                ) state = 12; /* BOL */
6693
 
           else                                state = 18;
6694
 
         break;
6695
 
 
6696
 
         case 31: /* PJL: set paperlength  */
6697
 
           if(     (c == 0x47) || (c == 0x67)) state = 32; /* set paperleng */
6698
 
           else if( c == 0x0a                ) state = 12; /* BOL */
6699
 
           else                                state = 18;
6700
 
         break;
6701
 
 
6702
 
         case 32: /* PJL: set paperlength  */
6703
 
           if(     (c == 0x54) || (c == 0x74)) state = 33; /* set paperlengt */
6704
 
           else if( c == 0x0a                ) state = 12; /* BOL */
6705
 
           else                                state = 18;
6706
 
         break;
6707
 
 
6708
 
         case 33: /* PJL: set paperlength  */
6709
 
           if(     (c == 0x48) || (c == 0x68)) state = 34; /* set paperlength */
6710
 
           else if( c == 0x0a                ) state = 12; /* BOL */
6711
 
           else                                state = 18;
6712
 
         break;
6713
 
 
6714
 
         case 34: /* PJL: set paperlength  */
6715
 
           j = i; /* This character is not part of the replaced text */
6716
 
           if(      c == 0x3d                ) state = 51; /* set paperlength */
6717
 
           else if( c == 0x0a                ) state = 12; /* BOL */
6718
 
           else if((c != 0x20) && (c != 0x09)) state = 18;
6719
 
         break;
6720
 
 
6721
 
         case 51: /* PJL: set paperlength = ws */
6722
 
           if(     c == 0x0a)                  state = 12;
6723
 
           else if((c == 0x20) || (c == 0x09)) j     = i;
6724
 
           else if(( 0x30 > c) || ( c > 0x39)) state = 18;
6725
 
           else                                state = 35;
6726
 
         break;
6727
 
 
6728
 
         case 35: /* PJL: set paperlength */
6729
 
           if((0x30 > c) || (c > 0x39)) { /* End of number */
6730
 
 
6731
 
             if(B_PAGELENGTH  & upd->flags) { /* insert new number */
6732
 
 
6733
 
               sprintf(cv,"%d",(int)
6734
 
                 (720.0 * udev->height / udev->y_pixels_per_inch + 0.5));
6735
 
               ncv = strlen(cv);
6736
 
 
6737
 
               nbp = (j+1) + ncv + (upd->strings[S_BEGIN].size-i);
6738
 
               UPD_MM_GET_ARRAY(udev->memory, bp,nbp);
6739
 
 
6740
 
               if(0 <= j) memcpy(bp,upd->strings[S_BEGIN].data,j+1);
6741
 
               memcpy(bp+j+1,    cv,ncv);
6742
 
               memcpy(bp+j+1+ncv,upd->strings[S_BEGIN].data+i,
6743
 
                               upd->strings[S_BEGIN].size-i);
6744
 
               i = j+1+ncv;
6745
 
               UPD_MM_DEL_PARAM(udev->memory, upd->strings[S_BEGIN]);
6746
 
               upd->strings[S_BEGIN].data = bp;
6747
 
               upd->strings[S_BEGIN].size = nbp;
6748
 
             }                                /* insert new number */
6749
 
 
6750
 
             if( c == 0x0a ) state = 12;
6751
 
             else            state = 18;
6752
 
           }
6753
 
         break;
6754
 
 
6755
 
         case 36: /* PJL: set paperwidth  */
6756
 
           if(     (c == 0x49) || (c == 0x69)) state = 37; /* set paperwi */
6757
 
           else if( c == 0x0a                ) state = 12; /* BOL */
6758
 
           else                                state = 18;
6759
 
         break;
6760
 
 
6761
 
         case 37: /* PJL: set paperwidth */
6762
 
           if(     (c == 0x44) || (c == 0x64)) state = 38; /* set paperwid */
6763
 
           else if( c == 0x0a                ) state = 12; /* BOL */
6764
 
           else                                state = 18;
6765
 
         break;
6766
 
 
6767
 
         case 38: /* PJL: set paperwidth  */
6768
 
           if(     (c == 0x54) || (c == 0x74)) state = 39; /* set paperwidt */
6769
 
           else if( c == 0x0a                ) state = 12; /* BOL */
6770
 
           else                                state = 18;
6771
 
         break;
6772
 
 
6773
 
         case 39: /* PJL: set paperwidth  */
6774
 
           if(     (c == 0x48) || (c == 0x68)) state = 52; /* set paperwidth */
6775
 
           else if( c == 0x0a                ) state = 12; /* BOL */
6776
 
           else                                state = 18;
6777
 
         break;
6778
 
 
6779
 
         case 52: /* PJL: set paperwidth  */
6780
 
           j = i; /* This character is not part of the replaced text */
6781
 
           if(      c == 0x3d                ) state = 53; /* set paperwidth */
6782
 
           else if( c == 0x0a                ) state = 12; /* BOL */
6783
 
           else if((c != 0x20) && (c != 0x09)) state = 18;
6784
 
         break;
6785
 
 
6786
 
         case 53: /* PJL: set paperwidth = ws */
6787
 
           if(     c == 0x0a)                  state = 12;
6788
 
           else if((c == 0x20) || (c == 0x09)) j     = i;
6789
 
           else if(( 0x30 > c) || ( c > 0x39)) state = 18;
6790
 
           else                                state = 40;
6791
 
         break;
6792
 
 
6793
 
         case 40: /* PJL: set paperlength */
6794
 
           if((0x30 > c) || (c > 0x39)) { /* End of number */
6795
 
 
6796
 
             if(B_PAGEWIDTH  & upd->flags) { /* insert new number */
6797
 
 
6798
 
               sprintf(cv,"%d",(int)
6799
 
                 (720.0 * udev->width / udev->x_pixels_per_inch + 0.5));
6800
 
               ncv = strlen(cv);
6801
 
 
6802
 
               nbp = (j+1) + ncv + (upd->strings[S_BEGIN].size-i);
6803
 
               UPD_MM_GET_ARRAY(udev->memory, bp,nbp);
6804
 
 
6805
 
               if(0 <= j) memcpy(bp,upd->strings[S_BEGIN].data,j+1);
6806
 
               memcpy(bp+j+1,    cv,ncv);
6807
 
               memcpy(bp+j+1+ncv,upd->strings[S_BEGIN].data+i,
6808
 
                               upd->strings[S_BEGIN].size-i);
6809
 
               i = j+1+ncv;
6810
 
               UPD_MM_DEL_PARAM(udev->memory, upd->strings[S_BEGIN]);
6811
 
               upd->strings[S_BEGIN].data = bp;
6812
 
               upd->strings[S_BEGIN].size = nbp;
6813
 
             }                                /* insert new number */
6814
 
 
6815
 
             if( c == 0x0a ) state = 12;
6816
 
             else            state = 18;
6817
 
           }
6818
 
         break;
6819
 
 
6820
 
         case 41: /* PJL: set resolution */
6821
 
           if(     (c == 0x45) || (c == 0x65)) state = 42; /* set re */
6822
 
           else if( c == 0x0a                ) state = 12; /* BOL */
6823
 
           else                                state = 18;
6824
 
         break;
6825
 
 
6826
 
         case 42: /* PJL: set resolution */
6827
 
           if(     (c == 0x53) || (c == 0x73)) state = 43; /* set res */
6828
 
           else if( c == 0x0a                ) state = 12; /* BOL */
6829
 
           else                                state = 18;
6830
 
         break;
6831
 
 
6832
 
         case 43: /* PJL: set resolution */
6833
 
           if(     (c == 0x4f) || (c == 0x6f)) state = 44; /* set reso */
6834
 
           else if( c == 0x0a                ) state = 12; /* BOL */
6835
 
           else                                state = 18;
6836
 
         break;
6837
 
 
6838
 
         case 44: /* PJL: set resolution */
6839
 
           if(     (c == 0x4c) || (c == 0x6c)) state = 45; /* set resol */
6840
 
           else if( c == 0x0a                ) state = 12; /* BOL */
6841
 
           else                                state = 18;
6842
 
         break;
6843
 
 
6844
 
         case 45: /* PJL: set resolution */
6845
 
           if(     (c == 0x55) || (c == 0x75)) state = 46; /* set resolu */
6846
 
           else if( c == 0x0a                ) state = 12; /* BOL */
6847
 
           else                                state = 18;
6848
 
         break;
6849
 
 
6850
 
         case 46: /* PJL: set resolution */
6851
 
           if(     (c == 0x54) || (c == 0x74)) state = 47; /* set resolut */
6852
 
           else if( c == 0x0a                ) state = 12; /* BOL */
6853
 
           else                                state = 18;
6854
 
         break;
6855
 
 
6856
 
         case 47: /* PJL: set resolution */
6857
 
           if(     (c == 0x49) || (c == 0x69)) state = 48; /* set resoluti */
6858
 
           else if( c == 0x0a                ) state = 12; /* BOL */
6859
 
           else                                state = 18;
6860
 
         break;
6861
 
 
6862
 
         case 48: /* PJL: set resolution */
6863
 
           if(     (c == 0x4f) || (c == 0x6f)) state = 49; /* set resolutio */
6864
 
           else if( c == 0x0a                ) state = 12; /* BOL */
6865
 
           else                                state = 18;
6866
 
         break;
6867
 
 
6868
 
         case 49: /* PJL: set resolution */
6869
 
           if(     (c == 0x4e) || (c == 0x6e)) state = 54; /* set resolution */
6870
 
           else if( c == 0x0a                ) state = 12; /* BOL */
6871
 
           else                                state = 18;
6872
 
         break;
6873
 
 
6874
 
         case 54: /* PJL: set resolution  */
6875
 
           j = i; /* This character is not part of the replaced text */
6876
 
           if(      c == 0x3d                ) state = 55; /* set resolution */
6877
 
           else if( c == 0x0a                ) state = 12; /* BOL */
6878
 
           else if((c != 0x20) && (c != 0x09)) state = 18;
6879
 
         break;
6880
 
 
6881
 
         case 55: /* PJL: set resolution = ws */
6882
 
           if(     c == 0x0a)                  state = 12;
6883
 
           else if((c == 0x20) || (c == 0x09)) j     = i;
6884
 
           else if(( 0x30 > c) || ( c > 0x39)) state = 18;
6885
 
           else                                state = 50;
6886
 
         break;
6887
 
 
6888
 
         case 50: /* PJL: set resolution */
6889
 
           if((0x30 > c) || (c > 0x39)) { /* End of number */
6890
 
 
6891
 
             if(B_RESOLUTION  & upd->flags) { /* insert new number */
6892
 
 
6893
 
               sprintf(cv,"%d",(int)
6894
 
                 ((udev->y_pixels_per_inch < udev->x_pixels_per_inch ?
6895
 
                   udev->x_pixels_per_inch : udev->y_pixels_per_inch)
6896
 
                 +0.5));
6897
 
               ncv = strlen(cv);
6898
 
 
6899
 
               nbp = (j+1) + ncv + (upd->strings[S_BEGIN].size-i);
6900
 
               UPD_MM_GET_ARRAY(udev->memory, bp,nbp);
6901
 
 
6902
 
               if(0 <= j) memcpy(bp,upd->strings[S_BEGIN].data,j+1);
6903
 
               memcpy(bp+j+1,    cv,ncv);
6904
 
               memcpy(bp+j+1+ncv,upd->strings[S_BEGIN].data+i,
6905
 
                               upd->strings[S_BEGIN].size-i);
6906
 
               i = j+1+ncv;
6907
 
               UPD_MM_DEL_PARAM(udev->memory, upd->strings[S_BEGIN]);
6908
 
               upd->strings[S_BEGIN].data = bp;
6909
 
               upd->strings[S_BEGIN].size = nbp;
6910
 
             }                                /* insert new number */
6911
 
 
6912
 
             if( c == 0x0a ) state = 12;
6913
 
             else            state = 18;
6914
 
           }
6915
 
         break;
6916
 
 
6917
 
         default:
6918
 
#if UPD_MESSAGES & UPD_M_ERROR
6919
 
           errprintf(udev->memory,
6920
 
                     "UNIPRINT-Coding error, wrrtl, state = %d\n",state);
6921
 
#endif
6922
 
           state = 0;
6923
 
         break;
6924
 
       }
6925
 
     }
6926
 
   }                                    /* BOP-Checker */
6927
 
 
6928
 
/** SA_WRITECOMP must be valid */
6929
 
   if(upd->ocomp > upd->string_a[SA_WRITECOMP].size) {
6930
 
#if UPD_MESSAGES & UPD_M_WARNING
6931
 
      errprintf(udev->memory,
6932
 
         "PCL-Open: WRITECOMP-Commands must be given\n");
6933
 
#endif
6934
 
      error = -1;
6935
 
   }
6936
 
 
6937
 
/**
6938
 
If all this is correct, it's time to compute the size of the output-buffer.
6939
 
It must hold:
6940
 
  1. Y-Positioning
6941
 
  2. Component-Data
6942
 
*/
6943
 
   if(0 <= error) {
6944
 
      int32_t ny,noutbuf;
6945
 
      char  tmp[16];
6946
 
 
6947
 
      if(0 < upd->strings[S_YMOVE].size) {
6948
 
         sprintf(tmp,"%d",upd->pheight);
6949
 
         ny = upd->strings[S_YMOVE].size + strlen(tmp);
6950
 
      } else {
6951
 
         ny = 1 + upd->string_a[SA_WRITECOMP].data[upd->ocomp-1].size;
6952
 
         ny *= upd->pheight;
6953
 
      }
6954
 
 
6955
 
      noutbuf = upd->nbytes + (upd->nbytes + 127) / 128;
6956
 
 
6957
 
      if(ny > noutbuf) noutbuf = ny;
6958
 
      noutbuf += 16;
6959
 
 
6960
 
      if((0 < noutbuf) && (noutbuf <= INT_MAX)) {
6961
 
         upd->noutbuf      = noutbuf;
6962
 
         upd->writer       = upd_wrtrtl;
6963
 
         error             = 1;
6964
 
      } else {
6965
 
         error = -1;
6966
 
#if      UPD_MESSAGES & UPD_M_WARNING
6967
 
            errprintf(udev->memory,
6968
 
              "PCL-Open: %ld is unreasonable size of Outputbuffer\n",
6969
 
              (long) noutbuf);
6970
 
#endif
6971
 
      }
6972
 
   }
6973
 
 
6974
 
   return error;
6975
 
}
6976
 
 
6977
 
/* ------------------------------------------------------------------- */
6978
 
/* upd_wrtrtl: Write a pass                                            */
6979
 
/* ------------------------------------------------------------------- */
6980
 
 
6981
 
static int
6982
 
upd_wrtrtl(upd_p upd, FILE *out)
6983
 
{
6984
 
   const updscan_p scan = upd->scnbuf[upd->yscan & upd->scnmsk];
6985
 
 
6986
 
   int  x,xend,icomp,ioutbuf;
6987
 
   byte *data;
6988
 
 
6989
 
/** Determine Width of this scan */
6990
 
 
6991
 
   xend   = -1;
6992
 
   for(icomp = 0; icomp < upd->ocomp; ++icomp) {
6993
 
 
6994
 
      data = scan[icomp].bytes;
6995
 
 
6996
 
      for(x = upd->nbytes-1; 0 <= x; --x) if(data[x]) break;
6997
 
      if(x > xend) xend  = x;
6998
 
   }
6999
 
 
7000
 
   if(0 <= xend) { /* Some data to write */
7001
 
 
7002
 
      ioutbuf = 0;
7003
 
      xend   += 1;
7004
 
/*
7005
 
 *    Adjust the Printers Y-Position
7006
 
 */
7007
 
      if(upd->yscan != upd->yprinter) { /* Adjust Y-Position */
7008
 
         if(1 < upd->strings[S_YMOVE].size) {
7009
 
           sprintf((char *)upd->outbuf+ioutbuf,
7010
 
             (const char *) upd->strings[S_YMOVE].data,
7011
 
             upd->yscan - upd->yprinter);
7012
 
           ioutbuf += strlen((char *)upd->outbuf+ioutbuf);
7013
 
         } else {
7014
 
           while(upd->yscan > upd->yprinter) {
7015
 
             for(icomp = 0; icomp < upd->ocomp; ++icomp) {
7016
 
               sprintf((char *)upd->outbuf+ioutbuf,
7017
 
                 (const char *) upd->string_a[SA_WRITECOMP].data[icomp].data,0);
7018
 
               ioutbuf += strlen((char *)upd->outbuf+ioutbuf);
7019
 
             }
7020
 
             fwrite(upd->outbuf,1,ioutbuf,out);
7021
 
             ioutbuf = 0;
7022
 
             upd->yprinter += 1;
7023
 
           }
7024
 
         }
7025
 
         upd->yprinter = upd->yscan;
7026
 
         fwrite(upd->outbuf,1,ioutbuf,out);
7027
 
         ioutbuf = 0;
7028
 
      }                                 /* Adjust Y-Position */
7029
 
/*
7030
 
 * Now write the all! components
7031
 
 */
7032
 
      for(icomp = 0; icomp < upd->ocomp; ++icomp) { /* Component-Print */
7033
 
         data = scan[icomp].bytes;
7034
 
         for(x = 0; x <= xend; ++x) if(data[x]) break;
7035
 
         if(x <= xend) {
7036
 
           ioutbuf = upd_rle(upd->outbuf,scan[icomp].bytes,xend);
7037
 
           fprintf(out,
7038
 
            (const char *)upd->string_a[SA_WRITECOMP].data[icomp].data,ioutbuf);
7039
 
            fwrite(upd->outbuf,1,ioutbuf,out);
7040
 
         } else {
7041
 
           fprintf(out,
7042
 
             (const char *)upd->string_a[SA_WRITECOMP].data[icomp].data,0);
7043
 
         }
7044
 
      }
7045
 
 
7046
 
      upd->yprinter += 1;
7047
 
 
7048
 
   }                    /* Some data to write */
7049
 
 
7050
 
/** Advance scan by one */
7051
 
 
7052
 
   upd->yscan += 1;
7053
 
 
7054
 
   return 0;
7055
 
}
7056
 
 
7057
 
/* ------------------------------------------------------------------- */
7058
 
/* upd_open_wrtcanon: Basic Canon Extended Mode Writer (hr)            */
7059
 
/* ------------------------------------------------------------------- */
7060
 
 
7061
 
static int
7062
 
upd_open_wrtcanon(upd_device *udev)
7063
 
{
7064
 
  const upd_p upd = udev->upd;
7065
 
  int error = 0;
7066
 
 
7067
 
  /* max length of one printer line */
7068
 
  upd->noutbuf = upd->nbytes + (upd->nbytes + 127) / 128;
7069
 
  upd->writer  = upd_wrtcanon;
7070
 
  error        = 1;
7071
 
 
7072
 
  return error;
7073
 
}
7074
 
 
7075
 
/* ------------------------------------------------------------------- */
7076
 
/* upd_wrtcanon: Write a pass (hr)                                     */
7077
 
/* ------------------------------------------------------------------- */
7078
 
 
7079
 
#define LOW(b)     ((b)&0xFF)
7080
 
#define HIGH(b)    ((b)>>8)
7081
 
#define ESC 0x1B
7082
 
#define CR  0x0D
7083
 
 
7084
 
static int
7085
 
upd_wrtcanon(upd_p upd, FILE *out)
7086
 
{
7087
 
  const updscan_p scan = upd->scnbuf[upd->yscan & upd->scnmsk];
7088
 
 
7089
 
  int x, xend, icomp, ioutbuf, step, ioutbuf1;
7090
 
  byte *data;
7091
 
 
7092
 
  /* Check length of the printable date */
7093
 
  xend = -1;
7094
 
  for(icomp = 0; icomp < upd->ocomp; ++icomp) {
7095
 
    data = scan[icomp].bytes;
7096
 
 
7097
 
    for(x = upd->nbytes-1; 0 <= x; --x) if(data[x]) break;
7098
 
 
7099
 
    if(x > xend) xend  = x;
7100
 
  }
7101
 
 
7102
 
  /* If some date to print */
7103
 
  if(0 <= xend) { /* Some data to write */
7104
 
    ioutbuf = 0;
7105
 
    xend   += 1;
7106
 
 
7107
 
    /* Perform vertical tab */
7108
 
    if(upd->yscan != upd->yprinter) {
7109
 
      step = upd->yscan - upd->yprinter;
7110
 
 
7111
 
      fputc(ESC,        out);
7112
 
      fputc('(',        out);
7113
 
      fputc('e',        out);
7114
 
      fputc(2,          out);
7115
 
      fputc(0,          out);
7116
 
      fputc(HIGH(step), out);
7117
 
      fputc(LOW(step),  out);
7118
 
 
7119
 
      upd->yprinter = upd->yscan;
7120
 
    }
7121
 
 
7122
 
    for(icomp = 0; icomp < upd->ocomp; ++icomp) {
7123
 
 
7124
 
      /* Are there date to print for the selected color component */
7125
 
      data = scan[icomp].bytes;
7126
 
      for(x = 0; x <= xend; ++x) if(data[x]) break;
7127
 
 
7128
 
      /* Compressing of the scan line */
7129
 
      if(x <= xend) {
7130
 
        ioutbuf = upd_rle(upd->outbuf, scan[icomp].bytes, xend);
7131
 
      } else {
7132
 
        ioutbuf = 0;
7133
 
      }
7134
 
 
7135
 
      ioutbuf1 = ioutbuf + 1;
7136
 
 
7137
 
      /* prints the scan line */
7138
 
      fputc(ESC,            out);
7139
 
      fputc('(',            out);
7140
 
      fputc('A',            out);
7141
 
      fputc(LOW(ioutbuf1),  out);
7142
 
      fputc(HIGH(ioutbuf1), out);
7143
 
      switch(upd->ocomp) {
7144
 
        case 1:  fputc('K',out); break;
7145
 
        case 3:
7146
 
        case 4:  fputc("YMCK"[icomp],out); break;
7147
 
/*
7148
 
 *      Please Note:
7149
 
 *         the validity of the NCOMP-setting should be checked
7150
 
 *         in the put_params-routine, thus the default-case is
7151
 
 *         just a matter of coding-style.
7152
 
 */
7153
 
        default: fputc('K',out); break;
7154
 
      }
7155
 
 
7156
 
      fwrite(upd->outbuf, 1, ioutbuf, out);
7157
 
 
7158
 
      fputc(CR,             out);
7159
 
    }
7160
 
 
7161
 
    /* Printer advances one raster line */
7162
 
    fputc(ESC,        out);
7163
 
    fputc('(',        out);
7164
 
    fputc('e',        out);
7165
 
    fputc(2,          out);
7166
 
    fputc(0,          out);
7167
 
    fputc(HIGH(1),    out);
7168
 
    fputc(LOW(1),     out);
7169
 
 
7170
 
    upd->yprinter += 1;
7171
 
 
7172
 
  }
7173
 
 
7174
 
  /* Advance scan by one */
7175
 
  upd->yscan += 1;
7176
 
 
7177
 
  return 0;
7178
 
}
7179
 
 
7180
 
/* ------------------------------------------------------------------- */
7181
 
/* All the Pixel-Get Routines                                          */
7182
 
/* ------------------------------------------------------------------- */
7183
 
 
7184
 
/* That bunch of Pixel-Get Routines */
7185
 
 
7186
 
static upd_proc_pxlget(upd_pxlgetnix); /* A Dummy */
7187
 
 
7188
 
static upd_proc_pxlget(upd_pxlget1f1); /* 1 Bit Forward */
7189
 
static upd_proc_pxlget(upd_pxlget1f2);
7190
 
static upd_proc_pxlget(upd_pxlget1f3);
7191
 
static upd_proc_pxlget(upd_pxlget1f4);
7192
 
static upd_proc_pxlget(upd_pxlget1f5);
7193
 
static upd_proc_pxlget(upd_pxlget1f6);
7194
 
static upd_proc_pxlget(upd_pxlget1f7);
7195
 
static upd_proc_pxlget(upd_pxlget1f8);
7196
 
 
7197
 
static upd_proc_pxlget(upd_pxlget1r1); /* 1 Bit Reverse */
7198
 
static upd_proc_pxlget(upd_pxlget1r2);
7199
 
static upd_proc_pxlget(upd_pxlget1r3);
7200
 
static upd_proc_pxlget(upd_pxlget1r4);
7201
 
static upd_proc_pxlget(upd_pxlget1r5);
7202
 
static upd_proc_pxlget(upd_pxlget1r6);
7203
 
static upd_proc_pxlget(upd_pxlget1r7);
7204
 
static upd_proc_pxlget(upd_pxlget1r8);
7205
 
 
7206
 
static upd_proc_pxlget(upd_pxlget2f1); /* 2 Bit Forward */
7207
 
static upd_proc_pxlget(upd_pxlget2f2);
7208
 
static upd_proc_pxlget(upd_pxlget2f3);
7209
 
static upd_proc_pxlget(upd_pxlget2f4);
7210
 
 
7211
 
static upd_proc_pxlget(upd_pxlget2r1); /* 2 Bit Reverse */
7212
 
static upd_proc_pxlget(upd_pxlget2r2);
7213
 
static upd_proc_pxlget(upd_pxlget2r3);
7214
 
static upd_proc_pxlget(upd_pxlget2r4);
7215
 
 
7216
 
static upd_proc_pxlget(upd_pxlget4f1); /* 4 Bit Forward */
7217
 
static upd_proc_pxlget(upd_pxlget4f2);
7218
 
 
7219
 
static upd_proc_pxlget(upd_pxlget4r1); /* 4 Bit Reverse */
7220
 
static upd_proc_pxlget(upd_pxlget4r2);
7221
 
 
7222
 
static upd_proc_pxlget(upd_pxlget8f);  /* 8 Bit Forward */
7223
 
static upd_proc_pxlget(upd_pxlget8r);  /* 8 Bit Reverse */
7224
 
 
7225
 
static upd_proc_pxlget(upd_pxlget16f); /* 16 Bit Forward */
7226
 
static upd_proc_pxlget(upd_pxlget16r); /* 16Bit Reverse */
7227
 
 
7228
 
static upd_proc_pxlget(upd_pxlget24f); /* 24 Bit Forward */
7229
 
static upd_proc_pxlget(upd_pxlget24r); /* 24 Bit Reverse */
7230
 
 
7231
 
static upd_proc_pxlget(upd_pxlget32f); /* 32 Bit Forward */
7232
 
static upd_proc_pxlget(upd_pxlget32r); /* 32 Bit Reverse */
7233
 
 
7234
 
/* Initialize Forward-Run */
7235
 
 
7236
 
static uint32_t
7237
 
upd_pxlfwd(upd_p upd)
7238
 
{
7239
 
   if(!(upd->pxlptr = upd->gsscan)) {
7240
 
 
7241
 
      upd->pxlget = upd_pxlgetnix;
7242
 
 
7243
 
   } else {
7244
 
      switch(upd->int_a[IA_COLOR_INFO].data[1]) {
7245
 
         case  1: upd->pxlget = upd_pxlget1f1; break;
7246
 
         case  2: upd->pxlget = upd_pxlget2f1; break;
7247
 
         case  4: upd->pxlget = upd_pxlget4f1; break;
7248
 
         case  8: upd->pxlget = upd_pxlget8f;  break;
7249
 
         case 16: upd->pxlget = upd_pxlget16f; break;
7250
 
         case 24: upd->pxlget = upd_pxlget24f; break;
7251
 
         case 32: upd->pxlget = upd_pxlget32f; break;
7252
 
         default:
7253
 
#if UPD_MESSAGES & UPD_M_ERROR
7254
 
           errprintf(upd->memory, "upd_pxlfwd: unsupported depth (%d)\n",
7255
 
                     upd->int_a[IA_COLOR_INFO].data[1]);
7256
 
#endif
7257
 
           upd->pxlget = upd_pxlgetnix;
7258
 
           break;
7259
 
      }
7260
 
   }
7261
 
   return (uint32_t) 0;
7262
 
}
7263
 
 
7264
 
/* 1 Bit Forward */
7265
 
 
7266
 
static uint32_t
7267
 
upd_pxlget1f1(upd_p upd)
7268
 
{
7269
 
   upd->pxlget = upd_pxlget1f2;
7270
 
   return *upd->pxlptr   & 0x80 ? (uint32_t) 1 : (uint32_t) 0;
7271
 
}
7272
 
 
7273
 
static uint32_t
7274
 
upd_pxlget1f2(upd_p upd)
7275
 
{
7276
 
   upd->pxlget = upd_pxlget1f3;
7277
 
   return *upd->pxlptr   & 0x40 ? (uint32_t) 1 : (uint32_t) 0;
7278
 
}
7279
 
 
7280
 
static uint32_t
7281
 
upd_pxlget1f3(upd_p upd)
7282
 
{
7283
 
   upd->pxlget = upd_pxlget1f4;
7284
 
   return *upd->pxlptr   & 0x20 ? (uint32_t) 1 : (uint32_t) 0;
7285
 
}
7286
 
 
7287
 
static uint32_t
7288
 
upd_pxlget1f4(upd_p upd)
7289
 
{
7290
 
   upd->pxlget = upd_pxlget1f5;
7291
 
   return *upd->pxlptr   & 0x10 ? (uint32_t) 1 : (uint32_t) 0;
7292
 
}
7293
 
 
7294
 
static uint32_t
7295
 
upd_pxlget1f5(upd_p upd)
7296
 
{
7297
 
   upd->pxlget = upd_pxlget1f6;
7298
 
   return *upd->pxlptr   & 0x08 ? (uint32_t) 1 : (uint32_t) 0;
7299
 
}
7300
 
 
7301
 
static uint32_t
7302
 
upd_pxlget1f6(upd_p upd)
7303
 
{
7304
 
   upd->pxlget = upd_pxlget1f7;
7305
 
   return *upd->pxlptr   & 0x04 ? (uint32_t) 1 : (uint32_t) 0;
7306
 
}
7307
 
 
7308
 
static uint32_t
7309
 
upd_pxlget1f7(upd_p upd)
7310
 
{
7311
 
   upd->pxlget = upd_pxlget1f8;
7312
 
   return *upd->pxlptr   & 0x02 ? (uint32_t) 1 : (uint32_t) 0;
7313
 
}
7314
 
 
7315
 
static uint32_t
7316
 
upd_pxlget1f8(upd_p upd)
7317
 
{
7318
 
   upd->pxlget = upd_pxlget1f1;
7319
 
   return *upd->pxlptr++ & 0x01 ? (uint32_t) 1 : (uint32_t) 0;
7320
 
}
7321
 
 
7322
 
/* 2 Bit Forward */
7323
 
 
7324
 
static uint32_t
7325
 
upd_pxlget2f1(upd_p upd)
7326
 
{
7327
 
   upd->pxlget = upd_pxlget2f2;
7328
 
   return ((uint32_t) (*upd->pxlptr  ) & (uint32_t) 0xC0) >> 6;
7329
 
}
7330
 
 
7331
 
static uint32_t
7332
 
upd_pxlget2f2(upd_p upd)
7333
 
{
7334
 
   upd->pxlget = upd_pxlget2f3;
7335
 
   return ((uint32_t) (*upd->pxlptr  ) & (uint32_t) 0x30) >> 4;
7336
 
}
7337
 
 
7338
 
static uint32_t
7339
 
upd_pxlget2f3(upd_p upd)
7340
 
{
7341
 
   upd->pxlget = upd_pxlget2f4;
7342
 
   return ((uint32_t) (*upd->pxlptr  ) & (uint32_t) 0x0C) >> 2;
7343
 
}
7344
 
 
7345
 
static uint32_t
7346
 
upd_pxlget2f4(upd_p upd)
7347
 
{
7348
 
   upd->pxlget = upd_pxlget2f1;
7349
 
   return  (uint32_t) (*upd->pxlptr++) & (uint32_t) 0x03;
7350
 
}
7351
 
 
7352
 
/* 4 Bit Forward */
7353
 
static uint32_t
7354
 
upd_pxlget4f1(upd_p upd)
7355
 
{
7356
 
   upd->pxlget = upd_pxlget4f2;
7357
 
   return ((uint32_t) (*upd->pxlptr  ) & (uint32_t) 0xF0) >> 4;
7358
 
}
7359
 
 
7360
 
static uint32_t
7361
 
upd_pxlget4f2(upd_p upd)
7362
 
{
7363
 
   upd->pxlget = upd_pxlget4f1;
7364
 
   return  (uint32_t) (*upd->pxlptr++) & (uint32_t) 0x0F;
7365
 
}
7366
 
 
7367
 
/* 8 Bit Forward */
7368
 
static uint32_t
7369
 
upd_pxlget8f(upd_p upd)
7370
 
{
7371
 
   return (uint32_t) (*upd->pxlptr++);
7372
 
}
7373
 
 
7374
 
/* 16 Bit Forward */
7375
 
static uint32_t
7376
 
upd_pxlget16f(upd_p upd)
7377
 
{
7378
 
   uint32_t ci  = (uint32_t) (*upd->pxlptr++) << 8;
7379
 
                  ci |=                   *upd->pxlptr++;
7380
 
   return         ci;
7381
 
}
7382
 
 
7383
 
/* 24 Bit Forward */
7384
 
static uint32_t
7385
 
upd_pxlget24f(upd_p upd)
7386
 
{
7387
 
   uint32_t ci  = (uint32_t) (*upd->pxlptr++) << 16;
7388
 
          ci |= (uint32_t) (*upd->pxlptr++) <<  8;
7389
 
          ci |=           *upd->pxlptr++;
7390
 
   return ci;
7391
 
}
7392
 
 
7393
 
/* 32 Bit Forward */
7394
 
static uint32_t
7395
 
upd_pxlget32f(upd_p upd)
7396
 
{
7397
 
   uint32_t ci  = (uint32_t) (*upd->pxlptr++) << 24;
7398
 
                  ci |= (uint32_t) (*upd->pxlptr++) << 16;
7399
 
                  ci |= (uint32_t) (*upd->pxlptr++) <<  8;
7400
 
                  ci |=                   *upd->pxlptr++;
7401
 
   return         ci;
7402
 
}
7403
 
 
7404
 
/* Dummy-Routine */
7405
 
 
7406
 
static uint32_t
7407
 
upd_pxlgetnix(upd_p upd)
7408
 
{
7409
 
   return (uint32_t) 0;
7410
 
}
7411
 
 
7412
 
/* Initialize Reverse-Run */
7413
 
 
7414
 
static uint32_t
7415
 
upd_pxlrev(upd_p upd)
7416
 
{
7417
 
   const uint width = upd->pwidth < upd->gswidth ? upd->pwidth : upd->gswidth;
7418
 
 
7419
 
   if(!(upd->pxlptr = upd->gsscan)) {
7420
 
 
7421
 
      upd->pxlget = upd_pxlgetnix;
7422
 
 
7423
 
   } else {
7424
 
      uint32_t ofs = (uint32_t) upd->int_a[IA_COLOR_INFO].data[1] * (width-1);
7425
 
 
7426
 
      upd->pxlptr += ofs>>3;
7427
 
 
7428
 
      ofs &= 7;
7429
 
 
7430
 
      switch(upd->int_a[IA_COLOR_INFO].data[1]) {
7431
 
         case  1: switch(ofs) {
7432
 
               case 0:  upd->pxlget = upd_pxlget1r1; break;
7433
 
               case 1:  upd->pxlget = upd_pxlget1r2; break;
7434
 
               case 2:  upd->pxlget = upd_pxlget1r3; break;
7435
 
               case 3:  upd->pxlget = upd_pxlget1r4; break;
7436
 
               case 4:  upd->pxlget = upd_pxlget1r5; break;
7437
 
               case 5:  upd->pxlget = upd_pxlget1r6; break;
7438
 
               case 6:  upd->pxlget = upd_pxlget1r7; break;
7439
 
               case 7:  upd->pxlget = upd_pxlget1r8; break;
7440
 
            } break;
7441
 
         case  2: switch(ofs) {
7442
 
               case 0:  upd->pxlget = upd_pxlget2r1; break;
7443
 
               case 2:  upd->pxlget = upd_pxlget2r2; break;
7444
 
               case 4:  upd->pxlget = upd_pxlget2r3; break;
7445
 
               case 6:  upd->pxlget = upd_pxlget2r4; break;
7446
 
            } break;
7447
 
         case  4: switch(ofs) {
7448
 
               case 0:  upd->pxlget = upd_pxlget4r1; break;
7449
 
               case 4:  upd->pxlget = upd_pxlget4r2; break;
7450
 
            } break;
7451
 
         case  8: upd->pxlget = upd_pxlget8r;  break;
7452
 
         case 16:
7453
 
            upd->pxlget  = upd_pxlget16r;
7454
 
            upd->pxlptr += 1;
7455
 
            break;
7456
 
         case 24:
7457
 
            upd->pxlget = upd_pxlget24r;
7458
 
            upd->pxlptr += 2;
7459
 
            break;
7460
 
         case 32:
7461
 
            upd->pxlget = upd_pxlget32r;
7462
 
            upd->pxlptr += 3;
7463
 
            break;
7464
 
         default:
7465
 
#if UPD_MESSAGES & UPD_M_ERROR
7466
 
           errprintf(upd->memory, "upd_pxlrev: unsupported depth (%d)\n",
7467
 
                     upd->int_a[IA_COLOR_INFO].data[1]);
7468
 
#endif
7469
 
           upd->pxlget = upd_pxlgetnix;
7470
 
           break;
7471
 
      }
7472
 
   }
7473
 
   return (uint32_t) 0;
7474
 
}
7475
 
 
7476
 
/* 1 Bit Reverse */
7477
 
 
7478
 
static uint32_t
7479
 
upd_pxlget1r1(upd_p upd)
7480
 
{
7481
 
   upd->pxlget = upd_pxlget1r8;
7482
 
   return *upd->pxlptr-- & 0x80 ? (uint32_t) 1 : (uint32_t) 0;
7483
 
}
7484
 
 
7485
 
static uint32_t
7486
 
upd_pxlget1r2(upd_p upd)
7487
 
{
7488
 
   upd->pxlget = upd_pxlget1r1;
7489
 
   return *upd->pxlptr   & 0x40 ? (uint32_t) 1 : (uint32_t) 0;
7490
 
}
7491
 
 
7492
 
static uint32_t
7493
 
upd_pxlget1r3(upd_p upd)
7494
 
{
7495
 
   upd->pxlget = upd_pxlget1r2;
7496
 
   return *upd->pxlptr   & 0x20 ? (uint32_t) 1 : (uint32_t) 0;
7497
 
}
7498
 
 
7499
 
static uint32_t
7500
 
upd_pxlget1r4(upd_p upd)
7501
 
{
7502
 
   upd->pxlget = upd_pxlget1r3;
7503
 
   return *upd->pxlptr   & 0x10 ? (uint32_t) 1 : (uint32_t) 0;
7504
 
}
7505
 
 
7506
 
static uint32_t
7507
 
upd_pxlget1r5(upd_p upd)
7508
 
{
7509
 
   upd->pxlget = upd_pxlget1r4;
7510
 
   return *upd->pxlptr   & 0x08 ? (uint32_t) 1 : (uint32_t) 0;
7511
 
}
7512
 
 
7513
 
static uint32_t
7514
 
upd_pxlget1r6(upd_p upd)
7515
 
{
7516
 
   upd->pxlget = upd_pxlget1r5;
7517
 
   return *upd->pxlptr   & 0x04 ? (uint32_t) 1 : (uint32_t) 0;
7518
 
}
7519
 
 
7520
 
static uint32_t
7521
 
upd_pxlget1r7(upd_p upd)
7522
 
{
7523
 
   upd->pxlget = upd_pxlget1r6;
7524
 
   return *upd->pxlptr   & 0x02 ? (uint32_t) 1 : (uint32_t) 0;
7525
 
}
7526
 
 
7527
 
static uint32_t
7528
 
upd_pxlget1r8(upd_p upd)
7529
 
{
7530
 
   upd->pxlget = upd_pxlget1r7;
7531
 
   return *upd->pxlptr   & 0x01 ? (uint32_t) 1 : (uint32_t) 0;
7532
 
}
7533
 
 
7534
 
/* 2 Bit Reverse */
7535
 
 
7536
 
static uint32_t
7537
 
upd_pxlget2r1(upd_p upd)
7538
 
{
7539
 
   upd->pxlget = upd_pxlget2r4;
7540
 
   return ((uint32_t) (*upd->pxlptr--) & (uint32_t) 0xC0) >> 6;
7541
 
}
7542
 
 
7543
 
static uint32_t
7544
 
upd_pxlget2r2(upd_p upd)
7545
 
{
7546
 
   upd->pxlget = upd_pxlget2r1;
7547
 
   return ((uint32_t) (*upd->pxlptr  ) & (uint32_t) 0x30) >> 4;
7548
 
}
7549
 
 
7550
 
static uint32_t
7551
 
upd_pxlget2r3(upd_p upd)
7552
 
{
7553
 
   upd->pxlget = upd_pxlget2r2;
7554
 
   return ((uint32_t) (*upd->pxlptr  ) & (uint32_t) 0x0C) >> 2;
7555
 
}
7556
 
 
7557
 
static uint32_t
7558
 
upd_pxlget2r4(upd_p upd)
7559
 
{
7560
 
   upd->pxlget = upd_pxlget2r3;
7561
 
   return  (uint32_t) (*upd->pxlptr  ) & (uint32_t) 0x03;
7562
 
}
7563
 
 
7564
 
/* 4 Bit Reverse */
7565
 
 
7566
 
static uint32_t
7567
 
upd_pxlget4r1(upd_p upd)
7568
 
{
7569
 
   upd->pxlget = upd_pxlget4r2;
7570
 
   return ((uint32_t) (*upd->pxlptr--) & (uint32_t) 0xF0) >> 4;
7571
 
}
7572
 
 
7573
 
static uint32_t
7574
 
upd_pxlget4r2(upd_p upd)
7575
 
{
7576
 
   upd->pxlget = upd_pxlget4r1;
7577
 
   return  (uint32_t) (*upd->pxlptr  ) & (uint32_t) 0x0F;
7578
 
}
7579
 
 
7580
 
/* 8 Bit Reverse */
7581
 
static uint32_t
7582
 
upd_pxlget8r(upd_p upd)
7583
 
{
7584
 
   return (uint32_t) (*upd->pxlptr--);
7585
 
}
7586
 
 
7587
 
/* 16 Bit Reverse */
7588
 
static uint32_t
7589
 
upd_pxlget16r(upd_p upd)
7590
 
{
7591
 
   uint32_t ci  =                   *upd->pxlptr--;
7592
 
                  ci |= (uint32_t) (*upd->pxlptr--) << 8;
7593
 
   return         ci;
7594
 
}
7595
 
 
7596
 
/* 24 Bit Reverse */
7597
 
static uint32_t
7598
 
upd_pxlget24r(upd_p upd)
7599
 
{
7600
 
   uint32_t ci  =           *upd->pxlptr--;
7601
 
          ci |= (uint32_t) (*upd->pxlptr--) <<  8;
7602
 
          ci |= (uint32_t) (*upd->pxlptr--) << 16;
7603
 
   return ci;
7604
 
}
7605
 
 
7606
 
/* 32 Bit Reverse */
7607
 
static uint32_t
7608
 
upd_pxlget32r(upd_p upd)
7609
 
{
7610
 
   uint32_t ci  =                   *upd->pxlptr--;
7611
 
                  ci |= (uint32_t) (*upd->pxlptr--) <<  8;
7612
 
                  ci |= (uint32_t) (*upd->pxlptr--) << 16;
7613
 
                  ci |= (uint32_t) (*upd->pxlptr--) << 24;
7614
 
   return         ci;
7615
 
}