Subversion Repositories planix.SVN

Rev

Rev 2 | Details | Compare with Previous | Last modification | View Log | RSS feed

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