Coverage Report

Created: 2022-10-31 07:00

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